1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <string.h>
21 
22 #include <vcl/window.hxx>
23 
24 #include <wrtsh.hxx>
25 #include <doc.hxx>
26 #include <docary.hxx>
27 #include <charfmt.hxx>
28 
29 #include <sfx2/bindings.hxx>
30 #include <sfx2/dispatch.hxx>
31 #include <sfx2/request.hxx>
32 #include <sfx2/viewfrm.hxx>
33 #include <editeng/eeitem.hxx>
34 #include <editeng/editeng.hxx>
35 #include <editeng/editdata.hxx>
36 #include <editeng/outliner.hxx>
37 #include <editeng/editview.hxx>
38 #include <editeng/scripttypeitem.hxx>
39 #include <editeng/langitem.hxx>
40 
41 #include <svl/languageoptions.hxx>
42 #include <svtools/langtab.hxx>
43 #include <svl/slstitm.hxx>
44 #include <svl/stritem.hxx>
45 #include <svx/svxids.hrc>
46 
47 #include <ndtxt.hxx>
48 #include <pam.hxx>
49 #include <view.hxx>
50 #include <viewopt.hxx>
51 
52 #include <swabstdlg.hxx>
53 
54 #include <langhelper.hxx>
55 #include <memory>
56 
57 using namespace ::com::sun::star;
58 
59 namespace SwLangHelper
60 {
61 
GetLanguageStatus(OutlinerView * pOLV,SfxItemSet & rSet)62     void GetLanguageStatus( OutlinerView* pOLV, SfxItemSet& rSet )
63     {
64         ESelection aSelection = pOLV->GetSelection();
65         EditView& rEditView=pOLV->GetEditView();
66         EditEngine* pEditEngine=rEditView.GetEditEngine();
67 
68         // the value of used script types
69         const SvtScriptType nScriptType =pOLV->GetSelectedScriptType();
70         OUString aScriptTypesInUse( OUString::number( static_cast<int>(nScriptType) ) );//pEditEngine->GetScriptType(aSelection)
71 
72         // get keyboard language
73         OUString aKeyboardLang;
74         LanguageType nLang = LANGUAGE_DONTKNOW;
75 
76         vcl::Window* pWin = rEditView.GetWindow();
77         if(pWin)
78             nLang = pWin->GetInputLanguage();
79         if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
80             aKeyboardLang = SvtLanguageTable::GetLanguageString( nLang );
81 
82         // get the language that is in use
83         OUString aCurrentLang("*");
84         SfxItemSet aSet(pOLV->GetAttribs());
85         nLang = SwLangHelper::GetCurrentLanguage( aSet,nScriptType );
86         if (nLang != LANGUAGE_DONTKNOW)
87             aCurrentLang = SvtLanguageTable::GetLanguageString( nLang );
88 
89         // build sequence for status value
90         uno::Sequence< OUString > aSeq( 4 );
91         aSeq[0] = aCurrentLang;
92         aSeq[1] = aScriptTypesInUse;
93         aSeq[2] = aKeyboardLang;
94         aSeq[3] = SwLangHelper::GetTextForLanguageGuessing( pEditEngine, aSelection );
95 
96         // set sequence as status value
97         SfxStringListItem aItem( SID_LANGUAGE_STATUS );
98         aItem.SetStringList( aSeq );
99         rSet.Put( aItem );
100     }
101 
SetLanguageStatus(OutlinerView * pOLV,SfxRequest & rReq,SwView const & rView,SwWrtShell & rSh)102     bool SetLanguageStatus( OutlinerView* pOLV, SfxRequest &rReq, SwView const &rView, SwWrtShell &rSh )
103     {
104         bool bRestoreSelection = false;
105         SfxItemSet aEditAttr(pOLV->GetAttribs());
106         ESelection   aSelection  = pOLV->GetSelection();
107         EditView   & rEditView   = pOLV->GetEditView();
108         EditEngine * pEditEngine = rEditView.GetEditEngine();
109 
110         // get the language
111         OUString aNewLangText;
112 
113         const SfxStringItem* pItem = rReq.GetArg<SfxStringItem>(SID_LANGUAGE_STATUS);
114         if (pItem)
115             aNewLangText = pItem->GetValue();
116 
117         //!! Remember the view frame right now...
118         //!! (call to GetView().GetViewFrame() will break if the
119         //!! SwTextShell got destroyed meanwhile.)
120         SfxViewFrame *pViewFrame = rView.GetViewFrame();
121 
122         if (aNewLangText == "*" )
123         {
124             // open the dialog "Tools/Options/Language Settings - Language"
125             SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
126             ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateVclDialog( rView.GetFrameWeld(), SID_LANGUAGE_OPTIONS ));
127             pDlg->Execute();
128         }
129         else
130         {
131             // setting the new language...
132             if (!aNewLangText.isEmpty())
133             {
134                 const OUString aSelectionLangPrefix("Current_");
135                 const OUString aParagraphLangPrefix("Paragraph_");
136                 const OUString aDocumentLangPrefix("Default_");
137 
138                 sal_Int32 nPos = 0;
139                 bool bForSelection = true;
140                 bool bForParagraph = false;
141                 if (-1 != (nPos = aNewLangText.indexOf( aSelectionLangPrefix )))
142                 {
143                     // ... for the current selection
144                     aNewLangText = aNewLangText.replaceAt(nPos, aSelectionLangPrefix.getLength(), "");
145                     bForSelection = true;
146                 }
147                 else if (-1 != (nPos = aNewLangText.indexOf( aParagraphLangPrefix )))
148                 {
149                     // ... for the current paragraph language
150                     aNewLangText = aNewLangText.replaceAt(nPos, aParagraphLangPrefix.getLength(), "");
151                     bForSelection = true;
152                     bForParagraph = true;
153                 }
154                 else if (-1 != (nPos = aNewLangText.indexOf( aDocumentLangPrefix )))
155                 {
156                     // ... as default document language
157                     aNewLangText = aNewLangText.replaceAt(nPos, aDocumentLangPrefix.getLength(), "");
158                     bForSelection = false;
159                 }
160 
161                 if (bForParagraph)
162                 {
163                     bRestoreSelection = true;
164                     SwLangHelper::SelectPara( rEditView, aSelection );
165                     aSelection = pOLV->GetSelection();
166                 }
167                 if (!bForSelection) // document language to be changed...
168                 {
169                     rSh.StartAction();
170                     rSh.LockView( true );
171                     rSh.Push();
172 
173                     // prepare to apply new language to all text in document
174                     rSh.SelAll();
175                     rSh.ExtendedSelectAll();
176                 }
177 
178                 if (aNewLangText == "LANGUAGE_NONE")
179                     SwLangHelper::SetLanguage_None( rSh, pOLV, aSelection, bForSelection, aEditAttr );
180                 else if (aNewLangText == "RESET_LANGUAGES")
181                     SwLangHelper::ResetLanguages( rSh, pOLV );
182                 else
183                     SwLangHelper::SetLanguage( rSh, pOLV, aSelection, aNewLangText, bForSelection, aEditAttr );
184 
185                 // ugly hack, as it seems that EditView/EditEngine does not update their spellchecking marks
186                 // when setting a new language attribute
187                 if (bForSelection)
188                 {
189                     const SwViewOption* pVOpt = rView.GetWrtShellPtr()->GetViewOptions();
190                     EEControlBits nCntrl = pEditEngine->GetControlWord();
191                     // turn off
192                     nCntrl &= ~EEControlBits::ONLINESPELLING;
193                     pEditEngine->SetControlWord(nCntrl);
194 
195                     //turn back on
196                     if (pVOpt->IsOnlineSpell())
197                         nCntrl |= EEControlBits::ONLINESPELLING;
198                     else
199                         nCntrl &= ~EEControlBits::ONLINESPELLING;
200                     pEditEngine->SetControlWord(nCntrl);
201 
202                     pEditEngine->CompleteOnlineSpelling();
203                     rEditView.Invalidate();
204                 }
205 
206                 if (!bForSelection)
207                 {
208                     // need to release view and restore selection...
209                     rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
210                     rSh.LockView( false );
211                     rSh.EndAction();
212                 }
213             }
214         }
215 
216         // invalidate slot to get the new language displayed
217         pViewFrame->GetBindings().Invalidate( rReq.GetSlot() );
218 
219         rReq.Done();
220         return bRestoreSelection;
221     }
222 
SetLanguage(SwWrtShell & rWrtSh,const OUString & rLangText,bool bIsForSelection,SfxItemSet & rCoreSet)223     void SetLanguage( SwWrtShell &rWrtSh, const OUString &rLangText, bool bIsForSelection, SfxItemSet &rCoreSet )
224     {
225         SetLanguage( rWrtSh, nullptr , ESelection(), rLangText, bIsForSelection, rCoreSet );
226     }
227 
SetLanguage(SwWrtShell & rWrtSh,OutlinerView const * pOLV,const ESelection & rSelection,const OUString & rLangText,bool bIsForSelection,SfxItemSet & rCoreSet)228     void SetLanguage( SwWrtShell &rWrtSh, OutlinerView const * pOLV, const ESelection& rSelection, const OUString &rLangText, bool bIsForSelection, SfxItemSet &rCoreSet )
229     {
230         const LanguageType nLang = SvtLanguageTable::GetLanguageType( rLangText );
231         if (nLang != LANGUAGE_DONTKNOW)
232         {
233             EditEngine* pEditEngine = pOLV ? pOLV->GetEditView().GetEditEngine() : nullptr;
234             OSL_ENSURE( !pOLV || pEditEngine, "OutlinerView without EditEngine???" );
235 
236             //get ScriptType
237             sal_uInt16 nLangWhichId = 0;
238             bool bIsSingleScriptType = true;
239             switch (SvtLanguageOptions::GetScriptTypeOfLanguage( nLang ))
240             {
241                 case SvtScriptType::LATIN :    nLangWhichId = pEditEngine ? sal_uInt16(EE_CHAR_LANGUAGE) : sal_uInt16(RES_CHRATR_LANGUAGE); break;
242                 case SvtScriptType::ASIAN :    nLangWhichId = pEditEngine ? sal_uInt16(EE_CHAR_LANGUAGE_CJK) : sal_uInt16(RES_CHRATR_CJK_LANGUAGE); break;
243                 case SvtScriptType::COMPLEX :  nLangWhichId = pEditEngine ? sal_uInt16(EE_CHAR_LANGUAGE_CTL) : sal_uInt16(RES_CHRATR_CTL_LANGUAGE); break;
244                 default:
245                     bIsSingleScriptType = false;
246                     OSL_FAIL("unexpected case" );
247             }
248             if (bIsSingleScriptType)
249             {
250                 // change language for selection or paragraph
251                 // (for paragraph is handled by previously having set the selection to the
252                 // whole paragraph)
253                 if (bIsForSelection)
254                 {
255                     // apply language to current selection
256                     if (pEditEngine)
257                     {
258                         rCoreSet.Put( SvxLanguageItem( nLang, nLangWhichId ));
259                         pEditEngine->QuickSetAttribs(rCoreSet, rSelection);
260                     }
261                     else
262                     {
263                         rWrtSh.GetCurAttr( rCoreSet );
264                         rCoreSet.Put( SvxLanguageItem( nLang, nLangWhichId ));
265                         rWrtSh.SetAttrSet( rCoreSet );
266                     }
267                 }
268                 else // change language for all text
269                 {
270                     // set document default language
271                     switch (nLangWhichId)
272                     {
273                          case EE_CHAR_LANGUAGE :      nLangWhichId = RES_CHRATR_LANGUAGE; break;
274                          case EE_CHAR_LANGUAGE_CJK :  nLangWhichId = RES_CHRATR_CJK_LANGUAGE; break;
275                          case EE_CHAR_LANGUAGE_CTL :  nLangWhichId = RES_CHRATR_CTL_LANGUAGE; break;
276                     }
277                     //Set the default document language
278                     rWrtSh.SetDefault( SvxLanguageItem( nLang, nLangWhichId ) );
279 
280                     //Resolves: fdo#35282 Clear the language from all Text Styles, and
281                     //fallback to default document language
282                     const SwTextFormatColls *pColls = rWrtSh.GetDoc()->GetTextFormatColls();
283                     for(size_t i = 0, nCount = pColls->size(); i < nCount; ++i)
284                     {
285                         SwTextFormatColl &rTextColl = *(*pColls)[ i ];
286                         rTextColl.ResetFormatAttr(nLangWhichId);
287                     }
288                     //Resolves: fdo#35282 Clear the language from all Character Styles,
289                     //and fallback to default document language
290                     const SwCharFormats *pCharFormats = rWrtSh.GetDoc()->GetCharFormats();
291                     for(size_t i = 0, nCount = pCharFormats->size(); i < nCount; ++i)
292                     {
293                         SwCharFormat &rCharFormat = *(*pCharFormats)[ i ];
294                         rCharFormat.ResetFormatAttr(nLangWhichId);
295                     }
296 
297                     // #i102191: hard set respective language attribute in text document
298                     // (for all text in the document - which should be selected by now...)
299                     rWrtSh.SetAttrItem( SvxLanguageItem( nLang, nLangWhichId ) );
300                 }
301             }
302         }
303     }
304 
SetLanguage_None(SwWrtShell & rWrtSh,bool bIsForSelection,SfxItemSet & rCoreSet)305     void SetLanguage_None( SwWrtShell &rWrtSh, bool bIsForSelection, SfxItemSet &rCoreSet )
306     {
307         SetLanguage_None( rWrtSh,nullptr,ESelection(),bIsForSelection,rCoreSet );
308     }
309 
SetLanguage_None(SwWrtShell & rWrtSh,OutlinerView const * pOLV,const ESelection & rSelection,bool bIsForSelection,SfxItemSet & rCoreSet)310     void SetLanguage_None( SwWrtShell &rWrtSh, OutlinerView const * pOLV, const ESelection& rSelection, bool bIsForSelection, SfxItemSet &rCoreSet )
311     {
312         // EditEngine IDs
313         const sal_uInt16 aLangWhichId_EE[3] =
314         {
315             EE_CHAR_LANGUAGE,
316             EE_CHAR_LANGUAGE_CJK,
317             EE_CHAR_LANGUAGE_CTL
318         };
319 
320         // Writer IDs
321         const sal_uInt16 aLangWhichId_Writer[3] =
322         {
323             RES_CHRATR_LANGUAGE,
324             RES_CHRATR_CJK_LANGUAGE,
325             RES_CHRATR_CTL_LANGUAGE
326         };
327 
328         if (bIsForSelection)
329         {
330             // change language for selection or paragraph
331             // (for paragraph is handled by previously having set the selection to the
332             // whole paragraph)
333 
334             EditEngine* pEditEngine = pOLV ? pOLV->GetEditView().GetEditEngine() : nullptr;
335             OSL_ENSURE( !pOLV || pEditEngine, "OutlinerView without EditEngine???" );
336             if (pEditEngine)
337             {
338                 for (sal_uInt16 i : aLangWhichId_EE)
339                     rCoreSet.Put( SvxLanguageItem( LANGUAGE_NONE, i ));
340                 pEditEngine->QuickSetAttribs(rCoreSet, rSelection);
341             }
342             else
343             {
344                 rWrtSh.GetCurAttr( rCoreSet );
345                 for (sal_uInt16 i : aLangWhichId_Writer)
346                     rCoreSet.Put( SvxLanguageItem( LANGUAGE_NONE, i ));
347                 rWrtSh.SetAttrSet( rCoreSet );
348             }
349         }
350         else // change language for all text
351         {
352             std::set<sal_uInt16> aAttribs;
353             for (sal_uInt16 i : aLangWhichId_Writer)
354             {
355                 rWrtSh.SetDefault( SvxLanguageItem( LANGUAGE_NONE, i ) );
356                 aAttribs.insert( i );
357             }
358 
359             // set all language attributes to default
360             // (for all text in the document - which should be selected by now...)
361             rWrtSh.ResetAttr( aAttribs );
362         }
363     }
364 
ResetLanguages(SwWrtShell & rWrtSh,OutlinerView const * pOLV)365     void ResetLanguages( SwWrtShell &rWrtSh, OutlinerView const * pOLV )
366     {
367         // reset language for current selection.
368         // The selection should already have been expanded to the whole paragraph or
369         // to all text in the document if those are the ranges where to reset
370         // the language attributes
371 
372         if (pOLV)
373         {
374             EditView &rEditView = pOLV->GetEditView();
375             rEditView.RemoveAttribs( true, EE_CHAR_LANGUAGE );
376             rEditView.RemoveAttribs( true, EE_CHAR_LANGUAGE_CJK );
377             rEditView.RemoveAttribs( true, EE_CHAR_LANGUAGE_CTL );
378         }
379         else
380         {
381             std::set<sal_uInt16> aAttribs;
382             aAttribs.insert( RES_CHRATR_LANGUAGE );
383             aAttribs.insert( RES_CHRATR_CJK_LANGUAGE );
384             aAttribs.insert( RES_CHRATR_CTL_LANGUAGE );
385             rWrtSh.ResetAttr( aAttribs );
386         }
387     }
388 
389     /// @returns : the language for the selected text that is set for the
390     ///     specified attribute (script type).
391     ///     If there are more than one languages used LANGUAGE_DONTKNOW will be returned.
392     /// @param nLangWhichId : one of
393     ///     RES_CHRATR_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CTL_LANGUAGE,
GetLanguage(SwWrtShell & rSh,sal_uInt16 nLangWhichId)394     LanguageType GetLanguage( SwWrtShell &rSh, sal_uInt16 nLangWhichId )
395     {
396         SfxItemSet aSet( rSh.GetAttrPool(), {{nLangWhichId, nLangWhichId}} );
397         rSh.GetCurAttr( aSet );
398 
399         return GetLanguage(aSet,nLangWhichId);
400     }
401 
GetLanguage(SfxItemSet const & aSet,sal_uInt16 nLangWhichId)402     LanguageType GetLanguage( SfxItemSet const & aSet, sal_uInt16 nLangWhichId )
403     {
404 
405         LanguageType nLang = LANGUAGE_SYSTEM;
406 
407         const SfxPoolItem *pItem = nullptr;
408         SfxItemState nState = aSet.GetItemState( nLangWhichId, true, &pItem );
409         if (nState > SfxItemState::DEFAULT && pItem)
410         {
411             // the item is set and can be used
412             nLang = dynamic_cast<const SvxLanguageItem&>(*pItem).GetLanguage();
413         }
414         else if (nState == SfxItemState::DEFAULT)
415         {
416             // since the attribute is not set: retrieve the default value
417             nLang = dynamic_cast<const SvxLanguageItem&>(aSet.GetPool()->GetDefaultItem( nLangWhichId )).GetLanguage();
418         }
419         else if (nState == SfxItemState::DONTCARE)
420         {
421             // there is more than one language...
422             nLang = LANGUAGE_DONTKNOW;
423         }
424         OSL_ENSURE( nLang != LANGUAGE_SYSTEM, "failed to get the language?" );
425 
426         return nLang;
427     }
428 
429     /// @returns: the language in use for the selected text.
430     ///     'In use' means the language(s) matching the script type(s) of the
431     ///     selected text. Or in other words, the language a spell checker would use.
432     ///     If there is more than one language LANGUAGE_DONTKNOW will be returned.
GetCurrentLanguage(SwWrtShell & rSh)433     LanguageType GetCurrentLanguage( SwWrtShell &rSh )
434     {
435         //set language attribute to use according to the script type
436         sal_uInt16 nLangWhichId = 0;
437         bool bIsSingleScriptType = true;
438         switch (rSh.GetScriptType())
439         {
440              case SvtScriptType::LATIN :    nLangWhichId = RES_CHRATR_LANGUAGE; break;
441              case SvtScriptType::ASIAN :    nLangWhichId = RES_CHRATR_CJK_LANGUAGE; break;
442              case SvtScriptType::COMPLEX :  nLangWhichId = RES_CHRATR_CTL_LANGUAGE; break;
443              default: bIsSingleScriptType = false; break;
444         }
445 
446         // get language according to the script type(s) in use
447         LanguageType nCurrentLang = LANGUAGE_SYSTEM;
448         if (bIsSingleScriptType)
449             nCurrentLang = GetLanguage( rSh, nLangWhichId );
450         else
451         {
452             // check if all script types are set to LANGUAGE_NONE and return
453             // that if this is the case. Otherwise, having multiple script types
454             // in use always means there are several languages in use...
455             const sal_uInt16 aScriptTypes[3] =
456             {
457                 RES_CHRATR_LANGUAGE,
458                 RES_CHRATR_CJK_LANGUAGE,
459                 RES_CHRATR_CTL_LANGUAGE
460             };
461             nCurrentLang = LANGUAGE_NONE;
462             for (sal_uInt16 aScriptType : aScriptTypes)
463             {
464                 LanguageType nTmpLang = GetLanguage( rSh, aScriptType );
465                 if (nTmpLang != LANGUAGE_NONE)
466                 {
467                     nCurrentLang = LANGUAGE_DONTKNOW;
468                     break;
469                 }
470             }
471         }
472         OSL_ENSURE( nCurrentLang != LANGUAGE_SYSTEM, "failed to get the language?" );
473 
474         return nCurrentLang;
475     }
476 
477     /// @returns: the language in use for the selected text.
478     ///     'In use' means the language(s) matching the script type(s) of the
479     ///     selected text. Or in other words, the language a spell checker would use.
480     ///     If there is more than one language LANGUAGE_DONTKNOW will be returned.
GetCurrentLanguage(SfxItemSet const & aSet,SvtScriptType nScriptType)481     LanguageType GetCurrentLanguage( SfxItemSet const & aSet, SvtScriptType nScriptType )
482     {
483         //set language attribute to use according to the script type
484         sal_uInt16 nLangWhichId = 0;
485         bool bIsSingleScriptType = true;
486         switch (nScriptType)
487         {
488              case SvtScriptType::LATIN :    nLangWhichId = EE_CHAR_LANGUAGE; break;
489              case SvtScriptType::ASIAN :    nLangWhichId = EE_CHAR_LANGUAGE_CJK; break;
490              case SvtScriptType::COMPLEX :  nLangWhichId = EE_CHAR_LANGUAGE_CTL; break;
491              default: bIsSingleScriptType = false;
492         }
493 
494         // get language according to the script type(s) in use
495         LanguageType nCurrentLang = LANGUAGE_SYSTEM;
496         if (bIsSingleScriptType)
497             nCurrentLang = GetLanguage( aSet, nLangWhichId );
498         else
499         {
500             // check if all script types are set to LANGUAGE_NONE and return
501             // that if this is the case. Otherwise, having multiple script types
502             // in use always means there are several languages in use...
503             const sal_uInt16 aScriptTypes[3] =
504             {
505                 EE_CHAR_LANGUAGE,
506                 EE_CHAR_LANGUAGE_CJK,
507                 EE_CHAR_LANGUAGE_CTL
508             };
509             nCurrentLang = LANGUAGE_NONE;
510             for (sal_uInt16 aScriptType : aScriptTypes)
511             {
512                 LanguageType nTmpLang = GetLanguage( aSet, aScriptType );
513                 if (nTmpLang != LANGUAGE_NONE)
514                 {
515                     nCurrentLang = LANGUAGE_DONTKNOW;
516                     break;
517                 }
518             }
519         }
520         OSL_ENSURE( nCurrentLang != LANGUAGE_SYSTEM, "failed to get the language?" );
521 
522         return nCurrentLang;
523     }
524 
GetTextForLanguageGuessing(SwWrtShell const & rSh)525     OUString GetTextForLanguageGuessing( SwWrtShell const &rSh )
526     {
527         // string for guessing language
528         OUString aText;
529         SwPaM *pCursor = rSh.GetCursor();
530         SwTextNode *pNode = pCursor->GetNode().GetTextNode();
531         if (pNode)
532         {
533             aText = pNode->GetText();
534             if (!aText.isEmpty())
535             {
536                 sal_Int32 nEnd = pCursor->GetPoint()->nContent.GetIndex();
537                 // at most 100 chars to the left...
538                 const sal_Int32 nStt = nEnd > 100 ? nEnd - 100 : 0;
539                 // ... and 100 to the right of the cursor position
540                 nEnd = aText.getLength() - nEnd > 100 ? nEnd + 100 : aText.getLength();
541                 aText = aText.copy( nStt, nEnd - nStt );
542             }
543         }
544         return aText;
545     }
546 
GetTextForLanguageGuessing(EditEngine const * rEditEngine,const ESelection & rDocSelection)547     OUString GetTextForLanguageGuessing(EditEngine const * rEditEngine, const ESelection& rDocSelection)
548     {
549         // string for guessing language
550 
551         // get the full text of the paragraph that the end of selection is in
552         OUString aText = rEditEngine->GetText(rDocSelection.nEndPos);
553         if (!aText.isEmpty())
554         {
555             sal_Int32 nStt = 0;
556             sal_Int32 nEnd = rDocSelection.nEndPos;
557             // at most 100 chars to the left...
558             nStt = nEnd > 100 ? nEnd - 100 : 0;
559             // ... and 100 to the right of the cursor position
560             nEnd = aText.getLength() - nEnd > 100 ? nEnd + 100 : aText.getLength();
561             aText = aText.copy( nStt, nEnd - nStt );
562         }
563 
564         return aText;
565     }
566 
SelectPara(EditView & rEditView,const ESelection & rCurSel)567     void SelectPara( EditView &rEditView, const ESelection &rCurSel )
568     {
569         ESelection aParaSel( rCurSel.nStartPara, 0, rCurSel.nStartPara, EE_TEXTPOS_ALL );
570         rEditView.SetSelection( aParaSel );
571     }
572 
SelectCurrentPara(SwWrtShell & rWrtSh)573     void SelectCurrentPara( SwWrtShell &rWrtSh )
574     {
575         // select current para
576         if (!rWrtSh.IsSttPara())
577             rWrtSh.MovePara( GoCurrPara, fnParaStart );
578         if (!rWrtSh.HasMark())
579             rWrtSh.SetMark();
580         rWrtSh.SwapPam();
581         if (!rWrtSh.IsEndPara())
582             rWrtSh.MovePara( GoCurrPara, fnParaEnd );
583     #if OSL_DEBUG_LEVEL > 1
584         OUString aSelText;
585         rWrtSh.GetSelectedText( aSelText );
586         (void) aSelText;
587     #endif
588     }
589 }
590 
591 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
592