1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "scitems.hxx"
21 #include <sfx2/dispatch.hxx>
22 #include <sfx2/docfile.hxx>
23 #include <sfx2/objsh.hxx>
24 #include <svl/zforlist.hxx>
25 #include <svl/stritem.hxx>
26 #include <svtools/treelistbox.hxx>
27 #include <sfx2/viewfrm.hxx>
28 #include <vcl/svapp.hxx>
29 #include <vcl/mnemonic.hxx>
30 #include <unotools/charclass.hxx>
31 #include <tools/urlobj.hxx>
32 #include <formula/formulahelper.hxx>
33 #include <formula/IFunctionDescription.hxx>
35 #include "tokenuno.hxx"
36 #include "formula.hxx"
37 #include "formdata.hxx"
38 #include "globstr.hrc"
39 #include "scresid.hxx"
40 #include "reffact.hxx"
41 #include "document.hxx"
42 #include "simpleformulacalc.hxx"
44 #include "inputhdl.hxx"
45 #include "tabvwsh.hxx"
46 #include "appoptio.hxx"
48 #include "funcdesc.hxx"
49 #include <formula/token.hxx>
50 #include "tokenarray.hxx"
52 #include "servuno.hxx"
53 #include "unonames.hxx"
54 #include "externalrefmgr.hxx"
56 #include <com/sun/star/table/CellAddress.hpp>
59 using namespace formula
;
60 using namespace com::sun::star
;
62 ScDocument
* ScFormulaDlg::pDoc
= NULL
;
63 ScAddress
ScFormulaDlg::aCursorPos
;
66 // Initialisierung / gemeinsame Funktionen fuer Dialog
69 ScFormulaDlg::ScFormulaDlg( SfxBindings
* pB
, SfxChildWindow
* pCW
,
70 Window
* pParent
, ScViewData
* pViewData
,formula::IFunctionManager
* _pFunctionMgr
)
71 : formula::FormulaDlg( pB
, pCW
, pParent
, true,true,true, _pFunctionMgr
,this)
74 m_aHelper
.SetWindow(this);
75 ScModule
* pScMod
= SC_MOD();
76 pScMod
->InputEnterHandler();
77 ScTabViewShell
* pScViewShell
= NULL
;
79 // title has to be from the view that opened the dialog,
80 // even if it's not the current view
84 SfxDispatcher
* pMyDisp
= pB
->GetDispatcher();
87 SfxViewFrame
* pMyViewFrm
= pMyDisp
->GetFrame();
90 pScViewShell
= PTR_CAST( ScTabViewShell
, pMyViewFrm
->GetViewShell() );
92 pScViewShell
->UpdateInputHandler(true);
98 pDoc
= pViewData
->GetDocument();
99 m_xParser
.set(ScServiceProvider::MakeInstance(SC_SERVICE_FORMULAPARS
,(ScDocShell
*)pDoc
->GetDocumentShell()),uno::UNO_QUERY
);
100 uno::Reference
< beans::XPropertySet
> xSet(m_xParser
,uno::UNO_QUERY
);
101 xSet
->setPropertyValue(OUString(SC_UNO_COMPILEFAP
),uno::makeAny(sal_True
));
103 m_xOpCodeMapper
.set(ScServiceProvider::MakeInstance(SC_SERVICE_OPCODEMAPPER
,(ScDocShell
*)pDoc
->GetDocumentShell()),uno::UNO_QUERY
);
105 ScInputHandler
* pInputHdl
= SC_MOD()->GetInputHdl(pScViewShell
);
107 OSL_ENSURE( pInputHdl
, "Missing input handler :-/" );
110 pInputHdl
->NotifyChange( NULL
);
112 m_aHelper
.enableInput( false );
113 m_aHelper
.EnableSpreadsheets();
115 m_aHelper
.SetDispatcherLock( true );
120 ScFormEditData
* pData
= pScMod
->GetFormEditData();
123 //Nun wird es Zeit den Inputhandler festzulegen
124 pScMod
->SetRefInputHdl(pScMod
->GetInputHdl());
126 pDoc
= pViewData
->GetDocument();
127 SCCOL nCol
= pViewData
->GetCurX();
128 SCROW nRow
= pViewData
->GetCurY();
129 SCTAB nTab
= pViewData
->GetTabNo();
130 aCursorPos
= ScAddress( nCol
, nRow
, nTab
);
132 pScMod
->InitFormEditData(); // neu anlegen
133 pData
= pScMod
->GetFormEditData();
134 pData
->SetInputHandler(pScMod
->GetInputHdl());
135 pData
->SetDocShell(pViewData
->GetDocShell());
137 OSL_ENSURE(pData
,"FormEditData ist nicht da");
139 formula::FormulaDlgMode eMode
= FORMULA_FORMDLG_FORMULA
; // Default...
141 // Formel vorhanden? Dann editieren
144 pDoc
->GetFormula( nCol
, nRow
, nTab
, aFormula
);
145 bool bEdit
= ( aFormula
.getLength() > 1 );
146 bool bMatrix
= false;
149 bMatrix
= CheckMatrix(aFormula
);
151 sal_Int32 nFStart
= 0;
153 if ( GetFormulaHelper().GetNextFunc( aFormula
, false, nFStart
, &nFEnd
) )
155 pScMod
->InputReplaceSelection( aFormula
);
156 pScMod
->InputSetSelection( nFStart
, nFEnd
);
157 sal_Int32 PrivStart
, PrivEnd
;
158 pScMod
->InputGetSelection( PrivStart
, PrivEnd
);
160 eMode
= SetMeText(pScMod
->InputGetFormulaStr(),PrivStart
, PrivEnd
, bMatrix
, true, true);
161 pData
->SetFStart( nFStart
);
169 OUString
aNewFormula('=');
170 if ( aFormula
.startsWith("=") )
171 aNewFormula
= aFormula
;
173 pScMod
->InputReplaceSelection( aNewFormula
);
174 pScMod
->InputSetSelection( 1, aNewFormula
.getLength()+1 );
175 sal_Int32 PrivStart
, PrivEnd
;
176 pScMod
->InputGetSelection( PrivStart
, PrivEnd
);
177 SetMeText(pScMod
->InputGetFormulaStr(),PrivStart
, PrivEnd
,bMatrix
,false,false);
179 pData
->SetFStart( 1 ); // hinter dem "="
182 pData
->SetMode( (sal_uInt16
) eMode
);
183 OUString rStrExp
= GetMeText();
190 void ScFormulaDlg::notifyChange()
192 ScModule
* pScMod
= SC_MOD();
194 ScInputHandler
* pInputHdl
= pScMod
->GetInputHdl();
196 pInputHdl
->NotifyChange( NULL
);
199 void ScFormulaDlg::fill()
201 ScModule
* pScMod
= SC_MOD();
202 ScFormEditData
* pData
= pScMod
->GetFormEditData();
207 // Daten schon vorhanden -> Zustand wiederherstellen (nach Umschalten)
208 // pDoc und aCursorPos nicht neu initialisieren
209 //pDoc = pViewData->GetDocument();
210 if(IsInputHdl(pData
->GetInputHandler()))
212 pScMod
->SetRefInputHdl(pData
->GetInputHandler());
216 PtrTabViewShell pTabViewShell
;
217 ScInputHandler
* pInputHdl
= GetNextInputHandler(pData
->GetDocShell(),&pTabViewShell
);
219 if ( pInputHdl
== NULL
) //DocShell hat keinen InputHandler mehr,
220 { //hat der Anwender halt Pech gehabt.
222 pInputHdl
= pScMod
->GetInputHdl();
226 pInputHdl
->SetRefViewShell(pTabViewShell
);
228 pScMod
->SetRefInputHdl(pInputHdl
);
229 pData
->SetInputHandler(pInputHdl
);
232 OUString
aOldFormulaTmp(pScMod
->InputGetFormulaStr());
233 pScMod
->InputSetSelection( 0, aOldFormulaTmp
.getLength());
235 rStrExp
=pData
->GetUndoStr();
236 pScMod
->InputReplaceSelection(rStrExp
);
241 // Jetzt nochmals zurueckschalten, da evtl. neues Doc geoeffnet wurde!
242 pScMod
->SetRefInputHdl(NULL
);
246 ScFormulaDlg::~ScFormulaDlg()
248 ScModule
* pScMod
= SC_MOD();
249 ScFormEditData
* pData
= pScMod
->GetFormEditData();
251 if (pData
) // wird nicht ueber Close zerstoert;
253 //Referenz Inputhandler zuruecksetzen
254 pScMod
->SetRefInputHdl(NULL
);
255 StoreFormEditData(pData
);
256 } // if (pData) // wird nicht ueber Close zerstoert;
259 bool ScFormulaDlg::IsInputHdl(ScInputHandler
* pHdl
)
263 // gehoert der InputHandler zu irgendeiner ViewShell ?
265 TypeId aScType
= TYPE(ScTabViewShell
);
266 SfxViewShell
* pSh
= SfxViewShell::GetFirst( &aScType
);
267 while ( pSh
&& !bAlive
)
269 if (((ScTabViewShell
*)pSh
)->GetInputHandler() == pHdl
)
271 pSh
= SfxViewShell::GetNext( *pSh
, &aScType
);
278 ScInputHandler
* ScFormulaDlg::GetNextInputHandler(ScDocShell
* pDocShell
,PtrTabViewShell
* ppViewSh
)
280 ScInputHandler
* pHdl
=NULL
;
282 SfxViewFrame
* pFrame
= SfxViewFrame::GetFirst( pDocShell
);
283 while( pFrame
&& pHdl
==NULL
)
285 SfxViewShell
* p
= pFrame
->GetViewShell();
286 ScTabViewShell
* pViewSh
= PTR_CAST(ScTabViewShell
,p
);
289 pHdl
=pViewSh
->GetInputHandler();
290 if(ppViewSh
!=NULL
) *ppViewSh
=pViewSh
;
292 pFrame
= SfxViewFrame::GetNext( *pFrame
, pDocShell
);
300 bool ScFormulaDlg::Close()
307 // Funktionen fuer rechte Seite
309 bool ScFormulaDlg::calculateValue( const OUString
& rStrExp
, OUString
& rStrResult
)
311 boost::scoped_ptr
<ScSimpleFormulaCalculator
> pFCell( new ScSimpleFormulaCalculator( pDoc
, aCursorPos
, rStrExp
) );
313 // HACK! um bei ColRowNames kein #REF! zu bekommen,
314 // wenn ein Name eigentlich als Bereich in die Gesamt-Formel
315 // eingefuegt wird, bei der Einzeldarstellung aber als
316 // single-Zellbezug interpretiert wird
317 bool bColRowName
= pFCell
->HasColRowName();
320 // ColRowName im RPN-Code?
321 if ( pFCell
->GetCode()->GetCodeLen() <= 1 )
322 { // ==1: einzelner ist als Parameter immer Bereich
323 // ==0: es waere vielleicht einer, wenn..
324 OUStringBuffer aBraced
;
326 aBraced
.append(rStrExp
);
328 pFCell
.reset( new ScSimpleFormulaCalculator( pDoc
, aCursorPos
, aBraced
.makeStringAndClear() ) );
334 sal_uInt16 nErrCode
= pFCell
->GetErrCode();
337 SvNumberFormatter
& aFormatter
= *(pDoc
->GetFormatTable());
339 if ( pFCell
->IsValue() )
341 double n
= pFCell
->GetValue();
342 sal_uLong nFormat
= aFormatter
.GetStandardFormat( n
, 0,
343 pFCell
->GetFormatType(), ScGlobal::eLnge
);
344 aFormatter
.GetOutputString( n
, nFormat
,
345 rStrResult
, &pColor
);
349 sal_uLong nFormat
= aFormatter
.GetStandardFormat(
350 pFCell
->GetFormatType(), ScGlobal::eLnge
);
351 aFormatter
.GetOutputString( pFCell
->GetString().getString(), nFormat
,
352 rStrResult
, &pColor
);
356 if ( bColRowName
|| (aTestRange
.Parse(rStrExp
) & SCA_VALID
) )
357 rStrResult
+= " ...";
361 rStrResult
+= ScGlobal::GetErrorString(nErrCode
);
366 // virtuelle Methoden von ScAnyRefDlg:
367 void ScFormulaDlg::RefInputStart( formula::RefEdit
* pEdit
, formula::RefButton
* pButton
)
369 pEdit
->SetSelection(Selection(0, SELECTION_MAX
));
370 ::std::pair
<formula::RefButton
*,formula::RefEdit
*> aPair
= RefInputStartBefore( pEdit
, pButton
);
371 m_aHelper
.RefInputStart( aPair
.second
, aPair
.first
);
372 RefInputStartAfter( aPair
.second
, aPair
.first
);
375 void ScFormulaDlg::RefInputDone( bool bForced
)
377 m_aHelper
.RefInputDone( bForced
);
378 RefInputDoneAfter( bForced
);
381 void ScFormulaDlg::SetReference( const ScRange
& rRef
, ScDocument
* pRefDoc
)
383 const IFunctionDescription
* pFunc
= getCurrentFunctionDescription();
384 if ( pFunc
&& pFunc
->getSuppressedArgumentCount() > 0 )
387 bool bRefNull
= UpdateParaWin(theSel
);
389 if ( rRef
.aStart
!= rRef
.aEnd
&& bRefNull
)
391 RefInputStart(GetActiveEdit());
395 bool bOtherDoc
= ( pRefDoc
!= pDoc
&& pRefDoc
->GetDocumentShell()->HasName() );
398 // Referenz auf anderes Dokument - wie inputhdl.cxx
400 OSL_ENSURE(rRef
.aStart
.Tab()==rRef
.aEnd
.Tab(), "nStartTab!=nEndTab");
402 OUString
aTmp(rRef
.Format(SCA_VALID
|SCA_TAB_3D
, pRefDoc
)); // immer 3d
404 SfxObjectShell
* pObjSh
= pRefDoc
->GetDocumentShell();
406 // #i75893# convert escaped URL of the document to something user friendly
407 // OUString aFileName = pObjSh->GetMedium()->GetName();
408 OUString aFileName
= pObjSh
->GetMedium()->GetURLObject().GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS
);
411 aRefStr
+= aFileName
;
417 // We can't use ScRange::Format here because in R1C1 mode we need
418 // to display the reference position relative to the cursor
421 ScComplexRefData aRefData
;
422 aRefData
.InitRangeRel(rRef
, aCursorPos
);
423 bool bSingle
= aRefData
.Ref1
== aRefData
.Ref2
;
424 if (aCursorPos
.Tab() != rRef
.aStart
.Tab())
425 aRefData
.Ref1
.SetFlag3D(true);
427 aArray
.AddSingleReference(aRefData
.Ref1
);
429 aArray
.AddDoubleReference(aRefData
);
430 ScCompiler
aComp(pDoc
, aCursorPos
, aArray
);
431 aComp
.SetGrammar(pDoc
->GetGrammar());
433 aComp
.CreateStringFromTokenArray(aBuf
);
434 aRefStr
= aBuf
.makeStringAndClear();
437 UpdateParaWin(theSel
,aRefStr
);
441 bool ScFormulaDlg::IsRefInputMode() const
443 const IFunctionDescription
* pDesc
= getCurrentFunctionDescription();
444 bool bRef
= (pDesc
&& (pDesc
->getSuppressedArgumentCount() > 0)) && (pDoc
!=NULL
);
448 bool ScFormulaDlg::IsDocAllowed(SfxObjectShell
* pDocSh
) const
450 // not allowed: different from this doc, and no name
451 // pDocSh is always a ScDocShell
452 if ( pDocSh
&& ((ScDocShell
*)pDocSh
)->GetDocument() != pDoc
&& !pDocSh
->HasName() )
455 return true; // everything else is allowed
458 void ScFormulaDlg::SetActive()
460 const IFunctionDescription
* pFunc
= getCurrentFunctionDescription();
461 if ( pFunc
&& pFunc
->getSuppressedArgumentCount() > 0 )
468 void ScFormulaDlg::SaveLRUEntry(const ScFuncDesc
* pFuncDescP
)
470 if (pFuncDescP
&& pFuncDescP
->nFIndex
!=0)
472 ScModule
* pScMod
= SC_MOD();
473 pScMod
->InsertEntryToLRUList(pFuncDescP
->nFIndex
);
477 void ScFormulaDlg::doClose(bool /*_bOk*/)
479 m_aHelper
.DoClose( ScFormulaDlgWrapper::GetChildWindowId() );
481 void ScFormulaDlg::insertEntryToLRUList(const formula::IFunctionDescription
* _pDesc
)
483 const ScFuncDesc
* pDesc
= dynamic_cast<const ScFuncDesc
*>(_pDesc
);
486 void ScFormulaDlg::showReference(const OUString
& _sFormula
)
488 ShowReference(_sFormula
);
490 void ScFormulaDlg::ShowReference(const OUString
& _sFormula
)
492 m_aHelper
.ShowReference(_sFormula
);
494 void ScFormulaDlg::HideReference( bool bDoneRefMode
)
496 m_aHelper
.HideReference(bDoneRefMode
);
498 void ScFormulaDlg::ViewShellChanged()
500 m_aHelper
.ViewShellChanged();
502 void ScFormulaDlg::AddRefEntry( )
506 bool ScFormulaDlg::IsTableLocked( ) const
508 // per Default kann bei Referenzeingabe auch die Tabelle umgeschaltet werden
511 void ScFormulaDlg::ToggleCollapsed( formula::RefEdit
* pEdit
, formula::RefButton
* pButton
)
513 m_aHelper
.ToggleCollapsed(pEdit
,pButton
);
515 void ScFormulaDlg::ReleaseFocus( formula::RefEdit
* pEdit
, formula::RefButton
* pButton
)
517 m_aHelper
.ReleaseFocus(pEdit
,pButton
);
519 void ScFormulaDlg::dispatch(bool _bOK
, bool _bMatrixChecked
)
521 SfxBoolItem
aRetItem( SID_DLG_RETOK
, _bOK
);
522 SfxBoolItem
aMatItem( SID_DLG_MATRIX
, _bMatrixChecked
);
523 SfxStringItem
aStrItem( SCITEM_STRING
, getCurrentFormula() );
525 // Wenn durch Dokument-Umschalterei die Eingabezeile weg war/ist,
526 // ist der String leer. Dann nicht die alte Formel loeschen.
527 if ( aStrItem
.GetValue().isEmpty() )
528 aRetItem
.SetValue( false ); // sal_False = Cancel
530 m_aHelper
.SetDispatcherLock( false ); // Modal-Modus ausschalten
534 GetBindings().GetDispatcher()->Execute( SID_INS_FUNCTION
,
535 SFX_CALLMODE_ASYNCHRON
| SFX_CALLMODE_RECORD
,
536 &aRetItem
, &aStrItem
, &aMatItem
, 0L );
538 void ScFormulaDlg::setDispatcherLock( bool bLock
)
540 m_aHelper
.SetDispatcherLock( bLock
);
542 void ScFormulaDlg::setReferenceInput(const formula::FormEditData
* _pData
)
544 ScModule
* pScMod
= SC_MOD();
545 ScFormEditData
* pData
= const_cast<ScFormEditData
*>(dynamic_cast<const ScFormEditData
*>(_pData
));
546 pScMod
->SetRefInputHdl(pData
->GetInputHandler());
548 void ScFormulaDlg::deleteFormData()
550 ScModule
* pScMod
= SC_MOD();
551 pScMod
->ClearFormEditData(); // pData wird ungueltig!
553 void ScFormulaDlg::clear()
557 //Referenz Inputhandler zuruecksetzen
558 ScModule
* pScMod
= SC_MOD();
559 pScMod
->SetRefInputHdl(NULL
);
561 // Enable() der Eingabezeile erzwingen:
562 ScTabViewShell
* pScViewShell
= PTR_CAST(ScTabViewShell
, SfxViewShell::Current());
564 pScViewShell
->UpdateInputHandler();
566 void ScFormulaDlg::switchBack()
568 ScModule
* pScMod
= SC_MOD();
569 // auf das Dokument zurueckschalten
570 // (noetig, weil ein fremdes oben sein kann - #34222#)
571 ScInputHandler
* pHdl
= pScMod
->GetInputHdl();
574 pHdl
->ViewShellGone(NULL
); // -> aktive View neu holen
575 pHdl
->ShowRefFrame();
578 // aktuelle Tabelle ggF. restaurieren (wg. Maus-RefInput)
579 ScTabViewShell
* pScViewShell
= PTR_CAST(ScTabViewShell
, SfxViewShell::Current());
582 ScViewData
* pVD
=pScViewShell
->GetViewData();
583 SCTAB nExecTab
= aCursorPos
.Tab();
584 if ( nExecTab
!= pVD
->GetTabNo() )
585 pScViewShell
->SetTabNo( nExecTab
);
587 SCROW nRow
=aCursorPos
.Row();
588 SCCOL nCol
=aCursorPos
.Col();
590 if(pVD
->GetCurX()!=nCol
|| pVD
->GetCurY()!=nRow
)
591 pScViewShell
->SetCursor(nCol
,nRow
);
594 formula::FormEditData
* ScFormulaDlg::getFormEditData() const
596 ScModule
* pScMod
= SC_MOD();
597 return pScMod
->GetFormEditData();
599 void ScFormulaDlg::setCurrentFormula(const OUString
& _sReplacement
)
601 ScModule
* pScMod
= SC_MOD();
603 //fdo#69971 We need the EditEngine Modification handler of the inputbar that we
604 //are feeding to be disabled while this dialog is open. Otherwise we end up in
605 //a situation where...
606 //a) this ScFormulaDlg changes the editengine
607 //b) the modify callback gets called
608 //c) which also modifies the editengine
609 //d) on return from that modify handler the editengine attempts to use
610 // old node pointers which were replaced and removed by c
612 //We turn it off in the ctor and back on in the dtor, but if calc has
613 //to repaint, e.g. when switching to another window and back, then in
614 //ScMultiTextWnd::Paint a new editengine will have been created via
615 //GetEditView with its default Modification handler enabled. So ensure
616 //its off when we will access it via InputReplaceSelection
617 pScMod
->InputTurnOffWinEngine();
619 pScMod
->InputReplaceSelection(_sReplacement
);
621 void ScFormulaDlg::setSelection(sal_Int32 _nStart
, sal_Int32 _nEnd
)
623 ScModule
* pScMod
= SC_MOD();
624 pScMod
->InputSetSelection( _nStart
, _nEnd
);
626 void ScFormulaDlg::getSelection(sal_Int32
& _nStart
, sal_Int32
& _nEnd
) const
628 ScModule
* pScMod
= SC_MOD();
629 pScMod
->InputGetSelection( _nStart
, _nEnd
);
631 OUString
ScFormulaDlg::getCurrentFormula() const
633 ScModule
* pScMod
= SC_MOD();
634 return pScMod
->InputGetFormulaStr();
636 formula::IFunctionManager
* ScFormulaDlg::getFunctionManager()
638 return ScGlobal::GetStarCalcFunctionMgr();
640 uno::Reference
< sheet::XFormulaParser
> ScFormulaDlg::getFormulaParser() const
644 uno::Reference
< sheet::XFormulaOpCodeMapper
> ScFormulaDlg::getFormulaOpCodeMapper() const
646 return m_xOpCodeMapper
;
649 table::CellAddress
ScFormulaDlg::getReferencePosition() const
651 return table::CellAddress(aCursorPos
.Tab(),aCursorPos
.Col(),aCursorPos
.Row());
654 SAL_WNODEPRECATED_DECLARATIONS_PUSH
655 ::std::auto_ptr
<formula::FormulaTokenArray
> ScFormulaDlg::convertToTokenArray(const uno::Sequence
< sheet::FormulaToken
>& _aTokenList
)
657 ::std::auto_ptr
<formula::FormulaTokenArray
> pArray(new ScTokenArray());
658 pArray
->Fill(_aTokenList
, pDoc
->GetSharedStringPool(), pDoc
->GetExternalRefManager());
661 // for mysterious reasons Apple llvm-g++ 4.2.1 needs these explicit
662 // template instantiations; otherwise linking fails with unresolved symbols
663 template class ::std::auto_ptr
<formula::FormulaTokenArray
>;
664 template std::auto_ptr
<formula::FormulaTokenArray
>::operator std::auto_ptr_ref
<formula::FormulaTokenArray
>();
665 SAL_WNODEPRECATED_DECLARATIONS_POP
667 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */