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