merge the formfield patch from ooo-build
[ooovba.git] / svx / source / dialog / splwrap.cxx
blobd22cdb26ad9e2ff241bfc878071cbe0315467653
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: splwrap.cxx,v $
10 * $Revision: 1.19 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
33 #include<rtl/ustring.hxx>
34 #include <tools/shl.hxx>
35 #include <vcl/wrkwin.hxx>
36 #include <vcl/svapp.hxx>
37 #include <vcl/msgbox.hxx>
38 #include <tools/debug.hxx>
40 #ifndef __RSC
41 #include <tools/errinf.hxx>
42 #endif
43 #include <svxerr.hxx>
44 #include <dlgutil.hxx>
45 #include <unolingu.hxx>
46 #include <sfx2/sfxuno.hxx>
47 #include <linguistic/lngprops.hxx>
48 #include <com/sun/star/frame/XStorable.hpp>
50 #include <map>
52 #include <svx/svxenum.hxx>
53 #include "hyphen.hxx" // Der HyphenDialog
54 #include <svx/splwrap.hxx> // Der Wrapper
55 #include <svx/thesdlg.hxx> // ThesaurusDlg
56 #include <svx/dialmgr.hxx>
58 #include <svx/dialogs.hrc>
61 #define WAIT_ON() if(pWin != NULL) { pWin->EnterWait(); }
63 #define WAIT_OFF() if(pWin != NULL) { pWin->LeaveWait(); }
65 using namespace ::com::sun::star;
66 using namespace ::com::sun::star::uno;
67 using namespace ::com::sun::star::beans;
68 using namespace ::com::sun::star::linguistic2;
71 // misc functions ---------------------------------------------
73 void SvxPrepareAutoCorrect( String &rOldText, String &rNewText )
75 // This function should be used to strip (or add) trailing '.' from
76 // the strings before passing them on to the autocorrect function in
77 // order that the autocorrect function will hopefully
78 // works properly with normal words and abbreviations (with trailing '.')
79 // independ of if they are at the end of the sentence or not.
81 // rOldText: text to be replaced
82 // rNewText: replacement text
84 xub_StrLen nOldLen = rOldText.Len(),
85 nNewLen = rNewText.Len();
86 if (nOldLen && nNewLen)
88 sal_Bool bOldHasDot = sal_Unicode( '.' ) == rOldText.GetChar( nOldLen - 1 ),
89 bNewHasDot = sal_Unicode( '.' ) == rNewText.GetChar( nNewLen - 1 );
90 if (bOldHasDot && !bNewHasDot
91 /*this is: !(bOldHasDot && bNewHasDot) && bOldHasDot*/)
92 rOldText.Erase( nOldLen - 1 );
96 // -----------------------------------------------------------------------
98 #define SVX_LANG_NEED_CHECK 0
99 #define SVX_LANG_OK 1
100 #define SVX_LANG_MISSING 2
101 #define SVX_LANG_MISSING_DO_WARN 3
103 #define SVX_FLAGS_NEW
106 struct lt_LanguageType
108 bool operator()( LanguageType n1, LanguageType n2 ) const
110 return n1 < n2;
114 typedef std::map< LanguageType, USHORT, lt_LanguageType > LangCheckState_map_t;
116 static LangCheckState_map_t & GetLangCheckState()
118 static LangCheckState_map_t aLangCheckState;
119 return aLangCheckState;
122 void SvxSpellWrapper::ShowLanguageErrors()
124 // display message boxes for languages not available for
125 // spellchecking or hyphenation
126 LangCheckState_map_t &rLCS = GetLangCheckState();
127 LangCheckState_map_t::iterator aIt( rLCS.begin() );
128 while (aIt != rLCS.end())
130 LanguageType nLang = aIt->first;
131 sal_uInt16 nVal = aIt->second;
132 sal_uInt16 nTmpSpell = nVal & 0x00FF;
133 sal_uInt16 nTmpHyph = (nVal >> 8) & 0x00FF;
135 if (SVX_LANG_MISSING_DO_WARN == nTmpSpell)
137 String aErr( ::GetLanguageString( nLang ) );
138 ErrorHandler::HandleError(
139 *new StringErrorInfo( ERRCODE_SVX_LINGU_LANGUAGENOTEXISTS, aErr ) );
140 nTmpSpell = SVX_LANG_MISSING;
142 if (SVX_LANG_MISSING_DO_WARN == nTmpHyph)
144 String aErr( ::GetLanguageString( nLang ) );
145 ErrorHandler::HandleError(
146 *new StringErrorInfo( ERRCODE_SVX_LINGU_LANGUAGENOTEXISTS, aErr ) );
147 nTmpHyph = SVX_LANG_MISSING;
150 rLCS[ nLang ] = (nTmpHyph << 8) | nTmpSpell;
151 ++aIt;
156 SvxSpellWrapper::~SvxSpellWrapper()
160 /*--------------------------------------------------------------------
161 * Beschreibung: Ctor, die Pruefreihenfolge wird festgelegt
163 * !bStart && !bOtherCntnt: BODY_END, BODY_START, OTHER
164 * !bStart && bOtherCntnt: OTHER, BODY
165 * bStart && !bOtherCntnt: BODY_END, OTHER
166 * bStart && bOtherCntnt: OTHER
168 --------------------------------------------------------------------*/
170 SvxSpellWrapper::SvxSpellWrapper( Window* pWn,
171 Reference< XSpellChecker1 > &xSpellChecker,
172 const sal_Bool bStart, const sal_Bool bIsAllRight,
173 const sal_Bool bOther, const sal_Bool bRevAllow ) :
175 pWin ( pWn ),
176 xSpell ( xSpellChecker ),
177 bOtherCntnt ( bOther ),
178 bDialog ( sal_False ),
179 bHyphen ( sal_False ),
180 bAuto ( sal_False ),
181 bStartChk ( bOther ),
182 bRevAllowed ( bRevAllow ),
183 bAllRight ( bIsAllRight )
185 Reference< beans::XPropertySet > xProp( SvxGetLinguPropertySet() );
186 sal_Bool bWrapReverse = xProp.is() ?
187 *(sal_Bool*)xProp->getPropertyValue(
188 ::rtl::OUString::createFromAscii(UPN_IS_WRAP_REVERSE) ).getValue()
189 : sal_False;
190 bReverse = bRevAllow && bWrapReverse;
191 bStartDone = bOther || ( !bReverse && bStart );
192 bEndDone = bReverse && bStart && !bOther;
195 // -----------------------------------------------------------------------
197 SvxSpellWrapper::SvxSpellWrapper( Window* pWn,
198 Reference< XHyphenator > &xHyphenator,
199 const sal_Bool bStart, const sal_Bool bOther ) :
200 pWin ( pWn ),
201 xHyph ( xHyphenator ),
202 bOtherCntnt ( bOther ),
203 bDialog ( sal_False ),
204 bHyphen ( sal_False ),
205 bAuto ( sal_False ),
206 bReverse ( sal_False ),
207 bStartDone ( bOther || ( !bReverse && bStart ) ),
208 bEndDone ( bReverse && bStart && !bOther ),
209 bStartChk ( bOther ),
210 bRevAllowed ( sal_False ),
211 bAllRight ( sal_True )
215 // -----------------------------------------------------------------------
217 sal_Int16 SvxSpellWrapper::CheckSpellLang(
218 Reference< XSpellChecker1 > xSpell, sal_Int16 nLang)
220 LangCheckState_map_t &rLCS = GetLangCheckState();
222 LangCheckState_map_t::iterator aIt( rLCS.find( nLang ) );
223 sal_uInt16 nVal = aIt == rLCS.end() ? SVX_LANG_NEED_CHECK : aIt->second;
225 if (aIt == rLCS.end())
226 rLCS[ nLang ] = nVal;
228 if (SVX_LANG_NEED_CHECK == (nVal & 0x00FF))
230 sal_uInt16 nTmpVal = SVX_LANG_MISSING_DO_WARN;
231 if (xSpell.is() && xSpell->hasLanguage( nLang ))
232 nTmpVal = SVX_LANG_OK;
233 nVal &= 0xFF00;
234 nVal |= nTmpVal;
236 rLCS[ nLang ] = nVal;
239 return (sal_Int16) nVal;
242 sal_Int16 SvxSpellWrapper::CheckHyphLang(
243 Reference< XHyphenator > xHyph, sal_Int16 nLang)
245 LangCheckState_map_t &rLCS = GetLangCheckState();
247 LangCheckState_map_t::iterator aIt( rLCS.find( nLang ) );
248 sal_uInt16 nVal = aIt == rLCS.end() ? 0 : aIt->second;
250 if (aIt == rLCS.end())
251 rLCS[ nLang ] = nVal;
253 if (SVX_LANG_NEED_CHECK == ((nVal >> 8) & 0x00FF))
255 sal_uInt16 nTmpVal = SVX_LANG_MISSING_DO_WARN;
256 if (xHyph.is() && xHyph->hasLocale( SvxCreateLocale( nLang ) ))
257 nTmpVal = SVX_LANG_OK;
258 nVal &= 0x00FF;
259 nVal |= nTmpVal << 8;
261 rLCS[ nLang ] = nVal;
264 return (sal_Int16) nVal;
267 // -----------------------------------------------------------------------
270 void SvxSpellWrapper::SpellStart( SvxSpellArea /*eSpell*/ )
271 { // Hier muessen die notwendigen Vorbereitungen fuer SpellContinue
272 } // im uebergebenen Bereich getroffen werden.
274 // -----------------------------------------------------------------------
277 sal_Bool SvxSpellWrapper::HasOtherCnt()
279 return sal_False; // Gibt es ueberhaupt einen Sonderbereich?
282 // -----------------------------------------------------------------------
285 sal_Bool SvxSpellWrapper::SpellMore()
287 return sal_False; // Sollen weitere Dokumente geprueft werden?
290 // -----------------------------------------------------------------------
293 void SvxSpellWrapper::SpellEnd()
294 { // Bereich ist abgeschlossen, ggf. Aufraeumen
296 // display error for last language not found
297 ShowLanguageErrors();
300 // -----------------------------------------------------------------------
303 sal_Bool SvxSpellWrapper::SpellContinue()
305 return sal_False;
308 // -----------------------------------------------------------------------
310 void SvxSpellWrapper::AutoCorrect( const String&, const String& )
314 // -----------------------------------------------------------------------
317 void SvxSpellWrapper::ScrollArea()
318 { // Scrollarea einstellen
321 // -----------------------------------------------------------------------
324 void SvxSpellWrapper::ChangeWord( const String&, const sal_uInt16 )
325 { // Wort ersetzen
328 // -----------------------------------------------------------------------
331 String SvxSpellWrapper::GetThesWord()
333 // Welches Wort soll nachgeschlagen werden?
334 return String();
337 // -----------------------------------------------------------------------
340 void SvxSpellWrapper::ChangeThesWord( const String& )
342 // Wort wg. Thesaurus ersetzen
345 // -----------------------------------------------------------------------
347 void SvxSpellWrapper::StartThesaurus( const String &rWord, sal_uInt16 nLanguage )
350 String sErr( SVX_RES( RID_SVXSTR_HMERR_THESAURUS ) );
352 Reference< XThesaurus > xThes( SvxGetThesaurus() );
353 if (!xThes.is())
355 InfoBox( pWin, sErr ).Execute();
356 return;
359 WAIT_ON(); // while looking up for initial word
360 SvxThesaurusDialog aDlg(pWin, xThes, rWord, nLanguage);
361 WAIT_OFF();
363 if ( aDlg.Execute()== RET_OK )
365 ChangeThesWord( aDlg.GetWord() );
370 // -----------------------------------------------------------------------
372 void SvxSpellWrapper::ReplaceAll( const String &, sal_Int16 )
373 { // Wort aus der Replace-Liste ersetzen
376 // -----------------------------------------------------------------------
379 void SvxSpellWrapper::SetLanguage( const sal_uInt16 )
380 { // Sprache aendern
383 // -----------------------------------------------------------------------
386 void SvxSpellWrapper::InsertHyphen( const sal_uInt16 )
387 { // Hyphen einfuegen bzw. loeschen
390 // -----------------------------------------------------------------------
391 // Pruefung der Dokumentbereiche in der durch die Flags angegebenen Reihenfolge
394 void SvxSpellWrapper::SpellDocument( )
396 if ( bOtherCntnt )
398 bReverse = sal_False;
399 SpellStart( SVX_SPELL_OTHER );
401 else
403 bStartChk = bReverse;
404 SpellStart( bReverse ? SVX_SPELL_BODY_START : SVX_SPELL_BODY_END );
407 if ( FindSpellError() )
409 Reference< XSpellAlternatives > xAlt( GetLast(), UNO_QUERY );
410 Reference< XHyphenatedWord > xHyphWord( GetLast(), UNO_QUERY );
412 Window *pOld = pWin;
413 bDialog = sal_True;
414 if (xHyphWord.is())
416 DBG_ASSERT(xHyphWord.is(), "NULL pointer");
417 SvxHyphenWordDialog* pDlg =
418 new SvxHyphenWordDialog( xHyphWord->getWord(),
419 SvxLocaleToLanguage( xHyphWord->getLocale() ),
420 pWin, xHyph, this );
421 pWin = pDlg;
422 pDlg->Execute();
423 delete pDlg;
425 bDialog = sal_False;
426 pWin = pOld;
430 // -----------------------------------------------------------------------
431 // Naechsten Bereich auswaehlen
434 sal_Bool SvxSpellWrapper::SpellNext( )
436 Reference< beans::XPropertySet > xProp( SvxGetLinguPropertySet() );
437 sal_Bool bWrapReverse = xProp.is() ?
438 *(sal_Bool*)xProp->getPropertyValue(
439 ::rtl::OUString::createFromAscii(UPN_IS_WRAP_REVERSE) ).getValue()
440 : sal_False;
441 sal_Bool bActRev = bRevAllowed && bWrapReverse;
443 // bActRev ist die Richtung nach dem Spellen, bReverse die am Anfang.
444 if( bActRev == bReverse )
445 { // Keine Richtungsaenderung, also ist
446 if( bStartChk ) // der gewuenschte Bereich ( bStartChk )
447 bStartDone = sal_True; // vollstaendig abgearbeitet.
448 else
449 bEndDone = sal_True;
451 else if( bReverse == bStartChk ) // Bei einer Richtungsaenderung kann
452 { // u.U. auch ein Bereich abgearbeitet sein.
453 if( bStartChk ) // Sollte der vordere Teil rueckwaerts gespellt
454 bEndDone = sal_True; // werden und wir kehren unterwegs um, so ist
455 else // der hintere Teil abgearbeitet (und umgekehrt).
456 bStartDone = sal_True;
459 bReverse = bActRev;
460 if( bOtherCntnt && bStartDone && bEndDone ) // Dokument komplett geprueft?
462 if ( SpellMore() ) // ein weiteres Dokument pruefen?
464 bOtherCntnt = sal_False;
465 bStartDone = !bReverse;
466 bEndDone = bReverse;
467 SpellStart( SVX_SPELL_BODY );
468 return sal_True;
470 return sal_False;
473 ResMgr& rMgr = DIALOG_MGR();
474 sal_Bool bGoOn = sal_False;
476 if ( bOtherCntnt )
478 bStartChk = sal_False;
479 SpellStart( SVX_SPELL_BODY );
480 bGoOn = sal_True;
482 else if ( bStartDone && bEndDone )
484 sal_Bool bIsSpellSpecial = xProp.is() ?
485 *(sal_Bool*)xProp->getPropertyValue(
486 ::rtl::OUString::createFromAscii(UPN_IS_SPELL_SPECIAL) ).getValue()
487 : sal_False;
488 // Bodybereich erledigt, Frage nach Sonderbereich
489 if( !IsHyphen() && bIsSpellSpecial && HasOtherCnt() )
491 SpellStart( SVX_SPELL_OTHER );
492 bOtherCntnt = bGoOn = sal_True;
494 else if ( SpellMore() ) // ein weiteres Dokument pruefen?
496 bOtherCntnt = sal_False;
497 bStartDone = !bReverse;
498 bEndDone = bReverse;
499 SpellStart( SVX_SPELL_BODY );
500 return sal_True;
503 else
505 // Ein BODY_Bereich erledigt, Frage nach dem anderen BODY_Bereich
506 WAIT_OFF();
508 // Sobald im Dialog das DontWrapAround gesetzt werden kann, kann der
509 // folgende #ifdef-Zweig aktiviert werden ...
510 #ifdef USED
511 sal_Bool bDontWrapAround = IsHyphen() ?
512 pSpell->GetOptions() & DONT_WRAPAROUND :
513 pSpell->GetHyphOptions() & HYPH_DONT_WRAPAROUND;
514 if( bDontWrapAround )
515 #else
516 sal_uInt16 nResId = bReverse ? RID_SVXQB_BW_CONTINUE : RID_SVXQB_CONTINUE;
517 QueryBox aBox( pWin, ResId( nResId, rMgr ) );
518 if ( aBox.Execute() != RET_YES )
519 #endif
522 // Verzicht auf den anderen Bereich, ggf. Frage nach Sonderbereich
523 WAIT_ON();
524 bStartDone = bEndDone = sal_True;
525 return SpellNext();
527 else
529 bStartChk = !bStartDone;
530 SpellStart( bStartChk ? SVX_SPELL_BODY_START : SVX_SPELL_BODY_END );
531 bGoOn = sal_True;
533 WAIT_ON();
535 return bGoOn;
538 // -----------------------------------------------------------------------
540 Reference< XDictionary > SvxSpellWrapper::GetAllRightDic() const
542 Reference< XDictionary > xDic;
544 Reference< XDictionaryList > xDicList( SvxGetDictionaryList() );
545 if (xDicList.is())
547 Sequence< Reference< XDictionary > > aDics( xDicList->getDictionaries() );
548 const Reference< XDictionary > *pDic = aDics.getConstArray();
549 sal_Int32 nCount = aDics.getLength();
551 sal_Int32 i = 0;
552 while (!xDic.is() && i < nCount)
554 Reference< XDictionary > xTmp( pDic[i], UNO_QUERY );
555 if (xTmp.is())
557 if ( xTmp->isActive() &&
558 xTmp->getDictionaryType() != DictionaryType_NEGATIVE &&
559 SvxLocaleToLanguage( xTmp->getLocale() ) == LANGUAGE_NONE )
561 Reference< frame::XStorable > xStor( xTmp, UNO_QUERY );
562 if (xStor.is() && xStor->hasLocation() && !xStor->isReadonly())
564 xDic = xTmp;
568 ++i;
571 if (!xDic.is())
573 xDic = SvxGetOrCreatePosDic( xDicList );
574 if (xDic.is())
575 xDic->setActive( sal_True );
579 return xDic;
582 // -----------------------------------------------------------------------
584 sal_Bool SvxSpellWrapper::FindSpellError()
586 ShowLanguageErrors();
588 Reference< XInterface > xRef;
590 WAIT_ON();
591 sal_Bool bSpell = sal_True;
593 Reference< XDictionary > xAllRightDic;
594 if (IsAllRight())
595 xAllRightDic = GetAllRightDic();
597 while ( bSpell )
599 SpellContinue();
601 Reference< XSpellAlternatives > xAlt( GetLast(), UNO_QUERY );
602 Reference< XHyphenatedWord > xHyphWord( GetLast(), UNO_QUERY );
604 if (xAlt.is())
606 if (IsAllRight() && xAllRightDic.is())
608 xAllRightDic->add( xAlt->getWord(), sal_False, ::rtl::OUString() );
610 else
612 // look up in ChangeAllList for misspelled word
613 Reference< XDictionary > xChangeAllList(
614 SvxGetChangeAllList(), UNO_QUERY );
615 Reference< XDictionaryEntry > xEntry;
616 if (xChangeAllList.is())
617 xEntry = xChangeAllList->getEntry( xAlt->getWord() );
619 if (xEntry.is())
621 // replace word without asking
622 ReplaceAll( xEntry->getReplacementText(),
623 SvxLocaleToLanguage( xAlt->getLocale() ) );
625 else
626 bSpell = sal_False;
629 else if (xHyphWord.is())
630 bSpell = sal_False;
631 else
633 SpellEnd();
634 bSpell = SpellNext();
637 WAIT_OFF();
638 return GetLast().is();