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