diff options
Diffstat (limited to 'sc/source/core/data/global.cxx')
-rw-r--r-- | sc/source/core/data/global.cxx | 2010 |
1 files changed, 2010 insertions, 0 deletions
diff --git a/sc/source/core/data/global.cxx b/sc/source/core/data/global.cxx new file mode 100644 index 000000000000..d49e8e1aa139 --- /dev/null +++ b/sc/source/core/data/global.cxx @@ -0,0 +1,2010 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: global.cxx,v $ + * $Revision: 1.56.102.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 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 <svx/brshitem.hxx> +#include <svx/editobj.hxx> +#include <svx/scripttypeitem.hxx> +#include <svx/srchitem.hxx> +#include <svx/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; + +USHORT ScGlobal::nDefFontHeight = 240; +USHORT ScGlobal::nStdRowHeight = 257; + +long ScGlobal::nLastRowHeightExtra = 0; +long ScGlobal::nLastColWidthExtra = STD_EXTRA_WIDTH; + +static USHORT nPPTZoom = 0; // ScreenZoom used to determine nScreenPPTX/Y + + +// ... oder so? + +BOOL bOderSo; + +bool SC_DLLPUBLIC ScGetWriteTeamInfo() +{ + return bOderSo; +} + +class SfxViewShell; +SfxViewShell* pScActiveViewShell = NULL; //! als Member !!!!! +USHORT nScClickMouseModifier = 0; //! dito +USHORT nScFillModeMouseModifier = 0; //! dito + +// Hack: ScGlobal::GetUserList() muss InitAppOptions in der UI aufrufen, +// damit UserList aus Cfg geladen wird + +void global_InitAppOptions(); + +//======================================================================== +// +// statische Funktionen +// +//======================================================================== + +BOOL ScGlobal::HasAttrChanged( const SfxItemSet& rNewAttrs, + const SfxItemSet& rOldAttrs, + const USHORT nWhich ) +{ + BOOL bInvalidate = 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<BOOL>(rNewItem != rOldItem); + } + + return bInvalidate; +} + +ULONG ScGlobal::GetStandardFormat( SvNumberFormatter& rFormatter, + ULONG nFormat, short nType ) +{ + const SvNumberformat* pFormat = rFormatter.GetEntry( nFormat ); + if ( pFormat ) + return rFormatter.GetStandardFormat( nFormat, nType, pFormat->GetLanguage() ); + return rFormatter.GetStandardFormat( nType, eLnge ); +} + +ULONG ScGlobal::GetStandardFormat( double fNumber, SvNumberFormatter& rFormatter, + 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; +} + + +//------------------------------------------------------------------------ + +BOOL ScGlobal::CheckWidthInvalidate( 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 ); +} + +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( USHORT 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(USHORT 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(USHORT 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 ) ); + if( bOderSo ) + { + String aOderSo( GetRscString( STR_ODER_SO ) ); + aOderSo.SearchAndReplace( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("%s")), aRes ); + aRes = aOderSo; + } + 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( USHORT 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 ) +{ + USHORT 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 = (USHORT) aVirtWindow.PixelToLogic(Size(0, aVirtWindow.GetTextHeight()), + MAP_TWIP).Height(); + + const SvxMarginItem* pMargin = (const SvxMarginItem*)&pPattern->GetItem(ATTR_MARGIN); + + nStdRowHeight = (USHORT) ( 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( USHORT 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; +} + +//------------------------------------------------------------------------ + +BOOL ScGlobal::EETextObjEqual( const EditTextObject* pObj1, + const EditTextObject* pObj2 ) +{ + if ( pObj1 == pObj2 ) // both empty or the same object + return TRUE; + + if ( pObj1 && pObj2 ) + { + // first test for equal text content + USHORT nParCount = pObj1->GetParagraphCount(); + if ( nParCount != pObj2->GetParagraphCount() ) + return FALSE; + for (USHORT nPar=0; nPar<nParCount; nPar++) + if ( pObj1->GetText(nPar) != pObj2->GetText(nPar) ) + return FALSE; + + SvMemoryStream aStream1; + SvMemoryStream aStream2; + pObj1->Store( aStream1 ); + pObj2->Store( aStream2 ); + ULONG nSize = aStream1.Tell(); + if ( aStream2.Tell() == nSize ) + if ( !memcmp( aStream1.GetData(), aStream2.GetData(), (USHORT) nSize ) ) + return TRUE; + } + + return 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, FALSE ); + SfxBoolItem aBrowsing( SID_BROWSE, 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 ); +} + +//------------------------------------------------------------------------ + +BOOL ScGlobal::IsSystemRTL() +{ + return MsLangId::isRightToLeft( Application::GetSettings().GetLanguage() ); +} + +BYTE 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 (BYTE) SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguage() ); +} + +LanguageType ScGlobal::GetEditDefaultLanguage() +{ + // used for EditEngine::SetDefaultLanguage + + return Application::GetSettings().GetLanguage(); +} + +USHORT ScGlobal::GetScriptedWhichID( BYTE nScriptType, USHORT 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, FALSE ) == SFX_ITEM_DEFAULT, + "ScGlobal::AddLanguage - language already added"); + + const SfxPoolItem* pHardItem; + if ( rSet.GetItemState( ATTR_VALUE_FORMAT, FALSE, &pHardItem ) == SFX_ITEM_SET ) + { + const SvNumberformat* pHardFormat = rFormatter.GetEntry( + ((const SfxUInt32Item*)pHardItem)->GetValue() ); + + 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: + USHORT GetNum(); +}; + +//-------------------------------------------------------------------- + +ScFuncRes::ScFuncRes( ResId &aRes, ScFuncDesc* pDesc, bool & rbSuppressed ) + : Resource(aRes) +{ + rbSuppressed = (bool)GetNum(); + pDesc->nCategory = GetNum(); + pDesc->nHelpId = GetNum() + 32768; //! Hack, see scfuncs.src + pDesc->nArgCount = GetNum(); + USHORT nArgs = pDesc->nArgCount; + if (nArgs >= VAR_ARGS) + nArgs -= VAR_ARGS - 1; + if (nArgs) + { + pDesc->pDefArgFlags = new ScFuncDesc::ParameterFlags[nArgs]; + for (USHORT 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. + USHORT 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 (USHORT i=0; i < nSuppressed; ++i) + { + USHORT nParam = GetNum(); + if (nParam < nArgs) + { + 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 (USHORT 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(); +} + +//------------------------------------------------------------------------ + +USHORT 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(); } + BOOL IsAvailableRes( const ResId& rId ) const + { return Resource::IsAvailableRes( rId ); } + +}; + + +ScFunctionList::ScFunctionList() : + nMaxFuncNameLen ( 0 ) +{ + ScFuncDesc* pDesc = NULL; + xub_StrLen nStrLen = 0; + FuncCollection* pFuncColl; + USHORT i,j; + USHORT nDescBlock[] = + { + RID_SC_FUNCTION_DESCRIPTIONS1, + RID_SC_FUNCTION_DESCRIPTIONS2 + }; + const USHORT nBlocks = sizeof(nDescBlock) / sizeof(USHORT); + + aFunctionList.Clear(); + + for ( USHORT 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; + } + } + } + } + + USHORT 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); + USHORT 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), + nHelpId (0), + bIncomplete (false), + bHasSuppressedArgs(false) +{} + +//------------------------------------------------------------------------ + +ScFuncDesc::~ScFuncDesc() +{ + Clear(); +} + +//------------------------------------------------------------------------ + +void ScFuncDesc::Clear() +{ + USHORT nArgs = nArgCount; + if (nArgs >= VAR_ARGS) nArgs -= VAR_ARGS-1; + if (nArgs) + { + for (USHORT 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; + nHelpId = 0; + bIncomplete = false; + bHasSuppressedArgs = false; +} + +//------------------------------------------------------------------------ + +String ScFuncDesc::GetParamList() const +{ + const String& sep = ScCompiler::GetNativeSymbol(ocSep); + + String aSig; + + if ( nArgCount > 0 ) + { + if ( nArgCount < VAR_ARGS ) + { + USHORT nLastSuppressed = nArgCount; + USHORT nLastAdded = nArgCount; + for ( USHORT 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 + { + USHORT nFix = nArgCount - VAR_ARGS; + for ( USHORT 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( " ... " )); + } + } + + 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 ) + { + 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(); +} + +//------------------------------------------------------------------------ + +USHORT ScFuncDesc::GetSuppressedArgCount() const +{ + if (!bHasSuppressedArgs || !pDefArgFlags) + return nArgCount; + + USHORT nArgs = nArgCount; + if (nArgs >= VAR_ARGS) + nArgs -= VAR_ARGS - 1; + USHORT nCount = nArgs; + for (USHORT i=0; i < nArgs; ++i) + { + if (pDefArgFlags[i].bSuppress) + --nCount; + } + 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<USHORT>& _rArguments) const +{ + if (!bHasSuppressedArgs || !pDefArgFlags) + { + _rArguments.resize( nArgCount); + ::std::iota( _rArguments.begin(), _rArguments.end(), 0); + } + + _rArguments.reserve( nArgCount); + USHORT nArgs = nArgCount; + if (nArgs >= VAR_ARGS) + nArgs -= VAR_ARGS - 1; + for (USHORT 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, 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 = FALSE; // even if there was an error, don't try again + } + } +} +// ----------------------------------------------------------------------------- +::rtl::OUString ScFuncDesc::getSignature() const +{ + return GetSignature(); +} +// ----------------------------------------------------------------------------- +long ScFuncDesc::getHelpId() const +{ + return nHelpId; +} +// ----------------------------------------------------------------------------- + +// 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." ); + ULONG nCount = pFuncList->GetCount(); + const ScFuncDesc* pDesc; + List* pRootList; + ULONG n; + + for ( USHORT 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++ ) + { + 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 (USHORT 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( USHORT nFIndex ) const +{ + const ScFuncDesc* pDesc; + for (pDesc = First(0); pDesc; pDesc = Next()) + if (pDesc->nFIndex == nFIndex) + break; + return pDesc; +} + +//------------------------------------------------------------------------ + +const ScFuncDesc* ScFunctionMgr::First( USHORT 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(); + USHORT nLRUFuncCount = Min( rAppOpt.GetLRUFuncListCount(), (USHORT)LRU_MAX ); + USHORT* pLRUListIds = rAppOpt.GetLRUFuncList(); + + if ( pLRUListIds ) + { + for ( USHORT 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((USHORT)_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; +} + |