update dev300-m57
[ooovba.git] / sc / source / core / data / documen8.cxx
blob78be061c30f8b31480070e01bb4ee8740864aede
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: documen8.cxx,v $
10 * $Revision: 1.52.32.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
35 #define _ZFORLIST_DECLARE_TABLE
36 #include "scitems.hxx"
37 #include <svx/eeitem.hxx>
39 #include <tools/string.hxx>
40 #include <svx/editobj.hxx>
41 #include <svx/editstat.hxx>
42 #include <svx/frmdiritem.hxx>
43 #include <svx/langitem.hxx>
44 #include <svx/linkmgr.hxx>
45 #include <svx/scripttypeitem.hxx>
46 #include <svx/unolingu.hxx>
47 #include <sfx2/bindings.hxx>
48 #include <sfx2/objsh.hxx>
49 #include <sfx2/printer.hxx>
50 #include <sfx2/viewfrm.hxx>
51 #include <sfx2/viewsh.hxx>
52 #include <svtools/flagitem.hxx>
53 #include <svtools/intitem.hxx>
54 #define _SVSTDARR_USHORTS
55 #include <svtools/svstdarr.hxx>
56 #include <svtools/zforlist.hxx>
57 #include <svtools/zformat.hxx>
58 #include <svtools/misccfg.hxx>
59 #include <sfx2/app.hxx>
60 #include <unotools/transliterationwrapper.hxx>
61 #include <svtools/securityoptions.hxx>
63 #include <vcl/virdev.hxx>
64 #include <vcl/msgbox.hxx>
66 #include "inputopt.hxx"
67 #include "global.hxx"
68 #include "table.hxx"
69 #include "column.hxx"
70 #include "cell.hxx"
71 #include "poolhelp.hxx"
72 #include "docpool.hxx"
73 #include "stlpool.hxx"
74 #include "stlsheet.hxx"
75 #include "docoptio.hxx"
76 #include "viewopti.hxx"
77 #include "scextopt.hxx"
78 #include "rechead.hxx"
79 #include "ddelink.hxx"
80 #include "scmatrix.hxx"
81 #include "arealink.hxx"
82 #include "dociter.hxx"
83 #include "patattr.hxx"
84 #include "hints.hxx"
85 #include "editutil.hxx"
86 #include "progress.hxx"
87 #include "document.hxx"
88 #include "chartlis.hxx"
89 #include "chartlock.hxx"
90 #include "refupdat.hxx"
91 #include "validat.hxx" // fuer HasMacroCalls
92 #include "markdata.hxx"
93 #include "scmod.hxx"
94 #include "printopt.hxx"
95 #include "externalrefmgr.hxx"
96 #include "globstr.hrc"
97 #include "sc.hrc"
98 #include "charthelper.hxx"
99 #include "macromgr.hxx"
101 #define GET_SCALEVALUE(set,id) ((const SfxUInt16Item&)(set.Get( id ))).GetValue()
103 // states for online spelling in the visible range (0 is set initially)
104 #define VSPL_START 0
105 #define VSPL_DONE 1
108 // STATIC DATA -----------------------------------------------------------
110 //------------------------------------------------------------------------
112 void ScDocument::ImplCreateOptions()
114 pDocOptions = new ScDocOptions();
115 pViewOptions = new ScViewOptions();
118 //------------------------------------------------------------------------
120 void ScDocument::ImplDeleteOptions()
122 delete pDocOptions;
123 delete pViewOptions;
124 delete pExtDocOptions;
127 //------------------------------------------------------------------------
129 SfxPrinter* ScDocument::GetPrinter(BOOL bCreateIfNotExist)
131 if ( !pPrinter && bCreateIfNotExist )
133 SfxItemSet* pSet =
134 new SfxItemSet( *xPoolHelper->GetDocPool(),
135 SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN,
136 SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC,
137 SID_PRINT_SELECTEDSHEET, SID_PRINT_SELECTEDSHEET,
138 SID_SCPRINTOPTIONS, SID_SCPRINTOPTIONS,
139 NULL );
141 SfxMiscCfg* pOffCfg = SFX_APP()->GetMiscConfig();
142 if ( pOffCfg )
144 USHORT nFlags = 0;
145 if ( pOffCfg->IsPaperOrientationWarning() )
146 nFlags |= SFX_PRINTER_CHG_ORIENTATION;
147 if ( pOffCfg->IsPaperSizeWarning() )
148 nFlags |= SFX_PRINTER_CHG_SIZE;
149 pSet->Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC, nFlags ) );
150 pSet->Put( SfxBoolItem( SID_PRINTER_NOTFOUND_WARN, pOffCfg->IsNotFoundWarning() ) );
153 pPrinter = new SfxPrinter( pSet );
154 pPrinter->SetMapMode( MAP_100TH_MM );
155 UpdateDrawPrinter();
156 pPrinter->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
159 return pPrinter;
162 //------------------------------------------------------------------------
164 void ScDocument::SetPrinter( SfxPrinter* pNewPrinter )
166 if ( pNewPrinter == pPrinter )
168 // #i6706# SetPrinter is called with the same printer again if
169 // the JobSetup has changed. In that case just call UpdateDrawPrinter
170 // (SetRefDevice for drawing layer) because of changed text sizes.
171 UpdateDrawPrinter();
173 else
175 SfxPrinter* pOld = pPrinter;
176 pPrinter = pNewPrinter;
177 UpdateDrawPrinter();
178 pPrinter->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
179 delete pOld;
181 InvalidateTextWidth(NULL, NULL, FALSE); // in both cases
184 //------------------------------------------------------------------------
186 void ScDocument::SetPrintOptions()
188 if ( !pPrinter ) GetPrinter(); // setzt pPrinter
189 DBG_ASSERT( pPrinter, "Error in printer creation :-/" );
191 if ( pPrinter )
193 SfxMiscCfg* pOffCfg = SFX_APP()->GetMiscConfig();
194 if ( pOffCfg )
196 SfxItemSet aOptSet( pPrinter->GetOptions() );
198 USHORT nFlags = 0;
199 if ( pOffCfg->IsPaperOrientationWarning() )
200 nFlags |= SFX_PRINTER_CHG_ORIENTATION;
201 if ( pOffCfg->IsPaperSizeWarning() )
202 nFlags |= SFX_PRINTER_CHG_SIZE;
203 aOptSet.Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC, nFlags ) );
204 aOptSet.Put( SfxBoolItem( SID_PRINTER_NOTFOUND_WARN, pOffCfg->IsNotFoundWarning() ) );
206 pPrinter->SetOptions( aOptSet );
211 //------------------------------------------------------------------------
213 VirtualDevice* ScDocument::GetVirtualDevice_100th_mm()
215 if (!pVirtualDevice_100th_mm)
217 // pVirtualDevice_100th_mm = new VirtualDevice;
218 // pVirtualDevice_100th_mm->SetMapMode( MAP_100TH_MM );
220 pVirtualDevice_100th_mm = new VirtualDevice( 1 );
221 pVirtualDevice_100th_mm->SetReferenceDevice(VirtualDevice::REFDEV_MODE_MSO1);
222 MapMode aMapMode( pVirtualDevice_100th_mm->GetMapMode() );
223 aMapMode.SetMapUnit( MAP_100TH_MM );
224 pVirtualDevice_100th_mm->SetMapMode( aMapMode );
226 return pVirtualDevice_100th_mm;
229 OutputDevice* ScDocument::GetRefDevice()
231 // Create printer like ref device, see Writer...
232 OutputDevice* pRefDevice = NULL;
233 if ( SC_MOD()->GetInputOptions().GetTextWysiwyg() )
234 pRefDevice = GetPrinter();
235 else
236 pRefDevice = GetVirtualDevice_100th_mm();
237 return pRefDevice;
240 //------------------------------------------------------------------------
242 void ScDocument::ModifyStyleSheet( SfxStyleSheetBase& rStyleSheet,
243 const SfxItemSet& rChanges )
245 SfxItemSet& rSet = rStyleSheet.GetItemSet();
247 switch ( rStyleSheet.GetFamily() )
249 case SFX_STYLE_FAMILY_PAGE:
251 const USHORT nOldScale = GET_SCALEVALUE(rSet,ATTR_PAGE_SCALE);
252 const USHORT nOldScaleToPages = GET_SCALEVALUE(rSet,ATTR_PAGE_SCALETOPAGES);
253 rSet.Put( rChanges );
254 const USHORT nNewScale = GET_SCALEVALUE(rSet,ATTR_PAGE_SCALE);
255 const USHORT nNewScaleToPages = GET_SCALEVALUE(rSet,ATTR_PAGE_SCALETOPAGES);
257 if ( (nOldScale != nNewScale) || (nOldScaleToPages != nNewScaleToPages) )
258 InvalidateTextWidth( rStyleSheet.GetName() );
260 if( SvtLanguageOptions().IsCTLFontEnabled() )
262 const SfxPoolItem *pItem = NULL;
263 if( rChanges.GetItemState(ATTR_WRITINGDIR, TRUE, &pItem ) == SFX_ITEM_SET )
264 ScChartHelper::DoUpdateAllCharts( this );
267 break;
269 case SFX_STYLE_FAMILY_PARA:
271 BOOL bNumFormatChanged;
272 if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
273 rSet, rChanges ) )
274 InvalidateTextWidth( NULL, NULL, bNumFormatChanged );
275 ULONG nOldFormat =
276 ((const SfxUInt32Item*)&rSet.Get(
277 ATTR_VALUE_FORMAT ))->GetValue();
278 ULONG nNewFormat =
279 ((const SfxUInt32Item*)&rChanges.Get(
280 ATTR_VALUE_FORMAT ))->GetValue();
281 LanguageType eNewLang, eOldLang;
282 eNewLang = eOldLang = LANGUAGE_DONTKNOW;
283 if ( nNewFormat != nOldFormat )
285 SvNumberFormatter* pFormatter = GetFormatTable();
286 eOldLang = pFormatter->GetEntry( nOldFormat )->GetLanguage();
287 eNewLang = pFormatter->GetEntry( nNewFormat )->GetLanguage();
290 // Bedeutung der Items in rChanges:
291 // Item gesetzt - Aenderung uebernehmen
292 // Dontcare - Default setzen
293 // Default - keine Aenderung
294 // ("keine Aenderung" geht nicht mit PutExtended, darum Schleife)
295 for (USHORT nWhich = ATTR_PATTERN_START; nWhich <= ATTR_PATTERN_END; nWhich++)
297 const SfxPoolItem* pItem;
298 SfxItemState eState = rChanges.GetItemState( nWhich, FALSE, &pItem );
299 if ( eState == SFX_ITEM_SET )
300 rSet.Put( *pItem );
301 else if ( eState == SFX_ITEM_DONTCARE )
302 rSet.ClearItem( nWhich );
303 // bei Default nichts
306 if ( eNewLang != eOldLang )
307 rSet.Put(
308 SvxLanguageItem( eNewLang, ATTR_LANGUAGE_FORMAT ) );
310 break;
311 default:
313 // added to avoid warnings
318 //------------------------------------------------------------------------
320 void ScDocument::CopyStdStylesFrom( ScDocument* pSrcDoc )
322 // #b5017505# number format exchange list has to be handled here, too
323 NumFmtMergeHandler aNumFmtMergeHdl(this, pSrcDoc);
324 xPoolHelper->GetStylePool()->CopyStdStylesFrom( pSrcDoc->xPoolHelper->GetStylePool() );
327 //------------------------------------------------------------------------
329 void ScDocument::InvalidateTextWidth( const String& rStyleName )
331 const SCTAB nCount = GetTableCount();
332 for ( SCTAB i=0; i<nCount && pTab[i]; i++ )
333 if ( pTab[i]->GetPageStyle() == rStyleName )
334 InvalidateTextWidth( i );
337 //------------------------------------------------------------------------
339 void ScDocument::InvalidateTextWidth( SCTAB nTab )
341 ScAddress aAdrFrom( 0, 0, nTab );
342 ScAddress aAdrTo ( MAXCOL, MAXROW, nTab );
343 InvalidateTextWidth( &aAdrFrom, &aAdrTo, FALSE );
346 //------------------------------------------------------------------------
348 BOOL ScDocument::IsPageStyleInUse( const String& rStrPageStyle, SCTAB* pInTab )
350 BOOL bInUse = FALSE;
351 const SCTAB nCount = GetTableCount();
352 SCTAB i;
354 for ( i = 0; !bInUse && i < nCount && pTab[i]; i++ )
355 bInUse = ( pTab[i]->GetPageStyle() == rStrPageStyle );
357 if ( pInTab )
358 *pInTab = i-1;
360 return bInUse;
363 //------------------------------------------------------------------------
365 BOOL ScDocument::RemovePageStyleInUse( const String& rStyle )
367 BOOL bWasInUse = FALSE;
368 const SCTAB nCount = GetTableCount();
370 for ( SCTAB i=0; i<nCount && pTab[i]; i++ )
371 if ( pTab[i]->GetPageStyle() == rStyle )
373 bWasInUse = TRUE;
374 pTab[i]->SetPageStyle( ScGlobal::GetRscString(STR_STYLENAME_STANDARD) );
377 return bWasInUse;
380 BOOL ScDocument::RenamePageStyleInUse( const String& rOld, const String& rNew )
382 BOOL bWasInUse = FALSE;
383 const SCTAB nCount = GetTableCount();
385 for ( SCTAB i=0; i<nCount && pTab[i]; i++ )
386 if ( pTab[i]->GetPageStyle() == rOld )
388 bWasInUse = TRUE;
389 pTab[i]->SetPageStyle( rNew );
392 return bWasInUse;
395 //------------------------------------------------------------------------
397 BYTE ScDocument::GetEditTextDirection(SCTAB nTab) const
399 EEHorizontalTextDirection eRet = EE_HTEXTDIR_DEFAULT;
401 String aStyleName = GetPageStyle( nTab );
402 SfxStyleSheetBase* pStyle = xPoolHelper->GetStylePool()->Find( aStyleName, SFX_STYLE_FAMILY_PAGE );
403 if ( pStyle )
405 SfxItemSet& rStyleSet = pStyle->GetItemSet();
406 SvxFrameDirection eDirection = (SvxFrameDirection)
407 ((const SvxFrameDirectionItem&)rStyleSet.Get( ATTR_WRITINGDIR )).GetValue();
409 if ( eDirection == FRMDIR_HORI_LEFT_TOP )
410 eRet = EE_HTEXTDIR_L2R;
411 else if ( eDirection == FRMDIR_HORI_RIGHT_TOP )
412 eRet = EE_HTEXTDIR_R2L;
413 // else (invalid for EditEngine): keep "default"
416 return sal::static_int_cast<BYTE>(eRet);
419 ScMacroManager* ScDocument::GetMacroManager()
421 if (!mpMacroMgr.get())
422 mpMacroMgr.reset(new ScMacroManager(this));
423 return mpMacroMgr.get();
426 //------------------------------------------------------------------------
428 void ScDocument::InvalidateTextWidth( const ScAddress* pAdrFrom, const ScAddress* pAdrTo,
429 BOOL bNumFormatChanged )
431 BOOL bBroadcast = (bNumFormatChanged && GetDocOptions().IsCalcAsShown() && !IsImportingXML() && !IsClipboard());
432 if ( pAdrFrom && !pAdrTo )
434 const SCTAB nTab = pAdrFrom->Tab();
436 if ( pTab[nTab] )
437 pTab[nTab]->InvalidateTextWidth( pAdrFrom, NULL, bNumFormatChanged, bBroadcast );
439 else
441 const SCTAB nTabStart = pAdrFrom ? pAdrFrom->Tab() : 0;
442 const SCTAB nTabEnd = pAdrTo ? pAdrTo->Tab() : MAXTAB;
444 for ( SCTAB nTab=nTabStart; nTab<=nTabEnd; nTab++ )
445 if ( pTab[nTab] )
446 pTab[nTab]->InvalidateTextWidth( pAdrFrom, pAdrTo, bNumFormatChanged, bBroadcast );
450 //------------------------------------------------------------------------
452 #define CALCMAX 1000 // Berechnungen
453 #define ABORT_EVENTS (INPUT_ANY & ~INPUT_TIMER & ~INPUT_OTHER)
455 BOOL ScDocument::IdleCalcTextWidth() // TRUE = demnaechst wieder versuchen
457 // #i75610# if a printer hasn't been set or created yet, don't create one for this
458 if ( bIdleDisabled || IsInLinkUpdate() || GetPrinter(FALSE) == NULL )
459 return FALSE;
460 bIdleDisabled = TRUE;
462 // ULONG nMs = 0;
463 // USHORT nIter = 0;
465 const ULONG nStart = Time::GetSystemTicks();
466 double nPPTX = 0.0;
467 double nPPTY = 0.0;
468 OutputDevice* pDev = NULL;
469 MapMode aOldMap;
470 ScStyleSheet* pStyle = NULL;
471 ScColumnIterator* pColIter = NULL;
472 ScTable* pTable = NULL;
473 ScColumn* pColumn = NULL;
474 ScBaseCell* pCell = NULL;
475 SCTAB nTab = aCurTextWidthCalcPos.Tab();
476 SCROW nRow = aCurTextWidthCalcPos.Row();
477 SCsCOL nCol = aCurTextWidthCalcPos.Col();
478 USHORT nRestart = 0;
479 USHORT nZoom = 0;
480 BOOL bNeedMore= FALSE;
482 if ( !ValidRow(nRow) )
483 nRow = 0, nCol--;
484 if ( nCol < 0 )
485 nCol = MAXCOL, nTab++;
486 if ( !ValidTab(nTab) || !pTab[nTab] )
487 nTab = 0;
489 // DBG_ERROR( String("Start = ") + String(nTab) + String(',') + String(nCol) + String(',') + String(nRow) );
491 // SearchMask/Family muss gemerkt werden,
492 // damit z.B. der Organizer nicht durcheinanderkommt, wenn zwischendurch eine
493 // Query-Box aufgemacht wird !!!
495 ScStyleSheetPool* pStylePool = xPoolHelper->GetStylePool();
496 USHORT nOldMask = pStylePool->GetSearchMask();
497 SfxStyleFamily eOldFam = pStylePool->GetSearchFamily();
499 pTable = pTab[nTab];
500 pStylePool->SetSearchMask( SFX_STYLE_FAMILY_PAGE, SFXSTYLEBIT_ALL );
501 pStyle = (ScStyleSheet*)pStylePool->Find( pTable->aPageStyle,
502 SFX_STYLE_FAMILY_PAGE );
504 DBG_ASSERT( pStyle, "Missing StyleSheet :-/" );
506 BOOL bProgress = FALSE;
507 if ( pStyle && 0 == GET_SCALEVALUE(pStyle->GetItemSet(),ATTR_PAGE_SCALETOPAGES) )
509 USHORT nCount = 0;
511 nZoom = GET_SCALEVALUE(pStyle->GetItemSet(),ATTR_PAGE_SCALE);
512 Fraction aZoomFract( nZoom, 100 );
513 pColumn = &pTable->aCol[nCol];
514 pColIter = new ScColumnIterator( pColumn, nRow, MAXROW );
516 while ( (nZoom > 0) && (nCount < CALCMAX) && (nRestart < 2) )
518 if ( pColIter->Next( nRow, pCell ) )
520 if ( TEXTWIDTH_DIRTY == pCell->GetTextWidth() )
522 if ( !pDev )
524 pDev = GetPrinter();
525 aOldMap = pDev->GetMapMode();
526 pDev->SetMapMode( MAP_PIXEL ); // wichtig fuer GetNeededSize
528 Point aPix1000 = pDev->LogicToPixel( Point(1000,1000), MAP_TWIP );
529 nPPTX = aPix1000.X() / 1000.0;
530 nPPTY = aPix1000.Y() / 1000.0;
532 if ( !bProgress && pCell->GetCellType() == CELLTYPE_FORMULA
533 && ((ScFormulaCell*)pCell)->GetDirty() )
535 ScProgress::CreateInterpretProgress( this, FALSE );
536 bProgress = TRUE;
539 // DBG_ERROR( String("t,c,r = ") + String(nTab) + String(',') + String(nCol) + String(',') + String(nRow) );
540 // DBG_ERROR( String("nOldWidth = ") + String(pCell->GetTextWidth()) );
542 USHORT nNewWidth = (USHORT)GetNeededSize( nCol, nRow, nTab,
543 pDev, nPPTX, nPPTY,
544 aZoomFract,aZoomFract, TRUE,
545 TRUE ); // bTotalSize
547 // DBG_ERROR( String("nNewWidth = ") + String(nNewWidth) );
549 pCell->SetTextWidth( nNewWidth );
551 bNeedMore = TRUE;
554 else
556 BOOL bNewTab = FALSE;
558 nRow = 0;
559 nCol--;
561 if ( nCol < 0 )
563 nCol = MAXCOL;
564 nTab++;
565 bNewTab = TRUE;
568 if ( !ValidTab(nTab) || !pTab[nTab] )
570 nTab = 0;
571 nRestart++;
572 bNewTab = TRUE;
575 if ( nRestart < 2 )
577 if ( bNewTab )
579 pTable = pTab[nTab];
580 pStyle = (ScStyleSheet*)pStylePool->Find( pTable->aPageStyle,
581 SFX_STYLE_FAMILY_PAGE );
583 if ( pStyle )
585 SfxItemSet& rSet = pStyle->GetItemSet();
586 if ( GET_SCALEVALUE( rSet, ATTR_PAGE_SCALETOPAGES ) == 0 )
587 nZoom = GET_SCALEVALUE(rSet, ATTR_PAGE_SCALE );
588 else
589 nZoom = 0;
591 else
593 DBG_ERROR( "Missing StyleSheet :-/" );
597 if ( nZoom > 0 )
599 delete pColIter;
601 pColumn = &pTable->aCol[nCol];
602 pColIter = new ScColumnIterator( pColumn, nRow, MAXROW );
604 else
605 nTab++; // Tabelle nicht mit absolutem Zoom -> naechste
609 // nIter = nCount;
611 nCount++;
613 // Idle Berechnung abbrechen, wenn Berechnungen laenger als
614 // 50ms dauern, oder nach 32 Berechnungen mal nachschauen, ob
615 // bestimmte Events anstehen, die Beachtung wuenschen:
617 // nMs = SysTicksToMs( GetSysTicks() - nStart );
619 if ( ( 50L < Time::GetSystemTicks() - nStart )
620 || ( !(nCount&31) && Application::AnyInput( ABORT_EVENTS ) ) )
621 nCount = CALCMAX;
624 else
625 nTab++; // Tabelle nicht mit absolutem Zoom -> naechste
627 if ( bProgress )
628 ScProgress::DeleteInterpretProgress();
630 delete pColIter;
632 // DBG_ERROR( String(nCount) + String(" End = ") + String(nTab) + String(',') + String(nCol) + String(',') + String(nRow) );
634 if (pDev)
635 pDev->SetMapMode(aOldMap);
637 aCurTextWidthCalcPos.SetTab( nTab );
638 aCurTextWidthCalcPos.SetRow( nRow );
639 aCurTextWidthCalcPos.SetCol( (SCCOL)nCol );
641 // DBG_ERROR( String(nMs) + String(" ms (") + String(nIter) + String(')') );
643 pStylePool->SetSearchMask( eOldFam, nOldMask );
644 bIdleDisabled = FALSE;
646 return bNeedMore;
649 //------------------------------------------------------------------------
651 class ScSpellStatus
653 public:
654 BOOL bModified;
656 ScSpellStatus() : bModified(FALSE) {};
658 DECL_LINK (EventHdl, EditStatus*);
661 IMPL_LINK( ScSpellStatus, EventHdl, EditStatus *, pStatus )
663 ULONG nStatus = pStatus->GetStatusWord();
664 if ( nStatus & EE_STAT_WRONGWORDCHANGED )
665 bModified = TRUE;
667 return 0;
670 // SPELL_MAXCELLS muss mindestens 256 sein, solange am Iterator keine
671 // Start-Spalte gesetzt werden kann
673 //! SPELL_MAXTEST fuer Timer und Idle unterschiedlich ???
675 // SPELL_MAXTEST now divided between visible and rest of document
677 #define SPELL_MAXTEST_VIS 1
678 #define SPELL_MAXTEST_ALL 3
679 #define SPELL_MAXCELLS 256
681 BOOL ScDocument::OnlineSpellInRange( const ScRange& rSpellRange, ScAddress& rSpellPos,
682 USHORT nMaxTest )
684 ScEditEngineDefaulter* pEngine = NULL; //! am Dokument speichern
685 SfxItemSet* pDefaults = NULL;
686 ScSpellStatus aStatus;
688 USHORT nCellCount = 0; // Zellen insgesamt
689 USHORT nTestCount = 0; // Aufrufe Spelling
690 BOOL bChanged = FALSE; // Aenderungen?
692 SCCOL nCol = rSpellRange.aStart.Col(); // iterator always starts on the left edge
693 SCROW nRow = rSpellPos.Row();
694 SCTAB nTab = rSpellPos.Tab();
695 if ( !pTab[nTab] ) // sheet deleted?
697 nTab = rSpellRange.aStart.Tab();
698 nRow = rSpellRange.aStart.Row();
699 if ( !pTab[nTab] )
701 // may happen for visible range
702 return FALSE;
705 ScHorizontalCellIterator aIter( this, nTab,
706 rSpellRange.aStart.Col(), nRow,
707 rSpellRange.aEnd.Col(), rSpellRange.aEnd.Row() );
708 ScBaseCell* pCell = aIter.GetNext( nCol, nRow );
709 // skip everything left of rSpellPos:
710 while ( pCell && nRow == rSpellPos.Row() && nCol < rSpellPos.Col() )
711 pCell = aIter.GetNext( nCol, nRow );
712 while ( pCell )
714 CellType eType = pCell->GetCellType();
715 if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT )
717 if (!pEngine)
719 // #71154# ScTabEditEngine is needed
720 // because MapMode must be set for some old documents
721 pEngine = new ScTabEditEngine( this );
722 pEngine->SetControlWord( pEngine->GetControlWord() |
723 ( EE_CNTRL_ONLINESPELLING | EE_CNTRL_ALLOWBIGOBJS ) );
724 pEngine->SetStatusEventHdl( LINK( &aStatus, ScSpellStatus, EventHdl ) );
725 // Delimiters hier wie in inputhdl.cxx !!!
726 pEngine->SetWordDelimiters(
727 ScEditUtil::ModifyDelimiters( pEngine->GetWordDelimiters() ) );
728 pDefaults = new SfxItemSet( pEngine->GetEmptyItemSet() );
730 com::sun::star::uno::Reference<com::sun::star::linguistic2::XSpellChecker1> xXSpellChecker1( LinguMgr::GetSpellChecker() );
732 pEngine->SetSpeller( xXSpellChecker1 );
735 const ScPatternAttr* pPattern = GetPattern( nCol, nRow, nTab );
736 pPattern->FillEditItemSet( pDefaults );
737 pEngine->SetDefaults( pDefaults, FALSE ); //! noetig ?
739 USHORT nCellLang = ((const SvxLanguageItem&)
740 pPattern->GetItem(ATTR_FONT_LANGUAGE)).GetValue();
741 if ( nCellLang == LANGUAGE_SYSTEM )
742 nCellLang = Application::GetSettings().GetLanguage(); // never use SYSTEM for spelling
743 pEngine->SetDefaultLanguage( nCellLang );
745 if ( eType == CELLTYPE_STRING )
747 String aText;
748 ((ScStringCell*)pCell)->GetString(aText);
749 pEngine->SetText( aText );
751 else
752 pEngine->SetText( *((ScEditCell*)pCell)->GetData() );
754 aStatus.bModified = FALSE;
755 pEngine->CompleteOnlineSpelling();
756 if ( aStatus.bModified ) // Fehler dazu oder weggekommen?
758 BOOL bNeedEdit = TRUE; // Test auf einfachen Text
759 if ( !pEngine->HasOnlineSpellErrors() )
761 ScEditAttrTester aTester( pEngine );
762 bNeedEdit = aTester.NeedsObject();
765 if ( bNeedEdit )
767 EditTextObject* pNewData = pEngine->CreateTextObject();
768 if ( eType == CELLTYPE_EDIT )
769 ((ScEditCell*)pCell)->SetData( pNewData,
770 pEngine->GetEditTextObjectPool() );
771 else
772 PutCell( nCol, nRow, nTab, new ScEditCell( pNewData,
773 this, pEngine->GetEditTextObjectPool() ) );
774 delete pNewData;
776 else // einfacher String
777 PutCell( nCol, nRow, nTab, new ScStringCell( pEngine->GetText() ) );
779 // Paint
780 if (pShell)
782 // #47751# Seitenvorschau ist davon nicht betroffen
783 // (sollte jedenfalls nicht)
784 ScPaintHint aHint( ScRange( nCol, nRow, nTab ), PAINT_GRID );
785 aHint.SetPrintFlag( FALSE );
786 pShell->Broadcast( aHint );
789 bChanged = TRUE;
792 if ( ++nTestCount >= nMaxTest ) // checked enough text?
793 break;
796 if ( ++nCellCount >= SPELL_MAXCELLS ) // seen enough cells?
797 break;
799 pCell = aIter.GetNext( nCol, nRow );
802 if ( pCell )
804 ++nCol; // continue after last cell
805 if ( nCol > rSpellRange.aEnd.Col() )
807 nCol = rSpellRange.aStart.Col();
808 ++nRow;
809 if ( nRow > rSpellRange.aEnd.Row() )
810 pCell = NULL;
814 if (!pCell) // end of range reached -> next sheet
816 ++nTab;
817 if ( nTab > rSpellRange.aEnd.Tab() || !pTab[nTab] )
818 nTab = rSpellRange.aStart.Tab();
819 nCol = rSpellRange.aStart.Col();
820 nRow = rSpellRange.aStart.Row();
822 nVisSpellState = VSPL_DONE; //! only if this is for the visible range
824 rSpellPos.Set( nCol, nRow, nTab );
826 delete pDefaults;
827 delete pEngine; // bevor aStatus out of scope geht
829 return bChanged;
833 BOOL ScDocument::ContinueOnlineSpelling()
835 if ( bIdleDisabled || !pDocOptions->IsAutoSpell() || (pShell && pShell->IsReadOnly()) )
836 return FALSE;
838 // #i48433# set bInsertingFromOtherDoc flag so there are no broadcasts when PutCell is called
839 // (same behavior as in RemoveAutoSpellObj: just transfer the broadcaster)
840 BOOL bOldInserting = IsInsertingFromOtherDoc();
841 SetInsertingFromOtherDoc( TRUE );
843 //! use one EditEngine for both calls
845 // #41504# first check visible range
846 BOOL bResult = OnlineSpellInRange( aVisSpellRange, aVisSpellPos, SPELL_MAXTEST_VIS );
848 // during first pass through visible range, always continue
849 if ( nVisSpellState == VSPL_START )
850 bResult = TRUE;
852 if (bResult)
854 // if errors found, continue there
855 OnlineSpellInRange( aVisSpellRange, aVisSpellPos, SPELL_MAXTEST_ALL );
857 else
859 // if nothing found there, continue with rest of document
860 ScRange aTotalRange( 0,0,0, MAXCOL,MAXROW,MAXTAB );
861 bResult = OnlineSpellInRange( aTotalRange, aOnlineSpellPos, SPELL_MAXTEST_ALL );
864 SetInsertingFromOtherDoc( bOldInserting );
866 return bResult;
870 void ScDocument::SetOnlineSpellPos( const ScAddress& rPos )
872 aOnlineSpellPos = rPos;
874 // skip visible area for aOnlineSpellPos
875 if ( aVisSpellRange.In( aOnlineSpellPos ) )
876 aOnlineSpellPos = aVisSpellRange.aEnd;
879 BOOL ScDocument::SetVisibleSpellRange( const ScRange& rNewRange )
881 BOOL bChange = ( aVisSpellRange != rNewRange );
882 if (bChange)
884 // continue spelling through visible range when scrolling down
885 BOOL bContDown = ( nVisSpellState == VSPL_START && rNewRange.In( aVisSpellPos ) &&
886 rNewRange.aStart.Row() > aVisSpellRange.aStart.Row() &&
887 rNewRange.aStart.Col() == aVisSpellRange.aStart.Col() &&
888 rNewRange.aEnd.Col() == aVisSpellRange.aEnd.Col() );
890 aVisSpellRange = rNewRange;
892 if ( !bContDown )
894 aVisSpellPos = aVisSpellRange.aStart;
895 nVisSpellState = VSPL_START;
898 // skip visible area for aOnlineSpellPos
899 if ( aVisSpellRange.In( aOnlineSpellPos ) )
900 aOnlineSpellPos = aVisSpellRange.aEnd;
902 return bChange;
905 void ScDocument::RemoveAutoSpellObj()
907 // alle Spelling-Informationen entfernen
909 for (SCTAB nTab=0; nTab<=MAXTAB && pTab[nTab]; nTab++)
910 pTab[nTab]->RemoveAutoSpellObj();
913 //------------------------------------------------------------------------
915 BOOL ScDocument::IdleCheckLinks() // TRUE = demnaechst wieder versuchen
917 BOOL bAnyLeft = FALSE;
919 if (pLinkManager)
921 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
922 USHORT nCount = rLinks.Count();
923 for (USHORT i=0; i<nCount; i++)
925 ::sfx2::SvBaseLink* pBase = *rLinks[i];
926 if (pBase->ISA(ScDdeLink))
928 ScDdeLink* pDdeLink = (ScDdeLink*)pBase;
929 if (pDdeLink->NeedsUpdate())
931 pDdeLink->TryUpdate();
932 if (pDdeLink->NeedsUpdate()) // war nix?
933 bAnyLeft = TRUE;
939 return bAnyLeft;
942 void ScDocument::SaveDdeLinks(SvStream& rStream) const
944 // bei 4.0-Export alle mit Modus != DEFAULT weglassen
945 BOOL bExport40 = ( rStream.GetVersion() <= SOFFICE_FILEFORMAT_40 );
947 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
948 USHORT nCount = rLinks.Count();
950 // erstmal zaehlen...
952 USHORT nDdeCount = 0;
953 USHORT i;
954 for (i=0; i<nCount; i++)
956 ::sfx2::SvBaseLink* pBase = *rLinks[i];
957 if (pBase->ISA(ScDdeLink))
958 if ( !bExport40 || ((ScDdeLink*)pBase)->GetMode() == SC_DDE_DEFAULT )
959 ++nDdeCount;
962 // Header
964 ScMultipleWriteHeader aHdr( rStream );
965 rStream << nDdeCount;
967 // Links speichern
969 for (i=0; i<nCount; i++)
971 ::sfx2::SvBaseLink* pBase = *rLinks[i];
972 if (pBase->ISA(ScDdeLink))
974 ScDdeLink* pLink = (ScDdeLink*)pBase;
975 if ( !bExport40 || pLink->GetMode() == SC_DDE_DEFAULT )
976 pLink->Store( rStream, aHdr );
981 void ScDocument::LoadDdeLinks(SvStream& rStream)
983 ScMultipleReadHeader aHdr( rStream );
985 USHORT nCount;
986 rStream >> nCount;
987 for (USHORT i=0; i<nCount; i++)
989 ScDdeLink* pLink = new ScDdeLink( this, rStream, aHdr );
990 pLinkManager->InsertDDELink( pLink,
991 pLink->GetAppl(), pLink->GetTopic(), pLink->GetItem() );
995 BOOL ScDocument::HasDdeLinks() const
997 if (pLinkManager) // Clipboard z.B. hat keinen LinkManager
999 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1000 USHORT nCount = rLinks.Count();
1001 for (USHORT i=0; i<nCount; i++)
1002 if ((*rLinks[i])->ISA(ScDdeLink))
1003 return TRUE;
1006 return FALSE;
1009 void ScDocument::SetInLinkUpdate(BOOL bSet)
1011 // called from TableLink and AreaLink
1013 DBG_ASSERT( bInLinkUpdate != bSet, "SetInLinkUpdate twice" );
1014 bInLinkUpdate = bSet;
1017 BOOL ScDocument::IsInLinkUpdate() const
1019 return bInLinkUpdate || IsInDdeLinkUpdate();
1022 void ScDocument::UpdateExternalRefLinks()
1024 if (!pLinkManager)
1025 return;
1027 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1028 USHORT nCount = rLinks.Count();
1030 bool bAny = false;
1031 for (USHORT i = 0; i < nCount; ++i)
1033 ::sfx2::SvBaseLink* pBase = *rLinks[i];
1034 ScExternalRefLink* pRefLink = dynamic_cast<ScExternalRefLink*>(pBase);
1035 if (pRefLink)
1037 pRefLink->Update();
1038 bAny = true;
1041 if (bAny)
1043 TrackFormulas();
1044 pShell->Broadcast( SfxSimpleHint(FID_DATACHANGED) );
1045 ResetChanged( ScRange(0, 0, 0, MAXCOL, MAXROW, MAXTAB) );
1047 // #i101960# set document modified, as in TrackTimeHdl for DDE links
1048 if (!pShell->IsModified())
1050 pShell->SetModified( TRUE );
1051 SfxBindings* pBindings = GetViewBindings();
1052 if (pBindings)
1054 pBindings->Invalidate( SID_SAVEDOC );
1055 pBindings->Invalidate( SID_DOC_MODIFIED );
1061 void ScDocument::UpdateDdeLinks()
1063 if (pLinkManager)
1065 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1066 USHORT nCount = rLinks.Count();
1067 USHORT i;
1069 // #49226# falls das Updaten laenger dauert, erstmal alle Werte
1070 // zuruecksetzen, damit nichts altes (falsches) stehen bleibt
1071 BOOL bAny = FALSE;
1072 for (i=0; i<nCount; i++)
1074 ::sfx2::SvBaseLink* pBase = *rLinks[i];
1075 if (pBase->ISA(ScDdeLink))
1077 ((ScDdeLink*)pBase)->ResetValue();
1078 bAny = TRUE;
1081 if (bAny)
1083 // Formeln berechnen und painten wie im TrackTimeHdl
1084 TrackFormulas();
1085 pShell->Broadcast( SfxSimpleHint( FID_DATACHANGED ) );
1086 ResetChanged( ScRange(0,0,0,MAXCOL,MAXROW,MAXTAB) );
1088 // wenn FID_DATACHANGED irgendwann mal asynchron werden sollte
1089 // (z.B. mit Invalidate am Window), muss hier ein Update erzwungen werden.
1092 // nun wirklich updaten...
1093 for (i=0; i<nCount; i++)
1095 ::sfx2::SvBaseLink* pBase = *rLinks[i];
1096 if (pBase->ISA(ScDdeLink))
1097 ((ScDdeLink*)pBase)->TryUpdate(); // bei DDE-Links TryUpdate statt Update
1102 BOOL ScDocument::UpdateDdeLink( const String& rAppl, const String& rTopic, const String& rItem )
1104 // fuer refresh() per StarOne Api
1105 // ResetValue() fuer einzelnen Link nicht noetig
1106 //! wenn's mal alles asynchron wird, aber auch hier
1108 BOOL bFound = FALSE;
1109 if (pLinkManager)
1111 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1112 USHORT nCount = rLinks.Count();
1113 for (USHORT i=0; i<nCount; i++)
1115 ::sfx2::SvBaseLink* pBase = *rLinks[i];
1116 if (pBase->ISA(ScDdeLink))
1118 ScDdeLink* pDdeLink = (ScDdeLink*)pBase;
1119 if ( pDdeLink->GetAppl() == rAppl &&
1120 pDdeLink->GetTopic() == rTopic &&
1121 pDdeLink->GetItem() == rItem )
1123 pDdeLink->TryUpdate();
1124 bFound = TRUE; // koennen theoretisch mehrere sein (Mode), darum weitersuchen
1129 return bFound;
1132 void ScDocument::DisconnectDdeLinks()
1134 if (pLinkManager)
1136 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1137 USHORT nCount = rLinks.Count();
1138 for (USHORT i=0; i<nCount; i++)
1140 ::sfx2::SvBaseLink* pBase = *rLinks[i];
1141 if (pBase->ISA(ScDdeLink))
1142 pBase->Disconnect(); // bleibt im LinkManager eingetragen
1147 void ScDocument::CopyDdeLinks( ScDocument* pDestDoc ) const
1149 if (bIsClip) // aus Stream erzeugen
1151 if (pClipData)
1153 pClipData->Seek(0);
1154 pDestDoc->LoadDdeLinks(*pClipData);
1157 else if (pLinkManager) // Links direkt kopieren
1159 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1160 USHORT nCount = rLinks.Count();
1161 for (USHORT i=0; i<nCount; i++)
1163 ::sfx2::SvBaseLink* pBase = *rLinks[i];
1164 if (pBase->ISA(ScDdeLink))
1166 ScDdeLink* pNew = new ScDdeLink( pDestDoc, *(ScDdeLink*)pBase );
1168 pDestDoc->pLinkManager->InsertDDELink( pNew,
1169 pNew->GetAppl(), pNew->GetTopic(), pNew->GetItem() );
1175 USHORT ScDocument::GetDdeLinkCount() const
1177 USHORT nDdeCount = 0;
1178 if (pLinkManager)
1180 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1181 USHORT nCount = rLinks.Count();
1182 for (USHORT i=0; i<nCount; i++)
1183 if ((*rLinks[i])->ISA(ScDdeLink))
1184 ++nDdeCount;
1186 return nDdeCount;
1189 // ----------------------------------------------------------------------------
1191 namespace {
1193 /** Tries to find the specified DDE link.
1194 @param pnDdePos (out-param) if not 0, the index of the DDE link is returned here
1195 (does not include other links from link manager).
1196 @return The DDE link, if it exists, otherwise 0. */
1197 ScDdeLink* lclGetDdeLink(
1198 const SvxLinkManager* pLinkManager,
1199 const String& rAppl, const String& rTopic, const String& rItem, BYTE nMode,
1200 USHORT* pnDdePos = NULL )
1202 if( pLinkManager )
1204 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1205 USHORT nCount = rLinks.Count();
1206 if( pnDdePos ) *pnDdePos = 0;
1207 for( USHORT nIndex = 0; nIndex < nCount; ++nIndex )
1209 ::sfx2::SvBaseLink* pLink = *rLinks[ nIndex ];
1210 if( ScDdeLink* pDdeLink = PTR_CAST( ScDdeLink, pLink ) )
1212 if( (pDdeLink->GetAppl() == rAppl) &&
1213 (pDdeLink->GetTopic() == rTopic) &&
1214 (pDdeLink->GetItem() == rItem) &&
1215 ((nMode == SC_DDE_IGNOREMODE) || (nMode == pDdeLink->GetMode())) )
1216 return pDdeLink;
1217 if( pnDdePos ) ++*pnDdePos;
1221 return NULL;
1224 /** Returns a pointer to the specified DDE link.
1225 @param nDdePos Index of the DDE link (does not include other links from link manager).
1226 @return The DDE link, if it exists, otherwise 0. */
1227 ScDdeLink* lclGetDdeLink( const SvxLinkManager* pLinkManager, USHORT nDdePos )
1229 if( pLinkManager )
1231 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1232 USHORT nCount = rLinks.Count();
1233 USHORT nDdeIndex = 0; // counts only the DDE links
1234 for( USHORT nIndex = 0; nIndex < nCount; ++nIndex )
1236 ::sfx2::SvBaseLink* pLink = *rLinks[ nIndex ];
1237 if( ScDdeLink* pDdeLink = PTR_CAST( ScDdeLink, pLink ) )
1239 if( nDdeIndex == nDdePos )
1240 return pDdeLink;
1241 ++nDdeIndex;
1245 return NULL;
1248 } // namespace
1250 // ----------------------------------------------------------------------------
1252 bool ScDocument::FindDdeLink( const String& rAppl, const String& rTopic, const String& rItem, BYTE nMode, USHORT& rnDdePos )
1254 return lclGetDdeLink( pLinkManager, rAppl, rTopic, rItem, nMode, &rnDdePos ) != NULL;
1257 bool ScDocument::GetDdeLinkData( USHORT nDdePos, String& rAppl, String& rTopic, String& rItem ) const
1259 if( const ScDdeLink* pDdeLink = lclGetDdeLink( pLinkManager, nDdePos ) )
1261 rAppl = pDdeLink->GetAppl();
1262 rTopic = pDdeLink->GetTopic();
1263 rItem = pDdeLink->GetItem();
1264 return true;
1266 return false;
1269 bool ScDocument::GetDdeLinkMode( USHORT nDdePos, BYTE& rnMode ) const
1271 if( const ScDdeLink* pDdeLink = lclGetDdeLink( pLinkManager, nDdePos ) )
1273 rnMode = pDdeLink->GetMode();
1274 return true;
1276 return false;
1279 const ScMatrix* ScDocument::GetDdeLinkResultMatrix( USHORT nDdePos ) const
1281 const ScDdeLink* pDdeLink = lclGetDdeLink( pLinkManager, nDdePos );
1282 return pDdeLink ? pDdeLink->GetResult() : NULL;
1285 bool ScDocument::CreateDdeLink( const String& rAppl, const String& rTopic, const String& rItem, BYTE nMode, ScMatrix* pResults )
1287 /* Create a DDE link without updating it (i.e. for Excel import), to prevent
1288 unwanted connections. First try to find existing link. Set result array
1289 on existing and new links. */
1290 //! store DDE links additionally at document (for efficiency)?
1291 DBG_ASSERT( nMode != SC_DDE_IGNOREMODE, "ScDocument::CreateDdeLink - SC_DDE_IGNOREMODE not allowed here" );
1292 if( pLinkManager && (nMode != SC_DDE_IGNOREMODE) )
1294 ScDdeLink* pDdeLink = lclGetDdeLink( pLinkManager, rAppl, rTopic, rItem, nMode );
1295 if( !pDdeLink )
1297 // create a new DDE link, but without TryUpdate
1298 pDdeLink = new ScDdeLink( this, rAppl, rTopic, rItem, nMode );
1299 pLinkManager->InsertDDELink( pDdeLink, rAppl, rTopic, rItem );
1302 // insert link results
1303 if( pResults )
1304 pDdeLink->SetResult( pResults );
1306 return true;
1308 return false;
1311 bool ScDocument::SetDdeLinkResultMatrix( USHORT nDdePos, ScMatrix* pResults )
1313 if( ScDdeLink* pDdeLink = lclGetDdeLink( pLinkManager, nDdePos ) )
1315 pDdeLink->SetResult( pResults );
1316 return true;
1318 return false;
1321 //------------------------------------------------------------------------
1323 BOOL ScDocument::HasAreaLinks() const
1325 if (pLinkManager) // Clipboard z.B. hat keinen LinkManager
1327 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1328 USHORT nCount = rLinks.Count();
1329 for (USHORT i=0; i<nCount; i++)
1330 if ((*rLinks[i])->ISA(ScAreaLink))
1331 return TRUE;
1334 return FALSE;
1337 void ScDocument::UpdateAreaLinks()
1339 if (pLinkManager)
1341 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1342 USHORT nCount = rLinks.Count();
1343 for (USHORT i=0; i<nCount; i++)
1345 ::sfx2::SvBaseLink* pBase = *rLinks[i];
1346 if (pBase->ISA(ScAreaLink))
1347 pBase->Update();
1352 void ScDocument::DeleteAreaLinksOnTab( SCTAB nTab )
1354 if (pLinkManager)
1356 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1357 USHORT nPos = 0;
1358 while ( nPos < rLinks.Count() )
1360 const ::sfx2::SvBaseLink* pBase = *rLinks[nPos];
1361 if ( pBase->ISA(ScAreaLink) &&
1362 static_cast<const ScAreaLink*>(pBase)->GetDestArea().aStart.Tab() == nTab )
1363 pLinkManager->Remove( nPos );
1364 else
1365 ++nPos;
1370 void ScDocument::UpdateRefAreaLinks( UpdateRefMode eUpdateRefMode,
1371 const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
1373 if (pLinkManager)
1375 bool bAnyUpdate = false;
1377 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1378 USHORT nCount = rLinks.Count();
1379 for (USHORT i=0; i<nCount; i++)
1381 ::sfx2::SvBaseLink* pBase = *rLinks[i];
1382 if (pBase->ISA(ScAreaLink))
1384 ScAreaLink* pLink = (ScAreaLink*) pBase;
1385 ScRange aOutRange = pLink->GetDestArea();
1387 SCCOL nCol1 = aOutRange.aStart.Col();
1388 SCROW nRow1 = aOutRange.aStart.Row();
1389 SCTAB nTab1 = aOutRange.aStart.Tab();
1390 SCCOL nCol2 = aOutRange.aEnd.Col();
1391 SCROW nRow2 = aOutRange.aEnd.Row();
1392 SCTAB nTab2 = aOutRange.aEnd.Tab();
1394 ScRefUpdateRes eRes =
1395 ScRefUpdate::Update( this, eUpdateRefMode,
1396 rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
1397 rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(), nDx, nDy, nDz,
1398 nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
1399 if ( eRes != UR_NOTHING )
1401 pLink->SetDestArea( ScRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ) );
1402 bAnyUpdate = true;
1407 if ( bAnyUpdate )
1409 // #i52120# Look for duplicates (after updating all positions).
1410 // If several links start at the same cell, the one with the lower index is removed
1411 // (file format specifies only one link definition for a cell).
1413 USHORT nFirstIndex = 0;
1414 while ( nFirstIndex < nCount )
1416 bool bFound = false;
1417 ::sfx2::SvBaseLink* pFirst = *rLinks[nFirstIndex];
1418 if ( pFirst->ISA(ScAreaLink) )
1420 ScAddress aFirstPos = static_cast<ScAreaLink*>(pFirst)->GetDestArea().aStart;
1421 for ( USHORT nSecondIndex = nFirstIndex + 1; nSecondIndex < nCount && !bFound; ++nSecondIndex )
1423 ::sfx2::SvBaseLink* pSecond = *rLinks[nSecondIndex];
1424 if ( pSecond->ISA(ScAreaLink) &&
1425 static_cast<ScAreaLink*>(pSecond)->GetDestArea().aStart == aFirstPos )
1427 // remove the first link, exit the inner loop, don't increment nFirstIndex
1428 pLinkManager->Remove( pFirst );
1429 nCount = rLinks.Count();
1430 bFound = true;
1434 if (!bFound)
1435 ++nFirstIndex;
1441 //------------------------------------------------------------------------
1443 // TimerDelays etc.
1444 void ScDocument::KeyInput( const KeyEvent& )
1446 if ( pChartListenerCollection->GetCount() )
1447 pChartListenerCollection->StartTimer();
1448 if( apTemporaryChartLock.get() )
1449 apTemporaryChartLock->StartOrContinueLocking();
1452 // ----------------------------------------------------------------------------
1454 BOOL ScDocument::CheckMacroWarn()
1456 // The check for macro configuration, macro warning and disabling is now handled
1457 // in SfxObjectShell::AdjustMacroMode, called by SfxObjectShell::CallBasic.
1459 return TRUE;
1462 //------------------------------------------------------------------------
1464 SfxBindings* ScDocument::GetViewBindings()
1466 // used to invalidate slots after changes to this document
1468 if ( !pShell )
1469 return NULL; // no ObjShell -> no view
1471 // first check current view
1472 SfxViewFrame* pViewFrame = SfxViewFrame::Current();
1473 if ( pViewFrame && pViewFrame->GetObjectShell() != pShell ) // wrong document?
1474 pViewFrame = NULL;
1476 // otherwise use first view for this doc
1477 if ( !pViewFrame )
1478 pViewFrame = SfxViewFrame::GetFirst( pShell );
1480 if (pViewFrame)
1481 return &pViewFrame->GetBindings();
1482 else
1483 return NULL;
1486 //------------------------------------------------------------------------
1488 void lcl_TransliterateEditEngine( ScEditEngineDefaulter& rEngine,
1489 utl::TransliterationWrapper& rTranslitarationWrapper,
1490 BOOL bConsiderLanguage, ScDocument* pDoc )
1492 //! should use TransliterateText method of EditEngine instead, when available!
1494 sal_uInt16 nLanguage = LANGUAGE_SYSTEM;
1496 USHORT nParCount = rEngine.GetParagraphCount();
1497 for (USHORT nPar=0; nPar<nParCount; nPar++)
1499 SvUShorts aPortions;
1500 rEngine.GetPortions( (USHORT)nPar, aPortions );
1502 for ( USHORT nPos = aPortions.Count(); nPos; )
1504 --nPos;
1505 USHORT nEnd = aPortions.GetObject( nPos );
1506 USHORT nStart = nPos ? aPortions.GetObject( nPos - 1 ) : 0;
1508 ESelection aSel( nPar, nStart, nPar, nEnd );
1509 String aOldStr = rEngine.GetText( aSel );
1510 SfxItemSet aAttr = rEngine.GetAttribs( aSel );
1512 if ( aAttr.GetItemState( EE_FEATURE_FIELD ) != SFX_ITEM_ON ) // fields are not touched
1514 if ( bConsiderLanguage )
1516 BYTE nScript = pDoc->GetStringScriptType( aOldStr );
1517 USHORT nWhich = ( nScript == SCRIPTTYPE_ASIAN ) ? EE_CHAR_LANGUAGE_CJK :
1518 ( ( nScript == SCRIPTTYPE_COMPLEX ) ? EE_CHAR_LANGUAGE_CTL :
1519 EE_CHAR_LANGUAGE );
1520 nLanguage = ((const SvxLanguageItem&)aAttr.Get(nWhich)).GetValue();
1523 com::sun::star::uno::Sequence<sal_Int32> aOffsets;
1524 String aNewStr = rTranslitarationWrapper.transliterate( aOldStr, nLanguage, 0, aOldStr.Len(), &aOffsets );
1526 if ( aNewStr != aOldStr )
1528 // replace string, keep attributes
1530 rEngine.QuickInsertText( aNewStr, aSel );
1531 aSel.nEndPos = aSel.nStartPos + aNewStr.Len();
1532 rEngine.QuickSetAttribs( aAttr, aSel );
1539 void ScDocument::TransliterateText( const ScMarkData& rMultiMark, sal_Int32 nType )
1541 DBG_ASSERT( rMultiMark.IsMultiMarked(), "TransliterateText: no selection" );
1543 utl::TransliterationWrapper aTranslitarationWrapper( xServiceManager, nType );
1544 BOOL bConsiderLanguage = aTranslitarationWrapper.needLanguageForTheMode();
1545 sal_uInt16 nLanguage = LANGUAGE_SYSTEM;
1547 ScEditEngineDefaulter* pEngine = NULL; // not using pEditEngine member because of defaults
1549 SCTAB nCount = GetTableCount();
1550 for (SCTAB nTab = 0; nTab < nCount; nTab++)
1551 if ( pTab[nTab] && rMultiMark.GetTableSelect(nTab) )
1553 SCCOL nCol = 0;
1554 SCROW nRow = 0;
1556 BOOL bFound = rMultiMark.IsCellMarked( nCol, nRow );
1557 if (!bFound)
1558 bFound = GetNextMarkedCell( nCol, nRow, nTab, rMultiMark );
1560 while (bFound)
1562 const ScBaseCell* pCell = GetCell( ScAddress( nCol, nRow, nTab ) );
1563 CellType eType = pCell ? pCell->GetCellType() : CELLTYPE_NONE;
1565 if ( eType == CELLTYPE_STRING )
1567 String aOldStr;
1568 ((const ScStringCell*)pCell)->GetString(aOldStr);
1569 xub_StrLen nOldLen = aOldStr.Len();
1571 if ( bConsiderLanguage )
1573 BYTE nScript = GetStringScriptType( aOldStr ); //! cell script type?
1574 USHORT nWhich = ( nScript == SCRIPTTYPE_ASIAN ) ? ATTR_CJK_FONT_LANGUAGE :
1575 ( ( nScript == SCRIPTTYPE_COMPLEX ) ? ATTR_CTL_FONT_LANGUAGE :
1576 ATTR_FONT_LANGUAGE );
1577 nLanguage = ((const SvxLanguageItem*)GetAttr( nCol, nRow, nTab, nWhich ))->GetValue();
1580 com::sun::star::uno::Sequence<sal_Int32> aOffsets;
1581 String aNewStr = aTranslitarationWrapper.transliterate( aOldStr, nLanguage, 0, nOldLen, &aOffsets );
1583 if ( aNewStr != aOldStr )
1584 PutCell( nCol, nRow, nTab, new ScStringCell( aNewStr ) );
1586 else if ( eType == CELLTYPE_EDIT )
1588 if (!pEngine)
1589 pEngine = new ScFieldEditEngine( GetEnginePool(), GetEditPool() );
1591 // defaults from cell attributes must be set so right language is used
1592 const ScPatternAttr* pPattern = GetPattern( nCol, nRow, nTab );
1593 SfxItemSet* pDefaults = new SfxItemSet( pEngine->GetEmptyItemSet() );
1594 pPattern->FillEditItemSet( pDefaults );
1595 pEngine->SetDefaults( pDefaults, TRUE );
1597 const EditTextObject* pData = ((const ScEditCell*)pCell)->GetData();
1598 pEngine->SetText( *pData );
1600 pEngine->ClearModifyFlag();
1602 lcl_TransliterateEditEngine( *pEngine, aTranslitarationWrapper, bConsiderLanguage, this );
1604 if ( pEngine->IsModified() )
1606 ScEditAttrTester aTester( pEngine );
1607 if ( aTester.NeedsObject() )
1609 // remove defaults (paragraph attributes) before creating text object
1610 SfxItemSet* pEmpty = new SfxItemSet( pEngine->GetEmptyItemSet() );
1611 pEngine->SetDefaults( pEmpty, TRUE );
1613 EditTextObject* pNewData = pEngine->CreateTextObject();
1614 PutCell( nCol, nRow, nTab,
1615 new ScEditCell( pNewData, this, pEngine->GetEditTextObjectPool() ) );
1616 delete pNewData;
1618 else
1620 String aNewStr = pEngine->GetText();
1621 PutCell( nCol, nRow, nTab, new ScStringCell( aNewStr ) );
1626 bFound = GetNextMarkedCell( nCol, nRow, nTab, rMultiMark );
1630 delete pEngine;