merge the formfield patch from ooo-build
[ooovba.git] / sw / source / ui / shells / langhelper.cxx
blob7a3c424d278f1fcc55c5732ec280794395c6caf9
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: langhelper.cxx,v $
10 * $Revision: 1.4 $
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"
34 #include <string.h>
36 #include <vcl/window.hxx>
38 #include <wrtsh.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>
57 #include <ndtxt.hxx>
58 #include <pam.hxx>
59 #include <view.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
85 String aKeyboardLang;
86 LanguageType nLang = LANGUAGE_DONTKNOW;
88 Window* pWin = rEditView.GetWindow();
89 if(pWin)
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 );
113 return 0;
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();
124 // get the language
125 String aNewLangTxt;
127 SFX_REQUEST_ARG( rReq, pItem, SfxStringItem, SID_LANGUAGE_STATUS , sal_False );
128 if (pItem)
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();
140 if (pFact)
142 VclAbstractDialog* pDlg = pFact->CreateVclDialog( rView.GetWindow(), SID_LANGUAGE_OPTIONS );
143 pDlg->Execute();
144 delete pDlg;
147 else
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") );
157 xub_StrLen nPos = 0;
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;
180 if (bForParagraph)
182 bRestoreSelection = true;
183 SwLangHelper::SelectPara( rEditView, aSelection );
184 aSelection = pOLV->GetSelection();
186 if (!bForSelection) // document language to be changed...
188 rSh.StartAction();
189 rSh.LockView( TRUE );
190 rSh.Push();
192 // prepare to apply new language to all text in document
193 rSh.SelAll();
194 rSh.ExtendedSelectAll();
197 if (aNewLangTxt != aStrNone)
198 SwLangHelper::SetLanguage( rSh, pEditEngine, aSelection, aNewLangTxt, bForSelection, aEditAttr );
199 else
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
204 if (bForSelection)
206 const SwViewOption* pVOpt = rView.GetWrtShellPtr()->GetViewOptions();
207 ULONG nCntrl = pEditEngine->GetControlWord();
208 // turn off
209 if (!pVOpt->IsOnlineSpell())
210 nCntrl &= ~EE_CNTRL_ONLINESPELLING;
211 else
212 nCntrl &= ~EE_CNTRL_ONLINESPELLING;
213 pEditEngine->SetControlWord(nCntrl);
215 //turn back on
216 if (pVOpt->IsOnlineSpell())
217 nCntrl |= EE_CNTRL_ONLINESPELLING;
218 else
219 nCntrl &= ~EE_CNTRL_ONLINESPELLING;
220 pEditEngine->SetControlWord(nCntrl);
222 pEditEngine->CompleteOnlineSpelling();
223 rEditView.Invalidate();
226 if (!bForSelection)
228 // need to release view and restore selection...
229 rSh.Pop( FALSE );
230 rSh.LockView( FALSE );
231 rSh.EndAction();
236 // invalidate slot to get the new language displayed
237 pViewFrame->GetBindings().Invalidate( rReq.GetSlot() );
239 rReq.Done();
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 );
256 //get ScriptType
257 USHORT nLangWhichId = 0;
258 bool bIsSingleScriptType = true;
259 switch (nScriptType)
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;
264 default:
265 bIsSingleScriptType = false;
266 DBG_ERROR( "unexpected case" );
268 if (bIsSingleScriptType)
270 if (bIsForSelection)
272 // apply language to current selection
273 if (pEditEngine)
275 rCoreSet.Put( SvxLanguageItem( nLang, nLangWhichId ));
276 pEditEngine->QuickSetAttribs( rCoreSet, aSelection);
278 else
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 )
313 // EditEngine IDs
314 const USHORT aLangWhichId_EE[3] =
316 EE_CHAR_LANGUAGE,
317 EE_CHAR_LANGUAGE_CJK,
318 EE_CHAR_LANGUAGE_CTL
321 // Writewr IDs
322 const USHORT aLangWhichId_Writer[3] =
324 RES_CHRATR_LANGUAGE,
325 RES_CHRATR_CJK_LANGUAGE,
326 RES_CHRATR_CTL_LANGUAGE
329 if (bIsForSelection)
331 // apply language to current selection
332 if (pEditEngine)
334 for (sal_uInt16 i = 0; i < 3; ++i)
335 rCoreSet.Put( SvxLanguageItem( LANGUAGE_NONE, aLangWhichId_EE[i] ));
336 pEditEngine->QuickSetAttribs( rCoreSet, aSelection);
338 else
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?" );
398 return nLang;
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;
413 switch (nScriptType)
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 );
425 else
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] =
432 RES_CHRATR_LANGUAGE,
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;
443 break;
447 DBG_ASSERT( nCurrentLang != LANGUAGE_SYSTEM, "failed to get the language?" );
449 return nCurrentLang;
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;
461 switch (nScriptType)
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 );
473 else
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] =
480 EE_CHAR_LANGUAGE,
481 EE_CHAR_LANGUAGE_CJK,
482 EE_CHAR_LANGUAGE_CTL
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;
491 break;
495 DBG_ASSERT( nCurrentLang != LANGUAGE_SYSTEM, "failed to get the language?" );
497 return nCurrentLang;
500 String GetTextForLanguageGuessing( SwWrtShell &rSh )
502 // string for guessing language
503 String aText;
504 SwPaM *pCrsr = rSh.GetCrsr();
505 SwTxtNode *pNode = pCrsr->GetNode()->GetTxtNode();
506 if (pNode)
508 aText = pNode->GetTxt();
509 if (aText.Len() > 0)
511 xub_StrLen nStt = 0;
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 );
520 return aText;
523 String GetTextForLanguageGuessing(EditEngine* rEditEngine, ESelection aDocSelection )
525 // string for guessing language
526 String aText;
528 aText = rEditEngine->GetText(aDocSelection);
529 if (aText.Len() > 0)
531 xub_StrLen nStt = 0;
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 );
540 return aText;
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())
556 rWrtSh.SetMark();
557 rWrtSh.SwapPam();
558 if (!rWrtSh.IsEndPara())
559 rWrtSh.MovePara( fnParaCurr, fnParaEnd );
560 #if OSL_DEBUG_LEVEL > 1
561 String aSelTxt;
562 rWrtSh.GetSelectedText( aSelTxt );
563 (void) aSelTxt;
564 #endif