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;
DECLARE_TABLE(SvxAutoCorrLanguageTable_Impl,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
IsLowerLetter(sal_Int32 nCharType)128 inline int IsLowerLetter( sal_Int32 nCharType )
129 {
130 return CharClass::isLetterType( nCharType ) &&
131 0 == ( ::com::sun::star::i18n::KCharacterType::UPPER & nCharType);
132 }
IsUpperLetter(sal_Int32 nCharType)133 inline int IsUpperLetter( sal_Int32 nCharType )
134 {
135 return CharClass::isLetterType( nCharType ) &&
136 0 == ( ::com::sun::star::i18n::KCharacterType::LOWER & nCharType);
137 }
138
lcl_IsUnsupportedUnicodeChar(CharClass & rCC,const String & rTxt,xub_StrLen nStt,xub_StrLen nEnd)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
lcl_IsSymbolChar(CharClass & rCC,const String & rTxt,xub_StrLen nStt,xub_StrLen nEnd)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
lcl_IsInAsciiArr(const sal_Char * pArr,const sal_Unicode c)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
~SvxAutoCorrDoc()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.
SaveCpltSttWord(sal_uLong,xub_StrLen,const String &,sal_Unicode)215 void SvxAutoCorrDoc::SaveCpltSttWord( sal_uLong, xub_StrLen, const String&,
216 sal_Unicode )
217 {
218 }
219
GetLanguage(xub_StrLen,sal_Bool) const220 LanguageType SvxAutoCorrDoc::GetLanguage( xub_StrLen , sal_Bool ) const
221 {
222 return LANGUAGE_SYSTEM;
223 }
224
225 static ::com::sun::star::uno::Reference<
GetProcessFact()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
GetAppLang()234 static sal_uInt16 GetAppLang()
235 {
236 return Application::GetSettings().GetLanguage();
237 }
GetLocaleDataWrapper(sal_uInt16 nLang)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 }
GetIgnoreTranslWrapper()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 }
GetCollatorWrapper()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
DeleteAndDestroy(sal_uInt16 nP,sal_uInt16 nL)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
Seek_Entry(const SvxAutocorrWordPtr aE,sal_uInt16 * pP) const288 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 * --------------------------------------------------*/
lcl_ClearTable(SvxAutoCorrLanguageTable_Impl & rLangTable)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
IsAutoCorrectChar(sal_Unicode cChar)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
NeedsHardspaceAutocorr(sal_Unicode cChar)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 * --------------------------------------------------*/
GetDefaultFlags()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
SvxAutoCorrect(const String & rShareAutocorrFile,const String & rUserAutocorrFile)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
SvxAutoCorrect(const SvxAutoCorrect & rCpy)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
~SvxAutoCorrect()424 SvxAutoCorrect::~SvxAutoCorrect()
425 {
426 lcl_ClearTable(*pLangTable);
427 delete pLangTable;
428 delete pLastFileTable;
429 delete pCharClass;
430 }
431
_GetCharClass(LanguageType eLang)432 void SvxAutoCorrect::_GetCharClass( LanguageType eLang )
433 {
434 delete pCharClass;
435 pCharClass = new CharClass( SvxCreateLocale( eLang ));
436 eCharClassLang = eLang;
437 }
438
SetAutoCorrFlag(long nFlag,sal_Bool bOn)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 ??
FnCptlSttWrd(SvxAutoCorrDoc & rDoc,const String & rTxt,xub_StrLen nSttPos,xub_StrLen nEndPos,LanguageType eLang)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
FnChgOrdinalNumber(SvxAutoCorrDoc & rDoc,const String & rTxt,xub_StrLen nSttPos,xub_StrLen nEndPos,LanguageType eLang)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
FnChgToEnEmDash(SvxAutoCorrDoc & rDoc,const String & rTxt,xub_StrLen nSttPos,xub_StrLen nEndPos,LanguageType eLang)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
FnAddNonBrkSpace(SvxAutoCorrDoc & rDoc,const String & rTxt,xub_StrLen,xub_StrLen nEndPos,LanguageType eLang)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
FnSetINetAttr(SvxAutoCorrDoc & rDoc,const String & rTxt,xub_StrLen nSttPos,xub_StrLen nEndPos,LanguageType eLang)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
FnChgWeightUnderl(SvxAutoCorrDoc & rDoc,const String & rTxt,xub_StrLen,xub_StrLen nEndPos,LanguageType eLang)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
FnCptlSttSntnc(SvxAutoCorrDoc & rDoc,const String & rTxt,sal_Bool bNormalPos,xub_StrLen nSttPos,xub_StrLen nEndPos,LanguageType eLang)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
GetQuote(sal_Unicode cInsChar,sal_Bool bSttQuote,LanguageType eLang) const1111 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
InsertQuote(SvxAutoCorrDoc & rDoc,xub_StrLen nInsPos,sal_Unicode cInsChar,sal_Bool bSttQuote,sal_Bool bIns)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
GetQuote(SvxAutoCorrDoc & rDoc,xub_StrLen nInsPos,sal_Unicode cInsChar,sal_Bool bSttQuote)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
AutoCorrect(SvxAutoCorrDoc & rDoc,const String & rTxt,xub_StrLen nInsPos,sal_Unicode cChar,sal_Bool bInsert)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
_GetLanguageList(LanguageType eLang)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
SaveCplSttExceptList(LanguageType eLang)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
SaveWrdSttExceptList(LanguageType eLang)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!
AddCplSttException(const String & rNew,LanguageType eLang)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!
AddWrtSttException(const String & rNew,LanguageType eLang)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
SetUserAutoCorrFileName(const String & rNew)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
SetShareAutoCorrFileName(const String & rNew)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
GetPrevAutoCorrWord(SvxAutoCorrDoc & rDoc,const String & rTxt,xub_StrLen nPos,String & rWord) const1591 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
CreateLanguageFile(LanguageType eLang,sal_Bool bNewFile)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
PutText(const String & rShort,const String & rLong,LanguageType eLang)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
DeleteText(const String & rShort,LanguageType eLang)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!)
GetLongText(const com::sun::star::uno::Reference<com::sun::star::embed::XStorage> &,const String &,const String &,String &)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!)
PutText(const com::sun::star::uno::Reference<com::sun::star::embed::XStorage> &,const String &,const String &,SfxObjectShell &,String &)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
EncryptBlockName_Imp(String & rName)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 */
GeneratePackageName(const String & rShort,String & rPackageName)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
DecryptBlockName_Imp(String & rName)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 * --------------------------------------------------*/
lcl_SearchWordsInList(SvxAutoCorrectLanguageListsPtr pList,const String & rTxt,xub_StrLen & rStt,xub_StrLen nEndPos,SvxAutoCorrDoc &)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
SearchWordsInList(const String & rTxt,xub_StrLen & rStt,xub_StrLen nEndPos,SvxAutoCorrDoc & rDoc,LanguageType & rLang)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 * --------------------------------------------------*/
FindInWrdSttExceptList(LanguageType eLang,const String & sWord)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 * --------------------------------------------------*/
lcl_FindAbbreviation(const SvStringsISortDtor * pList,const String & sWord)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 * --------------------------------------------------*/
FindInCplSttExceptList(LanguageType eLang,const String & sWord,sal_Bool bAbbreviation)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 * --------------------------------------------------*/
GetAutoCorrFileName(LanguageType eLang,sal_Bool bNewFile,sal_Bool bTst) const1992 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 * --------------------------------------------------*/
SvxAutoCorrectLanguageLists(SvxAutoCorrect & rParent,const String & rShareAutoCorrectFile,const String & rUserAutoCorrectFile,LanguageType eLang)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 * --------------------------------------------------*/
~SvxAutoCorrectLanguageLists()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 * --------------------------------------------------*/
IsFileChanged_Imp()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
LoadXMLExceptList_Imp(SvStringsISortDtor * & rpLst,const sal_Char * pStrmName,SotStorageRef & rStg)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 * --------------------------------------------------*/
SaveExceptList_Imp(const SvStringsISortDtor & rLst,const sal_Char * pStrmName,SotStorageRef & rStg,sal_Bool bConvert)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 * --------------------------------------------------*/
LoadAutocorrWordList()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
SetAutocorrWordList(SvxAutocorrWordList * pList)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( sal_False, "no valid list" );
2298 pAutocorr_List = new SvxAutocorrWordList( 16, 16 );
2299 }
2300 nFlags |= ChgWordLstLoad;
2301 }
2302
2303 /* -----------------18.11.98 11:26-------------------
2304 *
2305 * --------------------------------------------------*/
GetAutocorrWordList()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 * --------------------------------------------------*/
GetCplSttExceptList()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 * --------------------------------------------------*/
AddToCplSttExceptList(const String & rNew)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 * --------------------------------------------------*/
AddToWrdSttExceptList(const String & rNew)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 * --------------------------------------------------*/
LoadCplSttExceptList()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 * --------------------------------------------------*/
SaveCplSttExceptList()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 * --------------------------------------------------*/
SetCplSttExceptList(SvStringsISortDtor * pList)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( sal_False, "no valid list" );
2412 pCplStt_ExcptLst = new SvStringsISortDtor( 16, 16 );
2413 }
2414 nFlags |= CplSttLstLoad;
2415 }
2416 /* -----------------18.11.98 11:26-------------------
2417 *
2418 * --------------------------------------------------*/
LoadWrdSttExceptList()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 * --------------------------------------------------*/
SaveWrdSttExceptList()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 * --------------------------------------------------*/
SetWrdSttExceptList(SvStringsISortDtor * pList)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( sal_False, "no valid list" );
2454 pWrdStt_ExcptLst = new SvStringsISortDtor( 16, 16 );
2455 }
2456 nFlags |= WrdSttLstLoad;
2457 }
2458 /* -----------------18.11.98 11:26-------------------
2459 *
2460 * --------------------------------------------------*/
GetWrdSttExceptList()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 * --------------------------------------------------*/
RemoveStream_Imp(const String & rName)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
MakeUserStorage_Impl()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 * --------------------------------------------------*/
MakeBlocklist_Imp(SvStorage & rStg)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 * --------------------------------------------------*/
PutText(const String & rShort,const String & rLong)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!)
PutText(const String & rShort,SfxObjectShell & rShell)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
DeleteText(const String & rShort)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