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 "scitems.hxx"
21 : #include <editeng/eeitem.hxx>
22 :
23 : #include <tools/string.hxx>
24 : #include <tools/urlobj.hxx>
25 : #include <editeng/editobj.hxx>
26 : #include <editeng/editstat.hxx>
27 : #include <editeng/frmdiritem.hxx>
28 : #include <editeng/langitem.hxx>
29 : #include <sfx2/linkmgr.hxx>
30 : #include <editeng/scripttypeitem.hxx>
31 : #include <editeng/unolingu.hxx>
32 : #include <sfx2/bindings.hxx>
33 : #include <sfx2/objsh.hxx>
34 : #include <sfx2/printer.hxx>
35 : #include <sfx2/viewfrm.hxx>
36 : #include <sfx2/viewsh.hxx>
37 : #include <svl/flagitem.hxx>
38 : #include <svl/intitem.hxx>
39 : #include <svl/zforlist.hxx>
40 : #include <svl/zformat.hxx>
41 : #include <unotools/misccfg.hxx>
42 : #include <sfx2/app.hxx>
43 : #include <unotools/transliterationwrapper.hxx>
44 : #include <unotools/securityoptions.hxx>
45 :
46 : #include <vcl/virdev.hxx>
47 : #include <vcl/msgbox.hxx>
48 :
49 : #include <com/sun/star/i18n/TransliterationModulesExtra.hpp>
50 :
51 : #include "inputopt.hxx"
52 : #include "global.hxx"
53 : #include "table.hxx"
54 : #include "column.hxx"
55 : #include "poolhelp.hxx"
56 : #include "docpool.hxx"
57 : #include "stlpool.hxx"
58 : #include "stlsheet.hxx"
59 : #include "docoptio.hxx"
60 : #include "viewopti.hxx"
61 : #include "scextopt.hxx"
62 : #include "rechead.hxx"
63 : #include "ddelink.hxx"
64 : #include "scmatrix.hxx"
65 : #include "arealink.hxx"
66 : #include "dociter.hxx"
67 : #include "patattr.hxx"
68 : #include "hints.hxx"
69 : #include "editutil.hxx"
70 : #include "progress.hxx"
71 : #include "document.hxx"
72 : #include "chartlis.hxx"
73 : #include "chartlock.hxx"
74 : #include "refupdat.hxx"
75 : #include "validat.hxx" // fuer HasMacroCalls
76 : #include "markdata.hxx"
77 : #include "scmod.hxx"
78 : #include "printopt.hxx"
79 : #include "externalrefmgr.hxx"
80 : #include "globstr.hrc"
81 : #include "sc.hrc"
82 : #include "charthelper.hxx"
83 : #include "macromgr.hxx"
84 : #include "dpobject.hxx"
85 : #include "docuno.hxx"
86 : #include "scresid.hxx"
87 : #include "columniterator.hxx"
88 : #include "globalnames.hxx"
89 : #include "stringutil.hxx"
90 :
91 : #include <memory>
92 : #include <boost/scoped_ptr.hpp>
93 :
94 : // states for online spelling in the visible range (0 is set initially)
95 : #define VSPL_START 0
96 : #define VSPL_DONE 1
97 :
98 : using namespace com::sun::star;
99 :
100 : // STATIC DATA -----------------------------------------------------------
101 :
102 : namespace {
103 :
104 314 : inline sal_uInt16 getScaleValue(SfxStyleSheetBase& rStyle, sal_uInt16 nWhich)
105 : {
106 314 : return static_cast<const SfxUInt16Item&>(rStyle.GetItemSet().Get(nWhich)).GetValue();
107 : }
108 :
109 : }
110 :
111 1455 : void ScDocument::ImplCreateOptions()
112 : {
113 1455 : pDocOptions = new ScDocOptions();
114 1455 : pViewOptions = new ScViewOptions();
115 1455 : }
116 :
117 : //------------------------------------------------------------------------
118 :
119 1340 : void ScDocument::ImplDeleteOptions()
120 : {
121 1340 : delete pDocOptions;
122 1340 : delete pViewOptions;
123 1340 : delete pExtDocOptions;
124 1340 : }
125 :
126 : //------------------------------------------------------------------------
127 :
128 3562 : SfxPrinter* ScDocument::GetPrinter(bool bCreateIfNotExist)
129 : {
130 3562 : if ( !pPrinter && bCreateIfNotExist )
131 : {
132 : SfxItemSet* pSet =
133 112 : new SfxItemSet( *xPoolHelper->GetDocPool(),
134 : SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN,
135 : SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC,
136 : SID_PRINT_SELECTEDSHEET, SID_PRINT_SELECTEDSHEET,
137 : SID_SCPRINTOPTIONS, SID_SCPRINTOPTIONS,
138 112 : NULL );
139 :
140 112 : ::utl::MiscCfg aMisc;
141 112 : sal_uInt16 nFlags = 0;
142 112 : if ( aMisc.IsPaperOrientationWarning() )
143 0 : nFlags |= SFX_PRINTER_CHG_ORIENTATION;
144 112 : if ( aMisc.IsPaperSizeWarning() )
145 0 : nFlags |= SFX_PRINTER_CHG_SIZE;
146 112 : pSet->Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC, nFlags ) );
147 112 : pSet->Put( SfxBoolItem( SID_PRINTER_NOTFOUND_WARN, aMisc.IsNotFoundWarning() ) );
148 :
149 112 : pPrinter = new SfxPrinter( pSet );
150 112 : pPrinter->SetMapMode( MAP_100TH_MM );
151 112 : UpdateDrawPrinter();
152 112 : pPrinter->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
153 : }
154 :
155 3562 : return pPrinter;
156 : }
157 :
158 : //------------------------------------------------------------------------
159 :
160 38 : void ScDocument::SetPrinter( SfxPrinter* pNewPrinter )
161 : {
162 38 : if ( pNewPrinter == pPrinter )
163 : {
164 : // #i6706# SetPrinter is called with the same printer again if
165 : // the JobSetup has changed. In that case just call UpdateDrawPrinter
166 : // (SetRefDevice for drawing layer) because of changed text sizes.
167 0 : UpdateDrawPrinter();
168 : }
169 : else
170 : {
171 38 : SfxPrinter* pOld = pPrinter;
172 38 : pPrinter = pNewPrinter;
173 38 : UpdateDrawPrinter();
174 38 : pPrinter->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
175 38 : delete pOld;
176 : }
177 38 : InvalidateTextWidth(NULL, NULL, false); // in both cases
178 38 : }
179 :
180 : //------------------------------------------------------------------------
181 :
182 76 : void ScDocument::SetPrintOptions()
183 : {
184 76 : if ( !pPrinter ) GetPrinter(); // setzt pPrinter
185 : OSL_ENSURE( pPrinter, "Error in printer creation :-/" );
186 :
187 76 : if ( pPrinter )
188 : {
189 76 : ::utl::MiscCfg aMisc;
190 152 : SfxItemSet aOptSet( pPrinter->GetOptions() );
191 :
192 76 : sal_uInt16 nFlags = 0;
193 76 : if ( aMisc.IsPaperOrientationWarning() )
194 0 : nFlags |= SFX_PRINTER_CHG_ORIENTATION;
195 76 : if ( aMisc.IsPaperSizeWarning() )
196 0 : nFlags |= SFX_PRINTER_CHG_SIZE;
197 76 : aOptSet.Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC, nFlags ) );
198 76 : aOptSet.Put( SfxBoolItem( SID_PRINTER_NOTFOUND_WARN, aMisc.IsNotFoundWarning() ) );
199 :
200 152 : pPrinter->SetOptions( aOptSet );
201 : }
202 76 : }
203 :
204 : //------------------------------------------------------------------------
205 :
206 2615 : VirtualDevice* ScDocument::GetVirtualDevice_100th_mm()
207 : {
208 2615 : if (!pVirtualDevice_100th_mm)
209 : {
210 : #ifdef IOS
211 : pVirtualDevice_100th_mm = new VirtualDevice( 8 );
212 : #else
213 290 : pVirtualDevice_100th_mm = new VirtualDevice( 1 );
214 : #endif
215 290 : pVirtualDevice_100th_mm->SetReferenceDevice(VirtualDevice::REFDEV_MODE_MSO1);
216 290 : MapMode aMapMode( pVirtualDevice_100th_mm->GetMapMode() );
217 290 : aMapMode.SetMapUnit( MAP_100TH_MM );
218 290 : pVirtualDevice_100th_mm->SetMapMode( aMapMode );
219 : }
220 2615 : return pVirtualDevice_100th_mm;
221 : }
222 :
223 2693 : OutputDevice* ScDocument::GetRefDevice()
224 : {
225 : // Create printer like ref device, see Writer...
226 2693 : OutputDevice* pRefDevice = NULL;
227 2693 : if ( SC_MOD()->GetInputOptions().GetTextWysiwyg() )
228 78 : pRefDevice = GetPrinter();
229 : else
230 2615 : pRefDevice = GetVirtualDevice_100th_mm();
231 2693 : return pRefDevice;
232 : }
233 :
234 : //------------------------------------------------------------------------
235 :
236 0 : void ScDocument::ModifyStyleSheet( SfxStyleSheetBase& rStyleSheet,
237 : const SfxItemSet& rChanges )
238 : {
239 0 : SfxItemSet& rSet = rStyleSheet.GetItemSet();
240 :
241 0 : switch ( rStyleSheet.GetFamily() )
242 : {
243 : case SFX_STYLE_FAMILY_PAGE:
244 : {
245 0 : const sal_uInt16 nOldScale = getScaleValue(rStyleSheet, ATTR_PAGE_SCALE);
246 0 : const sal_uInt16 nOldScaleToPages = getScaleValue(rStyleSheet, ATTR_PAGE_SCALETOPAGES);
247 0 : rSet.Put( rChanges );
248 0 : const sal_uInt16 nNewScale = getScaleValue(rStyleSheet, ATTR_PAGE_SCALE);
249 0 : const sal_uInt16 nNewScaleToPages = getScaleValue(rStyleSheet, ATTR_PAGE_SCALETOPAGES);
250 :
251 0 : if ( (nOldScale != nNewScale) || (nOldScaleToPages != nNewScaleToPages) )
252 0 : InvalidateTextWidth( rStyleSheet.GetName() );
253 :
254 0 : if( SvtLanguageOptions().IsCTLFontEnabled() )
255 : {
256 0 : const SfxPoolItem *pItem = NULL;
257 0 : if( rChanges.GetItemState(ATTR_WRITINGDIR, true, &pItem ) == SFX_ITEM_SET )
258 0 : ScChartHelper::DoUpdateAllCharts( this );
259 : }
260 : }
261 0 : break;
262 :
263 : case SFX_STYLE_FAMILY_PARA:
264 : {
265 : bool bNumFormatChanged;
266 0 : if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
267 0 : rSet, rChanges ) )
268 0 : InvalidateTextWidth( NULL, NULL, bNumFormatChanged );
269 :
270 0 : for (SCTAB nTab=0; nTab<=MAXTAB; ++nTab)
271 0 : if (maTabs[nTab] && maTabs[nTab]->IsStreamValid())
272 0 : maTabs[nTab]->SetStreamValid( false );
273 :
274 : sal_uLong nOldFormat =
275 : ((const SfxUInt32Item*)&rSet.Get(
276 0 : ATTR_VALUE_FORMAT ))->GetValue();
277 : sal_uLong nNewFormat =
278 : ((const SfxUInt32Item*)&rChanges.Get(
279 0 : ATTR_VALUE_FORMAT ))->GetValue();
280 : LanguageType eNewLang, eOldLang;
281 0 : eNewLang = eOldLang = LANGUAGE_DONTKNOW;
282 0 : if ( nNewFormat != nOldFormat )
283 : {
284 0 : SvNumberFormatter* pFormatter = GetFormatTable();
285 0 : eOldLang = pFormatter->GetEntry( nOldFormat )->GetLanguage();
286 0 : eNewLang = pFormatter->GetEntry( nNewFormat )->GetLanguage();
287 : }
288 :
289 : // Bedeutung der Items in rChanges:
290 : // Item gesetzt - Aenderung uebernehmen
291 : // Dontcare - Default setzen
292 : // Default - keine Aenderung
293 : // ("keine Aenderung" geht nicht mit PutExtended, darum Schleife)
294 0 : for (sal_uInt16 nWhich = ATTR_PATTERN_START; nWhich <= ATTR_PATTERN_END; nWhich++)
295 : {
296 : const SfxPoolItem* pItem;
297 0 : SfxItemState eState = rChanges.GetItemState( nWhich, false, &pItem );
298 0 : if ( eState == SFX_ITEM_SET )
299 0 : rSet.Put( *pItem );
300 0 : else if ( eState == SFX_ITEM_DONTCARE )
301 0 : rSet.ClearItem( nWhich );
302 : // bei Default nichts
303 : }
304 :
305 0 : if ( eNewLang != eOldLang )
306 : rSet.Put(
307 0 : SvxLanguageItem( eNewLang, ATTR_LANGUAGE_FORMAT ) );
308 : }
309 0 : break;
310 : default:
311 : {
312 : // added to avoid warnings
313 : }
314 : }
315 0 : }
316 :
317 : //------------------------------------------------------------------------
318 :
319 0 : void ScDocument::CopyStdStylesFrom( ScDocument* pSrcDoc )
320 : {
321 : // number format exchange list has to be handled here, too
322 0 : NumFmtMergeHandler aNumFmtMergeHdl(this, pSrcDoc);
323 0 : xPoolHelper->GetStylePool()->CopyStdStylesFrom( pSrcDoc->xPoolHelper->GetStylePool() );
324 0 : }
325 :
326 : //------------------------------------------------------------------------
327 :
328 0 : void ScDocument::InvalidateTextWidth( const OUString& rStyleName )
329 : {
330 0 : const SCTAB nCount = GetTableCount();
331 0 : for ( SCTAB i=0; i<nCount && maTabs[i]; i++ )
332 0 : if ( maTabs[i]->GetPageStyle() == rStyleName )
333 0 : InvalidateTextWidth( i );
334 0 : }
335 :
336 : //------------------------------------------------------------------------
337 :
338 0 : void ScDocument::InvalidateTextWidth( SCTAB nTab )
339 : {
340 0 : ScAddress aAdrFrom( 0, 0, nTab );
341 0 : ScAddress aAdrTo ( MAXCOL, MAXROW, nTab );
342 0 : InvalidateTextWidth( &aAdrFrom, &aAdrTo, false );
343 0 : }
344 :
345 : //------------------------------------------------------------------------
346 :
347 0 : bool ScDocument::IsPageStyleInUse( const OUString& rStrPageStyle, SCTAB* pInTab )
348 : {
349 0 : bool bInUse = false;
350 0 : const SCTAB nCount = GetTableCount();
351 : SCTAB i;
352 :
353 0 : for ( i = 0; !bInUse && i < nCount && maTabs[i]; i++ )
354 0 : bInUse = ( maTabs[i]->GetPageStyle() == rStrPageStyle );
355 :
356 0 : if ( pInTab )
357 0 : *pInTab = i-1;
358 :
359 0 : return bInUse;
360 : }
361 :
362 : //------------------------------------------------------------------------
363 :
364 0 : bool ScDocument::RemovePageStyleInUse( const OUString& rStyle )
365 : {
366 0 : bool bWasInUse = false;
367 0 : const SCTAB nCount = GetTableCount();
368 :
369 0 : for ( SCTAB i=0; i<nCount && maTabs[i]; i++ )
370 0 : if ( maTabs[i]->GetPageStyle() == rStyle )
371 : {
372 0 : bWasInUse = true;
373 0 : maTabs[i]->SetPageStyle( ScGlobal::GetRscString(STR_STYLENAME_STANDARD) );
374 : }
375 :
376 0 : return bWasInUse;
377 : }
378 :
379 0 : bool ScDocument::RenamePageStyleInUse( const OUString& rOld, const OUString& rNew )
380 : {
381 0 : bool bWasInUse = false;
382 0 : const SCTAB nCount = GetTableCount();
383 :
384 0 : for ( SCTAB i=0; i<nCount && maTabs[i]; i++ )
385 0 : if ( maTabs[i]->GetPageStyle() == rOld )
386 : {
387 0 : bWasInUse = true;
388 0 : maTabs[i]->SetPageStyle( rNew );
389 : }
390 :
391 0 : return bWasInUse;
392 : }
393 :
394 : //------------------------------------------------------------------------
395 :
396 13940 : sal_uInt8 ScDocument::GetEditTextDirection(SCTAB nTab) const
397 : {
398 13940 : EEHorizontalTextDirection eRet = EE_HTEXTDIR_DEFAULT;
399 :
400 13940 : OUString aStyleName = GetPageStyle( nTab );
401 13940 : SfxStyleSheetBase* pStyle = xPoolHelper->GetStylePool()->Find( aStyleName, SFX_STYLE_FAMILY_PAGE );
402 13940 : if ( pStyle )
403 : {
404 13940 : SfxItemSet& rStyleSet = pStyle->GetItemSet();
405 : SvxFrameDirection eDirection = (SvxFrameDirection)
406 13940 : ((const SvxFrameDirectionItem&)rStyleSet.Get( ATTR_WRITINGDIR )).GetValue();
407 :
408 13940 : if ( eDirection == FRMDIR_HORI_LEFT_TOP )
409 13878 : eRet = EE_HTEXTDIR_L2R;
410 62 : else if ( eDirection == FRMDIR_HORI_RIGHT_TOP )
411 0 : eRet = EE_HTEXTDIR_R2L;
412 : // else (invalid for EditEngine): keep "default"
413 : }
414 :
415 13940 : return sal::static_int_cast<sal_uInt8>(eRet);
416 : }
417 :
418 1 : ScMacroManager* ScDocument::GetMacroManager()
419 : {
420 1 : if (!mpMacroMgr.get())
421 1 : mpMacroMgr.reset(new ScMacroManager(this));
422 1 : return mpMacroMgr.get();
423 : }
424 :
425 0 : bool ScDocument::IsEmptyData( SCTAB nTab, SCCOL nCol ) const
426 : {
427 0 : const ScTable* pTab = FetchTable(nTab);
428 0 : if (!pTab)
429 0 : return true;
430 :
431 0 : return pTab->IsEmptyData(nCol);
432 : }
433 :
434 20 : void ScDocument::FillMatrix(
435 : ScMatrix& rMat, SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) const
436 : {
437 20 : const ScTable* pTab = FetchTable(nTab);
438 20 : if (!pTab)
439 0 : return;
440 :
441 20 : if (nCol1 > nCol2 || nRow1 > nRow2)
442 0 : return;
443 :
444 : SCSIZE nC, nR;
445 20 : rMat.GetDimensions(nC, nR);
446 20 : if (static_cast<SCROW>(nR) != nRow2 - nRow1 + 1 || static_cast<SCCOL>(nC) != nCol2 - nCol1 + 1)
447 0 : return;
448 :
449 20 : pTab->FillMatrix(rMat, nCol1, nRow1, nCol2, nRow2);
450 : }
451 :
452 0 : void ScDocument::SetFormulaResults( const ScAddress& rTopPos, const double* pResults, size_t nLen )
453 : {
454 0 : ScTable* pTab = FetchTable(rTopPos.Tab());
455 0 : if (!pTab)
456 0 : return;
457 :
458 0 : pTab->SetFormulaResults(rTopPos.Col(), rTopPos.Row(), pResults, nLen);
459 : }
460 :
461 :
462 : //------------------------------------------------------------------------
463 :
464 5665 : void ScDocument::InvalidateTextWidth( const ScAddress* pAdrFrom, const ScAddress* pAdrTo,
465 : bool bNumFormatChanged )
466 : {
467 5665 : bool bBroadcast = (bNumFormatChanged && GetDocOptions().IsCalcAsShown() && !IsImportingXML() && !IsClipboard());
468 5665 : if ( pAdrFrom && !pAdrTo )
469 : {
470 0 : const SCTAB nTab = pAdrFrom->Tab();
471 :
472 0 : if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
473 0 : maTabs[nTab]->InvalidateTextWidth( pAdrFrom, NULL, bNumFormatChanged, bBroadcast );
474 : }
475 : else
476 : {
477 5665 : const SCTAB nTabStart = pAdrFrom ? pAdrFrom->Tab() : 0;
478 5665 : const SCTAB nTabEnd = pAdrTo ? pAdrTo->Tab() : MAXTAB;
479 :
480 11330 : for ( SCTAB nTab=nTabStart; nTab<=nTabEnd && nTab < static_cast<SCTAB>(maTabs.size()); nTab++ )
481 5665 : if ( maTabs[nTab] )
482 5665 : maTabs[nTab]->InvalidateTextWidth( pAdrFrom, pAdrTo, bNumFormatChanged, bBroadcast );
483 : }
484 5665 : }
485 :
486 : //------------------------------------------------------------------------
487 :
488 : #define CALCMAX 1000 // Berechnungen
489 : #define ABORT_EVENTS (VCL_INPUT_ANY & ~VCL_INPUT_TIMER & ~VCL_INPUT_OTHER)
490 :
491 : namespace {
492 :
493 : class IdleCalcTextWidthScope
494 : {
495 : ScDocument& mrDoc;
496 : ScAddress& mrCalcPos;
497 : MapMode maOldMapMode;
498 : sal_uLong mnStartTime;
499 : ScStyleSheetPool* mpStylePool;
500 : sal_uInt16 mnOldSearchMask;
501 : SfxStyleFamily meOldFamily;
502 : bool mbNeedMore;
503 : bool mbProgress;
504 :
505 : public:
506 314 : IdleCalcTextWidthScope(ScDocument& rDoc, ScAddress& rCalcPos) :
507 : mrDoc(rDoc),
508 : mrCalcPos(rCalcPos),
509 314 : mnStartTime(Time::GetSystemTicks()),
510 314 : mpStylePool(rDoc.GetStyleSheetPool()),
511 314 : mnOldSearchMask(mpStylePool->GetSearchMask()),
512 314 : meOldFamily(mpStylePool->GetSearchFamily()),
513 : mbNeedMore(false),
514 1570 : mbProgress(false)
515 : {
516 : // The old search mask / family flags must be restored so that e.g.
517 : // the styles dialog shows correct listing when it's opened in-between
518 : // the calls.
519 :
520 314 : mrDoc.EnableIdle(false);
521 314 : mpStylePool->SetSearchMask(SFX_STYLE_FAMILY_PAGE, SFXSTYLEBIT_ALL);
522 314 : }
523 :
524 314 : ~IdleCalcTextWidthScope()
525 314 : {
526 314 : SfxPrinter* pDev = mrDoc.GetPrinter();
527 314 : if (pDev)
528 314 : pDev->SetMapMode(maOldMapMode);
529 :
530 314 : if (mbProgress)
531 0 : ScProgress::DeleteInterpretProgress();
532 :
533 314 : mpStylePool->SetSearchMask(meOldFamily, mnOldSearchMask);
534 314 : mrDoc.EnableIdle(true);
535 314 : }
536 :
537 998 : SCTAB Tab() const { return mrCalcPos.Tab(); }
538 314 : SCCOL Col() const { return mrCalcPos.Col(); }
539 314 : SCROW Row() const { return mrCalcPos.Row(); }
540 :
541 : const ScAddress& Pos() const { return mrCalcPos; }
542 :
543 258 : void setTab(SCTAB nTab) { mrCalcPos.SetTab(nTab); }
544 0 : void setCol(SCCOL nCol) { mrCalcPos.SetCol(nCol); }
545 0 : void setRow(SCROW nRow) { mrCalcPos.SetRow(nRow); }
546 :
547 314 : void incTab(SCTAB nInc=1) { mrCalcPos.IncTab(nInc); }
548 0 : void incCol(SCCOL nInc=1) { mrCalcPos.IncCol(nInc); }
549 : void incRow(SCROW nInc=1) { mrCalcPos.IncRow(nInc); }
550 :
551 0 : void setOldMapMode(const MapMode& rOldMapMode) { maOldMapMode = rOldMapMode; }
552 :
553 0 : void setNeedMore(bool b) { mbNeedMore = b; }
554 0 : bool getNeedMore() const { return mbNeedMore; }
555 :
556 0 : sal_uLong getStartTime() const { return mnStartTime; }
557 :
558 0 : void createProgressBar()
559 : {
560 0 : ScProgress::CreateInterpretProgress(&mrDoc, false);
561 0 : mbProgress = true;
562 0 : }
563 :
564 0 : bool hasProgressBar() const { return mbProgress; }
565 :
566 314 : ScStyleSheetPool* getStylePool() { return mpStylePool; }
567 : };
568 :
569 : }
570 :
571 1590 : bool ScDocument::IdleCalcTextWidth() // true = demnaechst wieder versuchen
572 : {
573 : // #i75610# if a printer hasn't been set or created yet, don't create one for this
574 1590 : if (!mbIdleEnabled || IsInLinkUpdate() || GetPrinter(false) == NULL)
575 1276 : return false;
576 :
577 314 : IdleCalcTextWidthScope aScope(*this, aCurTextWidthCalcPos);
578 :
579 314 : if (!ValidRow(aScope.Row()))
580 : {
581 0 : aScope.setRow(0);
582 0 : aScope.incCol(-1);
583 : }
584 :
585 314 : if (aScope.Col() < 0)
586 : {
587 0 : aScope.setCol(MAXCOL);
588 0 : aScope.incTab();
589 : }
590 :
591 314 : if (!ValidTab(aScope.Tab()) || aScope.Tab() >= static_cast<SCTAB>(maTabs.size()) || !maTabs[aScope.Tab()])
592 258 : aScope.setTab(0);
593 :
594 314 : ScTable* pTab = maTabs[aScope.Tab()];
595 314 : ScStyleSheet* pStyle = (ScStyleSheet*)aScope.getStylePool()->Find(pTab->aPageStyle, SFX_STYLE_FAMILY_PAGE);
596 : OSL_ENSURE( pStyle, "Missing StyleSheet :-/" );
597 :
598 314 : if (!pStyle || getScaleValue(*pStyle, ATTR_PAGE_SCALETOPAGES) == 0)
599 : {
600 : // Move to the next sheet as the current one has scale-to-pages set,
601 : // and bail out.
602 314 : aScope.incTab();
603 314 : return false;
604 : }
605 :
606 0 : sal_uInt16 nZoom = getScaleValue(*pStyle, ATTR_PAGE_SCALE);
607 0 : Fraction aZoomFract(nZoom, 100);
608 :
609 : // Start at specified cell position (nCol, nRow, nTab).
610 0 : ScColumn* pCol = &pTab->aCol[aScope.Col()];
611 0 : boost::scoped_ptr<ScColumnTextWidthIterator> pColIter(new ScColumnTextWidthIterator(*pCol, aScope.Row(), MAXROW));
612 :
613 0 : OutputDevice* pDev = NULL;
614 0 : sal_uInt16 nRestart = 0;
615 0 : sal_uInt16 nCount = 0;
616 0 : while ( (nZoom > 0) && (nCount < CALCMAX) && (nRestart < 2) )
617 : {
618 0 : if (pColIter->hasCell())
619 : {
620 : // More cell in this column.
621 0 : SCROW nRow = pColIter->getPos();
622 0 : aScope.setRow(nRow);
623 :
624 0 : if (pColIter->getValue() == TEXTWIDTH_DIRTY)
625 : {
626 : // Calculate text width for this cell.
627 0 : double nPPTX = 0.0;
628 0 : double nPPTY = 0.0;
629 0 : if (!pDev)
630 : {
631 0 : pDev = GetPrinter();
632 0 : aScope.setOldMapMode(pDev->GetMapMode());
633 0 : pDev->SetMapMode( MAP_PIXEL ); // wichtig fuer GetNeededSize
634 :
635 0 : Point aPix1000 = pDev->LogicToPixel( Point(1000,1000), MAP_TWIP );
636 0 : nPPTX = aPix1000.X() / 1000.0;
637 0 : nPPTY = aPix1000.Y() / 1000.0;
638 : }
639 :
640 0 : if (!aScope.hasProgressBar() && pCol->IsFormulaDirty(nRow))
641 0 : aScope.createProgressBar();
642 :
643 : sal_uInt16 nNewWidth = (sal_uInt16)GetNeededSize(
644 0 : aScope.Col(), aScope.Row(), aScope.Tab(),
645 0 : pDev, nPPTX, nPPTY, aZoomFract,aZoomFract, true, true); // bTotalSize
646 :
647 0 : pColIter->setValue(nNewWidth);
648 0 : aScope.setNeedMore(true);
649 : }
650 0 : pColIter->next();
651 : }
652 : else
653 : {
654 : // No more cell in this column. Move to the left column and start at row 0.
655 :
656 0 : bool bNewTab = false;
657 :
658 0 : aScope.setRow(0);
659 0 : aScope.incCol(-1);
660 :
661 0 : if (aScope.Col() < 0)
662 : {
663 : // No more column to the left. Move to the right-most column of the next sheet.
664 0 : aScope.setCol(MAXCOL);
665 0 : aScope.incTab();
666 0 : bNewTab = true;
667 : }
668 :
669 0 : if (!ValidTab(aScope.Tab()) || aScope.Tab() >= static_cast<SCTAB>(maTabs.size()) || !maTabs[aScope.Tab()] )
670 : {
671 : // Sheet doesn't exist at specified sheet position. Restart at sheet 0.
672 0 : aScope.setTab(0);
673 0 : nRestart++;
674 0 : bNewTab = true;
675 : }
676 :
677 0 : if ( nRestart < 2 )
678 : {
679 0 : if ( bNewTab )
680 : {
681 0 : pTab = maTabs[aScope.Tab()];
682 0 : pStyle = (ScStyleSheet*)aScope.getStylePool()->Find(
683 0 : pTab->aPageStyle, SFX_STYLE_FAMILY_PAGE);
684 :
685 0 : if ( pStyle )
686 : {
687 : // Check if the scale-to-pages setting is set. If
688 : // set, we exit the loop. If not, get the page
689 : // scale factor of the new sheet.
690 0 : if (getScaleValue(*pStyle, ATTR_PAGE_SCALETOPAGES) == 0)
691 : {
692 0 : nZoom = getScaleValue(*pStyle, ATTR_PAGE_SCALE);
693 0 : aZoomFract = Fraction(nZoom, 100);
694 : }
695 : else
696 0 : nZoom = 0;
697 : }
698 : else
699 : {
700 : OSL_FAIL( "Missing StyleSheet :-/" );
701 : }
702 : }
703 :
704 0 : if ( nZoom > 0 )
705 : {
706 0 : pCol = &pTab->aCol[aScope.Col()];
707 0 : pColIter.reset(new ScColumnTextWidthIterator(*pCol, aScope.Row(), MAXROW));
708 : }
709 : else
710 : {
711 0 : aScope.incTab(); // Move to the next sheet as the current one has scale-to-pages set.
712 0 : return false;
713 : }
714 : }
715 : }
716 :
717 0 : ++nCount;
718 :
719 : // Quit if either 1) its duration exceeds 50 ms, or 2) there is any
720 : // pending event after processing 32 cells.
721 0 : if ((50L < Time::GetSystemTicks() - aScope.getStartTime()) || (nCount > 31 && Application::AnyInput(ABORT_EVENTS)))
722 0 : nCount = CALCMAX;
723 : }
724 :
725 314 : return aScope.getNeedMore();
726 : }
727 :
728 : //------------------------------------------------------------------------
729 :
730 : class ScSpellStatus
731 : {
732 : public:
733 : bool bModified;
734 :
735 3668 : ScSpellStatus() : bModified(false) {};
736 :
737 : DECL_LINK (EventHdl, EditStatus*);
738 : };
739 :
740 4392 : IMPL_LINK( ScSpellStatus, EventHdl, EditStatus *, pStatus )
741 : {
742 2196 : sal_uLong nStatus = pStatus->GetStatusWord();
743 2196 : if ( nStatus & EE_STAT_WRONGWORDCHANGED )
744 159 : bModified = true;
745 :
746 2196 : return 0;
747 : }
748 :
749 : // SPELL_MAXCELLS muss mindestens 256 sein, solange am Iterator keine
750 : // Start-Spalte gesetzt werden kann
751 :
752 : //! SPELL_MAXTEST fuer Timer und Idle unterschiedlich ???
753 :
754 : // SPELL_MAXTEST now divided between visible and rest of document
755 :
756 : #define SPELL_MAXTEST_VIS 1
757 : #define SPELL_MAXTEST_ALL 3
758 : #define SPELL_MAXCELLS 256
759 :
760 3668 : bool ScDocument::OnlineSpellInRange( const ScRange& rSpellRange, ScAddress& rSpellPos,
761 : sal_uInt16 nMaxTest )
762 : {
763 3668 : ScEditEngineDefaulter* pEngine = NULL; //! am Dokument speichern
764 3668 : SfxItemSet* pDefaults = NULL;
765 3668 : ScSpellStatus aStatus;
766 :
767 3668 : sal_uInt16 nCellCount = 0; // Zellen insgesamt
768 3668 : sal_uInt16 nTestCount = 0; // Aufrufe Spelling
769 3668 : bool bChanged = false; // Aenderungen?
770 :
771 3668 : SCCOL nCol = rSpellRange.aStart.Col(); // iterator always starts on the left edge
772 3668 : SCROW nRow = rSpellPos.Row();
773 3668 : SCTAB nTab = rSpellPos.Tab();
774 3668 : if ( nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] ) // sheet deleted?
775 : {
776 3 : nTab = rSpellRange.aStart.Tab();
777 3 : nRow = rSpellRange.aStart.Row();
778 3 : if ( nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] )
779 : {
780 : // may happen for visible range
781 0 : return false;
782 : }
783 : }
784 :
785 3668 : ScRangeList aPivotRanges;
786 3668 : if (pDPCollection)
787 526 : aPivotRanges = pDPCollection->GetAllTableRanges(nTab);
788 :
789 : ScHorizontalCellIterator aIter( this, nTab,
790 3668 : rSpellRange.aStart.Col(), nRow,
791 11004 : rSpellRange.aEnd.Col(), rSpellRange.aEnd.Row() );
792 3668 : ScRefCellValue* pCell = aIter.GetNext( nCol, nRow );
793 : // skip everything left of rSpellPos:
794 10006 : while ( pCell && nRow == rSpellPos.Row() && nCol < rSpellPos.Col() )
795 2670 : pCell = aIter.GetNext( nCol, nRow );
796 :
797 13368 : for (; pCell; pCell = aIter.GetNext(nCol, nRow))
798 : {
799 11061 : if (!aPivotRanges.empty() && aPivotRanges.In(ScAddress(nCol, nRow, nTab)))
800 : // Don't spell check within pivot tables.
801 188 : continue;
802 :
803 10873 : CellType eType = pCell->meType;
804 10873 : if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT )
805 : {
806 2732 : if (!pEngine)
807 : {
808 : // ScTabEditEngine is needed
809 : // because MapMode must be set for some old documents
810 1771 : pEngine = new ScTabEditEngine( this );
811 1771 : pEngine->SetControlWord( pEngine->GetControlWord() |
812 1771 : ( EE_CNTRL_ONLINESPELLING | EE_CNTRL_ALLOWBIGOBJS ) );
813 1771 : pEngine->SetStatusEventHdl( LINK( &aStatus, ScSpellStatus, EventHdl ) );
814 : // Delimiters hier wie in inputhdl.cxx !!!
815 : pEngine->SetWordDelimiters(
816 1771 : ScEditUtil::ModifyDelimiters( pEngine->GetWordDelimiters() ) );
817 1771 : pDefaults = new SfxItemSet( pEngine->GetEmptyItemSet() );
818 :
819 1771 : com::sun::star::uno::Reference<com::sun::star::linguistic2::XSpellChecker1> xXSpellChecker1( LinguMgr::GetSpellChecker() );
820 :
821 1771 : pEngine->SetSpeller( xXSpellChecker1 );
822 : }
823 :
824 2732 : const ScPatternAttr* pPattern = GetPattern( nCol, nRow, nTab );
825 2732 : pPattern->FillEditItemSet( pDefaults );
826 2732 : pEngine->SetDefaults( pDefaults, false ); //! noetig ?
827 :
828 : sal_uInt16 nCellLang = ((const SvxLanguageItem&)
829 2732 : pPattern->GetItem(ATTR_FONT_LANGUAGE)).GetValue();
830 2732 : if ( nCellLang == LANGUAGE_SYSTEM )
831 0 : nCellLang = Application::GetSettings().GetLanguageTag().getLanguageType(); // never use SYSTEM for spelling
832 2732 : pEngine->SetDefaultLanguage( nCellLang );
833 :
834 2732 : if ( eType == CELLTYPE_STRING )
835 : {
836 2470 : pEngine->SetText(*pCell->mpString);
837 : }
838 262 : else if (pCell->mpEditText)
839 262 : pEngine->SetText(*pCell->mpEditText);
840 : else
841 0 : pEngine->SetText(EMPTY_OUSTRING);
842 :
843 2732 : aStatus.bModified = false;
844 2732 : pEngine->CompleteOnlineSpelling();
845 2732 : if ( aStatus.bModified ) // Fehler dazu oder weggekommen?
846 : {
847 159 : bool bNeedEdit = true; // Test auf einfachen Text
848 159 : if ( !pEngine->HasOnlineSpellErrors() )
849 : {
850 0 : ScEditAttrTester aTester( pEngine );
851 0 : bNeedEdit = aTester.NeedsObject();
852 : }
853 :
854 159 : if ( bNeedEdit )
855 : {
856 : // The cell will take ownership of pNewData.
857 159 : SetEditText(ScAddress(nCol,nRow,nTab), pEngine->CreateTextObject());
858 159 : aIter.RehashCol(nCol);
859 : }
860 : else
861 : {
862 0 : ScSetStringParam aParam;
863 0 : aParam.setTextInput();
864 0 : SetString(ScAddress(nCol,nRow,nTab), pEngine->GetText(), &aParam);
865 0 : aIter.RehashCol(nCol);
866 : }
867 :
868 : // Paint
869 159 : if (pShell)
870 : {
871 : // Seitenvorschau ist davon nicht betroffen
872 : // (sollte jedenfalls nicht)
873 159 : ScPaintHint aHint( ScRange( nCol, nRow, nTab ), PAINT_GRID );
874 159 : aHint.SetPrintFlag( false );
875 159 : pShell->Broadcast( aHint );
876 : }
877 :
878 159 : bChanged = true;
879 : }
880 :
881 2732 : if ( ++nTestCount >= nMaxTest ) // checked enough text?
882 1355 : break;
883 : }
884 :
885 9518 : if ( ++nCellCount >= SPELL_MAXCELLS ) // seen enough cells?
886 6 : break;
887 : }
888 :
889 3668 : if ( pCell )
890 : {
891 1361 : ++nCol; // continue after last cell
892 1361 : if ( nCol > rSpellRange.aEnd.Col() )
893 : {
894 18 : nCol = rSpellRange.aStart.Col();
895 18 : ++nRow;
896 18 : if ( nRow > rSpellRange.aEnd.Row() )
897 0 : pCell = NULL;
898 : }
899 : }
900 :
901 3668 : if (!pCell) // end of range reached -> next sheet
902 : {
903 2307 : ++nTab;
904 2307 : if ( nTab > rSpellRange.aEnd.Tab() || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] )
905 2157 : nTab = rSpellRange.aStart.Tab();
906 2307 : nCol = rSpellRange.aStart.Col();
907 2307 : nRow = rSpellRange.aStart.Row();
908 :
909 2307 : nVisSpellState = VSPL_DONE; //! only if this is for the visible range
910 : }
911 3668 : rSpellPos.Set( nCol, nRow, nTab );
912 :
913 3668 : delete pDefaults;
914 3668 : delete pEngine; // bevor aStatus out of scope geht
915 :
916 7336 : return bChanged;
917 : }
918 :
919 :
920 1856 : bool ScDocument::ContinueOnlineSpelling()
921 : {
922 1856 : if (!mbIdleEnabled || !pDocOptions->IsAutoSpell() || (pShell && pShell->IsReadOnly()))
923 22 : return false;
924 :
925 : // #i48433# set bInsertingFromOtherDoc flag so there are no broadcasts when PutCell is called
926 : // (same behavior as in RemoveAutoSpellObj: just transfer the broadcaster)
927 1834 : bool bOldInserting = IsInsertingFromOtherDoc();
928 1834 : SetInsertingFromOtherDoc( true );
929 :
930 : //! use one EditEngine for both calls
931 :
932 : // first check visible range
933 1834 : bool bResult = OnlineSpellInRange( aVisSpellRange, aVisSpellPos, SPELL_MAXTEST_VIS );
934 :
935 : // during first pass through visible range, always continue
936 1834 : if ( nVisSpellState == VSPL_START )
937 213 : bResult = true;
938 :
939 1834 : if (bResult)
940 : {
941 : // if errors found, continue there
942 345 : OnlineSpellInRange( aVisSpellRange, aVisSpellPos, SPELL_MAXTEST_ALL );
943 : }
944 : else
945 : {
946 : // if nothing found there, continue with rest of document
947 1489 : ScRange aTotalRange( 0,0,0, MAXCOL,MAXROW,MAXTAB );
948 1489 : bResult = OnlineSpellInRange( aTotalRange, aOnlineSpellPos, SPELL_MAXTEST_ALL );
949 : }
950 :
951 1834 : SetInsertingFromOtherDoc( bOldInserting );
952 :
953 1834 : return bResult;
954 : }
955 :
956 :
957 0 : void ScDocument::SetOnlineSpellPos( const ScAddress& rPos )
958 : {
959 0 : aOnlineSpellPos = rPos;
960 :
961 : // skip visible area for aOnlineSpellPos
962 0 : if ( aVisSpellRange.In( aOnlineSpellPos ) )
963 0 : aOnlineSpellPos = aVisSpellRange.aEnd;
964 0 : }
965 :
966 1362 : bool ScDocument::SetVisibleSpellRange( const ScRange& rNewRange )
967 : {
968 1362 : bool bChange = ( aVisSpellRange != rNewRange );
969 1362 : if (bChange)
970 : {
971 : // continue spelling through visible range when scrolling down
972 1032 : bool bContDown = ( nVisSpellState == VSPL_START && rNewRange.In( aVisSpellPos ) &&
973 240 : rNewRange.aStart.Row() > aVisSpellRange.aStart.Row() &&
974 486 : rNewRange.aStart.Col() == aVisSpellRange.aStart.Col() &&
975 485 : rNewRange.aEnd.Col() == aVisSpellRange.aEnd.Col() );
976 :
977 485 : aVisSpellRange = rNewRange;
978 :
979 485 : if ( !bContDown )
980 : {
981 485 : aVisSpellPos = aVisSpellRange.aStart;
982 485 : nVisSpellState = VSPL_START;
983 : }
984 :
985 : // skip visible area for aOnlineSpellPos
986 485 : if ( aVisSpellRange.In( aOnlineSpellPos ) )
987 240 : aOnlineSpellPos = aVisSpellRange.aEnd;
988 : }
989 1362 : return bChange;
990 : }
991 :
992 0 : void ScDocument::RemoveAutoSpellObj()
993 : {
994 : // alle Spelling-Informationen entfernen
995 :
996 0 : for (SCTAB nTab=0; nTab< static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]; nTab++)
997 0 : maTabs[nTab]->RemoveAutoSpellObj();
998 0 : }
999 :
1000 3778 : void ScDocument::RepaintRange( const ScRange& rRange )
1001 : {
1002 3778 : if ( bIsVisible && pShell )
1003 : {
1004 160 : ScModelObj* pModel = ScModelObj::getImplementation( pShell->GetModel() );
1005 160 : if ( pModel )
1006 160 : pModel->RepaintRange( rRange ); // locked repaints are checked there
1007 : }
1008 3778 : }
1009 :
1010 0 : void ScDocument::RepaintRange( const ScRangeList& rRange )
1011 : {
1012 0 : if ( bIsVisible && pShell )
1013 : {
1014 0 : ScModelObj* pModel = ScModelObj::getImplementation( pShell->GetModel() );
1015 0 : if ( pModel )
1016 0 : pModel->RepaintRange( rRange ); // locked repaints are checked there
1017 : }
1018 0 : }
1019 :
1020 : //------------------------------------------------------------------------
1021 :
1022 1590 : bool ScDocument::IdleCheckLinks() // true = demnaechst wieder versuchen
1023 : {
1024 1590 : bool bAnyLeft = false;
1025 :
1026 1590 : if (GetLinkManager())
1027 : {
1028 1590 : const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1029 1590 : sal_uInt16 nCount = rLinks.size();
1030 1604 : for (sal_uInt16 i=0; i<nCount; i++)
1031 : {
1032 14 : ::sfx2::SvBaseLink* pBase = *rLinks[i];
1033 14 : if (pBase->ISA(ScDdeLink))
1034 : {
1035 0 : ScDdeLink* pDdeLink = (ScDdeLink*)pBase;
1036 0 : if (pDdeLink->NeedsUpdate())
1037 : {
1038 0 : pDdeLink->TryUpdate();
1039 0 : if (pDdeLink->NeedsUpdate()) // war nix?
1040 0 : bAnyLeft = true;
1041 : }
1042 : }
1043 : }
1044 : }
1045 :
1046 1590 : return bAnyLeft;
1047 : }
1048 :
1049 0 : void ScDocument::SaveDdeLinks(SvStream& rStream) const
1050 : {
1051 : // bei 4.0-Export alle mit Modus != DEFAULT weglassen
1052 0 : bool bExport40 = ( rStream.GetVersion() <= SOFFICE_FILEFORMAT_40 );
1053 :
1054 0 : const ::sfx2::SvBaseLinks& rLinks = GetLinkManager()->GetLinks();
1055 0 : sal_uInt16 nCount = rLinks.size();
1056 :
1057 : // erstmal zaehlen...
1058 :
1059 0 : sal_uInt16 nDdeCount = 0;
1060 : sal_uInt16 i;
1061 0 : for (i=0; i<nCount; i++)
1062 : {
1063 0 : ::sfx2::SvBaseLink* pBase = *rLinks[i];
1064 0 : if (pBase->ISA(ScDdeLink))
1065 0 : if ( !bExport40 || ((ScDdeLink*)pBase)->GetMode() == SC_DDE_DEFAULT )
1066 0 : ++nDdeCount;
1067 : }
1068 :
1069 : // Header
1070 :
1071 0 : ScMultipleWriteHeader aHdr( rStream );
1072 0 : rStream << nDdeCount;
1073 :
1074 : // Links speichern
1075 :
1076 0 : for (i=0; i<nCount; i++)
1077 : {
1078 0 : ::sfx2::SvBaseLink* pBase = *rLinks[i];
1079 0 : if (pBase->ISA(ScDdeLink))
1080 : {
1081 0 : ScDdeLink* pLink = (ScDdeLink*)pBase;
1082 0 : if ( !bExport40 || pLink->GetMode() == SC_DDE_DEFAULT )
1083 0 : pLink->Store( rStream, aHdr );
1084 : }
1085 0 : }
1086 0 : }
1087 :
1088 0 : void ScDocument::LoadDdeLinks(SvStream& rStream)
1089 : {
1090 0 : ScMultipleReadHeader aHdr( rStream );
1091 :
1092 0 : GetLinkManager();
1093 : sal_uInt16 nCount;
1094 0 : rStream >> nCount;
1095 0 : for (sal_uInt16 i=0; i<nCount; i++)
1096 : {
1097 0 : ScDdeLink* pLink = new ScDdeLink( this, rStream, aHdr );
1098 : pLinkManager->InsertDDELink( pLink,
1099 0 : pLink->GetAppl(), pLink->GetTopic(), pLink->GetItem() );
1100 0 : }
1101 0 : }
1102 :
1103 238 : bool ScDocument::HasDdeLinks() const
1104 : {
1105 238 : if (GetLinkManager()) // Clipboard z.B. hat keinen LinkManager
1106 : {
1107 238 : const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1108 238 : sal_uInt16 nCount = rLinks.size();
1109 238 : for (sal_uInt16 i=0; i<nCount; i++)
1110 0 : if ((*rLinks[i])->ISA(ScDdeLink))
1111 0 : return true;
1112 : }
1113 :
1114 238 : return false;
1115 : }
1116 :
1117 12 : void ScDocument::SetInLinkUpdate(bool bSet)
1118 : {
1119 : // called from TableLink and AreaLink
1120 :
1121 : OSL_ENSURE( bInLinkUpdate != bSet, "SetInLinkUpdate twice" );
1122 12 : bInLinkUpdate = bSet;
1123 12 : }
1124 :
1125 1579 : bool ScDocument::IsInLinkUpdate() const
1126 : {
1127 1579 : return bInLinkUpdate || IsInDdeLinkUpdate();
1128 : }
1129 :
1130 0 : void ScDocument::UpdateExternalRefLinks(Window* pWin)
1131 : {
1132 0 : if (!GetLinkManager())
1133 0 : return;
1134 :
1135 0 : const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1136 0 : sal_uInt16 nCount = rLinks.size();
1137 :
1138 0 : bool bAny = false;
1139 0 : for (sal_uInt16 i = 0; i < nCount; ++i)
1140 : {
1141 0 : ::sfx2::SvBaseLink* pBase = *rLinks[i];
1142 0 : ScExternalRefLink* pRefLink = dynamic_cast<ScExternalRefLink*>(pBase);
1143 0 : if (pRefLink)
1144 : {
1145 0 : if (pRefLink->Update())
1146 0 : bAny = true;
1147 : else
1148 : {
1149 : // Update failed. Notify the user.
1150 :
1151 0 : OUString aFile;
1152 0 : pLinkManager->GetDisplayNames(pRefLink, NULL, &aFile, NULL, NULL);
1153 : // Decode encoded URL for display friendliness.
1154 0 : INetURLObject aUrl(aFile,INetURLObject::WAS_ENCODED);
1155 0 : aFile = aUrl.GetMainURL(INetURLObject::DECODE_UNAMBIGUOUS);
1156 :
1157 0 : OUStringBuffer aBuf;
1158 0 : aBuf.append(String(ScResId(SCSTR_EXTDOC_NOT_LOADED)));
1159 0 : aBuf.appendAscii("\n\n");
1160 0 : aBuf.append(aFile);
1161 0 : ErrorBox aBox(pWin, WB_OK, aBuf.makeStringAndClear());
1162 0 : aBox.Execute();
1163 : }
1164 : }
1165 : }
1166 0 : if (bAny)
1167 : {
1168 0 : TrackFormulas();
1169 0 : pShell->Broadcast( SfxSimpleHint(FID_DATACHANGED) );
1170 :
1171 : // #i101960# set document modified, as in TrackTimeHdl for DDE links
1172 0 : if (!pShell->IsModified())
1173 : {
1174 0 : pShell->SetModified( true );
1175 0 : SfxBindings* pBindings = GetViewBindings();
1176 0 : if (pBindings)
1177 : {
1178 0 : pBindings->Invalidate( SID_SAVEDOC );
1179 0 : pBindings->Invalidate( SID_DOC_MODIFIED );
1180 : }
1181 : }
1182 : }
1183 : }
1184 :
1185 0 : void ScDocument::UpdateDdeLinks(Window* pWin)
1186 : {
1187 0 : if (GetLinkManager())
1188 : {
1189 0 : const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1190 0 : sal_uInt16 nCount = rLinks.size();
1191 : sal_uInt16 i;
1192 :
1193 : // falls das Updaten laenger dauert, erstmal alle Werte
1194 : // zuruecksetzen, damit nichts altes (falsches) stehen bleibt
1195 0 : bool bAny = false;
1196 0 : for (i=0; i<nCount; i++)
1197 : {
1198 0 : ::sfx2::SvBaseLink* pBase = *rLinks[i];
1199 0 : ScDdeLink* pDdeLink = dynamic_cast<ScDdeLink*>(pBase);
1200 0 : if (pDdeLink)
1201 : {
1202 0 : if (pDdeLink->Update())
1203 0 : bAny = true;
1204 : else
1205 : {
1206 : // Update failed. Notify the user.
1207 0 : OUString aFile = pDdeLink->GetTopic();
1208 0 : OUString aElem = pDdeLink->GetItem();
1209 0 : OUString aType = pDdeLink->GetAppl();
1210 :
1211 0 : OUStringBuffer aBuf;
1212 0 : aBuf.append(String(ScResId(SCSTR_DDEDOC_NOT_LOADED)));
1213 0 : aBuf.appendAscii("\n\n");
1214 0 : aBuf.appendAscii("Source : ");
1215 0 : aBuf.append(aFile);
1216 0 : aBuf.appendAscii("\nElement : ");
1217 0 : aBuf.append(aElem);
1218 0 : aBuf.appendAscii("\nType : ");
1219 0 : aBuf.append(aType);
1220 0 : ErrorBox aBox(pWin, WB_OK, aBuf.makeStringAndClear());
1221 0 : aBox.Execute();
1222 : }
1223 : }
1224 : }
1225 0 : if (bAny)
1226 : {
1227 : // Formeln berechnen und painten wie im TrackTimeHdl
1228 0 : TrackFormulas();
1229 0 : pShell->Broadcast( SfxSimpleHint( FID_DATACHANGED ) );
1230 :
1231 : // wenn FID_DATACHANGED irgendwann mal asynchron werden sollte
1232 : // (z.B. mit Invalidate am Window), muss hier ein Update erzwungen werden.
1233 : }
1234 :
1235 0 : pLinkManager->CloseCachedComps();
1236 : }
1237 0 : }
1238 :
1239 2 : bool ScDocument::UpdateDdeLink( const OUString& rAppl, const OUString& rTopic, const OUString& rItem )
1240 : {
1241 : // fuer refresh() per StarOne Api
1242 : // ResetValue() fuer einzelnen Link nicht noetig
1243 : //! wenn's mal alles asynchron wird, aber auch hier
1244 :
1245 2 : bool bFound = false;
1246 2 : if (GetLinkManager())
1247 : {
1248 2 : const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1249 2 : sal_uInt16 nCount = rLinks.size();
1250 4 : for (sal_uInt16 i=0; i<nCount; i++)
1251 : {
1252 2 : ::sfx2::SvBaseLink* pBase = *rLinks[i];
1253 2 : if (pBase->ISA(ScDdeLink))
1254 : {
1255 2 : ScDdeLink* pDdeLink = (ScDdeLink*)pBase;
1256 12 : if ( OUString(pDdeLink->GetAppl()) == rAppl &&
1257 14 : OUString(pDdeLink->GetTopic()) == rTopic &&
1258 6 : OUString(pDdeLink->GetItem()) == rItem )
1259 : {
1260 2 : pDdeLink->TryUpdate();
1261 2 : bFound = true; // koennen theoretisch mehrere sein (Mode), darum weitersuchen
1262 : }
1263 : }
1264 : }
1265 2 : pLinkManager->CloseCachedComps();
1266 : }
1267 2 : return bFound;
1268 : }
1269 :
1270 0 : void ScDocument::DisconnectDdeLinks()
1271 : {
1272 0 : if (GetLinkManager())
1273 : {
1274 0 : const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1275 0 : sal_uInt16 nCount = rLinks.size();
1276 0 : for (sal_uInt16 i=0; i<nCount; i++)
1277 : {
1278 0 : ::sfx2::SvBaseLink* pBase = *rLinks[i];
1279 0 : if (pBase->ISA(ScDdeLink))
1280 0 : pBase->Disconnect(); // bleibt im LinkManager eingetragen
1281 : }
1282 : }
1283 0 : }
1284 :
1285 0 : void ScDocument::CopyDdeLinks( ScDocument* pDestDoc ) const
1286 : {
1287 0 : if (bIsClip) // aus Stream erzeugen
1288 : {
1289 0 : if (pClipData)
1290 : {
1291 0 : pClipData->Seek(0);
1292 0 : pDestDoc->LoadDdeLinks(*pClipData);
1293 : }
1294 : }
1295 0 : else if (GetLinkManager()) // Links direkt kopieren
1296 : {
1297 0 : const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1298 0 : size_t nCount = rLinks.size();
1299 0 : for (size_t i=0; i<nCount; i++)
1300 : {
1301 0 : ::sfx2::SvBaseLink* pBase = *rLinks[i];
1302 0 : if (pBase->ISA(ScDdeLink))
1303 : {
1304 0 : ScDdeLink* pNew = new ScDdeLink( pDestDoc, *(ScDdeLink*)pBase );
1305 :
1306 : pDestDoc->pLinkManager->InsertDDELink( pNew,
1307 0 : pNew->GetAppl(), pNew->GetTopic(), pNew->GetItem() );
1308 : }
1309 : }
1310 : }
1311 0 : }
1312 :
1313 19 : size_t ScDocument::GetDdeLinkCount() const
1314 : {
1315 19 : size_t nDdeCount = 0;
1316 19 : if (GetLinkManager())
1317 : {
1318 19 : const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1319 19 : size_t nCount = rLinks.size();
1320 30 : for (size_t i=0; i<nCount; i++)
1321 11 : if ((*rLinks[i])->ISA(ScDdeLink))
1322 11 : ++nDdeCount;
1323 : }
1324 19 : return nDdeCount;
1325 : }
1326 :
1327 : // ----------------------------------------------------------------------------
1328 :
1329 : namespace {
1330 :
1331 : /** Tries to find the specified DDE link.
1332 : @param pnDdePos (out-param) if not 0, the index of the DDE link is returned here
1333 : (does not include other links from link manager).
1334 : @return The DDE link, if it exists, otherwise 0. */
1335 0 : ScDdeLink* lclGetDdeLink(
1336 : const sfx2::LinkManager* pLinkManager,
1337 : const OUString& rAppl, const OUString& rTopic, const OUString& rItem, sal_uInt8 nMode,
1338 : size_t* pnDdePos = NULL )
1339 : {
1340 0 : if( pLinkManager )
1341 : {
1342 0 : const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1343 0 : size_t nCount = rLinks.size();
1344 0 : if( pnDdePos ) *pnDdePos = 0;
1345 0 : for( size_t nIndex = 0; nIndex < nCount; ++nIndex )
1346 : {
1347 0 : ::sfx2::SvBaseLink* pLink = *rLinks[ nIndex ];
1348 0 : if( ScDdeLink* pDdeLink = PTR_CAST( ScDdeLink, pLink ) )
1349 : {
1350 0 : if( (OUString(pDdeLink->GetAppl()) == rAppl) &&
1351 0 : (OUString(pDdeLink->GetTopic()) == rTopic) &&
1352 0 : (OUString(pDdeLink->GetItem()) == rItem) &&
1353 0 : ((nMode == SC_DDE_IGNOREMODE) || (nMode == pDdeLink->GetMode())) )
1354 0 : return pDdeLink;
1355 0 : if( pnDdePos ) ++*pnDdePos;
1356 : }
1357 : }
1358 : }
1359 0 : return NULL;
1360 : }
1361 :
1362 : /** Returns a pointer to the specified DDE link.
1363 : @param nDdePos Index of the DDE link (does not include other links from link manager).
1364 : @return The DDE link, if it exists, otherwise 0. */
1365 13 : ScDdeLink* lclGetDdeLink( const sfx2::LinkManager* pLinkManager, size_t nDdePos )
1366 : {
1367 13 : if( pLinkManager )
1368 : {
1369 13 : const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1370 13 : size_t nCount = rLinks.size();
1371 13 : size_t nDdeIndex = 0; // counts only the DDE links
1372 15 : for( size_t nIndex = 0; nIndex < nCount; ++nIndex )
1373 : {
1374 13 : ::sfx2::SvBaseLink* pLink = *rLinks[ nIndex ];
1375 13 : if( ScDdeLink* pDdeLink = PTR_CAST( ScDdeLink, pLink ) )
1376 : {
1377 13 : if( nDdeIndex == nDdePos )
1378 11 : return pDdeLink;
1379 2 : ++nDdeIndex;
1380 : }
1381 : }
1382 : }
1383 2 : return NULL;
1384 : }
1385 :
1386 : } // namespace
1387 :
1388 : // ----------------------------------------------------------------------------
1389 :
1390 0 : bool ScDocument::FindDdeLink( const OUString& rAppl, const OUString& rTopic, const OUString& rItem,
1391 : sal_uInt8 nMode, size_t& rnDdePos )
1392 : {
1393 0 : return lclGetDdeLink( GetLinkManager(), rAppl, rTopic, rItem, nMode, &rnDdePos ) != NULL;
1394 : }
1395 :
1396 13 : bool ScDocument::GetDdeLinkData( size_t nDdePos, OUString& rAppl, OUString& rTopic, OUString& rItem ) const
1397 : {
1398 13 : if( const ScDdeLink* pDdeLink = lclGetDdeLink( GetLinkManager(), nDdePos ) )
1399 : {
1400 11 : rAppl = pDdeLink->GetAppl();
1401 11 : rTopic = pDdeLink->GetTopic();
1402 11 : rItem = pDdeLink->GetItem();
1403 11 : return true;
1404 : }
1405 2 : return false;
1406 : }
1407 :
1408 0 : bool ScDocument::GetDdeLinkMode( size_t nDdePos, sal_uInt8& rnMode ) const
1409 : {
1410 0 : if( const ScDdeLink* pDdeLink = lclGetDdeLink( GetLinkManager(), nDdePos ) )
1411 : {
1412 0 : rnMode = pDdeLink->GetMode();
1413 0 : return true;
1414 : }
1415 0 : return false;
1416 : }
1417 :
1418 0 : const ScMatrix* ScDocument::GetDdeLinkResultMatrix( size_t nDdePos ) const
1419 : {
1420 0 : const ScDdeLink* pDdeLink = lclGetDdeLink( GetLinkManager(), nDdePos );
1421 0 : return pDdeLink ? pDdeLink->GetResult() : NULL;
1422 : }
1423 :
1424 0 : bool ScDocument::CreateDdeLink( const OUString& rAppl, const OUString& rTopic, const OUString& rItem, sal_uInt8 nMode, ScMatrixRef pResults )
1425 : {
1426 : /* Create a DDE link without updating it (i.e. for Excel import), to prevent
1427 : unwanted connections. First try to find existing link. Set result array
1428 : on existing and new links. */
1429 : //! store DDE links additionally at document (for efficiency)?
1430 : OSL_ENSURE( nMode != SC_DDE_IGNOREMODE, "ScDocument::CreateDdeLink - SC_DDE_IGNOREMODE not allowed here" );
1431 0 : if( GetLinkManager() && (nMode != SC_DDE_IGNOREMODE) )
1432 : {
1433 0 : ScDdeLink* pDdeLink = lclGetDdeLink( pLinkManager, rAppl, rTopic, rItem, nMode );
1434 0 : if( !pDdeLink )
1435 : {
1436 : // create a new DDE link, but without TryUpdate
1437 0 : pDdeLink = new ScDdeLink( this, rAppl, rTopic, rItem, nMode );
1438 0 : pLinkManager->InsertDDELink( pDdeLink, rAppl, rTopic, rItem );
1439 : }
1440 :
1441 : // insert link results
1442 0 : if( pResults )
1443 0 : pDdeLink->SetResult( pResults );
1444 :
1445 0 : return true;
1446 : }
1447 0 : return false;
1448 : }
1449 :
1450 0 : bool ScDocument::SetDdeLinkResultMatrix( size_t nDdePos, ScMatrixRef pResults )
1451 : {
1452 0 : if( ScDdeLink* pDdeLink = lclGetDdeLink( GetLinkManager(), nDdePos ) )
1453 : {
1454 0 : pDdeLink->SetResult( pResults );
1455 0 : return true;
1456 : }
1457 0 : return false;
1458 : }
1459 :
1460 : //------------------------------------------------------------------------
1461 :
1462 202 : bool ScDocument::HasAreaLinks() const
1463 : {
1464 202 : if (GetLinkManager()) // Clipboard z.B. hat keinen LinkManager
1465 : {
1466 202 : const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1467 202 : sal_uInt16 nCount = rLinks.size();
1468 202 : for (sal_uInt16 i=0; i<nCount; i++)
1469 0 : if ((*rLinks[i])->ISA(ScAreaLink))
1470 0 : return true;
1471 : }
1472 :
1473 202 : return false;
1474 : }
1475 :
1476 0 : void ScDocument::UpdateAreaLinks()
1477 : {
1478 0 : if (GetLinkManager())
1479 : {
1480 0 : const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1481 0 : for (sal_uInt16 i=0; i<rLinks.size(); i++)
1482 : {
1483 0 : ::sfx2::SvBaseLink* pBase = *rLinks[i];
1484 0 : if (pBase->ISA(ScAreaLink))
1485 0 : pBase->Update();
1486 : }
1487 : }
1488 0 : }
1489 :
1490 54 : void ScDocument::DeleteAreaLinksOnTab( SCTAB nTab )
1491 : {
1492 54 : if (GetLinkManager())
1493 : {
1494 54 : const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1495 54 : sal_uInt16 nPos = 0;
1496 108 : while ( nPos < rLinks.size() )
1497 : {
1498 0 : const ::sfx2::SvBaseLink* pBase = *rLinks[nPos];
1499 0 : if ( pBase->ISA(ScAreaLink) &&
1500 0 : static_cast<const ScAreaLink*>(pBase)->GetDestArea().aStart.Tab() == nTab )
1501 0 : pLinkManager->Remove( nPos );
1502 : else
1503 0 : ++nPos;
1504 : }
1505 : }
1506 54 : }
1507 :
1508 144 : void ScDocument::UpdateRefAreaLinks( UpdateRefMode eUpdateRefMode,
1509 : const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
1510 : {
1511 144 : if (GetLinkManager())
1512 : {
1513 144 : bool bAnyUpdate = false;
1514 :
1515 144 : const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1516 144 : sal_uInt16 nCount = rLinks.size();
1517 144 : for (sal_uInt16 i=0; i<nCount; i++)
1518 : {
1519 0 : ::sfx2::SvBaseLink* pBase = *rLinks[i];
1520 0 : if (pBase->ISA(ScAreaLink))
1521 : {
1522 0 : ScAreaLink* pLink = (ScAreaLink*) pBase;
1523 0 : ScRange aOutRange = pLink->GetDestArea();
1524 :
1525 0 : SCCOL nCol1 = aOutRange.aStart.Col();
1526 0 : SCROW nRow1 = aOutRange.aStart.Row();
1527 0 : SCTAB nTab1 = aOutRange.aStart.Tab();
1528 0 : SCCOL nCol2 = aOutRange.aEnd.Col();
1529 0 : SCROW nRow2 = aOutRange.aEnd.Row();
1530 0 : SCTAB nTab2 = aOutRange.aEnd.Tab();
1531 :
1532 : ScRefUpdateRes eRes =
1533 : ScRefUpdate::Update( this, eUpdateRefMode,
1534 0 : rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
1535 0 : rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(), nDx, nDy, nDz,
1536 0 : nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
1537 0 : if ( eRes != UR_NOTHING )
1538 : {
1539 0 : pLink->SetDestArea( ScRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ) );
1540 0 : bAnyUpdate = true;
1541 : }
1542 : }
1543 : }
1544 :
1545 144 : if ( bAnyUpdate )
1546 : {
1547 : // #i52120# Look for duplicates (after updating all positions).
1548 : // If several links start at the same cell, the one with the lower index is removed
1549 : // (file format specifies only one link definition for a cell).
1550 :
1551 0 : sal_uInt16 nFirstIndex = 0;
1552 0 : while ( nFirstIndex < nCount )
1553 : {
1554 0 : bool bFound = false;
1555 0 : ::sfx2::SvBaseLink* pFirst = *rLinks[nFirstIndex];
1556 0 : if ( pFirst->ISA(ScAreaLink) )
1557 : {
1558 0 : ScAddress aFirstPos = static_cast<ScAreaLink*>(pFirst)->GetDestArea().aStart;
1559 0 : for ( sal_uInt16 nSecondIndex = nFirstIndex + 1; nSecondIndex < nCount && !bFound; ++nSecondIndex )
1560 : {
1561 0 : ::sfx2::SvBaseLink* pSecond = *rLinks[nSecondIndex];
1562 0 : if ( pSecond->ISA(ScAreaLink) &&
1563 0 : static_cast<ScAreaLink*>(pSecond)->GetDestArea().aStart == aFirstPos )
1564 : {
1565 : // remove the first link, exit the inner loop, don't increment nFirstIndex
1566 0 : pLinkManager->Remove( pFirst );
1567 0 : nCount = rLinks.size();
1568 0 : bFound = true;
1569 : }
1570 : }
1571 : }
1572 0 : if (!bFound)
1573 0 : ++nFirstIndex;
1574 : }
1575 : }
1576 : }
1577 144 : }
1578 :
1579 : //------------------------------------------------------------------------
1580 :
1581 : // TimerDelays etc.
1582 0 : void ScDocument::KeyInput( const KeyEvent& )
1583 : {
1584 0 : if ( pChartListenerCollection->hasListeners() )
1585 0 : pChartListenerCollection->StartTimer();
1586 0 : if( apTemporaryChartLock.get() )
1587 0 : apTemporaryChartLock->StartOrContinueLocking();
1588 0 : }
1589 :
1590 : // ----------------------------------------------------------------------------
1591 :
1592 0 : bool ScDocument::CheckMacroWarn()
1593 : {
1594 : // The check for macro configuration, macro warning and disabling is now handled
1595 : // in SfxObjectShell::AdjustMacroMode, called by SfxObjectShell::CallBasic.
1596 :
1597 0 : return true;
1598 : }
1599 :
1600 : //------------------------------------------------------------------------
1601 :
1602 9 : SfxBindings* ScDocument::GetViewBindings()
1603 : {
1604 : // used to invalidate slots after changes to this document
1605 :
1606 9 : if ( !pShell )
1607 0 : return NULL; // no ObjShell -> no view
1608 :
1609 : // first check current view
1610 9 : SfxViewFrame* pViewFrame = SfxViewFrame::Current();
1611 9 : if ( pViewFrame && pViewFrame->GetObjectShell() != pShell ) // wrong document?
1612 9 : pViewFrame = NULL;
1613 :
1614 : // otherwise use first view for this doc
1615 9 : if ( !pViewFrame )
1616 9 : pViewFrame = SfxViewFrame::GetFirst( pShell );
1617 :
1618 9 : if (pViewFrame)
1619 9 : return &pViewFrame->GetBindings();
1620 : else
1621 0 : return NULL;
1622 : }
1623 :
1624 13342 : ScDrawLayer* ScDocument::GetDrawLayer()
1625 : {
1626 13342 : return pDrawLayer;
1627 : }
1628 :
1629 : //------------------------------------------------------------------------
1630 :
1631 0 : void ScDocument::TransliterateText( const ScMarkData& rMultiMark, sal_Int32 nType )
1632 : {
1633 : OSL_ENSURE( rMultiMark.IsMultiMarked(), "TransliterateText: no selection" );
1634 :
1635 0 : utl::TransliterationWrapper aTranslitarationWrapper( comphelper::getProcessComponentContext(), nType );
1636 0 : bool bConsiderLanguage = aTranslitarationWrapper.needLanguageForTheMode();
1637 0 : sal_uInt16 nLanguage = LANGUAGE_SYSTEM;
1638 :
1639 0 : ScEditEngineDefaulter* pEngine = NULL; // not using pEditEngine member because of defaults
1640 :
1641 0 : SCTAB nCount = GetTableCount();
1642 0 : ScMarkData::const_iterator itr = rMultiMark.begin(), itrEnd = rMultiMark.end();
1643 0 : for (; itr != itrEnd && *itr < nCount; ++itr)
1644 0 : if ( maTabs[*itr] )
1645 : {
1646 0 : SCTAB nTab = *itr;
1647 0 : SCCOL nCol = 0;
1648 0 : SCROW nRow = 0;
1649 :
1650 0 : bool bFound = rMultiMark.IsCellMarked( nCol, nRow );
1651 0 : if (!bFound)
1652 0 : bFound = GetNextMarkedCell( nCol, nRow, nTab, rMultiMark );
1653 :
1654 0 : while (bFound)
1655 : {
1656 0 : ScRefCellValue aCell;
1657 0 : aCell.assign(*this, ScAddress(nCol, nRow, nTab));
1658 :
1659 : // fdo#32786 TITLE_CASE/SENTENCE_CASE need the extra handling in EditEngine (loop over words/sentences).
1660 : // Still use TransliterationWrapper directly for text cells with other transliteration types,
1661 : // for performance reasons.
1662 0 : if (aCell.meType == CELLTYPE_EDIT ||
1663 0 : (aCell.meType == CELLTYPE_STRING &&
1664 0 : ( nType == i18n::TransliterationModulesExtra::SENTENCE_CASE || nType == i18n::TransliterationModulesExtra::TITLE_CASE)))
1665 : {
1666 0 : if (!pEngine)
1667 0 : pEngine = new ScFieldEditEngine(this, GetEnginePool(), GetEditPool());
1668 :
1669 : // defaults from cell attributes must be set so right language is used
1670 0 : const ScPatternAttr* pPattern = GetPattern( nCol, nRow, nTab );
1671 0 : SfxItemSet* pDefaults = new SfxItemSet( pEngine->GetEmptyItemSet() );
1672 0 : pPattern->FillEditItemSet( pDefaults );
1673 0 : pEngine->SetDefaults( pDefaults, true );
1674 :
1675 0 : if (aCell.meType == CELLTYPE_STRING)
1676 0 : pEngine->SetText(*aCell.mpString);
1677 0 : else if (aCell.mpEditText)
1678 0 : pEngine->SetText(*aCell.mpEditText);
1679 :
1680 0 : pEngine->ClearModifyFlag();
1681 :
1682 0 : sal_Int32 nLastPar = pEngine->GetParagraphCount();
1683 0 : if (nLastPar)
1684 0 : --nLastPar;
1685 0 : xub_StrLen nTxtLen = pEngine->GetTextLen(nLastPar);
1686 0 : ESelection aSelAll( 0, 0, nLastPar, nTxtLen );
1687 :
1688 0 : pEngine->TransliterateText( aSelAll, nType );
1689 :
1690 0 : if ( pEngine->IsModified() )
1691 : {
1692 0 : ScEditAttrTester aTester( pEngine );
1693 0 : if ( aTester.NeedsObject() )
1694 : {
1695 : // remove defaults (paragraph attributes) before creating text object
1696 0 : SfxItemSet* pEmpty = new SfxItemSet( pEngine->GetEmptyItemSet() );
1697 0 : pEngine->SetDefaults( pEmpty, true );
1698 :
1699 : // The cell will take ownership of the text object instance.
1700 0 : SetEditText(ScAddress(nCol,nRow,nTab), pEngine->CreateTextObject());
1701 : }
1702 : else
1703 : {
1704 0 : ScSetStringParam aParam;
1705 0 : aParam.setTextInput();
1706 0 : SetString(ScAddress(nCol,nRow,nTab), pEngine->GetText(), &aParam);
1707 0 : }
1708 0 : }
1709 : }
1710 :
1711 0 : else if (aCell.meType == CELLTYPE_STRING)
1712 : {
1713 0 : OUString aOldStr = *aCell.mpString;
1714 0 : sal_Int32 nOldLen = aOldStr.getLength();
1715 :
1716 0 : if ( bConsiderLanguage )
1717 : {
1718 0 : sal_uInt8 nScript = GetStringScriptType( aOldStr ); //! cell script type?
1719 : sal_uInt16 nWhich = ( nScript == SCRIPTTYPE_ASIAN ) ? ATTR_CJK_FONT_LANGUAGE :
1720 : ( ( nScript == SCRIPTTYPE_COMPLEX ) ? ATTR_CTL_FONT_LANGUAGE :
1721 0 : ATTR_FONT_LANGUAGE );
1722 0 : nLanguage = ((const SvxLanguageItem*)GetAttr( nCol, nRow, nTab, nWhich ))->GetValue();
1723 : }
1724 :
1725 0 : uno::Sequence<sal_Int32> aOffsets;
1726 0 : OUString aNewStr = aTranslitarationWrapper.transliterate( aOldStr, nLanguage, 0, nOldLen, &aOffsets );
1727 :
1728 0 : if ( aNewStr != aOldStr )
1729 : {
1730 0 : ScSetStringParam aParam;
1731 0 : aParam.setTextInput();
1732 0 : SetString(ScAddress(nCol,nRow,nTab), aNewStr, &aParam);
1733 0 : }
1734 : }
1735 0 : bFound = GetNextMarkedCell( nCol, nRow, nTab, rMultiMark );
1736 0 : }
1737 : }
1738 0 : delete pEngine;
1739 93 : }
1740 :
1741 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|