xref: /trunk/main/sc/source/core/data/global.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 
32 
33 // INCLUDE ---------------------------------------------------------------
34 #include <vcl/svapp.hxx>
35 #include "scitems.hxx"
36 #include <svx/algitem.hxx>
37 #include <editeng/brshitem.hxx>
38 #include <editeng/editobj.hxx>
39 #include <editeng/scripttypeitem.hxx>
40 #include <svl/srchitem.hxx>
41 #include <editeng/langitem.hxx>
42 #include <sfx2/docfile.hxx>
43 #include <sfx2/dispatch.hxx>
44 #include <sfx2/objsh.hxx>
45 #include <sfx2/viewfrm.hxx>
46 #include <sfx2/viewsh.hxx>
47 #include <svl/stritem.hxx>
48 #include <svl/zforlist.hxx>
49 #include <svl/zformat.hxx>
50 #include <vcl/image.hxx>
51 #include <vcl/virdev.hxx>
52 #include <tools/rcid.h>
53 #include <unotools/charclass.hxx>
54 #include <stdlib.h>
55 #include <time.h>
56 #include <ctype.h>
57 #include <numeric>
58 
59 
60 #include <i18npool/mslangid.hxx>
61 #include <com/sun/star/lang/Locale.hpp>
62 #include <comphelper/processfactory.hxx>
63 #include <unotools/calendarwrapper.hxx>
64 #include <unotools/collatorwrapper.hxx>
65 #include <com/sun/star/i18n/CollatorOptions.hpp>
66 #include <unotools/intlwrapper.hxx>
67 #include <unotools/syslocale.hxx>
68 #include <unotools/transliterationwrapper.hxx>
69 
70 #include "global.hxx"
71 #include "scresid.hxx"
72 #include "autoform.hxx"
73 #include "document.hxx"
74 #include "patattr.hxx"
75 #include "addincol.hxx"
76 #include "adiasync.hxx"
77 #include "userlist.hxx"
78 #include "interpre.hxx"
79 #include "strload.hxx"
80 #include "docpool.hxx"
81 #include "unitconv.hxx"
82 #include "compiler.hxx"
83 #include "parclass.hxx"
84 #include "funcdesc.hxx"
85 #include "globstr.hrc"
86 #include "scfuncs.hrc"
87 #include "sc.hrc"
88 #include "scmod.hxx"
89 #include "appoptio.hxx"
90 
91 // -----------------------------------------------------------------------
92 
93 #define CLIPST_AVAILABLE	0
94 #define CLIPST_CAPTURED		1
95 #define CLIPST_DELETE		2
96 #define CLIPST_DRAW			3
97 
98 ScDocShellRef*	ScGlobal::pDrawClipDocShellRef = NULL;
99 SvxSearchItem*	ScGlobal::pSearchItem = NULL;
100 ScAutoFormat*	ScGlobal::pAutoFormat = NULL;
101 FuncCollection* ScGlobal::pFuncCollection = NULL;
102 ScUnoAddInCollection* ScGlobal::pAddInCollection = NULL;
103 ScUserList*		ScGlobal::pUserList = NULL;
104 String**		ScGlobal::ppRscString = NULL;
105 LanguageType    ScGlobal::eLnge = LANGUAGE_SYSTEM;
106 ::com::sun::star::lang::Locale*		ScGlobal::pLocale = NULL;
107 SvtSysLocale*   ScGlobal::pSysLocale = NULL;
108 const CharClass*  ScGlobal::pCharClass = NULL;
109 const LocaleDataWrapper*  ScGlobal::pLocaleData = NULL;
110 CalendarWrapper* ScGlobal::pCalendar = NULL;
111 CollatorWrapper* ScGlobal::pCollator = NULL;
112 CollatorWrapper* ScGlobal::pCaseCollator = NULL;
113 ::utl::TransliterationWrapper* ScGlobal::pTransliteration = NULL;
114 ::utl::TransliterationWrapper* ScGlobal::pCaseTransliteration = NULL;
115 ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XOrdinalSuffix> ScGlobal::xOrdinalSuffix = NULL;
116 IntlWrapper*    ScGlobal::pScIntlWrapper = NULL;
117 sal_Unicode		ScGlobal::cListDelimiter = ',';
118 String*			ScGlobal::pEmptyString = NULL;
119 String*			ScGlobal::pStrClipDocName = NULL;
120 
121 SvxBrushItem*	ScGlobal::pEmptyBrushItem = NULL;
122 SvxBrushItem*	ScGlobal::pButtonBrushItem = NULL;
123 SvxBrushItem*	ScGlobal::pEmbeddedBrushItem = NULL;
124 SvxBrushItem*	ScGlobal::pProtectedBrushItem = NULL;
125 
126 ImageList*      ScGlobal::pOutlineBitmaps = NULL;
127 ImageList*      ScGlobal::pOutlineBitmapsHC = NULL;
128 
129 ScFunctionList* ScGlobal::pStarCalcFunctionList = NULL;
130 ScFunctionMgr*	ScGlobal::pStarCalcFunctionMgr	= NULL;
131 
132 ScUnitConverter* ScGlobal::pUnitConverter = NULL;
133 SvNumberFormatter* ScGlobal::pEnglishFormatter = NULL;
134 
135 double			ScGlobal::nScreenPPTX			= 96.0;
136 double			ScGlobal::nScreenPPTY			= 96.0;
137 
138 sal_uInt16			ScGlobal::nDefFontHeight		= 240;
139 sal_uInt16			ScGlobal::nStdRowHeight			= 257;
140 
141 long			ScGlobal::nLastRowHeightExtra	= 0;
142 long			ScGlobal::nLastColWidthExtra	= STD_EXTRA_WIDTH;
143 
144 static sal_uInt16 nPPTZoom = 0;		// ScreenZoom used to determine nScreenPPTX/Y
145 
146 
147 class SfxViewShell;
148 SfxViewShell* pScActiveViewShell = NULL;			//! als Member !!!!!
149 sal_uInt16 nScClickMouseModifier = 0;					//! dito
150 sal_uInt16 nScFillModeMouseModifier = 0;				//! dito
151 
152 // Hack: ScGlobal::GetUserList() muss InitAppOptions in der UI aufrufen,
153 //		 damit UserList aus Cfg geladen wird
154 
155 void global_InitAppOptions();
156 
157 //========================================================================
158 //
159 //		statische Funktionen
160 //
161 //========================================================================
162 
163 sal_Bool ScGlobal::HasAttrChanged( const SfxItemSet&  rNewAttrs,
164 							   const SfxItemSet&  rOldAttrs,
165 							   const sal_uInt16		  nWhich )
166 {
167 	sal_Bool				bInvalidate = sal_False;
168 	const SfxItemState	eNewState	= rNewAttrs.GetItemState( nWhich );
169 	const SfxItemState	eOldState	= rOldAttrs.GetItemState( nWhich );
170 
171 	//----------------------------------------------------------
172 
173 	if ( eNewState == eOldState )
174 	{
175 		// beide Items gesetzt
176 		// PoolItems, d.h. Pointer-Vergleich zulaessig
177 		if ( SFX_ITEM_SET == eOldState )
178 			bInvalidate = (&rNewAttrs.Get( nWhich ) != &rOldAttrs.Get( nWhich ));
179 	}
180 	else
181 	{
182 		// ein Default-Item dabei
183 		// PoolItems, d.h. Item-Vergleich noetig
184 
185 		const SfxPoolItem& rOldItem = ( SFX_ITEM_SET == eOldState )
186 					? rOldAttrs.Get( nWhich )
187 					: rOldAttrs.GetPool()->GetDefaultItem( nWhich );
188 
189 		const SfxPoolItem& rNewItem = ( SFX_ITEM_SET == eNewState )
190 					? rNewAttrs.Get( nWhich )
191 					: rNewAttrs.GetPool()->GetDefaultItem( nWhich );
192 
193         bInvalidate = sal::static_int_cast<sal_Bool>(rNewItem != rOldItem);
194 	}
195 
196 	return bInvalidate;
197 }
198 
199 sal_uLong ScGlobal::GetStandardFormat( SvNumberFormatter& rFormatter,
200 		sal_uLong nFormat, short nType )
201 {
202 	const SvNumberformat* pFormat = rFormatter.GetEntry( nFormat );
203 	if ( pFormat )
204 		return rFormatter.GetStandardFormat( nFormat, nType, pFormat->GetLanguage() );
205 	return rFormatter.GetStandardFormat( nType, eLnge );
206 }
207 
208 sal_uLong ScGlobal::GetStandardFormat( double fNumber, SvNumberFormatter& rFormatter,
209 		sal_uLong nFormat, short nType )
210 {
211 	const SvNumberformat* pFormat = rFormatter.GetEntry( nFormat );
212 	if ( pFormat )
213 		return rFormatter.GetStandardFormat( fNumber, nFormat, nType,
214 			pFormat->GetLanguage() );
215 	return rFormatter.GetStandardFormat( nType, eLnge );
216 }
217 
218 
219 // static
220 SvNumberFormatter* ScGlobal::GetEnglishFormatter()
221 {
222     if ( !pEnglishFormatter )
223     {
224         pEnglishFormatter = new SvNumberFormatter(
225             ::comphelper::getProcessServiceFactory(), LANGUAGE_ENGLISH_US );
226         pEnglishFormatter->SetEvalDateFormat( NF_EVALDATEFORMAT_INTL_FORMAT );
227     }
228     return pEnglishFormatter;
229 }
230 
231 
232 //------------------------------------------------------------------------
233 
234 sal_Bool ScGlobal::CheckWidthInvalidate( sal_Bool& bNumFormatChanged,
235 									 const SfxItemSet& rNewAttrs,
236 									 const SfxItemSet& rOldAttrs )
237 {
238 	// Ueberpruefen, ob Attributaenderungen in rNewAttrs gegnueber
239 	// rOldAttrs die Textbreite an einer Zelle ungueltig machen
240 
241 	bNumFormatChanged =
242 			HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_VALUE_FORMAT );
243 	return ( bNumFormatChanged
244 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_LANGUAGE_FORMAT )
245 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT )
246 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CJK_FONT )
247 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CTL_FONT )
248 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_HEIGHT )
249 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CJK_FONT_HEIGHT )
250 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CTL_FONT_HEIGHT )
251 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_WEIGHT )
252 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CJK_FONT_WEIGHT )
253 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CTL_FONT_WEIGHT )
254 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_POSTURE )
255 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CJK_FONT_POSTURE )
256 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_CTL_FONT_POSTURE )
257 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_UNDERLINE )
258 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_OVERLINE )
259 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_CROSSEDOUT )
260 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_CONTOUR )
261 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_SHADOWED )
262         || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_STACKED )
263 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_ROTATE_VALUE )
264 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_ROTATE_MODE )
265 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_LINEBREAK )
266 		|| HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_MARGIN )
267 		);
268 }
269 
270 const SvxSearchItem& ScGlobal::GetSearchItem()
271 {
272 	if (!pSearchItem)
273 	{
274 		pSearchItem = new SvxSearchItem( SID_SEARCH_ITEM );
275 		pSearchItem->SetAppFlag( SVX_SEARCHAPP_CALC );
276 	}
277 	return *pSearchItem;
278 }
279 
280 void ScGlobal::SetSearchItem( const SvxSearchItem& rNew )
281 {
282 	// Hier waere ein Zuweisungsoperator ganz nett:
283 	delete pSearchItem;
284 	pSearchItem	= (SvxSearchItem*)rNew.Clone();
285 
286 	pSearchItem->SetWhich( SID_SEARCH_ITEM );
287     pSearchItem->SetAppFlag( SVX_SEARCHAPP_CALC );
288 }
289 
290 void ScGlobal::ClearAutoFormat()
291 {
292 	if (pAutoFormat!=NULL)
293 	{
294 		delete pAutoFormat;
295 		pAutoFormat=NULL;
296 	}
297 }
298 
299 ScAutoFormat* ScGlobal::GetAutoFormat()
300 {
301 	if ( !pAutoFormat )
302 	{
303 		pAutoFormat = new ScAutoFormat;
304 		pAutoFormat->Load();
305 	}
306 
307 	return pAutoFormat;
308 }
309 
310 FuncCollection* ScGlobal::GetFuncCollection()
311 {
312 	if (!pFuncCollection)
313 		pFuncCollection = new FuncCollection();
314 	return pFuncCollection;
315 }
316 
317 ScUnoAddInCollection* ScGlobal::GetAddInCollection()
318 {
319 	if (!pAddInCollection)
320 		pAddInCollection = new ScUnoAddInCollection();
321 	return pAddInCollection;
322 }
323 
324 ScUserList* ScGlobal::GetUserList()
325 {
326 	// Hack: Cfg-Item an der App ggF. laden
327 
328 	global_InitAppOptions();
329 
330 	if (!pUserList)
331 		pUserList = new ScUserList();
332 	return pUserList;
333 }
334 
335 void ScGlobal::SetUserList( const ScUserList* pNewList )
336 {
337 	if ( pNewList )
338 	{
339 		if ( !pUserList )
340 			pUserList = new ScUserList( *pNewList );
341 		else
342 			*pUserList = *pNewList;
343 	}
344 	else
345 	{
346 		delete pUserList;
347 		pUserList = NULL;
348 	}
349 }
350 
351 const String& ScGlobal::GetRscString( sal_uInt16 nIndex )
352 {
353 	DBG_ASSERT( nIndex < STR_COUNT, "ScGlobal::GetRscString - invalid string index");
354 	if( !ppRscString[ nIndex ] )
355 	{
356         OpCode eOp = ocNone;
357         // Map former globstr.src strings moved to compiler.src
358         switch (nIndex)
359         {
360             case STR_NULL_ERROR:
361                 eOp = ocErrNull;
362                 break;
363             case STR_DIV_ZERO:
364                 eOp = ocErrDivZero;
365                 break;
366             case STR_NO_VALUE:
367                 eOp = ocErrValue;
368                 break;
369             case STR_NOREF_STR:
370                 eOp = ocErrRef;
371                 break;
372             case STR_NO_NAME_REF:
373                 eOp = ocErrName;
374                 break;
375             case STR_NUM_ERROR:
376                 eOp = ocErrNum;
377                 break;
378             case STR_NV_STR:
379                 eOp = ocErrNA;
380                 break;
381             default:
382                 ;   // nothing
383         }
384         if (eOp != ocNone)
385             ppRscString[ nIndex ] = new String(
386                     ScCompiler::GetNativeSymbol( eOp));
387         else
388             ppRscString[ nIndex ] = new String(
389                     ScRscStrLoader( RID_GLOBSTR, nIndex ).GetString());
390 	}
391 	return *ppRscString[ nIndex ];
392 }
393 
394 String ScGlobal::GetErrorString(sal_uInt16 nErrNumber)
395 {
396 	String sResStr;
397 	switch (nErrNumber)
398 	{
399 		case NOTAVAILABLE          : nErrNumber = STR_NV_STR; break;
400 		case errNoRef              : nErrNumber = STR_NO_REF_TABLE; break;
401 		case errNoName             : nErrNumber = STR_NO_NAME_REF; break;
402 		case errNoAddin            : nErrNumber = STR_NO_ADDIN; break;
403 		case errNoMacro            : nErrNumber = STR_NO_MACRO; break;
404 		case errDoubleRef          :
405 		case errNoValue            : nErrNumber = STR_NO_VALUE; break;
406 		case errNoCode             : nErrNumber = STR_NULL_ERROR; break;
407 		case errDivisionByZero     : nErrNumber = STR_DIV_ZERO; break;
408 		case errIllegalFPOperation : nErrNumber = STR_NUM_ERROR; break;
409 
410 		default		     : sResStr = GetRscString(STR_ERROR_STR);
411 						   sResStr += String::CreateFromInt32( nErrNumber );
412 						   nErrNumber = 0;
413 						   break;
414 	}
415 	if( nErrNumber )
416 		sResStr = GetRscString( nErrNumber );
417 	return sResStr;
418 }
419 
420 String ScGlobal::GetLongErrorString(sal_uInt16 nErrNumber)
421 {
422 	switch (nErrNumber)
423 	{
424 		case 0:
425 			break;
426 		case 1:
427 		case errIllegalArgument:
428 			nErrNumber = STR_LONG_ERR_ILL_ARG;
429 		break;
430 		case 2:
431 		case 3:
432 		case 4:
433 		case 5:
434 		case errIllegalFPOperation:
435 			nErrNumber = STR_LONG_ERR_ILL_FPO;
436 		break;
437 		case errIllegalChar:
438 			nErrNumber = STR_LONG_ERR_ILL_CHAR;
439 		break;
440 		case errIllegalParameter:
441 			nErrNumber = STR_LONG_ERR_ILL_PAR;
442 		break;
443 		case errSeparator:
444 			nErrNumber = STR_LONG_ERR_ILL_SEP;
445 		break;
446 		case errPair:
447 		case errPairExpected:
448 			nErrNumber = STR_LONG_ERR_PAIR;
449 		break;
450 		case errOperatorExpected:
451 			nErrNumber = STR_LONG_ERR_OP_EXP;
452 		break;
453 		case errVariableExpected:
454 		case errParameterExpected:
455 			nErrNumber = STR_LONG_ERR_VAR_EXP;
456 		break;
457 		case errCodeOverflow:
458 			nErrNumber = STR_LONG_ERR_CODE_OVF;
459 		break;
460 		case errStringOverflow:
461 			nErrNumber = STR_LONG_ERR_STR_OVF;
462 		break;
463 		case errStackOverflow:
464 		case errInterpOverflow:
465 			nErrNumber = STR_LONG_ERR_STACK_OVF;
466 		break;
467 		case errIllegalJump:
468 		case errUnknownState:
469 		case errUnknownVariable:
470 		case errUnknownOpCode:
471 		case errUnknownStackVariable:
472 		case errUnknownToken:
473 		case errNoCode:
474 		case errDoubleRef:
475 			nErrNumber = STR_LONG_ERR_SYNTAX;
476 		break;
477 		case errCircularReference:
478 			nErrNumber = STR_LONG_ERR_CIRC_REF;
479 		break;
480 		case errNoConvergence:
481 			nErrNumber = STR_LONG_ERR_NO_CONV;
482 		break;
483 		case errNoRef:
484 			nErrNumber = STR_LONG_ERR_NO_REF;
485 		break;
486 		case errNoName:
487 			nErrNumber = STR_LONG_ERR_NO_NAME;
488 		break;
489         case errNoAddin:
490             nErrNumber = STR_LONG_ERR_NO_ADDIN;
491 		break;
492         case errNoMacro:
493             nErrNumber = STR_LONG_ERR_NO_MACRO;
494 		break;
495         case errDivisionByZero:
496             nErrNumber = STR_LONG_ERR_DIV_ZERO;
497 		break;
498         case errNestedArray:
499             nErrNumber = STR_ERR_LONG_NESTED_ARRAY;
500         break;
501 		case errNoValue:
502 			nErrNumber = STR_LONG_ERR_NO_VALUE;
503 		break;
504 		case NOTAVAILABLE:
505 			nErrNumber = STR_LONG_ERR_NV;
506 		break;
507 		default:
508 			nErrNumber = STR_ERROR_STR;
509 		break;
510 	}
511 	String aRes( GetRscString( nErrNumber ) );
512 	return aRes;
513 }
514 
515 SvxBrushItem* ScGlobal::GetButtonBrushItem()
516 {
517     pButtonBrushItem->SetColor( Application::GetSettings().GetStyleSettings().GetFaceColor() );
518     return pButtonBrushItem;
519 }
520 
521 const String& ScGlobal::GetEmptyString()
522 {
523 	return *pEmptyString;
524 }
525 
526 ImageList* ScGlobal::GetOutlineSymbols( bool bHC )
527 {
528     ImageList*& rpImageList = bHC ? pOutlineBitmapsHC : pOutlineBitmaps;
529     if( !rpImageList )
530         rpImageList = new ImageList( ScResId( bHC ? RID_OUTLINEBITMAPS_H : RID_OUTLINEBITMAPS ) );
531     return rpImageList;
532 }
533 
534 void ScGlobal::Init()
535 {
536 	pEmptyString = new String;
537 
538 	//	Die Default-Sprache fuer Zahlenformate (ScGlobal::eLnge)
539 	//	muss immer LANGUAGE_SYSTEM sein
540 	//!	Dann kann auch die Variable raus
541 	eLnge = LANGUAGE_SYSTEM;
542 
543 	//!	Wenn Sortierung etc. von der Sprache der installierten Offfice-Version
544     //! abhaengen sollen, hier "Application::GetSettings().GetUILanguage()"
545     pSysLocale = new SvtSysLocale;
546     pCharClass = pSysLocale->GetCharClassPtr();
547     pLocaleData = pSysLocale->GetLocaleDataPtr();
548 
549 	ppRscString = new String *[ STR_COUNT ];
550 	for( sal_uInt16 nC = 0 ; nC < STR_COUNT ; nC++ ) ppRscString[ nC ] = NULL;
551 
552     pEmptyBrushItem = new SvxBrushItem( Color( COL_TRANSPARENT ), ATTR_BACKGROUND );
553     pButtonBrushItem = new SvxBrushItem( Color(), ATTR_BACKGROUND );
554     pEmbeddedBrushItem = new SvxBrushItem( Color( COL_LIGHTCYAN ), ATTR_BACKGROUND );
555     pProtectedBrushItem = new SvxBrushItem( Color( COL_LIGHTGRAY ), ATTR_BACKGROUND );
556 
557 	UpdatePPT(NULL);
558 	//ScCompiler::InitSymbolsNative();
559     // ScParameterClassification _after_ Compiler, needs function resources if
560     // arguments are to be merged in, which in turn need strings of function
561     // names from the compiler.
562     ScParameterClassification::Init();
563 	srand( (unsigned) time( NULL ) );		// Random Seed Init fuer Interpreter
564 
565 	InitAddIns();
566 
567 	pStrClipDocName = new String( ScResId( SCSTR_NONAME ) );
568 	*pStrClipDocName += '1';
569 
570 	//	ScDocumentPool::InitVersionMaps() ist schon vorher gerufen worden
571 }
572 
573 void ScGlobal::UpdatePPT( OutputDevice* pDev )
574 {
575 	sal_uInt16 nCurrentZoom = Application::GetSettings().GetStyleSettings().GetScreenZoom();
576 	if ( nCurrentZoom != nPPTZoom )
577 	{
578 		//	Screen PPT values must be updated when ScreenZoom has changed.
579 		//	If called from Window::DataChanged, the window is passed as pDev,
580 		//	to make sure LogicToPixel uses a device which already uses the new zoom.
581 		//	For the initial settings, NULL is passed and GetDefaultDevice used.
582 
583 		if ( !pDev )
584 			pDev = Application::GetDefaultDevice();
585 		Point aPix1000 = pDev->LogicToPixel( Point(1000,1000), MAP_TWIP );
586 		nScreenPPTX = aPix1000.X() / 1000.0;
587 		nScreenPPTY = aPix1000.Y() / 1000.0;
588 		nPPTZoom = nCurrentZoom;
589 	}
590 }
591 
592 const String& ScGlobal::GetClipDocName()
593 {
594 	return *pStrClipDocName;
595 }
596 
597 void ScGlobal::SetClipDocName( const String& rNew )
598 {
599 	*pStrClipDocName = rNew;
600 }
601 
602 
603 void ScGlobal::InitTextHeight(SfxItemPool* pPool)
604 {
605 	if (!pPool)
606 	{
607 		DBG_ERROR("kein Pool bei ScGlobal::InitTextHeight");
608 		return;
609 	}
610 
611 	const ScPatternAttr* pPattern = (const ScPatternAttr*)&pPool->GetDefaultItem(ATTR_PATTERN);
612 	if (!pPattern)
613 	{
614 		DBG_ERROR("kein Default-Pattern bei ScGlobal::InitTextHeight");
615 		return;
616 	}
617 
618 //	String aTestString('X');
619 	OutputDevice* pDefaultDev = Application::GetDefaultDevice();
620 	VirtualDevice aVirtWindow( *pDefaultDev );
621 	aVirtWindow.SetMapMode(MAP_PIXEL);
622 	Font aDefFont;
623 	pPattern->GetFont(aDefFont, SC_AUTOCOL_BLACK, &aVirtWindow);		// font color doesn't matter here
624 	aVirtWindow.SetFont(aDefFont);
625 	nDefFontHeight = (sal_uInt16) aVirtWindow.PixelToLogic(Size(0, aVirtWindow.GetTextHeight()),
626 								MAP_TWIP).Height();
627 
628 	const SvxMarginItem* pMargin = (const SvxMarginItem*)&pPattern->GetItem(ATTR_MARGIN);
629 
630 	nStdRowHeight = (sal_uInt16) ( nDefFontHeight +
631 								pMargin->GetTopMargin() + pMargin->GetBottomMargin()
632 								- STD_ROWHEIGHT_DIFF );
633 }
634 
635 void ScGlobal::Clear()
636 {
637 	// asyncs _vor_ ExitExternalFunc zerstoeren!
638 	theAddInAsyncTbl.DeleteAndDestroy( 0, theAddInAsyncTbl.Count() );
639 	ExitExternalFunc();
640 	DELETEZ(pAutoFormat);
641 	DELETEZ(pSearchItem);
642 	DELETEZ(pFuncCollection);
643 	DELETEZ(pAddInCollection);
644 	DELETEZ(pUserList);
645 
646 	for( sal_uInt16 nC = 0 ; nC < STR_COUNT ; nC++ )
647 		if( ppRscString ) delete ppRscString[ nC ];
648 	delete[] ppRscString;
649 	ppRscString = NULL;
650 
651 	DELETEZ(pStarCalcFunctionList);		// vor ResMgr zerstoeren!
652 	DELETEZ(pStarCalcFunctionMgr);
653     ScParameterClassification::Exit();
654 	ScCompiler::DeInit();
655 	ScInterpreter::GlobalExit();			// statischen Stack loeschen
656 
657 	DELETEZ(pEmptyBrushItem);
658 	DELETEZ(pButtonBrushItem);
659 	DELETEZ(pEmbeddedBrushItem);
660 	DELETEZ(pProtectedBrushItem);
661     DELETEZ(pOutlineBitmaps);
662     DELETEZ(pOutlineBitmapsHC);
663 //	DELETEZ(pAnchorBitmap);
664 //	DELETEZ(pGrayAnchorBitmap);
665     DELETEZ(pEnglishFormatter);
666     DELETEZ(pCaseTransliteration);
667     DELETEZ(pTransliteration);
668 	DELETEZ(pCaseCollator);
669 	DELETEZ(pCollator);
670 	DELETEZ(pCalendar);
671     //! do NOT delete pCharClass since it is a pointer to the single SvtSysLocale instance
672     pCharClass = NULL;
673     //! do NOT delete pLocaleData since it is a pointer to the single SvtSysLocale instance
674     pLocaleData = NULL;
675     DELETEZ(pSysLocale);
676 	DELETEZ(pLocale);
677     DELETEZ(pScIntlWrapper);
678 	DELETEZ(pStrClipDocName);
679 
680 	DELETEZ(pUnitConverter);
681 
682 	ScDocumentPool::DeleteVersionMaps();
683 
684 	DELETEZ(pEmptyString);
685 }
686 
687 //------------------------------------------------------------------------
688 
689 // static
690 CharSet ScGlobal::GetCharsetValue( const String& rCharSet )
691 {
692 	// new TextEncoding values
693 	if ( CharClass::isAsciiNumeric( rCharSet ) )
694 	{
695 		sal_Int32 nVal = rCharSet.ToInt32();
696 		if ( !nVal || nVal == RTL_TEXTENCODING_DONTKNOW )
697 			return gsl_getSystemTextEncoding();
698 		return (CharSet) nVal;
699 	}
700 	// old CharSet values for compatibility
701 	else if	(rCharSet.EqualsIgnoreCaseAscii("ANSI")		) return RTL_TEXTENCODING_MS_1252;
702 	else if (rCharSet.EqualsIgnoreCaseAscii("MAC")		) return RTL_TEXTENCODING_APPLE_ROMAN;
703 	else if (rCharSet.EqualsIgnoreCaseAscii("IBMPC")	) return RTL_TEXTENCODING_IBM_850;
704 	else if (rCharSet.EqualsIgnoreCaseAscii("IBMPC_437")) return RTL_TEXTENCODING_IBM_437;
705 	else if (rCharSet.EqualsIgnoreCaseAscii("IBMPC_850")) return RTL_TEXTENCODING_IBM_850;
706 	else if (rCharSet.EqualsIgnoreCaseAscii("IBMPC_860")) return RTL_TEXTENCODING_IBM_860;
707 	else if (rCharSet.EqualsIgnoreCaseAscii("IBMPC_861")) return RTL_TEXTENCODING_IBM_861;
708 	else if (rCharSet.EqualsIgnoreCaseAscii("IBMPC_863")) return RTL_TEXTENCODING_IBM_863;
709 	else if (rCharSet.EqualsIgnoreCaseAscii("IBMPC_865")) return RTL_TEXTENCODING_IBM_865;
710 //	else if (rCharSet.EqualsIgnoreCaseAscii("SYSTEM")	) return gsl_getSystemTextEncoding();
711 	else return gsl_getSystemTextEncoding();
712 }
713 
714 //------------------------------------------------------------------------
715 
716 // static
717 String ScGlobal::GetCharsetString( CharSet eVal )
718 {
719 	const sal_Char* pChar;
720 	switch ( eVal )
721 	{
722 		// old CharSet strings for compatibility
723 		case RTL_TEXTENCODING_MS_1252:		pChar = "ANSI";			break;
724 		case RTL_TEXTENCODING_APPLE_ROMAN:	pChar = "MAC";			break;
725 		// IBMPC == IBMPC_850
726 		case RTL_TEXTENCODING_IBM_437:		pChar = "IBMPC_437";	break;
727 		case RTL_TEXTENCODING_IBM_850:		pChar = "IBMPC_850";	break;
728 		case RTL_TEXTENCODING_IBM_860:		pChar = "IBMPC_860";	break;
729 		case RTL_TEXTENCODING_IBM_861:		pChar = "IBMPC_861";	break;
730 		case RTL_TEXTENCODING_IBM_863:		pChar = "IBMPC_863";	break;
731 		case RTL_TEXTENCODING_IBM_865:		pChar = "IBMPC_865";	break;
732 		case RTL_TEXTENCODING_DONTKNOW:		pChar = "SYSTEM";		break;
733 		// new string of TextEncoding value
734 		default:
735 			return String::CreateFromInt32( eVal );
736 	}
737 	return String::CreateFromAscii(pChar);
738 }
739 
740 //------------------------------------------------------------------------
741 
742 bool ScGlobal::HasStarCalcFunctionList()
743 {
744     return ( pStarCalcFunctionList != NULL );
745 }
746 
747 ScFunctionList* ScGlobal::GetStarCalcFunctionList()
748 {
749 	if ( !pStarCalcFunctionList )
750 		pStarCalcFunctionList = new	ScFunctionList;
751 
752 	return pStarCalcFunctionList;
753 }
754 
755 //------------------------------------------------------------------------
756 
757 ScFunctionMgr* ScGlobal::GetStarCalcFunctionMgr()
758 {
759 	if ( !pStarCalcFunctionMgr )
760 		pStarCalcFunctionMgr = new ScFunctionMgr;
761 
762 	return pStarCalcFunctionMgr;
763 }
764 
765 void ScGlobal::ResetFunctionList()
766 {
767     // FunctionMgr has pointers into FunctionList, must also be updated
768 
769     DELETEZ( pStarCalcFunctionMgr );
770     DELETEZ( pStarCalcFunctionList );
771 }
772 
773 //------------------------------------------------------------------------
774 
775 // static
776 ScUnitConverter* ScGlobal::GetUnitConverter()
777 {
778 	if ( !pUnitConverter )
779 		pUnitConverter = new ScUnitConverter;
780 
781 	return pUnitConverter;
782 }
783 
784 
785 //------------------------------------------------------------------------
786 
787 // static
788 const sal_Unicode* ScGlobal::UnicodeStrChr( const sal_Unicode* pStr,
789 			sal_Unicode c )
790 {
791 	if ( !pStr )
792 		return NULL;
793 	while ( *pStr )
794 	{
795 		if ( *pStr == c )
796 			return pStr;
797 		pStr++;
798 	}
799 	return NULL;
800 }
801 
802 // ----------------------------------------------------------------------------
803 
804 void ScGlobal::AddToken( String& rTokenList, const String& rToken, sal_Unicode cSep, xub_StrLen nSepCount, bool bForceSep )
805 {
806     if( bForceSep || (rToken.Len() && rTokenList.Len()) )
807         rTokenList.Expand( rTokenList.Len() + nSepCount, cSep );
808     rTokenList.Append( rToken );
809 }
810 
811 bool ScGlobal::IsQuoted( const String& rString, sal_Unicode cQuote )
812 {
813     return (rString.Len() >= 2) && (rString.GetChar( 0 ) == cQuote) && (rString.GetChar( rString.Len() - 1 ) == cQuote);
814 }
815 
816 void ScGlobal::AddQuotes( String& rString, sal_Unicode cQuote, bool bEscapeEmbedded )
817 {
818     if (bEscapeEmbedded)
819     {
820         sal_Unicode pQ[3];
821         pQ[0] = pQ[1] = cQuote;
822         pQ[2] = 0;
823         String aQuotes( pQ );
824         rString.SearchAndReplaceAll( cQuote, aQuotes);
825     }
826     rString.Insert( cQuote, 0 ).Append( cQuote );
827 }
828 
829 void ScGlobal::EraseQuotes( String& rString, sal_Unicode cQuote, bool bUnescapeEmbedded )
830 {
831     if ( IsQuoted( rString, cQuote ) )
832     {
833         rString.Erase( rString.Len() - 1 ).Erase( 0, 1 );
834         if (bUnescapeEmbedded)
835         {
836             sal_Unicode pQ[3];
837             pQ[0] = pQ[1] = cQuote;
838             pQ[2] = 0;
839             String aQuotes( pQ );
840             rString.SearchAndReplaceAll( aQuotes, cQuote);
841         }
842     }
843 }
844 
845 xub_StrLen ScGlobal::FindUnquoted( const String& rString, sal_Unicode cChar, xub_StrLen nStart, sal_Unicode cQuote )
846 {
847     const sal_Unicode* const pStart = rString.GetBuffer();
848     const sal_Unicode* const pStop = pStart + rString.Len();
849     const sal_Unicode* p = pStart + nStart;
850     bool bQuoted = false;
851     while (p < pStop)
852     {
853         if (*p == cChar && !bQuoted)
854             return sal::static_int_cast< xub_StrLen >( p - pStart );
855         else if (*p == cQuote)
856         {
857             if (!bQuoted)
858                 bQuoted = true;
859             else if (p < pStop-1 && *(p+1) == cQuote)
860                 ++p;
861             else
862                 bQuoted = false;
863         }
864         ++p;
865     }
866     return STRING_NOTFOUND;
867 }
868 
869 const sal_Unicode* ScGlobal::FindUnquoted( const sal_Unicode* pString, sal_Unicode cChar, sal_Unicode cQuote )
870 {
871     const sal_Unicode* p = pString;
872     bool bQuoted = false;
873     while (*p)
874     {
875         if (*p == cChar && !bQuoted)
876             return p;
877         else if (*p == cQuote)
878         {
879             if (!bQuoted)
880                 bQuoted = true;
881             else if (*(p+1) == cQuote)
882                 ++p;
883             else
884                 bQuoted = false;
885         }
886         ++p;
887     }
888     return NULL;
889 }
890 
891 //------------------------------------------------------------------------
892 
893 sal_Bool ScGlobal::EETextObjEqual( const EditTextObject* pObj1,
894 							   const EditTextObject* pObj2 )
895 {
896 	if ( pObj1 == pObj2 )				// both empty or the same object
897 		return sal_True;
898 
899 	if ( pObj1 && pObj2 )
900 	{
901 		//	first test for equal text content
902 		sal_uInt16 nParCount = pObj1->GetParagraphCount();
903 		if ( nParCount != pObj2->GetParagraphCount() )
904 			return sal_False;
905 		for (sal_uInt16 nPar=0; nPar<nParCount; nPar++)
906 			if ( pObj1->GetText(nPar) != pObj2->GetText(nPar) )
907 				return sal_False;
908 
909 		SvMemoryStream	aStream1;
910 		SvMemoryStream	aStream2;
911 		pObj1->Store( aStream1 );
912 		pObj2->Store( aStream2 );
913 		sal_uLong nSize = aStream1.Tell();
914 		if ( aStream2.Tell() == nSize )
915 			if ( !memcmp( aStream1.GetData(), aStream2.GetData(), (sal_uInt16) nSize ) )
916 				return sal_True;
917 	}
918 
919 	return sal_False;
920 }
921 
922 void ScGlobal::OpenURL( const String& rURL, const String& rTarget )
923 {
924 	//	OpenURL wird immer ueber irgendwelche Umwege durch Mausklicks im GridWindow
925 	//	aufgerufen, darum stimmen pScActiveViewShell und nScClickMouseModifier.
926 
927 	SfxStringItem aUrl( SID_FILE_NAME, rURL );
928 	SfxStringItem aTarget( SID_TARGETNAME, rTarget );
929 
930 	if ( nScClickMouseModifier & KEY_MOD1 )		// control-click -> into new window
931 		aTarget.SetValue(
932 			String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("_blank")) );
933 
934 	SfxViewFrame* pFrame = NULL;
935 	String aReferName;
936 	if ( pScActiveViewShell )
937 	{
938 		pFrame = pScActiveViewShell->GetViewFrame();
939 		SfxMedium* pMed = pFrame->GetObjectShell()->GetMedium();
940 		if (pMed)
941 			aReferName = pMed->GetName();
942 	}
943 
944 	SfxFrameItem aFrm( SID_DOCFRAME, pFrame );
945 	SfxStringItem aReferer( SID_REFERER, aReferName );
946 
947 	SfxBoolItem aNewView( SID_OPEN_NEW_VIEW, sal_False );
948 	SfxBoolItem aBrowsing( SID_BROWSE, sal_True );
949 
950 	//	kein SID_SILENT mehr wegen Bug #42525# (war angeblich sowieso falsch)
951 
952 	SfxViewFrame* pViewFrm = SfxViewFrame::Current();
953 	if (pViewFrm)
954 		pViewFrm->GetDispatcher()->Execute( SID_OPENDOC,
955 									SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD,
956 									&aUrl, &aTarget,
957 									&aFrm, &aReferer,
958 									&aNewView, &aBrowsing,
959 									0L );
960 }
961 
962 //------------------------------------------------------------------------
963 
964 sal_Bool ScGlobal::IsSystemRTL()
965 {
966     return MsLangId::isRightToLeft( Application::GetSettings().GetLanguage() );
967 }
968 
969 sal_uInt8 ScGlobal::GetDefaultScriptType()
970 {
971 	//	Used when text contains only WEAK characters.
972 	//	Script type of office language is used then (same as GetEditDefaultLanguage,
973 	//	to get consistent behavior of text in simple cells and EditEngine,
974 	//	also same as GetAppLanguage() in Writer)
975 
976 	return (sal_uInt8) SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguage() );
977 }
978 
979 LanguageType ScGlobal::GetEditDefaultLanguage()
980 {
981 	//	used for EditEngine::SetDefaultLanguage
982 
983 	return Application::GetSettings().GetLanguage();
984 }
985 
986 sal_uInt16 ScGlobal::GetScriptedWhichID( sal_uInt8 nScriptType, sal_uInt16 nWhich )
987 {
988     switch ( nScriptType )
989     {
990         case SCRIPTTYPE_LATIN:
991 	    case SCRIPTTYPE_ASIAN:
992         case SCRIPTTYPE_COMPLEX:
993         break;      // take exact matches
994         default:    // prefer one, first COMPLEX, then ASIAN
995             if ( nScriptType & SCRIPTTYPE_COMPLEX )
996                 nScriptType = SCRIPTTYPE_COMPLEX;
997             else if ( nScriptType & SCRIPTTYPE_ASIAN )
998                 nScriptType = SCRIPTTYPE_ASIAN;
999     }
1000     switch ( nScriptType )
1001     {
1002         case SCRIPTTYPE_COMPLEX:
1003         {
1004             switch ( nWhich )
1005             {
1006                 case ATTR_FONT:
1007                 case ATTR_CJK_FONT:
1008                     nWhich = ATTR_CTL_FONT;
1009                 break;
1010                 case ATTR_FONT_HEIGHT:
1011                 case ATTR_CJK_FONT_HEIGHT:
1012                     nWhich = ATTR_CTL_FONT_HEIGHT;
1013                 break;
1014                 case ATTR_FONT_WEIGHT:
1015                 case ATTR_CJK_FONT_WEIGHT:
1016                     nWhich = ATTR_CTL_FONT_WEIGHT;
1017                 break;
1018                 case ATTR_FONT_POSTURE:
1019                 case ATTR_CJK_FONT_POSTURE:
1020                     nWhich = ATTR_CTL_FONT_POSTURE;
1021                 break;
1022             }
1023         }
1024         break;
1025 	    case SCRIPTTYPE_ASIAN:
1026         {
1027             switch ( nWhich )
1028             {
1029                 case ATTR_FONT:
1030                 case ATTR_CTL_FONT:
1031                     nWhich = ATTR_CJK_FONT;
1032                 break;
1033                 case ATTR_FONT_HEIGHT:
1034                 case ATTR_CTL_FONT_HEIGHT:
1035                     nWhich = ATTR_CJK_FONT_HEIGHT;
1036                 break;
1037                 case ATTR_FONT_WEIGHT:
1038                 case ATTR_CTL_FONT_WEIGHT:
1039                     nWhich = ATTR_CJK_FONT_WEIGHT;
1040                 break;
1041                 case ATTR_FONT_POSTURE:
1042                 case ATTR_CTL_FONT_POSTURE:
1043                     nWhich = ATTR_CJK_FONT_POSTURE;
1044                 break;
1045             }
1046         }
1047         break;
1048         default:
1049         {
1050             switch ( nWhich )
1051             {
1052                 case ATTR_CTL_FONT:
1053                 case ATTR_CJK_FONT:
1054                     nWhich = ATTR_FONT;
1055                 break;
1056                 case ATTR_CTL_FONT_HEIGHT:
1057                 case ATTR_CJK_FONT_HEIGHT:
1058                     nWhich = ATTR_FONT_HEIGHT;
1059                 break;
1060                 case ATTR_CTL_FONT_WEIGHT:
1061                 case ATTR_CJK_FONT_WEIGHT:
1062                     nWhich = ATTR_FONT_WEIGHT;
1063                 break;
1064                 case ATTR_CTL_FONT_POSTURE:
1065                 case ATTR_CJK_FONT_POSTURE:
1066                     nWhich = ATTR_FONT_POSTURE;
1067                 break;
1068             }
1069         }
1070     }
1071     return nWhich;
1072 }
1073 
1074 //------------------------------------------------------------------------
1075 
1076 void ScGlobal::AddLanguage( SfxItemSet& rSet, SvNumberFormatter& rFormatter )
1077 {
1078     DBG_ASSERT( rSet.GetItemState( ATTR_LANGUAGE_FORMAT, sal_False ) == SFX_ITEM_DEFAULT,
1079         "ScGlobal::AddLanguage - language already added");
1080 
1081     const SfxPoolItem* pHardItem;
1082     if ( rSet.GetItemState( ATTR_VALUE_FORMAT, sal_False, &pHardItem ) == SFX_ITEM_SET )
1083     {
1084         const SvNumberformat* pHardFormat = rFormatter.GetEntry(
1085             ((const SfxUInt32Item*)pHardItem)->GetValue() );
1086 
1087         sal_uLong nParentFmt = 0;   // pool default
1088         const SfxItemSet* pParent = rSet.GetParent();
1089         if ( pParent )
1090             nParentFmt = ((const SfxUInt32Item&)pParent->Get( ATTR_VALUE_FORMAT )).GetValue();
1091         const SvNumberformat* pParFormat = rFormatter.GetEntry( nParentFmt );
1092 
1093         if ( pHardFormat && pParFormat &&
1094                 (pHardFormat->GetLanguage() != pParFormat->GetLanguage()) )
1095             rSet.Put( SvxLanguageItem( pHardFormat->GetLanguage(), ATTR_LANGUAGE_FORMAT ) );
1096     }
1097 }
1098 
1099 
1100 
1101 
1102 
1103 //===================================================================
1104 // class ScFunctionList:
1105 //===================================================================
1106 
1107 //===================================================================
1108 //		class ScFuncRes
1109 // fuer temporaere Objekte zum Holen der Resourcen
1110 
1111 class ScFuncRes : public Resource
1112 {
1113 public:
1114 	ScFuncRes( ResId&, ScFuncDesc*, bool & rbSuppressed );
1115 
1116 private:
1117 	sal_uInt16 GetNum();
1118 };
1119 
1120 //--------------------------------------------------------------------
1121 
1122 ScFuncRes::ScFuncRes( ResId &aRes, ScFuncDesc* pDesc, bool & rbSuppressed )
1123  : Resource(aRes)
1124 {
1125     rbSuppressed = (bool)GetNum();
1126 	pDesc->nCategory = GetNum();
1127 	pDesc->sHelpId = ReadByteStringRes();		//! Hack, see scfuncs.src
1128 	pDesc->nArgCount = GetNum();
1129 	sal_uInt16 nArgs = pDesc->nArgCount;
1130 	if (nArgs >= VAR_ARGS)
1131         nArgs -= VAR_ARGS - 1;
1132 	if (nArgs)
1133 	{
1134 		pDesc->pDefArgFlags = new ScFuncDesc::ParameterFlags[nArgs];
1135 		for (sal_uInt16 i = 0; i < nArgs; i++)
1136         {
1137             pDesc->pDefArgFlags[i].bOptional = (bool)GetNum();
1138         }
1139 	}
1140     // Need to read the value from the resource even if nArgs==0 to advance the
1141     // resource position pointer, so this can't be in the if(nArgs) block above.
1142     sal_uInt16 nSuppressed = GetNum();
1143     if (nSuppressed)
1144     {
1145         if (nSuppressed > nArgs)
1146         {
1147             DBG_ERROR3( "ScFuncRes: suppressed parameters count mismatch on OpCode %u: suppressed %d > params %d",
1148                     aRes.GetId(), (int)nSuppressed, (int)nArgs);
1149             nSuppressed = nArgs;    // sanitize
1150         }
1151         for (sal_uInt16 i=0; i < nSuppressed; ++i)
1152         {
1153             sal_uInt16 nParam = GetNum();
1154             if (nParam < nArgs)
1155             {
1156                 if (pDesc->nArgCount >= VAR_ARGS && nParam == nArgs-1)
1157                 {
1158                     DBG_ERROR3( "ScFuncRes: VAR_ARGS parameters can't be suppressed, on OpCode %u: param %d == arg %d-1",
1159                             aRes.GetId(), (int)nParam, (int)nArgs);
1160                 }
1161                 else
1162                 {
1163                     pDesc->pDefArgFlags[nParam].bSuppress = true;
1164                     pDesc->bHasSuppressedArgs = true;
1165                 }
1166             }
1167             else
1168             {
1169                 DBG_ERROR3( "ScFuncRes: suppressed parameter exceeds count on OpCode %u: param %d >= args %d",
1170                         aRes.GetId(), (int)nParam, (int)nArgs);
1171             }
1172         }
1173     }
1174 
1175     pDesc->pFuncName = new String( ScCompiler::GetNativeSymbol( static_cast<OpCode>( aRes.GetId())));
1176 	pDesc->pFuncDesc = new String(ScResId(1));
1177 
1178 	if (nArgs)
1179 	{
1180 		pDesc->ppDefArgNames = new String*[nArgs];
1181 		pDesc->ppDefArgDescs = new String*[nArgs];
1182 		for (sal_uInt16 i = 0; i < nArgs; i++)
1183 		{
1184 			pDesc->ppDefArgNames[i] = new String(ScResId(2*(i+1)  ));
1185 			pDesc->ppDefArgDescs[i] = new String(ScResId(2*(i+1)+1));
1186 		}
1187 	}
1188 
1189 	FreeResource();
1190 }
1191 
1192 //------------------------------------------------------------------------
1193 
1194 sal_uInt16 ScFuncRes::GetNum()
1195 {
1196 	return ReadShortRes();
1197 }
1198 
1199 //=========================================================================
1200 
1201 // um an die protected von Resource ranzukommen
1202 class ScResourcePublisher : public Resource
1203 {
1204 private:
1205     void			FreeResource() { Resource::FreeResource(); }
1206 public:
1207 		ScResourcePublisher( const ScResId& rId ) : Resource( rId ) {}
1208         ~ScResourcePublisher() { FreeResource(); }
1209 	sal_Bool			IsAvailableRes( const ResId& rId ) const
1210 						{ return Resource::IsAvailableRes( rId ); }
1211 
1212 };
1213 
1214 
1215 ScFunctionList::ScFunctionList() :
1216 		nMaxFuncNameLen	( 0 )
1217 {
1218 	ScFuncDesc*		pDesc	= NULL;
1219 	xub_StrLen		nStrLen = 0;
1220 	FuncCollection*	pFuncColl;
1221 	sal_uInt16 i,j;
1222 	sal_uInt16 nDescBlock[] =
1223 	{
1224 		RID_SC_FUNCTION_DESCRIPTIONS1,
1225 		RID_SC_FUNCTION_DESCRIPTIONS2
1226 	};
1227 	const sal_uInt16 nBlocks = sizeof(nDescBlock) / sizeof(sal_uInt16);
1228 
1229 	aFunctionList.Clear();
1230 
1231 	for ( sal_uInt16 k = 0; k < nBlocks; k++ )
1232 	{
1233         ::std::auto_ptr<ScResourcePublisher> pBlock( new ScResourcePublisher( ScResId( nDescBlock[k] ) ) );
1234         // Browse for all possible OpCodes. This is not the fastest method, but
1235         // otherwise the sub resources within the resource blocks and the
1236         // resource blocks themselfs would had to be ordered according to
1237         // OpCodes, which is utopian..
1238 		for (i = 0; i <= SC_OPCODE_LAST_OPCODE_ID; i++)
1239 		{
1240 			ScResId aRes(i);
1241 			aRes.SetRT(RSC_RESOURCE);
1242             // Sub resource of OpCode available?
1243 			if (pBlock->IsAvailableRes(aRes))
1244 			{
1245 				pDesc = new ScFuncDesc;
1246                 bool bSuppressed = false;
1247 				ScFuncRes aSubRes( aRes, pDesc, bSuppressed);
1248                 // Instead of dealing with this exceptional case at 1001 places
1249                 // we simply don't add an entirely suppressed function to the
1250                 // list and delete it.
1251                 if (bSuppressed)
1252                     delete pDesc;
1253                 else
1254                 {
1255                     pDesc->nFIndex = i;
1256                     aFunctionList.Insert( pDesc, LIST_APPEND );
1257 
1258                     nStrLen = (*(pDesc->pFuncName)).Len();
1259                     if (nStrLen > nMaxFuncNameLen)
1260                         nMaxFuncNameLen = nStrLen;
1261                 }
1262 			}
1263 		}
1264 	}
1265 
1266 	sal_uInt16 nNextId = SC_OPCODE_LAST_OPCODE_ID + 1;		// FuncID for AddIn functions
1267 
1268 	// Auswertung AddIn-Liste
1269 	String aDefArgNameValue(RTL_CONSTASCII_STRINGPARAM("value"));
1270 	String aDefArgNameString(RTL_CONSTASCII_STRINGPARAM("string"));
1271 	String aDefArgNameValues(RTL_CONSTASCII_STRINGPARAM("values"));
1272 	String aDefArgNameStrings(RTL_CONSTASCII_STRINGPARAM("strings"));
1273 	String aDefArgNameCells(RTL_CONSTASCII_STRINGPARAM("cells"));
1274 	String aDefArgNameNone(RTL_CONSTASCII_STRINGPARAM("none"));
1275 	String aDefArgDescValue(RTL_CONSTASCII_STRINGPARAM("a value"));
1276 	String aDefArgDescString(RTL_CONSTASCII_STRINGPARAM("a string"));
1277 	String aDefArgDescValues(RTL_CONSTASCII_STRINGPARAM("array of values"));
1278 	String aDefArgDescStrings(RTL_CONSTASCII_STRINGPARAM("array of strings"));
1279 	String aDefArgDescCells(RTL_CONSTASCII_STRINGPARAM("range of cells"));
1280 	String aDefArgDescNone(RTL_CONSTASCII_STRINGPARAM("none"));
1281 	String aArgName, aArgDesc;
1282 	pFuncColl = ScGlobal::GetFuncCollection();
1283 	for (i = 0; i < pFuncColl->GetCount(); i++)
1284 	{
1285 		pDesc = new ScFuncDesc;
1286 		FuncData *pAddInFuncData = (FuncData*)pFuncColl->At(i);
1287 		sal_uInt16 nArgs = pAddInFuncData->GetParamCount() - 1;
1288 		pAddInFuncData->GetParamDesc( aArgName, aArgDesc, 0 );
1289 		  pDesc->nFIndex     = nNextId++;				//  ??? OpCode vergeben
1290 		  pDesc->nCategory   = ID_FUNCTION_GRP_ADDINS;
1291 		  pDesc->pFuncName   = new String(pAddInFuncData->GetInternalName());
1292 		  pDesc->pFuncName->ToUpperAscii();
1293 		  pDesc->pFuncDesc   = new String( aArgDesc );
1294 		*(pDesc->pFuncDesc) += '\n';
1295 		  pDesc->pFuncDesc->AppendAscii(RTL_CONSTASCII_STRINGPARAM( "( AddIn: " ));
1296 		*(pDesc->pFuncDesc) += pAddInFuncData->GetModuleName();
1297 		  pDesc->pFuncDesc->AppendAscii(RTL_CONSTASCII_STRINGPARAM( " )" ));
1298 		  pDesc->nArgCount   = nArgs;
1299 		if (nArgs)
1300 		{
1301 			pDesc->pDefArgFlags  = new ScFuncDesc::ParameterFlags[nArgs];
1302 			pDesc->ppDefArgNames = new String*[nArgs];
1303 			pDesc->ppDefArgDescs = new String*[nArgs];
1304 			for (j = 0; j < nArgs; j++)
1305 			{
1306 				pDesc->pDefArgFlags[j].bOptional = false;
1307                 pDesc->pDefArgFlags[j].bSuppress = false;
1308 				pAddInFuncData->GetParamDesc( aArgName, aArgDesc, j+1 );
1309 				if ( aArgName.Len() )
1310 					pDesc->ppDefArgNames[j] = new String( aArgName );
1311 				else
1312 				{
1313 					switch (pAddInFuncData->GetParamType(j+1))
1314 					{
1315 						case PTR_DOUBLE:
1316 							pDesc->ppDefArgNames[j] = new String( aDefArgNameValue );
1317 							break;
1318 						case PTR_STRING:
1319 							pDesc->ppDefArgNames[j] = new String( aDefArgNameString );
1320 							break;
1321 						case PTR_DOUBLE_ARR:
1322 							pDesc->ppDefArgNames[j] = new String( aDefArgNameValues );
1323 							break;
1324 						case PTR_STRING_ARR:
1325 							pDesc->ppDefArgNames[j] = new String( aDefArgNameStrings );
1326 							break;
1327 						case PTR_CELL_ARR:
1328 							pDesc->ppDefArgNames[j] = new String( aDefArgNameCells );
1329 							break;
1330 						default:
1331 							pDesc->ppDefArgNames[j] = new String( aDefArgNameNone );
1332 							break;
1333 					}
1334 				}
1335 				if ( aArgDesc.Len() )
1336 					pDesc->ppDefArgDescs[j] = new String( aArgDesc );
1337 				else
1338 				{
1339 					switch (pAddInFuncData->GetParamType(j+1))
1340 					{
1341 						case PTR_DOUBLE:
1342 							pDesc->ppDefArgDescs[j] = new String( aDefArgDescValue );
1343 							break;
1344 						case PTR_STRING:
1345 							pDesc->ppDefArgDescs[j] = new String( aDefArgDescString );
1346 							break;
1347 						case PTR_DOUBLE_ARR:
1348 							pDesc->ppDefArgDescs[j] = new String( aDefArgDescValues );
1349 							break;
1350 						case PTR_STRING_ARR:
1351 							pDesc->ppDefArgDescs[j] = new String( aDefArgDescStrings );
1352 							break;
1353 						case PTR_CELL_ARR:
1354 							pDesc->ppDefArgDescs[j] = new String( aDefArgDescCells );
1355 							break;
1356 						default:
1357 							pDesc->ppDefArgDescs[j] = new String( aDefArgDescNone );
1358 							break;
1359 					}
1360 				}
1361 			}
1362 		}
1363 //		pDesc->nHelpId    = 0;
1364 
1365 		aFunctionList.Insert(pDesc, LIST_APPEND);
1366 		nStrLen = (*(pDesc->pFuncName)).Len();
1367 		if ( nStrLen > nMaxFuncNameLen)
1368 			nMaxFuncNameLen = nStrLen;
1369 	}
1370 
1371 	//	StarOne AddIns
1372 
1373 	ScUnoAddInCollection* pUnoAddIns = ScGlobal::GetAddInCollection();
1374 	long nUnoCount = pUnoAddIns->GetFuncCount();
1375 	for (long nFunc=0; nFunc<nUnoCount; nFunc++)
1376 	{
1377 		pDesc = new ScFuncDesc;
1378 		pDesc->nFIndex = nNextId++;
1379 
1380 		if ( pUnoAddIns->FillFunctionDesc( nFunc, *pDesc ) )
1381 		{
1382 			aFunctionList.Insert(pDesc, LIST_APPEND);
1383 			nStrLen = (*(pDesc->pFuncName)).Len();
1384 			if (nStrLen > nMaxFuncNameLen)
1385 				nMaxFuncNameLen = nStrLen;
1386 		}
1387 		else
1388 			delete pDesc;
1389 	}
1390 }
1391 
1392 //------------------------------------------------------------------------
1393 
1394 ScFunctionList::~ScFunctionList()
1395 {
1396 	const ScFuncDesc* pDesc = First();
1397 	while (pDesc)
1398 	{
1399 		delete pDesc;
1400 		pDesc = Next();
1401 	}
1402 }
1403 
1404 
1405 //========================================================================
1406 // class ScFuncDesc:
1407 
1408 ScFuncDesc::ScFuncDesc() :
1409         pFuncName       (NULL),
1410         pFuncDesc       (NULL),
1411         ppDefArgNames   (NULL),
1412         ppDefArgDescs   (NULL),
1413         pDefArgFlags    (NULL),
1414         nFIndex         (0),
1415         nCategory       (0),
1416         nArgCount       (0),
1417         bIncomplete     (false),
1418         bHasSuppressedArgs(false)
1419 {}
1420 
1421 //------------------------------------------------------------------------
1422 
1423 ScFuncDesc::~ScFuncDesc()
1424 {
1425     Clear();
1426 }
1427 
1428 //------------------------------------------------------------------------
1429 
1430 void ScFuncDesc::Clear()
1431 {
1432     sal_uInt16 nArgs = nArgCount;
1433     if (nArgs >= VAR_ARGS) nArgs -= VAR_ARGS-1;
1434     if (nArgs)
1435     {
1436         for (sal_uInt16 i=0; i<nArgs; i++ )
1437         {
1438             delete ppDefArgNames[i];
1439             delete ppDefArgDescs[i];
1440         }
1441         delete [] ppDefArgNames;
1442         delete [] ppDefArgDescs;
1443         delete [] pDefArgFlags;
1444     }
1445     nArgCount = 0;
1446     ppDefArgNames = NULL;
1447     ppDefArgDescs = NULL;
1448     pDefArgFlags = NULL;
1449 
1450     delete pFuncName;
1451     pFuncName = NULL;
1452 
1453     delete pFuncDesc;
1454     pFuncDesc = NULL;
1455 
1456     nFIndex = 0;
1457     nCategory = 0;
1458     sHelpId = "";
1459     bIncomplete = false;
1460     bHasSuppressedArgs = false;
1461 }
1462 
1463 //------------------------------------------------------------------------
1464 
1465 String ScFuncDesc::GetParamList() const
1466 {
1467     const String& sep = ScCompiler::GetNativeSymbol(ocSep);
1468 
1469     String aSig;
1470 
1471     if ( nArgCount > 0 )
1472     {
1473         if ( nArgCount < VAR_ARGS )
1474         {
1475             sal_uInt16 nLastSuppressed = nArgCount;
1476             sal_uInt16 nLastAdded = nArgCount;
1477             for ( sal_uInt16 i=0; i<nArgCount; i++ )
1478             {
1479                 if (pDefArgFlags[i].bSuppress)
1480                     nLastSuppressed = i;
1481                 else
1482                 {
1483                     nLastAdded = i;
1484                     aSig += *(ppDefArgNames[i]);
1485                     if ( i != nArgCount-1 )
1486                     {
1487                         aSig.Append(sep);
1488                         aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " " ));
1489                     }
1490                 }
1491             }
1492             // If only suppressed parameters follow the last added parameter,
1493             // remove one "; "
1494             if (nLastSuppressed < nArgCount && nLastAdded < nLastSuppressed &&
1495                     aSig.Len() >= 2)
1496                 aSig.Erase( aSig.Len() - 2 );
1497         }
1498         else
1499         {
1500             sal_uInt16 nFix = nArgCount - VAR_ARGS;
1501             for ( sal_uInt16 nArg = 0; nArg < nFix; nArg++ )
1502             {
1503                 if (!pDefArgFlags[nArg].bSuppress)
1504                 {
1505                     aSig += *(ppDefArgNames[nArg]);
1506                     aSig.Append(sep);
1507                     aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " " ));
1508                 }
1509             }
1510             /* NOTE: Currently there are no suppressed var args parameters. If
1511              * there were, we'd have to cope with it here and above for the fix
1512              * parameters. For now parameters are always added, so no special
1513              * treatment of a trailing "; " necessary. */
1514             aSig += *(ppDefArgNames[nFix]);
1515             aSig += '1';
1516             aSig.Append(sep);
1517             aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " " ));
1518             aSig += *(ppDefArgNames[nFix]);
1519             aSig += '2';
1520             aSig.Append(sep);
1521             aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " ... " ));
1522         }
1523     }
1524 
1525     return aSig;
1526 }
1527 
1528 //------------------------------------------------------------------------
1529 
1530 String ScFuncDesc::GetSignature() const
1531 {
1532 	String aSig;
1533 
1534 	if(pFuncName)
1535 	{
1536 		aSig = *pFuncName;
1537 
1538         String aParamList( GetParamList() );
1539         if( aParamList.Len() )
1540         {
1541 			aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "( " ));
1542             aSig.Append( aParamList );
1543             // U+00A0 (NBSP) prevents automatic line break
1544             aSig.Append( static_cast< sal_Unicode >(0xA0) ).Append( ')' );
1545 		}
1546 		else
1547 			aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "()" ));
1548 	}
1549 	return aSig;
1550 }
1551 
1552 //------------------------------------------------------------------------
1553 
1554 ::rtl::OUString ScFuncDesc::getFormula( const ::std::vector< ::rtl::OUString >& _aArguments ) const
1555 {
1556     const String& sep = ScCompiler::GetNativeSymbol(ocSep);
1557 
1558 	::rtl::OUStringBuffer aFormula;
1559 
1560 	if(pFuncName)
1561 	{
1562 		aFormula.append( *pFuncName );
1563 
1564 		aFormula.appendAscii( "(" );
1565         ::std::vector< ::rtl::OUString >::const_iterator aIter = _aArguments.begin();
1566         ::std::vector< ::rtl::OUString >::const_iterator aEnd = _aArguments.end();
1567 
1568 		if ( nArgCount > 0 && aIter != aEnd )
1569 		{
1570 			sal_Bool bLastArg = ( aIter->getLength() == 0 );
1571 
1572             while( aIter != aEnd && !bLastArg )
1573             {
1574 				aFormula.append( *(aIter) );
1575                 if ( aIter != (aEnd-1) )
1576 				{
1577 					bLastArg = !( (aIter+1)->getLength() > 0 );
1578 					if ( !bLastArg )
1579 						aFormula.append( sep );
1580 				}
1581 
1582                 ++aIter;
1583 			}
1584 		}
1585 
1586 		aFormula.appendAscii( ")" );
1587 	}
1588 	return aFormula.makeStringAndClear();
1589 }
1590 
1591 //------------------------------------------------------------------------
1592 
1593 sal_uInt16 ScFuncDesc::GetSuppressedArgCount() const
1594 {
1595     if (!bHasSuppressedArgs || !pDefArgFlags)
1596         return nArgCount;
1597 
1598     sal_uInt16 nArgs = nArgCount;
1599     if (nArgs >= VAR_ARGS)
1600         nArgs -= VAR_ARGS - 1;
1601     sal_uInt16 nCount = nArgs;
1602     for (sal_uInt16 i=0; i < nArgs; ++i)
1603     {
1604         if (pDefArgFlags[i].bSuppress)
1605             --nCount;
1606     }
1607     if (nArgCount >= VAR_ARGS)
1608         nCount += VAR_ARGS - 1;
1609     return nCount;
1610 }
1611 
1612 //------------------------------------------------------------------------
1613 
1614 ::rtl::OUString ScFuncDesc::getFunctionName() const
1615 {
1616     ::rtl::OUString sRet;
1617     if ( pFuncName )
1618         sRet = *pFuncName;
1619     return sRet;
1620 }
1621 // -----------------------------------------------------------------------------
1622 const formula::IFunctionCategory* ScFuncDesc::getCategory() const
1623 {
1624     return ScGlobal::GetStarCalcFunctionMgr()->getCategory(nCategory);
1625 }
1626 // -----------------------------------------------------------------------------
1627 ::rtl::OUString ScFuncDesc::getDescription() const
1628 {
1629     ::rtl::OUString sRet;
1630     if ( pFuncDesc )
1631         sRet = *pFuncDesc;
1632     return sRet;
1633 }
1634 // -----------------------------------------------------------------------------
1635 // GetSuppressedArgCount
1636 xub_StrLen ScFuncDesc::getSuppressedArgumentCount() const
1637 {
1638     return GetSuppressedArgCount();
1639 }
1640 // -----------------------------------------------------------------------------
1641 //
1642 void ScFuncDesc::fillVisibleArgumentMapping(::std::vector<sal_uInt16>& _rArguments) const
1643 {
1644     if (!bHasSuppressedArgs || !pDefArgFlags)
1645     {
1646         _rArguments.resize( nArgCount);
1647         ::std::iota( _rArguments.begin(), _rArguments.end(), 0);
1648     }
1649 
1650     _rArguments.reserve( nArgCount);
1651     sal_uInt16 nArgs = nArgCount;
1652     if (nArgs >= VAR_ARGS)
1653         nArgs -= VAR_ARGS - 1;
1654     for (sal_uInt16 i=0; i < nArgs; ++i)
1655     {
1656         if (!pDefArgFlags[i].bSuppress)
1657             _rArguments.push_back(i);
1658     }
1659 }
1660 // -----------------------------------------------------------------------------
1661 void ScFuncDesc::initArgumentInfo()  const
1662 {
1663     // get the full argument description
1664     // (add-in has to be instantiated to get the type information)
1665 
1666     if ( bIncomplete && pFuncName )
1667     {
1668         ScUnoAddInCollection& rAddIns = *ScGlobal::GetAddInCollection();
1669         String aIntName = rAddIns.FindFunction( *pFuncName, sal_True );         // pFuncName is upper-case
1670 
1671         if ( aIntName.Len() )
1672         {
1673             // GetFuncData with bComplete=true loads the component and updates
1674             // the global function list if needed.
1675 
1676             rAddIns.GetFuncData( aIntName, true );
1677         }
1678 
1679         if ( bIncomplete )
1680         {
1681             DBG_ERRORFILE( "couldn't initialize add-in function" );
1682             const_cast<ScFuncDesc*>(this)->bIncomplete = sal_False;         // even if there was an error, don't try again
1683         }
1684     }
1685 }
1686 // -----------------------------------------------------------------------------
1687 ::rtl::OUString ScFuncDesc::getSignature() const
1688 {
1689     return GetSignature();
1690 }
1691 // -----------------------------------------------------------------------------
1692 rtl::OString ScFuncDesc::getHelpId() const
1693 {
1694     return sHelpId;
1695 }
1696 // -----------------------------------------------------------------------------
1697 
1698 // parameter
1699 sal_uInt32 ScFuncDesc::getParameterCount() const
1700 {
1701     return nArgCount;
1702 }
1703 // -----------------------------------------------------------------------------
1704 ::rtl::OUString ScFuncDesc::getParameterName(sal_uInt32 _nPos) const
1705 {
1706     return *(ppDefArgNames[_nPos]);
1707 }
1708 // -----------------------------------------------------------------------------
1709 ::rtl::OUString ScFuncDesc::getParameterDescription(sal_uInt32 _nPos) const
1710 {
1711     return *(ppDefArgDescs[_nPos]);
1712 }
1713 // -----------------------------------------------------------------------------
1714 bool ScFuncDesc::isParameterOptional(sal_uInt32 _nPos) const
1715 {
1716     return pDefArgFlags[_nPos].bOptional;
1717 }
1718 // -----------------------------------------------------------------------------
1719 //========================================================================
1720 // class ScFunctionMgr:
1721 
1722 ScFunctionMgr::ScFunctionMgr()
1723 	:	pFuncList	( ScGlobal::GetStarCalcFunctionList() ),
1724 		pCurCatList	( NULL )
1725 {
1726 	DBG_ASSERT( pFuncList, "Funktionsliste nicht gefunden." );
1727 	sal_uLong		nCount	= pFuncList->GetCount();
1728 	const ScFuncDesc*	pDesc;
1729 	List*		pRootList;
1730 	sal_uLong		n;
1731 
1732 	for ( sal_uInt16 i=0; i<MAX_FUNCCAT; i++ )					// Kategorie-Listen erstellen
1733 		aCatLists[i] = new List;
1734 
1735 	pRootList = aCatLists[0];								// Gesamtliste ("Alle") erstellen
1736     CollatorWrapper* pCaseCollator = ScGlobal::GetCaseCollator();
1737 	for ( n=0; n<nCount; n++ )
1738 	{
1739 		sal_uLong nTmpCnt=0;
1740 		pDesc = pFuncList->GetFunction(n);
1741 		for (nTmpCnt = 0; nTmpCnt < n; nTmpCnt++)
1742 		{
1743 			// ist zwar case-sensitiv, aber Umlaute muessen richtig einsortiert werden
1744 
1745 			const ScFuncDesc*	pTmpDesc = (const ScFuncDesc*)pRootList->GetObject(nTmpCnt);
1746 			if ( pCaseCollator->compareString(*pDesc->pFuncName, *pTmpDesc->pFuncName ) == COMPARE_LESS )
1747 				break;
1748 		}
1749 		pRootList->Insert((void*)pDesc, nTmpCnt);					// Einsortieren
1750 	}
1751 
1752 	for ( n=0; n<nCount; n++ )								// in Gruppenlisten kopieren
1753 	{
1754 		pDesc = (const ScFuncDesc*)pRootList->GetObject(n);
1755 		DBG_ASSERT((pDesc->nCategory) < MAX_FUNCCAT, "Unbekannte Kategorie");
1756 		if ((pDesc->nCategory) < MAX_FUNCCAT)
1757 			aCatLists[pDesc->nCategory]->Insert((void*)pDesc, LIST_APPEND);
1758 	}
1759 }
1760 
1761 //------------------------------------------------------------------------
1762 
1763 ScFunctionMgr::~ScFunctionMgr()
1764 {
1765 	for (sal_uInt16 i = 0; i < MAX_FUNCCAT; i++)
1766 		delete aCatLists[i];
1767 //  delete pFuncList;       // Macht spaeter die App
1768 }
1769 
1770 //------------------------------------------------------------------------
1771 
1772 const ScFuncDesc* ScFunctionMgr::Get( const String& rFName ) const
1773 {
1774 	const ScFuncDesc*	pDesc = NULL;
1775 	if (rFName.Len() <= pFuncList->GetMaxFuncNameLen())
1776 		for (pDesc = First(0); pDesc; pDesc = Next())
1777 			if (rFName.EqualsIgnoreCaseAscii(*(pDesc->pFuncName)))
1778 				break;
1779 	return pDesc;
1780 }
1781 
1782 //------------------------------------------------------------------------
1783 
1784 const ScFuncDesc* ScFunctionMgr::Get( sal_uInt16 nFIndex ) const
1785 {
1786 	const ScFuncDesc*	pDesc;
1787 	for (pDesc = First(0); pDesc; pDesc = Next())
1788 		if (pDesc->nFIndex == nFIndex)
1789 			break;
1790 	return pDesc;
1791 }
1792 
1793 //------------------------------------------------------------------------
1794 
1795 const ScFuncDesc*	ScFunctionMgr::First( sal_uInt16 nCategory ) const
1796 {
1797 	DBG_ASSERT( nCategory < MAX_FUNCCAT, "Unbekannte Kategorie" );
1798 
1799 	if ( nCategory < MAX_FUNCCAT )
1800 	{
1801 		pCurCatList = aCatLists[nCategory];
1802 		return (const ScFuncDesc*)pCurCatList->First();
1803 	}
1804 	else
1805 	{
1806 		pCurCatList = NULL;
1807 		return NULL;
1808 	}
1809 }
1810 
1811 //------------------------------------------------------------------------
1812 
1813 const ScFuncDesc* ScFunctionMgr::Next() const
1814 {
1815 	if ( pCurCatList )
1816 		return (const ScFuncDesc*)pCurCatList->Next();
1817 	else
1818 		return NULL;
1819 }
1820 sal_uInt32 ScFunctionMgr::getCount() const
1821 {
1822     return MAX_FUNCCAT - 1;
1823 }
1824 const formula::IFunctionCategory* ScFunctionMgr::getCategory(sal_uInt32 nCategory) const
1825 {
1826     formula::IFunctionCategory* pRet = NULL;
1827     if ( nCategory < (MAX_FUNCCAT-1) )
1828 	{
1829 		 pRet = new ScFunctionCategory(const_cast<ScFunctionMgr*>(this),aCatLists[nCategory+1],nCategory); // aCatLists[0] is "all"
1830     }
1831     return pRet;
1832 }
1833 // -----------------------------------------------------------------------------
1834 const formula::IFunctionDescription* ScFunctionMgr::getFunctionByName(const ::rtl::OUString& _sFunctionName) const
1835 {
1836     return Get(_sFunctionName);
1837 }
1838 // -----------------------------------------------------------------------------
1839 void ScFunctionMgr::fillLastRecentlyUsedFunctions(::std::vector< const formula::IFunctionDescription*>& _rLastRUFunctions) const
1840 {
1841 #define LRU_MAX 10
1842 
1843     const ScAppOptions& rAppOpt = SC_MOD()->GetAppOptions();
1844 	sal_uInt16 nLRUFuncCount = Min( rAppOpt.GetLRUFuncListCount(), (sal_uInt16)LRU_MAX );
1845 	sal_uInt16*	pLRUListIds = rAppOpt.GetLRUFuncList();
1846 
1847 	if ( pLRUListIds )
1848 	{
1849 		for ( sal_uInt16 i=0; i<nLRUFuncCount; i++ )
1850 			_rLastRUFunctions.push_back( Get( pLRUListIds[i] ) );
1851 	}
1852 }
1853 // -----------------------------------------------------------------------------
1854 String ScFunctionMgr::GetCategoryName(sal_uInt32 _nCategoryNumber )
1855 {
1856     if ( _nCategoryNumber > SC_FUNCGROUP_COUNT )
1857     {
1858         DBG_ERROR("Invalid category number!");
1859         return String();
1860     } // if ( _nCategoryNumber >= SC_FUNCGROUP_COUNT )
1861 
1862     ::std::auto_ptr<ScResourcePublisher> pCategories( new ScResourcePublisher( ScResId( RID_FUNCTION_CATEGORIES ) ) );
1863     return String(ScResId((sal_uInt16)_nCategoryNumber));
1864 }
1865 sal_Unicode ScFunctionMgr::getSingleToken(const formula::IFunctionManager::EToken _eToken) const
1866 {
1867     switch(_eToken)
1868     {
1869         case eOk:
1870             return ScCompiler::GetNativeSymbol(ocOpen).GetChar(0);
1871         case eClose:
1872             return ScCompiler::GetNativeSymbol(ocClose).GetChar(0);
1873         case eSep:
1874             return ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
1875         case eArrayOpen:
1876             return ScCompiler::GetNativeSymbol(ocArrayOpen).GetChar(0);
1877         case eArrayClose:
1878             return ScCompiler::GetNativeSymbol(ocArrayClose).GetChar(0);
1879     } // switch(_eToken)
1880     return 0;
1881 }
1882 // -----------------------------------------------------------------------------
1883 sal_uInt32 ScFunctionCategory::getCount() const
1884 {
1885     return m_pCategory->Count();
1886 }
1887 // -----------------------------------------------------------------------------
1888 const formula::IFunctionManager* ScFunctionCategory::getFunctionManager() const
1889 {
1890     return m_pMgr;
1891 }
1892 // -----------------------------------------------------------------------------
1893 ::rtl::OUString ScFunctionCategory::getName() const
1894 {
1895     if ( !m_sName.getLength() )
1896         m_sName = ScFunctionMgr::GetCategoryName(m_nCategory+1);
1897     return m_sName;
1898 }
1899 // -----------------------------------------------------------------------------
1900 const formula::IFunctionDescription* ScFunctionCategory::getFunction(sal_uInt32 _nPos) const
1901 {
1902     const ScFuncDesc*	pDesc = NULL;
1903     sal_uInt32 i = 0;
1904 	for (pDesc = (const ScFuncDesc*)m_pCategory->First(); i < _nPos &&  pDesc; pDesc = (const ScFuncDesc*)m_pCategory->Next(),++i)
1905         ;
1906 	return pDesc;
1907 }
1908 // -----------------------------------------------------------------------------
1909 sal_uInt32 ScFunctionCategory::getNumber() const
1910 {
1911     return m_nCategory;
1912 }
1913 // -----------------------------------------------------------------------------
1914 
1915 //------------------------------------------------------------------------
1916 
1917 utl::TransliterationWrapper* ScGlobal::GetpTransliteration() //add by CHINA001
1918 {
1919     if ( !pTransliteration )
1920     {
1921         const LanguageType eOfficeLanguage = Application::GetSettings().GetLanguage();
1922         pTransliteration = new ::utl::TransliterationWrapper(
1923             ::comphelper::getProcessServiceFactory(), SC_TRANSLITERATION_IGNORECASE );
1924         pTransliteration->loadModuleIfNeeded( eOfficeLanguage );
1925     }
1926 	DBG_ASSERT(
1927 		pTransliteration,
1928 		"ScGlobal::GetpTransliteration() called before ScGlobal::Init()");
1929 	return pTransliteration;
1930 }
1931 
1932 const LocaleDataWrapper* ScGlobal::GetpLocaleData()
1933 {
1934 	DBG_ASSERT(
1935 		pLocaleData,
1936 		"ScGlobal::GetpLocaleData() called before ScGlobal::Init()");
1937 	return pLocaleData;
1938 }
1939 CalendarWrapper*     ScGlobal::GetCalendar()
1940 {
1941     if ( !pCalendar )
1942     {
1943         pCalendar = new CalendarWrapper( ::comphelper::getProcessServiceFactory() );
1944 	    pCalendar->loadDefaultCalendar( *GetLocale() );
1945     }
1946     return pCalendar;
1947 }
1948 CollatorWrapper*		ScGlobal::GetCollator()
1949 {
1950     if ( !pCollator )
1951     {
1952         pCollator = new CollatorWrapper( ::comphelper::getProcessServiceFactory() );
1953 	    pCollator->loadDefaultCollator( *GetLocale(), SC_COLLATOR_IGNORES );
1954     } // if ( !pCollator )
1955     return pCollator;
1956 }
1957 CollatorWrapper*		ScGlobal::GetCaseCollator()
1958 {
1959     if ( !pCaseCollator )
1960     {
1961         pCaseCollator = new CollatorWrapper( ::comphelper::getProcessServiceFactory() );
1962 	    pCaseCollator->loadDefaultCollator( *GetLocale(), 0 );
1963     } // if ( !pCaseCollator )
1964     return pCaseCollator;
1965 }
1966 ::utl::TransliterationWrapper* ScGlobal::GetCaseTransliteration()
1967 {
1968     if ( !pCaseTransliteration )
1969     {
1970         const LanguageType eOfficeLanguage = Application::GetSettings().GetLanguage();
1971         pCaseTransliteration = new ::utl::TransliterationWrapper(::comphelper::getProcessServiceFactory(), SC_TRANSLITERATION_CASESENSE );
1972         pCaseTransliteration->loadModuleIfNeeded( eOfficeLanguage );
1973     } // if ( !pCaseTransliteration )
1974     return pCaseTransliteration;
1975 }
1976 IntlWrapper*         ScGlobal::GetScIntlWrapper()
1977 {
1978     if ( !pScIntlWrapper )
1979     {
1980         pScIntlWrapper = new IntlWrapper( ::comphelper::getProcessServiceFactory(), *GetLocale() );
1981     }
1982     return pScIntlWrapper;
1983 }
1984 ::com::sun::star::lang::Locale*		ScGlobal::GetLocale()
1985 {
1986     if ( !pLocale )
1987     {
1988         pLocale = new ::com::sun::star::lang::Locale( Application::GetSettings().GetLocale());
1989     }
1990     return pLocale;
1991 }
1992 
1993