blob: ce32d1f0a4fdbcd5b52aab7e5527d277a897e17f [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
// INCLUDE ---------------------------------------------------------------
#include <vcl/svapp.hxx>
#include "scitems.hxx"
#include <svx/algitem.hxx>
#include <editeng/brshitem.hxx>
#include <editeng/editobj.hxx>
#include <editeng/scripttypeitem.hxx>
#include <svl/srchitem.hxx>
#include <editeng/langitem.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/viewsh.hxx>
#include <svl/stritem.hxx>
#include <svl/zforlist.hxx>
#include <svl/zformat.hxx>
#include <vcl/image.hxx>
#include <vcl/virdev.hxx>
#include <tools/rcid.h>
#include <unotools/charclass.hxx>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <numeric>
#include <i18npool/mslangid.hxx>
#include <com/sun/star/lang/Locale.hpp>
#include <comphelper/processfactory.hxx>
#include <unotools/calendarwrapper.hxx>
#include <unotools/collatorwrapper.hxx>
#include <com/sun/star/i18n/CollatorOptions.hpp>
#include <unotools/intlwrapper.hxx>
#include <unotools/syslocale.hxx>
#include <unotools/transliterationwrapper.hxx>
#include "global.hxx"
#include "scresid.hxx"
#include "autoform.hxx"
#include "document.hxx"
#include "patattr.hxx"
#include "addincol.hxx"
#include "adiasync.hxx"
#include "userlist.hxx"
#include "interpre.hxx"
#include "strload.hxx"
#include "docpool.hxx"
#include "unitconv.hxx"
#include "compiler.hxx"
#include "parclass.hxx"
#include "funcdesc.hxx"
#include "globstr.hrc"
#include "scfuncs.hrc"
#include "sc.hrc"
#include "scmod.hxx"
#include "appoptio.hxx"
// -----------------------------------------------------------------------
#define CLIPST_AVAILABLE 0
#define CLIPST_CAPTURED 1
#define CLIPST_DELETE 2
#define CLIPST_DRAW 3
ScDocShellRef* ScGlobal::pDrawClipDocShellRef = NULL;
SvxSearchItem* ScGlobal::pSearchItem = NULL;
ScAutoFormat* ScGlobal::pAutoFormat = NULL;
FuncCollection* ScGlobal::pFuncCollection = NULL;
ScUnoAddInCollection* ScGlobal::pAddInCollection = NULL;
ScUserList* ScGlobal::pUserList = NULL;
String** ScGlobal::ppRscString = NULL;
LanguageType ScGlobal::eLnge = LANGUAGE_SYSTEM;
::com::sun::star::lang::Locale* ScGlobal::pLocale = NULL;
SvtSysLocale* ScGlobal::pSysLocale = NULL;
const CharClass* ScGlobal::pCharClass = NULL;
const LocaleDataWrapper* ScGlobal::pLocaleData = NULL;
CalendarWrapper* ScGlobal::pCalendar = NULL;
CollatorWrapper* ScGlobal::pCollator = NULL;
CollatorWrapper* ScGlobal::pCaseCollator = NULL;
::utl::TransliterationWrapper* ScGlobal::pTransliteration = NULL;
::utl::TransliterationWrapper* ScGlobal::pCaseTransliteration = NULL;
::com::sun::star::uno::Reference< ::com::sun::star::i18n::XOrdinalSuffix> ScGlobal::xOrdinalSuffix = NULL;
IntlWrapper* ScGlobal::pScIntlWrapper = NULL;
sal_Unicode ScGlobal::cListDelimiter = ',';
String* ScGlobal::pEmptyString = NULL;
String* ScGlobal::pStrClipDocName = NULL;
SvxBrushItem* ScGlobal::pEmptyBrushItem = NULL;
SvxBrushItem* ScGlobal::pButtonBrushItem = NULL;
SvxBrushItem* ScGlobal::pEmbeddedBrushItem = NULL;
SvxBrushItem* ScGlobal::pProtectedBrushItem = NULL;
ImageList* ScGlobal::pOutlineBitmaps = NULL;
ImageList* ScGlobal::pOutlineBitmapsHC = NULL;
ScFunctionList* ScGlobal::pStarCalcFunctionList = NULL;
ScFunctionMgr* ScGlobal::pStarCalcFunctionMgr = NULL;
ScUnitConverter* ScGlobal::pUnitConverter = NULL;
SvNumberFormatter* ScGlobal::pEnglishFormatter = NULL;
double ScGlobal::nScreenPPTX = 96.0;
double ScGlobal::nScreenPPTY = 96.0;
sal_uInt16 ScGlobal::nDefFontHeight = 240;
sal_uInt16 ScGlobal::nStdRowHeight = 257;
long ScGlobal::nLastRowHeightExtra = 0;
long ScGlobal::nLastColWidthExtra = STD_EXTRA_WIDTH;
static sal_uInt16 nPPTZoom = 0; // ScreenZoom used to determine nScreenPPTX/Y
class SfxViewShell;
SfxViewShell* pScActiveViewShell = NULL; //! als Member !!!!!
sal_uInt16 nScClickMouseModifier = 0; //! dito
sal_uInt16 nScFillModeMouseModifier = 0; //! dito
// Hack: ScGlobal::GetUserList() muss InitAppOptions in der UI aufrufen,
// damit UserList aus Cfg geladen wird
void global_InitAppOptions();
//========================================================================
//
// statische Funktionen
//
//========================================================================
sal_Bool ScGlobal::HasAttrChanged( const SfxItemSet& rNewAttrs,
const SfxItemSet& rOldAttrs,
const sal_uInt16 nWhich )
{
sal_Bool bInvalidate = sal_False;
const SfxItemState eNewState = rNewAttrs.GetItemState( nWhich );
const SfxItemState eOldState = rOldAttrs.GetItemState( nWhich );
//----------------------------------------------------------
if ( eNewState == eOldState )
{
// beide Items gesetzt
// PoolItems, d.h. Pointer-Vergleich zulaessig
if ( SFX_ITEM_SET == eOldState )
bInvalidate = (&rNewAttrs.Get( nWhich ) != &rOldAttrs.Get( nWhich ));
}
else
{
// ein Default-Item dabei
// PoolItems, d.h. Item-Vergleich noetig
const SfxPoolItem& rOldItem = ( SFX_ITEM_SET == eOldState )
? rOldAttrs.Get( nWhich )
: rOldAttrs.GetPool()->GetDefaultItem( nWhich );
const SfxPoolItem& rNewItem = ( SFX_ITEM_SET == eNewState )
? rNewAttrs.Get( nWhich )
: rNewAttrs.GetPool()->GetDefaultItem( nWhich );
bInvalidate = sal::static_int_cast<sal_Bool>(rNewItem != rOldItem);
}
return bInvalidate;
}
sal_uLong ScGlobal::GetStandardFormat( SvNumberFormatter& rFormatter,
sal_uLong nFormat, short nType )
{
const SvNumberformat* pFormat = rFormatter.GetEntry( nFormat );
if ( pFormat )
return rFormatter.GetStandardFormat( nFormat, nType, pFormat->GetLanguage() );
return rFormatter.GetStandardFormat( nType, eLnge );
}
sal_uLong ScGlobal::GetStandardFormat( double fNumber, SvNumberFormatter& rFormatter,
sal_uLong nFormat, short nType )
{
const SvNumberformat* pFormat = rFormatter.GetEntry( nFormat );
if ( pFormat )
return rFormatter.GetStandardFormat( fNumber, nFormat, nType,
pFormat->GetLanguage() );
return rFormatter.GetStandardFormat( nType, eLnge );
}
// static
SvNumberFormatter* ScGlobal::GetEnglishFormatter()
{
if ( !pEnglishFormatter )
{
pEnglishFormatter = new SvNumberFormatter(
::comphelper::getProcessServiceFactory(), LANGUAGE_ENGLISH_US );
pEnglishFormatter->SetEvalDateFormat( NF_EVALDATEFORMAT_INTL_FORMAT );
}
return pEnglishFormatter;
}
//------------------------------------------------------------------------
sal_Bool ScGlobal::CheckWidthInvalidate( sal_Bool& bNumFormatChanged,
const SfxItemSet& rNewAttrs,
const SfxItemSet& rOldAttrs )
{
// Ueberpruefen, ob Attributaenderungen in rNewAttrs gegnueber
// rOldAttrs die Textbreite an einer Zelle ungueltig machen
bNumFormatChanged =
HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_VALUE_FORMAT );
return ( bNumFormatChanged
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_LANGUAGE_FORMAT )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CJK_FONT )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CTL_FONT )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_HEIGHT )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CJK_FONT_HEIGHT )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CTL_FONT_HEIGHT )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_WEIGHT )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CJK_FONT_WEIGHT )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CTL_FONT_WEIGHT )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_POSTURE )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CJK_FONT_POSTURE )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CTL_FONT_POSTURE )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_UNDERLINE )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_OVERLINE )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_CROSSEDOUT )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_CONTOUR )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_SHADOWED )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_STACKED )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_ROTATE_VALUE )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_ROTATE_MODE )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_LINEBREAK )
|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_MARGIN )
);
}
const SvxSearchItem& ScGlobal::GetSearchItem()
{
if (!pSearchItem)
{
pSearchItem = new SvxSearchItem( SID_SEARCH_ITEM );
pSearchItem->SetAppFlag( SVX_SEARCHAPP_CALC );
}
return *pSearchItem;
}
void ScGlobal::SetSearchItem( const SvxSearchItem& rNew )
{
// Hier waere ein Zuweisungsoperator ganz nett:
delete pSearchItem;
pSearchItem = (SvxSearchItem*)rNew.Clone();
pSearchItem->SetWhich( SID_SEARCH_ITEM );
pSearchItem->SetAppFlag( SVX_SEARCHAPP_CALC );
}
void ScGlobal::ClearAutoFormat()
{
if (pAutoFormat!=NULL)
{
delete pAutoFormat;
pAutoFormat=NULL;
}
}
ScAutoFormat* ScGlobal::GetAutoFormat()
{
if ( !pAutoFormat )
{
pAutoFormat = new ScAutoFormat;
pAutoFormat->Load();
}
return pAutoFormat;
}
FuncCollection* ScGlobal::GetFuncCollection()
{
if (!pFuncCollection)
pFuncCollection = new FuncCollection();
return pFuncCollection;
}
ScUnoAddInCollection* ScGlobal::GetAddInCollection()
{
if (!pAddInCollection)
pAddInCollection = new ScUnoAddInCollection();
return pAddInCollection;
}
ScUserList* ScGlobal::GetUserList()
{
// Hack: Cfg-Item an der App ggF. laden
global_InitAppOptions();
if (!pUserList)
pUserList = new ScUserList();
return pUserList;
}
void ScGlobal::SetUserList( const ScUserList* pNewList )
{
if ( pNewList )
{
if ( !pUserList )
pUserList = new ScUserList( *pNewList );
else
*pUserList = *pNewList;
}
else
{
delete pUserList;
pUserList = NULL;
}
}
const String& ScGlobal::GetRscString( sal_uInt16 nIndex )
{
DBG_ASSERT( nIndex < STR_COUNT, "ScGlobal::GetRscString - invalid string index");
if( !ppRscString[ nIndex ] )
{
OpCode eOp = ocNone;
// Map former globstr.src strings moved to compiler.src
switch (nIndex)
{
case STR_NULL_ERROR:
eOp = ocErrNull;
break;
case STR_DIV_ZERO:
eOp = ocErrDivZero;
break;
case STR_NO_VALUE:
eOp = ocErrValue;
break;
case STR_NOREF_STR:
eOp = ocErrRef;
break;
case STR_NO_NAME_REF:
eOp = ocErrName;
break;
case STR_NUM_ERROR:
eOp = ocErrNum;
break;
case STR_NV_STR:
eOp = ocErrNA;
break;
default:
; // nothing
}
if (eOp != ocNone)
ppRscString[ nIndex ] = new String(
ScCompiler::GetNativeSymbol( eOp));
else
ppRscString[ nIndex ] = new String(
ScRscStrLoader( RID_GLOBSTR, nIndex ).GetString());
}
return *ppRscString[ nIndex ];
}
String ScGlobal::GetErrorString(sal_uInt16 nErrNumber)
{
String sResStr;
switch (nErrNumber)
{
case NOTAVAILABLE : nErrNumber = STR_NV_STR; break;
case errNoRef : nErrNumber = STR_NO_REF_TABLE; break;
case errNoName : nErrNumber = STR_NO_NAME_REF; break;
case errNoAddin : nErrNumber = STR_NO_ADDIN; break;
case errNoMacro : nErrNumber = STR_NO_MACRO; break;
case errDoubleRef :
case errNoValue : nErrNumber = STR_NO_VALUE; break;
case errNoCode : nErrNumber = STR_NULL_ERROR; break;
case errDivisionByZero : nErrNumber = STR_DIV_ZERO; break;
case errIllegalFPOperation : nErrNumber = STR_NUM_ERROR; break;
default : sResStr = GetRscString(STR_ERROR_STR);
sResStr += String::CreateFromInt32( nErrNumber );
nErrNumber = 0;
break;
}
if( nErrNumber )
sResStr = GetRscString( nErrNumber );
return sResStr;
}
String ScGlobal::GetLongErrorString(sal_uInt16 nErrNumber)
{
switch (nErrNumber)
{
case 0:
break;
case 1:
case errIllegalArgument:
nErrNumber = STR_LONG_ERR_ILL_ARG;
break;
case 2:
case 3:
case 4:
case 5:
case errIllegalFPOperation:
nErrNumber = STR_LONG_ERR_ILL_FPO;
break;
case errIllegalChar:
nErrNumber = STR_LONG_ERR_ILL_CHAR;
break;
case errIllegalParameter:
nErrNumber = STR_LONG_ERR_ILL_PAR;
break;
case errSeparator:
nErrNumber = STR_LONG_ERR_ILL_SEP;
break;
case errPair:
case errPairExpected:
nErrNumber = STR_LONG_ERR_PAIR;
break;
case errOperatorExpected:
nErrNumber = STR_LONG_ERR_OP_EXP;
break;
case errVariableExpected:
case errParameterExpected:
nErrNumber = STR_LONG_ERR_VAR_EXP;
break;
case errCodeOverflow:
nErrNumber = STR_LONG_ERR_CODE_OVF;
break;
case errStringOverflow:
nErrNumber = STR_LONG_ERR_STR_OVF;
break;
case errStackOverflow:
case errInterpOverflow:
nErrNumber = STR_LONG_ERR_STACK_OVF;
break;
case errIllegalJump:
case errUnknownState:
case errUnknownVariable:
case errUnknownOpCode:
case errUnknownStackVariable:
case errUnknownToken:
case errNoCode:
case errDoubleRef:
nErrNumber = STR_LONG_ERR_SYNTAX;
break;
case errCircularReference:
nErrNumber = STR_LONG_ERR_CIRC_REF;
break;
case errNoConvergence:
nErrNumber = STR_LONG_ERR_NO_CONV;
break;
case errNoRef:
nErrNumber = STR_LONG_ERR_NO_REF;
break;
case errNoName:
nErrNumber = STR_LONG_ERR_NO_NAME;
break;
case errNoAddin:
nErrNumber = STR_LONG_ERR_NO_ADDIN;
break;
case errNoMacro:
nErrNumber = STR_LONG_ERR_NO_MACRO;
break;
case errDivisionByZero:
nErrNumber = STR_LONG_ERR_DIV_ZERO;
break;
case errNestedArray:
nErrNumber = STR_ERR_LONG_NESTED_ARRAY;
break;
case errNoValue:
nErrNumber = STR_LONG_ERR_NO_VALUE;
break;
case NOTAVAILABLE:
nErrNumber = STR_LONG_ERR_NV;
break;
default:
nErrNumber = STR_ERROR_STR;
break;
}
String aRes( GetRscString( nErrNumber ) );
return aRes;
}
SvxBrushItem* ScGlobal::GetButtonBrushItem()
{
pButtonBrushItem->SetColor( Application::GetSettings().GetStyleSettings().GetFaceColor() );
return pButtonBrushItem;
}
const String& ScGlobal::GetEmptyString()
{
return *pEmptyString;
}
ImageList* ScGlobal::GetOutlineSymbols( bool bHC )
{
ImageList*& rpImageList = bHC ? pOutlineBitmapsHC : pOutlineBitmaps;
if( !rpImageList )
rpImageList = new ImageList( ScResId( bHC ? RID_OUTLINEBITMAPS_H : RID_OUTLINEBITMAPS ) );
return rpImageList;
}
void ScGlobal::Init()
{
pEmptyString = new String;
// Die Default-Sprache fuer Zahlenformate (ScGlobal::eLnge)
// muss immer LANGUAGE_SYSTEM sein
//! Dann kann auch die Variable raus
eLnge = LANGUAGE_SYSTEM;
//! Wenn Sortierung etc. von der Sprache der installierten Offfice-Version
//! abhaengen sollen, hier "Application::GetSettings().GetUILanguage()"
pSysLocale = new SvtSysLocale;
pCharClass = pSysLocale->GetCharClassPtr();
pLocaleData = pSysLocale->GetLocaleDataPtr();
ppRscString = new String *[ STR_COUNT ];
for( sal_uInt16 nC = 0 ; nC < STR_COUNT ; nC++ ) ppRscString[ nC ] = NULL;
pEmptyBrushItem = new SvxBrushItem( Color( COL_TRANSPARENT ), ATTR_BACKGROUND );
pButtonBrushItem = new SvxBrushItem( Color(), ATTR_BACKGROUND );
pEmbeddedBrushItem = new SvxBrushItem( Color( COL_LIGHTCYAN ), ATTR_BACKGROUND );
pProtectedBrushItem = new SvxBrushItem( Color( COL_LIGHTGRAY ), ATTR_BACKGROUND );
UpdatePPT(NULL);
//ScCompiler::InitSymbolsNative();
// ScParameterClassification _after_ Compiler, needs function resources if
// arguments are to be merged in, which in turn need strings of function
// names from the compiler.
ScParameterClassification::Init();
srand( (unsigned) time( NULL ) ); // Random Seed Init fuer Interpreter
InitAddIns();
pStrClipDocName = new String( ScResId( SCSTR_NONAME ) );
*pStrClipDocName += '1';
// ScDocumentPool::InitVersionMaps() ist schon vorher gerufen worden
}
void ScGlobal::UpdatePPT( OutputDevice* pDev )
{
sal_uInt16 nCurrentZoom = Application::GetSettings().GetStyleSettings().GetScreenZoom();
if ( nCurrentZoom != nPPTZoom )
{
// Screen PPT values must be updated when ScreenZoom has changed.
// If called from Window::DataChanged, the window is passed as pDev,
// to make sure LogicToPixel uses a device which already uses the new zoom.
// For the initial settings, NULL is passed and GetDefaultDevice used.
if ( !pDev )
pDev = Application::GetDefaultDevice();
Point aPix1000 = pDev->LogicToPixel( Point(1000,1000), MAP_TWIP );
nScreenPPTX = aPix1000.X() / 1000.0;
nScreenPPTY = aPix1000.Y() / 1000.0;
nPPTZoom = nCurrentZoom;
}
}
const String& ScGlobal::GetClipDocName()
{
return *pStrClipDocName;
}
void ScGlobal::SetClipDocName( const String& rNew )
{
*pStrClipDocName = rNew;
}
void ScGlobal::InitTextHeight(SfxItemPool* pPool)
{
if (!pPool)
{
DBG_ERROR("kein Pool bei ScGlobal::InitTextHeight");
return;
}
const ScPatternAttr* pPattern = (const ScPatternAttr*)&pPool->GetDefaultItem(ATTR_PATTERN);
if (!pPattern)
{
DBG_ERROR("kein Default-Pattern bei ScGlobal::InitTextHeight");
return;
}
// String aTestString('X');
OutputDevice* pDefaultDev = Application::GetDefaultDevice();
VirtualDevice aVirtWindow( *pDefaultDev );
aVirtWindow.SetMapMode(MAP_PIXEL);
Font aDefFont;
pPattern->GetFont(aDefFont, SC_AUTOCOL_BLACK, &aVirtWindow); // font color doesn't matter here
aVirtWindow.SetFont(aDefFont);
nDefFontHeight = (sal_uInt16) aVirtWindow.PixelToLogic(Size(0, aVirtWindow.GetTextHeight()),
MAP_TWIP).Height();
const SvxMarginItem* pMargin = (const SvxMarginItem*)&pPattern->GetItem(ATTR_MARGIN);
nStdRowHeight = (sal_uInt16) ( nDefFontHeight +
pMargin->GetTopMargin() + pMargin->GetBottomMargin()
- STD_ROWHEIGHT_DIFF );
}
void ScGlobal::Clear()
{
// asyncs _vor_ ExitExternalFunc zerstoeren!
theAddInAsyncTbl.DeleteAndDestroy( 0, theAddInAsyncTbl.Count() );
ExitExternalFunc();
DELETEZ(pAutoFormat);
DELETEZ(pSearchItem);
DELETEZ(pFuncCollection);
DELETEZ(pAddInCollection);
DELETEZ(pUserList);
for( sal_uInt16 nC = 0 ; nC < STR_COUNT ; nC++ )
if( ppRscString ) delete ppRscString[ nC ];
delete[] ppRscString;
ppRscString = NULL;
DELETEZ(pStarCalcFunctionList); // vor ResMgr zerstoeren!
DELETEZ(pStarCalcFunctionMgr);
ScParameterClassification::Exit();
ScCompiler::DeInit();
ScInterpreter::GlobalExit(); // statischen Stack loeschen
DELETEZ(pEmptyBrushItem);
DELETEZ(pButtonBrushItem);
DELETEZ(pEmbeddedBrushItem);
DELETEZ(pProtectedBrushItem);
DELETEZ(pOutlineBitmaps);
DELETEZ(pOutlineBitmapsHC);
// DELETEZ(pAnchorBitmap);
// DELETEZ(pGrayAnchorBitmap);
DELETEZ(pEnglishFormatter);
DELETEZ(pCaseTransliteration);
DELETEZ(pTransliteration);
DELETEZ(pCaseCollator);
DELETEZ(pCollator);
DELETEZ(pCalendar);
//! do NOT delete pCharClass since it is a pointer to the single SvtSysLocale instance
pCharClass = NULL;
//! do NOT delete pLocaleData since it is a pointer to the single SvtSysLocale instance
pLocaleData = NULL;
DELETEZ(pSysLocale);
DELETEZ(pLocale);
DELETEZ(pScIntlWrapper);
DELETEZ(pStrClipDocName);
DELETEZ(pUnitConverter);
ScDocumentPool::DeleteVersionMaps();
DELETEZ(pEmptyString);
}
//------------------------------------------------------------------------
// static
CharSet ScGlobal::GetCharsetValue( const String& rCharSet )
{
// new TextEncoding values
if ( CharClass::isAsciiNumeric( rCharSet ) )
{
sal_Int32 nVal = rCharSet.ToInt32();
if ( !nVal || nVal == RTL_TEXTENCODING_DONTKNOW )
return gsl_getSystemTextEncoding();
return (CharSet) nVal;
}
// old CharSet values for compatibility
else if (rCharSet.EqualsIgnoreCaseAscii("ANSI") ) return RTL_TEXTENCODING_MS_1252;
else if (rCharSet.EqualsIgnoreCaseAscii("MAC") ) return RTL_TEXTENCODING_APPLE_ROMAN;
else if (rCharSet.EqualsIgnoreCaseAscii("IBMPC") ) return RTL_TEXTENCODING_IBM_850;
else if (rCharSet.EqualsIgnoreCaseAscii("IBMPC_437")) return RTL_TEXTENCODING_IBM_437;
else if (rCharSet.EqualsIgnoreCaseAscii("IBMPC_850")) return RTL_TEXTENCODING_IBM_850;
else if (rCharSet.EqualsIgnoreCaseAscii("IBMPC_860")) return RTL_TEXTENCODING_IBM_860;
else if (rCharSet.EqualsIgnoreCaseAscii("IBMPC_861")) return RTL_TEXTENCODING_IBM_861;
else if (rCharSet.EqualsIgnoreCaseAscii("IBMPC_863")) return RTL_TEXTENCODING_IBM_863;
else if (rCharSet.EqualsIgnoreCaseAscii("IBMPC_865")) return RTL_TEXTENCODING_IBM_865;
// else if (rCharSet.EqualsIgnoreCaseAscii("SYSTEM") ) return gsl_getSystemTextEncoding();
else return gsl_getSystemTextEncoding();
}
//------------------------------------------------------------------------
// static
String ScGlobal::GetCharsetString( CharSet eVal )
{
const sal_Char* pChar;
switch ( eVal )
{
// old CharSet strings for compatibility
case RTL_TEXTENCODING_MS_1252: pChar = "ANSI"; break;
case RTL_TEXTENCODING_APPLE_ROMAN: pChar = "MAC"; break;
// IBMPC == IBMPC_850
case RTL_TEXTENCODING_IBM_437: pChar = "IBMPC_437"; break;
case RTL_TEXTENCODING_IBM_850: pChar = "IBMPC_850"; break;
case RTL_TEXTENCODING_IBM_860: pChar = "IBMPC_860"; break;
case RTL_TEXTENCODING_IBM_861: pChar = "IBMPC_861"; break;
case RTL_TEXTENCODING_IBM_863: pChar = "IBMPC_863"; break;
case RTL_TEXTENCODING_IBM_865: pChar = "IBMPC_865"; break;
case RTL_TEXTENCODING_DONTKNOW: pChar = "SYSTEM"; break;
// new string of TextEncoding value
default:
return String::CreateFromInt32( eVal );
}
return String::CreateFromAscii(pChar);
}
//------------------------------------------------------------------------
bool ScGlobal::HasStarCalcFunctionList()
{
return ( pStarCalcFunctionList != NULL );
}
ScFunctionList* ScGlobal::GetStarCalcFunctionList()
{
if ( !pStarCalcFunctionList )
pStarCalcFunctionList = new ScFunctionList;
return pStarCalcFunctionList;
}
//------------------------------------------------------------------------
ScFunctionMgr* ScGlobal::GetStarCalcFunctionMgr()
{
if ( !pStarCalcFunctionMgr )
pStarCalcFunctionMgr = new ScFunctionMgr;
return pStarCalcFunctionMgr;
}
void ScGlobal::ResetFunctionList()
{
// FunctionMgr has pointers into FunctionList, must also be updated
DELETEZ( pStarCalcFunctionMgr );
DELETEZ( pStarCalcFunctionList );
}
//------------------------------------------------------------------------
// static
ScUnitConverter* ScGlobal::GetUnitConverter()
{
if ( !pUnitConverter )
pUnitConverter = new ScUnitConverter;
return pUnitConverter;
}
//------------------------------------------------------------------------
// static
const sal_Unicode* ScGlobal::UnicodeStrChr( const sal_Unicode* pStr,
sal_Unicode c )
{
if ( !pStr )
return NULL;
while ( *pStr )
{
if ( *pStr == c )
return pStr;
pStr++;
}
return NULL;
}
// ----------------------------------------------------------------------------
void ScGlobal::AddToken( String& rTokenList, const String& rToken, sal_Unicode cSep, xub_StrLen nSepCount, bool bForceSep )
{
if( bForceSep || (rToken.Len() && rTokenList.Len()) )
rTokenList.Expand( rTokenList.Len() + nSepCount, cSep );
rTokenList.Append( rToken );
}
bool ScGlobal::IsQuoted( const String& rString, sal_Unicode cQuote )
{
return (rString.Len() >= 2) && (rString.GetChar( 0 ) == cQuote) && (rString.GetChar( rString.Len() - 1 ) == cQuote);
}
void ScGlobal::AddQuotes( String& rString, sal_Unicode cQuote, bool bEscapeEmbedded )
{
if (bEscapeEmbedded)
{
sal_Unicode pQ[3];
pQ[0] = pQ[1] = cQuote;
pQ[2] = 0;
String aQuotes( pQ );
rString.SearchAndReplaceAll( cQuote, aQuotes);
}
rString.Insert( cQuote, 0 ).Append( cQuote );
}
void ScGlobal::EraseQuotes( String& rString, sal_Unicode cQuote, bool bUnescapeEmbedded )
{
if ( IsQuoted( rString, cQuote ) )
{
rString.Erase( rString.Len() - 1 ).Erase( 0, 1 );
if (bUnescapeEmbedded)
{
sal_Unicode pQ[3];
pQ[0] = pQ[1] = cQuote;
pQ[2] = 0;
String aQuotes( pQ );
rString.SearchAndReplaceAll( aQuotes, cQuote);
}
}
}
xub_StrLen ScGlobal::FindUnquoted( const String& rString, sal_Unicode cChar, xub_StrLen nStart, sal_Unicode cQuote )
{
const sal_Unicode* const pStart = rString.GetBuffer();
const sal_Unicode* const pStop = pStart + rString.Len();
const sal_Unicode* p = pStart + nStart;
bool bQuoted = false;
while (p < pStop)
{
if (*p == cChar && !bQuoted)
return sal::static_int_cast< xub_StrLen >( p - pStart );
else if (*p == cQuote)
{
if (!bQuoted)
bQuoted = true;
else if (p < pStop-1 && *(p+1) == cQuote)
++p;
else
bQuoted = false;
}
++p;
}
return STRING_NOTFOUND;
}
const sal_Unicode* ScGlobal::FindUnquoted( const sal_Unicode* pString, sal_Unicode cChar, sal_Unicode cQuote )
{
const sal_Unicode* p = pString;
bool bQuoted = false;
while (*p)
{
if (*p == cChar && !bQuoted)
return p;
else if (*p == cQuote)
{
if (!bQuoted)
bQuoted = true;
else if (*(p+1) == cQuote)
++p;
else
bQuoted = false;
}
++p;
}
return NULL;
}
//------------------------------------------------------------------------
sal_Bool ScGlobal::EETextObjEqual( const EditTextObject* pObj1,
const EditTextObject* pObj2 )
{
if ( pObj1 == pObj2 ) // both empty or the same object
return sal_True;
if ( pObj1 && pObj2 )
{
// first test for equal text content
sal_uInt16 nParCount = pObj1->GetParagraphCount();
if ( nParCount != pObj2->GetParagraphCount() )
return sal_False;
for (sal_uInt16 nPar=0; nPar<nParCount; nPar++)
if ( pObj1->GetText(nPar) != pObj2->GetText(nPar) )
return sal_False;
SvMemoryStream aStream1;
SvMemoryStream aStream2;
pObj1->Store( aStream1 );
pObj2->Store( aStream2 );
sal_uLong nSize = aStream1.Tell();
if ( aStream2.Tell() == nSize )
if ( !memcmp( aStream1.GetData(), aStream2.GetData(), (sal_uInt16) nSize ) )
return sal_True;
}
return sal_False;
}
void ScGlobal::OpenURL( const String& rURL, const String& rTarget )
{
// OpenURL wird immer ueber irgendwelche Umwege durch Mausklicks im GridWindow
// aufgerufen, darum stimmen pScActiveViewShell und nScClickMouseModifier.
SfxStringItem aUrl( SID_FILE_NAME, rURL );
SfxStringItem aTarget( SID_TARGETNAME, rTarget );
if ( nScClickMouseModifier & KEY_MOD1 ) // control-click -> into new window
aTarget.SetValue(
String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("_blank")) );
SfxViewFrame* pFrame = NULL;
String aReferName;
if ( pScActiveViewShell )
{
pFrame = pScActiveViewShell->GetViewFrame();
SfxMedium* pMed = pFrame->GetObjectShell()->GetMedium();
if (pMed)
aReferName = pMed->GetName();
}
SfxFrameItem aFrm( SID_DOCFRAME, pFrame );
SfxStringItem aReferer( SID_REFERER, aReferName );
SfxBoolItem aNewView( SID_OPEN_NEW_VIEW, sal_False );
SfxBoolItem aBrowsing( SID_BROWSE, sal_True );
// kein SID_SILENT mehr wegen Bug #42525# (war angeblich sowieso falsch)
SfxViewFrame* pViewFrm = SfxViewFrame::Current();
if (pViewFrm)
pViewFrm->GetDispatcher()->Execute( SID_OPENDOC,
SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD,
&aUrl, &aTarget,
&aFrm, &aReferer,
&aNewView, &aBrowsing,
0L );
}
//------------------------------------------------------------------------
sal_Bool ScGlobal::IsSystemRTL()
{
return MsLangId::isRightToLeft( Application::GetSettings().GetLanguage() );
}
sal_uInt8 ScGlobal::GetDefaultScriptType()
{
// Used when text contains only WEAK characters.
// Script type of office language is used then (same as GetEditDefaultLanguage,
// to get consistent behavior of text in simple cells and EditEngine,
// also same as GetAppLanguage() in Writer)
return (sal_uInt8) SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguage() );
}
LanguageType ScGlobal::GetEditDefaultLanguage()
{
// used for EditEngine::SetDefaultLanguage
return Application::GetSettings().GetLanguage();
}
sal_uInt16 ScGlobal::GetScriptedWhichID( sal_uInt8 nScriptType, sal_uInt16 nWhich )
{
switch ( nScriptType )
{
case SCRIPTTYPE_LATIN:
case SCRIPTTYPE_ASIAN:
case SCRIPTTYPE_COMPLEX:
break; // take exact matches
default: // prefer one, first COMPLEX, then ASIAN
if ( nScriptType & SCRIPTTYPE_COMPLEX )
nScriptType = SCRIPTTYPE_COMPLEX;
else if ( nScriptType & SCRIPTTYPE_ASIAN )
nScriptType = SCRIPTTYPE_ASIAN;
}
switch ( nScriptType )
{
case SCRIPTTYPE_COMPLEX:
{
switch ( nWhich )
{
case ATTR_FONT:
case ATTR_CJK_FONT:
nWhich = ATTR_CTL_FONT;
break;
case ATTR_FONT_HEIGHT:
case ATTR_CJK_FONT_HEIGHT:
nWhich = ATTR_CTL_FONT_HEIGHT;
break;
case ATTR_FONT_WEIGHT:
case ATTR_CJK_FONT_WEIGHT:
nWhich = ATTR_CTL_FONT_WEIGHT;
break;
case ATTR_FONT_POSTURE:
case ATTR_CJK_FONT_POSTURE:
nWhich = ATTR_CTL_FONT_POSTURE;
break;
}
}
break;
case SCRIPTTYPE_ASIAN:
{
switch ( nWhich )
{
case ATTR_FONT:
case ATTR_CTL_FONT:
nWhich = ATTR_CJK_FONT;
break;
case ATTR_FONT_HEIGHT:
case ATTR_CTL_FONT_HEIGHT:
nWhich = ATTR_CJK_FONT_HEIGHT;
break;
case ATTR_FONT_WEIGHT:
case ATTR_CTL_FONT_WEIGHT:
nWhich = ATTR_CJK_FONT_WEIGHT;
break;
case ATTR_FONT_POSTURE:
case ATTR_CTL_FONT_POSTURE:
nWhich = ATTR_CJK_FONT_POSTURE;
break;
}
}
break;
default:
{
switch ( nWhich )
{
case ATTR_CTL_FONT:
case ATTR_CJK_FONT:
nWhich = ATTR_FONT;
break;
case ATTR_CTL_FONT_HEIGHT:
case ATTR_CJK_FONT_HEIGHT:
nWhich = ATTR_FONT_HEIGHT;
break;
case ATTR_CTL_FONT_WEIGHT:
case ATTR_CJK_FONT_WEIGHT:
nWhich = ATTR_FONT_WEIGHT;
break;
case ATTR_CTL_FONT_POSTURE:
case ATTR_CJK_FONT_POSTURE:
nWhich = ATTR_FONT_POSTURE;
break;
}
}
}
return nWhich;
}
//------------------------------------------------------------------------
void ScGlobal::AddLanguage( SfxItemSet& rSet, SvNumberFormatter& rFormatter )
{
DBG_ASSERT( rSet.GetItemState( ATTR_LANGUAGE_FORMAT, sal_False ) == SFX_ITEM_DEFAULT,
"ScGlobal::AddLanguage - language already added");
const SfxPoolItem* pHardItem;
if ( rSet.GetItemState( ATTR_VALUE_FORMAT, sal_False, &pHardItem ) == SFX_ITEM_SET )
{
const SvNumberformat* pHardFormat = rFormatter.GetEntry(
((const SfxUInt32Item*)pHardItem)->GetValue() );
sal_uLong nParentFmt = 0; // pool default
const SfxItemSet* pParent = rSet.GetParent();
if ( pParent )
nParentFmt = ((const SfxUInt32Item&)pParent->Get( ATTR_VALUE_FORMAT )).GetValue();
const SvNumberformat* pParFormat = rFormatter.GetEntry( nParentFmt );
if ( pHardFormat && pParFormat &&
(pHardFormat->GetLanguage() != pParFormat->GetLanguage()) )
rSet.Put( SvxLanguageItem( pHardFormat->GetLanguage(), ATTR_LANGUAGE_FORMAT ) );
}
}
//===================================================================
// class ScFunctionList:
//===================================================================
//===================================================================
// class ScFuncRes
// fuer temporaere Objekte zum Holen der Resourcen
class ScFuncRes : public Resource
{
public:
ScFuncRes( ResId&, ScFuncDesc*, bool & rbSuppressed );
private:
sal_uInt16 GetNum();
};
//--------------------------------------------------------------------
ScFuncRes::ScFuncRes( ResId &aRes, ScFuncDesc* pDesc, bool & rbSuppressed )
: Resource(aRes)
{
rbSuppressed = (bool)GetNum();
pDesc->nCategory = GetNum();
pDesc->sHelpId = ReadByteStringRes(); //! Hack, see scfuncs.src
pDesc->nArgCount = GetNum();
sal_uInt16 nArgs = pDesc->nArgCount;
if (nArgs >= PAIRED_VAR_ARGS)
nArgs -= PAIRED_VAR_ARGS - 2;
else if (nArgs >= VAR_ARGS)
nArgs -= VAR_ARGS - 1;
if (nArgs)
{
pDesc->pDefArgFlags = new ScFuncDesc::ParameterFlags[nArgs];
for (sal_uInt16 i = 0; i < nArgs; i++)
{
pDesc->pDefArgFlags[i].bOptional = (bool)GetNum();
}
}
// Need to read the value from the resource even if nArgs==0 to advance the
// resource position pointer, so this can't be in the if(nArgs) block above.
sal_uInt16 nSuppressed = GetNum();
if (nSuppressed)
{
if (nSuppressed > nArgs)
{
DBG_ERROR3( "ScFuncRes: suppressed parameters count mismatch on OpCode %u: suppressed %d > params %d",
aRes.GetId(), (int)nSuppressed, (int)nArgs);
nSuppressed = nArgs; // sanitize
}
for (sal_uInt16 i=0; i < nSuppressed; ++i)
{
sal_uInt16 nParam = GetNum();
if (nParam < nArgs)
{
if (pDesc->nArgCount >= PAIRED_VAR_ARGS && nParam >= nArgs-2)
{
DBG_ERROR3( "ScFuncRes: PAIRED_VAR_ARGS parameters can't be suppressed, on OpCode %u: param %d >= arg %d-2",
aRes.GetId(), (int)nParam, (int)nArgs);
}
else if (pDesc->nArgCount >= VAR_ARGS && nParam == nArgs-1)
{
DBG_ERROR3( "ScFuncRes: VAR_ARGS parameters can't be suppressed, on OpCode %u: param %d == arg %d-1",
aRes.GetId(), (int)nParam, (int)nArgs);
}
else
{
pDesc->pDefArgFlags[nParam].bSuppress = true;
pDesc->bHasSuppressedArgs = true;
}
}
else
{
DBG_ERROR3( "ScFuncRes: suppressed parameter exceeds count on OpCode %u: param %d >= args %d",
aRes.GetId(), (int)nParam, (int)nArgs);
}
}
}
pDesc->pFuncName = new String( ScCompiler::GetNativeSymbol( static_cast<OpCode>( aRes.GetId())));
pDesc->pFuncDesc = new String(ScResId(1));
if (nArgs)
{
pDesc->ppDefArgNames = new String*[nArgs];
pDesc->ppDefArgDescs = new String*[nArgs];
for (sal_uInt16 i = 0; i < nArgs; i++)
{
pDesc->ppDefArgNames[i] = new String(ScResId(2*(i+1) ));
pDesc->ppDefArgDescs[i] = new String(ScResId(2*(i+1)+1));
}
}
FreeResource();
}
//------------------------------------------------------------------------
sal_uInt16 ScFuncRes::GetNum()
{
return ReadShortRes();
}
//=========================================================================
// um an die protected von Resource ranzukommen
class ScResourcePublisher : public Resource
{
private:
void FreeResource() { Resource::FreeResource(); }
public:
ScResourcePublisher( const ScResId& rId ) : Resource( rId ) {}
~ScResourcePublisher() { FreeResource(); }
sal_Bool IsAvailableRes( const ResId& rId ) const
{ return Resource::IsAvailableRes( rId ); }
};
ScFunctionList::ScFunctionList() :
nMaxFuncNameLen ( 0 )
{
ScFuncDesc* pDesc = NULL;
xub_StrLen nStrLen = 0;
FuncCollection* pFuncColl;
sal_uInt16 i,j;
sal_uInt16 nDescBlock[] =
{
RID_SC_FUNCTION_DESCRIPTIONS1,
RID_SC_FUNCTION_DESCRIPTIONS2
};
const sal_uInt16 nBlocks = sizeof(nDescBlock) / sizeof(sal_uInt16);
aFunctionList.Clear();
for ( sal_uInt16 k = 0; k < nBlocks; k++ )
{
::std::auto_ptr<ScResourcePublisher> pBlock( new ScResourcePublisher( ScResId( nDescBlock[k] ) ) );
// Browse for all possible OpCodes. This is not the fastest method, but
// otherwise the sub resources within the resource blocks and the
// resource blocks themselfs would had to be ordered according to
// OpCodes, which is utopian..
for (i = 0; i <= SC_OPCODE_LAST_OPCODE_ID; i++)
{
ScResId aRes(i);
aRes.SetRT(RSC_RESOURCE);
// Sub resource of OpCode available?
if (pBlock->IsAvailableRes(aRes))
{
pDesc = new ScFuncDesc;
bool bSuppressed = false;
ScFuncRes aSubRes( aRes, pDesc, bSuppressed);
// Instead of dealing with this exceptional case at 1001 places
// we simply don't add an entirely suppressed function to the
// list and delete it.
if (bSuppressed)
delete pDesc;
else
{
pDesc->nFIndex = i;
aFunctionList.Insert( pDesc, LIST_APPEND );
nStrLen = (*(pDesc->pFuncName)).Len();
if (nStrLen > nMaxFuncNameLen)
nMaxFuncNameLen = nStrLen;
}
}
}
}
sal_uInt16 nNextId = SC_OPCODE_LAST_OPCODE_ID + 1; // FuncID for AddIn functions
// Auswertung AddIn-Liste
String aDefArgNameValue(RTL_CONSTASCII_STRINGPARAM("value"));
String aDefArgNameString(RTL_CONSTASCII_STRINGPARAM("string"));
String aDefArgNameValues(RTL_CONSTASCII_STRINGPARAM("values"));
String aDefArgNameStrings(RTL_CONSTASCII_STRINGPARAM("strings"));
String aDefArgNameCells(RTL_CONSTASCII_STRINGPARAM("cells"));
String aDefArgNameNone(RTL_CONSTASCII_STRINGPARAM("none"));
String aDefArgDescValue(RTL_CONSTASCII_STRINGPARAM("a value"));
String aDefArgDescString(RTL_CONSTASCII_STRINGPARAM("a string"));
String aDefArgDescValues(RTL_CONSTASCII_STRINGPARAM("array of values"));
String aDefArgDescStrings(RTL_CONSTASCII_STRINGPARAM("array of strings"));
String aDefArgDescCells(RTL_CONSTASCII_STRINGPARAM("range of cells"));
String aDefArgDescNone(RTL_CONSTASCII_STRINGPARAM("none"));
String aArgName, aArgDesc;
pFuncColl = ScGlobal::GetFuncCollection();
for (i = 0; i < pFuncColl->GetCount(); i++)
{
pDesc = new ScFuncDesc;
FuncData *pAddInFuncData = (FuncData*)pFuncColl->At(i);
sal_uInt16 nArgs = pAddInFuncData->GetParamCount() - 1;
pAddInFuncData->GetParamDesc( aArgName, aArgDesc, 0 );
pDesc->nFIndex = nNextId++; // ??? OpCode vergeben
pDesc->nCategory = ID_FUNCTION_GRP_ADDINS;
pDesc->pFuncName = new String(pAddInFuncData->GetInternalName());
pDesc->pFuncName->ToUpperAscii();
pDesc->pFuncDesc = new String( aArgDesc );
*(pDesc->pFuncDesc) += '\n';
pDesc->pFuncDesc->AppendAscii(RTL_CONSTASCII_STRINGPARAM( "( AddIn: " ));
*(pDesc->pFuncDesc) += pAddInFuncData->GetModuleName();
pDesc->pFuncDesc->AppendAscii(RTL_CONSTASCII_STRINGPARAM( " )" ));
pDesc->nArgCount = nArgs;
if (nArgs)
{
pDesc->pDefArgFlags = new ScFuncDesc::ParameterFlags[nArgs];
pDesc->ppDefArgNames = new String*[nArgs];
pDesc->ppDefArgDescs = new String*[nArgs];
for (j = 0; j < nArgs; j++)
{
pDesc->pDefArgFlags[j].bOptional = false;
pDesc->pDefArgFlags[j].bSuppress = false;
pAddInFuncData->GetParamDesc( aArgName, aArgDesc, j+1 );
if ( aArgName.Len() )
pDesc->ppDefArgNames[j] = new String( aArgName );
else
{
switch (pAddInFuncData->GetParamType(j+1))
{
case PTR_DOUBLE:
pDesc->ppDefArgNames[j] = new String( aDefArgNameValue );
break;
case PTR_STRING:
pDesc->ppDefArgNames[j] = new String( aDefArgNameString );
break;
case PTR_DOUBLE_ARR:
pDesc->ppDefArgNames[j] = new String( aDefArgNameValues );
break;
case PTR_STRING_ARR:
pDesc->ppDefArgNames[j] = new String( aDefArgNameStrings );
break;
case PTR_CELL_ARR:
pDesc->ppDefArgNames[j] = new String( aDefArgNameCells );
break;
default:
pDesc->ppDefArgNames[j] = new String( aDefArgNameNone );
break;
}
}
if ( aArgDesc.Len() )
pDesc->ppDefArgDescs[j] = new String( aArgDesc );
else
{
switch (pAddInFuncData->GetParamType(j+1))
{
case PTR_DOUBLE:
pDesc->ppDefArgDescs[j] = new String( aDefArgDescValue );
break;
case PTR_STRING:
pDesc->ppDefArgDescs[j] = new String( aDefArgDescString );
break;
case PTR_DOUBLE_ARR:
pDesc->ppDefArgDescs[j] = new String( aDefArgDescValues );
break;
case PTR_STRING_ARR:
pDesc->ppDefArgDescs[j] = new String( aDefArgDescStrings );
break;
case PTR_CELL_ARR:
pDesc->ppDefArgDescs[j] = new String( aDefArgDescCells );
break;
default:
pDesc->ppDefArgDescs[j] = new String( aDefArgDescNone );
break;
}
}
}
}
// pDesc->nHelpId = 0;
aFunctionList.Insert(pDesc, LIST_APPEND);
nStrLen = (*(pDesc->pFuncName)).Len();
if ( nStrLen > nMaxFuncNameLen)
nMaxFuncNameLen = nStrLen;
}
// StarOne AddIns
ScUnoAddInCollection* pUnoAddIns = ScGlobal::GetAddInCollection();
long nUnoCount = pUnoAddIns->GetFuncCount();
for (long nFunc=0; nFunc<nUnoCount; nFunc++)
{
pDesc = new ScFuncDesc;
pDesc->nFIndex = nNextId++;
if ( pUnoAddIns->FillFunctionDesc( nFunc, *pDesc ) )
{
aFunctionList.Insert(pDesc, LIST_APPEND);
nStrLen = (*(pDesc->pFuncName)).Len();
if (nStrLen > nMaxFuncNameLen)
nMaxFuncNameLen = nStrLen;
}
else
delete pDesc;
}
}
//------------------------------------------------------------------------
ScFunctionList::~ScFunctionList()
{
const ScFuncDesc* pDesc = First();
while (pDesc)
{
delete pDesc;
pDesc = Next();
}
}
//========================================================================
// class ScFuncDesc:
ScFuncDesc::ScFuncDesc() :
pFuncName (NULL),
pFuncDesc (NULL),
ppDefArgNames (NULL),
ppDefArgDescs (NULL),
pDefArgFlags (NULL),
nFIndex (0),
nCategory (0),
nArgCount (0),
bIncomplete (false),
bHasSuppressedArgs(false)
{}
//------------------------------------------------------------------------
ScFuncDesc::~ScFuncDesc()
{
Clear();
}
//------------------------------------------------------------------------
void ScFuncDesc::Clear()
{
sal_uInt16 nArgs = nArgCount;
if (nArgs >= PAIRED_VAR_ARGS) nArgs -= PAIRED_VAR_ARGS - 2;
else if (nArgs >= VAR_ARGS) nArgs -= VAR_ARGS - 1;
if (nArgs)
{
for (sal_uInt16 i=0; i<nArgs; i++ )
{
delete ppDefArgNames[i];
delete ppDefArgDescs[i];
}
delete [] ppDefArgNames;
delete [] ppDefArgDescs;
delete [] pDefArgFlags;
}
nArgCount = 0;
ppDefArgNames = NULL;
ppDefArgDescs = NULL;
pDefArgFlags = NULL;
delete pFuncName;
pFuncName = NULL;
delete pFuncDesc;
pFuncDesc = NULL;
nFIndex = 0;
nCategory = 0;
sHelpId = "";
bIncomplete = false;
bHasSuppressedArgs = false;
}
//------------------------------------------------------------------------
String ScFuncDesc::GetParamList() const
{
const String& sep = ScCompiler::GetNativeSymbol(ocSep);
String aSig;
if ( nArgCount > 0 )
{
if ( nArgCount < VAR_ARGS )
{
sal_uInt16 nLastSuppressed = nArgCount;
sal_uInt16 nLastAdded = nArgCount;
for ( sal_uInt16 i=0; i<nArgCount; i++ )
{
if (pDefArgFlags[i].bSuppress)
nLastSuppressed = i;
else
{
nLastAdded = i;
aSig += *(ppDefArgNames[i]);
if ( i != nArgCount-1 )
{
aSig.Append(sep);
aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " " ));
}
}
}
// If only suppressed parameters follow the last added parameter,
// remove one "; "
if (nLastSuppressed < nArgCount && nLastAdded < nLastSuppressed &&
aSig.Len() >= 2)
aSig.Erase( aSig.Len() - 2 );
}
else if ( nArgCount < PAIRED_VAR_ARGS)
{
sal_uInt16 nFix = nArgCount - VAR_ARGS;
for ( sal_uInt16 nArg = 0; nArg < nFix; nArg++ )
{
if (!pDefArgFlags[nArg].bSuppress)
{
aSig += *(ppDefArgNames[nArg]);
aSig.Append(sep);
aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " " ));
}
}
/* NOTE: Currently there are no suppressed var args parameters. If
* there were, we'd have to cope with it here and above for the fix
* parameters. For now parameters are always added, so no special
* treatment of a trailing "; " necessary. */
aSig += *(ppDefArgNames[nFix]);
aSig += '1';
aSig.Append(sep);
aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " " ));
aSig += *(ppDefArgNames[nFix]);
aSig += '2';
aSig.Append(sep);
aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " ... " ));
}
else
{
sal_uInt16 nFix = nArgCount - PAIRED_VAR_ARGS;
for ( sal_uInt16 nArg = 0; nArg < nFix; nArg++ )
{
if (!pDefArgFlags[nArg].bSuppress)
{
aSig += *(ppDefArgNames[nArg]);
aSig.Append(sep);
aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " " ));
}
}
aSig += *(ppDefArgNames[nFix]);
aSig += '1';
aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ", " ));
aSig += *(ppDefArgNames[nFix+1]);
aSig += '1';
aSig.Append(sep);
aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " " ));
aSig += *(ppDefArgNames[nFix]);
aSig += '2';
aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ", " ));
aSig += *(ppDefArgNames[nFix+1]);
aSig += '2';
aSig.Append(sep);
aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " ... " ));
}
}
return aSig;
}
//------------------------------------------------------------------------
String ScFuncDesc::GetSignature() const
{
String aSig;
if(pFuncName)
{
aSig = *pFuncName;
String aParamList( GetParamList() );
if( aParamList.Len() )
{
aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "( " ));
aSig.Append( aParamList );
// U+00A0 (NBSP) prevents automatic line break
aSig.Append( static_cast< sal_Unicode >(0xA0) ).Append( ')' );
}
else
aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "()" ));
}
return aSig;
}
//------------------------------------------------------------------------
::rtl::OUString ScFuncDesc::getFormula( const ::std::vector< ::rtl::OUString >& _aArguments ) const
{
const String& sep = ScCompiler::GetNativeSymbol(ocSep);
::rtl::OUStringBuffer aFormula;
if(pFuncName)
{
aFormula.append( *pFuncName );
aFormula.appendAscii( "(" );
::std::vector< ::rtl::OUString >::const_iterator aIter = _aArguments.begin();
::std::vector< ::rtl::OUString >::const_iterator aEnd = _aArguments.end();
if ( nArgCount > 0 && aIter != aEnd )
{
sal_Bool bLastArg = ( aIter->getLength() == 0 );
while( aIter != aEnd && !bLastArg )
{
aFormula.append( *(aIter) );
if ( aIter != (aEnd-1) )
{
bLastArg = !( (aIter+1)->getLength() > 0 );
if ( !bLastArg )
aFormula.append( sep );
}
++aIter;
}
}
aFormula.appendAscii( ")" );
}
return aFormula.makeStringAndClear();
}
//------------------------------------------------------------------------
sal_uInt16 ScFuncDesc::GetSuppressedArgCount() const
{
if (!bHasSuppressedArgs || !pDefArgFlags)
return nArgCount;
sal_uInt16 nArgs = nArgCount;
if (nArgs >= PAIRED_VAR_ARGS)
nArgs -= PAIRED_VAR_ARGS - 2;
else if (nArgs >= VAR_ARGS)
nArgs -= VAR_ARGS - 1;
sal_uInt16 nCount = nArgs;
for (sal_uInt16 i=0; i < nArgs; ++i)
{
if (pDefArgFlags[i].bSuppress)
--nCount;
}
if (nArgCount >= PAIRED_VAR_ARGS)
nCount += PAIRED_VAR_ARGS - 2;
else if (nArgCount >= VAR_ARGS)
nCount += VAR_ARGS - 1;
return nCount;
}
//------------------------------------------------------------------------
::rtl::OUString ScFuncDesc::getFunctionName() const
{
::rtl::OUString sRet;
if ( pFuncName )
sRet = *pFuncName;
return sRet;
}
// -----------------------------------------------------------------------------
const formula::IFunctionCategory* ScFuncDesc::getCategory() const
{
return ScGlobal::GetStarCalcFunctionMgr()->getCategory(nCategory);
}
// -----------------------------------------------------------------------------
::rtl::OUString ScFuncDesc::getDescription() const
{
::rtl::OUString sRet;
if ( pFuncDesc )
sRet = *pFuncDesc;
return sRet;
}
// -----------------------------------------------------------------------------
// GetSuppressedArgCount
xub_StrLen ScFuncDesc::getSuppressedArgumentCount() const
{
return GetSuppressedArgCount();
}
// -----------------------------------------------------------------------------
//
void ScFuncDesc::fillVisibleArgumentMapping(::std::vector<sal_uInt16>& _rArguments) const
{
if (!bHasSuppressedArgs || !pDefArgFlags)
{
_rArguments.resize( nArgCount);
::std::vector<sal_uInt16>::iterator it = _rArguments.begin();
for( sal_uInt16 n = 0; n < nArgCount; ++n, ++it )
*it = n;
}
_rArguments.reserve( nArgCount);
sal_uInt16 nArgs = nArgCount;
if (nArgs >= PAIRED_VAR_ARGS)
nArgs -= PAIRED_VAR_ARGS - 2;
else if (nArgs >= VAR_ARGS)
nArgs -= VAR_ARGS - 1;
for (sal_uInt16 i=0; i < nArgs; ++i)
{
if (!pDefArgFlags[i].bSuppress)
_rArguments.push_back(i);
}
}
// -----------------------------------------------------------------------------
void ScFuncDesc::initArgumentInfo() const
{
// get the full argument description
// (add-in has to be instantiated to get the type information)
if ( bIncomplete && pFuncName )
{
ScUnoAddInCollection& rAddIns = *ScGlobal::GetAddInCollection();
String aIntName = rAddIns.FindFunction( *pFuncName, sal_True ); // pFuncName is upper-case
if ( aIntName.Len() )
{
// GetFuncData with bComplete=true loads the component and updates
// the global function list if needed.
rAddIns.GetFuncData( aIntName, true );
}
if ( bIncomplete )
{
DBG_ERRORFILE( "couldn't initialize add-in function" );
const_cast<ScFuncDesc*>(this)->bIncomplete = sal_False; // even if there was an error, don't try again
}
}
}
// -----------------------------------------------------------------------------
::rtl::OUString ScFuncDesc::getSignature() const
{
return GetSignature();
}
// -----------------------------------------------------------------------------
rtl::OString ScFuncDesc::getHelpId() const
{
return sHelpId;
}
// -----------------------------------------------------------------------------
// parameter
sal_uInt32 ScFuncDesc::getParameterCount() const
{
return nArgCount;
}
// -----------------------------------------------------------------------------
::rtl::OUString ScFuncDesc::getParameterName(sal_uInt32 _nPos) const
{
return *(ppDefArgNames[_nPos]);
}
// -----------------------------------------------------------------------------
::rtl::OUString ScFuncDesc::getParameterDescription(sal_uInt32 _nPos) const
{
return *(ppDefArgDescs[_nPos]);
}
// -----------------------------------------------------------------------------
bool ScFuncDesc::isParameterOptional(sal_uInt32 _nPos) const
{
return pDefArgFlags[_nPos].bOptional;
}
// -----------------------------------------------------------------------------
//========================================================================
// class ScFunctionMgr:
ScFunctionMgr::ScFunctionMgr()
: pFuncList ( ScGlobal::GetStarCalcFunctionList() ),
pCurCatList ( NULL )
{
DBG_ASSERT( pFuncList, "Funktionsliste nicht gefunden." );
sal_uLong nCount = pFuncList->GetCount();
const ScFuncDesc* pDesc;
List* pRootList;
sal_uLong n;
for ( sal_uInt16 i=0; i<MAX_FUNCCAT; i++ ) // Kategorie-Listen erstellen
aCatLists[i] = new List;
pRootList = aCatLists[0]; // Gesamtliste ("Alle") erstellen
CollatorWrapper* pCaseCollator = ScGlobal::GetCaseCollator();
for ( n=0; n<nCount; n++ )
{
sal_uLong nTmpCnt=0;
pDesc = pFuncList->GetFunction(n);
for (nTmpCnt = 0; nTmpCnt < n; nTmpCnt++)
{
// ist zwar case-sensitiv, aber Umlaute muessen richtig einsortiert werden
const ScFuncDesc* pTmpDesc = (const ScFuncDesc*)pRootList->GetObject(nTmpCnt);
if ( pCaseCollator->compareString(*pDesc->pFuncName, *pTmpDesc->pFuncName ) == COMPARE_LESS )
break;
}
pRootList->Insert((void*)pDesc, nTmpCnt); // Einsortieren
}
for ( n=0; n<nCount; n++ ) // in Gruppenlisten kopieren
{
pDesc = (const ScFuncDesc*)pRootList->GetObject(n);
DBG_ASSERT((pDesc->nCategory) < MAX_FUNCCAT, "Unbekannte Kategorie");
if ((pDesc->nCategory) < MAX_FUNCCAT)
aCatLists[pDesc->nCategory]->Insert((void*)pDesc, LIST_APPEND);
}
}
//------------------------------------------------------------------------
ScFunctionMgr::~ScFunctionMgr()
{
for (sal_uInt16 i = 0; i < MAX_FUNCCAT; i++)
delete aCatLists[i];
// delete pFuncList; // Macht spaeter die App
}
//------------------------------------------------------------------------
const ScFuncDesc* ScFunctionMgr::Get( const String& rFName ) const
{
const ScFuncDesc* pDesc = NULL;
if (rFName.Len() <= pFuncList->GetMaxFuncNameLen())
for (pDesc = First(0); pDesc; pDesc = Next())
if (rFName.EqualsIgnoreCaseAscii(*(pDesc->pFuncName)))
break;
return pDesc;
}
//------------------------------------------------------------------------
const ScFuncDesc* ScFunctionMgr::Get( sal_uInt16 nFIndex ) const
{
const ScFuncDesc* pDesc;
for (pDesc = First(0); pDesc; pDesc = Next())
if (pDesc->nFIndex == nFIndex)
break;
return pDesc;
}
//------------------------------------------------------------------------
const ScFuncDesc* ScFunctionMgr::First( sal_uInt16 nCategory ) const
{
DBG_ASSERT( nCategory < MAX_FUNCCAT, "Unbekannte Kategorie" );
if ( nCategory < MAX_FUNCCAT )
{
pCurCatList = aCatLists[nCategory];
return (const ScFuncDesc*)pCurCatList->First();
}
else
{
pCurCatList = NULL;
return NULL;
}
}
//------------------------------------------------------------------------
const ScFuncDesc* ScFunctionMgr::Next() const
{
if ( pCurCatList )
return (const ScFuncDesc*)pCurCatList->Next();
else
return NULL;
}
sal_uInt32 ScFunctionMgr::getCount() const
{
return MAX_FUNCCAT - 1;
}
const formula::IFunctionCategory* ScFunctionMgr::getCategory(sal_uInt32 nCategory) const
{
formula::IFunctionCategory* pRet = NULL;
if ( nCategory < (MAX_FUNCCAT-1) )
{
pRet = new ScFunctionCategory(const_cast<ScFunctionMgr*>(this),aCatLists[nCategory+1],nCategory); // aCatLists[0] is "all"
}
return pRet;
}
// -----------------------------------------------------------------------------
const formula::IFunctionDescription* ScFunctionMgr::getFunctionByName(const ::rtl::OUString& _sFunctionName) const
{
return Get(_sFunctionName);
}
// -----------------------------------------------------------------------------
void ScFunctionMgr::fillLastRecentlyUsedFunctions(::std::vector< const formula::IFunctionDescription*>& _rLastRUFunctions) const
{
#define LRU_MAX 10
const ScAppOptions& rAppOpt = SC_MOD()->GetAppOptions();
sal_uInt16 nLRUFuncCount = Min( rAppOpt.GetLRUFuncListCount(), (sal_uInt16)LRU_MAX );
sal_uInt16* pLRUListIds = rAppOpt.GetLRUFuncList();
if ( pLRUListIds )
{
for ( sal_uInt16 i=0; i<nLRUFuncCount; i++ )
_rLastRUFunctions.push_back( Get( pLRUListIds[i] ) );
}
}
// -----------------------------------------------------------------------------
String ScFunctionMgr::GetCategoryName(sal_uInt32 _nCategoryNumber )
{
if ( _nCategoryNumber > SC_FUNCGROUP_COUNT )
{
DBG_ERROR("Invalid category number!");
return String();
} // if ( _nCategoryNumber >= SC_FUNCGROUP_COUNT )
::std::auto_ptr<ScResourcePublisher> pCategories( new ScResourcePublisher( ScResId( RID_FUNCTION_CATEGORIES ) ) );
return String(ScResId((sal_uInt16)_nCategoryNumber));
}
sal_Unicode ScFunctionMgr::getSingleToken(const formula::IFunctionManager::EToken _eToken) const
{
switch(_eToken)
{
case eOk:
return ScCompiler::GetNativeSymbol(ocOpen).GetChar(0);
case eClose:
return ScCompiler::GetNativeSymbol(ocClose).GetChar(0);
case eSep:
return ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
case eArrayOpen:
return ScCompiler::GetNativeSymbol(ocArrayOpen).GetChar(0);
case eArrayClose:
return ScCompiler::GetNativeSymbol(ocArrayClose).GetChar(0);
} // switch(_eToken)
return 0;
}
// -----------------------------------------------------------------------------
sal_uInt32 ScFunctionCategory::getCount() const
{
return m_pCategory->Count();
}
// -----------------------------------------------------------------------------
const formula::IFunctionManager* ScFunctionCategory::getFunctionManager() const
{
return m_pMgr;
}
// -----------------------------------------------------------------------------
::rtl::OUString ScFunctionCategory::getName() const
{
if ( !m_sName.getLength() )
m_sName = ScFunctionMgr::GetCategoryName(m_nCategory+1);
return m_sName;
}
// -----------------------------------------------------------------------------
const formula::IFunctionDescription* ScFunctionCategory::getFunction(sal_uInt32 _nPos) const
{
const ScFuncDesc* pDesc = NULL;
sal_uInt32 i = 0;
for (pDesc = (const ScFuncDesc*)m_pCategory->First(); i < _nPos && pDesc; pDesc = (const ScFuncDesc*)m_pCategory->Next(),++i)
;
return pDesc;
}
// -----------------------------------------------------------------------------
sal_uInt32 ScFunctionCategory::getNumber() const
{
return m_nCategory;
}
// -----------------------------------------------------------------------------
//------------------------------------------------------------------------
utl::TransliterationWrapper* ScGlobal::GetpTransliteration() //add by CHINA001
{
if ( !pTransliteration )
{
const LanguageType eOfficeLanguage = Application::GetSettings().GetLanguage();
pTransliteration = new ::utl::TransliterationWrapper(
::comphelper::getProcessServiceFactory(), SC_TRANSLITERATION_IGNORECASE );
pTransliteration->loadModuleIfNeeded( eOfficeLanguage );
}
DBG_ASSERT(
pTransliteration,
"ScGlobal::GetpTransliteration() called before ScGlobal::Init()");
return pTransliteration;
}
const LocaleDataWrapper* ScGlobal::GetpLocaleData()
{
DBG_ASSERT(
pLocaleData,
"ScGlobal::GetpLocaleData() called before ScGlobal::Init()");
return pLocaleData;
}
CalendarWrapper* ScGlobal::GetCalendar()
{
if ( !pCalendar )
{
pCalendar = new CalendarWrapper( ::comphelper::getProcessServiceFactory() );
pCalendar->loadDefaultCalendar( *GetLocale() );
}
return pCalendar;
}
CollatorWrapper* ScGlobal::GetCollator()
{
if ( !pCollator )
{
pCollator = new CollatorWrapper( ::comphelper::getProcessServiceFactory() );
pCollator->loadDefaultCollator( *GetLocale(), SC_COLLATOR_IGNORES );
} // if ( !pCollator )
return pCollator;
}
CollatorWrapper* ScGlobal::GetCaseCollator()
{
if ( !pCaseCollator )
{
pCaseCollator = new CollatorWrapper( ::comphelper::getProcessServiceFactory() );
pCaseCollator->loadDefaultCollator( *GetLocale(), 0 );
} // if ( !pCaseCollator )
return pCaseCollator;
}
::utl::TransliterationWrapper* ScGlobal::GetCaseTransliteration()
{
if ( !pCaseTransliteration )
{
const LanguageType eOfficeLanguage = Application::GetSettings().GetLanguage();
pCaseTransliteration = new ::utl::TransliterationWrapper(::comphelper::getProcessServiceFactory(), SC_TRANSLITERATION_CASESENSE );
pCaseTransliteration->loadModuleIfNeeded( eOfficeLanguage );
} // if ( !pCaseTransliteration )
return pCaseTransliteration;
}
IntlWrapper* ScGlobal::GetScIntlWrapper()
{
if ( !pScIntlWrapper )
{
pScIntlWrapper = new IntlWrapper( ::comphelper::getProcessServiceFactory(), *GetLocale() );
}
return pScIntlWrapper;
}
::com::sun::star::lang::Locale* ScGlobal::GetLocale()
{
if ( !pLocale )
{
pLocale = new ::com::sun::star::lang::Locale( Application::GetSettings().GetLocale());
}
return pLocale;
}