1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: langhelper.cxx,v $
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_sw.hxx"
36 #include <vcl/window.hxx>
40 #include <sfx2/bindings.hxx>
41 #include <sfx2/dispatch.hxx>
42 #include <sfx2/request.hxx>
43 #include <svx/eeitem.hxx>
44 #include <svx/editeng.hxx>
45 #include <svx/editdata.hxx>
46 #include <svx/outliner.hxx>
47 #include <svx/editview.hxx>
48 #include <svx/scripttypeitem.hxx>
49 #include <svx/langitem.hxx>
51 #include <svtools/languageoptions.hxx>
52 #include <svtools/langtab.hxx>
53 #include <svtools/slstitm.hxx>
54 #include <svtools/svstdarr.hxx>
55 #include <svtools/stritem.hxx>
60 #include <viewopt.hxx>
62 #include "swabstdlg.hxx"
64 #include <vcl/msgbox.hxx>
66 #include <langhelper.hxx>
68 using namespace ::com::sun::star
;
70 namespace SwLangHelper
72 USHORT
GetLanguageStatus(OutlinerView
* pOLV
,SfxItemSet
& rSet
)
74 ESelection aSelection
= pOLV
->GetSelection();
75 EditView
& rEditView
=pOLV
->GetEditView();
76 EditEngine
* pEditEngine
=rEditView
.GetEditEngine();
78 // the value of used script types
79 const USHORT nScriptType
=pOLV
->GetSelectedScriptType();
80 String
aScriptTypesInUse( String::CreateFromInt32( nScriptType
) );//pEditEngine->GetScriptType(aSelection)
82 SvtLanguageTable aLangTable
;
84 // get keyboard language
86 LanguageType nLang
= LANGUAGE_DONTKNOW
;
88 Window
* pWin
= rEditView
.GetWindow();
90 nLang
= pWin
->GetInputLanguage();
91 if (nLang
!= LANGUAGE_DONTKNOW
&& nLang
!= LANGUAGE_SYSTEM
)
92 aKeyboardLang
= aLangTable
.GetString( nLang
);
94 // get the language that is in use
95 const String aMultipleLanguages
= String::CreateFromAscii("*");
96 String aCurrentLang
= aMultipleLanguages
;
97 SfxItemSet
aSet(pOLV
->GetAttribs());
98 nLang
= SwLangHelper::GetCurrentLanguage( aSet
,nScriptType
);
99 if (nLang
!= LANGUAGE_DONTKNOW
)
100 aCurrentLang
= aLangTable
.GetString( nLang
);
102 // build sequence for status value
103 uno::Sequence
< ::rtl::OUString
> aSeq( 4 );
104 aSeq
[0] = aCurrentLang
;
105 aSeq
[1] = aScriptTypesInUse
;
106 aSeq
[2] = aKeyboardLang
;
107 aSeq
[3] = SwLangHelper::GetTextForLanguageGuessing( pEditEngine
, aSelection
);
109 // set sequence as status value
110 SfxStringListItem
aItem( SID_LANGUAGE_STATUS
);
111 aItem
.SetStringList( aSeq
);
112 rSet
.Put( aItem
, SID_LANGUAGE_STATUS
);
116 bool SetLanguageStatus(OutlinerView
* pOLV
,SfxRequest
&rReq
,SwView
&rView
,SwWrtShell
&rSh
)
118 bool bRestoreSelection
= false;
119 SfxItemSet
aEditAttr(pOLV
->GetAttribs());
120 ESelection aSelection
= pOLV
->GetSelection();
121 EditView
& rEditView
= pOLV
->GetEditView();
122 EditEngine
* pEditEngine
= rEditView
.GetEditEngine();
127 SFX_REQUEST_ARG( rReq
, pItem
, SfxStringItem
, SID_LANGUAGE_STATUS
, sal_False
);
129 aNewLangTxt
= pItem
->GetValue();
131 //!! Remember the view frame right now...
132 //!! (call to GetView().GetViewFrame() will break if the
133 //!! SwTextShell got destroyed meanwhile.)
134 SfxViewFrame
*pViewFrame
= rView
.GetViewFrame();
136 if (aNewLangTxt
.EqualsAscii( "*" ))
138 // open the dialog "Tools/Options/Language Settings - Language"
139 SfxAbstractDialogFactory
* pFact
= SfxAbstractDialogFactory::Create();
142 VclAbstractDialog
* pDlg
= pFact
->CreateVclDialog( rView
.GetWindow(), SID_LANGUAGE_OPTIONS
);
149 // setting the new language...
150 if (aNewLangTxt
.Len() > 0)
152 const String
aSelectionLangPrefix( String::CreateFromAscii("Current_") );
153 const String
aParagraphLangPrefix( String::CreateFromAscii("Paragraph_") );
154 const String
aDocumentLangPrefix( String::CreateFromAscii("Default_") );
155 const String
aStrNone( String::CreateFromAscii("LANGUAGE_NONE") );
158 bool bForSelection
= true;
159 bool bForParagraph
= false;
160 if (STRING_NOTFOUND
!= (nPos
= aNewLangTxt
.Search( aSelectionLangPrefix
, 0 )))
162 // ... for the current selection
163 aNewLangTxt
= aNewLangTxt
.Erase( nPos
, aSelectionLangPrefix
.Len() );
164 bForSelection
= true;
166 else if (STRING_NOTFOUND
!= (nPos
= aNewLangTxt
.Search( aParagraphLangPrefix
, 0 )))
168 // ... for the current paragraph language
169 aNewLangTxt
= aNewLangTxt
.Erase( nPos
, aParagraphLangPrefix
.Len() );
170 bForSelection
= true;
171 bForParagraph
= true;
173 else if (STRING_NOTFOUND
!= (nPos
= aNewLangTxt
.Search( aDocumentLangPrefix
, 0 )))
175 // ... as default document language
176 aNewLangTxt
= aNewLangTxt
.Erase( nPos
, aDocumentLangPrefix
.Len() );
177 bForSelection
= false;
182 bRestoreSelection
= true;
183 SwLangHelper::SelectPara( rEditView
, aSelection
);
184 aSelection
= pOLV
->GetSelection();
186 if (!bForSelection
) // document language to be changed...
189 rSh
.LockView( TRUE
);
192 // prepare to apply new language to all text in document
194 rSh
.ExtendedSelectAll();
197 if (aNewLangTxt
!= aStrNone
)
198 SwLangHelper::SetLanguage( rSh
, pEditEngine
, aSelection
, aNewLangTxt
, bForSelection
, aEditAttr
);
200 SwLangHelper::SetLanguage_None( rSh
, pEditEngine
, aSelection
, bForSelection
, aEditAttr
);
202 // ugly hack, as it seems that EditView/EditEngine does not update their spellchecking marks
203 // when setting a new language attribute
206 const SwViewOption
* pVOpt
= rView
.GetWrtShellPtr()->GetViewOptions();
207 ULONG nCntrl
= pEditEngine
->GetControlWord();
209 if (!pVOpt
->IsOnlineSpell())
210 nCntrl
&= ~EE_CNTRL_ONLINESPELLING
;
212 nCntrl
&= ~EE_CNTRL_ONLINESPELLING
;
213 pEditEngine
->SetControlWord(nCntrl
);
216 if (pVOpt
->IsOnlineSpell())
217 nCntrl
|= EE_CNTRL_ONLINESPELLING
;
219 nCntrl
&= ~EE_CNTRL_ONLINESPELLING
;
220 pEditEngine
->SetControlWord(nCntrl
);
222 pEditEngine
->CompleteOnlineSpelling();
223 rEditView
.Invalidate();
228 // need to release view and restore selection...
230 rSh
.LockView( FALSE
);
236 // invalidate slot to get the new language displayed
237 pViewFrame
->GetBindings().Invalidate( rReq
.GetSlot() );
240 return bRestoreSelection
;
244 void SetLanguage(SwWrtShell
&rWrtSh
, const String
&rLangText
, bool bIsForSelection
, SfxItemSet
&rCoreSet
)
246 SetLanguage(rWrtSh
,0,ESelection(),rLangText
,bIsForSelection
,rCoreSet
);
249 void SetLanguage(SwWrtShell
&rWrtSh
, EditEngine
* pEditEngine
,ESelection aSelection
, const String
&rLangText
, bool bIsForSelection
, SfxItemSet
&rCoreSet
)
251 const LanguageType nLang
= SvtLanguageTable().GetType( rLangText
);
252 if (nLang
!= LANGUAGE_DONTKNOW
)
254 USHORT nScriptType
= SvtLanguageOptions::GetScriptTypeOfLanguage( nLang
);
257 USHORT nLangWhichId
= 0;
258 bool bIsSingleScriptType
= true;
261 case SCRIPTTYPE_LATIN
: nLangWhichId
= pEditEngine
? EE_CHAR_LANGUAGE
: RES_CHRATR_LANGUAGE
; break;
262 case SCRIPTTYPE_ASIAN
: nLangWhichId
= pEditEngine
? EE_CHAR_LANGUAGE_CJK
: RES_CHRATR_CJK_LANGUAGE
; break;
263 case SCRIPTTYPE_COMPLEX
: nLangWhichId
= pEditEngine
? EE_CHAR_LANGUAGE_CTL
: RES_CHRATR_CTL_LANGUAGE
; break;
265 bIsSingleScriptType
= false;
266 DBG_ERROR( "unexpected case" );
268 if (bIsSingleScriptType
)
272 // apply language to current selection
275 rCoreSet
.Put( SvxLanguageItem( nLang
, nLangWhichId
));
276 pEditEngine
->QuickSetAttribs( rCoreSet
, aSelection
);
280 rWrtSh
.GetCurAttr( rCoreSet
);
281 rCoreSet
.Put( SvxLanguageItem( nLang
, nLangWhichId
));
282 rWrtSh
.SetAttr( rCoreSet
);
285 else // change document language
287 // set document default language
288 switch (nLangWhichId
)
290 case EE_CHAR_LANGUAGE
: nLangWhichId
= RES_CHRATR_LANGUAGE
; break;
291 case EE_CHAR_LANGUAGE_CJK
: nLangWhichId
= RES_CHRATR_CJK_LANGUAGE
; break;
292 case EE_CHAR_LANGUAGE_CTL
: nLangWhichId
= RES_CHRATR_CTL_LANGUAGE
; break;
294 rWrtSh
.SetDefault( SvxLanguageItem( nLang
, nLangWhichId
) );
296 // set respective language attribute in text document to default
297 // (for all text in the document - which should be selected by now...)
298 SvUShortsSort aAttribs
;
299 aAttribs
.Insert( nLangWhichId
);
300 rWrtSh
.ResetAttr( &aAttribs
);
306 void SetLanguage_None(SwWrtShell
&rWrtSh
,bool bIsForSelection
, SfxItemSet
&rCoreSet
)
308 SetLanguage_None(rWrtSh
,0,ESelection(),bIsForSelection
,rCoreSet
);
311 void SetLanguage_None(SwWrtShell
&rWrtSh
, EditEngine
* pEditEngine
,ESelection aSelection
, bool bIsForSelection
, SfxItemSet
&rCoreSet
)
314 const USHORT aLangWhichId_EE
[3] =
317 EE_CHAR_LANGUAGE_CJK
,
322 const USHORT aLangWhichId_Writer
[3] =
325 RES_CHRATR_CJK_LANGUAGE
,
326 RES_CHRATR_CTL_LANGUAGE
331 // apply language to current selection
334 for (sal_uInt16 i
= 0; i
< 3; ++i
)
335 rCoreSet
.Put( SvxLanguageItem( LANGUAGE_NONE
, aLangWhichId_EE
[i
] ));
336 pEditEngine
->QuickSetAttribs( rCoreSet
, aSelection
);
340 rWrtSh
.GetCurAttr( rCoreSet
);
341 for (sal_uInt16 i
= 0; i
< 3; ++i
)
342 rCoreSet
.Put( SvxLanguageItem( LANGUAGE_NONE
, aLangWhichId_Writer
[i
] ));
343 rWrtSh
.SetAttr( rCoreSet
);
346 else // change document language
348 SvUShortsSort aAttribs
;
349 for (sal_uInt16 i
= 0; i
< 3; ++i
)
351 rWrtSh
.SetDefault( SvxLanguageItem( LANGUAGE_NONE
, aLangWhichId_Writer
[i
] ) );
352 aAttribs
.Insert( aLangWhichId_Writer
[i
] );
355 // set all language attributes to default
356 // (for all text in the document - which should be selected by now...)
357 rWrtSh
.ResetAttr( &aAttribs
);
361 /// @returns : the language for the selected text that is set for the
362 /// specified attribute (script type).
363 /// If there are more than one languages used LANGUAGE_DONTKNOW will be returned.
364 /// @param nLangWhichId : one of
365 /// RES_CHRATR_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CTL_LANGUAGE,
366 LanguageType
GetLanguage( SwWrtShell
&rSh
, USHORT nLangWhichId
)
368 SfxItemSet
aSet( rSh
.GetAttrPool(), nLangWhichId
, nLangWhichId
);
369 rSh
.GetCurAttr( aSet
);
371 return GetLanguage(aSet
,nLangWhichId
);
374 LanguageType
GetLanguage( SfxItemSet aSet
, USHORT nLangWhichId
)
377 LanguageType nLang
= LANGUAGE_SYSTEM
;
379 const SfxPoolItem
*pItem
= 0;
380 SfxItemState nState
= aSet
.GetItemState( nLangWhichId
, TRUE
, &pItem
);
381 if (nState
> SFX_ITEM_DEFAULT
&& pItem
)
383 // the item is set and can be used
384 nLang
= (dynamic_cast< const SvxLanguageItem
* >(pItem
))->GetLanguage();
386 else if (nState
== SFX_ITEM_DEFAULT
)
388 // since the attribute is not set: retrieve the default value
389 nLang
= (dynamic_cast< const SvxLanguageItem
& >(aSet
.GetPool()->GetDefaultItem( nLangWhichId
))).GetLanguage();
391 else if (nState
== SFX_ITEM_DONTCARE
)
393 // there is more than one language...
394 nLang
= LANGUAGE_DONTKNOW
;
396 DBG_ASSERT( nLang
!= LANGUAGE_SYSTEM
, "failed to get the language?" );
401 /// @returns: the language in use for the selected text.
402 /// 'In use' means the language(s) matching the script type(s) of the
403 /// selected text. Or in other words, the language a spell checker would use.
404 /// If there is more than one language LANGUAGE_DONTKNOW will be returned.
405 LanguageType
GetCurrentLanguage( SwWrtShell
&rSh
)
407 // get all script types used in current selection
408 const USHORT nScriptType
= rSh
.GetScriptType();
410 //set language attribute to use according to the script type
411 USHORT nLangWhichId
= 0;
412 bool bIsSingleScriptType
= true;
415 case SCRIPTTYPE_LATIN
: nLangWhichId
= RES_CHRATR_LANGUAGE
; break;
416 case SCRIPTTYPE_ASIAN
: nLangWhichId
= RES_CHRATR_CJK_LANGUAGE
; break;
417 case SCRIPTTYPE_COMPLEX
: nLangWhichId
= RES_CHRATR_CTL_LANGUAGE
; break;
418 default: bIsSingleScriptType
= false; break;
421 // get language according to the script type(s) in use
422 LanguageType nCurrentLang
= LANGUAGE_SYSTEM
;
423 if (bIsSingleScriptType
)
424 nCurrentLang
= GetLanguage( rSh
, nLangWhichId
);
427 // check if all script types are set to LANGUAGE_NONE and return
428 // that if this is the case. Otherwise, having multiple script types
429 // in use always means there are several languages in use...
430 const USHORT aScriptTypes
[3] =
433 RES_CHRATR_CJK_LANGUAGE
,
434 RES_CHRATR_CTL_LANGUAGE
436 nCurrentLang
= LANGUAGE_NONE
;
437 for (sal_uInt16 i
= 0; i
< 3; ++i
)
439 LanguageType nTmpLang
= GetLanguage( rSh
, aScriptTypes
[i
] );
440 if (nTmpLang
!= LANGUAGE_NONE
)
442 nCurrentLang
= LANGUAGE_DONTKNOW
;
447 DBG_ASSERT( nCurrentLang
!= LANGUAGE_SYSTEM
, "failed to get the language?" );
452 /// @returns: the language in use for the selected text.
453 /// 'In use' means the language(s) matching the script type(s) of the
454 /// selected text. Or in other words, the language a spell checker would use.
455 /// If there is more than one language LANGUAGE_DONTKNOW will be returned.
456 LanguageType
GetCurrentLanguage(SfxItemSet aSet
,USHORT nScriptType
)
458 //set language attribute to use according to the script type
459 USHORT nLangWhichId
= 0;
460 bool bIsSingleScriptType
= true;
463 case SCRIPTTYPE_LATIN
: nLangWhichId
= EE_CHAR_LANGUAGE
; break;
464 case SCRIPTTYPE_ASIAN
: nLangWhichId
= EE_CHAR_LANGUAGE_CJK
; break;
465 case SCRIPTTYPE_COMPLEX
: nLangWhichId
= EE_CHAR_LANGUAGE_CTL
; break;
466 default: bIsSingleScriptType
= false;
469 // get language according to the script type(s) in use
470 LanguageType nCurrentLang
= LANGUAGE_SYSTEM
;
471 if (bIsSingleScriptType
)
472 nCurrentLang
= GetLanguage( aSet
, nLangWhichId
);
475 // check if all script types are set to LANGUAGE_NONE and return
476 // that if this is the case. Otherwise, having multiple script types
477 // in use always means there are several languages in use...
478 const USHORT aScriptTypes
[3] =
481 EE_CHAR_LANGUAGE_CJK
,
484 nCurrentLang
= LANGUAGE_NONE
;
485 for (sal_uInt16 i
= 0; i
< 3; ++i
)
487 LanguageType nTmpLang
= GetLanguage( aSet
, aScriptTypes
[i
] );
488 if (nTmpLang
!= LANGUAGE_NONE
)
490 nCurrentLang
= LANGUAGE_DONTKNOW
;
495 DBG_ASSERT( nCurrentLang
!= LANGUAGE_SYSTEM
, "failed to get the language?" );
500 String
GetTextForLanguageGuessing( SwWrtShell
&rSh
)
502 // string for guessing language
504 SwPaM
*pCrsr
= rSh
.GetCrsr();
505 SwTxtNode
*pNode
= pCrsr
->GetNode()->GetTxtNode();
508 aText
= pNode
->GetTxt();
512 xub_StrLen nEnd
= pCrsr
->GetPoint()->nContent
.GetIndex();
513 // at most 100 chars to the left...
514 nStt
= nEnd
> 100 ? nEnd
- 100 : 0;
515 // ... and 100 to the right of the cursor position
516 nEnd
= aText
.Len() - nEnd
> 100 ? nEnd
+ 100 : aText
.Len();
517 aText
= aText
.Copy( nStt
, nEnd
- nStt
);
523 String
GetTextForLanguageGuessing(EditEngine
* rEditEngine
, ESelection aDocSelection
)
525 // string for guessing language
528 aText
= rEditEngine
->GetText(aDocSelection
);
532 xub_StrLen nEnd
= aDocSelection
.nEndPos
;
533 // at most 100 chars to the left...
534 nStt
= nEnd
> 100 ? nEnd
- 100 : 0;
535 // ... and 100 to the right of the cursor position
536 nEnd
= aText
.Len() - nEnd
> 100 ? nEnd
+ 100 : aText
.Len();
537 aText
= aText
.Copy( nStt
, nEnd
- nStt
);
544 void SelectPara( EditView
&rEditView
, const ESelection
&rCurSel
)
546 ESelection
aParaSel( rCurSel
.nStartPara
, 0, rCurSel
.nStartPara
, USHRT_MAX
);
547 rEditView
.SetSelection( aParaSel
);
550 void SelectCurrentPara( SwWrtShell
&rWrtSh
)
552 // select current para
553 if (!rWrtSh
.IsSttPara())
554 rWrtSh
.MovePara( fnParaCurr
, fnParaStart
);
555 if (!rWrtSh
.HasMark())
558 if (!rWrtSh
.IsEndPara())
559 rWrtSh
.MovePara( fnParaCurr
, fnParaEnd
);
560 #if OSL_DEBUG_LEVEL > 1
562 rWrtSh
.GetSelectedText( aSelTxt
);