xref: /trunk/main/sc/source/core/data/global.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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