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_editeng.hxx" 30 31 32 #include <com/sun/star/io/XStream.hpp> 33 #include <com/sun/star/lang/Locale.hpp> 34 #include <tools/urlobj.hxx> 35 #include <tools/table.hxx> 36 #include <i18npool/mslangid.hxx> 37 #include <vcl/svapp.hxx> 38 #include <sot/storinfo.hxx> 39 // fuer die Sort-String-Arrays aus dem SVMEM.HXX 40 #define _SVSTDARR_STRINGSISORTDTOR 41 #define _SVSTDARR_STRINGSDTOR 42 #include <svl/svstdarr.hxx> 43 #include <svl/fstathelper.hxx> 44 #include <svtools/helpopt.hxx> 45 #include <svl/urihelper.hxx> 46 #include <unotools/charclass.hxx> 47 #include <com/sun/star/i18n/UnicodeType.hdl> 48 #include <unotools/collatorwrapper.hxx> 49 #include <com/sun/star/i18n/CollatorOptions.hpp> 50 #include <com/sun/star/i18n/UnicodeScript.hpp> 51 #include <unotools/localedatawrapper.hxx> 52 #include <unotools/transliterationwrapper.hxx> 53 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 54 #include <comphelper/processfactory.hxx> 55 #include <com/sun/star/io/XActiveDataSource.hpp> 56 #include <editeng/editids.hrc> 57 #include <sot/storage.hxx> 58 #include <comphelper/storagehelper.hxx> 59 #include <editeng/udlnitem.hxx> 60 #include <editeng/wghtitem.hxx> 61 #include <editeng/escpitem.hxx> 62 #include <editeng/svxacorr.hxx> 63 #include <editeng/unolingu.hxx> 64 #include <helpid.hrc> 65 #include <comphelper/processfactory.hxx> 66 #include <com/sun/star/xml/sax/InputSource.hpp> 67 #include <com/sun/star/xml/sax/XParser.hpp> 68 #include <unotools/streamwrap.hxx> 69 #include <SvXMLAutoCorrectImport.hxx> 70 #include <SvXMLAutoCorrectExport.hxx> 71 #include <ucbhelper/content.hxx> 72 #include <com/sun/star/ucb/XCommandEnvironment.hpp> 73 #include <com/sun/star/ucb/TransferInfo.hpp> 74 #include <com/sun/star/ucb/NameClash.hpp> 75 #include <xmloff/xmltoken.hxx> 76 #include <vcl/help.hxx> 77 78 #define CHAR_HARDBLANK ((sal_Unicode)0x00A0) 79 80 using namespace ::com::sun::star::ucb; 81 using namespace ::com::sun::star::uno; 82 using namespace ::com::sun::star; 83 using namespace ::xmloff::token; 84 using namespace ::rtl; 85 using namespace ::utl; 86 87 const int C_NONE = 0x00; 88 const int C_FULL_STOP = 0x01; 89 const int C_EXCLAMATION_MARK = 0x02; 90 const int C_QUESTION_MARK = 0x04; 91 92 static const sal_Char pImplWrdStt_ExcptLstStr[] = "WordExceptList"; 93 static const sal_Char pImplCplStt_ExcptLstStr[] = "SentenceExceptList"; 94 static const sal_Char pImplAutocorr_ListStr[] = "DocumentList"; 95 static const sal_Char pXMLImplWrdStt_ExcptLstStr[] = "WordExceptList.xml"; 96 static const sal_Char pXMLImplCplStt_ExcptLstStr[] = "SentenceExceptList.xml"; 97 static const sal_Char pXMLImplAutocorr_ListStr[] = "DocumentList.xml"; 98 99 static const sal_Char 100 /* auch bei diesen Anfaengen - Klammern auf und alle Arten von Anf.Zei. */ 101 sImplSttSkipChars[] = "\"\'([{\x83\x84\x89\x91\x92\x93\x94", 102 /* auch bei diesen Ende - Klammern auf und alle Arten von Anf.Zei. */ 103 sImplEndSkipChars[] = "\"\')]}\x83\x84\x89\x91\x92\x93\x94"; 104 105 // diese Zeichen sind in Worten erlaubt: (fuer FnCptlSttSntnc) 106 static const sal_Char sImplWordChars[] = "-'"; 107 108 void EncryptBlockName_Imp( String& rName ); 109 void DecryptBlockName_Imp( String& rName ); 110 111 112 // FileVersions Nummern fuer die Ersetzungs-/Ausnahmelisten getrennt 113 #define WORDLIST_VERSION_358 1 114 #define EXEPTLIST_VERSION_358 0 115 116 117 _SV_IMPL_SORTAR_ALG( SvxAutocorrWordList, SvxAutocorrWordPtr ) 118 TYPEINIT0(SvxAutoCorrect) 119 120 typedef SvxAutoCorrectLanguageLists* SvxAutoCorrectLanguageListsPtr; 121 DECLARE_TABLE( SvxAutoCorrLanguageTable_Impl, SvxAutoCorrectLanguageListsPtr) 122 123 DECLARE_TABLE( SvxAutoCorrLastFileAskTable_Impl, long ) 124 125 126 inline int IsWordDelim( const sal_Unicode c ) 127 { 128 return ' ' == c || '\t' == c || 0x0a == c || 129 0xA0 == c || 0x2011 == c || 0x1 == c; 130 } 131 132 inline int IsLowerLetter( sal_Int32 nCharType ) 133 { 134 return CharClass::isLetterType( nCharType ) && 135 0 == ( ::com::sun::star::i18n::KCharacterType::UPPER & nCharType); 136 } 137 inline int IsUpperLetter( sal_Int32 nCharType ) 138 { 139 return CharClass::isLetterType( nCharType ) && 140 0 == ( ::com::sun::star::i18n::KCharacterType::LOWER & nCharType); 141 } 142 143 bool lcl_IsUnsupportedUnicodeChar( CharClass& rCC, const String& rTxt, 144 xub_StrLen nStt, xub_StrLen nEnd ) 145 { 146 for( ; nStt < nEnd; ++nStt ) 147 { 148 #if OSL_DEBUG_LEVEL > 1 149 sal_Int32 nCharType; 150 sal_Int32 nChType; 151 nCharType = rCC.getCharacterType( rTxt, nStt ); 152 nChType = rCC.getType( rTxt, nStt ); 153 #endif 154 short nScript = rCC.getScript( rTxt, nStt ); 155 switch( nScript ) 156 { 157 case ::com::sun::star::i18n::UnicodeScript_kCJKRadicalsSupplement: 158 case ::com::sun::star::i18n::UnicodeScript_kHangulJamo: 159 case ::com::sun::star::i18n::UnicodeScript_kCJKSymbolPunctuation: 160 case ::com::sun::star::i18n::UnicodeScript_kHiragana: 161 case ::com::sun::star::i18n::UnicodeScript_kKatakana: 162 case ::com::sun::star::i18n::UnicodeScript_kHangulCompatibilityJamo: 163 case ::com::sun::star::i18n::UnicodeScript_kEnclosedCJKLetterMonth: 164 case ::com::sun::star::i18n::UnicodeScript_kCJKCompatibility: 165 case ::com::sun::star::i18n::UnicodeScript_k_CJKUnifiedIdeographsExtensionA: 166 case ::com::sun::star::i18n::UnicodeScript_kCJKUnifiedIdeograph: 167 case ::com::sun::star::i18n::UnicodeScript_kHangulSyllable: 168 case ::com::sun::star::i18n::UnicodeScript_kCJKCompatibilityIdeograph: 169 case ::com::sun::star::i18n::UnicodeScript_kHalfwidthFullwidthForm: 170 return true; 171 default: ; //do nothing 172 } 173 174 } 175 return false; 176 } 177 178 sal_Bool lcl_IsSymbolChar( CharClass& rCC, const String& rTxt, 179 xub_StrLen nStt, xub_StrLen nEnd ) 180 { 181 for( ; nStt < nEnd; ++nStt ) 182 { 183 #if OSL_DEBUG_LEVEL > 1 184 sal_Int32 nCharType; 185 sal_Int32 nChType; 186 nCharType = rCC.getCharacterType( rTxt, nStt ); 187 nChType = rCC.getType( rTxt, nStt ); 188 #endif 189 if( ::com::sun::star::i18n::UnicodeType::PRIVATE_USE == 190 rCC.getType( rTxt, nStt )) 191 return sal_True; 192 } 193 return sal_False; 194 } 195 196 197 static sal_Bool lcl_IsInAsciiArr( const sal_Char* pArr, const sal_Unicode c ) 198 { 199 sal_Bool bRet = sal_False; 200 for( ; *pArr; ++pArr ) 201 if( *pArr == c ) 202 { 203 bRet = sal_True; 204 break; 205 } 206 return bRet; 207 } 208 209 SvxAutoCorrDoc::~SvxAutoCorrDoc() 210 { 211 } 212 213 214 // wird nach dem austauschen der Zeichen von den Funktionen 215 // - FnCptlSttWrd 216 // - FnCptlSttSntnc 217 // gerufen. Dann koennen die Worte ggfs. in die Ausnahmelisten 218 // aufgenommen werden. 219 void SvxAutoCorrDoc::SaveCpltSttWord( sal_uLong, xub_StrLen, const String&, 220 sal_Unicode ) 221 { 222 } 223 224 LanguageType SvxAutoCorrDoc::GetLanguage( xub_StrLen , sal_Bool ) const 225 { 226 return LANGUAGE_SYSTEM; 227 } 228 229 static ::com::sun::star::uno::Reference< 230 ::com::sun::star::lang::XMultiServiceFactory >& GetProcessFact() 231 { 232 static ::com::sun::star::uno::Reference< 233 ::com::sun::star::lang::XMultiServiceFactory > xMSF = 234 ::comphelper::getProcessServiceFactory(); 235 return xMSF; 236 } 237 238 static sal_uInt16 GetAppLang() 239 { 240 return Application::GetSettings().GetLanguage(); 241 } 242 static LocaleDataWrapper& GetLocaleDataWrapper( sal_uInt16 nLang ) 243 { 244 static LocaleDataWrapper aLclDtWrp( GetProcessFact(), 245 SvxCreateLocale( GetAppLang() ) ); 246 ::com::sun::star::lang::Locale aLcl( SvxCreateLocale( nLang )); 247 const ::com::sun::star::lang::Locale& rLcl = aLclDtWrp.getLoadedLocale(); 248 if( aLcl.Language != rLcl.Language || 249 aLcl.Country != rLcl.Country || 250 aLcl.Variant != rLcl.Variant ) 251 aLclDtWrp.setLocale( aLcl ); 252 return aLclDtWrp; 253 } 254 static TransliterationWrapper& GetIgnoreTranslWrapper() 255 { 256 static int bIsInit = 0; 257 static TransliterationWrapper aWrp( GetProcessFact(), 258 ::com::sun::star::i18n::TransliterationModules_IGNORE_CASE | 259 ::com::sun::star::i18n::TransliterationModules_IGNORE_KANA | 260 ::com::sun::star::i18n::TransliterationModules_IGNORE_WIDTH ); 261 if( !bIsInit ) 262 { 263 aWrp.loadModuleIfNeeded( GetAppLang() ); 264 bIsInit = 1; 265 } 266 return aWrp; 267 } 268 static CollatorWrapper& GetCollatorWrapper() 269 { 270 static int bIsInit = 0; 271 static CollatorWrapper aCollWrp( GetProcessFact() ); 272 if( !bIsInit ) 273 { 274 aCollWrp.loadDefaultCollator( SvxCreateLocale( GetAppLang() ), 0 ); 275 bIsInit = 1; 276 } 277 return aCollWrp; 278 } 279 280 281 void SvxAutocorrWordList::DeleteAndDestroy( sal_uInt16 nP, sal_uInt16 nL ) 282 { 283 if( nL ) 284 { 285 DBG_ASSERT( nP < nA && nP + nL <= nA, "ERR_VAR_DEL" ); 286 for( sal_uInt16 n=nP; n < nP + nL; n++ ) 287 delete *((SvxAutocorrWordPtr*)pData+n); 288 SvPtrarr::Remove( nP, nL ); 289 } 290 } 291 292 293 sal_Bool SvxAutocorrWordList::Seek_Entry( const SvxAutocorrWordPtr aE, sal_uInt16* pP ) const 294 { 295 register sal_uInt16 nO = SvxAutocorrWordList_SAR::Count(), 296 nM, 297 nU = 0; 298 if( nO > 0 ) 299 { 300 CollatorWrapper& rCmp = ::GetCollatorWrapper(); 301 nO--; 302 while( nU <= nO ) 303 { 304 nM = nU + ( nO - nU ) / 2; 305 long nCmp = rCmp.compareString( aE->GetShort(), 306 (*((SvxAutocorrWordPtr*)pData + nM))->GetShort() ); 307 if( 0 == nCmp ) 308 { 309 if( pP ) *pP = nM; 310 return sal_True; 311 } 312 else if( 0 < nCmp ) 313 nU = nM + 1; 314 else if( nM == 0 ) 315 { 316 if( pP ) *pP = nU; 317 return sal_False; 318 } 319 else 320 nO = nM - 1; 321 } 322 } 323 if( pP ) *pP = nU; 324 return sal_False; 325 } 326 327 /* -----------------18.11.98 15:28------------------- 328 * 329 * --------------------------------------------------*/ 330 void lcl_ClearTable(SvxAutoCorrLanguageTable_Impl& rLangTable) 331 { 332 SvxAutoCorrectLanguageListsPtr pLists = rLangTable.Last(); 333 while(pLists) 334 { 335 delete pLists; 336 pLists = rLangTable.Prev(); 337 } 338 rLangTable.Clear(); 339 } 340 341 /* -----------------03.11.06 10:15------------------- 342 * 343 * --------------------------------------------------*/ 344 345 sal_Bool SvxAutoCorrect::IsAutoCorrectChar( sal_Unicode cChar ) 346 { 347 return cChar == '\0' || cChar == '\t' || cChar == 0x0a || 348 cChar == ' ' || cChar == '\'' || cChar == '\"' || 349 cChar == '*' || cChar == '_' || 350 cChar == '.' || cChar == ',' || cChar == ';' || 351 cChar == ':' || cChar == '?' || cChar == '!' || cChar == '/'; 352 } 353 354 sal_Bool SvxAutoCorrect::NeedsHardspaceAutocorr( sal_Unicode cChar ) 355 { 356 return cChar == ';' || cChar == ':' || cChar == '?' || cChar == '!' || 357 cChar == '/' /*case for the urls exception*/; 358 } 359 360 /* -----------------19.11.98 10:15------------------- 361 * 362 * --------------------------------------------------*/ 363 long SvxAutoCorrect::GetDefaultFlags() 364 { 365 long nRet = Autocorrect 366 | CptlSttSntnc 367 | CptlSttWrd 368 | ChgOrdinalNumber 369 | ChgToEnEmDash 370 | AddNonBrkSpace 371 | ChgWeightUnderl 372 | SetINetAttr 373 | ChgQuotes 374 | SaveWordCplSttLst 375 | SaveWordWrdSttLst; 376 LanguageType eLang = GetAppLang(); 377 switch( eLang ) 378 { 379 case LANGUAGE_ENGLISH: 380 case LANGUAGE_ENGLISH_US: 381 case LANGUAGE_ENGLISH_UK: 382 case LANGUAGE_ENGLISH_AUS: 383 case LANGUAGE_ENGLISH_CAN: 384 case LANGUAGE_ENGLISH_NZ: 385 case LANGUAGE_ENGLISH_EIRE: 386 case LANGUAGE_ENGLISH_SAFRICA: 387 case LANGUAGE_ENGLISH_JAMAICA: 388 case LANGUAGE_ENGLISH_CARRIBEAN: 389 nRet &= ~(ChgQuotes|ChgSglQuotes); 390 break; 391 } 392 return nRet; 393 } 394 395 396 SvxAutoCorrect::SvxAutoCorrect( const String& rShareAutocorrFile, 397 const String& rUserAutocorrFile ) 398 : sShareAutoCorrFile( rShareAutocorrFile ), 399 sUserAutoCorrFile( rUserAutocorrFile ), 400 pLangTable( new SvxAutoCorrLanguageTable_Impl ), 401 pLastFileTable( new SvxAutoCorrLastFileAskTable_Impl ), 402 pCharClass( 0 ), bRunNext( false ), 403 cStartDQuote( 0 ), cEndDQuote( 0 ), cStartSQuote( 0 ), cEndSQuote( 0 ) 404 { 405 nFlags = SvxAutoCorrect::GetDefaultFlags(); 406 407 cEmDash = ByteString::ConvertToUnicode( '\x97', RTL_TEXTENCODING_MS_1252 ); 408 cEnDash = ByteString::ConvertToUnicode( '\x96', RTL_TEXTENCODING_MS_1252 ); 409 } 410 411 SvxAutoCorrect::SvxAutoCorrect( const SvxAutoCorrect& rCpy ) 412 : sShareAutoCorrFile( rCpy.sShareAutoCorrFile ), 413 sUserAutoCorrFile( rCpy.sUserAutoCorrFile ), 414 415 aSwFlags( rCpy.aSwFlags ), 416 417 pLangTable( new SvxAutoCorrLanguageTable_Impl ), 418 pLastFileTable( new SvxAutoCorrLastFileAskTable_Impl ), 419 pCharClass( 0 ), bRunNext( false ), 420 421 nFlags( rCpy.nFlags & ~(ChgWordLstLoad|CplSttLstLoad|WrdSttLstLoad)), 422 cStartDQuote( rCpy.cStartDQuote ), cEndDQuote( rCpy.cEndDQuote ), 423 cStartSQuote( rCpy.cStartSQuote ), cEndSQuote( rCpy.cEndSQuote ), 424 cEmDash( rCpy.cEmDash ), cEnDash( rCpy.cEnDash ) 425 { 426 } 427 428 429 SvxAutoCorrect::~SvxAutoCorrect() 430 { 431 lcl_ClearTable(*pLangTable); 432 delete pLangTable; 433 delete pLastFileTable; 434 delete pCharClass; 435 } 436 437 void SvxAutoCorrect::_GetCharClass( LanguageType eLang ) 438 { 439 delete pCharClass; 440 pCharClass = new CharClass( SvxCreateLocale( eLang )); 441 eCharClassLang = eLang; 442 } 443 444 void SvxAutoCorrect::SetAutoCorrFlag( long nFlag, sal_Bool bOn ) 445 { 446 long nOld = nFlags; 447 nFlags = bOn ? nFlags | nFlag 448 : nFlags & ~nFlag; 449 450 if( !bOn ) 451 { 452 if( (nOld & CptlSttSntnc) != (nFlags & CptlSttSntnc) ) 453 nFlags &= ~CplSttLstLoad; 454 if( (nOld & CptlSttWrd) != (nFlags & CptlSttWrd) ) 455 nFlags &= ~WrdSttLstLoad; 456 if( (nOld & Autocorrect) != (nFlags & Autocorrect) ) 457 nFlags &= ~ChgWordLstLoad; 458 } 459 } 460 461 462 // Zwei Grossbuchstaben am Wort-Anfang ?? 463 sal_Bool SvxAutoCorrect::FnCptlSttWrd( SvxAutoCorrDoc& rDoc, const String& rTxt, 464 xub_StrLen nSttPos, xub_StrLen nEndPos, 465 LanguageType eLang ) 466 { 467 sal_Bool bRet = sal_False; 468 CharClass& rCC = GetCharClass( eLang ); 469 470 // loesche alle nicht alpanum. Zeichen am Wortanfang/-ende und 471 // teste dann ( erkennt: "(min.", "/min.", usw.) 472 for( ; nSttPos < nEndPos; ++nSttPos ) 473 if( rCC.isLetterNumeric( rTxt, nSttPos )) 474 break; 475 for( ; nSttPos < nEndPos; --nEndPos ) 476 if( rCC.isLetterNumeric( rTxt, nEndPos - 1 )) 477 break; 478 479 // Zwei Grossbuchstaben am Wort-Anfang ?? 480 if( nSttPos+2 < nEndPos && 481 IsUpperLetter( rCC.getCharacterType( rTxt, nSttPos )) && 482 IsUpperLetter( rCC.getCharacterType( rTxt, ++nSttPos )) && 483 // ist das 3. Zeichen ein klein geschiebenes Alpha-Zeichen 484 IsLowerLetter( rCC.getCharacterType( rTxt, nSttPos +1 )) && 485 // keine Sonder-Attribute ersetzen 486 0x1 != rTxt.GetChar( nSttPos ) && 0x2 != rTxt.GetChar( nSttPos )) 487 { 488 // teste ob das Wort in einer Ausnahmeliste steht 489 String sWord( rTxt.Copy( nSttPos - 1, nEndPos - nSttPos + 1 )); 490 if( !FindInWrdSttExceptList(eLang, sWord) ) 491 { 492 sal_Unicode cSave = rTxt.GetChar( nSttPos ); 493 String sChar( cSave ); 494 rCC.toLower( sChar ); 495 if( sChar.GetChar(0) != cSave && rDoc.ReplaceRange( nSttPos, 1, sChar )) 496 { 497 if( SaveWordWrdSttLst & nFlags ) 498 rDoc.SaveCpltSttWord( CptlSttWrd, nSttPos, sWord, cSave ); 499 bRet = sal_True; 500 } 501 } 502 } 503 return bRet; 504 } 505 506 507 sal_Bool SvxAutoCorrect::FnChgOrdinalNumber( 508 SvxAutoCorrDoc& rDoc, const String& rTxt, 509 xub_StrLen nSttPos, xub_StrLen nEndPos, 510 LanguageType eLang ) 511 { 512 // 1st, 2nd, 3rd, 4 - 0th 513 // 201th oder 201st 514 // 12th oder 12nd 515 CharClass& rCC = GetCharClass( eLang ); 516 sal_Bool bChg = sal_False; 517 518 for( ; nSttPos < nEndPos; ++nSttPos ) 519 if( !lcl_IsInAsciiArr( sImplSttSkipChars, rTxt.GetChar( nSttPos ) )) 520 break; 521 for( ; nSttPos < nEndPos; --nEndPos ) 522 if( !lcl_IsInAsciiArr( sImplEndSkipChars, rTxt.GetChar( nEndPos - 1 ) )) 523 break; 524 525 if( 2 < nEndPos - nSttPos && 526 rCC.isDigit( rTxt, nEndPos - 3 ) ) 527 { 528 static sal_Char __READONLY_DATA 529 sAll[] = "th", /* rest */ 530 sFirst[] = "st", /* 1 */ 531 sSecond[] = "nd", /* 2 */ 532 sThird[] = "rd"; /* 3 */ 533 static const sal_Char* __READONLY_DATA aNumberTab[ 4 ] = 534 { 535 sAll, sFirst, sSecond, sThird 536 }; 537 538 sal_Unicode c = rTxt.GetChar( nEndPos - 3 ); 539 if( ( c -= '0' ) > 3 ) 540 c = 0; 541 542 bChg = ( ((sal_Unicode)*((aNumberTab[ c ])+0)) == 543 rTxt.GetChar( nEndPos - 2 ) && 544 ((sal_Unicode)*((aNumberTab[ c ])+1)) == 545 rTxt.GetChar( nEndPos - 1 )) || 546 ( 3 < nEndPos - nSttPos && 547 ( ((sal_Unicode)*(sAll+0)) == rTxt.GetChar( nEndPos - 2 ) && 548 ((sal_Unicode)*(sAll+1)) == rTxt.GetChar( nEndPos - 1 ))); 549 550 if( bChg ) 551 { 552 // dann pruefe mal, ob alle bis zum Start alle Zahlen sind 553 for( xub_StrLen n = nEndPos - 3; nSttPos < n; ) 554 if( !rCC.isDigit( rTxt, --n ) ) 555 { 556 bChg = !rCC.isLetter( rTxt, n ); 557 break; 558 } 559 560 if( bChg ) // dann setze mal das Escapement Attribut 561 { 562 SvxEscapementItem aSvxEscapementItem( DFLT_ESC_AUTO_SUPER, 563 DFLT_ESC_PROP, SID_ATTR_CHAR_ESCAPEMENT ); 564 rDoc.SetAttr( nEndPos - 2, nEndPos, 565 SID_ATTR_CHAR_ESCAPEMENT, 566 aSvxEscapementItem); 567 } 568 } 569 570 } 571 return bChg; 572 } 573 574 575 sal_Bool SvxAutoCorrect::FnChgToEnEmDash( 576 SvxAutoCorrDoc& rDoc, const String& rTxt, 577 xub_StrLen nSttPos, xub_StrLen nEndPos, 578 LanguageType eLang ) 579 { 580 sal_Bool bRet = sal_False; 581 CharClass& rCC = GetCharClass( eLang ); 582 if (eLang == LANGUAGE_SYSTEM) 583 eLang = GetAppLang(); 584 bool bAlwaysUseEmDash = (cEmDash && (eLang == LANGUAGE_RUSSIAN || eLang == LANGUAGE_UKRAINIAN)); 585 586 // ersetze " - " oder " --" durch "enDash" 587 if( cEnDash && 1 < nSttPos && 1 <= nEndPos - nSttPos ) 588 { 589 sal_Unicode cCh = rTxt.GetChar( nSttPos ); 590 if( '-' == cCh ) 591 { 592 if( ' ' == rTxt.GetChar( nSttPos-1 ) && 593 '-' == rTxt.GetChar( nSttPos+1 )) 594 { 595 xub_StrLen n; 596 for( n = nSttPos+2; n < nEndPos && lcl_IsInAsciiArr( 597 sImplSttSkipChars,(cCh = rTxt.GetChar( n ))); 598 ++n ) 599 ; 600 601 // found: " --[<AnySttChars>][A-z0-9] 602 if( rCC.isLetterNumeric( cCh ) ) 603 { 604 for( n = nSttPos-1; n && lcl_IsInAsciiArr( 605 sImplEndSkipChars,(cCh = rTxt.GetChar( --n ))); ) 606 ; 607 608 // found: "[A-z0-9][<AnyEndChars>] --[<AnySttChars>][A-z0-9] 609 if( rCC.isLetterNumeric( cCh )) 610 { 611 rDoc.Delete( nSttPos, nSttPos + 2 ); 612 rDoc.Insert( nSttPos, bAlwaysUseEmDash ? cEmDash : cEnDash ); 613 bRet = sal_True; 614 } 615 } 616 } 617 } 618 else if( 3 < nSttPos && 619 ' ' == rTxt.GetChar( nSttPos-1 ) && 620 '-' == rTxt.GetChar( nSttPos-2 )) 621 { 622 xub_StrLen n, nLen = 1, nTmpPos = nSttPos - 2; 623 if( '-' == ( cCh = rTxt.GetChar( nTmpPos-1 )) ) 624 { 625 --nTmpPos; 626 ++nLen; 627 cCh = rTxt.GetChar( nTmpPos-1 ); 628 } 629 if( ' ' == cCh ) 630 { 631 for( n = nSttPos; n < nEndPos && lcl_IsInAsciiArr( 632 sImplSttSkipChars,(cCh = rTxt.GetChar( n ))); 633 ++n ) 634 ; 635 636 // found: " - [<AnySttChars>][A-z0-9] 637 if( rCC.isLetterNumeric( cCh ) ) 638 { 639 cCh = ' '; 640 for( n = nTmpPos-1; n && lcl_IsInAsciiArr( 641 sImplEndSkipChars,(cCh = rTxt.GetChar( --n ))); ) 642 ; 643 // found: "[A-z0-9][<AnyEndChars>] - [<AnySttChars>][A-z0-9] 644 if( rCC.isLetterNumeric( cCh )) 645 { 646 rDoc.Delete( nTmpPos, nTmpPos + nLen ); 647 rDoc.Insert( nTmpPos, bAlwaysUseEmDash ? cEmDash : cEnDash ); 648 bRet = sal_True; 649 } 650 } 651 } 652 } 653 } 654 655 // Replace [A-z0-9]--[A-z0-9] double dash with "emDash" or "enDash". 656 // Finnish and Hungarian use enDash instead of emDash. 657 bool bEnDash = (eLang == LANGUAGE_HUNGARIAN || eLang == LANGUAGE_FINNISH); 658 if( ((cEmDash && !bEnDash) || (cEnDash && bEnDash)) && 4 <= nEndPos - nSttPos ) 659 { 660 String sTmp( rTxt.Copy( nSttPos, nEndPos - nSttPos ) ); 661 xub_StrLen nFndPos = sTmp.SearchAscii( "--" ); 662 if( STRING_NOTFOUND != nFndPos && nFndPos && 663 nFndPos + 2 < sTmp.Len() && 664 ( rCC.isLetterNumeric( sTmp, nFndPos - 1 ) || 665 lcl_IsInAsciiArr( sImplEndSkipChars, rTxt.GetChar( nFndPos - 1 ) )) && 666 ( rCC.isLetterNumeric( sTmp, nFndPos + 2 ) || 667 lcl_IsInAsciiArr( sImplSttSkipChars, rTxt.GetChar( nFndPos + 2 ) ))) 668 { 669 nSttPos = nSttPos + nFndPos; 670 rDoc.Delete( nSttPos, nSttPos + 2 ); 671 rDoc.Insert( nSttPos, (bEnDash ? cEnDash : cEmDash) ); 672 bRet = sal_True; 673 } 674 } 675 return bRet; 676 } 677 678 sal_Bool SvxAutoCorrect::FnAddNonBrkSpace( 679 SvxAutoCorrDoc& rDoc, const String& rTxt, 680 xub_StrLen, xub_StrLen nEndPos, 681 LanguageType eLang ) 682 { 683 bool bRet = false; 684 685 CharClass& rCC = GetCharClass( eLang ); 686 const lang::Locale rLocale = rCC.getLocale( ); 687 688 if ( rLocale.Language == OUString::createFromAscii( "fr" ) ) 689 { 690 bool bFrCA = rLocale.Country == OUString::createFromAscii( "CA" ); 691 OUString allChars = OUString::createFromAscii( ":;!?" ); 692 OUString chars( allChars ); 693 if ( bFrCA ) 694 chars = OUString::createFromAscii( ":" ); 695 696 sal_Unicode cChar = rTxt.GetChar( nEndPos ); 697 bool bHasSpace = chars.indexOf( sal_Unicode( cChar ) ) != -1; 698 bool bIsSpecial = allChars.indexOf( sal_Unicode( cChar ) ) != -1; 699 if ( bIsSpecial ) 700 { 701 // Get the last word delimiter position 702 xub_StrLen nSttWdPos = nEndPos; 703 while( nSttWdPos && !IsWordDelim( rTxt.GetChar( --nSttWdPos ))) 704 ; 705 706 // Check the presence of "://" in the word 707 xub_StrLen nStrPos = rTxt.Search( String::CreateFromAscii( "://" ), nSttWdPos + 1 ); 708 if ( STRING_NOTFOUND == nStrPos && nEndPos > 0 ) 709 { 710 // Check the previous char 711 sal_Unicode cPrevChar = rTxt.GetChar( nEndPos - 1 ); 712 if ( ( chars.indexOf( sal_Unicode( cPrevChar ) ) == -1 ) && cPrevChar != '\t' ) 713 { 714 // Remove any previous normal space 715 xub_StrLen nPos = nEndPos - 1; 716 while ( cPrevChar == ' ' || cPrevChar == CHAR_HARDBLANK ) 717 { 718 if ( nPos == 0 ) break; 719 nPos--; 720 cPrevChar = rTxt.GetChar( nPos ); 721 } 722 723 if ( nPos != 0 ) 724 { 725 nPos++; 726 if ( nEndPos - nPos > 0 ) 727 rDoc.Delete( nPos, nEndPos ); 728 729 // Add the non-breaking space at the end pos 730 if ( bHasSpace ) 731 rDoc.Insert( nPos, CHAR_HARDBLANK ); 732 bRunNext = true; 733 bRet = true; 734 } 735 } 736 else if ( chars.indexOf( sal_Unicode( cPrevChar ) ) != -1 ) 737 bRunNext = true; 738 } 739 } 740 else if ( cChar == '/' && nEndPos > 1 && rTxt.Len() > (nEndPos - 1) ) 741 { 742 // Remove the hardspace right before to avoid formatting URLs 743 sal_Unicode cPrevChar = rTxt.GetChar( nEndPos - 1 ); 744 sal_Unicode cMaybeSpaceChar = rTxt.GetChar( nEndPos - 2 ); 745 if ( cPrevChar == ':' && cMaybeSpaceChar == CHAR_HARDBLANK ) 746 { 747 rDoc.Delete( nEndPos - 2, nEndPos - 1 ); 748 bRet = true; 749 } 750 } 751 } 752 753 return bRet; 754 } 755 756 sal_Bool SvxAutoCorrect::FnSetINetAttr( SvxAutoCorrDoc& rDoc, const String& rTxt, 757 xub_StrLen nSttPos, xub_StrLen nEndPos, 758 LanguageType eLang ) 759 { 760 String sURL( URIHelper::FindFirstURLInText( rTxt, nSttPos, nEndPos, 761 GetCharClass( eLang ) )); 762 sal_Bool bRet = 0 != sURL.Len(); 763 if( bRet ) // also Attribut setzen: 764 rDoc.SetINetAttr( nSttPos, nEndPos, sURL ); 765 return bRet; 766 } 767 768 769 sal_Bool SvxAutoCorrect::FnChgWeightUnderl( SvxAutoCorrDoc& rDoc, const String& rTxt, 770 xub_StrLen, xub_StrLen nEndPos, 771 LanguageType eLang ) 772 { 773 // Bedingung: 774 // Am Anfang: _ oder * hinter Space mit nachfolgenden !Space 775 // Am Ende: _ oder * vor Space (Worttrenner?) 776 777 sal_Unicode c, cInsChar = rTxt.GetChar( nEndPos ); // unterstreichen oder fett 778 if( ++nEndPos != rTxt.Len() && 779 !IsWordDelim( rTxt.GetChar( nEndPos ) ) ) 780 return sal_False; 781 782 --nEndPos; 783 784 sal_Bool bAlphaNum = sal_False; 785 xub_StrLen nPos = nEndPos, nFndPos = STRING_NOTFOUND; 786 CharClass& rCC = GetCharClass( eLang ); 787 788 while( nPos ) 789 { 790 switch( c = rTxt.GetChar( --nPos ) ) 791 { 792 case '_': 793 case '*': 794 if( c == cInsChar ) 795 { 796 if( bAlphaNum && nPos+1 < nEndPos && ( !nPos || 797 IsWordDelim( rTxt.GetChar( nPos-1 ))) && 798 !IsWordDelim( rTxt.GetChar( nPos+1 ))) 799 nFndPos = nPos; 800 else 801 // Bedingung ist nicht erfuellt, also abbrechen 802 nFndPos = STRING_NOTFOUND; 803 nPos = 0; 804 } 805 break; 806 default: 807 if( !bAlphaNum ) 808 bAlphaNum = rCC.isLetterNumeric( rTxt, nPos ); 809 } 810 } 811 812 if( STRING_NOTFOUND != nFndPos ) 813 { 814 // ueber den gefundenen Bereich das Attribut aufspannen und 815 // das gefunde und am Ende stehende Zeichen loeschen 816 if( '*' == cInsChar ) // Fett 817 { 818 SvxWeightItem aSvxWeightItem( WEIGHT_BOLD, SID_ATTR_CHAR_WEIGHT ); 819 rDoc.SetAttr( nFndPos + 1, nEndPos, 820 SID_ATTR_CHAR_WEIGHT, 821 aSvxWeightItem); 822 } 823 else // unterstrichen 824 { 825 SvxUnderlineItem aSvxUnderlineItem( UNDERLINE_SINGLE, SID_ATTR_CHAR_UNDERLINE ); 826 rDoc.SetAttr( nFndPos + 1, nEndPos, 827 SID_ATTR_CHAR_UNDERLINE, 828 aSvxUnderlineItem); 829 } 830 rDoc.Delete( nEndPos, nEndPos + 1 ); 831 rDoc.Delete( nFndPos, nFndPos + 1 ); 832 } 833 834 return STRING_NOTFOUND != nFndPos; 835 } 836 837 838 sal_Bool SvxAutoCorrect::FnCptlSttSntnc( SvxAutoCorrDoc& rDoc, 839 const String& rTxt, sal_Bool bNormalPos, 840 xub_StrLen nSttPos, xub_StrLen nEndPos, 841 LanguageType eLang ) 842 { 843 // Grossbuchstabe am Satz-Anfang ?? 844 if( !rTxt.Len() || nEndPos <= nSttPos ) 845 return sal_False; 846 847 CharClass& rCC = GetCharClass( eLang ); 848 String aText( rTxt ); 849 const sal_Unicode *pStart = aText.GetBuffer(), 850 *pStr = pStart + nEndPos, 851 *pWordStt = 0, 852 *pDelim = 0; 853 854 sal_Bool bAtStart = sal_False, bPrevPara = sal_False; 855 do { 856 --pStr; 857 if( rCC.isLetter( 858 aText, sal::static_int_cast< xub_StrLen >( pStr - pStart ) ) ) 859 { 860 if( !pWordStt ) 861 pDelim = pStr+1; 862 pWordStt = pStr; 863 } 864 else if( pWordStt && 865 !rCC.isDigit( 866 aText, 867 sal::static_int_cast< xub_StrLen >( pStr - pStart ) ) ) 868 { 869 if( lcl_IsInAsciiArr( sImplWordChars, *pStr ) && 870 pWordStt - 1 == pStr && 871 // --> FME 2005-02-14 #i38971# 872 // l'intallazione at beginning of paragraph. Replaced < by <= 873 (long)(pStart + 1) <= (long)pStr && 874 // <-- 875 rCC.isLetter( 876 aText, 877 sal::static_int_cast< xub_StrLen >( pStr-1 - pStart ) ) ) 878 pWordStt = --pStr; 879 else 880 break; 881 } 882 } while( 0 == ( bAtStart = (pStart == pStr)) ); 883 884 885 if( !pWordStt || 886 rCC.isDigit( 887 aText, sal::static_int_cast< xub_StrLen >( pStr - pStart ) ) || 888 IsUpperLetter( 889 rCC.getCharacterType( 890 aText, 891 sal::static_int_cast< xub_StrLen >( pWordStt - pStart ) ) ) || 892 0x1 == *pWordStt || 0x2 == *pWordStt ) 893 return sal_False; // kein zu ersetzendes Zeichen, oder schon ok 894 895 // JP 27.10.97: wenn das Wort weniger als 3 Zeichen hat und der Trenner 896 // ein "Num"-Trenner ist, dann nicht ersetzen! 897 // Damit wird ein "a.", "a)", "a-a" nicht ersetzt! 898 if( *pDelim && 2 >= pDelim - pWordStt && 899 lcl_IsInAsciiArr( ".-)>", *pDelim ) ) 900 return sal_False; 901 902 if( !bAtStart ) // noch kein Absatz Anfang ? 903 { 904 if ( IsWordDelim( *pStr ) ) 905 { 906 while( 0 == ( bAtStart = (pStart == pStr--) ) && IsWordDelim( *pStr )) 907 ; 908 } 909 // Asian full stop, full width full stop, full width exclamation mark 910 // and full width question marks are treated as word delimiters 911 else if ( 0x3002 != *pStr && 0xFF0E != *pStr && 0xFF01 != *pStr && 912 0xFF1F != *pStr ) 913 return sal_False; // kein gueltiger Trenner -> keine Ersetzung 914 } 915 916 if( bAtStart ) // am Absatz Anfang ? 917 { 918 // Ueberpruefe den vorherigen Absatz, wenn es diesen gibt. 919 // Wenn ja, dann pruefe auf SatzTrenner am Ende. 920 const String* pPrevPara = rDoc.GetPrevPara( bNormalPos ); 921 if( !pPrevPara ) 922 { 923 // gueltiger Trenner -> Ersetze 924 String sChar( *pWordStt ); 925 rCC.toUpper( sChar ); 926 return sChar != *pWordStt && 927 rDoc.ReplaceRange( xub_StrLen( pWordStt - pStart ), 1, sChar ); 928 } 929 930 aText = *pPrevPara; 931 bPrevPara = sal_True; 932 bAtStart = sal_False; 933 pStart = aText.GetBuffer(); 934 pStr = pStart + aText.Len(); 935 936 do { // alle Blanks ueberlesen 937 --pStr; 938 if( !IsWordDelim( *pStr )) 939 break; 940 } while( 0 == ( bAtStart = (pStart == pStr)) ); 941 942 if( bAtStart ) 943 return sal_False; // kein gueltiger Trenner -> keine Ersetzung 944 } 945 946 // bis hierhier wurde [ \t]+[A-Z0-9]+ gefunden. Test jetzt auf den 947 // Satztrenner. Es koennen alle 3 vorkommen, aber nicht mehrfach !! 948 const sal_Unicode* pExceptStt = 0; 949 if( !bAtStart ) 950 { 951 sal_Bool bWeiter = sal_True; 952 int nFlag = C_NONE; 953 do { 954 switch( *pStr ) 955 { 956 // Western and Asian full stop 957 case '.': 958 case 0x3002 : 959 case 0xFF0E : 960 { 961 if( nFlag & C_FULL_STOP ) 962 return sal_False; // kein gueltiger Trenner -> keine Ersetzung 963 nFlag |= C_FULL_STOP; 964 pExceptStt = pStr; 965 } 966 break; 967 case '!': 968 case 0xFF01 : 969 { 970 if( nFlag & C_EXCLAMATION_MARK ) 971 return sal_False; // kein gueltiger Trenner -> keine Ersetzung 972 nFlag |= C_EXCLAMATION_MARK; 973 } 974 break; 975 case '?': 976 case 0xFF1F : 977 { 978 if( nFlag & C_QUESTION_MARK) 979 return sal_False; // kein gueltiger Trenner -> keine Ersetzung 980 nFlag |= C_QUESTION_MARK; 981 } 982 break; 983 default: 984 if( !nFlag ) 985 return sal_False; // kein gueltiger Trenner -> keine Ersetzung 986 else 987 bWeiter = sal_False; 988 break; 989 } 990 991 if( bWeiter && pStr-- == pStart ) 992 { 993 // !!! wenn am Anfang, dann nie ersetzen. 994 // if( !nFlag ) 995 return sal_False; // kein gueltiger Trenner -> keine Ersetzung 996 // ++pStr; 997 // break; // Schleife beenden 998 } 999 } while( bWeiter ); 1000 if( C_FULL_STOP != nFlag ) 1001 pExceptStt = 0; 1002 } 1003 1004 if( 2 > ( pStr - pStart ) ) 1005 return sal_False; 1006 1007 if( !rCC.isLetterNumeric( 1008 aText, sal::static_int_cast< xub_StrLen >( pStr-- - pStart ) ) ) 1009 { 1010 sal_Bool bValid = sal_False, bAlphaFnd = sal_False; 1011 const sal_Unicode* pTmpStr = pStr; 1012 while( !bValid ) 1013 { 1014 if( rCC.isDigit( 1015 aText, 1016 sal::static_int_cast< xub_StrLen >( pTmpStr - pStart ) ) ) 1017 { 1018 bValid = sal_True; 1019 pStr = pTmpStr - 1; 1020 } 1021 else if( rCC.isLetter( 1022 aText, 1023 sal::static_int_cast< xub_StrLen >( 1024 pTmpStr - pStart ) ) ) 1025 { 1026 if( bAlphaFnd ) 1027 { 1028 bValid = sal_True; 1029 pStr = pTmpStr; 1030 } 1031 else 1032 bAlphaFnd = sal_True; 1033 } 1034 else if( bAlphaFnd || IsWordDelim( *pTmpStr ) ) 1035 break; 1036 1037 if( pTmpStr == pStart ) 1038 break; 1039 1040 --pTmpStr; 1041 } 1042 1043 if( !bValid ) 1044 return sal_False; // kein gueltiger Trenner -> keine Ersetzung 1045 } 1046 1047 sal_Bool bNumericOnly = '0' <= *(pStr+1) && *(pStr+1) <= '9'; 1048 1049 // suche den Anfang vom Wort 1050 while( !IsWordDelim( *pStr )) 1051 { 1052 if( bNumericOnly && 1053 rCC.isLetter( 1054 aText, sal::static_int_cast< xub_StrLen >( pStr - pStart ) ) ) 1055 bNumericOnly = sal_False; 1056 1057 if( pStart == pStr ) 1058 break; 1059 1060 --pStr; 1061 } 1062 1063 if( bNumericOnly ) // besteht nur aus Zahlen, dann nicht 1064 return sal_False; 1065 1066 if( IsWordDelim( *pStr )) 1067 ++pStr; 1068 1069 String sWord; 1070 1071 // ueberpruefe anhand der Exceptionliste 1072 if( pExceptStt ) 1073 { 1074 sWord = String( 1075 pStr, sal::static_int_cast< xub_StrLen >( pExceptStt - pStr + 1 ) ); 1076 if( FindInCplSttExceptList(eLang, sWord) ) 1077 return sal_False; 1078 1079 // loesche alle nicht alpanum. Zeichen am Wortanfang/-ende und 1080 // teste dann noch mal ( erkennt: "(min.", "/min.", usw.) 1081 String sTmp( sWord ); 1082 while( sTmp.Len() && 1083 !rCC.isLetterNumeric( sTmp, 0 ) ) 1084 sTmp.Erase( 0, 1 ); 1085 1086 // alle hinteren nicht alphanumerische Zeichen bis auf das 1087 // Letzte entfernen 1088 xub_StrLen nLen = sTmp.Len(); 1089 while( nLen && !rCC.isLetterNumeric( sTmp, nLen-1 ) ) 1090 --nLen; 1091 if( nLen + 1 < sTmp.Len() ) 1092 sTmp.Erase( nLen + 1 ); 1093 1094 if( sTmp.Len() && sTmp.Len() != sWord.Len() && 1095 FindInCplSttExceptList(eLang, sTmp)) 1096 return sal_False; 1097 1098 if(FindInCplSttExceptList(eLang, sWord, sal_True)) 1099 return sal_False; 1100 } 1101 1102 // Ok, dann ersetze mal 1103 sal_Unicode cSave = *pWordStt; 1104 nSttPos = sal::static_int_cast< xub_StrLen >( pWordStt - rTxt.GetBuffer() ); 1105 String sChar( cSave ); 1106 rCC.toUpper( sChar ); 1107 sal_Bool bRet = sChar.GetChar(0) != cSave && rDoc.ReplaceRange( nSttPos, 1, sChar ); 1108 1109 // das Wort will vielleicht jemand haben 1110 if( bRet && SaveWordCplSttLst & nFlags ) 1111 rDoc.SaveCpltSttWord( CptlSttSntnc, nSttPos, sWord, cSave ); 1112 1113 return bRet; 1114 } 1115 //The method below is renamed from _GetQuote to GetQuote by BerryJia for Bug95846 Time:2002-8-13 15:50 1116 sal_Unicode SvxAutoCorrect::GetQuote( sal_Unicode cInsChar, sal_Bool bSttQuote, 1117 LanguageType eLang ) const 1118 { 1119 sal_Unicode cRet = bSttQuote ? ( '\"' == cInsChar 1120 ? GetStartDoubleQuote() 1121 : GetStartSingleQuote() ) 1122 : ( '\"' == cInsChar 1123 ? GetEndDoubleQuote() 1124 : GetEndSingleQuote() ); 1125 if( !cRet ) 1126 { 1127 // dann ueber die Language das richtige Zeichen heraussuchen 1128 if( LANGUAGE_NONE == eLang ) 1129 cRet = cInsChar; 1130 else 1131 { 1132 LocaleDataWrapper& rLcl = GetLocaleDataWrapper( eLang ); 1133 String sRet( bSttQuote 1134 ? ( '\"' == cInsChar 1135 ? rLcl.getDoubleQuotationMarkStart() 1136 : rLcl.getQuotationMarkStart() ) 1137 : ( '\"' == cInsChar 1138 ? rLcl.getDoubleQuotationMarkEnd() 1139 : rLcl.getQuotationMarkEnd() )); 1140 cRet = sRet.Len() ? sRet.GetChar( 0 ) : cInsChar; 1141 } 1142 } 1143 return cRet; 1144 } 1145 1146 void SvxAutoCorrect::InsertQuote( SvxAutoCorrDoc& rDoc, xub_StrLen nInsPos, 1147 sal_Unicode cInsChar, sal_Bool bSttQuote, 1148 sal_Bool bIns ) 1149 { 1150 LanguageType eLang = rDoc.GetLanguage( nInsPos, sal_False ); 1151 sal_Unicode cRet = GetQuote( cInsChar, bSttQuote, eLang ); 1152 1153 //JP 13.02.99: damit beim Undo das "einfuegte" Zeichen wieder erscheint, 1154 // wird es erstmal eingefuegt und dann ueberschrieben 1155 String sChg( cInsChar ); 1156 if( bIns ) 1157 rDoc.Insert( nInsPos, sChg ); 1158 else 1159 rDoc.Replace( nInsPos, sChg ); 1160 1161 //JP 13.08.97: Bug 42477 - bei doppelten Anfuehrungszeichen muss bei 1162 // franzoesischer Sprache an Anfang ein Leerzeichen dahinter 1163 // und am Ende ein Leerzeichen dahinter eingefuegt werden. 1164 sChg = cRet; 1165 1166 if( '\"' == cInsChar ) 1167 { 1168 if( LANGUAGE_SYSTEM == eLang ) 1169 eLang = GetAppLang(); 1170 switch( eLang ) 1171 { 1172 case LANGUAGE_FRENCH: 1173 case LANGUAGE_FRENCH_BELGIAN: 1174 case LANGUAGE_FRENCH_CANADIAN: 1175 case LANGUAGE_FRENCH_SWISS: 1176 case LANGUAGE_FRENCH_LUXEMBOURG: 1177 // JP 09.02.99: das zusaetzliche Zeichen immer per Insert einfuegen. 1178 // Es ueberschreibt nichts! 1179 { 1180 String s( static_cast< sal_Unicode >(0xA0) ); 1181 // UNICODE code for no break space 1182 if( rDoc.Insert( bSttQuote ? nInsPos+1 : nInsPos, s )) 1183 { 1184 if( !bSttQuote ) 1185 ++nInsPos; 1186 } 1187 } 1188 break; 1189 } 1190 } 1191 1192 rDoc.Replace( nInsPos, sChg ); 1193 } 1194 1195 String SvxAutoCorrect::GetQuote( SvxAutoCorrDoc& rDoc, xub_StrLen nInsPos, 1196 sal_Unicode cInsChar, sal_Bool bSttQuote ) 1197 { 1198 LanguageType eLang = rDoc.GetLanguage( nInsPos, sal_False ); 1199 sal_Unicode cRet = GetQuote( cInsChar, bSttQuote, eLang ); 1200 1201 String sRet( cRet ); 1202 //JP 13.08.97: Bug 42477 - bei doppelten Anfuehrungszeichen muss bei 1203 // franzoesischer Sprache an Anfang ein Leerzeichen dahinter 1204 // und am Ende ein Leerzeichen dahinter eingefuegt werden. 1205 if( '\"' == cInsChar ) 1206 { 1207 if( LANGUAGE_SYSTEM == eLang ) 1208 eLang = GetAppLang(); 1209 switch( eLang ) 1210 { 1211 case LANGUAGE_FRENCH: 1212 case LANGUAGE_FRENCH_BELGIAN: 1213 case LANGUAGE_FRENCH_CANADIAN: 1214 case LANGUAGE_FRENCH_SWISS: 1215 case LANGUAGE_FRENCH_LUXEMBOURG: 1216 if( bSttQuote ) 1217 sRet += ' '; 1218 else 1219 sRet.Insert( ' ', 0 ); 1220 break; 1221 } 1222 } 1223 return sRet; 1224 } 1225 1226 sal_uLong SvxAutoCorrect::AutoCorrect( SvxAutoCorrDoc& rDoc, const String& rTxt, 1227 xub_StrLen nInsPos, sal_Unicode cChar, 1228 sal_Bool bInsert ) 1229 { 1230 sal_uLong nRet = 0; 1231 bool bIsNextRun = bRunNext; 1232 bRunNext = false; // if it was set, then it has to be turned off 1233 1234 do{ // only for middle check loop !! 1235 if( cChar ) 1236 { 1237 //JP 10.02.97: doppelte Spaces verhindern 1238 if( nInsPos && ' ' == cChar && 1239 IsAutoCorrFlag( IgnoreDoubleSpace ) && 1240 ' ' == rTxt.GetChar( nInsPos - 1 ) ) 1241 { 1242 nRet = IgnoreDoubleSpace; 1243 break; 1244 } 1245 1246 sal_Bool bSingle = '\'' == cChar; 1247 sal_Bool bIsReplaceQuote = 1248 (IsAutoCorrFlag( ChgQuotes ) && ('\"' == cChar )) || 1249 (IsAutoCorrFlag( ChgSglQuotes ) && bSingle ); 1250 if( bIsReplaceQuote ) 1251 { 1252 sal_Unicode cPrev; 1253 sal_Bool bSttQuote = !nInsPos || 1254 IsWordDelim( ( cPrev = rTxt.GetChar( nInsPos-1 ))) || 1255 // os: #56034# - Warum kein schliessendes Anfuehrungszeichen nach dem Bindestrich? 1256 // strchr( "-([{", cPrev ) || 1257 lcl_IsInAsciiArr( "([{", cPrev ) || 1258 ( cEmDash && cEmDash == cPrev ) || 1259 ( cEnDash && cEnDash == cPrev ); 1260 1261 InsertQuote( rDoc, nInsPos, cChar, bSttQuote, bInsert ); 1262 nRet = bSingle ? ChgSglQuotes : ChgQuotes; 1263 break; 1264 } 1265 1266 if( bInsert ) 1267 rDoc.Insert( nInsPos, cChar ); 1268 else 1269 rDoc.Replace( nInsPos, cChar ); 1270 1271 // Hardspaces autocorrection 1272 if ( IsAutoCorrFlag( AddNonBrkSpace ) ) 1273 { 1274 if ( NeedsHardspaceAutocorr( cChar ) && 1275 FnAddNonBrkSpace( rDoc, rTxt, 0, nInsPos, rDoc.GetLanguage( nInsPos, sal_False ) ) ) 1276 { 1277 nRet = AddNonBrkSpace; 1278 } 1279 else if ( bIsNextRun && !IsAutoCorrectChar( cChar ) ) 1280 { 1281 // Remove the NBSP if it wasn't an autocorrection 1282 if ( nInsPos != 0 && NeedsHardspaceAutocorr( rTxt.GetChar( nInsPos - 1 ) ) && 1283 cChar != ' ' && cChar != '\t' && cChar != CHAR_HARDBLANK ) 1284 { 1285 // Look for the last HARD_SPACE 1286 xub_StrLen nPos = nInsPos - 1; 1287 bool bContinue = true; 1288 while ( bContinue ) 1289 { 1290 const sal_Unicode cTmpChar = rTxt.GetChar( nPos ); 1291 if ( cTmpChar == CHAR_HARDBLANK ) 1292 { 1293 rDoc.Delete( nPos, nPos + 1 ); 1294 nRet = AddNonBrkSpace; 1295 bContinue = false; 1296 } 1297 else if ( !NeedsHardspaceAutocorr( cTmpChar ) || nPos == 0 ) 1298 bContinue = false; 1299 nPos--; 1300 } 1301 } 1302 } 1303 } 1304 } 1305 1306 if( !nInsPos ) 1307 break; 1308 1309 xub_StrLen nPos = nInsPos - 1; 1310 1311 // Bug 19286: nur direkt hinter dem "Wort" aufsetzen 1312 if( IsWordDelim( rTxt.GetChar( nPos ))) 1313 break; 1314 1315 // automatisches Fett oder Unterstreichen setzen? 1316 if( '*' == cChar || '_' == cChar ) 1317 { 1318 if( IsAutoCorrFlag( ChgWeightUnderl ) && 1319 FnChgWeightUnderl( rDoc, rTxt, 0, nPos+1 ) ) 1320 nRet = ChgWeightUnderl; 1321 break; 1322 } 1323 1324 while( nPos && !IsWordDelim( rTxt.GetChar( --nPos ))) 1325 ; 1326 1327 // Absatz-Anfang oder ein Blank gefunden, suche nach dem Wort 1328 // Kuerzel im Auto 1329 xub_StrLen nCapLttrPos = nPos+1; // auf das 1. Zeichen 1330 if( !nPos && !IsWordDelim( rTxt.GetChar( 0 ))) 1331 --nCapLttrPos; // Absatz Anfang und kein Blank ! 1332 1333 LanguageType eLang = rDoc.GetLanguage( nCapLttrPos, sal_False ); 1334 if( LANGUAGE_SYSTEM == eLang ) 1335 eLang = MsLangId::getSystemLanguage(); 1336 CharClass& rCC = GetCharClass( eLang ); 1337 1338 // no symbol characters 1339 if( lcl_IsSymbolChar( rCC, rTxt, nCapLttrPos, nInsPos )) 1340 break; 1341 1342 if( IsAutoCorrFlag( Autocorrect ) ) 1343 { 1344 const String* pPara = 0; 1345 const String** ppPara = IsAutoCorrFlag(CptlSttSntnc) ? &pPara : 0; 1346 1347 sal_Bool bChgWord = rDoc.ChgAutoCorrWord( nCapLttrPos, nInsPos, 1348 *this, ppPara ); 1349 if( !bChgWord ) 1350 { 1351 // JP 16.06.98: dann versuche mal alle !AlphaNum. Zeichen los zu 1352 // werden und teste dann nochmals 1353 //JP 22.04.99: Bug 63883 - entferne nur die "Klammern Start/-Anfaenge", 1354 // alle anderen Zeichen muessen drin bleiben. 1355 xub_StrLen nCapLttrPos1 = nCapLttrPos, nInsPos1 = nInsPos; 1356 while( nCapLttrPos1 < nInsPos && 1357 lcl_IsInAsciiArr( sImplSttSkipChars, rTxt.GetChar( nCapLttrPos1 ) ) 1358 ) 1359 ++nCapLttrPos1; 1360 while( nCapLttrPos1 < nInsPos1 && nInsPos1 && 1361 lcl_IsInAsciiArr( sImplEndSkipChars, rTxt.GetChar( nInsPos1-1 ) ) 1362 ) 1363 --nInsPos1; 1364 1365 if( (nCapLttrPos1 != nCapLttrPos || nInsPos1 != nInsPos ) && 1366 nCapLttrPos1 < nInsPos1 && 1367 rDoc.ChgAutoCorrWord( nCapLttrPos1, nInsPos1, *this, ppPara )) 1368 { 1369 bChgWord = sal_True; 1370 nCapLttrPos = nCapLttrPos1; 1371 } 1372 } 1373 1374 if( bChgWord ) 1375 { 1376 nRet = Autocorrect; 1377 if( pPara ) 1378 { 1379 xub_StrLen nEnd = nCapLttrPos; 1380 while( nEnd < pPara->Len() && 1381 !IsWordDelim( pPara->GetChar( nEnd ))) 1382 ++nEnd; 1383 1384 // Grossbuchstabe am Satz-Anfang ?? 1385 if( IsAutoCorrFlag( CptlSttSntnc ) && 1386 FnCptlSttSntnc( rDoc, *pPara, sal_False, 1387 nCapLttrPos, nEnd, eLang ) ) 1388 nRet |= CptlSttSntnc; 1389 1390 if( IsAutoCorrFlag( ChgToEnEmDash ) && 1391 FnChgToEnEmDash( rDoc, rTxt, nCapLttrPos, nEnd, eLang ) ) 1392 nRet |= ChgToEnEmDash; 1393 } 1394 break; 1395 } 1396 } 1397 1398 if( ( IsAutoCorrFlag( nRet = ChgOrdinalNumber ) && 1399 FnChgOrdinalNumber( rDoc, rTxt, nCapLttrPos, nInsPos, eLang ) ) || 1400 ( IsAutoCorrFlag( nRet = SetINetAttr ) && 1401 ( ' ' == cChar || '\t' == cChar || 0x0a == cChar || !cChar ) && 1402 FnSetINetAttr( rDoc, rTxt, nCapLttrPos, nInsPos, eLang ) ) ) 1403 ; 1404 else 1405 { 1406 nRet = 0; 1407 bool bUnsupported = lcl_IsUnsupportedUnicodeChar( rCC, rTxt, nCapLttrPos, nInsPos ); 1408 // Grossbuchstabe am Satz-Anfang ?? 1409 if( !bUnsupported && 1410 IsAutoCorrFlag( CptlSttSntnc ) && 1411 FnCptlSttSntnc( rDoc, rTxt, sal_True, nCapLttrPos, nInsPos, eLang ) ) 1412 nRet |= CptlSttSntnc; 1413 1414 // Zwei Grossbuchstaben am Wort-Anfang ?? 1415 if( !bUnsupported && 1416 IsAutoCorrFlag( CptlSttWrd ) && 1417 FnCptlSttWrd( rDoc, rTxt, nCapLttrPos, nInsPos, eLang ) ) 1418 nRet |= CptlSttWrd; 1419 1420 if( IsAutoCorrFlag( ChgToEnEmDash ) && 1421 FnChgToEnEmDash( rDoc, rTxt, nCapLttrPos, nInsPos, eLang ) ) 1422 nRet |= ChgToEnEmDash; 1423 } 1424 1425 } while( sal_False ); 1426 1427 if( nRet ) 1428 { 1429 const char* aHelpIds[] = 1430 { 1431 HID_AUTOCORR_HELP_WORD, 1432 HID_AUTOCORR_HELP_SENT, 1433 HID_AUTOCORR_HELP_SENTWORD, 1434 HID_AUTOCORR_HELP_ACORWORD, 1435 "", 1436 HID_AUTOCORR_HELP_ACORSENTWORD, 1437 "", 1438 HID_AUTOCORR_HELP_CHGTOENEMDASH, 1439 HID_AUTOCORR_HELP_WORDENEMDASH, 1440 HID_AUTOCORR_HELP_SENTENEMDASH, 1441 HID_AUTOCORR_HELP_SENTWORDENEMDASH, 1442 HID_AUTOCORR_HELP_ACORWORDENEMDASH, 1443 "", 1444 HID_AUTOCORR_HELP_ACORSENTWORDENEMDASH, 1445 "", 1446 HID_AUTOCORR_HELP_CHGQUOTES, 1447 HID_AUTOCORR_HELP_CHGSGLQUOTES, 1448 HID_AUTOCORR_HELP_SETINETATTR, 1449 HID_AUTOCORR_HELP_INGNOREDOUBLESPACE, 1450 HID_AUTOCORR_HELP_CHGWEIGHTUNDERL, 1451 HID_AUTOCORR_HELP_CHGFRACTIONSYMBOL, 1452 HID_AUTOCORR_HELP_CHGORDINALNUMBER 1453 }; 1454 1455 sal_uLong nHelpId = 0; 1456 if( nRet & ( Autocorrect|CptlSttSntnc|CptlSttWrd|ChgToEnEmDash ) ) 1457 { 1458 // von 0 - 15 1459 if( nRet & ChgToEnEmDash ) 1460 nHelpId += 8; 1461 if( nRet & Autocorrect ) 1462 nHelpId += 4; 1463 if( nRet & CptlSttSntnc ) 1464 nHelpId += 2; 1465 if( nRet & CptlSttWrd ) 1466 nHelpId += 1; 1467 } 1468 else 1469 { 1470 if( nRet & ChgQuotes) nHelpId = 16; 1471 else if( nRet & ChgSglQuotes) nHelpId = 17; 1472 else if( nRet & SetINetAttr) nHelpId = 18; 1473 else if( nRet & IgnoreDoubleSpace) nHelpId = 19; 1474 else if( nRet & ChgWeightUnderl) nHelpId = 20; 1475 else if( nRet & AddNonBrkSpace) nHelpId = 21; 1476 else if( nRet & ChgOrdinalNumber) nHelpId = 22; 1477 } 1478 1479 if( nHelpId ) 1480 { 1481 nHelpId -= 1; 1482 Application::GetHelp()->OpenHelpAgent( aHelpIds[nHelpId] ); 1483 } 1484 } 1485 1486 1487 return nRet; 1488 } 1489 1490 SvxAutoCorrectLanguageLists& SvxAutoCorrect::_GetLanguageList( 1491 LanguageType eLang ) 1492 { 1493 if( !pLangTable->IsKeyValid( sal_uLong( eLang ))) 1494 CreateLanguageFile( eLang, sal_True); 1495 return *pLangTable->Seek( sal_uLong( eLang ) ); 1496 } 1497 1498 void SvxAutoCorrect::SaveCplSttExceptList( LanguageType eLang ) 1499 { 1500 if( pLangTable->IsKeyValid( sal_uLong( eLang ))) 1501 { 1502 SvxAutoCorrectLanguageListsPtr pLists = pLangTable->Seek(sal_uLong(eLang)); 1503 if( pLists ) 1504 pLists->SaveCplSttExceptList(); 1505 } 1506 #ifdef DBG_UTIL 1507 else 1508 { 1509 DBG_ERROR("speichern einer leeren Liste?"); 1510 } 1511 #endif 1512 } 1513 1514 void SvxAutoCorrect::SaveWrdSttExceptList(LanguageType eLang) 1515 { 1516 if(pLangTable->IsKeyValid(sal_uLong(eLang))) 1517 { 1518 SvxAutoCorrectLanguageListsPtr pLists = pLangTable->Seek(sal_uLong(eLang)); 1519 if(pLists) 1520 pLists->SaveWrdSttExceptList(); 1521 } 1522 #ifdef DBG_UTIL 1523 else 1524 { 1525 DBG_ERROR("speichern einer leeren Liste?"); 1526 } 1527 #endif 1528 } 1529 1530 1531 // fuegt ein einzelnes Wort hinzu. Die Liste wird sofort 1532 // in die Datei geschrieben! 1533 sal_Bool SvxAutoCorrect::AddCplSttException( const String& rNew, 1534 LanguageType eLang ) 1535 { 1536 SvxAutoCorrectLanguageListsPtr pLists = 0; 1537 //entweder die richtige Sprache ist vorhanden oder es kommt in die allg. Liste 1538 if( pLangTable->IsKeyValid(sal_uLong(eLang))) 1539 pLists = pLangTable->Seek(sal_uLong(eLang)); 1540 else if(pLangTable->IsKeyValid(sal_uLong(LANGUAGE_DONTKNOW))|| 1541 CreateLanguageFile(LANGUAGE_DONTKNOW, sal_True)) 1542 { 1543 pLists = pLangTable->Seek(sal_uLong(LANGUAGE_DONTKNOW)); 1544 } 1545 DBG_ASSERT(pLists, "keine Autokorrekturdatei"); 1546 return pLists->AddToCplSttExceptList(rNew); 1547 } 1548 1549 1550 // fuegt ein einzelnes Wort hinzu. Die Liste wird sofort 1551 // in die Datei geschrieben! 1552 sal_Bool SvxAutoCorrect::AddWrtSttException( const String& rNew, 1553 LanguageType eLang ) 1554 { 1555 SvxAutoCorrectLanguageListsPtr pLists = 0; 1556 //entweder die richtige Sprache ist vorhanden oder es kommt in die allg. Liste 1557 if(pLangTable->IsKeyValid(sal_uLong(eLang))) 1558 pLists = pLangTable->Seek(sal_uLong(eLang)); 1559 else if(pLangTable->IsKeyValid(sal_uLong(LANGUAGE_DONTKNOW))|| 1560 CreateLanguageFile(LANGUAGE_DONTKNOW, sal_True)) 1561 pLists = pLangTable->Seek(sal_uLong(LANGUAGE_DONTKNOW)); 1562 DBG_ASSERT(pLists, "keine Autokorrekturdatei"); 1563 return pLists->AddToWrdSttExceptList(rNew); 1564 } 1565 1566 1567 1568 1569 void SvxAutoCorrect::SetUserAutoCorrFileName( const String& rNew ) 1570 { 1571 if( sUserAutoCorrFile != rNew ) 1572 { 1573 sUserAutoCorrFile = rNew; 1574 1575 // sind die Listen gesetzt sind, so muessen sie jetzt geloescht 1576 // werden 1577 lcl_ClearTable(*pLangTable); 1578 nFlags &= ~(CplSttLstLoad | WrdSttLstLoad | ChgWordLstLoad ); 1579 } 1580 } 1581 1582 void SvxAutoCorrect::SetShareAutoCorrFileName( const String& rNew ) 1583 { 1584 if( sShareAutoCorrFile != rNew ) 1585 { 1586 sShareAutoCorrFile = rNew; 1587 1588 // sind die Listen gesetzt sind, so muessen sie jetzt geloescht 1589 // werden 1590 lcl_ClearTable(*pLangTable); 1591 nFlags &= ~(CplSttLstLoad | WrdSttLstLoad | ChgWordLstLoad ); 1592 } 1593 } 1594 1595 1596 sal_Bool SvxAutoCorrect::GetPrevAutoCorrWord( SvxAutoCorrDoc& rDoc, 1597 const String& rTxt, xub_StrLen nPos, 1598 String& rWord ) const 1599 { 1600 if( !nPos ) 1601 return sal_False; 1602 1603 xub_StrLen nEnde = nPos; 1604 1605 // dahinter muss ein Blank oder Tab folgen! 1606 if( ( nPos < rTxt.Len() && 1607 !IsWordDelim( rTxt.GetChar( nPos ))) || 1608 IsWordDelim( rTxt.GetChar( --nPos ))) 1609 return sal_False; 1610 1611 while( nPos && !IsWordDelim( rTxt.GetChar( --nPos ))) 1612 ; 1613 1614 // Absatz-Anfang oder ein Blank gefunden, suche nach dem Wort 1615 // Kuerzel im Auto 1616 xub_StrLen nCapLttrPos = nPos+1; // auf das 1. Zeichen 1617 if( !nPos && !IsWordDelim( rTxt.GetChar( 0 ))) 1618 --nCapLttrPos; // Absatz Anfang und kein Blank ! 1619 1620 while( lcl_IsInAsciiArr( sImplSttSkipChars, rTxt.GetChar( nCapLttrPos )) ) 1621 if( ++nCapLttrPos >= nEnde ) 1622 return sal_False; 1623 1624 // Bug 19285: Symbolzeichen nicht anfassen 1625 // Interresant erst ab 3 Zeichen 1626 if( 3 > nEnde - nCapLttrPos ) 1627 return sal_False; 1628 1629 LanguageType eLang = rDoc.GetLanguage( nCapLttrPos, sal_False ); 1630 if( LANGUAGE_SYSTEM == eLang ) 1631 eLang = MsLangId::getSystemLanguage(); 1632 1633 SvxAutoCorrect* pThis = (SvxAutoCorrect*)this; 1634 CharClass& rCC = pThis->GetCharClass( eLang ); 1635 1636 if( lcl_IsSymbolChar( rCC, rTxt, nCapLttrPos, nEnde )) 1637 return sal_False; 1638 1639 rWord = rTxt.Copy( nCapLttrPos, nEnde - nCapLttrPos ); 1640 return sal_True; 1641 } 1642 1643 sal_Bool SvxAutoCorrect::CreateLanguageFile( LanguageType eLang, sal_Bool bNewFile ) 1644 { 1645 DBG_ASSERT(!pLangTable->IsKeyValid(sal_uLong(eLang)), "Sprache ist bereits vorhanden"); 1646 1647 String sUserDirFile( GetAutoCorrFileName( eLang, sal_True, sal_False )), 1648 sShareDirFile( sUserDirFile ); 1649 SvxAutoCorrectLanguageListsPtr pLists = 0; 1650 1651 Time nMinTime( 0, 2 ), nAktTime, nLastCheckTime; 1652 sal_uLong nFndPos; 1653 if( TABLE_ENTRY_NOTFOUND != 1654 pLastFileTable->SearchKey( sal_uLong( eLang ), &nFndPos ) && 1655 ( nLastCheckTime.SetTime( pLastFileTable->GetObject( nFndPos )), 1656 nLastCheckTime < nAktTime ) && 1657 ( nAktTime - nLastCheckTime ) < nMinTime ) 1658 { 1659 // no need to test the file, because the last check is not older then 1660 // 2 minutes. 1661 if( bNewFile ) 1662 { 1663 sShareDirFile = sUserDirFile; 1664 pLists = new SvxAutoCorrectLanguageLists( *this, sShareDirFile, 1665 sUserDirFile, eLang ); 1666 pLangTable->Insert( sal_uLong(eLang), pLists ); 1667 pLastFileTable->Remove( sal_uLong( eLang ) ); 1668 } 1669 } 1670 else if( ( FStatHelper::IsDocument( sUserDirFile ) || 1671 FStatHelper::IsDocument( sShareDirFile = 1672 GetAutoCorrFileName( eLang, sal_False, sal_False ) ) ) || 1673 ( sShareDirFile = sUserDirFile, bNewFile )) 1674 { 1675 pLists = new SvxAutoCorrectLanguageLists( *this, sShareDirFile, 1676 sUserDirFile, eLang ); 1677 pLangTable->Insert( sal_uLong(eLang), pLists ); 1678 pLastFileTable->Remove( sal_uLong( eLang ) ); 1679 } 1680 else if( !bNewFile ) 1681 { 1682 if( !pLastFileTable->Insert( sal_uLong( eLang ), nAktTime.GetTime() )) 1683 pLastFileTable->Replace( sal_uLong( eLang ), nAktTime.GetTime() ); 1684 } 1685 return pLists != 0; 1686 } 1687 1688 sal_Bool SvxAutoCorrect::PutText( const String& rShort, const String& rLong, 1689 LanguageType eLang ) 1690 { 1691 sal_Bool bRet = sal_False; 1692 if( pLangTable->IsKeyValid( sal_uLong(eLang)) || CreateLanguageFile(eLang) ) 1693 bRet = pLangTable->Seek( sal_uLong(eLang) )->PutText(rShort, rLong); 1694 return bRet; 1695 } 1696 1697 1698 // - loesche einen Eintrag 1699 sal_Bool SvxAutoCorrect::DeleteText( const String& rShort, LanguageType eLang ) 1700 { 1701 sal_Bool bRet = sal_False; 1702 if( pLangTable->IsKeyValid( sal_uLong( eLang )) ) 1703 bRet = pLangTable->Seek( sal_uLong( eLang ))->DeleteText( rShort ); 1704 return bRet; 1705 } 1706 1707 1708 // - return den Ersetzungstext (nur fuer SWG-Format, alle anderen 1709 // koennen aus der Wortliste herausgeholt werden!) 1710 sal_Bool SvxAutoCorrect::GetLongText( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >&, const String&, const String& , String& ) 1711 { 1712 return sal_False; 1713 } 1714 1715 // - Text mit Attributierung (kann nur der SWG - SWG-Format!) 1716 sal_Bool SvxAutoCorrect::PutText( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >&, const String&, const String&, SfxObjectShell&, 1717 String& ) 1718 { 1719 return sal_False; 1720 } 1721 1722 void EncryptBlockName_Imp( String& rName ) 1723 { 1724 xub_StrLen nLen, nPos = 1; 1725 rName.Insert( '#', 0 ); 1726 sal_Unicode* pName = rName.GetBufferAccess(); 1727 for ( nLen = rName.Len(), ++pName; nPos < nLen; ++nPos, ++pName ) 1728 { 1729 if( lcl_IsInAsciiArr( "!/:.\\", *pName )) 1730 *pName &= 0x0f; 1731 } 1732 } 1733 1734 /* This code is copied from SwXMLTextBlocks::GeneratePackageName */ 1735 void GeneratePackageName ( const String& rShort, String& rPackageName ) 1736 { 1737 rPackageName = rShort; 1738 xub_StrLen nPos = 0; 1739 sal_Unicode pDelims[] = { '!', '/', ':', '.', '\\', 0 }; 1740 ByteString sByte ( rPackageName, RTL_TEXTENCODING_UTF7); 1741 rPackageName = String (sByte, RTL_TEXTENCODING_ASCII_US); 1742 while( STRING_NOTFOUND != ( nPos = rPackageName.SearchChar( pDelims, nPos ))) 1743 { 1744 rPackageName.SetChar( nPos, '_' ); 1745 ++nPos; 1746 } 1747 } 1748 1749 void DecryptBlockName_Imp( String& rName ) 1750 { 1751 if( '#' == rName.GetChar( 0 ) ) 1752 { 1753 rName.Erase( 0, 1 ); 1754 sal_Unicode* pName = rName.GetBufferAccess(); 1755 xub_StrLen nLen, nPos; 1756 for ( nLen = rName.Len(), nPos = 0; nPos < nLen; ++nPos, ++pName ) 1757 switch( *pName ) 1758 { 1759 case 0x01: *pName = '!'; break; 1760 case 0x0A: *pName = ':'; break; 1761 case 0x0C: *pName = '\\'; break; 1762 case 0x0E: *pName = '.'; break; 1763 case 0x0F: *pName = '/'; break; 1764 } 1765 } 1766 } 1767 1768 1769 /* -----------------18.11.98 16:00------------------- 1770 * 1771 * --------------------------------------------------*/ 1772 const SvxAutocorrWord* lcl_SearchWordsInList( 1773 SvxAutoCorrectLanguageListsPtr pList, const String& rTxt, 1774 xub_StrLen& rStt, xub_StrLen nEndPos, SvxAutoCorrDoc& ) 1775 { 1776 const SvxAutocorrWordList* pAutoCorrWordList = pList->GetAutocorrWordList(); 1777 TransliterationWrapper& rCmp = GetIgnoreTranslWrapper(); 1778 for( xub_StrLen nPos = 0; nPos < pAutoCorrWordList->Count(); ++nPos ) 1779 { 1780 const SvxAutocorrWord* pFnd = (*pAutoCorrWordList)[ nPos ]; 1781 const String& rChk = pFnd->GetShort(); 1782 if( nEndPos >= rChk.Len() ) 1783 { 1784 xub_StrLen nCalcStt = nEndPos - rChk.Len(); 1785 if( ( !nCalcStt || nCalcStt == rStt || 1786 ( nCalcStt < rStt && 1787 IsWordDelim( rTxt.GetChar(nCalcStt - 1 ) ))) ) 1788 { 1789 String sWord( rTxt.GetBuffer() + nCalcStt, rChk.Len() ); 1790 if( rCmp.isEqual( rChk, sWord )) 1791 { 1792 rStt = nCalcStt; 1793 return pFnd; 1794 } 1795 } 1796 } 1797 } 1798 return 0; 1799 } 1800 1801 1802 // suche das oder die Worte in der ErsetzungsTabelle 1803 const SvxAutocorrWord* SvxAutoCorrect::SearchWordsInList( 1804 const String& rTxt, xub_StrLen& rStt, xub_StrLen nEndPos, 1805 SvxAutoCorrDoc& rDoc, LanguageType& rLang ) 1806 { 1807 LanguageType eLang = rLang; 1808 const SvxAutocorrWord* pRet = 0; 1809 if( LANGUAGE_SYSTEM == eLang ) 1810 eLang = MsLangId::getSystemLanguage(); 1811 1812 // zuerst nach eLang suchen, dann nach der Obersprache 1813 // US-Englisch -> Englisch und zuletzt in LANGUAGE_DONTKNOW 1814 1815 if( pLangTable->IsKeyValid( sal_uLong( eLang ) ) || 1816 CreateLanguageFile( eLang, sal_False )) 1817 { 1818 //die Sprache ist vorhanden - also her damit 1819 SvxAutoCorrectLanguageListsPtr pList = pLangTable->Seek(sal_uLong(eLang)); 1820 pRet = lcl_SearchWordsInList( pList, rTxt, rStt, nEndPos, rDoc ); 1821 if( pRet ) 1822 { 1823 rLang = eLang; 1824 return pRet; 1825 } 1826 } 1827 1828 // wenn es hier noch nicht gefunden werden konnte, dann weitersuchen 1829 sal_uLong nTmpKey1 = eLang & 0x7ff, // die Hauptsprache in vielen Faellen u.B. DE 1830 nTmpKey2 = eLang & 0x3ff, // sonst z.B. EN 1831 nTmp; 1832 1833 if( ((nTmp = nTmpKey1) != (sal_uLong)eLang && 1834 ( pLangTable->IsKeyValid( nTmpKey1 ) || 1835 CreateLanguageFile( LanguageType( nTmpKey1 ), sal_False ) )) || 1836 (( nTmp = nTmpKey2) != (sal_uLong)eLang && 1837 ( pLangTable->IsKeyValid( nTmpKey2 ) || 1838 CreateLanguageFile( LanguageType( nTmpKey2 ), sal_False ) )) ) 1839 { 1840 //die Sprache ist vorhanden - also her damit 1841 SvxAutoCorrectLanguageListsPtr pList = pLangTable->Seek( nTmp ); 1842 pRet = lcl_SearchWordsInList( pList, rTxt, rStt, nEndPos, rDoc); 1843 if( pRet ) 1844 { 1845 rLang = LanguageType( nTmp ); 1846 return pRet; 1847 } 1848 } 1849 if( pLangTable->IsKeyValid( sal_uLong( LANGUAGE_DONTKNOW ) ) || 1850 CreateLanguageFile( LANGUAGE_DONTKNOW, sal_False ) ) 1851 { 1852 //die Sprache ist vorhanden - also her damit 1853 SvxAutoCorrectLanguageListsPtr pList = pLangTable->Seek(sal_uLong(LANGUAGE_DONTKNOW)); 1854 pRet = lcl_SearchWordsInList( pList, rTxt, rStt, nEndPos, rDoc); 1855 if( pRet ) 1856 { 1857 rLang = LANGUAGE_DONTKNOW; 1858 return pRet; 1859 } 1860 } 1861 return 0; 1862 } 1863 /* -----------------18.11.98 13:46------------------- 1864 * 1865 * --------------------------------------------------*/ 1866 sal_Bool SvxAutoCorrect::FindInWrdSttExceptList( LanguageType eLang, 1867 const String& sWord ) 1868 { 1869 //zuerst nach eLang suchen, dann nach der Obersprace US-Englisch -> Englisch 1870 //und zuletzt in LANGUAGE_DONTKNOW 1871 sal_uLong nTmpKey1 = eLang & 0x7ff; // die Hauptsprache in vielen Faellen u.B. DE 1872 sal_uLong nTmpKey2 = eLang & 0x3ff; // sonst z.B. EN 1873 String sTemp(sWord); 1874 if( pLangTable->IsKeyValid( sal_uLong( eLang )) || 1875 CreateLanguageFile( eLang, sal_False ) ) 1876 { 1877 //die Sprache ist vorhanden - also her damit 1878 SvxAutoCorrectLanguageListsPtr pList = pLangTable->Seek(sal_uLong(eLang)); 1879 String _sTemp(sWord); 1880 if(pList->GetWrdSttExceptList()->Seek_Entry(&_sTemp)) 1881 return sal_True; 1882 1883 } 1884 // wenn es hier noch nicht gefunden werden konnte, dann weitersuchen 1885 sal_uLong nTmp; 1886 if( ((nTmp = nTmpKey1) != (sal_uLong)eLang && 1887 ( pLangTable->IsKeyValid( nTmpKey1 ) || 1888 CreateLanguageFile( LanguageType( nTmpKey1 ), sal_False ) )) || 1889 (( nTmp = nTmpKey2) != (sal_uLong)eLang && 1890 ( pLangTable->IsKeyValid( nTmpKey2 ) || 1891 CreateLanguageFile( LanguageType( nTmpKey2 ), sal_False ) )) ) 1892 { 1893 //die Sprache ist vorhanden - also her damit 1894 SvxAutoCorrectLanguageListsPtr pList = pLangTable->Seek(nTmp); 1895 if(pList->GetWrdSttExceptList()->Seek_Entry(&sTemp)) 1896 return sal_True; 1897 } 1898 if(pLangTable->IsKeyValid(sal_uLong(LANGUAGE_DONTKNOW))|| CreateLanguageFile(LANGUAGE_DONTKNOW, sal_False)) 1899 { 1900 //die Sprache ist vorhanden - also her damit 1901 SvxAutoCorrectLanguageListsPtr pList = pLangTable->Seek(sal_uLong(LANGUAGE_DONTKNOW)); 1902 if(pList->GetWrdSttExceptList()->Seek_Entry(&sTemp)) 1903 return sal_True; 1904 } 1905 return sal_False; 1906 } 1907 /* -----------------18.11.98 14:28------------------- 1908 * 1909 * --------------------------------------------------*/ 1910 sal_Bool lcl_FindAbbreviation( const SvStringsISortDtor* pList, const String& sWord) 1911 { 1912 String sAbk( '~' ); 1913 sal_uInt16 nPos; 1914 pList->Seek_Entry( &sAbk, &nPos ); 1915 if( nPos < pList->Count() ) 1916 { 1917 String sLowerWord( sWord ); sLowerWord.ToLowerAscii(); 1918 const String* pAbk; 1919 for( sal_uInt16 n = nPos; 1920 n < pList->Count() && 1921 '~' == ( pAbk = (*pList)[ n ])->GetChar( 0 ); 1922 ++n ) 1923 { 1924 // ~ und ~. sind nicht erlaubt! 1925 if( 2 < pAbk->Len() && pAbk->Len() - 1 <= sWord.Len() ) 1926 { 1927 String sLowerAbk( *pAbk ); sLowerAbk.ToLowerAscii(); 1928 for( xub_StrLen i = sLowerAbk.Len(), ii = sLowerWord.Len(); i; ) 1929 { 1930 if( !--i ) // stimmt ueberein 1931 return sal_True; 1932 1933 if( sLowerAbk.GetChar( i ) != sLowerWord.GetChar( --ii )) 1934 break; 1935 } 1936 } 1937 } 1938 } 1939 DBG_ASSERT( !(nPos && '~' == (*pList)[ --nPos ]->GetChar( 0 ) ), 1940 "falsch sortierte ExeptionListe?" ); 1941 return sal_False; 1942 } 1943 /* -----------------18.11.98 14:49------------------- 1944 * 1945 * --------------------------------------------------*/ 1946 sal_Bool SvxAutoCorrect::FindInCplSttExceptList(LanguageType eLang, 1947 const String& sWord, sal_Bool bAbbreviation) 1948 { 1949 //zuerst nach eLang suchen, dann nach der Obersprace US-Englisch -> Englisch 1950 //und zuletzt in LANGUAGE_DONTKNOW 1951 sal_uLong nTmpKey1 = eLang & 0x7ff; // die Hauptsprache in vielen Faellen u.B. DE 1952 sal_uLong nTmpKey2 = eLang & 0x3ff; // sonst z.B. EN 1953 String sTemp( sWord ); 1954 if( pLangTable->IsKeyValid( sal_uLong( eLang )) || 1955 CreateLanguageFile( eLang, sal_False )) 1956 { 1957 //die Sprache ist vorhanden - also her damit 1958 SvxAutoCorrectLanguageListsPtr pLists = pLangTable->Seek(sal_uLong(eLang)); 1959 const SvStringsISortDtor* pList = pLists->GetCplSttExceptList(); 1960 if(bAbbreviation ? lcl_FindAbbreviation( pList, sWord) 1961 : pList->Seek_Entry( &sTemp ) ) 1962 return sal_True; 1963 } 1964 // wenn es hier noch nicht gefunden werden konnte, dann weitersuchen 1965 sal_uLong nTmp; 1966 1967 if( ((nTmp = nTmpKey1) != (sal_uLong)eLang && 1968 ( pLangTable->IsKeyValid( nTmpKey1 ) || 1969 CreateLanguageFile( LanguageType( nTmpKey1 ), sal_False ) )) || 1970 (( nTmp = nTmpKey2) != (sal_uLong)eLang && 1971 ( pLangTable->IsKeyValid( nTmpKey2 ) || 1972 CreateLanguageFile( LanguageType( nTmpKey2 ), sal_False ) )) ) 1973 { 1974 //die Sprache ist vorhanden - also her damit 1975 SvxAutoCorrectLanguageListsPtr pLists = pLangTable->Seek(nTmp); 1976 const SvStringsISortDtor* pList = pLists->GetCplSttExceptList(); 1977 if(bAbbreviation ? lcl_FindAbbreviation( pList, sWord) 1978 : pList->Seek_Entry( &sTemp ) ) 1979 return sal_True; 1980 } 1981 if(pLangTable->IsKeyValid(sal_uLong(LANGUAGE_DONTKNOW))|| CreateLanguageFile(LANGUAGE_DONTKNOW, sal_False)) 1982 { 1983 //die Sprache ist vorhanden - also her damit 1984 SvxAutoCorrectLanguageListsPtr pLists = pLangTable->Seek(LANGUAGE_DONTKNOW); 1985 const SvStringsISortDtor* pList = pLists->GetCplSttExceptList(); 1986 if(bAbbreviation ? lcl_FindAbbreviation( pList, sWord) 1987 : pList->Seek_Entry( &sTemp ) ) 1988 return sal_True; 1989 } 1990 return sal_False; 1991 1992 } 1993 1994 /* -----------------20.11.98 11:53------------------- 1995 * 1996 * --------------------------------------------------*/ 1997 String SvxAutoCorrect::GetAutoCorrFileName( LanguageType eLang, 1998 sal_Bool bNewFile, sal_Bool bTst ) const 1999 { 2000 String sRet, sExt( MsLangId::convertLanguageToIsoString( eLang ) ); 2001 sExt.Insert('_', 0); 2002 sExt.AppendAscii( ".dat" ); 2003 if( bNewFile ) 2004 ( sRet = sUserAutoCorrFile ) += sExt; 2005 else if( !bTst ) 2006 ( sRet = sShareAutoCorrFile ) += sExt; 2007 else 2008 { 2009 // test first in the user directory - if not exist, then 2010 ( sRet = sUserAutoCorrFile ) += sExt; 2011 if( !FStatHelper::IsDocument( sRet )) 2012 ( sRet = sShareAutoCorrFile ) += sExt; 2013 } 2014 return sRet; 2015 } 2016 2017 /* -----------------18.11.98 11:16------------------- 2018 * 2019 * --------------------------------------------------*/ 2020 SvxAutoCorrectLanguageLists::SvxAutoCorrectLanguageLists( 2021 SvxAutoCorrect& rParent, 2022 const String& rShareAutoCorrectFile, 2023 const String& rUserAutoCorrectFile, 2024 LanguageType eLang) 2025 : sShareAutoCorrFile( rShareAutoCorrectFile ), 2026 sUserAutoCorrFile( rUserAutoCorrectFile ), 2027 eLanguage(eLang), 2028 pCplStt_ExcptLst( 0 ), 2029 pWrdStt_ExcptLst( 0 ), 2030 pAutocorr_List( 0 ), 2031 rAutoCorrect(rParent), 2032 nFlags(0) 2033 { 2034 } 2035 2036 /* -----------------18.11.98 11:16------------------- 2037 * 2038 * --------------------------------------------------*/ 2039 SvxAutoCorrectLanguageLists::~SvxAutoCorrectLanguageLists() 2040 { 2041 delete pCplStt_ExcptLst; 2042 delete pWrdStt_ExcptLst; 2043 delete pAutocorr_List; 2044 } 2045 2046 /* -----------------18.11.98 11:26------------------- 2047 * 2048 * --------------------------------------------------*/ 2049 sal_Bool SvxAutoCorrectLanguageLists::IsFileChanged_Imp() 2050 { 2051 // nur alle 2 Minuten aufs FileSystem zugreifen um den 2052 // Dateistempel zu ueberpruefen 2053 sal_Bool bRet = sal_False; 2054 2055 Time nMinTime( 0, 2 ); 2056 Time nAktTime; 2057 if( aLastCheckTime > nAktTime || // ueberlauf ? 2058 ( nAktTime -= aLastCheckTime ) > nMinTime ) // min Zeit vergangen 2059 { 2060 Date aTstDate; Time aTstTime; 2061 if( FStatHelper::GetModifiedDateTimeOfFile( sShareAutoCorrFile, 2062 &aTstDate, &aTstTime ) && 2063 ( aModifiedDate != aTstDate || aModifiedTime != aTstTime )) 2064 { 2065 bRet = sal_True; 2066 // dann mal schnell alle Listen entfernen! 2067 if( CplSttLstLoad & nFlags && pCplStt_ExcptLst ) 2068 delete pCplStt_ExcptLst, pCplStt_ExcptLst = 0; 2069 if( WrdSttLstLoad & nFlags && pWrdStt_ExcptLst ) 2070 delete pWrdStt_ExcptLst, pWrdStt_ExcptLst = 0; 2071 if( ChgWordLstLoad & nFlags && pAutocorr_List ) 2072 delete pAutocorr_List, pAutocorr_List = 0; 2073 nFlags &= ~(CplSttLstLoad | WrdSttLstLoad | ChgWordLstLoad ); 2074 } 2075 aLastCheckTime = Time(); 2076 } 2077 return bRet; 2078 } 2079 2080 void SvxAutoCorrectLanguageLists::LoadXMLExceptList_Imp( 2081 SvStringsISortDtor*& rpLst, 2082 const sal_Char* pStrmName, 2083 SotStorageRef& rStg) 2084 { 2085 if( rpLst ) 2086 rpLst->DeleteAndDestroy( 0, rpLst->Count() ); 2087 else 2088 rpLst = new SvStringsISortDtor( 16, 16 ); 2089 2090 { 2091 String sStrmName( pStrmName, RTL_TEXTENCODING_MS_1252 ); 2092 String sTmp( sStrmName ); 2093 2094 if( rStg.Is() && rStg->IsStream( sStrmName ) ) 2095 { 2096 SvStorageStreamRef xStrm = rStg->OpenSotStream( sTmp, 2097 ( STREAM_READ | STREAM_SHARE_DENYWRITE | STREAM_NOCREATE ) ); 2098 if( SVSTREAM_OK != xStrm->GetError()) 2099 { 2100 xStrm.Clear(); 2101 rStg.Clear(); 2102 RemoveStream_Imp( sStrmName ); 2103 } 2104 else 2105 { 2106 uno::Reference< lang::XMultiServiceFactory > xServiceFactory = 2107 comphelper::getProcessServiceFactory(); 2108 DBG_ASSERT( xServiceFactory.is(), 2109 "XMLReader::Read: got no service manager" ); 2110 if( !xServiceFactory.is() ) 2111 { 2112 // Throw an exception ? 2113 } 2114 2115 xml::sax::InputSource aParserInput; 2116 aParserInput.sSystemId = sStrmName; 2117 2118 xStrm->Seek( 0L ); 2119 xStrm->SetBufferSize( 8 * 1024 ); 2120 aParserInput.aInputStream = new utl::OInputStreamWrapper( *xStrm ); 2121 2122 // get parser 2123 uno::Reference< XInterface > xXMLParser = xServiceFactory->createInstance( 2124 OUString::createFromAscii("com.sun.star.xml.sax.Parser") ); 2125 DBG_ASSERT( xXMLParser.is(), 2126 "XMLReader::Read: com.sun.star.xml.sax.Parser service missing" ); 2127 if( !xXMLParser.is() ) 2128 { 2129 // Maybe throw an exception? 2130 } 2131 2132 // get filter 2133 // #110680# 2134 // uno::Reference< xml::sax::XDocumentHandler > xFilter = new SvXMLExceptionListImport ( *rpLst ); 2135 uno::Reference< xml::sax::XDocumentHandler > xFilter = new SvXMLExceptionListImport ( xServiceFactory, *rpLst ); 2136 2137 // connect parser and filter 2138 uno::Reference< xml::sax::XParser > xParser( xXMLParser, UNO_QUERY ); 2139 xParser->setDocumentHandler( xFilter ); 2140 2141 // parse 2142 try 2143 { 2144 xParser->parseStream( aParserInput ); 2145 } 2146 catch( xml::sax::SAXParseException& ) 2147 { 2148 // re throw ? 2149 } 2150 catch( xml::sax::SAXException& ) 2151 { 2152 // re throw ? 2153 } 2154 catch( io::IOException& ) 2155 { 2156 // re throw ? 2157 } 2158 } 2159 } 2160 2161 // Zeitstempel noch setzen 2162 FStatHelper::GetModifiedDateTimeOfFile( sShareAutoCorrFile, 2163 &aModifiedDate, &aModifiedTime ); 2164 aLastCheckTime = Time(); 2165 } 2166 2167 } 2168 /* -----------------18.11.98 11:26------------------- 2169 * 2170 * --------------------------------------------------*/ 2171 void SvxAutoCorrectLanguageLists::SaveExceptList_Imp( 2172 const SvStringsISortDtor& rLst, 2173 const sal_Char* pStrmName, 2174 SotStorageRef &rStg, 2175 sal_Bool bConvert ) 2176 { 2177 if( rStg.Is() ) 2178 { 2179 String sStrmName( pStrmName, RTL_TEXTENCODING_MS_1252 ); 2180 if( !rLst.Count() ) 2181 { 2182 rStg->Remove( sStrmName ); 2183 rStg->Commit(); 2184 } 2185 else 2186 { 2187 SotStorageStreamRef xStrm = rStg->OpenSotStream( sStrmName, 2188 ( STREAM_READ | STREAM_WRITE | STREAM_SHARE_DENYWRITE ) ); 2189 if( xStrm.Is() ) 2190 { 2191 xStrm->SetSize( 0 ); 2192 xStrm->SetBufferSize( 8192 ); 2193 String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) ); 2194 OUString aMime( RTL_CONSTASCII_USTRINGPARAM("text/xml") ); 2195 uno::Any aAny; 2196 aAny <<= aMime; 2197 xStrm->SetProperty( aPropName, aAny ); 2198 2199 2200 uno::Reference< lang::XMultiServiceFactory > xServiceFactory = 2201 comphelper::getProcessServiceFactory(); 2202 DBG_ASSERT( xServiceFactory.is(), 2203 "XMLReader::Read: got no service manager" ); 2204 if( !xServiceFactory.is() ) 2205 { 2206 // Throw an exception ? 2207 } 2208 2209 uno::Reference < XInterface > xWriter (xServiceFactory->createInstance( 2210 OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Writer")))); 2211 DBG_ASSERT(xWriter.is(),"com.sun.star.xml.sax.Writer service missing"); 2212 uno::Reference < io::XOutputStream> xOut = new utl::OOutputStreamWrapper( *xStrm ); 2213 uno::Reference<io::XActiveDataSource> xSrc(xWriter, uno::UNO_QUERY); 2214 xSrc->setOutputStream(xOut); 2215 2216 uno::Reference<xml::sax::XDocumentHandler> xHandler(xWriter, uno::UNO_QUERY); 2217 2218 // #110680# 2219 // SvXMLExceptionListExport aExp(rLst, sStrmName, xHandler); 2220 SvXMLExceptionListExport aExp( xServiceFactory, rLst, sStrmName, xHandler ); 2221 2222 aExp.exportDoc( XML_BLOCK_LIST ); 2223 2224 xStrm->Commit(); 2225 if( xStrm->GetError() == SVSTREAM_OK ) 2226 { 2227 xStrm.Clear(); 2228 if (!bConvert) 2229 { 2230 rStg->Commit(); 2231 if( SVSTREAM_OK != rStg->GetError() ) 2232 { 2233 rStg->Remove( sStrmName ); 2234 rStg->Commit(); 2235 } 2236 } 2237 } 2238 } 2239 } 2240 } 2241 } 2242 /* -----------------18.11.98 11:26------------------- 2243 * 2244 * --------------------------------------------------*/ 2245 SvxAutocorrWordList* SvxAutoCorrectLanguageLists::LoadAutocorrWordList() 2246 { 2247 if( pAutocorr_List ) 2248 pAutocorr_List->DeleteAndDestroy( 0, pAutocorr_List->Count() ); 2249 else 2250 pAutocorr_List = new SvxAutocorrWordList( 16, 16 ); 2251 2252 SvStringsDtor aRemoveArr; 2253 try 2254 { 2255 uno::Reference < embed::XStorage > xStg = comphelper::OStorageHelper::GetStorageFromURL( sShareAutoCorrFile, embed::ElementModes::READ ); 2256 String aXMLWordListName( pXMLImplAutocorr_ListStr, RTL_TEXTENCODING_MS_1252 ); 2257 uno::Reference < io::XStream > xStrm = xStg->openStreamElement( aXMLWordListName, embed::ElementModes::READ ); 2258 uno::Reference< lang::XMultiServiceFactory > xServiceFactory = comphelper::getProcessServiceFactory(); 2259 2260 xml::sax::InputSource aParserInput; 2261 aParserInput.sSystemId = aXMLWordListName; 2262 aParserInput.aInputStream = xStrm->getInputStream(); 2263 2264 // get parser 2265 uno::Reference< XInterface > xXMLParser = xServiceFactory->createInstance( OUString::createFromAscii("com.sun.star.xml.sax.Parser") ); 2266 DBG_ASSERT( xXMLParser.is(), "XMLReader::Read: com.sun.star.xml.sax.Parser service missing" ); 2267 if( xXMLParser.is() ) 2268 { 2269 uno::Reference< xml::sax::XDocumentHandler > xFilter = new SvXMLAutoCorrectImport( xServiceFactory, pAutocorr_List, rAutoCorrect, xStg ); 2270 2271 // connect parser and filter 2272 uno::Reference< xml::sax::XParser > xParser( xXMLParser, UNO_QUERY ); 2273 xParser->setDocumentHandler( xFilter ); 2274 2275 // parse 2276 xParser->parseStream( aParserInput ); 2277 } 2278 } 2279 catch ( uno::Exception& ) 2280 { 2281 } 2282 2283 // Zeitstempel noch setzen 2284 FStatHelper::GetModifiedDateTimeOfFile( sShareAutoCorrFile, 2285 &aModifiedDate, &aModifiedTime ); 2286 aLastCheckTime = Time(); 2287 2288 return pAutocorr_List; 2289 } 2290 2291 /* -----------------18.11.98 11:26------------------- 2292 * 2293 * --------------------------------------------------*/ 2294 2295 void SvxAutoCorrectLanguageLists::SetAutocorrWordList( SvxAutocorrWordList* pList ) 2296 { 2297 if( pAutocorr_List && pList != pAutocorr_List ) 2298 delete pAutocorr_List; 2299 pAutocorr_List = pList; 2300 if( !pAutocorr_List ) 2301 { 2302 DBG_ASSERT( !this, "keine gueltige Liste" ); 2303 pAutocorr_List = new SvxAutocorrWordList( 16, 16 ); 2304 } 2305 nFlags |= ChgWordLstLoad; 2306 } 2307 2308 /* -----------------18.11.98 11:26------------------- 2309 * 2310 * --------------------------------------------------*/ 2311 const SvxAutocorrWordList* SvxAutoCorrectLanguageLists::GetAutocorrWordList() 2312 { 2313 if( !( ChgWordLstLoad & nFlags ) || IsFileChanged_Imp() ) 2314 SetAutocorrWordList( LoadAutocorrWordList() ); 2315 return pAutocorr_List; 2316 } 2317 /* -----------------18.11.98 11:26------------------- 2318 * 2319 * --------------------------------------------------*/ 2320 SvStringsISortDtor* SvxAutoCorrectLanguageLists::GetCplSttExceptList() 2321 { 2322 if( !( CplSttLstLoad & nFlags ) || IsFileChanged_Imp() ) 2323 SetCplSttExceptList( LoadCplSttExceptList() ); 2324 return pCplStt_ExcptLst; 2325 } 2326 /* -----------------18.11.98 11:26------------------- 2327 * 2328 * --------------------------------------------------*/ 2329 sal_Bool SvxAutoCorrectLanguageLists::AddToCplSttExceptList(const String& rNew) 2330 { 2331 String* pNew = new String( rNew ); 2332 if( rNew.Len() && GetCplSttExceptList()->Insert( pNew ) ) 2333 { 2334 MakeUserStorage_Impl(); 2335 SotStorageRef xStg = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, sal_True ); 2336 2337 SaveExceptList_Imp( *pCplStt_ExcptLst, pXMLImplCplStt_ExcptLstStr, xStg ); 2338 2339 xStg = 0; 2340 // Zeitstempel noch setzen 2341 FStatHelper::GetModifiedDateTimeOfFile( sUserAutoCorrFile, 2342 &aModifiedDate, &aModifiedTime ); 2343 aLastCheckTime = Time(); 2344 } 2345 else 2346 delete pNew, pNew = 0; 2347 return 0 != pNew; 2348 } 2349 /* -----------------18.11.98 15:20------------------- 2350 * 2351 * --------------------------------------------------*/ 2352 sal_Bool SvxAutoCorrectLanguageLists::AddToWrdSttExceptList(const String& rNew) 2353 { 2354 String* pNew = new String( rNew ); 2355 SvStringsISortDtor* pExceptList = LoadWrdSttExceptList(); 2356 if( rNew.Len() && pExceptList && pExceptList->Insert( pNew ) ) 2357 { 2358 MakeUserStorage_Impl(); 2359 SotStorageRef xStg = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, sal_True ); 2360 2361 SaveExceptList_Imp( *pWrdStt_ExcptLst, pXMLImplWrdStt_ExcptLstStr, xStg ); 2362 2363 xStg = 0; 2364 // Zeitstempel noch setzen 2365 FStatHelper::GetModifiedDateTimeOfFile( sUserAutoCorrFile, 2366 &aModifiedDate, &aModifiedTime ); 2367 aLastCheckTime = Time(); 2368 } 2369 else 2370 delete pNew, pNew = 0; 2371 return 0 != pNew; 2372 } 2373 2374 /* -----------------18.11.98 11:26------------------- 2375 * 2376 * --------------------------------------------------*/ 2377 SvStringsISortDtor* SvxAutoCorrectLanguageLists::LoadCplSttExceptList() 2378 { 2379 SotStorageRef xStg = new SotStorage( sShareAutoCorrFile, STREAM_READ | STREAM_SHARE_DENYNONE, sal_True ); 2380 String sTemp ( RTL_CONSTASCII_USTRINGPARAM ( pXMLImplCplStt_ExcptLstStr ) ); 2381 if( xStg.Is() && xStg->IsContained( sTemp ) ) 2382 LoadXMLExceptList_Imp( pCplStt_ExcptLst, pXMLImplCplStt_ExcptLstStr, xStg ); 2383 2384 return pCplStt_ExcptLst; 2385 } 2386 2387 /* -----------------18.11.98 11:26------------------- 2388 * 2389 * --------------------------------------------------*/ 2390 void SvxAutoCorrectLanguageLists::SaveCplSttExceptList() 2391 { 2392 MakeUserStorage_Impl(); 2393 SotStorageRef xStg = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, sal_True ); 2394 2395 SaveExceptList_Imp( *pCplStt_ExcptLst, pXMLImplCplStt_ExcptLstStr, xStg ); 2396 2397 xStg = 0; 2398 2399 // Zeitstempel noch setzen 2400 FStatHelper::GetModifiedDateTimeOfFile( sUserAutoCorrFile, 2401 &aModifiedDate, &aModifiedTime ); 2402 aLastCheckTime = Time(); 2403 } 2404 2405 /* -----------------18.11.98 11:26------------------- 2406 * 2407 * --------------------------------------------------*/ 2408 void SvxAutoCorrectLanguageLists::SetCplSttExceptList( SvStringsISortDtor* pList ) 2409 { 2410 if( pCplStt_ExcptLst && pList != pCplStt_ExcptLst ) 2411 delete pCplStt_ExcptLst; 2412 2413 pCplStt_ExcptLst = pList; 2414 if( !pCplStt_ExcptLst ) 2415 { 2416 DBG_ASSERT( !this, "keine gueltige Liste" ); 2417 pCplStt_ExcptLst = new SvStringsISortDtor( 16, 16 ); 2418 } 2419 nFlags |= CplSttLstLoad; 2420 } 2421 /* -----------------18.11.98 11:26------------------- 2422 * 2423 * --------------------------------------------------*/ 2424 SvStringsISortDtor* SvxAutoCorrectLanguageLists::LoadWrdSttExceptList() 2425 { 2426 SotStorageRef xStg = new SotStorage( sShareAutoCorrFile, STREAM_READ | STREAM_SHARE_DENYNONE, sal_True ); 2427 String sTemp ( RTL_CONSTASCII_USTRINGPARAM ( pXMLImplWrdStt_ExcptLstStr ) ); 2428 if( xStg.Is() && xStg->IsContained( sTemp ) ) 2429 LoadXMLExceptList_Imp( pWrdStt_ExcptLst, pXMLImplWrdStt_ExcptLstStr, xStg ); 2430 return pWrdStt_ExcptLst; 2431 } 2432 /* -----------------18.11.98 11:26------------------- 2433 * 2434 * --------------------------------------------------*/ 2435 void SvxAutoCorrectLanguageLists::SaveWrdSttExceptList() 2436 { 2437 MakeUserStorage_Impl(); 2438 SotStorageRef xStg = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, sal_True ); 2439 2440 SaveExceptList_Imp( *pWrdStt_ExcptLst, pXMLImplWrdStt_ExcptLstStr, xStg ); 2441 2442 xStg = 0; 2443 // Zeitstempel noch setzen 2444 FStatHelper::GetModifiedDateTimeOfFile( sUserAutoCorrFile, 2445 &aModifiedDate, &aModifiedTime ); 2446 aLastCheckTime = Time(); 2447 } 2448 /* -----------------18.11.98 11:26------------------- 2449 * 2450 * --------------------------------------------------*/ 2451 void SvxAutoCorrectLanguageLists::SetWrdSttExceptList( SvStringsISortDtor* pList ) 2452 { 2453 if( pWrdStt_ExcptLst && pList != pWrdStt_ExcptLst ) 2454 delete pWrdStt_ExcptLst; 2455 pWrdStt_ExcptLst = pList; 2456 if( !pWrdStt_ExcptLst ) 2457 { 2458 DBG_ASSERT( !this, "keine gueltige Liste" ); 2459 pWrdStt_ExcptLst = new SvStringsISortDtor( 16, 16 ); 2460 } 2461 nFlags |= WrdSttLstLoad; 2462 } 2463 /* -----------------18.11.98 11:26------------------- 2464 * 2465 * --------------------------------------------------*/ 2466 SvStringsISortDtor* SvxAutoCorrectLanguageLists::GetWrdSttExceptList() 2467 { 2468 if( !( WrdSttLstLoad & nFlags ) || IsFileChanged_Imp() ) 2469 SetWrdSttExceptList( LoadWrdSttExceptList() ); 2470 return pWrdStt_ExcptLst; 2471 } 2472 /* -----------------18.11.98 11:26------------------- 2473 * 2474 * --------------------------------------------------*/ 2475 void SvxAutoCorrectLanguageLists::RemoveStream_Imp( const String& rName ) 2476 { 2477 if( sShareAutoCorrFile != sUserAutoCorrFile ) 2478 { 2479 SotStorageRef xStg = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, sal_True ); 2480 if( xStg.Is() && SVSTREAM_OK == xStg->GetError() && 2481 xStg->IsStream( rName ) ) 2482 { 2483 xStg->Remove( rName ); 2484 xStg->Commit(); 2485 2486 xStg = 0; 2487 } 2488 } 2489 } 2490 2491 void SvxAutoCorrectLanguageLists::MakeUserStorage_Impl() 2492 { 2493 // The conversion needs to happen if the file is already in the user 2494 // directory and is in the old format. Additionally it needs to 2495 // happen when the file is being copied from share to user. 2496 2497 sal_Bool bError = sal_False, bConvert = sal_False, bCopy = sal_False; 2498 INetURLObject aDest; 2499 INetURLObject aSource; 2500 2501 // String sDestPath = sUserAutoCorrFile.Copy ( 0, sUserAutoCorrFile.Len()-3); 2502 // sDestPath.AppendAscii ("bak"); 2503 2504 2505 if (sUserAutoCorrFile != sShareAutoCorrFile ) 2506 { 2507 aSource = INetURLObject ( sShareAutoCorrFile ); //aSource.setFSysPath ( sShareAutoCorrFile, INetURLObject::FSYS_DETECT ); 2508 aDest = INetURLObject ( sUserAutoCorrFile ); 2509 if ( SotStorage::IsOLEStorage ( sShareAutoCorrFile ) ) 2510 { 2511 aDest.SetExtension ( String::CreateFromAscii ( "bak" ) ); 2512 bConvert = sal_True; 2513 } 2514 bCopy = sal_True; 2515 } 2516 else if ( SotStorage::IsOLEStorage ( sUserAutoCorrFile ) ) 2517 { 2518 aSource = INetURLObject ( sUserAutoCorrFile ); 2519 aDest = INetURLObject ( sUserAutoCorrFile ); 2520 aDest.SetExtension ( String::CreateFromAscii ( "bak" ) ); 2521 bCopy = bConvert = sal_True; 2522 } 2523 if (bCopy) 2524 { 2525 try 2526 { 2527 String sMain(aDest.GetMainURL( INetURLObject::DECODE_TO_IURI )); 2528 sal_Unicode cSlash = '/'; 2529 xub_StrLen nSlashPos = sMain.SearchBackward(cSlash); 2530 sMain.Erase(nSlashPos); 2531 ::ucbhelper::Content aNewContent( sMain, uno::Reference< XCommandEnvironment > ()); 2532 Any aAny; 2533 TransferInfo aInfo; 2534 aInfo.NameClash = NameClash::OVERWRITE; 2535 aInfo.NewTitle = aDest.GetName(); 2536 aInfo.SourceURL = aSource.GetMainURL( INetURLObject::DECODE_TO_IURI ); 2537 aInfo.MoveData = sal_False; 2538 aAny <<= aInfo; 2539 aNewContent.executeCommand( OUString ( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ), aAny); 2540 } 2541 catch (...) 2542 { 2543 bError = sal_True; 2544 } 2545 } 2546 if (bConvert && !bError) 2547 { 2548 SotStorageRef xSrcStg = new SotStorage( aDest.GetMainURL( INetURLObject::DECODE_TO_IURI ), STREAM_READ, sal_True ); 2549 SotStorageRef xDstStg = new SotStorage( sUserAutoCorrFile, STREAM_WRITE, sal_True ); 2550 2551 if( xSrcStg.Is() && xDstStg.Is() ) 2552 { 2553 String sWord ( RTL_CONSTASCII_USTRINGPARAM ( pImplWrdStt_ExcptLstStr ) ); 2554 String sSentence ( RTL_CONSTASCII_USTRINGPARAM ( pImplCplStt_ExcptLstStr ) ); 2555 String sXMLWord ( RTL_CONSTASCII_USTRINGPARAM ( pXMLImplWrdStt_ExcptLstStr ) ); 2556 String sXMLSentence ( RTL_CONSTASCII_USTRINGPARAM ( pXMLImplCplStt_ExcptLstStr ) ); 2557 SvStringsISortDtor *pTmpWordList = NULL; 2558 2559 if (xSrcStg->IsContained( sXMLWord ) ) 2560 LoadXMLExceptList_Imp( pTmpWordList, pXMLImplWrdStt_ExcptLstStr, xSrcStg ); 2561 2562 if (pTmpWordList) 2563 { 2564 SaveExceptList_Imp( *pTmpWordList, pXMLImplWrdStt_ExcptLstStr, xDstStg, sal_True ); 2565 pTmpWordList->DeleteAndDestroy( 0, pTmpWordList->Count() ); 2566 pTmpWordList = NULL; 2567 } 2568 2569 2570 if (xSrcStg->IsContained( sXMLSentence ) ) 2571 LoadXMLExceptList_Imp( pTmpWordList, pXMLImplCplStt_ExcptLstStr, xSrcStg ); 2572 2573 if (pTmpWordList) 2574 { 2575 SaveExceptList_Imp( *pTmpWordList, pXMLImplCplStt_ExcptLstStr, xDstStg, sal_True ); 2576 pTmpWordList->DeleteAndDestroy( 0, pTmpWordList->Count() ); 2577 } 2578 2579 GetAutocorrWordList(); 2580 MakeBlocklist_Imp( *xDstStg ); 2581 // xDstStg is committed in MakeBlocklist_Imp 2582 /*xSrcStg->CopyTo( &xDstStg );*/ 2583 sShareAutoCorrFile = sUserAutoCorrFile; 2584 xDstStg = 0; 2585 try 2586 { 2587 ::ucbhelper::Content aContent ( aDest.GetMainURL( INetURLObject::DECODE_TO_IURI ), uno::Reference < XCommandEnvironment > ()); 2588 aContent.executeCommand ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "delete" ) ), makeAny ( sal_Bool (sal_True ) ) ); 2589 } 2590 catch (...) 2591 { 2592 } 2593 } 2594 } 2595 else if( bCopy && !bError ) 2596 sShareAutoCorrFile = sUserAutoCorrFile; 2597 } 2598 2599 /* -----------------18.11.98 11:26------------------- 2600 * 2601 * --------------------------------------------------*/ 2602 sal_Bool SvxAutoCorrectLanguageLists::MakeBlocklist_Imp( SvStorage& rStg ) 2603 { 2604 String sStrmName( pXMLImplAutocorr_ListStr, RTL_TEXTENCODING_MS_1252 ); 2605 sal_Bool bRet = sal_True, bRemove = !pAutocorr_List || !pAutocorr_List->Count(); 2606 if( !bRemove ) 2607 { 2608 /* 2609 if ( rStg.IsContained( sStrmName) ) 2610 { 2611 rStg.Remove ( sStrmName ); 2612 rStg.Commit(); 2613 } 2614 */ 2615 SvStorageStreamRef refList = rStg.OpenSotStream( sStrmName, 2616 ( STREAM_READ | STREAM_WRITE | STREAM_SHARE_DENYWRITE ) ); 2617 if( refList.Is() ) 2618 { 2619 refList->SetSize( 0 ); 2620 refList->SetBufferSize( 8192 ); 2621 String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) ); 2622 OUString aMime( RTL_CONSTASCII_USTRINGPARAM("text/xml") ); 2623 uno::Any aAny; 2624 aAny <<= aMime; 2625 refList->SetProperty( aPropName, aAny ); 2626 2627 uno::Reference< lang::XMultiServiceFactory > xServiceFactory = 2628 comphelper::getProcessServiceFactory(); 2629 DBG_ASSERT( xServiceFactory.is(), 2630 "XMLReader::Read: got no service manager" ); 2631 if( !xServiceFactory.is() ) 2632 { 2633 // Throw an exception ? 2634 } 2635 2636 uno::Reference < XInterface > xWriter (xServiceFactory->createInstance( 2637 OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Writer")))); 2638 DBG_ASSERT(xWriter.is(),"com.sun.star.xml.sax.Writer service missing"); 2639 uno::Reference < io::XOutputStream> xOut = new utl::OOutputStreamWrapper( *refList ); 2640 uno::Reference<io::XActiveDataSource> xSrc(xWriter, uno::UNO_QUERY); 2641 xSrc->setOutputStream(xOut); 2642 2643 uno::Reference<xml::sax::XDocumentHandler> xHandler(xWriter, uno::UNO_QUERY); 2644 2645 // #110680# 2646 // SvXMLAutoCorrectExport aExp(pAutocorr_List, sStrmName, xHandler); 2647 SvXMLAutoCorrectExport aExp( xServiceFactory, pAutocorr_List, sStrmName, xHandler ); 2648 2649 aExp.exportDoc( XML_BLOCK_LIST ); 2650 2651 refList->Commit(); 2652 bRet = SVSTREAM_OK == refList->GetError(); 2653 if( bRet ) 2654 { 2655 refList.Clear(); 2656 rStg.Commit(); 2657 if( SVSTREAM_OK != rStg.GetError() ) 2658 { 2659 bRemove = sal_True; 2660 bRet = sal_False; 2661 } 2662 } 2663 2664 /* 2665 refList->SetSize( 0 ); 2666 refList->SetBufferSize( 8192 ); 2667 rtl_TextEncoding eEncoding = gsl_getSystemTextEncoding(); 2668 2669 String aDummy; // Erkennungszeichen fuer neue Streams 2670 refList->WriteByteString( aDummy, RTL_TEXTENCODING_MS_1252 ) 2671 << (sal_uInt8) 4 // Laenge des Headers (ohne den Leerstring) 2672 << (sal_uInt16)WORDLIST_VERSION_358 // Version des Streams 2673 << (sal_uInt8)eEncoding; // der Zeichensatz 2674 2675 for( sal_uInt16 i = 0; i < pAutocorr_List->Count() && 2676 SVSTREAM_OK == refList->GetError(); ++i ) 2677 { 2678 SvxAutocorrWord* p = pAutocorr_List->GetObject( i ); 2679 refList->WriteByteString( p->GetShort(), eEncoding ). 2680 WriteByteString( p->IsTextOnly() 2681 ? p->GetLong() 2682 : p->GetShort(), eEncoding ); 2683 } 2684 refList->Commit(); 2685 bRet = SVSTREAM_OK == refList->GetError(); 2686 if( bRet ) 2687 { 2688 refList.Clear(); 2689 rStg.Commit(); 2690 if( SVSTREAM_OK != rStg.GetError() ) 2691 { 2692 bRemove = sal_True; 2693 bRet = sal_False; 2694 } 2695 } 2696 */ 2697 } 2698 else 2699 bRet = sal_False; 2700 } 2701 2702 if( bRemove ) 2703 { 2704 rStg.Remove( sStrmName ); 2705 rStg.Commit(); 2706 } 2707 2708 return bRet; 2709 } 2710 2711 /* -----------------18.11.98 11:26------------------- 2712 * 2713 * --------------------------------------------------*/ 2714 sal_Bool SvxAutoCorrectLanguageLists::PutText( const String& rShort, 2715 const String& rLong ) 2716 { 2717 // erstmal akt. Liste besorgen! 2718 GetAutocorrWordList(); 2719 2720 MakeUserStorage_Impl(); 2721 SotStorageRef xStg = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, sal_True ); 2722 2723 sal_Bool bRet = xStg.Is() && SVSTREAM_OK == xStg->GetError(); 2724 2725 /* if( bRet ) 2726 { 2727 // PutText( *xStg, rShort ); 2728 } 2729 */ 2730 // die Wortliste aktualisieren 2731 if( bRet ) 2732 { 2733 sal_uInt16 nPos; 2734 SvxAutocorrWord* pNew = new SvxAutocorrWord( rShort, rLong, sal_True ); 2735 if( pAutocorr_List->Seek_Entry( pNew, &nPos ) ) 2736 { 2737 if( !(*pAutocorr_List)[ nPos ]->IsTextOnly() ) 2738 { 2739 // dann ist der Storage noch zu entfernen 2740 String sStgNm( rShort ); 2741 if (xStg->IsOLEStorage()) 2742 EncryptBlockName_Imp( sStgNm ); 2743 else 2744 GeneratePackageName ( rShort, sStgNm); 2745 2746 if( xStg->IsContained( sStgNm ) ) 2747 xStg->Remove( sStgNm ); 2748 } 2749 pAutocorr_List->DeleteAndDestroy( nPos ); 2750 } 2751 2752 if( pAutocorr_List->Insert( pNew ) ) 2753 { 2754 bRet = MakeBlocklist_Imp( *xStg ); 2755 xStg = 0; 2756 } 2757 else 2758 { 2759 delete pNew; 2760 bRet = sal_False; 2761 } 2762 } 2763 return bRet; 2764 } 2765 /* -----------------18.11.98 11:26------------------- 2766 * 2767 * --------------------------------------------------*/ 2768 // - Text mit Attributierung (kann nur der SWG - SWG-Format!) 2769 sal_Bool SvxAutoCorrectLanguageLists::PutText( const String& rShort, 2770 SfxObjectShell& rShell ) 2771 { 2772 // erstmal akt. Liste besorgen! 2773 GetAutocorrWordList(); 2774 2775 MakeUserStorage_Impl(); 2776 2777 sal_Bool bRet = sal_False; 2778 String sLong; 2779 try 2780 { 2781 uno::Reference < embed::XStorage > xStg = comphelper::OStorageHelper::GetStorageFromURL( sUserAutoCorrFile, embed::ElementModes::READWRITE ); 2782 // String aName( rShort ); 2783 // EncryptBlockName_Imp( aName ); 2784 // bRet = PutText( *xStg, aName, rShell, sLong ); 2785 bRet = rAutoCorrect.PutText( xStg, sUserAutoCorrFile, rShort, rShell, sLong ); 2786 xStg = 0; 2787 2788 // die Wortliste aktualisieren 2789 if( bRet ) 2790 { 2791 SvxAutocorrWord* pNew = new SvxAutocorrWord( rShort, sLong, sal_False ); 2792 if( pAutocorr_List->Insert( pNew ) ) 2793 { 2794 SotStorageRef xStor = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, sal_True ); 2795 MakeBlocklist_Imp( *xStor ); 2796 } 2797 else 2798 delete pNew; 2799 } 2800 } 2801 catch ( uno::Exception& ) 2802 { 2803 } 2804 2805 return bRet; 2806 } 2807 2808 /* -----------------18.11.98 11:26------------------- 2809 * 2810 * --------------------------------------------------*/ 2811 // - loesche einen Eintrag 2812 sal_Bool SvxAutoCorrectLanguageLists::DeleteText( const String& rShort ) 2813 { 2814 // erstmal akt. Liste besorgen! 2815 GetAutocorrWordList(); 2816 2817 MakeUserStorage_Impl(); 2818 2819 SotStorageRef xStg = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, sal_True ); 2820 sal_Bool bRet = xStg.Is() && SVSTREAM_OK == xStg->GetError(); 2821 if( bRet ) 2822 { 2823 sal_uInt16 nPos; 2824 SvxAutocorrWord aTmp( rShort, rShort ); 2825 if( pAutocorr_List->Seek_Entry( &aTmp, &nPos ) ) 2826 { 2827 SvxAutocorrWord* pFnd = (*pAutocorr_List)[ nPos ]; 2828 if( !pFnd->IsTextOnly() ) 2829 { 2830 String aName( rShort ); 2831 if (xStg->IsOLEStorage()) 2832 EncryptBlockName_Imp( aName ); 2833 else 2834 GeneratePackageName ( rShort, aName ); 2835 if( xStg->IsContained( aName ) ) 2836 { 2837 xStg->Remove( aName ); 2838 bRet = xStg->Commit(); 2839 } 2840 2841 } 2842 // die Wortliste aktualisieren 2843 pAutocorr_List->DeleteAndDestroy( nPos ); 2844 MakeBlocklist_Imp( *xStg ); 2845 xStg = 0; 2846 } 2847 else 2848 bRet = sal_False; 2849 } 2850 return bRet; 2851 } 2852