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 "spelleng.hxx"
21 : #include <com/sun/star/i18n/TextConversionOption.hpp>
22 :
23 : #include "scitems.hxx"
24 : #include <editeng/eeitem.hxx>
25 :
26 :
27 : #include <editeng/langitem.hxx>
28 : #include <editeng/editobj.hxx>
29 : #include <editeng/editview.hxx>
30 : #include <sfx2/viewfrm.hxx>
31 : #include <vcl/msgbox.hxx>
32 : #include <vcl/svapp.hxx>
33 : #include <vcl/settings.hxx>
34 :
35 : #include "spelldialog.hxx"
36 : #include "tabvwsh.hxx"
37 : #include "docsh.hxx"
38 : #include "formulacell.hxx"
39 : #include "patattr.hxx"
40 : #include "waitoff.hxx"
41 : #include "globstr.hrc"
42 : #include "markdata.hxx"
43 :
44 : #include <boost/scoped_ptr.hpp>
45 :
46 : using namespace ::com::sun::star;
47 :
48 0 : ScConversionEngineBase::ScConversionEngineBase(
49 : SfxItemPool* pEnginePoolP, ScViewData& rViewData,
50 : ScDocument* pUndoDoc, ScDocument* pRedoDoc ) :
51 : ScEditEngineDefaulter( pEnginePoolP ),
52 : mrViewData( rViewData ),
53 0 : mrDocShell( *rViewData.GetDocShell() ),
54 0 : mrDoc( *rViewData.GetDocShell()->GetDocument() ),
55 : maSelState( rViewData ),
56 : mpUndoDoc( pUndoDoc ),
57 : mpRedoDoc( pRedoDoc ),
58 : meCurrLang( LANGUAGE_ENGLISH_US ),
59 : mbIsAnyModified( false ),
60 : mbInitialState( true ),
61 : mbWrappedInTable( false ),
62 0 : mbFinished( false )
63 : {
64 0 : maSelState.GetCellCursor().GetVars( mnStartCol, mnStartRow, mnStartTab );
65 : // start with cell A1 in cell/range/multi-selection, will seek to first selected
66 0 : if( maSelState.GetSelectionType() == SC_SELECTTYPE_SHEET )
67 : {
68 0 : mnStartCol = 0;
69 0 : mnStartRow = 0;
70 : }
71 0 : mnCurrCol = mnStartCol;
72 0 : mnCurrRow = mnStartRow;
73 0 : }
74 :
75 0 : ScConversionEngineBase::~ScConversionEngineBase()
76 : {
77 0 : }
78 :
79 0 : bool ScConversionEngineBase::FindNextConversionCell()
80 : {
81 0 : ScMarkData& rMark = mrViewData.GetMarkData();
82 0 : ScTabViewShell* pViewShell = mrViewData.GetViewShell();
83 0 : const ScPatternAttr* pPattern = NULL;
84 0 : const ScPatternAttr* pLastPattern = NULL;
85 :
86 0 : boost::scoped_ptr<SfxItemSet> pEditDefaults(new SfxItemSet(GetEmptyItemSet()));
87 :
88 0 : if( IsModified() )
89 : {
90 0 : mbIsAnyModified = true;
91 :
92 0 : OUString aNewStr = GetText();
93 :
94 0 : bool bMultiTab = (rMark.GetSelectCount() > 1);
95 0 : OUString aVisibleStr;
96 0 : if( bMultiTab )
97 0 : aVisibleStr = mrDoc.GetString(mnCurrCol, mnCurrRow, mnStartTab);
98 :
99 0 : for( SCTAB nTab = 0, nTabCount = mrDoc.GetTableCount(); nTab < nTabCount; ++nTab )
100 : {
101 : // always change the cell on the visible tab,
102 : // on the other selected tabs only if they contain the same text
103 :
104 0 : if ((nTab == mnStartTab) ||
105 0 : (bMultiTab && rMark.GetTableSelect(nTab) && mrDoc.GetString(mnCurrCol, mnCurrRow, nTab) == aVisibleStr))
106 : {
107 0 : ScAddress aPos( mnCurrCol, mnCurrRow, nTab );
108 0 : CellType eCellType = mrDoc.GetCellType( aPos );
109 0 : bool bEmptyCell = eCellType == CELLTYPE_NONE;
110 :
111 0 : if (mpUndoDoc && !bEmptyCell)
112 0 : mrDoc.CopyCellToDocument(aPos, aPos, *mpUndoDoc);
113 :
114 0 : if (eCellType == CELLTYPE_EDIT)
115 : {
116 0 : boost::scoped_ptr<EditTextObject> pEditObj(CreateTextObject());
117 0 : mrDoc.SetEditText(aPos, *pEditObj, GetEditTextObjectPool());
118 : }
119 : else
120 0 : mrDoc.SetString(aPos, aNewStr);
121 :
122 0 : if (mpRedoDoc && !bEmptyCell)
123 0 : mrDoc.CopyCellToDocument(aPos, aPos, *mpRedoDoc);
124 :
125 0 : mrDocShell.PostPaintCell(aPos);
126 : }
127 0 : }
128 : }
129 :
130 0 : SCCOL nNewCol = mnCurrCol;
131 0 : SCROW nNewRow = mnCurrRow;
132 :
133 0 : if( mbInitialState )
134 : {
135 : /* On very first call, decrement row to let GetNextSpellingCell() find
136 : the first cell of current range. */
137 0 : mbInitialState = false;
138 0 : --nNewRow;
139 : }
140 :
141 0 : bool bSheetSel = maSelState.GetSelectionType() == SC_SELECTTYPE_SHEET;
142 0 : bool bLoop = true;
143 0 : bool bFound = false;
144 0 : while( bLoop && !bFound )
145 : {
146 0 : bLoop = mrDoc.GetNextSpellingCell( nNewCol, nNewRow, mnStartTab, bSheetSel, rMark );
147 0 : if( bLoop )
148 : {
149 0 : FillFromCell( mnCurrCol, mnCurrRow, mnStartTab );
150 :
151 0 : if( mbWrappedInTable && ((nNewCol > mnStartCol) || ((nNewCol == mnStartCol) && (nNewRow >= mnStartRow))) )
152 : {
153 0 : ShowFinishDialog();
154 0 : bLoop = false;
155 0 : mbFinished = true;
156 : }
157 0 : else if( nNewCol > MAXCOL )
158 : {
159 : // no more cells in the sheet - try to restart at top of sheet
160 :
161 0 : if( bSheetSel || ((mnStartCol == 0) && (mnStartRow == 0)) )
162 : {
163 : // conversion started at cell A1 or in selection, do not query to restart at top
164 0 : ShowFinishDialog();
165 0 : bLoop = false;
166 0 : mbFinished = true;
167 : }
168 0 : else if( ShowTableWrapDialog() )
169 : {
170 : // conversion started anywhere but in cell A1, user wants to restart
171 0 : nNewRow = MAXROW + 2;
172 0 : mbWrappedInTable = true;
173 : }
174 : else
175 : {
176 0 : bLoop = false;
177 0 : mbFinished = true;
178 : }
179 : }
180 : else
181 : {
182 0 : pPattern = mrDoc.GetPattern( nNewCol, nNewRow, mnStartTab );
183 0 : if( pPattern && (pPattern != pLastPattern) )
184 : {
185 0 : pPattern->FillEditItemSet( pEditDefaults.get() );
186 0 : SetDefaults( *pEditDefaults );
187 0 : pLastPattern = pPattern;
188 : }
189 :
190 : // language changed?
191 0 : const SfxPoolItem* pItem = mrDoc.GetAttr( nNewCol, nNewRow, mnStartTab, ATTR_FONT_LANGUAGE );
192 0 : if( const SvxLanguageItem* pLangItem = PTR_CAST( SvxLanguageItem, pItem ) )
193 : {
194 0 : LanguageType eLang = static_cast< LanguageType >( pLangItem->GetValue() );
195 0 : if( eLang == LANGUAGE_SYSTEM )
196 0 : eLang = Application::GetSettings().GetLanguageTag().getLanguageType(); // never use SYSTEM for spelling
197 0 : if( eLang != meCurrLang )
198 : {
199 0 : meCurrLang = eLang;
200 0 : SetDefaultLanguage( eLang );
201 : }
202 : }
203 :
204 0 : FillFromCell( nNewCol, nNewRow, mnStartTab );
205 :
206 0 : bFound = bLoop && NeedsConversion();
207 : }
208 : }
209 : }
210 :
211 0 : if( bFound )
212 : {
213 0 : pViewShell->AlignToCursor( nNewCol, nNewRow, SC_FOLLOW_JUMP );
214 0 : pViewShell->SetCursor( nNewCol, nNewRow, true );
215 0 : mrViewData.GetView()->MakeEditView( this, nNewCol, nNewRow );
216 0 : EditView* pEditView = mrViewData.GetSpellingView();
217 : // maSelState.GetEditSelection() returns (0,0) if not in edit mode -> ok
218 0 : pEditView->SetSelection( maSelState.GetEditSelection() );
219 :
220 0 : ClearModifyFlag();
221 0 : mnCurrCol = nNewCol;
222 0 : mnCurrRow = nNewRow;
223 : }
224 :
225 0 : return bFound;
226 : }
227 :
228 0 : void ScConversionEngineBase::RestoreCursorPos()
229 : {
230 0 : const ScAddress& rPos = maSelState.GetCellCursor();
231 0 : mrViewData.GetViewShell()->SetCursor( rPos.Col(), rPos.Row() );
232 0 : }
233 :
234 0 : bool ScConversionEngineBase::ShowTableWrapDialog()
235 : {
236 : // default: no dialog, always restart at top
237 0 : return true;
238 : }
239 :
240 0 : void ScConversionEngineBase::ShowFinishDialog()
241 : {
242 : // default: no dialog
243 0 : }
244 :
245 : // private --------------------------------------------------------------------
246 :
247 0 : void ScConversionEngineBase::FillFromCell( SCCOL nCol, SCROW nRow, SCTAB nTab )
248 : {
249 0 : ScAddress aPos(nCol, nRow, nTab);
250 :
251 0 : switch (mrDoc.GetCellType(aPos))
252 : {
253 : case CELLTYPE_STRING:
254 : {
255 0 : OUString aText = mrDoc.GetString(aPos);
256 0 : SetText( aText );
257 : }
258 0 : break;
259 : case CELLTYPE_EDIT:
260 : {
261 0 : const EditTextObject* pNewEditObj = mrDoc.GetEditText(aPos);
262 0 : if (pNewEditObj)
263 0 : SetText(*pNewEditObj);
264 : }
265 0 : break;
266 : default:
267 0 : SetText(EMPTY_OUSTRING);
268 : }
269 0 : }
270 :
271 0 : ScSpellingEngine::ScSpellingEngine(
272 : SfxItemPool* pEnginePoolP, ScViewData& rViewData,
273 : ScDocument* pUndoDoc, ScDocument* pRedoDoc,
274 : XSpellCheckerRef xSpeller ) :
275 0 : ScConversionEngineBase( pEnginePoolP, rViewData, pUndoDoc, pRedoDoc )
276 : {
277 0 : SetSpeller( xSpeller );
278 0 : }
279 :
280 0 : void ScSpellingEngine::ConvertAll( EditView& rEditView )
281 : {
282 0 : EESpellState eState = EE_SPELL_OK;
283 0 : if( FindNextConversionCell() )
284 0 : eState = rEditView.StartSpeller( true );
285 :
286 : OSL_ENSURE( eState != EE_SPELL_NOSPELLER, "ScSpellingEngine::Convert - no spell checker" );
287 0 : if( eState == EE_SPELL_NOLANGUAGE )
288 : {
289 0 : Window* pParent = GetDialogParent();
290 0 : ScWaitCursorOff aWaitOff( pParent );
291 0 : InfoBox( pParent, ScGlobal::GetRscString( STR_NOLANGERR ) ).Execute();
292 : }
293 0 : }
294 :
295 0 : bool ScSpellingEngine::SpellNextDocument()
296 : {
297 0 : return FindNextConversionCell();
298 : }
299 :
300 0 : bool ScSpellingEngine::NeedsConversion()
301 : {
302 0 : return HasSpellErrors() != EE_SPELL_OK;
303 : }
304 :
305 0 : bool ScSpellingEngine::ShowTableWrapDialog()
306 : {
307 0 : Window* pParent = GetDialogParent();
308 0 : ScWaitCursorOff aWaitOff( pParent );
309 : MessBox aMsgBox( pParent, WinBits( WB_YES_NO | WB_DEF_YES ),
310 0 : ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ),
311 0 : ScGlobal::GetRscString( STR_SPELLING_BEGIN_TAB) );
312 0 : return aMsgBox.Execute() == RET_YES;
313 : }
314 :
315 0 : void ScSpellingEngine::ShowFinishDialog()
316 : {
317 0 : Window* pParent = GetDialogParent();
318 0 : ScWaitCursorOff aWaitOff( pParent );
319 0 : InfoBox( pParent, ScGlobal::GetRscString( STR_SPELLING_STOP_OK ) ).Execute();
320 0 : }
321 :
322 0 : Window* ScSpellingEngine::GetDialogParent()
323 : {
324 0 : sal_uInt16 nWinId = ScSpellDialogChildWindow::GetChildWindowId();
325 0 : SfxViewFrame* pViewFrm = mrViewData.GetViewShell()->GetViewFrame();
326 0 : if( pViewFrm->HasChildWindow( nWinId ) )
327 0 : if( SfxChildWindow* pChild = pViewFrm->GetChildWindow( nWinId ) )
328 0 : if( Window* pWin = pChild->GetWindow() )
329 0 : if( pWin->IsVisible() )
330 0 : return pWin;
331 :
332 : // fall back to standard dialog parent
333 0 : return mrDocShell.GetActiveDialogParent();
334 : }
335 :
336 0 : ScConversionParam::ScConversionParam( ScConversionType eConvType ) :
337 : meConvType( eConvType ),
338 : meSourceLang( LANGUAGE_NONE ),
339 : meTargetLang( LANGUAGE_NONE ),
340 : mnOptions( 0 ),
341 : mbUseTargetFont( false ),
342 0 : mbIsInteractive( false )
343 : {
344 0 : }
345 :
346 0 : ScConversionParam::ScConversionParam( ScConversionType eConvType,
347 : LanguageType eLang, sal_Int32 nOptions, bool bIsInteractive ) :
348 : meConvType( eConvType ),
349 : meSourceLang( eLang ),
350 : meTargetLang( eLang ),
351 : mnOptions( nOptions ),
352 : mbUseTargetFont( false ),
353 0 : mbIsInteractive( bIsInteractive )
354 : {
355 0 : if (LANGUAGE_KOREAN == eLang)
356 0 : mnOptions = i18n::TextConversionOption::CHARACTER_BY_CHARACTER;
357 0 : }
358 :
359 0 : ScConversionParam::ScConversionParam( ScConversionType eConvType,
360 : LanguageType eSourceLang, LanguageType eTargetLang, const Font& rTargetFont,
361 : sal_Int32 nOptions, bool bIsInteractive ) :
362 : meConvType( eConvType ),
363 : meSourceLang( eSourceLang ),
364 : meTargetLang( eTargetLang ),
365 : maTargetFont( rTargetFont ),
366 : mnOptions( nOptions ),
367 : mbUseTargetFont( true ),
368 0 : mbIsInteractive( bIsInteractive )
369 : {
370 0 : if (LANGUAGE_KOREAN == meSourceLang && LANGUAGE_KOREAN == meTargetLang)
371 0 : mnOptions = i18n::TextConversionOption::CHARACTER_BY_CHARACTER;
372 0 : }
373 :
374 0 : ScTextConversionEngine::ScTextConversionEngine(
375 : SfxItemPool* pEnginePoolP, ScViewData& rViewData,
376 : const ScConversionParam& rConvParam,
377 : ScDocument* pUndoDoc, ScDocument* pRedoDoc ) :
378 : ScConversionEngineBase( pEnginePoolP, rViewData, pUndoDoc, pRedoDoc ),
379 0 : maConvParam( rConvParam )
380 : {
381 0 : }
382 :
383 0 : void ScTextConversionEngine::ConvertAll( EditView& rEditView )
384 : {
385 0 : if( FindNextConversionCell() )
386 : {
387 : rEditView.StartTextConversion(
388 0 : maConvParam.GetSourceLang(), maConvParam.GetTargetLang(), maConvParam.GetTargetFont(),
389 0 : maConvParam.GetOptions(), maConvParam.IsInteractive(), true );
390 : // #i34769# restore initial cursor position
391 0 : RestoreCursorPos();
392 : }
393 0 : }
394 :
395 0 : bool ScTextConversionEngine::ConvertNextDocument()
396 : {
397 0 : return FindNextConversionCell();
398 : }
399 :
400 0 : bool ScTextConversionEngine::NeedsConversion()
401 : {
402 0 : return HasConvertibleTextPortion( maConvParam.GetSourceLang() );
403 0 : }
404 :
405 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|