Line data Source code
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 "SwRewriter.hxx"
21 : #include "chrdlg.hrc"
22 : #include "cmdid.h"
23 : #include "comcore.hrc"
24 : #include "crsskip.hxx"
25 : #include "doc.hxx"
26 : #include "docsh.hxx"
27 : #include "edtwin.hxx"
28 : #include "helpid.h"
29 : #include "hintids.hxx"
30 : #include "langhelper.hxx"
31 : #include "ndtxt.hxx"
32 : #include "olmenu.hrc"
33 : #include "olmenu.hxx"
34 : #include "swabstdlg.hxx"
35 : #include "swmodule.hxx"
36 : #include "swtypes.hxx"
37 : #include "swundo.hxx"
38 : #include "uitool.hxx"
39 : #include "unomid.h"
40 : #include "view.hxx"
41 : #include "viewopt.hxx"
42 : #include "wrtsh.hxx"
43 : #include "wview.hxx"
44 :
45 : #include <comphelper/anytostring.hxx>
46 : #include <comphelper/processfactory.hxx>
47 : #include <cppuhelper/exc_hlp.hxx>
48 : #include <editeng/acorrcfg.hxx>
49 : #include <editeng/svxacorr.hxx>
50 : #include <editeng/langitem.hxx>
51 : #include <editeng/splwrap.hxx>
52 : #include <editeng/brushitem.hxx>
53 : #include <editeng/unolingu.hxx>
54 : #include <editeng/editview.hxx>
55 : #include <i18nlangtag/mslangid.hxx>
56 : #include <i18nlangtag/languagetag.hxx>
57 : #include <linguistic/lngprops.hxx>
58 : #include <linguistic/misc.hxx>
59 : #include <osl/file.hxx>
60 : #include <rtl/string.hxx>
61 : #include <vcl/graphicfilter.hxx>
62 : #include <sfx2/dispatch.hxx>
63 : #include <sfx2/imagemgr.hxx>
64 : #include <sfx2/request.hxx>
65 : #include <sfx2/sfxdlg.hxx>
66 : #include <svl/itemset.hxx>
67 : #include <svl/languageoptions.hxx>
68 : #include <svl/stritem.hxx>
69 : #include <svtools/langtab.hxx>
70 : #include <svx/dlgutil.hxx>
71 : #include <unotools/lingucfg.hxx>
72 : #include <unotools/linguprops.hxx>
73 : #include <vcl/layout.hxx>
74 : #include <vcl/settings.hxx>
75 : #include <vcl/svapp.hxx>
76 : #include <sal/macros.h>
77 :
78 : #include <map>
79 :
80 : #include <com/sun/star/container/XIndexAccess.hpp>
81 : #include <com/sun/star/container/XNameAccess.hpp>
82 : #include <com/sun/star/document/XDocumentLanguages.hpp>
83 : #include <com/sun/star/frame/XModuleManager.hpp>
84 : #include <com/sun/star/frame/XStorable.hpp>
85 : #include <com/sun/star/i18n/ScriptType.hpp>
86 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
87 : #include <com/sun/star/lang/XServiceInfo.hpp>
88 : #include <com/sun/star/linguistic2/SingleProofreadingError.hpp>
89 : #include <com/sun/star/linguistic2/XLanguageGuessing.hpp>
90 : #include <com/sun/star/linguistic2/XSpellChecker1.hpp>
91 : #include <com/sun/star/uno/Any.hxx>
92 : #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
93 : #include <com/sun/star/system/SystemShellExecute.hpp>
94 : #include <com/sun/star/frame/theUICommandDescription.hpp>
95 :
96 : using namespace ::com::sun::star;
97 :
98 : extern void sw_CharDialog( SwWrtShell &rWrtSh, bool bUseDialog, sal_uInt16 nSlot,const SfxItemSet *pArgs, SfxRequest *pReq );
99 :
100 : /// @returns : the language for the selected text that is set for the
101 : /// specified attribute (script type).
102 : /// If there are more than one languages used LANGUAGE_DONTKNOW will be returned.
103 : /// @param nLangWhichId : one of
104 : /// RES_CHRATR_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CTL_LANGUAGE,
105 : /// @returns: the language in use for the selected text.
106 : /// 'In use' means the language(s) matching the script type(s) of the
107 : /// selected text. Or in other words, the language a spell checker would use.
108 : /// If there is more than one language LANGUAGE_DONTKNOW will be returned.
109 : // check if nScriptType includes the script type associated to nLang
110 0 : static inline bool lcl_checkScriptType( sal_Int16 nScriptType, LanguageType nLang )
111 : {
112 0 : return 0 != (nScriptType & SvtLanguageOptions::GetScriptTypeOfLanguage( nLang ));
113 : }
114 :
115 0 : void SwSpellPopup::fillLangPopupMenu(
116 : PopupMenu *pPopupMenu,
117 : sal_uInt16 nLangItemIdStart,
118 : uno::Sequence< OUString > aSeq,
119 : SwWrtShell* pWrtSh,
120 : std::map< sal_Int16, OUString > &rLangTable )
121 : {
122 0 : if (!pPopupMenu)
123 0 : return;
124 :
125 0 : SvtLanguageTable aLanguageTable;
126 :
127 : // set of languages to be displayed in the sub menus
128 0 : std::set< OUString > aLangItems;
129 :
130 0 : OUString aCurLang( aSeq[0] );
131 0 : sal_uInt16 nScriptType = static_cast< sal_Int16 >(aSeq[1].toInt32());
132 0 : OUString aKeyboardLang( aSeq[2] );
133 0 : OUString aGuessedTextLang( aSeq[3] );
134 :
135 0 : if (!aCurLang.isEmpty() &&
136 0 : LANGUAGE_DONTKNOW != aLanguageTable.GetType( aCurLang ))
137 0 : aLangItems.insert( aCurLang );
138 :
139 : //2--System
140 0 : const AllSettings& rAllSettings = Application::GetSettings();
141 0 : LanguageType rSystemLanguage = rAllSettings.GetLanguageTag().getLanguageType();
142 0 : if (rSystemLanguage != LANGUAGE_DONTKNOW)
143 : {
144 0 : if (lcl_checkScriptType( nScriptType, rSystemLanguage ))
145 0 : aLangItems.insert( aLanguageTable.GetString(rSystemLanguage) );
146 : }
147 :
148 : //3--UI
149 0 : LanguageType rUILanguage = rAllSettings.GetUILanguageTag().getLanguageType();
150 0 : if (rUILanguage != LANGUAGE_DONTKNOW)
151 : {
152 0 : if (lcl_checkScriptType(nScriptType, rUILanguage ))
153 0 : aLangItems.insert( aLanguageTable.GetString(rUILanguage) );
154 : }
155 :
156 : //4--guessed language
157 0 : if (!aGuessedTextLang.isEmpty())
158 : {
159 0 : if (lcl_checkScriptType(nScriptType, aLanguageTable.GetType(aGuessedTextLang)))
160 0 : aLangItems.insert( aGuessedTextLang );
161 : }
162 :
163 : //5--keyboard language
164 0 : if (!aKeyboardLang.isEmpty())
165 : {
166 0 : if (lcl_checkScriptType(nScriptType, aLanguageTable.GetType(aKeyboardLang)))
167 0 : aLangItems.insert( aKeyboardLang );
168 : }
169 :
170 : //6--all languages used in current document
171 0 : uno::Reference< com::sun::star::frame::XModel > xModel;
172 0 : uno::Reference< com::sun::star::frame::XController > xController( pWrtSh->GetView().GetViewFrame()->GetFrame().GetFrameInterface()->getController(), uno::UNO_QUERY );
173 0 : if ( xController.is() )
174 0 : xModel = xController->getModel();
175 0 : uno::Reference< document::XDocumentLanguages > xDocumentLanguages( xModel, uno::UNO_QUERY );
176 : /*the description of nScriptType flags
177 : LATIN : 0x0001
178 : ASIAN : 0x0002
179 : COMPLEX: 0x0004
180 : */
181 0 : const sal_Int16 nMaxCount = 7;
182 0 : if (xDocumentLanguages.is())
183 : {
184 0 : uno::Sequence< lang::Locale > rLocales( xDocumentLanguages->getDocumentLanguages( nScriptType, nMaxCount ) );
185 0 : if (rLocales.getLength() > 0)
186 : {
187 0 : for (sal_uInt16 i = 0; i < rLocales.getLength(); ++i)
188 : {
189 0 : if (aLangItems.size() == (size_t)nMaxCount)
190 0 : break;
191 0 : const lang::Locale& rLocale = rLocales[i];
192 0 : if (lcl_checkScriptType( nScriptType, aLanguageTable.GetType( rLocale.Language )))
193 0 : aLangItems.insert( rLocale.Language );
194 : }
195 0 : }
196 : }
197 :
198 0 : sal_uInt16 nItemId = nLangItemIdStart;
199 0 : std::set< OUString >::const_iterator it;
200 0 : for (it = aLangItems.begin(); it != aLangItems.end(); ++it)
201 : {
202 0 : OUString aEntryTxt( *it );
203 0 : if (aEntryTxt != OUString( aLanguageTable.GetString( LANGUAGE_NONE ) )&&
204 0 : aEntryTxt != "*" && // multiple languages in current selection
205 0 : !aEntryTxt.isEmpty()) // 'no language found' from language guessing
206 : {
207 : OSL_ENSURE( nLangItemIdStart <= nItemId && nItemId <= nLangItemIdStart + MN_MAX_NUM_LANG,
208 : "nItemId outside of expected range!" );
209 0 : pPopupMenu->InsertItem( nItemId, aEntryTxt, MIB_RADIOCHECK );
210 0 : if (aEntryTxt == aCurLang)
211 : {
212 : //make a check mark for the current language
213 0 : pPopupMenu->CheckItem( nItemId, true );
214 : }
215 0 : rLangTable[ nItemId ] = aEntryTxt;
216 0 : ++nItemId;
217 : }
218 0 : }
219 :
220 0 : pPopupMenu->InsertItem( nLangItemIdStart + MN_NONE_OFFSET, OUString(SW_RES( STR_LANGSTATUS_NONE )), MIB_RADIOCHECK );
221 0 : if ( aLanguageTable.GetString( LANGUAGE_NONE ) == aCurLang )
222 0 : pPopupMenu->CheckItem( nLangItemIdStart + MN_NONE_OFFSET, true );
223 :
224 0 : pPopupMenu->InsertItem( nLangItemIdStart + MN_RESET_OFFSET, OUString(SW_RES( STR_RESET_TO_DEFAULT_LANGUAGE )), 0 );
225 0 : pPopupMenu->InsertItem( nLangItemIdStart + MN_MORE_OFFSET, OUString(SW_RES( STR_LANGSTATUS_MORE )), 0 );
226 : }
227 :
228 0 : OUString RetrieveLabelFromCommand( const OUString& aCmdURL )
229 : {
230 0 : OUString aLabel;
231 0 : if ( !aCmdURL.isEmpty() )
232 : {
233 : try
234 : {
235 : uno::Reference< container::XNameAccess > const xNameAccess(
236 : frame::theUICommandDescription::get(
237 : ::comphelper::getProcessComponentContext() ),
238 0 : uno::UNO_QUERY_THROW );
239 0 : uno::Reference< container::XNameAccess > xUICommandLabels;
240 0 : uno::Any a = xNameAccess->getByName( "com.sun.star.text.TextDocument" );
241 0 : uno::Reference< container::XNameAccess > xUICommands;
242 0 : a >>= xUICommandLabels;
243 0 : OUString aStr;
244 0 : uno::Sequence< beans::PropertyValue > aPropSeq;
245 0 : a = xUICommandLabels->getByName( aCmdURL );
246 0 : if ( a >>= aPropSeq )
247 : {
248 0 : for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ )
249 : {
250 0 : if ( aPropSeq[i].Name == "Name" )
251 : {
252 0 : aPropSeq[i].Value >>= aStr;
253 0 : break;
254 : }
255 : }
256 : }
257 0 : aLabel = aStr;
258 : }
259 0 : catch (const uno::Exception&)
260 : {
261 : }
262 : }
263 :
264 0 : return aLabel;
265 : }
266 :
267 0 : SwSpellPopup::SwSpellPopup(
268 : SwWrtShell* pWrtSh,
269 : const uno::Reference< linguistic2::XSpellAlternatives > &xAlt,
270 : const OUString &rParaText
271 : ) : PopupMenu( SW_RES(MN_SPELL_POPUP) )
272 : , m_pSh( pWrtSh )
273 : , m_xSpellAlt(xAlt)
274 0 : , m_bGrammarResults(false)
275 : {
276 : OSL_ENSURE(m_xSpellAlt.is(), "no spelling alternatives available");
277 :
278 0 : SetMenuFlags(MENU_FLAG_NOAUTOMNEMONICS);
279 0 : bool bUseImagesInMenus = Application::GetSettings().GetStyleSettings().GetUseImagesInMenus();
280 :
281 0 : m_nCheckedLanguage = LANGUAGE_NONE;
282 0 : if (m_xSpellAlt.is())
283 : {
284 0 : m_nCheckedLanguage = LanguageTag( m_xSpellAlt->getLocale() ).getLanguageType();
285 0 : m_aSuggestions = m_xSpellAlt->getAlternatives();
286 : }
287 0 : sal_Int16 nStringCount = static_cast< sal_Int16 >( m_aSuggestions.getLength() );
288 :
289 0 : SvtLinguConfig aCfg;
290 :
291 0 : PopupMenu *pMenu = GetPopupMenu(MN_AUTOCORR);
292 0 : pMenu->SetMenuFlags(MENU_FLAG_NOAUTOMNEMONICS);
293 0 : sal_Bool bEnable = sal_False;
294 0 : if( nStringCount )
295 : {
296 0 : Image aImage;
297 0 : OUString aSuggestionImageUrl;
298 :
299 0 : if (bUseImagesInMenus)
300 : {
301 0 : uno::Reference< container::XNamed > xNamed( m_xSpellAlt, uno::UNO_QUERY );
302 0 : if (xNamed.is())
303 : {
304 0 : aSuggestionImageUrl = aCfg.GetSpellAndGrammarContextSuggestionImage( xNamed->getName() );
305 0 : aImage = Image( aSuggestionImageUrl );
306 0 : }
307 : }
308 :
309 0 : InsertSeparator(OString(), 0);
310 0 : bEnable = sal_True;
311 0 : sal_uInt16 nAutoCorrItemId = MN_AUTOCORR_START;
312 0 : sal_uInt16 nItemId = MN_SUGGESTION_START;
313 0 : for (sal_uInt16 i = 0; i < nStringCount; ++i)
314 : {
315 0 : const OUString aEntry = m_aSuggestions[ i ];
316 0 : InsertItem(nItemId, aEntry, 0, OString(), i);
317 0 : SetHelpId( nItemId, HID_LINGU_REPLACE);
318 0 : if (!aSuggestionImageUrl.isEmpty())
319 0 : SetItemImage( nItemId, aImage );
320 :
321 0 : pMenu->InsertItem( nAutoCorrItemId, aEntry );
322 0 : pMenu->SetHelpId( nAutoCorrItemId, HID_LINGU_AUTOCORR);
323 :
324 0 : ++nAutoCorrItemId;
325 0 : ++nItemId;
326 0 : }
327 : }
328 :
329 0 : OUString aIgnoreSelection( SW_RES( STR_IGNORE_SELECTION ) );
330 0 : OUString aSpellingAndGrammar = RetrieveLabelFromCommand( ".uno:SpellingAndGrammarDialog" );
331 0 : SetItemText( MN_SPELLING_DLG, aSpellingAndGrammar );
332 0 : sal_uInt16 nItemPos = GetItemPos( MN_IGNORE_WORD );
333 0 : InsertItem(MN_IGNORE_SELECTION, aIgnoreSelection, 0, OString(), nItemPos);
334 0 : SetHelpId( MN_IGNORE_SELECTION, HID_LINGU_IGNORE_SELECTION);
335 :
336 0 : EnableItem( MN_AUTOCORR, bEnable );
337 :
338 0 : uno::Reference< linguistic2::XLanguageGuessing > xLG = SW_MOD()->GetLanguageGuesser();
339 0 : m_nGuessLangWord = LANGUAGE_NONE;
340 0 : m_nGuessLangPara = LANGUAGE_NONE;
341 0 : if (m_xSpellAlt.is() && xLG.is())
342 : {
343 0 : m_nGuessLangWord = EditView::CheckLanguage( m_xSpellAlt->getWord(), ::GetSpellChecker(), xLG, false );
344 0 : m_nGuessLangPara = EditView::CheckLanguage( rParaText, ::GetSpellChecker(), xLG, true );
345 : }
346 0 : if (m_nGuessLangWord != LANGUAGE_NONE || m_nGuessLangPara != LANGUAGE_NONE)
347 : {
348 : // make sure LANGUAGE_NONE gets not used as menu entry
349 0 : if (m_nGuessLangWord == LANGUAGE_NONE)
350 0 : m_nGuessLangWord = m_nGuessLangPara;
351 0 : if (m_nGuessLangPara == LANGUAGE_NONE)
352 0 : m_nGuessLangPara = m_nGuessLangWord;
353 : }
354 :
355 0 : pMenu = GetPopupMenu(MN_ADD_TO_DIC);
356 0 : pMenu->SetMenuFlags(MENU_FLAG_NOAUTOMNEMONICS); //! necessary to retrieve the correct dictionary name in 'Execute' below
357 0 : uno::Reference< linguistic2::XSearchableDictionaryList > xDicList( SvxGetDictionaryList() );
358 0 : sal_uInt16 nItemId = MN_DICTIONARIES_START;
359 0 : if (xDicList.is())
360 : {
361 : // add the default positive dictionary to dic-list (if not already done).
362 : // This is to ensure that there is at least one dictionary to which
363 : // words could be added.
364 0 : uno::Reference< linguistic2::XDictionary > xDic( SvxGetOrCreatePosDic( xDicList ) );
365 0 : if (xDic.is())
366 0 : xDic->setActive( sal_True );
367 :
368 0 : m_aDics = xDicList->getDictionaries();
369 0 : const uno::Reference< linguistic2::XDictionary > *pDic = m_aDics.getConstArray();
370 0 : sal_uInt16 nDicCount = static_cast< sal_uInt16 >(m_aDics.getLength());
371 :
372 0 : for( sal_uInt16 i = 0; i < nDicCount; i++ )
373 : {
374 0 : uno::Reference< linguistic2::XDictionary > xDicTmp( pDic[i], uno::UNO_QUERY );
375 0 : if (!xDicTmp.is() || SvxGetIgnoreAllList() == xDicTmp)
376 0 : continue;
377 :
378 0 : uno::Reference< frame::XStorable > xStor( xDicTmp, uno::UNO_QUERY );
379 0 : LanguageType nActLanguage = LanguageTag( xDicTmp->getLocale() ).getLanguageType();
380 0 : if( xDicTmp->isActive()
381 0 : && xDicTmp->getDictionaryType() != linguistic2::DictionaryType_NEGATIVE
382 0 : && (m_nCheckedLanguage == nActLanguage || LANGUAGE_NONE == nActLanguage )
383 0 : && (!xStor.is() || !xStor->isReadonly()) )
384 : {
385 : // the extra 1 is because of the (possible) external
386 : // linguistic entry above
387 0 : pMenu->InsertItem( nItemId, xDicTmp->getName() );
388 0 : m_aDicNameSingle = xDicTmp->getName();
389 :
390 0 : if (bUseImagesInMenus)
391 : {
392 0 : uno::Reference< lang::XServiceInfo > xSvcInfo( xDicTmp, uno::UNO_QUERY );
393 0 : if (xSvcInfo.is())
394 : {
395 : OUString aDictionaryImageUrl( aCfg.GetSpellAndGrammarContextDictionaryImage(
396 0 : xSvcInfo->getImplementationName() ) );
397 0 : if (!aDictionaryImageUrl.isEmpty())
398 : {
399 0 : Image aImage( aDictionaryImageUrl );
400 0 : pMenu->SetItemImage( nItemId, aImage );
401 0 : }
402 0 : }
403 : }
404 :
405 0 : ++nItemId;
406 : }
407 0 : }
408 : }
409 0 : EnableItem( MN_ADD_TO_DIC, ((nItemId - MN_DICTIONARIES_START) > 1)?sal_True:sal_False );
410 0 : EnableItem( MN_ADD_TO_DIC_SINGLE, ((nItemId - MN_DICTIONARIES_START) == 1)?sal_True:sal_False );
411 :
412 : //ADD NEW LANGUAGE MENU ITEM
413 :
414 0 : OUString aScriptTypesInUse( OUString::number( pWrtSh->GetScriptType() ) );
415 0 : SvtLanguageTable aLanguageTable;
416 :
417 : // get keyboard language
418 0 : OUString aKeyboardLang;
419 0 : SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin();
420 0 : LanguageType nLang = rEditWin.GetInputLanguage();
421 0 : if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
422 0 : aKeyboardLang = aLanguageTable.GetString( nLang );
423 :
424 : // get the language that is in use
425 0 : OUString aCurrentLang("*");
426 0 : nLang = SwLangHelper::GetCurrentLanguage( *pWrtSh );
427 0 : if (nLang != LANGUAGE_DONTKNOW)
428 0 : aCurrentLang = aLanguageTable.GetString( nLang );
429 :
430 : // build sequence for status value
431 0 : uno::Sequence< OUString > aSeq( 4 );
432 0 : aSeq[0] = aCurrentLang;
433 0 : aSeq[1] = aScriptTypesInUse;
434 0 : aSeq[2] = aKeyboardLang;
435 0 : aSeq[3] = aLanguageTable.GetString(m_nGuessLangWord);
436 :
437 0 : pMenu = GetPopupMenu(MN_SET_LANGUAGE_SELECTION);
438 0 : fillLangPopupMenu( pMenu, MN_SET_LANGUAGE_SELECTION_START, aSeq, pWrtSh, m_aLangTable_Text );
439 0 : EnableItem( MN_SET_LANGUAGE_SELECTION, true );
440 :
441 0 : pMenu = GetPopupMenu(MN_SET_LANGUAGE_PARAGRAPH);
442 0 : fillLangPopupMenu( pMenu, MN_SET_LANGUAGE_PARAGRAPH_START, aSeq, pWrtSh, m_aLangTable_Paragraph );
443 0 : EnableItem( MN_SET_LANGUAGE_PARAGRAPH, true );
444 :
445 0 : if (bUseImagesInMenus)
446 : {
447 0 : uno::Reference< frame::XFrame > xFrame = pWrtSh->GetView().GetViewFrame()->GetFrame().GetFrameInterface();
448 0 : Image rImg = ::GetImage( xFrame, ".uno:SpellingAndGrammarDialog", false );
449 0 : SetItemImage( MN_SPELLING_DLG, rImg );
450 : }
451 :
452 0 : checkRedline();
453 0 : RemoveDisabledEntries( true, true );
454 0 : }
455 :
456 0 : SwSpellPopup::SwSpellPopup(
457 : SwWrtShell *pWrtSh,
458 : const linguistic2::ProofreadingResult &rResult,
459 : sal_Int32 nErrorInResult,
460 : const uno::Sequence< OUString > &rSuggestions,
461 : const OUString &rParaText ) :
462 : PopupMenu( SW_RES(MN_SPELL_POPUP) ),
463 : m_pSh( pWrtSh ),
464 : m_xGrammarResult( rResult ),
465 : m_aSuggestions( rSuggestions ),
466 : m_sExplanationLink( ),
467 : m_bGrammarResults( true ),
468 0 : m_aInfo16( SW_RES(IMG_INFO_16) )
469 : {
470 0 : m_nCheckedLanguage = LanguageTag::convertToLanguageType( rResult.aLocale );
471 0 : m_nGrammarError = nErrorInResult;
472 0 : bool bUseImagesInMenus = Application::GetSettings().GetStyleSettings().GetUseImagesInMenus();
473 :
474 0 : sal_uInt16 nPos = 0;
475 0 : OUString aMessageText( rResult.aErrors[ nErrorInResult ].aShortComment );
476 0 : InsertSeparator(OString(), nPos++);
477 0 : InsertItem(MN_SHORT_COMMENT, aMessageText, MIB_NOSELECT, OString(), nPos++);
478 0 : if (bUseImagesInMenus)
479 0 : SetItemImage( MN_SHORT_COMMENT, m_aInfo16 );
480 :
481 : // Add an item to show detailled infos if the FullCommentURL property is defined
482 0 : beans::PropertyValues aProperties = rResult.aErrors[ nErrorInResult ].aProperties;
483 : {
484 0 : sal_Int32 i = 0;
485 0 : while ( m_sExplanationLink.isEmpty() && i < aProperties.getLength() )
486 : {
487 0 : if ( aProperties[i].Name == "FullCommentURL" )
488 : {
489 0 : uno::Any aValue = aProperties[i].Value;
490 0 : aValue >>= m_sExplanationLink;
491 : }
492 0 : ++i;
493 : }
494 : }
495 :
496 0 : if ( !m_sExplanationLink.isEmpty( ) )
497 : {
498 0 : InsertItem(MN_EXPLANATION_LINK, SW_RESSTR(STR_EXPLANATION_LINK), MIB_TEXT | MIB_HELP, OString(), nPos++);
499 : }
500 :
501 0 : SetMenuFlags(MENU_FLAG_NOAUTOMNEMONICS);
502 :
503 0 : InsertSeparator(OString(), nPos++);
504 0 : sal_Int32 nStringCount = m_aSuggestions.getLength();
505 0 : if ( nStringCount ) // suggestions available...
506 : {
507 0 : Image aImage;
508 0 : OUString aSuggestionImageUrl;
509 :
510 0 : if (bUseImagesInMenus)
511 : {
512 0 : uno::Reference< lang::XServiceInfo > xInfo( rResult.xProofreader, uno::UNO_QUERY );
513 0 : if (xInfo.is())
514 : {
515 0 : aSuggestionImageUrl = SvtLinguConfig().GetSpellAndGrammarContextSuggestionImage( xInfo->getImplementationName() );
516 0 : aImage = Image( aSuggestionImageUrl );
517 0 : }
518 : }
519 :
520 0 : sal_uInt16 nItemId = MN_SUGGESTION_START;
521 0 : for (sal_uInt16 i = 0; i < nStringCount; ++i)
522 : {
523 0 : const OUString aEntry = m_aSuggestions[ i ];
524 0 : InsertItem(nItemId, aEntry, 0, OString(), nPos++);
525 0 : SetHelpId( nItemId, HID_LINGU_REPLACE );
526 0 : if (!aSuggestionImageUrl.isEmpty())
527 0 : SetItemImage( nItemId, aImage );
528 :
529 0 : ++nItemId;
530 0 : }
531 0 : InsertSeparator(OString(), nPos++);
532 : }
533 :
534 0 : OUString aIgnoreSelection( SW_RES( STR_IGNORE_SELECTION ) );
535 0 : OUString aSpellingAndGrammar = RetrieveLabelFromCommand( ".uno:SpellingAndGrammarDialog" );
536 0 : SetItemText( MN_SPELLING_DLG, aSpellingAndGrammar );
537 0 : sal_uInt16 nItemPos = GetItemPos( MN_IGNORE_WORD );
538 0 : InsertItem( MN_IGNORE_SELECTION, aIgnoreSelection, 0, OString(), nItemPos );
539 0 : SetHelpId( MN_IGNORE_SELECTION, HID_LINGU_IGNORE_SELECTION);
540 :
541 0 : EnableItem( MN_AUTOCORR, false );
542 :
543 0 : uno::Reference< linguistic2::XLanguageGuessing > xLG = SW_MOD()->GetLanguageGuesser();
544 0 : m_nGuessLangWord = LANGUAGE_NONE;
545 0 : m_nGuessLangPara = LANGUAGE_NONE;
546 0 : if (xLG.is())
547 : {
548 0 : m_nGuessLangPara = EditView::CheckLanguage( rParaText, ::GetSpellChecker(), xLG, true );
549 : }
550 0 : if (m_nGuessLangWord != LANGUAGE_NONE || m_nGuessLangPara != LANGUAGE_NONE)
551 : {
552 : // make sure LANGUAGE_NONE gets not used as menu entry
553 0 : if (m_nGuessLangWord == LANGUAGE_NONE)
554 0 : m_nGuessLangWord = m_nGuessLangPara;
555 0 : if (m_nGuessLangPara == LANGUAGE_NONE)
556 0 : m_nGuessLangPara = m_nGuessLangWord;
557 : }
558 :
559 0 : EnableItem( MN_ADD_TO_DIC, false );
560 0 : EnableItem( MN_ADD_TO_DIC_SINGLE, false );
561 :
562 : //ADD NEW LANGUAGE MENU ITEM
563 :
564 0 : OUString aScriptTypesInUse( OUString::number( pWrtSh->GetScriptType() ) );
565 0 : SvtLanguageTable aLanguageTable;
566 :
567 : // get keyboard language
568 0 : OUString aKeyboardLang;
569 0 : SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin();
570 0 : LanguageType nLang = rEditWin.GetInputLanguage();
571 0 : if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
572 0 : aKeyboardLang = aLanguageTable.GetString( nLang );
573 :
574 : // get the language that is in use
575 0 : OUString aCurrentLang("*");
576 0 : nLang = SwLangHelper::GetCurrentLanguage( *pWrtSh );
577 0 : if (nLang != LANGUAGE_DONTKNOW)
578 0 : aCurrentLang = aLanguageTable.GetString( nLang );
579 :
580 : // build sequence for status value
581 0 : uno::Sequence< OUString > aSeq( 4 );
582 0 : aSeq[0] = aCurrentLang;
583 0 : aSeq[1] = aScriptTypesInUse;
584 0 : aSeq[2] = aKeyboardLang;
585 0 : aSeq[3] = aLanguageTable.GetString(m_nGuessLangWord);
586 :
587 0 : PopupMenu *pMenu = GetPopupMenu(MN_SET_LANGUAGE_SELECTION);
588 0 : fillLangPopupMenu( pMenu, MN_SET_LANGUAGE_SELECTION_START, aSeq, pWrtSh, m_aLangTable_Text );
589 0 : EnableItem( MN_SET_LANGUAGE_SELECTION, true );
590 :
591 0 : pMenu = GetPopupMenu(MN_SET_LANGUAGE_PARAGRAPH);
592 0 : fillLangPopupMenu( pMenu, MN_SET_LANGUAGE_PARAGRAPH_START, aSeq, pWrtSh, m_aLangTable_Paragraph );
593 0 : EnableItem( MN_SET_LANGUAGE_PARAGRAPH, true );
594 :
595 0 : if (bUseImagesInMenus)
596 : {
597 0 : uno::Reference< frame::XFrame > xFrame = pWrtSh->GetView().GetViewFrame()->GetFrame().GetFrameInterface();
598 0 : Image rImg = ::GetImage( xFrame, ".uno:SpellingAndGrammarDialog", false );
599 0 : SetItemImage( MN_SPELLING_DLG, rImg );
600 : }
601 :
602 0 : checkRedline();
603 0 : RemoveDisabledEntries( true, true );
604 0 : }
605 :
606 0 : void SwSpellPopup::checkRedline()
607 : {
608 : // Let SwView::GetState() already has the logic on when to disable the
609 : // accept/reject and the next/prev change items, let it do the decision.
610 :
611 : // Build an item set that contains a void item for each menu entry. The
612 : // WhichId of each item is set, so SwView may clear it.
613 : static const sal_uInt16 pRedlineIds[] = {
614 : FN_REDLINE_ACCEPT_DIRECT,
615 : FN_REDLINE_REJECT_DIRECT,
616 : FN_REDLINE_NEXT_CHANGE,
617 : FN_REDLINE_PREV_CHANGE
618 : };
619 0 : SwDoc *pDoc = m_pSh->GetDoc();
620 0 : SfxItemSet aSet(pDoc->GetAttrPool(), FN_REDLINE_ACCEPT_DIRECT, FN_REDLINE_PREV_CHANGE);
621 0 : for (size_t i = 0; i < SAL_N_ELEMENTS(pRedlineIds); ++i)
622 : {
623 0 : const sal_uInt16 nWhich = pRedlineIds[i];
624 0 : aSet.Put(SfxVoidItem(nWhich), nWhich);
625 : }
626 0 : m_pSh->GetView().GetState(aSet);
627 :
628 : // Enable/disable items based on if the which id of the void items are
629 : // cleared or not.
630 0 : for (size_t i = 0; i < SAL_N_ELEMENTS(pRedlineIds); ++i)
631 : {
632 0 : const sal_uInt16 nWhich = pRedlineIds[i];
633 0 : EnableItem(nWhich, aSet.Get(nWhich).Which());
634 0 : }
635 0 : }
636 :
637 0 : sal_uInt16 SwSpellPopup::Execute( const Rectangle& rWordPos, Window* pWin )
638 : {
639 0 : sal_uInt16 nRet = PopupMenu::Execute(pWin, pWin->LogicToPixel(rWordPos));
640 0 : Execute( nRet );
641 0 : return nRet;
642 : }
643 :
644 0 : void SwSpellPopup::Execute( sal_uInt16 nId )
645 : {
646 0 : if (nId == USHRT_MAX)
647 0 : return;
648 :
649 0 : if (/*m_bGrammarResults && */nId == MN_SHORT_COMMENT)
650 0 : return; // nothing to do since it is the error message (short comment)
651 :
652 0 : if ((MN_SUGGESTION_START <= nId && nId <= MN_SUGGESTION_END) ||
653 0 : (MN_AUTOCORR_START <= nId && nId <= MN_AUTOCORR_END))
654 : {
655 0 : sal_Int32 nAltIdx = (MN_SUGGESTION_START <= nId && nId <= MN_SUGGESTION_END) ?
656 0 : nId - MN_SUGGESTION_START : nId - MN_AUTOCORR_START;
657 : OSL_ENSURE( 0 <= nAltIdx && nAltIdx < m_aSuggestions.getLength(), "index out of range" );
658 0 : if (0 <= nAltIdx && nAltIdx < m_aSuggestions.getLength() && (m_bGrammarResults || m_xSpellAlt.is()))
659 : {
660 0 : sal_Bool bOldIns = m_pSh->IsInsMode();
661 0 : m_pSh->SetInsMode( sal_True );
662 :
663 0 : OUString aTmp( m_aSuggestions[ nAltIdx ] );
664 0 : OUString aOrig( m_bGrammarResults ? OUString() : m_xSpellAlt->getWord() );
665 :
666 : // if original word has a trailing . (likely the end of a sentence)
667 : // and the replacement text hasn't, then add it to the replacement
668 0 : if (!aTmp.isEmpty() && !aOrig.isEmpty() &&
669 0 : aOrig.endsWith(".") && /* !IsAlphaNumeric ??*/
670 0 : !aTmp.endsWith("."))
671 : {
672 0 : aTmp += ".";
673 : }
674 :
675 : // #111827#
676 0 : SwRewriter aRewriter;
677 :
678 0 : aRewriter.AddRule(UndoArg1, m_pSh->GetCrsrDescr());
679 0 : aRewriter.AddRule(UndoArg2, OUString(SW_RES(STR_YIELDS)));
680 :
681 0 : OUString aTmpStr( SW_RES(STR_START_QUOTE) );
682 0 : aTmpStr += aTmp;
683 0 : aTmpStr += OUString(SW_RES(STR_END_QUOTE));
684 0 : aRewriter.AddRule(UndoArg3, aTmpStr);
685 :
686 0 : m_pSh->StartUndo(UNDO_UI_REPLACE, &aRewriter);
687 0 : m_pSh->StartAction();
688 0 : m_pSh->DelLeft();
689 :
690 0 : m_pSh->Insert( aTmp );
691 :
692 : /* #102505# EndAction/EndUndo moved down since insertion
693 : of temporary auto correction is now undoable two and
694 : must reside in the same undo group.*/
695 :
696 : // record only if it's NOT already present in autocorrection
697 0 : SvxAutoCorrect* pACorr = SvxAutoCorrCfg::Get().GetAutoCorrect();
698 :
699 0 : OUString aOrigWord( m_bGrammarResults ? OUString() : m_xSpellAlt->getWord() ) ;
700 0 : OUString aNewWord( m_aSuggestions[ nAltIdx ] );
701 0 : SvxPrepareAutoCorrect( aOrigWord, aNewWord );
702 :
703 0 : if (MN_AUTOCORR_START <= nId && nId <= MN_AUTOCORR_END)
704 0 : pACorr->PutText( aOrigWord, aNewWord, m_nCheckedLanguage );
705 :
706 : /* #102505# EndAction/EndUndo moved down since insertion
707 : of temporary auto correction is now undoable two and
708 : must reside in the same undo group.*/
709 0 : m_pSh->EndAction();
710 0 : m_pSh->EndUndo();
711 :
712 0 : m_pSh->SetInsMode( bOldIns );
713 0 : }
714 : }
715 0 : else if (nId == MN_SPELLING_DLG)
716 : {
717 0 : if (m_bGrammarResults)
718 : {
719 0 : SvtLinguConfig().SetProperty( UPN_IS_GRAMMAR_INTERACTIVE, uno::makeAny( sal_True ));
720 : }
721 0 : m_pSh->Left(CRSR_SKIP_CHARS, sal_False, 1, sal_False );
722 : {
723 0 : uno::Reference<linguistic2::XSearchableDictionaryList> xDictionaryList( SvxGetDictionaryList() );
724 0 : SvxDicListChgClamp aClamp( xDictionaryList );
725 0 : m_pSh->GetView().GetViewFrame()->GetDispatcher()->
726 0 : Execute( FN_SPELL_GRAMMAR_DIALOG, SFX_CALLMODE_ASYNCHRON );
727 : }
728 : }
729 0 : else if (nId == MN_IGNORE_SELECTION)
730 : {
731 0 : SwPaM *pPaM = m_pSh->GetCrsr();
732 0 : if (pPaM)
733 0 : m_pSh->IgnoreGrammarErrorAt( *pPaM );
734 : }
735 0 : else if (nId == MN_IGNORE_WORD)
736 : {
737 0 : uno::Reference< linguistic2::XDictionary > xDictionary( SvxGetIgnoreAllList(), uno::UNO_QUERY );
738 0 : if (m_bGrammarResults) {
739 : try
740 : {
741 0 : m_xGrammarResult.xProofreader->ignoreRule(
742 0 : m_xGrammarResult.aErrors[ m_nGrammarError ].aRuleIdentifier,
743 0 : m_xGrammarResult.aLocale );
744 : // refresh the layout of the actual paragraph (faster)
745 0 : SwPaM *pPaM = m_pSh->GetCrsr();
746 0 : if (pPaM)
747 0 : m_pSh->IgnoreGrammarErrorAt( *pPaM );
748 : // refresh the layout of all paragraphs (workaround to launch a dictionary event)
749 0 : xDictionary->setActive(sal_False);
750 0 : xDictionary->setActive(sal_True);
751 : }
752 0 : catch( const uno::Exception& )
753 : {
754 : }
755 : } else {
756 : linguistic::AddEntryToDic( xDictionary,
757 0 : m_xSpellAlt->getWord(), false, OUString(), LANGUAGE_NONE );
758 0 : }
759 : }
760 0 : else if ((MN_DICTIONARIES_START <= nId && nId <= MN_DICTIONARIES_END) || nId == MN_ADD_TO_DIC_SINGLE)
761 : {
762 0 : OUString aWord( m_xSpellAlt->getWord() );
763 0 : OUString aDicName;
764 :
765 0 : if (MN_DICTIONARIES_START <= nId && nId <= MN_DICTIONARIES_END)
766 : {
767 0 : PopupMenu *pMenu = GetPopupMenu(MN_ADD_TO_DIC);
768 0 : aDicName = pMenu->GetItemText(nId);
769 : }
770 : else
771 0 : aDicName = m_aDicNameSingle;
772 :
773 0 : uno::Reference< linguistic2::XDictionary > xDic;
774 0 : uno::Reference< linguistic2::XSearchableDictionaryList > xDicList( SvxGetDictionaryList() );
775 0 : if (xDicList.is())
776 0 : xDic = xDicList->getDictionaryByName( aDicName );
777 :
778 0 : if (xDic.is())
779 : {
780 0 : sal_Int16 nAddRes = linguistic::AddEntryToDic( xDic, aWord, false, OUString(), LANGUAGE_NONE );
781 : // save modified user-dictionary if it is persistent
782 0 : uno::Reference< frame::XStorable > xSavDic( xDic, uno::UNO_QUERY );
783 0 : if (xSavDic.is())
784 0 : xSavDic->store();
785 :
786 0 : if (DIC_ERR_NONE != nAddRes
787 0 : && !xDic->getEntry( aWord ).is())
788 : {
789 : SvxDicError(
790 0 : &m_pSh->GetView().GetViewFrame()->GetWindow(),
791 0 : nAddRes );
792 0 : }
793 0 : }
794 : }
795 0 : else if ( nId == MN_EXPLANATION_LINK && !m_sExplanationLink.isEmpty() )
796 : {
797 : try
798 : {
799 : uno::Reference< com::sun::star::system::XSystemShellExecute > xSystemShellExecute(
800 0 : com::sun::star::system::SystemShellExecute::create( ::comphelper::getProcessComponentContext() ) );
801 0 : xSystemShellExecute->execute( m_sExplanationLink, OUString(),
802 0 : com::sun::star::system::SystemShellExecuteFlags::URIS_ONLY );
803 : }
804 0 : catch (const uno::Exception&)
805 : {
806 0 : uno::Any exc( ::cppu::getCaughtException() );
807 0 : OUString msg( ::comphelper::anyToString( exc ) );
808 0 : const SolarMutexGuard guard;
809 0 : MessageDialog aErrorBox(NULL, msg);
810 0 : aErrorBox.SetText( "Explanations" );
811 0 : aErrorBox.Execute();
812 : }
813 : }
814 0 : else if (nId == FN_REDLINE_ACCEPT_DIRECT || nId == FN_REDLINE_REJECT_DIRECT
815 0 : || nId == FN_REDLINE_NEXT_CHANGE || nId == FN_REDLINE_PREV_CHANGE)
816 : {
817 : // Let SwView::Execute() handle the redline actions.
818 0 : SfxRequest aReq(m_pSh->GetView().GetViewFrame(), nId);
819 0 : m_pSh->GetView().Execute(aReq);
820 : }
821 : else
822 : {
823 : // Set language for selection or for paragraph...
824 :
825 0 : SfxItemSet aCoreSet( m_pSh->GetView().GetPool(),
826 : RES_CHRATR_LANGUAGE, RES_CHRATR_LANGUAGE,
827 : RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_LANGUAGE,
828 : RES_CHRATR_CTL_LANGUAGE, RES_CHRATR_CTL_LANGUAGE,
829 0 : 0 );
830 0 : OUString aNewLangTxt;
831 :
832 0 : if (MN_SET_LANGUAGE_SELECTION_START <= nId && nId <= MN_SET_LANGUAGE_SELECTION_END)
833 : {
834 : //Set language for current selection
835 0 : aNewLangTxt = m_aLangTable_Text[nId];
836 0 : SwLangHelper::SetLanguage( *m_pSh, aNewLangTxt, true, aCoreSet );
837 : }
838 0 : else if (nId == MN_SET_SELECTION_NONE)
839 : {
840 : //Set Language_None for current selection
841 0 : SwLangHelper::SetLanguage_None( *m_pSh, true, aCoreSet );
842 : }
843 0 : else if (nId == MN_SET_SELECTION_RESET)
844 : {
845 : //reset languages for current selection
846 0 : SwLangHelper::ResetLanguages( *m_pSh, true );
847 : }
848 0 : else if (nId == MN_SET_SELECTION_MORE)
849 : {
850 : //Open Format/Character Dialog
851 0 : sw_CharDialog( *m_pSh, true, SID_ATTR_CHAR_FONT, 0, 0 );
852 : }
853 0 : else if (MN_SET_LANGUAGE_PARAGRAPH_START <= nId && nId <= MN_SET_LANGUAGE_PARAGRAPH_END)
854 : {
855 : //Set language for current paragraph
856 0 : aNewLangTxt = m_aLangTable_Paragraph[nId];
857 0 : m_pSh->Push(); // save cursor
858 0 : SwLangHelper::SelectCurrentPara( *m_pSh );
859 0 : SwLangHelper::SetLanguage( *m_pSh, aNewLangTxt, true, aCoreSet );
860 0 : m_pSh->Pop( sal_False ); // restore cursor
861 : }
862 0 : else if (nId == MN_SET_PARA_NONE)
863 : {
864 : //Set Language_None for current paragraph
865 0 : m_pSh->Push(); // save cursor
866 0 : SwLangHelper::SelectCurrentPara( *m_pSh );
867 0 : SwLangHelper::SetLanguage_None( *m_pSh, true, aCoreSet );
868 0 : m_pSh->Pop( sal_False ); // restore cursor
869 : }
870 0 : else if (nId == MN_SET_PARA_RESET)
871 : {
872 : //reset languages for current paragraph
873 0 : m_pSh->Push(); // save cursor
874 0 : SwLangHelper::SelectCurrentPara( *m_pSh );
875 0 : SwLangHelper::ResetLanguages( *m_pSh, true );
876 0 : m_pSh->Pop( sal_False ); // restore cursor
877 : }
878 0 : else if (nId == MN_SET_PARA_MORE)
879 : {
880 0 : m_pSh->Push(); // save cursor
881 0 : SwLangHelper::SelectCurrentPara( *m_pSh );
882 : //Open Format/Character Dialog
883 0 : sw_CharDialog( *m_pSh, true, SID_ATTR_CHAR_FONT, 0, 0 );
884 0 : m_pSh->Pop( sal_False ); // restore cursor
885 0 : }
886 : }
887 :
888 0 : m_pSh->EnterStdMode();
889 0 : }
890 :
891 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|