/src/libreoffice/sd/source/ui/docshell/docshel3.cxx
Line | Count | Source |
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 <DrawDocShell.hxx> |
21 | | |
22 | | #include <svx/svxids.hrc> |
23 | | |
24 | | #include <svx/ofaitem.hxx> |
25 | | #include <svl/stritem.hxx> |
26 | | #include <svl/srchitem.hxx> |
27 | | #include <svl/languageoptions.hxx> |
28 | | #include <svtools/langtab.hxx> |
29 | | #include <sfx2/request.hxx> |
30 | | #include <sfx2/sfxdlg.hxx> |
31 | | #include <sfx2/viewfrm.hxx> |
32 | | #include <vcl/abstdlg.hxx> |
33 | | #include <svx/drawitem.hxx> |
34 | | #include <editeng/langitem.hxx> |
35 | | #include <editeng/eeitem.hxx> |
36 | | #include <editeng/outlobj.hxx> |
37 | | #include <editeng/editobj.hxx> |
38 | | #include <com/sun/star/i18n/TextConversionOption.hpp> |
39 | | #include <sfx2/notebookbar/SfxNotebookBar.hxx> |
40 | | #include <editeng/editeng.hxx> |
41 | | #include <osl/diagnose.h> |
42 | | |
43 | | #include <sdmod.hxx> |
44 | | #include <drawdoc.hxx> |
45 | | #include <fusearch.hxx> |
46 | | #include <ViewShell.hxx> |
47 | | #include <slideshow.hxx> |
48 | | #include <fuhhconv.hxx> |
49 | | #include <memory> |
50 | | |
51 | | using namespace ::com::sun::star; |
52 | | |
53 | | namespace sd { |
54 | | |
55 | | static void lcl_setLanguageForObj( SdrObject *pObj, LanguageType nLang, bool bLanguageNone ) |
56 | 0 | { |
57 | 0 | const sal_uInt16 aLangWhichId_EE[3] = |
58 | 0 | { |
59 | 0 | EE_CHAR_LANGUAGE, |
60 | 0 | EE_CHAR_LANGUAGE_CJK, |
61 | 0 | EE_CHAR_LANGUAGE_CTL |
62 | 0 | }; |
63 | |
|
64 | 0 | if( bLanguageNone ) |
65 | 0 | nLang = LANGUAGE_NONE; |
66 | |
|
67 | 0 | if( nLang != LANGUAGE_DONTKNOW ) |
68 | 0 | { |
69 | 0 | if( nLang == LANGUAGE_NONE ) |
70 | 0 | { |
71 | 0 | for(sal_uInt16 n : aLangWhichId_EE) |
72 | 0 | pObj->SetMergedItem( SvxLanguageItem( nLang, n ) ); |
73 | 0 | } |
74 | 0 | else |
75 | 0 | { |
76 | 0 | sal_uInt16 nLangWhichId = 0; |
77 | 0 | SvtScriptType nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( nLang ); |
78 | 0 | switch (nScriptType) |
79 | 0 | { |
80 | 0 | case SvtScriptType::LATIN : nLangWhichId = EE_CHAR_LANGUAGE; break; |
81 | 0 | case SvtScriptType::ASIAN : nLangWhichId = EE_CHAR_LANGUAGE_CJK; break; |
82 | 0 | case SvtScriptType::COMPLEX : nLangWhichId = EE_CHAR_LANGUAGE_CTL; break; |
83 | 0 | default: |
84 | 0 | OSL_FAIL("unexpected case" ); |
85 | 0 | return; |
86 | 0 | } |
87 | 0 | pObj->SetMergedItem( SvxLanguageItem( nLang, nLangWhichId ) ); |
88 | | |
89 | | // Reset shape text language to default, so it inherits the shape language set above. |
90 | 0 | OutlinerParaObject* pOutliner = pObj->GetOutlinerParaObject(); |
91 | 0 | if (pOutliner) |
92 | 0 | { |
93 | 0 | EditTextObject& rEditTextObject |
94 | 0 | = const_cast<EditTextObject&>(pOutliner->GetTextObject()); |
95 | 0 | for (sal_uInt16 n : aLangWhichId_EE) |
96 | 0 | { |
97 | 0 | rEditTextObject.RemoveCharAttribs(n); |
98 | 0 | } |
99 | 0 | } |
100 | 0 | } |
101 | 0 | } |
102 | 0 | else // Reset to default |
103 | 0 | { |
104 | 0 | for(sal_uInt16 n : aLangWhichId_EE) |
105 | 0 | pObj->ClearMergedItem( n ); |
106 | 0 | } |
107 | 0 | } |
108 | | |
109 | | static void lcl_setLanguage( const SdDrawDocument *pDoc, std::u16string_view rLanguage, bool bLanguageNone = false ) |
110 | 0 | { |
111 | 0 | LanguageType nLang = SvtLanguageTable::GetLanguageType( rLanguage ); |
112 | | |
113 | | // Do it for SdDrawDocument->SetLanguage as well? |
114 | |
|
115 | 0 | sal_uInt16 nPageCount = pDoc->GetPageCount(); // Pick All Pages |
116 | 0 | for( sal_uInt16 nPage = 0; nPage < nPageCount; nPage++ ) |
117 | 0 | { |
118 | 0 | const SdrPage *pPage = pDoc->GetPage( nPage ); |
119 | 0 | for (const rtl::Reference<SdrObject>& pObj : *pPage) |
120 | 0 | if (pObj->GetObjIdentifier() != SdrObjKind::Page) |
121 | 0 | lcl_setLanguageForObj( pObj.get(), nLang, bLanguageNone ); |
122 | 0 | } |
123 | 0 | } |
124 | | |
125 | | /** |
126 | | * Handles SFX-Requests |
127 | | */ |
128 | | void DrawDocShell::Execute( SfxRequest& rReq ) |
129 | 0 | { |
130 | 0 | if(mpViewShell && SlideShow::IsRunning( mpViewShell->GetViewShellBase() ) |
131 | 0 | && !SlideShow::IsInteractiveSlideshow( mpViewShell->GetViewShellBase() ) ) // IASS |
132 | 0 | { |
133 | | // during a running presentation no slot will be executed |
134 | 0 | return; |
135 | 0 | } |
136 | | |
137 | 0 | switch ( rReq.GetSlot() ) |
138 | 0 | { |
139 | 0 | case SID_SEARCH_ITEM: |
140 | 0 | { |
141 | 0 | const SfxItemSet* pReqArgs = rReq.GetArgs(); |
142 | |
|
143 | 0 | if (pReqArgs) |
144 | 0 | { |
145 | 0 | const SvxSearchItem & rSearchItem = pReqArgs->Get(SID_SEARCH_ITEM); |
146 | |
|
147 | 0 | SdModule::get()->SetSearchItem(std::unique_ptr<SvxSearchItem>(rSearchItem.Clone())); |
148 | 0 | } |
149 | |
|
150 | 0 | rReq.Done(); |
151 | 0 | } |
152 | 0 | break; |
153 | | |
154 | 0 | case FID_SEARCH_ON: |
155 | 0 | { |
156 | | // no action needed |
157 | 0 | rReq.Done(); |
158 | 0 | } |
159 | 0 | break; |
160 | | |
161 | 0 | case FID_SEARCH_OFF: |
162 | 0 | { |
163 | 0 | if (mpViewShell) |
164 | 0 | { |
165 | 0 | sd::View* pView = mpViewShell->GetView(); |
166 | 0 | if (pView) |
167 | 0 | { |
168 | 0 | auto& rFunctionContext = pView->getSearchContext(); |
169 | 0 | rtl::Reference<FuSearch>& xFuSearch(rFunctionContext.getFunctionSearch()); |
170 | |
|
171 | 0 | if (xFuSearch.is()) |
172 | 0 | { |
173 | | // End Search&Replace in all docshells |
174 | 0 | SfxObjectShell* pFirstShell = SfxObjectShell::GetFirst(); |
175 | 0 | SfxObjectShell* pShell = pFirstShell; |
176 | |
|
177 | 0 | while (pShell) |
178 | 0 | { |
179 | 0 | auto pDrawDocShell = dynamic_cast<DrawDocShell*>(pShell); |
180 | 0 | if (pDrawDocShell) |
181 | 0 | pDrawDocShell->CancelSearching(); |
182 | |
|
183 | 0 | pShell = SfxObjectShell::GetNext(*pShell); |
184 | |
|
185 | 0 | if (pShell == pFirstShell) |
186 | 0 | pShell = nullptr; |
187 | 0 | } |
188 | |
|
189 | 0 | rFunctionContext.resetSearchFunction(); |
190 | 0 | Invalidate(); |
191 | 0 | rReq.Done(); |
192 | 0 | } |
193 | 0 | } |
194 | 0 | } |
195 | 0 | } |
196 | 0 | break; |
197 | | |
198 | 0 | case FID_SEARCH_NOW: |
199 | 0 | { |
200 | 0 | const SfxItemSet* pReqArgs = rReq.GetArgs(); |
201 | |
|
202 | 0 | if (pReqArgs && mpViewShell) |
203 | 0 | { |
204 | 0 | sd::View* pView = mpViewShell->GetView(); |
205 | 0 | if (pView) |
206 | 0 | { |
207 | 0 | rtl::Reference<FuSearch> & xFuSearch = pView->getSearchContext().getFunctionSearch(); |
208 | |
|
209 | 0 | if (!xFuSearch.is()) |
210 | 0 | { |
211 | 0 | xFuSearch = rtl::Reference<FuSearch>( |
212 | 0 | FuSearch::createPtr(*mpViewShell, |
213 | 0 | mpViewShell->GetActiveWindow(), |
214 | 0 | pView, *mpDoc, rReq)); |
215 | |
|
216 | 0 | pView->getSearchContext().setSearchFunction(xFuSearch); |
217 | 0 | } |
218 | |
|
219 | 0 | if (xFuSearch.is()) |
220 | 0 | { |
221 | 0 | const SvxSearchItem& rSearchItem = pReqArgs->Get(SID_SEARCH_ITEM); |
222 | |
|
223 | 0 | SdModule::get()->SetSearchItem(std::unique_ptr<SvxSearchItem>(rSearchItem.Clone())); |
224 | 0 | xFuSearch->SearchAndReplace(&rSearchItem); |
225 | 0 | } |
226 | 0 | } |
227 | 0 | } |
228 | |
|
229 | 0 | rReq.Done(); |
230 | 0 | } |
231 | 0 | break; |
232 | | |
233 | 0 | case SID_SAVEDOC: |
234 | 0 | case SID_SAVEASDOC: |
235 | 0 | { |
236 | 0 | const SfxPoolItem* pItem = nullptr; |
237 | 0 | bool bCommitChanges = false; |
238 | 0 | const SfxItemSet* pReqArgs = rReq.GetArgs(); |
239 | 0 | bool bHasDontTerminateEdit = pReqArgs && pReqArgs->HasItem(FN_PARAM_1, &pItem); |
240 | 0 | if (bHasDontTerminateEdit && pItem) |
241 | 0 | bCommitChanges = !static_cast<const SfxBoolItem*>(pItem)->GetValue(); |
242 | |
|
243 | 0 | if (mpViewShell && bCommitChanges) |
244 | 0 | { |
245 | 0 | SdrView* pView = mpViewShell->GetView(); |
246 | 0 | if (pView) |
247 | 0 | pView->SdrEndTextEdit(); |
248 | 0 | } |
249 | |
|
250 | 0 | ExecuteSlot( rReq, SfxObjectShell::GetStaticInterface() ); |
251 | 0 | } |
252 | 0 | break; |
253 | | |
254 | 0 | case SID_VERSION: |
255 | 0 | case SID_CLOSEDOC: |
256 | 0 | { |
257 | 0 | ExecuteSlot(rReq, SfxObjectShell::GetStaticInterface()); |
258 | 0 | } |
259 | 0 | break; |
260 | | |
261 | 0 | case SID_GET_COLORLIST: |
262 | 0 | { |
263 | 0 | const SvxColorListItem* pColItem = GetItem( SID_COLOR_TABLE ); |
264 | 0 | const XColorListRef& pList = pColItem->GetColorList(); |
265 | 0 | rReq.SetReturnValue( OfaXColorListItem( SID_GET_COLORLIST, pList ) ); |
266 | 0 | } |
267 | 0 | break; |
268 | | |
269 | 0 | case SID_HANGUL_HANJA_CONVERSION: |
270 | 0 | { |
271 | 0 | if( mpViewShell ) |
272 | 0 | { |
273 | 0 | rtl::Reference<FuPoor> aFunc( FuHangulHanjaConversion::Create(*mpViewShell, mpViewShell->GetActiveWindow(), mpViewShell->GetView(), *mpDoc, rReq ) ); |
274 | 0 | static_cast< FuHangulHanjaConversion* >( aFunc.get() )->StartConversion( LANGUAGE_KOREAN, LANGUAGE_KOREAN, nullptr, i18n::TextConversionOption::CHARACTER_BY_CHARACTER, true ); |
275 | 0 | } |
276 | 0 | } |
277 | 0 | break; |
278 | | |
279 | 0 | case SID_CHINESE_CONVERSION: |
280 | 0 | { |
281 | 0 | if( mpViewShell ) |
282 | 0 | { |
283 | 0 | rtl::Reference<FuPoor> aFunc( FuHangulHanjaConversion::Create(*mpViewShell, mpViewShell->GetActiveWindow(), mpViewShell->GetView(), *mpDoc, rReq ) ); |
284 | 0 | static_cast< FuHangulHanjaConversion* >( aFunc.get() )->StartChineseConversion(); |
285 | 0 | } |
286 | 0 | } |
287 | 0 | break; |
288 | 0 | case SID_LANGUAGE_STATUS: |
289 | 0 | { |
290 | 0 | OUString aNewLangTxt; |
291 | 0 | const SfxStringItem* pItem = rReq.GetArg<SfxStringItem>(SID_LANGUAGE_STATUS); |
292 | 0 | if (pItem) |
293 | 0 | aNewLangTxt = pItem->GetValue(); |
294 | |
|
295 | 0 | if (aNewLangTxt == "*" ) |
296 | 0 | { |
297 | | // open the dialog "Tools/Options/Languages and Locales - General" |
298 | 0 | if (mpViewShell) |
299 | 0 | { |
300 | 0 | SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); |
301 | 0 | ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateVclDialog( mpViewShell->GetFrameWeld(), SID_LANGUAGE_OPTIONS )); |
302 | 0 | pDlg->Execute(); |
303 | 0 | } |
304 | 0 | } |
305 | 0 | else |
306 | 0 | { |
307 | 0 | if( mpViewShell ) |
308 | 0 | { |
309 | | // setting the new language... |
310 | 0 | if (!aNewLangTxt.isEmpty()) |
311 | 0 | { |
312 | 0 | static constexpr OUString aSelectionLangPrefix(u"Current_"_ustr); |
313 | 0 | static constexpr OUString aParagraphLangPrefix(u"Paragraph_"_ustr); |
314 | 0 | static constexpr OUString aDocumentLangPrefix(u"Default_"_ustr); |
315 | |
|
316 | 0 | bool bSelection = false; |
317 | 0 | bool bParagraph = false; |
318 | |
|
319 | 0 | SdDrawDocument* pDoc = mpViewShell->GetDoc(); |
320 | 0 | sal_Int32 nPos = -1; |
321 | 0 | if (-1 != (nPos = aNewLangTxt.indexOf( aDocumentLangPrefix ))) |
322 | 0 | { |
323 | 0 | aNewLangTxt = aNewLangTxt.replaceAt( nPos, aDocumentLangPrefix.getLength(), u"" ); |
324 | |
|
325 | 0 | if (aNewLangTxt == "LANGUAGE_NONE") |
326 | 0 | lcl_setLanguage( pDoc, u"", true ); |
327 | 0 | else if (aNewLangTxt == "RESET_LANGUAGES") |
328 | 0 | lcl_setLanguage( pDoc, u"" ); |
329 | 0 | else |
330 | 0 | lcl_setLanguage( pDoc, aNewLangTxt ); |
331 | 0 | } |
332 | 0 | else if (-1 != (nPos = aNewLangTxt.indexOf( aSelectionLangPrefix ))) |
333 | 0 | { |
334 | 0 | bSelection = true; |
335 | 0 | aNewLangTxt = aNewLangTxt.replaceAt( nPos, aSelectionLangPrefix.getLength(), u"" ); |
336 | 0 | } |
337 | 0 | else if (-1 != (nPos = aNewLangTxt.indexOf( aParagraphLangPrefix ))) |
338 | 0 | { |
339 | 0 | bParagraph = true; |
340 | 0 | aNewLangTxt = aNewLangTxt.replaceAt( nPos, aParagraphLangPrefix.getLength(), u"" ); |
341 | 0 | } |
342 | |
|
343 | 0 | if (bSelection || bParagraph) |
344 | 0 | { |
345 | 0 | SdrView* pSdrView = mpViewShell->GetDrawView(); |
346 | 0 | if (!pSdrView) |
347 | 0 | return; |
348 | | |
349 | 0 | EditView& rEditView = pSdrView->GetTextEditOutlinerView()->GetEditView(); |
350 | 0 | const LanguageType nLangToUse = SvtLanguageTable::GetLanguageType( aNewLangTxt ); |
351 | 0 | SvtScriptType nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( nLangToUse ); |
352 | |
|
353 | 0 | SfxItemSet aAttrs = rEditView.getEditEngine().GetEmptyItemSet(); |
354 | 0 | if (nScriptType == SvtScriptType::LATIN) |
355 | 0 | aAttrs.Put( SvxLanguageItem( nLangToUse, EE_CHAR_LANGUAGE ) ); |
356 | 0 | if (nScriptType == SvtScriptType::COMPLEX) |
357 | 0 | aAttrs.Put( SvxLanguageItem( nLangToUse, EE_CHAR_LANGUAGE_CTL ) ); |
358 | 0 | if (nScriptType == SvtScriptType::ASIAN) |
359 | 0 | aAttrs.Put( SvxLanguageItem( nLangToUse, EE_CHAR_LANGUAGE_CJK ) ); |
360 | 0 | ESelection aOldSel; |
361 | 0 | if (bParagraph) |
362 | 0 | { |
363 | 0 | ESelection aSel = rEditView.GetSelection(); |
364 | 0 | aOldSel = aSel; |
365 | 0 | aSel.start.nIndex = 0; |
366 | 0 | aSel.end.nIndex = EE_TEXTPOS_MAX; |
367 | 0 | rEditView.SetSelection( aSel ); |
368 | 0 | } |
369 | |
|
370 | 0 | rEditView.SetAttribs( aAttrs ); |
371 | 0 | if (bParagraph) |
372 | 0 | rEditView.SetSelection( aOldSel ); |
373 | 0 | } |
374 | | |
375 | 0 | if ( pDoc->GetOnlineSpell() ) |
376 | 0 | { |
377 | 0 | pDoc->StartOnlineSpelling(); |
378 | 0 | } |
379 | 0 | } |
380 | 0 | } |
381 | 0 | } |
382 | 0 | Broadcast(SfxHint(SfxHintId::LanguageChanged)); |
383 | 0 | } |
384 | 0 | break; |
385 | 0 | case SID_SPELLCHECK_IGNORE_ALL: |
386 | 0 | { |
387 | 0 | if (!mpViewShell) |
388 | 0 | return; |
389 | 0 | SdrView* pSdrView = mpViewShell->GetDrawView(); |
390 | 0 | if (!pSdrView) |
391 | 0 | return; |
392 | | |
393 | 0 | EditView& rEditView = pSdrView->GetTextEditOutlinerView()->GetEditView(); |
394 | 0 | OUString sIgnoreText; |
395 | 0 | const SfxStringItem* pItem2 = rReq.GetArg<SfxStringItem>(FN_PARAM_1); |
396 | 0 | if (pItem2) |
397 | 0 | sIgnoreText = pItem2->GetValue(); |
398 | |
|
399 | 0 | if(sIgnoreText == "Spelling") |
400 | 0 | { |
401 | 0 | ESelection aOldSel = rEditView.GetSelection(); |
402 | 0 | rEditView.SpellIgnoreWord(); |
403 | 0 | rEditView.SetSelection( aOldSel ); |
404 | 0 | } |
405 | 0 | } |
406 | 0 | break; |
407 | 0 | case SID_SPELLCHECK_APPLY_SUGGESTION: |
408 | 0 | { |
409 | 0 | if (!mpViewShell) |
410 | 0 | return; |
411 | 0 | SdrView* pSdrView = mpViewShell->GetDrawView(); |
412 | 0 | if (!pSdrView) |
413 | 0 | return; |
414 | | |
415 | 0 | EditView& rEditView = pSdrView->GetTextEditOutlinerView()->GetEditView(); |
416 | 0 | OUString sApplyText; |
417 | 0 | const SfxStringItem* pItem2 = rReq.GetArg<SfxStringItem>(FN_PARAM_1); |
418 | 0 | if (pItem2) |
419 | 0 | sApplyText = pItem2->GetValue(); |
420 | |
|
421 | 0 | static constexpr OUString sSpellingRule(u"Spelling_"_ustr); |
422 | 0 | sal_Int32 nPos = 0; |
423 | 0 | if(-1 != (nPos = sApplyText.indexOf( sSpellingRule ))) |
424 | 0 | { |
425 | 0 | sApplyText = sApplyText.replaceAt(nPos, sSpellingRule.getLength(), u""); |
426 | 0 | rEditView.InsertText( sApplyText ); |
427 | 0 | } |
428 | 0 | } |
429 | 0 | break; |
430 | | |
431 | 0 | case SID_NOTEBOOKBAR: |
432 | 0 | { |
433 | 0 | const SfxStringItem* pFile = rReq.GetArg<SfxStringItem>( SID_NOTEBOOKBAR ); |
434 | |
|
435 | 0 | if ( mpViewShell ) |
436 | 0 | { |
437 | 0 | SfxBindings& rBindings( mpViewShell->GetFrame()->GetBindings() ); |
438 | |
|
439 | 0 | if ( sfx2::SfxNotebookBar::IsActive() ) |
440 | 0 | sfx2::SfxNotebookBar::ExecMethod( rBindings, pFile ? pFile->GetValue() : u""_ustr ); |
441 | 0 | else |
442 | 0 | sfx2::SfxNotebookBar::CloseMethod( rBindings ); |
443 | 0 | } |
444 | 0 | } |
445 | 0 | break; |
446 | | |
447 | 0 | default: |
448 | 0 | break; |
449 | 0 | } |
450 | 0 | } |
451 | | |
452 | | } // end of namespace sd |
453 | | |
454 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |