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