Files
libreoffice/sc/source/core/data/documen8.cxx

1698 lines
56 KiB
C++
Raw Normal View History

2000-09-18 23:16:46 +00:00
/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
2000-09-18 23:16:46 +00:00
*
* $RCSfile: documen8.cxx,v $
2000-09-18 23:16:46 +00:00
*
* $Revision: 1.40 $
2000-09-18 23:16:46 +00:00
*
* last change: $Author: hr $ $Date: 2005-09-28 11:31:22 $
2000-09-18 23:16:46 +00:00
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
2000-09-18 23:16:46 +00:00
*
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2005 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
2000-09-18 23:16:46 +00:00
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
2000-09-18 23:16:46 +00:00
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
2000-09-18 23:16:46 +00:00
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
2000-09-18 23:16:46 +00:00
*
************************************************************************/
#ifdef PCH
#include "core_pch.hxx"
#endif
#pragma hdrstop
#define _ZFORLIST_DECLARE_TABLE
2000-09-18 23:16:46 +00:00
#include "scitems.hxx"
#include <svx/eeitem.hxx>
#define ITEMID_FIELD EE_FEATURE_FIELD
2000-09-18 23:16:46 +00:00
#include <tools/string.hxx>
#include <svx/editobj.hxx>
#include <svx/editstat.hxx>
#include <svx/frmdiritem.hxx>
2000-09-18 23:16:46 +00:00
#include <svx/langitem.hxx>
#include <svx/linkmgr.hxx>
2001-03-26 18:26:30 +00:00
#include <svx/scripttypeitem.hxx>
#include <svx/unolingu.hxx>
2000-09-18 23:16:46 +00:00
#include <sfx2/objsh.hxx>
#include <sfx2/printer.hxx>
2000-09-22 17:57:10 +00:00
#include <sfx2/viewfrm.hxx>
2000-09-18 23:16:46 +00:00
#include <sfx2/viewsh.hxx>
#include <svtools/flagitem.hxx>
#include <svtools/intitem.hxx>
2001-03-27 12:48:15 +00:00
#define _SVSTDARR_USHORTS
#include <svtools/svstdarr.hxx>
2000-09-18 23:16:46 +00:00
#include <svtools/zforlist.hxx>
#include <svtools/zformat.hxx>
#include <svtools/misccfg.hxx>
#include <sfx2/app.hxx>
2001-03-26 18:26:30 +00:00
#include <unotools/transliterationwrapper.hxx>
2001-12-12 18:00:03 +00:00
#include <svtools/securityoptions.hxx>
2000-09-18 23:16:46 +00:00
#include <vcl/msgbox.hxx>
#include "global.hxx"
#include "table.hxx"
#include "column.hxx"
#include "cell.hxx"
#include "poolhelp.hxx"
2000-09-18 23:16:46 +00:00
#include "docpool.hxx"
#include "stlpool.hxx"
#include "stlsheet.hxx"
#include "docoptio.hxx"
#include "viewopti.hxx"
#include "scextopt.hxx"
#include "rechead.hxx"
#include "ddelink.hxx"
#include "scmatrix.hxx"
2000-09-18 23:16:46 +00:00
#include "arealink.hxx"
#include "dociter.hxx"
#include "patattr.hxx"
#include "hints.hxx"
#include "editutil.hxx"
#include "progress.hxx"
#include "document.hxx"
#include "chartlis.hxx"
2000-10-30 10:33:41 +00:00
#include "refupdat.hxx"
2000-09-18 23:16:46 +00:00
#include "validat.hxx" // fuer HasMacroCalls
2001-03-26 18:26:30 +00:00
#include "markdata.hxx"
#include "scmod.hxx"
2000-09-18 23:16:46 +00:00
#include "globstr.hrc"
#include "sc.hrc"
#define GET_SCALEVALUE(set,id) ((const SfxUInt16Item&)(set.Get( id ))).GetValue()
// states for online spelling in the visible range (0 is set initially)
#define VSPL_START 0
#define VSPL_DONE 1
// STATIC DATA -----------------------------------------------------------
//------------------------------------------------------------------------
void ScDocument::ImplLoadDocOptions( SvStream& rStream )
{
USHORT d,m,y;
DBG_ASSERT( pDocOptions, "No DocOptions to load! :-(" );
pDocOptions->Load( rStream );
if ( pDocOptions->GetStdPrecision() > 20 ) //!!! ist 20 als Maximum konstant ???
{
DBG_ERROR( "Document options corrupted. Setting to defaults." );
pDocOptions->ResetDocOptions();
}
pDocOptions->GetDate( d,m,y );
SvNumberFormatter* pFormatter = xPoolHelper->GetFormTable();
pFormatter->ChangeNullDate( d,m,y );
pFormatter->ChangeStandardPrec( pDocOptions->GetStdPrecision() );
pFormatter->SetYear2000( pDocOptions->GetYear2000() );
2000-09-18 23:16:46 +00:00
}
//------------------------------------------------------------------------
void ScDocument::ImplLoadViewOptions( SvStream& rStream )
{
DBG_ASSERT( pViewOptions, "No ViewOptions to load! :-(" );
rStream >> *pViewOptions;
}
//------------------------------------------------------------------------
void ScDocument::ImplSaveDocOptions( SvStream& rStream ) const
{
DBG_ASSERT( pDocOptions, "No DocOptions to save! :-(" );
pDocOptions->Save( rStream );
}
//------------------------------------------------------------------------
void ScDocument::ImplSaveViewOptions( SvStream& rStream ) const
{
DBG_ASSERT( pViewOptions, "No ViewOptions to save! :-(" );
rStream << *pViewOptions;
}
//------------------------------------------------------------------------
void ScDocument::ImplCreateOptions()
{
pDocOptions = new ScDocOptions();
pViewOptions = new ScViewOptions();
}
//------------------------------------------------------------------------
void ScDocument::ImplDeleteOptions()
{
delete pDocOptions;
delete pViewOptions;
delete pExtDocOptions;
}
//------------------------------------------------------------------------
SfxPrinter* ScDocument::GetPrinter()
{
if ( !pPrinter )
{
SfxItemSet* pSet =
new SfxItemSet( *xPoolHelper->GetDocPool(),
2000-09-18 23:16:46 +00:00
SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN,
SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC,
2001-05-29 18:46:58 +00:00
SID_SCPRINTOPTIONS, SID_SCPRINTOPTIONS,
2000-09-18 23:16:46 +00:00
NULL );
2001-03-02 14:59:05 +00:00
SfxMiscCfg* pOffCfg = SFX_APP()->GetMiscConfig();
2000-09-18 23:16:46 +00:00
if ( pOffCfg )
{
USHORT nFlags = 0;
2001-03-02 14:59:05 +00:00
if ( pOffCfg->IsPaperOrientationWarning() )
2000-09-18 23:16:46 +00:00
nFlags |= SFX_PRINTER_CHG_ORIENTATION;
if ( pOffCfg->IsPaperSizeWarning() )
nFlags |= SFX_PRINTER_CHG_SIZE;
pSet->Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC, nFlags ) );
pSet->Put( SfxBoolItem( SID_PRINTER_NOTFOUND_WARN, pOffCfg->IsNotFoundWarning() ) );
}
pPrinter = new SfxPrinter( pSet );
UpdateDrawPrinter();
pPrinter->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
2000-09-18 23:16:46 +00:00
}
return pPrinter;
}
//------------------------------------------------------------------------
void ScDocument::SetPrinter( SfxPrinter* pNewPrinter )
{
if ( pNewPrinter == pPrinter )
{
// #i6706# SetPrinter is called with the same printer again if
// the JobSetup has changed. In that case just call UpdateDrawPrinter
// (SetRefDevice for drawing layer) because of changed text sizes.
UpdateDrawPrinter();
}
else
{
SfxPrinter* pOld = pPrinter;
pPrinter = pNewPrinter;
UpdateDrawPrinter();
pPrinter->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
delete pOld;
}
InvalidateTextWidth(); // in both cases
2000-09-18 23:16:46 +00:00
}
//------------------------------------------------------------------------
void ScDocument::SetPrintOptions()
{
if ( !pPrinter ) GetPrinter(); // setzt pPrinter
DBG_ASSERT( pPrinter, "Error in printer creation :-/" );
if ( pPrinter )
{
2001-03-02 14:59:05 +00:00
SfxMiscCfg* pOffCfg = SFX_APP()->GetMiscConfig();
2000-09-18 23:16:46 +00:00
if ( pOffCfg )
{
SfxItemSet aOptSet( pPrinter->GetOptions() );
USHORT nFlags = 0;
2001-03-02 14:59:05 +00:00
if ( pOffCfg->IsPaperOrientationWarning() )
2000-09-18 23:16:46 +00:00
nFlags |= SFX_PRINTER_CHG_ORIENTATION;
if ( pOffCfg->IsPaperSizeWarning() )
nFlags |= SFX_PRINTER_CHG_SIZE;
aOptSet.Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC, nFlags ) );
aOptSet.Put( SfxBoolItem( SID_PRINTER_NOTFOUND_WARN, pOffCfg->IsNotFoundWarning() ) );
pPrinter->SetOptions( aOptSet );
}
}
}
//------------------------------------------------------------------------
void ScDocument::ModifyStyleSheet( SfxStyleSheetBase& rStyleSheet,
const SfxItemSet& rChanges )
{
SfxItemSet& rSet = rStyleSheet.GetItemSet();
switch ( rStyleSheet.GetFamily() )
{
case SFX_STYLE_FAMILY_PAGE:
{
const USHORT nOldScale = GET_SCALEVALUE(rSet,ATTR_PAGE_SCALE);
const USHORT nOldScaleToPages = GET_SCALEVALUE(rSet,ATTR_PAGE_SCALETOPAGES);
rSet.Put( rChanges );
const USHORT nNewScale = GET_SCALEVALUE(rSet,ATTR_PAGE_SCALE);
const USHORT nNewScaleToPages = GET_SCALEVALUE(rSet,ATTR_PAGE_SCALETOPAGES);
if ( (nOldScale != nNewScale) || (nOldScaleToPages != nNewScaleToPages) )
InvalidateTextWidth( rStyleSheet.GetName() );
}
break;
case SFX_STYLE_FAMILY_PARA:
{
BOOL bNumFormatChanged;
if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
rSet, rChanges ) )
InvalidateTextWidth( NULL, NULL, bNumFormatChanged );
ULONG nOldFormat =
((const SfxUInt32Item*)&rSet.Get(
ATTR_VALUE_FORMAT ))->GetValue();
ULONG nNewFormat =
((const SfxUInt32Item*)&rChanges.Get(
ATTR_VALUE_FORMAT ))->GetValue();
LanguageType eNewLang, eOldLang;
eNewLang = eOldLang = LANGUAGE_DONTKNOW;
if ( nNewFormat != nOldFormat )
{
SvNumberFormatter* pFormatter = GetFormatTable();
eOldLang = pFormatter->GetEntry( nOldFormat )->GetLanguage();
eNewLang = pFormatter->GetEntry( nNewFormat )->GetLanguage();
}
// Bedeutung der Items in rChanges:
// Item gesetzt - Aenderung uebernehmen
// Dontcare - Default setzen
// Default - keine Aenderung
// ("keine Aenderung" geht nicht mit PutExtended, darum Schleife)
for (USHORT nWhich = ATTR_PATTERN_START; nWhich <= ATTR_PATTERN_END; nWhich++)
{
const SfxPoolItem* pItem;
SfxItemState eState = rChanges.GetItemState( nWhich, FALSE, &pItem );
if ( eState == SFX_ITEM_SET )
rSet.Put( *pItem );
else if ( eState == SFX_ITEM_DONTCARE )
rSet.ClearItem( nWhich );
// bei Default nichts
}
if ( eNewLang != eOldLang )
rSet.Put(
SvxLanguageItem( eNewLang, ATTR_LANGUAGE_FORMAT ) );
}
break;
}
}
//------------------------------------------------------------------------
void ScDocument::CopyStdStylesFrom( ScDocument* pSrcDoc )
{
// #b5017505# number format exchange list has to be handled here, too
SvNumberFormatter* pThisFormatter = xPoolHelper->GetFormTable();
SvNumberFormatter* pOtherFormatter = pSrcDoc->xPoolHelper->GetFormTable();
if (pOtherFormatter && pOtherFormatter != pThisFormatter)
{
SvULONGTable* pExchangeList =
pThisFormatter->MergeFormatter(*(pOtherFormatter));
if (pExchangeList->Count() > 0)
pFormatExchangeList = pExchangeList;
}
xPoolHelper->GetStylePool()->CopyStdStylesFrom( pSrcDoc->xPoolHelper->GetStylePool() );
pFormatExchangeList = NULL;
2000-09-18 23:16:46 +00:00
}
//------------------------------------------------------------------------
void ScDocument::InvalidateTextWidth( const String& rStyleName )
{
const SCTAB nCount = GetTableCount();
for ( SCTAB i=0; i<nCount && pTab[i]; i++ )
2000-09-18 23:16:46 +00:00
if ( pTab[i]->GetPageStyle() == rStyleName )
InvalidateTextWidth( i );
}
//------------------------------------------------------------------------
void ScDocument::InvalidateTextWidth( SCTAB nTab )
2000-09-18 23:16:46 +00:00
{
ScAddress aAdrFrom( 0, 0, nTab );
ScAddress aAdrTo ( MAXCOL, MAXROW, nTab );
InvalidateTextWidth( &aAdrFrom, &aAdrTo );
}
//------------------------------------------------------------------------
BOOL ScDocument::IsPageStyleInUse( const String& rStrPageStyle, SCTAB* pInTab )
2000-09-18 23:16:46 +00:00
{
BOOL bInUse = FALSE;
const SCTAB nCount = GetTableCount();
SCTAB i;
2000-09-18 23:16:46 +00:00
for ( i = 0; !bInUse && i < nCount && pTab[i]; i++ )
2000-09-18 23:16:46 +00:00
bInUse = ( pTab[i]->GetPageStyle() == rStrPageStyle );
if ( pInTab )
*pInTab = i-1;
return bInUse;
}
//------------------------------------------------------------------------
BOOL ScDocument::RemovePageStyleInUse( const String& rStyle )
{
BOOL bWasInUse = FALSE;
const SCTAB nCount = GetTableCount();
2000-09-18 23:16:46 +00:00
for ( SCTAB i=0; i<nCount && pTab[i]; i++ )
2000-09-18 23:16:46 +00:00
if ( pTab[i]->GetPageStyle() == rStyle )
{
bWasInUse = TRUE;
pTab[i]->SetPageStyle( ScGlobal::GetRscString(STR_STYLENAME_STANDARD) );
2000-09-18 23:16:46 +00:00
}
return bWasInUse;
}
BOOL ScDocument::RenamePageStyleInUse( const String& rOld, const String& rNew )
{
BOOL bWasInUse = FALSE;
const SCTAB nCount = GetTableCount();
2000-09-18 23:16:46 +00:00
for ( SCTAB i=0; i<nCount && pTab[i]; i++ )
2000-09-18 23:16:46 +00:00
if ( pTab[i]->GetPageStyle() == rOld )
{
bWasInUse = TRUE;
pTab[i]->SetPageStyle( rNew );
}
return bWasInUse;
}
//------------------------------------------------------------------------
BYTE ScDocument::GetEditTextDirection(SCTAB nTab) const
{
EEHorizontalTextDirection eRet = EE_HTEXTDIR_DEFAULT;
String aStyleName = GetPageStyle( nTab );
SfxStyleSheetBase* pStyle = xPoolHelper->GetStylePool()->Find( aStyleName, SFX_STYLE_FAMILY_PAGE );
if ( pStyle )
{
SfxItemSet& rStyleSet = pStyle->GetItemSet();
SvxFrameDirection eDirection = (SvxFrameDirection)
((const SvxFrameDirectionItem&)rStyleSet.Get( ATTR_WRITINGDIR )).GetValue();
if ( eDirection == FRMDIR_HORI_LEFT_TOP )
eRet = EE_HTEXTDIR_L2R;
else if ( eDirection == FRMDIR_HORI_RIGHT_TOP )
eRet = EE_HTEXTDIR_R2L;
// else (invalid for EditEngine): keep "default"
}
return eRet;
}
//------------------------------------------------------------------------
2000-09-18 23:16:46 +00:00
void ScDocument::InvalidateTextWidth( const ScAddress* pAdrFrom,
const ScAddress* pAdrTo,
BOOL bBroadcast )
{
bBroadcast = (bBroadcast && GetDocOptions().IsCalcAsShown() && !IsImportingXML());
2000-09-18 23:16:46 +00:00
if ( pAdrFrom && !pAdrTo )
{
const SCTAB nTab = pAdrFrom->Tab();
2000-09-18 23:16:46 +00:00
if ( pTab[nTab] )
pTab[nTab]->InvalidateTextWidth( pAdrFrom, NULL, bBroadcast );
}
else
{
const SCTAB nTabStart = pAdrFrom ? pAdrFrom->Tab() : 0;
const SCTAB nTabEnd = pAdrTo ? pAdrTo->Tab() : MAXTAB;
2000-09-18 23:16:46 +00:00
for ( SCTAB nTab=nTabStart; nTab<=nTabEnd; nTab++ )
2000-09-18 23:16:46 +00:00
if ( pTab[nTab] )
pTab[nTab]->InvalidateTextWidth( pAdrFrom, pAdrTo, bBroadcast );
}
}
//------------------------------------------------------------------------
#define CALCMAX 1000 // Berechnungen
#define ABORT_EVENTS (INPUT_ANY & ~INPUT_TIMER & ~INPUT_OTHER)
BOOL ScDocument::IdleCalcTextWidth() // TRUE = demnaechst wieder versuchen
{
if ( bIdleDisabled || IsInLinkUpdate() )
return FALSE;
bIdleDisabled = TRUE;
// ULONG nMs = 0;
// USHORT nIter = 0;
const ULONG nStart = Time::GetSystemTicks();
2000-09-18 23:16:46 +00:00
double nPPTX = 0.0;
double nPPTY = 0.0;
OutputDevice* pDev = NULL;
MapMode aOldMap;
ScStyleSheet* pStyle = NULL;
ScColumnIterator* pColIter = NULL;
ScTable* pTable = NULL;
ScColumn* pColumn = NULL;
ScBaseCell* pCell = NULL;
SCTAB nTab = aCurTextWidthCalcPos.Tab();
SCROW nRow = aCurTextWidthCalcPos.Row();
SCsCOL nCol = aCurTextWidthCalcPos.Col();
2000-09-18 23:16:46 +00:00
USHORT nRestart = 0;
USHORT nZoom = 0;
BOOL bNeedMore= FALSE;
if ( !ValidRow(nRow) )
2000-09-18 23:16:46 +00:00
nRow = 0, nCol--;
if ( nCol < 0 )
nCol = MAXCOL, nTab++;
if ( !ValidTab(nTab) || !pTab[nTab] )
2000-09-18 23:16:46 +00:00
nTab = 0;
// DBG_ERROR( String("Start = ") + String(nTab) + String(',') + String(nCol) + String(',') + String(nRow) );
// SearchMask/Family muss gemerkt werden,
// damit z.B. der Organizer nicht durcheinanderkommt, wenn zwischendurch eine
// Query-Box aufgemacht wird !!!
ScStyleSheetPool* pStylePool = xPoolHelper->GetStylePool();
2000-09-18 23:16:46 +00:00
USHORT nOldMask = pStylePool->GetSearchMask();
SfxStyleFamily eOldFam = pStylePool->GetSearchFamily();
pTable = pTab[nTab];
pStylePool->SetSearchMask( SFX_STYLE_FAMILY_PAGE, SFXSTYLEBIT_ALL );
pStyle = (ScStyleSheet*)pStylePool->Find( pTable->aPageStyle,
SFX_STYLE_FAMILY_PAGE );
if ( !pStyle )
DBG_ERROR( "Missing StyleSheet :-/" );
BOOL bProgress = FALSE;
if ( pStyle && 0 == GET_SCALEVALUE(pStyle->GetItemSet(),ATTR_PAGE_SCALETOPAGES) )
{
USHORT nCount = 0;
nZoom = GET_SCALEVALUE(pStyle->GetItemSet(),ATTR_PAGE_SCALE);
Fraction aZoomFract( nZoom, 100 );
pColumn = &pTable->aCol[nCol];
pColIter = new ScColumnIterator( pColumn, nRow, MAXROW );
while ( (nZoom > 0) && (nCount < CALCMAX) && (nRestart < 2) )
{
if ( pColIter->Next( nRow, pCell ) )
{
if ( TEXTWIDTH_DIRTY == pCell->GetTextWidth() )
{
if ( !pDev )
{
pDev = GetPrinter();
aOldMap = pDev->GetMapMode();
pDev->SetMapMode( MAP_PIXEL ); // wichtig fuer GetNeededSize
Point aPix1000 = pDev->LogicToPixel( Point(1000,1000), MAP_TWIP );
nPPTX = aPix1000.X() / 1000.0;
nPPTY = aPix1000.Y() / 1000.0;
}
if ( !bProgress && pCell->GetCellType() == CELLTYPE_FORMULA
&& ((ScFormulaCell*)pCell)->GetDirty() )
{
ScProgress::CreateInterpretProgress( this, FALSE );
bProgress = TRUE;
}
// DBG_ERROR( String("t,c,r = ") + String(nTab) + String(',') + String(nCol) + String(',') + String(nRow) );
// DBG_ERROR( String("nOldWidth = ") + String(pCell->GetTextWidth()) );
USHORT nNewWidth = (USHORT)GetNeededSize( nCol, nRow, nTab,
pDev, nPPTX, nPPTY,
aZoomFract,aZoomFract, TRUE,
TRUE ); // bTotalSize
// DBG_ERROR( String("nNewWidth = ") + String(nNewWidth) );
pCell->SetTextWidth( nNewWidth );
bNeedMore = TRUE;
}
}
else
{
BOOL bNewTab = FALSE;
nRow = 0;
nCol--;
if ( nCol < 0 )
{
nCol = MAXCOL;
nTab++;
bNewTab = TRUE;
}
if ( !ValidTab(nTab) || !pTab[nTab] )
2000-09-18 23:16:46 +00:00
{
nTab = 0;
nRestart++;
bNewTab = TRUE;
}
if ( nRestart < 2 )
{
if ( bNewTab )
{
pTable = pTab[nTab];
pStyle = (ScStyleSheet*)pStylePool->Find( pTable->aPageStyle,
SFX_STYLE_FAMILY_PAGE );
if ( pStyle )
{
SfxItemSet& rSet = pStyle->GetItemSet();
if ( GET_SCALEVALUE( rSet, ATTR_PAGE_SCALETOPAGES ) == 0 )
nZoom = GET_SCALEVALUE(rSet, ATTR_PAGE_SCALE );
else
nZoom = 0;
}
else
DBG_ERROR( "Missing StyleSheet :-/" );
}
if ( nZoom > 0 )
{
delete pColIter;
pColumn = &pTable->aCol[nCol];
pColIter = new ScColumnIterator( pColumn, nRow, MAXROW );
}
else
nTab++; // Tabelle nicht mit absolutem Zoom -> naechste
}
}
// nIter = nCount;
nCount++;
// Idle Berechnung abbrechen, wenn Berechnungen laenger als
// 50ms dauern, oder nach 32 Berechnungen mal nachschauen, ob
// bestimmte Events anstehen, die Beachtung wuenschen:
// nMs = SysTicksToMs( GetSysTicks() - nStart );
if ( ( 50L < Time::GetSystemTicks() - nStart )
2000-09-18 23:16:46 +00:00
|| ( !(nCount&31) && Application::AnyInput( ABORT_EVENTS ) ) )
nCount = CALCMAX;
}
}
else
nTab++; // Tabelle nicht mit absolutem Zoom -> naechste
if ( bProgress )
ScProgress::DeleteInterpretProgress();
delete pColIter;
// DBG_ERROR( String(nCount) + String(" End = ") + String(nTab) + String(',') + String(nCol) + String(',') + String(nRow) );
if (pDev)
pDev->SetMapMode(aOldMap);
aCurTextWidthCalcPos.SetTab( nTab );
aCurTextWidthCalcPos.SetRow( nRow );
aCurTextWidthCalcPos.SetCol( (SCCOL)nCol );
2000-09-18 23:16:46 +00:00
// DBG_ERROR( String(nMs) + String(" ms (") + String(nIter) + String(')') );
pStylePool->SetSearchMask( eOldFam, nOldMask );
bIdleDisabled = FALSE;
return bNeedMore;
}
//------------------------------------------------------------------------
class ScSpellStatus
{
public:
BOOL bModified;
ScSpellStatus() : bModified(FALSE) {};
DECL_LINK (EventHdl, EditStatus*);
};
IMPL_LINK( ScSpellStatus, EventHdl, EditStatus *, pStatus )
{
ULONG nStatus = pStatus->GetStatusWord();
if ( nStatus & EE_STAT_WRONGWORDCHANGED )
bModified = TRUE;
return 0;
}
// SPELL_MAXCELLS muss mindestens 256 sein, solange am Iterator keine
// Start-Spalte gesetzt werden kann
//! SPELL_MAXTEST fuer Timer und Idle unterschiedlich ???
// SPELL_MAXTEST now divided between visible and rest of document
#define SPELL_MAXTEST_VIS 1
#define SPELL_MAXTEST_ALL 3
#define SPELL_MAXCELLS 256
BOOL ScDocument::OnlineSpellInRange( const ScRange& rSpellRange, ScAddress& rSpellPos,
USHORT nMaxTest )
{
ScEditEngineDefaulter* pEngine = NULL; //! am Dokument speichern
SfxItemSet* pDefaults = NULL;
ScSpellStatus aStatus;
USHORT nCellCount = 0; // Zellen insgesamt
USHORT nTestCount = 0; // Aufrufe Spelling
BOOL bChanged = FALSE; // Aenderungen?
SCCOL nCol = rSpellRange.aStart.Col(); // iterator always starts on the left edge
SCROW nRow = rSpellPos.Row();
SCTAB nTab = rSpellPos.Tab();
2000-09-18 23:16:46 +00:00
if ( !pTab[nTab] ) // sheet deleted?
{
nTab = rSpellRange.aStart.Tab();
nRow = rSpellRange.aStart.Row();
if ( !pTab[nTab] )
{
// may happen for visible range
return FALSE;
}
}
ScHorizontalCellIterator aIter( this, nTab,
rSpellRange.aStart.Col(), nRow,
rSpellRange.aEnd.Col(), rSpellRange.aEnd.Row() );
ScBaseCell* pCell = aIter.GetNext( nCol, nRow );
// skip everything left of rSpellPos:
while ( pCell && nRow == rSpellPos.Row() && nCol < rSpellPos.Col() )
pCell = aIter.GetNext( nCol, nRow );
while ( pCell )
{
CellType eType = pCell->GetCellType();
if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT )
{
if (!pEngine)
{
// #71154# ScTabEditEngine is needed
// because MapMode must be set for some old documents
pEngine = new ScTabEditEngine( this );
pEngine->SetControlWord( pEngine->GetControlWord() |
( EE_CNTRL_ONLINESPELLING | EE_CNTRL_ALLOWBIGOBJS ) );
pEngine->SetStatusEventHdl( LINK( &aStatus, ScSpellStatus, EventHdl ) );
// Delimiters hier wie in inputhdl.cxx !!!
pEngine->SetWordDelimiters(
ScEditUtil::ModifyDelimiters( pEngine->GetWordDelimiters() ) );
pDefaults = new SfxItemSet( pEngine->GetEmptyItemSet() );
2001-12-05 11:47:07 +00:00
com::sun::star::uno::Reference<com::sun::star::linguistic2::XSpellChecker1> xXSpellChecker1( LinguMgr::GetSpellChecker() );
pEngine->SetSpeller( xXSpellChecker1 );
2000-09-18 23:16:46 +00:00
}
const ScPatternAttr* pPattern = GetPattern( nCol, nRow, nTab );
pPattern->FillEditItemSet( pDefaults );
pEngine->SetDefaults( pDefaults, FALSE ); //! noetig ?
USHORT nCellLang = ((const SvxLanguageItem&)
pPattern->GetItem(ATTR_FONT_LANGUAGE)).GetValue();
if ( nCellLang == LANGUAGE_SYSTEM )
nCellLang = Application::GetSettings().GetLanguage(); // never use SYSTEM for spelling
2000-09-18 23:16:46 +00:00
pEngine->SetDefaultLanguage( nCellLang );
if ( eType == CELLTYPE_STRING )
{
String aText;
((ScStringCell*)pCell)->GetString(aText);
pEngine->SetText( aText );
}
else
pEngine->SetText( *((ScEditCell*)pCell)->GetData() );
aStatus.bModified = FALSE;
pEngine->CompleteOnlineSpelling();
if ( aStatus.bModified ) // Fehler dazu oder weggekommen?
{
BOOL bNeedEdit = TRUE; // Test auf einfachen Text
if ( !pEngine->HasOnlineSpellErrors() )
{
ScEditAttrTester aTester( pEngine );
bNeedEdit = aTester.NeedsObject();
}
if ( bNeedEdit )
{
EditTextObject* pNewData = pEngine->CreateTextObject();
if ( eType == CELLTYPE_EDIT )
((ScEditCell*)pCell)->SetData( pNewData,
pEngine->GetEditTextObjectPool() );
else
PutCell( nCol, nRow, nTab, new ScEditCell( pNewData,
this, pEngine->GetEditTextObjectPool() ) );
delete pNewData;
}
else // einfacher String
PutCell( nCol, nRow, nTab, new ScStringCell( pEngine->GetText() ) );
// Paint
if (pShell)
{
// #47751# Seitenvorschau ist davon nicht betroffen
// (sollte jedenfalls nicht)
ScPaintHint aHint( ScRange( nCol, nRow, nTab ), PAINT_GRID );
aHint.SetPrintFlag( FALSE );
pShell->Broadcast( aHint );
}
bChanged = TRUE;
}
if ( ++nTestCount >= nMaxTest ) // checked enough text?
break;
}
if ( ++nCellCount >= SPELL_MAXCELLS ) // seen enough cells?
break;
pCell = aIter.GetNext( nCol, nRow );
}
if ( pCell )
{
++nCol; // continue after last cell
if ( nCol > rSpellRange.aEnd.Col() )
{
nCol = rSpellRange.aStart.Col();
++nRow;
if ( nRow > rSpellRange.aEnd.Row() )
pCell = NULL;
}
}
if (!pCell) // end of range reached -> next sheet
{
++nTab;
if ( nTab > rSpellRange.aEnd.Tab() || !pTab[nTab] )
nTab = rSpellRange.aStart.Tab();
nCol = rSpellRange.aStart.Col();
nRow = rSpellRange.aStart.Row();
nVisSpellState = VSPL_DONE; //! only if this is for the visible range
}
rSpellPos.Set( nCol, nRow, nTab );
delete pDefaults;
delete pEngine; // bevor aStatus out of scope geht
return bChanged;
}
BOOL ScDocument::ContinueOnlineSpelling()
{
if ( bIdleDisabled || !pDocOptions->IsAutoSpell() || (pShell && pShell->IsReadOnly()) )
return FALSE;
// #i48433# set bInsertingFromOtherDoc flag so there are no broadcasts when PutCell is called
// (same behavior as in RemoveAutoSpellObj: just transfer the broadcaster)
BOOL bOldInserting = IsInsertingFromOtherDoc();
SetInsertingFromOtherDoc( TRUE );
2000-09-18 23:16:46 +00:00
//! use one EditEngine for both calls
// #41504# first check visible range
BOOL bResult = OnlineSpellInRange( aVisSpellRange, aVisSpellPos, SPELL_MAXTEST_VIS );
// during first pass through visible range, always continue
if ( nVisSpellState == VSPL_START )
bResult = TRUE;
if (bResult)
{
// if errors found, continue there
OnlineSpellInRange( aVisSpellRange, aVisSpellPos, SPELL_MAXTEST_ALL );
}
else
{
// if nothing found there, continue with rest of document
ScRange aTotalRange( 0,0,0, MAXCOL,MAXROW,MAXTAB );
bResult = OnlineSpellInRange( aTotalRange, aOnlineSpellPos, SPELL_MAXTEST_ALL );
}
SetInsertingFromOtherDoc( bOldInserting );
2000-09-18 23:16:46 +00:00
return bResult;
}
void ScDocument::SetOnlineSpellPos( const ScAddress& rPos )
{
aOnlineSpellPos = rPos;
// skip visible area for aOnlineSpellPos
if ( aVisSpellRange.In( aOnlineSpellPos ) )
aOnlineSpellPos = aVisSpellRange.aEnd;
}
BOOL ScDocument::SetVisibleSpellRange( const ScRange& rNewRange )
{
BOOL bChange = ( aVisSpellRange != rNewRange );
if (bChange)
{
// continue spelling through visible range when scrolling down
BOOL bContDown = ( nVisSpellState == VSPL_START && rNewRange.In( aVisSpellPos ) &&
rNewRange.aStart.Row() > aVisSpellRange.aStart.Row() &&
rNewRange.aStart.Col() == aVisSpellRange.aStart.Col() &&
rNewRange.aEnd.Col() == aVisSpellRange.aEnd.Col() );
aVisSpellRange = rNewRange;
if ( !bContDown )
{
aVisSpellPos = aVisSpellRange.aStart;
nVisSpellState = VSPL_START;
}
// skip visible area for aOnlineSpellPos
if ( aVisSpellRange.In( aOnlineSpellPos ) )
aOnlineSpellPos = aVisSpellRange.aEnd;
}
return bChange;
}
void ScDocument::RemoveAutoSpellObj()
{
// alle Spelling-Informationen entfernen
for (SCTAB nTab=0; nTab<=MAXTAB && pTab[nTab]; nTab++)
2000-09-18 23:16:46 +00:00
pTab[nTab]->RemoveAutoSpellObj();
}
//------------------------------------------------------------------------
BOOL ScDocument::IdleCheckLinks() // TRUE = demnaechst wieder versuchen
{
BOOL bAnyLeft = FALSE;
if (pLinkManager)
2000-09-18 23:16:46 +00:00
{
const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
USHORT nCount = rLinks.Count();
for (USHORT i=0; i<nCount; i++)
2000-09-18 23:16:46 +00:00
{
::sfx2::SvBaseLink* pBase = *rLinks[i];
if (pBase->ISA(ScDdeLink))
2000-09-18 23:16:46 +00:00
{
ScDdeLink* pDdeLink = (ScDdeLink*)pBase;
if (pDdeLink->NeedsUpdate())
{
pDdeLink->TryUpdate();
if (pDdeLink->NeedsUpdate()) // war nix?
bAnyLeft = TRUE;
}
2000-09-18 23:16:46 +00:00
}
}
}
return bAnyLeft;
}
void ScDocument::SaveDdeLinks(SvStream& rStream) const
{
// bei 4.0-Export alle mit Modus != DEFAULT weglassen
BOOL bExport40 = ( rStream.GetVersion() <= SOFFICE_FILEFORMAT_40 );
const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
2000-09-18 23:16:46 +00:00
USHORT nCount = rLinks.Count();
// erstmal zaehlen...
USHORT nDdeCount = 0;
USHORT i;
for (i=0; i<nCount; i++)
{
::sfx2::SvBaseLink* pBase = *rLinks[i];
2000-09-18 23:16:46 +00:00
if (pBase->ISA(ScDdeLink))
if ( !bExport40 || ((ScDdeLink*)pBase)->GetMode() == SC_DDE_DEFAULT )
++nDdeCount;
}
// Header
ScMultipleWriteHeader aHdr( rStream );
rStream << nDdeCount;
// Links speichern
for (i=0; i<nCount; i++)
{
::sfx2::SvBaseLink* pBase = *rLinks[i];
2000-09-18 23:16:46 +00:00
if (pBase->ISA(ScDdeLink))
{
ScDdeLink* pLink = (ScDdeLink*)pBase;
if ( !bExport40 || pLink->GetMode() == SC_DDE_DEFAULT )
pLink->Store( rStream, aHdr );
}
}
}
void ScDocument::LoadDdeLinks(SvStream& rStream)
{
ScMultipleReadHeader aHdr( rStream );
USHORT nCount;
rStream >> nCount;
for (USHORT i=0; i<nCount; i++)
{
ScDdeLink* pLink = new ScDdeLink( this, rStream, aHdr );
pLinkManager->InsertDDELink( pLink,
2000-09-18 23:16:46 +00:00
pLink->GetAppl(), pLink->GetTopic(), pLink->GetItem() );
}
}
BOOL ScDocument::HasDdeLinks() const
{
if (pLinkManager) // Clipboard z.B. hat keinen LinkManager
{
const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
2000-09-18 23:16:46 +00:00
USHORT nCount = rLinks.Count();
for (USHORT i=0; i<nCount; i++)
if ((*rLinks[i])->ISA(ScDdeLink))
return TRUE;
}
return FALSE;
}
void ScDocument::SetInLinkUpdate(BOOL bSet)
{
// called from TableLink and AreaLink
DBG_ASSERT( bInLinkUpdate != bSet, "SetInLinkUpdate twice" );
bInLinkUpdate = bSet;
}
BOOL ScDocument::IsInLinkUpdate() const
{
return bInLinkUpdate || IsInDdeLinkUpdate();
2000-09-18 23:16:46 +00:00
}
void ScDocument::UpdateDdeLinks()
{
if (pLinkManager)
2000-09-18 23:16:46 +00:00
{
const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
USHORT nCount = rLinks.Count();
USHORT i;
// #49226# falls das Updaten laenger dauert, erstmal alle Werte
// zuruecksetzen, damit nichts altes (falsches) stehen bleibt
BOOL bAny = FALSE;
for (i=0; i<nCount; i++)
2000-09-18 23:16:46 +00:00
{
::sfx2::SvBaseLink* pBase = *rLinks[i];
if (pBase->ISA(ScDdeLink))
{
((ScDdeLink*)pBase)->ResetValue();
bAny = TRUE;
}
2000-09-18 23:16:46 +00:00
}
if (bAny)
{
// Formeln berechnen und painten wie im TrackTimeHdl
TrackFormulas();
pShell->Broadcast( SfxSimpleHint( FID_DATACHANGED ) );
ResetChanged( ScRange(0,0,0,MAXCOL,MAXROW,MAXTAB) );
2000-09-18 23:16:46 +00:00
// wenn FID_DATACHANGED irgendwann mal asynchron werden sollte
// (z.B. mit Invalidate am Window), muss hier ein Update erzwungen werden.
}
2000-09-18 23:16:46 +00:00
// nun wirklich updaten...
for (i=0; i<nCount; i++)
{
::sfx2::SvBaseLink* pBase = *rLinks[i];
if (pBase->ISA(ScDdeLink))
((ScDdeLink*)pBase)->TryUpdate(); // bei DDE-Links TryUpdate statt Update
}
2000-09-18 23:16:46 +00:00
}
}
BOOL ScDocument::UpdateDdeLink( const String& rAppl, const String& rTopic, const String& rItem )
{
// fuer refresh() per StarOne Api
// ResetValue() fuer einzelnen Link nicht noetig
//! wenn's mal alles asynchron wird, aber auch hier
BOOL bFound = FALSE;
if (pLinkManager)
2000-09-18 23:16:46 +00:00
{
const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
USHORT nCount = rLinks.Count();
for (USHORT i=0; i<nCount; i++)
2000-09-18 23:16:46 +00:00
{
::sfx2::SvBaseLink* pBase = *rLinks[i];
if (pBase->ISA(ScDdeLink))
2000-09-18 23:16:46 +00:00
{
ScDdeLink* pDdeLink = (ScDdeLink*)pBase;
if ( pDdeLink->GetAppl() == rAppl &&
pDdeLink->GetTopic() == rTopic &&
pDdeLink->GetItem() == rItem )
{
pDdeLink->TryUpdate();
bFound = TRUE; // koennen theoretisch mehrere sein (Mode), darum weitersuchen
}
2000-09-18 23:16:46 +00:00
}
}
}
return bFound;
}
void ScDocument::DisconnectDdeLinks()
{
if (pLinkManager)
{
const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
2000-09-18 23:16:46 +00:00
USHORT nCount = rLinks.Count();
for (USHORT i=0; i<nCount; i++)
{
::sfx2::SvBaseLink* pBase = *rLinks[i];
2000-09-18 23:16:46 +00:00
if (pBase->ISA(ScDdeLink))
pBase->Disconnect(); // bleibt im LinkManager eingetragen
}
}
}
void ScDocument::CopyDdeLinks( ScDocument* pDestDoc ) const
{
if (bIsClip) // aus Stream erzeugen
{
if (pClipData)
{
pClipData->Seek(0);
pDestDoc->LoadDdeLinks(*pClipData);
}
}
else if (pLinkManager) // Links direkt kopieren
2000-09-18 23:16:46 +00:00
{
const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
2000-09-18 23:16:46 +00:00
USHORT nCount = rLinks.Count();
for (USHORT i=0; i<nCount; i++)
{
::sfx2::SvBaseLink* pBase = *rLinks[i];
2000-09-18 23:16:46 +00:00
if (pBase->ISA(ScDdeLink))
{
ScDdeLink* pNew = new ScDdeLink( pDestDoc, *(ScDdeLink*)pBase );
pDestDoc->pLinkManager->InsertDDELink( pNew,
2000-09-18 23:16:46 +00:00
pNew->GetAppl(), pNew->GetTopic(), pNew->GetItem() );
}
}
}
}
USHORT ScDocument::GetDdeLinkCount() const
{
USHORT nDdeCount = 0;
if (pLinkManager)
{
const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
2000-09-18 23:16:46 +00:00
USHORT nCount = rLinks.Count();
for (USHORT i=0; i<nCount; i++)
if ((*rLinks[i])->ISA(ScDdeLink))
++nDdeCount;
}
return nDdeCount;
}
// ----------------------------------------------------------------------------
namespace {
/** Tries to find the specified DDE link.
@param pnDdePos (out-param) if not 0, the index of the DDE link is returned here
(does not include other links from link manager).
@return The DDE link, if it exists, otherwise 0. */
ScDdeLink* lclGetDdeLink(
const SvxLinkManager* pLinkManager,
const String& rAppl, const String& rTopic, const String& rItem, BYTE nMode,
USHORT* pnDdePos = NULL )
2000-09-18 23:16:46 +00:00
{
if( pLinkManager )
2000-09-18 23:16:46 +00:00
{
const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
2000-09-18 23:16:46 +00:00
USHORT nCount = rLinks.Count();
if( pnDdePos ) *pnDdePos = 0;
for( USHORT nIndex = 0; nIndex < nCount; ++nIndex )
2000-09-18 23:16:46 +00:00
{
::sfx2::SvBaseLink* pLink = *rLinks[ nIndex ];
if( ScDdeLink* pDdeLink = PTR_CAST( ScDdeLink, pLink ) )
2000-09-18 23:16:46 +00:00
{
if( (pDdeLink->GetAppl() == rAppl) &&
(pDdeLink->GetTopic() == rTopic) &&
(pDdeLink->GetItem() == rItem) &&
((nMode == SC_DDE_IGNOREMODE) || (nMode == pDdeLink->GetMode())) )
return pDdeLink;
if( pnDdePos ) ++*pnDdePos;
2000-09-18 23:16:46 +00:00
}
}
}
return NULL;
2000-09-18 23:16:46 +00:00
}
/** Returns a pointer to the specified DDE link.
@param nDdePos Index of the DDE link (does not include other links from link manager).
@return The DDE link, if it exists, otherwise 0. */
ScDdeLink* lclGetDdeLink( const SvxLinkManager* pLinkManager, USHORT nDdePos )
{
if( pLinkManager )
{
const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
USHORT nCount = rLinks.Count();
USHORT nDdeIndex = 0; // counts only the DDE links
for( USHORT nIndex = 0; nIndex < nCount; ++nIndex )
{
::sfx2::SvBaseLink* pLink = *rLinks[ nIndex ];
if( ScDdeLink* pDdeLink = PTR_CAST( ScDdeLink, pLink ) )
{
if( nDdeIndex == nDdePos )
return pDdeLink;
++nDdeIndex;
}
}
}
return NULL;
}
} // namespace
// ----------------------------------------------------------------------------
bool ScDocument::FindDdeLink( const String& rAppl, const String& rTopic, const String& rItem, BYTE nMode, USHORT& rnDdePos )
{
return lclGetDdeLink( pLinkManager, rAppl, rTopic, rItem, nMode, &rnDdePos ) != NULL;
}
bool ScDocument::GetDdeLinkData( USHORT nDdePos, String& rAppl, String& rTopic, String& rItem ) const
{
if( const ScDdeLink* pDdeLink = lclGetDdeLink( pLinkManager, nDdePos ) )
{
rAppl = pDdeLink->GetAppl();
rTopic = pDdeLink->GetTopic();
rItem = pDdeLink->GetItem();
return true;
}
return false;
}
bool ScDocument::GetDdeLinkMode( USHORT nDdePos, BYTE& rnMode ) const
{
if( const ScDdeLink* pDdeLink = lclGetDdeLink( pLinkManager, nDdePos ) )
{
rnMode = pDdeLink->GetMode();
return true;
}
return false;
}
const ScMatrix* ScDocument::GetDdeLinkResultMatrix( USHORT nDdePos ) const
{
const ScDdeLink* pDdeLink = lclGetDdeLink( pLinkManager, nDdePos );
return pDdeLink ? pDdeLink->GetResult() : NULL;
}
bool ScDocument::CreateDdeLink( const String& rAppl, const String& rTopic, const String& rItem, BYTE nMode, ScMatrix* pResults )
{
/* Create a DDE link without updating it (i.e. for Excel import), to prevent
unwanted connections. First try to find existing link. Set result array
on existing and new links. */
//! store DDE links additionally at document (for efficiency)?
DBG_ASSERT( nMode != SC_DDE_IGNOREMODE, "ScDocument::CreateDdeLink - SC_DDE_IGNOREMODE not allowed here" );
if( pLinkManager && (nMode != SC_DDE_IGNOREMODE) )
{
ScDdeLink* pDdeLink = lclGetDdeLink( pLinkManager, rAppl, rTopic, rItem, nMode );
if( !pDdeLink )
{
// create a new DDE link, but without TryUpdate
pDdeLink = new ScDdeLink( this, rAppl, rTopic, rItem, nMode );
pLinkManager->InsertDDELink( pDdeLink, rAppl, rTopic, rItem );
}
// insert link results
if( pResults )
pDdeLink->SetResult( pResults );
return true;
}
return false;
}
bool ScDocument::SetDdeLinkResultMatrix( USHORT nDdePos, ScMatrix* pResults )
{
if( ScDdeLink* pDdeLink = lclGetDdeLink( pLinkManager, nDdePos ) )
{
pDdeLink->SetResult( pResults );
return true;
}
return false;
}
2000-09-18 23:16:46 +00:00
//------------------------------------------------------------------------
BOOL ScDocument::HasAreaLinks() const
{
if (pLinkManager) // Clipboard z.B. hat keinen LinkManager
{
const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
2000-09-18 23:16:46 +00:00
USHORT nCount = rLinks.Count();
for (USHORT i=0; i<nCount; i++)
if ((*rLinks[i])->ISA(ScAreaLink))
return TRUE;
}
return FALSE;
}
void ScDocument::UpdateAreaLinks()
{
if (pLinkManager)
2000-09-18 23:16:46 +00:00
{
const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
USHORT nCount = rLinks.Count();
for (USHORT i=0; i<nCount; i++)
{
::sfx2::SvBaseLink* pBase = *rLinks[i];
if (pBase->ISA(ScAreaLink))
pBase->Update();
}
2000-09-18 23:16:46 +00:00
}
}
void ScDocument::DeleteAreaLinksOnTab( SCTAB nTab )
{
if (pLinkManager)
{
const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
USHORT nPos = 0;
while ( nPos < rLinks.Count() )
{
const ::sfx2::SvBaseLink* pBase = *rLinks[nPos];
if ( pBase->ISA(ScAreaLink) &&
static_cast<const ScAreaLink*>(pBase)->GetDestArea().aStart.Tab() == nTab )
pLinkManager->Remove( nPos );
else
++nPos;
}
}
}
2000-10-30 10:33:41 +00:00
void ScDocument::UpdateRefAreaLinks( UpdateRefMode eUpdateRefMode,
const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
2000-10-30 10:33:41 +00:00
{
if (pLinkManager)
2000-10-30 10:33:41 +00:00
{
bool bAnyUpdate = false;
const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
USHORT nCount = rLinks.Count();
for (USHORT i=0; i<nCount; i++)
2000-10-30 10:33:41 +00:00
{
::sfx2::SvBaseLink* pBase = *rLinks[i];
if (pBase->ISA(ScAreaLink))
{
ScAreaLink* pLink = (ScAreaLink*) pBase;
ScRange aOutRange = pLink->GetDestArea();
SCCOL nCol1 = aOutRange.aStart.Col();
SCROW nRow1 = aOutRange.aStart.Row();
SCTAB nTab1 = aOutRange.aStart.Tab();
SCCOL nCol2 = aOutRange.aEnd.Col();
SCROW nRow2 = aOutRange.aEnd.Row();
SCTAB nTab2 = aOutRange.aEnd.Tab();
ScRefUpdateRes eRes =
ScRefUpdate::Update( this, eUpdateRefMode,
rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(), nDx, nDy, nDz,
nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
if ( eRes != UR_NOTHING )
{
pLink->SetDestArea( ScRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ) );
bAnyUpdate = true;
}
}
}
if ( bAnyUpdate )
{
// #i52120# Look for duplicates (after updating all positions).
// If several links start at the same cell, the one with the lower index is removed
// (file format specifies only one link definition for a cell).
USHORT nFirstIndex = 0;
while ( nFirstIndex < nCount )
{
bool bFound = false;
::sfx2::SvBaseLink* pFirst = *rLinks[nFirstIndex];
if ( pFirst->ISA(ScAreaLink) )
{
ScAddress aFirstPos = static_cast<ScAreaLink*>(pFirst)->GetDestArea().aStart;
for ( USHORT nSecondIndex = nFirstIndex + 1; nSecondIndex < nCount && !bFound; ++nSecondIndex )
{
::sfx2::SvBaseLink* pSecond = *rLinks[nSecondIndex];
if ( pSecond->ISA(ScAreaLink) &&
static_cast<ScAreaLink*>(pSecond)->GetDestArea().aStart == aFirstPos )
{
// remove the first link, exit the inner loop, don't increment nFirstIndex
pLinkManager->Remove( pFirst );
nCount = rLinks.Count();
bFound = true;
}
}
}
if (!bFound)
++nFirstIndex;
}
2000-10-30 10:33:41 +00:00
}
}
}
2000-09-18 23:16:46 +00:00
void ScDocument::SaveAreaLinks(SvStream& rStream) const
{
#if SC_ROWLIMIT_STREAM_ACCESS
#error address types changed!
const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
2000-09-18 23:16:46 +00:00
USHORT nCount = rLinks.Count();
// erstmal zaehlen...
USHORT nAreaCount = 0;
USHORT i;
for (i=0; i<nCount; i++)
if ((*rLinks[i])->ISA(ScAreaLink)) // rLinks[i] = Pointer auf Ref
++nAreaCount;
// Header
ScMultipleWriteHeader aHdr( rStream );
rStream << nAreaCount;
// Links speichern
for (i=0; i<nCount; i++)
{
::sfx2::SvBaseLink* pBase = *rLinks[i];
2000-09-18 23:16:46 +00:00
if (pBase->ISA(ScAreaLink))
{
ScAreaLink* pLink = (ScAreaLink*)pBase;
aHdr.StartEntry();
rStream.WriteByteString( pLink->GetFile(), rStream.GetStreamCharSet() );
rStream.WriteByteString( pLink->GetFilter(), rStream.GetStreamCharSet() );
rStream.WriteByteString( pLink->GetSource(), rStream.GetStreamCharSet() );
rStream << pLink->GetDestArea(); // ScRange
rStream.WriteByteString( pLink->GetOptions(), rStream.GetStreamCharSet() );
// filter options starting from 336
aHdr.EndEntry();
}
}
#endif // SC_ROWLIMIT_STREAM_ACCESS
2000-09-18 23:16:46 +00:00
}
void ScDocument::LoadAreaLinks(SvStream& rStream)
{
ScMultipleReadHeader aHdr( rStream );
#if SC_ROWLIMIT_STREAM_ACCESS
#error address types changed!
2000-09-18 23:16:46 +00:00
if (!pShell)
{
DBG_ERROR("AreaLinks koennen nicht ohne Shell geladen werden");
return;
}
String aFile, aFilter, aOptions, aSource;
ScRange aDestArea;
USHORT nCount;
rStream >> nCount;
for (USHORT i=0; i<nCount; i++)
{
aHdr.StartEntry();
rStream.ReadByteString( aFile, rStream.GetStreamCharSet() );
rStream.ReadByteString( aFilter, rStream.GetStreamCharSet() );
rStream.ReadByteString( aSource, rStream.GetStreamCharSet() );
rStream >> aDestArea;
if ( aHdr.BytesLeft() ) // Filter-Optionen ab 336
rStream.ReadByteString( aOptions, rStream.GetStreamCharSet() );
else
aOptions.Erase();
aHdr.EndEntry();
ScAreaLink* pLink = new ScAreaLink( pShell, aFile, aFilter, aOptions,
2001-04-05 09:52:34 +00:00
aSource, aDestArea.aStart, 0 );
2000-09-18 23:16:46 +00:00
pLink->SetInCreate( TRUE );
pLink->SetDestArea( aDestArea );
pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, aFile, &aFilter, &aSource );
pLink->Update();
pLink->SetInCreate( FALSE );
}
#endif // SC_ROWLIMIT_STREAM_ACCESS
2000-09-18 23:16:46 +00:00
}
//------------------------------------------------------------------------
// TimerDelays etc.
void ScDocument::KeyInput( const KeyEvent& rKEvt )
{
if ( pChartListenerCollection->GetCount() )
pChartListenerCollection->StartTimer();
}
// ----------------------------------------------------------------------------
BOOL ScDocument::CheckMacroWarn()
{
// The check for macro configuration, macro warning and disabling is now handled
// in SfxObjectShell::AdjustMacroMode, called by SfxObjectShell::CallBasic.
2000-09-18 23:16:46 +00:00
return TRUE;
2000-09-18 23:16:46 +00:00
}
BOOL ScDocument::HasMacroCallsAfterLoad()
2000-09-18 23:16:46 +00:00
{
// not used any longer
2000-09-18 23:16:46 +00:00
DBG_ERROR("obsolete method HasMacroCallsAfterLoad called");
return FALSE;
2000-09-18 23:16:46 +00:00
}
2000-09-22 17:57:10 +00:00
//------------------------------------------------------------------------
SfxBindings* ScDocument::GetViewBindings()
{
// used to invalidate slots after changes to this document
if ( !pShell )
return NULL; // no ObjShell -> no view
// first check current view
SfxViewFrame* pViewFrame = SfxViewFrame::Current();
if ( pViewFrame && pViewFrame->GetObjectShell() != pShell ) // wrong document?
pViewFrame = NULL;
// otherwise use first view for this doc
if ( !pViewFrame )
pViewFrame = SfxViewFrame::GetFirst( pShell );
if (pViewFrame)
return &pViewFrame->GetBindings();
else
return NULL;
}
2000-09-18 23:16:46 +00:00
2001-03-26 18:26:30 +00:00
//------------------------------------------------------------------------
2001-03-27 12:48:15 +00:00
void lcl_TransliterateEditEngine( ScEditEngineDefaulter& rEngine,
utl::TransliterationWrapper& rTranslitarationWrapper,
BOOL bConsiderLanguage, ScDocument* pDoc )
{
//! should use TransliterateText method of EditEngine instead, when available!
sal_uInt16 nLanguage = LANGUAGE_SYSTEM;
USHORT nParCount = rEngine.GetParagraphCount();
for (USHORT nPar=0; nPar<nParCount; nPar++)
{
SvUShorts aPortions;
rEngine.GetPortions( (USHORT)nPar, aPortions );
for ( USHORT nPos = aPortions.Count(); nPos; )
{
--nPos;
USHORT nEnd = aPortions.GetObject( nPos );
USHORT nStart = nPos ? aPortions.GetObject( nPos - 1 ) : 0;
ESelection aSel( nPar, nStart, nPar, nEnd );
String aOldStr = rEngine.GetText( aSel );
SfxItemSet aAttr = rEngine.GetAttribs( aSel );
if ( aAttr.GetItemState( EE_FEATURE_FIELD ) != SFX_ITEM_ON ) // fields are not touched
{
if ( bConsiderLanguage )
{
BYTE nScript = pDoc->GetStringScriptType( aOldStr );
USHORT nWhich = ( nScript == SCRIPTTYPE_ASIAN ) ? EE_CHAR_LANGUAGE_CJK :
( ( nScript == SCRIPTTYPE_COMPLEX ) ? EE_CHAR_LANGUAGE_CTL :
EE_CHAR_LANGUAGE );
nLanguage = ((const SvxLanguageItem&)aAttr.Get(nWhich)).GetValue();
}
com::sun::star::uno::Sequence<sal_Int32> aOffsets;
String aNewStr = rTranslitarationWrapper.transliterate( aOldStr, nLanguage, 0, aOldStr.Len(), &aOffsets );
if ( aNewStr != aOldStr )
{
// replace string, keep attributes
rEngine.QuickInsertText( aNewStr, aSel );
aSel.nEndPos = aSel.nStartPos + aNewStr.Len();
rEngine.QuickSetAttribs( aAttr, aSel );
}
}
}
}
}
2001-03-26 18:26:30 +00:00
void ScDocument::TransliterateText( const ScMarkData& rMultiMark, sal_Int32 nType )
{
DBG_ASSERT( rMultiMark.IsMultiMarked(), "TransliterateText: no selection" );
utl::TransliterationWrapper aTranslitarationWrapper( xServiceManager, nType );
BOOL bConsiderLanguage = aTranslitarationWrapper.needLanguageForTheMode();
sal_uInt16 nLanguage = LANGUAGE_SYSTEM;
2001-03-27 12:48:15 +00:00
ScEditEngineDefaulter* pEngine = NULL; // not using pEditEngine member because of defaults
SCTAB nCount = GetTableCount();
for (SCTAB nTab = 0; nTab < nCount; nTab++)
2001-03-26 18:26:30 +00:00
if ( pTab[nTab] && rMultiMark.GetTableSelect(nTab) )
{
SCCOL nCol = 0;
SCROW nRow = 0;
2001-03-26 18:26:30 +00:00
BOOL bFound = rMultiMark.IsCellMarked( nCol, nRow );
if (!bFound)
bFound = GetNextMarkedCell( nCol, nRow, nTab, rMultiMark );
while (bFound)
{
const ScBaseCell* pCell = GetCell( ScAddress( nCol, nRow, nTab ) );
CellType eType = pCell ? pCell->GetCellType() : CELLTYPE_NONE;
2001-03-27 12:48:15 +00:00
if ( eType == CELLTYPE_STRING )
2001-03-26 18:26:30 +00:00
{
String aOldStr;
2001-03-27 12:48:15 +00:00
((const ScStringCell*)pCell)->GetString(aOldStr);
2001-03-26 18:26:30 +00:00
xub_StrLen nOldLen = aOldStr.Len();
if ( bConsiderLanguage )
{
BYTE nScript = GetStringScriptType( aOldStr ); //! cell script type?
USHORT nWhich = ( nScript == SCRIPTTYPE_ASIAN ) ? ATTR_CJK_FONT_LANGUAGE :
( ( nScript == SCRIPTTYPE_COMPLEX ) ? ATTR_CTL_FONT_LANGUAGE :
ATTR_FONT_LANGUAGE );
nLanguage = ((const SvxLanguageItem*)GetAttr( nCol, nRow, nTab, nWhich ))->GetValue();
}
com::sun::star::uno::Sequence<sal_Int32> aOffsets;
String aNewStr = aTranslitarationWrapper.transliterate( aOldStr, nLanguage, 0, nOldLen, &aOffsets );
2000-09-18 23:16:46 +00:00
2001-03-26 18:26:30 +00:00
if ( aNewStr != aOldStr )
2001-03-27 12:48:15 +00:00
PutCell( nCol, nRow, nTab, new ScStringCell( aNewStr ) );
}
else if ( eType == CELLTYPE_EDIT )
{
if (!pEngine)
pEngine = new ScFieldEditEngine( GetEnginePool(), GetEditPool() );
// defaults from cell attributes must be set so right language is used
const ScPatternAttr* pPattern = GetPattern( nCol, nRow, nTab );
SfxItemSet* pDefaults = new SfxItemSet( pEngine->GetEmptyItemSet() );
pPattern->FillEditItemSet( pDefaults );
pEngine->SetDefaults( pDefaults, TRUE );
const EditTextObject* pData = ((const ScEditCell*)pCell)->GetData();
pEngine->SetText( *pData );
pEngine->ClearModifyFlag();
lcl_TransliterateEditEngine( *pEngine, aTranslitarationWrapper, bConsiderLanguage, this );
if ( pEngine->IsModified() )
{
ScEditAttrTester aTester( pEngine );
if ( aTester.NeedsObject() )
{
// remove defaults (paragraph attributes) before creating text object
SfxItemSet* pEmpty = new SfxItemSet( pEngine->GetEmptyItemSet() );
pEngine->SetDefaults( pEmpty, TRUE );
EditTextObject* pNewData = pEngine->CreateTextObject();
PutCell( nCol, nRow, nTab,
new ScEditCell( pNewData, this, pEngine->GetEditTextObjectPool() ) );
delete pNewData;
}
else
{
String aNewStr = pEngine->GetText();
PutCell( nCol, nRow, nTab, new ScStringCell( aNewStr ) );
}
}
2001-03-26 18:26:30 +00:00
}
bFound = GetNextMarkedCell( nCol, nRow, nTab, rMultiMark );
}
}
2001-03-27 12:48:15 +00:00
delete pEngine;
2001-03-26 18:26:30 +00:00
}
2000-09-18 23:16:46 +00:00