summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens-Heiner Rechtien <hr@openoffice.org>2000-09-18 23:16:46 +0000
committerJens-Heiner Rechtien <hr@openoffice.org>2000-09-18 23:16:46 +0000
commitd0484bcdcbffd42d242647a2fdc1a203d176b775 (patch)
tree5a55e322eba52fffac58b43beb88568721d13a9b
parent9ae5a91f7955e44d3b24a3f7741f9bca02ac7f24 (diff)
initial import
-rw-r--r--sc/source/core/data/attarray.cxx2438
-rw-r--r--sc/source/core/data/attrib.cxx1478
-rw-r--r--sc/source/core/data/bcaslot.cxx801
-rw-r--r--sc/source/core/data/cell.cxx1574
-rw-r--r--sc/source/core/data/cell2.cxx1415
-rw-r--r--sc/source/core/data/column.cxx2060
-rw-r--r--sc/source/core/data/column2.cxx2123
-rw-r--r--sc/source/core/data/column3.cxx2133
-rw-r--r--sc/source/core/data/conditio.cxx1542
-rw-r--r--sc/source/core/data/dociter.cxx1390
-rw-r--r--sc/source/core/data/docpool.cxx829
-rw-r--r--sc/source/core/data/documen2.cxx1812
-rw-r--r--sc/source/core/data/documen3.cxx1723
-rw-r--r--sc/source/core/data/documen4.cxx1265
-rw-r--r--sc/source/core/data/documen5.cxx709
-rw-r--r--sc/source/core/data/documen6.cxx186
-rw-r--r--sc/source/core/data/documen7.cxx509
-rw-r--r--sc/source/core/data/documen8.cxx1356
-rw-r--r--sc/source/core/data/documen9.cxx838
-rw-r--r--sc/source/core/data/document.cxx3900
-rw-r--r--sc/source/core/data/dpobject.cxx1718
-rw-r--r--sc/source/core/data/dpoutput.cxx1003
-rw-r--r--sc/source/core/data/dpsave.cxx945
-rw-r--r--sc/source/core/data/dpsdbtab.cxx606
-rw-r--r--sc/source/core/data/dpshttab.cxx422
-rw-r--r--sc/source/core/data/dptabdat.cxx173
-rw-r--r--sc/source/core/data/dptabres.cxx1278
-rw-r--r--sc/source/core/data/dptabsrc.cxx2002
-rw-r--r--sc/source/core/data/drawpage.cxx317
-rw-r--r--sc/source/core/data/drwlayer.cxx2099
-rw-r--r--sc/source/core/data/fillinfo.cxx981
-rw-r--r--sc/source/core/data/global.cxx1668
-rw-r--r--sc/source/core/data/global2.cxx1993
-rw-r--r--sc/source/core/data/globalx.cxx162
-rw-r--r--sc/source/core/data/makefile.mk203
-rw-r--r--sc/source/core/data/markarr.cxx430
-rw-r--r--sc/source/core/data/markdata.cxx606
-rw-r--r--sc/source/core/data/olinetab.cxx876
-rw-r--r--sc/source/core/data/pagepar.cxx262
-rw-r--r--sc/source/core/data/patattr.cxx943
-rw-r--r--sc/source/core/data/pivot.cxx2051
-rw-r--r--sc/source/core/data/pivot2.cxx529
-rw-r--r--sc/source/core/data/stlpool.cxx618
-rw-r--r--sc/source/core/data/stlsheet.cxx348
-rw-r--r--sc/source/core/data/table1.cxx1406
-rw-r--r--sc/source/core/data/table2.cxx3147
-rw-r--r--sc/source/core/data/table3.cxx1611
-rw-r--r--sc/source/core/data/table4.cxx2014
-rw-r--r--sc/source/core/data/table5.cxx644
-rw-r--r--sc/source/core/data/table6.cxx710
-rw-r--r--sc/source/core/data/userdat.cxx755
-rw-r--r--sc/source/core/data/validat.cxx633
-rw-r--r--sc/source/core/inc/addinlis.hxx145
-rw-r--r--sc/source/core/inc/adiasync.hxx127
-rw-r--r--sc/source/core/inc/bcaslot.hxx197
-rw-r--r--sc/source/core/inc/core_pch.hxx312
-rw-r--r--sc/source/core/inc/ddelink.hxx135
-rw-r--r--sc/source/core/inc/interpre.hxx721
-rw-r--r--sc/source/core/inc/makefile.mk61
-rw-r--r--sc/source/core/inc/refupdat.hxx120
-rw-r--r--sc/source/core/inc/sctictac.hxx164
-rw-r--r--sc/source/core/src/compiler.src7409
-rw-r--r--sc/source/core/src/makefile.mk86
-rw-r--r--sc/source/core/tool/addincol.cxx1205
-rw-r--r--sc/source/core/tool/addinlis.cxx225
-rw-r--r--sc/source/core/tool/adiasync.cxx229
-rw-r--r--sc/source/core/tool/appoptio.cxx343
-rw-r--r--sc/source/core/tool/autoform.cxx1215
-rw-r--r--sc/source/core/tool/callform.cxx554
-rw-r--r--sc/source/core/tool/cellform.cxx272
-rw-r--r--sc/source/core/tool/chartarr.cxx1394
-rw-r--r--sc/source/core/tool/chartlis.cxx468
-rw-r--r--sc/source/core/tool/chgtrack.cxx4543
-rw-r--r--sc/source/core/tool/chgviset.cxx226
-rw-r--r--sc/source/core/tool/collect.cxx562
-rw-r--r--sc/source/core/tool/compiler.cxx3468
-rw-r--r--sc/source/core/tool/consoli.cxx886
-rw-r--r--sc/source/core/tool/dbcolect.cxx1223
-rw-r--r--sc/source/core/tool/ddelink.cxx315
-rw-r--r--sc/source/core/tool/detdata.cxx175
-rw-r--r--sc/source/core/tool/detfunc.cxx1553
-rw-r--r--sc/source/core/tool/docoptio.cxx337
-rw-r--r--sc/source/core/tool/editutil.cxx655
-rw-r--r--sc/source/core/tool/hints.cxx186
-rw-r--r--sc/source/core/tool/indexmap.cxx112
-rw-r--r--sc/source/core/tool/inputopt.cxx336
-rw-r--r--sc/source/core/tool/interpr1.cxx5204
-rw-r--r--sc/source/core/tool/interpr2.cxx1957
-rw-r--r--sc/source/core/tool/interpr3.cxx3970
-rw-r--r--sc/source/core/tool/interpr4.cxx3588
-rw-r--r--sc/source/core/tool/interpr5.cxx4062
-rw-r--r--sc/source/core/tool/interpr6.cxx216
-rw-r--r--sc/source/core/tool/makefile.mk199
-rw-r--r--sc/source/core/tool/navicfg.cxx169
-rw-r--r--sc/source/core/tool/printopt.cxx297
-rw-r--r--sc/source/core/tool/prnsave.cxx189
-rw-r--r--sc/source/core/tool/progress.cxx216
-rw-r--r--sc/source/core/tool/rangelst.cxx781
-rw-r--r--sc/source/core/tool/rangenam.cxx857
-rw-r--r--sc/source/core/tool/rangeseq.cxx345
-rw-r--r--sc/source/core/tool/rangeutl.cxx568
-rw-r--r--sc/source/core/tool/rechead.cxx264
-rw-r--r--sc/source/core/tool/refdata.cxx377
-rw-r--r--sc/source/core/tool/reffind.cxx201
-rw-r--r--sc/source/core/tool/refupdat.cxx983
-rw-r--r--sc/source/core/tool/scmatrix.cxx592
-rw-r--r--sc/source/core/tool/sctictac.cxx581
-rw-r--r--sc/source/core/tool/subtotal.cxx541
-rw-r--r--sc/source/core/tool/token.cxx1660
-rw-r--r--sc/source/core/tool/unitconv.cxx275
-rw-r--r--sc/source/core/tool/userlist.cxx326
-rw-r--r--sc/source/core/tool/viewopti.cxx915
-rw-r--r--sc/source/core/tool/zforauto.cxx174
113 files changed, 122700 insertions, 0 deletions
diff --git a/sc/source/core/data/attarray.cxx b/sc/source/core/data/attarray.cxx
new file mode 100644
index 000000000000..ddcecd562e18
--- /dev/null
+++ b/sc/source/core/data/attarray.cxx
@@ -0,0 +1,2438 @@
+/*************************************************************************
+ *
+ * $RCSfile: attarray.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+//------------------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <svx/algitem.hxx>
+#include <svx/boxitem.hxx>
+#include <svx/shaditem.hxx>
+#include <svtools/poolcach.hxx>
+
+#include "attarray.hxx"
+#include "global.hxx"
+#include "document.hxx"
+#include "docpool.hxx"
+#include "patattr.hxx"
+#include "stlsheet.hxx"
+#include "stlpool.hxx"
+#include "markarr.hxx"
+#include "rechead.hxx"
+#include "globstr.hrc"
+
+
+#undef DBG_INVALIDATE
+#define DBGOUTPUT(s) \
+ DBG_ERROR( String("Invalidate ") + String(s) + String(": ") \
+ + String(nCol) + String('/') + String(aAdrStart.Row()) + String('/') + String(nTab) \
+ + String(" bis ") \
+ + String(nCol) + String('/') + String(aAdrEnd.Row()) + String('/') + String(nTab) \
+ );
+
+// STATIC DATA -----------------------------------------------------------
+
+
+//------------------------------------------------------------------------
+
+ScAttrArray::ScAttrArray( USHORT nNewCol, USHORT nNewTab, ScDocument* pDoc ) :
+ nCol( nNewCol ),
+ nTab( nNewTab ),
+ pDocument( pDoc )
+{
+ ScDocumentPool* pDocPool = pDocument->GetPool();
+
+ nCount = 1;
+ pData = new ScAttrEntry[1];
+ if (pData)
+ {
+ pData[0].nRow = MAXROW;
+ pData[0].pPattern = pDocument->GetDefPattern(); // ohne Put !!!
+ }
+}
+
+//------------------------------------------------------------------------
+
+ScAttrArray::~ScAttrArray()
+{
+#ifdef DBG_UTIL
+ TestData();
+#endif
+
+ if (pData)
+ {
+ ScDocumentPool* pDocPool = pDocument->GetPool();
+ for (USHORT i=0; i<nCount; i++)
+ pDocPool->Remove(*pData[i].pPattern);
+
+ delete[] pData;
+ }
+}
+
+//------------------------------------------------------------------------
+
+void ScAttrArray::TestData() const
+{
+#ifdef DBG_UTIL
+ USHORT nErr = 0;
+ if (pData)
+ {
+ for (USHORT nPos=0; nPos<nCount; nPos++)
+ {
+ if (nPos)
+ if (pData[nPos].pPattern == pData[nPos-1].pPattern || pData[nPos].nRow <= pData[nPos-1].nRow)
+ ++nErr;
+ if (pData[nPos].pPattern->Which() != ATTR_PATTERN)
+ ++nErr;
+ }
+ }
+ if (nErr)
+ {
+ ByteString aMsg = ByteString::CreateFromInt32(nErr);
+ aMsg += " errors in attribute array, column ";
+ aMsg += ByteString::CreateFromInt32(nCol);
+ DBG_ERROR( aMsg.GetBuffer() );
+ }
+#endif
+}
+
+//------------------------------------------------------------------------
+
+void ScAttrArray::Reset( const ScPatternAttr* pPattern, BOOL bAlloc )
+{
+ if (pData)
+ {
+ ScDocumentPool* pDocPool = pDocument->GetPool();
+ const ScPatternAttr* pOldPattern;
+ ScAddress aAdrStart( nCol, 0, nTab );
+ ScAddress aAdrEnd ( nCol, 0, nTab );
+
+ for (USHORT i=0; i<nCount; i++)
+ {
+ // ueberpruefen, ob Attributierung die Textbreite der Zelle aendert
+ pOldPattern = pData[i].pPattern;
+ BOOL bNumFormatChanged;
+ if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
+ pPattern->GetItemSet(), pOldPattern->GetItemSet() ) )
+ {
+ aAdrStart.SetRow( i ? pData[i-1].nRow+1 : 0 );
+ aAdrEnd .SetRow( pData[i].nRow );
+ pDocument->InvalidateTextWidth( &aAdrStart, &aAdrEnd, bNumFormatChanged );
+#ifdef DBG_INVALIDATE
+ DBGOUTPUT("Reset");
+#endif
+ }
+ // bedingtes Format gesetzt oder geloescht?
+ if ( &pPattern->GetItem(ATTR_CONDITIONAL) != &pOldPattern->GetItem(ATTR_CONDITIONAL) )
+ {
+ pDocument->ConditionalChanged( ((const SfxUInt32Item&)
+ pOldPattern->GetItem(ATTR_CONDITIONAL)).GetValue() );
+ pDocument->ConditionalChanged( ((const SfxUInt32Item&)
+ pPattern->GetItem(ATTR_CONDITIONAL)).GetValue() );
+ }
+ pDocPool->Remove(*pOldPattern);
+ }
+ delete[] pData;
+
+ if (bAlloc)
+ {
+ nCount = 1;
+ pData = new ScAttrEntry[1];
+ if (pData)
+ {
+ ScPatternAttr* pNewPattern = (ScPatternAttr*) &pDocPool->Put(*pPattern);
+ pData[0].nRow = MAXROW;
+ pData[0].pPattern = pNewPattern;
+ }
+ }
+ else
+ {
+ nCount = 0;
+ pData = NULL; // muss sofort wieder belegt werden !
+ }
+ }
+}
+
+
+BOOL ScAttrArray::Concat(USHORT nPos)
+{
+ BOOL bRet = FALSE;
+ if (pData && (nPos < nCount))
+ {
+ if (nPos > 0)
+ {
+ if (pData[nPos - 1].pPattern == pData[nPos].pPattern)
+ {
+ pData[nPos - 1].nRow = pData[nPos].nRow;
+ pDocument->GetPool()->Remove(*pData[nPos].pPattern);
+ memmove(&pData[nPos], &pData[nPos + 1], (nCount - nPos - 1) * sizeof(ScAttrEntry));
+ pData[nCount - 1].pPattern = NULL;
+ pData[nCount - 1].nRow = 0;
+ nCount--;
+ nPos--;
+ bRet = TRUE;
+ }
+ }
+ if (nPos + 1 < nCount)
+ {
+ if (pData[nPos + 1].pPattern == pData[nPos].pPattern)
+ {
+ pData[nPos].nRow = pData[nPos + 1].nRow;
+ pDocument->GetPool()->Remove(*pData[nPos].pPattern);
+ memmove(&pData[nPos + 1], &pData[nPos + 2], (nCount - nPos - 2) * sizeof(ScAttrEntry));
+ pData[nCount - 1].pPattern = NULL;
+ pData[nCount - 1].nRow = 0;
+ nCount--;
+ bRet = TRUE;
+ }
+ }
+ }
+ return bRet;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScAttrArray::Search( USHORT nRow, short& nIndex ) const
+{
+ short nLo = 0;
+ short nHi = ((short) nCount) - 1;
+ short nStartRow = 0;
+ short nEndRow = 0;
+ short i = 0;
+ BOOL bFound = (nCount == 1);
+ if (pData)
+ {
+ while ( !bFound && nLo <= nHi )
+ {
+ i = (nLo + nHi) / 2;
+ if (i > 0)
+ nStartRow = (short) pData[i - 1].nRow;
+ else
+ nStartRow = -1;
+ nEndRow = (short) pData[i].nRow;
+ if (nEndRow < (short) nRow)
+ nLo = ++i;
+ else
+ if (nStartRow >= (short) nRow)
+ nHi = --i;
+ else
+ bFound = TRUE;
+ }
+ }
+ else
+ bFound = FALSE;
+
+ if (bFound)
+ nIndex=i;
+ else
+ nIndex=0;
+ return bFound;
+}
+
+
+const ScPatternAttr* ScAttrArray::GetPattern( USHORT nRow ) const
+{
+ short i;
+ if (Search( nRow, i ))
+ return pData[i].pPattern;
+ else
+ return NULL;
+}
+
+
+const ScPatternAttr* ScAttrArray::GetPatternRange( USHORT& rStartRow,
+ USHORT& rEndRow, USHORT nRow ) const
+{
+ short nIndex;
+ if ( Search( nRow, nIndex ) )
+ {
+ if ( nIndex > 0 )
+ rStartRow = pData[nIndex-1].nRow + 1;
+ else
+ rStartRow = 0;
+ rEndRow = pData[nIndex].nRow;
+ return pData[nIndex].pPattern;
+ }
+ return NULL;
+}
+
+//------------------------------------------------------------------------
+
+void ScAttrArray::SetPattern( USHORT nRow, const ScPatternAttr* pPattern, BOOL bPutToPool )
+{
+ SetPatternArea( nRow, nRow, pPattern, bPutToPool );
+}
+
+
+void ScAttrArray::SetPatternArea(USHORT nStartRow, USHORT nEndRow, const ScPatternAttr *pPattern, BOOL bPutToPool )
+{
+ if (nStartRow >= 0 && nStartRow <= MAXROW && nEndRow >= 0 && nEndRow <= MAXROW)
+ {
+ if (bPutToPool)
+ pPattern = (const ScPatternAttr*) &pDocument->GetPool()->Put(*pPattern);
+
+ if ((nStartRow == 0) && (nEndRow == MAXROW))
+ Reset(pPattern);
+ else
+ {
+ USHORT nNewCount = 0;
+ ScAttrEntry* pNewData = new ScAttrEntry[nCount + 2];
+
+ if (pNewData)
+ {
+ ScAddress aAdrStart( nCol, 0, nTab );
+ ScAddress aAdrEnd ( nCol, 0, nTab );
+ ScPatternAttr* pOldPattern = NULL;
+
+ USHORT ni = 0;
+ USHORT nx = 0;
+ USHORT ns = 0;
+ if (nStartRow > 0)
+ {
+ // Anfangsbereich kopieren
+ short nIndex;
+ Search( nStartRow, nIndex );
+ ni = nNewCount = nIndex;
+ memcpy( pNewData, pData, ni*sizeof(ScAttrEntry) );
+
+ if ( ni )
+ {
+ nx = ni;
+ ns = pData[ni-1].nRow+1;
+ }
+
+ // erzeugen des neuen Daten-Array fortsetzen
+
+ if ((pData[ni].pPattern != pPattern) &&
+ ((ni==0) ? TRUE : (pData[ni - 1].nRow < nStartRow - 1)))
+ {
+ // Eintrag splitten
+ pNewData[nNewCount].nRow = nStartRow - 1;
+ pNewData[nNewCount].pPattern = pData[ni].pPattern;
+ nNewCount++;
+ ni++;
+ }
+ if (ni > 0)
+ if (pData[ni-1].pPattern == pPattern) // zusammenfassen
+ {
+ ni--;
+ nNewCount--;
+ }
+ } // if StartRow > 0
+
+ // ueberpruefen, ob Attributierung die Textbreite der Zelle aendert
+ // oder bedingte Formate neu gesetzt oder geloescht werden
+ while ( ns <= nEndRow )
+ {
+ const SfxItemSet& rNewSet = pPattern->GetItemSet();
+ const SfxItemSet& rOldSet = pData[nx].pPattern->GetItemSet();
+
+ BOOL bNumFormatChanged;
+ if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
+ rNewSet, rOldSet ) )
+ {
+ aAdrStart.SetRow( Max(nStartRow,ns) );
+ aAdrEnd .SetRow( Min(nEndRow,pData[nx].nRow) );
+ pDocument->InvalidateTextWidth( &aAdrStart, &aAdrEnd, bNumFormatChanged );
+#ifdef DBG_INVALIDATE
+ DBGOUTPUT("SetPatternArea");
+#endif
+ }
+ if ( &rNewSet.Get(ATTR_CONDITIONAL) != &rOldSet.Get(ATTR_CONDITIONAL) )
+ {
+ pDocument->ConditionalChanged( ((const SfxUInt32Item&)
+ rOldSet.Get(ATTR_CONDITIONAL)).GetValue() );
+ pDocument->ConditionalChanged( ((const SfxUInt32Item&)
+ rNewSet.Get(ATTR_CONDITIONAL)).GetValue() );
+ }
+ ns = pData[nx].nRow + 1;
+ nx++;
+ }
+
+
+ // Bereich setzen
+ pNewData[nNewCount].nRow = nEndRow;
+ pNewData[nNewCount].pPattern = pPattern;
+ nNewCount++;
+
+ USHORT nj = 0;
+ if (nEndRow < MAXROW)
+ {
+ // mittleren Bereich ueberspringen
+ while (pData[nj].nRow <= nEndRow) nj++;
+ if (pData[nj].pPattern == pPattern)
+ {
+ // Eintrag zusammenfassen
+ pNewData[nNewCount - 1].nRow = pData[nj].nRow;
+ nj++;
+ }
+ ScDocumentPool* pDocPool = pDocument->GetPool();
+ if (nj<ni)
+ {
+ // gesplitteten Eintrag im Pool verdoppeln
+ pDocPool->Put(*pData[ni-1].pPattern);
+
+ }
+ // Eintraege aus Pool loeschen
+ for (USHORT nk=ni; nk<nj; nk++)
+ {
+ pDocPool->Remove(*pData[nk].pPattern);
+ }
+ // Den Endbereich kopieren
+ while (nj < nCount)
+ {
+ pNewData[nNewCount].nRow = pData[nj].nRow;
+ pNewData[nNewCount].pPattern = pData[nj].pPattern;
+ nNewCount++;
+ nj++;
+ }
+ } // if EndRow < MaxRow
+ // Zeiger umsetzen
+ delete[] pData;
+ nCount = nNewCount;
+ pData = pNewData;
+ }
+ }
+ }
+// InfoBox(0, String(nCount) + String(" Eintraege") ).Execute();
+
+#ifdef DBG_UTIL
+ TestData();
+#endif
+}
+
+
+void ScAttrArray::ApplyStyleArea( USHORT nStartRow, USHORT nEndRow, ScStyleSheet* pStyle )
+{
+ if (nStartRow >= 0 && nStartRow <= MAXROW && nEndRow >= 0 && nEndRow <= MAXROW)
+ {
+ short nPos;
+ USHORT nStart=0;
+ if (!Search( nStartRow, nPos ))
+ {
+ DBG_ERROR("Search-Fehler");
+ return;
+ }
+
+ ScAddress aAdrStart( nCol, 0, nTab );
+ ScAddress aAdrEnd ( nCol, 0, nTab );
+
+ do
+ {
+ const ScPatternAttr* pOldPattern = pData[nPos].pPattern;
+ ScPatternAttr* pNewPattern = new ScPatternAttr(*pOldPattern);
+ pNewPattern->SetStyleSheet(pStyle);
+ USHORT nY1 = nStart;
+ USHORT nY2 = pData[nPos].nRow;
+ nStart = pData[nPos].nRow + 1;
+
+ if ( nY1 < nStartRow || nY2 > nEndRow )
+ {
+ if (nY1 < nStartRow) nY1=nStartRow;
+ if (nY2 > nEndRow) nY2=nEndRow;
+ SetPatternArea( nY1, nY2, pNewPattern, TRUE );
+ Search( nStart, nPos );
+ }
+ else
+ {
+ // ueberpruefen, ob Attributierung die Textbreite der Zelle aendert
+ // bedingte Formate in Vorlagen gibt es (noch) nicht
+
+ const SfxItemSet& rNewSet = pNewPattern->GetItemSet();
+ const SfxItemSet& rOldSet = pOldPattern->GetItemSet();
+
+ BOOL bNumFormatChanged;
+ if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
+ rNewSet, rOldSet ) )
+ {
+ aAdrStart.SetRow( nPos ? pData[nPos-1].nRow+1 : 0 );
+ aAdrEnd .SetRow( pData[nPos].nRow );
+ pDocument->InvalidateTextWidth( &aAdrStart, &aAdrEnd, bNumFormatChanged );
+#ifdef DBG_INVALIDATE
+ DBGOUTPUT("ApplyStyleArea");
+#endif
+ }
+
+ pDocument->GetPool()->Remove(*pData[nPos].pPattern);
+ pData[nPos].pPattern = (const ScPatternAttr*)
+ &pDocument->GetPool()->Put(*pNewPattern);
+ if (Concat(nPos))
+ Search(nStart, nPos);
+ else
+ nPos++;
+ }
+ delete pNewPattern;
+ }
+ while ((nStart <= nEndRow) && (nPos < (short)nCount));
+ }
+
+#ifdef DBG_UTIL
+ TestData();
+#endif
+}
+
+
+ // const wird weggecastet, weil es sonst
+ // zu ineffizient/kompliziert wird!
+#define SET_LINECOLOR(dest,c) \
+ if ((dest)) \
+ { \
+ ((SvxBorderLine*)(dest))->SetColor((c)); \
+ }
+
+#define SET_LINE(dest,src) \
+ if ((dest)) \
+ { \
+ SvxBorderLine* pCast = (SvxBorderLine*)(dest); \
+ pCast->SetOutWidth((src)->GetOutWidth()); \
+ pCast->SetInWidth ((src)->GetInWidth()); \
+ pCast->SetDistance((src)->GetDistance()); \
+ }
+
+void ScAttrArray::ApplyLineStyleArea( USHORT nStartRow, USHORT nEndRow,
+ const SvxBorderLine* pLine, BOOL bColorOnly )
+{
+ if ( bColorOnly && !pLine )
+ return;
+
+ if (nStartRow >= 0 && nStartRow <= MAXROW && nEndRow >= 0 && nEndRow <= MAXROW)
+ {
+ short nPos;
+ USHORT nStart=0;
+ if (!Search( nStartRow, nPos ))
+ {
+ DBG_ERROR("Search-Fehler");
+ return;
+ }
+
+ do
+ {
+ const ScPatternAttr* pOldPattern = pData[nPos].pPattern;
+ const SfxPoolItem* pItem = NULL;
+
+ if ( SFX_ITEM_SET == pOldPattern->GetItemSet().
+ GetItemState( ATTR_BORDER, TRUE, &pItem ) )
+ {
+ ScPatternAttr* pNewPattern = new ScPatternAttr(*pOldPattern);
+ SvxBoxItem aBoxItem( *(const SvxBoxItem*)pItem );
+ USHORT nY1 = nStart;
+ USHORT nY2 = pData[nPos].nRow;
+
+ // Linienattribute holen und mit Parametern aktualisieren
+
+ if ( !pLine )
+ {
+ if ( aBoxItem.GetTop() ) aBoxItem.SetLine( NULL, BOX_LINE_TOP );
+ if ( aBoxItem.GetBottom() ) aBoxItem.SetLine( NULL, BOX_LINE_BOTTOM );
+ if ( aBoxItem.GetLeft() ) aBoxItem.SetLine( NULL, BOX_LINE_LEFT );
+ if ( aBoxItem.GetRight() ) aBoxItem.SetLine( NULL, BOX_LINE_RIGHT );
+ }
+ else
+ {
+ if ( bColorOnly )
+ {
+ Color aColor( pLine->GetColor() );
+ SET_LINECOLOR( aBoxItem.GetTop(), aColor );
+ SET_LINECOLOR( aBoxItem.GetBottom(), aColor );
+ SET_LINECOLOR( aBoxItem.GetLeft(), aColor );
+ SET_LINECOLOR( aBoxItem.GetRight(), aColor );
+ }
+ else
+ {
+ SET_LINE( aBoxItem.GetTop(), pLine );
+ SET_LINE( aBoxItem.GetBottom(), pLine );
+ SET_LINE( aBoxItem.GetLeft(), pLine );
+ SET_LINE( aBoxItem.GetRight(), pLine );
+ }
+ }
+ pNewPattern->GetItemSet().Put( aBoxItem );
+
+ nStart = pData[nPos].nRow + 1;
+
+ if ( nY1 < nStartRow || nY2 > nEndRow )
+ {
+ if (nY1 < nStartRow) nY1=nStartRow;
+ if (nY2 > nEndRow) nY2=nEndRow;
+ SetPatternArea( nY1, nY2, pNewPattern, TRUE );
+ Search( nStart, nPos );
+ }
+ else
+ {
+ //! aus Pool loeschen?
+ pDocument->GetPool()->Remove(*pData[nPos].pPattern);
+ pData[nPos].pPattern = (const ScPatternAttr*)
+ &pDocument->GetPool()->Put(*pNewPattern);
+
+ if (Concat(nPos))
+ Search(nStart, nPos);
+ else
+ nPos++;
+ }
+ delete pNewPattern;
+ }
+ else
+ {
+ nStart = pData[nPos].nRow + 1;
+ nPos++;
+ }
+ }
+ while ((nStart <= nEndRow) && (nPos < (short)nCount));
+ }
+}
+
+#undef SET_LINECOLOR
+#undef SET_LINE
+
+
+void ScAttrArray::ApplyCacheArea( USHORT nStartRow, USHORT nEndRow, SfxItemPoolCache* pCache )
+{
+#ifdef DBG_UTIL
+ TestData();
+#endif
+
+ if (nStartRow >= 0 && nStartRow <= MAXROW && nEndRow >= 0 && nEndRow <= MAXROW)
+ {
+ short nPos;
+ USHORT nStart=0;
+ if (!Search( nStartRow, nPos ))
+ {
+ DBG_ERROR("Search-Fehler");
+ return;
+ }
+
+ ScAddress aAdrStart( nCol, 0, nTab );
+ ScAddress aAdrEnd ( nCol, 0, nTab );
+
+ do
+ {
+ const ScPatternAttr* pOldPattern = pData[nPos].pPattern;
+ const ScPatternAttr* pNewPattern = (const ScPatternAttr*) &pCache->ApplyTo( *pOldPattern, TRUE );
+ ScDocumentPool::CheckRef( *pOldPattern );
+ ScDocumentPool::CheckRef( *pNewPattern );
+ if (pNewPattern != pOldPattern)
+ {
+ USHORT nY1 = nStart;
+ USHORT nY2 = pData[nPos].nRow;
+ nStart = pData[nPos].nRow + 1;
+
+ if ( nY1 < nStartRow || nY2 > nEndRow )
+ {
+ if (nY1 < nStartRow) nY1=nStartRow;
+ if (nY2 > nEndRow) nY2=nEndRow;
+ SetPatternArea( nY1, nY2, pNewPattern );
+ Search( nStart, nPos );
+ }
+ else
+ {
+ // ueberpruefen, ob Attributierung die Textbreite der Zelle aendert
+
+ const SfxItemSet& rNewSet = pNewPattern->GetItemSet();
+ const SfxItemSet& rOldSet = pOldPattern->GetItemSet();
+
+ BOOL bNumFormatChanged;
+ if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
+ rNewSet, rOldSet ) )
+ {
+ aAdrStart.SetRow( nPos ? pData[nPos-1].nRow+1 : 0 );
+ aAdrEnd .SetRow( pData[nPos].nRow );
+ pDocument->InvalidateTextWidth( &aAdrStart, &aAdrEnd, bNumFormatChanged );
+#ifdef DBG_INVALIDATE
+ DBGOUTPUT("ApplyCacheArea");
+#endif
+ }
+
+ // bedingte Formate neu gesetzt oder geloescht ?
+
+ if ( &rNewSet.Get(ATTR_CONDITIONAL) != &rOldSet.Get(ATTR_CONDITIONAL) )
+ {
+ pDocument->ConditionalChanged( ((const SfxUInt32Item&)
+ rOldSet.Get(ATTR_CONDITIONAL)).GetValue() );
+ pDocument->ConditionalChanged( ((const SfxUInt32Item&)
+ rNewSet.Get(ATTR_CONDITIONAL)).GetValue() );
+ }
+
+ pDocument->GetPool()->Remove(*pData[nPos].pPattern);
+ pData[nPos].pPattern = pNewPattern;
+ if (Concat(nPos))
+ Search(nStart, nPos);
+ else
+ ++nPos;
+ }
+ }
+ else
+ {
+//!!!!!!!!!!!!!!!!!! mit diesem Remove gibt es Abstuerze (Calc1 Import)
+//! pDocument->GetPool()->Remove(*pNewPattern);
+ nStart = pData[nPos].nRow + 1;
+ ++nPos;
+ }
+ }
+ while (nStart <= nEndRow);
+ }
+
+#ifdef DBG_UTIL
+ TestData();
+#endif
+}
+
+
+void lcl_MergeDeep( SfxItemSet& rMergeSet, const SfxItemSet& rSource )
+{
+ const SfxPoolItem* pNewItem;
+ const SfxPoolItem* pOldItem;
+ for (USHORT nId=ATTR_PATTERN_START; nId<=ATTR_PATTERN_END; nId++)
+ {
+ // pMergeSet hat keinen Parent
+ SfxItemState eOldState = rMergeSet.GetItemState( nId, FALSE, &pOldItem );
+
+ if ( eOldState == SFX_ITEM_DEFAULT ) // Default
+ {
+ SfxItemState eNewState = rSource.GetItemState( nId, TRUE, &pNewItem );
+ if ( eNewState == SFX_ITEM_SET )
+ {
+ if ( *pNewItem != rMergeSet.GetPool()->GetDefaultItem(nId) )
+ rMergeSet.InvalidateItem( nId );
+ }
+ }
+ else if ( eOldState == SFX_ITEM_SET ) // Item gesetzt
+ {
+ SfxItemState eNewState = rSource.GetItemState( nId, TRUE, &pNewItem );
+ if ( eNewState == SFX_ITEM_SET )
+ {
+ if ( pNewItem != pOldItem ) // beide gepuhlt
+ rMergeSet.InvalidateItem( nId );
+ }
+ else // Default
+ {
+ if ( *pOldItem != rSource.GetPool()->GetDefaultItem(nId) )
+ rMergeSet.InvalidateItem( nId );
+ }
+ }
+ // Dontcare bleibt Dontcare
+ }
+}
+
+
+void ScAttrArray::MergePatternArea( USHORT nStartRow, USHORT nEndRow,
+ SfxItemSet** ppSet, BOOL bDeep ) const
+{
+ if (nStartRow >= 0 && nStartRow <= MAXROW && nEndRow >= 0 && nEndRow <= MAXROW)
+ {
+ const ScPatternAttr* pOld1 = NULL;
+ const ScPatternAttr* pOld2 = NULL;
+
+ short nPos;
+ USHORT nStart=0;
+ if (!Search( nStartRow, nPos ))
+ {
+ DBG_ERROR("Search-Fehler");
+ return;
+ }
+
+ do
+ {
+ // gleiche Patterns muessen nicht mehrfach angesehen werden
+
+ const ScPatternAttr* pPattern = pData[nPos].pPattern;
+ if ( pPattern != pOld1 && pPattern != pOld2 )
+ {
+ const SfxItemSet& rThisSet = pPattern->GetItemSet();
+ if (*ppSet)
+ {
+ // (*ppSet)->MergeValues( rThisSet, FALSE );
+ // geht nicht, weil die Vorlagen nicht beruecksichtigt werden
+
+ if (bDeep)
+ lcl_MergeDeep( **ppSet, rThisSet );
+ else
+ (*ppSet)->MergeValues( rThisSet, FALSE );
+ }
+ else
+ {
+ // erstes Pattern - in Set ohne Parent kopieren
+ *ppSet = new SfxItemSet( *rThisSet.GetPool(), rThisSet.GetRanges() );
+ (*ppSet)->Set( rThisSet, bDeep );
+ }
+
+ pOld2 = pOld1;
+ pOld1 = pPattern;
+ }
+
+ nStart = pData[nPos].nRow + 1;
+ ++nPos;
+ }
+ while (nStart <= nEndRow);
+ }
+}
+
+
+
+// Umrandung zusammenbauen
+
+BOOL lcl_TestAttr( const SvxBorderLine* pOldLine, const SvxBorderLine* pNewLine,
+ BYTE& rModified, const SvxBorderLine*& rpNew )
+{
+ if (rModified == SC_LINE_DONTCARE)
+ return FALSE; // weiter geht's nicht
+
+ if (rModified == SC_LINE_EMPTY)
+ {
+ rModified = SC_LINE_SET;
+ rpNew = pNewLine;
+ return TRUE; // zum ersten mal gesetzt
+ }
+
+ if (pOldLine == pNewLine)
+ {
+ rpNew = pOldLine;
+ return FALSE;
+ }
+
+ if (pOldLine && pNewLine)
+ if (*pOldLine == *pNewLine)
+ {
+ rpNew = pOldLine;
+ return FALSE;
+ }
+
+ rModified = SC_LINE_DONTCARE;
+ rpNew = NULL;
+ return TRUE; // andere Linie -> dontcare
+}
+
+
+void lcl_MergeToFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner,
+ ScLineFlags& rFlags, const ScPatternAttr* pPattern,
+ BOOL bLeft, USHORT nDistRight, BOOL bTop, USHORT nDistBottom )
+{
+ // rechten/unteren Rahmen setzen, wenn Zelle bis zum Ende zusammengefasst:
+ const ScMergeAttr& rMerge = (const ScMergeAttr&)pPattern->GetItem(ATTR_MERGE);
+ if ( rMerge.GetColMerge() == nDistRight + 1 )
+ nDistRight = 0;
+ if ( rMerge.GetRowMerge() == nDistBottom + 1 )
+ nDistBottom = 0;
+
+ const SvxBoxItem* pCellFrame = (SvxBoxItem*) &pPattern->GetItemSet().Get( ATTR_BORDER );
+ const SvxBorderLine* pLeftAttr = pCellFrame->GetLeft();
+ const SvxBorderLine* pRightAttr = pCellFrame->GetRight();
+ const SvxBorderLine* pTopAttr = pCellFrame->GetTop();
+ const SvxBorderLine* pBottomAttr = pCellFrame->GetBottom();
+ const SvxBorderLine* pNew;
+
+ if (bTop)
+ {
+ if (lcl_TestAttr( pLineOuter->GetTop(), pTopAttr, rFlags.nTop, pNew ))
+ pLineOuter->SetLine( pNew, BOX_LINE_TOP );
+ }
+ else
+ {
+ if (lcl_TestAttr( pLineInner->GetHori(), pTopAttr, rFlags.nHori, pNew ))
+ pLineInner->SetLine( pNew, BOXINFO_LINE_HORI );
+ }
+
+ if (nDistBottom == 0)
+ {
+ if (lcl_TestAttr( pLineOuter->GetBottom(), pBottomAttr, rFlags.nBottom, pNew ))
+ pLineOuter->SetLine( pNew, BOX_LINE_BOTTOM );
+ }
+ else
+ {
+ if (lcl_TestAttr( pLineInner->GetHori(), pBottomAttr, rFlags.nHori, pNew ))
+ pLineInner->SetLine( pNew, BOXINFO_LINE_HORI );
+ }
+
+ if (bLeft)
+ {
+ if (lcl_TestAttr( pLineOuter->GetLeft(), pLeftAttr, rFlags.nLeft, pNew ))
+ pLineOuter->SetLine( pNew, BOX_LINE_LEFT );
+ }
+ else
+ {
+ if (lcl_TestAttr( pLineInner->GetVert(), pLeftAttr, rFlags.nVert, pNew ))
+ pLineInner->SetLine( pNew, BOXINFO_LINE_VERT );
+ }
+
+ if (nDistRight == 0)
+ {
+ if (lcl_TestAttr( pLineOuter->GetRight(), pRightAttr, rFlags.nRight, pNew ))
+ pLineOuter->SetLine( pNew, BOX_LINE_RIGHT );
+ }
+ else
+ {
+ if (lcl_TestAttr( pLineInner->GetVert(), pRightAttr, rFlags.nVert, pNew ))
+ pLineInner->SetLine( pNew, BOXINFO_LINE_VERT );
+ }
+}
+
+
+void ScAttrArray::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner,
+ ScLineFlags& rFlags,
+ USHORT nStartRow, USHORT nEndRow, BOOL bLeft, USHORT nDistRight ) const
+{
+ const ScPatternAttr* pPattern;
+
+ if (nStartRow == nEndRow)
+ {
+ pPattern = GetPattern( nStartRow );
+ lcl_MergeToFrame( pLineOuter, pLineInner, rFlags, pPattern, bLeft, nDistRight, TRUE, 0 );
+ }
+ else
+ {
+ pPattern = GetPattern( nStartRow );
+ lcl_MergeToFrame( pLineOuter, pLineInner, rFlags, pPattern, bLeft, nDistRight, TRUE,
+ nEndRow-nStartRow );
+
+ short nStartIndex;
+ short nEndIndex;
+ Search( nStartRow+1, nStartIndex );
+ Search( nEndRow-1, nEndIndex );
+ for (short i=nStartIndex; i<=nEndIndex; i++)
+ {
+ pPattern = (ScPatternAttr*) pData[i].pPattern;
+ lcl_MergeToFrame( pLineOuter, pLineInner, rFlags, pPattern, bLeft, nDistRight, FALSE,
+ nEndRow - Min( pData[i].nRow, (USHORT)(nEndRow-1) ) );
+ // nDistBottom hier immer > 0
+ }
+
+ pPattern = GetPattern( nEndRow );
+ lcl_MergeToFrame( pLineOuter, pLineInner, rFlags, pPattern, bLeft, nDistRight, FALSE, 0 );
+ }
+}
+
+//
+// Rahmen anwenden
+//
+
+// ApplyFrame - auf einen Eintrag im Array
+
+
+BOOL ScAttrArray::ApplyFrame( const SvxBoxItem* pBoxItem,
+ const SvxBoxInfoItem* pBoxInfoItem,
+ USHORT nStartRow, USHORT nEndRow,
+ BOOL bLeft, USHORT nDistRight, BOOL bTop, USHORT nDistBottom )
+{
+ DBG_ASSERT( pBoxItem && pBoxInfoItem, "Linienattribute fehlen!" );
+
+ const ScPatternAttr* pPattern = GetPattern( nStartRow );
+ const SvxBoxItem* pOldFrame = (const SvxBoxItem*)
+ &pPattern->GetItemSet().Get( ATTR_BORDER );
+
+ // rechten/unteren Rahmen setzen, wenn Zelle bis zum Ende zusammengefasst:
+ const ScMergeAttr& rMerge = (const ScMergeAttr&)pPattern->GetItem(ATTR_MERGE);
+ if ( rMerge.GetColMerge() == nDistRight + 1 )
+ nDistRight = 0;
+ if ( rMerge.GetRowMerge() == nDistBottom + 1 )
+ nDistBottom = 0;
+
+ SvxBoxItem* pNewFrame = new SvxBoxItem( *pOldFrame );
+
+ if ( bLeft ? pBoxInfoItem->IsValid(VALID_LEFT) : pBoxInfoItem->IsValid(VALID_VERT) )
+ pNewFrame->SetLine( bLeft ? pBoxItem->GetLeft() : pBoxInfoItem->GetVert(),
+ BOX_LINE_LEFT );
+ if ( (nDistRight==0) ? pBoxInfoItem->IsValid(VALID_RIGHT) : pBoxInfoItem->IsValid(VALID_VERT) )
+ pNewFrame->SetLine( (nDistRight==0) ? pBoxItem->GetRight() : pBoxInfoItem->GetVert(),
+ BOX_LINE_RIGHT );
+ if ( bTop ? pBoxInfoItem->IsValid(VALID_TOP) : pBoxInfoItem->IsValid(VALID_HORI) )
+ pNewFrame->SetLine( bTop ? pBoxItem->GetTop() : pBoxInfoItem->GetHori(),
+ BOX_LINE_TOP );
+ if ( (nDistBottom==0) ? pBoxInfoItem->IsValid(VALID_BOTTOM) : pBoxInfoItem->IsValid(VALID_HORI) )
+ pNewFrame->SetLine( (nDistBottom==0) ? pBoxItem->GetBottom() : pBoxInfoItem->GetHori(),
+ BOX_LINE_BOTTOM );
+
+ if (*pNewFrame == *pOldFrame)
+ {
+ delete pNewFrame;
+ return FALSE;
+ }
+ else
+ {
+ SfxItemPoolCache aCache( pDocument->GetPool(), pNewFrame );
+ ApplyCacheArea( nStartRow, nEndRow, &aCache );
+
+/* ScPatternAttr* pNewPattern = (ScPatternAttr*) pPattern->Clone();
+ pNewPattern->GetItemSet().Put( *pNewFrame );
+ SetPatternArea( nStartRow, nEndRow, pNewPattern, TRUE );
+ delete pNewFrame;
+*/
+ return TRUE;
+ }
+}
+
+
+void ScAttrArray::ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInfoItem* pLineInner,
+ USHORT nStartRow, USHORT nEndRow, BOOL bLeft, USHORT nDistRight )
+{
+ if (nStartRow == nEndRow)
+ ApplyFrame( pLineOuter, pLineInner, nStartRow, nEndRow, bLeft, nDistRight, TRUE, 0 );
+ else
+ {
+ ApplyFrame( pLineOuter, pLineInner, nStartRow, nStartRow, bLeft, nDistRight,
+ TRUE, nEndRow-nStartRow );
+
+ if ( nEndRow > nStartRow+1 ) // innerer Teil vorhanden?
+ {
+ short nStartIndex;
+ short nEndIndex;
+ Search( nStartRow+1, nStartIndex );
+ Search( nEndRow-1, nEndIndex );
+ USHORT nTmpStart = nStartRow+1;
+ USHORT nTmpEnd;
+ for (short i=nStartIndex; i<=nEndIndex;)
+ {
+ nTmpEnd = Min( (USHORT)(nEndRow-1), (USHORT)(pData[i].nRow) );
+ BOOL bChanged = ApplyFrame( pLineOuter, pLineInner, nTmpStart, nTmpEnd,
+ bLeft, nDistRight, FALSE, nEndRow-nTmpEnd );
+ nTmpStart = nTmpEnd+1;
+ if (bChanged)
+ {
+ Search(nTmpStart, i);
+ Search(nEndRow-1, nEndIndex);
+ }
+ else
+ i++;
+ }
+ }
+
+ ApplyFrame( pLineOuter, pLineInner, nEndRow, nEndRow, bLeft, nDistRight, FALSE, 0 );
+ }
+}
+
+
+long lcl_LineSize( const SvxBorderLine& rLine )
+{
+ // nur eine Linie -> halbe Breite, min. 20
+ // doppelte Linie -> halber Abstand + eine Linie (je min. 20)
+
+ long nTotal = 0;
+ USHORT nWidth = Max( rLine.GetOutWidth(), rLine.GetInWidth() );
+ USHORT nDist = rLine.GetDistance();
+ if (nDist)
+ {
+ DBG_ASSERT( rLine.GetOutWidth() && rLine.GetInWidth(),
+ "Linie hat Abstand, aber nur eine Breite ???" );
+
+// nTotal += ( nDist > 40 ) ? ( nDist / 2 ) : 20;
+ nTotal += ( nDist > 20 ) ? nDist : 20;
+ nTotal += ( nWidth > 20 ) ? nWidth : 20;
+ }
+ else if (nWidth)
+// nTotal += ( nWidth > 40 ) ? ( nWidth / 2 ) : 20;
+ nTotal += ( nWidth > 20 ) ? nWidth : 20;
+
+ //! auch halbieren ???
+
+ return nTotal;
+}
+
+
+BOOL ScAttrArray::HasLines( USHORT nRow1, USHORT nRow2, Rectangle& rSizes,
+ BOOL bLeft, BOOL bRight ) const
+{
+ short nStartIndex;
+ short nEndIndex;
+ Search( nRow1, nStartIndex );
+ Search( nRow2, nEndIndex );
+ BOOL bFound = FALSE;
+
+ const SvxBoxItem* pItem = 0;
+ const SvxBorderLine* pLine = 0;
+ long nCmp;
+
+ // oben
+
+ pItem = (const SvxBoxItem*) &pData[nStartIndex].pPattern->GetItem(ATTR_BORDER);
+ pLine = pItem->GetTop();
+ if (pLine)
+ {
+ nCmp = lcl_LineSize(*pLine);
+ if ( nCmp > rSizes.Top() )
+ rSizes.Top() = nCmp;
+ bFound = TRUE;
+ }
+
+ // unten
+
+ if ( nEndIndex != nStartIndex )
+ pItem = (const SvxBoxItem*) &pData[nEndIndex].pPattern->GetItem(ATTR_BORDER);
+ pLine = pItem->GetBottom();
+ if (pLine)
+ {
+ nCmp = lcl_LineSize(*pLine);
+ if ( nCmp > rSizes.Bottom() )
+ rSizes.Bottom() = nCmp;
+ bFound = TRUE;
+ }
+
+ if ( bLeft || bRight )
+ for ( USHORT i=nStartIndex; i<=nEndIndex; i++)
+ {
+ pItem = (const SvxBoxItem*) &pData[i].pPattern->GetItem(ATTR_BORDER);
+
+ // links
+
+ if (bLeft)
+ {
+ pLine = pItem->GetLeft();
+ if (pLine)
+ {
+ nCmp = lcl_LineSize(*pLine);
+ if ( nCmp > rSizes.Left() )
+ rSizes.Left() = nCmp;
+ bFound = TRUE;
+ }
+ }
+
+ // rechts
+
+ if (bRight)
+ {
+ pLine = pItem->GetRight();
+ if (pLine)
+ {
+ nCmp = lcl_LineSize(*pLine);
+ if ( nCmp > rSizes.Right() )
+ rSizes.Right() = nCmp;
+ bFound = TRUE;
+ }
+ }
+ }
+
+ return bFound;
+}
+
+// Testen, ob Bereich bestimmtes Attribut enthaelt
+
+BOOL ScAttrArray::HasAttrib( USHORT nRow1, USHORT nRow2, USHORT nMask ) const
+{
+ short nStartIndex;
+ short nEndIndex;
+ Search( nRow1, nStartIndex );
+ Search( nRow2, nEndIndex );
+ BOOL bFound = FALSE;
+
+ for (short i=nStartIndex; i<=nEndIndex && !bFound; i++)
+ {
+ const ScPatternAttr* pPattern = pData[i].pPattern;
+ if ( nMask & HASATTR_MERGED )
+ {
+ const ScMergeAttr* pMerge =
+ (const ScMergeAttr*) &pPattern->GetItem( ATTR_MERGE );
+ if ( pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1 )
+ bFound = TRUE;
+ }
+ if ( nMask & ( HASATTR_OVERLAPPED | HASATTR_NOTOVERLAPPED | HASATTR_AUTOFILTER ) )
+ {
+ const ScMergeFlagAttr* pMergeFlag =
+ (const ScMergeFlagAttr*) &pPattern->GetItem( ATTR_MERGE_FLAG );
+ if ( (nMask & HASATTR_OVERLAPPED) && pMergeFlag->IsOverlapped() )
+ bFound = TRUE;
+ if ( (nMask & HASATTR_NOTOVERLAPPED) && !pMergeFlag->IsOverlapped() )
+ bFound = TRUE;
+ if ( (nMask & HASATTR_AUTOFILTER) && pMergeFlag->HasAutoFilter() )
+ bFound = TRUE;
+ }
+ if ( nMask & HASATTR_LINES )
+ {
+ const SvxBoxItem* pBox =
+ (const SvxBoxItem*) &pPattern->GetItem( ATTR_BORDER );
+ if ( pBox->GetLeft() || pBox->GetRight() || pBox->GetTop() || pBox->GetBottom() )
+ bFound = TRUE;
+ }
+ if ( nMask & HASATTR_SHADOW )
+ {
+ const SvxShadowItem* pShadow =
+ (const SvxShadowItem*) &pPattern->GetItem( ATTR_SHADOW );
+ if ( pShadow->GetLocation() != SVX_SHADOW_NONE )
+ bFound = TRUE;
+ }
+ if ( nMask & HASATTR_CONDITIONAL )
+ {
+ const SfxUInt32Item* pConditional =
+ (const SfxUInt32Item*) &pPattern->GetItem( ATTR_CONDITIONAL );
+ if ( pConditional->GetValue() != 0 )
+ bFound = TRUE;
+ }
+ if ( nMask & HASATTR_PROTECTED )
+ {
+ const ScProtectionAttr* pProtect =
+ (const ScProtectionAttr*) &pPattern->GetItem( ATTR_PROTECTION );
+ if ( pProtect->GetProtection() || pProtect->GetHideCell() )
+ bFound = TRUE;
+ }
+ if ( nMask & HASATTR_ROTATE )
+ {
+ const SfxInt32Item* pRotate =
+ (const SfxInt32Item*) &pPattern->GetItem( ATTR_ROTATE_VALUE );
+ if ( pRotate->GetValue() != 0 )
+ bFound = TRUE;
+ }
+ if ( nMask & HASATTR_NEEDHEIGHT )
+ {
+ SvxCellOrientation eOrient = (SvxCellOrientation)
+ ((const SvxOrientationItem&)pPattern->GetItem( ATTR_ORIENTATION )).GetValue();
+ if (eOrient != SVX_ORIENTATION_STANDARD)
+ bFound = TRUE;
+ else if (((const SfxBoolItem&)pPattern->GetItem( ATTR_LINEBREAK )).GetValue())
+ bFound = TRUE;
+ else if ((SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->
+ GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK)
+ bFound = TRUE;
+ else if (((const SfxUInt32Item&)pPattern->GetItem( ATTR_CONDITIONAL )).GetValue())
+ bFound = TRUE;
+ else if (((const SfxInt32Item&)pPattern->GetItem( ATTR_ROTATE_VALUE )).GetValue())
+ bFound = TRUE;
+ }
+ if ( nMask & ( HASATTR_SHADOW_RIGHT | HASATTR_SHADOW_DOWN ) )
+ {
+ const SvxShadowItem* pShadow =
+ (const SvxShadowItem*) &pPattern->GetItem( ATTR_SHADOW );
+ SvxShadowLocation eLoc = pShadow->GetLocation();
+ if ( nMask & HASATTR_SHADOW_RIGHT )
+ if ( eLoc == SVX_SHADOW_TOPRIGHT || eLoc == SVX_SHADOW_BOTTOMRIGHT )
+ bFound = TRUE;
+ if ( nMask & HASATTR_SHADOW_DOWN )
+ if ( eLoc == SVX_SHADOW_BOTTOMLEFT || eLoc == SVX_SHADOW_BOTTOMRIGHT )
+ bFound = TRUE;
+ }
+ }
+
+ return bFound;
+}
+
+// Bereich um evtl. enthaltene Zusammenfassungen erweitern
+// und evtl. MergeFlag anpassen (bRefresh)
+
+BOOL ScAttrArray::ExtendMerge( USHORT nThisCol, USHORT nStartRow, USHORT nEndRow,
+ USHORT& rPaintCol, USHORT& rPaintRow,
+ BOOL bRefresh, BOOL bAttrs )
+{
+ const ScPatternAttr* pPattern;
+ const ScMergeAttr* pItem;
+ short nStartIndex;
+ short nEndIndex;
+ Search( nStartRow, nStartIndex );
+ Search( nEndRow, nEndIndex );
+ BOOL bFound = FALSE;
+
+ for (short i=nStartIndex; i<=nEndIndex; i++)
+ {
+ pPattern = pData[i].pPattern;
+ pItem = (const ScMergeAttr*) &pPattern->GetItem( ATTR_MERGE );
+ INT16 nCountX = pItem->GetColMerge();
+ INT16 nCountY = pItem->GetRowMerge();
+ if (nCountX>1 || nCountY>1)
+ {
+ USHORT nThisRow = (i>0) ? pData[i-1].nRow+1 : 0;
+ USHORT nMergeEndCol = nThisCol + nCountX - 1;
+ USHORT nMergeEndRow = nThisRow + nCountY - 1;
+ if (nMergeEndCol > rPaintCol && nMergeEndCol <= MAXCOL)
+ rPaintCol = nMergeEndCol;
+ if (nMergeEndRow > rPaintRow && nMergeEndRow <= MAXROW)
+ rPaintRow = nMergeEndRow;
+ bFound = TRUE;
+
+ if (bAttrs)
+ {
+ const SvxShadowItem* pShadow =
+ (const SvxShadowItem*) &pPattern->GetItem( ATTR_SHADOW );
+ SvxShadowLocation eLoc = pShadow->GetLocation();
+ if ( eLoc == SVX_SHADOW_TOPRIGHT || eLoc == SVX_SHADOW_BOTTOMRIGHT )
+ if ( nMergeEndCol+1 > rPaintCol && nMergeEndCol < MAXCOL )
+ rPaintCol = nMergeEndCol+1;
+ if ( eLoc == SVX_SHADOW_BOTTOMLEFT || eLoc == SVX_SHADOW_BOTTOMRIGHT )
+ if ( nMergeEndRow+1 > rPaintRow && nMergeEndRow < MAXROW )
+ rPaintRow = nMergeEndRow+1;
+ }
+
+ if (bRefresh)
+ {
+ if ( nMergeEndCol > nThisCol )
+ pDocument->ApplyFlagsTab( nThisCol+1, nThisRow, nMergeEndCol, pData[i].nRow,
+ nTab, SC_MF_HOR );
+ if ( nMergeEndRow > nThisRow )
+ pDocument->ApplyFlagsTab( nThisCol, nThisRow+1, nThisCol, nMergeEndRow,
+ nTab, SC_MF_VER );
+ if ( nMergeEndCol > nThisCol && nMergeEndRow > nThisRow )
+ pDocument->ApplyFlagsTab( nThisCol+1, nThisRow+1, nMergeEndCol, nMergeEndRow,
+ nTab, SC_MF_HOR | SC_MF_VER );
+
+ Search( nThisRow, i ); // Daten wurden veraendert
+ Search( nStartRow, nStartIndex );
+ Search( nEndRow, nEndIndex );
+ }
+ }
+ }
+
+ return bFound;
+}
+
+
+BOOL ScAttrArray::RemoveAreaMerge(USHORT nStartRow, USHORT nEndRow)
+{
+ BOOL bFound = FALSE;
+ const ScPatternAttr* pPattern;
+ const ScMergeAttr* pItem;
+ short nIndex;
+
+ Search( nStartRow, nIndex );
+ USHORT nThisStart = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
+ if (nThisStart < nStartRow)
+ nThisStart = nStartRow;
+
+ while ( nThisStart <= nEndRow )
+ {
+ USHORT nThisEnd = pData[nIndex].nRow;
+ if (nThisEnd > nEndRow)
+ nThisEnd = nEndRow;
+
+ pPattern = pData[nIndex].pPattern;
+ pItem = (const ScMergeAttr*) &pPattern->GetItem( ATTR_MERGE );
+ INT16 nCountX = pItem->GetColMerge();
+ INT16 nCountY = pItem->GetRowMerge();
+ if (nCountX>1 || nCountY>1)
+ {
+ const ScMergeAttr* pAttr = (const ScMergeAttr*)
+ &pDocument->GetPool()->GetDefaultItem( ATTR_MERGE );
+ const ScMergeFlagAttr* pFlagAttr = (const ScMergeFlagAttr*)
+ &pDocument->GetPool()->GetDefaultItem( ATTR_MERGE_FLAG );
+
+ DBG_ASSERT( nCountY==1 || nThisStart==nThisEnd, "was'n hier los?" );
+
+ USHORT nThisCol = nCol;
+ USHORT nMergeEndCol = nThisCol + nCountX - 1;
+ USHORT nMergeEndRow = nThisEnd + nCountY - 1;
+
+ //! ApplyAttr fuer Bereiche !!!
+
+ for (USHORT nThisRow = nThisStart; nThisRow <= nThisEnd; nThisRow++)
+ pDocument->ApplyAttr( nThisCol, nThisRow, nTab, *pAttr );
+
+ ScPatternAttr* pNewPattern = new ScPatternAttr( pDocument->GetPool() );
+ SfxItemSet* pSet = &pNewPattern->GetItemSet();
+ pSet->Put( *pFlagAttr );
+ pDocument->ApplyPatternAreaTab( nThisCol, nThisStart, nMergeEndCol, nMergeEndRow,
+ nTab, *pNewPattern );
+ delete pNewPattern;
+
+ Search( nThisEnd, nIndex ); // Daten wurden veraendert !!!
+ }
+
+ ++nIndex;
+ if ( nIndex < (short) nCount )
+ nThisStart = pData[nIndex-1].nRow+1;
+ else
+ nThisStart = MAXROW+1; // Ende
+ }
+
+ return bFound;
+}
+
+ // Bereich loeschen, aber Merge-Flags stehenlassen
+
+void ScAttrArray::DeleteAreaSafe(USHORT nStartRow, USHORT nEndRow)
+{
+ SetPatternAreaSafe( nStartRow, nEndRow, pDocument->GetDefPattern(), TRUE );
+}
+
+
+void ScAttrArray::SetPatternAreaSafe( USHORT nStartRow, USHORT nEndRow,
+ const ScPatternAttr* pWantedPattern, BOOL bDefault )
+{
+ const ScPatternAttr* pOldPattern;
+ const ScMergeFlagAttr* pItem;
+
+ short nIndex;
+ USHORT nRow;
+ USHORT nThisRow;
+ BOOL bFirstUse = TRUE;
+
+ Search( nStartRow, nIndex );
+ nThisRow = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
+ while ( nThisRow <= nEndRow )
+ {
+ pOldPattern = pData[nIndex].pPattern;
+ if (pOldPattern != pWantedPattern) //! else-Zweig ?
+ {
+ if (nThisRow < nStartRow) nThisRow = nStartRow;
+ nRow = pData[nIndex].nRow;
+ USHORT nAttrRow = Min( (USHORT)nRow, (USHORT)nEndRow );
+ pItem = (const ScMergeFlagAttr*) &pOldPattern->GetItem( ATTR_MERGE_FLAG );
+
+ if (pItem->IsOverlapped() || pItem->HasAutoFilter())
+ {
+ ScPatternAttr* pNewPattern;
+ if (bDefault)
+ pNewPattern = new ScPatternAttr( pDocument->GetPool() );
+ else
+ pNewPattern = new ScPatternAttr( *pWantedPattern );
+ SfxItemSet* pSet = &pNewPattern->GetItemSet();
+ pSet->Put( *pItem );
+ SetPatternArea( nThisRow, nAttrRow, pNewPattern, TRUE );
+ delete pNewPattern;
+ }
+ else
+ {
+ if ( !bDefault )
+ {
+ if (bFirstUse)
+ bFirstUse = FALSE;
+ else
+ pDocument->GetPool()->Put( *pWantedPattern ); // im Pool ist es schon!
+ }
+ SetPatternArea( nThisRow, nAttrRow, pWantedPattern );
+ }
+
+ Search( nThisRow, nIndex ); // Daten wurden veraendert !!!
+ }
+
+ ++nIndex;
+ nThisRow = pData[nIndex-1].nRow+1;
+ }
+}
+
+
+BOOL ScAttrArray::ApplyFlags( USHORT nStartRow, USHORT nEndRow, INT16 nFlags )
+{
+ const ScPatternAttr* pOldPattern;
+
+ INT16 nOldValue;
+ short nIndex;
+ USHORT nRow;
+ USHORT nThisRow;
+ BOOL bChanged = FALSE;
+
+ Search( nStartRow, nIndex );
+ nThisRow = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
+ if (nThisRow < nStartRow) nThisRow = nStartRow;
+
+ while ( nThisRow <= nEndRow )
+ {
+ pOldPattern = pData[nIndex].pPattern;
+ nOldValue = ((const ScMergeFlagAttr*) &pOldPattern->GetItem( ATTR_MERGE_FLAG ))->GetValue();
+ if ( (nOldValue | nFlags) != nOldValue )
+ {
+ nRow = pData[nIndex].nRow;
+ USHORT nAttrRow = Min( (USHORT)nRow, (USHORT)nEndRow );
+ ScPatternAttr aNewPattern(*pOldPattern);
+ aNewPattern.GetItemSet().Put( ScMergeFlagAttr( nOldValue | nFlags ) );
+ SetPatternArea( nThisRow, nAttrRow, &aNewPattern, TRUE );
+ Search( nThisRow, nIndex ); // Daten wurden veraendert !!!
+ bChanged = TRUE;
+ }
+
+ ++nIndex;
+ nThisRow = pData[nIndex-1].nRow+1;
+ }
+
+ return bChanged;
+}
+
+
+BOOL ScAttrArray::RemoveFlags( USHORT nStartRow, USHORT nEndRow, INT16 nFlags )
+{
+ const ScPatternAttr* pOldPattern;
+
+ INT16 nOldValue;
+ short nIndex;
+ USHORT nRow;
+ USHORT nThisRow;
+ BOOL bChanged = FALSE;
+
+ Search( nStartRow, nIndex );
+ nThisRow = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
+ if (nThisRow < nStartRow) nThisRow = nStartRow;
+
+ while ( nThisRow <= nEndRow )
+ {
+ pOldPattern = pData[nIndex].pPattern;
+ nOldValue = ((const ScMergeFlagAttr*) &pOldPattern->GetItem( ATTR_MERGE_FLAG ))->GetValue();
+ if ( (nOldValue & ~nFlags) != nOldValue )
+ {
+ nRow = pData[nIndex].nRow;
+ USHORT nAttrRow = Min( (USHORT)nRow, (USHORT)nEndRow );
+ ScPatternAttr aNewPattern(*pOldPattern);
+ aNewPattern.GetItemSet().Put( ScMergeFlagAttr( nOldValue & ~nFlags ) );
+ SetPatternArea( nThisRow, nAttrRow, &aNewPattern, TRUE );
+ Search( nThisRow, nIndex ); // Daten wurden veraendert !!!
+ bChanged = TRUE;
+ }
+
+ ++nIndex;
+ nThisRow = pData[nIndex-1].nRow+1;
+ }
+
+ return bChanged;
+}
+
+
+void ScAttrArray::ClearItems( USHORT nStartRow, USHORT nEndRow, const USHORT* pWhich )
+{
+ const ScPatternAttr* pOldPattern;
+
+ short nIndex;
+ USHORT nRow;
+ USHORT nThisRow;
+
+ Search( nStartRow, nIndex );
+ nThisRow = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
+ if (nThisRow < nStartRow) nThisRow = nStartRow;
+
+ while ( nThisRow <= nEndRow )
+ {
+ pOldPattern = pData[nIndex].pPattern;
+ if ( pOldPattern->HasItemsSet( pWhich ) )
+ {
+ ScPatternAttr aNewPattern(*pOldPattern);
+ aNewPattern.ClearItems( pWhich );
+
+ nRow = pData[nIndex].nRow;
+ USHORT nAttrRow = Min( (USHORT)nRow, (USHORT)nEndRow );
+ SetPatternArea( nThisRow, nAttrRow, &aNewPattern, TRUE );
+ Search( nThisRow, nIndex ); // Daten wurden veraendert !!!
+ }
+
+ ++nIndex;
+ nThisRow = pData[nIndex-1].nRow+1;
+ }
+}
+
+
+void ScAttrArray::ChangeIndent( USHORT nStartRow, USHORT nEndRow, BOOL bIncrement )
+{
+ short nIndex;
+ Search( nStartRow, nIndex );
+ USHORT nThisStart = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
+ if (nThisStart < nStartRow) nThisStart = nStartRow;
+
+ while ( nThisStart <= nEndRow )
+ {
+ const ScPatternAttr* pOldPattern = pData[nIndex].pPattern;
+ const SfxItemSet& rOldSet = pOldPattern->GetItemSet();
+ const SfxPoolItem* pItem;
+
+ BOOL bNeedJust = ( rOldSet.GetItemState( ATTR_HOR_JUSTIFY, FALSE, &pItem ) != SFX_ITEM_SET
+ || ((const SvxHorJustifyItem*)pItem)->GetValue() != SVX_HOR_JUSTIFY_LEFT );
+ USHORT nOldValue = ((const SfxUInt16Item&)rOldSet.Get( ATTR_INDENT )).GetValue();
+ USHORT nNewValue = nOldValue;
+ if ( bIncrement )
+ {
+ if ( nNewValue < SC_MAX_INDENT )
+ {
+ nNewValue += SC_INDENT_STEP;
+ if ( nNewValue > SC_MAX_INDENT ) nNewValue = SC_MAX_INDENT;
+ }
+ }
+ else
+ {
+ if ( nNewValue > 0 )
+ {
+ if ( nNewValue > SC_INDENT_STEP )
+ nNewValue -= SC_INDENT_STEP;
+ else
+ nNewValue = 0;
+ }
+ }
+
+ if ( bNeedJust || nNewValue != nOldValue )
+ {
+ USHORT nThisEnd = pData[nIndex].nRow;
+ USHORT nAttrRow = Min( nThisEnd, nEndRow );
+ ScPatternAttr aNewPattern(*pOldPattern);
+ aNewPattern.GetItemSet().Put( SfxUInt16Item( ATTR_INDENT, nNewValue ) );
+ if ( bNeedJust )
+ aNewPattern.GetItemSet().Put(
+ SvxHorJustifyItem( SVX_HOR_JUSTIFY_LEFT, ATTR_HOR_JUSTIFY ) );
+ SetPatternArea( nThisStart, nAttrRow, &aNewPattern, TRUE );
+
+ nThisStart = nThisEnd + 1;
+ Search( nThisStart, nIndex ); // Daten wurden veraendert !!!
+ }
+ else
+ {
+ nThisStart = pData[nIndex].nRow + 1; // weiterzaehlen...
+ ++nIndex;
+ }
+ }
+}
+
+
+short ScAttrArray::GetNextUnprotected( short nRow, BOOL bUp ) const
+{
+ short nRet = nRow;
+ if (VALIDROW(nRow))
+ {
+ short nIndex;
+ Search(nRow, nIndex);
+ while (((const ScProtectionAttr&)pData[nIndex].pPattern->
+ GetItem(ATTR_PROTECTION)).GetProtection())
+ {
+ if (bUp)
+ {
+ --nIndex;
+ if (nIndex<0)
+ return -1; // nichts gefunden
+ nRet = pData[nIndex].nRow;
+ }
+ else
+ {
+ nRet = pData[nIndex].nRow+1;
+ ++nIndex;
+ if (nIndex>=nCount)
+ return MAXROW+1; // nichts gefunden
+ }
+ }
+ }
+ return nRet;
+}
+
+
+void ScAttrArray::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, BOOL* pUsed, BOOL bReset )
+{
+ USHORT nStart = 0;
+ short nPos = 0;
+ while (nPos < (short) nCount)
+ {
+ USHORT nEnd = pData[nPos].nRow;
+ if (pData[nPos].pPattern->GetStyleSheet() == pStyleSheet)
+ {
+// for (USHORT nRow = nStart; nRow <= nEnd; nRow++)
+// pUsed[nRow] = TRUE;
+
+ memset( &pUsed[nStart], TRUE, nEnd-nStart+1 );
+
+ if (bReset)
+ {
+ ScPatternAttr* pNewPattern = new ScPatternAttr(*pData[nPos].pPattern);
+ pDocument->GetPool()->Remove(*pData[nPos].pPattern);
+ pNewPattern->SetStyleSheet( (ScStyleSheet*)
+ pDocument->GetStyleSheetPool()->
+ Find( ScGlobal::GetRscString(STR_STYLENAME_STANDARD),
+ SFX_STYLE_FAMILY_PARA,
+ SFXSTYLEBIT_AUTO | SCSTYLEBIT_STANDARD ) );
+ pData[nPos].pPattern = (const ScPatternAttr*)
+ &pDocument->GetPool()->Put(*pNewPattern);
+ delete pNewPattern;
+
+ if (Concat(nPos))
+ {
+ Search(nStart, nPos);
+ --nPos; // wegen ++ am Ende
+ }
+ }
+ }
+ nStart = nEnd + 1;
+ ++nPos;
+ }
+}
+
+
+BOOL ScAttrArray::IsStyleSheetUsed( const SfxStyleSheetBase& rStyle ) const
+{
+ BOOL bIsUsed = FALSE;
+ short nPos = 0;
+
+ while ( !bIsUsed && ( nPos < (short)nCount ) )
+ {
+ bIsUsed = ( pData[nPos].pPattern->GetStyleSheet() == &rStyle );
+ nPos++;
+ }
+
+ return bIsUsed;
+}
+
+
+BOOL ScAttrArray::IsEmpty() const
+{
+ if (nCount == 1)
+ {
+ if ( pData[0].pPattern != pDocument->GetDefPattern() )
+ return FALSE;
+ else
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+
+USHORT ScAttrArray::GetFirstEntryPos() const
+{
+ DBG_ASSERT( nCount, "nCount = 0" );
+
+ if ( pData[0].pPattern != pDocument->GetDefPattern() )
+ return 0;
+ else
+ {
+ if (nCount==1)
+ return 0; // leer
+ else
+ return pData[0].nRow + 1;
+ }
+}
+
+
+USHORT ScAttrArray::GetLastEntryPos( BOOL bIncludeBottom ) const
+{
+ DBG_ASSERT( nCount, "nCount == 0" );
+
+ if (bIncludeBottom)
+ bIncludeBottom = ( pData[nCount-1].pPattern != pDocument->GetDefPattern() );
+
+ if (bIncludeBottom)
+ return MAXROW;
+ else
+ {
+ if (nCount<=1)
+ return 0; // leer
+ else
+ return pData[nCount-2].nRow;
+ }
+}
+
+
+BOOL ScAttrArray::HasVisibleAttr( USHORT& rFirstRow, USHORT& rLastRow, BOOL bSkipFirst ) const
+{
+ DBG_ASSERT( nCount, "nCount == 0" );
+
+ BOOL bFound = FALSE;
+ USHORT nStart = 0;
+
+ if ( bSkipFirst ) // Anfang ueberspringen, wenn >1 Zeile
+ {
+ USHORT nVisStart = 1;
+ while ( nVisStart < nCount &&
+ pData[nVisStart].pPattern->IsVisibleEqual(*pData[nVisStart-1].pPattern) )
+ ++nVisStart;
+ if ( nVisStart >= nCount || pData[nVisStart-1].nRow > 0 ) // mehr als 1 Zeile?
+ nStart = nVisStart;
+ }
+
+ USHORT nVisCount = nCount-1; // am Ende zusammengehoerende weglassen
+ while ( nVisCount > nStart &&
+ pData[nVisCount].pPattern->IsVisibleEqual(*pData[nVisCount-1].pPattern) )
+ --nVisCount;
+
+ while ( nStart < nVisCount && !bFound )
+ {
+ if ( pData[nStart].pPattern->IsVisible() )
+ {
+ rFirstRow = nStart ? ( pData[nStart-1].nRow + 1 ) : 0;
+ rLastRow = pData[nStart].nRow;
+ bFound = TRUE;
+ }
+ else
+ ++nStart;
+ }
+
+ if (!bFound)
+ return FALSE;
+
+ BOOL bEnd = FALSE;
+ USHORT nPos = nVisCount;
+ while ( nPos > nStart && !bEnd )
+ {
+ --nPos;
+ if ( pData[nPos].pPattern->IsVisible() )
+ {
+ rLastRow = pData[nPos].nRow;
+ bEnd = TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+BOOL ScAttrArray::HasVisibleAttrIn( USHORT nStartRow, USHORT nEndRow ) const
+{
+ short nIndex;
+ Search( nStartRow, nIndex );
+ USHORT nThisStart = nStartRow;
+ BOOL bFound = FALSE;
+ while ( nIndex < nCount && nThisStart <= nEndRow && !bFound )
+ {
+ if ( pData[nIndex].pPattern->IsVisible() )
+ bFound = TRUE;
+
+ nThisStart = pData[nIndex].nRow + 1;
+ ++nIndex;
+ }
+
+ return bFound;
+}
+
+
+BOOL ScAttrArray::IsVisibleEqual( const ScAttrArray& rOther,
+ USHORT nStartRow, USHORT nEndRow ) const
+{
+ BOOL bEqual = TRUE;
+ short nThisPos = 0;
+ short nOtherPos = 0;
+ if ( nStartRow )
+ {
+ Search( nStartRow, nThisPos );
+ rOther.Search( nStartRow, nOtherPos );
+ }
+
+ while ( nThisPos<nCount && nOtherPos<rOther.nCount && bEqual )
+ {
+ USHORT nThisRow = pData[nThisPos].nRow;
+ USHORT nOtherRow = rOther.pData[nOtherPos].nRow;
+ const ScPatternAttr* pThisPattern = pData[nThisPos].pPattern;
+ const ScPatternAttr* pOtherPattern = rOther.pData[nOtherPos].pPattern;
+ bEqual = ( pThisPattern == pOtherPattern ||
+ pThisPattern->IsVisibleEqual(*pOtherPattern) );
+
+ if ( nThisRow >= nOtherRow )
+ {
+ if ( nOtherRow >= nEndRow ) break;
+ ++nOtherPos;
+ }
+ if ( nThisRow <= nOtherRow )
+ {
+ if ( nThisRow >= nEndRow ) break;
+ ++nThisPos;
+ }
+ }
+
+ return bEqual;
+}
+
+
+BOOL ScAttrArray::IsAllEqual( const ScAttrArray& rOther, USHORT nStartRow, USHORT nEndRow ) const
+{
+ //! mit IsVisibleEqual zusammenfassen?
+
+ BOOL bEqual = TRUE;
+ short nThisPos = 0;
+ short nOtherPos = 0;
+ if ( nStartRow )
+ {
+ Search( nStartRow, nThisPos );
+ rOther.Search( nStartRow, nOtherPos );
+ }
+
+ while ( nThisPos<nCount && nOtherPos<rOther.nCount && bEqual )
+ {
+ USHORT nThisRow = pData[nThisPos].nRow;
+ USHORT nOtherRow = rOther.pData[nOtherPos].nRow;
+ const ScPatternAttr* pThisPattern = pData[nThisPos].pPattern;
+ const ScPatternAttr* pOtherPattern = rOther.pData[nOtherPos].pPattern;
+ bEqual = ( pThisPattern == pOtherPattern );
+
+ if ( nThisRow >= nOtherRow )
+ {
+ if ( nOtherRow >= nEndRow ) break;
+ ++nOtherPos;
+ }
+ if ( nThisRow <= nOtherRow )
+ {
+ if ( nThisRow >= nEndRow ) break;
+ ++nThisPos;
+ }
+ }
+
+ return bEqual;
+}
+
+
+BOOL ScAttrArray::TestInsertCol( USHORT nStartRow, USHORT nEndRow) const
+{
+ // horizontal zusammengefasste duerfen nicht herausgeschoben werden
+ // (ob die ganze Zusammenfassung betroffen ist, ist hier nicht zu erkennen)
+
+ BOOL bTest = TRUE;
+ if (!IsEmpty())
+ {
+ short nIndex = 0;
+ if ( nStartRow )
+ Search( nStartRow, nIndex );
+
+ for ( ; nIndex < nCount; nIndex++ )
+ {
+ if ( ((const ScMergeFlagAttr&)pData[nIndex].pPattern->
+ GetItem(ATTR_MERGE_FLAG)).IsHorOverlapped() )
+ {
+ bTest = FALSE; // darf nicht herausgeschoben werden
+ break;
+ }
+ if ( pData[nIndex].nRow >= nEndRow ) // Ende des Bereichs
+ break;
+ }
+ }
+ return bTest;
+}
+
+
+BOOL ScAttrArray::TestInsertRow( USHORT nSize ) const
+{
+ // wenn die erste herausgeschobene Zeile vertikal ueberlappt ist,
+ // wuerde eine kaputte Zusammenfassung uebrigbleiben
+
+ if (pData)
+ {
+ // MAXROW + 1 - nSize = erste herausgeschobene Zeile
+
+ USHORT nFirstLost = nCount-1;
+ while ( nFirstLost && pData[nFirstLost-1].nRow >= MAXROW + 1 - nSize )
+ --nFirstLost;
+
+ if ( ((const ScMergeFlagAttr&)pData[nFirstLost].pPattern->
+ GetItem(ATTR_MERGE_FLAG)).IsVerOverlapped() )
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+void ScAttrArray::InsertRow( USHORT nStartRow, USHORT nSize )
+{
+ if (!pData)
+ return;
+
+ USHORT nSearch = nStartRow ? nStartRow - 1 : 0; // Vorgaenger erweitern
+ short nIndex;
+ Search( nSearch, nIndex );
+
+ // ein gesetztes ScMergeAttr darf nicht ausgedehnt werden
+ // (darum hinterher wieder loeschen)
+
+ BOOL bDoMerge = ((const ScMergeAttr&) pData[nIndex].pPattern->GetItem(ATTR_MERGE)).IsMerged();
+
+ USHORT nRemove = 0;
+ USHORT i;
+ for (i = nIndex; i < nCount-1; i++)
+ {
+ USHORT nNew = pData[i].nRow + nSize;
+ if ( nNew >= MAXROW ) // Ende erreicht ?
+ {
+ nNew = MAXROW;
+ if (!nRemove)
+ nRemove = i+1; // folgende loeschen
+ }
+ pData[i].nRow = nNew;
+ }
+
+ // muessen Eintraege am Ende geloescht werden?
+
+ if (nRemove && nRemove < nCount)
+ DeleteRange( nRemove, nCount-1 );
+
+ if (bDoMerge) // ausgedehntes ScMergeAttr wieder reparieren
+ {
+ //! ApplyAttr fuer Bereiche !!!
+
+ const SfxPoolItem& rDef = pDocument->GetPool()->GetDefaultItem( ATTR_MERGE );
+ for (i=0; i<nSize; i++)
+ pDocument->ApplyAttr( nCol, nStartRow+i, nTab, rDef );
+
+ // im eingefuegten Bereich ist nichts zusammengefasst
+ }
+
+ // Flags nicht duplizieren
+ //! direkt am Pattern testen ??
+ RemoveFlags( nStartRow, nStartRow+nSize-1, SC_MF_HOR | SC_MF_VER | SC_MF_AUTO );
+}
+
+
+void ScAttrArray::DeleteRow( USHORT nStartRow, USHORT nSize )
+{
+ if (pData)
+ {
+ BOOL bFirst=TRUE;
+ USHORT nStartIndex;
+ USHORT nEndIndex;
+ for (USHORT i = 0; i < nCount-1; i++)
+ if (pData[i].nRow >= nStartRow && pData[i].nRow <= nStartRow+nSize-1)
+ {
+ if (bFirst)
+ {
+ nStartIndex = i;
+ bFirst = FALSE;
+ }
+ nEndIndex = i;
+ }
+ if (!bFirst)
+ {
+ USHORT nStart;
+ if (nStartIndex==0)
+ nStart = 0;
+ else
+ nStart = pData[nStartIndex-1].nRow + 1;
+
+ if (nStart < nStartRow)
+ {
+ pData[nStartIndex].nRow = nStartRow - 1;
+ ++nStartIndex;
+ }
+ if (nEndIndex >= nStartIndex)
+ {
+ DeleteRange( nStartIndex, nEndIndex );
+ if (nStartIndex > 0)
+ if ( pData[nStartIndex-1].pPattern == pData[nStartIndex].pPattern )
+ DeleteRange( nStartIndex-1, nStartIndex-1 );
+ }
+ }
+ for (i = 0; i < nCount-1; i++)
+ if (pData[i].nRow >= nStartRow)
+ pData[i].nRow -= nSize;
+
+// unten nicht Default-Pattern nachschieben, um Druckbereiche erkennen zu koennen
+// stattdessen nur Merge-Flags loeschen
+
+ RemoveFlags( MAXROW-nSize+1, MAXROW, SC_MF_HOR | SC_MF_VER | SC_MF_AUTO );
+ }
+}
+
+
+void ScAttrArray::DeleteRange( USHORT nStartIndex, USHORT nEndIndex )
+{
+ ScDocumentPool* pDocPool = pDocument->GetPool();
+ for (USHORT i = nStartIndex; i <= nEndIndex; i++)
+ pDocPool->Remove(*pData[i].pPattern);
+
+ memmove( &pData[nStartIndex], &pData[nEndIndex + 1], (nCount - nEndIndex - 1) * sizeof(ScAttrEntry) );
+ nCount -= nEndIndex-nStartIndex+1;
+}
+
+
+void ScAttrArray::DeleteArea(USHORT nStartRow, USHORT nEndRow)
+{
+ RemoveAreaMerge( nStartRow, nEndRow ); // von zusammengefassten auch die Flags loeschen
+
+ if ( !HasAttrib( nStartRow, nEndRow, HASATTR_OVERLAPPED | HASATTR_AUTOFILTER) )
+ SetPatternArea( nStartRow, nEndRow, pDocument->GetDefPattern() );
+ else
+ DeleteAreaSafe( nStartRow, nEndRow ); // Merge-Flags stehenlassen
+}
+
+
+void ScAttrArray::DeleteHardAttr(USHORT nStartRow, USHORT nEndRow)
+{
+ const ScPatternAttr* pDefPattern = pDocument->GetDefPattern();
+ const ScPatternAttr* pOldPattern;
+
+ short nIndex;
+ USHORT nRow;
+ USHORT nThisRow;
+
+ Search( nStartRow, nIndex );
+ nThisRow = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
+ if (nThisRow < nStartRow) nThisRow = nStartRow;
+
+ while ( nThisRow <= nEndRow )
+ {
+ pOldPattern = pData[nIndex].pPattern;
+
+ if ( pOldPattern->GetItemSet().Count() ) // harte Attribute ?
+ {
+ nRow = pData[nIndex].nRow;
+ USHORT nAttrRow = Min( (USHORT)nRow, (USHORT)nEndRow );
+
+ ScPatternAttr aNewPattern(*pOldPattern);
+ SfxItemSet& rSet = aNewPattern.GetItemSet();
+ for (USHORT nId = ATTR_PATTERN_START; nId <= ATTR_PATTERN_END; nId++)
+ if (nId != ATTR_MERGE && nId != ATTR_MERGE_FLAG)
+ rSet.ClearItem(nId);
+
+ if ( aNewPattern == *pDefPattern )
+ SetPatternArea( nThisRow, nAttrRow, pDefPattern, FALSE );
+ else
+ SetPatternArea( nThisRow, nAttrRow, &aNewPattern, TRUE );
+
+ Search( nThisRow, nIndex ); // Daten wurden veraendert !!!
+ }
+
+ ++nIndex;
+ nThisRow = pData[nIndex-1].nRow+1;
+ }
+}
+
+ // Verschieben innerhalb eines Dokuments
+
+void ScAttrArray::MoveTo(USHORT nStartRow, USHORT nEndRow, ScAttrArray& rAttrArray)
+{
+ USHORT nStart = nStartRow;
+ for (USHORT i = 0; i < nCount; i++)
+ {
+ if ((pData[i].nRow >= nStartRow) && ((i==0) ? TRUE : pData[i-1].nRow < nEndRow))
+ {
+ // Kopieren (bPutToPool=TRUE)
+ rAttrArray.SetPatternArea( nStart, Min( (USHORT)pData[i].nRow, (USHORT)nEndRow ),
+ pData[i].pPattern, TRUE );
+ }
+ nStart = Max( (USHORT)nStart, (USHORT)(pData[i].nRow + 1) );
+ }
+ DeleteArea(nStartRow, nEndRow);
+}
+
+
+ // Kopieren zwischen Dokumenten (Clipboard)
+
+void ScAttrArray::CopyArea( USHORT nStartRow, USHORT nEndRow, short nDy, ScAttrArray& rAttrArray,
+ INT16 nStripFlags )
+{
+ nStartRow -= nDy; // Source
+ nEndRow -= nDy;
+
+ USHORT nDestStart = Max((short)((short)nStartRow + nDy), (short) 0);
+ USHORT nDestEnd = Min((short)((short)nEndRow + nDy), (short) MAXROW);
+
+ ScDocumentPool* pSourceDocPool = pDocument->GetPool();
+ ScDocumentPool* pDestDocPool = rAttrArray.pDocument->GetPool();
+ BOOL bSamePool = (pSourceDocPool==pDestDocPool);
+
+ for (USHORT i = 0; (i < nCount) && (nDestStart <= nDestEnd); i++)
+ {
+ if (pData[i].nRow >= nStartRow)
+ {
+ const ScPatternAttr* pOldPattern = pData[i].pPattern;
+ const ScPatternAttr* pNewPattern;
+
+ if (IsDefaultItem( pOldPattern ))
+ {
+ // am Default muss nichts veraendert werden
+
+ pNewPattern = (const ScPatternAttr*)
+ &pDestDocPool->GetDefaultItem( ATTR_PATTERN );
+ }
+ else if ( nStripFlags )
+ {
+ ScPatternAttr* pTmpPattern = new ScPatternAttr( *pOldPattern );
+ INT16 nNewFlags = 0;
+ if ( nStripFlags != SC_MF_ALL )
+ nNewFlags = ((const ScMergeFlagAttr&)pTmpPattern->GetItem(ATTR_MERGE_FLAG)).
+ GetValue() & ~nStripFlags;
+
+ if ( nNewFlags )
+ pTmpPattern->GetItemSet().Put( ScMergeFlagAttr( nNewFlags ) );
+ else
+ pTmpPattern->GetItemSet().ClearItem( ATTR_MERGE_FLAG );
+
+ if (bSamePool)
+ pNewPattern = (ScPatternAttr*) &pDestDocPool->Put(*pTmpPattern);
+ else
+ pNewPattern = pTmpPattern->PutInPool( rAttrArray.pDocument, pDocument );
+ delete pTmpPattern;
+ }
+ else
+ {
+ if (bSamePool)
+ pNewPattern = (ScPatternAttr*) &pDestDocPool->Put(*pOldPattern);
+ else
+ pNewPattern = pOldPattern->PutInPool( rAttrArray.pDocument, pDocument );
+ }
+
+ rAttrArray.SetPatternArea(nDestStart,
+ Min((USHORT)(pData[i].nRow + nDy), nDestEnd), pNewPattern);
+ }
+ nDestStart = Max(nDestStart, (USHORT)(pData[i].nRow + nDy + 1));
+ }
+}
+
+ // Flags stehenlassen
+ //! mit CopyArea zusammenfassen !!!
+
+void ScAttrArray::CopyAreaSafe( USHORT nStartRow, USHORT nEndRow, short nDy, ScAttrArray& rAttrArray )
+{
+ nStartRow -= nDy; // Source
+ nEndRow -= nDy;
+
+ USHORT nDestStart = Max((short)((short)nStartRow + nDy), (short) 0);
+ USHORT nDestEnd = Min((short)((short)nEndRow + nDy), (short) MAXROW);
+
+ if ( !rAttrArray.HasAttrib( nDestStart, nDestEnd, HASATTR_OVERLAPPED ) )
+ {
+ CopyArea( nStartRow+nDy, nEndRow+nDy, nDy, rAttrArray );
+ return;
+ }
+
+ ScDocumentPool* pSourceDocPool = pDocument->GetPool();
+ ScDocumentPool* pDestDocPool = rAttrArray.pDocument->GetPool();
+ BOOL bSamePool = (pSourceDocPool==pDestDocPool);
+
+ for (USHORT i = 0; (i < nCount) && (nDestStart <= nDestEnd); i++)
+ {
+ if (pData[i].nRow >= nStartRow)
+ {
+ const ScPatternAttr* pOldPattern = pData[i].pPattern;
+ const ScPatternAttr* pNewPattern;
+
+ if (bSamePool)
+ pNewPattern = (ScPatternAttr*) &pDestDocPool->Put(*pOldPattern);
+ else
+ pNewPattern = pOldPattern->PutInPool( rAttrArray.pDocument, pDocument );
+
+ rAttrArray.SetPatternAreaSafe(nDestStart,
+ Min((USHORT)(pData[i].nRow + nDy), nDestEnd), pNewPattern, FALSE);
+ }
+ nDestStart = Max(nDestStart, (USHORT)(pData[i].nRow + nDy + 1));
+ }
+}
+
+
+short ScAttrArray::SearchStyle( short nRow, const ScStyleSheet* pSearchStyle,
+ BOOL bUp, ScMarkArray* pMarkArray )
+{
+ BOOL bFound = FALSE;
+
+ if (pMarkArray)
+ {
+ nRow = pMarkArray->GetNextMarked( nRow, bUp );
+ if (nRow<0 || nRow>MAXROW)
+ return nRow;
+ }
+
+ short nIndex;
+ Search(nRow, nIndex);
+ const ScPatternAttr* pPattern = pData[nIndex].pPattern;
+
+ while (nIndex>=0 && nIndex<(short)nCount && !bFound)
+ {
+ if (pPattern->GetStyleSheet() == pSearchStyle)
+ {
+ if (pMarkArray)
+ {
+ nRow = pMarkArray->GetNextMarked( nRow, bUp );
+ short nStart = nIndex ? pData[nIndex-1].nRow+1 : 0;
+ if (nRow >= nStart && nRow <= (short) pData[nIndex].nRow)
+ bFound = TRUE;
+ }
+ else
+ bFound = TRUE;
+ }
+
+ if (!bFound)
+ {
+ if (bUp)
+ {
+ --nIndex;
+ if (nIndex>=0)
+ {
+ nRow = pData[nIndex].nRow;
+ pPattern = pData[nIndex].pPattern;
+ }
+ else
+ nRow = -1;
+ }
+ else
+ {
+ nRow = pData[nIndex].nRow+1;
+ ++nIndex;
+ if (nIndex<(short)nCount)
+ pPattern = pData[nIndex].pPattern;
+ }
+ }
+ }
+
+ DBG_ASSERT( bFound || nRow<0 || nRow>MAXROW, "interner Fehler in ScAttrArray::SearchStyle" );
+
+ return nRow;
+}
+
+
+BOOL ScAttrArray::SearchStyleRange( short& rRow, short& rEndRow,
+ const ScStyleSheet* pSearchStyle, BOOL bUp, ScMarkArray* pMarkArray )
+{
+ short nStartRow = SearchStyle( rRow, pSearchStyle, bUp, pMarkArray );
+ if (VALIDROW(nStartRow))
+ {
+ short nIndex;
+ Search(nStartRow,nIndex);
+
+ rRow = nStartRow;
+ if (bUp)
+ {
+ if (nIndex>0)
+ rEndRow = pData[nIndex-1].nRow + 1;
+ else
+ rEndRow = 0;
+ if (pMarkArray)
+ {
+ short nMarkEnd = pMarkArray->GetMarkEnd( nStartRow, TRUE );
+ if (nMarkEnd>rEndRow)
+ rEndRow = nMarkEnd;
+ }
+ }
+ else
+ {
+ rEndRow = pData[nIndex].nRow;
+ if (pMarkArray)
+ {
+ short nMarkEnd = pMarkArray->GetMarkEnd( nStartRow, FALSE );
+ if (nMarkEnd<rEndRow)
+ rEndRow = nMarkEnd;
+ }
+ }
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+//------------------------------------------------------------------------
+//
+// Laden / Speichern
+//
+
+
+void ScAttrArray::Save( SvStream& rStream ) const
+{
+ ScWriteHeader aHdr( rStream, 8 );
+
+ ScDocumentPool* pDocPool = pDocument->GetPool();
+
+ USHORT nSaveCount = nCount;
+ USHORT nSaveMaxRow = pDocument->GetSrcMaxRow();
+ if ( nSaveMaxRow != MAXROW )
+ {
+ if ( nSaveCount > 1 && pData[nSaveCount-2].nRow >= nSaveMaxRow )
+ {
+ pDocument->SetLostData(); // Warnung ausgeben
+ do
+ --nSaveCount;
+ while ( nSaveCount > 1 && pData[nSaveCount-2].nRow >= nSaveMaxRow );
+ }
+ }
+
+ rStream << nSaveCount;
+
+ const SfxPoolItem* pItem;
+ for (USHORT i=0; i<nSaveCount; i++)
+ {
+ rStream << Min( pData[i].nRow, nSaveMaxRow );
+
+ const ScPatternAttr* pPattern = pData[i].pPattern;
+ pDocPool->StoreSurrogate( rStream, pPattern );
+
+ // FALSE, weil ATTR_CONDITIONAL (noch) nicht in Vorlagen:
+ if (pPattern->GetItemSet().GetItemState(ATTR_CONDITIONAL,FALSE,&pItem) == SFX_ITEM_SET)
+ pDocument->SetConditionalUsed( ((const SfxUInt32Item*)pItem)->GetValue() );
+
+ if (pPattern->GetItemSet().GetItemState(ATTR_VALIDDATA,FALSE,&pItem) == SFX_ITEM_SET)
+ pDocument->SetValidationUsed( ((const SfxUInt32Item*)pItem)->GetValue() );
+ }
+}
+
+
+void ScAttrArray::Load( SvStream& rStream )
+{
+ ScDocumentPool* pDocPool = pDocument->GetPool();
+
+ ScReadHeader aHdr( rStream );
+
+ USHORT nNewCount;
+ rStream >> nNewCount;
+ if ( nNewCount > MAXROW+1 ) // wuerde das Array zu gross?
+ {
+ pDocument->SetLostData();
+ rStream.SetError( SVSTREAM_FILEFORMAT_ERROR );
+ return;
+ }
+
+ Reset( pDocument->GetDefPattern(), FALSE ); // loeschen
+ pData = new ScAttrEntry[nNewCount]; // neu anlegen
+ for (USHORT i=0; i<nNewCount; i++)
+ {
+ rStream >> pData[i].nRow;
+
+ USHORT nWhich = ATTR_PATTERN;
+ const ScPatternAttr* pNewPattern = (const ScPatternAttr*)
+ pDocPool->LoadSurrogate( rStream, nWhich, ATTR_PATTERN );
+ if (!pNewPattern)
+ {
+ // da is was schiefgelaufen
+ DBG_ERROR("ScAttrArray::Load: Surrogat nicht im Pool");
+ pNewPattern = pDocument->GetDefPattern();
+ }
+ ScDocumentPool::CheckRef( *pNewPattern );
+ pData[i].pPattern = pNewPattern;
+
+ // LoadSurrogate erhoeht auch die Ref
+ }
+ nCount = nNewCount;
+
+ if ( nCount > 1 && pData[nCount-2].nRow >= MAXROW ) // faengt ein Attribut hinter MAXROW an?
+ {
+ pDocument->SetLostData();
+ rStream.SetError( SVSTREAM_FILEFORMAT_ERROR );
+ return;
+ }
+
+ if ( pDocument->GetSrcMaxRow() != MAXROW ) // Ende anpassen?
+ {
+ // Ende immer auf MAXROW umsetzen (nur auf 32 Bit)
+
+ DBG_ASSERT( pData[nCount-1].nRow == pDocument->GetSrcMaxRow(), "Attribut-Ende ?!?" );
+ pData[nCount-1].nRow = MAXROW;
+ }
+}
+
+
+
+
diff --git a/sc/source/core/data/attrib.cxx b/sc/source/core/data/attrib.cxx
new file mode 100644
index 000000000000..9b9604a00180
--- /dev/null
+++ b/sc/source/core/data/attrib.cxx
@@ -0,0 +1,1478 @@
+/*************************************************************************
+ *
+ * $RCSfile: attrib.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+
+#ifndef _COM_SUN_STAR_UTIL_CELLPROTECTION_HPP_
+#include <com/sun/star/util/CellProtection.hpp>
+#endif
+#ifndef _COM_SUN_STAR_UTIL_XPROTECTABLE_HPP_
+#include <com/sun/star/util/XProtectable.hpp>
+#endif
+#ifndef _COM_SUN_STAR_TEXT_XTEXT_HPP_
+#include <com/sun/star/text/XText.hpp>
+#endif
+#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
+#include <com/sun/star/beans/XPropertySet.hpp>
+#endif
+
+#include "scitems.hxx"
+#include <svx/eeitem.hxx>
+#define ITEMID_FIELD EE_FEATURE_FIELD
+
+#include <svx/boxitem.hxx>
+#include <svx/editdata.hxx>
+#include <svx/editeng.hxx>
+#include <svx/editobj.hxx>
+#include <svx/flditem.hxx>
+#include <svtools/args.hxx>
+
+#include "attrib.hxx"
+#include "global.hxx"
+#include "editutil.hxx"
+#include "sc.hrc"
+#include "globstr.hrc"
+
+#include "textuno.hxx" // ScHeaderFooterContentObj
+
+using namespace com::sun::star;
+
+//------------------------------------------------------------------------
+
+TYPEINIT1(ScMergeAttr, SfxPoolItem);
+TYPEINIT1(ScProtectionAttr, SfxPoolItem);
+TYPEINIT1(ScRangeItem, SfxPoolItem);
+TYPEINIT1(ScTableListItem, SfxPoolItem);
+TYPEINIT1(ScPageHFItem, SfxPoolItem);
+TYPEINIT1(ScViewObjectModeItem, SfxEnumItem);
+TYPEINIT1(ScDoubleItem, SfxPoolItem);
+
+//------------------------------------------------------------------------
+
+//
+// allgemeine Hilfsfunktionen
+//
+
+BOOL HasPriority( const SvxBorderLine* pThis, const SvxBorderLine* pOther )
+{
+// DBG_ASSERT( pThis || pOther, "LineAttr == 0" );
+
+ if (!pThis)
+ return FALSE;
+ if (!pOther)
+ return TRUE;
+
+ USHORT nThisSize = pThis->GetOutWidth() + pThis->GetDistance() + pThis->GetInWidth();
+ USHORT nOtherSize = pOther->GetOutWidth() + pOther->GetDistance() + pOther->GetInWidth();
+
+ if (nThisSize > nOtherSize)
+ return TRUE;
+ else if (nThisSize < nOtherSize)
+ return FALSE;
+ else
+ {
+ if ( pOther->GetInWidth() && !pThis->GetInWidth() )
+ return TRUE;
+ else if ( pThis->GetInWidth() && !pOther->GetInWidth() )
+ return FALSE;
+ else
+ {
+ return TRUE; //! ???
+ }
+ }
+}
+
+
+//
+// Item - Implementierungen
+//
+
+//------------------------------------------------------------------------
+// Merge
+//------------------------------------------------------------------------
+
+ScMergeAttr::ScMergeAttr():
+ SfxPoolItem(ATTR_MERGE),
+ nColMerge(0),
+ nRowMerge(0)
+{}
+
+//------------------------------------------------------------------------
+
+ScMergeAttr::ScMergeAttr( INT16 nCol, INT16 nRow):
+ SfxPoolItem(ATTR_MERGE),
+ nColMerge(nCol),
+ nRowMerge(nRow)
+{}
+
+//------------------------------------------------------------------------
+
+ScMergeAttr::ScMergeAttr(const ScMergeAttr& rItem):
+ SfxPoolItem(ATTR_MERGE)
+{
+ nColMerge = rItem.nColMerge;
+ nRowMerge = rItem.nRowMerge;
+}
+
+__EXPORT ScMergeAttr::~ScMergeAttr()
+{
+}
+
+//------------------------------------------------------------------------
+
+String __EXPORT ScMergeAttr::GetValueText() const
+{
+ String aString( '(' );
+ aString += String::CreateFromInt32( nColMerge );
+ aString += ',';
+ aString += String::CreateFromInt32( nRowMerge );
+ aString += ')';
+ return aString;
+}
+
+//------------------------------------------------------------------------
+
+int __EXPORT ScMergeAttr::operator==( const SfxPoolItem& rItem ) const
+{
+ DBG_ASSERT( Which() != rItem.Which() || Type() == rItem.Type(), "which ==, type !=" );
+ return (Which() == rItem.Which())
+ && (nColMerge == ((ScMergeAttr&)rItem).nColMerge)
+ && (nRowMerge == ((ScMergeAttr&)rItem).nRowMerge);
+}
+
+//------------------------------------------------------------------------
+
+SfxPoolItem* __EXPORT ScMergeAttr::Clone( SfxItemPool * ) const
+{
+ return new ScMergeAttr(*this);
+}
+
+//------------------------------------------------------------------------
+
+SfxPoolItem* __EXPORT ScMergeAttr::Create( SvStream& rStream, USHORT nVer ) const
+{
+ INT16 nCol;
+ INT16 nRow;
+ rStream >> nCol;
+ rStream >> nRow;
+ return new ScMergeAttr(nCol,nRow);
+}
+
+//------------------------------------------------------------------------
+
+SvStream& __EXPORT ScMergeAttr::Store( SvStream& rStream, USHORT nVer ) const
+{
+ rStream << nColMerge;
+ rStream << nRowMerge;
+ return rStream;
+}
+
+//------------------------------------------------------------------------
+// MergeFlag
+//------------------------------------------------------------------------
+
+ScMergeFlagAttr::ScMergeFlagAttr():
+ SfxInt16Item(ATTR_MERGE_FLAG, 0)
+{
+}
+
+//------------------------------------------------------------------------
+
+ScMergeFlagAttr::ScMergeFlagAttr(INT16 nFlags):
+ SfxInt16Item(ATTR_MERGE_FLAG, nFlags)
+{
+}
+
+__EXPORT ScMergeFlagAttr::~ScMergeFlagAttr()
+{
+}
+
+//------------------------------------------------------------------------
+// Protection
+//------------------------------------------------------------------------
+
+ScProtectionAttr::ScProtectionAttr():
+ SfxPoolItem(ATTR_PROTECTION),
+ bProtection(TRUE),
+ bHideFormula(FALSE),
+ bHideCell(FALSE),
+ bHidePrint(FALSE)
+{
+}
+
+//------------------------------------------------------------------------
+
+ScProtectionAttr::ScProtectionAttr( BOOL bProtect, BOOL bHFormula,
+ BOOL bHCell, BOOL bHPrint):
+ SfxPoolItem(ATTR_PROTECTION),
+ bProtection(bProtect),
+ bHideFormula(bHFormula),
+ bHideCell(bHCell),
+ bHidePrint(bHPrint)
+{
+}
+
+//------------------------------------------------------------------------
+
+ScProtectionAttr::ScProtectionAttr(const ScProtectionAttr& rItem):
+ SfxPoolItem(ATTR_PROTECTION)
+{
+ bProtection = rItem.bProtection;
+ bHideFormula = rItem.bHideFormula;
+ bHideCell = rItem.bHideCell;
+ bHidePrint = rItem.bHidePrint;
+}
+
+__EXPORT ScProtectionAttr::~ScProtectionAttr()
+{
+}
+
+//------------------------------------------------------------------------
+
+BOOL __EXPORT ScProtectionAttr::QueryValue( uno::Any& rVal, BYTE nMemberId ) const
+{
+ util::CellProtection aProtection;
+ aProtection.IsLocked = bProtection;
+ aProtection.IsFormulaHidden = bHideFormula;
+ aProtection.IsHidden = bHideCell;
+ aProtection.IsPrintHidden = bHidePrint;
+ rVal <<= aProtection;
+ return TRUE;
+}
+
+BOOL __EXPORT ScProtectionAttr::PutValue( const uno::Any& rVal, BYTE nMemberId )
+{
+ BOOL bRet = FALSE;
+ util::CellProtection aProtection;
+ if ( rVal >>= aProtection )
+ {
+ bProtection = aProtection.IsLocked;
+ bHideFormula = aProtection.IsFormulaHidden;
+ bHideCell = aProtection.IsHidden;
+ bHidePrint = aProtection.IsPrintHidden;
+ bRet = TRUE;
+ }
+ else
+ DBG_ERROR("exception - wrong argument");
+
+ return bRet;
+}
+
+//------------------------------------------------------------------------
+
+String __EXPORT ScProtectionAttr::GetValueText() const
+{
+ String aValue;
+ String aStrYes ( ScGlobal::GetRscString(STR_YES) );
+ String aStrNo ( ScGlobal::GetRscString(STR_NO) );
+ sal_Unicode cDelim = ',';
+
+ aValue = '(';
+ aValue += (bProtection ? aStrYes : aStrNo); aValue += cDelim;
+ aValue += (bHideFormula ? aStrYes : aStrNo); aValue += cDelim;
+ aValue += (bHideCell ? aStrYes : aStrNo); aValue += cDelim;
+ aValue += (bHidePrint ? aStrYes : aStrNo);
+ aValue += ')';
+
+ return aValue;
+}
+
+//------------------------------------------------------------------------
+
+SfxItemPresentation __EXPORT ScProtectionAttr::GetPresentation
+ (
+ SfxItemPresentation ePres,
+ SfxMapUnit eCoreMetric,
+ SfxMapUnit ePresMetric,
+ String& rText,
+ const International* pIntl
+ ) const
+{
+ String aStrYes ( ScGlobal::GetRscString(STR_YES) );
+ String aStrNo ( ScGlobal::GetRscString(STR_NO) );
+ String aStrSep = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM( ": " ));
+ String aStrDelim = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM( ", " ));
+
+ switch ( ePres )
+ {
+ case SFX_ITEM_PRESENTATION_NONE:
+ rText.Erase();
+ break;
+
+ case SFX_ITEM_PRESENTATION_NAMELESS:
+ rText = GetValueText();
+ break;
+
+ case SFX_ITEM_PRESENTATION_COMPLETE:
+ rText = ScGlobal::GetRscString(STR_PROTECTION); rText += aStrSep;
+ rText += (bProtection ? aStrYes : aStrNo); rText += aStrDelim;
+ rText += ScGlobal::GetRscString(STR_FORMULAS); rText += aStrSep;
+ rText += (!bHideFormula ? aStrYes : aStrNo); rText += aStrDelim;
+ rText += ScGlobal::GetRscString(STR_HIDE); rText += aStrSep;
+ rText += (bHideCell ? aStrYes : aStrNo); rText += aStrDelim;
+ rText += ScGlobal::GetRscString(STR_PRINT); rText += aStrSep;
+ rText += (!bHidePrint ? aStrYes : aStrNo);
+ break;
+
+ default:
+ ePres = SFX_ITEM_PRESENTATION_NONE;
+ }
+
+ return ePres;
+}
+
+//------------------------------------------------------------------------
+
+int __EXPORT ScProtectionAttr::operator==( const SfxPoolItem& rItem ) const
+{
+ DBG_ASSERT( Which() != rItem.Which() || Type() == rItem.Type(), "which ==, type !=" );
+ return (Which() == rItem.Which())
+ && (bProtection == ((ScProtectionAttr&)rItem).bProtection)
+ && (bHideFormula == ((ScProtectionAttr&)rItem).bHideFormula)
+ && (bHideCell == ((ScProtectionAttr&)rItem).bHideCell)
+ && (bHidePrint == ((ScProtectionAttr&)rItem).bHidePrint);
+}
+
+//------------------------------------------------------------------------
+
+SfxPoolItem* __EXPORT ScProtectionAttr::Clone( SfxItemPool * ) const
+{
+ return new ScProtectionAttr(*this);
+}
+
+//------------------------------------------------------------------------
+
+SfxPoolItem* __EXPORT ScProtectionAttr::Create( SvStream& rStream, USHORT n ) const
+{
+ BOOL bProtect;
+ BOOL bHFormula;
+ BOOL bHCell;
+ BOOL bHPrint;
+
+ rStream >> bProtect;
+ rStream >> bHFormula;
+ rStream >> bHCell;
+ rStream >> bHPrint;
+
+ return new ScProtectionAttr(bProtect,bHFormula,bHCell,bHPrint);
+}
+
+//------------------------------------------------------------------------
+
+SvStream& __EXPORT ScProtectionAttr::Store( SvStream& rStream, USHORT nVer ) const
+{
+ rStream << bProtection;
+ rStream << bHideFormula;
+ rStream << bHideCell;
+ rStream << bHidePrint;
+
+ return rStream;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScProtectionAttr::SetProtection( BOOL bProtect)
+{
+ bProtection = bProtect;
+ return TRUE;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScProtectionAttr::SetHideFormula( BOOL bHFormula)
+{
+ bHideFormula = bHFormula;
+ return TRUE;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScProtectionAttr::SetHideCell( BOOL bHCell)
+{
+ bHideCell = bHCell;
+ return TRUE;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScProtectionAttr::SetHidePrint( BOOL bHPrint)
+{
+ bHidePrint = bHPrint;
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+// ScRangeItem - Tabellenbereich
+// -----------------------------------------------------------------------
+
+void __EXPORT ScRangeItem::Record( SfxArguments& rArgs ) const
+{
+ const ScAddress& rStart = aRange.aStart;
+ const ScAddress& rEnd = aRange.aEnd;
+
+ rArgs.AppendInteger( rStart.Col() );
+ rArgs.AppendInteger( rStart.Row() );
+ rArgs.AppendInteger( rStart.Tab() );
+ rArgs.AppendInteger( rEnd .Col() );
+ rArgs.AppendInteger( rEnd .Row() );
+ rArgs.AppendInteger( rEnd.Tab() );
+ rArgs.AppendInteger( nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+SfxArgumentError __EXPORT ScRangeItem::Construct( USHORT nId, const SfxArguments& rArgs )
+{
+ if ( rArgs.Count() < 7 )
+ return SFX_ARGUMENT_ERROR( rArgs.Count(), SFX_ERR_ARGUMENT_EXPECTED );
+ if ( rArgs.Count() > 7 )
+ return SFX_ARGUMENT_ERROR( rArgs.Count()-1, SFX_ERR_TOO_MANY_ARGUMENTS );
+
+ ScAddress& rStart = aRange.aStart;
+ ScAddress& rEnd = aRange.aEnd;
+
+ SetWhich( nId );
+ rStart.SetCol( rArgs.Get( 0 ).GetInteger() );
+ rStart.SetRow( rArgs.Get( 1 ).GetInteger() );
+ rStart.SetTab( rArgs.Get( 2 ).GetInteger() );
+ rEnd .SetCol( rArgs.Get( 3 ).GetInteger() );
+ rEnd .SetRow( rArgs.Get( 4 ).GetInteger() );
+ rEnd .SetTab( rArgs.Get( 5 ).GetInteger() );
+ nFlags = (USHORT)rArgs.Get( 6 ).GetInteger();
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+int __EXPORT ScRangeItem::operator==( const SfxPoolItem& rAttr ) const
+{
+ DBG_ASSERT( SfxPoolItem::operator==(rAttr), "unequal types" );
+
+ return ( aRange == ( (ScRangeItem&)rAttr ).aRange );
+}
+
+// -----------------------------------------------------------------------
+
+SfxPoolItem* __EXPORT ScRangeItem::Clone( SfxItemPool* ) const
+{
+ return new ScRangeItem( *this );
+}
+
+//------------------------------------------------------------------------
+
+SfxItemPresentation __EXPORT ScRangeItem::GetPresentation
+ (
+ SfxItemPresentation ePres,
+ SfxMapUnit eCoreUnit,
+ SfxMapUnit ePresUnit,
+ String& rText,
+ const International* pIntl
+ ) const
+{
+ rText.Erase();
+
+ switch ( ePres )
+ {
+ case SFX_ITEM_PRESENTATION_COMPLETE:
+ rText = ScGlobal::GetRscString(STR_AREA);
+ rText.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ": " ));
+// break;// Durchfallen !!!
+
+ case SFX_ITEM_PRESENTATION_NAMELESS:
+ {
+ String aText;
+ aRange.Format( aText );
+ rText += aText;
+ }
+ break;
+ }
+
+ return ePres;
+}
+
+//-----------------------------------------------------------------------
+
+USHORT __EXPORT ScRangeItem::GetVersion( USHORT nFileVersion ) const
+{
+ return 2;
+}
+
+//-----------------------------------------------------------------------
+
+SvStream& __EXPORT ScRangeItem::Store( SvStream& rStrm, USHORT nVer ) const
+{
+ rStrm << aRange;
+ rStrm << nFlags;
+
+ return rStrm;
+}
+
+//-----------------------------------------------------------------------
+
+SfxPoolItem* __EXPORT ScRangeItem::Create( SvStream& rStream, USHORT nVersion ) const
+{
+ ScRange aNewRange;
+ BOOL nNewFlags = FALSE;
+
+ switch ( nVersion )
+ {
+ case 2:
+ rStream >> aNewRange;
+ rStream >> nNewFlags;
+ break;
+
+ case 1:
+ rStream >> aNewRange;
+ nNewFlags = 0;
+ break;
+
+ case 0:
+ {
+ // alte Version mit ScArea -> 5 USHORTs lesen
+ ScAddress& rStart = aNewRange.aStart;
+ ScAddress& rEnd = aNewRange.aEnd;
+ USHORT n;
+
+ rStream >> n;
+
+ if ( n > MAXTAB )
+ {
+ nNewFlags = SCR_ALLTABS;
+ rStart.SetTab( 0 ); rEnd.SetTab( 0 );
+ }
+ else
+ {
+ nNewFlags = 0;
+ rStart.SetTab( n ); rEnd.SetTab( n );
+ }
+
+ rStream >> n; rStart.SetCol( n );
+ rStream >> n; rStart.SetRow( n );
+ rStream >> n; rEnd .SetCol( n );
+ rStream >> n; rEnd .SetRow( n );
+ }
+ break;
+
+ default:
+ DBG_ERROR( "ScRangeItem::Create: Unknown Version!" );
+ }
+
+ return ( new ScRangeItem( Which(), aNewRange, nNewFlags ) );
+}
+
+
+// -----------------------------------------------------------------------
+// ScTableListItem - Liste von Tabellen(-nummern)
+// -----------------------------------------------------------------------
+
+ScTableListItem::ScTableListItem( const ScTableListItem& rCpy )
+ : SfxPoolItem ( rCpy.Which() ),
+ nCount ( rCpy.nCount )
+{
+ if ( nCount > 0 )
+ {
+ pTabArr = new USHORT [nCount];
+
+ for ( USHORT i=0; i<nCount; i++ )
+ pTabArr[i] = rCpy.pTabArr[i];
+ }
+ else
+ pTabArr = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ScTableListItem::ScTableListItem( const USHORT nWhich, const List& rList )
+ : SfxPoolItem ( nWhich ),
+ nCount ( 0 ),
+ pTabArr ( NULL )
+{
+ SetTableList( rList );
+}
+
+// -----------------------------------------------------------------------
+
+__EXPORT ScTableListItem::~ScTableListItem()
+{
+ delete [] pTabArr;
+}
+
+// -----------------------------------------------------------------------
+
+void __EXPORT ScTableListItem::Record( SfxArguments& rArgs ) const
+{
+ rArgs.AppendInteger( nCount );
+
+ if ( nCount>0 && pTabArr )
+ for ( USHORT i=0; i<nCount; i++ )
+ rArgs.AppendInteger( pTabArr[i] );
+}
+
+// -----------------------------------------------------------------------
+
+SfxArgumentError __EXPORT ScTableListItem::Construct( USHORT nId, const SfxArguments& rArgs )
+{
+ USHORT nCount = rArgs.Get( 0 ).GetInteger();
+
+ if ( pTabArr )
+ delete [] pTabArr, pTabArr = NULL;
+
+ if ( nCount > 0 )
+ {
+ if ( rArgs.Count()-1 < nCount )
+ return SFX_ARGUMENT_ERROR( rArgs.Count(), SFX_ERR_ARGUMENT_EXPECTED );
+ if ( rArgs.Count()-1 > nCount )
+ return SFX_ARGUMENT_ERROR( rArgs.Count()-1, SFX_ERR_TOO_MANY_ARGUMENTS );
+
+ SetWhich( nId );
+ pTabArr = new USHORT [nCount];
+
+ for ( USHORT i=0; i<nCount; i++ )
+ pTabArr[i] = rArgs.Get( i+1 ).GetInteger();
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+ScTableListItem& ScTableListItem::operator=( const ScTableListItem& rCpy )
+{
+ delete [] pTabArr;
+
+ if ( rCpy.nCount > 0 )
+ {
+ pTabArr = new USHORT [rCpy.nCount];
+ for ( USHORT i=0; i<rCpy.nCount; i++ )
+ pTabArr[i] = rCpy.pTabArr[i];
+ }
+ else
+ pTabArr = NULL;
+
+ nCount = rCpy.nCount;
+
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+int __EXPORT ScTableListItem::operator==( const SfxPoolItem& rAttr ) const
+{
+ DBG_ASSERT( SfxPoolItem::operator==(rAttr), "unequal types" );
+
+ ScTableListItem& rCmp = (ScTableListItem&)rAttr;
+ BOOL bEqual = (nCount == rCmp.nCount);
+
+ if ( nCount > 0 )
+ {
+ USHORT i=0;
+
+ bEqual = ( pTabArr && rCmp.pTabArr );
+
+ while ( bEqual && i<nCount )
+ {
+ bEqual = ( pTabArr[i] == rCmp.pTabArr[i] );
+ i++;
+ }
+ }
+ return bEqual;
+}
+
+// -----------------------------------------------------------------------
+
+SfxPoolItem* __EXPORT ScTableListItem::Clone( SfxItemPool* ) const
+{
+ return new ScTableListItem( *this );
+}
+
+//------------------------------------------------------------------------
+
+SfxItemPresentation __EXPORT ScTableListItem::GetPresentation
+ (
+ SfxItemPresentation ePres,
+ SfxMapUnit eCoreUnit,
+ SfxMapUnit ePresUnit,
+ String& rText,
+ const International* pIntl
+ ) const
+{
+ const sal_Unicode cDelim = ',';
+
+ switch ( ePres )
+ {
+ case SFX_ITEM_PRESENTATION_NONE:
+ rText.Erase();
+ return ePres;
+
+ case SFX_ITEM_PRESENTATION_NAMELESS:
+ {
+ rText = '(';
+ if ( nCount>0 && pTabArr )
+ for ( USHORT i=0; i<nCount; i++ )
+ {
+ rText += String::CreateFromInt32( pTabArr[i] );
+ if ( i<(nCount-1) )
+ rText += cDelim;
+ }
+ rText += ')';
+ }
+ return ePres;
+
+ case SFX_ITEM_PRESENTATION_COMPLETE:
+ rText.Erase();
+ return SFX_ITEM_PRESENTATION_NONE;
+ }
+
+ return SFX_ITEM_PRESENTATION_NONE;
+}
+
+//-----------------------------------------------------------------------
+
+SvStream& __EXPORT ScTableListItem::Store( SvStream& rStrm, USHORT nVer ) const
+{
+ rStrm << nCount;
+
+ if ( nCount>0 && pTabArr )
+ for ( USHORT i=0; i<nCount; i++ )
+ rStrm << pTabArr[i];
+
+ return rStrm;
+}
+
+//-----------------------------------------------------------------------
+
+SfxPoolItem* __EXPORT ScTableListItem::Create( SvStream& rStrm, USHORT ) const
+{
+ ScTableListItem* pNewItem;
+ List aList;
+ USHORT* p;
+ USHORT nTabCount;
+ USHORT nTabNo;
+
+ rStrm >> nTabCount;
+
+ if ( nTabCount > 0 )
+ {
+ for ( USHORT i=0; i<nTabCount; i++ )
+ {
+ rStrm >> nTabNo;
+ aList.Insert( new USHORT(nTabNo) );
+ }
+ }
+
+ pNewItem = new ScTableListItem( Which(), aList );
+
+ aList.First();
+ while ( p = (USHORT*)aList.Remove() )
+ delete p;
+
+ return pNewItem;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ScTableListItem::GetTableList( List& aList ) const
+{
+ for ( USHORT i=0; i<nCount; i++ )
+ aList.Insert( new USHORT( pTabArr[i] ) );
+
+ return ( nCount > 0 );
+}
+
+// -----------------------------------------------------------------------
+
+void ScTableListItem::SetTableList( const List& rList )
+{
+ nCount = (USHORT)rList.Count();
+
+ delete [] pTabArr;
+
+ if ( nCount > 0 )
+ {
+ pTabArr = new USHORT [nCount];
+
+ for ( USHORT i=0; i<nCount; i++ )
+ pTabArr[i] = *( (USHORT*)rList.GetObject( i ) );
+ }
+ else
+ pTabArr = NULL;
+}
+
+
+// -----------------------------------------------------------------------
+// ScPageHFItem - Daten der Kopf-/Fußzeilen
+// -----------------------------------------------------------------------
+
+ScPageHFItem::ScPageHFItem( USHORT nWhich )
+ : SfxPoolItem ( nWhich ),
+ pLeftArea ( NULL ),
+ pCenterArea ( NULL ),
+ pRightArea ( NULL )
+{
+}
+
+//------------------------------------------------------------------------
+
+ScPageHFItem::ScPageHFItem( const ScPageHFItem& rItem )
+ : SfxPoolItem ( rItem ),
+ pLeftArea ( NULL ),
+ pCenterArea ( NULL ),
+ pRightArea ( NULL )
+{
+ if ( rItem.pLeftArea )
+ pLeftArea = rItem.pLeftArea->Clone();
+ if ( rItem.pCenterArea )
+ pCenterArea = rItem.pCenterArea->Clone();
+ if ( rItem.pRightArea )
+ pRightArea = rItem.pRightArea->Clone();
+}
+
+//------------------------------------------------------------------------
+
+__EXPORT ScPageHFItem::~ScPageHFItem()
+{
+ delete pLeftArea;
+ delete pCenterArea;
+ delete pRightArea;
+}
+
+//------------------------------------------------------------------------
+
+BOOL __EXPORT ScPageHFItem::QueryValue( uno::Any& rVal, BYTE nMemberId ) const
+{
+ uno::Reference<sheet::XHeaderFooterContent> xContent =
+ new ScHeaderFooterContentObj( pLeftArea, pCenterArea, pRightArea );
+
+ rVal <<= xContent;
+ return TRUE;
+}
+
+BOOL __EXPORT ScPageHFItem::PutValue( const uno::Any& rVal, BYTE nMemberId )
+{
+ BOOL bRet = FALSE;
+ uno::Reference<sheet::XHeaderFooterContent> xContent;
+ if ( rVal >>= xContent )
+ {
+ if ( xContent.is() )
+ {
+ ScHeaderFooterContentObj* pImp =
+ ScHeaderFooterContentObj::getImplementation( xContent );
+ if (pImp)
+ {
+ const EditTextObject* pImpLeft = pImp->GetLeftEditObject();
+ delete pLeftArea;
+ pLeftArea = pImpLeft ? pImpLeft->Clone() : NULL;
+
+ const EditTextObject* pImpCenter = pImp->GetCenterEditObject();
+ delete pCenterArea;
+ pCenterArea = pImpCenter ? pImpCenter->Clone() : NULL;
+
+ const EditTextObject* pImpRight = pImp->GetRightEditObject();
+ delete pRightArea;
+ pRightArea = pImpRight ? pImpRight->Clone() : NULL;
+
+ if ( !pLeftArea || !pCenterArea || !pRightArea )
+ {
+ // keine Texte auf NULL stehen lassen
+ ScEditEngineDefaulter aEngine( EditEngine::CreatePool(), TRUE );
+ if (!pLeftArea)
+ pLeftArea = aEngine.CreateTextObject();
+ if (!pCenterArea)
+ pCenterArea = aEngine.CreateTextObject();
+ if (!pRightArea)
+ pRightArea = aEngine.CreateTextObject();
+ }
+
+ bRet = TRUE;
+ }
+ }
+ }
+
+ if (!bRet)
+ {
+ DBG_ERROR("exception - wrong argument");
+ }
+
+ return bRet;
+}
+
+//------------------------------------------------------------------------
+
+String __EXPORT ScPageHFItem::GetValueText() const
+{
+ return String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("ScPageHFItem"));
+}
+
+//------------------------------------------------------------------------
+
+int __EXPORT ScPageHFItem::operator==( const SfxPoolItem& rItem ) const
+{
+ DBG_ASSERT( SfxPoolItem::operator==( rItem ), "unequal Which or Type" );
+
+ const ScPageHFItem& r = (const ScPageHFItem&)rItem;
+
+ return ScGlobal::EETextObjEqual(pLeftArea, r.pLeftArea)
+ && ScGlobal::EETextObjEqual(pCenterArea, r.pCenterArea)
+ && ScGlobal::EETextObjEqual(pRightArea, r.pRightArea);
+}
+
+//------------------------------------------------------------------------
+
+SfxPoolItem* __EXPORT ScPageHFItem::Clone( SfxItemPool* ) const
+{
+ return new ScPageHFItem( *this );
+}
+
+//------------------------------------------------------------------------
+
+USHORT __EXPORT ScPageHFItem::GetVersion( USHORT nFileVersion ) const
+{
+ // 0 = ohne Feldbefehle
+ // 1 = Titel bzw. Dateiname mit SvxFileField
+ // 2 = Pfad und/oder Dateiname mit SvxExtFileField, Titel mit SvxFileField
+ return 2;
+}
+
+//------------------------------------------------------------------------
+
+void lcl_SetSpace( String& rStr, const ESelection& rSel )
+{
+ // Text durch ein Leerzeichen ersetzen, damit Positionen stimmen:
+
+ xub_StrLen nLen = rSel.nEndPos-rSel.nStartPos;
+ rStr.Erase( rSel.nStartPos, nLen-1 );
+ rStr.SetChar( rSel.nStartPos, ' ' );
+}
+
+BOOL lcl_ConvertFields(EditEngine& rEng, const String* pCommands)
+{
+ BOOL bChange = FALSE;
+ USHORT nParCnt = rEng.GetParagraphCount();
+ for (USHORT nPar = 0; nPar<nParCnt; nPar++)
+ {
+ String aStr = rEng.GetText( nPar );
+ xub_StrLen nPos;
+
+ while ((nPos = aStr.Search(pCommands[0])) != STRING_NOTFOUND)
+ {
+ ESelection aSel( nPar,nPos, nPar,nPos+pCommands[0].Len() );
+ rEng.QuickInsertField( SvxFieldItem(SvxPageField()), aSel );
+ lcl_SetSpace(aStr, aSel ); bChange = TRUE;
+ }
+ while ((nPos = aStr.Search(pCommands[1])) != STRING_NOTFOUND)
+ {
+ ESelection aSel( nPar,nPos, nPar,nPos+pCommands[1].Len() );
+ rEng.QuickInsertField( SvxFieldItem(SvxPagesField()), aSel );
+ lcl_SetSpace(aStr, aSel ); bChange = TRUE;
+ }
+ while ((nPos = aStr.Search(pCommands[2])) != STRING_NOTFOUND)
+ {
+ ESelection aSel( nPar,nPos, nPar,nPos+pCommands[2].Len() );
+ rEng.QuickInsertField( SvxFieldItem(SvxDateField(Date(),SVXDATETYPE_VAR)), aSel );
+ lcl_SetSpace(aStr, aSel ); bChange = TRUE;
+ }
+ while ((nPos = aStr.Search(pCommands[3])) != STRING_NOTFOUND)
+ {
+ ESelection aSel( nPar,nPos, nPar,nPos+pCommands[3].Len() );
+ rEng.QuickInsertField( SvxFieldItem(SvxTimeField()), aSel );
+ lcl_SetSpace(aStr, aSel ); bChange = TRUE;
+ }
+ while ((nPos = aStr.Search(pCommands[4])) != STRING_NOTFOUND)
+ {
+ ESelection aSel( nPar,nPos, nPar,nPos+pCommands[4].Len() );
+ rEng.QuickInsertField( SvxFieldItem(SvxFileField()), aSel );
+ lcl_SetSpace(aStr, aSel ); bChange = TRUE;
+ }
+ while ((nPos = aStr.Search(pCommands[5])) != STRING_NOTFOUND)
+ {
+ ESelection aSel( nPar,nPos, nPar,nPos+pCommands[5].Len() );
+ rEng.QuickInsertField( SvxFieldItem(SvxTableField()), aSel );
+ lcl_SetSpace(aStr, aSel ); bChange = TRUE;
+ }
+ }
+ return bChange;
+}
+
+#define SC_FIELD_COUNT 6
+
+SfxPoolItem* __EXPORT ScPageHFItem::Create( SvStream& rStream, USHORT nVer ) const
+{
+ EditTextObject* pLeft = EditTextObject::Create(rStream);
+ EditTextObject* pCenter = EditTextObject::Create(rStream);
+ EditTextObject* pRight = EditTextObject::Create(rStream);
+
+ DBG_ASSERT( pLeft && pCenter && pRight, "Error reading ScPageHFItem" );
+
+ if ( nVer < 1 ) // alte Feldbefehle umsetzen
+ {
+ USHORT i;
+ const String& rDel = ScGlobal::GetRscString( STR_HFCMD_DELIMITER );
+ String aCommands[SC_FIELD_COUNT];
+ for (i=0; i<SC_FIELD_COUNT; i++)
+ aCommands[i] = rDel;
+ aCommands[0] += ScGlobal::GetRscString(STR_HFCMD_PAGE);
+ aCommands[1] += ScGlobal::GetRscString(STR_HFCMD_PAGES);
+ aCommands[2] += ScGlobal::GetRscString(STR_HFCMD_DATE);
+ aCommands[3] += ScGlobal::GetRscString(STR_HFCMD_TIME);
+ aCommands[4] += ScGlobal::GetRscString(STR_HFCMD_FILE);
+ aCommands[5] += ScGlobal::GetRscString(STR_HFCMD_TABLE);
+ for (i=0; i<SC_FIELD_COUNT; i++)
+ aCommands[i] += rDel;
+
+ ScEditEngineDefaulter aEngine( EditEngine::CreatePool(), TRUE );
+ aEngine.SetText(*pLeft);
+ if (lcl_ConvertFields(aEngine,aCommands))
+ {
+ delete pLeft;
+ pLeft = aEngine.CreateTextObject();
+ }
+ aEngine.SetText(*pCenter);
+ if (lcl_ConvertFields(aEngine,aCommands))
+ {
+ delete pCenter;
+ pCenter = aEngine.CreateTextObject();
+ }
+ aEngine.SetText(*pRight);
+ if (lcl_ConvertFields(aEngine,aCommands))
+ {
+ delete pRight;
+ pRight = aEngine.CreateTextObject();
+ }
+ }
+ else if ( nVer < 2 )
+ { // nichts tun, SvxFileField nicht gegen SvxExtFileField austauschen
+ }
+
+ ScPageHFItem* pItem = new ScPageHFItem( Which() );
+ pItem->SetArea( pLeft, SC_HF_LEFTAREA );
+ pItem->SetArea( pCenter, SC_HF_CENTERAREA );
+ pItem->SetArea( pRight, SC_HF_RIGHTAREA );
+
+ return pItem;
+}
+
+//------------------------------------------------------------------------
+
+class ScFieldChangerEditEngine : public ScEditEngineDefaulter
+{
+ TypeId aExtFileId;
+ USHORT nConvPara;
+ xub_StrLen nConvPos;
+ BOOL bConvert;
+
+public:
+ ScFieldChangerEditEngine( SfxItemPool* pEnginePool, BOOL bDeleteEnginePool );
+ virtual ~ScFieldChangerEditEngine() {}
+
+ virtual String CalcFieldValue( const SvxFieldItem& rField, USHORT nPara,
+ USHORT nPos, Color*& rTxtColor,
+ Color*& rFldColor );
+
+ BOOL ConvertFields();
+};
+
+ScFieldChangerEditEngine::ScFieldChangerEditEngine( SfxItemPool* pEnginePool,
+ BOOL bDeleteEnginePool ) :
+ ScEditEngineDefaulter( pEnginePool, bDeleteEnginePool ),
+ aExtFileId( TYPE( SvxExtFileField ) ),
+ nConvPara( 0 ),
+ nConvPos( 0 ),
+ bConvert( FALSE )
+{
+}
+
+String ScFieldChangerEditEngine::CalcFieldValue( const SvxFieldItem& rField,
+ USHORT nPara, USHORT nPos, Color*& rTxtColor, Color*& rFldColor )
+{
+ const SvxFieldData* pFieldData = rField.GetField();
+ if ( pFieldData && pFieldData->Type() == aExtFileId )
+ {
+ bConvert = TRUE;
+ nConvPara = nPara;
+ nConvPos = nPos;
+ }
+ return EMPTY_STRING;
+}
+
+BOOL ScFieldChangerEditEngine::ConvertFields()
+{
+ BOOL bConverted = FALSE;
+ do
+ {
+ bConvert = FALSE;
+ UpdateFields();
+ if ( bConvert )
+ {
+ ESelection aSel( nConvPara, nConvPos, nConvPara, nConvPos+1 );
+ QuickInsertField( SvxFileField(), aSel );
+ bConverted = TRUE;
+ }
+ } while ( bConvert );
+ return bConverted;
+}
+
+void lcl_StoreOldFields( ScFieldChangerEditEngine& rEngine,
+ const EditTextObject* pArea, SvStream& rStream )
+{
+ rEngine.SetText( *pArea );
+ if ( rEngine.ConvertFields() )
+ {
+ EditTextObject* pObj = rEngine.CreateTextObject();
+ pObj->Store( rStream );
+ delete pObj;
+ }
+ else
+ pArea->Store( rStream );
+}
+
+SvStream& __EXPORT ScPageHFItem::Store( SvStream& rStream, USHORT nVer ) const
+{
+ if ( pLeftArea && pCenterArea && pRightArea )
+ {
+ if ( rStream.GetVersion() < SOFFICE_FILEFORMAT_50 )
+ {
+ ScFieldChangerEditEngine aEngine( EditEngine::CreatePool(), TRUE );
+ lcl_StoreOldFields( aEngine, pLeftArea, rStream );
+ lcl_StoreOldFields( aEngine, pCenterArea, rStream );
+ lcl_StoreOldFields( aEngine, pRightArea, rStream );
+ }
+ else
+ {
+ pLeftArea->Store(rStream);
+ pCenterArea->Store(rStream);
+ pRightArea->Store(rStream);
+ }
+ }
+ else
+ {
+ // soll eigentlich nicht sein, kommt aber vor, wenn das Default-Item
+ // fuer ein ItemSet kopiert wird (#61826#) ...
+
+ ScFieldChangerEditEngine aEngine( EditEngine::CreatePool(), TRUE );
+ EditTextObject* pEmpytObj = aEngine.CreateTextObject();
+
+ DBG_ASSERT( pEmpytObj, "Error creating empty EditTextObject :-(" );
+
+ if ( rStream.GetVersion() < SOFFICE_FILEFORMAT_50 )
+ {
+ if ( pLeftArea )
+ lcl_StoreOldFields( aEngine, pLeftArea, rStream );
+ else
+ pEmpytObj->Store( rStream );
+
+ if ( pCenterArea )
+ lcl_StoreOldFields( aEngine, pCenterArea, rStream );
+ else
+ pEmpytObj->Store( rStream );
+
+ if ( pRightArea )
+ lcl_StoreOldFields( aEngine, pRightArea, rStream );
+ else
+ pEmpytObj->Store( rStream );
+ }
+ else
+ {
+ (pLeftArea ? pLeftArea : pEmpytObj )->Store(rStream);
+ (pCenterArea ? pCenterArea : pEmpytObj )->Store(rStream);
+ (pRightArea ? pRightArea : pEmpytObj )->Store(rStream);
+ }
+
+ delete pEmpytObj;
+ }
+
+ return rStream;
+}
+
+//------------------------------------------------------------------------
+
+void __EXPORT ScPageHFItem::SetLeftArea( const EditTextObject& rNew )
+{
+ delete pLeftArea;
+ pLeftArea = rNew.Clone();
+}
+
+//------------------------------------------------------------------------
+
+void __EXPORT ScPageHFItem::SetCenterArea( const EditTextObject& rNew )
+{
+ delete pCenterArea;
+ pCenterArea = rNew.Clone();
+}
+
+//------------------------------------------------------------------------
+
+void __EXPORT ScPageHFItem::SetRightArea( const EditTextObject& rNew )
+{
+ delete pRightArea;
+ pRightArea = rNew.Clone();
+}
+
+void __EXPORT ScPageHFItem::SetArea( EditTextObject *pNew, int nArea )
+{
+ switch ( nArea )
+ {
+ case SC_HF_LEFTAREA: delete pLeftArea; pLeftArea = pNew; break;
+ case SC_HF_CENTERAREA: delete pCenterArea; pCenterArea = pNew; break;
+ case SC_HF_RIGHTAREA: delete pRightArea; pRightArea = pNew; break;
+ default:
+ DBG_ERROR( "New Area?" );
+ }
+}
+
+//-----------------------------------------------------------------------
+// ScViewObjectModeItem - Darstellungsmodus von ViewObjekten
+//-----------------------------------------------------------------------
+
+ScViewObjectModeItem::ScViewObjectModeItem( USHORT nWhich )
+ : SfxEnumItem( nWhich, VOBJ_MODE_SHOW )
+{
+}
+
+//------------------------------------------------------------------------
+
+ScViewObjectModeItem::ScViewObjectModeItem( USHORT nWhich, ScVObjMode eMode )
+ : SfxEnumItem( nWhich, eMode )
+{
+}
+
+//------------------------------------------------------------------------
+
+__EXPORT ScViewObjectModeItem::~ScViewObjectModeItem()
+{
+}
+
+//------------------------------------------------------------------------
+
+SfxItemPresentation __EXPORT ScViewObjectModeItem::GetPresentation
+(
+ SfxItemPresentation ePres,
+ SfxMapUnit eCoreUnit,
+ SfxMapUnit ePresUnit,
+ String& rText,
+ const International* pIntl
+) const
+{
+ String aDel = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(": "));
+ rText.Erase();
+
+ switch ( ePres )
+ {
+ case SFX_ITEM_PRESENTATION_COMPLETE:
+ switch( Which() )
+ {
+ case SID_SCATTR_PAGE_CHARTS:
+ rText = ScGlobal::GetRscString(STR_VOBJ_CHART);
+ rText += aDel;
+ break;
+
+ case SID_SCATTR_PAGE_OBJECTS:
+ rText = ScGlobal::GetRscString(STR_VOBJ_OBJECT);
+ rText += aDel;
+ break;
+
+ case SID_SCATTR_PAGE_DRAWINGS:
+ rText = ScGlobal::GetRscString(STR_VOBJ_DRAWINGS);
+ rText += aDel;
+ break;
+
+ default:
+ ePres = SFX_ITEM_PRESENTATION_NAMELESS;//das geht immer!
+ break;
+ }
+// break; // DURCHFALLEN!!!
+
+ case SFX_ITEM_PRESENTATION_NAMELESS:
+ rText += ScGlobal::GetRscString(STR_VOBJ_MODE_SHOW+GetValue());
+ break;
+ }
+
+ return ePres;
+}
+
+//------------------------------------------------------------------------
+
+String __EXPORT ScViewObjectModeItem::GetValueText( USHORT nVal ) const
+{
+ DBG_ASSERT( nVal <= VOBJ_MODE_DUMMY, "enum overflow!" );
+
+ return ScGlobal::GetRscString( STR_VOBJ_MODE_SHOW + nVal );
+}
+
+//------------------------------------------------------------------------
+
+USHORT __EXPORT ScViewObjectModeItem::GetValueCount() const
+{
+ return 3;
+}
+
+//------------------------------------------------------------------------
+
+SfxPoolItem* __EXPORT ScViewObjectModeItem::Clone( SfxItemPool* ) const
+{
+ return new ScViewObjectModeItem( *this );
+}
+
+//------------------------------------------------------------------------
+
+USHORT __EXPORT ScViewObjectModeItem::GetVersion( USHORT nFileVersion ) const
+{
+ return 1;
+}
+
+//------------------------------------------------------------------------
+
+SfxPoolItem* __EXPORT ScViewObjectModeItem::Create(
+ SvStream& rStream,
+ USHORT nVersion ) const
+{
+ if ( nVersion == 0 )
+ {
+ // alte Version mit AllEnumItem -> mit Mode "Show" erzeugen
+ return new ScViewObjectModeItem( Which() );
+ }
+ else
+ {
+ USHORT nVal;
+ rStream >> nVal;
+ return new ScViewObjectModeItem( Which(), (ScVObjMode)nVal );
+ }
+}
+
+// -----------------------------------------------------------------------
+// double
+// -----------------------------------------------------------------------
+
+ScDoubleItem::ScDoubleItem( USHORT nWhich, double nVal )
+ : SfxPoolItem ( nWhich ),
+ nValue ( nVal )
+{
+}
+
+//------------------------------------------------------------------------
+
+ScDoubleItem::ScDoubleItem( const ScDoubleItem& rItem )
+ : SfxPoolItem ( rItem )
+{
+ nValue = rItem.nValue;
+}
+
+//------------------------------------------------------------------------
+
+String __EXPORT ScDoubleItem::GetValueText() const
+{
+ return String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("ScDoubleItem"));
+}
+
+//------------------------------------------------------------------------
+
+int __EXPORT ScDoubleItem::operator==( const SfxPoolItem& rItem ) const
+{
+ DBG_ASSERT( SfxPoolItem::operator==( rItem ), "unequal Which or Type" );
+ return int(nValue == ((const ScDoubleItem&)rItem).nValue);
+}
+
+//------------------------------------------------------------------------
+
+SfxPoolItem* __EXPORT ScDoubleItem::Clone( SfxItemPool* ) const
+{
+ return new ScDoubleItem( *this );
+}
+
+//------------------------------------------------------------------------
+
+SfxPoolItem* __EXPORT ScDoubleItem::Create( SvStream& rStream, USHORT nVer ) const
+{
+ double nTmp=0;
+ rStream >> nTmp;
+
+ ScDoubleItem* pItem = new ScDoubleItem( Which(), nTmp );
+
+ return pItem;
+}
+
+//------------------------------------------------------------------------
+
+SvStream& __EXPORT ScDoubleItem::Store( SvStream& rStream, USHORT nVer ) const
+{
+ rStream << nValue;
+
+ return rStream;
+}
+
+//------------------------------------------------------------------------
+
+__EXPORT ScDoubleItem::~ScDoubleItem()
+{
+}
+
+// -----------------------------------------------------------------------
+
+
+
+
diff --git a/sc/source/core/data/bcaslot.cxx b/sc/source/core/data/bcaslot.cxx
new file mode 100644
index 000000000000..45054a37fbe0
--- /dev/null
+++ b/sc/source/core/data/bcaslot.cxx
@@ -0,0 +1,801 @@
+/*************************************************************************
+ *
+ * $RCSfile: bcaslot.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+// System - Includes -----------------------------------------------------
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include <sfx2/objsh.hxx>
+#include <svtools/lstner.hxx>
+#include <segmentc.hxx>
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "document.hxx"
+#include "brdcst.hxx"
+#include "bcaslot.hxx"
+#include "scerrors.hxx"
+#include "docoptio.hxx"
+#include "refupdat.hxx"
+#include "table.hxx"
+
+// Anzahl der Slots je Dimension
+// muessen ganzzahlige Teiler von MAXCOL+1 bzw. MAXROW+1 sein
+#define BCA_SLOTS_COL 16
+#define BCA_SLOTS_ROW 256
+#define BCA_SLOT_COLS ((MAXCOL+1) / BCA_SLOTS_COL)
+#define BCA_SLOT_ROWS ((MAXROW+1) / BCA_SLOTS_ROW)
+// vielfaches?
+#if (BCA_SLOT_COLS * BCA_SLOTS_COL) != (MAXCOL+1)
+#error bad BCA_SLOTS_COL value!
+#endif
+#if (BCA_SLOT_ROWS * BCA_SLOTS_ROW) != (MAXROW+1)
+#error bad BCA_SLOTS_ROW value!
+#endif
+// Groesse des Slot-Arrays
+#define BCA_SLOTS (BCA_SLOTS_COL * BCA_SLOTS_ROW)
+#if BCA_SLOTS > 16350
+#error BCA_SLOTS DOOMed!
+#endif
+
+DECLARE_LIST( ScBroadcastAreaList, ScBroadcastArea* );
+
+// STATIC DATA -----------------------------------------------------------
+
+#ifdef erDEBUG
+ULONG erCountBCAInserts = 0;
+ULONG erCountBCAFinds = 0;
+#endif
+
+SEG_EOFGLOBALS()
+
+#pragma SEG_SEGCLASS(PTRARR_SEG,WORKSET_CODE)
+
+SV_IMPL_OP_PTRARR_SORT( ScBroadcastAreas, ScBroadcastAreaPtr );
+
+#pragma SEG_SEGCLASS(TYPEINIT_SEG,WORKSET_CODE)
+
+TYPEINIT1( ScHint, SfxSimpleHint );
+TYPEINIT1( ScAreaChangedHint, SfxHint );
+
+#pragma SEG_FUNCDEF(bcaslot_01)
+
+ScBroadcastAreaSlot::ScBroadcastAreaSlot( ScDocument* pDocument,
+ ScBroadcastAreaSlotMachine* pBASMa ) :
+ pDoc( pDocument ),
+ pBASM( pBASMa )
+{
+ pBroadcastAreaTbl = new ScBroadcastAreas( BCA_INITGROWSIZE, BCA_INITGROWSIZE );
+ pTmpSeekBroadcastArea = new ScBroadcastArea( ScRange() );
+}
+
+
+#pragma SEG_FUNCDEF(bcaslot_02)
+
+ScBroadcastAreaSlot::~ScBroadcastAreaSlot()
+{
+ USHORT nPos = pBroadcastAreaTbl->Count();
+ if ( nPos )
+ {
+ ScBroadcastArea** ppArea =
+ ((ScBroadcastArea**) pBroadcastAreaTbl->GetData()) + nPos - 1;
+ for ( ; nPos-- >0; ppArea-- )
+ {
+ if ( !(*ppArea)->DecRef() )
+ delete *ppArea;
+ }
+ }
+ delete pBroadcastAreaTbl;
+ delete pTmpSeekBroadcastArea;
+}
+
+
+#pragma SEG_FUNCDEF(bcaslot_03)
+
+// nur hier werden neue BroadcastAreas angelegt, wodurch keine doppelten entstehen.
+// Ist rpArea != NULL werden keine Listener gestartet sondern nur die Area
+// eingetragen und der RefCount erhoeht
+void ScBroadcastAreaSlot::StartListeningArea( const ScRange& rRange,
+ SfxListener* pListener, ScBroadcastArea*& rpArea
+ )
+{
+ DBG_ASSERT(pListener, "StartListeningArea: pListener Null");
+ if ( pDoc->GetHardRecalcState() )
+ return;
+ if ( (long)( (pBroadcastAreaTbl->Count() + 1 + BCA_INITGROWSIZE)
+ * sizeof(ScBroadcastArea*) ) >= USHRT_MAX
+ )
+ {
+ if ( !pDoc->GetHardRecalcState() )
+ {
+ pDoc->SetHardRecalcState( 1 );
+
+ SfxObjectShell* pShell = pDoc->GetDocumentShell();
+ DBG_ASSERT( pShell, "Missing DocShell :-/" );
+
+ if ( pShell )
+ pShell->SetError( SCWARN_CORE_HARD_RECALC );
+
+ pDoc->SetAutoCalc( FALSE );
+ pDoc->SetHardRecalcState( 2 );
+ }
+ return;
+ }
+ if ( !rpArea )
+ {
+ rpArea = new ScBroadcastArea( rRange );
+ // meistens existiert die Area noch nicht, der Versuch sofort zu inserten
+ // erspart in diesen Faellen ein doppeltes Seek_Entry
+ if ( pBroadcastAreaTbl->Insert( rpArea ) )
+ rpArea->IncRef();
+ else
+ {
+ delete rpArea;
+ rpArea = GetBroadcastArea( rRange );
+ }
+ pListener->StartListening( *rpArea, TRUE );
+ }
+ else
+ {
+ if ( pBroadcastAreaTbl->Insert( rpArea ) )
+ rpArea->IncRef();
+ }
+}
+
+
+#pragma SEG_FUNCDEF(bcaslot_04)
+
+// Ist rpArea != NULL werden keine Listener gestopt sondern nur die Area
+// ausgetragen und der RefCount vermindert
+void ScBroadcastAreaSlot::EndListeningArea( const ScRange& rRange,
+ SfxListener* pListener, ScBroadcastArea*& rpArea
+ )
+{
+ DBG_ASSERT(pListener, "EndListeningArea: pListener Null");
+ if ( !rpArea )
+ {
+ USHORT nPos;
+ if ( (nPos = FindBroadcastArea( rRange )) == USHRT_MAX )
+ return;
+ rpArea = (*pBroadcastAreaTbl)[ nPos ];
+ pListener->EndListening( *rpArea );
+ if ( !rpArea->HasListeners() )
+ { // wenn keiner mehr zuhoert ist die Area ueberfluessig
+ pBroadcastAreaTbl->Remove( nPos );
+ if ( !rpArea->DecRef() )
+ {
+ delete rpArea;
+ rpArea = NULL;
+ }
+ }
+ }
+ else
+ {
+ if ( !rpArea->HasListeners() )
+ {
+ USHORT nPos;
+ if ( (nPos = FindBroadcastArea( rRange )) == USHRT_MAX )
+ return;
+ pBroadcastAreaTbl->Remove( nPos );
+ if ( !rpArea->DecRef() )
+ {
+ delete rpArea;
+ rpArea = NULL;
+ }
+ }
+ }
+}
+
+
+#pragma SEG_FUNCDEF(bcaslot_05)
+
+USHORT ScBroadcastAreaSlot::FindBroadcastArea( const ScRange& rRange ) const
+{
+ USHORT nPos;
+ pTmpSeekBroadcastArea->UpdateRange( rRange );
+ if ( pBroadcastAreaTbl->Seek_Entry( pTmpSeekBroadcastArea, &nPos ) )
+ return nPos;
+ return USHRT_MAX;
+}
+
+
+#pragma SEG_FUNCDEF(bcaslot_06)
+
+ScBroadcastArea* ScBroadcastAreaSlot::GetBroadcastArea(
+ const ScRange& rRange ) const
+{
+ USHORT nPos;
+ if ( (nPos = FindBroadcastArea( rRange )) != USHRT_MAX )
+ return (*pBroadcastAreaTbl)[ nPos ];
+ return 0;
+}
+
+
+#pragma SEG_FUNCDEF(bcaslot_07)
+
+BOOL ScBroadcastAreaSlot::AreaBroadcast( const ScAddress& rAddress,
+ const ScHint& rHint
+ ) const
+{
+ USHORT nCount = pBroadcastAreaTbl->Count();
+ if ( nCount == 0 )
+ return FALSE;
+ const ScBroadcastArea** ppArea =
+ (const ScBroadcastArea**) pBroadcastAreaTbl->GetData();
+ BOOL bIsBroadcasted = FALSE;
+ // leider laesst sich nicht nach dem erstmoeglichen suchen
+ USHORT nPos = 0;
+ // den letztmoeglichen suchen, Seek_Entry liefert naechst groesseren
+ // oder freie Position wenn nicht gefunden
+ USHORT nPosEnd;
+ pTmpSeekBroadcastArea->UpdateRange( ScRange( rAddress,
+ ScAddress( MAXCOL, MAXROW, MAXTAB ) ) );
+ if ( !pBroadcastAreaTbl->Seek_Entry( pTmpSeekBroadcastArea, &nPosEnd )
+ && nPosEnd > 0 )
+ --nPosEnd;
+ for ( ; nPos <= nPosEnd; ++nPos, ppArea++ )
+ {
+ if ( ((ScBroadcastArea*)*ppArea)->In( rAddress ) )
+ {
+ ((ScBroadcastArea*)*ppArea)->Broadcast( rHint );
+ bIsBroadcasted = TRUE;
+ }
+ }
+ return bIsBroadcasted;
+}
+
+#pragma SEG_FUNCDEF(bcaslot_08)
+
+// DelBroadcastAreasInRange wird unter Windows (16 Bit) kaputtoptimiert
+
+#ifdef WIN
+#pragma optimize("",off)
+#endif
+
+void ScBroadcastAreaSlot::DelBroadcastAreasInRange( const ScRange& rRange )
+{
+ ScBroadcastArea* pArea;
+ ScAddress aStart( rRange.aStart );
+ USHORT nPos = pBroadcastAreaTbl->Count();
+ const ScBroadcastArea** ppArea =
+ (const ScBroadcastArea**) pBroadcastAreaTbl->GetData() + nPos - 1;
+ for ( ; nPos-- >0; ppArea-- )
+ { // rueckwaerts wg. Pointer-Aufrueckerei im Array
+ pArea = (ScBroadcastArea*)*ppArea;
+ if ( pArea->aStart < aStart )
+ return; // davor nur noch niedrigere
+ // gesuchte muessen komplett innerhalb von rRange liegen
+ if ( rRange.In( pArea->aStart ) && rRange.In( pArea->aEnd ) )
+ {
+ pBroadcastAreaTbl->Remove( nPos );
+ ppArea = (const ScBroadcastArea**) pBroadcastAreaTbl->GetData()
+ + nPos;
+ if ( !pArea->DecRef() )
+ delete pArea;
+ }
+ }
+}
+
+#ifdef WIN
+#pragma optimize("",on)
+#endif
+
+#pragma SEG_FUNCDEF(bcaslot_09)
+
+void ScBroadcastAreaSlot::UpdateRemove( UpdateRefMode eUpdateRefMode,
+ const ScRange& rRange, short nDx, short nDy, short nDz
+ )
+{
+ USHORT nPos = pBroadcastAreaTbl->Count();
+ if ( nPos )
+ {
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ USHORT theCol1, theRow1, theTab1, theCol2, theRow2, theTab2;
+ nCol1 = rRange.aStart.Col();
+ nRow1 = rRange.aStart.Row();
+ nTab1 = rRange.aStart.Tab();
+ nCol2 = rRange.aEnd.Col();
+ nRow2 = rRange.aEnd.Row();
+ nTab2 = rRange.aEnd.Tab();
+ ScAddress aAdr;
+ const ScBroadcastArea** ppArea =
+ ((const ScBroadcastArea**) pBroadcastAreaTbl->GetData()) + nPos - 1;
+ for ( ; nPos-- >0; ppArea-- )
+ { // rueckwaerts wg. Pointer-Aufrueckerei im Array
+ ScBroadcastArea* pArea = (ScBroadcastArea*) *ppArea;
+ if ( pArea->IsInUpdateChain() )
+ {
+ pBroadcastAreaTbl->Remove( nPos );
+ // Remove kann pData veraendern
+ ppArea = (const ScBroadcastArea**)
+ pBroadcastAreaTbl->GetData() + nPos;
+ pArea->DecRef();
+ }
+ else
+ {
+ aAdr = pArea->GetStart();
+ theCol1 = aAdr.Col();
+ theRow1 = aAdr.Row();
+ theTab1 = aAdr.Tab();
+ aAdr = pArea->GetEnd();
+ theCol2 = aAdr.Col();
+ theRow2 = aAdr.Row();
+ theTab2 = aAdr.Tab();
+ if ( ScRefUpdate::Update( pDoc, eUpdateRefMode,
+ nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, nDx,nDy,nDz,
+ theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 )
+ )
+ {
+ pBroadcastAreaTbl->Remove( nPos );
+ // Remove kann pData veraendern
+ ppArea = (const ScBroadcastArea**)
+ pBroadcastAreaTbl->GetData() + nPos;
+ pArea->DecRef();
+ pArea->SetInUpdateChain( TRUE );
+ ScBroadcastArea* pUC = pBASM->GetEOUpdateChain();
+ if ( pUC )
+ pUC->SetUpdateChainNext( pArea );
+ else // kein Ende kein Anfang
+ pBASM->SetUpdateChain( pArea );
+ pBASM->SetEOUpdateChain( pArea );
+ }
+ }
+ }
+ }
+}
+
+
+#pragma SEG_FUNCDEF(bcaslot_0a)
+
+void ScBroadcastAreaSlot::UpdateInsert( ScBroadcastArea* pArea )
+{
+ if ( pBroadcastAreaTbl->Insert( pArea ) )
+ pArea->IncRef();
+}
+
+
+// --- ScBroadcastAreaSlotMachine -------------------------------------
+
+#pragma SEG_FUNCDEF(bcaslot_0b)
+
+ScBroadcastAreaSlotMachine::ScBroadcastAreaSlotMachine(
+ ScDocument* pDocument ) :
+ pDoc( pDocument ),
+ pBCAlwaysList( new ScBroadcastAreaList ),
+ pUpdateChain( NULL ),
+ pEOUpdateChain( NULL )
+{
+ ppSlots = new ScBroadcastAreaSlot* [ BCA_SLOTS ];
+ memset( ppSlots, 0 , sizeof( ScBroadcastAreaSlot* ) * BCA_SLOTS );
+}
+
+
+#pragma SEG_FUNCDEF(bcaslot_0c)
+
+ScBroadcastAreaSlotMachine::~ScBroadcastAreaSlotMachine()
+{
+
+ ScBroadcastAreaSlot** pp = ppSlots;
+ for ( USHORT j=0; j < BCA_SLOTS; ++j, ++pp )
+ {
+ if ( *pp )
+ delete *pp;
+ }
+ delete ppSlots;
+
+ for ( ScBroadcastArea* pBCA = pBCAlwaysList->First(); pBCA; pBCA = pBCAlwaysList->Next() )
+ {
+ delete pBCA;
+ }
+ delete pBCAlwaysList;
+}
+
+
+//#pragma SEG_FUNCDEF(bcaslot_0d)
+
+inline USHORT ScBroadcastAreaSlotMachine::ComputeSlotOffset(
+ const ScAddress& rAddress ) const
+{
+ USHORT nRow = rAddress.Row();
+ USHORT nCol = rAddress.Col();
+ if ( nRow > MAXROW || nCol > MAXCOL )
+ {
+ DBG_ASSERT( FALSE, "Row/Col ungueltig!" );
+ return 0;
+ }
+ else
+ return
+ nRow / BCA_SLOT_ROWS +
+ nCol / BCA_SLOT_COLS * BCA_SLOTS_ROW;
+}
+
+
+#pragma SEG_FUNCDEF(bcaslot_0e)
+
+void ScBroadcastAreaSlotMachine::ComputeAreaPoints( const ScRange& rRange,
+ USHORT& rStart, USHORT& rEnd, USHORT& rRowBreak
+ ) const
+{
+ rStart = ComputeSlotOffset( rRange.aStart );
+ rEnd = ComputeSlotOffset( rRange.aEnd );
+ // Anzahl Zeilen-Slots pro Spalte minus eins
+ rRowBreak = ComputeSlotOffset(
+ ScAddress( rRange.aStart.Col(), rRange.aEnd.Row(), 0 ) ) - rStart;
+}
+
+
+#pragma SEG_FUNCDEF(bcaslot_0f)
+
+void ScBroadcastAreaSlotMachine::StartListeningArea( const ScRange& rRange,
+ SfxListener* pListener
+ )
+{
+ if ( rRange == BCA_LISTEN_ALWAYS )
+ {
+ ScBroadcastArea* pBCA;
+ if ( !pBCAlwaysList->Count() )
+ {
+ pBCA = new ScBroadcastArea( rRange );
+ pListener->StartListening( *pBCA, FALSE ); // kein PreventDupes
+ pBCAlwaysList->Insert( pBCA, LIST_APPEND );
+ return ;
+ }
+ ScBroadcastArea* pLast;
+ for ( pBCA = pBCAlwaysList->First(); pBCA; pBCA = pBCAlwaysList->Next() )
+ {
+ if ( pListener->IsListening( *pBCA ) )
+ return ; // keine Dupes
+ pLast = pBCA;
+ }
+ pBCA = pLast;
+ //! ListenerArrays don't shrink!
+ if ( pBCA->GetListenerCount() > ((USHRT_MAX / 2) / sizeof(SfxBroadcaster*)) )
+ { // Arrays nicht zu gross werden lassen
+ pBCA = new ScBroadcastArea( rRange );
+ pBCAlwaysList->Insert( pBCA, LIST_APPEND );
+ }
+ pListener->StartListening( *pBCA, FALSE ); // kein PreventDupes
+ }
+ else
+ {
+ USHORT nStart, nEnd, nRowBreak;
+ ComputeAreaPoints( rRange, nStart, nEnd, nRowBreak );
+ USHORT nOff = nStart;
+ USHORT nBreak = nOff + nRowBreak;
+ ScBroadcastAreaSlot** pp = ppSlots + nOff;
+ ScBroadcastArea* pArea = NULL;
+ while ( nOff <= nEnd )
+ {
+ if ( !*pp )
+ *pp = new ScBroadcastAreaSlot( pDoc, this );
+ // der erste erzeugt ggbf. die BroadcastArea
+ (*pp)->StartListeningArea( rRange, pListener, pArea );
+ if ( nOff < nBreak )
+ {
+ ++nOff;
+ ++pp;
+ }
+ else
+ {
+ nStart += BCA_SLOTS_ROW;
+ nOff = nStart;
+ pp = ppSlots + nOff;
+ nBreak = nOff + nRowBreak;
+ }
+ }
+ }
+}
+
+
+#pragma SEG_FUNCDEF(bcaslot_10)
+
+void ScBroadcastAreaSlotMachine::EndListeningArea( const ScRange& rRange,
+ SfxListener* pListener
+ )
+{
+ if ( rRange == BCA_LISTEN_ALWAYS )
+ {
+ if ( pBCAlwaysList->Count() )
+ {
+ for ( ScBroadcastArea* pBCA = pBCAlwaysList->First(); pBCA; pBCA = pBCAlwaysList->Next() )
+ {
+ // EndListening liefert FALSE wenn !IsListening, keine Dupes
+ if ( pListener->EndListening( *pBCA, FALSE ) )
+ {
+ if ( !pBCA->HasListeners() )
+ {
+ pBCAlwaysList->Remove();
+ delete pBCA;
+ }
+ return ;
+ }
+ }
+ }
+ }
+ else
+ {
+ USHORT nStart, nEnd, nRowBreak;
+ ComputeAreaPoints( rRange, nStart, nEnd, nRowBreak );
+ USHORT nOff = nStart;
+ USHORT nBreak = nOff + nRowBreak;
+ ScBroadcastAreaSlot** pp = ppSlots + nOff;
+ ScBroadcastArea* pArea = NULL;
+ while ( nOff <= nEnd )
+ {
+ if ( *pp )
+ (*pp)->EndListeningArea( rRange, pListener, pArea );
+ if ( nOff < nBreak )
+ {
+ ++nOff;
+ ++pp;
+ }
+ else
+ {
+ nStart += BCA_SLOTS_ROW;
+ nOff = nStart;
+ pp = ppSlots + nOff;
+ nBreak = nOff + nRowBreak;
+ }
+ }
+ }
+}
+
+
+#pragma SEG_FUNCDEF(bcaslot_11)
+
+BOOL ScBroadcastAreaSlotMachine::AreaBroadcast( const ScAddress& rAddress,
+ const ScHint& rHint
+ ) const
+{
+ if ( rAddress == BCA_BRDCST_ALWAYS )
+ {
+ if ( pBCAlwaysList->Count() )
+ {
+ for ( ScBroadcastArea* pBCA = pBCAlwaysList->First(); pBCA; pBCA = pBCAlwaysList->Next() )
+ {
+ pBCA->Broadcast( rHint );
+ }
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+ else
+ {
+ ScBroadcastAreaSlot* pSlot = ppSlots[ ComputeSlotOffset( rAddress ) ];
+ if ( pSlot )
+ return pSlot->AreaBroadcast( rAddress, rHint );
+ else
+ return FALSE;
+ }
+}
+
+
+#pragma SEG_FUNCDEF(bcaslot_12)
+
+void ScBroadcastAreaSlotMachine::DelBroadcastAreasInRange(
+ const ScRange& rRange
+ )
+{
+ USHORT nStart, nEnd, nRowBreak;
+ ComputeAreaPoints( rRange, nStart, nEnd, nRowBreak );
+ USHORT nOff = nStart;
+ USHORT nBreak = nOff + nRowBreak;
+ ScBroadcastAreaSlot** pp = ppSlots + nOff;
+ while ( nOff <= nEnd )
+ {
+ if ( *pp )
+ (*pp)->DelBroadcastAreasInRange( rRange );
+ if ( nOff < nBreak )
+ {
+ ++nOff;
+ ++pp;
+ }
+ else
+ {
+ nStart += BCA_SLOTS_ROW;
+ nOff = nStart;
+ pp = ppSlots + nOff;
+ nBreak = nOff + nRowBreak;
+ }
+ }
+}
+
+
+#pragma SEG_FUNCDEF(bcaslot_13)
+
+// alle Betroffenen austragen, verketten, Range anpassen, neu eintragen
+void ScBroadcastAreaSlotMachine::UpdateBroadcastAreas(
+ UpdateRefMode eUpdateRefMode,
+ const ScRange& rRange, short nDx, short nDy, short nDz
+ )
+{
+ USHORT nStart, nEnd, nRowBreak;
+ // Betroffene austragen und verketten
+ ComputeAreaPoints( rRange, nStart, nEnd, nRowBreak );
+ USHORT nOff = nStart;
+ USHORT nBreak = nOff + nRowBreak;
+ ScBroadcastAreaSlot** pp = ppSlots + nOff;
+ while ( nOff <= nEnd )
+ {
+ if ( *pp )
+ (*pp)->UpdateRemove( eUpdateRefMode, rRange, nDx, nDy, nDz );
+ if ( nOff < nBreak )
+ {
+ ++nOff;
+ ++pp;
+ }
+ else
+ {
+ nStart += BCA_SLOTS_ROW;
+ nOff = nStart;
+ pp = ppSlots + nOff;
+ nBreak = nOff + nRowBreak;
+ }
+ }
+ // Verkettung abarbeiten
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ USHORT theCol1, theRow1, theTab1, theCol2, theRow2, theTab2;
+ nCol1 = rRange.aStart.Col();
+ nRow1 = rRange.aStart.Row();
+ nTab1 = rRange.aStart.Tab();
+ nCol2 = rRange.aEnd.Col();
+ nRow2 = rRange.aEnd.Row();
+ nTab2 = rRange.aEnd.Tab();
+ while ( pUpdateChain )
+ {
+ ScAddress aAdr;
+ ScRange aRange;
+ ScBroadcastArea* pArea = pUpdateChain;
+ pUpdateChain = pArea->GetUpdateChainNext();
+
+ // Range anpassen
+ aAdr = pArea->GetStart();
+ theCol1 = aAdr.Col();
+ theRow1 = aAdr.Row();
+ theTab1 = aAdr.Tab();
+ aAdr = pArea->GetEnd();
+ theCol2 = aAdr.Col();
+ theRow2 = aAdr.Row();
+ theTab2 = aAdr.Tab();
+ if ( ScRefUpdate::Update( pDoc, eUpdateRefMode,
+ nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, nDx,nDy,nDz,
+ theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 )
+ )
+ {
+ aRange = ScRange( ScAddress( theCol1,theRow1,theTab1 ),
+ ScAddress( theCol2,theRow2,theTab2 ) );
+ pArea->UpdateRange( aRange );
+ pArea->Broadcast( ScAreaChangedHint( aRange ) ); // fuer DDE
+ }
+
+ // in die Slots eintragen
+ ComputeAreaPoints( aRange, nStart, nEnd, nRowBreak );
+ nOff = nStart;
+ nBreak = nOff + nRowBreak;
+ pp = ppSlots + nOff;
+ while ( nOff <= nEnd )
+ {
+ if ( *pp )
+ (*pp)->UpdateInsert( pArea );
+ if ( nOff < nBreak )
+ {
+ ++nOff;
+ ++pp;
+ }
+ else
+ {
+ nStart += BCA_SLOTS_ROW;
+ nOff = nStart;
+ pp = ppSlots + nOff;
+ nBreak = nOff + nRowBreak;
+ }
+ }
+
+ // Verkettung loesen
+ pArea->SetUpdateChainNext( NULL );
+ pArea->SetInUpdateChain( FALSE );
+ }
+ pEOUpdateChain = NULL;
+}
+
+/*------------------------------------------------------------------------
+
+ $Log: not supported by cvs2svn $
+ Revision 1.9 2000/09/17 14:08:34 willem.vandorp
+ OpenOffice header added.
+
+ Revision 1.8 2000/08/31 16:37:55 willem.vandorp
+ Header and footer replaced
+
+ Revision 1.7 1997/12/04 21:07:30 NN
+ includes
+
+
+ Rev 1.6 04 Dec 1997 22:07:30 NN
+ includes
+
+ Rev 1.5 13 Nov 1997 20:54:50 NN
+ ifndef PCH raus
+
+ Rev 1.4 06 Mar 1997 16:47:38 ER
+ #36765# Teil2: RC_ALWAYS als Liste von Broadcastern
+
+ Rev 1.3 08 Jan 1997 20:11:06 ER
+ ScAddress als Reference (keine temporaeren Objekte ohne inlining)
+
+ Rev 1.2 31 Jan 1996 15:15:38 NN
+ Optimierung nur auf Windows16 abschalten
+
+ Rev 1.1 31 Jan 1996 14:42:52 NN
+ #24968# DelBroadcastAreasInRange ohne Optimierung
+
+ Rev 1.0 26 Jan 1996 20:04:46 ER
+ #24511# new: ScBroadcastAreaSlotMachine (Performance)
+
+------------------------------------------------------------------------*/
+
+#pragma SEG_EOFMODULE
+
diff --git a/sc/source/core/data/cell.cxx b/sc/source/core/data/cell.cxx
new file mode 100644
index 000000000000..c20737ecab7a
--- /dev/null
+++ b/sc/source/core/data/cell.cxx
@@ -0,0 +1,1574 @@
+/*************************************************************************
+ *
+ * $RCSfile: cell.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#ifdef MAC
+ // StackSpace
+#include <mac_start.h>
+#include <Memory.h>
+#include <fp.h>
+#include <mac_end.h>
+#endif
+
+#ifdef SOLARIS
+#include <ieeefp.h>
+#elif ( defined ( LINUX ) && ( GLIBC < 2 ) )
+#include <i386/ieeefp.h>
+#endif
+
+#include <svtools/zforlist.hxx>
+#include <float.h> // _finite
+
+#include "scitems.hxx"
+#include "attrib.hxx"
+#include "cell.hxx"
+#include "compiler.hxx"
+#include "interpre.hxx"
+#include "document.hxx"
+#include "scmatrix.hxx"
+#include "dociter.hxx"
+#include "docoptio.hxx"
+#include "rechead.hxx"
+#include "rangenam.hxx"
+#include "brdcst.hxx"
+#include "ddelink.hxx"
+#include "validat.hxx"
+#include "progress.hxx"
+#include "bclist.hxx"
+
+// jetzt fuer alle Systeme niedriger Wert, Rest wird per FormulaTree ausgebuegelt,
+// falls wirklich eine tiefe Rekursion ist, geht das schneller, als zu versuchen
+// und dann doch nicht zu schaffen..
+#define SIMPLEMAXRECURSION
+#ifdef SIMPLEMAXRECURSION
+ #define MAXRECURSION 50
+#else
+#if defined( WIN ) || defined( OS2 )
+ #define MAXRECURSION 50
+#elif defined( MAC )
+ // wird per StackSpace() ermittelt
+#else
+ #define MAXRECURSION 1000
+#endif
+#endif
+
+// STATIC DATA -----------------------------------------------------------
+
+#pragma code_seg("SCSTATICS")
+
+#ifdef USE_MEMPOOL
+// MemPools auf 4k Boundaries - 64 Bytes ausrichten
+const USHORT nMemPoolValueCell = (0x8000 - 64) / sizeof(ScValueCell);
+const USHORT nMemPoolFormulaCell = (0x8000 - 64) / sizeof(ScFormulaCell);
+const USHORT nMemPoolStringCell = (0x4000 - 64) / sizeof(ScStringCell);
+const USHORT nMemPoolNoteCell = (0x1000 - 64) / sizeof(ScNoteCell);
+IMPL_FIXEDMEMPOOL_NEWDEL( ScValueCell, nMemPoolValueCell, nMemPoolValueCell )
+IMPL_FIXEDMEMPOOL_NEWDEL( ScFormulaCell, nMemPoolFormulaCell, nMemPoolFormulaCell )
+IMPL_FIXEDMEMPOOL_NEWDEL( ScStringCell, nMemPoolStringCell, nMemPoolStringCell )
+IMPL_FIXEDMEMPOOL_NEWDEL( ScNoteCell, nMemPoolNoteCell, nMemPoolNoteCell )
+#endif
+
+#pragma code_seg()
+
+INT8 ScFormulaCell::nIterMode = 0;
+
+#ifndef PRODUCT
+static const sal_Char __FAR_DATA msgDbgInfinity[] =
+ "Formelzelle INFINITY ohne Err503 !!! (os/2?)\n"
+ "NICHTS anruehren und ER bescheid sagen!";
+#endif
+
+// -----------------------------------------------------------------------
+
+DECLARE_LIST (ScFormulaCellList, ScFormulaCell*);
+
+
+ScBaseCell* ScBaseCell::Clone(ScDocument* pDoc) const
+{
+ switch (eCellType)
+ {
+ case CELLTYPE_VALUE:
+ return new ScValueCell(*(const ScValueCell*)this);
+ case CELLTYPE_STRING:
+ return new ScStringCell(*(const ScStringCell*)this);
+ case CELLTYPE_EDIT:
+ return new ScEditCell(*(const ScEditCell*)this, pDoc);
+ case CELLTYPE_FORMULA:
+ return new ScFormulaCell(pDoc, ((ScFormulaCell*)this)->aPos,
+ *(const ScFormulaCell*)this);
+ case CELLTYPE_NOTE:
+ return new ScNoteCell(*(const ScNoteCell*)this);
+ default:
+ DBG_ERROR("Unbekannter Zellentyp");
+ return NULL;
+ }
+}
+
+ScBaseCell::~ScBaseCell()
+{
+ delete pNote;
+ delete pBroadcaster;
+ DBG_ASSERT( eCellType == CELLTYPE_DESTROYED, "BaseCell Destructor" );
+}
+
+void ScBaseCell::Delete()
+{
+ DELETEZ(pNote);
+ switch (eCellType)
+ {
+ case CELLTYPE_VALUE:
+ delete (ScValueCell*) this;
+ break;
+ case CELLTYPE_STRING:
+ delete (ScStringCell*) this;
+ break;
+ case CELLTYPE_EDIT:
+ delete (ScEditCell*) this;
+ break;
+ case CELLTYPE_FORMULA:
+ delete (ScFormulaCell*) this;
+ break;
+ case CELLTYPE_NOTE:
+ delete (ScNoteCell*) this;
+ break;
+ default:
+ DBG_ERROR("Unbekannter Zellentyp");
+ break;
+ }
+}
+
+void ScBaseCell::SetNote( const ScPostIt& rNote )
+{
+ if (rNote.GetText().Len() > 0)
+ {
+ if (!pNote)
+ pNote = new ScPostIt(rNote);
+ else
+ *pNote = rNote;
+ }
+ else
+ DELETEZ(pNote);
+}
+
+BOOL ScBaseCell::GetNote( ScPostIt& rNote ) const
+{
+ if ( pNote )
+ rNote = *pNote;
+ else
+ rNote.Clear();
+
+ return ( pNote != NULL );
+}
+
+ScBaseCell* ScBaseCell::CreateTextCell( const String& rString, ScDocument* pDoc )
+{
+ if ( rString.Search('\n') != STRING_NOTFOUND || rString.Search(CHAR_CR) != STRING_NOTFOUND )
+ return new ScEditCell( rString, pDoc );
+ else
+ return new ScStringCell( rString );
+}
+
+void ScBaseCell::LoadNote( SvStream& rStream )
+{
+ pNote = new ScPostIt;
+ rStream >> *pNote;
+}
+
+void ScBaseCell::SetBroadcaster(ScBroadcasterList* pNew)
+{
+ delete pBroadcaster;
+ pBroadcaster = pNew;
+}
+
+void ScBaseCell::StartListeningTo( ScDocument* pDoc, BOOL bOnlyRelNames )
+{
+ if ( eCellType == CELLTYPE_FORMULA && !pDoc->IsClipOrUndo()
+ && !pDoc->GetNoListening()
+ && !((ScFormulaCell*)this)->IsInChangeTrack()
+ )
+ {
+ pDoc->SetDetectiveDirty(TRUE); // es hat sich was geaendert...
+
+ ScFormulaCell* pFormCell = (ScFormulaCell*)this;
+ if( pFormCell->GetCode()->IsRecalcModeAlways() )
+ pDoc->StartListeningArea( BCA_LISTEN_ALWAYS, pFormCell );
+ else
+ {
+ ScTokenArray* pArr = pFormCell->GetCode();
+ pArr->Reset();
+ for( ScToken* t = pArr->GetNextReferenceRPN(); t;
+ t = pArr->GetNextReferenceRPN() )
+ {
+ if ( !bOnlyRelNames || (bOnlyRelNames
+ && (t->aRef.Ref1.IsRelName() || t->aRef.Ref2.IsRelName())))
+ {
+ switch( t->GetType() )
+ {
+ case svSingleRef:
+ t->aRef.Ref1.CalcAbsIfRel( pFormCell->aPos );
+ if ( t->aRef.Ref1.Valid() )
+ {
+ pDoc->StartListeningCell(
+ ScAddress( t->aRef.Ref1.nCol,
+ t->aRef.Ref1.nRow,
+ t->aRef.Ref1.nTab ), pFormCell );
+ }
+ break;
+ case svDoubleRef:
+ t->aRef.CalcAbsIfRel( pFormCell->aPos );
+ if ( t->aRef.Valid() )
+ {
+ if ( t->GetOpCode() == ocColRowNameAuto )
+ { // automagically
+ if ( t->aRef.Ref1.IsColRel() )
+ { // ColName
+ pDoc->StartListeningArea( ScRange (
+ 0,
+ t->aRef.Ref1.nRow,
+ t->aRef.Ref1.nTab,
+ MAXCOL,
+ t->aRef.Ref2.nRow,
+ t->aRef.Ref2.nTab ), pFormCell );
+ }
+ else
+ { // RowName
+ pDoc->StartListeningArea( ScRange (
+ t->aRef.Ref1.nCol,
+ 0,
+ t->aRef.Ref1.nTab,
+ t->aRef.Ref2.nCol,
+ MAXROW,
+ t->aRef.Ref2.nTab ), pFormCell );
+ }
+ }
+ else
+ {
+ pDoc->StartListeningArea( ScRange (
+ t->aRef.Ref1.nCol,
+ t->aRef.Ref1.nRow,
+ t->aRef.Ref1.nTab,
+ t->aRef.Ref2.nCol,
+ t->aRef.Ref2.nRow,
+ t->aRef.Ref2.nTab ), pFormCell );
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+// pArr gesetzt -> Referenzen von anderer Zelle nehmen
+// dann muss auch aPos uebergeben werden!
+
+void ScBaseCell::EndListeningTo( ScDocument* pDoc, BOOL bOnlyRelNames,
+ ScTokenArray* pArr, ScAddress aPos )
+{
+ if ( eCellType == CELLTYPE_FORMULA && !pDoc->IsClipOrUndo()
+ && !((ScFormulaCell*)this)->IsInChangeTrack()
+ )
+ {
+ pDoc->SetDetectiveDirty(TRUE); // es hat sich was geaendert...
+
+ ScFormulaCell* pFormCell = (ScFormulaCell*)this;
+ if( pFormCell->GetCode()->IsRecalcModeAlways() )
+ pDoc->EndListeningArea( BCA_LISTEN_ALWAYS, pFormCell );
+ else
+ {
+ if (!pArr)
+ {
+ pArr = pFormCell->GetCode();
+ aPos = pFormCell->aPos;
+ }
+ pArr->Reset();
+ for( ScToken* t = pArr->GetNextReferenceRPN(); t;
+ t = pArr->GetNextReferenceRPN() )
+ {
+ if ( !bOnlyRelNames || (bOnlyRelNames
+ && (t->aRef.Ref1.IsRelName() || t->aRef.Ref2.IsRelName())))
+ {
+ switch( t->GetType() )
+ {
+ case svSingleRef:
+ t->aRef.Ref1.CalcAbsIfRel( aPos );
+ if ( t->aRef.Ref1.Valid() )
+ {
+ pDoc->EndListeningCell(
+ ScAddress( t->aRef.Ref1.nCol,
+ t->aRef.Ref1.nRow,
+ t->aRef.Ref1.nTab ), pFormCell );
+ }
+ break;
+ case svDoubleRef:
+ t->aRef.CalcAbsIfRel( aPos );
+ if ( t->aRef.Valid() )
+ {
+ if ( t->GetOpCode() == ocColRowNameAuto )
+ { // automagically
+ if ( t->aRef.Ref1.IsColRel() )
+ { // ColName
+ pDoc->EndListeningArea( ScRange (
+ 0,
+ t->aRef.Ref1.nRow,
+ t->aRef.Ref1.nTab,
+ MAXCOL,
+ t->aRef.Ref2.nRow,
+ t->aRef.Ref2.nTab ), pFormCell );
+ }
+ else
+ { // RowName
+ pDoc->EndListeningArea( ScRange (
+ t->aRef.Ref1.nCol,
+ 0,
+ t->aRef.Ref1.nTab,
+ t->aRef.Ref2.nCol,
+ MAXROW,
+ t->aRef.Ref2.nTab ), pFormCell );
+ }
+ }
+ else
+ {
+ pDoc->EndListeningArea( ScRange (
+ t->aRef.Ref1.nCol,
+ t->aRef.Ref1.nRow,
+ t->aRef.Ref1.nTab,
+ t->aRef.Ref2.nCol,
+ t->aRef.Ref2.nRow,
+ t->aRef.Ref2.nTab ), pFormCell );
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+BOOL ScBaseCell::HasValueData() const
+{
+ switch ( eCellType )
+ {
+ case CELLTYPE_VALUE :
+ return TRUE;
+ case CELLTYPE_FORMULA :
+ return ((ScFormulaCell*)this)->IsValue();
+ default:
+ return FALSE;
+ }
+}
+
+
+BOOL ScBaseCell::HasStringData() const
+{
+ switch ( eCellType )
+ {
+ case CELLTYPE_STRING :
+ case CELLTYPE_EDIT :
+ return TRUE;
+ case CELLTYPE_FORMULA :
+ return !((ScFormulaCell*)this)->IsValue();
+ default:
+ return FALSE;
+ }
+}
+
+String ScBaseCell::GetStringData() const
+{
+ String aStr;
+ switch ( eCellType )
+ {
+ case CELLTYPE_STRING:
+ ((const ScStringCell*)this)->GetString( aStr );
+ break;
+ case CELLTYPE_EDIT:
+ ((const ScEditCell*)this)->GetString( aStr );
+ break;
+ case CELLTYPE_FORMULA:
+ ((ScFormulaCell*)this)->GetString( aStr ); // an der Formelzelle nicht-const
+ break;
+ }
+ return aStr;
+}
+
+// static
+BOOL ScBaseCell::CellEqual( const ScBaseCell* pCell1, const ScBaseCell* pCell2 )
+{
+ CellType eType1 = CELLTYPE_NONE;
+ CellType eType2 = CELLTYPE_NONE;
+ if ( pCell1 )
+ {
+ eType1 = pCell1->GetCellType();
+ if (eType1 == CELLTYPE_EDIT)
+ eType1 = CELLTYPE_STRING;
+ else if (eType1 == CELLTYPE_NOTE)
+ eType1 = CELLTYPE_NONE;
+ }
+ if ( pCell2 )
+ {
+ eType2 = pCell2->GetCellType();
+ if (eType2 == CELLTYPE_EDIT)
+ eType2 = CELLTYPE_STRING;
+ else if (eType2 == CELLTYPE_NOTE)
+ eType2 = CELLTYPE_NONE;
+ }
+ if ( eType1 != eType2 )
+ return FALSE;
+
+ switch ( eType1 ) // beide Typen gleich
+ {
+ case CELLTYPE_NONE: // beide leer
+ return TRUE;
+ case CELLTYPE_VALUE: // wirklich Value-Zellen
+ return ( ((const ScValueCell*)pCell1)->GetValue() ==
+ ((const ScValueCell*)pCell2)->GetValue() );
+ case CELLTYPE_STRING: // String oder Edit
+ {
+ String aText1;
+ if ( pCell1->GetCellType() == CELLTYPE_STRING )
+ ((const ScStringCell*)pCell1)->GetString(aText1);
+ else
+ ((const ScEditCell*)pCell1)->GetString(aText1);
+ String aText2;
+ if ( pCell2->GetCellType() == CELLTYPE_STRING )
+ ((const ScStringCell*)pCell2)->GetString(aText2);
+ else
+ ((const ScEditCell*)pCell2)->GetString(aText2);
+ return ( aText1 == aText2 );
+ }
+ case CELLTYPE_FORMULA:
+ {
+ //! eingefuegte Zeilen / Spalten beruecksichtigen !!!!!
+ //! Vergleichsfunktion an der Formelzelle ???
+ //! Abfrage mit ScColumn::SwapRow zusammenfassen!
+
+ ScTokenArray* pCode1 = ((ScFormulaCell*)pCell1)->GetCode();
+ ScTokenArray* pCode2 = ((ScFormulaCell*)pCell2)->GetCode();
+
+ if (pCode1->GetLen() == pCode2->GetLen()) // nicht-UPN
+ {
+ BOOL bEqual = TRUE;
+ USHORT nLen = pCode1->GetLen();
+ ScToken** ppToken1 = pCode1->GetArray();
+ ScToken** ppToken2 = pCode2->GetArray();
+ for (USHORT i=0; i<nLen; i++)
+ if ( !ppToken1[i]->TextEqual(*(ppToken2[i])) )
+ {
+ bEqual = FALSE;
+ break;
+ }
+
+ if (bEqual)
+ return TRUE;
+ }
+
+ return FALSE; // unterschiedlich lang oder unterschiedliche Tokens
+ }
+ default:
+ DBG_ERROR("huch, was fuer Zellen???");
+ }
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------------
+
+//
+// ScFormulaCell
+//
+
+ScFormulaCell::ScFormulaCell() :
+ ScBaseCell( CELLTYPE_FORMULA ),
+ pCode( NULL ),
+ nErgValue( 0.0 ),
+ bIsValue( TRUE ),
+ bDirty( FALSE ),
+ bChanged( FALSE ),
+ bRunning( FALSE ),
+ bCompile( FALSE ),
+ bSubTotal( FALSE ),
+ pDocument( NULL ),
+ nFormatType( NUMBERFORMAT_NUMBER ),
+ nFormatIndex(0),
+ cMatrixFlag ( MM_NONE ),
+ pMatrix ( NULL ),
+ bIsIterCell (FALSE),
+ bInChangeTrack( FALSE ),
+ pPrevious(0),
+ pNext(0),
+ pPreviousTrack(0),
+ pNextTrack(0),
+ aPos(0),
+ nMatCols(0),
+ nMatRows(0)
+{
+}
+
+ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
+ const String& rFormula, BYTE cMatInd ) :
+ ScBaseCell( CELLTYPE_FORMULA ),
+ aPos( rPos ),
+ pCode( NULL ),
+ nErgValue( 0.0 ),
+ bIsValue( TRUE ),
+ bDirty( TRUE ), // -> wg. Benutzung im Fkt.AutoPiloten, war: cMatInd != 0
+ bChanged( FALSE ),
+ bRunning( FALSE ),
+ bCompile( FALSE ),
+ bSubTotal( FALSE ),
+ pDocument( pDoc ),
+ nFormatType( NUMBERFORMAT_NUMBER ),
+ nFormatIndex(0),
+ cMatrixFlag ( cMatInd ),
+ pMatrix( NULL ),
+ bIsIterCell (FALSE),
+ bInChangeTrack( FALSE ),
+ pPrevious(0),
+ pNext(0),
+ pPreviousTrack(0),
+ pNextTrack(0),
+ nMatCols(0),
+ nMatRows(0)
+{
+ Compile( rFormula, TRUE ); // bNoListening, erledigt Insert
+}
+
+// Wird von den Importfiltern verwendet
+
+ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
+ const ScTokenArray* pArr, BYTE cInd ) :
+ ScBaseCell( CELLTYPE_FORMULA ),
+ aPos( rPos ),
+ pCode( pArr ? new ScTokenArray( *pArr ) : new ScTokenArray ),
+ nErgValue( 0.0 ),
+ bIsValue( TRUE ),
+ bDirty( NULL != pArr ), // -> wg. Benutzung im Fkt.AutoPiloten, war: cInd != 0
+ bChanged( FALSE ),
+ bRunning( FALSE ),
+ bCompile( FALSE ),
+ bSubTotal( FALSE ),
+ pDocument( pDoc ),
+ nFormatType( NUMBERFORMAT_NUMBER ),
+ nFormatIndex(0),
+ cMatrixFlag ( cInd ),
+ pMatrix ( NULL ),
+ bIsIterCell (FALSE),
+ bInChangeTrack( FALSE ),
+ pPrevious(0),
+ pNext(0),
+ pPreviousTrack(0),
+ pNextTrack(0),
+ nMatCols(0),
+ nMatRows(0)
+{
+ // UPN-Array erzeugen
+ if( pCode->GetLen() && !pCode->GetError() && !pCode->GetCodeLen() )
+ {
+ ScCompiler aComp(pDocument, aPos, *pCode);
+ bSubTotal = aComp.CompileTokenArray();
+ nFormatType = aComp.GetNumFormatType();
+ }
+ else
+ {
+ pCode->Reset();
+ if ( pCode->GetNextOpCodeRPN( ocSubTotal ) )
+ bSubTotal = TRUE;
+ }
+}
+
+ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rNewPos,
+ const ScFormulaCell& rScFormulaCell ) :
+ ScBaseCell( rScFormulaCell ),
+ SfxListener(),
+ aErgString( rScFormulaCell.aErgString ),
+ nErgValue( rScFormulaCell.nErgValue ),
+ bIsValue( rScFormulaCell.bIsValue ),
+ bDirty( rScFormulaCell.bDirty ),
+ bChanged( rScFormulaCell.bChanged ),
+ bRunning( rScFormulaCell.bRunning ),
+ bCompile( rScFormulaCell.bCompile ),
+ bSubTotal( rScFormulaCell.bSubTotal ),
+ pDocument( pDoc ),
+ nFormatType( rScFormulaCell.nFormatType ),
+ nFormatIndex( pDoc == rScFormulaCell.pDocument ? rScFormulaCell.nFormatIndex : 0 ),
+ cMatrixFlag ( rScFormulaCell.cMatrixFlag ),
+ bIsIterCell (FALSE),
+ bInChangeTrack( FALSE ),
+ pPrevious(0),
+ pNext(0),
+ pPreviousTrack(0),
+ pNextTrack(0),
+ aPos( rNewPos ),
+ nMatCols( rScFormulaCell.nMatCols ),
+ nMatRows( rScFormulaCell.nMatRows )
+{
+ if (rScFormulaCell.pMatrix)
+ pMatrix = rScFormulaCell.pMatrix->Clone();
+ else
+ pMatrix = NULL;
+ pCode = rScFormulaCell.pCode->Clone();
+ // evtl. Fehler zuruecksetzen und neu kompilieren
+ // nicht im Clipboard - da muss das Fehlerflag erhalten bleiben
+ // Spezialfall Laenge=0: als Fehlerzelle erzeugt, dann auch Fehler behalten
+ if ( pCode->GetError() && !pDocument->IsClipboard() && pCode->GetLen() )
+ {
+ pCode->SetError( 0 );
+ bCompile = TRUE;
+ }
+ // Hat der Code Name-Referenzen mit Referenzen?
+ BOOL bCompileLater = FALSE; //! bei ColRowNames und URM_MOVE nach UpdateReference
+ BOOL bCutMode = (rScFormulaCell.pDocument->IsClipboard()
+ && rScFormulaCell.pDocument->IsCutMode());
+ if( !bCompile )
+ {
+ for( ScToken* t = pCode->GetNextReferenceOrName(); t && !bCompile;
+ t = pCode->GetNextReferenceOrName() )
+ {
+ if ( t->GetType() == svIndex )
+ {
+ ScRangeData* pRangeData = pDoc->GetRangeName()->FindIndex( t->nIndex );
+ if( pRangeData )
+ {
+ if( pRangeData->HasReferences() )
+ bCompile = TRUE;
+ }
+ else
+ bCompile = TRUE; // ungueltige Referenz!
+ }
+ else if ( t->GetOpCode() == ocColRowName )
+ {
+ bCompile = TRUE; // neuer LookUp noetig
+ bCompileLater = bCutMode;
+ }
+ }
+ }
+ if( bCompile )
+ {
+ if ( !bCompileLater && bCutMode )
+ {
+ pCode->Reset();
+ bCompileLater = (pCode->GetNextColRowName() != NULL);
+ }
+ if ( !bCompileLater )
+ {
+ // bNoListening, bei in Clip/Undo sowieso nicht,
+ // bei aus Clip auch nicht, sondern nach Insert(Clone) und UpdateReference
+ CompileTokenArray( TRUE );
+ }
+ }
+}
+
+// +---+---+---+---+---+---+---+---+
+// | |Str|Num|Dir|cMatrix|
+// +---+---+---+---+---+---+---+---+
+
+ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
+ SvStream& rStream, ScMultipleReadHeader& rHdr ) :
+ ScBaseCell( CELLTYPE_FORMULA ),
+ aPos( rPos ),
+ pCode( new ScTokenArray ),
+ nErgValue( 0.0 ),
+ bIsValue( TRUE ),
+ bDirty( FALSE ),
+ bChanged( FALSE ),
+ bRunning( FALSE ),
+ bCompile( FALSE ),
+ bSubTotal( FALSE ),
+ pDocument( pDoc ),
+ nFormatType( 0 ),
+ nFormatIndex(0),
+ pMatrix ( NULL ),
+ bIsIterCell (FALSE),
+ bInChangeTrack( FALSE ),
+ pPrevious(0),
+ pNext(0),
+ pPreviousTrack(0),
+ pNextTrack(0),
+ nMatCols(0),
+ nMatRows(0)
+{
+// ScReadHeader aHdr( rStream );
+ rHdr.StartEntry();
+
+ USHORT nVer = (USHORT) pDoc->GetSrcVersion();
+
+ if( nVer >= SC_NUMFMT )
+ {
+ BYTE cData;
+ rStream >> cData;
+#ifndef PRODUCT
+ static BOOL bShown = 0;
+ if ( !bShown && SOFFICE_FILEFORMAT_NOW > SOFFICE_FILEFORMAT_50 )
+ {
+ bShown = 1;
+ DBG_ERRORFILE( "bei inkompatiblem FileFormat den FormatIndex umheben!" );
+ }
+#endif
+ if( cData & 0x0F )
+ {
+ BYTE nSkip = cData & 0x0F;
+ if ( (cData & 0x10) && nSkip >= sizeof(UINT32) )
+ {
+ UINT32 n;
+ rStream >> n;
+ nFormatIndex = n;
+ nSkip -= sizeof(UINT32);
+ }
+ if ( nSkip )
+ rStream.SeekRel( nSkip );
+ }
+ BYTE cFlags;
+ rStream >> cFlags >> nFormatType;
+ cMatrixFlag = (BYTE) ( cFlags & 0x03 );
+ bDirty = BOOL( ( cFlags & 0x04 ) != 0 );
+ if( cFlags & 0x08 )
+ rStream >> nErgValue;
+ if( cFlags & 0x10 )
+ {
+ rStream.ReadByteString( aErgString, rStream.GetStreamCharSet() );
+ bIsValue = FALSE;
+ }
+ pCode->Load( rStream, nVer, aPos );
+ if ( (cFlags & 0x18) == 0 )
+ bDirty = TRUE; // #67161# no result stored => recalc
+ if( cFlags & 0x20 )
+ bSubTotal = TRUE;
+ else if ( nVer < SC_SUBTOTAL_BUGFIX )
+ { // #65285# in alten Dokumenten war Flag nicht gesetzt, wenn Formel
+ // manuell eingegeben wurde (nicht via Daten->Teilergebnisse)
+ if ( pCode->HasOpCodeRPN( ocSubTotal ) )
+ {
+ bDirty = TRUE; // neu berechnen
+ bSubTotal = TRUE;
+ }
+ }
+ if ( cMatrixFlag == MM_FORMULA && rHdr.BytesLeft() )
+ rStream >> nMatCols >> nMatRows;
+ }
+ else
+ {
+ UINT16 nCodeLen;
+ if( pDoc->GetSrcVersion() >= SC_FORMULA_LCLVER )
+ rStream.SeekRel( 2 );
+ rStream >> cMatrixFlag >> nCodeLen;
+ if( cMatrixFlag == 5 )
+ cMatrixFlag = 0;
+ cMatrixFlag &= 3;
+ if( nCodeLen )
+ pCode->Load30( rStream, aPos );
+ // Wir koennen hier bei Calc 3.0-Docs noch kein UPN-Array
+ // erzeugen, da die Named Ranges noch nicht eingelesen sind
+ }
+
+ rHdr.EndEntry();
+
+ // after loading, it must be known if ocMacro is in any formula
+ // (for macro warning, and to insert the hidden view)
+ if ( !pDoc->GetHasMacroFunc() && pCode->HasOpCodeRPN( ocMacro ) )
+ pDoc->SetHasMacroFunc( TRUE );
+}
+
+BOOL lcl_IsBeyond( ScTokenArray* pCode, USHORT nMaxRow )
+{
+ ScToken* t;
+ pCode->Reset();
+ while ( t = pCode->GetNextReferenceRPN() ) // RPN -> auch in Namen
+ if ( t->aRef.Ref1.nRow > nMaxRow || t->aRef.Ref2.nRow > nMaxRow )
+ return TRUE;
+ return FALSE;
+}
+
+void ScFormulaCell::Save( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const
+{
+ USHORT nSaveMaxRow = pDocument->GetSrcMaxRow();
+ if ( nSaveMaxRow < MAXROW && lcl_IsBeyond( pCode, nSaveMaxRow ) )
+ {
+ // Zelle mit Ref-Error erzeugen und speichern
+ // StartEntry/EndEntry passiert beim Speichern der neuen Zelle
+
+ SingleRefData aRef;
+ aRef.InitAddress(ScAddress());
+ aRef.SetColRel(TRUE);
+ aRef.SetColDeleted(TRUE);
+ aRef.SetRowRel(TRUE);
+ aRef.SetRowDeleted(TRUE);
+ aRef.CalcRelFromAbs(aPos);
+ ScTokenArray aArr;
+ aArr.AddSingleReference(aRef);
+ aArr.AddOpCode(ocStop);
+ ScFormulaCell* pErrCell = new ScFormulaCell( pDocument, aPos, &aArr );
+ pErrCell->Save( rStream, rHdr );
+ delete pErrCell;
+
+ pDocument->SetLostData(); // Warnung ausgeben
+ return;
+ }
+
+ rHdr.StartEntry();
+
+ if ( bIsValue && !pCode->GetError() && !SOMA_FINITE( nErgValue ) )
+ {
+ DBG_ERRORFILE( msgDbgInfinity );
+ pCode->SetError( errIllegalFPOperation );
+ }
+ BYTE cFlags = cMatrixFlag & 0x03;
+ if( bDirty )
+ cFlags |= 0x04;
+ // Daten speichern?
+ if( pCode->IsRecalcModeNormal() && !pCode->GetError() )
+ cFlags |= bIsValue ? 0x08 : 0x10;
+ if ( bSubTotal )
+ cFlags |= 0x20;
+#ifndef PRODUCT
+ static BOOL bShown = 0;
+ if ( !bShown && rStream.GetVersion() > SOFFICE_FILEFORMAT_50 )
+ {
+ bShown = 1;
+ DBG_ERRORFILE( "bei inkompatiblem FileFormat den FormatIndex umheben!" );
+ }
+// rStream << (BYTE) 0x00;
+#endif
+ if ( nFormatIndex )
+ rStream << (BYTE) (0x10 | sizeof(UINT32)) << nFormatIndex;
+ else
+ rStream << (BYTE) 0x00;
+ rStream << cFlags << (UINT16) nFormatType;
+ if( cFlags & 0x08 )
+ rStream << nErgValue;
+ if( cFlags & 0x10 )
+ rStream.WriteByteString( aErgString, rStream.GetStreamCharSet() );
+ pCode->Store( rStream, aPos );
+ if ( cMatrixFlag == MM_FORMULA )
+ rStream << nMatCols << nMatRows;
+
+ rHdr.EndEntry();
+}
+
+ScBaseCell* ScFormulaCell::Clone( ScDocument* pDoc, const ScAddress& rPos,
+ BOOL bNoListening ) const
+{
+ ScFormulaCell* pCell = new ScFormulaCell( pDoc, rPos, *this );
+ if ( !bNoListening )
+ pCell->StartListeningTo( pDoc );
+ return pCell;
+}
+
+void ScFormulaCell::GetFormula( String& rFormula ) const
+{
+ if( pCode->GetError() && !pCode->GetLen() )
+ {
+ rFormula = ScGlobal::GetErrorString( pCode->GetError() ); return;
+ }
+ else if( cMatrixFlag == MM_REFERENCE )
+ {
+ // Referenz auf eine andere Zelle, die eine Matrixformel enthaelt
+ pCode->Reset();
+ ScToken* p = pCode->GetNextReferenceRPN();
+ if( p )
+ {
+ ScBaseCell* pCell;
+ p->aRef.Ref1.CalcAbsIfRel( aPos );
+ if ( p->aRef.Ref1.Valid() )
+ pCell = pDocument->GetCell( ScAddress( p->aRef.Ref1.nCol,
+ p->aRef.Ref1.nRow, p->aRef.Ref1.nTab ) );
+ else
+ pCell = NULL;
+ if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA)
+ {
+ ((ScFormulaCell*)pCell)->GetFormula(rFormula);
+ return;
+ }
+ else
+ {
+ ScCompiler aComp( pDocument, aPos, *pCode );
+ aComp.CreateStringFromTokenArray( rFormula );
+ }
+ }
+ else
+ {
+ DBG_ERROR("ScFormulaCell::GetFormula: Keine Matrix");
+ }
+ }
+ else
+ {
+ ScCompiler aComp( pDocument, aPos, *pCode );
+ aComp.CreateStringFromTokenArray( rFormula );
+ }
+
+ rFormula.Insert( '=',0 );
+ if( cMatrixFlag )
+ {
+ rFormula.Insert('{', 0);
+ rFormula += '}';
+ }
+}
+
+void ScFormulaCell::GetResultDimensions( USHORT& rCols, USHORT& rRows )
+{
+ if (bDirty && pDocument->GetAutoCalc())
+ Interpret();
+
+ if ( !pCode->GetError() && pMatrix )
+ pMatrix->GetDimensions( rCols, rRows );
+ else
+ rCols = rRows = 0;
+}
+
+void ScFormulaCell::Compile( const String& rFormula, BOOL bNoListening )
+{
+ if ( pDocument->IsClipOrUndo() ) return;
+ BOOL bWasInFormulaTree = pDocument->IsInFormulaTree( this );
+ if ( bWasInFormulaTree )
+ pDocument->RemoveFromFormulaTree( this );
+ // pCode darf fuer Abfragen noch nicht geloescht, muss aber leer sein
+ if ( pCode )
+ pCode->Clear();
+ ScTokenArray* pCodeOld = pCode;
+ ScCompiler aComp(pDocument, aPos);
+ if ( pDocument->IsImportingXML() )
+ aComp.SetCompileEnglish( TRUE );
+ pCode = aComp.CompileString( rFormula );
+ if ( pCodeOld )
+ delete pCodeOld;
+ if( !pCode->GetError() )
+ {
+ if ( !pCode->GetLen() && aErgString.Len() && rFormula == aErgString )
+ { // #65994# nicht rekursiv CompileTokenArray/Compile/CompileTokenArray
+ if ( rFormula.GetChar(0) == '=' )
+ pCode->AddBad( rFormula.GetBuffer() + 1 );
+ else
+ pCode->AddBad( rFormula.GetBuffer() );
+ }
+ bCompile = TRUE;
+ CompileTokenArray( bNoListening );
+ }
+ else
+ {
+ bChanged = TRUE;
+ SetTextWidth( TEXTWIDTH_DIRTY );
+ }
+ if ( bWasInFormulaTree )
+ pDocument->PutInFormulaTree( this );
+}
+
+
+void ScFormulaCell::CompileTokenArray( BOOL bNoListening )
+{
+ // Noch nicht compiliert?
+ if( !pCode->GetLen() && aErgString.Len() )
+ Compile( aErgString );
+ else if( bCompile && !pDocument->IsClipOrUndo() && !pCode->GetError() )
+ {
+ // RPN-Laenge kann sich aendern
+ BOOL bWasInFormulaTree = pDocument->IsInFormulaTree( this );
+ if ( bWasInFormulaTree )
+ pDocument->RemoveFromFormulaTree( this );
+
+ // Laden aus Filter? Dann noch nix machen!
+ if( pDocument->IsInsertingFromOtherDoc() )
+ bNoListening = TRUE;
+
+ if( !bNoListening && pCode->GetCodeLen() )
+ EndListeningTo( pDocument );
+ ScCompiler aComp(pDocument, aPos, *pCode );
+ bSubTotal = aComp.CompileTokenArray();
+ if( !pCode->GetError() )
+ {
+ nFormatType = aComp.GetNumFormatType();
+ nFormatIndex = 0;
+ bChanged = TRUE;
+ nErgValue = 0.0;
+ aErgString.Erase();
+ bCompile = FALSE;
+ if ( !bNoListening )
+ StartListeningTo( pDocument );
+ }
+ if ( bWasInFormulaTree )
+ pDocument->PutInFormulaTree( this );
+ }
+}
+
+
+void ScFormulaCell::CompileXML()
+{
+ if ( cMatrixFlag == MM_REFERENCE )
+ return ;
+
+ ScCompiler aComp( pDocument, aPos, *pCode );
+ aComp.SetCompileEnglish( TRUE );
+ aComp.SetImportXML( TRUE );
+ String aFormula;
+ aComp.CreateStringFromTokenArray( aFormula );
+ // pCode darf fuer Abfragen noch nicht geloescht, muss aber leer sein
+ if ( pCode )
+ pCode->Clear();
+ ScTokenArray* pCodeOld = pCode;
+ pCode = aComp.CompileString( aFormula );
+ delete pCodeOld;
+ if( !pCode->GetError() )
+ {
+ if ( !pCode->GetLen() )
+ {
+ if ( aFormula.GetChar(0) == '=' )
+ pCode->AddBad( aFormula.GetBuffer() + 1 );
+ else
+ pCode->AddBad( aFormula.GetBuffer() );
+ }
+ bSubTotal = aComp.CompileTokenArray();
+ if( !pCode->GetError() )
+ {
+ nFormatType = aComp.GetNumFormatType();
+ nFormatIndex = 0;
+ bChanged = TRUE;
+ bCompile = FALSE;
+ StartListeningTo( pDocument );
+ }
+ }
+ else
+ {
+ bChanged = TRUE;
+ SetTextWidth( TEXTWIDTH_DIRTY );
+ }
+}
+
+
+void ScFormulaCell::CalcAfterLoad()
+{
+ BOOL bNewCompiled = FALSE;
+ // Falls ein Calc 1.0-Doc eingelesen wird, haben wir ein Ergebnis,
+ // aber kein TokenArray
+ if( !pCode->GetLen() && aErgString.Len() )
+ {
+ Compile( aErgString, TRUE );
+ aErgString.Erase();
+ bDirty = TRUE;
+ bNewCompiled = TRUE;
+ }
+ // Das UPN-Array wird nicht erzeugt, wenn ein Calc 3.0-Doc eingelesen
+ // wurde, da die RangeNames erst jetzt existieren.
+ if( pCode->GetLen() && !pCode->GetCodeLen() && !pCode->GetError() )
+ {
+ ScCompiler aComp(pDocument, aPos, *pCode);
+ bSubTotal = aComp.CompileTokenArray();
+ nFormatType = aComp.GetNumFormatType();
+ nFormatIndex = 0;
+ bDirty = TRUE;
+ bCompile = FALSE;
+ bNewCompiled = TRUE;
+ }
+ // irgendwie koennen unter os/2 mit rotter FPU-Exception /0 ohne Err503
+ // gespeichert werden, woraufhin spaeter im NumberFormatter die BLC Lib
+ // bei einem fabs(-NAN) abstuerzt (#32739#)
+ // hier fuer alle Systeme ausbuegeln, damit da auch Err503 steht
+ if ( bIsValue && !SOMA_FINITE( nErgValue ) )
+ {
+ DBG_ERRORFILE("Formelzelle INFINITY !!! Woher kommt das Dokument?");
+ nErgValue = 0.0;
+ pCode->SetError( errIllegalFPOperation );
+ bDirty = TRUE;
+ }
+ // DoubleRefs bei binaeren Operatoren waren vor v5.0 immer Matrix,
+ // jetzt nur noch wenn in Matrixformel, sonst implizite Schnittmenge
+ if ( pDocument->GetSrcVersion() < SC_MATRIX_DOUBLEREF &&
+ GetMatrixFlag() == MM_NONE && pCode->HasMatrixDoubleRefOps() )
+ {
+ cMatrixFlag = MM_FORMULA;
+ nMatCols = 1;
+ nMatRows = 1;
+ }
+ // Muss die Zelle berechnet werden?
+ // Nach Load koennen Zellen einen Fehlercode enthalten, auch dann
+ // Listener starten und ggbf. neu berechnen wenn nicht RECALCMODE_NORMAL
+ if( !bNewCompiled || !pCode->GetError() )
+ {
+ StartListeningTo( pDocument );
+ if( !pCode->IsRecalcModeNormal() )
+ bDirty = TRUE;
+ }
+ if ( pCode->GetError() == errInterpOverflow )
+ { // versuchen Err527 wegzubuegeln
+ bDirty = TRUE;
+ }
+ else if ( pCode->IsRecalcModeAlways() )
+ { // zufall(), heute(), jetzt() bleiben immer im FormulaTree, damit sie
+ // auch bei jedem F9 berechnet werden.
+ bDirty = TRUE;
+ }
+ // Noch kein SetDirty weil noch nicht alle Listener bekannt, erst in
+ // SetDirtyAfterLoad.
+}
+
+void ScFormulaCell::Interpret()
+{
+ static USHORT nRecCount = 0;
+ static ScFormulaCell* pLastIterInterpreted = NULL;
+ if ( !bDirty )
+ return; // fuer IterCircRef, nix doppelt
+
+ //! HACK:
+ // Wenn der Aufruf aus einem Reschedule im DdeLink-Update kommt, dirty stehenlassen
+ // Besser: Dde-Link Update ohne Reschedule oder ganz asynchron !!!
+
+ if ( ScDdeLink::IsInUpdate() )
+ return;
+
+ if (bRunning)
+ {
+ // Keine Iterierung?
+ if (!pDocument->GetDocOptions().IsIter())
+ pCode->SetError( errCircularReference );
+ else
+ {
+ if (pCode->GetError() == errCircularReference)
+ pCode->SetError( 0 );
+ nIterMode = 1;
+ bIsIterCell = TRUE;
+ pLastIterInterpreted = NULL;
+ }
+ return;
+ }
+ // #63038# fuer GetErrCode, IsValue, GetValue nicht mehrfach interpretieren
+ if ( nIterMode && pLastIterInterpreted == this )
+ return ;
+
+ if( !pCode->GetCodeLen() && !pCode->GetError() )
+ CompileTokenArray();
+
+ if( pCode->GetCodeLen() && pDocument )
+ {
+#if defined(MAC) && !defined(SIMPLEMAXRECURSION)
+ if( StackSpace() < 2048 ) // 2K Stack noch uebriglassen
+#else
+ if( nRecCount > MAXRECURSION )
+#endif
+ {
+ pCode->SetError( errInterpOverflow );
+ // Zelle bleibt in FormulaTree, naechstes Mal sind evtl.
+ // Vorgaenger bereits berechnet worden bzw. von der View wird
+ // via ScCellFormat::GetString CalcFormulaTree angeworfen
+ bDirty = FALSE;
+ nErgValue = 0.0;
+ bIsValue = TRUE;
+ nIterMode = 0;
+ bIsIterCell = FALSE;
+ pLastIterInterpreted = NULL;
+ bChanged = TRUE;
+ SetTextWidth( TEXTWIDTH_DIRTY );
+ return;
+ }
+ nRecCount++;
+ pDocument->IncInterpretLevel();
+ ScInterpreter* p = new ScInterpreter( this, pDocument, aPos, *pCode );
+ USHORT nOldErrCode = pCode->GetError();
+ USHORT nIterCount = 0;
+ if ( nIterMode == 0 )
+ { // nur beim ersten Mal
+// wenn neu kompilierte Zelle 0.0 ergibt wird kein Changed erkannt
+// und die Zelle wird nicht sofort repainted!
+// bChanged = FALSE;
+ if ( nOldErrCode == errNoConvergence
+ && pDocument->GetDocOptions().IsIter() )
+ pCode->SetError( 0 );
+ }
+ BOOL bRepeat = TRUE;
+ while( bRepeat )
+ {
+ if ( pMatrix )
+ {
+ delete pMatrix;
+ pMatrix = NULL;
+ }
+
+ switch ( pCode->GetError() )
+ {
+ case errCircularReference : // wird neu festgestellt
+ case errInterpOverflow : // Err527 eine Chance geben
+ pCode->SetError( 0 );
+ break;
+ }
+
+ bRunning = TRUE;
+ p->Interpret();
+ bRunning = FALSE;
+ if( pCode->GetError()
+ && pCode->GetError() != errCircularReference )
+ {
+ bDirty = FALSE;
+ nIterMode = 0;
+ bIsIterCell = FALSE;
+ pLastIterInterpreted = NULL;
+ bChanged = TRUE;
+ bIsValue = TRUE;
+ break;
+ }
+ if( nIterMode == 1 && bIsIterCell )
+ {
+ pLastIterInterpreted = NULL;
+ ++nIterCount;
+ // schoen konvergiert?
+ if( (p->GetResultType() == svDouble
+ && fabs( p->GetNumResult() - nErgValue ) <=
+ pDocument->GetDocOptions().GetIterEps())
+ )
+ {
+ nIterMode = 0;
+ bIsIterCell = FALSE;
+ bDirty = FALSE;
+ bRepeat = FALSE;
+ }
+ // Zu oft rumgelaufen?
+ else if( nIterCount >= pDocument->GetDocOptions().GetIterCount() )
+ {
+ nIterMode = 0;
+ bIsIterCell = FALSE;
+ bDirty = FALSE;
+ bRepeat = FALSE;
+ pCode->SetError( errNoConvergence );
+ }
+ if ( p->GetResultType() == svDouble )
+ {
+ if( !bIsValue || nErgValue != p->GetNumResult() )
+ bChanged = TRUE;
+ bIsValue = TRUE;
+ nErgValue = p->GetNumResult();
+ }
+ }
+ else
+ bRepeat = FALSE;
+ }
+
+ switch( p->GetResultType() )
+ {
+ case svDouble:
+ if( nErgValue != p->GetNumResult() || !bIsValue )
+ {
+ bChanged = TRUE;
+ bIsValue = TRUE;
+ nErgValue = p->GetNumResult();
+ }
+ break;
+ case svString:
+ if( aErgString != p->GetStringResult() || bIsValue )
+ {
+ bChanged = TRUE;
+ bIsValue = FALSE;
+ aErgString = p->GetStringResult();
+ }
+ break;
+ }
+
+ // Neuer Fehlercode?
+ if( !bChanged && pCode->GetError() != nOldErrCode )
+ bChanged = TRUE;
+ // Anderes Zahlenformat?
+ if( nFormatType != p->GetRetFormatType() )
+ {
+ nFormatType = p->GetRetFormatType();
+ bChanged = TRUE;
+ }
+ if( nFormatIndex != p->GetRetFormatIndex() )
+ {
+ nFormatIndex = p->GetRetFormatIndex();
+ bChanged = TRUE;
+ }
+ // Genauigkeit wie angezeigt?
+ if ( bIsValue && !pCode->GetError()
+ && pDocument->GetDocOptions().IsCalcAsShown()
+ && nFormatType != NUMBERFORMAT_DATE
+ && nFormatType != NUMBERFORMAT_TIME
+ && nFormatType != NUMBERFORMAT_DATETIME )
+ {
+ ULONG nFormat = pDocument->GetNumberFormat( aPos );
+ if ( nFormatIndex && (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
+ nFormat = nFormatIndex;
+ if ( (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
+ nFormat = ScGlobal::GetStandardFormat(
+ *pDocument->GetFormatTable(), nFormat, nFormatType );
+ nErgValue = pDocument->RoundValueAsShown( nErgValue, nFormat );
+ }
+ if ( nIterMode == 0 )
+ bDirty = FALSE;
+ else
+ pLastIterInterpreted = this;
+ pMatrix = p->GetMatrixResult();
+ if( pMatrix )
+ {
+#if 0
+//! MatrixFormel immer changed?!?
+// ist bei MD's Rundumschlag von r1.167 --> r1.168 reingekommen
+// => ewiges Repaint von MatrixFormel, besonders bei DDE laestig
+// ab r1.260 (sv369b) probieren wir's mal ohne..
+ if( cMatrixFlag == MM_FORMULA )
+ bChanged = TRUE;
+ else
+#else
+ if( cMatrixFlag != MM_FORMULA )
+#endif
+ { // mit linker oberer Ecke weiterleben
+ delete pMatrix;
+ pMatrix = NULL;
+ }
+ }
+ if( bChanged )
+ SetTextWidth( TEXTWIDTH_DIRTY );
+ delete p;
+ nRecCount--;
+ pDocument->DecInterpretLevel();
+ if ( pCode->GetError() != errInterpOverflow
+ && !pCode->IsRecalcModeAlways() )
+ pDocument->RemoveFromFormulaTree( this );
+#ifndef PRODUCT
+ if ( bIsValue && !pCode->GetError() && !SOMA_FINITE( nErgValue ) )
+ {
+ DBG_ERRORFILE( msgDbgInfinity );
+ nErgValue = 0.0;
+ pCode->SetError( errIllegalFPOperation );
+ }
+#endif
+
+ // FORCED Zellen auch sofort auf Gueltigkeit testen (evtl. Makro starten)
+
+ if ( pCode->IsRecalcModeForced() )
+ {
+ ULONG nValidation = ((const SfxUInt32Item*) pDocument->GetAttr(
+ aPos.Col(), aPos.Row(), aPos.Tab(), ATTR_VALIDDATA ))->GetValue();
+ if ( nValidation )
+ {
+ const ScValidationData* pData = pDocument->GetValidationEntry( nValidation );
+ if ( pData && !pData->IsDataValid( this, aPos ) )
+ pData->DoCalcError( this );
+ }
+ }
+
+ // Reschedule verlangsamt das ganze erheblich, nur bei Prozentaenderung ausfuehren
+ ScProgress::GetInterpretProgress()->SetStateCountDownOnPercent(
+ pDocument->GetFormulaCodeInTree() );
+ }
+ else
+ {
+ // Zelle bei Compiler-Fehlern nicht ewig auf dirty stehenlassen
+ DBG_ASSERT( pCode->GetError(), "kein UPN-Code und kein Fehler ?!?!" );
+ bDirty = FALSE;
+ }
+}
+
+ULONG ScFormulaCell::GetStandardFormat( SvNumberFormatter& rFormatter, ULONG nFormat ) const
+{
+ if ( nFormatIndex && (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
+ return nFormatIndex;
+ if ( bIsValue ) //! nicht IsValue()
+ return ScGlobal::GetStandardFormat( nErgValue, rFormatter, nFormat, nFormatType );
+ else
+ return ScGlobal::GetStandardFormat( rFormatter, nFormat, nFormatType );
+}
+
+
+void __EXPORT ScFormulaCell::SFX_NOTIFY( SfxBroadcaster& rBC,
+ const TypeId& rBCType, const SfxHint& rHint, const TypeId& rHintType )
+{
+ if ( !pDocument->IsInDtorClear() && !pDocument->GetHardRecalcState() )
+ {
+ const ScHint* p = PTR_CAST( ScHint, &rHint );
+ if( p && (p->GetId() & (SC_HINT_DATACHANGED | SC_HINT_DYING)) )
+ {
+ bDirty = TRUE;
+ // #35962# nicht ewig aus FormulaTree rausholen um in FormulaTrack
+ // zu stellen und wieder in FormulaTree reinzupacken..
+ // kann ausser bei RECALCMODE_ALWAYS jemals eine Zelle im
+ // FormulaTree sein, wenn sie durch FormulaTrack eine Zelle
+ // anstossen wuerde, die nicht in FormulaTrack/FormulaTree ist?!?
+ if ( (!pDocument->IsInFormulaTree( this )
+ || pCode->IsRecalcModeAlways())
+ && !pDocument->IsInFormulaTrack( this ) )
+ pDocument->AppendToFormulaTrack( this );
+ }
+ }
+}
+
+void ScFormulaCell::SetDirty()
+{
+ if ( !IsInChangeTrack() )
+ {
+ if ( pDocument->GetHardRecalcState() )
+ bDirty = TRUE;
+ else
+ {
+ // Mehrfach-FormulaTracking in Load und in CompileAll
+ // nach CopyScenario und CopyBlockFromClip vermeiden.
+ // Wenn unbedingtes FormulaTracking noetig, vor SetDirty bDirty=FALSE
+ // setzen, z.B. in CompileTokenArray
+ if ( !bDirty || !pDocument->IsInFormulaTree( this ) )
+ {
+ bDirty = TRUE;
+ pDocument->AppendToFormulaTrack( this );
+ pDocument->TrackFormulas();
+ }
+ }
+ }
+}
+
+void ScFormulaCell::SetErrCode( USHORT n )
+{
+ pCode->SetError( n );
+ bIsValue = FALSE;
+}
+
+void ScFormulaCell::AddRecalcMode( ScRecalcMode nBits )
+{
+ if ( (nBits & RECALCMODE_EMASK) != RECALCMODE_NORMAL )
+ bDirty = TRUE;
+ if ( nBits & RECALCMODE_ONLOAD_ONCE )
+ { // OnLoadOnce nur zum Dirty setzen nach Filter-Import
+ nBits = (nBits & ~RECALCMODE_EMASK) | RECALCMODE_NORMAL;
+ }
+ pCode->AddRecalcMode( nBits );
+}
+
+//------------------------------------------------------------------------
+
+ScDetectiveRefIter::ScDetectiveRefIter( ScFormulaCell* pCell )
+{
+ pCode = pCell->GetCode();
+ pCode->Reset();
+ aPos = pCell->aPos;
+}
+
+BOOL ScDetectiveRefIter::GetNextRef( ScTripel& rStart, ScTripel& rEnd )
+{
+ BOOL bRet = FALSE;
+
+ ScToken* p = pCode->GetNextReferenceRPN();
+ if (p)
+ p->aRef.CalcAbsIfRel( aPos );
+
+ while ( p && ( p->aRef.Ref1.IsColDeleted() || p->aRef.Ref2.IsColDeleted() ||
+ p->aRef.Ref1.IsRowDeleted() || p->aRef.Ref2.IsRowDeleted() ||
+ p->aRef.Ref1.IsTabDeleted() || p->aRef.Ref2.IsTabDeleted() ||
+ !p->aRef.Ref1.Valid() || !p->aRef.Ref2.Valid() ) )
+ {
+ p = pCode->GetNextReferenceRPN();
+ if (p)
+ p->aRef.CalcAbsIfRel( aPos );
+ }
+
+ if( p )
+ {
+ rStart.Put( p->aRef.Ref1.nCol,
+ p->aRef.Ref1.nRow,
+ p->aRef.Ref1.nTab );
+ rEnd.Put( p->aRef.Ref2.nCol,
+ p->aRef.Ref2.nRow,
+ p->aRef.Ref2.nTab );
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+//-----------------------------------------------------------------------------------
+
+ScFormulaCell::~ScFormulaCell()
+{
+ pDocument->RemoveFromFormulaTree( this );
+ delete pCode;
+ delete pMatrix;
+ pMatrix = NULL;
+#ifdef DBG_UTIL
+ eCellType = CELLTYPE_DESTROYED;
+#endif
+}
+
+
+#ifdef DBG_UTIL
+
+ScStringCell::~ScStringCell()
+{
+ eCellType = CELLTYPE_DESTROYED;
+}
+#endif
+ //! ValueCell auch nur bei DBG_UTIL,
+ //! auch in cell.hxx aendern !!!!!!!!!!!!!!!!!!!!
+
+ScValueCell::~ScValueCell()
+{
+ eCellType = CELLTYPE_DESTROYED;
+}
+
+#ifdef DBG_UTIL
+
+ScNoteCell::~ScNoteCell()
+{
+ eCellType = CELLTYPE_DESTROYED;
+}
+#endif
+
+
+
+
diff --git a/sc/source/core/data/cell2.cxx b/sc/source/core/data/cell2.cxx
new file mode 100644
index 000000000000..b6a087c9956e
--- /dev/null
+++ b/sc/source/core/data/cell2.cxx
@@ -0,0 +1,1415 @@
+/*************************************************************************
+ *
+ * $RCSfile: cell2.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#ifndef _SV_MAPMOD_HXX //autogen
+#include <vcl/mapmod.hxx>
+#endif
+#ifndef _EDITOBJ_HXX //autogen
+#include <svx/editobj.hxx>
+#endif
+#ifndef _EDITSTAT_HXX //autogen
+#include <svx/editstat.hxx>
+#endif
+
+#include "cell.hxx"
+#include "compiler.hxx"
+#include "document.hxx"
+#include "rangenam.hxx"
+#include "rechead.hxx"
+#include "refupdat.hxx"
+#include "scmatrix.hxx"
+#include "editutil.hxx"
+#include "chgtrack.hxx"
+#include "indexmap.hxx"
+
+
+// STATIC DATA -----------------------------------------------------------
+
+#pragma code_seg("SCSTATICS")
+
+#ifdef USE_MEMPOOL
+const USHORT nMemPoolEditCell = (0x1000 - 64) / sizeof(ScNoteCell);
+IMPL_FIXEDMEMPOOL_NEWDEL( ScEditCell, nMemPoolEditCell, nMemPoolEditCell )
+#endif
+
+#pragma code_seg()
+
+// -----------------------------------------------------------------------
+
+ScEditCell::ScEditCell( ScDocument* pDocP ) :
+ ScBaseCell( CELLTYPE_EDIT ),
+ pData( NULL ),
+ pString( NULL ),
+ pDoc( pDocP )
+{
+}
+
+ScEditCell::ScEditCell( const EditTextObject* pObject, ScDocument* pDocP,
+ const SfxItemPool* pFromPool ) :
+ ScBaseCell( CELLTYPE_EDIT ),
+ pString( NULL ),
+ pDoc( pDocP )
+{
+ SetTextObject( pObject, pFromPool );
+}
+
+ScEditCell::ScEditCell( const ScEditCell& rEditCell, ScDocument* pDocP ) :
+ ScBaseCell( CELLTYPE_EDIT ),
+ pString( NULL ),
+ pDoc( pDocP )
+{
+ SetTextObject( rEditCell.pData, rEditCell.pDoc->GetEditPool() );
+}
+
+ScEditCell::ScEditCell( SvStream& rStream, USHORT nVer, ScDocument* pDocP ) :
+ ScBaseCell( CELLTYPE_EDIT ),
+ pString( NULL ),
+ pDoc( pDocP )
+{
+ if( nVer >= SC_DATABYTES2 )
+ {
+ BYTE cData;
+ rStream >> cData;
+ if( cData & 0x0F )
+ rStream.SeekRel( cData & 0x0F );
+ }
+ if ( nVer < SC_VERSION_EDITPOOL )
+ { // jedes hat seinen eigenen Pool, dem neuen zuordnen
+ EditTextObject* pTmp = EditTextObject::Create( rStream );
+ SetTextObject( pTmp, NULL );
+ delete pTmp;
+ }
+ else
+ pData = EditTextObject::Create( rStream, pDoc->GetEditPool() );
+}
+
+ScEditCell::ScEditCell( const String& rString, ScDocument* pDocP ) :
+ ScBaseCell( CELLTYPE_EDIT ),
+ pString( NULL ),
+ pDoc( pDocP )
+{
+ DBG_ASSERT( rString.Search('\n') != STRING_NOTFOUND ||
+ rString.Search(CHAR_CR) != STRING_NOTFOUND,
+ "EditCell mit einfachem Text !?!?" );
+
+ EditEngine& rEngine = pDoc->GetEditEngine();
+ rEngine.SetText( rString );
+ pData = rEngine.CreateTextObject();
+}
+
+ScEditCell::~ScEditCell()
+{
+ delete pData;
+ delete pString;
+
+#ifdef DBG_UTIL
+ eCellType = CELLTYPE_DESTROYED;
+#endif
+}
+
+ScBaseCell* ScEditCell::Clone( ScDocument* pNewDoc ) const
+{
+ return new ScEditCell( *this, pNewDoc );
+}
+
+void ScEditCell::SetData( const EditTextObject* pObject,
+ const SfxItemPool* pFromPool )
+{
+ if ( pString )
+ {
+ delete pString;
+ pString = NULL;
+ }
+ delete pData;
+ SetTextObject( pObject, pFromPool );
+}
+
+void ScEditCell::GetData( const EditTextObject*& rpObject ) const
+{
+ rpObject = pData;
+}
+
+void ScEditCell::GetString( String& rString ) const
+{
+ if ( pString )
+ rString = *pString;
+ else if ( pData )
+ {
+ // auch Text von URL-Feldern, Doc-Engine ist eine ScFieldEditEngine
+ EditEngine& rEngine = pDoc->GetEditEngine();
+ rEngine.SetText( *pData );
+ rString = ScEditUtil::GetSpaceDelimitedString(rEngine); // space between paragraphs
+ // kurze Strings fuer Formeln merken
+ if ( rString.Len() < MAXSTRLEN )
+ ((ScEditCell*)this)->pString = new String( rString ); //! non-const
+ }
+ else
+ rString.Erase();
+}
+
+void ScEditCell::Save( SvStream& rStream ) const
+{
+ DBG_ASSERT(pData,"StoreTextObject(NULL)");
+ rStream << (BYTE) 0x00;
+ if ( rStream.GetVersion() < SOFFICE_FILEFORMAT_50 )
+ { // jedem seinen eigenen Pool
+ ScEditEngineDefaulter aEngine( EditEngine::CreatePool(), TRUE );
+ // #52396# richtige Metric schreiben
+ aEngine.SetRefMapMode( MAP_100TH_MM );
+ aEngine.SetText( *pData );
+ EditTextObject* pTmp = aEngine.CreateTextObject();
+ pTmp->Store( rStream );
+ delete pTmp;
+ }
+ else
+ pData->Store( rStream );
+}
+
+void ScEditCell::SetTextObject( const EditTextObject* pObject,
+ const SfxItemPool* pFromPool )
+{
+ if ( pObject )
+ {
+ if ( pFromPool && pDoc->GetEditPool() == pFromPool )
+ pData = pObject->Clone();
+ else
+ { //! anderer Pool
+ // Leider gibt es keinen anderen Weg, um den Pool umzuhaengen,
+ // als das Object durch eine entsprechende Engine zu schleusen..
+ EditEngine& rEngine = pDoc->GetEditEngine();
+ if ( pObject->HasOnlineSpellErrors() )
+ {
+ ULONG nControl = rEngine.GetControlWord();
+ const ULONG nSpellControl = EE_CNTRL_ONLINESPELLING | EE_CNTRL_ALLOWBIGOBJS;
+ BOOL bNewControl = ( (nControl & nSpellControl) != nSpellControl );
+ if ( bNewControl )
+ rEngine.SetControlWord( nControl | nSpellControl );
+ rEngine.SetText( *pObject );
+ pData = rEngine.CreateTextObject();
+ if ( bNewControl )
+ rEngine.SetControlWord( nControl );
+ }
+ else
+ {
+ rEngine.SetText( *pObject );
+ pData = rEngine.CreateTextObject();
+ }
+ }
+ }
+ else
+ pData = NULL;
+}
+
+//---------------------------------------------------------------------
+
+void ScFormulaCell::GetEnglishFormula( String& rFormula, BOOL bCompileXML ) const
+{
+ //! mit GetFormula zusammenfassen !!!
+
+ if( pCode->GetError() && !pCode->GetLen() )
+ {
+ rFormula = ScGlobal::GetErrorString( pCode->GetError() ); return;
+ }
+ else if( cMatrixFlag == MM_REFERENCE )
+ {
+ // Referenz auf eine andere Zelle, die eine Matrixformel enthaelt
+ pCode->Reset();
+ ScToken* p = pCode->GetNextReferenceRPN();
+ if( p )
+ {
+ ScBaseCell* pCell;
+ p->aRef.Ref1.CalcAbsIfRel( aPos );
+ if ( p->aRef.Ref1.Valid() )
+ pCell = pDocument->GetCell( ScAddress( p->aRef.Ref1.nCol,
+ p->aRef.Ref1.nRow, p->aRef.Ref1.nTab ) );
+ else
+ pCell = NULL;
+ if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA)
+ {
+ ((ScFormulaCell*)pCell)->GetEnglishFormula(rFormula);
+ return;
+ }
+ else
+ {
+ ScCompiler aComp( pDocument, aPos, *pCode );
+ aComp.SetCompileEnglish( TRUE );
+ aComp.SetCompileXML( bCompileXML );
+ aComp.CreateStringFromTokenArray( rFormula );
+ }
+ }
+ else
+ {
+ DBG_ERROR("ScFormulaCell::GetEnglishFormula: Keine Matrix");
+ }
+ }
+ else
+ {
+ ScCompiler aComp( pDocument, aPos, *pCode );
+ aComp.SetCompileEnglish( TRUE );
+ aComp.SetCompileXML( bCompileXML );
+ aComp.CreateStringFromTokenArray( rFormula );
+ }
+
+ rFormula.Insert( '=',0 );
+ if( cMatrixFlag )
+ {
+ rFormula.Insert('{', 0);
+ rFormula += '}';
+ }
+}
+
+BOOL ScFormulaCell::IsValue()
+{
+ if (bDirty && pDocument->GetAutoCalc())
+ Interpret();
+ return bIsValue;
+}
+
+double ScFormulaCell::GetValue()
+{
+ if (bDirty && pDocument->GetAutoCalc())
+ Interpret();
+ if ( !pCode->GetError() || pCode->GetError() == errDoubleRef)
+ return nErgValue;
+ return 0.0;
+}
+
+void ScFormulaCell::GetString( String& rString )
+{
+ if (bDirty && pDocument->GetAutoCalc())
+ Interpret();
+ if ( !pCode->GetError() || pCode->GetError() == errDoubleRef)
+ rString = aErgString;
+ else
+ rString.Erase();
+}
+
+void ScFormulaCell::GetMatrix(ScMatrix** ppMat)
+{
+ if ( pDocument->GetAutoCalc() )
+ {
+ // war !bDirty gespeichert aber zugehoerige Matrixzelle bDirty?
+ // => wir brauchen pMatrix
+ if ( !pMatrix && cMatrixFlag == MM_FORMULA )
+ bDirty = TRUE;
+ if ( bDirty )
+ Interpret();
+ }
+ if (!pCode->GetError())
+ *ppMat = pMatrix;
+ else
+ *ppMat = NULL;
+}
+
+BOOL ScFormulaCell::GetMatrixOrigin( ScAddress& rPos ) const
+{
+ switch ( cMatrixFlag )
+ {
+ case MM_FORMULA :
+ rPos = aPos;
+ return TRUE;
+ break;
+ case MM_REFERENCE :
+ {
+ pCode->Reset();
+ ScToken* t = pCode->GetNextReferenceRPN();
+ if( t )
+ {
+ t->aRef.Ref1.CalcAbsIfRel( aPos );
+ if ( t->aRef.Ref1.Valid() )
+ {
+ rPos.Set( t->aRef.Ref1.nCol, t->aRef.Ref1.nRow, t->aRef.Ref1.nTab );
+ return TRUE;
+ }
+ }
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+/*
+ Edge-Values:
+
+ 8
+ 4 16
+ 2
+
+ innerhalb: 1
+ ausserhalb: 0
+ (reserviert: offen: 32)
+ */
+
+USHORT ScFormulaCell::GetMatrixEdge( ScAddress& rOrgPos )
+{
+ switch ( cMatrixFlag )
+ {
+ case MM_FORMULA :
+ case MM_REFERENCE :
+ {
+ static USHORT nC, nR;
+ ScAddress aOrg;
+ if ( !GetMatrixOrigin( aOrg ) )
+ return 0; // dumm gelaufen..
+ if ( aOrg != rOrgPos )
+ { // erstes Mal oder andere Matrix als letztes Mal
+ rOrgPos = aOrg;
+ ScFormulaCell* pFCell;
+ if ( cMatrixFlag == MM_REFERENCE )
+ pFCell = (ScFormulaCell*) pDocument->GetCell( aOrg );
+ else
+ pFCell = this; // this MM_FORMULA
+ // this gibt's nur einmal, kein Vergleich auf pFCell==this
+ if ( pFCell && pFCell->GetCellType() == CELLTYPE_FORMULA
+ && pFCell->cMatrixFlag == MM_FORMULA )
+ {
+ pFCell->GetMatColsRows( nC, nR );
+ if ( nC == 0 || nR == 0 )
+ { // aus altem Dokument geladen, neu erzeugen
+ nC = nR = 1;
+ ScAddress aTmpOrg;
+ ScBaseCell* pCell;
+ ScAddress aAdr( aOrg );
+ aAdr.IncCol();
+ BOOL bCont = TRUE;
+ do
+ {
+ pCell = pDocument->GetCell( aAdr );
+ if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA
+ && ((ScFormulaCell*)pCell)->cMatrixFlag == MM_REFERENCE
+ && GetMatrixOrigin( aTmpOrg ) && aTmpOrg == aOrg )
+ {
+ nC++;
+ aAdr.IncCol();
+ }
+ else
+ bCont = FALSE;
+ } while ( bCont );
+ aAdr = aOrg;
+ aAdr.IncRow();
+ bCont = TRUE;
+ do
+ {
+ pCell = pDocument->GetCell( aAdr );
+ if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA
+ && ((ScFormulaCell*)pCell)->cMatrixFlag == MM_REFERENCE
+ && GetMatrixOrigin( aTmpOrg ) && aTmpOrg == aOrg )
+ {
+ nR++;
+ aAdr.IncRow();
+ }
+ else
+ bCont = FALSE;
+ } while ( bCont );
+ pFCell->SetMatColsRows( nC, nR );
+ }
+ }
+ else
+ return 0; // dumm gelaufen..
+ }
+ // here we are, healthy and clean, somewhere in between
+ short dC = aPos.Col() - aOrg.Col();
+ short dR = aPos.Row() - aOrg.Row();
+ USHORT nEdges = 0;
+ if ( dC >= 0 && dR >= 0 && dC < nC && dR < nR )
+ {
+ if ( dC == 0 )
+ nEdges |= 4; // linke Kante
+ if ( dC+1 == nC )
+ nEdges |= 16; // rechte Kante
+ if ( dR == 0 )
+ nEdges |= 8; // obere Kante
+ if ( dR+1 == nR )
+ nEdges |= 2; // untere Kante
+ if ( !nEdges )
+ nEdges = 1; // mittendrin
+ }
+#ifndef PRODUCT
+ else
+ {
+ String aTmp;
+ ByteString aMsg( "kaputte Matrix, Pos: " );
+ aPos.Format( aTmp, SCA_VALID_COL | SCA_VALID_ROW, pDocument );
+ aMsg += ByteString( aTmp, RTL_TEXTENCODING_ASCII_US );
+ aMsg += ", MatOrg: ";
+ aOrg.Format( aTmp, SCA_VALID_COL | SCA_VALID_ROW, pDocument );
+ aMsg += ByteString( aTmp, RTL_TEXTENCODING_ASCII_US );
+ aMsg += ", MatCols: ";
+ aMsg += nC;
+ aMsg += ", MatRows: ";
+ aMsg += nR;
+ aMsg += ", DiffCols: ";
+ aMsg += dC;
+ aMsg += ", DiffRows: ";
+ aMsg += dR;
+ DBG_ERRORFILE( aMsg.GetBuffer() );
+ }
+#endif
+ return nEdges;
+ break;
+ }
+ default:
+ return 0;
+ }
+}
+
+USHORT ScFormulaCell::GetErrCode()
+{
+ if (bDirty && pDocument->GetAutoCalc())
+ Interpret();
+ return pCode->GetError();
+}
+
+BOOL ScFormulaCell::HasOneReference( ScRange& r ) const
+{
+ pCode->Reset();
+ ScToken* p = pCode->GetNextReferenceRPN();
+ if( p && !pCode->GetNextReferenceRPN() ) // nur eine!
+ {
+ p->aRef.CalcAbsIfRel( aPos );
+ r.aStart.Set( p->aRef.Ref1.nCol,
+ p->aRef.Ref1.nRow,
+ p->aRef.Ref1.nTab );
+ r.aEnd.Set( p->aRef.Ref2.nCol,
+ p->aRef.Ref2.nRow,
+ p->aRef.Ref2.nTab );
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+BOOL ScFormulaCell::HasRelNameReference() const
+{
+ pCode->Reset();
+ for( ScToken* t = pCode->GetNextReferenceRPN(); t;
+ t = pCode->GetNextReferenceRPN() )
+ {
+ if ( t->aRef.Ref1.IsRelName() || t->aRef.Ref2.IsRelName() )
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL ScFormulaCell::HasDBArea() const
+{
+ pCode->Reset();
+ return (pCode->GetNextDBArea() != NULL);
+}
+
+BOOL ScFormulaCell::HasColRowName() const
+{
+ pCode->Reset();
+ return (pCode->GetNextColRowName() != NULL);
+}
+
+void ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode,
+ const ScRange& r,
+ short nDx, short nDy, short nDz,
+ ScDocument* pUndoDoc )
+{
+ BOOL bHasRefs = FALSE;
+ BOOL bOnRefMove = FALSE;
+ if ( !pDocument->IsClipOrUndo() )
+ {
+ pCode->Reset();
+ bHasRefs = (pCode->GetNextReferenceRPN() != NULL);
+ if ( !bHasRefs )
+ {
+ pCode->Reset();
+ bHasRefs = (pCode->GetNextColRowName() != NULL);
+ }
+ bOnRefMove = pCode->IsRecalcModeOnRefMove();
+ }
+ if( bHasRefs || bOnRefMove )
+ {
+ USHORT nCol1 = r.aStart.Col();
+ USHORT nRow1 = r.aStart.Row();
+ USHORT nTab1 = r.aStart.Tab();
+ USHORT nCol2 = r.aEnd.Col();
+ USHORT nRow2 = r.aEnd.Row();
+ USHORT nTab2 = r.aEnd.Tab();
+ USHORT nCol = aPos.Col();
+ USHORT nRow = aPos.Row();
+ USHORT nTab = aPos.Tab();
+ ScAddress aOldPos( aPos );
+// BOOL bPosChanged = FALSE; // ob diese Zelle bewegt wurde
+ ScTokenArray* pOld = pUndoDoc ? pCode->Clone() : NULL;
+ BOOL bIsInsert = FALSE;
+ if (eUpdateRefMode == URM_INSDEL)
+ {
+ bIsInsert = (nDx >= 0 && nDy >= 0 && nDz >= 0);
+ if ( nDx && nRow >= nRow1 && nRow <= nRow2 &&
+ nTab >= nTab1 && nTab <= nTab2 )
+ {
+ if (nCol >= nCol1)
+ {
+ nCol += nDx;
+ if ((short) nCol < 0)
+ nCol = 0;
+ else if ( nCol > MAXCOL )
+ nCol = MAXCOL;
+ aPos.SetCol( nCol );
+// bPosChanged = TRUE;
+ }
+ }
+ if ( nDy && nCol >= nCol1 && nCol <= nCol2 &&
+ nTab >= nTab1 && nTab <= nTab2 )
+ {
+ if (nRow >= nRow1)
+ {
+ nRow += nDy;
+ if ((short) nRow < 0)
+ nRow = 0;
+ else if ( nRow > MAXROW )
+ nRow = MAXROW;
+ aPos.SetRow( nRow );
+// bPosChanged = TRUE;
+ }
+ }
+ if ( nDz && nCol >= nCol1 && nCol <= nCol2 &&
+ nRow >= nRow1 && nRow <= nRow2 )
+ {
+ if (nTab >= nTab1)
+ {
+ USHORT nMaxTab = pDocument->GetTableCount() - 1;
+ nTab += nDz;
+ if ((short) nTab < 0)
+ nTab = 0;
+ else if ( nTab > nMaxTab )
+ nTab = nMaxTab;
+ aPos.SetTab( nTab );
+// bPosChanged = TRUE;
+ }
+ }
+ }
+ else if ( r.In( aPos ) )
+ {
+ aOldPos.Set( nCol - nDx, nRow - nDy, nTab - nDz );
+// bPosChanged = TRUE;
+ }
+
+ BOOL bValChanged;
+ ScRangeData* pRangeData;
+ BOOL bRangeModified; // beliebiger Range (nicht nur shared Formula)
+ if ( bHasRefs )
+ {
+ ScCompiler aComp(pDocument, aPos, *pCode);
+ pRangeData = aComp.UpdateReference(eUpdateRefMode, aOldPos, r,
+ nDx, nDy, nDz,
+ bValChanged);
+ bRangeModified = aComp.HasModifiedRange();
+ }
+ else
+ {
+ bValChanged = FALSE;
+ pRangeData = NULL;
+ bRangeModified = FALSE;
+ }
+ if ( bOnRefMove )
+ bOnRefMove = (bValChanged || (!bHasRefs && aPos != aOldPos));
+ // Zelle referiert sich evtl. selbst, z.B. ocColumn, ocRow ohne Parameter
+
+ BOOL bColRowNameCompile, bHasRelName, bNewListening, bNewRelName,
+ bInDeleteUndo;
+ if ( bHasRefs )
+ {
+ // Bei Insert muessen ColRowNames neu kompiliert werden, falls genau
+ // am Beginn des Bereiches inserted wird.
+ bColRowNameCompile =
+ (eUpdateRefMode == URM_INSDEL && (nDx > 0 || nDy > 0));
+ if ( bColRowNameCompile )
+ {
+ bColRowNameCompile = FALSE;
+ ScToken* t;
+ ScRangePairList* pColList = pDocument->GetColNameRanges();
+ ScRangePairList* pRowList = pDocument->GetRowNameRanges();
+ pCode->Reset();
+ while ( !bColRowNameCompile && (t = pCode->GetNextColRowName()) )
+ {
+ if ( nDy > 0 && t->aRef.Ref1.IsColRel() )
+ { // ColName
+ SingleRefData& rRef = t->aRef.Ref1;
+ rRef.CalcAbsIfRel( aPos );
+ ScAddress aAdr( rRef.nCol, rRef.nRow, rRef.nTab );
+ ScRangePair* pR = pColList->Find( aAdr );
+ if ( pR )
+ { // definiert
+ if ( pR->GetRange(1).aStart.Row() == nRow1 )
+ bColRowNameCompile = TRUE;
+ }
+ else
+ { // on the fly
+ if ( t->aRef.Ref1.nRow + 1 == nRow1 )
+ bColRowNameCompile = TRUE;
+ }
+ }
+ if ( nDx > 0 && t->aRef.Ref1.IsRowRel() )
+ { // RowName
+ SingleRefData& rRef = t->aRef.Ref1;
+ rRef.CalcAbsIfRel( aPos );
+ ScAddress aAdr( rRef.nCol, rRef.nRow, rRef.nTab );
+ ScRangePair* pR = pRowList->Find( aAdr );
+ if ( pR )
+ { // definiert
+ if ( pR->GetRange(1).aStart.Col() == nCol1 )
+ bColRowNameCompile = TRUE;
+ }
+ else
+ { // on the fly
+ if ( t->aRef.Ref1.nCol + 1 == nCol1 )
+ bColRowNameCompile = TRUE;
+ }
+ }
+ }
+ }
+ else if ( eUpdateRefMode == URM_MOVE )
+ { // bei Move/D&D neu kompilieren wenn ColRowName verschoben wurde
+ // oder diese Zelle auf einen zeigt und verschoben wurde
+ bColRowNameCompile = bCompile; // evtl. aus Copy-ctor
+ if ( !bColRowNameCompile )
+ {
+ BOOL bMoved = (aPos != aOldPos);
+ pCode->Reset();
+ ScToken* t = pCode->GetNextColRowName();
+ if ( t && bMoved )
+ bColRowNameCompile = TRUE;
+ while ( t && !bColRowNameCompile )
+ {
+ SingleRefData& rRef = t->aRef.Ref1;
+ rRef.CalcAbsIfRel( aPos );
+ if ( rRef.Valid() )
+ {
+ ScAddress aAdr( rRef.nCol, rRef.nRow, rRef.nTab );
+ if ( r.In( aAdr ) )
+ bColRowNameCompile = TRUE;
+ }
+ t = pCode->GetNextColRowName();
+ }
+ }
+ }
+ ScChangeTrack* pChangeTrack = pDocument->GetChangeTrack();
+ if ( pChangeTrack && pChangeTrack->IsInDeleteUndo() )
+ bInDeleteUndo = TRUE;
+ else
+ bInDeleteUndo = FALSE;
+ // Referenz geaendert und neues Listening noetig?
+ // ausser Insert/Delete ohne Spezialitaeten
+ bNewListening = ( bRangeModified || pRangeData || bColRowNameCompile
+ || (bValChanged && (eUpdateRefMode != URM_INSDEL ||
+ bInDeleteUndo)) );
+ bHasRelName = HasRelNameReference();
+ bNewRelName = (bHasRelName && eUpdateRefMode != URM_COPY);
+ if ( bNewListening )
+ EndListeningTo( pDocument, FALSE, pOld, aOldPos );
+ else if ( bNewRelName )
+ EndListeningTo( pDocument, TRUE, pOld, aOldPos );
+ // RelNameRefs werden immer mitverschoben
+ }
+ else
+ {
+ bColRowNameCompile = bHasRelName = bNewListening = bNewRelName =
+ bInDeleteUndo = FALSE;
+ }
+
+ BOOL bNeedDirty;
+ // NeedDirty bei Aenderungen ausser Copy und Move/Insert ohne RelNames
+ if ( bRangeModified || pRangeData || bColRowNameCompile
+ || (bValChanged && eUpdateRefMode != URM_COPY
+ && (eUpdateRefMode != URM_MOVE || bHasRelName)
+ && (!bIsInsert || bHasRelName || bInDeleteUndo)) || bOnRefMove )
+ bNeedDirty = TRUE;
+ else
+ bNeedDirty = FALSE;
+ if (pUndoDoc && (bValChanged || pRangeData || bOnRefMove))
+ {
+ ScFormulaCell* pFCell = new ScFormulaCell( pUndoDoc, aPos, pOld );
+ pFCell->nErgValue = MINDOUBLE; // damit spaeter changed (Cut/Paste!)
+ pUndoDoc->PutCell( nCol, nRow, nTab, pFCell );
+ }
+ bValChanged = FALSE;
+ if (pRangeData) // Shared Formula gegen echte Formel
+ { // austauschen
+
+// hier wird noch zu oft ausgetauscht. Es muesste noch ein Test implementiert werden,
+// ob diese Zelle mit ihrer Formel wirklich von der Referenzaenderung betroffen ist.
+// (analog in TabInsert und TabDelete).
+
+ pDocument->RemoveFromFormulaTree( this ); // update formula count
+ delete pCode;
+ pCode = pRangeData->GetCode()->Clone();
+ ScCompiler aComp2(pDocument, aPos, *pCode);
+ aComp2.MoveRelWrap();
+ aComp2.UpdateSharedFormulaReference( eUpdateRefMode, aOldPos, r,
+ nDx, nDy, nDz );
+ bValChanged = TRUE;
+ bNeedDirty = TRUE;
+ }
+ if ( ( bCompile = (bCompile || bValChanged || bRangeModified || bColRowNameCompile) ) != 0 )
+ {
+ CompileTokenArray( bNewListening ); // kein Listening
+ bNeedDirty = TRUE;
+ }
+ if ( !bInDeleteUndo )
+ { // bei ChangeTrack Delete-Reject werden in InsertCol/Row die
+ // Listener neu aufgesezt
+ if ( bNewListening )
+ StartListeningTo( pDocument );
+ else if ( bNewRelName && eUpdateRefMode != URM_INSDEL )
+ StartListeningTo( pDocument, TRUE );
+ // bei Insert/Delete RelNameListening/SetDirty erst spaeter
+ }
+ if ( bNeedDirty && (!(eUpdateRefMode == URM_INSDEL && bHasRelName) || pRangeData) )
+ { // Referenzen abgeschnitten, ungueltig o.ae.?
+ BOOL bOldAutoCalc = pDocument->GetAutoCalc();
+ // kein Interpret in SubMinimalRecalc wegen evtl. falscher Referenzen
+ pDocument->SetAutoCalc( FALSE );
+ SetDirty();
+ pDocument->SetAutoCalc( bOldAutoCalc );
+ }
+
+ delete pOld;
+ }
+}
+
+void ScFormulaCell::UpdateInsertTab(USHORT nTable)
+{
+ BOOL bPosChanged = ( aPos.Tab() >= nTable ? TRUE : FALSE );
+ pCode->Reset();
+ if( pCode->GetNextReferenceRPN() && !pDocument->IsClipOrUndo() )
+ {
+ EndListeningTo( pDocument );
+ // IncTab _nach_ EndListeningTo und _vor_ Compiler UpdateInsertTab !
+ if ( bPosChanged )
+ aPos.IncTab();
+ ScRangeData* pRangeData;
+ ScCompiler aComp(pDocument, aPos, *pCode);
+ pRangeData = aComp.UpdateInsertTab( nTable, FALSE );
+ if (pRangeData) // Shared Formula gegen echte Formel
+ { // austauschen
+ BOOL bChanged;
+ pDocument->RemoveFromFormulaTree( this ); // update formula count
+ delete pCode;
+ pCode = new ScTokenArray( *pRangeData->GetCode() );
+ ScCompiler aComp2(pDocument, aPos, *pCode);
+ aComp2.MoveRelWrap();
+ aComp2.UpdateInsertTab( nTable, FALSE );
+ // 13.05.96 16:30 warum DeleteTab nach InsertTab ?!?
+ aComp2.UpdateDeleteTab( nTable, FALSE, TRUE, bChanged );
+ bCompile = TRUE;
+ }
+ // kein StartListeningTo weil pTab[nTab] noch nicht existiert!
+ }
+ else if ( bPosChanged )
+ aPos.IncTab();
+}
+
+BOOL ScFormulaCell::UpdateDeleteTab(USHORT nTable, BOOL bIsMove)
+{
+ BOOL bChanged = FALSE;
+ BOOL bPosChanged = ( aPos.Tab() > nTable ? TRUE : FALSE );
+ pCode->Reset();
+ if( pCode->GetNextReferenceRPN() && !pDocument->IsClipOrUndo() )
+ {
+ EndListeningTo( pDocument );
+ // IncTab _nach_ EndListeningTo und _vor_ Compiler UpdateDeleteTab !
+ if ( bPosChanged )
+ aPos.IncTab(-1);
+ ScRangeData* pRangeData;
+ ScCompiler aComp(pDocument, aPos, *pCode);
+ pRangeData = aComp.UpdateDeleteTab(nTable, bIsMove, FALSE, bChanged);
+ if (pRangeData) // Shared Formula gegen echte Formel
+ { // austauschen
+ pDocument->RemoveFromFormulaTree( this ); // update formula count
+ delete pCode;
+ pCode = pRangeData->GetCode()->Clone();
+ ScCompiler aComp2(pDocument, aPos, *pCode);
+ aComp2.CompileTokenArray();
+ aComp2.MoveRelWrap();
+ aComp2.UpdateDeleteTab( nTable, FALSE, FALSE, bChanged );
+ // 13.05.96 16:30 warum InsertTab nach DeleteTab ?!?
+ aComp2.UpdateInsertTab( nTable,TRUE );
+ // bChanged kann beim letzten UpdateDeleteTab zurueckgesetzt worden sein
+ bChanged = TRUE;
+ bCompile = TRUE;
+ }
+ // kein StartListeningTo weil pTab[nTab] noch nicht korrekt!
+ }
+ else if ( bPosChanged )
+ aPos.IncTab(-1);
+
+ return bChanged;
+}
+
+void ScFormulaCell::UpdateMoveTab( USHORT nOldPos, USHORT nNewPos, USHORT nTabNo )
+{
+ pCode->Reset();
+ if( pCode->GetNextReferenceRPN() && !pDocument->IsClipOrUndo() )
+ {
+ EndListeningTo( pDocument );
+ // SetTab _nach_ EndListeningTo und _vor_ Compiler UpdateMoveTab !
+ aPos.SetTab( nTabNo );
+ ScRangeData* pRangeData;
+ ScCompiler aComp(pDocument, aPos, *pCode);
+ pRangeData = aComp.UpdateMoveTab( nOldPos, nNewPos, FALSE );
+ if (pRangeData) // Shared Formula gegen echte Formel
+ { // austauschen
+ pDocument->RemoveFromFormulaTree( this ); // update formula count
+ delete pCode;
+ pCode = pRangeData->GetCode()->Clone();
+ ScCompiler aComp2(pDocument, aPos, *pCode);
+ aComp2.CompileTokenArray();
+ aComp2.MoveRelWrap();
+ aComp2.UpdateMoveTab( nOldPos, nNewPos, TRUE );
+ bCompile = TRUE;
+ }
+ // kein StartListeningTo weil pTab[nTab] noch nicht korrekt!
+ }
+ else
+ aPos.SetTab( nTabNo );
+}
+
+void ScFormulaCell::UpdateInsertTabAbs(USHORT nTable)
+{
+ if( !pDocument->IsClipOrUndo() )
+ {
+ pCode->Reset();
+ ScToken* p = pCode->GetNextReferenceRPN();
+ while( p )
+ {
+ if( !p->aRef.Ref1.IsTabRel() && (short) nTable <= p->aRef.Ref1.nTab )
+ p->aRef.Ref1.nTab++;
+ if( p->GetType() == svDoubleRef )
+ {
+ if( !p->aRef.Ref2.IsTabRel() && (short) nTable <= p->aRef.Ref2.nTab )
+ p->aRef.Ref2.nTab++;
+ }
+ else
+ p->aRef.Ref2.nTab = p->aRef.Ref1.nTab;
+ p = pCode->GetNextReferenceRPN();
+ }
+ }
+}
+
+BOOL ScFormulaCell::TestTabRefAbs(USHORT nTable)
+{
+ BOOL bRet = FALSE;
+ if( !pDocument->IsClipOrUndo() )
+ {
+ pCode->Reset();
+ ScToken* p = pCode->GetNextReferenceRPN();
+ while( p )
+ {
+ if( !p->aRef.Ref1.IsTabRel() )
+ {
+ if( (short) nTable != p->aRef.Ref1.nTab )
+ bRet = TRUE;
+ else if (nTable != aPos.Tab())
+ p->aRef.Ref1.nTab = aPos.Tab();
+ }
+ if( p->GetType() == svDoubleRef )
+ {
+ if( !p->aRef.Ref2.IsTabRel() )
+ {
+ if( (short)nTable != p->aRef.Ref1.nTab )
+ bRet = TRUE;
+ else if (nTable != aPos.Tab())
+ p->aRef.Ref2.nTab = aPos.Tab();
+ }
+ }
+ else
+ p->aRef.Ref2.nTab = p->aRef.Ref1.nTab;
+ p = pCode->GetNextReferenceRPN();
+ }
+ }
+ return bRet;
+}
+
+void ScFormulaCell::UpdateCompile( BOOL bForceIfNameInUse )
+{
+ if ( bForceIfNameInUse && !bCompile )
+ bCompile = pCode->HasName();
+ if ( bCompile )
+ pCode->SetError( 0 ); // damit auch wirklich kompiliert wird
+ CompileTokenArray();
+}
+
+// Referenzen transponieren - wird nur in Clipboard-Dokumenten aufgerufen
+
+void ScFormulaCell::TransposeReference()
+{
+ BOOL bFound = FALSE;
+ pCode->Reset();
+ for( ScToken* t = pCode->GetNextReference(); t;
+ t = pCode->GetNextReference() )
+ {
+ if ( t->aRef.Ref1.IsColRel() && t->aRef.Ref1.IsRowRel() &&
+ t->aRef.Ref2.IsColRel() && t->aRef.Ref2.IsRowRel() )
+ {
+ INT16 nTemp;
+
+ nTemp = t->aRef.Ref1.nRelCol;
+ t->aRef.Ref1.nRelCol = t->aRef.Ref1.nRelRow;
+ t->aRef.Ref1.nRelRow = nTemp;
+
+ nTemp = t->aRef.Ref2.nRelCol;
+ t->aRef.Ref2.nRelCol = t->aRef.Ref2.nRelRow;
+ t->aRef.Ref2.nRelRow = nTemp;
+
+ bFound = TRUE;
+ }
+ }
+
+ if (bFound)
+ bCompile = TRUE;
+}
+
+void ScFormulaCell::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
+ ScDocument* pUndoDoc )
+{
+ EndListeningTo( pDocument );
+
+ ScAddress aOldPos = aPos;
+ BOOL bPosChanged = FALSE; // ob diese Zelle bewegt wurde
+
+ ScRange aDestRange( rDest, ScAddress(
+ rDest.Col() + rSource.aEnd.Row() - rSource.aStart.Row(),
+ rDest.Row() + rSource.aEnd.Col() - rSource.aStart.Col(),
+ rDest.Tab() + rSource.aEnd.Tab() - rSource.aStart.Tab() ) );
+ if ( aDestRange.In( aOldPos ) )
+ {
+ // Position zurueckrechnen
+ short nRelPosX = aOldPos.Col();
+ short nRelPosY = aOldPos.Row();
+ short nRelPosZ = aOldPos.Tab();
+ ScRefUpdate::DoTranspose( nRelPosX, nRelPosY, nRelPosZ, pDocument, aDestRange, rSource.aStart );
+ aOldPos.Set( nRelPosX, nRelPosY, nRelPosZ );
+ bPosChanged = TRUE;
+ }
+
+ ScTokenArray* pOld = pUndoDoc ? pCode->Clone() : NULL;
+ BOOL bChanged = FALSE;
+ ScToken* t;
+
+ ScRangeData* pShared = NULL;
+ pCode->Reset();
+ for( t = pCode->GetNextReferenceOrName(); t; t = pCode->GetNextReferenceOrName() )
+ {
+ if( t->GetOpCode() == ocName )
+ {
+ ScRangeData* pName = pDocument->GetRangeName()->FindIndex( t->nIndex );
+ if (pName)
+ {
+ if (pName->IsModified())
+ bChanged = TRUE;
+ if (pName->HasType(RT_SHAREDMOD))
+ pShared = pName;
+ }
+ }
+ else if( t->GetType() != svIndex )
+ {
+ t->aRef.CalcAbsIfRel( aOldPos );
+ if ( ScRefUpdate::UpdateTranspose( pDocument, rSource, rDest, t->aRef ) != UR_NOTHING
+ || bPosChanged )
+ {
+ t->aRef.CalcRelFromAbs( aPos );
+ bChanged = TRUE;
+ }
+ }
+ }
+
+ if (pShared) // Shared Formula gegen echte Formel austauschen
+ {
+ pDocument->RemoveFromFormulaTree( this ); // update formula count
+ delete pCode;
+ pCode = new ScTokenArray( *pShared->GetCode() );
+ bChanged = TRUE;
+ pCode->Reset();
+ for( t = pCode->GetNextReference(); t; t = pCode->GetNextReference() )
+ {
+ if( t->GetType() != svIndex )
+ {
+ t->aRef.CalcAbsIfRel( aOldPos );
+ if ( ScRefUpdate::UpdateTranspose( pDocument, rSource, rDest, t->aRef ) != UR_NOTHING
+ || bPosChanged )
+ {
+ t->aRef.CalcRelFromAbs( aPos );
+ }
+ }
+ }
+ }
+
+ if (bChanged)
+ {
+ if (pUndoDoc)
+ {
+ ScFormulaCell* pFCell = new ScFormulaCell( pUndoDoc, aPos, pOld );
+ pFCell->nErgValue = MINDOUBLE; // damit spaeter changed (Cut/Paste!)
+ pUndoDoc->PutCell( aPos.Col(), aPos.Row(), aPos.Tab(), pFCell );
+ }
+
+ bCompile = TRUE;
+ CompileTokenArray(); // ruft auch StartListeningTo
+ SetDirty();
+ }
+ else
+ StartListeningTo( pDocument ); // Listener wie vorher
+
+ delete pOld;
+}
+
+void ScFormulaCell::UpdateGrow( const ScRange& rArea, USHORT nGrowX, USHORT nGrowY )
+{
+ EndListeningTo( pDocument );
+
+ BOOL bChanged = FALSE;
+ ScToken* t;
+ ScRangeData* pShared = NULL;
+
+ pCode->Reset();
+ for( t = pCode->GetNextReferenceOrName(); t; t = pCode->GetNextReferenceOrName() )
+ {
+ if( t->GetOpCode() == ocName )
+ {
+ ScRangeData* pName = pDocument->GetRangeName()->FindIndex( t->nIndex );
+ if (pName)
+ {
+ if (pName->IsModified())
+ bChanged = TRUE;
+ if (pName->HasType(RT_SHAREDMOD))
+ pShared = pName;
+ }
+ }
+ else if( t->GetType() != svIndex )
+ {
+ t->aRef.CalcAbsIfRel( aPos );
+ if ( ScRefUpdate::UpdateGrow( rArea,nGrowX,nGrowY, t->aRef ) != UR_NOTHING )
+ {
+ t->aRef.CalcRelFromAbs( aPos );
+ bChanged = TRUE;
+ }
+ }
+ }
+
+ if (pShared) // Shared Formula gegen echte Formel austauschen
+ {
+ pDocument->RemoveFromFormulaTree( this ); // update formula count
+ delete pCode;
+ pCode = new ScTokenArray( *pShared->GetCode() );
+ bChanged = TRUE;
+ pCode->Reset();
+ for( t = pCode->GetNextReference(); t; t = pCode->GetNextReference() )
+ {
+ if( t->GetType() != svIndex )
+ {
+ t->aRef.CalcAbsIfRel( aPos );
+ if ( ScRefUpdate::UpdateGrow( rArea,nGrowX,nGrowY, t->aRef ) != UR_NOTHING )
+ t->aRef.CalcRelFromAbs( aPos );
+ }
+ }
+ }
+
+ if (bChanged)
+ {
+ bCompile = TRUE;
+ CompileTokenArray(); // ruft auch StartListeningTo
+ SetDirty();
+ }
+ else
+ StartListeningTo( pDocument ); // Listener wie vorher
+}
+
+BOOL lcl_IsRangeNameInUse(USHORT nIndex, ScTokenArray* pCode, ScRangeName* pNames)
+{
+ for (ScToken* p = pCode->First(); p; p = pCode->Next())
+ {
+ if (p->GetOpCode() == ocName)
+ {
+ if (p->nIndex == nIndex)
+ return TRUE;
+ else
+ {
+ // RangeData kann Null sein in bestimmten Excel-Dateien (#31168#)
+ ScRangeData* pSubName = pNames->FindIndex(p->nIndex);
+ if (pSubName && lcl_IsRangeNameInUse(nIndex,
+ pSubName->GetCode(), pNames))
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+BOOL ScFormulaCell::IsRangeNameInUse(USHORT nIndex) const
+{
+ return lcl_IsRangeNameInUse( nIndex, pCode, pDocument->GetRangeName() );
+}
+
+void ScFormulaCell::ReplaceRangeNamesInUse( const ScIndexMap& rMap )
+{
+ for( ScToken* p = pCode->First(); p; p = pCode->Next() )
+ {
+ if( p->GetOpCode() == ocName )
+ {
+ USHORT nNewIndex = rMap.Find( p->nIndex );
+ if ( p->nIndex != nNewIndex )
+ {
+ p->nIndex = nNewIndex;
+ bCompile = TRUE;
+ }
+ }
+ }
+ if( bCompile )
+ CompileTokenArray();
+}
+
+void ScFormulaCell::CompileDBFormula()
+{
+ for( ScToken* p = pCode->First(); p; p = pCode->Next() )
+ {
+ if ( p->GetOpCode() == ocDBArea
+ || (p->GetOpCode() == ocName && p->nIndex >= SC_START_INDEX_DB_COLL) )
+ {
+ bCompile = TRUE;
+ CompileTokenArray();
+ SetDirty();
+ break;
+ }
+ }
+}
+
+void ScFormulaCell::CompileDBFormula( BOOL bCreateFormulaString )
+{
+ // zwei Phasen, muessen (!) nacheinander aufgerufen werden:
+ // 1. FormelString mit alten Namen erzeugen
+ // 2. FormelString mit neuen Namen kompilieren
+ if ( bCreateFormulaString )
+ {
+ BOOL bRecompile = FALSE;
+ pCode->Reset();
+ for ( ScToken* p = pCode->First(); p && !bRecompile; p = pCode->Next() )
+ {
+ switch ( p->GetOpCode() )
+ {
+ case ocBad: // DB-Bereich evtl. zugefuegt
+ case ocColRowName: // #36762# falls Namensgleichheit
+ case ocDBArea: // DB-Bereich
+ bRecompile = TRUE;
+ break;
+ case ocName:
+ if ( p->nIndex >= SC_START_INDEX_DB_COLL )
+ bRecompile = TRUE; // DB-Bereich
+ }
+ }
+ if ( bRecompile )
+ {
+ String aFormula;
+ GetFormula( aFormula );
+ if ( GetMatrixFlag() != MM_NONE && aFormula.Len() )
+ {
+ if ( aFormula.GetChar( aFormula.Len()-1 ) == '}' )
+ aFormula.Erase( aFormula.Len()-1 , 1 );
+ if ( aFormula.GetChar(0) == '{' )
+ aFormula.Erase( 0, 1 );
+ }
+ EndListeningTo( pDocument );
+ pDocument->RemoveFromFormulaTree( this );
+ pCode->Clear();
+ aErgString = aFormula;
+ }
+ }
+ else if ( !pCode->GetLen() && aErgString.Len() )
+ {
+ Compile( aErgString );
+ aErgString.Erase();
+ SetDirty();
+ }
+}
+
+void ScFormulaCell::CompileNameFormula( BOOL bCreateFormulaString )
+{
+ // zwei Phasen, muessen (!) nacheinander aufgerufen werden:
+ // 1. FormelString mit alten RangeNames erzeugen
+ // 2. FormelString mit neuen RangeNames kompilieren
+ if ( bCreateFormulaString )
+ {
+ BOOL bRecompile = FALSE;
+ pCode->Reset();
+ for ( ScToken* p = pCode->First(); p && !bRecompile; p = pCode->Next() )
+ {
+ switch ( p->GetOpCode() )
+ {
+ case ocBad: // RangeName evtl. zugefuegt
+ case ocColRowName: // #36762# falls Namensgleichheit
+ bRecompile = TRUE;
+ break;
+ default:
+ if ( p->GetType() == svIndex )
+ bRecompile = TRUE; // RangeName
+ }
+ }
+ if ( bRecompile )
+ {
+ String aFormula;
+ GetFormula( aFormula );
+ if ( GetMatrixFlag() != MM_NONE && aFormula.Len() )
+ {
+ if ( aFormula.GetChar( aFormula.Len()-1 ) == '}' )
+ aFormula.Erase( aFormula.Len()-1 , 1 );
+ if ( aFormula.GetChar(0) == '{' )
+ aFormula.Erase( 0, 1 );
+ }
+ EndListeningTo( pDocument );
+ pDocument->RemoveFromFormulaTree( this );
+ pCode->Clear();
+ aErgString = aFormula;
+ }
+ }
+ else if ( !pCode->GetLen() && aErgString.Len() )
+ {
+ Compile( aErgString );
+ aErgString.Erase();
+ SetDirty();
+ }
+}
+
+void ScFormulaCell::CompileColRowNameFormula()
+{
+ pCode->Reset();
+ for ( ScToken* p = pCode->First(); p; p = pCode->Next() )
+ {
+ if ( p->GetOpCode() == ocColRowName )
+ {
+ bCompile = TRUE;
+ CompileTokenArray();
+ SetDirty();
+ break;
+ }
+ }
+}
+
+ScValueCell::ScValueCell( SvStream& rStream, USHORT nVer ) :
+ ScBaseCell( CELLTYPE_VALUE )
+{
+ if( nVer >= SC_DATABYTES2 )
+ {
+ BYTE cData;
+ rStream >> cData;
+ if( cData & 0x0F )
+ rStream.SeekRel( cData & 0x0F );
+ }
+ rStream >> aValue;
+}
+
+void ScValueCell::Save( SvStream& rStream ) const
+{
+ rStream << (BYTE) 0x00 << aValue;
+}
+
+ScStringCell::ScStringCell( SvStream& rStream, USHORT nVer ) :
+ ScBaseCell( CELLTYPE_STRING )
+{
+ if( nVer >= SC_DATABYTES2 )
+ {
+ BYTE cData;
+ rStream >> cData;
+ if( cData & 0x0F )
+ rStream.SeekRel( cData & 0x0F );
+ }
+ rStream.ReadByteString( aString, rStream.GetStreamCharSet() );
+}
+
+void ScStringCell::Save( SvStream& rStream ) const
+{
+ rStream << (BYTE) 0x00;
+ rStream.WriteByteString( aString, rStream.GetStreamCharSet() );
+}
+
+ScNoteCell::ScNoteCell( SvStream& rStream, USHORT nVer ) :
+ ScBaseCell( CELLTYPE_NOTE )
+{
+ if( nVer >= SC_DATABYTES2 )
+ {
+ BYTE cData;
+ rStream >> cData;
+ if( cData & 0x0F )
+ rStream.SeekRel( cData & 0x0F );
+ }
+}
+
+void ScNoteCell::Save( SvStream& rStream ) const
+{
+ rStream << (BYTE) 0x00;
+}
+
+
+
+
+
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
new file mode 100644
index 000000000000..d3a4c3815779
--- /dev/null
+++ b/sc/source/core/data/column.cxx
@@ -0,0 +1,2060 @@
+/*************************************************************************
+ *
+ * $RCSfile: column.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <svtools/poolcach.hxx>
+#include <svtools/zforlist.hxx>
+#include <string.h>
+
+#include "scitems.hxx"
+#include "column.hxx"
+#include "cell.hxx"
+#include "document.hxx"
+#include "docpool.hxx"
+#include "attarray.hxx"
+#include "patattr.hxx"
+#include "compiler.hxx"
+#include "brdcst.hxx"
+#include "markdata.hxx"
+
+//#pragma optimize ( "", off )
+// nur Search ohne Optimierung!
+
+// STATIC DATA -----------------------------------------------------------
+
+
+inline BOOL CellVisible( const ScBaseCell* pCell ) //! an Zelle verschieben
+{
+ return ( pCell->GetCellType() != CELLTYPE_NOTE || pCell->GetNotePtr() );
+}
+
+// -----------------------------------------------------------------------------------------
+
+
+ScColumn::ScColumn() :
+ nCol( 0 ),
+ nCount( 0 ),
+ nLimit( 0 ),
+ pItems( NULL ),
+ pDocument( NULL ),
+ pAttrArray( NULL )
+{
+}
+
+
+ScColumn::~ScColumn()
+{
+ FreeAll();
+ if (pAttrArray) delete pAttrArray;
+}
+
+
+void ScColumn::Init(USHORT nNewCol, USHORT nNewTab, ScDocument* pDoc)
+{
+ nCol = nNewCol;
+ nTab = nNewTab;
+ pDocument = pDoc;
+ pAttrArray = new ScAttrArray( nCol, nTab, pDocument );
+}
+
+
+short ScColumn::GetNextUnprotected( short nRow, BOOL bUp ) const
+{
+ return pAttrArray->GetNextUnprotected(nRow, bUp);
+}
+
+
+USHORT ScColumn::GetBlockMatrixEdges( USHORT nRow1, USHORT nRow2, USHORT nMask ) const
+{
+ // nix:0, mitte:1, unten:2, links:4, oben:8, rechts:16, offen:32
+ if ( !pItems )
+ return 0;
+ if ( nRow1 == nRow2 )
+ {
+ USHORT nIndex;
+ if ( Search( nRow1, nIndex ) )
+ {
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA
+ && ((ScFormulaCell*)pCell)->GetMatrixFlag() )
+ {
+ ScAddress aOrg( (UINT32)0xFFFFFFFF );
+ return ((ScFormulaCell*)pCell)->GetMatrixEdge( aOrg );
+ }
+ }
+ return 0;
+ }
+ else
+ {
+ ScAddress aOrg( (UINT32)0xFFFFFFFF );
+ BOOL bOpen = FALSE;
+ USHORT nEdges = 0;
+ USHORT nIndex;
+ Search( nRow1, nIndex );
+ while ( nIndex < nCount && pItems[nIndex].nRow <= nRow2 )
+ {
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA
+ && ((ScFormulaCell*)pCell)->GetMatrixFlag() )
+ {
+ nEdges = ((ScFormulaCell*)pCell)->GetMatrixEdge( aOrg );
+ if ( nEdges )
+ {
+ if ( nEdges & 8 )
+ bOpen = TRUE; // obere Kante oeffnet, weitersehen
+ else if ( !bOpen )
+ return nEdges | 32; // es gibt was, was nicht geoeffnet wurde
+ else if ( nEdges & 1 )
+ return nEdges; // mittendrin
+ // (nMask & 16 und (4 und nicht 16)) oder
+ // (nMask & 4 und (16 und nicht 4))
+ if ( ((nMask & 16) && (nEdges & 4) && !(nEdges & 16))
+ || ((nMask & 4) && (nEdges & 16) && !(nEdges & 4)) )
+ return nEdges; // nur linke/rechte Kante
+ if ( nEdges & 2 )
+ bOpen = FALSE; // untere Kante schliesst
+ }
+ }
+ nIndex++;
+ }
+ if ( bOpen )
+ nEdges |= 32; // es geht noch weiter
+ return nEdges;
+ }
+}
+
+
+BOOL ScColumn::HasSelectionMatrixFragment(const ScMarkData& rMark) const
+{
+ if ( rMark.IsMultiMarked() )
+ {
+ BOOL bFound = FALSE;
+
+ ScAddress aOrg( (UINT32)0xFFFFFFFF );
+ ScAddress aCurOrg( (UINT32)0xFFFFFFFF );
+ USHORT nTop, nBottom;
+ ScMarkArrayIter aMarkIter( rMark.GetArray()+nCol );
+ while ( !bFound && aMarkIter.Next( nTop, nBottom ) )
+ {
+ BOOL bOpen = FALSE;
+ USHORT nEdges;
+ USHORT nIndex;
+ Search( nTop, nIndex );
+ while ( !bFound && nIndex < nCount && pItems[nIndex].nRow <= nBottom )
+ {
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA
+ && ((ScFormulaCell*)pCell)->GetMatrixFlag() )
+ {
+ nEdges = ((ScFormulaCell*)pCell)->GetMatrixEdge( aOrg );
+ if ( nEdges )
+ {
+ if ( nEdges & 8 )
+ bOpen = TRUE; // obere Kante oeffnet, weitersehen
+ else if ( !bOpen )
+ return TRUE; // es gibt was, was nicht geoeffnet wurde
+ else if ( nEdges & 1 )
+ bFound = TRUE; // mittendrin, alles selektiert?
+ // (4 und nicht 16) oder (16 und nicht 4)
+ if ( (((nEdges & 4) | 16) ^ ((nEdges & 16) | 4)) )
+ bFound = TRUE; // nur linke/rechte Kante, alles selektiert?
+ if ( nEdges & 2 )
+ bOpen = FALSE; // untere Kante schliesst
+
+ if ( bFound )
+ { // alles selektiert?
+ if ( aCurOrg != aOrg )
+ { // neue Matrix zu pruefen?
+ aCurOrg = aOrg;
+ ScFormulaCell* pFCell;
+ if ( ((ScFormulaCell*)pCell)->GetMatrixFlag()
+ == MM_REFERENCE )
+ pFCell = (ScFormulaCell*) pDocument->GetCell( aOrg );
+ else
+ pFCell = (ScFormulaCell*)pCell;
+ USHORT nC, nR;
+ pFCell->GetMatColsRows( nC, nR );
+ ScRange aRange( aOrg, ScAddress(
+ aOrg.Col() + nC - 1, aOrg.Row() + nR - 1,
+ aOrg.Tab() ) );
+ if ( rMark.IsAllMarked( aRange ) )
+ bFound = FALSE;
+ }
+ else
+ bFound = FALSE; // war schon
+ }
+ }
+ }
+ nIndex++;
+ }
+ if ( bOpen )
+ return TRUE;
+ }
+ return bFound;
+ }
+ else
+ return FALSE;
+}
+
+
+BOOL ScColumn::HasLines( USHORT nRow1, USHORT nRow2, Rectangle& rSizes,
+ BOOL bLeft, BOOL bRight ) const
+{
+ return pAttrArray->HasLines( nRow1, nRow2, rSizes, bLeft, bRight );
+}
+
+
+BOOL ScColumn::HasAttrib( USHORT nRow1, USHORT nRow2, USHORT nMask ) const
+{
+ return pAttrArray->HasAttrib( nRow1, nRow2, nMask );
+}
+
+
+BOOL ScColumn::HasAttribSelection( const ScMarkData& rMark, USHORT nMask ) const
+{
+ BOOL bFound = FALSE;
+
+ USHORT nTop;
+ USHORT nBottom;
+
+ if (rMark.IsMultiMarked())
+ {
+ ScMarkArrayIter aMarkIter( rMark.GetArray()+nCol );
+ while (aMarkIter.Next( nTop, nBottom ) && !bFound)
+ {
+ if (pAttrArray->HasAttrib( nTop, nBottom, nMask ))
+ bFound = TRUE;
+ }
+ }
+
+ return bFound;
+}
+
+
+BOOL ScColumn::ExtendMerge( USHORT nThisCol, USHORT nStartRow, USHORT nEndRow,
+ USHORT& rPaintCol, USHORT& rPaintRow,
+ BOOL bRefresh, BOOL bAttrs )
+{
+ return pAttrArray->ExtendMerge( nThisCol, nStartRow, nEndRow, rPaintCol, rPaintRow, bRefresh, bAttrs );
+}
+
+
+void ScColumn::MergeSelectionPattern( SfxItemSet** ppSet, const ScMarkData& rMark, BOOL bDeep ) const
+{
+ USHORT nTop;
+ USHORT nBottom;
+
+ if ( rMark.IsMultiMarked() )
+ {
+ ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
+ while (aMarkIter.Next( nTop, nBottom ))
+ pAttrArray->MergePatternArea( nTop, nBottom, ppSet, bDeep );
+ }
+}
+
+
+void ScColumn::MergePatternArea( SfxItemSet** ppSet, USHORT nRow1, USHORT nRow2, BOOL bDeep ) const
+{
+ pAttrArray->MergePatternArea( nRow1, nRow2, ppSet, bDeep );
+}
+
+
+void ScColumn::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner,
+ ScLineFlags& rFlags,
+ USHORT nStartRow, USHORT nEndRow, BOOL bLeft, USHORT nDistRight ) const
+{
+ pAttrArray->MergeBlockFrame( pLineOuter, pLineInner, rFlags, nStartRow, nEndRow, bLeft, nDistRight );
+}
+
+
+void ScColumn::ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInfoItem* pLineInner,
+ USHORT nStartRow, USHORT nEndRow, BOOL bLeft, USHORT nDistRight )
+{
+ pAttrArray->ApplyBlockFrame( pLineOuter, pLineInner, nStartRow, nEndRow, bLeft, nDistRight );
+}
+
+
+const ScPatternAttr* ScColumn::GetPattern( USHORT nRow ) const
+{
+ return pAttrArray->GetPattern( nRow );
+}
+
+
+const SfxPoolItem* ScColumn::GetAttr( USHORT nRow, USHORT nWhich ) const
+{
+ return &pAttrArray->GetPattern( nRow )->GetItemSet().Get(nWhich);
+}
+
+
+ULONG ScColumn::GetNumberFormat( USHORT nRow ) const
+{
+ return pAttrArray->GetPattern( nRow )->GetNumberFormat( pDocument->GetFormatTable() );
+}
+
+
+short ScColumn::ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark )
+{
+ USHORT nTop;
+ USHORT nBottom;
+ BOOL bFound = FALSE;
+
+ if ( rMark.IsMultiMarked() )
+ {
+ ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
+ while (aMarkIter.Next( nTop, nBottom ))
+ {
+ pAttrArray->ApplyCacheArea( nTop, nBottom, pCache );
+ bFound = TRUE;
+ }
+ }
+
+ if (!bFound)
+ return -1;
+ else if (nTop==0 && nBottom==MAXROW)
+ return 0;
+ else
+ return (short) nBottom;
+}
+
+
+void ScColumn::ChangeSelectionIndent( BOOL bIncrement, const ScMarkData& rMark )
+{
+ USHORT nTop;
+ USHORT nBottom;
+
+ if ( pAttrArray && rMark.IsMultiMarked() )
+ {
+ ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
+ while (aMarkIter.Next( nTop, nBottom ))
+ pAttrArray->ChangeIndent(nTop, nBottom, bIncrement);
+ }
+}
+
+
+void ScColumn::ClearSelectionItems( const USHORT* pWhich,const ScMarkData& rMark )
+{
+ USHORT nTop;
+ USHORT nBottom;
+
+ if ( pAttrArray && rMark.IsMultiMarked() )
+ {
+ ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
+ while (aMarkIter.Next( nTop, nBottom ))
+ pAttrArray->ClearItems(nTop, nBottom, pWhich);
+ }
+}
+
+
+void ScColumn::DeleteSelection( USHORT nDelFlag, const ScMarkData& rMark )
+{
+ USHORT nTop;
+ USHORT nBottom;
+
+ if ( rMark.IsMultiMarked() )
+ {
+ ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
+ while (aMarkIter.Next( nTop, nBottom ))
+ DeleteArea(nTop, nBottom, nDelFlag);
+ }
+}
+
+
+void ScColumn::ApplyPattern( USHORT nRow, const ScPatternAttr& rPatAttr )
+{
+ const SfxItemSet* pSet = &rPatAttr.GetItemSet();
+ SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
+
+ const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );
+
+ // TRUE = alten Eintrag behalten
+
+ ScPatternAttr* pNewPattern = (ScPatternAttr*) &aCache.ApplyTo( *pPattern, TRUE );
+ ScDocumentPool::CheckRef( *pPattern );
+ ScDocumentPool::CheckRef( *pNewPattern );
+
+ if (pNewPattern != pPattern)
+ pAttrArray->SetPattern( nRow, pNewPattern );
+}
+
+
+void ScColumn::ApplyPatternArea( USHORT nStartRow, USHORT nEndRow, const ScPatternAttr& rPatAttr )
+{
+ const SfxItemSet* pSet = &rPatAttr.GetItemSet();
+ SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
+ pAttrArray->ApplyCacheArea( nStartRow, nEndRow, &aCache );
+}
+
+
+void ScColumn::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
+ const ScPatternAttr& rPattern, short nNewType )
+{
+ const SfxItemSet* pSet = &rPattern.GetItemSet();
+ SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
+ SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
+ USHORT nEndRow = rRange.aEnd.Row();
+ for ( USHORT nRow = rRange.aStart.Row(); nRow <= nEndRow; nRow++ )
+ {
+ USHORT nRow1, nRow2;
+ const ScPatternAttr* pPattern = pAttrArray->GetPatternRange(
+ nRow1, nRow2, nRow );
+ ULONG nFormat = pPattern->GetNumberFormat( pFormatter );
+ short nOldType = pFormatter->GetType( nFormat );
+ if ( nOldType == nNewType || pFormatter->IsCompatible( nOldType, nNewType ) )
+ nRow = nRow2;
+ else
+ {
+ USHORT nNewRow1 = Max( nRow1, nRow );
+ USHORT nNewRow2 = Min( nRow2, nEndRow );
+ pAttrArray->ApplyCacheArea( nNewRow1, nNewRow2, &aCache );
+ nRow = nNewRow2;
+ }
+ }
+}
+
+
+void ScColumn::ApplyStyle( USHORT nRow, const ScStyleSheet& rStyle )
+{
+ const ScPatternAttr* pPattern = pAttrArray->GetPattern(nRow);
+ ScPatternAttr* pNewPattern = new ScPatternAttr(*pPattern);
+ if (pNewPattern)
+ {
+ pNewPattern->SetStyleSheet((ScStyleSheet*)&rStyle);
+ pAttrArray->SetPattern(nRow, pNewPattern, TRUE);
+ delete pNewPattern;
+ }
+}
+
+
+void ScColumn::ApplyStyleArea( USHORT nStartRow, USHORT nEndRow, const ScStyleSheet& rStyle )
+{
+ pAttrArray->ApplyStyleArea(nStartRow, nEndRow, (ScStyleSheet*)&rStyle);
+}
+
+
+void ScColumn::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
+{
+ USHORT nTop;
+ USHORT nBottom;
+
+ if ( rMark.IsMultiMarked() )
+ {
+ ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
+ while (aMarkIter.Next( nTop, nBottom ))
+ pAttrArray->ApplyStyleArea(nTop, nBottom, (ScStyleSheet*)&rStyle);
+ }
+}
+
+
+void ScColumn::ApplySelectionLineStyle( const ScMarkData& rMark,
+ const SvxBorderLine* pLine, BOOL bColorOnly )
+{
+ if ( bColorOnly && !pLine )
+ return;
+
+ USHORT nTop;
+ USHORT nBottom;
+
+ if (rMark.IsMultiMarked())
+ {
+ ScMarkArrayIter aMarkIter( rMark.GetArray()+nCol );
+ while (aMarkIter.Next( nTop, nBottom ))
+ pAttrArray->ApplyLineStyleArea(nTop, nBottom, pLine, bColorOnly );
+ }
+}
+
+
+const ScStyleSheet* ScColumn::GetStyle( USHORT nRow ) const
+{
+ return pAttrArray->GetPattern( nRow )->GetStyleSheet();
+}
+
+
+const ScStyleSheet* ScColumn::GetSelectionStyle( const ScMarkData& rMark, BOOL& rFound ) const
+{
+ rFound = FALSE;
+ if (!rMark.IsMultiMarked())
+ {
+ DBG_ERROR("ScColumn::GetSelectionStyle ohne Selektion");
+ return NULL;
+ }
+
+ BOOL bEqual = TRUE;
+
+ const ScStyleSheet* pStyle = NULL;
+ const ScStyleSheet* pNewStyle;
+
+ ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
+ USHORT nTop;
+ USHORT nBottom;
+ while (bEqual && aMarkIter.Next( nTop, nBottom ))
+ {
+ ScAttrIterator aAttrIter( pAttrArray, nTop, nBottom );
+ USHORT nRow;
+ USHORT nDummy;
+ const ScPatternAttr* pPattern;
+ while (bEqual && ( pPattern = aAttrIter.Next( nRow, nDummy ) ))
+ {
+ pNewStyle = pPattern->GetStyleSheet();
+ rFound = TRUE;
+ if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
+ bEqual = FALSE; // unterschiedliche
+ pStyle = pNewStyle;
+ }
+ }
+
+ return bEqual ? pStyle : NULL;
+}
+
+
+const ScStyleSheet* ScColumn::GetAreaStyle( BOOL& rFound, USHORT nRow1, USHORT nRow2 ) const
+{
+ rFound = FALSE;
+
+ BOOL bEqual = TRUE;
+
+ const ScStyleSheet* pStyle = NULL;
+ const ScStyleSheet* pNewStyle;
+
+ ScAttrIterator aAttrIter( pAttrArray, nRow1, nRow2 );
+ USHORT nRow;
+ USHORT nDummy;
+ const ScPatternAttr* pPattern;
+ while (bEqual && ( pPattern = aAttrIter.Next( nRow, nDummy ) ))
+ {
+ pNewStyle = pPattern->GetStyleSheet();
+ rFound = TRUE;
+ if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
+ bEqual = FALSE; // unterschiedliche
+ pStyle = pNewStyle;
+ }
+
+ return bEqual ? pStyle : NULL;
+}
+
+
+void ScColumn::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, BOOL* pUsed, BOOL bReset )
+{
+ pAttrArray->FindStyleSheet( pStyleSheet, pUsed, bReset );
+}
+
+
+BOOL ScColumn::IsStyleSheetUsed( const SfxStyleSheetBase& rStyle ) const
+{
+ return pAttrArray->IsStyleSheetUsed( rStyle );
+}
+
+
+BOOL ScColumn::ApplyFlags( USHORT nStartRow, USHORT nEndRow, INT16 nFlags )
+{
+ return pAttrArray->ApplyFlags( nStartRow, nEndRow, nFlags );
+}
+
+
+BOOL ScColumn::RemoveFlags( USHORT nStartRow, USHORT nEndRow, INT16 nFlags )
+{
+ return pAttrArray->RemoveFlags( nStartRow, nEndRow, nFlags );
+}
+
+
+void ScColumn::SetPattern( USHORT nRow, const ScPatternAttr& rPatAttr, BOOL bPutToPool )
+{
+ pAttrArray->SetPattern( nRow, &rPatAttr, bPutToPool );
+}
+
+
+void ScColumn::SetPatternArea( USHORT nStartRow, USHORT nEndRow,
+ const ScPatternAttr& rPatAttr, BOOL bPutToPool )
+{
+ pAttrArray->SetPatternArea( nStartRow, nEndRow, &rPatAttr, bPutToPool );
+}
+
+
+void ScColumn::ApplyAttr( USHORT nRow, const SfxPoolItem& rAttr )
+{
+ // um nur ein neues SetItem zu erzeugen, brauchen wir keinen SfxItemPoolCache.
+ //! Achtung: der SfxItemPoolCache scheint zuviele Refs fuer das neue SetItem zu erzeugen ??
+
+ ScDocumentPool* pDocPool = pDocument->GetPool();
+
+ const ScPatternAttr* pOldPattern = pAttrArray->GetPattern( nRow );
+ ScPatternAttr* pTemp = new ScPatternAttr(*pOldPattern);
+ pTemp->GetItemSet().Put(rAttr);
+ const ScPatternAttr* pNewPattern = (const ScPatternAttr*) &pDocPool->Put( *pTemp );
+
+ if ( pNewPattern != pOldPattern )
+ pAttrArray->SetPattern( nRow, pNewPattern );
+ else
+ pDocPool->Remove( *pNewPattern ); // ausser Spesen nichts gewesen
+
+ delete pTemp;
+
+ // alte Version mit SfxItemPoolCache:
+#if 0
+ SfxItemPoolCache aCache( pDocument->GetPool(), &rAttr );
+
+ const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );
+
+ // TRUE = alten Eintrag behalten
+
+ ScPatternAttr* pNewPattern = (ScPatternAttr*) &aCache.ApplyTo( *pPattern, TRUE );
+ ScDocumentPool::CheckRef( *pPattern );
+ ScDocumentPool::CheckRef( *pNewPattern );
+
+ if (pNewPattern != pPattern)
+ pAttrArray->SetPattern( nRow, pNewPattern );
+#endif
+}
+
+#pragma optimize ( "", off )
+
+
+BOOL ScColumn::Search( USHORT nRow, USHORT& nIndex ) const
+{
+ if ( !pItems || !nCount )
+ {
+ nIndex = 0;
+ return FALSE;
+ }
+ USHORT nMinRow = pItems[0].nRow;
+ if ( nRow <= nMinRow )
+ {
+ nIndex = 0;
+ return nRow == nMinRow;
+ }
+ USHORT nMaxRow = pItems[nCount-1].nRow;
+ if ( nRow >= nMaxRow )
+ {
+ if ( nRow == nMaxRow )
+ {
+ nIndex = nCount - 1;
+ return TRUE;
+ }
+ else
+ {
+ nIndex = nCount;
+ return FALSE;
+ }
+ }
+
+ short nOldLo, nOldHi;
+ short nLo = nOldLo = 0;
+ short nHi = nOldHi = Min( (short)(nCount-1), (short)nRow );
+ short i = 0;
+ BOOL bFound = FALSE;
+ // einigermassen durchgaengige Belegung? => interpolierende Suche
+ BOOL bInterpol = (nMaxRow - nMinRow < nCount * 2);
+ USHORT nR;
+
+ while ( !bFound && nLo <= nHi )
+ {
+ if ( !bInterpol || nHi - nLo < 3 )
+ i = (nLo+nHi) / 2; // kein Aufwand, kein division by zero
+ else
+ { // interpolierende Suche
+ long nLoRow = pItems[nLo].nRow; // kein USHORT Unterlauf bei Subtraktion
+ i = nLo + (short)((long)(nRow - nLoRow) * (nHi - nLo)
+ / (pItems[nHi].nRow - nLoRow));
+ if ( i < 0 || i >= nCount )
+ { // oops ...
+ i = (nLo+nHi) / 2;
+ bInterpol = FALSE;
+ }
+ }
+ nR = pItems[i].nRow;
+ if ( nR < nRow )
+ {
+ nLo = i+1;
+ if ( bInterpol )
+ {
+ if ( nLo <= nOldLo )
+ bInterpol = FALSE;
+ else
+ nOldLo = nLo;
+ }
+ }
+ else
+ {
+ if ( nR > nRow )
+ {
+ nHi = i-1;
+ if ( bInterpol )
+ {
+ if ( nHi >= nOldHi )
+ bInterpol = FALSE;
+ else
+ nOldHi = nHi;
+ }
+ }
+ else
+ bFound = TRUE;
+ }
+ }
+ if (bFound)
+ nIndex = i;
+ else
+ nIndex = nLo; // hinterer Index
+ return bFound;
+}
+
+#pragma optimize ( "", on )
+
+
+ScBaseCell* ScColumn::GetCell( USHORT nRow ) const
+{
+ USHORT nIndex;
+ if (Search(nRow, nIndex))
+ return pItems[nIndex].pCell;
+ return NULL;
+}
+
+
+void ScColumn::Resize( USHORT nSize )
+{
+ if (nSize > MAXROW+1)
+ nSize = MAXROW+1;
+ if (nSize < nCount)
+ nSize = nCount;
+
+ ColEntry* pNewItems;
+ if (nSize)
+ {
+ USHORT nNewSize = nSize + COLUMN_DELTA - 1;
+ nNewSize -= nNewSize % COLUMN_DELTA;
+ nLimit = nNewSize;
+ pNewItems = new ColEntry[nLimit];
+ }
+ else
+ {
+ nLimit = 0;
+ pNewItems = NULL;
+ }
+ if (pItems)
+ {
+ if (pNewItems)
+ memmove( pNewItems, pItems, nCount * sizeof(ColEntry) );
+ delete[] pItems;
+ }
+ pItems = pNewItems;
+}
+
+// SetNewRow gehoert zu SwapRow
+
+void ScColumn::SetNewRow( USHORT nOldRow, USHORT nNewRow ) // nNewRow muss leer sein
+{
+ USHORT nIndex;
+ if (Search(nOldRow, nIndex))
+ {
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ --nCount;
+ memmove( &pItems[nIndex], &pItems[nIndex + 1], (nCount - nIndex) * sizeof(ColEntry) );
+
+ ScBroadcasterList* pBC = pCell->GetBroadcaster();
+ if (pBC)
+ {
+ MoveListeners( *pBC, nOldRow ); // Broadcaster bleibt an alter Stelle
+ pCell->SetBroadcaster(NULL);
+ }
+
+ if (pCell->GetCellType() != CELLTYPE_NOTE) // sonst geloescht
+ {
+ Insert(nNewRow, pCell);
+
+ short dy = (short)nNewRow - (short)nOldRow;
+ if (pCell->GetCellType() == CELLTYPE_FORMULA)
+ {
+ ScFormulaCell* pFormula = (ScFormulaCell*)pCell;
+ ScRange aRange( ScAddress( 0, nNewRow, nTab ),
+ ScAddress( MAXCOL, nNewRow, nTab ) );
+ pFormula->aPos.SetRow( nNewRow );
+ pFormula->UpdateReference(URM_MOVE, aRange, 0, -dy, 0);
+ }
+ }
+ }
+}
+
+// SwapRow zum Sortieren
+
+void ScColumn::SwapRow(USHORT nRow1, USHORT nRow2)
+{
+ // Zeiger vertauschen klappt nicht wegen Broadcastern
+ // (Absturz, wenn Zelle, auch indirekt, auf sich selbst broadcasted)
+
+ ScBaseCell *pCell1, *pCell2;
+ USHORT nIndex1, nIndex2;
+
+ if ( Search( nRow1, nIndex1 ) )
+ pCell1 = pItems[nIndex1].pCell;
+ else
+ pCell1 = NULL;
+ if ( Search( nRow2, nIndex2 ) )
+ pCell2 = pItems[nIndex2].pCell;
+ else
+ pCell2 = NULL;
+
+ if ( !pCell1 && !pCell2 )
+ return ;
+
+ CellType eType1 = ( pCell1 ? pCell1->GetCellType() : CELLTYPE_NONE );
+ CellType eType2 = ( pCell2 ? pCell2->GetCellType() : CELLTYPE_NONE );
+
+ // Broadcaster bleiben an alter Stelle
+ ScBroadcasterList *pBC1, *pBC2;
+
+ if ( eType1 != CELLTYPE_FORMULA && eType2 != CELLTYPE_FORMULA )
+ { // simple swap, kann nichts auf sich selbst broadcasten
+ if ( pCell1 )
+ {
+ pBC1 = pCell1->GetBroadcaster();
+ if ( pBC1 )
+ pCell1->ForgetBroadcaster();
+ }
+ else
+ pBC1 = NULL;
+
+ if ( pCell2 )
+ {
+ pBC2 = pCell2->GetBroadcaster();
+ if ( pBC2 )
+ pCell2->ForgetBroadcaster();
+ }
+ else
+ pBC2 = NULL;
+
+ if ( pCell1 && pCell2 )
+ {
+ pItems[nIndex1].pCell = pCell2;
+ pItems[nIndex2].pCell = pCell1;
+ if ( pBC1 )
+ pCell2->SetBroadcaster( pBC1 );
+ if ( pBC2 )
+ pCell1->SetBroadcaster( pBC2 );
+ ScAddress aPos( nCol, nRow1, nTab );
+ pDocument->Broadcast( SC_HINT_DATACHANGED, aPos, pCell2 );
+ aPos.SetRow( nRow2 );
+ pDocument->Broadcast( SC_HINT_DATACHANGED, aPos, pCell1 );
+ }
+ else if ( pCell1 )
+ {
+ ScNoteCell* pNew = ( pBC1 ? new ScNoteCell : NULL );
+ if ( pNew )
+ {
+ pItems[nIndex1].pCell = pNew;
+ pNew->SetBroadcaster( pBC1 );
+ }
+ else
+ { // Loeschen
+ --nCount;
+ memmove( &pItems[nIndex1], &pItems[nIndex1 + 1], (nCount - nIndex1) * sizeof(ColEntry) );
+ pItems[nCount].nRow = 0;
+ pItems[nCount].pCell = NULL;
+ }
+ // Einfuegen
+ Insert( nRow2, pCell1 );
+ pDocument->Broadcast( SC_HINT_DATACHANGED,
+ ScAddress( nCol, nRow1, nTab ), pNew );
+ }
+ else // pCell2
+ {
+ ScNoteCell* pNew = ( pBC2 ? new ScNoteCell : NULL );
+ if ( pNew )
+ {
+ pItems[nIndex2].pCell = pNew;
+ pNew->SetBroadcaster( pBC2 );
+ }
+ else
+ { // Loeschen
+ --nCount;
+ memmove( &pItems[nIndex2], &pItems[nIndex2 + 1], (nCount - nIndex2) * sizeof(ColEntry) );
+ pItems[nCount].nRow = 0;
+ pItems[nCount].pCell = NULL;
+ }
+ // Einfuegen
+ Insert( nRow1, pCell2 );
+ pDocument->Broadcast( SC_HINT_DATACHANGED,
+ ScAddress( nCol, nRow2, nTab ), pNew );
+ }
+
+ return ;
+ }
+
+ // ab hier ist mindestens eine Formelzelle beteiligt
+
+ if ( eType1 == CELLTYPE_FORMULA && eType2 == CELLTYPE_FORMULA )
+ {
+ ScTokenArray* pCode1 = ((ScFormulaCell*)pCell1)->GetCode();
+ ScTokenArray* pCode2 = ((ScFormulaCell*)pCell2)->GetCode();
+
+ if (pCode1->GetLen() == pCode2->GetLen()) // nicht-UPN
+ {
+ BOOL bEqual = TRUE;
+ USHORT nLen = pCode1->GetLen();
+ ScToken** ppToken1 = pCode1->GetArray();
+ ScToken** ppToken2 = pCode2->GetArray();
+ for (USHORT i=0; i<nLen; i++)
+ if ( !ppToken1[i]->TextEqual(*(ppToken2[i])) )
+ {
+ bEqual = FALSE;
+ break;
+ }
+
+ if (bEqual) // gleiche Formeln nicht vertauschen
+ return;
+ }
+ }
+
+ ScBaseCell *pNew1, *pNew2;
+
+ // hier kein UpdateReference wegen #30529# - mitsortiert werden nur noch relative Referenzen
+// short dy = (short)nRow2 - (short)nRow1;
+
+ if (pCell1)
+ {
+ pBC1 = pCell1->GetBroadcaster();
+ if ( pBC1 )
+ pCell1->ForgetBroadcaster();
+ if ( eType1 == CELLTYPE_FORMULA )
+ {
+ pNew2 = ((ScFormulaCell*)pCell1)->Clone( pDocument, ScAddress( nCol, nRow2, nTab ) );
+// ScRange aRange( ScAddress( 0, nRow2, nTab ), ScAddress( MAXCOL, nRow2, nTab ) );
+// ((ScFormulaCell*)pNew2)->UpdateReference(URM_MOVE, aRange, 0, dy, 0);
+ }
+ else
+ pNew2 = pCell1->Clone( pDocument );
+ }
+ else
+ {
+ pNew2 = NULL;
+ pBC1 = NULL;
+ }
+
+ if (pCell2)
+ {
+ pBC2 = pCell2->GetBroadcaster();
+ if ( pBC2 )
+ pCell2->ForgetBroadcaster();
+ if ( eType2 == CELLTYPE_FORMULA )
+ {
+ pNew1 = ((ScFormulaCell*)pCell2)->Clone( pDocument, ScAddress( nCol, nRow1, nTab ) );
+// ScRange aRange( ScAddress( 0, nRow1, nTab ), ScAddress( MAXCOL, nRow1, nTab ) );
+// ((ScFormulaCell*)pNew1)->UpdateReference(URM_MOVE, aRange, 0, -dy, 0);
+ }
+ else
+ pNew1 = pCell2->Clone( pDocument );
+ }
+ else
+ {
+ pNew1 = NULL;
+ pBC2 = NULL;
+ }
+
+ if ( !pNew1 && pBC1 )
+ pNew1 = new ScNoteCell;
+ if ( !pNew2 && pBC2 )
+ pNew2 = new ScNoteCell;
+
+ // Delete nur, wenn es keine neue Zelle gibt (Insert loescht die alte Zelle auch)
+ // Notizen muessen aber einzeln geloescht werden, weil Insert sie stehenlaesst
+
+ if ( pCell1 && ( !pNew1 || (pCell1->GetNotePtr() && !pNew1->GetNotePtr()) ) )
+ Delete( nRow1 );
+ if ( pCell2 && ( !pNew2 || (pCell2->GetNotePtr() && !pNew2->GetNotePtr()) ) )
+ Delete( nRow2 );
+
+ if (pNew1)
+ {
+ Insert( nRow1, pNew1 );
+ if ( pBC1 )
+ pNew1->SetBroadcaster( pBC1 );
+ }
+ if (pNew2)
+ {
+ Insert( nRow2, pNew2 );
+ if ( pBC2 )
+ pNew2->SetBroadcaster( pBC2 );
+ }
+
+ // #64122# Bei Formeln hinterher nochmal broadcasten, damit die Formel nicht in irgendwelchen
+ // FormulaTrack-Listen landet, ohne die Broadcaster beruecksichtigt zu haben
+ // (erst hier, wenn beide Zellen eingefuegt sind)
+ if ( pBC1 && eType2 == CELLTYPE_FORMULA )
+ pDocument->Broadcast( SC_HINT_DATACHANGED, ScAddress( nCol, nRow1, nTab ), pNew1 );
+ if ( pBC2 && eType1 == CELLTYPE_FORMULA )
+ pDocument->Broadcast( SC_HINT_DATACHANGED, ScAddress( nCol, nRow2, nTab ), pNew2 );
+}
+
+
+void ScColumn::SwapCell( USHORT nRow, ScColumn& rCol)
+{
+ BOOL bFound1;
+ BOOL bFound2;
+ USHORT nIndex1;
+ USHORT nIndex2;
+ bFound1 = Search(nRow, nIndex1);
+ bFound2 = rCol.Search(nRow, nIndex2);
+ if (bFound1 && bFound2)
+ {
+ // Tauschen
+ ScFormulaCell* pCell1 = (ScFormulaCell*) pItems[nIndex1].pCell;
+ ScFormulaCell* pCell2 = (ScFormulaCell*) rCol.pItems[nIndex2].pCell;
+ pItems[nIndex1].pCell = pCell2;
+ rCol.pItems[nIndex2].pCell = pCell1;
+ // Referenzen aktualisieren
+ short dx = (short)rCol.nCol - (short)nCol;
+ if (pCell1->GetCellType() == CELLTYPE_FORMULA)
+ {
+ ScRange aRange( ScAddress( rCol.nCol, 0, nTab ),
+ ScAddress( rCol.nCol, MAXROW, nTab ) );
+ pCell1->aPos.SetCol( rCol.nCol );
+ pCell1->UpdateReference(URM_MOVE, aRange, dx, 0, 0);
+ }
+ if (pCell2->GetCellType() == CELLTYPE_FORMULA)
+ {
+ ScRange aRange( ScAddress( nCol, 0, nTab ),
+ ScAddress( nCol, MAXROW, nTab ) );
+ pCell2->aPos.SetCol( nCol );
+ pCell2->UpdateReference(URM_MOVE, aRange, -dx, 0, 0);
+ }
+ }
+ else if (bFound1)
+ {
+ ScFormulaCell* pCell = (ScFormulaCell*) pItems[nIndex1].pCell;
+ // Loeschen
+ --nCount;
+ memmove( &pItems[nIndex1], &pItems[nIndex1 + 1], (nCount - nIndex1) * sizeof(ColEntry) );
+ pItems[nCount].nRow = 0;
+ pItems[nCount].pCell = NULL;
+ // Referenzen aktualisieren
+ short dx = (short)rCol.nCol - (short)nCol;
+ if (pCell->GetCellType() == CELLTYPE_FORMULA)
+ {
+ ScRange aRange( ScAddress( rCol.nCol, 0, nTab ),
+ ScAddress( rCol.nCol, MAXROW, nTab ) );
+ pCell->aPos.SetCol( rCol.nCol );
+ pCell->UpdateReference(URM_MOVE, aRange, dx, 0, 0);
+ }
+ // Einfuegen
+ rCol.Insert(nRow, pCell);
+ }
+ else if (bFound2)
+ {
+ ScFormulaCell* pCell = (ScFormulaCell*) rCol.pItems[nIndex2].pCell;
+ // Loeschen
+ --(rCol.nCount);
+ memmove( &rCol.pItems[nIndex2], &rCol.pItems[nIndex2 + 1], (rCol.nCount - nIndex2) * sizeof(ColEntry) );
+ rCol.pItems[rCol.nCount].nRow = 0;
+ rCol.pItems[rCol.nCount].pCell = NULL;
+ // Referenzen aktualisieren
+ short dx = (short)rCol.nCol - (short)nCol;
+ if (pCell->GetCellType() == CELLTYPE_FORMULA)
+ {
+ ScRange aRange( ScAddress( nCol, 0, nTab ),
+ ScAddress( nCol, MAXROW, nTab ) );
+ pCell->aPos.SetCol( nCol );
+ pCell->UpdateReference(URM_MOVE, aRange, dx, 0, 0);
+ }
+ // Einfuegen
+ Insert(nRow, pCell);
+ }
+}
+
+
+BOOL ScColumn::TestInsertCol( USHORT nStartRow, USHORT nEndRow) const
+{
+ if (!IsEmpty())
+ {
+ BOOL bTest = TRUE;
+ if (pItems)
+ for (USHORT i=0; (i<nCount) && bTest; i++)
+ bTest = ((pItems[i].nRow < nStartRow) && (pItems[i].nRow > nEndRow))
+ || !CellVisible(pItems[i].pCell);
+
+ // AttrArray testet nur zusammengefasste
+
+ if ((bTest) && (pAttrArray))
+ bTest = pAttrArray->TestInsertCol(nStartRow, nEndRow);
+
+ //! rausgeschobene Attribute bei Undo beruecksichtigen
+
+ return bTest;
+ }
+ else
+ return TRUE;
+}
+
+
+BOOL ScColumn::TestInsertRow( USHORT nSize ) const
+{
+ // AttrArray testet nur zusammengefasste
+
+ if ( pItems && nCount )
+ return ( pItems[nCount-1].nRow <= MAXROW-nSize && pAttrArray->TestInsertRow( nSize ) );
+ else
+ return pAttrArray->TestInsertRow( nSize );
+
+ //! rausgeschobene Attribute bei Undo beruecksichtigen
+
+ if ( nSize > MAXROW )
+ return FALSE;
+
+ USHORT nVis = nCount;
+ while ( nVis && !CellVisible(pItems[nVis-1].pCell) )
+ --nVis;
+
+ if ( nVis )
+ return ( pItems[nVis-1].nRow <= MAXROW-nSize );
+ else
+ return TRUE;
+}
+
+
+void ScColumn::InsertRow( USHORT nStartRow, USHORT nSize )
+{
+ pAttrArray->InsertRow( nStartRow, nSize );
+
+ //! Search
+
+ if ( !pItems || !nCount )
+ return;
+
+ USHORT i;
+ Search( nStartRow, i );
+ if ( i >= nCount )
+ return ;
+
+ BOOL bOldAutoCalc = pDocument->GetAutoCalc();
+ pDocument->SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+
+ USHORT nNewCount = nCount;
+ BOOL bCountChanged = FALSE;
+ USHORT nLastBroadcast = MAXROW+1;
+ ScAddress aAdr( nCol, 0, nTab );
+
+ for ( ; i < nCount; i++)
+ {
+ USHORT nOldRow = pItems[i].nRow;
+ // #43940# Aenderung Quelle broadcasten
+ if ( nLastBroadcast != nOldRow )
+ { // direkt aufeinanderfolgende nicht doppelt broadcasten
+ aAdr.SetRow( nOldRow );
+ pDocument->Broadcast( SC_HINT_DATACHANGED, aAdr, NULL ); // nur Areas
+ }
+ USHORT nNewRow = (pItems[i].nRow += nSize);
+ // #43940# Aenderung Ziel broadcasten
+ aAdr.SetRow( nNewRow );
+ pDocument->Broadcast( SC_HINT_DATACHANGED, aAdr, NULL ); // nur Areas
+ nLastBroadcast = nNewRow;
+ ScBaseCell* pCell = pItems[i].pCell;
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ ((ScFormulaCell*)pCell)->aPos.SetRow( nNewRow );
+ if ( nNewRow > MAXROW && !bCountChanged )
+ {
+ nNewCount = i;
+ bCountChanged = TRUE;
+ }
+ }
+
+ if (bCountChanged)
+ {
+ USHORT nDelCount = nCount - nNewCount;
+ ScBaseCell** ppDelCells = new ScBaseCell*[nDelCount];
+ USHORT* pDelRows = new USHORT[nDelCount];
+ for (i = 0; i < nDelCount; i++)
+ {
+ ppDelCells[i] = pItems[nNewCount+i].pCell;
+ pDelRows[i] = pItems[nNewCount+i].nRow;
+ }
+ nCount = nNewCount;
+
+ for (i = 0; i < nDelCount; i++)
+ {
+ ScBaseCell* pCell = ppDelCells[i];
+ DBG_ASSERT( !CellVisible(pCell), "sichtbare Zelle weggeschoben" );
+ ScBroadcasterList* pBC = pCell->GetBroadcaster();
+ if (pBC)
+ {
+ MoveListeners( *pBC, pDelRows[i] - nSize );
+ pCell->SetBroadcaster(NULL);
+ pCell->Delete();
+ }
+ }
+
+ delete pDelRows;
+ delete ppDelCells;
+ }
+
+ pDocument->SetAutoCalc( bOldAutoCalc );
+}
+
+
+void ScColumn::CopyToClip(USHORT nRow1, USHORT nRow2, ScColumn& rColumn, BOOL bKeepScenarioFlags)
+{
+ pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray,
+ bKeepScenarioFlags ? (SC_MF_ALL & ~SC_MF_SCENARIO) : SC_MF_ALL );
+
+ USHORT i;
+ USHORT nBlockCount = 0;
+ USHORT nStartIndex, nEndIndex;
+ for (i = 0; i < nCount; i++)
+ if ((pItems[i].nRow >= nRow1) && (pItems[i].nRow <= nRow2))
+ {
+ if (!nBlockCount)
+ nStartIndex = i;
+ nEndIndex = i;
+ ++nBlockCount;
+
+ // im Clipboard muessen interpretierte Zellen stehen, um andere Formate
+ // (Text, Grafik...) erzueugen zu koennen
+
+ if ( pItems[i].pCell->GetCellType() == CELLTYPE_FORMULA )
+ {
+ ScFormulaCell* pFCell = (ScFormulaCell*) pItems[i].pCell;
+ if (pFCell->GetDirty() && pDocument->GetAutoCalc())
+ pFCell->Interpret();
+ }
+ }
+
+ if (nBlockCount)
+ {
+ rColumn.Resize( rColumn.GetCellCount() + nBlockCount );
+ for (i = nStartIndex; i <= nEndIndex; i++)
+ rColumn.Append(pItems[i].nRow, pItems[i].pCell->Clone(rColumn.pDocument));
+ }
+}
+
+
+void ScColumn::CopyToColumn(USHORT nRow1, USHORT nRow2, USHORT nFlags, BOOL bMarked,
+ ScColumn& rColumn, const ScMarkData* pMarkData, BOOL bAsLink )
+{
+ if (bMarked)
+ {
+ USHORT nStart, nEnd;
+ if (pMarkData && pMarkData->IsMultiMarked())
+ {
+ ScMarkArrayIter aIter( pMarkData->GetArray()+nCol );
+
+ while ( aIter.Next( nStart, nEnd ) && nStart <= nRow2 )
+ {
+ if ( nEnd >= nRow1 )
+ CopyToColumn( Max(nRow1,nStart), Min(nRow2,nEnd),
+ nFlags, FALSE, rColumn, pMarkData, bAsLink );
+ }
+ }
+ else
+ DBG_ERROR("CopyToColumn: bMarked, aber keine Markierung");
+ return;
+ }
+
+ if ( (nFlags & IDF_ATTRIB) != 0 )
+ {
+ if ( (nFlags & IDF_STYLES) != IDF_STYLES )
+ { // StyleSheets im Zieldokument bleiben erhalten
+ // z.B. DIF und RTF Clipboard-Import
+ for ( USHORT nRow = nRow1; nRow <= nRow2; nRow++ )
+ {
+ const ScStyleSheet* pStyle =
+ rColumn.pAttrArray->GetPattern( nRow )->GetStyleSheet();
+ const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );
+ ScPatternAttr* pNewPattern = new ScPatternAttr( *pPattern );
+ pNewPattern->SetStyleSheet( (ScStyleSheet*)pStyle );
+ rColumn.pAttrArray->SetPattern( nRow, pNewPattern, TRUE );
+ delete pNewPattern;
+ }
+ }
+ else
+ pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray);
+ }
+
+
+ if ((nFlags & IDF_CONTENTS) != 0)
+ {
+ USHORT i;
+ USHORT nBlockCount = 0;
+ USHORT nStartIndex, nEndIndex;
+ for (i = 0; i < nCount; i++)
+ if ((pItems[i].nRow >= nRow1) && (pItems[i].nRow <= nRow2))
+ {
+ if (!nBlockCount)
+ nStartIndex = i;
+ nEndIndex = i;
+ ++nBlockCount;
+ }
+
+ if (nBlockCount)
+ {
+ rColumn.Resize( rColumn.GetCellCount() + nBlockCount );
+ ScAddress aAdr( rColumn.nCol, 0, rColumn.nTab );
+ for (i = nStartIndex; i <= nEndIndex; i++)
+ {
+ ScBaseCell* pOld = pItems[i].pCell;
+ aAdr.SetRow( pItems[i].nRow );
+ ScBaseCell* pNew;
+ if (bAsLink)
+ {
+ pNew = CreateRefCell( rColumn.pDocument, aAdr, i, nFlags );
+ }
+ else
+ {
+ pNew = CloneCell( i, nFlags, rColumn.pDocument, aAdr );
+
+ if ( pNew && pNew->GetNotePtr() && (nFlags & IDF_NOTE) == 0 )
+ pNew->DeleteNote();
+ }
+
+ if (pNew)
+ rColumn.Insert(pItems[i].nRow, pNew);
+ }
+ }
+ }
+}
+
+
+void ScColumn::UndoToColumn(USHORT nRow1, USHORT nRow2, USHORT nFlags, BOOL bMarked,
+ ScColumn& rColumn, const ScMarkData* pMarkData )
+{
+ if (nRow1 > 0)
+ CopyToColumn( 0, nRow1-1, IDF_FORMULA, FALSE, rColumn );
+
+ CopyToColumn( nRow1, nRow2, nFlags, bMarked, rColumn, pMarkData ); //! bMarked ????
+
+ if (nRow2 < MAXROW)
+ CopyToColumn( nRow2+1, MAXROW, IDF_FORMULA, FALSE, rColumn );
+}
+
+
+void ScColumn::CopyUpdated( const ScColumn& rPosCol, ScColumn& rDestCol ) const
+{
+ ScDocument* pDestDoc = rDestCol.pDocument;
+
+ USHORT nPosCount = rPosCol.nCount;
+ for (USHORT nPosIndex = 0; nPosIndex < nPosCount; nPosIndex++)
+ {
+ USHORT nRow = rPosCol.pItems[nPosIndex].nRow;
+ USHORT nThisIndex;
+ if ( Search( nRow, nThisIndex ) )
+ {
+ ScBaseCell* pNew = pItems[nThisIndex].pCell->Clone(pDestDoc);
+ rDestCol.Insert( nRow, pNew );
+ }
+ }
+
+ // Dummy:
+ // CopyToColumn( 0,MAXROW, IDF_FORMULA, FALSE, rDestCol, NULL, FALSE );
+}
+
+
+void ScColumn::CopyScenarioFrom( const ScColumn& rSrcCol )
+{
+ // Dies ist die Szenario-Tabelle, die Daten werden hineinkopiert
+
+ ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
+ USHORT nStart, nEnd;
+ const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
+ while (pPattern)
+ {
+ if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
+ {
+ DeleteArea( nStart, nEnd, IDF_CONTENTS );
+ ((ScColumn&)rSrcCol).
+ CopyToColumn( nStart, nEnd, IDF_CONTENTS, FALSE, *this );
+
+ // UpdateUsed nicht noetig, schon in TestCopyScenario passiert
+
+ short nDz = ((short)nTab) - (short)rSrcCol.nTab;
+ UpdateReference(URM_COPY, nCol, nStart, nTab,
+ nCol, nEnd, nTab,
+ 0, 0, nDz, NULL);
+ UpdateCompile();
+ }
+
+ //! CopyToColumn "const" machen !!!
+
+ pPattern = aAttrIter.Next( nStart, nEnd );
+ }
+}
+
+
+void ScColumn::CopyScenarioTo( ScColumn& rDestCol ) const
+{
+ // Dies ist die Szenario-Tabelle, die Daten werden in die andere kopiert
+
+ ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
+ USHORT nStart, nEnd;
+ const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
+ while (pPattern)
+ {
+ if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
+ {
+ rDestCol.DeleteArea( nStart, nEnd, IDF_CONTENTS );
+ ((ScColumn*)this)->
+ CopyToColumn( nStart, nEnd, IDF_CONTENTS, FALSE, rDestCol );
+
+ // UpdateUsed nicht noetig, schon in TestCopyScenario passiert
+
+ short nDz = ((short)rDestCol.nTab) - (short)nTab;
+ rDestCol.UpdateReference(URM_COPY, rDestCol.nCol, nStart, rDestCol.nTab,
+ rDestCol.nCol, nEnd, rDestCol.nTab,
+ 0, 0, nDz, NULL);
+ rDestCol.UpdateCompile();
+ }
+
+ //! CopyToColumn "const" machen !!!
+
+ pPattern = aAttrIter.Next( nStart, nEnd );
+ }
+}
+
+
+BOOL ScColumn::TestCopyScenarioTo( const ScColumn& rDestCol ) const
+{
+ BOOL bOk = TRUE;
+ ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
+ USHORT nStart, nEnd;
+ const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
+ while (pPattern && bOk)
+ {
+ if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
+ if ( rDestCol.pAttrArray->HasAttrib( nStart, nEnd, HASATTR_PROTECTED ) )
+ bOk = FALSE;
+
+ pPattern = aAttrIter.Next( nStart, nEnd );
+ }
+ return bOk;
+}
+
+
+void ScColumn::MarkScenarioIn( ScMarkData& rDestMark ) const
+{
+ ScRange aRange( nCol, 0, nTab );
+
+ ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
+ USHORT nStart, nEnd;
+ const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
+ while (pPattern)
+ {
+ if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
+ {
+ aRange.aStart.SetRow( nStart );
+ aRange.aEnd.SetRow( nEnd );
+ rDestMark.SetMultiMarkArea( aRange, TRUE );
+ }
+
+ pPattern = aAttrIter.Next( nStart, nEnd );
+ }
+}
+
+
+void ScColumn::SwapCol(ScColumn& rCol)
+{
+ USHORT nTemp;
+
+ nTemp = rCol.nCount;
+ rCol.nCount = nCount;
+ nCount = nTemp;
+
+ nTemp = rCol.nLimit;
+ rCol.nLimit = nLimit;
+ nLimit = nTemp;
+
+ ColEntry* pTempItems = rCol.pItems;
+ rCol.pItems = pItems;
+ pItems = pTempItems;
+
+ ScAttrArray* pTempAttr = rCol.pAttrArray;
+ rCol.pAttrArray = pAttrArray;
+ pAttrArray = pTempAttr;
+
+ // #38415# AttrArray muss richtige Spaltennummer haben
+ pAttrArray->SetCol(nCol);
+ rCol.pAttrArray->SetCol(rCol.nCol);
+
+ USHORT i;
+ if (pItems)
+ for (i = 0; i < nCount; i++)
+ {
+ ScFormulaCell* pCell = (ScFormulaCell*) pItems[i].pCell;
+ if( pCell->GetCellType() == CELLTYPE_FORMULA)
+ pCell->aPos.SetCol(nCol);
+ }
+ if (rCol.pItems)
+ for (i = 0; i < rCol.nCount; i++)
+ {
+ ScFormulaCell* pCell = (ScFormulaCell*) rCol.pItems[i].pCell;
+ if( pCell->GetCellType() == CELLTYPE_FORMULA)
+ pCell->aPos.SetCol(rCol.nCol);
+ }
+}
+
+
+void ScColumn::MoveTo(USHORT nStartRow, USHORT nEndRow, ScColumn& rCol)
+{
+ pAttrArray->MoveTo(nStartRow, nEndRow, *rCol.pAttrArray);
+
+ if (pItems)
+ {
+ USHORT nStartPos;
+ USHORT nMoveCount=0;
+ USHORT i;
+ for (i=0; i < nCount; i++)
+ {
+ if ((pItems[i].nRow >= nStartRow) && (pItems[i].nRow <= nEndRow))
+ {
+ if (nMoveCount==0)
+ nStartPos=i;
+ ++nMoveCount;
+
+ rCol.Insert(pItems[i].nRow, pItems[i].pCell);
+ }
+ }
+ if (nMoveCount > 0)
+ {
+ // Formeln benachrichtigen, dass sich etwas aendert
+
+ ScNoteCell* pNoteCell = new ScNoteCell; // Dummy wie in DeleteRange
+ USHORT nEndPos = nStartPos+nMoveCount-1;
+ for (i=nStartPos; i<=nEndPos; i++)
+ pItems[i].pCell = pNoteCell; // nicht auf die verschobenen zugreifen
+ for (i=nStartPos; i<=nEndPos; i++)
+ pDocument->Broadcast( SC_HINT_DYING,
+ ScAddress( nCol, pItems[i].nRow, nTab ), NULL ); // nur Areas
+ delete pNoteCell;
+
+ nCount -= nMoveCount;
+ memmove( &pItems[nStartPos], &pItems[nStartPos+nMoveCount],
+ (nCount - nStartPos) * sizeof(ColEntry) );
+ pItems[nCount].nRow = 0;
+ pItems[nCount].pCell = NULL;
+ }
+ }
+}
+
+
+void ScColumn::UpdateReference( UpdateRefMode eUpdateRefMode, USHORT nCol1, USHORT nRow1, USHORT nTab1,
+ USHORT nCol2, USHORT nRow2, USHORT nTab2, short nDx, short nDy, short nDz,
+ ScDocument* pUndoDoc )
+{
+ if (pItems)
+ {
+ ScRange aRange( ScAddress( nCol1, nRow1, nTab1 ),
+ ScAddress( nCol2, nRow2, nTab2 ) );
+ if ( eUpdateRefMode == URM_COPY && nRow1 == nRow2 )
+ { // z.B. eine einzelne Zelle aus dem Clipboard eingefuegt
+ USHORT nIndex;
+ if ( Search( nRow1, nIndex ) )
+ {
+ ScFormulaCell* pCell = (ScFormulaCell*) pItems[nIndex].pCell;
+ if( pCell->GetCellType() == CELLTYPE_FORMULA)
+ pCell->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc );
+ }
+ }
+ else
+ {
+ USHORT i, nRow;
+ if ( eUpdateRefMode == URM_COPY )
+ Search( nRow1, i );
+ else
+ i = 0;
+ for ( ; i < nCount; i++ )
+ {
+ nRow = pItems[i].nRow;
+ if ( eUpdateRefMode == URM_COPY && nRow > nRow2 )
+ break;
+ ScFormulaCell* pCell = (ScFormulaCell*) pItems[i].pCell;
+ if( pCell->GetCellType() == CELLTYPE_FORMULA)
+ pCell->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc );
+ if ( nRow != pItems[i].nRow )
+ Search( nRow, i ); // Listener geloescht/eingefuegt?
+ }
+ }
+ }
+}
+
+
+void ScColumn::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
+ ScDocument* pUndoDoc )
+{
+ if (pItems)
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScBaseCell* pCell = pItems[i].pCell;
+ if (pCell->GetCellType() == CELLTYPE_FORMULA)
+ {
+ USHORT nRow = pItems[i].nRow;
+ ((ScFormulaCell*)pCell)->UpdateTranspose( rSource, rDest, pUndoDoc );
+ if ( nRow != pItems[i].nRow )
+ Search( nRow, i ); // Listener geloescht/eingefuegt?
+ }
+ }
+}
+
+
+void ScColumn::UpdateGrow( const ScRange& rArea, USHORT nGrowX, USHORT nGrowY )
+{
+ if (pItems)
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScBaseCell* pCell = pItems[i].pCell;
+ if (pCell->GetCellType() == CELLTYPE_FORMULA)
+ {
+ USHORT nRow = pItems[i].nRow;
+ ((ScFormulaCell*)pCell)->UpdateGrow( rArea, nGrowX, nGrowY );
+ if ( nRow != pItems[i].nRow )
+ Search( nRow, i ); // Listener geloescht/eingefuegt?
+ }
+ }
+}
+
+
+void ScColumn::UpdateInsertTab( USHORT nTable)
+{
+ if (nTab >= nTable) nTab++;
+ if( pItems )
+ UpdateInsertTabOnlyCells( nTable );
+}
+
+
+void ScColumn::UpdateInsertTabOnlyCells( USHORT nTable)
+{
+ if (pItems)
+ for (USHORT i = 0; i < nCount; i++)
+ {
+ ScFormulaCell* pCell = (ScFormulaCell*) pItems[i].pCell;
+ if( pCell->GetCellType() == CELLTYPE_FORMULA)
+ {
+ USHORT nRow = pItems[i].nRow;
+ pCell->UpdateInsertTab(nTable);
+ if ( nRow != pItems[i].nRow )
+ Search( nRow, i ); // Listener geloescht/eingefuegt?
+ }
+ }
+}
+
+
+void ScColumn::UpdateInsertTabAbs(USHORT nTable)
+{
+ if (pItems)
+ for (USHORT i = 0; i < nCount; i++)
+ {
+ ScFormulaCell* pCell = (ScFormulaCell*) pItems[i].pCell;
+ if( pCell->GetCellType() == CELLTYPE_FORMULA)
+ {
+ USHORT nRow = pItems[i].nRow;
+ pCell->UpdateInsertTabAbs(nTable);
+ if ( nRow != pItems[i].nRow )
+ Search( nRow, i ); // Listener geloescht/eingefuegt?
+ }
+ }
+}
+
+
+void ScColumn::UpdateDeleteTab( USHORT nTable, BOOL bIsMove, ScColumn* pRefUndo )
+{
+ if (nTab > nTable)
+ pAttrArray->SetTab(--nTab);
+
+ if (pItems)
+ for (USHORT i = 0; i < nCount; i++)
+ if ( pItems[i].pCell->GetCellType() == CELLTYPE_FORMULA )
+ {
+ USHORT nRow = pItems[i].nRow;
+ ScFormulaCell* pOld = (ScFormulaCell*)pItems[i].pCell;
+
+ ScFormulaCell* pSave = NULL;
+ if (pRefUndo)
+ pSave = (ScFormulaCell*)pOld->Clone( pDocument,
+ ScAddress( nCol, nRow, nTab ), TRUE );
+
+ BOOL bChanged = pOld->UpdateDeleteTab(nTable, bIsMove);
+ if ( nRow != pItems[i].nRow )
+ Search( nRow, i ); // Listener geloescht/eingefuegt?
+
+ if (pRefUndo)
+ {
+ if (bChanged)
+ pRefUndo->Insert( nRow, pSave );
+ else
+ delete pSave;
+ }
+ }
+}
+
+
+void ScColumn::UpdateMoveTab( USHORT nOldPos, USHORT nNewPos, USHORT nTabNo )
+{
+ nTab = nTabNo;
+ pAttrArray->SetTab( nTabNo );
+ if (pItems)
+ for (USHORT i = 0; i < nCount; i++)
+ {
+ ScFormulaCell* pCell = (ScFormulaCell*) pItems[i].pCell;
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ {
+ USHORT nRow = pItems[i].nRow;
+ pCell->UpdateMoveTab( nOldPos, nNewPos, nTabNo );
+ if ( nRow != pItems[i].nRow )
+ Search( nRow, i ); // Listener geloescht/eingefuegt?
+ }
+ }
+}
+
+
+void ScColumn::UpdateCompile( BOOL bForceIfNameInUse )
+{
+ if (pItems)
+ for (USHORT i = 0; i < nCount; i++)
+ {
+ ScFormulaCell* p = (ScFormulaCell*) pItems[i].pCell;
+ if( p->GetCellType() == CELLTYPE_FORMULA )
+ {
+ USHORT nRow = pItems[i].nRow;
+ p->UpdateCompile( bForceIfNameInUse );
+ if ( nRow != pItems[i].nRow )
+ Search( nRow, i ); // Listener geloescht/eingefuegt?
+ }
+ }
+}
+
+
+void ScColumn::SetTabNo(USHORT nNewTab)
+{
+ nTab = nNewTab;
+ pAttrArray->SetTab( nNewTab );
+ if (pItems)
+ for (USHORT i = 0; i < nCount; i++)
+ {
+ ScFormulaCell* p = (ScFormulaCell*) pItems[i].pCell;
+ if( p->GetCellType() == CELLTYPE_FORMULA )
+ p->aPos.SetTab( nNewTab );
+ }
+}
+
+
+BOOL ScColumn::IsRangeNameInUse(USHORT nRow1, USHORT nRow2, USHORT nIndex) const
+{
+ BOOL bInUse = FALSE;
+ if (pItems)
+ for (USHORT i = 0; !bInUse && (i < nCount); i++)
+ if ((pItems[i].nRow >= nRow1) &&
+ (pItems[i].nRow <= nRow2) &&
+ (pItems[i].pCell->GetCellType() == CELLTYPE_FORMULA))
+ bInUse = ((ScFormulaCell*)pItems[i].pCell)->IsRangeNameInUse(nIndex);
+ return bInUse;
+}
+
+
+void ScColumn::ReplaceRangeNamesInUse(USHORT nRow1, USHORT nRow2,
+ const ScIndexMap& rMap )
+{
+ BOOL bInUse = FALSE;
+ if (pItems)
+ for (USHORT i = 0; i < nCount; i++)
+ {
+ if ((pItems[i].nRow >= nRow1) &&
+ (pItems[i].nRow <= nRow2) &&
+ (pItems[i].pCell->GetCellType() == CELLTYPE_FORMULA))
+ {
+ USHORT nRow = pItems[i].nRow;
+ ((ScFormulaCell*)pItems[i].pCell)->ReplaceRangeNamesInUse( rMap );
+ if ( nRow != pItems[i].nRow )
+ Search( nRow, i ); // Listener geloescht/eingefuegt?
+ }
+ }
+}
+
+
+void ScColumn::SetDirtyVar()
+{
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScFormulaCell* p = (ScFormulaCell*) pItems[i].pCell;
+ if( p->GetCellType() == CELLTYPE_FORMULA )
+ p->SetDirtyVar();
+ }
+}
+
+
+void ScColumn::SetDirty()
+{
+ // wird nur dokumentweit verwendet, kein FormulaTrack
+ BOOL bOldAutoCalc = pDocument->GetAutoCalc();
+ pDocument->SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScFormulaCell* p = (ScFormulaCell*) pItems[i].pCell;
+ if( p->GetCellType() == CELLTYPE_FORMULA )
+ {
+ p->SetDirtyVar();
+ if ( !pDocument->IsInFormulaTree( p ) )
+ pDocument->PutInFormulaTree( p );
+ }
+ }
+ pDocument->SetAutoCalc( bOldAutoCalc );
+}
+
+
+void ScColumn::SetDirty( const ScRange& rRange )
+{ // broadcastet alles innerhalb eines Range, mit FormulaTrack
+ if ( !pItems || !nCount )
+ return ;
+ BOOL bOldAutoCalc = pDocument->GetAutoCalc();
+ pDocument->SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ USHORT nRow2 = rRange.aEnd.Row();
+ ScAddress aPos( nCol, 0, nTab );
+ USHORT nRow, nIndex;
+ Search( rRange.aStart.Row(), nIndex );
+ while ( nIndex < nCount && (nRow = pItems[nIndex].nRow) <= nRow2 )
+ {
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ ((ScFormulaCell*)pCell)->SetDirty();
+ else
+ {
+ aPos.SetRow( nRow );
+ pDocument->Broadcast( SC_HINT_DATACHANGED, aPos, pCell );
+ }
+ nIndex++;
+ }
+ pDocument->SetAutoCalc( bOldAutoCalc );
+}
+
+
+void ScColumn::SetDirtyAfterLoad()
+{
+ BOOL bOldAutoCalc = pDocument->GetAutoCalc();
+ pDocument->SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScFormulaCell* p = (ScFormulaCell*) pItems[i].pCell;
+ if ( p->GetCellType() == CELLTYPE_FORMULA && p->GetDirty() )
+ p->SetDirty();
+ // wenn die Zelle durch CalcAfterLoad schon bDirty war, muss
+ // jetzt noch FormulaTracking stattfinden
+ }
+ pDocument->SetAutoCalc( bOldAutoCalc );
+}
+
+
+void ScColumn::SetRelNameDirty()
+{
+ BOOL bOldAutoCalc = pDocument->GetAutoCalc();
+ pDocument->SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScFormulaCell* p = (ScFormulaCell*) pItems[i].pCell;
+ if( p->GetCellType() == CELLTYPE_FORMULA && p->HasRelNameReference() )
+ p->SetDirty();
+ }
+ pDocument->SetAutoCalc( bOldAutoCalc );
+}
+
+
+void ScColumn::CalcAll()
+{
+ if (pItems)
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScBaseCell* pCell = pItems[i].pCell;
+ if (pCell->GetCellType() == CELLTYPE_FORMULA)
+ {
+#ifdef DEBUG
+ // nach F9 ctrl-F9: ueberprueft die Berechnung per FormulaTree
+ ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
+ double nOldVal, nNewVal;
+ nOldVal = pFCell->GetValue();
+#endif
+ ((ScFormulaCell*)pCell)->Interpret();
+#ifdef DEBUG
+ if ( pFCell->GetCode()->IsRecalcModeNormal() )
+ nNewVal = pFCell->GetValue();
+ else
+ nNewVal = nOldVal; // random(), jetzt() etc.
+ DBG_ASSERT( nOldVal==nNewVal, "CalcAll: nOldVal != nNewVal" );
+#endif
+ }
+ }
+}
+
+
+void ScColumn::CompileAll()
+{
+ if (pItems)
+ for (USHORT i = 0; i < nCount; i++)
+ {
+ ScBaseCell* pCell = pItems[i].pCell;
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ {
+ USHORT nRow = pItems[i].nRow;
+ // fuer unbedingtes kompilieren
+ // bCompile=TRUE und pCode->nError=0
+ ((ScFormulaCell*)pCell)->GetCode()->SetError( 0 );
+ ((ScFormulaCell*)pCell)->SetCompile( TRUE );
+ ((ScFormulaCell*)pCell)->CompileTokenArray();
+ if ( nRow != pItems[i].nRow )
+ Search( nRow, i ); // Listener geloescht/eingefuegt?
+ }
+ }
+}
+
+
+void ScColumn::CompileXML()
+{
+ if (pItems)
+ for (USHORT i = 0; i < nCount; i++)
+ {
+ ScBaseCell* pCell = pItems[i].pCell;
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ {
+ USHORT nRow = pItems[i].nRow;
+ ((ScFormulaCell*)pCell)->CompileXML();
+ if ( nRow != pItems[i].nRow )
+ Search( nRow, i ); // Listener geloescht/eingefuegt?
+ }
+ }
+}
+
+
+void ScColumn::CalcAfterLoad()
+{
+ if (pItems)
+ for (USHORT i = 0; i < nCount; i++)
+ {
+ ScBaseCell* pCell = pItems[i].pCell;
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ ((ScFormulaCell*)pCell)->CalcAfterLoad();
+ }
+}
+
+
+void ScColumn::ResetChanged( USHORT nStartRow, USHORT nEndRow )
+{
+ if (pItems)
+ {
+ USHORT nIndex;
+ Search(nStartRow,nIndex);
+ while (nIndex<nCount && pItems[nIndex].nRow <= nEndRow)
+ {
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ if (pCell->GetCellType() == CELLTYPE_FORMULA)
+ ((ScFormulaCell*)pCell)->ResetChanged();
+ ++nIndex;
+ }
+ }
+}
+
+
+BOOL ScColumn::HasEditCells(USHORT nStartRow, USHORT nEndRow, USHORT& rFirst) const
+{
+ USHORT nRow;
+ USHORT nIndex;
+ Search(nStartRow,nIndex);
+ while ( (nIndex < nCount) ? ((nRow=pItems[nIndex].nRow) <= nEndRow) : FALSE )
+ {
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ if (pCell->GetCellType() == CELLTYPE_EDIT)
+ {
+ rFirst = nRow;
+ return TRUE;
+ }
+ ++nIndex;
+ }
+
+ return FALSE;
+}
+
+
+short ScColumn::SearchStyle( short nRow, const ScStyleSheet* pSearchStyle,
+ BOOL bUp, BOOL bInSelection, const ScMarkData& rMark )
+{
+ if (bInSelection)
+ {
+ if (rMark.IsMultiMarked())
+ return pAttrArray->SearchStyle( nRow, pSearchStyle, bUp,
+ (ScMarkArray*) rMark.GetArray()+nCol ); //! const
+ else
+ return -1;
+ }
+ else
+ return pAttrArray->SearchStyle( nRow, pSearchStyle, bUp, NULL );
+}
+
+
+BOOL ScColumn::SearchStyleRange( short& rRow, short& rEndRow, const ScStyleSheet* pSearchStyle,
+ BOOL bUp, BOOL bInSelection, const ScMarkData& rMark )
+{
+ if (bInSelection)
+ {
+ if (rMark.IsMultiMarked())
+ return pAttrArray->SearchStyleRange( rRow, rEndRow, pSearchStyle, bUp,
+ (ScMarkArray*) rMark.GetArray()+nCol ); //! const
+ else
+ return FALSE;
+ }
+ else
+ return pAttrArray->SearchStyleRange( rRow, rEndRow, pSearchStyle, bUp, NULL );
+}
+
+
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
new file mode 100644
index 000000000000..a216b4a021fd
--- /dev/null
+++ b/sc/source/core/data/column2.cxx
@@ -0,0 +1,2123 @@
+/*************************************************************************
+ *
+ * $RCSfile: column2.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <svx/algitem.hxx>
+#include <svx/editobj.hxx>
+#include <svx/editstat.hxx>
+#include <svx/fhgtitem.hxx>
+#include <svx/rotmodit.hxx>
+#include <svtools/zforlist.hxx>
+#include <vcl/outdev.hxx>
+#include <math.h>
+
+#include "column.hxx"
+#include "cell.hxx"
+#include "document.hxx"
+#include "docpool.hxx"
+#include "attarray.hxx"
+#include "patattr.hxx"
+#include "cellform.hxx"
+#include "collect.hxx"
+#include "stlsheet.hxx"
+#include "rechead.hxx"
+#include "brdcst.hxx"
+#include "editutil.hxx"
+#include "subtotal.hxx"
+#include "markdata.hxx"
+#include "compiler.hxx" // ScTokenArray GetCodeLen
+#include "dbcolect.hxx"
+#include "bclist.hxx"
+
+// -----------------------------------------------------------------------
+
+// factor from font size to optimal cell height (text width)
+#define SC_ROT_BREAK_FACTOR 6
+
+// -----------------------------------------------------------------------
+
+inline BOOL CellVisible( const ScBaseCell* pCell )
+{
+ return ( pCell->GetCellType() != CELLTYPE_NOTE || pCell->GetNotePtr() );
+}
+
+// -----------------------------------------------------------------------------------------
+
+//
+// Datei-Operationen
+//
+
+// -----------------------------------------------------------------------------------------
+
+// special handling for non-convertable characters is no longer needed
+#if 0
+
+// read string from a string cell in original CharSet
+
+String lcl_ReadOriginalStringCell( SvStream& rStream, USHORT nVer, CharSet eSystemCharSet )
+{
+ if( nVer >= SC_DATABYTES2 )
+ {
+ BYTE cData;
+ rStream >> cData;
+ if( cData & 0x0F )
+ rStream.SeekRel( cData & 0x0F );
+ }
+
+ CharSet eOld = rStream.GetStreamCharSet();
+ rStream.SetStreamCharSet( eSystemCharSet ); // no conversion
+
+ String aString;
+ rStream >> aString;
+
+ rStream.SetStreamCharSet( eOld );
+
+ return aString;
+}
+
+#endif
+
+// -----------------------------------------------------------------------------------------
+
+void ScColumn::LoadData( SvStream& rStream )
+{
+ USHORT nNewCount;
+ USHORT nNewRow;
+ BYTE nByte;
+ USHORT nVer = (USHORT) pDocument->GetSrcVersion();
+
+ ScMultipleReadHeader aHdr( rStream );
+
+ rStream >> nNewCount;
+ if ( nNewCount > MAXROW+1 ) // wuerde das Array zu gross?
+ {
+ pDocument->SetLostData();
+ rStream.SetError( SVSTREAM_FILEFORMAT_ERROR );
+ return;
+ }
+
+ Resize( nNewCount ); // veraendert nCount nicht
+ for (USHORT i=0; i<nNewCount; i++)
+ {
+ rStream >> nNewRow;
+ rStream >> nByte;
+
+ if ( nNewRow > MAXROW ) // Zeilennummer zu gross?
+ {
+ pDocument->SetLostData();
+ rStream.SetError( SVSTREAM_FILEFORMAT_ERROR );
+ return;
+ }
+
+ switch ((CellType) nByte)
+ {
+ case CELLTYPE_VALUE:
+ {
+ ScValueCell* pCell = new ScValueCell( rStream, nVer );
+ Append( nNewRow, pCell );
+ }
+ break;
+ case CELLTYPE_STRING:
+ {
+ ScStringCell* pCell = new ScStringCell( rStream, nVer );
+ Append( nNewRow, pCell );
+
+// special handling for non-convertable characters is no longer needed here
+//! handle non-convertable characters when saving to file?
+#if 0
+ // #68427# manually convert CharSet so non-convertable characters
+ // can be stored in an EditEngine cell
+
+ CharSet eSystemCharSet = ::GetSystemCharSet();
+ CharSet eSourceCharSet = pDocument->GetSrcCharSet();
+ String aSourceString = lcl_ReadOriginalStringCell( rStream, nVer, eSystemCharSet );
+
+ ScBaseCell* pCell = NULL;
+ String aCellString = aSourceString;
+ if ( eSourceCharSet != eSystemCharSet )
+ {
+ // bReplace = FALSE: null characters for non-convertable
+ aCellString.Convert( eSourceCharSet, eSystemCharSet, FALSE );
+ if ( aCellString.Search( (char)0 ) != STRING_NOTFOUND )
+ {
+ // contains non-convertable characters -> use EditEngine
+
+ EditEngine& rEngine = pDocument->GetEditEngine();
+ rEngine.SetText( aSourceString, eSourceCharSet );
+ EditTextObject* pObj = rEngine.CreateTextObject();
+ pCell = new ScEditCell( pObj, pDocument, rEngine.GetEditTextObjectPool() );
+ delete pObj;
+ }
+ // else use aCellString
+ }
+
+ // create string cell if no edit cell is needed
+ if ( !pCell )
+ pCell = new ScStringCell( aCellString );
+ Append( nNewRow, pCell );
+#endif
+ }
+ break;
+ case CELLTYPE_SYMBOLS:
+ {
+//! CharSet eOld = rStream.GetStreamCharSet();
+//! // convert into true symbol characters
+//! rStream.SetStreamCharSet( RTL_TEXTENCODING_SYMBOL );
+ ScStringCell* pCell = new ScStringCell( rStream, nVer );
+ Append( nNewRow, pCell );
+//! rStream.SetStreamCharSet( eOld );
+ }
+ break;
+ case CELLTYPE_EDIT:
+ {
+ ScEditCell* pCell = new ScEditCell( rStream, nVer, pDocument );
+ Append( nNewRow, pCell );
+ }
+ break;
+ case CELLTYPE_FORMULA:
+ {
+ ScFormulaCell* pCell = new ScFormulaCell(
+ pDocument, ScAddress( nCol, nNewRow, nTab ), rStream, aHdr );
+ Append( nNewRow, pCell);
+ }
+ break;
+ case CELLTYPE_NOTE:
+ {
+ ScNoteCell *pCell = new ScNoteCell( rStream, nVer );
+ Append( nNewRow, pCell);
+ }
+ break;
+ default:
+ DBG_ERROR( "Falscher Zellentyp" );
+ rStream.SetError( SVSTREAM_FILEFORMAT_ERROR );
+ return;
+ }
+ }
+}
+
+BOOL lcl_RemoveAny( ScDocument* pDocument, USHORT nCol, USHORT nTab )
+{
+ ScDBCollection* pDBColl = pDocument->GetDBCollection();
+ if ( pDBColl )
+ {
+ USHORT nCount = pDBColl->GetCount();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScDBData* pData = (*pDBColl)[i];
+ if ( pData->IsStripData() &&
+ pData->HasImportParam() && !pData->HasImportSelection() )
+ {
+ ScRange aDBRange;
+ pData->GetArea(aDBRange);
+ if ( nTab == aDBRange.aStart.Tab() &&
+ nCol >= aDBRange.aStart.Col() && nCol <= aDBRange.aEnd.Col() )
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+BOOL lcl_RemoveThis( ScDocument* pDocument, USHORT nCol, USHORT nRow, USHORT nTab )
+{
+ ScDBCollection* pDBColl = pDocument->GetDBCollection();
+ if ( pDBColl )
+ {
+ USHORT nCount = pDBColl->GetCount();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScDBData* pData = (*pDBColl)[i];
+ if ( pData->IsStripData() &&
+ pData->HasImportParam() && !pData->HasImportSelection() )
+ {
+ ScRange aDBRange;
+ pData->GetArea(aDBRange);
+ if ( nTab == aDBRange.aStart.Tab() &&
+ nCol >= aDBRange.aStart.Col() && nCol <= aDBRange.aEnd.Col() &&
+ nRow >= aDBRange.aStart.Row() && nRow <= aDBRange.aEnd.Row() )
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+void ScColumn::SaveData( SvStream& rStream ) const
+{
+ CellType eCellType;
+ ScBaseCell* pCell;
+ USHORT i;
+
+ ScMultipleWriteHeader aHdr( rStream );
+
+ USHORT nSaveCount = nCount;
+
+ // Zeilen hinter MAXROW abziehen
+ USHORT nSaveMaxRow = pDocument->GetSrcMaxRow();
+ if ( nSaveMaxRow != MAXROW )
+ {
+ if ( nSaveCount && pItems[nSaveCount-1].nRow > nSaveMaxRow )
+ {
+ pDocument->SetLostData(); // Warnung ausgeben
+ do
+ --nSaveCount;
+ while ( nSaveCount && pItems[nSaveCount-1].nRow > nSaveMaxRow );
+ }
+ }
+
+ // Zellen abziehen, die wegen Import nicht gespeichert werden
+ BOOL bRemoveAny = lcl_RemoveAny( pDocument, nCol, nTab );
+ USHORT nEffCount = nSaveCount;
+ if ( bRemoveAny )
+ {
+ for (i=0; i<nSaveCount; i++)
+ if ( lcl_RemoveThis( pDocument, nCol, pItems[i].nRow, nTab ) )
+ --nEffCount;
+
+// String aDbg("Tab ");aDbg+=nTab;aDbg+=" Col ";aDbg+=nCol;
+// aDbg+=" Remove ";aDbg+=nSaveCount-nEffCount; DBG_ERROR(aDbg);
+ }
+
+ rStream << nEffCount; // nEffCount: Zellen, die wirklich gespeichert werden
+
+ ScAttrIterator aIter( pAttrArray, 0, MAXROW );
+ USHORT nStt, nEnd;
+ const ScPatternAttr* pAttr;
+ do
+ {
+ pAttr = aIter.Next( nStt, nEnd );
+ }
+ while( pAttr && !pAttr->IsSymbolFont() );
+
+ for (i=0; i<nSaveCount; i++) // nSaveCount: Ende auf MAXROW angepasst
+ {
+ USHORT nRow = pItems[i].nRow;
+
+ if ( !bRemoveAny || !lcl_RemoveThis( pDocument, nCol, nRow, nTab ) )
+ {
+ rStream << nRow;
+
+ pCell = pItems[i].pCell;
+ eCellType = pCell->GetCellType();
+
+ switch( eCellType )
+ {
+ case CELLTYPE_VALUE:
+ rStream << (BYTE) eCellType;
+ ((ScValueCell*)pCell)->Save( rStream );
+ break;
+ case CELLTYPE_STRING:
+ if( pAttr )
+ {
+ if( nRow > nEnd )
+ do
+ {
+ pAttr = aIter.Next( nStt, nEnd );
+ }
+ while( pAttr && !pAttr->IsSymbolFont() );
+ if( pAttr && nRow >= nStt && nRow <= nEnd )
+ eCellType = CELLTYPE_SYMBOLS;
+ }
+ rStream << (BYTE) eCellType;
+ if ( eCellType == CELLTYPE_SYMBOLS )
+ {
+ // cell string contains true symbol characters
+//! CharSet eOld = rStream.GetStreamCharSet();
+//! rStream.SetStreamCharSet( RTL_TEXTENCODING_SYMBOL );
+ ((ScStringCell*)pCell)->Save( rStream );
+//! rStream.SetStreamCharSet( eOld );
+ }
+ else
+ ((ScStringCell*)pCell)->Save( rStream );
+ break;
+ case CELLTYPE_EDIT:
+ rStream << (BYTE) eCellType;
+ ((ScEditCell*)pCell)->Save( rStream );
+ break;
+ case CELLTYPE_FORMULA:
+ rStream << (BYTE) eCellType;
+ ((ScFormulaCell*)pCell)->Save( rStream, aHdr );
+ break;
+ case CELLTYPE_NOTE:
+ rStream << (BYTE) eCellType;
+ ((ScNoteCell*)pCell)->Save( rStream );
+ break;
+ default:
+ {
+ // #53846# soll zwar nicht vorkommen, aber falls doch,
+ // eine leere NoteCell speichern, damit das Dokument
+ // ueberhaupt wieder geladen werden kann.
+ rStream << (BYTE) CELLTYPE_NOTE;
+ ScNoteCell aDummyCell;
+ aDummyCell.Save( rStream );
+ DBG_ERROR( "Falscher Zellentyp" );
+ }
+ break;
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------------------
+
+void ScColumn::LoadNotes( SvStream& rStream )
+{
+ ScReadHeader aHdr(rStream);
+
+ USHORT nNoteCount;
+ rStream >> nNoteCount;
+ for (USHORT i=0; i<nNoteCount && rStream.GetError() == SVSTREAM_OK; i++)
+ {
+ USHORT nPos;
+ rStream >> nPos;
+ if (nPos < nCount)
+ pItems[nPos].pCell->LoadNote(rStream);
+ else
+ {
+ DBG_ERROR("falsche Pos in ScColumn::LoadNotes");
+ rStream.SetError( SVSTREAM_FILEFORMAT_ERROR );
+ }
+ }
+}
+
+USHORT ScColumn::NoteCount( USHORT nMaxRow ) const
+{
+ USHORT nNoteCount = 0;
+ USHORT i;
+
+ for (i=0; i<nCount; i++)
+ if ( pItems[i].pCell->GetNotePtr() && pItems[i].nRow<=nMaxRow )
+ ++nNoteCount;
+
+ return nNoteCount;
+}
+
+void ScColumn::SaveNotes( SvStream& rStream ) const
+{
+ USHORT nSaveMaxRow = pDocument->GetSrcMaxRow();
+ USHORT i;
+
+ BOOL bRemoveAny = lcl_RemoveAny( pDocument, nCol, nTab );
+ USHORT nNoteCount;
+ if ( bRemoveAny )
+ {
+ // vorher zaehlen, wieviele Notizen es werden
+
+ nNoteCount = 0;
+ for (i=0; i<nCount; i++)
+ if ( pItems[i].pCell->GetNotePtr() && pItems[i].nRow<=nSaveMaxRow &&
+ !lcl_RemoveThis( pDocument, nCol, pItems[i].nRow, nTab ) )
+ ++nNoteCount;
+ }
+ else
+ nNoteCount = NoteCount(nSaveMaxRow);
+
+ // Speichern
+ // Als Positionen muessen die Indizes gespeichert werden, die beim Laden entstehen,
+ // also ohne die weggelassenen Zellen mitzuzaehlen.
+
+ ScWriteHeader aHdr(rStream);
+ rStream << nNoteCount;
+
+ USHORT nDestPos = 0;
+ for (i=0; i<nCount && rStream.GetError() == SVSTREAM_OK; i++)
+ {
+ USHORT nRow = pItems[i].nRow;
+ if ( !bRemoveAny || !lcl_RemoveThis( pDocument, nCol, nRow, nTab ) )
+ {
+ const ScPostIt* pNote = pItems[i].pCell->GetNotePtr();
+ if ( pNote && nRow <= nSaveMaxRow )
+ {
+ rStream << nDestPos;
+ rStream << *pNote;
+ }
+ ++nDestPos; // nDestPos zaehlt die in SaveData gespeicherten Zellen
+ }
+ }
+
+ // SetLostData ist schon in SaveData passiert, wenn noetig
+}
+
+// -----------------------------------------------------------------------------------------
+
+BOOL ScColumn::Load( SvStream& rStream, ScMultipleReadHeader& rHdr )
+{
+ rHdr.StartEntry();
+ while (rHdr.BytesLeft() && rStream.GetError() == SVSTREAM_OK)
+ {
+ USHORT nID;
+ rStream >> nID;
+ switch (nID)
+ {
+ case SCID_COLDATA:
+ LoadData( rStream );
+ break;
+ case SCID_COLNOTES:
+ LoadNotes( rStream );
+ break;
+ case SCID_COLATTRIB:
+ pAttrArray->Load( rStream );
+ break;
+ default:
+ {
+ DBG_ERROR("unbekannter Sub-Record in ScColumn::Load");
+ ScReadHeader aDummyHeader( rStream );
+ }
+ }
+ }
+ rHdr.EndEntry();
+
+ return TRUE;
+}
+
+BOOL ScColumn::Save( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const
+{
+ rHdr.StartEntry();
+
+ if (!IsEmptyData()) //! Test, ob alles weggelassen wird?
+ {
+ rStream << (USHORT) SCID_COLDATA;
+ SaveData( rStream );
+ }
+ USHORT nNotes = NoteCount(); //! Test, ob alles weggelassen wird?
+ if (nNotes)
+ {
+ rStream << (USHORT) SCID_COLNOTES;
+ SaveNotes( rStream );
+ }
+ if (!IsEmptyAttr())
+ {
+ rStream << (USHORT) SCID_COLATTRIB;
+ pAttrArray->Save( rStream );
+ }
+
+ rHdr.EndEntry();
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------------------------
+
+ // GetNeededSize: optimale Hoehe / Breite in Pixeln
+
+long ScColumn::GetNeededSize( USHORT nRow, OutputDevice* pDev,
+ double nPPTX, double nPPTY,
+ const Fraction& rZoomX, const Fraction& rZoomY,
+ BOOL bWidth, const ScNeededSizeOptions& rOptions )
+{
+ long nValue=0;
+ USHORT nIndex;
+ double nPPT = bWidth ? nPPTX : nPPTY;
+ if (Search(nRow,nIndex))
+ {
+ const ScPatternAttr* pPattern = rOptions.pPattern;
+ if (!pPattern)
+ pPattern = pAttrArray->GetPattern( nRow );
+
+ // zusammengefasst?
+ // Merge nicht in bedingter Formatierung
+
+ const ScMergeAttr* pMerge = (const ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE);
+ const ScMergeFlagAttr* pFlag = (const ScMergeFlagAttr*)&pPattern->GetItem(ATTR_MERGE_FLAG);
+
+ if ( bWidth )
+ {
+ if ( pFlag->IsHorOverlapped() )
+ return 0;
+ if ( rOptions.bSkipMerged && pMerge->GetColMerge() > 1 )
+ return 0;
+ }
+ else
+ {
+ if ( pFlag->IsVerOverlapped() )
+ return 0;
+ if ( rOptions.bSkipMerged && pMerge->GetRowMerge() > 1 )
+ return 0;
+ }
+
+ // bedingte Formatierung
+ const SfxItemSet* pCondSet = NULL;
+ if ( ((const SfxUInt32Item&)pPattern->GetItem(ATTR_CONDITIONAL)).GetValue() )
+ pCondSet = pDocument->GetCondResult( nCol, nRow, nTab );
+
+ // Zeilenumbruch?
+
+ const SfxPoolItem* pCondItem;
+ SvxCellHorJustify eHorJust;
+ if (pCondSet &&
+ pCondSet->GetItemState(ATTR_HOR_JUSTIFY, TRUE, &pCondItem) == SFX_ITEM_SET)
+ eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem*)pCondItem)->GetValue();
+ else
+ eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&)
+ pPattern->GetItem( ATTR_HOR_JUSTIFY )).GetValue();
+ BOOL bBreak;
+ if ( eHorJust == SVX_HOR_JUSTIFY_BLOCK )
+ bBreak = TRUE;
+ else if ( pCondSet &&
+ pCondSet->GetItemState(ATTR_LINEBREAK, TRUE, &pCondItem) == SFX_ITEM_SET)
+ bBreak = ((const SfxBoolItem*)pCondItem)->GetValue();
+ else
+ bBreak = ((const SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue();
+
+ if ( bWidth && bBreak )
+ return 0;
+
+ // restliche Attribute aus Pattern und bedingter Formatierung zusammensuchen
+
+ SvxCellOrientation eOrient;
+ if (pCondSet &&
+ pCondSet->GetItemState(ATTR_ORIENTATION, TRUE, &pCondItem) == SFX_ITEM_SET)
+ eOrient = (SvxCellOrientation)((const SvxOrientationItem*)pCondItem)->GetValue();
+ else
+ eOrient = (SvxCellOrientation)((const SvxOrientationItem&)
+ pPattern->GetItem(ATTR_ORIENTATION)).GetValue();
+ long nRotate = 0;
+ SvxRotateMode eRotMode = SVX_ROTATE_MODE_STANDARD;
+ if ( eOrient == SVX_ORIENTATION_STANDARD )
+ {
+ if (pCondSet &&
+ pCondSet->GetItemState(ATTR_ROTATE_VALUE, TRUE, &pCondItem) == SFX_ITEM_SET)
+ nRotate = ((const SfxInt32Item*)pCondItem)->GetValue();
+ else
+ nRotate = ((const SfxInt32Item&)pPattern->GetItem(ATTR_ROTATE_VALUE)).GetValue();
+ if ( nRotate )
+ {
+ if (pCondSet &&
+ pCondSet->GetItemState(ATTR_ROTATE_MODE, TRUE, &pCondItem) == SFX_ITEM_SET)
+ eRotMode = (SvxRotateMode)((const SvxRotateModeItem*)pCondItem)->GetValue();
+ else
+ eRotMode = (SvxRotateMode)((const SvxRotateModeItem&)
+ pPattern->GetItem(ATTR_ROTATE_MODE)).GetValue();
+
+ if ( nRotate == 18000 )
+ eRotMode = SVX_ROTATE_MODE_STANDARD; // keinen Ueberlauf
+ }
+ }
+ const SvxMarginItem* pMargin;
+ if (pCondSet &&
+ pCondSet->GetItemState(ATTR_MARGIN, TRUE, &pCondItem) == SFX_ITEM_SET)
+ pMargin = (const SvxMarginItem*) pCondItem;
+ else
+ pMargin = (const SvxMarginItem*) &pPattern->GetItem(ATTR_MARGIN);
+ USHORT nIndent = 0;
+ if ( eHorJust == SVX_HOR_JUSTIFY_LEFT )
+ {
+ if (pCondSet &&
+ pCondSet->GetItemState(ATTR_INDENT, TRUE, &pCondItem) == SFX_ITEM_SET)
+ nIndent = ((const SfxUInt16Item*)pCondItem)->GetValue();
+ else
+ nIndent = ((const SfxUInt16Item&)pPattern->GetItem(ATTR_INDENT)).GetValue();
+ }
+
+ // SetFont auch bei Edit-Zellen, weil bGetFont evtl. nur einmal gesetzt ist
+ if (rOptions.bGetFont)
+ {
+ Fraction aFontZoom = ( eOrient == SVX_ORIENTATION_STANDARD ) ? rZoomX : rZoomY;
+ Font aFont;
+ pPattern->GetFont( aFont, pDev, &aFontZoom, pCondSet );
+ pDev->SetFont(aFont);
+ }
+
+ BOOL bAddMargin = TRUE;
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ BOOL bEditEngine = ( pCell->GetCellType() == CELLTYPE_EDIT ||
+ eOrient == SVX_ORIENTATION_STACKED );
+
+ if (!bEditEngine) // direkte Ausgabe
+ {
+ String aValStr;
+ Color* pColor;
+ SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
+ ULONG nFormat = pPattern->GetNumberFormat( pFormatter, pCondSet );
+ ScCellFormat::GetString( pCell, nFormat, aValStr, &pColor,
+ *pFormatter,
+ TRUE, rOptions.bFormula, ftCheck );
+ if (aValStr.Len())
+ {
+ // SetFont ist nach oben verschoben
+
+ Size aSize( pDev->GetTextWidth( aValStr ), pDev->GetTextHeight() );
+ if ( eOrient != SVX_ORIENTATION_STANDARD )
+ {
+ long nTemp = aSize.Width();
+ aSize.Width() = aSize.Height();
+ aSize.Height() = nTemp;
+ }
+ else if ( nRotate )
+ {
+ //! unterschiedliche Skalierung X/Y beruecksichtigen
+
+ double nRealOrient = nRotate * F_PI18000; // nRotate sind 1/100 Grad
+ double nCosAbs = fabs( cos( nRealOrient ) );
+ double nSinAbs = fabs( sin( nRealOrient ) );
+ long nHeight = (long)( aSize.Height() * nCosAbs + aSize.Width() * nSinAbs );
+ long nWidth;
+ if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
+ nWidth = (long)( aSize.Width() * nCosAbs + aSize.Height() * nSinAbs );
+ else if ( rOptions.bTotalSize )
+ {
+ nWidth = (long) ( pDocument->GetColWidth( nCol,nTab ) * nPPT );
+ bAddMargin = FALSE;
+ // nur nach rechts:
+ //! unterscheiden nach Ausrichtung oben/unten (nur Text/ganze Hoehe)
+ if ( pPattern->GetRotateDir( pCondSet ) == SC_ROTDIR_RIGHT )
+ nWidth += (long)( pDocument->GetRowHeight( nRow,nTab ) *
+ nPPT * nCosAbs / nSinAbs );
+ }
+ else
+ nWidth = (long)( aSize.Height() / nSinAbs ); //! begrenzen?
+
+ if ( bBreak && !rOptions.bTotalSize )
+ {
+ // #47744# limit size for line break
+ long nCmp = pDev->GetFont().GetSize().Height() * SC_ROT_BREAK_FACTOR;
+ if ( nHeight > nCmp )
+ nHeight = nCmp;
+ }
+
+ aSize = Size( nWidth, nHeight );
+ }
+ nValue = bWidth ? aSize.Width() : aSize.Height();
+
+ if ( bAddMargin )
+ {
+ if (bWidth)
+ {
+ nValue += (long) ( pMargin->GetLeftMargin() * nPPT ) +
+ (long) ( pMargin->GetRightMargin() * nPPT );
+ if ( nIndent )
+ nValue += (long) ( nIndent * nPPT );
+ }
+ else
+ nValue += (long) ( pMargin->GetTopMargin() * nPPT ) +
+ (long) ( pMargin->GetBottomMargin() * nPPT );
+ }
+
+ // Zeilenumbruch ausgefuehrt ?
+
+ if ( bBreak && !bWidth )
+ {
+ // Test mit EditEngine zur Sicherheit schon bei 90%
+ // (wegen Rundungsfehlern und weil EditEngine teilweise anders formatiert)
+
+ long nDocPixel = (long) ( ( pDocument->GetColWidth( nCol,nTab ) -
+ pMargin->GetLeftMargin() - pMargin->GetRightMargin() -
+ nIndent )
+ * nPPT );
+ nDocPixel = (nDocPixel * 9) / 10; // zur Sicherheit
+ if ( aSize.Width() > nDocPixel )
+ bEditEngine = TRUE;
+ }
+ }
+ }
+
+ if (bEditEngine)
+ {
+ // der Font wird bei !bEditEngine nicht jedesmal neu gesetzt
+ Font aOldFont = pDev->GetFont();
+
+ MapMode aHMMMode( MAP_100TH_MM, Point(), rZoomX, rZoomY );
+
+ // am Dokument speichern ?
+ ScEditEngineDefaulter* pEngine = new ScFieldEditEngine(
+ pDocument->GetEnginePool(), pDocument->GetEditPool() );
+ MapMode aOld = pDev->GetMapMode();
+ pDev->SetMapMode( aHMMMode );
+ pEngine->SetRefDevice( pDev );
+ SfxItemSet* pSet = new SfxItemSet( pEngine->GetEmptyItemSet() );
+ pPattern->FillEditItemSet( pSet, pCondSet );
+ pEngine->SetDefaults( pSet );
+
+ Size aPaper = Size( 1000000, 1000000 );
+ if (eOrient==SVX_ORIENTATION_STACKED)
+ aPaper.Width() = 1;
+ else if (bBreak)
+ {
+ // bei ausgeblendeten Spalten die alte Spaltenbreite:
+ long nDocWidth = (long) ( pDocument->GetOriginalWidth(nCol,nTab) * nPPTX );
+ USHORT nColMerge = pMerge->GetColMerge();
+ if (nColMerge > 1)
+ for (USHORT nColAdd=1; nColAdd<nColMerge; nColAdd++)
+ nDocWidth += (long) ( pDocument->GetColWidth(nCol+nColAdd,nTab) * nPPTX );
+ nDocWidth -= (long) ( pMargin->GetLeftMargin() * nPPTX )
+ + (long) ( pMargin->GetRightMargin() * nPPTX )
+ + 1; // Ausgabebereich ist Breite-1 Pixel (wegen Gitterlinien)
+ if ( nIndent )
+ nDocWidth -= (long) ( nIndent * nPPTX );
+
+ // Platz fuer Autofilter-Button: 20 * nZoom/100
+ if ( pFlag->HasAutoFilter() )
+ nDocWidth -= (rZoomX.GetNumerator()*20)/rZoomX.GetDenominator();
+
+ aPaper.Width() = nDocWidth;
+ aPaper = pDev->PixelToLogic( aPaper, aHMMMode );
+ }
+ pEngine->SetPaperSize(aPaper);
+
+ if ( pCell->GetCellType() == CELLTYPE_EDIT )
+ {
+ const EditTextObject* pData;
+ ((ScEditCell*)pCell)->GetData(pData);
+ pEngine->SetText(*pData);
+ }
+ else
+ {
+ Color* pColor;
+ SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
+ ULONG nFormat = pPattern->GetNumberFormat( pFormatter, pCondSet );
+ String aString;
+ ScCellFormat::GetString( pCell, nFormat, aString, &pColor,
+ *pFormatter,
+ TRUE, rOptions.bFormula, ftCheck );
+ pEngine->SetText(aString);
+ }
+
+ BOOL bEdWidth = bWidth;
+ if ( eOrient != SVX_ORIENTATION_STANDARD && eOrient != SVX_ORIENTATION_STACKED )
+ bEdWidth = !bEdWidth;
+ if ( nRotate )
+ {
+ //! unterschiedliche Skalierung X/Y beruecksichtigen
+
+ Size aSize( pEngine->CalcTextWidth(), pEngine->GetTextHeight() );
+ double nRealOrient = nRotate * F_PI18000; // nRotate sind 1/100 Grad
+ double nCosAbs = fabs( cos( nRealOrient ) );
+ double nSinAbs = fabs( sin( nRealOrient ) );
+ long nHeight = (long)( aSize.Height() * nCosAbs + aSize.Width() * nSinAbs );
+ long nWidth;
+ if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
+ nWidth = (long)( aSize.Width() * nCosAbs + aSize.Height() * nSinAbs );
+ else if ( rOptions.bTotalSize )
+ {
+ nWidth = (long) ( pDocument->GetColWidth( nCol,nTab ) * nPPT );
+ bAddMargin = FALSE;
+ if ( pPattern->GetRotateDir( pCondSet ) == SC_ROTDIR_RIGHT )
+ nWidth += (long)( pDocument->GetRowHeight( nRow,nTab ) *
+ nPPT * nCosAbs / nSinAbs );
+ }
+ else
+ nWidth = (long)( aSize.Height() / nSinAbs ); //! begrenzen?
+ aSize = Size( nWidth, nHeight );
+
+ Size aPixSize = pDev->LogicToPixel( aSize, aHMMMode );
+ if ( bEdWidth )
+ nValue = aPixSize.Width();
+ else
+ {
+ nValue = aPixSize.Height();
+
+ if ( bBreak && !rOptions.bTotalSize )
+ {
+ // #47744# limit size for line break
+ long nCmp = aOldFont.GetSize().Height() * SC_ROT_BREAK_FACTOR;
+ if ( nValue > nCmp )
+ nValue = nCmp;
+ }
+ }
+ }
+ else if ( bEdWidth )
+ {
+ if (bBreak)
+ nValue = 0;
+ else
+ nValue = pDev->LogicToPixel(Size( pEngine->CalcTextWidth(), 0 ),
+ aHMMMode).Width();
+ }
+ else // Hoehe
+ {
+ nValue = pDev->LogicToPixel(Size( 0, pEngine->GetTextHeight() ),
+ aHMMMode).Height();
+ }
+
+ if ( nValue && bAddMargin )
+ {
+ if (bWidth)
+ {
+ nValue += (long) ( pMargin->GetLeftMargin() * nPPT ) +
+ (long) ( pMargin->GetRightMargin() * nPPT );
+ if (nIndent)
+ nValue += (long) ( nIndent * nPPT );
+ }
+ else
+ nValue += (long) ( pMargin->GetTopMargin() * nPPT ) +
+ (long) ( pMargin->GetBottomMargin() * nPPT );
+ }
+
+ delete pEngine;
+ pDev->SetMapMode( aOld );
+ pDev->SetFont( aOldFont );
+ }
+
+ if (bWidth)
+ {
+ // Platz fuer Autofilter-Button
+ // 20 * nZoom/100
+ // bedingte Formatierung hier nicht interessant
+
+ INT16 nFlags = ((const ScMergeFlagAttr&)pPattern->GetItem(ATTR_MERGE_FLAG)).GetValue();
+ if (nFlags & SC_MF_AUTO)
+ nValue += (rZoomX.GetNumerator()*20)/rZoomX.GetDenominator();
+ }
+ }
+ return nValue;
+}
+
+long ScColumn::GetSimpleTextNeededSize( USHORT nIndex, OutputDevice* pDev,
+ BOOL bWidth )
+{
+ long nValue=0;
+ if ( nIndex < nCount )
+ {
+ USHORT nRow = pItems[nIndex].nRow;
+ const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ String aValStr;
+ Color* pColor;
+ SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
+ ULONG nFormat = pPattern->GetNumberFormat( pFormatter );
+ ScCellFormat::GetString( pCell, nFormat, aValStr, &pColor,
+ *pFormatter, TRUE, FALSE, ftCheck );
+ if ( aValStr.Len() )
+ {
+ if ( bWidth )
+ nValue = pDev->GetTextWidth( aValStr );
+ else
+ nValue = pDev->GetTextHeight();
+ }
+ }
+ return nValue;
+}
+
+USHORT ScColumn::GetOptimalColWidth( OutputDevice* pDev, double nPPTX, double nPPTY,
+ const Fraction& rZoomX, const Fraction& rZoomY,
+ BOOL bFormula, USHORT nOldWidth,
+ const ScMarkData* pMarkData,
+ BOOL bSimpleTextImport )
+{
+ if (nCount == 0)
+ return nOldWidth;
+
+ USHORT nWidth = (USHORT) (nOldWidth * nPPTX);
+ BOOL bFound = FALSE;
+
+ USHORT nIndex;
+ ScMarkedDataIter aDataIter(this, pMarkData, TRUE);
+ if ( bSimpleTextImport )
+ { // alles eins bis auf NumberFormate
+ const ScPatternAttr* pPattern = GetPattern( 0 );
+ Font aFont;
+ pPattern->GetFont( aFont, pDev, &rZoomX, NULL );
+ pDev->SetFont( aFont );
+ const SvxMarginItem* pMargin = (const SvxMarginItem*) &pPattern->GetItem(ATTR_MARGIN);
+ long nMargin = (long) ( pMargin->GetLeftMargin() * nPPTX ) +
+ (long) ( pMargin->GetRightMargin() * nPPTX );
+
+ while (aDataIter.Next( nIndex ))
+ {
+ USHORT nThis = (USHORT) (GetSimpleTextNeededSize( nIndex, pDev,
+ TRUE ) + nMargin);
+ if (nThis)
+ {
+ if (nThis>nWidth || !bFound)
+ {
+ nWidth = nThis;
+ bFound = TRUE;
+ }
+ }
+ }
+ }
+ else
+ {
+ ScNeededSizeOptions aOptions;
+ aOptions.bFormula = bFormula;
+ const ScPatternAttr* pOldPattern = NULL;
+
+ while (aDataIter.Next( nIndex ))
+ {
+ USHORT nRow = pItems[nIndex].nRow;
+ const ScPatternAttr* pPattern = GetPattern( nRow );
+ aOptions.pPattern = pPattern;
+ aOptions.bGetFont = (pPattern != pOldPattern);
+ USHORT nThis = (USHORT) GetNeededSize( nRow, pDev, nPPTX, nPPTY,
+ rZoomX, rZoomY, TRUE, aOptions );
+ pOldPattern = pPattern;
+ if (nThis)
+ {
+ if (nThis>nWidth || !bFound)
+ {
+ nWidth = nThis;
+ bFound = TRUE;
+ }
+ }
+ }
+ }
+
+ if (bFound)
+ {
+ nWidth += 2;
+ USHORT nTwips = (USHORT) (nWidth / nPPTX);
+ return nTwips;
+ }
+ else
+ return nOldWidth;
+}
+
+// pHeight in Twips
+// nMinHeight, nMinStart zur Optimierung: ab nRow >= nMinStart ist mindestens nMinHeight
+// (wird nur bei bStdAllowed ausgewertet)
+
+void ScColumn::GetOptimalHeight( USHORT nStartRow, USHORT nEndRow, USHORT* pHeight,
+ OutputDevice* pDev,
+ double nPPTX, double nPPTY,
+ const Fraction& rZoomX, const Fraction& rZoomY,
+ BOOL bShrink, USHORT nMinHeight, USHORT nMinStart )
+{
+ ScAttrIterator aIter( pAttrArray, nStartRow, nEndRow );
+
+ USHORT nStart;
+ USHORT nEnd;
+ USHORT nEditPos = 0;
+ USHORT nNextEnd = 0;
+
+ // bei bedingter Formatierung werden immer die einzelnen Zellen angesehen
+
+ const ScPatternAttr* pPattern = aIter.Next(nStart,nEnd);
+ while ( pPattern )
+ {
+ const ScMergeAttr* pMerge = (const ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE);
+ const ScMergeFlagAttr* pFlag = (const ScMergeFlagAttr*)&pPattern->GetItem(ATTR_MERGE_FLAG);
+ if ( pMerge->GetRowMerge() > 1 || pFlag->IsOverlapped() )
+ {
+ // nix - vertikal bei der zusammengefassten und den ueberdeckten,
+ // horizontal nur bei den ueberdeckten (unsichtbaren) -
+ // eine nur horizontal zusammengefasste wird aber beruecksichtigt
+ }
+ else
+ {
+ USHORT nRow;
+ USHORT nHeight;
+ BOOL bStdAllowed = ((const SvxOrientationItem&) pPattern->GetItem(ATTR_ORIENTATION)).
+ GetValue() == (USHORT) SVX_ORIENTATION_STANDARD;
+ BOOL bStdOnly = FALSE;
+ if (bStdAllowed)
+ {
+ BOOL bBreak = ((SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue() ||
+ ((SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->
+ GetItem( ATTR_HOR_JUSTIFY )).GetValue() ==
+ SVX_HOR_JUSTIFY_BLOCK);
+ bStdOnly = !bBreak;
+
+ // bedingte Formatierung: Zellen durchgehen
+ if ( bStdOnly && ((const SfxUInt32Item&)pPattern->
+ GetItem(ATTR_CONDITIONAL)).GetValue() )
+ bStdOnly = FALSE;
+
+ // gedrehter Text: Zellen durchgehen
+ if ( bStdOnly && ((const SfxInt32Item&)pPattern->
+ GetItem(ATTR_ROTATE_VALUE)).GetValue() )
+ bStdOnly = FALSE;
+ }
+
+ if (bStdOnly)
+ if (HasEditCells(nStart,nEnd,nEditPos))
+ {
+ if (nEditPos == nStart)
+ {
+ bStdOnly = FALSE;
+ if (nEnd > nEditPos)
+ nNextEnd = nEnd;
+ nEnd = nEditPos; // einzeln ausrechnen
+ bStdAllowed = FALSE; // wird auf jeden Fall per Zelle berechnet
+ }
+ else
+ {
+ nNextEnd = nEnd;
+ nEnd = nEditPos - 1; // Standard - Teil
+ }
+ }
+
+ if (bStdAllowed)
+ {
+ nHeight = (USHORT) ((const SvxFontHeightItem&) pPattern->GetItem(ATTR_FONT_HEIGHT)).
+ GetHeight();
+ const SvxMarginItem* pMargin = (const SvxMarginItem*) &pPattern->GetItem(ATTR_MARGIN);
+ nHeight += nHeight / 5;
+ // gibt bei 10pt 240
+
+ if ( nHeight + 240 > ScGlobal::nDefFontHeight )
+ {
+ nHeight += ScGlobal::nDefFontHeight;
+ nHeight -= 240;
+ }
+
+ // Standard-Hoehe: TextHeight + Raender - 23
+ // -> 257 unter Windows
+
+ if (nHeight > STD_ROWHEIGHT_DIFF)
+ nHeight -= STD_ROWHEIGHT_DIFF;
+
+ nHeight += pMargin->GetTopMargin() + pMargin->GetBottomMargin();
+
+ //! OS2: 1pt mehr ?? (+20)
+
+ // wenn eh alles schon groesser ist, muss die Schleife nicht mehr
+ // ewig durchgenudelt werden
+ USHORT nStdEnd = nEnd;
+ if ( nHeight <= nMinHeight && nStdEnd >= nMinStart )
+ nStdEnd = nMinStart ? nMinStart-1 : 0;
+
+ for (nRow=nStart; nRow<=nStdEnd; nRow++)
+ if (nHeight > pHeight[nRow-nStartRow])
+ pHeight[nRow-nStartRow] = nHeight;
+ }
+
+ if (!bStdOnly) // belegte Zellen suchen
+ {
+ ScNeededSizeOptions aOptions;
+
+ USHORT nIndex;
+ Search(nStart,nIndex);
+ while ( (nIndex < nCount) ? ((nRow=pItems[nIndex].nRow) <= nEnd) : FALSE )
+ {
+ // Zellhoehe nur berechnen, wenn sie spaeter auch gebraucht wird (#37928#)
+
+ if ( bShrink || !(pDocument->GetRowFlags(nRow, nTab) & CR_MANUALSIZE) )
+ {
+ aOptions.pPattern = pPattern;
+ nHeight = (USHORT)
+ ( GetNeededSize( nRow, pDev, nPPTX, nPPTY,
+ rZoomX, rZoomY, FALSE, aOptions ) / nPPTY );
+ if (nHeight > pHeight[nRow-nStartRow])
+ pHeight[nRow-nStartRow] = nHeight;
+ }
+ ++nIndex;
+ }
+ }
+ }
+
+ if (nNextEnd)
+ {
+ nStart = nEnd + 1;
+ nEnd = nNextEnd;
+ nNextEnd = 0;
+ }
+ else
+ pPattern = aIter.Next(nStart,nEnd);
+ }
+}
+
+BOOL ScColumn::GetNextSpellingCell(USHORT& nRow, BOOL bInSel, const ScMarkData& rData) const
+{
+ BOOL bStop = FALSE;
+ CellType eCellType;
+ USHORT nIndex;
+ if (!bInSel && Search(nRow, nIndex))
+ {
+ eCellType = GetCellType(nRow);
+ if ( (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT) &&
+ !(HasAttrib( nRow, nRow, HASATTR_PROTECTED) &&
+ pDocument->IsTabProtected(nTab)) )
+ return TRUE;
+ }
+ while (!bStop)
+ {
+ if (bInSel)
+ {
+ nRow = rData.GetNextMarked(nCol, nRow, FALSE);
+ if (nRow > MAXROW)
+ {
+ nRow = MAXROW+1;
+ bStop = TRUE;
+ }
+ else
+ {
+ eCellType = GetCellType(nRow);
+ if ( (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT) &&
+ !(HasAttrib( nRow, nRow, HASATTR_PROTECTED) &&
+ pDocument->IsTabProtected(nTab)) )
+ return TRUE;
+ else
+ nRow++;
+ }
+ }
+ else if (GetNextDataPos(nRow))
+ {
+ eCellType = GetCellType(nRow);
+ if ( (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT) &&
+ !(HasAttrib( nRow, nRow, HASATTR_PROTECTED) &&
+ pDocument->IsTabProtected(nTab)) )
+ return TRUE;
+ else
+ nRow++;
+ }
+ else
+ {
+ nRow = MAXROW+1;
+ bStop = TRUE;
+ }
+ }
+ return FALSE;
+}
+
+// =========================================================================================
+
+void ScColumn::RemoveAutoSpellObj()
+{
+ ScTabEditEngine* pEngine = NULL;
+
+ for (USHORT i=0; i<nCount; i++)
+ if ( pItems[i].pCell->GetCellType() == CELLTYPE_EDIT )
+ {
+ ScEditCell* pOldCell = (ScEditCell*) pItems[i].pCell;
+ const EditTextObject* pData = pOldCell->GetData();
+ // keine Abfrage auf HasOnlineSpellErrors, damit es auch
+ // nach dem Laden funktioniert
+
+ // Fuer den Test auf harte Formatierung (ScEditAttrTester) sind die Defaults
+ // in der EditEngine unwichtig. Wenn der Tester spaeter einmal gleiche
+ // Attribute in Default und harter Formatierung erkennen und weglassen sollte,
+ // muessten an der EditEngine zu jeder Zelle die richtigen Defaults gesetzt
+ // werden!
+
+ // auf Attribute testen
+ if ( !pEngine )
+ pEngine = new ScTabEditEngine(pDocument);
+ pEngine->SetText( *pData );
+ ScEditAttrTester aTester( pEngine );
+ if ( aTester.NeedsObject() ) // nur Spell-Errors entfernen
+ {
+ EditTextObject* pNewData = pEngine->CreateTextObject(); // ohne BIGOBJ
+ pOldCell->SetData( pNewData, pEngine->GetEditTextObjectPool() );
+ delete pNewData;
+ }
+ else // String erzeugen
+ {
+ String aText = ScEditUtil::GetSpaceDelimitedString( *pEngine );
+ ScBaseCell* pNewCell = new ScStringCell( aText );
+ ScBroadcasterList* pBC = pOldCell->GetBroadcaster();
+ pNewCell->SetBroadcaster( pBC );
+ pOldCell->ForgetBroadcaster();
+ if (pOldCell->GetNotePtr())
+ pNewCell->SetNote( *pOldCell->GetNotePtr() );
+ pItems[i].pCell = pNewCell;
+ delete pOldCell;
+ }
+ }
+
+ delete pEngine;
+}
+
+void ScColumn::RemoveEditAttribs( USHORT nStartRow, USHORT nEndRow )
+{
+ ScFieldEditEngine* pEngine = NULL;
+
+ USHORT i;
+ Search( nStartRow, i );
+ for (; i<nCount && pItems[i].nRow <= nEndRow; i++)
+ if ( pItems[i].pCell->GetCellType() == CELLTYPE_EDIT )
+ {
+ ScEditCell* pOldCell = (ScEditCell*) pItems[i].pCell;
+ const EditTextObject* pData = pOldCell->GetData();
+
+ // Fuer den Test auf harte Formatierung (ScEditAttrTester) sind die Defaults
+ // in der EditEngine unwichtig. Wenn der Tester spaeter einmal gleiche
+ // Attribute in Default und harter Formatierung erkennen und weglassen sollte,
+ // muessten an der EditEngine zu jeder Zelle die richtigen Defaults gesetzt
+ // werden!
+
+ // auf Attribute testen
+ if ( !pEngine )
+ {
+ //pEngine = new ScTabEditEngine(pDocument);
+ pEngine = new ScFieldEditEngine( pDocument->GetEditPool() );
+ // EE_CNTRL_ONLINESPELLING falls schon Fehler drin sind
+ pEngine->SetControlWord( pEngine->GetControlWord() | EE_CNTRL_ONLINESPELLING );
+ }
+ pEngine->SetText( *pData );
+ USHORT nParCount = pEngine->GetParagraphCount();
+ for (USHORT nPar=0; nPar<nParCount; nPar++)
+ {
+ pEngine->QuickRemoveCharAttribs( nPar );
+ const SfxItemSet& rOld = pEngine->GetParaAttribs( nPar );
+ if ( rOld.Count() )
+ {
+ SfxItemSet aNew( *rOld.GetPool(), rOld.GetRanges() ); // leer
+ pEngine->SetParaAttribs( nPar, aNew );
+ }
+ }
+ // URL-Felder in Text wandeln (andere gibt's nicht, darum pType=0)
+ pEngine->RemoveFields( TRUE );
+
+ BOOL bSpellErrors = pEngine->HasOnlineSpellErrors();
+ BOOL bNeedObject = bSpellErrors || nParCount>1; // Errors/Absaetze behalten
+ // ScEditAttrTester nicht mehr noetig, Felder sind raus
+
+ if ( bNeedObject ) // bleibt Edit-Zelle
+ {
+ ULONG nCtrl = pEngine->GetControlWord();
+ ULONG nWantBig = bSpellErrors ? EE_CNTRL_ALLOWBIGOBJS : 0;
+ if ( ( nCtrl & EE_CNTRL_ALLOWBIGOBJS ) != nWantBig )
+ pEngine->SetControlWord( (nCtrl & ~EE_CNTRL_ALLOWBIGOBJS) | nWantBig );
+ EditTextObject* pNewData = pEngine->CreateTextObject();
+ pOldCell->SetData( pNewData, pEngine->GetEditTextObjectPool() );
+ delete pNewData;
+ }
+ else // String erzeugen
+ {
+ String aText = ScEditUtil::GetSpaceDelimitedString( *pEngine );
+ ScBaseCell* pNewCell = new ScStringCell( aText );
+ ScBroadcasterList* pBC = pOldCell->GetBroadcaster();
+ pNewCell->SetBroadcaster( pBC );
+ pOldCell->ForgetBroadcaster();
+ if (pOldCell->GetNotePtr())
+ pNewCell->SetNote( *pOldCell->GetNotePtr() );
+ pItems[i].pCell = pNewCell;
+ delete pOldCell;
+ }
+ }
+
+ delete pEngine;
+}
+
+// =========================================================================================
+
+BOOL ScColumn::TestTabRefAbs(USHORT nTable)
+{
+ BOOL bRet = FALSE;
+ if (pItems)
+ for (USHORT i = 0; i < nCount; i++)
+ if ( pItems[i].pCell->GetCellType() == CELLTYPE_FORMULA )
+ if (((ScFormulaCell*)pItems[i].pCell)->TestTabRefAbs(nTable))
+ bRet = TRUE;
+ return bRet;
+}
+
+// =========================================================================================
+
+ScColumnIterator::ScColumnIterator( const ScColumn* pCol, USHORT nStart, USHORT nEnd ) :
+ pColumn( pCol ),
+ nTop( nStart ),
+ nBottom( nEnd )
+{
+ pColumn->Search( nTop, nPos );
+}
+
+ScColumnIterator::~ScColumnIterator()
+{
+}
+
+BOOL ScColumnIterator::Next( USHORT& rRow, ScBaseCell*& rpCell )
+{
+ if ( nPos < pColumn->nCount )
+ {
+ rRow = pColumn->pItems[nPos].nRow;
+ if ( rRow <= nBottom )
+ {
+ rpCell = pColumn->pItems[nPos].pCell;
+ ++nPos;
+ return TRUE;
+ }
+ }
+
+ rRow = 0;
+ rpCell = NULL;
+ return FALSE;
+}
+
+USHORT ScColumnIterator::GetIndex() const // Index zur letzen abgefragten Zelle
+{
+ return nPos - 1; // bei Next ist Pos hochgezaehlt worden
+}
+
+// -----------------------------------------------------------------------------------------
+
+ScMarkedDataIter::ScMarkedDataIter( const ScColumn* pCol, const ScMarkData* pMarkData,
+ BOOL bAllIfNone ) :
+ pColumn( pCol ),
+ pMarkIter( NULL ),
+ bNext( TRUE ),
+ bAll( bAllIfNone )
+{
+ if (pMarkData && pMarkData->IsMultiMarked())
+ pMarkIter = new ScMarkArrayIter( pMarkData->GetArray() + pCol->GetCol() );
+}
+
+ScMarkedDataIter::~ScMarkedDataIter()
+{
+ delete pMarkIter;
+}
+
+BOOL ScMarkedDataIter::Next( USHORT& rIndex )
+{
+ BOOL bFound = FALSE;
+ do
+ {
+ if (bNext)
+ {
+ if (!pMarkIter || !pMarkIter->Next( nTop, nBottom ))
+ {
+ if (bAll) // ganze Spalte
+ {
+ nTop = 0;
+ nBottom = MAXROW;
+ }
+ else
+ return FALSE;
+ }
+ pColumn->Search( nTop, nPos );
+ bNext = FALSE;
+ bAll = FALSE; // nur beim ersten Versuch
+ }
+
+ if ( nPos >= pColumn->nCount )
+ return FALSE;
+
+ if ( pColumn->pItems[nPos].nRow <= nBottom )
+ bFound = TRUE;
+ else
+ bNext = TRUE;
+ }
+ while (!bFound);
+
+ rIndex = nPos++;
+ return TRUE;
+}
+
+USHORT ScColumn::GetErrorData( USHORT nRow ) const
+{
+ USHORT nIndex;
+ if (Search(nRow, nIndex))
+ {
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ switch (pCell->GetCellType())
+ {
+ case CELLTYPE_FORMULA :
+ return ((ScFormulaCell*)pCell)->GetErrCode();
+ break;
+ default:
+ return 0;
+ }
+ }
+ return 0;
+}
+
+//------------
+
+BOOL ScColumn::IsEmptyData() const
+{
+ return (nCount == 0);
+}
+
+BOOL ScColumn::IsEmptyVisData(BOOL bNotes) const
+{
+ if (!pItems || nCount == 0)
+ return TRUE;
+ else
+ {
+ BOOL bVisData = FALSE;
+ USHORT i;
+ for (i=0; i<nCount && !bVisData; i++)
+ {
+ ScBaseCell* pCell = pItems[i].pCell;
+ if ( pCell->GetCellType() != CELLTYPE_NOTE || (bNotes && pCell->GetNotePtr()) )
+ bVisData = TRUE;
+ }
+ return !bVisData;
+ }
+}
+
+USHORT ScColumn::VisibleCount( USHORT nStartRow, USHORT nEndRow ) const
+{
+ // Notizen werden nicht mitgezaehlt
+
+ USHORT nVisCount = 0;
+ USHORT nIndex;
+ Search( nStartRow, nIndex );
+ while ( nIndex < nCount && pItems[nIndex].nRow <= nEndRow )
+ {
+ if ( pItems[nIndex].nRow >= nStartRow &&
+ pItems[nIndex].pCell->GetCellType() != CELLTYPE_NOTE )
+ {
+ ++nVisCount;
+ }
+ ++nIndex;
+ }
+ return nVisCount;
+}
+
+USHORT ScColumn::GetLastVisDataPos(BOOL bNotes) const
+{
+ USHORT nRet = 0;
+ if (pItems)
+ {
+ USHORT i;
+ BOOL bFound = FALSE;
+ for (i=nCount; i>0 && !bFound; )
+ {
+ --i;
+ ScBaseCell* pCell = pItems[i].pCell;
+ if ( pCell->GetCellType() != CELLTYPE_NOTE || (bNotes && pCell->GetNotePtr()) )
+ {
+ bFound = TRUE;
+ nRet = pItems[i].nRow;
+ }
+ }
+ }
+ return nRet;
+}
+
+USHORT ScColumn::GetFirstVisDataPos(BOOL bNotes) const
+{
+ USHORT nRet = 0;
+ if (pItems)
+ {
+ USHORT i;
+ BOOL bFound = FALSE;
+ for (i=0; i<nCount && !bFound; i++)
+ {
+ ScBaseCell* pCell = pItems[i].pCell;
+ if ( pCell->GetCellType() != CELLTYPE_NOTE || (bNotes && pCell->GetNotePtr()) )
+ {
+ bFound = TRUE;
+ nRet = pItems[i].nRow;
+ }
+ }
+ }
+ return nRet;
+}
+
+BOOL ScColumn::HasVisibleDataAt(USHORT nRow) const
+{
+ USHORT nIndex;
+ if (Search(nRow, nIndex))
+ if (CellVisible(pItems[nIndex].pCell))
+ return TRUE;
+
+ return FALSE;
+}
+
+BOOL ScColumn::IsEmptyAttr() const
+{
+ if (pAttrArray)
+ return pAttrArray->IsEmpty();
+ else
+ return TRUE;
+}
+
+BOOL ScColumn::IsEmpty() const
+{
+ return (IsEmptyData() && IsEmptyAttr());
+}
+
+BOOL ScColumn::IsEmptyBlock(USHORT nStartRow, USHORT nEndRow) const
+{
+ if ( nCount == 0 || !pItems )
+ return TRUE;
+
+ USHORT nIndex;
+ Search( nStartRow, nIndex );
+ while ( nIndex < nCount && pItems[nIndex].nRow <= nEndRow )
+ {
+ if ( CellVisible(pItems[nIndex].pCell) ) // found a cell
+ return FALSE; // not empty
+ ++nIndex;
+ }
+ return TRUE; // no cell found
+}
+
+USHORT ScColumn::GetEmptyLinesInBlock( USHORT nStartRow, USHORT nEndRow, ScDirection eDir ) const
+{
+ USHORT nLines = 0;
+ BOOL bFound = FALSE;
+ short i;
+ if (pItems && (nCount > 0))
+ {
+ if (eDir == DIR_BOTTOM)
+ {
+ i = nCount;
+ while (!bFound && (i > 0))
+ {
+ i--;
+ if ( pItems[i].nRow < nStartRow )
+ break;
+ bFound = pItems[i].nRow <= nEndRow && CellVisible(pItems[i].pCell);
+ }
+ if (bFound)
+ nLines = nEndRow - pItems[i].nRow;
+ else
+ nLines = nEndRow - nStartRow;
+ }
+ else if (eDir == DIR_TOP)
+ {
+ i = -1;
+ while (!bFound && (i+1 < (short)nCount))
+ {
+ i++;
+ if ( pItems[i].nRow > nEndRow )
+ break;
+ bFound = pItems[i].nRow >= nStartRow && CellVisible(pItems[i].pCell);
+ }
+ if (bFound)
+ nLines = pItems[i].nRow - nStartRow;
+ else
+ nLines = nEndRow - nStartRow;
+ }
+ }
+ else
+ nLines = nEndRow - nStartRow;
+ return nLines;
+}
+
+USHORT ScColumn::GetFirstDataPos() const
+{
+ if (nCount)
+ return pItems[0].nRow;
+ else
+ return 0;
+}
+
+USHORT ScColumn::GetLastDataPos() const
+{
+ if (nCount)
+ return pItems[nCount-1].nRow;
+ else
+ return 0;
+}
+
+BOOL ScColumn::GetPrevDataPos(USHORT& rRow) const
+{
+ BOOL bFound = FALSE;
+ short i = (short)nCount - 1;
+ while (!bFound && (i >= 0))
+ {
+ bFound = (pItems[USHORT(i)].nRow < rRow);
+ if (bFound)
+ rRow = pItems[USHORT(i)].nRow;
+ i--;
+ }
+ return bFound;
+}
+
+BOOL ScColumn::GetNextDataPos(USHORT& rRow) const // groesser als rRow
+{
+ USHORT nIndex;
+ if (Search( rRow, nIndex ))
+ ++nIndex; // naechste Zelle
+
+ BOOL bMore = ( nIndex < nCount );
+ if ( bMore )
+ rRow = pItems[nIndex].nRow;
+ return bMore;
+}
+
+void ScColumn::FindDataAreaPos(USHORT& rRow, short nMovY) const
+{
+ if (!nMovY) return;
+ BOOL bForward = (nMovY>0);
+
+ USHORT nIndex;
+ BOOL bThere = Search(rRow, nIndex);
+ if (bThere && !CellVisible(pItems[nIndex].pCell))
+ bThere = FALSE;
+
+ if (bThere)
+ {
+ USHORT nLast = rRow;
+ USHORT nOldIndex = nIndex;
+ if (bForward)
+ {
+ if (nIndex<nCount-1)
+ {
+ ++nIndex;
+ while (nIndex<nCount-1 && pItems[nIndex].nRow==nLast+1
+ && CellVisible(pItems[nIndex].pCell))
+ {
+ ++nIndex;
+ ++nLast;
+ }
+ if (nIndex==nCount-1)
+ if (pItems[nIndex].nRow==nLast+1 && CellVisible(pItems[nIndex].pCell))
+ ++nLast;
+ }
+ }
+ else
+ {
+ if (nIndex>0)
+ {
+ --nIndex;
+ while (nIndex>0 && pItems[nIndex].nRow+1==nLast
+ && CellVisible(pItems[nIndex].pCell))
+ {
+ --nIndex;
+ --nLast;
+ }
+ if (nIndex==0)
+ if (pItems[nIndex].nRow+1==nLast && CellVisible(pItems[nIndex].pCell))
+ --nLast;
+ }
+ }
+ if (nLast==rRow)
+ {
+ bThere = FALSE;
+ nIndex = bForward ? nOldIndex+1 : nOldIndex;
+ }
+ else
+ rRow = nLast;
+ }
+
+ if (!bThere)
+ {
+ if (bForward)
+ {
+ while (nIndex<nCount && !CellVisible(pItems[nIndex].pCell))
+ ++nIndex;
+ if (nIndex<nCount)
+ rRow = pItems[nIndex].nRow;
+ else
+ rRow = MAXROW;
+ }
+ else
+ {
+ while (nIndex>0 && !CellVisible(pItems[nIndex-1].pCell))
+ --nIndex;
+ if (nIndex>0)
+ rRow = pItems[nIndex-1].nRow;
+ else
+ rRow = 0;
+ }
+ }
+}
+
+BOOL ScColumn::HasDataAt(USHORT nRow) const
+{
+/* USHORT nIndex;
+ return Search( nRow, nIndex );
+*/
+ // immer nur sichtbare interessant ?
+ //! dann HasVisibleDataAt raus
+
+ USHORT nIndex;
+ if (Search(nRow, nIndex))
+ if (CellVisible(pItems[nIndex].pCell))
+ return TRUE;
+
+ return FALSE;
+
+}
+
+USHORT ScColumn::GetFirstEntryPos() const
+{
+ if (pAttrArray)
+ return Min( GetFirstDataPos(), pAttrArray->GetFirstEntryPos() );
+ else
+ return GetFirstDataPos();
+}
+
+USHORT ScColumn::GetLastEntryPos() const
+{
+ if (pAttrArray)
+ return Max( GetLastDataPos(), pAttrArray->GetLastEntryPos(TRUE) );
+ else
+ return GetLastDataPos();
+}
+
+USHORT ScColumn::GetLastAttrPos() const
+{
+ if (pAttrArray)
+ return pAttrArray->GetLastEntryPos(FALSE);
+ else
+ return 0;
+}
+
+BOOL ScColumn::IsAllAttrEqual( const ScColumn& rCol, USHORT nStartRow, USHORT nEndRow ) const
+{
+ if (pAttrArray && rCol.pAttrArray)
+ return pAttrArray->IsAllEqual( *rCol.pAttrArray, nStartRow, nEndRow );
+ else
+ return !pAttrArray && !rCol.pAttrArray;
+}
+
+BOOL ScColumn::IsVisibleAttrEqual( const ScColumn& rCol, USHORT nStartRow, USHORT nEndRow ) const
+{
+ if (pAttrArray && rCol.pAttrArray)
+ return pAttrArray->IsVisibleEqual( *rCol.pAttrArray, nStartRow, nEndRow );
+ else
+ return !pAttrArray && !rCol.pAttrArray;
+}
+
+BOOL ScColumn::HasVisibleAttr( USHORT& rFirstRow, USHORT& rLastRow, BOOL bSkipFirst ) const
+{
+ if (pAttrArray)
+ return pAttrArray->HasVisibleAttr(rFirstRow,rLastRow,bSkipFirst);
+ else
+ return FALSE;
+}
+
+BOOL ScColumn::HasVisibleAttrIn( USHORT nStartRow, USHORT nEndRow ) const
+{
+ if (pAttrArray)
+ return pAttrArray->HasVisibleAttrIn( nStartRow, nEndRow );
+ else
+ return FALSE;
+}
+
+void ScColumn::FindUsed( USHORT nStartRow, USHORT nEndRow, BOOL* pUsed ) const
+{
+ USHORT nRow;
+ USHORT nIndex;
+ Search( nStartRow, nIndex );
+ while ( (nIndex < nCount) ? ((nRow=pItems[nIndex].nRow) <= nEndRow) : FALSE )
+ {
+ pUsed[nRow-nStartRow] = TRUE;
+ ++nIndex;
+ }
+}
+
+void ScColumn::StartListening( SfxListener& rLst, USHORT nRow )
+{
+ ScBroadcasterList* pBC = NULL;
+ ScBaseCell* pCell;
+
+ USHORT nIndex;
+ if (Search(nRow,nIndex))
+ {
+ pCell = pItems[nIndex].pCell;
+ pBC = pCell->GetBroadcaster();
+ }
+ else
+ {
+ pCell = new ScNoteCell;
+ Insert(nRow, pCell);
+ }
+
+ if (!pBC)
+ {
+ pBC = new ScBroadcasterList;
+ pCell->SetBroadcaster(pBC);
+ }
+// rLst.StartListening(*pBC,TRUE);
+ pBC->StartBroadcasting( rLst, TRUE );
+}
+
+void ScColumn::MoveListeners( ScBroadcasterList& rSource, USHORT nDestRow )
+{
+ ScBroadcasterList* pBC = NULL;
+ ScBaseCell* pCell;
+
+ USHORT nIndex;
+ if (Search(nDestRow,nIndex))
+ {
+ pCell = pItems[nIndex].pCell;
+ pBC = pCell->GetBroadcaster();
+ }
+ else
+ {
+ pCell = new ScNoteCell;
+ Insert(nDestRow, pCell);
+ }
+
+ if (!pBC)
+ {
+ pBC = new ScBroadcasterList;
+ pCell->SetBroadcaster(pBC);
+ }
+
+#if 0
+ USHORT nCount = rSource.GetListenerCount();
+ for (USHORT i=nCount; i>0;)
+ {
+ --i;
+ SfxListener* pLst = rSource.GetListener(i);
+ pLst->StartListening(*pBC,TRUE);
+ pLst->EndListening(rSource);
+ }
+#endif
+ rSource.MoveListenersTo( *pBC );
+}
+
+void ScColumn::EndListening( SfxListener& rLst, USHORT nRow )
+{
+ USHORT nIndex;
+ if (Search(nRow,nIndex))
+ {
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ ScBroadcasterList* pBC = pCell->GetBroadcaster();
+ if (pBC)
+ {
+// rLst.EndListening(*pBC);
+ pBC->EndBroadcasting(rLst);
+
+ if (!pBC->HasListeners())
+ {
+ if (pCell->GetCellType() == CELLTYPE_NOTE && !pCell->GetNotePtr())
+ DeleteAtIndex(nIndex);
+ else
+ pCell->SetBroadcaster(NULL);
+ }
+ }
+// else
+// DBG_ERROR("ScColumn::EndListening - kein Broadcaster");
+ }
+// else
+// DBG_ERROR("ScColumn::EndListening - keine Zelle");
+}
+
+void ScColumn::CompileDBFormula()
+{
+ if (pItems)
+ for (USHORT i = 0; i < nCount; i++)
+ {
+ ScBaseCell* pCell = pItems[i].pCell;
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ ((ScFormulaCell*) pCell)->CompileDBFormula();
+ }
+}
+
+void ScColumn::CompileDBFormula( BOOL bCreateFormulaString )
+{
+ if (pItems)
+ for (USHORT i = 0; i < nCount; i++)
+ {
+ ScBaseCell* pCell = pItems[i].pCell;
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ ((ScFormulaCell*) pCell)->CompileDBFormula( bCreateFormulaString );
+ }
+}
+
+void ScColumn::CompileNameFormula( BOOL bCreateFormulaString )
+{
+ if (pItems)
+ for (USHORT i = 0; i < nCount; i++)
+ {
+ ScBaseCell* pCell = pItems[i].pCell;
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ ((ScFormulaCell*) pCell)->CompileNameFormula( bCreateFormulaString );
+ }
+}
+
+void ScColumn::CompileColRowNameFormula()
+{
+ if (pItems)
+ for (USHORT i = 0; i < nCount; i++)
+ {
+ ScBaseCell* pCell = pItems[i].pCell;
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ ((ScFormulaCell*) pCell)->CompileColRowNameFormula();
+ }
+}
+
+void lcl_UpdateSubTotal( ScFunctionData& rData, ScBaseCell* pCell )
+{
+ double nValue;
+ BOOL bVal = FALSE;
+ BOOL bCell = TRUE;
+ switch (pCell->GetCellType())
+ {
+ case CELLTYPE_VALUE:
+ nValue = ((ScValueCell*)pCell)->GetValue();
+ bVal = TRUE;
+ break;
+ case CELLTYPE_FORMULA:
+ {
+ if ( rData.eFunc != SUBTOTAL_FUNC_CNT2 ) // da interessiert's nicht
+ {
+ ScFormulaCell* pFC = (ScFormulaCell*)pCell;
+ if ( pFC->GetErrCode() )
+ {
+ if ( rData.eFunc != SUBTOTAL_FUNC_CNT ) // fuer Anzahl einfach weglassen
+ rData.bError = TRUE;
+ }
+ else if (pFC->IsValue())
+ {
+ nValue = pFC->GetValue();
+ bVal = TRUE;
+ }
+ // sonst Text
+ }
+ }
+ break;
+ case CELLTYPE_NOTE:
+ bCell = FALSE;
+ break;
+ // bei Strings nichts
+ }
+
+ if (!rData.bError)
+ {
+ switch (rData.eFunc)
+ {
+ case SUBTOTAL_FUNC_SUM:
+ case SUBTOTAL_FUNC_AVE:
+ if (bVal)
+ {
+ ++rData.nCount;
+ if (!SubTotal::SafePlus( rData.nVal, nValue ))
+ rData.bError = TRUE;
+ }
+ break;
+ case SUBTOTAL_FUNC_CNT: // nur Werte
+ if (bVal)
+ ++rData.nCount;
+ break;
+ case SUBTOTAL_FUNC_CNT2: // alle
+ if (bCell)
+ ++rData.nCount;
+ break;
+ case SUBTOTAL_FUNC_MAX:
+ if (bVal)
+ if (++rData.nCount == 1 || nValue > rData.nVal )
+ rData.nVal = nValue;
+ break;
+ case SUBTOTAL_FUNC_MIN:
+ if (bVal)
+ if (++rData.nCount == 1 || nValue < rData.nVal )
+ rData.nVal = nValue;
+ break;
+ }
+ }
+}
+
+// Mehrfachselektion:
+void ScColumn::UpdateSelectionFunction( const ScMarkData& rMark,
+ ScFunctionData& rData, const BYTE* pRowFlags,
+ BOOL bDoExclude, USHORT nExStartRow, USHORT nExEndRow )
+{
+ USHORT nIndex;
+ ScMarkedDataIter aDataIter(this, &rMark, FALSE);
+ while (aDataIter.Next( nIndex ))
+ {
+ USHORT nRow = pItems[nIndex].nRow;
+ if ( !pRowFlags || !( pRowFlags[nRow] & CR_HIDDEN ) )
+ if ( !bDoExclude || nRow < nExStartRow || nRow > nExEndRow )
+ lcl_UpdateSubTotal( rData, pItems[nIndex].pCell );
+ }
+}
+
+// bei bNoMarked die Mehrfachselektion weglassen
+void ScColumn::UpdateAreaFunction( ScFunctionData& rData, BYTE* pRowFlags,
+ USHORT nStartRow, USHORT nEndRow )
+{
+ USHORT nIndex;
+ Search( nStartRow, nIndex );
+ while ( nIndex<nCount && pItems[nIndex].nRow<=nEndRow )
+ {
+ USHORT nRow = pItems[nIndex].nRow;
+ if ( !pRowFlags || !( pRowFlags[nRow] & CR_HIDDEN ) )
+ lcl_UpdateSubTotal( rData, pItems[nIndex].pCell );
+ ++nIndex;
+ }
+}
+
+long ScColumn::GetWeightedCount() const
+{
+ long nTotal = 0;
+
+ // Notizen werden nicht gezaehlt
+
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScBaseCell* pCell = pItems[i].pCell;
+ switch ( pCell->GetCellType() )
+ {
+ case CELLTYPE_VALUE:
+ case CELLTYPE_STRING:
+ ++nTotal;
+ break;
+ case CELLTYPE_FORMULA:
+ nTotal += 5 + ((ScFormulaCell*)pCell)->GetCode()->GetCodeLen();
+ break;
+ case CELLTYPE_EDIT:
+ nTotal += 50;
+ break;
+ }
+ }
+
+ return nTotal;
+}
+
+ULONG ScColumn::GetCodeCount() const
+{
+ ULONG nCodeCount = 0;
+
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScBaseCell* pCell = pItems[i].pCell;
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ nCodeCount += ((ScFormulaCell*)pCell)->GetCode()->GetCodeLen();
+ }
+
+ return nCodeCount;
+}
+
+
+
+
+
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
new file mode 100644
index 000000000000..b53bebcdef00
--- /dev/null
+++ b/sc/source/core/data/column3.cxx
@@ -0,0 +1,2133 @@
+/*************************************************************************
+ *
+ * $RCSfile: column3.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+// INCLUDE ---------------------------------------------------------------
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include <sfx2/objsh.hxx>
+#include <svtools/zforlist.hxx>
+#include <tools/intn.hxx>
+#include <segmentc.hxx>
+
+#include "scitems.hxx"
+#include "column.hxx"
+#include "cell.hxx"
+#include "document.hxx"
+#include "attarray.hxx"
+#include "patattr.hxx"
+#include "cellform.hxx"
+#include "collect.hxx"
+#include "compiler.hxx"
+#include "brdcst.hxx"
+#include "docoptio.hxx" // GetStdPrecision fuer GetMaxStringLen
+#include "subtotal.hxx"
+#include "markdata.hxx"
+#include "detfunc.hxx" // fuer Notizen bei DeleteRange
+
+// Err527 Workaround
+extern const ScFormulaCell* pLastFormulaTreeTop; // in cellform.cxx
+
+// STATIC DATA -----------------------------------------------------------
+
+BOOL ScColumn::bDoubleAlloc = FALSE; // fuer Import: Groesse beim Allozieren verdoppeln
+
+SEG_EOFGLOBALS()
+
+#pragma SEG_FUNCDEF(column3_01)
+
+void ScColumn::Insert( USHORT nRow, ScBaseCell* pNewCell )
+{
+ BOOL bIsAppended = FALSE;
+ if (pItems && nCount)
+ {
+ if (pItems[nCount-1].nRow < nRow)
+ {
+ Append(nRow, pNewCell );
+ bIsAppended = TRUE;
+ }
+ }
+ if ( !bIsAppended )
+ {
+ USHORT nIndex;
+ if (Search(nRow, nIndex))
+ {
+ ScBaseCell* pOldCell = pItems[nIndex].pCell;
+ ScBroadcasterList* pBC = pOldCell->GetBroadcaster();
+ if (pBC && !pNewCell->GetBroadcaster())
+ {
+ pNewCell->SetBroadcaster( pBC );
+ pOldCell->ForgetBroadcaster();
+ }
+ if (pOldCell->GetNotePtr() && !pNewCell->GetNotePtr())
+ pNewCell->SetNote( *pOldCell->GetNotePtr() );
+ if ( pOldCell->GetCellType() == CELLTYPE_FORMULA && !pDocument->IsClipOrUndo() )
+ {
+ pOldCell->EndListeningTo( pDocument );
+ // falls in EndListening NoteCell in gleicher Col zerstoert
+ if ( nIndex >= nCount || pItems[nIndex].nRow != nRow )
+ Search(nRow, nIndex);
+ }
+ pOldCell->Delete();
+ pItems[nIndex].pCell = pNewCell;
+ }
+ else
+ {
+ if (nCount + 1 > nLimit)
+ {
+ if (bDoubleAlloc)
+ {
+ if (nLimit < COLUMN_DELTA)
+ nLimit = COLUMN_DELTA;
+ else
+ {
+ nLimit *= 2;
+ if ( nLimit > MAXROW+1 )
+ nLimit = MAXROW+1;
+ }
+ }
+ else
+ nLimit += COLUMN_DELTA;
+
+ ColEntry* pNewItems = new ColEntry[nLimit];
+ if (pItems)
+ {
+ memmove( pNewItems, pItems, nCount * sizeof(ColEntry) );
+ delete[] pItems;
+ }
+ pItems = pNewItems;
+ }
+ memmove( &pItems[nIndex + 1], &pItems[nIndex], (nCount - nIndex) * sizeof(ColEntry) );
+ pItems[nIndex].pCell = pNewCell;
+ pItems[nIndex].nRow = nRow;
+ ++nCount;
+ }
+ }
+ // Bei aus Clipboard sind hier noch falsche (alte) Referenzen!
+ // Werden in CopyBlockFromClip per UpdateReference umgesetzt,
+ // danach StartListeningFromClip und BroadcastFromClip gerufen.
+ // Wird ins Clipboard/UndoDoc gestellt, wird kein Broadcast gebraucht.
+ // Nach Import wird CalcAfterLoad gerufen, dort Listening.
+ if ( !(pDocument->IsClipOrUndo() || pDocument->IsInsertingFromOtherDoc()) )
+ {
+ pNewCell->StartListeningTo( pDocument );
+ CellType eCellType = pNewCell->GetCellType();
+ // Notizzelle entsteht beim Laden nur durch StartListeningCell,
+ // ausloesende Formelzelle muss sowieso dirty sein.
+ if ( !(pDocument->IsCalcingAfterLoad() && eCellType == CELLTYPE_NOTE) )
+ {
+ if ( eCellType == CELLTYPE_FORMULA )
+ ((ScFormulaCell*)pNewCell)->SetDirty();
+ else
+ pDocument->Broadcast( SC_HINT_DATACHANGED,
+ ScAddress( nCol, nRow, nTab ), pNewCell );
+ }
+ }
+}
+
+#pragma SEG_FUNCDEF(column3_02)
+
+void ScColumn::Insert( USHORT nRow, ULONG nNumberFormat, ScBaseCell* pCell )
+{
+ Insert(nRow, pCell);
+ short eOldType = pDocument->GetFormatTable()->
+ GetType( (ULONG)
+ ((SfxUInt32Item*)GetAttr( nRow, ATTR_VALUE_FORMAT ))->
+ GetValue() );
+ short eNewType = pDocument->GetFormatTable()->GetType(nNumberFormat);
+ if (!pDocument->GetFormatTable()->IsCompatible(eOldType, eNewType))
+ ApplyAttr( nRow, SfxUInt32Item( ATTR_VALUE_FORMAT, (UINT32) nNumberFormat) );
+}
+
+#pragma SEG_FUNCDEF(column3_03)
+
+void ScColumn::Append( USHORT nRow, ScBaseCell* pCell )
+{
+ if (nCount + 1 > nLimit)
+ {
+ if (bDoubleAlloc)
+ {
+ if (nLimit < COLUMN_DELTA)
+ nLimit = COLUMN_DELTA;
+ else
+ {
+ nLimit *= 2;
+ if ( nLimit > MAXROW+1 )
+ nLimit = MAXROW+1;
+ }
+ }
+ else
+ nLimit += COLUMN_DELTA;
+
+ ColEntry* pNewItems = new ColEntry[nLimit];
+ if (pItems)
+ {
+ memmove( pNewItems, pItems, nCount * sizeof(ColEntry) );
+ delete[] pItems;
+ }
+ pItems = pNewItems;
+ }
+ pItems[nCount].pCell = pCell;
+ pItems[nCount].nRow = nRow;
+ ++nCount;
+}
+
+#pragma SEG_FUNCDEF(column3_04)
+
+void ScColumn::Delete( USHORT nRow )
+{
+ USHORT nIndex;
+
+ if (Search(nRow, nIndex))
+ {
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ ScNoteCell* pNoteCell = new ScNoteCell;
+ pItems[nIndex].pCell = pNoteCell; // Dummy fuer Interpret
+ pDocument->Broadcast( SC_HINT_DYING,
+ ScAddress( nCol, nRow, nTab ), pCell );
+ ScBroadcasterList* pBC = pCell->GetBroadcaster();
+ if ( pBC )
+ {
+ pNoteCell->SetBroadcaster( pBC );
+ pCell->ForgetBroadcaster();
+ }
+ else
+ {
+ delete pNoteCell;
+ --nCount;
+ memmove( &pItems[nIndex], &pItems[nIndex + 1], (nCount - nIndex) * sizeof(ColEntry) );
+ pItems[nCount].nRow = 0;
+ pItems[nCount].pCell = NULL;
+ // Soll man hier den Speicher freigeben (delta)? Wird dann langsamer!
+ }
+ pCell->EndListeningTo( pDocument );
+ pCell->Delete();
+ }
+}
+
+#pragma SEG_FUNCDEF(column3_05)
+
+void ScColumn::DeleteAtIndex( USHORT nIndex )
+{
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ ScNoteCell* pNoteCell = new ScNoteCell;
+ pItems[nIndex].pCell = pNoteCell; // Dummy fuer Interpret
+ pDocument->Broadcast( SC_HINT_DYING,
+ ScAddress( nCol, pItems[nIndex].nRow, nTab ), pCell );
+ delete pNoteCell;
+ --nCount;
+ memmove( &pItems[nIndex], &pItems[nIndex + 1], (nCount - nIndex) * sizeof(ColEntry) );
+ pItems[nCount].nRow = 0;
+ pItems[nCount].pCell = NULL;
+ pCell->EndListeningTo( pDocument );
+ pCell->Delete();
+}
+
+#pragma SEG_FUNCDEF(column3_06)
+
+void ScColumn::FreeAll()
+{
+ if (pItems)
+ {
+ for (USHORT i = 0; i < nCount; i++)
+ pItems[i].pCell->Delete();
+ delete[] pItems;
+ pItems = NULL;
+ }
+ nCount = 0;
+ nLimit = 0;
+}
+
+#pragma SEG_FUNCDEF(column3_07)
+
+void ScColumn::DeleteRow( USHORT nStartRow, USHORT nSize )
+{
+ pAttrArray->DeleteRow( nStartRow, nSize );
+
+ if ( !pItems || !nCount )
+ return ;
+
+ USHORT nFirstIndex;
+ Search( nStartRow, nFirstIndex );
+ if ( nFirstIndex >= nCount )
+ return ;
+
+ BOOL bOldAutoCalc = pDocument->GetAutoCalc();
+ pDocument->SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+
+ BOOL bFound=FALSE;
+ USHORT nEndRow = nStartRow + nSize - 1;
+ USHORT nStartIndex;
+ USHORT nEndIndex;
+ USHORT i;
+
+ for ( i = nFirstIndex; i < nCount && pItems[i].nRow <= nEndRow; i++ )
+ {
+ if (!bFound)
+ {
+ nStartIndex = i;
+ bFound = TRUE;
+ }
+ nEndIndex = i;
+
+ ScBaseCell* pCell = pItems[i].pCell;
+ ScBroadcasterList* pBC = pCell->GetBroadcaster();
+ if (pBC)
+ {
+// gibt jetzt invalid reference, kein Aufruecken der direkten Referenzen
+// MoveListeners( *pBC, nRow+nSize );
+ pCell->SetBroadcaster(NULL);
+ // in DeleteRange werden leere Broadcaster geloescht
+ }
+ }
+ if (bFound)
+ {
+ DeleteRange( nStartIndex, nEndIndex, IDF_CONTENTS );
+ Search( nStartRow, i );
+ if ( i >= nCount )
+ {
+ pDocument->SetAutoCalc( bOldAutoCalc );
+ return ;
+ }
+ }
+ else
+ i = nFirstIndex;
+
+ USHORT nLastBroadcast = MAXROW+1;
+ ScAddress aAdr( nCol, 0, nTab );
+
+ for ( ; i < nCount; i++ )
+ {
+ USHORT nOldRow = pItems[i].nRow;
+ // #43940# Aenderung Quelle broadcasten
+ aAdr.SetRow( nOldRow );
+ pDocument->Broadcast( SC_HINT_DATACHANGED, aAdr, NULL ); // nur Areas
+ USHORT nNewRow = (pItems[i].nRow -= nSize);
+ // #43940# Aenderung Ziel broadcasten
+ if ( nLastBroadcast != nNewRow )
+ { // direkt aufeinanderfolgende nicht doppelt broadcasten
+ aAdr.SetRow( nNewRow );
+ pDocument->Broadcast( SC_HINT_DATACHANGED, aAdr, NULL ); // nur Areas
+ }
+ nLastBroadcast = nOldRow;
+ ScBaseCell* pCell = pItems[i].pCell;
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ ((ScFormulaCell*)pCell)->aPos.SetRow( nNewRow );
+ }
+
+ pDocument->SetAutoCalc( bOldAutoCalc );
+}
+
+#pragma SEG_FUNCDEF(column3_08)
+
+void ScColumn::DeleteRange( USHORT nStartIndex, USHORT nEndIndex, USHORT nDelFlag )
+{
+ USHORT nDelCount = 0;
+ ScBaseCell** ppDelCells = new ScBaseCell*[nEndIndex-nStartIndex+1];
+
+ BOOL bSimple = ((nDelFlag & IDF_CONTENTS) == IDF_CONTENTS);
+ USHORT i;
+
+ // Notiz-Zeichenobjekte
+ if (nDelFlag & IDF_NOTE)
+ {
+ for ( i = nStartIndex; i <= nEndIndex; i++ )
+ {
+ const ScPostIt* pNote = pItems[i].pCell->GetNotePtr();
+ if ( pNote && pNote->IsShown() )
+ {
+ ScDetectiveFunc( pDocument, nTab ).HideComment( nCol, pItems[i].nRow );
+ }
+ }
+ }
+
+ // Broadcaster stehenlassen
+ if (bSimple)
+ {
+ for (i = nStartIndex; i <= nEndIndex && bSimple; i++)
+ if (pItems[i].pCell->GetBroadcaster())
+ bSimple = FALSE;
+ }
+
+ if (bSimple) // Bereich komplett loeschen
+ {
+ ScBaseCell* pOldCell;
+ ScNoteCell* pNoteCell = new ScNoteCell; // Dummy
+ for (i = nStartIndex; i <= nEndIndex; i++)
+ {
+ pOldCell = pItems[i].pCell;
+ if (pOldCell->GetCellType() == CELLTYPE_FORMULA) // Formeln spaeter loeschen
+ ppDelCells[nDelCount++] = pOldCell;
+ else
+ {
+ // Interpret in Broadcast darf kein Value finden
+ pItems[i].pCell = pNoteCell;
+ pDocument->Broadcast( SC_HINT_DYING,
+ ScAddress( nCol, pItems[i].nRow, nTab ), pOldCell );
+ pOldCell->Delete();
+ }
+ }
+ delete pNoteCell;
+ memmove( &pItems[nStartIndex], &pItems[nEndIndex + 1], (nCount - nEndIndex - 1) * sizeof(ColEntry) );
+ nCount -= nEndIndex-nStartIndex+1;
+ }
+ else // Zellen einzeln durchgehen
+ {
+ USHORT j = nStartIndex;
+ for (USHORT i = nStartIndex; i <= nEndIndex; i++)
+ {
+ BOOL bDelete = FALSE;
+ ScBaseCell* pOldCell = pItems[j].pCell;
+ CellType eCellType = pOldCell->GetCellType();
+ switch ( eCellType )
+ {
+ case CELLTYPE_VALUE:
+ if ( ( nDelFlag & (IDF_DATETIME|IDF_VALUE) ) == (IDF_DATETIME|IDF_VALUE) )
+ bDelete = TRUE;
+ else
+ {
+ ULONG nIndex = (ULONG)((SfxUInt32Item*)GetAttr( pItems[j].nRow, ATTR_VALUE_FORMAT ))->GetValue();
+ short nTyp = pDocument->GetFormatTable()->GetType(nIndex);
+ if ((nTyp == NUMBERFORMAT_DATE) || (nTyp == NUMBERFORMAT_TIME) || (nTyp == NUMBERFORMAT_DATETIME))
+ bDelete = ((nDelFlag & IDF_DATETIME) != 0);
+ else
+ bDelete = ((nDelFlag & IDF_VALUE) != 0);
+ }
+ break;
+ case CELLTYPE_STRING:
+ case CELLTYPE_EDIT: bDelete = ((nDelFlag & IDF_STRING) != 0); break;
+ case CELLTYPE_FORMULA: bDelete = ((nDelFlag & IDF_FORMULA) != 0); break;
+ case CELLTYPE_NOTE:
+ bDelete = ((nDelFlag & IDF_NOTE) != 0) &&
+ (pOldCell->GetBroadcaster() == NULL);
+ break;
+ }
+
+ if (bDelete)
+ {
+ ScNoteCell* pNoteCell = NULL;
+ if (eCellType != CELLTYPE_NOTE)
+ {
+ if ((nDelFlag & IDF_NOTE) == 0)
+ {
+ const ScPostIt* pNote = pOldCell->GetNotePtr();
+ if (pNote)
+ pNoteCell = new ScNoteCell(*pNote);
+ }
+ ScBroadcasterList* pBC = pOldCell->GetBroadcaster();
+ if (pBC)
+ {
+ if (!pNoteCell)
+ pNoteCell = new ScNoteCell;
+ pNoteCell->SetBroadcaster(pBC);
+ }
+ }
+
+ USHORT nOldRow = pItems[j].nRow;
+ if (pNoteCell)
+ {
+ pItems[j].pCell = pNoteCell;
+ ++j;
+ }
+ else
+ {
+ --nCount;
+ memmove( &pItems[j], &pItems[j + 1], (nCount - j) * sizeof(ColEntry) );
+ pItems[nCount].nRow = 0;
+ pItems[nCount].pCell = NULL;
+ }
+ // ACHTUNG! pItems bereits verschoben!
+ // Interpret in Broadcast muss neue/keine Zelle finden
+ if (eCellType == CELLTYPE_FORMULA) // Formeln spaeter loeschen
+ {
+ ppDelCells[nDelCount++] = pOldCell;
+ }
+ else
+ {
+ pDocument->Broadcast( SC_HINT_DYING,
+ ScAddress( nCol, nOldRow, nTab ), pOldCell );
+ if (eCellType != CELLTYPE_NOTE)
+ pOldCell->ForgetBroadcaster();
+ pOldCell->Delete();
+ }
+ }
+ else
+ {
+ if (nDelFlag & IDF_NOTE)
+ if (pItems[j].pCell->GetNotePtr())
+ pItems[j].pCell->DeleteNote();
+ ++j;
+ }
+ }
+ }
+
+ // erst Listener abhaengen kann Neuberechnungen sparen
+ // eventuell werden dabei vorher entstandene NoteCell mitsamt
+ // ihren Broadcaster deleted!
+ for (i=0; i<nDelCount; i++)
+ {
+ ((ScFormulaCell*) ppDelCells[i])->EndListeningTo( pDocument );
+ }
+ // gibts die NoteCell und damit den Broadcaster noch?
+ // If not, discard them all before broadcasting takes place!
+ for (i=0; i<nDelCount; i++)
+ {
+ ScFormulaCell* pOldCell = (ScFormulaCell*) ppDelCells[i];
+ USHORT nIndex;
+ if ( !Search( pOldCell->aPos.Row(), nIndex ) )
+ pOldCell->ForgetBroadcaster();
+ }
+ for (i=0; i<nDelCount; i++)
+ {
+ ScFormulaCell* pOldCell = (ScFormulaCell*) ppDelCells[i];
+ pDocument->Broadcast( SC_HINT_DYING, pOldCell->aPos, pOldCell );
+ pOldCell->ForgetBroadcaster();
+ pOldCell->Delete();
+ }
+ delete ppDelCells;
+}
+
+#pragma SEG_FUNCDEF(column3_09)
+
+void ScColumn::DeleteArea(USHORT nStartRow, USHORT nEndRow, USHORT nDelFlag)
+{
+ // FreeAll darf hier nicht gerufen werden wegen Broadcastern
+
+ // Attribute erst am Ende, damit vorher noch zwischen Zahlen und Datum
+ // unterschieden werden kann (#47901#)
+
+ USHORT nContFlag = nDelFlag & IDF_CONTENTS;
+ if (pItems && nCount && nContFlag)
+ {
+ if (nStartRow==0 && nEndRow==MAXROW)
+ DeleteRange( 0, nCount-1, nContFlag );
+ else
+ {
+ BOOL bFound=FALSE;
+ USHORT nStartIndex;
+ USHORT nEndIndex;
+ for (USHORT i = 0; i < nCount; i++)
+ if ((pItems[i].nRow >= nStartRow) && (pItems[i].nRow <= nEndRow))
+ {
+ if (!bFound)
+ {
+ nStartIndex = i;
+ bFound = TRUE;
+ }
+ nEndIndex = i;
+ }
+ if (bFound)
+ DeleteRange( nStartIndex, nEndIndex, nContFlag );
+ }
+ }
+
+ if ( nDelFlag & IDF_EDITATTR )
+ {
+ DBG_ASSERT( nContFlag == 0, "DeleteArea: falsche Flags" );
+ RemoveEditAttribs( nStartRow, nEndRow );
+ }
+
+ // Attribute erst hier
+ if ((nDelFlag & IDF_ATTRIB) == IDF_ATTRIB) pAttrArray->DeleteArea( nStartRow, nEndRow );
+ else if ((nDelFlag & IDF_ATTRIB) != 0) pAttrArray->DeleteHardAttr( nStartRow, nEndRow );
+}
+
+#pragma SEG_FUNCDEF(column3_26)
+
+ScFormulaCell* ScColumn::CreateRefCell( ScDocument* pDestDoc, const ScAddress& rDestPos,
+ USHORT nIndex, USHORT nFlags ) const
+{
+ USHORT nContFlags = nFlags & IDF_CONTENTS;
+ if (!nContFlags)
+ return NULL;
+
+ // Testen, ob Zelle kopiert werden soll
+ // auch bei IDF_CONTENTS komplett, wegen Notes / Broadcastern
+
+ BOOL bMatch = FALSE;
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ CellType eCellType = pCell->GetCellType();
+ switch ( eCellType )
+ {
+ case CELLTYPE_VALUE:
+ {
+ USHORT nValFlags = nFlags & (IDF_DATETIME|IDF_VALUE);
+
+ if ( nValFlags == (IDF_DATETIME|IDF_VALUE) )
+ bMatch = TRUE;
+ else if ( nValFlags )
+ {
+ ULONG nNumIndex = (ULONG)((SfxUInt32Item*)GetAttr(
+ pItems[nIndex].nRow, ATTR_VALUE_FORMAT ))->GetValue();
+ short nTyp = pDocument->GetFormatTable()->GetType(nNumIndex);
+ if ((nTyp == NUMBERFORMAT_DATE) || (nTyp == NUMBERFORMAT_TIME) || (nTyp == NUMBERFORMAT_DATETIME))
+ bMatch = ((nFlags & IDF_DATETIME) != 0);
+ else
+ bMatch = ((nFlags & IDF_VALUE) != 0);
+ }
+ }
+ break;
+ case CELLTYPE_STRING:
+ case CELLTYPE_EDIT: bMatch = ((nFlags & IDF_STRING) != 0); break;
+ case CELLTYPE_FORMULA: bMatch = ((nFlags & IDF_FORMULA) != 0); break;
+ }
+ if (!bMatch)
+ return NULL;
+
+
+ // Referenz einsetzen
+ SingleRefData aRef;
+ aRef.nCol = nCol;
+ aRef.nRow = pItems[nIndex].nRow;
+ aRef.nTab = nTab;
+ aRef.InitFlags(); // -> alles absolut
+ aRef.SetFlag3D(TRUE);
+
+ //! 3D(FALSE) und TabRel(TRUE), wenn die endgueltige Position auf der selben Tabelle ist?
+ //! (bei TransposeClip ist die Zielposition noch nicht bekannt)
+
+ aRef.CalcRelFromAbs( rDestPos );
+
+ ScTokenArray aArr;
+ aArr.AddSingleReference( aRef );
+
+ return new ScFormulaCell( pDestDoc, rDestPos, &aArr );
+}
+
+#pragma SEG_FUNCDEF(column3_0a)
+
+// rColumn = Quelle
+// nRow1, nRow2 = Zielposition
+
+void ScColumn::CopyFromClip(USHORT nRow1, USHORT nRow2, short nDy,
+ USHORT nInsFlag, BOOL bAsLink, ScColumn& rColumn)
+{
+ if ((nInsFlag & IDF_ATTRIB) != 0) rColumn.pAttrArray->CopyAreaSafe( nRow1, nRow2, nDy, *pAttrArray );
+ if ((nInsFlag & IDF_CONTENTS) == 0)
+ return;
+
+ if ( bAsLink && nInsFlag == IDF_ALL )
+ {
+ // bei "alles" werden auch leere Zellen referenziert
+ //! IDF_ALL muss immer mehr Flags enthalten, als bei "Inhalte Einfuegen"
+ //! einzeln ausgewaehlt werden koennen!
+
+ Resize( nCount + (nRow2-nRow1+1) );
+
+ ScAddress aDestPos( nCol, 0, nTab ); // Row wird angepasst
+
+ // Referenz erzeugen (Quell-Position)
+ SingleRefData aRef;
+ aRef.nCol = rColumn.nCol;
+ // nRow wird angepasst
+ aRef.nTab = rColumn.nTab;
+ aRef.InitFlags(); // -> alles absolut
+ aRef.SetFlag3D(TRUE);
+
+ for (USHORT nDestRow = nRow1; nDestRow <= nRow2; nDestRow++)
+ {
+ aRef.nRow = nDestRow - nDy; // Quell-Zeile
+ aDestPos.SetRow( nDestRow );
+
+ aRef.CalcRelFromAbs( aDestPos );
+ ScTokenArray aArr;
+ aArr.AddSingleReference( aRef );
+ Insert( nDestRow, new ScFormulaCell( pDocument, aDestPos, &aArr ) );
+ }
+
+ return;
+ }
+
+ USHORT nColCount = rColumn.nCount;
+ if ((nInsFlag & IDF_CONTENTS) == IDF_CONTENTS && nRow2-nRow1 >= 64)
+ {
+ //! Resize immer aussen, wenn die Wiederholungen bekannt sind
+ //! (dann hier gar nicht mehr)
+
+ USHORT nNew = nCount + nColCount;
+ if ( nLimit < nNew )
+ Resize( nNew );
+ }
+
+ USHORT nRowDiff = nRow2 - nRow1;
+ USHORT nDestRow;
+ for (USHORT i = 0; (i < nColCount) && (i <= nRowDiff); i++)
+ {
+ if ( (nDestRow = rColumn.pItems[i].nRow + nDy) <= nRow2 )
+ {
+ ScBaseCell* pOld = rColumn.pItems[i].pCell;
+ ScBaseCell* pNew;
+
+ if ( bAsLink )
+ {
+ pNew = rColumn.CreateRefCell( pDocument,
+ ScAddress( nCol, nDestRow, nTab ), i, nInsFlag );
+ }
+ else
+ {
+ pNew = rColumn.CloneCell( i, nInsFlag, pDocument, ScAddress(nCol,nDestRow,nTab) );
+
+ if ( pNew && pNew->GetNotePtr() && (nInsFlag & IDF_NOTE) == 0 )
+ pNew->DeleteNote();
+ }
+
+ if (pNew)
+ Insert(nDestRow, pNew);
+ }
+ }
+}
+
+#pragma SEG_FUNCDEF(column3_1e)
+
+ // Formelzellen werden jetzt schon hier kopiert,
+ // Notizen muessen aber evtl. noch geloescht werden
+
+ScBaseCell* ScColumn::CloneCell(USHORT nIndex, USHORT nFlags,
+ ScDocument* pDestDoc, const ScAddress& rDestPos)
+{
+ ScBaseCell* pNew = 0;
+ ScBaseCell* pSource = pItems[nIndex].pCell;
+ switch (pSource->GetCellType())
+ {
+ case CELLTYPE_NOTE:
+ if (nFlags & IDF_NOTE)
+ pNew = new ScNoteCell(*(ScNoteCell*)pSource);
+ break;
+ case CELLTYPE_EDIT:
+ if (nFlags & IDF_STRING)
+ pNew = new ScEditCell( *(ScEditCell*)pSource, pDestDoc );
+ break;
+ case CELLTYPE_STRING:
+ if (nFlags & IDF_STRING)
+ pNew = new ScStringCell(*(ScStringCell*)pSource);
+ break;
+ case CELLTYPE_VALUE:
+ {
+ BOOL bDoIns = FALSE;
+ USHORT nMask = nFlags & ( IDF_DATETIME | IDF_VALUE );
+ if ( nMask == (IDF_DATETIME | IDF_VALUE) )
+ bDoIns = TRUE;
+ else if ( nMask )
+ {
+ ULONG nNumIndex = (ULONG)((SfxUInt32Item*) GetAttr(
+ pItems[nIndex].nRow, ATTR_VALUE_FORMAT ))->GetValue();
+ short nTyp = pDocument->GetFormatTable()->GetType(nNumIndex);
+ if (nTyp == NUMBERFORMAT_DATE || nTyp == NUMBERFORMAT_TIME || nTyp == NUMBERFORMAT_DATETIME)
+ bDoIns = (nFlags & IDF_DATETIME)!=0;
+ else
+ bDoIns = (nFlags & IDF_VALUE)!=0;
+ }
+ if (bDoIns)
+ pNew = new ScValueCell(*(ScValueCell*)pSource);
+ }
+ break;
+ case CELLTYPE_FORMULA:
+ {
+ ScFormulaCell* pForm = (ScFormulaCell*)pSource;
+ if (nFlags & IDF_FORMULA)
+ {
+ pNew = pForm->Clone( pDestDoc, rDestPos, TRUE );
+ }
+ else if ( (nFlags & (IDF_VALUE | IDF_DATETIME | IDF_STRING)) &&
+ !pDestDoc->IsUndo() )
+ {
+ // #48491# ins Undo-Dokument immer nur die Original-Zelle kopieren,
+ // aus Formeln keine Value/String-Zellen erzeugen
+
+ USHORT nErr = pForm->GetErrCode();
+ if ( nErr )
+ {
+ // Fehler werden immer mit "Zahlen" kopiert
+ // (Das ist hiermit willkuerlich so festgelegt)
+
+ if ( nFlags & IDF_VALUE )
+ {
+ ScFormulaCell* pErrCell = new ScFormulaCell( pDestDoc, rDestPos );
+ pErrCell->SetErrCode( nErr );
+ pNew = pErrCell;
+ }
+ }
+ else if ( pForm->IsValue() )
+ {
+ BOOL bDoIns = FALSE;
+ USHORT nMask = nFlags & ( IDF_DATETIME | IDF_VALUE );
+ if ( nMask == (IDF_DATETIME | IDF_VALUE) )
+ bDoIns = TRUE;
+ else if ( nMask )
+ {
+ ULONG nNumIndex = (ULONG)((SfxUInt32Item*) GetAttr(
+ pItems[nIndex].nRow, ATTR_VALUE_FORMAT ))->GetValue();
+ short nTyp = pDocument->GetFormatTable()->GetType(nNumIndex);
+ if (nTyp == NUMBERFORMAT_DATE || nTyp == NUMBERFORMAT_TIME || nTyp == NUMBERFORMAT_DATETIME)
+ bDoIns = (nFlags & IDF_DATETIME)!=0;
+ else
+ bDoIns = (nFlags & IDF_VALUE)!=0;
+ }
+
+ if (bDoIns)
+ {
+ double nVal = pForm->GetValue();
+ pNew = new ScValueCell(nVal);
+ }
+ }
+ else
+ {
+ if (nFlags & IDF_STRING)
+ {
+ String aString;
+ pForm->GetString(aString);
+ if ( aString.Len() )
+ pNew = new ScStringCell(aString);
+ // #33224# LeerStrings nicht kopieren
+ }
+ }
+ if ( pNew && pSource->GetNotePtr() && ( nFlags & IDF_NOTE ) )
+ pNew->SetNote(*pSource->GetNotePtr());
+ }
+ }
+ break;
+ }
+
+ if ( !pNew && pSource->GetNotePtr() && ( nFlags & IDF_NOTE ) )
+ pNew = new ScNoteCell(*pSource->GetNotePtr());
+
+ return pNew;
+}
+
+#pragma SEG_FUNCDEF(column3_27)
+
+void ScColumn::MixMarked( const ScMarkData& rMark, USHORT nFunction,
+ BOOL bSkipEmpty, ScColumn& rSrcCol )
+{
+ USHORT nRow1, nRow2;
+
+ if (rMark.IsMultiMarked())
+ {
+ ScMarkArrayIter aIter( rMark.GetArray()+nCol );
+ while (aIter.Next( nRow1, nRow2 ))
+ MixData( nRow1, nRow2, nFunction, bSkipEmpty, rSrcCol );
+ }
+}
+
+#pragma SEG_FUNCDEF(column3_23)
+
+// Ergebnis in rVal1
+
+BOOL lcl_DoFunction( double& rVal1, double nVal2, USHORT nFunction )
+{
+ BOOL bOk = FALSE;
+ switch (nFunction)
+ {
+ case PASTE_ADD:
+ bOk = SubTotal::SafePlus( rVal1, nVal2 );
+ break;
+ case PASTE_SUB:
+ nVal2 = -nVal2; //! geht das immer ohne Fehler?
+ bOk = SubTotal::SafePlus( rVal1, nVal2 );
+ break;
+ case PASTE_MUL:
+ bOk = SubTotal::SafeMult( rVal1, nVal2 );
+ break;
+ case PASTE_DIV:
+ bOk = SubTotal::SafeDiv( rVal1, nVal2 );
+ break;
+ }
+ return bOk;
+}
+
+#pragma SEG_FUNCDEF(column3_24)
+
+void lcl_AddCode( ScTokenArray& rArr, ScFormulaCell* pCell )
+{
+ rArr.AddOpCode(ocOpen);
+
+ ScTokenArray* pCode = pCell->GetCode();
+ if (pCode)
+ {
+ ScToken* pToken = pCode->First();
+ while (pToken)
+ {
+ rArr.AddToken(*pToken);
+ pToken = pCode->Next();
+ }
+ }
+
+ rArr.AddOpCode(ocClose);
+}
+
+#pragma SEG_FUNCDEF(column3_22)
+
+void ScColumn::MixData( USHORT nRow1, USHORT nRow2,
+ USHORT nFunction, BOOL bSkipEmpty,
+ ScColumn& rSrcCol )
+{
+ USHORT nSrcCount = rSrcCol.nCount;
+
+ USHORT nIndex;
+ Search( nRow1, nIndex );
+
+// USHORT nSrcIndex = 0;
+ USHORT nSrcIndex;
+ rSrcCol.Search( nRow1, nSrcIndex ); //! Testen, ob Daten ganz vorne
+
+ USHORT nNextThis = MAXROW+1;
+ if ( nIndex < nCount )
+ nNextThis = pItems[nIndex].nRow;
+ USHORT nNextSrc = MAXROW+1;
+ if ( nSrcIndex < nSrcCount )
+ nNextSrc = rSrcCol.pItems[nSrcIndex].nRow;
+
+ while ( nNextThis <= nRow2 || nNextSrc <= nRow2 )
+ {
+ USHORT nRow = Min( nNextThis, nNextSrc );
+
+ ScBaseCell* pSrc = NULL;
+ ScBaseCell* pDest = NULL;
+ ScBaseCell* pNew = NULL;
+ BOOL bDelete = FALSE;
+
+ if ( nSrcIndex < nSrcCount && nNextSrc == nRow )
+ pSrc = rSrcCol.pItems[nSrcIndex].pCell;
+
+ if ( nIndex < nCount && nNextThis == nRow )
+ pDest = pItems[nIndex].pCell;
+
+ DBG_ASSERT( pSrc || pDest, "Nanu ??!?" );
+
+ CellType eSrcType = pSrc ? pSrc->GetCellType() : CELLTYPE_NONE;
+ CellType eDestType = pDest ? pDest->GetCellType() : CELLTYPE_NONE;
+
+ BOOL bSrcEmpty = ( eSrcType == CELLTYPE_NONE || eSrcType == CELLTYPE_NOTE );
+ BOOL bDestEmpty = ( eDestType == CELLTYPE_NONE || eDestType == CELLTYPE_NOTE );
+
+ if ( bSkipEmpty && bDestEmpty ) // Originalzelle wiederherstellen
+ {
+ if ( pSrc ) // war da eine Zelle?
+ {
+ pNew = pSrc->Clone( pDocument );
+ }
+ }
+ else if ( nFunction ) // wirklich Rechenfunktion angegeben
+ {
+ double nVal1;
+ double nVal2;
+ if ( eSrcType == CELLTYPE_VALUE )
+ nVal1 = ((ScValueCell*)pSrc)->GetValue();
+ else
+ nVal1 = 0.0;
+ if ( eDestType == CELLTYPE_VALUE )
+ nVal2 = ((ScValueCell*)pDest)->GetValue();
+ else
+ nVal2 = 0.0;
+
+ // leere Zellen werden als Werte behandelt
+
+ BOOL bSrcVal = ( bSrcEmpty || eSrcType == CELLTYPE_VALUE );
+ BOOL bDestVal = ( bDestEmpty || eDestType == CELLTYPE_VALUE );
+
+ BOOL bSrcText = ( eSrcType == CELLTYPE_STRING ||
+ eSrcType == CELLTYPE_EDIT );
+ BOOL bDestText = ( eDestType == CELLTYPE_STRING ||
+ eDestType == CELLTYPE_EDIT );
+
+ // sonst bleibt nur Formel...
+
+ if ( bSrcEmpty && bDestEmpty )
+ {
+ // beide leer -> nix
+ }
+ else if ( bSrcVal && bDestVal )
+ {
+ // neuen Wert eintragen, oder Fehler bei Ueberlauf
+
+ BOOL bOk = lcl_DoFunction( nVal1, nVal2, nFunction );
+
+ if (bOk)
+ pNew = new ScValueCell( nVal1 );
+ else
+ {
+ ScFormulaCell* pFC = new ScFormulaCell( pDocument,
+ ScAddress( nCol, nRow, nTab ) );
+ pFC->SetErrCode( errNoValue );
+ //! oder NOVALUE, dann auch in consoli,
+ //! sonst in Interpreter::GetCellValue die Abfrage auf errNoValue raus
+ //! (dann geht Stringzelle+Wertzelle nicht mehr)
+ pNew = pFC;
+ }
+ }
+ else if ( bSrcText || bDestText )
+ {
+ // mit Texten wird nicht gerechnet - immer "alte" Zelle, also pSrc
+
+ if (pSrc)
+ pNew = pSrc->Clone( pDocument );
+ else if (pDest)
+ bDelete = TRUE;
+ }
+ else
+ {
+ // Kombination aus Wert und mindestens einer Formel -> Formel erzeugen
+
+ ScTokenArray aArr;
+
+ // erste Zelle
+ if ( eSrcType == CELLTYPE_FORMULA )
+ lcl_AddCode( aArr, (ScFormulaCell*)pSrc );
+ else
+ aArr.AddDouble( nVal1 );
+
+ // Operator
+ OpCode eOp = ocAdd;
+ switch ( nFunction )
+ {
+ case PASTE_ADD: eOp = ocAdd; break;
+ case PASTE_SUB: eOp = ocSub; break;
+ case PASTE_MUL: eOp = ocMul; break;
+ case PASTE_DIV: eOp = ocDiv; break;
+ }
+ aArr.AddOpCode(eOp); // Funktion
+
+ // zweite Zelle
+ if ( eDestType == CELLTYPE_FORMULA )
+ lcl_AddCode( aArr, (ScFormulaCell*)pDest );
+ else
+ aArr.AddDouble( nVal2 );
+
+ pNew = new ScFormulaCell( pDocument, ScAddress( nCol, nRow, nTab ), &aArr );
+ }
+ }
+
+
+ if ( pNew || bDelete ) // neues Ergebnis ?
+ {
+ if (pDest && !pNew) // alte Zelle da ?
+ {
+ if ( pDest->GetBroadcaster() )
+ pNew = new ScNoteCell; // Broadcaster uebernehmen
+ else
+ Delete(nRow); // -> loeschen
+ }
+ if (pNew)
+ Insert(nRow, pNew); // neue einfuegen
+
+ Search( nRow, nIndex ); // alles kann sich verschoben haben
+ if (pNew)
+ nNextThis = nRow; // nIndex zeigt jetzt genau auf nRow
+ else
+ nNextThis = ( nIndex < nCount ) ? pItems[nIndex].nRow : MAXROW+1;
+ }
+
+ if ( nNextThis == nRow )
+ {
+ ++nIndex;
+ nNextThis = ( nIndex < nCount ) ? pItems[nIndex].nRow : MAXROW+1;
+ }
+ if ( nNextSrc == nRow )
+ {
+ ++nSrcIndex;
+ nNextSrc = ( nSrcIndex < nSrcCount ) ?
+ rSrcCol.pItems[nSrcIndex].nRow :
+ MAXROW+1;
+ }
+ }
+}
+
+#pragma SEG_FUNCDEF(column3_25)
+
+ScAttrIterator* ScColumn::CreateAttrIterator( USHORT nStartRow, USHORT nEndRow ) const
+{
+ return new ScAttrIterator( pAttrArray, nStartRow, nEndRow );
+}
+
+#pragma SEG_FUNCDEF(column3_1b)
+
+void ScColumn::StartAllListeners()
+{
+ if (pItems)
+ for (USHORT i = 0; i < nCount; i++)
+ {
+ ScBaseCell* pCell = pItems[i].pCell;
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ {
+ USHORT nRow = pItems[i].nRow;
+ ((ScFormulaCell*)pCell)->StartListeningTo( pDocument );
+ if ( nRow != pItems[i].nRow )
+ Search( nRow, i ); // Listener eingefuegt?
+ }
+ }
+}
+
+#pragma SEG_FUNCDEF(column3_1d)
+
+void ScColumn::StartRelNameListeners()
+{
+ if (pItems)
+ for (USHORT i = 0; i < nCount; i++)
+ {
+ ScBaseCell* pCell = pItems[i].pCell;
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ {
+ USHORT nRow = pItems[i].nRow;
+ ((ScFormulaCell*)pCell)->StartListeningTo( pDocument, TRUE );
+ if ( nRow != pItems[i].nRow )
+ Search( nRow, i ); // Listener eingefuegt?
+ }
+ }
+}
+
+#pragma SEG_FUNCDEF(column3_1a)
+
+void ScColumn::BroadcastInArea( USHORT nRow1, USHORT nRow2 )
+{
+ if ( pItems )
+ {
+ USHORT nIndex, nRow;
+ Search( nRow1, nIndex );
+ while ( nIndex < nCount && (nRow = pItems[nIndex].nRow) <= nRow2 )
+ {
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ ((ScFormulaCell*)pCell)->SetDirty();
+ else
+ pDocument->Broadcast( SC_HINT_DATACHANGED,
+ ScAddress( nCol, nRow, nTab ), pCell );
+ nIndex++;
+ }
+ }
+}
+
+#pragma SEG_FUNCDEF(column3_1c)
+
+void ScColumn::StartListeningInArea( USHORT nRow1, USHORT nRow2 )
+{
+ if ( pItems )
+ {
+ USHORT nIndex, nRow;
+ Search( nRow1, nIndex );
+ while ( nIndex < nCount && (nRow = pItems[nIndex].nRow) <= nRow2 )
+ {
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ ((ScFormulaCell*)pCell)->StartListeningTo( pDocument );
+ if ( nRow != pItems[nIndex].nRow )
+ Search( nRow, nIndex ); // durch Listening eingefuegt
+ nIndex++;
+ }
+ }
+}
+
+#pragma SEG_FUNCDEF(column3_0b)
+
+// TRUE = Zahlformat gesetzt
+BOOL ScColumn::SetString( USHORT nRow, USHORT nTab, const String& rString )
+{
+ BOOL bNumFmtSet = FALSE;
+ if (VALIDROW(nRow))
+ {
+ ScBaseCell* pNewCell = NULL;
+ BOOL bIsLoading = FALSE;
+ if (rString.Len() > 0)
+ {
+ double nVal;
+ ULONG nIndex, nOldIndex;
+ sal_Unicode cFirstChar;
+ SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
+ SfxObjectShell* pDocSh = pDocument->GetDocumentShell();
+ if ( pDocSh )
+ bIsLoading = pDocSh->IsLoading();
+ // IsLoading bei ConvertFrom Import
+ if ( !bIsLoading )
+ {
+ nIndex = nOldIndex = GetNumberFormat( nRow );
+ if ( rString.Len() > 1
+ && pFormatter->GetType(nIndex) != NUMBERFORMAT_TEXT )
+ cFirstChar = rString.GetChar(0);
+ else
+ cFirstChar = 0; // Text
+ }
+ else
+ { // waehrend ConvertFrom Import gibt es keine gesetzten Formate
+ cFirstChar = rString.GetChar(0);
+ }
+
+ if ( cFirstChar == '=' )
+ {
+ if ( rString.Len() == 1 ) // = Text
+ pNewCell = new ScStringCell( rString );
+ else // =Formel
+ pNewCell = new ScFormulaCell( pDocument,
+ ScAddress( nCol, nRow, nTab ), rString, 0 );
+ }
+ else if ( cFirstChar == '\'') // 'Text
+ pNewCell = new ScStringCell( rString.Copy(1) );
+ else
+ {
+ BOOL bIsText = FALSE;
+ if ( bIsLoading )
+ {
+ if ( pItems && nCount )
+ {
+ String aStr;
+ USHORT i = nCount;
+ USHORT nStop = (i >= 3 ? i - 3 : 0);
+ // die letzten Zellen vergleichen, ob gleicher String
+ // und IsNumberFormat eingespart werden kann
+ do
+ {
+ i--;
+ ScBaseCell* pCell = pItems[i].pCell;
+ switch ( pCell->GetCellType() )
+ {
+ case CELLTYPE_STRING :
+ ((ScStringCell*)pCell)->GetString( aStr );
+ if ( rString == aStr )
+ bIsText = TRUE;
+ break;
+ case CELLTYPE_NOTE : // durch =Formel referenziert
+ break;
+ default:
+ if ( i == nCount - 1 )
+ i = 0;
+ // wahrscheinlich ganze Spalte kein String
+ }
+ } while ( i && i > nStop && !bIsText );
+ }
+ // nIndex fuer IsNumberFormat vorbelegen
+ if ( !bIsText )
+ nIndex = nOldIndex = pFormatter->GetStandardIndex();
+ }
+ if ( !bIsText &&
+ pFormatter->IsNumberFormat(rString, nIndex, nVal) )
+ { // Zahl
+ pNewCell = new ScValueCell( nVal );
+ if ( nIndex != nOldIndex)
+ {
+ ApplyAttr( nRow, SfxUInt32Item( ATTR_VALUE_FORMAT,
+ (UINT32) nIndex) );
+ bNumFmtSet = TRUE;
+ }
+ }
+ else // Text
+ pNewCell = new ScStringCell( rString );
+ }
+ }
+
+ if ( bIsLoading && (!nCount || nRow > pItems[nCount-1].nRow) )
+ { // Search einsparen und ohne Umweg ueber Insert, Listener aufbauen
+ // und Broadcast kommt eh erst nach dem Laden
+ if ( pNewCell )
+ Append( nRow, pNewCell );
+ }
+ else
+ {
+ USHORT i;
+ if (Search(nRow, i))
+ {
+ ScBaseCell* pOldCell = pItems[i].pCell;
+ const ScPostIt* pNote = pOldCell->GetNotePtr();
+ ScBroadcasterList* pBC = pOldCell->GetBroadcaster();
+ if (pNewCell || pNote || pBC)
+ {
+ if (!pNewCell)
+ pNewCell = new ScNoteCell();
+ if (pNote)
+ pNewCell->SetNote(*pNote);
+ if (pBC)
+ {
+ pNewCell->SetBroadcaster(pBC);
+ pOldCell->ForgetBroadcaster();
+ pLastFormulaTreeTop = 0; // Err527 Workaround
+ }
+
+ if ( pOldCell->GetCellType() == CELLTYPE_FORMULA )
+ {
+ pOldCell->EndListeningTo( pDocument );
+ // falls in EndListening NoteCell in gleicher Col zerstoert
+ if ( i >= nCount || pItems[i].nRow != nRow )
+ Search(nRow, i);
+ }
+ pOldCell->Delete();
+ pItems[i].pCell = pNewCell; // ersetzen
+ if ( pNewCell->GetCellType() == CELLTYPE_FORMULA )
+ {
+ pNewCell->StartListeningTo( pDocument );
+ ((ScFormulaCell*)pNewCell)->SetDirty();
+ }
+ else
+ pDocument->Broadcast( SC_HINT_DATACHANGED,
+ ScAddress( nCol, nRow, nTab ), pNewCell );
+ }
+ else
+ {
+ DeleteAtIndex(i); // loeschen und Broadcast
+ }
+ }
+ else if (pNewCell)
+ {
+ Insert(nRow, pNewCell); // neu eintragen und Broadcast
+ }
+ }
+
+ // hier keine Formate mehr fuer Formeln setzen!
+ // (werden bei der Ausgabe abgefragt)
+
+ }
+ return bNumFmtSet;
+}
+
+#pragma SEG_FUNCDEF(column3_0c)
+
+void ScColumn::GetFilterEntries(USHORT nStartRow, USHORT nEndRow, TypedStrCollection& rStrings)
+{
+ SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
+ String aString;
+ USHORT nRow;
+ USHORT nIndex;
+
+ Search( nStartRow, nIndex );
+
+ while ( (nIndex < nCount) ? ((nRow=pItems[nIndex].nRow) <= nEndRow) : FALSE )
+ {
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ TypedStrData* pData;
+ ULONG nFormat = GetNumberFormat( nRow );
+
+ ScCellFormat::GetInputString( pCell, nFormat, aString, *pFormatter );
+
+ if ( pDocument->HasStringData( nCol, nRow, nTab ) )
+ pData = new TypedStrData( aString );
+ else
+ {
+ double nValue;
+
+ switch ( pCell->GetCellType() )
+ {
+ case CELLTYPE_VALUE:
+ nValue = ((ScValueCell*)pCell)->GetValue();
+ break;
+
+ case CELLTYPE_FORMULA:
+ nValue = ((ScFormulaCell*)pCell)->GetValue();
+ break;
+
+ default:
+ nValue = 0.0;
+ }
+
+ pData = new TypedStrData( aString, nValue, SC_STRTYPE_VALUE );
+ }
+
+ if ( !rStrings.Insert( pData ) )
+ delete pData; // doppelt
+
+ ++nIndex;
+ }
+}
+
+//
+// GetDataEntries - Strings aus zusammenhaengendem Bereich um nRow
+//
+
+// DATENT_MAX - max. Anzahl Eintrage in Liste fuer Auto-Eingabe
+// DATENT_SEARCH - max. Anzahl Zellen, die durchsucht werden - neu: nur Strings zaehlen
+#define DATENT_MAX 200
+#define DATENT_SEARCH 2000
+
+#pragma SEG_FUNCDEF(column3_1f)
+
+BOOL ScColumn::GetDataEntries(USHORT nStartRow, TypedStrCollection& rStrings, BOOL bLimit)
+{
+ BOOL bFound = FALSE;
+ USHORT nThisIndex;
+ BOOL bThisUsed = Search( nStartRow, nThisIndex );
+ String aString;
+ USHORT nCells = 0;
+
+ // Die Beschraenkung auf angrenzende Zellen (ohne Luecken) ist nicht mehr gewollt
+ // (Featurekommission zur 5.1), stattdessen abwechselnd nach oben und unten suchen,
+ // damit naheliegende Zellen wenigstens zuerst gefunden werden.
+ //! Abstaende der Zeilennummern vergleichen? (Performance??)
+
+ USHORT nUpIndex = nThisIndex; // zeigt hinter die Zelle
+ USHORT nDownIndex = nThisIndex; // zeigt auf die Zelle
+ if (bThisUsed)
+ ++nDownIndex; // Startzelle ueberspringen
+
+ while ( nUpIndex || nDownIndex < nCount )
+ {
+ if ( nUpIndex ) // nach oben
+ {
+ ScBaseCell* pCell = pItems[nUpIndex-1].pCell;
+ CellType eType = pCell->GetCellType();
+ if (eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT) // nur Strings interessieren
+ {
+ if (eType == CELLTYPE_STRING)
+ ((ScStringCell*)pCell)->GetString(aString);
+ else
+ ((ScEditCell*)pCell)->GetString(aString);
+
+ TypedStrData* pData = new TypedStrData(aString);
+ if ( !rStrings.Insert( pData ) )
+ delete pData; // doppelt
+ else if ( bLimit && rStrings.GetCount() >= DATENT_MAX )
+ break; // Maximum erreicht
+ bFound = TRUE;
+
+ if ( bLimit )
+ if (++nCells >= DATENT_SEARCH)
+ break; // genug gesucht
+ }
+ --nUpIndex;
+ }
+
+ if ( nDownIndex < nCount ) // nach unten
+ {
+ ScBaseCell* pCell = pItems[nDownIndex].pCell;
+ CellType eType = pCell->GetCellType();
+ if (eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT) // nur Strings interessieren
+ {
+ if (eType == CELLTYPE_STRING)
+ ((ScStringCell*)pCell)->GetString(aString);
+ else
+ ((ScEditCell*)pCell)->GetString(aString);
+
+ TypedStrData* pData = new TypedStrData(aString);
+ if ( !rStrings.Insert( pData ) )
+ delete pData; // doppelt
+ else if ( bLimit && rStrings.GetCount() >= DATENT_MAX )
+ break; // Maximum erreicht
+ bFound = TRUE;
+
+ if ( bLimit )
+ if (++nCells >= DATENT_SEARCH)
+ break; // genug gesucht
+ }
+ ++nDownIndex;
+ }
+ }
+
+ return bFound;
+}
+
+#undef DATENT_MAX
+#undef DATENT_SEARCH
+
+#pragma SEG_FUNCDEF(column3_0d)
+
+void ScColumn::RemoveProtected( USHORT nStartRow, USHORT nEndRow )
+{
+ ScAttrIterator aAttrIter( pAttrArray, nStartRow, nEndRow );
+ USHORT nTop;
+ USHORT nBottom;
+ USHORT nIndex;
+ const ScPatternAttr* pPattern = aAttrIter.Next( nTop, nBottom );
+ while (pPattern)
+ {
+ const ScProtectionAttr* pAttr = (const ScProtectionAttr*)&pPattern->GetItem(ATTR_PROTECTION);
+ if ( pAttr->GetHideCell() )
+ DeleteArea( nTop, nBottom, IDF_CONTENTS );
+ else if ( pAttr->GetHideFormula() )
+ {
+ Search( nTop, nIndex );
+ while ( nIndex<nCount && pItems[nIndex].nRow<=nBottom )
+ {
+ if ( pItems[nIndex].pCell->GetCellType() == CELLTYPE_FORMULA )
+ {
+ ScFormulaCell* pFormula = (ScFormulaCell*)pItems[nIndex].pCell;
+ if (pFormula->IsValue())
+ {
+ double nVal = pFormula->GetValue();
+ pItems[nIndex].pCell = new ScValueCell( nVal );
+ }
+ else
+ {
+ String aString;
+ pFormula->GetString(aString);
+ pItems[nIndex].pCell = new ScStringCell( aString );
+ }
+ delete pFormula;
+ }
+ ++nIndex;
+ }
+ }
+
+ pPattern = aAttrIter.Next( nTop, nBottom );
+ }
+}
+
+#pragma SEG_FUNCDEF(column3_0e)
+
+void ScColumn::SetError( USHORT nRow, const USHORT nError)
+{
+ if (VALIDROW(nRow))
+ {
+ ScFormulaCell* pCell = new ScFormulaCell
+ ( pDocument, ScAddress( nCol, nRow, nTab ) );
+ pCell->SetErrCode( nError );
+ Insert( nRow, pCell );
+ }
+}
+
+#pragma SEG_FUNCDEF(column3_0f)
+
+void ScColumn::SetValue( USHORT nRow, const double& rVal)
+{
+ if (VALIDROW(nRow))
+ {
+ ScBaseCell* pCell = new ScValueCell(rVal);
+ Insert( nRow, pCell );
+ }
+}
+
+#pragma SEG_FUNCDEF(column3_10)
+
+void ScColumn::SetNote( USHORT nRow, const ScPostIt& rNote)
+{
+ BOOL bEmpty = !rNote.GetText().Len();
+
+ USHORT nIndex;
+ if (Search(nRow, nIndex))
+ {
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ if (bEmpty && pCell->GetCellType() == CELLTYPE_NOTE && !pCell->GetBroadcaster())
+ DeleteAtIndex(nIndex);
+ else
+ pCell->SetNote(rNote);
+ }
+ else
+ {
+ if (!bEmpty)
+ Insert(nRow, new ScNoteCell(rNote));
+ }
+}
+
+#pragma SEG_FUNCDEF(column3_11)
+
+void ScColumn::GetString( USHORT nRow, String& rString ) const
+{
+ USHORT nIndex;
+ Color* pColor;
+ if (Search(nRow, nIndex))
+ {
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ if (pCell->GetCellType() != CELLTYPE_NOTE)
+ {
+ ULONG nFormat = GetNumberFormat( nRow );
+ ScCellFormat::GetString( pCell, nFormat, rString, &pColor, *(pDocument->GetFormatTable()) );
+ }
+ else
+ rString.Erase();
+ }
+ else
+ rString.Erase();
+}
+
+#pragma SEG_FUNCDEF(column3_12)
+
+void ScColumn::GetInputString( USHORT nRow, String& rString ) const
+{
+ USHORT nIndex;
+ if (Search(nRow, nIndex))
+ {
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ if (pCell->GetCellType() != CELLTYPE_NOTE)
+ {
+ ULONG nFormat = GetNumberFormat( nRow );
+ ScCellFormat::GetInputString( pCell, nFormat, rString, *(pDocument->GetFormatTable()) );
+ }
+ else
+ rString.Erase();
+ }
+ else
+ rString.Erase();
+}
+
+#pragma SEG_FUNCDEF(column3_13)
+
+double ScColumn::GetValue( USHORT nRow ) const
+{
+ USHORT nIndex;
+ if (Search(nRow, nIndex))
+ {
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ switch (pCell->GetCellType())
+ {
+ case CELLTYPE_VALUE:
+ return ((ScValueCell*)pCell)->GetValue();
+ break;
+ case CELLTYPE_FORMULA:
+ {
+ if (((ScFormulaCell*)pCell)->IsValue())
+ return ((ScFormulaCell*)pCell)->GetValue();
+ else
+ return 0.0;
+ }
+ break;
+ default:
+ return 0.0;
+ break;
+ }
+ }
+ return 0.0;
+}
+
+#pragma SEG_FUNCDEF(column3_14)
+
+void ScColumn::GetFormula( USHORT nRow, String& rFormula, BOOL ) const
+{
+ USHORT nIndex;
+ if (Search(nRow, nIndex))
+ {
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ if (pCell->GetCellType() == CELLTYPE_FORMULA)
+ ((ScFormulaCell*)pCell)->GetFormula( rFormula );
+ else
+ rFormula.Erase();
+ }
+ else
+ rFormula.Erase();
+}
+
+#pragma SEG_FUNCDEF(column3_15)
+
+BOOL ScColumn::GetNote( USHORT nRow, ScPostIt& rNote) const
+{
+ BOOL bHasNote = FALSE;
+ USHORT nIndex;
+ if (Search(nRow, nIndex))
+ bHasNote = pItems[nIndex].pCell->GetNote(rNote);
+ else
+ rNote.Clear();
+
+ return bHasNote;
+}
+
+#pragma SEG_FUNCDEF(column3_28)
+
+CellType ScColumn::GetCellType( USHORT nRow ) const
+{
+ USHORT nIndex;
+ if (Search(nRow, nIndex))
+ return pItems[nIndex].pCell->GetCellType();
+ return CELLTYPE_NONE;
+}
+
+#pragma SEG_FUNCDEF(column3_29)
+
+USHORT ScColumn::GetErrCode( USHORT nRow ) const
+{
+ USHORT nIndex;
+ if (Search(nRow, nIndex))
+ {
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ if (pCell->GetCellType() == CELLTYPE_FORMULA)
+ return ((ScFormulaCell*)pCell)->GetErrCode();
+ }
+ return 0;
+}
+
+#pragma SEG_FUNCDEF(column3_18)
+
+BOOL ScColumn::HasStringData( USHORT nRow ) const
+{
+ USHORT nIndex;
+ if (Search(nRow, nIndex))
+ return (pItems[nIndex].pCell)->HasStringData();
+ return FALSE;
+}
+
+#pragma SEG_FUNCDEF(column3_19)
+
+BOOL ScColumn::HasValueData( USHORT nRow ) const
+{
+ USHORT nIndex;
+ if (Search(nRow, nIndex))
+ return (pItems[nIndex].pCell)->HasValueData();
+ return FALSE;
+}
+
+BOOL ScColumn::HasStringCells( USHORT nStartRow, USHORT nEndRow ) const
+{
+ // TRUE, wenn String- oder Editzellen im Bereich
+
+ if ( pItems )
+ {
+ USHORT nIndex;
+ Search( nStartRow, nIndex );
+ while ( nIndex < nCount && pItems[nIndex].nRow <= nEndRow )
+ {
+ CellType eType = pItems[nIndex].pCell->GetCellType();
+ if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT )
+ return TRUE;
+ ++nIndex;
+ }
+ }
+ return FALSE;
+}
+
+#pragma SEG_FUNCDEF(column3_20)
+
+xub_StrLen ScColumn::GetMaxStringLen( USHORT nRowStart, USHORT nRowEnd ) const
+{
+ xub_StrLen nStringLen = 0;
+ if ( pItems )
+ {
+ String aString;
+ SvNumberFormatter* pNumFmt = pDocument->GetFormatTable();
+ USHORT nIndex, nRow;
+ Search( nRowStart, nIndex );
+ while ( nIndex < nCount && (nRow = pItems[nIndex].nRow) <= nRowEnd )
+ {
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ if ( pCell->GetCellType() != CELLTYPE_NOTE )
+ {
+ Color* pColor;
+ ULONG nFormat = (ULONG) ((SfxUInt32Item*) GetAttr(
+ nRow, ATTR_VALUE_FORMAT ))->GetValue();
+ ScCellFormat::GetString( pCell, nFormat, aString, &pColor,
+ *pNumFmt );
+ if ( nStringLen < aString.Len() )
+ nStringLen = aString.Len();
+ }
+ nIndex++;
+ }
+ }
+ return nStringLen;
+}
+
+#pragma SEG_FUNCDEF(column3_21)
+
+xub_StrLen ScColumn::GetMaxNumberStringLen( USHORT& nPrecision,
+ USHORT nRowStart, USHORT nRowEnd ) const
+{
+ xub_StrLen nStringLen = 0;
+ nPrecision = pDocument->GetDocOptions().GetStdPrecision();
+ if ( pItems )
+ {
+ String aString;
+ SvNumberFormatter* pNumFmt = pDocument->GetFormatTable();
+ sal_Unicode cDecSep = ScGlobal::pScInternational->GetNumDecimalSep();
+ USHORT nIndex, nRow;
+ Search( nRowStart, nIndex );
+ while ( nIndex < nCount && (nRow = pItems[nIndex].nRow) <= nRowEnd )
+ {
+ ScBaseCell* pCell = pItems[nIndex].pCell;
+ CellType eType = pCell->GetCellType();
+ if ( eType == CELLTYPE_VALUE || (eType == CELLTYPE_FORMULA
+ && ((ScFormulaCell*)pCell)->IsValue()) )
+ {
+ ULONG nFormat = (ULONG) ((SfxUInt32Item*) GetAttr(
+ nRow, ATTR_VALUE_FORMAT ))->GetValue();
+ ScCellFormat::GetInputString( pCell, nFormat, aString, *pNumFmt );
+ xub_StrLen nLen = aString.Len();
+ if ( nLen )
+ {
+ if ( nFormat )
+ { // mehr Nachkommastellen als Standard?
+ USHORT nPrec = pNumFmt->GetFormatPrecision( nFormat );
+ if ( nPrec > nPrecision )
+ nPrecision = nPrec;
+ }
+ if ( nPrecision )
+ { // falls im String zuwenig Nachkommas => verbreitern
+ // falls zuviel => kuerzen
+ xub_StrLen nToken = aString.GetTokenCount( cDecSep );
+ xub_StrLen nPrecLen = nPrecision;
+ if ( nToken > 1 )
+ {
+ String aTmp( aString.GetToken( nToken - 1, cDecSep ) );
+ if ( aTmp.Len() != nPrecLen )
+ nLen += nPrecLen - aTmp.Len();
+ // nPrecision > aTmp.Len() : nLen + Diff
+ // nPrecision < aTmp.Len() : nLen - Diff
+ }
+ else
+ nLen += nPrecLen + 1;
+ }
+ if ( nStringLen < nLen )
+ nStringLen = nLen;
+ }
+ }
+ nIndex++;
+ }
+ }
+ return nStringLen;
+}
+
+
+/*------------------------------------------------------------------------
+
+ $Log: not supported by cvs2svn $
+ Revision 1.100 2000/09/17 14:08:35 willem.vandorp
+ OpenOffice header added.
+
+ Revision 1.99 2000/08/31 16:37:56 willem.vandorp
+ Header and footer replaced
+
+ Revision 1.98 2000/04/10 17:02:18 nn
+ unicode changes
+
+ Revision 1.97 1999/07/28 12:21:10 ER
+ #67776# DeleteRange: discard all broadcasters of deleted cells prior to broadcasting
+
+
+ Rev 1.96 28 Jul 1999 14:21:10 ER
+ #67776# DeleteRange: discard all broadcasters of deleted cells prior to broadcasting
+
+ Rev 1.95 22 Jun 1999 16:57:04 ER
+ #66563# GetFilterEntries: GetInputString instead of GetString
+
+ Rev 1.94 23 Oct 1998 09:47:00 NN
+ #58367# GetDataEntries auch ueber Luecken hinweg, HasStringData
+
+ Rev 1.93 13 Jul 1998 21:50:20 NN
+ #52337# ScBroadcasterList statt SfxBroadcaster an der Zelle
+
+ Rev 1.92 06 Jul 1998 20:56:10 ER
+ #41640# SetString: bei Import direktes Append
+
+ Rev 1.91 02 Jul 1998 21:05:08 ER
+ #43509# EditCells mit EditPool
+
+ Rev 1.90 22 Jun 1998 21:17:42 NN
+ Delete/DeleteAtIndex: EndListeningTo
+
+ Rev 1.89 08 Jun 1998 16:37:42 ER
+ SetString: einzelnes '=' ist keine Formel
+
+ Rev 1.88 27 May 1998 18:00:52 NN
+ #50580# CopyFromClip: End-Zeile richtig abfragen
+
+ Rev 1.87 05 May 1998 17:19:06 NN
+ #48491# CloneCell: Wert aus Formel nicht in Undo-Dokument
+
+ Rev 1.86 19 Mar 1998 19:13:32 NN
+ #47901# DeleteArea: Attribute erst hinterher
+
+ Rev 1.85 04 Dec 1997 22:08:16 NN
+ includes
+
+ Rev 1.84 13 Nov 1997 20:55:26 NN
+ ifndef PCH raus
+
+ Rev 1.83 07 Nov 1997 18:07:16 ER
+ #45417# SetString: NumberformatIndex mit GetNumberFormat holen statt GetAttr
+
+ Rev 1.82 13 Oct 1997 15:32:10 NN
+ DeleteArea: ggf. RemoveEditAttribs aufrufen
+
+ Rev 1.81 07 Oct 1997 14:46:18 ER
+ #43940# DeleteRow: Quelle und Ziel broadcasten; Search eingebaut
+
+ Rev 1.80 01 Oct 1997 19:51:28 NN
+ alte includes raus
+
+ Rev 1.79 21 Jul 1997 17:21:54 ER
+ Insert: EndListening wenn bestehende Formelzelle ersetzt wird
+
+ Rev 1.78 10 Jul 1997 16:06:04 NN
+ #41542# Formelzellen und Fehler in Formeln bei CloneCell
+
+ Rev 1.77 07 Jul 1997 12:57:32 ER
+ SetString: uninitialized nIndex,nOldIndex bei bIsLoading in erster Zeile
+
+ Rev 1.76 18 Jun 1997 13:20:38 ER
+ SetString: bei IsLoading pruefen, ob letzte Zellen gleichen
+ String enthalten und NumberScanner einsparen
+
+ Rev 1.75 10 Jun 1997 18:40:36 ER
+ SetString: nur eine Ziffer ist auch Zahl
+
+ Rev 1.74 09 Jun 1997 16:54:54 ER
+ opt: SetString: bei IsLoading (ConvertFrom Import) keine NumberFormate holen
+
+ Rev 1.73 18 Apr 1997 19:10:12 ER
+ Delete: Broadcaster stehenlassen
+
+ Rev 1.72 10 Apr 1997 14:18:30 NN
+ #38648# Insert: Notizen stehenlassen
+
+ Rev 1.71 03 Mar 1997 10:53:44 NN
+ #35892# DeleteRange: Value/DateTime Abfrage richtig
+
+ Rev 1.70 17 Feb 1997 18:51:26 NN
+ TypedStrData: nStrType statt bIsString
+
+ Rev 1.69 10 Jan 1997 17:29:10 ER
+ GetErrCode, GetValue non-pascal
+
+ Rev 1.68 09 Jan 1997 20:04:40 ER
+ new: GetCellType, GetErrCode non-pascal
+
+ Rev 1.67 08 Jan 1997 20:11:14 ER
+ ScAddress als Reference (keine temporaeren Objekte ohne inlining)
+
+ Rev 1.66 19 Dec 1996 12:47:00 NN
+ SetString: TRUE zurueck, wenn Zahlformat gesetzt
+
+ Rev 1.65 06 Dec 1996 18:46:54 NN
+ #34142# CopyFromClip: Resize nur bei grossen Bloecken
+
+ Rev 1.64 27 Nov 1996 20:13:50 NN
+ #33572# beim Loeschen von Notizen auch Zeichenobjekte loeschen
+
+ Rev 1.63 12 Nov 1996 19:21:16 ER
+ #33224# CloneCell: LeerStrings nicht kopieren
+
+ Rev 1.62 01 Nov 1996 09:27:02 TRI
+ scitems.hxx included
+
+ Rev 1.61 10 Oct 1996 19:54:56 RJ
+ Eingabe mit ' am Anfang => String
+
+ Rev 1.60 04 Sep 1996 20:35:18 NN
+ CopyFromClip/bAsLink: bei IDF_ALL auch leere, sonst keine NoteCells
+
+ Rev 1.59 19 Aug 1996 21:23:48 NN
+ Markierungen werden nicht mehr am Dokument gehalten
+
+ Rev 1.58 06 Aug 1996 16:59:14 ER
+ new: Numberformat LanguageItem
+
+ Rev 1.57 04 Jun 1996 13:27:24 ER
+ GetMaxNumberStringLen: GetInputString statt GetString, und nur wenn Value
+
+ Rev 1.56 23 May 1996 19:37:34 NN
+ #27994# MixData: Source-Index auch von der Source-Spalte holen
+
+ Rev 1.55 21 May 1996 15:55:04 NN
+ Parameter bLimit bei GetDataEntries
+
+ Rev 1.54 20 May 1996 17:54:24 ER
+ again: StartRelNameListeners, SetRelNameDirty
+
+ Rev 1.53 15 May 1996 18:21:58 ER
+ chg: StartListeningFromClip --> StartListeningInArea
+ BroadcastFromClip --> BroadcastInArea
+
+ Rev 1.52 15 May 1996 17:00:12 ER
+ StartListeningFromClip, BroadcastFromClip:
+ Bloecke durchlaufen statt einzeln Search
+
+ Rev 1.51 14 May 1996 16:03:50 ER
+ del: HasRelNameReference, StartRelNameListeners, SetRelNameDirty
+
+ Rev 1.50 13 May 1996 14:08:32 NN
+ MixMarked, nStartIndex suchen bei MixData
+
+ Rev 1.49 10 May 1996 16:44:36 NN
+ Verknuepfen aus dem Clipboard
+
+ Rev 1.48 09 May 1996 10:37:12 ER
+ GetFormatSpecialInfo --> GetFormatPrecision
+
+ Rev 1.47 08 May 1996 08:44:30 NN
+ MixData, CreateAttrIterator
+
+ Rev 1.46 06 May 1996 12:51:46 ER
+ new: GetMaxStringLen, GetMaxNumberStringLen
+
+ Rev 1.45 03 May 1996 18:16:58 NN
+ GetDataEntries
+
+ Rev 1.44 22 Apr 1996 16:35:40 NN
+ DeleteRange: Abfrage auf IDF_DATETIME/IDF_VALUE richtig
+
+ Rev 1.43 19 Apr 1996 17:24:20 NN
+ nicht unnoetig GetPattern rufen
+
+ Rev 1.42 27 Mar 1996 12:27:30 ER
+ sv.hxx --> svgen.hxx
+
+ Rev 1.41 11 Mar 1996 14:34:54 ER
+ new: ScBaseCell HasValueData / HasStringData
+
+ Rev 1.40 01 Mar 1996 09:23:46 NN
+ Zelltyp-Abfrage von CopyFromClip nach CloneCell
+
+ Rev 1.39 12 Feb 1996 15:58:04 NN
+ wenn bDoubleAlloc gesetzt, Array fuer neue Zellen verdoppeln
+
+ Rev 1.38 10 Feb 1996 22:13:24 ER
+ #24719# ein weiterer Err527 Workaround
+ greift jetzt auch bei zweimal gleicher Zelle editiert
+
+ Rev 1.37 26 Jan 1996 12:16:26 ER
+ SetString: Index nach EndListening ggbf. wiederfinden
+
+ Rev 1.36 25 Jan 1996 17:51:06 ER
+ SetString: EndListening der alten Zelle
+
+ Rev 1.35 11 Jan 1996 23:18:20 ER
+ #23621# #23851# referierter Bereich geloescht => ungueltige Referenz
+
+ Rev 1.34 11 Jan 1996 01:47:16 ER
+ #23721# benannte Bereiche mit relativen Referenzen
+
+ Rev 1.33 21 Dec 1995 15:21:14 ER
+ DeleteRow: Formelzelle aPos anpassen
+
+ Rev 1.32 20 Dec 1995 20:58:56 ER
+ add: StartListeningFromClip, BroadcastFromClip
+
+ Rev 1.31 16 Dec 1995 22:53:32 ER
+ #23562 DeleteRange: Broadcaster kann durch EndListening zerstoert sein
+
+ Rev 1.30 15 Dec 1995 03:02:40 ER
+ ForgetBroadcaster erst nach Broadcast
+
+ Rev 1.29 14 Dec 1995 16:17:44 ER
+ StarAllListeners: Index wiederfinden falls Listener eingefuegt
+
+ Rev 1.28 13 Dec 1995 13:37:06 ER
+ default ist jetzt bNoSetDirty==TRUE (wg. IterCircRef)
+
+ Rev 1.27 06 Dec 1995 16:19:02 ER
+ del: StartListeningFromClip, add: StartAllListeners
+
+ Rev 1.26 06 Dec 1995 12:46:34 NN
+ bei SetString keine Formate mehr fuer Formeln setzen
+
+ Rev 1.25 05 Dec 1995 20:29:08 ER
+ Dummy NoteCell fuer Interpret in Broacast bei Delete
+
+ Rev 1.24 05 Dec 1995 16:36:34 ER
+ bCalcingAfterLoad in Insert fuer NoteCell
+
+ Rev 1.23 05 Dec 1995 10:35:22 ER
+ NoteCells broadcasten nicht beim Insert => Dok laedt schneller
+
+ Rev 1.22 01 Dec 1995 14:26:50 NN
+ DeleteRange: Formelzellen spaeter loeschen wegen EndListening
+
+ Rev 1.21 28 Nov 1995 22:17:22 ER
+ chg: Insert ohne bFromClip
+
+ Rev 1.20 27 Nov 1995 16:13:26 NN
+ CopyFromClip: Resize vorher
+
+ Rev 1.19 24 Nov 1995 17:28:44 ER
+ del: StartAllListeners
+
+ Rev 1.18 24 Nov 1995 14:25:14 ER
+ add: StartAllListeners
+
+ Rev 1.17 23 Nov 1995 17:41:12 ER
+ chg: Insert mit bFromClip, nur Append nicht
+
+ Rev 1.16 22 Nov 1995 16:45:00 MD
+ Insert/Append ohne bClipMode
+
+ Rev 1.15 20 Nov 1995 09:25:56 NN
+ Klammern bei Clone richtig
+
+ Rev 1.14 19 Nov 1995 16:50:32 ER
+ aus CopyFromClip Clone mit bNoListening
+
+ Rev 1.13 19 Nov 1995 16:17:10 MD
+ Umbau auf ScTokenArray
+
+ Rev 1.12 14 Nov 1995 18:39:40 ER
+ add: StartListenigFromClip
+
+ Rev 1.11 14 Nov 1995 17:04:04 ER
+ in Clipboard- und Undo-Doc kein Broadcasting/Listening bei Insert/Append
+
+ Rev 1.10 09 Nov 1995 17:09:22 MD
+ enum ScForceTextFmt
+
+ Rev 1.9 06 Nov 1995 19:31:06 ER
+ Broadcasting in Delete* und Append
+
+ Rev 1.8 03 Nov 1995 17:12:06 NN
+ DeleteRange: Notizzellen nur loeschen, wenn keine Broadcaster
+
+ Rev 1.7 03 Nov 1995 14:36:58 ER
+ add: BroadcastFromClip
+
+ Rev 1.6 01 Nov 1995 16:29:36 ER
+ StartListeningTo() in ersetzter Zelle
+
+ Rev 1.5 01 Nov 1995 16:22:10 NN
+ Broadcaster bei DeleteRow beruecksichtigen
+
+ Rev 1.4 31 Oct 1995 17:46:32 ER
+ EndListenigTo()
+
+ Rev 1.3 30 Oct 1995 19:31:50 ER
+ Broadcast nur wenn Zelle
+
+ Rev 1.2 30 Oct 1995 16:50:54 ER
+ add: ScBaseCell::Listening()
+
+ Rev 1.1 30 Oct 1995 15:52:42 ER
+ Broadcast() Wrapper
+
+ Rev 1.0 30 Oct 1995 12:11:26 NN
+ Initial revision.
+
+------------------------------------------------------------------------*/
+
+#pragma SEG_EOFMODULE
+
diff --git a/sc/source/core/data/conditio.cxx b/sc/source/core/data/conditio.cxx
new file mode 100644
index 000000000000..df3b387d0d75
--- /dev/null
+++ b/sc/source/core/data/conditio.cxx
@@ -0,0 +1,1542 @@
+/*************************************************************************
+ *
+ * $RCSfile: conditio.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+//------------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <sfx2/objsh.hxx>
+#include <svtools/itemset.hxx>
+#include <svtools/zforlist.hxx>
+#include <tools/intn.hxx>
+#include <tools/solmath.hxx>
+
+#include "conditio.hxx"
+#include "cell.hxx"
+#include "document.hxx"
+#include "hints.hxx"
+#include "compiler.hxx"
+#include "rechead.hxx"
+#include "rangelst.hxx"
+#include "stlpool.hxx"
+
+//------------------------------------------------------------------------
+
+SV_IMPL_OP_PTRARR_SORT( ScConditionalFormats_Impl, ScConditionalFormatPtr );
+
+//------------------------------------------------------------------------
+
+BOOL lcl_HasRelRef( ScTokenArray* pFormula )
+{
+ if (pFormula)
+ {
+ pFormula->Reset();
+ ScToken* t;
+ for( t = pFormula->GetNextReference(); t; t = pFormula->GetNextReference() )
+ {
+ ComplRefData& rRef = t->GetReference();
+ if ( rRef.Ref1.IsColRel() || rRef.Ref1.IsRowRel() || rRef.Ref1.IsTabRel() ||
+ rRef.Ref2.IsColRel() || rRef.Ref2.IsRowRel() || rRef.Ref2.IsTabRel() )
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+ScConditionEntry::ScConditionEntry( const ScConditionEntry& r ) :
+ eOp(r.eOp),
+ nOptions(r.nOptions),
+ nVal1(r.nVal1),
+ nVal2(r.nVal2),
+ aStrVal1(r.aStrVal1),
+ aStrVal2(r.aStrVal2),
+ bIsStr1(r.bIsStr1),
+ bIsStr2(r.bIsStr2),
+ bRelRef1(r.bRelRef1),
+ bRelRef2(r.bRelRef2),
+ pFormula1(NULL),
+ pFormula2(NULL),
+ pFCell1(NULL),
+ pFCell2(NULL),
+ pDoc(r.pDoc),
+ aSrcPos(r.aSrcPos),
+ bFirstRun(TRUE)
+{
+ // ScTokenArray copy ctor erzeugt flache Kopie
+
+ if (r.pFormula1)
+ pFormula1 = new ScTokenArray( *r.pFormula1 );
+ if (r.pFormula2)
+ pFormula2 = new ScTokenArray( *r.pFormula2 );
+
+ // Formelzellen werden erst bei IsValid angelegt
+}
+
+ScConditionEntry::ScConditionEntry( ScDocument* pDocument, const ScConditionEntry& r ) :
+ eOp(r.eOp),
+ nOptions(r.nOptions),
+ nVal1(r.nVal1),
+ nVal2(r.nVal2),
+ aStrVal1(r.aStrVal1),
+ aStrVal2(r.aStrVal2),
+ bIsStr1(r.bIsStr1),
+ bIsStr2(r.bIsStr2),
+ bRelRef1(r.bRelRef1),
+ bRelRef2(r.bRelRef2),
+ pFormula1(NULL),
+ pFormula2(NULL),
+ pFCell1(NULL),
+ pFCell2(NULL),
+ pDoc(pDocument),
+ aSrcPos(r.aSrcPos),
+ bFirstRun(TRUE)
+{
+ // echte Kopie der Formeln (fuer Ref-Undo)
+
+ if (r.pFormula1)
+ pFormula1 = r.pFormula1->Clone();
+ if (r.pFormula2)
+ pFormula2 = r.pFormula2->Clone();
+
+ // Formelzellen werden erst bei IsValid angelegt
+ //! im Clipboard nicht - dann vorher interpretieren !!!
+}
+
+ScConditionEntry::ScConditionEntry( ScConditionMode eOper,
+ const String& rExpr1, const String& rExpr2,
+ ScDocument* pDocument, const ScAddress& rPos,
+ BOOL bCompileEnglish ) :
+ eOp(eOper),
+ nOptions(0), // spaeter...
+ nVal1(0.0),
+ nVal2(0.0),
+ bIsStr1(FALSE),
+ bIsStr2(FALSE),
+ bRelRef1(FALSE),
+ bRelRef2(FALSE),
+ pFormula1(NULL),
+ pFormula2(NULL),
+ pFCell1(NULL),
+ pFCell2(NULL),
+ pDoc(pDocument),
+ aSrcPos(rPos),
+ bFirstRun(TRUE)
+{
+ Compile( rExpr1, rExpr2, bCompileEnglish );
+
+ // Formelzellen werden erst bei IsValid angelegt
+}
+
+ScConditionEntry::ScConditionEntry( ScConditionMode eOper,
+ const ScTokenArray* pArr1, const ScTokenArray* pArr2,
+ ScDocument* pDocument, const ScAddress& rPos ) :
+ eOp(eOper),
+ nOptions(0), // spaeter...
+ nVal1(0.0),
+ nVal2(0.0),
+ bIsStr1(FALSE),
+ bIsStr2(FALSE),
+ bRelRef1(FALSE),
+ bRelRef2(FALSE),
+ pFormula1(NULL),
+ pFormula2(NULL),
+ pFCell1(NULL),
+ pFCell2(NULL),
+ pDoc(pDocument),
+ aSrcPos(rPos),
+ bFirstRun(TRUE)
+{
+ if ( pArr1 )
+ {
+ pFormula1 = new ScTokenArray( *pArr1 );
+ if ( pFormula1->GetLen() == 1 )
+ {
+ // einzelne (konstante Zahl) ?
+ ScToken* pToken = pFormula1->First();
+ if ( pToken->GetOpCode() == ocPush )
+ {
+ if ( pToken->GetType() == svDouble )
+ {
+ nVal1 = pToken->nValue;
+ DELETEZ(pFormula1); // nicht als Formel merken
+ }
+ else if ( pToken->GetType() == svString )
+ {
+ bIsStr1 = TRUE;
+ aStrVal1 = pToken->cStr; // char-ptr
+ DELETEZ(pFormula1); // nicht als Formel merken
+ }
+ }
+ }
+ bRelRef1 = lcl_HasRelRef( pFormula1 );
+ }
+ if ( pArr2 )
+ {
+ pFormula2 = new ScTokenArray( *pArr2 );
+ if ( pFormula2->GetLen() == 1 )
+ {
+ // einzelne (konstante Zahl) ?
+ ScToken* pToken = pFormula2->First();
+ if ( pToken->GetOpCode() == ocPush )
+ {
+ if ( pToken->GetType() == svDouble )
+ {
+ nVal2 = pToken->nValue;
+ DELETEZ(pFormula2); // nicht als Formel merken
+ }
+ else if ( pToken->GetType() == svString )
+ {
+ bIsStr2 = TRUE;
+ aStrVal2 = pToken->cStr; // char-ptr
+ DELETEZ(pFormula2); // nicht als Formel merken
+ }
+ }
+ }
+ bRelRef2 = lcl_HasRelRef( pFormula2 );
+ }
+
+ // formula cells are created at IsValid
+}
+
+ScConditionEntry::~ScConditionEntry()
+{
+ delete pFCell1;
+ delete pFCell2;
+}
+
+ScConditionEntry::ScConditionEntry( SvStream& rStream, ScMultipleReadHeader& rHdr,
+ ScDocument* pDocument ) :
+ nVal1(0.0),
+ nVal2(0.0),
+ bIsStr1(FALSE),
+ bIsStr2(FALSE),
+ bRelRef1(FALSE),
+ bRelRef2(FALSE),
+ pFormula1(NULL),
+ pFormula2(NULL),
+ pFCell1(NULL),
+ pFCell2(NULL),
+ pDoc(pDocument),
+ bFirstRun(TRUE)
+{
+ USHORT nVer = (USHORT) pDoc->GetSrcVersion();
+
+ rHdr.StartEntry();
+
+ BYTE nOpByte;
+ rStream >> nOpByte;
+ eOp = (ScConditionMode) nOpByte;
+
+ rStream >> nOptions;
+
+ ScAddress aPos;
+ BYTE nTypeByte;
+ rStream >> nTypeByte;
+ ScConditionValType eType = (ScConditionValType) nTypeByte;
+ if ( eType == SC_VAL_FORMULA )
+ {
+ rStream >> aPos;
+ pFormula1 = new ScTokenArray;
+ pFormula1->Load( rStream, nVer, aPos );
+ bRelRef1 = lcl_HasRelRef( pFormula1 );
+ }
+ else if ( eType == SC_VAL_VALUE )
+ rStream >> nVal1;
+ else
+ {
+ bIsStr1 = TRUE;
+ rStream.ReadByteString( aStrVal1, rStream.GetStreamCharSet() );
+ }
+
+ if ( eOp == SC_COND_BETWEEN || eOp == SC_COND_NOTBETWEEN )
+ {
+ rStream >> nTypeByte;
+ eType = (ScConditionValType) nTypeByte;
+ if ( eType == SC_VAL_FORMULA )
+ {
+ rStream >> aPos;
+ pFormula2 = new ScTokenArray;
+ pFormula2->Load( rStream, nVer, aPos );
+ bRelRef2 = lcl_HasRelRef( pFormula2 );
+ }
+ else if ( eType == SC_VAL_VALUE )
+ rStream >> nVal2;
+ else
+ {
+ bIsStr2 = TRUE;
+ rStream.ReadByteString( aStrVal2, rStream.GetStreamCharSet() );
+ }
+ }
+
+ rHdr.EndEntry();
+
+ aSrcPos = aPos;
+
+ // Formelzellen werden erst bei IsValid angelegt
+}
+
+void ScConditionEntry::StoreCondition(SvStream& rStream, ScMultipleWriteHeader& rHdr) const
+{
+ rHdr.StartEntry();
+
+ // 1) Byte fuer die Operation
+ // 2) USHORT fuer Optionen
+ // 3) Byte, ob Wert, String oder Formel folgt
+ // 4) double, String oder TokenArray
+ // 5) je nach Operation 3 und 4 nochmal
+ // vor jedem TokenArray noch die Position als ScAddress
+
+ rStream << (BYTE) eOp;
+ rStream << nOptions;
+
+ ScConditionValType eType =
+ pFormula1 ? SC_VAL_FORMULA : ( bIsStr1 ? SC_VAL_STRING : SC_VAL_VALUE );
+ rStream << (BYTE) eType;
+ if ( eType == SC_VAL_FORMULA )
+ {
+ rStream << aSrcPos;
+ pFormula1->Store( rStream, aSrcPos );
+ }
+ else if ( eType == SC_VAL_VALUE )
+ rStream << nVal1;
+ else
+ rStream.WriteByteString( aStrVal1, rStream.GetStreamCharSet() );
+
+ if ( eOp == SC_COND_BETWEEN || eOp == SC_COND_NOTBETWEEN )
+ {
+ eType = pFormula2 ? SC_VAL_FORMULA : ( bIsStr2 ? SC_VAL_STRING : SC_VAL_VALUE );
+ rStream << (BYTE) eType;
+ if ( eType == SC_VAL_FORMULA )
+ {
+ rStream << aSrcPos;
+ pFormula2->Store( rStream, aSrcPos );
+ }
+ else if ( eType == SC_VAL_VALUE )
+ rStream << nVal2;
+ else
+ rStream.WriteByteString( aStrVal2, rStream.GetStreamCharSet() );
+ }
+
+ rHdr.EndEntry();
+}
+
+void ScConditionEntry::Compile( const String& rExpr1, const String& rExpr2, BOOL bEnglish )
+{
+ if ( rExpr1.Len() || rExpr2.Len() )
+ {
+ ScCompiler aComp( pDoc, aSrcPos );
+ aComp.SetCompileEnglish( bEnglish );
+
+ if ( rExpr1.Len() )
+ {
+ pFormula1 = aComp.CompileString( rExpr1 );
+ if ( pFormula1->GetLen() == 1 )
+ {
+ // einzelne (konstante Zahl) ?
+ ScToken* pToken = pFormula1->First();
+ if ( pToken->GetOpCode() == ocPush )
+ {
+ if ( pToken->GetType() == svDouble )
+ {
+ nVal1 = pToken->nValue;
+ DELETEZ(pFormula1); // nicht als Formel merken
+ }
+ else if ( pToken->GetType() == svString )
+ {
+ bIsStr1 = TRUE;
+ aStrVal1 = pToken->cStr; // char-ptr
+ DELETEZ(pFormula1); // nicht als Formel merken
+ }
+ }
+ }
+ bRelRef1 = lcl_HasRelRef( pFormula1 );
+ }
+
+ if ( rExpr2.Len() )
+ {
+ pFormula2 = aComp.CompileString( rExpr2 );
+ if ( pFormula2->GetLen() == 1 )
+ {
+ // einzelne (konstante Zahl) ?
+ ScToken* pToken = pFormula2->First();
+ if ( pToken->GetOpCode() == ocPush )
+ {
+ if ( pToken->GetType() == svDouble )
+ {
+ nVal2 = pToken->nValue;
+ DELETEZ(pFormula2); // nicht als Formel merken
+ }
+ else if ( pToken->GetType() == svString )
+ {
+ bIsStr2 = TRUE;
+ aStrVal2 = pToken->cStr; // char-ptr
+ DELETEZ(pFormula2); // nicht als Formel merken
+ }
+ }
+ }
+ bRelRef2 = lcl_HasRelRef( pFormula2 );
+ }
+ }
+}
+
+void ScConditionEntry::MakeCells( const ScAddress& rPos ) // Formelzellen anlegen
+{
+ if ( !pDoc->IsClipOrUndo() ) // nie im Clipboard rechnen!
+ {
+ if ( pFormula1 && !pFCell1 && !bRelRef1 )
+ {
+ pFCell1 = new ScFormulaCell( pDoc, rPos, pFormula1 );
+ pFCell1->StartListeningTo( pDoc );
+ }
+
+ if ( pFormula2 && !pFCell2 && !bRelRef2 )
+ {
+ pFCell2 = new ScFormulaCell( pDoc, rPos, pFormula2 );
+ pFCell2->StartListeningTo( pDoc );
+ }
+ }
+}
+
+void ScConditionEntry::SetIgnoreBlank(BOOL bSet)
+{
+ // Das Bit SC_COND_NOBLANKS wird gesetzt, wenn Blanks nicht ignoriert werden
+ // (nur bei Gueltigkeit)
+
+ if (bSet)
+ nOptions &= ~SC_COND_NOBLANKS;
+ else
+ nOptions |= SC_COND_NOBLANKS;
+}
+
+void ScConditionEntry::CompileAll()
+{
+ // Formelzellen loeschen, dann wird beim naechsten IsValid neu kompiliert
+
+ DELETEZ(pFCell1);
+ DELETEZ(pFCell2);
+}
+
+void ScConditionEntry::UpdateReference( UpdateRefMode eUpdateRefMode,
+ const ScRange& rRange, short nDx, short nDy, short nDz )
+{
+ BOOL bChanged1 = FALSE;
+ BOOL bChanged2 = FALSE;
+
+ if (pFormula1)
+ {
+ ScCompiler aComp( pDoc, aSrcPos, *pFormula1 );
+ aComp.UpdateNameReference( eUpdateRefMode, rRange, nDx, nDy, nDz, bChanged1);
+ if (bChanged1)
+ DELETEZ(pFCell1); // wird bei IsValid wieder angelegt
+ }
+ if (pFormula2)
+ {
+ ScCompiler aComp( pDoc, aSrcPos, *pFormula2 );
+ aComp.UpdateNameReference( eUpdateRefMode, rRange, nDx, nDy, nDz, bChanged2);
+ if (bChanged2)
+ DELETEZ(pFCell2); // wird bei IsValid wieder angelegt
+ }
+}
+
+void ScConditionEntry::UpdateMoveTab( USHORT nOldPos, USHORT nNewPos )
+{
+ if (pFormula1)
+ {
+ ScCompiler aComp( pDoc, aSrcPos, *pFormula1 );
+ aComp.UpdateMoveTab(nOldPos, nNewPos, TRUE );
+ DELETEZ(pFCell1);
+ }
+ if (pFormula2)
+ {
+ ScCompiler aComp( pDoc, aSrcPos, *pFormula2 );
+ aComp.UpdateMoveTab(nOldPos, nNewPos, TRUE );
+ DELETEZ(pFCell2);
+ }
+}
+
+//! als Vergleichsoperator ans TokenArray ???
+
+BOOL lcl_IsEqual( const ScTokenArray* pArr1, const ScTokenArray* pArr2 )
+{
+ // verglichen wird nur das nicht-UPN Array
+
+ if ( pArr1 && pArr2 )
+ {
+ USHORT nLen = pArr1->GetLen();
+ if ( pArr2->GetLen() != nLen )
+ return FALSE;
+
+ ScToken** ppToken1 = pArr1->GetArray();
+ ScToken** ppToken2 = pArr2->GetArray();
+ for (USHORT i=0; i<nLen; i++)
+ {
+ if ( ppToken1[i] != ppToken2[i] &&
+ !(*ppToken1[i] == *ppToken2[i]) )
+ return FALSE; // Unterschied
+ }
+ return TRUE; // alle Eintraege gleich
+ }
+ else
+ return !pArr1 && !pArr2; // beide 0 -> gleich
+}
+
+int ScConditionEntry::operator== ( const ScConditionEntry& r ) const
+{
+ BOOL bEq = (eOp == r.eOp && nOptions == r.nOptions &&
+ lcl_IsEqual( pFormula1, r.pFormula1 ) &&
+ lcl_IsEqual( pFormula2, r.pFormula2 ));
+ if (bEq)
+ {
+ // bei Formeln auch die Referenz-Tabelle vergleichen
+ if ( ( pFormula1 || pFormula2 ) && aSrcPos != r.aSrcPos )
+ bEq = FALSE;
+
+ // wenn keine Formeln, Werte vergleichen
+ if ( !pFormula1 && ( nVal1 != r.nVal1 || aStrVal1 != r.aStrVal1 || bIsStr1 != r.bIsStr1 ) )
+ bEq = FALSE;
+ if ( !pFormula2 && ( nVal2 != r.nVal2 || aStrVal2 != r.aStrVal2 || bIsStr2 != r.bIsStr2 ) )
+ bEq = FALSE;
+ }
+
+ return bEq;
+}
+
+void ScConditionEntry::Interpret( const ScAddress& rPos )
+{
+ // Formelzellen anlegen
+ // dabei koennen neue Broadcaster (Note-Zellen) ins Dokument eingefuegt werden !!!!
+
+ if ( ( pFormula1 && !pFCell1 ) || ( pFormula2 && !pFCell2 ) )
+ MakeCells( rPos );
+
+ // Formeln auswerten
+
+ BOOL bDirty = FALSE; //! 1 und 2 getrennt ???
+
+ ScFormulaCell* pTemp1 = NULL;
+ ScFormulaCell* pEff1 = pFCell1;
+ if ( bRelRef1 )
+ {
+ pTemp1 = new ScFormulaCell( pDoc, rPos, pFormula1 ); // ohne Listening
+ pEff1 = pTemp1;
+ }
+ if ( pEff1 )
+ {
+ if (!pEff1->IsRunning()) // keine 522 erzeugen
+ {
+ //! Changed statt Dirty abfragen !!!
+ if (pEff1->GetDirty() && !bRelRef1)
+ bDirty = TRUE;
+ if (pEff1->IsValue())
+ {
+ bIsStr1 = FALSE;
+ nVal1 = pEff1->GetValue();
+ aStrVal1.Erase();
+ }
+ else
+ {
+ bIsStr1 = TRUE;
+ pEff1->GetString( aStrVal1 );
+ nVal1 = 0.0;
+ }
+ }
+ }
+ delete pTemp1;
+
+ ScFormulaCell* pTemp2 = NULL;
+ ScFormulaCell* pEff2 = pFCell2; //@ 1!=2
+ if ( bRelRef2 )
+ {
+ pTemp2 = new ScFormulaCell( pDoc, rPos, pFormula2 ); // ohne Listening
+ pEff2 = pTemp2;
+ }
+ if ( pEff2 )
+ {
+ if (!pEff2->IsRunning()) // keine 522 erzeugen
+ {
+ if (pEff2->GetDirty() && !bRelRef2)
+ bDirty = TRUE;
+ if (pEff2->IsValue())
+ {
+ bIsStr2 = FALSE;
+ nVal2 = pEff2->GetValue();
+ aStrVal2.Erase();
+ }
+ else
+ {
+ bIsStr2 = TRUE;
+ pEff2->GetString( aStrVal2 );
+ nVal2 = 0.0;
+ }
+ }
+ }
+ delete pTemp2;
+
+ // wenn IsRunning, bleiben die letzten Werte erhalten
+
+ if (bDirty && !bFirstRun)
+ {
+ // bei bedingten Formaten neu painten
+
+ DataChanged( NULL ); // alles
+ }
+
+ bFirstRun = FALSE;
+}
+
+BOOL ScConditionEntry::IsValid( double nArg ) const
+{
+ // Interpret muss schon gerufen sein
+
+ if ( bIsStr1 )
+ {
+ // wenn auf String getestet wird, bei Zahlen immer FALSE, ausser bei "ungleich"
+
+ return ( eOp == SC_COND_NOTEQUAL );
+ }
+
+ if ( eOp == SC_COND_BETWEEN || eOp == SC_COND_NOTBETWEEN )
+ if ( bIsStr2 )
+ return FALSE;
+
+ double nComp1 = nVal1; // Kopie, damit vertauscht werden kann
+ double nComp2 = nVal2;
+
+ if ( eOp == SC_COND_BETWEEN || eOp == SC_COND_NOTBETWEEN )
+ if ( nComp1 > nComp2 )
+ {
+ // richtige Reihenfolge fuer Wertebereich
+ double nTemp = nComp1; nComp1 = nComp2; nComp2 = nTemp;
+ }
+
+ // Alle Grenzfaelle muessen per SolarMath::ApproxEqual getestet werden!
+
+ BOOL bValid = FALSE;
+ switch (eOp)
+ {
+ case SC_COND_NONE:
+ break; // immer FALSE;
+ case SC_COND_EQUAL:
+ bValid = SolarMath::ApproxEqual( nArg, nComp1 );
+ break;
+ case SC_COND_NOTEQUAL:
+ bValid = !SolarMath::ApproxEqual( nArg, nComp1 );
+ break;
+ case SC_COND_GREATER:
+ bValid = ( nArg > nComp1 ) && !SolarMath::ApproxEqual( nArg, nComp1 );
+ break;
+ case SC_COND_EQGREATER:
+ bValid = ( nArg >= nComp1 ) || SolarMath::ApproxEqual( nArg, nComp1 );
+ break;
+ case SC_COND_LESS:
+ bValid = ( nArg < nComp1 ) && !SolarMath::ApproxEqual( nArg, nComp1 );
+ break;
+ case SC_COND_EQLESS:
+ bValid = ( nArg <= nComp1 ) || SolarMath::ApproxEqual( nArg, nComp1 );
+ break;
+ case SC_COND_BETWEEN:
+ bValid = ( nArg >= nComp1 && nArg <= nComp2 ) ||
+ SolarMath::ApproxEqual( nArg, nComp1 ) || SolarMath::ApproxEqual( nArg, nComp2 );
+ break;
+ case SC_COND_NOTBETWEEN:
+ bValid = ( nArg < nComp1 || nArg > nComp2 ) &&
+ !SolarMath::ApproxEqual( nArg, nComp1 ) && !SolarMath::ApproxEqual( nArg, nComp2 );
+ break;
+ case SC_COND_DIRECT:
+ bValid = !SolarMath::ApproxEqual( nComp1, 0.0 );
+ break;
+ default:
+ DBG_ERROR("unbekannte Operation bei ScConditionEntry");
+ break;
+ }
+ return bValid;
+}
+
+BOOL ScConditionEntry::IsValidStr( const String& rArg ) const
+{
+ // Interpret muss schon gerufen sein
+
+ if ( eOp == SC_COND_DIRECT ) // Formel ist unabhaengig vom Inhalt
+ return !SolarMath::ApproxEqual( nVal1, 0.0 );
+
+ // Wenn Bedingung Zahl enthaelt, immer FALSE, ausser bei "ungleich"
+
+ if ( !bIsStr1 )
+ return ( eOp == SC_COND_NOTEQUAL );
+ if ( eOp == SC_COND_BETWEEN || eOp == SC_COND_NOTBETWEEN )
+ if ( !bIsStr2 )
+ return FALSE;
+
+ String aUpVal1( aStrVal1 ); //! als Member? (dann auch in Interpret setzen)
+ String aUpVal2( aStrVal2 );
+
+ if ( eOp == SC_COND_BETWEEN || eOp == SC_COND_NOTBETWEEN )
+ if ( ScGlobal::pScInternational->Compare( aUpVal1, aUpVal2,
+ INTN_COMPARE_IGNORECASE ) == COMPARE_GREATER )
+ {
+ // richtige Reihenfolge fuer Wertebereich
+ String aTemp( aUpVal1 ); aUpVal1 = aUpVal2; aUpVal2 = aTemp;
+ }
+
+ BOOL bValid;
+ switch ( eOp )
+ {
+ case SC_COND_EQUAL:
+ bValid = ScGlobal::pScInternational->CompareEqual(
+ rArg, aUpVal1, INTN_COMPARE_IGNORECASE );
+ break;
+ case SC_COND_NOTEQUAL:
+ bValid = !ScGlobal::pScInternational->CompareEqual(
+ rArg, aUpVal1, INTN_COMPARE_IGNORECASE );
+ break;
+ default:
+ {
+ StringCompare eCompare = ScGlobal::pScInternational->Compare(
+ rArg, aUpVal1, INTN_COMPARE_IGNORECASE );
+ switch ( eOp )
+ {
+ case SC_COND_GREATER:
+ bValid = ( eCompare == COMPARE_GREATER );
+ break;
+ case SC_COND_EQGREATER:
+ bValid = ( eCompare == COMPARE_EQUAL || eCompare == COMPARE_GREATER );
+ break;
+ case SC_COND_LESS:
+ bValid = ( eCompare == COMPARE_LESS );
+ break;
+ case SC_COND_EQLESS:
+ bValid = ( eCompare == COMPARE_EQUAL || eCompare == COMPARE_LESS );
+ break;
+ case SC_COND_BETWEEN:
+ case SC_COND_NOTBETWEEN:
+ // Test auf NOTBETWEEN:
+ bValid = ( eCompare == COMPARE_LESS ||
+ ScGlobal::pScInternational->Compare( rArg, aUpVal2,
+ INTN_COMPARE_IGNORECASE ) == COMPARE_GREATER );
+ if ( eOp == SC_COND_BETWEEN )
+ bValid = !bValid;
+ break;
+ // SC_COND_DIRECT schon oben abgefragt
+ default:
+ DBG_ERROR("unbekannte Operation bei ScConditionEntry");
+ bValid = FALSE;
+ break;
+ }
+ }
+ }
+ return bValid;
+}
+
+BOOL ScConditionEntry::IsCellValid( ScBaseCell* pCell, const ScAddress& rPos ) const
+{
+ ((ScConditionEntry*)this)->Interpret(rPos); // Formeln auswerten
+
+ double nArg = 0.0;
+ String aArgStr;
+ BOOL bVal = TRUE;
+
+ if ( pCell )
+ {
+ CellType eType = pCell->GetCellType();
+ switch (eType)
+ {
+ case CELLTYPE_VALUE:
+ nArg = ((ScValueCell*)pCell)->GetValue();
+ break;
+ case CELLTYPE_FORMULA:
+ {
+ ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
+ bVal = pFCell->IsValue();
+ if (bVal)
+ nArg = pFCell->GetValue();
+ else
+ pFCell->GetString(aArgStr);
+ }
+ break;
+ case CELLTYPE_STRING:
+ case CELLTYPE_EDIT:
+ bVal = FALSE;
+ if ( eType == CELLTYPE_STRING )
+ ((ScStringCell*)pCell)->GetString(aArgStr);
+ else
+ ((ScEditCell*)pCell)->GetString(aArgStr);
+ break;
+
+ default:
+ pCell = NULL; // Note-Zellen wie leere
+ break;
+ }
+ }
+
+ if (!pCell)
+ if (bIsStr1)
+ bVal = FALSE; // leere Zellen je nach Bedingung
+
+ if (bVal)
+ return IsValid( nArg );
+ else
+ return IsValidStr( aArgStr );
+}
+
+String ScConditionEntry::GetExpression( const ScAddress& rCursor, USHORT nIndex,
+ ULONG nNumFmt, BOOL bEnglish ) const
+{
+ String aRet;
+
+ if ( bEnglish && nNumFmt == 0 )
+ nNumFmt = pDoc->GetFormatTable()->GetStandardIndex( LANGUAGE_ENGLISH_US );
+
+ if ( nIndex==0 )
+ {
+ if ( pFormula1 )
+ {
+ ScCompiler aComp(pDoc, rCursor, *pFormula1);
+ aComp.SetCompileEnglish( bEnglish );
+ aComp.CreateStringFromTokenArray( aRet );
+ }
+ else if (bIsStr1)
+ {
+ aRet = '"';
+ aRet += aStrVal1;
+ aRet += '"';
+ }
+ else
+ pDoc->GetFormatTable()->GetInputLineString(nVal1, nNumFmt, aRet);
+ }
+ else if ( nIndex==1 )
+ {
+ if ( pFormula2 )
+ {
+ ScCompiler aComp(pDoc, rCursor, *pFormula2);
+ aComp.SetCompileEnglish( bEnglish );
+ aComp.CreateStringFromTokenArray( aRet );
+ }
+ else if (bIsStr2)
+ {
+ aRet = '"';
+ aRet += aStrVal2;
+ aRet += '"';
+ }
+ else
+ pDoc->GetFormatTable()->GetInputLineString(nVal2, nNumFmt, aRet);
+ }
+ else
+ DBG_ERROR("GetExpression: falscher Index");
+
+ return aRet;
+}
+
+ScTokenArray* ScConditionEntry::CreateTokenArry( USHORT nIndex ) const
+{
+ ScTokenArray* pRet;
+ ScAddress aAddr;
+
+ if ( nIndex==0 )
+ {
+ if ( pFormula1 )
+ pRet = new ScTokenArray( *pFormula1 );
+ else
+ {
+ pRet = new ScTokenArray();
+ if (bIsStr1)
+ pRet->AddString( aStrVal1.GetBuffer() );
+ else
+ pRet->AddDouble( nVal1 );
+ }
+ }
+ else if ( nIndex==1 )
+ {
+ if ( pFormula2 )
+ pRet = new ScTokenArray( *pFormula2 );
+ else
+ {
+ pRet = new ScTokenArray();
+ if (bIsStr2)
+ pRet->AddString( aStrVal2.GetBuffer() );
+ else
+ pRet->AddDouble( nVal2 );
+ }
+ }
+ else
+ DBG_ERROR("GetExpression: falscher Index");
+
+ return pRet;
+}
+
+void ScConditionEntry::SourceChanged( const ScAddress& rChanged )
+{
+ for (USHORT nPass = 0; nPass < 2; nPass++)
+ {
+ ScTokenArray* pFormula = nPass ? pFormula2 : pFormula1;
+ if (pFormula)
+ {
+ pFormula->Reset();
+ ScToken* t;
+ for( t = pFormula->GetNextReference(); t; t = pFormula->GetNextReference() )
+ {
+ ComplRefData& rRef = t->GetReference();
+ if ( rRef.Ref1.IsColRel() || rRef.Ref1.IsRowRel() || rRef.Ref1.IsTabRel() ||
+ rRef.Ref2.IsColRel() || rRef.Ref2.IsRowRel() || rRef.Ref2.IsTabRel() )
+ {
+ // absolut muss getroffen sein, relativ bestimmt Bereich
+
+ BOOL bHit = TRUE;
+ INT16 nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+
+ if ( rRef.Ref1.IsColRel() )
+ nCol2 = rChanged.Col() - rRef.Ref1.nRelCol;
+ else
+ {
+ bHit &= ( rChanged.Col() >= rRef.Ref1.nCol );
+ nCol2 = MAXCOL;
+ }
+ if ( rRef.Ref1.IsRowRel() )
+ nRow2 = rChanged.Row() - rRef.Ref1.nRelRow;
+ else
+ {
+ bHit &= ( rChanged.Row() >= rRef.Ref1.nRow );
+ nRow2 = MAXROW;
+ }
+ if ( rRef.Ref1.IsTabRel() )
+ nTab2 = rChanged.Tab() - rRef.Ref1.nRelTab;
+ else
+ {
+ bHit &= ( rChanged.Tab() >= rRef.Ref1.nTab );
+ nTab2 = MAXTAB;
+ }
+
+ if ( rRef.Ref2.IsColRel() )
+ nCol1 = rChanged.Col() - rRef.Ref2.nRelCol;
+ else
+ {
+ bHit &= ( rChanged.Col() <= rRef.Ref2.nCol );
+ nCol1 = 0;
+ }
+ if ( rRef.Ref2.IsRowRel() )
+ nRow1 = rChanged.Row() - rRef.Ref2.nRelRow;
+ else
+ {
+ bHit &= ( rChanged.Row() <= rRef.Ref2.nRow );
+ nRow1 = 0;
+ }
+ if ( rRef.Ref2.IsTabRel() )
+ nTab1 = rChanged.Tab() - rRef.Ref2.nRelTab;
+ else
+ {
+ bHit &= ( rChanged.Tab() <= rRef.Ref2.nTab );
+ nTab1 = 0;
+ }
+
+ if ( bHit )
+ {
+ //! begrenzen
+
+ ScRange aPaint( nCol1,nRow1,nTab1, nCol2,nRow2,nTab2 );
+
+ // kein Paint, wenn es nur die Zelle selber ist
+ if ( aPaint.aStart != rChanged || aPaint.aEnd != rChanged )
+ DataChanged( &aPaint );
+ }
+ }
+ }
+ }
+ }
+}
+
+void ScConditionEntry::DataChanged( const ScRange* pModified ) const
+{
+ // nix
+}
+
+//------------------------------------------------------------------------
+
+ScCondFormatEntry::ScCondFormatEntry( ScConditionMode eOper,
+ const String& rExpr1, const String& rExpr2,
+ ScDocument* pDocument, const ScAddress& rPos,
+ const String& rStyle, BOOL bCompileEnglish ) :
+ ScConditionEntry( eOper, rExpr1, rExpr2, pDocument, rPos, bCompileEnglish ),
+ aStyleName( rStyle ),
+ pParent( NULL )
+{
+}
+
+ScCondFormatEntry::ScCondFormatEntry( ScConditionMode eOper,
+ const ScTokenArray* pArr1, const ScTokenArray* pArr2,
+ ScDocument* pDocument, const ScAddress& rPos,
+ const String& rStyle ) :
+ ScConditionEntry( eOper, pArr1, pArr2, pDocument, rPos ),
+ aStyleName( rStyle ),
+ pParent( NULL )
+{
+}
+
+ScCondFormatEntry::ScCondFormatEntry( const ScCondFormatEntry& r ) :
+ ScConditionEntry( r ),
+ aStyleName( r.aStyleName ),
+ pParent( NULL )
+{
+}
+
+ScCondFormatEntry::ScCondFormatEntry( ScDocument* pDocument, const ScCondFormatEntry& r ) :
+ ScConditionEntry( pDocument, r ),
+ aStyleName( r.aStyleName ),
+ pParent( NULL )
+{
+}
+
+ScCondFormatEntry::ScCondFormatEntry( SvStream& rStream, ScMultipleReadHeader& rHdr,
+ ScDocument* pDocument ) :
+ ScConditionEntry( rStream, rHdr, pDocument ),
+ pParent( NULL )
+{
+ // im Datei-Header sind getrennte Eintraege fuer ScConditionEntry und ScCondFormatEntry
+
+ rHdr.StartEntry();
+ rStream.ReadByteString( aStyleName, rStream.GetStreamCharSet() );
+ rHdr.EndEntry();
+}
+
+void ScCondFormatEntry::Store(SvStream& rStream, ScMultipleWriteHeader& rHdr) const
+{
+ // im Datei-Header sind getrennte Eintraege fuer ScConditionEntry und ScCondFormatEntry
+
+ StoreCondition( rStream, rHdr );
+
+ rHdr.StartEntry();
+ rStream.WriteByteString( aStyleName, rStream.GetStreamCharSet() );
+ rHdr.EndEntry();
+}
+
+
+int ScCondFormatEntry::operator== ( const ScCondFormatEntry& r ) const
+{
+ return ScConditionEntry::operator==( r ) &&
+ aStyleName == r.aStyleName;
+
+ // Range wird nicht verglichen
+}
+
+ScCondFormatEntry::~ScCondFormatEntry()
+{
+}
+
+void ScCondFormatEntry::DataChanged( const ScRange* pModified ) const
+{
+ if ( pParent )
+ pParent->DoRepaint( pModified );
+}
+
+//------------------------------------------------------------------------
+
+ScConditionalFormat::ScConditionalFormat(ULONG nNewKey, ScDocument* pDocument) :
+ pDoc( pDocument ),
+ pAreas( NULL ),
+ nKey( nNewKey ),
+ ppEntries( NULL ),
+ nEntryCount( 0 )
+{
+}
+
+ScConditionalFormat::ScConditionalFormat(const ScConditionalFormat& r) :
+ pDoc( r.pDoc ),
+ pAreas( NULL ),
+ nKey( r.nKey ),
+ ppEntries( NULL ),
+ nEntryCount( r.nEntryCount )
+{
+ if (nEntryCount)
+ {
+ ppEntries = new ScCondFormatEntry*[nEntryCount];
+ for (USHORT i=0; i<nEntryCount; i++)
+ {
+ ppEntries[i] = new ScCondFormatEntry(*r.ppEntries[i]);
+ ppEntries[i]->SetParent(this);
+ }
+ }
+}
+
+ScConditionalFormat* ScConditionalFormat::Clone(ScDocument* pNewDoc) const
+{
+ // echte Kopie der Formeln (fuer Ref-Undo / zwischen Dokumenten)
+
+ if (!pNewDoc)
+ pNewDoc = pDoc;
+
+ ScConditionalFormat* pNew = new ScConditionalFormat(nKey, pNewDoc);
+ DBG_ASSERT(!pNew->ppEntries, "wo kommen die Eintraege her?");
+
+ if (nEntryCount)
+ {
+ pNew->ppEntries = new ScCondFormatEntry*[nEntryCount];
+ for (USHORT i=0; i<nEntryCount; i++)
+ {
+ pNew->ppEntries[i] = new ScCondFormatEntry( pNewDoc, *ppEntries[i] );
+ pNew->ppEntries[i]->SetParent(pNew);
+ }
+ pNew->nEntryCount = nEntryCount;
+ }
+
+ return pNew;
+}
+
+ScConditionalFormat::ScConditionalFormat(SvStream& rStream, ScMultipleReadHeader& rHdr,
+ ScDocument* pDocument) :
+ pDoc( pDocument ),
+ pAreas( NULL ),
+ ppEntries( NULL ),
+ nEntryCount( 0 )
+{
+ // ein Eintrag im Header fuer die ScConditionalFormat-Daten,
+ // je zwei Eintraege fuer jede Bedingung (ScConditionEntry und ScCondFormatEntry)
+
+ rHdr.StartEntry();
+
+ rStream >> nKey;
+ rStream >> nEntryCount;
+
+ rHdr.EndEntry();
+
+ // Eintraege laden
+
+ if (nEntryCount)
+ {
+ ppEntries = new ScCondFormatEntry*[nEntryCount];
+ for (USHORT i=0; i<nEntryCount; i++)
+ {
+ ppEntries[i] = new ScCondFormatEntry(rStream, rHdr, pDocument);
+ ppEntries[i]->SetParent(this);
+ }
+ }
+}
+
+void ScConditionalFormat::Store(SvStream& rStream, ScMultipleWriteHeader& rHdr) const
+{
+ // ein Eintrag im Header fuer die ScConditionalFormat-Daten,
+ // je zwei Eintraege fuer jede Bedingung (ScConditionEntry und ScCondFormatEntry)
+
+ rHdr.StartEntry();
+
+ rStream << nKey;
+ rStream << nEntryCount;
+
+ rHdr.EndEntry();
+
+ // Eintraege speichern
+
+ for (USHORT i=0; i<nEntryCount; i++)
+ ppEntries[i]->Store(rStream, rHdr);
+}
+
+BOOL ScConditionalFormat::EqualEntries( const ScConditionalFormat& r ) const
+{
+ if ( nEntryCount != r.nEntryCount )
+ return FALSE;
+
+ //! auf gleiche Eintraege in anderer Reihenfolge testen ???
+
+ for (USHORT i=0; i<nEntryCount; i++)
+ if ( ! (*ppEntries[i] == *r.ppEntries[i]) )
+ return FALSE;
+
+ return TRUE;
+}
+
+void ScConditionalFormat::AddEntry( const ScCondFormatEntry& rNew )
+{
+ ScCondFormatEntry** ppNew = new ScCondFormatEntry*[nEntryCount+1];
+ for (USHORT i=0; i<nEntryCount; i++)
+ ppNew[i] = ppEntries[i];
+ ppNew[nEntryCount] = new ScCondFormatEntry(rNew);
+ ppNew[nEntryCount]->SetParent(this);
+ ++nEntryCount;
+ delete[] ppEntries;
+ ppEntries = ppNew;
+}
+
+ScConditionalFormat::~ScConditionalFormat()
+{
+ for (USHORT i=0; i<nEntryCount; i++)
+ delete ppEntries[i];
+ delete[] ppEntries;
+
+ delete pAreas;
+}
+
+const ScCondFormatEntry* ScConditionalFormat::GetEntry( USHORT nPos ) const
+{
+ if ( nPos < nEntryCount )
+ return ppEntries[nPos];
+ else
+ return NULL;
+}
+
+const String& ScConditionalFormat::GetCellStyle( ScBaseCell* pCell, const ScAddress& rPos ) const
+{
+ for (USHORT i=0; i<nEntryCount; i++)
+ if ( ppEntries[i]->IsCellValid( pCell, rPos ) )
+ return ppEntries[i]->GetStyle();
+
+ return EMPTY_STRING;
+}
+
+void lcl_Extend( ScRange& rRange, ScDocument* pDoc, BOOL bLines )
+{
+ USHORT nTab = rRange.aStart.Tab();
+ DBG_ASSERT(rRange.aEnd.Tab() == nTab, "lcl_Extend - mehrere Tabellen?");
+
+ USHORT nStartCol = rRange.aStart.Col();
+ USHORT nStartRow = rRange.aStart.Row();
+ USHORT nEndCol = rRange.aEnd.Col();
+ USHORT nEndRow = rRange.aEnd.Row();
+
+ BOOL bEx = pDoc->ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, nTab );
+
+ if (bLines)
+ {
+ if (nStartCol > 0) --nStartCol;
+ if (nStartRow > 0) --nStartRow;
+ if (nEndCol < MAXCOL) ++nEndCol;
+ if (nEndRow < MAXROW) ++nEndRow;
+ }
+
+ if ( bEx || bLines )
+ {
+ rRange.aStart.Set( nStartCol, nStartRow, nTab );
+ rRange.aEnd.Set( nEndCol, nEndRow, nTab );
+ }
+}
+
+BOOL lcl_CutRange( ScRange& rRange, const ScRange& rOther )
+{
+ rRange.Justify();
+ ScRange aCmpRange = rOther;
+ aCmpRange.Justify();
+
+ if ( rRange.aStart.Col() <= aCmpRange.aEnd.Col() &&
+ rRange.aEnd.Col() >= aCmpRange.aStart.Col() &&
+ rRange.aStart.Row() <= aCmpRange.aEnd.Row() &&
+ rRange.aEnd.Row() >= aCmpRange.aStart.Row() &&
+ rRange.aStart.Tab() <= aCmpRange.aEnd.Tab() &&
+ rRange.aEnd.Tab() >= aCmpRange.aStart.Tab() )
+ {
+ if ( rRange.aStart.Col() < aCmpRange.aStart.Col() )
+ rRange.aStart.SetCol( aCmpRange.aStart.Col() );
+ if ( rRange.aStart.Row() < aCmpRange.aStart.Row() )
+ rRange.aStart.SetRow( aCmpRange.aStart.Row() );
+ if ( rRange.aStart.Tab() < aCmpRange.aStart.Tab() )
+ rRange.aStart.SetTab( aCmpRange.aStart.Tab() );
+ if ( rRange.aEnd.Col() > aCmpRange.aEnd.Col() )
+ rRange.aEnd.SetCol( aCmpRange.aEnd.Col() );
+ if ( rRange.aEnd.Row() > aCmpRange.aEnd.Row() )
+ rRange.aEnd.SetRow( aCmpRange.aEnd.Row() );
+ if ( rRange.aEnd.Tab() > aCmpRange.aEnd.Tab() )
+ rRange.aEnd.SetTab( aCmpRange.aEnd.Tab() );
+
+ return TRUE;
+ }
+
+ return FALSE; // ausserhalb
+}
+
+void ScConditionalFormat::DoRepaint( const ScRange* pModified )
+{
+ USHORT i;
+ SfxObjectShell* pSh = pDoc->GetDocumentShell();
+ if (pSh)
+ {
+ // Rahmen/Schatten enthalten?
+ // (alle Bedingungen testen)
+ BOOL bExtend = FALSE;
+ BOOL bRotate = FALSE;
+ for (i=0; i<nEntryCount; i++)
+ {
+ String aStyle = ppEntries[i]->GetStyle();
+ if (aStyle.Len())
+ {
+ SfxStyleSheetBase* pStyleSheet =
+ pDoc->GetStyleSheetPool()->Find( aStyle, SFX_STYLE_FAMILY_PARA );
+ if ( pStyleSheet )
+ {
+ const SfxItemSet& rSet = pStyleSheet->GetItemSet();
+ if (rSet.GetItemState( ATTR_BORDER, TRUE ) == SFX_ITEM_SET ||
+ rSet.GetItemState( ATTR_SHADOW, TRUE ) == SFX_ITEM_SET)
+ {
+ bExtend = TRUE;
+ }
+ if (rSet.GetItemState( ATTR_ROTATE_VALUE, TRUE ) == SFX_ITEM_SET ||
+ rSet.GetItemState( ATTR_ROTATE_MODE, TRUE ) == SFX_ITEM_SET)
+ {
+ bRotate = TRUE;
+ }
+ }
+ }
+ }
+
+ if (!pAreas) // RangeList ggf. holen
+ {
+ pAreas = new ScRangeList;
+ pDoc->FindConditionalFormat( nKey, *pAreas );
+ }
+ USHORT nCount = (USHORT) pAreas->Count();
+ for (i=0; i<nCount; i++)
+ {
+ ScRange aRange = *pAreas->GetObject(i);
+ BOOL bDo = TRUE;
+ if ( pModified )
+ {
+ if ( !lcl_CutRange( aRange, *pModified ) )
+ bDo = FALSE;
+ }
+ if (bDo)
+ {
+ lcl_Extend( aRange, pDoc, bExtend ); // zusammengefasste und bExtend
+ if ( bRotate )
+ {
+ aRange.aStart.SetCol(0);
+ aRange.aEnd.SetCol(MAXCOL); // gedreht: ganze Zeilen
+ }
+
+ // gedreht -> ganze Zeilen
+ if ( aRange.aStart.Col() != 0 || aRange.aEnd.Col() != MAXCOL )
+ {
+ if ( pDoc->HasAttrib( 0,aRange.aStart.Row(),aRange.aStart.Tab(),
+ MAXCOL,aRange.aEnd.Row(),aRange.aEnd.Tab(),
+ HASATTR_ROTATE ) )
+ {
+ aRange.aStart.SetCol(0);
+ aRange.aEnd.SetCol(MAXCOL);
+ }
+ }
+
+ pSh->Broadcast( ScPaintHint( aRange, PAINT_GRID ) );
+ }
+ }
+ }
+}
+
+void ScConditionalFormat::InvalidateArea()
+{
+ delete pAreas;
+ pAreas = NULL;
+}
+
+void ScConditionalFormat::CompileAll()
+{
+ for (USHORT i=0; i<nEntryCount; i++)
+ ppEntries[i]->CompileAll();
+}
+
+void ScConditionalFormat::UpdateReference( UpdateRefMode eUpdateRefMode,
+ const ScRange& rRange, short nDx, short nDy, short nDz )
+{
+ for (USHORT i=0; i<nEntryCount; i++)
+ ppEntries[i]->UpdateReference(eUpdateRefMode, rRange, nDx, nDy, nDz);
+
+ delete pAreas; // aus dem AttrArray kommt beim Einfuegen/Loeschen kein Aufruf
+ pAreas = NULL;
+}
+
+void ScConditionalFormat::UpdateMoveTab( USHORT nOldPos, USHORT nNewPos )
+{
+ for (USHORT i=0; i<nEntryCount; i++)
+ ppEntries[i]->UpdateMoveTab( nOldPos, nNewPos );
+
+ delete pAreas; // aus dem AttrArray kommt beim Einfuegen/Loeschen kein Aufruf
+ pAreas = NULL;
+}
+
+void ScConditionalFormat::SourceChanged( const ScAddress& rAddr )
+{
+ for (USHORT i=0; i<nEntryCount; i++)
+ ppEntries[i]->SourceChanged( rAddr );
+}
+
+//------------------------------------------------------------------------
+
+ScConditionalFormatList::ScConditionalFormatList(const ScConditionalFormatList& rList)
+{
+ // fuer Ref-Undo - echte Kopie mit neuen Tokens!
+
+ USHORT nCount = rList.Count();
+
+ for (USHORT i=0; i<nCount; i++)
+ InsertNew( rList[i]->Clone() );
+
+ //! sortierte Eintraege aus rList schneller einfuegen ???
+}
+
+ScConditionalFormatList::ScConditionalFormatList(ScDocument* pNewDoc,
+ const ScConditionalFormatList& rList)
+{
+ // fuer neues Dokument - echte Kopie mit neuen Tokens!
+
+ USHORT nCount = rList.Count();
+
+ for (USHORT i=0; i<nCount; i++)
+ InsertNew( rList[i]->Clone(pNewDoc) );
+
+ //! sortierte Eintraege aus rList schneller einfuegen ???
+}
+
+BOOL ScConditionalFormatList::operator==( const ScConditionalFormatList& r ) const
+{
+ // fuer Ref-Undo - interne Variablen werden nicht verglichen
+
+ USHORT nCount = Count();
+ BOOL bEqual = ( nCount == r.Count() );
+ for (USHORT i=0; i<nCount && bEqual; i++) // Eintraege sind sortiert
+ if ( !(*this)[i]->EqualEntries(*r[i]) ) // Eintraege unterschiedlich ?
+ bEqual = FALSE;
+
+ return bEqual;
+}
+
+void ScConditionalFormatList::Load( SvStream& rStream, ScDocument* pDocument )
+{
+ ScMultipleReadHeader aHdr( rStream );
+
+ USHORT nNewCount;
+ rStream >> nNewCount;
+
+ for (USHORT i=0; i<nNewCount; i++)
+ {
+ ScConditionalFormat* pNew = new ScConditionalFormat( rStream, aHdr, pDocument );
+ InsertNew( pNew );
+ }
+}
+
+void ScConditionalFormatList::Store( SvStream& rStream ) const
+{
+ USHORT i;
+ ScMultipleWriteHeader aHdr( rStream );
+
+ USHORT nCount = Count();
+ USHORT nUsed = 0;
+ for (i=0; i<nCount; i++)
+ if ((*this)[i]->IsUsed())
+ ++nUsed;
+
+ rStream << nUsed; // Anzahl der gespeicherten
+
+ for (i=0; i<nCount; i++)
+ {
+ const ScConditionalFormat* pForm = (*this)[i];
+ if (pForm->IsUsed())
+ pForm->Store( rStream, aHdr );
+ }
+}
+
+ScConditionalFormat* ScConditionalFormatList::GetFormat( ULONG nKey )
+{
+ //! binaer suchen
+
+ USHORT nCount = Count();
+ for (USHORT i=0; i<nCount; i++)
+ if ((*this)[i]->GetKey() == nKey)
+ return (*this)[i];
+
+ DBG_ERROR("ScConditionalFormatList: Eintrag nicht gefunden");
+ return NULL;
+}
+
+void ScConditionalFormatList::ResetUsed()
+{
+ USHORT nCount = Count();
+ for (USHORT i=0; i<nCount; i++)
+ (*this)[i]->SetUsed(FALSE);
+}
+
+void ScConditionalFormatList::CompileAll()
+{
+ USHORT nCount = Count();
+ for (USHORT i=0; i<nCount; i++)
+ (*this)[i]->CompileAll();
+}
+
+void ScConditionalFormatList::UpdateReference( UpdateRefMode eUpdateRefMode,
+ const ScRange& rRange, short nDx, short nDy, short nDz )
+{
+ USHORT nCount = Count();
+ for (USHORT i=0; i<nCount; i++)
+ (*this)[i]->UpdateReference( eUpdateRefMode, rRange, nDx, nDy, nDz );
+}
+
+void ScConditionalFormatList::UpdateMoveTab( USHORT nOldPos, USHORT nNewPos )
+{
+ USHORT nCount = Count();
+ for (USHORT i=0; i<nCount; i++)
+ (*this)[i]->UpdateMoveTab( nOldPos, nNewPos );
+}
+
+void ScConditionalFormatList::SourceChanged( const ScAddress& rAddr )
+{
+ USHORT nCount = Count();
+ for (USHORT i=0; i<nCount; i++)
+ (*this)[i]->SourceChanged( rAddr );
+}
+
+
+
diff --git a/sc/source/core/data/dociter.cxx b/sc/source/core/data/dociter.cxx
new file mode 100644
index 000000000000..6f618823875b
--- /dev/null
+++ b/sc/source/core/data/dociter.cxx
@@ -0,0 +1,1390 @@
+/*************************************************************************
+ *
+ * $RCSfile: dociter.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <svtools/zforlist.hxx>
+
+#include "scitems.hxx"
+#include "global.hxx"
+#include "dociter.hxx"
+#include "document.hxx"
+#include "table.hxx"
+#include "column.hxx"
+#include "cell.hxx"
+#include "attarray.hxx"
+#include "patattr.hxx"
+#include "docoptio.hxx"
+
+
+// STATIC DATA -----------------------------------------------------------
+
+ScDocumentIterator::ScDocumentIterator( ScDocument* pDocument,
+ USHORT nStartTable, USHORT nEndTable ) :
+ pDoc( pDocument ),
+ nStartTab( nStartTable ),
+ nEndTab( nEndTable )
+{
+ PutInOrder( nStartTab, nEndTab );
+ if (nStartTab > MAXTAB) nStartTab = MAXTAB;
+ if (nEndTab > MAXTAB) nEndTab = MAXTAB;
+
+ pDefPattern = pDoc->GetDefPattern();
+
+ nCol = 0;
+ nRow = 0;
+ nTab = nStartTab;
+
+ nColPos = 0;
+ nAttrPos = 0;
+}
+
+ScDocumentIterator::~ScDocumentIterator()
+{
+}
+
+BOOL ScDocumentIterator::GetThisCol()
+{
+ ScTable* pTab;
+ while ( (pTab = pDoc->pTab[nTab]) == NULL )
+ {
+ if ( nTab == nEndTab )
+ {
+ nCol = MAXCOL;
+ nRow = MAXROW;
+ return FALSE;
+ }
+ ++nTab;
+ }
+ ScColumn* pCol = &pTab->aCol[nCol];
+ ScAttrArray* pAtt = pCol->pAttrArray;
+
+ BOOL bFound = FALSE;
+ do
+ {
+ USHORT nColRow;
+ USHORT nAttrEnd;
+
+ do
+ {
+ nAttrEnd = pAtt->pData[nAttrPos].nRow;
+ if (nAttrEnd < nRow)
+ ++nAttrPos;
+ }
+ while (nAttrEnd < nRow);
+
+ do
+ {
+ nColRow = (nColPos < pCol->nCount) ? pCol->pItems[nColPos].nRow : MAXROW+1;
+ if (nColRow < nRow)
+ ++nColPos;
+ }
+ while (nColRow < nRow);
+
+ if (nColRow == nRow)
+ {
+ bFound = TRUE;
+ pCell = pCol->pItems[nColPos].pCell;
+ pPattern = pAtt->pData[nAttrPos].pPattern;
+ }
+ else if ( pAtt->pData[nAttrPos].pPattern != pDefPattern )
+ {
+ bFound = TRUE;
+ pCell = NULL;
+ pPattern = pAtt->pData[nAttrPos].pPattern;
+ }
+ else
+ {
+ nRow = Min( (USHORT)nColRow, (USHORT)(nAttrEnd+1) );
+ }
+ }
+ while (!bFound && nRow <= MAXROW);
+
+ return bFound;
+}
+
+BOOL ScDocumentIterator::GetThis()
+{
+ BOOL bEnd = FALSE;
+ BOOL bSuccess = FALSE;
+
+ while ( !bSuccess && !bEnd )
+ {
+ if ( nRow > MAXROW )
+ bSuccess = FALSE;
+ else
+ bSuccess = GetThisCol();
+
+ if ( !bSuccess )
+ {
+ ++nCol;
+ if (nCol > MAXCOL)
+ {
+ nCol = 0;
+ ++nTab;
+ if (nTab > nEndTab)
+ bEnd = TRUE;
+ }
+ nRow = 0;
+ nColPos = 0;
+ nAttrPos = 0;
+ }
+ }
+
+ return !bEnd;
+}
+
+BOOL ScDocumentIterator::GetFirst()
+{
+ nCol = 0;
+ nTab = nStartTab;
+
+ nRow = 0;
+ nColPos = 0;
+ nAttrPos = 0;
+
+ return GetThis();
+}
+
+BOOL ScDocumentIterator::GetNext()
+{
+ ++nRow;
+
+ return GetThis();
+}
+
+//------------------------------------------------------------------------
+
+ScBaseCell* ScDocumentIterator::GetCell()
+{
+ return pCell;
+}
+
+const ScPatternAttr* ScDocumentIterator::GetPattern()
+{
+ return pPattern;
+}
+
+void ScDocumentIterator::GetPos( USHORT& rCol, USHORT& rRow, USHORT& rTab )
+{
+ rCol = nCol;
+ rRow = nRow;
+ rTab = nTab;
+}
+
+
+//------------------------------------------------------------------------
+//------------------------------------------------------------------------
+void lcl_IterGetNumberFormat( ULONG& nFormat, const ScAttrArray*& rpArr,
+ USHORT& nAttrEndRow, const ScAttrArray* pNewArr, USHORT nRow,
+ ScDocument* pDoc )
+{
+ if ( rpArr != pNewArr || nAttrEndRow < nRow )
+ {
+ short nPos;
+ pNewArr->Search( nRow, nPos ); // nPos 0 gueltig wenn nicht gefunden
+ const ScPatternAttr* pPattern = pNewArr->pData[nPos].pPattern;
+ nFormat = pPattern->GetNumberFormat( pDoc->GetFormatTable() );
+ rpArr = pNewArr;
+ nAttrEndRow = pNewArr->pData[nPos].nRow;
+ }
+}
+
+ScValueIterator::ScValueIterator( ScDocument* pDocument,
+ USHORT nSCol, USHORT nSRow, USHORT nSTab,
+ USHORT nECol, USHORT nERow, USHORT nETab,
+ BOOL bSTotal, BOOL bTextZero ) :
+ pDoc( pDocument ),
+ nStartCol( nSCol),
+ nStartRow( nSRow),
+ nStartTab( nSTab ),
+ nEndCol( nECol ),
+ nEndRow( nERow),
+ nEndTab( nETab ),
+ bSubTotal(bSTotal),
+ nNumFmtType( NUMBERFORMAT_UNDEFINED ),
+ nNumFmtIndex(0),
+ bNumValid( FALSE ),
+ bNextValid( FALSE ),
+ bCalcAsShown( pDocument->GetDocOptions().IsCalcAsShown() ),
+ bTextAsZero( bTextZero )
+{
+ PutInOrder( nStartCol, nEndCol);
+ PutInOrder( nStartRow, nEndRow);
+ PutInOrder( nStartTab, nEndTab );
+
+ if (nStartCol > MAXCOL) nStartCol = MAXCOL;
+ if (nEndCol > MAXCOL) nEndCol = MAXCOL;
+ if (nStartRow > MAXROW) nStartRow = MAXROW;
+ if (nEndRow > MAXROW) nEndRow = MAXROW;
+ if (nStartTab > MAXTAB) nStartTab = MAXTAB;
+ if (nEndTab > MAXTAB) nEndTab = MAXTAB;
+
+ nCol = nStartCol;
+ nRow = nStartRow;
+ nTab = nStartTab;
+
+ nColRow = 0; // wird bei GetFirst initialisiert
+
+ nNumFormat = 0; // werden bei GetNumberFormat initialisiert
+ pAttrArray = 0;
+ nAttrEndRow = 0;
+}
+
+ScValueIterator::ScValueIterator( ScDocument* pDocument, const ScRange& rRange,
+ BOOL bSTotal, BOOL bTextZero ) :
+ pDoc( pDocument ),
+ nStartCol( rRange.aStart.Col() ),
+ nStartRow( rRange.aStart.Row() ),
+ nStartTab( rRange.aStart.Tab() ),
+ nEndCol( rRange.aEnd.Col() ),
+ nEndRow( rRange.aEnd.Row() ),
+ nEndTab( rRange.aEnd.Tab() ),
+ bSubTotal(bSTotal),
+ nNumFmtType( NUMBERFORMAT_UNDEFINED ),
+ nNumFmtIndex(0),
+ bNumValid( FALSE ),
+ bNextValid( FALSE ),
+ bCalcAsShown( pDocument->GetDocOptions().IsCalcAsShown() ),
+ bTextAsZero( bTextZero )
+{
+ PutInOrder( nStartCol, nEndCol);
+ PutInOrder( nStartRow, nEndRow);
+ PutInOrder( nStartTab, nEndTab );
+
+ if (nStartCol > MAXCOL) nStartCol = MAXCOL;
+ if (nEndCol > MAXCOL) nEndCol = MAXCOL;
+ if (nStartRow > MAXROW) nStartRow = MAXROW;
+ if (nEndRow > MAXROW) nEndRow = MAXROW;
+ if (nStartTab > MAXTAB) nStartTab = MAXTAB;
+ if (nEndTab > MAXTAB) nEndTab = MAXTAB;
+
+ nCol = nStartCol;
+ nRow = nStartRow;
+ nTab = nStartTab;
+
+ nColRow = 0; // wird bei GetFirst initialisiert
+
+ nNumFormat = 0; // werden bei GetNumberFormat initialisiert
+ pAttrArray = 0;
+ nAttrEndRow = 0;
+}
+
+BOOL ScValueIterator::GetThis(double& rValue, USHORT& rErr)
+{
+ ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
+ for (;;)
+ {
+ if ( nRow > nEndRow )
+ {
+ nRow = nStartRow;
+ do
+ {
+ nCol++;
+ if ( nCol > nEndCol )
+ {
+ nCol = nStartCol;
+ nTab++;
+ if ( nTab > nEndTab )
+ {
+ rValue = 0.0;
+ rErr = 0;
+ return FALSE; // Ende und Aus
+ }
+ }
+ pCol = &(pDoc->pTab[nTab])->aCol[nCol];
+ } while ( pCol->nCount == 0 );
+ pCol->Search( nRow, nColRow );
+ }
+
+ while (( nColRow < pCol->nCount ) && ( pCol->pItems[nColRow].nRow < nRow ))
+ nColRow++;
+
+ if ( nColRow < pCol->nCount && pCol->pItems[nColRow].nRow <= nEndRow )
+ {
+ nRow = pCol->pItems[nColRow].nRow + 1;
+ if ( !bSubTotal || !pDoc->pTab[nTab]->IsFiltered( nRow-1 ) )
+ {
+ ScBaseCell* pCell = pCol->pItems[nColRow].pCell;
+ ++nColRow;
+ switch (pCell->GetCellType())
+ {
+ case CELLTYPE_VALUE:
+ {
+ bNumValid = FALSE;
+ rValue = ((ScValueCell*)pCell)->GetValue();
+ rErr = 0;
+ --nRow;
+ if ( bCalcAsShown )
+ {
+#ifndef WTC
+ lcl_IterGetNumberFormat( nNumFormat,pAttrArray,
+#else
+ lcl_IterGetNumberFormat( nNumFormat,
+ (ScAttrArray const *&)pAttrArray,
+#endif
+ nAttrEndRow, pCol->pAttrArray, nRow, pDoc );
+ rValue = pDoc->RoundValueAsShown( rValue, nNumFormat );
+ }
+ //
+ // wenn in der selben Spalte gleich noch eine Value-Cell folgt, die
+ // auch noch im Block liegt, den Wert jetzt schon holen
+ //
+ if ( nColRow < pCol->nCount &&
+ pCol->pItems[nColRow].nRow <= nEndRow &&
+ pCol->pItems[nColRow].pCell->GetCellType() == CELLTYPE_VALUE &&
+ !bSubTotal )
+ {
+ fNextValue = ((ScValueCell*)pCol->pItems[nColRow].pCell)->GetValue();
+ nNextRow = pCol->pItems[nColRow].nRow;
+ bNextValid = TRUE;
+ if ( bCalcAsShown )
+ {
+#ifndef WTC
+ lcl_IterGetNumberFormat( nNumFormat, pAttrArray,
+#else
+ lcl_IterGetNumberFormat( nNumFormat,
+ (ScAttrArray const *&)pAttrArray,
+#endif
+ nAttrEndRow, pCol->pAttrArray, nNextRow, pDoc );
+ fNextValue = pDoc->RoundValueAsShown( fNextValue, nNumFormat );
+ }
+ }
+
+ return TRUE; // gefunden
+ }
+ break;
+ case CELLTYPE_FORMULA:
+ {
+ if (!bSubTotal || !((ScFormulaCell*)pCell)->IsSubTotal())
+ {
+ rErr = ((ScFormulaCell*)pCell)->GetErrCode();
+ if ( rErr || ((ScFormulaCell*)pCell)->IsValue() )
+ {
+ rValue = ((ScFormulaCell*)pCell)->GetValue();
+ nRow--;
+ bNumValid = FALSE;
+ return TRUE; // gefunden
+ }
+ }
+ }
+ break;
+ case CELLTYPE_STRING :
+ case CELLTYPE_EDIT :
+ {
+ if ( bTextAsZero )
+ {
+ rErr = 0;
+ rValue = 0.0;
+ nNumFmtType = NUMBERFORMAT_NUMBER;
+ nNumFmtIndex = 0;
+ bNumValid = TRUE;
+ --nRow;
+ return TRUE;
+ }
+ }
+ break;
+ }
+ }
+ }
+ else
+ nRow = nEndRow + 1; // naechste Spalte
+ }
+}
+
+void ScValueIterator::GetCurNumFmtInfo( short& nType, ULONG& nIndex )
+{
+ if (!bNumValid)
+ {
+ const ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
+ nNumFmtIndex = pCol->GetNumberFormat( nRow );
+ if ( (nNumFmtIndex % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
+ {
+ const ScBaseCell* pCell;
+ USHORT nIdx = nColRow - 1;
+ // there might be rearranged something, so be on the safe side
+ if ( nIdx < pCol->nCount && pCol->pItems[nIdx].nRow == nRow )
+ pCell = pCol->pItems[nIdx].pCell;
+ else
+ {
+ if ( pCol->Search( nRow, nIdx ) )
+ pCell = pCol->pItems[nIdx].pCell;
+ else
+ pCell = NULL;
+ }
+ if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
+ ((const ScFormulaCell*)pCell)->GetFormatInfo( nNumFmtType, nNumFmtIndex );
+ else
+ nNumFmtType = pDoc->GetFormatTable()->GetType( nNumFmtIndex );
+ }
+ else
+ nNumFmtType = pDoc->GetFormatTable()->GetType( nNumFmtIndex );
+ bNumValid = TRUE;
+ }
+ nType = nNumFmtType;
+ nIndex = nNumFmtIndex;
+}
+
+BOOL ScValueIterator::GetFirst(double& rValue, USHORT& rErr)
+{
+ nCol = nStartCol;
+ nRow = nStartRow;
+ nTab = nStartTab;
+
+// nColRow = 0;
+ ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
+ pCol->Search( nRow, nColRow );
+
+ nNumFormat = 0; // werden bei GetNumberFormat initialisiert
+ pAttrArray = 0;
+ nAttrEndRow = 0;
+
+ return GetThis(rValue, rErr);
+}
+
+/* ist inline:
+BOOL ScValueIterator::GetNext(double& rValue, USHORT& rErr)
+{
+ ++nRow;
+ return GetThis(rValue, rErr);
+}
+*/
+
+//------------------------------------------------------------------------
+//------------------------------------------------------------------------
+
+ScQueryValueIterator::ScQueryValueIterator(ScDocument* pDocument, USHORT nTable, const ScQueryParam& rParam) :
+ pDoc( pDocument ),
+ nTab( nTable),
+ aParam (rParam),
+ nNumFmtType( NUMBERFORMAT_UNDEFINED ),
+ nNumFmtIndex(0),
+ bCalcAsShown( pDocument->GetDocOptions().IsCalcAsShown() )
+{
+ nCol = aParam.nCol1;
+ nRow = aParam.nRow1;
+ nColRow = 0; // wird bei GetFirst initialisiert
+ USHORT i;
+ USHORT nCount = aParam.GetEntryCount();
+ for (i=0; (i<nCount) && (aParam.GetEntry(i).bDoQuery); i++)
+ {
+ ScQueryEntry& rEntry = aParam.GetEntry(i);
+ ULONG nIndex = 0;
+ rEntry.bQueryByString =
+ !(pDoc->GetFormatTable()->IsNumberFormat(*rEntry.pStr, nIndex, rEntry.nVal));
+ }
+ nNumFormat = 0; // werden bei GetNumberFormat initialisiert
+ pAttrArray = 0;
+ nAttrEndRow = 0;
+}
+
+BOOL ScQueryValueIterator::GetThis(double& rValue, USHORT& rErr)
+{
+ ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
+ for ( ;; )
+ {
+ if ( nRow > aParam.nRow2 )
+ {
+ nRow = aParam.nRow1;
+ if (aParam.bHasHeader)
+ nRow++;
+ do
+ {
+ nCol++;
+ if ( nCol > aParam.nCol2 )
+ {
+ rValue = 0.0;
+ rErr = 0;
+ return FALSE; // Ende und Aus
+ }
+ pCol = &(pDoc->pTab[nTab])->aCol[nCol];
+ } while ( pCol->nCount == 0 );
+ pCol->Search( nRow, nColRow );
+ }
+
+ while ( (nColRow < pCol->nCount) && (pCol->pItems[nColRow].nRow < nRow) )
+ nColRow++;
+
+ if ( nColRow < pCol->nCount && pCol->pItems[nColRow].nRow <= aParam.nRow2 )
+ {
+ nRow = pCol->pItems[nColRow].nRow;
+ if ((pDoc->pTab[nTab])->ValidQuery(nRow, aParam))
+ {
+ ScBaseCell* pCell = pCol->pItems[nColRow].pCell;
+ switch (pCell->GetCellType())
+ {
+ case CELLTYPE_VALUE:
+ {
+ rValue = ((ScValueCell*)pCell)->GetValue();
+ if ( bCalcAsShown )
+ {
+#if ! ( defined WTC || defined IRIX || defined ICC || defined HPUX || defined C50 )
+ lcl_IterGetNumberFormat( nNumFormat, pAttrArray,
+#else
+ lcl_IterGetNumberFormat( nNumFormat,
+ (ScAttrArray const *&)pAttrArray,
+#endif
+ nAttrEndRow, pCol->pAttrArray, nRow, pDoc );
+ rValue = pDoc->RoundValueAsShown( rValue, nNumFormat );
+ }
+ nNumFmtType = NUMBERFORMAT_NUMBER;
+ nNumFmtIndex = 0;
+ rErr = 0;
+ return TRUE; // gefunden
+ }
+ break;
+ case CELLTYPE_FORMULA:
+ {
+ if (((ScFormulaCell*)pCell)->IsValue())
+ {
+ rValue = ((ScFormulaCell*)pCell)->GetValue();
+ pDoc->GetNumberFormatInfo( nNumFmtType,
+ nNumFmtIndex, ScAddress( nCol, nRow, nTab ),
+ *((ScFormulaCell*)pCell) );
+ rErr = ((ScFormulaCell*)pCell)->GetErrCode();
+ return TRUE; // gefunden
+ }
+ else
+ nRow++;
+ }
+ break;
+ default:
+ nRow++;
+ break;
+ }
+ }
+ else
+ nRow++;
+ }
+ else
+ nRow = aParam.nRow2 + 1; // Naechste Spalte
+ }
+ return FALSE;
+}
+
+BOOL ScQueryValueIterator::GetFirst(double& rValue, USHORT& rErr)
+{
+ nCol = aParam.nCol1;
+ nRow = aParam.nRow1;
+ if (aParam.bHasHeader)
+ nRow++;
+// nColRow = 0;
+ ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
+ pCol->Search( nRow, nColRow );
+ return GetThis(rValue, rErr);
+}
+
+BOOL ScQueryValueIterator::GetNext(double& rValue, USHORT& rErr)
+{
+ ++nRow;
+ return GetThis(rValue, rErr);
+}
+
+//-------------------------------------------------------------------------------
+
+ScCellIterator::ScCellIterator( ScDocument* pDocument,
+ USHORT nSCol, USHORT nSRow, USHORT nSTab,
+ USHORT nECol, USHORT nERow, USHORT nETab, BOOL bSTotal ) :
+ pDoc( pDocument ),
+ nStartCol( nSCol),
+ nStartRow( nSRow),
+ nStartTab( nSTab ),
+ nEndCol( nECol ),
+ nEndRow( nERow),
+ nEndTab( nETab ),
+ bSubTotal(bSTotal)
+
+{
+ PutInOrder( nStartCol, nEndCol);
+ PutInOrder( nStartRow, nEndRow);
+ PutInOrder( nStartTab, nEndTab );
+
+ if (nStartCol > MAXCOL) nStartCol = MAXCOL;
+ if (nEndCol > MAXCOL) nEndCol = MAXCOL;
+ if (nStartRow > MAXROW) nStartRow = MAXROW;
+ if (nEndRow > MAXROW) nEndRow = MAXROW;
+ if (nStartTab > MAXTAB) nStartTab = MAXTAB;
+ if (nEndTab > MAXTAB) nEndTab = MAXTAB;
+
+ while (nEndTab>0 && !pDoc->pTab[nEndTab])
+ --nEndTab; // nur benutzte Tabellen
+ if (nStartTab>nEndTab)
+ nStartTab = nEndTab;
+
+ nCol = nStartCol;
+ nRow = nStartRow;
+ nTab = nStartTab;
+ nColRow = 0; // wird bei GetFirst initialisiert
+
+ if (!pDoc->pTab[nTab])
+ {
+ DBG_ERROR("Tabelle nicht gefunden");
+ nStartCol = nCol = MAXCOL+1;
+ nStartRow = nRow = MAXROW+1;
+ nStartTab = nTab = MAXTAB+1; // -> Abbruch bei GetFirst
+ }
+}
+
+ScCellIterator::ScCellIterator
+ ( ScDocument* pDocument, const ScRange& rRange, BOOL bSTotal ) :
+ pDoc( pDocument ),
+ nStartCol( rRange.aStart.Col() ),
+ nStartRow( rRange.aStart.Row() ),
+ nStartTab( rRange.aStart.Tab() ),
+ nEndCol( rRange.aEnd.Col() ),
+ nEndRow( rRange.aEnd.Row() ),
+ nEndTab( rRange.aEnd.Tab() ),
+ bSubTotal(bSTotal)
+
+{
+ PutInOrder( nStartCol, nEndCol);
+ PutInOrder( nStartRow, nEndRow);
+ PutInOrder( nStartTab, nEndTab );
+
+ if (nStartCol > MAXCOL) nStartCol = MAXCOL;
+ if (nEndCol > MAXCOL) nEndCol = MAXCOL;
+ if (nStartRow > MAXROW) nStartRow = MAXROW;
+ if (nEndRow > MAXROW) nEndRow = MAXROW;
+ if (nStartTab > MAXTAB) nStartTab = MAXTAB;
+ if (nEndTab > MAXTAB) nEndTab = MAXTAB;
+
+ while (nEndTab>0 && !pDoc->pTab[nEndTab])
+ --nEndTab; // nur benutzte Tabellen
+ if (nStartTab>nEndTab)
+ nStartTab = nEndTab;
+
+ nCol = nStartCol;
+ nRow = nStartRow;
+ nTab = nStartTab;
+ nColRow = 0; // wird bei GetFirst initialisiert
+
+ if (!pDoc->pTab[nTab])
+ {
+ DBG_ERROR("Tabelle nicht gefunden");
+ nStartCol = nCol = MAXCOL+1;
+ nStartRow = nRow = MAXROW+1;
+ nStartTab = nTab = MAXTAB+1; // -> Abbruch bei GetFirst
+ }
+}
+
+ScBaseCell* ScCellIterator::GetThis()
+{
+ ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
+ for ( ;; )
+ {
+ if ( nRow > nEndRow )
+ {
+ nRow = nStartRow;
+ do
+ {
+ nCol++;
+ if ( nCol > nEndCol )
+ {
+ nCol = nStartCol;
+ nTab++;
+ if ( nTab > nEndTab )
+ return NULL; // Ende und Aus
+ }
+ pCol = &(pDoc->pTab[nTab])->aCol[nCol];
+ } while ( pCol->nCount == 0 );
+ pCol->Search( nRow, nColRow );
+ }
+
+ while ( (nColRow < pCol->nCount) && (pCol->pItems[nColRow].nRow < nRow) )
+ nColRow++;
+
+ if ( nColRow < pCol->nCount && pCol->pItems[nColRow].nRow <= nEndRow )
+ {
+ nRow = pCol->pItems[nColRow].nRow;
+ if ( !bSubTotal || !pDoc->pTab[nTab]->IsFiltered( nRow ) )
+ {
+ ScBaseCell* pCell = pCol->pItems[nColRow].pCell;
+
+ if ( bSubTotal && pCell->GetCellType() == CELLTYPE_FORMULA
+ && ((ScFormulaCell*)pCell)->IsSubTotal() )
+ nRow++; // Sub-Total-Zeilen nicht
+ else
+ return pCell; // gefunden
+ }
+ else
+ nRow++;
+ }
+ else
+ nRow = nEndRow + 1; // Naechste Spalte
+ }
+}
+
+ScBaseCell* ScCellIterator::GetFirst()
+{
+ if ( nTab > MAXTAB )
+ return NULL;
+ nCol = nStartCol;
+ nRow = nStartRow;
+ nTab = nStartTab;
+// nColRow = 0;
+ ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
+ pCol->Search( nRow, nColRow );
+ return GetThis();
+}
+
+ScBaseCell* ScCellIterator::GetNext()
+{
+ ++nRow;
+ return GetThis();
+}
+
+//-------------------------------------------------------------------------------
+
+ScQueryCellIterator::ScQueryCellIterator(ScDocument* pDocument, USHORT nTable,
+ const ScQueryParam& rParam, BOOL bMod ) :
+ pDoc( pDocument ),
+ nTab( nTable),
+ aParam (rParam),
+ bAdvanceQuery( FALSE )
+{
+ nCol = aParam.nCol1;
+ nRow = aParam.nRow1;
+ nColRow = 0; // wird bei GetFirst initialisiert
+ USHORT i;
+ if (bMod) // sonst schon eingetragen
+ {
+ for (i=0; (i<MAXQUERY) && (aParam.GetEntry(i).bDoQuery); i++)
+ {
+ ScQueryEntry& rEntry = aParam.GetEntry(i);
+ ULONG nIndex = 0;
+ rEntry.bQueryByString =
+ !(pDoc->GetFormatTable()->IsNumberFormat(*rEntry.pStr,
+ nIndex, rEntry.nVal));
+ }
+ }
+ nNumFormat = 0; // werden bei GetNumberFormat initialisiert
+ pAttrArray = 0;
+ nAttrEndRow = 0;
+}
+
+ScBaseCell* ScQueryCellIterator::GetThis()
+{
+ ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
+ for ( ;; )
+ {
+ if ( nRow > aParam.nRow2 )
+ {
+ nRow = aParam.nRow1;
+ if (aParam.bHasHeader)
+ nRow++;
+ do
+ {
+ if ( bAdvanceQuery )
+ AdvanceQueryParamEntryField();
+ if ( ++nCol > aParam.nCol2 )
+ return NULL; // Ende und Aus
+ pCol = &(pDoc->pTab[nTab])->aCol[nCol];
+ } while ( pCol->nCount == 0 );
+ pCol->Search( nRow, nColRow );
+ }
+
+ while ( nColRow < pCol->nCount && pCol->pItems[nColRow].nRow < nRow )
+ nColRow++;
+
+ if ( nColRow < pCol->nCount && pCol->pItems[nColRow].nRow <= aParam.nRow2 )
+ {
+ if ( pCol->pItems[nColRow].pCell->GetCellType() == CELLTYPE_NOTE )
+ nRow++;
+ else
+ {
+ nRow = pCol->pItems[nColRow].nRow;
+ if ((pDoc->pTab[nTab])->ValidQuery(nRow, aParam))
+ return pCol->pItems[nColRow].pCell; // gefunden
+ else
+ nRow++;
+ }
+ }
+ else
+ nRow = aParam.nRow2 + 1; // Naechste Spalte
+ }
+}
+
+ScBaseCell* ScQueryCellIterator::GetFirst()
+{
+ nCol = aParam.nCol1;
+ nRow = aParam.nRow1;
+ if (aParam.bHasHeader)
+ nRow++;
+// nColRow = 0;
+ ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
+ pCol->Search( nRow, nColRow );
+ return GetThis();
+}
+
+ScBaseCell* ScQueryCellIterator::GetNext()
+{
+ ++nRow;
+ return GetThis();
+}
+
+ULONG ScQueryCellIterator::GetNumberFormat()
+{
+ ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
+#if ! ( defined WTC || defined IRIX || defined ICC || defined HPUX || defined C50 )
+ lcl_IterGetNumberFormat( nNumFormat, pAttrArray,
+#else
+ lcl_IterGetNumberFormat( nNumFormat,
+ (ScAttrArray const *&)pAttrArray,
+#endif
+ nAttrEndRow, pCol->pAttrArray, nRow, pDoc );
+ return nNumFormat;
+}
+
+void ScQueryCellIterator::AdvanceQueryParamEntryField()
+{
+ USHORT nEntries = aParam.GetEntryCount();
+ for ( USHORT j = 0; j < nEntries; j++ )
+ {
+ ScQueryEntry& rEntry = aParam.GetEntry( j );
+ if ( rEntry.bDoQuery )
+ {
+ if ( rEntry.nField < MAXCOL )
+ rEntry.nField++;
+ else
+ {
+ DBG_ERRORFILE( "AdvanceQueryParamEntryField: ++rEntry.nField > MAXCOL" );
+ }
+ }
+ else
+ break; // for
+ }
+}
+
+//-------------------------------------------------------------------------------
+
+ScHorizontalCellIterator::ScHorizontalCellIterator(ScDocument* pDocument, USHORT nTable,
+ USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2 ) :
+ pDoc( pDocument ),
+ nTab( nTable ),
+ nStartCol( nCol1 ),
+ nEndCol( nCol2 ),
+ nEndRow( nRow2 ),
+ nCol( nCol1 ),
+ nRow( nRow1 ),
+ bMore( TRUE )
+{
+ USHORT i;
+ USHORT nIndex;
+
+ pNextRows = new USHORT[ nCol2-nCol1+1 ];
+ pNextIndices = new USHORT[ nCol2-nCol1+1 ];
+
+ for (i=nStartCol; i<=nEndCol; i++)
+ {
+ ScColumn* pCol = &pDoc->pTab[nTab]->aCol[i];
+
+ pCol->Search( nRow1, nIndex );
+ if ( nIndex < pCol->nCount )
+ {
+ pNextRows[i-nStartCol] = pCol->pItems[nIndex].nRow;
+ pNextIndices[i-nStartCol] = nIndex;
+ }
+ else
+ {
+ pNextRows[i-nStartCol] = MAXROW+1; // nichts gefunden
+ pNextIndices[i-nStartCol] = MAXROW+1;
+ }
+ }
+
+ if (pNextRows[0] != nRow1)
+ Advance();
+}
+
+ScHorizontalCellIterator::~ScHorizontalCellIterator()
+{
+ delete [] pNextRows;
+ delete [] pNextIndices;
+}
+
+ScBaseCell* ScHorizontalCellIterator::GetNext( USHORT& rCol, USHORT& rRow )
+{
+ if ( bMore )
+ {
+ rCol = nCol;
+ rRow = nRow;
+
+ ScColumn* pCol = &pDoc->pTab[nTab]->aCol[nCol];
+ USHORT nIndex = pNextIndices[nCol-nStartCol];
+ DBG_ASSERT( nIndex < pCol->nCount, "ScHorizontalCellIterator::GetNext: nIndex out of range" );
+ ScBaseCell* pCell = pCol->pItems[nIndex].pCell;
+ if ( ++nIndex < pCol->nCount )
+ {
+ pNextRows[nCol-nStartCol] = pCol->pItems[nIndex].nRow;
+ pNextIndices[nCol-nStartCol] = nIndex;
+ }
+ else
+ {
+ pNextRows[nCol-nStartCol] = MAXROW+1; // nichts gefunden
+ pNextIndices[nCol-nStartCol] = MAXROW+1;
+ }
+
+ Advance();
+ return pCell;
+ }
+ else
+ return NULL;
+}
+
+BOOL ScHorizontalCellIterator::ReturnNext( USHORT& rCol, USHORT& rRow )
+{
+ rCol = nCol;
+ rRow = nRow;
+ return bMore;
+}
+
+void ScHorizontalCellIterator::Advance()
+{
+ BOOL bFound = FALSE;
+ USHORT i;
+
+ for (i=nCol+1; i<=nEndCol && !bFound; i++)
+ if (pNextRows[i-nStartCol] == nRow)
+ {
+ nCol = i;
+ bFound = TRUE;
+ }
+
+ if (!bFound)
+ {
+ USHORT nMinRow = MAXROW+1;
+ for (i=nStartCol; i<=nEndCol; i++)
+ if (pNextRows[i-nStartCol] < nMinRow)
+ {
+ nCol = i;
+ nMinRow = pNextRows[i-nStartCol];
+ }
+
+ if (nMinRow <= nEndRow)
+ {
+ nRow = nMinRow;
+ bFound = TRUE;
+ }
+ }
+
+ if ( !bFound )
+ bMore = FALSE;
+}
+
+//-------------------------------------------------------------------------------
+
+ScHorizontalAttrIterator::ScHorizontalAttrIterator( ScDocument* pDocument, USHORT nTable,
+ USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2 ) :
+ pDoc( pDocument ),
+ nTab( nTable ),
+ nStartCol( nCol1 ),
+ nStartRow( nRow1 ),
+ nEndCol( nCol2 ),
+ nEndRow( nRow2 )
+{
+ DBG_ASSERT( pDoc->pTab[nTab], "Tabelle nicht da" );
+
+ USHORT i;
+
+ nRow = nStartRow;
+ nCol = nStartCol;
+ bRowEmpty = FALSE;
+
+ pIndices = new USHORT[nEndCol-nStartCol+1];
+ pNextEnd = new USHORT[nEndCol-nStartCol+1];
+ ppPatterns = new const ScPatternAttr*[nEndCol-nStartCol+1];
+
+ USHORT nSkipTo = MAXROW;
+ BOOL bEmpty = TRUE;
+ for (i=nStartCol; i<=nEndCol; i++)
+ {
+ USHORT nPos = i - nStartCol;
+ ScAttrArray* pArray = pDoc->pTab[nTab]->aCol[i].pAttrArray;
+ DBG_ASSERT( pArray, "pArray == 0" );
+
+ short s;
+ pArray->Search( nStartRow, s );
+ USHORT nIndex = (USHORT) s;
+
+ const ScPatternAttr* pPattern = pArray->pData[nIndex].pPattern;
+ USHORT nThisEnd = pArray->pData[nIndex].nRow;
+ if ( IsDefaultItem( pPattern ) )
+ {
+ pPattern = NULL;
+ if ( nThisEnd < nSkipTo )
+ nSkipTo = nThisEnd; // nSkipTo kann gleich hier gesetzt werden
+ }
+ else
+ bEmpty = FALSE; // Attribute gefunden
+
+ pIndices[nPos] = nIndex;
+ pNextEnd[nPos] = nThisEnd;
+ ppPatterns[nPos] = pPattern;
+ }
+
+ if (bEmpty)
+ nRow = nSkipTo; // bis zum naechsten Bereichsende ueberspringen
+ bRowEmpty = bEmpty;
+}
+
+ScHorizontalAttrIterator::~ScHorizontalAttrIterator()
+{
+ delete[] (ScPatternAttr**)ppPatterns;
+ delete[] pNextEnd;
+ delete[] pIndices;
+}
+
+const ScPatternAttr* ScHorizontalAttrIterator::GetNext( USHORT& rCol1, USHORT& rCol2, USHORT& rRow )
+{
+ for (;;)
+ {
+ if (!bRowEmpty)
+ {
+ // in dieser Zeile suchen
+
+ while ( nCol <= nEndCol && !ppPatterns[nCol-nStartCol] )
+ ++nCol;
+
+ if ( nCol <= nEndCol )
+ {
+ const ScPatternAttr* pPat = ppPatterns[nCol-nStartCol];
+ rRow = nRow;
+ rCol1 = nCol;
+ while ( nCol < nEndCol && ppPatterns[nCol+1-nStartCol] == pPat )
+ ++nCol;
+ rCol2 = nCol;
+ ++nCol; // hochzaehlen fuer naechsten Aufruf
+ return pPat; // gefunden
+ }
+ }
+
+ // naechste Zeile
+
+ ++nRow;
+ if ( nRow > nEndRow ) // schon am Ende?
+ return NULL; // nichts gefunden
+
+ BOOL bEmpty = TRUE;
+ for (USHORT i=nStartCol; i<=nEndCol; i++)
+ {
+ USHORT nPos = i-nStartCol;
+ if ( pNextEnd[nPos] < nRow )
+ {
+ ScAttrArray* pArray = pDoc->pTab[nTab]->aCol[i].pAttrArray;
+
+ USHORT nIndex = ++pIndices[nPos];
+ if ( nIndex < pArray->nCount )
+ {
+ const ScPatternAttr* pPattern = pArray->pData[nIndex].pPattern;
+ USHORT nThisEnd = pArray->pData[nIndex].nRow;
+ if ( IsDefaultItem( pPattern ) )
+ pPattern = NULL;
+ else
+ bEmpty = FALSE; // Attribute gefunden
+
+ pNextEnd[nPos] = nThisEnd;
+ ppPatterns[nPos] = pPattern;
+
+ DBG_ASSERT( pNextEnd[nPos] >= nRow, "Reihenfolge durcheinander" );
+ }
+ else
+ {
+ DBG_ERROR("AttrArray reicht nicht bis MAXROW");
+ pNextEnd[nPos] = MAXROW;
+ ppPatterns[nPos] = NULL;
+ }
+ }
+ else if ( ppPatterns[nPos] )
+ bEmpty = FALSE; // Bereich noch nicht zuende
+ }
+
+ if (bEmpty)
+ {
+ USHORT nCount = nEndCol-nStartCol+1;
+ USHORT nSkipTo = pNextEnd[0]; // naechstes Bereichsende suchen
+ for (i=1; i<nCount; i++)
+ if ( pNextEnd[i] < nSkipTo )
+ nSkipTo = pNextEnd[i];
+ nRow = nSkipTo; // leere Zeilen ueberspringen
+ }
+ bRowEmpty = bEmpty;
+ nCol = nStartCol; // wieder links anfangen
+ }
+
+ return NULL;
+}
+
+//-------------------------------------------------------------------------------
+
+inline BOOL IsGreater( USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2 )
+{
+ return ( nRow1 > nRow2 ) || ( nRow1 == nRow2 && nCol1 > nCol2 );
+}
+
+ScUsedAreaIterator::ScUsedAreaIterator( ScDocument* pDocument, USHORT nTable,
+ USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2 ) :
+ aCellIter( pDocument, nTable, nCol1, nRow1, nCol2, nRow2 ),
+ aAttrIter( pDocument, nTable, nCol1, nRow1, nCol2, nRow2 ),
+ nNextCol( nCol1 ),
+ nNextRow( nRow1 )
+{
+ pCell = aCellIter.GetNext( nCellCol, nCellRow );
+ pPattern = aAttrIter.GetNext( nAttrCol1, nAttrCol2, nAttrRow );
+}
+
+ScUsedAreaIterator::~ScUsedAreaIterator()
+{
+}
+
+BOOL ScUsedAreaIterator::GetNext()
+{
+ // Iteratoren weiterzaehlen
+
+ if ( pCell && IsGreater( nNextCol, nNextRow, nCellCol, nCellRow ) )
+ pCell = aCellIter.GetNext( nCellCol, nCellRow );
+
+ while ( pCell && pCell->GetCellType() == CELLTYPE_NOTE && !pCell->GetNotePtr() )
+ pCell = aCellIter.GetNext( nCellCol, nCellRow );
+
+ if ( pPattern && IsGreater( nNextCol, nNextRow, nAttrCol2, nAttrRow ) )
+ pPattern = aAttrIter.GetNext( nAttrCol1, nAttrCol2, nAttrRow );
+
+ if ( pPattern && nAttrRow == nNextRow && nAttrCol1 < nNextCol )
+ nAttrCol1 = nNextCol;
+
+ // naechsten Abschnitt heraussuchen
+
+ BOOL bFound = TRUE;
+ BOOL bUseCell = FALSE;
+
+ if ( pCell && pPattern )
+ {
+ if ( IsGreater( nCellCol, nCellRow, nAttrCol1, nAttrRow ) ) // vorne nur Attribute ?
+ {
+ pFoundCell = NULL;
+ pFoundPattern = pPattern;
+ nFoundRow = nAttrRow;
+ nFoundStartCol = nAttrCol1;
+ if ( nCellRow == nAttrRow && nCellCol <= nAttrCol2 ) // auch Zelle im Bereich ?
+ nFoundEndCol = nCellCol - 1; // nur bis vor der Zelle
+ else
+ nFoundEndCol = nAttrCol2; // alles
+ }
+ else
+ {
+ bUseCell = TRUE;
+ if ( nAttrRow == nCellRow && nAttrCol1 == nCellCol ) // Attribute auf der Zelle ?
+ pFoundPattern = pPattern;
+ else
+ pFoundPattern = NULL;
+ }
+ }
+ else if ( pCell ) // nur Zelle -> direkt uebernehmen
+ {
+ pFoundPattern = NULL;
+ bUseCell = TRUE; // Position von Zelle
+ }
+ else if ( pPattern ) // nur Attribute -> direkt uebernehmen
+ {
+ pFoundCell = NULL;
+ pFoundPattern = pPattern;
+ nFoundRow = nAttrRow;
+ nFoundStartCol = nAttrCol1;
+ nFoundEndCol = nAttrCol2;
+ }
+ else // gar nichts
+ bFound = FALSE;
+
+ if ( bUseCell ) // Position von Zelle
+ {
+ pFoundCell = pCell;
+ nFoundRow = nCellRow;
+ nFoundStartCol = nFoundEndCol = nCellCol;
+ }
+
+ if (bFound)
+ {
+ nNextRow = nFoundRow;
+ nNextCol = nFoundEndCol + 1;
+ }
+
+ return bFound;
+}
+
+//-------------------------------------------------------------------------------
+
+ScDocAttrIterator::ScDocAttrIterator(ScDocument* pDocument, USHORT nTable,
+ USHORT nCol1, USHORT nRow1,
+ USHORT nCol2, USHORT nRow2) :
+ pDoc( pDocument ),
+ nTab( nTable ),
+ nCol( nCol1 ),
+ nEndCol( nCol2 ),
+ nStartRow( nRow1 ),
+ nEndRow( nRow2 )
+{
+ if ( nTab<=MAXTAB && pDoc->pTab[nTab] )
+ pColIter = pDoc->pTab[nTab]->aCol[nCol].CreateAttrIterator( nStartRow, nEndRow );
+ else
+ pColIter = NULL;
+}
+
+ScDocAttrIterator::~ScDocAttrIterator()
+{
+ delete pColIter;
+}
+
+const ScPatternAttr* ScDocAttrIterator::GetNext( USHORT& rCol, USHORT& rRow1, USHORT& rRow2 )
+{
+ while ( pColIter )
+ {
+ const ScPatternAttr* pPattern = pColIter->Next( rRow1, rRow2 );
+ if ( pPattern )
+ {
+ rCol = nCol;
+ return pPattern;
+ }
+
+ delete pColIter;
+ ++nCol;
+ if ( nCol <= nEndCol )
+ pColIter = pDoc->pTab[nTab]->aCol[nCol].CreateAttrIterator( nStartRow, nEndRow );
+ else
+ pColIter = NULL;
+ }
+ return NULL; // is nix mehr
+}
+
+//-------------------------------------------------------------------------------
+
+ScAttrRectIterator::ScAttrRectIterator(ScDocument* pDocument, USHORT nTable,
+ USHORT nCol1, USHORT nRow1,
+ USHORT nCol2, USHORT nRow2) :
+ pDoc( pDocument ),
+ nTab( nTable ),
+ nEndCol( nCol2 ),
+ nStartRow( nRow1 ),
+ nEndRow( nRow2 ),
+ nIterStartCol( nCol1 ),
+ nIterEndCol( nCol1 )
+{
+ if ( nTab<=MAXTAB && pDoc->pTab[nTab] )
+ {
+ pColIter = pDoc->pTab[nTab]->aCol[nIterStartCol].CreateAttrIterator( nStartRow, nEndRow );
+ while ( nIterEndCol < nEndCol &&
+ pDoc->pTab[nTab]->aCol[nIterEndCol].IsAllAttrEqual(
+ pDoc->pTab[nTab]->aCol[nIterEndCol+1], nStartRow, nEndRow ) )
+ ++nIterEndCol;
+ }
+ else
+ pColIter = NULL;
+}
+
+ScAttrRectIterator::~ScAttrRectIterator()
+{
+ delete pColIter;
+}
+
+void ScAttrRectIterator::DataChanged()
+{
+ if (pColIter)
+ {
+ USHORT nNextRow = pColIter->GetNextRow();
+ delete pColIter;
+ pColIter = pDoc->pTab[nTab]->aCol[nIterStartCol].CreateAttrIterator( nNextRow, nEndRow );
+ }
+}
+
+const ScPatternAttr* ScAttrRectIterator::GetNext( USHORT& rCol1, USHORT& rCol2,
+ USHORT& rRow1, USHORT& rRow2 )
+{
+ while ( pColIter )
+ {
+ const ScPatternAttr* pPattern = pColIter->Next( rRow1, rRow2 );
+ if ( pPattern )
+ {
+ rCol1 = nIterStartCol;
+ rCol2 = nIterEndCol;
+ return pPattern;
+ }
+
+ delete pColIter;
+ nIterStartCol = nIterEndCol+1;
+ if ( nIterStartCol <= nEndCol )
+ {
+ nIterEndCol = nIterStartCol;
+ pColIter = pDoc->pTab[nTab]->aCol[nIterStartCol].CreateAttrIterator( nStartRow, nEndRow );
+ while ( nIterEndCol < nEndCol &&
+ pDoc->pTab[nTab]->aCol[nIterEndCol].IsAllAttrEqual(
+ pDoc->pTab[nTab]->aCol[nIterEndCol+1], nStartRow, nEndRow ) )
+ ++nIterEndCol;
+ }
+ else
+ pColIter = NULL;
+ }
+ return NULL; // is nix mehr
+}
+
diff --git a/sc/source/core/data/docpool.cxx b/sc/source/core/data/docpool.cxx
new file mode 100644
index 000000000000..b707e826577b
--- /dev/null
+++ b/sc/source/core/data/docpool.cxx
@@ -0,0 +1,829 @@
+/*************************************************************************
+ *
+ * $RCSfile: docpool.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include "scitems.hxx"
+#include <tools/shl.hxx>
+#include <vcl/system.hxx>
+#include <svtools/aeitem.hxx>
+#include <svtools/itemiter.hxx>
+#include <svx/algitem.hxx>
+#include <svx/boxitem.hxx>
+#include <svx/brshitem.hxx>
+#include <svx/cntritem.hxx>
+#include <svx/colritem.hxx>
+#include <svx/crsditem.hxx>
+#include <svx/dialmgr.hxx>
+#include <svx/fhgtitem.hxx>
+#include <svx/fontitem.hxx>
+#include <svx/itemtype.hxx>
+#include <svx/langitem.hxx>
+#include <svx/lrspitem.hxx>
+#include <svx/pageitem.hxx>
+#include <svx/pbinitem.hxx>
+#include <svx/postitem.hxx>
+#include <svx/rotmodit.hxx>
+#include <svx/shaditem.hxx>
+#include <svx/shdditem.hxx>
+#include <svx/sizeitem.hxx>
+#include <svx/svxitems.hrc>
+#include <svx/udlnitem.hxx>
+#include <svx/ulspitem.hxx>
+#include <svx/wghtitem.hxx>
+
+#include "docpool.hxx"
+#include "global.hxx"
+#include "attrib.hxx"
+#include "patattr.hxx"
+#include "globstr.hrc"
+#include "sc.hrc" // Slot-IDs
+
+
+#define SC_MAX_POOLREF (SFX_ITEMS_MAXREF - 39)
+#define SC_SAFE_POOLREF (SC_MAX_POOLREF + 20)
+
+// STATIC DATA -----------------------------------------------------------
+
+USHORT* ScDocumentPool::pVersionMap1 = 0;
+USHORT* ScDocumentPool::pVersionMap2 = 0;
+USHORT* ScDocumentPool::pVersionMap3 = 0;
+USHORT* ScDocumentPool::pVersionMap4 = 0;
+
+static SfxItemInfo __READONLY_DATA aItemInfos[] =
+{
+ { SID_ATTR_CHAR_FONT, SFX_ITEM_POOLABLE }, // ATTR_FONT
+ { SID_ATTR_CHAR_FONTHEIGHT, SFX_ITEM_POOLABLE }, // ATTR_FONT_HEIGHT
+ { SID_ATTR_CHAR_WEIGHT, SFX_ITEM_POOLABLE }, // ATTR_FONT_WEIGHT
+ { SID_ATTR_CHAR_POSTURE, SFX_ITEM_POOLABLE }, // ATTR_FONT_POSTURE
+ { SID_ATTR_CHAR_UNDERLINE, SFX_ITEM_POOLABLE }, // ATTR_FONT_UNDERLINE
+ { SID_ATTR_CHAR_STRIKEOUT, SFX_ITEM_POOLABLE }, // ATTR_FONT_CROSSEDOUT
+ { SID_ATTR_CHAR_CONTOUR, SFX_ITEM_POOLABLE }, // ATTR_FONT_CONTOUR
+ { SID_ATTR_CHAR_SHADOWED, SFX_ITEM_POOLABLE }, // ATTR_FONT_SHADOWED
+ { SID_ATTR_CHAR_COLOR, SFX_ITEM_POOLABLE }, // ATTR_FONT_COLOR
+ { SID_ATTR_CHAR_LANGUAGE, SFX_ITEM_POOLABLE }, // ATTR_FONT_LANGUAGE
+ { SID_ATTR_ALIGN_HOR_JUSTIFY, SFX_ITEM_POOLABLE }, // ATTR_HOR_JUSTIFY
+ { SID_ATTR_ALIGN_INDENT, SFX_ITEM_POOLABLE }, // ATTR_INDENT ab 350
+ { SID_ATTR_ALIGN_VER_JUSTIFY, SFX_ITEM_POOLABLE }, // ATTR_VER_JUSTIFY
+ { SID_ATTR_ALIGN_ORIENTATION, SFX_ITEM_POOLABLE }, // ATTR_ORIENTATION
+ { SID_ATTR_ALIGN_DEGREES, SFX_ITEM_POOLABLE }, // ATTR_ROTATE_VALUE ab 367
+ { SID_ATTR_ALIGN_LOCKPOS, SFX_ITEM_POOLABLE }, // ATTR_ROTATE_MODE ab 367
+ { SID_ATTR_ALIGN_LINEBREAK, SFX_ITEM_POOLABLE }, // ATTR_LINEBREAK
+ { SID_ATTR_ALIGN_MARGIN, SFX_ITEM_POOLABLE }, // ATTR_MARGIN
+ { 0, SFX_ITEM_POOLABLE }, // ATTR_MERGE
+ { 0, SFX_ITEM_POOLABLE }, // ATTR_MERGE_FLAG
+ { SID_ATTR_NUMBERFORMAT_VALUE, SFX_ITEM_POOLABLE }, // ATTR_VALUE_FORMAT
+ { ATTR_LANGUAGE_FORMAT, SFX_ITEM_POOLABLE }, // ATTR_LANGUAGE_FORMAT ab 329, wird im Dialog mit SID_ATTR_NUMBERFORMAT_VALUE kombiniert
+ { SID_ATTR_BRUSH, SFX_ITEM_POOLABLE }, // ATTR_BACKGROUND
+ { SID_SCATTR_PROTECTION, SFX_ITEM_POOLABLE }, // ATTR_PROTECTION
+ { SID_ATTR_BORDER_OUTER, SFX_ITEM_POOLABLE }, // ATTR_BORDER
+ { SID_ATTR_BORDER_INNER, SFX_ITEM_POOLABLE }, // ATTR_BORDER_INNER
+ { SID_ATTR_BORDER_SHADOW, SFX_ITEM_POOLABLE }, // ATTR_SHADOW
+ { 0, SFX_ITEM_POOLABLE }, // ATTR_VALIDDATA
+ { 0, SFX_ITEM_POOLABLE }, // ATTR_CONDITIONAL
+ { 0, SFX_ITEM_POOLABLE }, // ATTR_PATTERN
+ { SID_ATTR_LRSPACE, SFX_ITEM_POOLABLE }, // ATTR_LRSPACE
+ { SID_ATTR_ULSPACE, SFX_ITEM_POOLABLE }, // ATTR_ULSPACE
+ { SID_ATTR_PAGE, SFX_ITEM_POOLABLE }, // ATTR_PAGE
+ { 0, SFX_ITEM_POOLABLE }, // ATTR_PAGE_PAPERTRAY, seit 303 nur noch dummy
+ { SID_ATTR_PAGE_PAPERBIN, SFX_ITEM_POOLABLE }, // ATTR_PAGE_PAPERBIN
+ { SID_ATTR_PAGE_SIZE, SFX_ITEM_POOLABLE }, // ATTR_PAGE_SIZE
+ { SID_ATTR_PAGE_MAXSIZE, SFX_ITEM_POOLABLE }, // ATTR_PAGE_MAXSIZE
+ { SID_ATTR_PAGE_EXT1, SFX_ITEM_POOLABLE }, // ATTR_PAGE_HORCENTER
+ { SID_ATTR_PAGE_EXT2, SFX_ITEM_POOLABLE }, // ATTR_PAGE_VERCENTER
+ { SID_ATTR_PAGE_ON, SFX_ITEM_POOLABLE }, // ATTR_PAGE_ON
+ { SID_ATTR_PAGE_DYNAMIC, SFX_ITEM_POOLABLE }, // ATTR_PAGE_DYNAMIC
+ { SID_ATTR_PAGE_SHARED, SFX_ITEM_POOLABLE }, // ATTR_PAGE_SHARED
+ { SID_SCATTR_PAGE_NOTES, SFX_ITEM_POOLABLE }, // ATTR_PAGE_NOTES
+ { SID_SCATTR_PAGE_GRID, SFX_ITEM_POOLABLE }, // ATTR_PAGE_GRID
+ { SID_SCATTR_PAGE_HEADERS, SFX_ITEM_POOLABLE }, // ATTR_PAGE_HEADERS
+ { SID_SCATTR_PAGE_CHARTS, SFX_ITEM_POOLABLE }, // ATTR_PAGE_CHARTS
+ { SID_SCATTR_PAGE_OBJECTS, SFX_ITEM_POOLABLE }, // ATTR_PAGE_OBJECTS
+ { SID_SCATTR_PAGE_DRAWINGS, SFX_ITEM_POOLABLE }, // ATTR_PAGE_DRAWINGS
+ { SID_SCATTR_PAGE_TOPDOWN, SFX_ITEM_POOLABLE }, // ATTR_PAGE_TOPDOWN
+ { SID_SCATTR_PAGE_SCALE, SFX_ITEM_POOLABLE }, // ATTR_PAGE_SCALE
+ { SID_SCATTR_PAGE_SCALETOPAGES, SFX_ITEM_POOLABLE }, // ATTR_PAGE_SCALETOPAGES
+ { SID_SCATTR_PAGE_FIRSTPAGENO, SFX_ITEM_POOLABLE }, // ATTR_PAGE_FIRSTPAGENO
+ { SID_SCATTR_PAGE_PRINTAREA, SFX_ITEM_POOLABLE }, // ATTR_PAGE_PRINTAREA
+ { SID_SCATTR_PAGE_REPEATROW, SFX_ITEM_POOLABLE }, // ATTR_PAGE_REPEATROW
+ { SID_SCATTR_PAGE_REPEATCOL, SFX_ITEM_POOLABLE }, // ATTR_PAGE_REPEATCOL
+ { SID_SCATTR_PAGE_PRINTTABLES, SFX_ITEM_POOLABLE }, // ATTR_PAGE_PRINTTABLES
+ { SID_SCATTR_PAGE_HEADERLEFT, SFX_ITEM_POOLABLE }, // ATTR_PAGE_HEADERLEFT
+ { SID_SCATTR_PAGE_FOOTERLEFT, SFX_ITEM_POOLABLE }, // ATTR_PAGE_FOOTERLEFT
+ { SID_SCATTR_PAGE_HEADERRIGHT, SFX_ITEM_POOLABLE }, // ATTR_PAGE_HEADERRIGHT
+ { SID_SCATTR_PAGE_FOOTERRIGHT, SFX_ITEM_POOLABLE }, // ATTR_PAGE_FOOTERRIGHT
+ { SID_ATTR_PAGE_HEADERSET, SFX_ITEM_POOLABLE }, // ATTR_PAGE_HEADERSET
+ { SID_ATTR_PAGE_FOOTERSET, SFX_ITEM_POOLABLE }, // ATTR_PAGE_FOOTERSET
+ { SID_SCATTR_PAGE_FORMULAS, SFX_ITEM_POOLABLE }, // ATTR_PAGE_FORMULAS
+ { SID_SCATTR_PAGE_NULLVALS, SFX_ITEM_POOLABLE } // ATTR_PAGE_NULLVALS
+};
+
+// -----------------------------------------------------------------------
+
+ScDocumentPool::ScDocumentPool( SfxItemPool* pSecPool, BOOL bLoadRefCounts )
+
+ : SfxItemPool ( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("ScDocumentPool")),
+ ATTR_STARTINDEX, ATTR_ENDINDEX,
+ aItemInfos, NULL, bLoadRefCounts ),
+ pSecondary ( pSecPool )
+{
+ Font aStdFont = System::GetStandardFont( STDFONT_SWISS );
+ SvxFontItem* pGlobalFontAttr = new SvxFontItem( aStdFont.GetFamily(),
+ aStdFont.GetName(),
+ aStdFont.GetStyleName(),
+ aStdFont.GetPitch(),
+ aStdFont.GetCharSet() );
+
+ SvxBoxInfoItem* pGlobalBorderInnerAttr = new SvxBoxInfoItem( ATTR_BORDER_INNER );
+ SfxItemSet* pSet = new SfxItemSet( *this, ATTR_PATTERN_START, ATTR_PATTERN_END );
+ SfxItemSet aSetItemItemSet( *this,
+ ATTR_BACKGROUND, ATTR_BACKGROUND,
+ ATTR_BORDER, ATTR_SHADOW,
+ ATTR_LRSPACE, ATTR_ULSPACE,
+ ATTR_PAGE_SIZE, ATTR_PAGE_SIZE,
+ ATTR_PAGE_ON, ATTR_PAGE_SHARED,
+ 0 );
+
+ pGlobalBorderInnerAttr->SetLine(NULL, BOXINFO_LINE_HORI);
+ pGlobalBorderInnerAttr->SetLine(NULL, BOXINFO_LINE_VERT);
+ pGlobalBorderInnerAttr->SetTable(TRUE);
+ pGlobalBorderInnerAttr->SetDist((BOOL)FALSE);
+ pGlobalBorderInnerAttr->SetMinDist(FALSE);
+
+ ppPoolDefaults = new SfxPoolItem*[ATTR_ENDINDEX-ATTR_STARTINDEX+1];
+
+ ppPoolDefaults[ ATTR_FONT - ATTR_STARTINDEX ] = pGlobalFontAttr;
+ ppPoolDefaults[ ATTR_FONT_HEIGHT - ATTR_STARTINDEX ] = new SvxFontHeightItem( 200 ); // 10 pt;
+ ppPoolDefaults[ ATTR_FONT_WEIGHT - ATTR_STARTINDEX ] = new SvxWeightItem;
+ ppPoolDefaults[ ATTR_FONT_POSTURE - ATTR_STARTINDEX ] = new SvxPostureItem;
+ ppPoolDefaults[ ATTR_FONT_UNDERLINE - ATTR_STARTINDEX ] = new SvxUnderlineItem;
+ ppPoolDefaults[ ATTR_FONT_CROSSEDOUT - ATTR_STARTINDEX ] = new SvxCrossedOutItem;
+ ppPoolDefaults[ ATTR_FONT_CONTOUR - ATTR_STARTINDEX ] = new SvxContourItem;
+ ppPoolDefaults[ ATTR_FONT_SHADOWED - ATTR_STARTINDEX ] = new SvxShadowedItem;
+ ppPoolDefaults[ ATTR_FONT_COLOR - ATTR_STARTINDEX ] = new SvxColorItem;
+ ppPoolDefaults[ ATTR_FONT_LANGUAGE - ATTR_STARTINDEX ] = new SvxLanguageItem( LanguageType(LANGUAGE_DONTKNOW), ATTR_FONT_LANGUAGE );
+ ppPoolDefaults[ ATTR_HOR_JUSTIFY - ATTR_STARTINDEX ] = new SvxHorJustifyItem;
+ ppPoolDefaults[ ATTR_INDENT - ATTR_STARTINDEX ] = new SfxUInt16Item( ATTR_INDENT, 0 );
+ ppPoolDefaults[ ATTR_VER_JUSTIFY - ATTR_STARTINDEX ] = new SvxVerJustifyItem;
+ ppPoolDefaults[ ATTR_ORIENTATION - ATTR_STARTINDEX ] = new SvxOrientationItem;
+ ppPoolDefaults[ ATTR_ROTATE_VALUE - ATTR_STARTINDEX ] = new SfxInt32Item( ATTR_ROTATE_VALUE, 0 );
+ ppPoolDefaults[ ATTR_ROTATE_MODE - ATTR_STARTINDEX ] = new SvxRotateModeItem( SVX_ROTATE_MODE_BOTTOM, ATTR_ROTATE_MODE );
+ ppPoolDefaults[ ATTR_LINEBREAK - ATTR_STARTINDEX ] = new SfxBoolItem( ATTR_LINEBREAK );
+ ppPoolDefaults[ ATTR_MARGIN - ATTR_STARTINDEX ] = new SvxMarginItem;
+ ppPoolDefaults[ ATTR_MERGE - ATTR_STARTINDEX ] = new ScMergeAttr;
+ ppPoolDefaults[ ATTR_MERGE_FLAG - ATTR_STARTINDEX ] = new ScMergeFlagAttr;
+ ppPoolDefaults[ ATTR_VALUE_FORMAT - ATTR_STARTINDEX ] = new SfxUInt32Item( ATTR_VALUE_FORMAT, 0 );
+ ppPoolDefaults[ ATTR_LANGUAGE_FORMAT - ATTR_STARTINDEX ] = new SvxLanguageItem( ScGlobal::eLnge, ATTR_LANGUAGE_FORMAT );
+ ppPoolDefaults[ ATTR_BACKGROUND - ATTR_STARTINDEX ] = new SvxBrushItem( Color(COL_TRANSPARENT), ATTR_BACKGROUND );
+ ppPoolDefaults[ ATTR_PROTECTION - ATTR_STARTINDEX ] = new ScProtectionAttr;
+ ppPoolDefaults[ ATTR_BORDER - ATTR_STARTINDEX ] = new SvxBoxItem( ATTR_BORDER );
+ ppPoolDefaults[ ATTR_BORDER_INNER - ATTR_STARTINDEX ] = pGlobalBorderInnerAttr;
+ ppPoolDefaults[ ATTR_SHADOW - ATTR_STARTINDEX ] = new SvxShadowItem( ATTR_SHADOW );
+ ppPoolDefaults[ ATTR_VALIDDATA - ATTR_STARTINDEX ] = new SfxUInt32Item( ATTR_VALIDDATA, 0 );
+ ppPoolDefaults[ ATTR_CONDITIONAL - ATTR_STARTINDEX ] = new SfxUInt32Item( ATTR_CONDITIONAL, 0 );
+
+ // GetRscString funktioniert erst nach ScGlobal::Init, zu erkennen am EmptyBrushItem
+ //! zusaetzliche Methode ScGlobal::IsInit() oder so...
+ //! oder erkennen, ob dies der Secondary-Pool fuer einen MessagePool ist
+ if ( ScGlobal::GetEmptyBrushItem() )
+ ppPoolDefaults[ ATTR_PATTERN - ATTR_STARTINDEX ] = new ScPatternAttr( pSet, ScGlobal::GetRscString(STR_STYLENAME_STANDARD) );
+ else
+ ppPoolDefaults[ ATTR_PATTERN - ATTR_STARTINDEX ] = new ScPatternAttr( pSet,
+ String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(STRING_STANDARD)) ); //! without name?
+
+ ppPoolDefaults[ ATTR_LRSPACE - ATTR_STARTINDEX ] = new SvxLRSpaceItem( ATTR_LRSPACE );
+ ppPoolDefaults[ ATTR_ULSPACE - ATTR_STARTINDEX ] = new SvxULSpaceItem( ATTR_ULSPACE );
+ ppPoolDefaults[ ATTR_PAGE - ATTR_STARTINDEX ] = new SvxPageItem( ATTR_PAGE );
+ ppPoolDefaults[ ATTR_PAGE_PAPERTRAY - ATTR_STARTINDEX ] = new SfxAllEnumItem( ATTR_PAGE_PAPERTRAY );
+ ppPoolDefaults[ ATTR_PAGE_PAPERBIN - ATTR_STARTINDEX ] = new SvxPaperBinItem( ATTR_PAGE_PAPERBIN );
+ ppPoolDefaults[ ATTR_PAGE_SIZE - ATTR_STARTINDEX ] = new SvxSizeItem( ATTR_PAGE_SIZE );
+ ppPoolDefaults[ ATTR_PAGE_MAXSIZE - ATTR_STARTINDEX ] = new SvxSizeItem( ATTR_PAGE_MAXSIZE );
+ ppPoolDefaults[ ATTR_PAGE_HORCENTER - ATTR_STARTINDEX ] = new SfxBoolItem( ATTR_PAGE_HORCENTER );
+ ppPoolDefaults[ ATTR_PAGE_VERCENTER - ATTR_STARTINDEX ] = new SfxBoolItem( ATTR_PAGE_VERCENTER );
+ ppPoolDefaults[ ATTR_PAGE_ON - ATTR_STARTINDEX ] = new SfxBoolItem( ATTR_PAGE_ON, TRUE );
+ ppPoolDefaults[ ATTR_PAGE_DYNAMIC - ATTR_STARTINDEX ] = new SfxBoolItem( ATTR_PAGE_DYNAMIC, TRUE );
+ ppPoolDefaults[ ATTR_PAGE_SHARED - ATTR_STARTINDEX ] = new SfxBoolItem( ATTR_PAGE_SHARED, TRUE );
+ ppPoolDefaults[ ATTR_PAGE_NOTES - ATTR_STARTINDEX ] = new SfxBoolItem( ATTR_PAGE_NOTES, FALSE );
+ ppPoolDefaults[ ATTR_PAGE_GRID - ATTR_STARTINDEX ] = new SfxBoolItem( ATTR_PAGE_GRID, FALSE );
+ ppPoolDefaults[ ATTR_PAGE_HEADERS - ATTR_STARTINDEX ] = new SfxBoolItem( ATTR_PAGE_HEADERS, FALSE );
+ ppPoolDefaults[ ATTR_PAGE_CHARTS - ATTR_STARTINDEX ] = new ScViewObjectModeItem( ATTR_PAGE_CHARTS );
+ ppPoolDefaults[ ATTR_PAGE_OBJECTS - ATTR_STARTINDEX ] = new ScViewObjectModeItem( ATTR_PAGE_OBJECTS );
+ ppPoolDefaults[ ATTR_PAGE_DRAWINGS - ATTR_STARTINDEX ] = new ScViewObjectModeItem( ATTR_PAGE_DRAWINGS );
+ ppPoolDefaults[ ATTR_PAGE_TOPDOWN - ATTR_STARTINDEX ] = new SfxBoolItem( ATTR_PAGE_TOPDOWN, TRUE );
+ ppPoolDefaults[ ATTR_PAGE_SCALE - ATTR_STARTINDEX ] = new SfxUInt16Item( ATTR_PAGE_SCALE, 100 );
+ ppPoolDefaults[ ATTR_PAGE_SCALETOPAGES-ATTR_STARTINDEX ] = new SfxUInt16Item( ATTR_PAGE_SCALETOPAGES, 1 );
+ ppPoolDefaults[ ATTR_PAGE_FIRSTPAGENO- ATTR_STARTINDEX ] = new SfxUInt16Item( ATTR_PAGE_FIRSTPAGENO, 1 );
+ ppPoolDefaults[ ATTR_PAGE_PRINTAREA - ATTR_STARTINDEX ] = new ScRangeItem( ATTR_PAGE_PRINTAREA );
+ ppPoolDefaults[ ATTR_PAGE_REPEATROW - ATTR_STARTINDEX ] = new ScRangeItem( ATTR_PAGE_REPEATROW );
+ ppPoolDefaults[ ATTR_PAGE_REPEATCOL - ATTR_STARTINDEX ] = new ScRangeItem( ATTR_PAGE_REPEATCOL );
+ ppPoolDefaults[ ATTR_PAGE_PRINTTABLES- ATTR_STARTINDEX ] = new ScTableListItem( ATTR_PAGE_PRINTTABLES );
+ ppPoolDefaults[ ATTR_PAGE_HEADERLEFT - ATTR_STARTINDEX ] = new ScPageHFItem( ATTR_PAGE_HEADERLEFT );
+ ppPoolDefaults[ ATTR_PAGE_FOOTERLEFT - ATTR_STARTINDEX ] = new ScPageHFItem( ATTR_PAGE_FOOTERLEFT );
+ ppPoolDefaults[ ATTR_PAGE_HEADERRIGHT- ATTR_STARTINDEX ] = new ScPageHFItem( ATTR_PAGE_HEADERRIGHT );
+ ppPoolDefaults[ ATTR_PAGE_FOOTERRIGHT- ATTR_STARTINDEX ] = new ScPageHFItem( ATTR_PAGE_FOOTERRIGHT );
+ ppPoolDefaults[ ATTR_PAGE_HEADERSET - ATTR_STARTINDEX ] = new SvxSetItem( ATTR_PAGE_HEADERSET, aSetItemItemSet );
+ ppPoolDefaults[ ATTR_PAGE_FOOTERSET - ATTR_STARTINDEX ] = new SvxSetItem( ATTR_PAGE_FOOTERSET, aSetItemItemSet );
+ ppPoolDefaults[ ATTR_PAGE_FORMULAS - ATTR_STARTINDEX ] = new SfxBoolItem( ATTR_PAGE_FORMULAS, FALSE );
+ ppPoolDefaults[ ATTR_PAGE_NULLVALS - ATTR_STARTINDEX ] = new SfxBoolItem( ATTR_PAGE_NULLVALS, TRUE );
+// ppPoolDefaults[ ATTR_ITEM_DOUBLE - ATTR_STARTINDEX ] = new ScDoubleItem( ATTR_ITEM_DOUBLE, 0 );
+
+ SetDefaults( ppPoolDefaults );
+
+ if ( pSecondary )
+ SetSecondaryPool( pSecondary );
+
+ // ATTR_LANGUAGE_FORMAT ab sv329 eingefuegt, VersionMap in _ScGlobal__Init
+ SetVersionMap( 1, 100, 157, pVersionMap1 );
+
+ // ATTR_VALIDDATA, ATTR_CONDITIONAL ab 341
+ SetVersionMap( 2, 100, 158, pVersionMap2 );
+
+ // ATTR_INDENT ab 350
+ SetVersionMap( 3, 100, 160, pVersionMap3 );
+
+ // ATTR_ROTATE_VALUE, ATTR_ROTATE_MODE ab 367
+ SetVersionMap( 4, 100, 161, pVersionMap4 );
+}
+
+__EXPORT ScDocumentPool::~ScDocumentPool()
+{
+ Delete();
+
+ for ( USHORT i=0; i < ATTR_ENDINDEX-ATTR_STARTINDEX+1; i++ )
+ {
+ SetRef( *ppPoolDefaults[i], 0 );
+ delete ppPoolDefaults[i];
+ }
+
+ delete[] ppPoolDefaults;
+ delete pSecondary;
+}
+
+void ScDocumentPool::InitVersionMaps()
+{
+ DBG_ASSERT( !pVersionMap1 && !pVersionMap2 &&
+ !pVersionMap3 && !pVersionMap4, "InitVersionMaps mehrfach" );
+
+ // alte WhichId's mappen
+ // nicht mit ATTR_* zaehlen, falls die sich nochmal aendern
+
+ // erste Map: ATTR_LANGUAGE_FORMAT ab sv329 eingefuegt
+
+ const USHORT nMap1Start = 100; // alter ATTR_STARTINDEX
+ const USHORT nMap1End = 157; // alter ATTR_ENDINDEX
+ const USHORT nMap1Count = nMap1End - nMap1Start + 1;
+ const USHORT nMap1New = 18; // ATTR_LANGUAGE_FORMAT - ATTR_STARTINDEX
+ pVersionMap1 = new USHORT [ nMap1Count ];
+ USHORT i, j;
+ for ( i=0, j=nMap1Start; i < nMap1New; i++, j++ )
+ pVersionMap1[i] = j;
+ // ein Eintrag eingefuegt...
+ for ( i=nMap1New, j=nMap1Start+nMap1New+1; i < nMap1Count; i++, j++ )
+ pVersionMap1[i] = j;
+
+ // zweite Map: ATTR_VALIDDATA und ATTR_CONDITIONAL ab 341 eingefuegt
+
+ const USHORT nMap2Start = 100; // ATTR_STARTINDEX
+ const USHORT nMap2End = 158; // ATTR_ENDINDEX
+ const USHORT nMap2Count = nMap2End - nMap2Start + 1;
+ const USHORT nMap2New = 24; // ATTR_VALIDDATA - ATTR_STARTINDEX
+ pVersionMap2 = new USHORT [ nMap2Count ];
+ for ( i=0, j=nMap2Start; i < nMap2New; i++, j++ )
+ pVersionMap2[i] = j;
+ // zwei Eintraege eingefuegt...
+ for ( i=nMap2New, j=nMap2Start+nMap2New+2; i < nMap2Count; i++, j++ )
+ pVersionMap2[i] = j;
+
+ // dritte Map: ATTR_INDENT ab 350 eingefuegt
+
+ const USHORT nMap3Start = 100; // ATTR_STARTINDEX
+ const USHORT nMap3End = 160; // ATTR_ENDINDEX
+ const USHORT nMap3Count = nMap3End - nMap3Start + 1;
+ const USHORT nMap3New = 11; // ATTR_INDENT - ATTR_STARTINDEX
+ pVersionMap3 = new USHORT [ nMap3Count ];
+ for ( i=0, j=nMap3Start; i < nMap3New; i++, j++ )
+ pVersionMap3[i] = j;
+ // ein Eintrag eingefuegt...
+ for ( i=nMap3New, j=nMap3Start+nMap3New+1; i < nMap3Count; i++, j++ )
+ pVersionMap3[i] = j;
+
+ // vierte Map: ATTR_ROTATE_VALUE und ATTR_ROTATE_MODE ab 367 eingefuegt
+
+ const USHORT nMap4Start = 100; // ATTR_STARTINDEX
+ const USHORT nMap4End = 161; // ATTR_ENDINDEX
+ const USHORT nMap4Count = nMap4End - nMap4Start + 1;
+ const USHORT nMap4New = 14; // ATTR_ROTATE_VALUE - ATTR_STARTINDEX
+ pVersionMap4 = new USHORT [ nMap4Count ];
+ for ( i=0, j=nMap4Start; i < nMap4New; i++, j++ )
+ pVersionMap4[i] = j;
+ // zwei Eintraege eingefuegt...
+ for ( i=nMap4New, j=nMap4Start+nMap4New+2; i < nMap4Count; i++, j++ )
+ pVersionMap4[i] = j;
+}
+
+void ScDocumentPool::DeleteVersionMaps()
+{
+ DBG_ASSERT( pVersionMap1 && pVersionMap2 &&
+ pVersionMap3 && pVersionMap4, "DeleteVersionMaps ohne Maps" );
+
+ delete[] pVersionMap4;
+ pVersionMap4 = 0;
+ delete[] pVersionMap3;
+ pVersionMap3 = 0;
+ delete[] pVersionMap2;
+ pVersionMap2 = 0;
+ delete[] pVersionMap1;
+ pVersionMap1 = 0;
+}
+
+// ----------------------------------------------------------------------------------------
+//
+// Fuer die Pattern-Attribute (SetItems) kann der USHORT RefCount leicht ueberlaufen
+// (z.B. 600 ganze Zeilen abwechselnd formatieren).
+// Darum wird der RefCount bei SC_MAX_POOLREF festgehalten und nicht mehr hoch- oder
+// heruntergezaehlt. Dieser RefCount wird dann erst beim naechsten Laden neu gezaehlt.
+// Die Differenz zwischen SC_MAX_POOLREF und SC_SAFE_POOLREF ist ein wenig groesser
+// als noetig, um zu erkennen, wenn der RefCount aus Versehen doch "normal" veraendert
+// wird (Assertions).
+//
+
+const SfxPoolItem& __EXPORT ScDocumentPool::Put( const SfxPoolItem& rItem, USHORT nWhich )
+{
+ if ( rItem.Which() != ATTR_PATTERN ) // nur Pattern ist special
+ return SfxItemPool::Put( rItem, nWhich );
+
+ // das Default-Pattern dieses Pools nicht kopieren
+ if (&rItem == ppPoolDefaults[ ATTR_PATTERN - ATTR_STARTINDEX ])
+ return rItem;
+
+ // ansonsten muss Put immer passieren, weil es ein anderer Pool sein kann
+ const SfxPoolItem& rNew = SfxItemPool::Put( rItem, nWhich );
+ CheckRef( rNew );
+ return rNew;
+}
+
+void __EXPORT ScDocumentPool::Remove( const SfxPoolItem& rItem )
+{
+ if ( rItem.Which() == ATTR_PATTERN ) // nur Pattern ist special
+ {
+ USHORT nRef = rItem.GetRef();
+ if ( nRef >= SC_MAX_POOLREF && nRef <= SFX_ITEMS_MAXREF )
+ {
+ if ( nRef != SC_SAFE_POOLREF )
+ {
+ DBG_ERROR("Wer fummelt da an meinen Ref-Counts herum");
+ SetRef( (SfxPoolItem&)rItem, SC_SAFE_POOLREF );
+ }
+ return; // nicht herunterzaehlen
+ }
+ }
+ SfxItemPool::Remove( rItem );
+}
+
+void ScDocumentPool::CheckRef( const SfxPoolItem& rItem ) // static
+{
+ USHORT nRef = rItem.GetRef();
+ if ( nRef >= SC_MAX_POOLREF && nRef <= SFX_ITEMS_MAXREF )
+ {
+ // beim Apply vom Cache wird evtl. um 2 hochgezaehlt (auf MAX+1 oder SAFE+2),
+ // heruntergezaehlt wird nur einzeln (in LoadCompleted)
+ DBG_ASSERT( nRef<=SC_MAX_POOLREF+1 || (nRef>=SC_SAFE_POOLREF-1 && nRef<=SC_SAFE_POOLREF+2),
+ "ScDocumentPool::CheckRef" );
+
+ SetRef( (SfxPoolItem&)rItem, SC_SAFE_POOLREF );
+ }
+}
+
+void ScDocumentPool::MyLoadCompleted()
+{
+ LoadCompleted();
+
+ USHORT nCount = GetItemCount(ATTR_PATTERN);
+ for (USHORT i=0; i<nCount; i++)
+ {
+ const SfxPoolItem* pItem = GetItem(ATTR_PATTERN, i);
+ if (pItem)
+ CheckRef(*pItem);
+ }
+}
+
+// ----------------------------------------------------------------------------------------
+
+void ScDocumentPool::StyleDeleted( ScStyleSheet* pStyle )
+{
+ USHORT nCount = GetItemCount(ATTR_PATTERN);
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScPatternAttr* pPattern = (ScPatternAttr*)GetItem(ATTR_PATTERN, i);
+ if ( pPattern && pPattern->GetStyleSheet() == pStyle )
+ pPattern->StyleToName();
+ }
+}
+
+SfxItemPool* __EXPORT ScDocumentPool::Clone() const
+{
+ return new SfxItemPool (*this, TRUE);
+}
+
+SfxItemPresentation lcl_HFPresentation
+(
+ const SfxPoolItem& rItem,
+ SfxItemPresentation ePresentation,
+ SfxMapUnit eCoreMetric,
+ SfxMapUnit ePresentationMetric,
+ String& rText,
+ const International* pIntl
+)
+{
+ const SfxItemSet& rSet = ((const SfxSetItem&)rItem).GetItemSet();
+ const SfxPoolItem* pItem;
+
+ if ( SFX_ITEM_SET == rSet.GetItemState(ATTR_PAGE_ON,FALSE,&pItem) )
+ {
+ if( FALSE == ((const SfxBoolItem*)pItem)->GetValue() )
+ return SFX_ITEM_PRESENTATION_NONE;
+ }
+
+ SfxItemIter aIter( rSet );
+ pItem = aIter.FirstItem();
+ String aText;
+ String aDel = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM( " + " ));
+
+ while( pItem )
+ {
+ USHORT nWhich = pItem->Which();
+
+ aText.Erase();
+
+ switch( nWhich )
+ {
+ case ATTR_PAGE_ON:
+ case ATTR_PAGE_DYNAMIC:
+ case ATTR_PAGE_SHARED:
+ break;
+
+ case ATTR_LRSPACE:
+ {
+ SvxLRSpaceItem& rLRItem = (SvxLRSpaceItem&)*pItem;
+ USHORT nPropLeftMargin = rLRItem.GetPropLeft();
+ USHORT nPropRightMargin = rLRItem.GetPropRight();
+ USHORT nLeftMargin, nRightMargin;
+ long nTmp;
+ nTmp = rLRItem.GetLeft();
+ nLeftMargin = nTmp < 0 ? 0 : USHORT(nTmp);
+ nTmp = rLRItem.GetRight();
+ nRightMargin = nTmp < 0 ? 0 : USHORT(nTmp);
+
+ aText = SVX_RESSTR(RID_SVXITEMS_LRSPACE_LEFT);
+ if ( 100 != nPropLeftMargin )
+ {
+ aText += String::CreateFromInt32( nPropLeftMargin );
+ aText += '%';
+ }
+ else
+ {
+ aText += GetMetricText( (long)nLeftMargin,
+ eCoreMetric, ePresentationMetric );
+ aText += SVX_RESSTR(GetMetricId(ePresentationMetric));
+ }
+ aText += cpDelim;
+
+ // nPropFirstLineOfst haben wir nicht
+
+ aText += SVX_RESSTR(RID_SVXITEMS_LRSPACE_RIGHT);
+ if ( 100 != nPropRightMargin )
+ {
+ aText += String::CreateFromInt32( nPropRightMargin );
+ aText += '%';
+ }
+ else
+ {
+ aText += GetMetricText( (long)nRightMargin,
+ eCoreMetric, ePresentationMetric );
+ aText += SVX_RESSTR(GetMetricId(ePresentationMetric));
+ }
+ }
+ break;
+
+ default:
+ if ( !pIntl )
+ pIntl = ScGlobal::pScInternational;
+ pItem->GetPresentation( ePresentation, eCoreMetric, ePresentationMetric, aText, pIntl );
+
+ }
+
+ if ( aText.Len() )
+ {
+ rText += aText;
+ rText += aDel;
+ }
+
+ pItem = aIter.NextItem();
+ }
+
+ rText.EraseTrailingChars();
+ rText.EraseTrailingChars( '+' );
+ rText.EraseTrailingChars();
+
+ return ePresentation;
+}
+
+SfxItemPresentation __EXPORT ScDocumentPool::GetPresentation(
+ const SfxPoolItem& rItem,
+ SfxItemPresentation ePresentation,
+ SfxMapUnit ePresentationMetric,
+ String& rText,
+ const International* pIntl ) const
+{
+ USHORT nW = rItem.Which();
+ String aStrYes ( ScGlobal::GetRscString(STR_YES) );
+ String aStrNo ( ScGlobal::GetRscString(STR_NO) );
+ String aStrSep = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(": "));
+
+ switch( nW )
+ {
+ case ATTR_PAGE_TOPDOWN:
+ switch ( ePresentation )
+ {
+ case SFX_ITEM_PRESENTATION_COMPLETE:
+ rText = ScGlobal::GetRscString(STR_SCATTR_PAGE_PRINTDIR);
+ rText += aStrSep;
+// break; // DURCHFALLEN!!!
+ case SFX_ITEM_PRESENTATION_NAMELESS:
+ rText += ((const SfxBoolItem&)rItem).GetValue() ?
+ ScGlobal::GetRscString(STR_SCATTR_PAGE_TOPDOWN) :
+ ScGlobal::GetRscString(STR_SCATTR_PAGE_LEFTRIGHT) ;
+ break;
+ }
+ break;
+
+ case ATTR_PAGE_HEADERS:
+ switch ( ePresentation )
+ {
+ case SFX_ITEM_PRESENTATION_COMPLETE:
+ rText = ScGlobal::GetRscString(STR_SCATTR_PAGE_HEADERS);
+ rText += aStrSep;
+// break; // DURCHFALLEN!!!
+ case SFX_ITEM_PRESENTATION_NAMELESS:
+ rText += ((const SfxBoolItem&)rItem).GetValue() ? aStrYes : aStrNo ;
+ break;
+ }
+ break;
+
+ case ATTR_PAGE_NULLVALS:
+ switch ( ePresentation )
+ {
+ case SFX_ITEM_PRESENTATION_COMPLETE:
+ rText = ScGlobal::GetRscString(STR_SCATTR_PAGE_NULLVALS);
+ rText += aStrSep;
+// break; // DURCHFALLEN!!!
+ case SFX_ITEM_PRESENTATION_NAMELESS:
+ rText += ((const SfxBoolItem&)rItem).GetValue() ? aStrYes : aStrNo ;
+ break;
+ }
+ break;
+
+ case ATTR_PAGE_FORMULAS:
+ switch ( ePresentation )
+ {
+ case SFX_ITEM_PRESENTATION_COMPLETE:
+ rText = ScGlobal::GetRscString(STR_SCATTR_PAGE_NULLVALS);
+ rText += aStrSep;
+// break; // DURCHFALLEN!!!
+ case SFX_ITEM_PRESENTATION_NAMELESS:
+ rText += ((const SfxBoolItem&)rItem).GetValue() ? aStrYes : aStrNo ;
+ break;
+ }
+ break;
+
+ case ATTR_PAGE_NOTES:
+ switch ( ePresentation )
+ {
+ case SFX_ITEM_PRESENTATION_COMPLETE:
+ rText = ScGlobal::GetRscString(STR_SCATTR_PAGE_NOTES);
+ rText += aStrSep;
+// break; // DURCHFALLEN!!!
+ case SFX_ITEM_PRESENTATION_NAMELESS:
+ rText += ((const SfxBoolItem&)rItem).GetValue() ? aStrYes : aStrNo ;
+ break;
+ }
+ break;
+
+ case ATTR_PAGE_GRID:
+ switch ( ePresentation )
+ {
+ case SFX_ITEM_PRESENTATION_COMPLETE:
+ rText = ScGlobal::GetRscString(STR_SCATTR_PAGE_GRID);
+ rText += aStrSep;
+// break; // DURCHFALLEN!!!
+ case SFX_ITEM_PRESENTATION_NAMELESS:
+ rText += ((const SfxBoolItem&)rItem).GetValue() ? aStrYes : aStrNo ;
+ break;
+ }
+ break;
+
+ case ATTR_PAGE_SCALETOPAGES:
+ {
+ USHORT nPagNo = ((const SfxUInt16Item&)rItem).GetValue();
+
+ if( nPagNo )
+ {
+ switch ( ePresentation )
+ {
+ case SFX_ITEM_PRESENTATION_COMPLETE:
+ rText = ScGlobal::GetRscString(STR_SCATTR_PAGE_SCALETOPAGES);
+ rText += aStrSep;
+// break; // DURCHFALLEN!!!
+ case SFX_ITEM_PRESENTATION_NAMELESS:
+ rText += String::CreateFromInt32( nPagNo );
+ break;
+ }
+ }
+ else
+ {
+ ePresentation = SFX_ITEM_PRESENTATION_NONE;
+ }
+ }
+ break;
+
+ case ATTR_PAGE_FIRSTPAGENO:
+ {
+ USHORT nPagNo = ((const SfxUInt16Item&)rItem).GetValue();
+
+ if( nPagNo )
+ {
+ switch ( ePresentation )
+ {
+ case SFX_ITEM_PRESENTATION_COMPLETE:
+ rText = ScGlobal::GetRscString(STR_SCATTR_PAGE_FIRSTPAGENO);
+ rText += aStrSep;
+// break; // DURCHFALLEN!!!
+ case SFX_ITEM_PRESENTATION_NAMELESS:
+ rText += String::CreateFromInt32( nPagNo );
+ break;
+ }
+ }
+ else
+ {
+ ePresentation = SFX_ITEM_PRESENTATION_NONE;
+ }
+ }
+ break;
+
+ case ATTR_PAGE_SCALE:
+ {
+ USHORT nPercent = ((const SfxUInt16Item&)rItem).GetValue();
+
+ if( nPercent )
+ {
+ switch ( ePresentation )
+ {
+ case SFX_ITEM_PRESENTATION_COMPLETE:
+ rText = ScGlobal::GetRscString(STR_SCATTR_PAGE_SCALE);
+ rText += aStrSep;
+// break; // DURCHFALLEN!!!
+ case SFX_ITEM_PRESENTATION_NAMELESS:
+ rText += String::CreateFromInt32( nPercent );
+ rText += '%';
+ break;
+ }
+ }
+ else
+ {
+ ePresentation = SFX_ITEM_PRESENTATION_NONE;
+ }
+ }
+ break;
+
+ case ATTR_PAGE_HEADERSET:
+ {
+ String aBuffer;
+
+ if( lcl_HFPresentation( rItem, ePresentation, GetMetric( nW ), ePresentationMetric, aBuffer, pIntl ) != SFX_ITEM_PRESENTATION_NONE )
+ {
+ rText = ScGlobal::GetRscString(STR_HEADER);
+ rText.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " ( " ));
+ rText += aBuffer;
+ rText.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " ) " ));
+ }
+ }
+ break;
+
+ case ATTR_PAGE_FOOTERSET:
+ {
+ String aBuffer;
+
+ if( lcl_HFPresentation( rItem, ePresentation, GetMetric( nW ), ePresentationMetric, aBuffer, pIntl ) != SFX_ITEM_PRESENTATION_NONE )
+ {
+ rText = ScGlobal::GetRscString(STR_FOOTER);
+ rText.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " ( " ));
+ rText += aBuffer;
+ rText.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " ) " ));
+ }
+ }
+ break;
+
+/*
+ case ATTR_PAGE_HEADERLEFT:
+ rText = "SID_SCATTR_PAGE_HEADERLEFT";
+ break;
+
+ case ATTR_PAGE_FOOTERLEFT:
+ rText = "SID_SCATTR_PAGE_FOOTERLEFT";
+ break;
+
+ case ATTR_PAGE_HEADERRIGHT:
+ rText = "SID_SCATTR_PAGE_HEADERRIGHT";
+ break;
+
+ case ATTR_PAGE_FOOTERRIGHT:
+ rText = "SID_SCATTR_PAGE_FOOTERRIGHT";
+ break;
+*/
+
+ default:
+ if ( !pIntl )
+ pIntl = ScGlobal::pScInternational;
+ ePresentation = rItem.GetPresentation( ePresentation, GetMetric( nW ), ePresentationMetric, rText, pIntl );
+ break;
+ }
+
+ return ePresentation;
+}
+
+SfxMapUnit __EXPORT ScDocumentPool::GetMetric( USHORT nWhich ) const
+{
+ // eigene Attribute: Twips, alles andere 1/100 mm
+
+ if ( nWhich >= ATTR_STARTINDEX && nWhich <= ATTR_ENDINDEX )
+ return SFX_MAPUNIT_TWIP;
+ else
+ return SFX_MAPUNIT_100TH_MM;
+}
+
+
+
+
+
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
new file mode 100644
index 000000000000..8940a421c26e
--- /dev/null
+++ b/sc/source/core/data/documen2.cxx
@@ -0,0 +1,1812 @@
+/*************************************************************************
+ *
+ * $RCSfile: documen2.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#define _BIGINT_HXX
+#define _SFXMULTISEL_HXX
+//#define _STACK_HXX
+//#define _QUEUE_HXX
+#define _DYNARR_HXX
+#define _TREELIST_HXX
+#define _CACHESTR_HXX
+#define _NEW_HXX
+//#define _SHL_HXX ***
+//#define _LINK_HXX ***
+//#define _ERRCODE_HXX ***
+//#define _GEN_HXX ***
+//#define _FRACT_HXX ***
+//#define _STRING_HXX ***
+//#define _MTF_HXX ***
+//#define _CONTNR_HXX ***
+//#define _LIST_HXX ***
+//#define _TABLE_HXX ***
+#define _DYNARY_HXX
+//#define _UNQIDX_HXX ***
+//#define _SVMEMPOOL_HXX ***
+//#define _UNQID_HXX ***
+//#define _DEBUG_HXX ***
+//#define _DATE_HXX ***
+//#define _TIME_HXX ***
+//#define _DATETIME_HXX ***
+//#define _INTN_HXX ***
+//#define _WLDCRD_HXX ***
+//#define _FSYS_HXX ***
+//#define _STREAM_HXX ***
+#define _CACHESTR_HXX
+#define _SV_MULTISEL_HXX
+
+
+
+#define _SV_NOXSOUND
+
+#define _BASDLG_HXX
+#define _CACHESTR_HXX
+#define _CTRLTOOL_HXX
+#define _DLGCFG_HXX
+#define _EXTATTR_HXX
+#define _FILDLG_HXX
+#define _FRM3D_HXX
+#define _INTRO_HXX
+#define _ISETBWR_HXX
+#define _NO_SVRTF_PARSER_HXX
+#define _MACRODLG_HXX
+#define _MODALDLG_HXX
+#define _MOREBUTTON_HXX
+#define _OUTLINER_HXX
+#define _PASSWD_HXX
+//#define _QUEUE_HXX
+#define _RULER_HXX
+#define _SCRWIN_HXX
+#define _SETBRW_HXX
+#define _STATUS_HXX
+#define _STDMENU_HXX
+#define _TABBAR_HXX
+#define _RULER_HXX
+#define _SCRWIN_HXX
+#define _SELENG_HXX
+#define _SETBRW_HXX
+#define _SOUND_HXX
+#define _STATUS_HXX
+#define _STDMENU_HXX
+
+
+//#define _PRNDLG_HXX ***
+//#define _POLY_HXX **
+// TOOLS
+#define _BIGINT_HXX
+#define _SFXMULTISEL_HXX
+//#define _STACK_HXX
+//#define _QUEUE_HXX
+#define _DYNARR_HXX
+#define _TREELIST_HXX
+#define _CACHESTR_HXX
+
+//SV
+//#define _CLIP_HXX
+#define _CONFIG_HXX
+#define _CURSOR_HXX
+#define _FONTDLG_HXX
+#define _PRVWIN_HXX
+
+#ifndef OS2
+#define _MENUBTN_HXX
+#endif
+
+//#define _SOBASE_HXX
+//#define _SOSTOR_HXX
+//#define _SOCORE_HXX
+//#define _SOINPL_HXX
+
+#define _SFX_DOCFILE_HXX
+#define _SFX_DOCFILT_HXX
+#define _SFX_DOCINF_HXX
+#define _SFX_DOCSH_HXX
+#define _SFX_INTERNO_HXX
+#define _SFX_PRNMON_HXX
+#define _SFX_RESMGR_HXX
+#define _SFX_TEMPLDLG_HXX
+#define _SFXAPPWIN_HXX
+#define _SFXBASIC_HXX
+#define _SFXCTRLITEM
+#define _SFXDLGCFG_HXX
+#define _SFXDISPATCH_HXX
+#define _SFXDOCFILE_HXX
+#define _SFXDOCMAN_HXX
+#define _SFXDOCMGR_HXX
+#define _SFXDOCTDLG_HXX
+#define _SFXFILEDLG_HXX
+#define _SFXIMGMGR_HXX
+#define _SFXIPFRM_HXX
+#define _SFX_MACRO_HXX
+#define _SFXMNUITEM_HXX
+#define _SFXMNUMGR_HXX
+#define _SFXMULTISEL_HXX
+//#define _SFXMSG_HXX
+#define _SFXMSGDESCR_HXX
+#define _SFXMSGPOOL_HXX
+#define _SFX_MINFITEM_HXX
+#define _SFXOBJFACE_HXX
+#define _SFXOBJFAC_HXX
+#define _SFX_SAVEOPT_HXX
+#define _SFXSTBITEM_HXX
+#define _SFXSTBMGR_HXX
+#define _SFXTBXCTRL_HXX
+#define _SFXTBXMGR_HXX
+
+//#define _SI_HXX
+//#define SI_NODRW
+#define _SI_DLL_HXX
+#define _SIDLL_HXX
+#define _SI_NOITEMS
+#define _SI_NOOTHERFORMS
+#define _SI_NOSBXCONTROLS
+#define _SINOSBXCONTROLS
+#define _SI_NODRW //
+#define _SI_NOCONTROL
+#define _VCBRW_HXX
+#define _VCTRLS_HXX
+//#define _VCSBX_HXX
+#define _VCONT_HXX
+#define _VDRWOBJ_HXX
+#define _VCATTR_HXX
+
+
+#define _SVBOXITM_HXX
+#define _SVCONTNR_HXX
+#define _SVDIALDLL_HXX
+//#define _SVDATTR_HXX
+#define _SVDRAG_HXX
+#define _SVDXOUT_HXX
+#define _SVDEC_HXX
+#define _SVDIO_HXX
+//#define _SVDLAYER_HXX
+#define _SVINCVW_HXX
+#define _SV_MULTISEL_HXX
+#define _SVRTV_HXX
+#define _SVTABBX_HXX
+#define _SVTREEBOX_HXX
+#define _SVTREELIST_HXX
+
+#define _SVX_DAILDLL_HXX
+#define _SVX_HYPHEN_HXX
+#define _SVX_IMPGRF_HXX
+#define _SVX_OPTITEMS_HXX
+#define _SVX_OPTGERL_HXX
+#define _SVX_OPTSAVE_HXX
+#define _SVX_OPTSPELL_HXX
+#define _SVX_OPTPATH_HXX
+#define _SVX_OPTLINGU_HXX
+#define _SVX_RULER_HXX
+#define _SVX_RULRITEM_HXX
+#define _SVX_SPLWRAP_HXX
+#define _SVX_SPLDLG_HXX
+#define _SVX_THESDLG_HXX
+
+
+// INCLUDE ---------------------------------------------------------------
+
+#define _ZFORLIST_DECLARE_TABLE
+#include "scitems.hxx"
+
+#include <svx/editeng.hxx>
+#include <svx/langitem.hxx>
+#include <svx/linkmgr.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/printer.hxx>
+#include <svtools/zforlist.hxx>
+#include <svtools/zformat.hxx>
+#include <vcl/system.hxx>
+
+#include "document.hxx"
+#include "table.hxx"
+#include "attrib.hxx"
+#include "patattr.hxx"
+#include "rangenam.hxx"
+#include "dbcolect.hxx"
+#include "pivot.hxx"
+#include "docpool.hxx"
+#include "stlpool.hxx"
+#include "stlsheet.hxx"
+#include "globstr.hrc"
+#include "chartarr.hxx"
+#include "rechead.hxx"
+#include "global.hxx"
+#include "brdcst.hxx"
+#include "bcaslot.hxx"
+#include "adiasync.hxx"
+#include "addinlis.hxx"
+#include "chartlis.hxx"
+#include "markdata.hxx"
+#include "conditio.hxx"
+#include "validat.hxx"
+#include "progress.hxx"
+#include "detdata.hxx"
+#include "sc.hrc" // FID_DATACHANGED
+#include "ddelink.hxx"
+#include "chgtrack.hxx"
+#include "chgviset.hxx"
+#include "editutil.hxx"
+#include "hints.hxx"
+#include "dpobject.hxx"
+#include "indexmap.hxx"
+
+// STATIC DATA -----------------------------------------------------------
+
+ScDocument::ScDocument( ScDocumentMode eMode,
+ SfxObjectShell* pDocShell ) :
+ pDrawLayer( NULL ),
+ pColorTable( NULL ),
+ bOwner( FALSE ),
+ pDocPool( NULL ),
+ pStylePool( NULL ),
+ pFormTable( NULL ),
+ pShell( pDocShell ),
+ pPrinter( NULL ),
+ bAutoCalc( eMode == SCDOCMODE_DOCUMENT ),
+ bAutoCalcShellDisabled( FALSE ),
+ bForcedFormulaPending( FALSE ),
+ bIsUndo( eMode == SCDOCMODE_UNDO ),
+ bIsClip( eMode == SCDOCMODE_CLIP ),
+ bCutMode( FALSE ),
+ nMaxTableNumber( 0 ),
+ pCondFormList( NULL ),
+ pValidationList( NULL ),
+ pFormatExchangeList( NULL ),
+ bIsEmbedded( FALSE ),
+ bProtected( FALSE ),
+ pLinkManager( NULL ),
+ pDocOptions( NULL ),
+ pViewOptions( NULL ),
+ pExtDocOptions( NULL ),
+ pConsolidateDlgData( NULL ),
+ pFormulaTree( NULL ),
+ pEOFormulaTree( NULL ),
+ aCurTextWidthCalcPos(MAXCOL,0,0),
+// bNoSetDirty( TRUE ),
+ bNoSetDirty( FALSE ),
+ pFormulaTrack( NULL ),
+ pEOFormulaTrack( NULL ),
+ nFormulaTrackCount(0),
+ bInsertingFromOtherDoc( FALSE ),
+ bImportingXML( FALSE ),
+ nHardRecalcState(0),
+ bCalcingAfterLoad( FALSE ),
+ bNoListening( FALSE ),
+ bLoadingDone( TRUE ),
+ nVisibleTab( 0 ),
+ bIdleDisabled( FALSE ),
+ bInLinkUpdate( FALSE ),
+ bDetectiveDirty( FALSE ),
+ nMacroCallMode( SC_MACROCALL_ALLOWED ),
+ bHasMacroFunc( FALSE ),
+ bChartListenerCollectionNeedsUpdate( FALSE ),
+ bHasForcedFormulas( FALSE ),
+ nVisSpellState( 0 ),
+ pClipData( NULL ),
+ nFormulaCodeInTree(0),
+ nInterpretLevel(0),
+ nMacroInterpretLevel(0),
+ bLostData(FALSE),
+ pDetOpList(NULL),
+ bInDtorClear( FALSE ),
+ bExpandRefs( FALSE ),
+ pUnoBroadcaster( NULL ),
+ pChangeTrack( NULL ),
+ pChangeViewSettings( NULL ),
+ pEditPool( NULL ),
+ pEnginePool( NULL ),
+ pEditEngine( NULL ),
+ eLinkMode(LM_UNKNOWN),
+ pDPCollection( NULL )
+{
+ eSrcSet = gsl_getSystemTextEncoding();
+ nSrcVer = SC_CURRENT_VERSION;
+ nSrcMaxRow = MAXROW;
+
+ if ( eMode == SCDOCMODE_DOCUMENT )
+ {
+ if ( pDocShell )
+ pLinkManager = new SvxLinkManager( pDocShell );
+
+ bOwner = TRUE;
+ pDocPool = new ScDocumentPool;
+ pDocPool->FreezeIdRanges();
+ pStylePool = new ScStyleSheetPool( *pDocPool, this );
+ pFormTable = new SvNumberFormatter( ScGlobal::eLnge );
+ aColorLink = LINK(this, ScDocument, GetUserDefinedColor);
+ pFormTable->SetColorLink(&aColorLink);
+ pFormTable->SetEvalDateFormat( NF_EVALDATEFORMAT_INTL_FORMAT );
+ pTab[0] = NULL;
+ pBASM = new ScBroadcastAreaSlotMachine( this );
+ pChartListenerCollection = new ScChartListenerCollection( this );
+ pEditPool = EditEngine::CreatePool();
+ pEditPool->SetDefaultMetric( SFX_MAPUNIT_100TH_MM );
+ pEditPool->FreezeIdRanges();
+ pEnginePool = EditEngine::CreatePool();
+ pEnginePool->SetDefaultMetric( SFX_MAPUNIT_100TH_MM );
+ pEnginePool->FreezeIdRanges();
+ }
+ else
+ {
+ pDrawLayer = NULL;
+ bOwner = FALSE;
+ pDocPool = NULL;
+ pStylePool = NULL;
+ pFormTable = NULL;
+ pTab[0] = NULL;
+ pBASM = NULL;
+ pChartListenerCollection = NULL;
+ pEditPool = NULL;
+ pEnginePool = NULL;
+ }
+
+ for (USHORT i=1; i<=MAXTAB; i++)
+ pTab[i] = NULL;
+
+ pRangeName = new ScRangeName( 4, 4, FALSE, this );
+ pDBCollection = new ScDBCollection( 4, 4, FALSE, this );
+ pPivotCollection = new ScPivotCollection(4, 4, this );
+ pSelectionAttr = NULL;
+ pChartCollection = new ScChartCollection;
+ xColNameRanges = new ScRangePairList;
+ xRowNameRanges = new ScRangePairList;
+ ImplCreateOptions();
+ SetLanguage( ScGlobal::eLnge );
+
+ aTrackTimer.SetTimeoutHdl( LINK( this, ScDocument, TrackTimeHdl ) );
+ aTrackTimer.SetTimeout( 100 );
+}
+
+void ScDocument::StartChangeTracking()
+{
+ if (!pChangeTrack)
+ pChangeTrack = new ScChangeTrack( this );
+}
+
+void ScDocument::EndChangeTracking()
+{
+ delete pChangeTrack;
+ pChangeTrack = NULL;
+}
+
+IMPL_LINK( ScDocument, TrackTimeHdl, Timer*, pTimer )
+{
+ if ( ScDdeLink::IsInUpdate() ) // nicht verschachteln
+ {
+ aTrackTimer.Start(); // spaeter nochmal versuchen
+ }
+ else if (pShell) // ausfuehren
+ {
+ TrackFormulas();
+ pShell->Broadcast( SfxSimpleHint( FID_DATACHANGED ) );
+ ResetChanged( ScRange(0,0,0,MAXCOL,MAXROW,MAXTAB) );
+
+ // modified...
+
+ if (!pShell->IsModified())
+ {
+ pShell->SetModified( TRUE );
+ SfxBindings& rBind = SFX_BINDINGS();
+ rBind.Invalidate( SID_SAVEDOC );
+ rBind.Invalidate( SID_DOC_MODIFIED );
+ }
+ }
+
+ return 0;
+}
+
+void ScDocument::StartTrackTimer()
+{
+ if (!aTrackTimer.IsActive()) // nicht ewig aufschieben
+ aTrackTimer.Start();
+}
+
+ScDocument::~ScDocument()
+{
+ DBG_ASSERT( !bInLinkUpdate, "bInLinkUpdate in dtor" );
+
+ bInDtorClear = TRUE;
+
+ // Links aufrauemen
+
+ if ( pLinkManager )
+ {
+ // BaseLinks freigeben
+ for ( USHORT n = pLinkManager->GetServers().Count(); n; )
+ ( (SvPseudoObject*) pLinkManager->GetServers()[ --n ])->Closed();
+
+ if ( pLinkManager->GetLinks().Count() )
+ pLinkManager->Remove( 0, pLinkManager->GetLinks().Count() );
+ }
+
+ ScAddInAsync::RemoveDocument( this );
+ ScAddInListener::RemoveDocument( this );
+ delete pChartListenerCollection; // vor pBASM wg. evtl. Listener!
+ pChartListenerCollection = NULL;
+ // BroadcastAreas vor allen Zellen zerstoeren um unnoetige
+ // Einzel-EndListenings der Formelzellen zu vermeiden
+ delete pBASM; // BroadcastAreaSlotMachine
+ pBASM = NULL;
+
+ if (pUnoBroadcaster)
+ {
+ delete pUnoBroadcaster; // broadcasted nochmal SFX_HINT_DYING
+ pUnoBroadcaster = NULL;
+ }
+
+ Clear();
+
+ if (pCondFormList)
+ {
+ pCondFormList->DeleteAndDestroy( 0, pCondFormList->Count() );
+ DELETEZ(pCondFormList);
+ }
+ if (pValidationList)
+ {
+ pValidationList->DeleteAndDestroy( 0, pValidationList->Count() );
+ DELETEZ(pValidationList);
+ }
+ delete pRangeName;
+ delete pDBCollection;
+ delete pPivotCollection;
+ delete pSelectionAttr;
+ delete pChartCollection;
+// delete pDrawLayer;
+ DeleteDrawLayer();
+ delete pFormatExchangeList;
+ delete pPrinter;
+ ImplDeleteOptions();
+ delete pConsolidateDlgData;
+ delete pLinkManager;
+ delete pClipData;
+ delete pDetOpList; // loescht auch die Eintraege
+ delete pChangeTrack;
+ delete pEditEngine;
+ delete pChangeViewSettings; // und weg damit
+
+ delete pDPCollection;
+
+ if (bOwner)
+ {
+ BOOL bDoDelete = FALSE;
+ if (bIsClip)
+ bDoDelete = TRUE;
+ else
+ {
+ ScDocument* pClipDoc = NULL;
+ if (ScGlobal::HasClipDoc()) // GetClipDoc legt das ClipDoc an
+ pClipDoc = ScGlobal::GetClipDoc();
+ if (pClipDoc && pClipDoc->pDocPool == pDocPool)
+ {
+ pClipDoc->bOwner = TRUE;
+ pStylePool->SetDocument(pClipDoc); // #67178# don't keep old document pointer
+ }
+ else
+ bDoDelete = TRUE;
+ }
+
+ if (bDoDelete)
+ {
+ delete pStylePool;
+ delete pDocPool;
+ delete pFormTable;
+ delete pEditPool;
+ delete pEnginePool;
+ }
+ }
+
+// delete pColorTable;
+ DeleteColorTable();
+}
+
+void ScDocument::InitClipPtrs( ScDocument* pSourceDoc )
+{
+ DBG_ASSERT(bIsClip, "InitClipPtrs und nicht bIsClip");
+
+ if (pCondFormList)
+ {
+ pCondFormList->DeleteAndDestroy( 0, pCondFormList->Count() );
+ DELETEZ(pCondFormList);
+ }
+ if (pValidationList)
+ {
+ pValidationList->DeleteAndDestroy( 0, pValidationList->Count() );
+ DELETEZ(pValidationList);
+ }
+
+ Clear();
+ if (bOwner)
+ {
+ delete pStylePool;
+ delete pDocPool;
+ delete pFormTable;
+ delete pEditPool;
+ delete pEnginePool;
+ }
+ bOwner = FALSE;
+ pDocPool = pSourceDoc->pDocPool;
+ pStylePool = pSourceDoc->pStylePool;
+ pFormTable = pSourceDoc->pFormTable;
+ pEditPool = pSourceDoc->pEditPool;
+ pEnginePool = pSourceDoc->pEnginePool;
+
+ // bedingte Formate / Gueltigkeiten
+ //! Vorlagen kopieren?
+ const ScConditionalFormatList* pSourceCond = pSourceDoc->pCondFormList;
+ if ( pSourceCond )
+ pCondFormList = new ScConditionalFormatList(this, *pSourceCond);
+ const ScValidationDataList* pSourceValid = pSourceDoc->pValidationList;
+ if ( pSourceValid )
+ pValidationList = new ScValidationDataList(this, *pSourceValid);
+
+ // Links in Stream speichern
+ delete pClipData;
+ if (pSourceDoc->HasDdeLinks())
+ {
+ pClipData = new SvMemoryStream;
+ pSourceDoc->SaveDdeLinks(*pClipData);
+ }
+ else
+ pClipData = NULL;
+}
+
+ScFieldEditEngine& ScDocument::GetEditEngine()
+{
+ if ( !pEditEngine )
+ {
+ pEditEngine = new ScFieldEditEngine( GetEditPool() );
+ pEditEngine->SetUpdateMode( FALSE );
+ pEditEngine->EnableUndo( FALSE );
+ pEditEngine->SetRefMapMode( MAP_100TH_MM );
+ }
+ return *pEditEngine;
+}
+
+void ScDocument::ResetClip( ScDocument* pSourceDoc, const ScMarkData* pMarks )
+{
+ if (bIsClip)
+ {
+ InitClipPtrs(pSourceDoc);
+
+ for (USHORT i = 0; i <= MAXTAB; i++)
+ if (pSourceDoc->pTab[i])
+ if (!pMarks || pMarks->GetTableSelect(i))
+ {
+ String aString;
+ pSourceDoc->pTab[i]->GetName(aString);
+ pTab[i] = new ScTable(this, i, aString);
+ nMaxTableNumber = i+1;
+ }
+ }
+ else
+ DBG_ERROR("ResetClip");
+}
+
+void ScDocument::ResetClip( ScDocument* pSourceDoc, USHORT nTab )
+{
+ if (bIsClip)
+ {
+ InitClipPtrs(pSourceDoc);
+
+ pTab[nTab] = new ScTable(this, nTab,
+ String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("baeh")));
+ nMaxTableNumber = nTab+1;
+ }
+ else
+ DBG_ERROR("ResetClip");
+}
+
+void lcl_RefreshPivotData( ScPivotCollection* pColl )
+{
+ USHORT nCount = pColl->GetCount();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScPivot* pPivot = (*pColl)[i];
+ if (pPivot->CreateData(TRUE))
+ pPivot->ReleaseData();
+ }
+}
+
+void lcl_AddLanguage( SfxItemSet& rSet, SvNumberFormatter& rFormatter )
+{
+ // Sprache dann dazutueten, wenn ein Zahlformat mit einer anderen Sprache
+ // als im Parent (incl. Default) hart eingestellt ist
+
+ DBG_ASSERT(rSet.GetItemState(ATTR_LANGUAGE_FORMAT,FALSE)==SFX_ITEM_DEFAULT,
+ "AddLanguage: Sprache ist schon da ?!??!");
+
+ const SfxPoolItem* pHardItem;
+ if ( rSet.GetItemState( ATTR_VALUE_FORMAT, FALSE, &pHardItem ) == SFX_ITEM_SET )
+ {
+ const SvNumberformat* pHardFormat = rFormatter.GetEntry(
+ ((const SfxUInt32Item*)pHardItem)->GetValue() );
+
+ ULONG nParentFmt = 0; // 0 ist Pool-Default
+ const SfxItemSet* pParent = rSet.GetParent();
+ if (pParent)
+ nParentFmt = ((const SfxUInt32Item&)pParent->Get(ATTR_VALUE_FORMAT)).GetValue();
+ const SvNumberformat* pParFormat = rFormatter.GetEntry( nParentFmt );
+
+ if ( pHardFormat && pParFormat &&
+ pHardFormat->GetLanguage() != pParFormat->GetLanguage() )
+ rSet.Put( SvxLanguageItem( pHardFormat->GetLanguage(), ATTR_LANGUAGE_FORMAT ) );
+ }
+}
+
+BOOL ScDocument::Load( SvStream& rStream, ScProgress* pProgress )
+{
+ bLoadingDone = FALSE;
+
+ //----------------------------------------------------
+
+ Clear();
+ USHORT nOldBufSize = rStream.GetBufferSize();
+ rStream.SetBufferSize( 32768 );
+
+ // Progress-Bar
+
+// ULONG nCurPos = rStream.Tell();
+// ULONG nEndPos = rStream.Seek( STREAM_SEEK_TO_END );
+// rStream.Seek( nCurPos );
+// ScProgress aProgress( NULL, ScGlobal::GetRscString(STR_LOAD_DOC), nEndPos - nCurPos );
+
+ BOOL bError = FALSE;
+ USHORT nVersion = 0;
+ USHORT nVerMaxRow = MAXROW_30; // 8191, wenn in der Datei nichts steht
+ USHORT nTab = 0;
+ USHORT nEnumDummy;
+ String aEmptyName;
+ String aPageStyle;
+ CharSet eOldSet = rStream.GetStreamCharSet();
+
+ USHORT nID;
+ rStream >> nID;
+ if (nID == SCID_DOCUMENT || nID == SCID_NEWDOCUMENT )
+ {
+ ScReadHeader aHdr( rStream );
+ while (aHdr.BytesLeft() && !bError )
+ {
+ USHORT nSubID;
+ rStream >> nSubID;
+ switch (nSubID)
+ {
+ case SCID_DOCFLAGS:
+ {
+ ScReadHeader aFlagsHdr( rStream );
+
+ rStream >> nVersion; // 312 abwaerts
+ rStream.ReadByteString( aPageStyle, rStream.GetStreamCharSet() );
+ rStream >> bProtected; // Dokument geschuetzt
+ rStream.ReadByteString( aProtectPass, rStream.GetStreamCharSet() );
+ if ( aFlagsHdr.BytesLeft() )
+ {
+ rStream >> nEnumDummy;
+ eLanguage = LanguageType( nEnumDummy );
+ }
+ if ( aFlagsHdr.BytesLeft() )
+ rStream >> bAutoCalc;
+ if ( aFlagsHdr.BytesLeft() )
+ rStream >> nVisibleTab;
+ if ( aFlagsHdr.BytesLeft() )
+ rStream >> nVersion; // echte Version
+ if ( aFlagsHdr.BytesLeft() )
+ rStream >> nVerMaxRow; // sonst auf 8191 lassen
+
+ nSrcVer = nVersion; // Member
+ nSrcMaxRow = nVerMaxRow; // Member
+
+ // Fuer Debugging bis hin zur SC 3.0a:
+ if( nVersion > 0x0002 && nVersion < SC_NUMFMT )
+ {
+ bError = TRUE;
+ rStream.SetError( SVSTREAM_WRONGVERSION );
+ }
+
+ // Das obere Byte muss kleiner oder gleich sein
+ // (3.1 Dateien mit 8192 Zeilen koennen noch gelesen werden)
+
+ if( ( nSrcVer & 0xFF00 ) > ( SC_CURRENT_VERSION & 0xFF00 ) )
+ {
+ bError = TRUE;
+ rStream.SetError( SVSTREAM_WRONGVERSION );
+ }
+ }
+ break;
+ case SCID_CHARSET:
+ {
+ ScReadHeader aSetHdr( rStream );
+ BYTE cSet, cGUI; // cGUI is dummy, old GUIType
+ rStream >> cGUI >> cSet;
+ eSrcSet = (CharSet) cSet;
+ rStream.SetStreamCharSet( eSrcSet );
+ }
+ break;
+ case SCID_LINKUPMODE: // Link Update Mode
+ {
+ ScReadHeader aSetHdr( rStream );
+ BYTE cSet;
+ rStream >> cSet;
+ eLinkMode=(ScLkUpdMode) cSet;
+ }
+ break;
+ case SCID_TABLE:
+ pTab[nTab] = new ScTable(this, nTab, aEmptyName);
+ pTab[nTab]->SetPageStyle( aPageStyle );
+ pTab[nTab]->Load(rStream,nVersion,pProgress);
+ ++nTab;
+ break;
+ case SCID_DRAWING:
+ LoadDrawLayer(rStream);
+ break;
+ case SCID_DDELINKS:
+ LoadDdeLinks(rStream);
+ break;
+ case SCID_AREALINKS:
+ LoadAreaLinks(rStream);
+ break;
+ case SCID_RANGENAME:
+ pRangeName->Load(rStream, nVersion );
+ break;
+ case SCID_DBAREAS:
+ pDBCollection->Load( rStream );
+ break;
+ case SCID_DATAPILOT:
+ GetDPCollection()->LoadNew( rStream );
+ break;
+ case SCID_PIVOT:
+ pPivotCollection->Load( rStream );
+ break;
+ case SCID_CHARTS:
+ pChartCollection->Load( this, rStream );
+ break;
+ case SCID_COLNAMERANGES:
+ xColNameRanges->Load( rStream, nVersion );
+ break;
+ case SCID_ROWNAMERANGES:
+ xRowNameRanges->Load( rStream, nVersion );
+ break;
+ case SCID_CONDFORMATS:
+ if (!pCondFormList)
+ pCondFormList = new ScConditionalFormatList;
+ pCondFormList->Load( rStream, this );
+ break;
+ case SCID_VALIDATION:
+ if (!pValidationList)
+ pValidationList = new ScValidationDataList;
+ pValidationList->Load( rStream, this );
+ break;
+ case SCID_DETOPLIST:
+ if (!pDetOpList)
+ pDetOpList = new ScDetOpList;
+ pDetOpList->Load( rStream );
+ break;
+ case SCID_NUMFORMAT:
+ {
+ ScReadHeader aNumHeader(rStream);
+ pFormTable->Load(rStream);
+ }
+ break;
+ case SCID_DOCOPTIONS:
+ ImplLoadDocOptions(rStream);
+ break;
+ case SCID_VIEWOPTIONS:
+ ImplLoadViewOptions(rStream);
+ break;
+ case SCID_PRINTSETUP:
+ {
+ ScReadHeader aJobHeader(rStream);
+ SfxItemSet* pSet = new SfxItemSet( *pDocPool,
+ SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN,
+ SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC,
+ NULL );
+ SetPrinter( SfxPrinter::Create( rStream, pSet ) );
+ }
+ break;
+ case SCID_CONSOLIDATA:
+ if (!pConsolidateDlgData)
+ pConsolidateDlgData = new ScConsolidateParam;
+ pConsolidateDlgData->Load( rStream );
+ break;
+ case SCID_CHANGETRACK:
+ if ( pChangeTrack )
+ pChangeTrack->Clear(); // es kann nur einen geben
+ else
+ StartChangeTracking();
+ pChangeTrack->Load( rStream, nVersion );
+ break;
+ case SCID_CHGVIEWSET:
+ if (!pChangeViewSettings)
+ pChangeViewSettings = new ScChangeViewSettings;
+ pChangeViewSettings->Load( rStream, nVersion );
+ break;
+ default:
+ {
+ DBG_ERROR("unbekannter Sub-Record in ScDocument::Load");
+ ScReadHeader aDummyHdr( rStream );
+ }
+ }
+
+ if (rStream.GetError() != SVSTREAM_OK)
+ bError = TRUE;
+ }
+ }
+ else
+ {
+ // Assertion nur, wenn kein Passwort gesetzt ist
+ DBG_ASSERT( rStream.GetKey().Len(), "Load: SCID_DOCUMENT nicht gefunden" );
+ bError = TRUE;
+ }
+
+ rStream.SetStreamCharSet( eOldSet );
+ rStream.SetBufferSize( nOldBufSize );
+
+ if (!bError) // Neuberechnungen
+ {
+ DBG_ASSERT( pStylePool, "Oops. No StyleSheetPool :-(" );
+
+ pStylePool->UpdateStdNames(); // falls mit Version in anderer Sprache gespeichert
+
+ // Zahlformat-Sprache
+ // (kann nicht in LoadPool passieren, weil der Numberformatter geladen sein muss)
+
+ if ( pDocPool->GetLoadingVersion() == 0 ) // 0 = Pool-Version bis 3.1
+ {
+ // in 3.1-Dokumenten gibt es ATTR_LANGUAGE_FORMAT noch nicht
+ // darum bei Bedarf zu ATTR_VALUE_FORMAT noch die Sprache dazutun
+ // (Bug #37441#)
+
+ // harte Attribute:
+
+ USHORT nCount = pDocPool->GetItemCount(ATTR_PATTERN);
+ ScPatternAttr* pPattern;
+ for (USHORT i=0; i<nCount; i++)
+ {
+ pPattern = (ScPatternAttr*)pDocPool->GetItem(ATTR_PATTERN, i);
+ if (pPattern)
+ lcl_AddLanguage( pPattern->GetItemSet(), *pFormTable );
+ }
+
+ // Vorlagen:
+
+ SfxStyleSheetIterator aIter( pStylePool, SFX_STYLE_FAMILY_PARA );
+ for ( SfxStyleSheetBase* pStyle = aIter.First(); pStyle; pStyle = aIter.Next() )
+ lcl_AddLanguage( pStyle->GetItemSet(), *pFormTable );
+ }
+
+ // Druckbereiche etc.
+
+ SfxStyleSheetIterator aIter( pStylePool, SFX_STYLE_FAMILY_PAGE );
+ ScStyleSheet* pStyleSheet = NULL;
+
+ nMaxTableNumber = 0;
+ for (USHORT i=0; i<=MAXTAB; i++)
+ if (pTab[i])
+ {
+ // MaxTableNumber ermitteln
+
+ nMaxTableNumber = i+1;
+
+ // Druckbereiche aus <= 3.00.2 Dokumenten
+ // aus den PageStyles holen und jetzt an
+ // der Tabelle speichern.
+
+ pStyleSheet = (ScStyleSheet*)aIter.Find( pTab[i]->GetPageStyle() );
+
+ if ( pStyleSheet )
+ {
+ SfxItemSet& rSet = pStyleSheet->GetItemSet();
+ const ScRangeItem* pPrintAreaItem = NULL;
+ const ScRangeItem* pRepeatColItem = NULL;
+ const ScRangeItem* pRepeatRowItem = NULL;
+
+ rSet.GetItemState( ATTR_PAGE_PRINTAREA, TRUE,
+ (const SfxPoolItem**)&pPrintAreaItem );
+ rSet.GetItemState( ATTR_PAGE_REPEATCOL, TRUE,
+ (const SfxPoolItem**)&pRepeatColItem );
+ rSet.GetItemState( ATTR_PAGE_REPEATROW, TRUE,
+ (const SfxPoolItem**)&pRepeatRowItem );
+
+ if ( pPrintAreaItem ) // Druckbereiche
+ {
+ if ( !pPrintAreaItem->GetFlags() )
+ {
+ SetPrintRangeCount( i, 1 );
+ SetPrintRange( i, 0, pPrintAreaItem->GetRange() );
+ }
+ rSet.ClearItem( ATTR_PAGE_PRINTAREA );
+ }
+
+ if ( pRepeatColItem ) // Wiederholungsspalte
+ {
+ SetRepeatColRange( i, !pRepeatColItem->GetFlags()
+ ? &pRepeatColItem->GetRange()
+ : (const ScRange *)NULL );
+ rSet.ClearItem( ATTR_PAGE_REPEATCOL );
+ }
+
+ if ( pRepeatRowItem ) // Wiederholungszeile
+ {
+ SetRepeatRowRange( i, !pRepeatRowItem->GetFlags()
+ ? &pRepeatRowItem->GetRange()
+ : (const ScRange *)NULL );
+ rSet.ClearItem( ATTR_PAGE_REPEATROW );
+ }
+ }
+ }
+
+
+ if ( pDPCollection && pDPCollection->GetCount() )
+ pPivotCollection->FreeAll();
+ else
+ {
+ lcl_RefreshPivotData( pPivotCollection );
+ GetDPCollection()->ConvertOldTables( *pPivotCollection );
+ }
+ if ( pDPCollection )
+ pDPCollection->EnsureNames(); // make sure every table has a name
+
+ SetAutoFilterFlags();
+ if (pDrawLayer)
+ UpdateAllCharts();
+#ifndef PRODUCT
+//2do: wg. #62107
+// ChartListenerCollection speichern/laden, damit nach dem Laden das Update
+// hier einmal eingespart werden kann und somit nicht mehr alle Charts
+// angefasst werden muessen. Die ChartListenerCollection muss dann zum Master
+// der Referenzen werden.
+ static BOOL bShown = 0;
+ if ( !bShown && SOFFICE_FILEFORMAT_NOW > SOFFICE_FILEFORMAT_50 )
+ {
+ bShown = 1;
+ DBG_ERRORFILE( "bei inkompatiblem FileFormat ChartListenerCollection speichern!" );
+ }
+#endif
+ UpdateChartListenerCollection();
+ if (pDrawLayer)
+ RefreshNoteFlags();
+ CalcAfterLoad();
+ }
+
+ //----------------------------------------------------
+
+ bLoadingDone = TRUE;
+
+ return !bError;
+}
+
+BOOL ScDocument::Save( SvStream& rStream, ScProgress* pProgress ) const
+{
+ ((ScDocument*)this)->bLoadingDone = FALSE; // nicht zwischendrin reinpfuschen lassen
+
+ ((ScDocument*)this)->bLostData = FALSE; // wird beim Speichern gesetzt
+
+ ((ScDocument*)this)->nSrcVer = SC_CURRENT_VERSION;
+ ((ScDocument*)this)->nSrcMaxRow = MAXROW;
+ if ( rStream.GetVersion() <= SOFFICE_FILEFORMAT_31 )
+ {
+ // 3.1 Export -> nur 8192 Zeilen schreiben, und kompatible Versionsnummer
+
+ ((ScDocument*)this)->nSrcVer = SC_31_EXPORT_VER;
+ ((ScDocument*)this)->nSrcMaxRow = MAXROW_30;
+ }
+ else if ( rStream.GetVersion() <= SOFFICE_FILEFORMAT_40 )
+ { // 4.0 Export -> kompatible Versionsnummer
+ ((ScDocument*)this)->nSrcVer = SC_40_EXPORT_VER;
+ }
+
+ USHORT i;
+ USHORT nOldBufSize = rStream.GetBufferSize();
+ rStream.SetBufferSize( 32768 );
+
+ CharSet eOldSet = rStream.GetStreamCharSet();
+ rStream.SetStreamCharSet( gsl_getSystemTextEncoding() );
+
+ // Progress-Bar
+
+ long nSavedDocCells = 0;
+// ScProgress aProgress( NULL, ScGlobal::GetRscString( STR_SAVE_DOC ), GetWeightedCount() + 1 );
+
+ {
+ rStream << (USHORT) SCID_NEWDOCUMENT;
+ ScWriteHeader aHdr( rStream );
+
+ // Flags
+
+ {
+ rStream << (USHORT) SCID_DOCFLAGS;
+ ScWriteHeader aFlagsHdr( rStream, 18 ); //! ausprobieren
+
+ // wg. Bug in 312 ScToken::RelToRelAbs mit DoubleRefs bekommt
+ // die 312er immer vorgegaukelt, dass es keine RelRefs gaebe,
+ // was auch ok ist, da immer absolut gespeichert wird und
+ // SR_RELATIVE nie zur Verwendung kam und nicht kommen darf.
+ if ( nSrcVer & 0xFF00 )
+ rStream << (USHORT) nSrcVer;
+ // hoehere Major-Version darf von 312 nicht geladen werden
+ else
+ rStream << (USHORT) (SC_RELATIVE_REFS - 1);
+
+ // dummy page style (for compatibility)
+ rStream.WriteByteString(
+ String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(STRING_STANDARD)),
+ rStream.GetStreamCharSet() );
+ rStream << bProtected; // Dokument geschuetzt
+ rStream.WriteByteString( aProtectPass, rStream.GetStreamCharSet() );
+ rStream << (USHORT) eLanguage;
+ rStream << bAutoCalc;
+
+ rStream << nVisibleTab;
+
+ // und hier jetzt die echte Versionsnummer
+ rStream << (USHORT) nSrcVer;
+
+ rStream << nSrcMaxRow; // Zeilenanzahl
+ }
+
+ // Zeichensatz
+
+ {
+ rStream << (USHORT) SCID_CHARSET;
+ ScWriteHeader aSetHdr( rStream, 2 );
+ rStream << (BYTE) 0 // dummy, old System::GetGUIType()
+ << (BYTE) ::GetStoreCharSet( gsl_getSystemTextEncoding() );
+ }
+
+ // Link Update Mode
+
+ if(eLinkMode!=LM_UNKNOWN)
+ {
+ rStream << (USHORT) SCID_LINKUPMODE;
+ ScWriteHeader aSetHdr( rStream, 1 );
+ rStream << (BYTE) eLinkMode;
+ }
+
+ rStream << (USHORT) SCID_RANGENAME;
+ pRangeName->Store( rStream );
+
+ rStream << (USHORT) SCID_DBAREAS;
+ pDBCollection->Store( rStream );
+
+ rStream << (USHORT) SCID_DDELINKS;
+ SaveDdeLinks( rStream );
+
+ rStream << (USHORT) SCID_AREALINKS;
+ SaveAreaLinks( rStream );
+
+ {
+ rStream << (USHORT) SCID_NUMFORMAT;
+ ScWriteHeader aNumHeader(rStream);
+ pFormTable->Save(rStream);
+ }
+
+ if ( xColNameRanges->Count() )
+ {
+ rStream << (USHORT) SCID_COLNAMERANGES;
+ xColNameRanges->Store( rStream );
+ }
+ if ( xRowNameRanges->Count() )
+ {
+ rStream << (USHORT) SCID_ROWNAMERANGES;
+ xRowNameRanges->Store( rStream );
+ }
+
+ if (pCondFormList)
+ pCondFormList->ResetUsed(); // wird beim Speichern der Tabellen gesetzt
+ if (pValidationList)
+ pValidationList->ResetUsed(); // wird beim Speichern der Tabellen gesetzt
+
+ // Tabellen (Daten)
+
+ for (i=0; i<=MAXTAB; i++)
+ {
+ if (pTab[i])
+ {
+ rStream << (USHORT) SCID_TABLE;
+ pTab[i]->Save(rStream, nSavedDocCells, pProgress);
+ }
+ }
+
+ // bedingte Formate / Gueltigkeit
+ // beim Speichern der Tabellen ist eingetragen worden,
+ // welche Eintraege benutzt werden
+
+ if (pCondFormList)
+ {
+ rStream << (USHORT) SCID_CONDFORMATS;
+ pCondFormList->Store(rStream);
+ }
+ if (pValidationList)
+ {
+ rStream << (USHORT) SCID_VALIDATION;
+ pValidationList->Store(rStream);
+ }
+
+ // Liste der Detektiv-Operationen (zum Aktualisieren)
+ if (pDetOpList)
+ {
+ rStream << (USHORT) SCID_DETOPLIST;
+ pDetOpList->Store(rStream);
+ }
+
+ // Drawing
+
+// if (pDrawLayer && pDrawLayer->HasObjects())
+ // auch ohne Objekte - wegen ColorTable etc.
+
+ if (pDrawLayer)
+ {
+ rStream << (USHORT) SCID_DRAWING;
+ StoreDrawLayer(rStream);
+ }
+
+ // Collections
+
+ // (new) DataPilot collection must be saved before old Pivot collection
+ // so old data can be skipped by new office
+ // not in 3.0 or 4.0 export to avoid warning messages
+
+ if ( nSrcVer > SC_40_EXPORT_VER && pDPCollection && pDPCollection->GetCount() )
+ {
+ rStream << (USHORT) SCID_DATAPILOT; // new data
+ pDPCollection->StoreNew( rStream );
+ }
+
+ rStream << (USHORT) SCID_PIVOT; // old data
+ if ( pDPCollection && pDPCollection->GetCount() )
+ pDPCollection->StoreOld( rStream );
+ else
+ pPivotCollection->Store( rStream ); // not converted or all empty
+
+ // Charts werden hier nicht mehr gespeichert, weil
+ // jedes Chart seine Daten selber speichert
+
+ DBG_ASSERT(!pChartCollection || !pChartCollection->GetCount(),
+ "wer hat da ein Chart eingetragen?");
+
+ rStream << (USHORT) SCID_DOCOPTIONS;
+ ImplSaveDocOptions(rStream);
+
+ rStream << (USHORT) SCID_VIEWOPTIONS;
+ ImplSaveViewOptions(rStream);
+
+ // Job-Setup vom Printer
+
+ if (pPrinter)
+ {
+ rStream << (USHORT) SCID_PRINTSETUP;
+ ScWriteHeader aJobHeader(rStream);
+
+ ((ScDocument*)this)->GetPrinter()->Store( rStream );
+ }
+
+ if ( nSrcVer > SC_40_EXPORT_VER ) // Das folgende nicht bei 3.0 oder 4.0 Export...
+ {
+ if (pConsolidateDlgData) // Einstellungen fuer den Konsolidieren-Dialog
+ {
+ rStream << (USHORT) SCID_CONSOLIDATA;
+ pConsolidateDlgData->Store( rStream );
+ }
+ if ( pChangeTrack )
+ {
+ rStream << (USHORT) SCID_CHANGETRACK;
+ pChangeTrack->Store( rStream );
+ }
+ if ( pChangeViewSettings )
+ {
+ rStream << (USHORT) SCID_CHGVIEWSET;
+ pChangeViewSettings->Store( rStream );
+ }
+ }
+ }
+
+ rStream.SetStreamCharSet( eOldSet );
+ rStream.SetBufferSize( nOldBufSize );
+
+ ((ScDocument*)this)->bLoadingDone = TRUE;
+
+ return ( rStream.GetError() == SVSTREAM_OK );
+}
+
+void ScDocument::SetLostData()
+{
+ bLostData = TRUE;
+}
+
+void ScDocument::DeleteNumberFormat( const ULONG* pDelKeys, ULONG nCount )
+{
+/*
+ for (ULONG i = 0; i < nCount; i++)
+ pFormTable->DeleteEntry(pDelKeys[i]);
+*/
+}
+
+void ScDocument::PutCell( USHORT nCol, USHORT nRow, USHORT nTab,
+ ScBaseCell* pCell, ULONG nFormatIndex, BOOL bForceTab )
+{
+ if (VALIDTAB(nTab))
+ {
+ if ( bForceTab && !pTab[nTab] )
+ {
+ BOOL bExtras = !bIsUndo; // Spaltenbreiten, Zeilenhoehen, Flags
+
+ pTab[nTab] = new ScTable(this, nTab,
+ String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("temp")),
+ bExtras, bExtras);
+ }
+
+ if (pTab[nTab])
+ pTab[nTab]->PutCell( nCol, nRow, nFormatIndex, pCell );
+ }
+}
+
+void ScDocument::PutCell( const ScAddress& rPos, ScBaseCell* pCell,
+ ULONG nFormatIndex, BOOL bForceTab )
+{
+ USHORT nTab = rPos.Tab();
+ if ( bForceTab && !pTab[nTab] )
+ {
+ BOOL bExtras = !bIsUndo; // Spaltenbreiten, Zeilenhoehen, Flags
+
+ pTab[nTab] = new ScTable(this, nTab,
+ String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("temp")),
+ bExtras, bExtras);
+ }
+
+ if (pTab[nTab])
+ pTab[nTab]->PutCell( rPos, nFormatIndex, pCell );
+}
+
+BOOL ScDocument::GetPrintArea( USHORT nTab, USHORT& rEndCol, USHORT& rEndRow,
+ BOOL bNotes ) const
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ {
+ BOOL bAny = pTab[nTab]->GetPrintArea( rEndCol, rEndRow, bNotes );
+ if (pDrawLayer)
+ {
+ ScRange aDrawRange(0,0,nTab, MAXCOL,MAXROW,nTab);
+ if (DrawGetPrintArea( aDrawRange, TRUE, TRUE ))
+ {
+ if (aDrawRange.aEnd.Col()>rEndCol) rEndCol=aDrawRange.aEnd.Col();
+ if (aDrawRange.aEnd.Row()>rEndRow) rEndRow=aDrawRange.aEnd.Row();
+ bAny = TRUE;
+ }
+ }
+ return bAny;
+ }
+
+ rEndCol = 0;
+ rEndRow = 0;
+ return FALSE;
+}
+
+BOOL ScDocument::GetPrintAreaHor( USHORT nTab, USHORT nStartRow, USHORT nEndRow,
+ USHORT& rEndCol, BOOL bNotes ) const
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ {
+ BOOL bAny = pTab[nTab]->GetPrintAreaHor( nStartRow, nEndRow, rEndCol, bNotes );
+ if (pDrawLayer)
+ {
+ ScRange aDrawRange(0,nStartRow,nTab, MAXCOL,nEndRow,nTab);
+ if (DrawGetPrintArea( aDrawRange, TRUE, FALSE ))
+ {
+ if (aDrawRange.aEnd.Col()>rEndCol) rEndCol=aDrawRange.aEnd.Col();
+ bAny = TRUE;
+ }
+ }
+ return bAny;
+ }
+
+ rEndCol = 0;
+ return FALSE;
+}
+
+BOOL ScDocument::GetPrintAreaVer( USHORT nTab, USHORT nStartCol, USHORT nEndCol,
+ USHORT& rEndRow, BOOL bNotes ) const
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ {
+ BOOL bAny = pTab[nTab]->GetPrintAreaVer( nStartCol, nEndCol, rEndRow, bNotes );
+ if (pDrawLayer)
+ {
+ ScRange aDrawRange(nStartCol,0,nTab, nEndCol,MAXROW,nTab);
+ if (DrawGetPrintArea( aDrawRange, FALSE, TRUE ))
+ {
+ if (aDrawRange.aEnd.Row()>rEndRow) rEndRow=aDrawRange.aEnd.Row();
+ bAny = TRUE;
+ }
+ }
+ return bAny;
+ }
+
+ rEndRow = 0;
+ return FALSE;
+}
+
+BOOL ScDocument::GetDataStart( USHORT nTab, USHORT& rStartCol, USHORT& rStartRow ) const
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ {
+ BOOL bAny = pTab[nTab]->GetDataStart( rStartCol, rStartRow );
+ if (pDrawLayer)
+ {
+ ScRange aDrawRange(0,0,nTab, MAXCOL,MAXROW,nTab);
+ if (DrawGetPrintArea( aDrawRange, TRUE, TRUE ))
+ {
+ if (aDrawRange.aStart.Col()<rStartCol) rStartCol=aDrawRange.aStart.Col();
+ if (aDrawRange.aStart.Row()<rStartRow) rStartRow=aDrawRange.aStart.Row();
+ bAny = TRUE;
+ }
+ }
+ return bAny;
+ }
+
+ rStartCol = 0;
+ rStartRow = 0;
+ return FALSE;
+}
+
+BOOL ScDocument::MoveTab( USHORT nOldPos, USHORT nNewPos )
+{
+ if (nOldPos == nNewPos) return FALSE;
+ BOOL bValid = FALSE;
+ if (VALIDTAB(nOldPos))
+ {
+ if (pTab[nOldPos])
+ {
+ USHORT nTabCount = GetTableCount();
+ if (nTabCount > 1)
+ {
+ BOOL bOldAutoCalc = GetAutoCalc();
+ SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ SetNoListening( TRUE );
+ ScProgress* pProgress = new ScProgress( GetDocumentShell(),
+ ScGlobal::GetRscString(STR_UNDO_MOVE_TAB), GetCodeCount() );
+ if (nNewPos == SC_TAB_APPEND)
+ nNewPos = nTabCount-1;
+
+ // Referenz-Updaterei
+ //! mit UpdateReference zusammenfassen!
+
+ short nDz = ((short)nNewPos) - (short)nOldPos;
+ ScRange aSourceRange( 0,0,nOldPos, MAXCOL,MAXROW,nOldPos );
+ pRangeName->UpdateTabRef(nOldPos, 3, nNewPos);
+ pDBCollection->UpdateMoveTab( nOldPos, nNewPos );
+ xColNameRanges->UpdateReference( URM_REORDER, this, aSourceRange, 0,0,nDz );
+ xRowNameRanges->UpdateReference( URM_REORDER, this, aSourceRange, 0,0,nDz );
+ if (pPivotCollection)
+ pPivotCollection->UpdateReference( URM_REORDER,
+ 0,0,nOldPos, MAXCOL,MAXROW,nOldPos, 0,0,nDz );
+ if (pDPCollection)
+ pDPCollection->UpdateReference( URM_REORDER, aSourceRange, 0,0,nDz );
+ if (pDetOpList)
+ pDetOpList->UpdateReference( this, URM_REORDER, aSourceRange, 0,0,nDz );
+ UpdateChartRef( URM_REORDER,
+ 0,0,nOldPos, MAXCOL,MAXROW,nOldPos, 0,0,nDz );
+ if ( pCondFormList )
+ pCondFormList->UpdateMoveTab( nOldPos, nNewPos );
+ if ( pUnoBroadcaster )
+ pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_REORDER,
+ aSourceRange, 0,0,nDz ) );
+
+ ScTable* pSaveTab = pTab[nOldPos];
+ USHORT i;
+ for (i = nOldPos + 1; i < nTabCount; i++)
+ pTab[i - 1] = pTab[i];
+ pTab[i-1] = NULL;
+ for (i = nTabCount - 1; i > nNewPos; i--)
+ pTab[i] = pTab[i - 1];
+ pTab[nNewPos] = pSaveTab;
+ for (i = 0; i <= MAXTAB; i++)
+ if (pTab[i])
+ pTab[i]->UpdateMoveTab( nOldPos, nNewPos, i, *pProgress );
+ delete pProgress; // freimachen fuer evtl. andere
+ for (i = 0; i <= MAXTAB; i++)
+ if (pTab[i])
+ pTab[i]->UpdateCompile();
+ SetNoListening( FALSE );
+ for (i = 0; i <= MAXTAB; i++)
+ if (pTab[i])
+ pTab[i]->StartAllListeners();
+ SetDirty();
+ SetAutoCalc( bOldAutoCalc );
+
+ if (pDrawLayer)
+ DrawMovePage( nOldPos, nNewPos );
+
+ bValid = TRUE;
+ }
+ }
+ }
+ return bValid;
+}
+
+BOOL ScDocument::CopyTab( USHORT nOldPos, USHORT nNewPos, const ScMarkData* pOnlyMarked )
+{
+ if (SC_TAB_APPEND == nNewPos ) nNewPos = nMaxTableNumber;
+ String aName;
+ GetName(nOldPos, aName);
+
+ // vorneweg testen, ob der Prefix als gueltig erkannt wird
+ // wenn nicht, nur doppelte vermeiden
+ BOOL bPrefix = ValidTabName( aName );
+ DBG_ASSERT(bPrefix, "ungueltiger Tabellenname");
+ USHORT nDummy;
+
+ CreateValidTabName(aName);
+
+ BOOL bValid;
+ if (bPrefix)
+ bValid = ( ValidNewTabName(aName) && (nMaxTableNumber <= MAXTAB) );
+ else
+ bValid = ( !GetTable( aName, nDummy ) && (nMaxTableNumber <= MAXTAB) );
+
+ BOOL bOldAutoCalc = GetAutoCalc();
+ SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ if (bValid)
+ {
+ if (nNewPos == nMaxTableNumber)
+ {
+ pTab[nMaxTableNumber] = new ScTable(this, nMaxTableNumber, aName);
+ ++nMaxTableNumber;
+ }
+ else
+ {
+ if (VALIDTAB(nNewPos) && (nNewPos < nMaxTableNumber))
+ {
+ SetNoListening( TRUE );
+
+ ScRange aRange( 0,0,nNewPos, MAXCOL,MAXROW,MAXTAB );
+ xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,1 );
+ xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,1 );
+ pRangeName->UpdateTabRef(nNewPos, 1);
+ pDBCollection->UpdateReference(
+ URM_INSDEL, 0,0,nNewPos, MAXCOL,MAXROW,MAXTAB, 0,0,1 );
+ if (pPivotCollection)
+ pPivotCollection->UpdateReference(
+ URM_INSDEL, 0,0,nNewPos, MAXCOL,MAXROW,MAXTAB, 0,0,1 );
+ if (pDPCollection)
+ pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,1 );
+ if (pDetOpList)
+ pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,1 );
+ UpdateChartRef( URM_INSDEL, 0,0,nNewPos, MAXCOL,MAXROW,MAXTAB, 0,0,1 );
+ if ( pUnoBroadcaster )
+ pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,1 ) );
+
+ USHORT i;
+ for (i = 0; i <= MAXTAB; i++)
+ if (pTab[i] && i != nOldPos)
+ pTab[i]->UpdateInsertTab(nNewPos);
+ for (i = nMaxTableNumber; i > nNewPos; i--)
+ pTab[i] = pTab[i - 1];
+ if (nNewPos <= nOldPos)
+ nOldPos++;
+ pTab[nNewPos] = new ScTable(this, nNewPos, aName);
+ ++nMaxTableNumber;
+ bValid = TRUE;
+ for (i = 0; i <= MAXTAB; i++)
+ if (pTab[i] && i != nOldPos && i != nNewPos)
+ pTab[i]->UpdateCompile();
+ SetNoListening( FALSE );
+ for (i = 0; i <= MAXTAB; i++)
+ if (pTab[i] && i != nOldPos && i != nNewPos)
+ pTab[i]->StartAllListeners();
+
+ // update conditional formats after table is inserted
+ if ( pCondFormList )
+ pCondFormList->UpdateReference( URM_INSDEL, aRange, 0,0,1 );
+ }
+ else
+ bValid = FALSE;
+ }
+ }
+ if (bValid)
+ {
+ SetNoListening( TRUE ); // noch nicht bei CopyToTable/Insert
+ pTab[nOldPos]->CopyToTable(0, 0, MAXCOL, MAXROW, IDF_ALL, (pOnlyMarked != NULL),
+ pTab[nNewPos], pOnlyMarked );
+ short nDz;
+/* if (nNewPos < nOldPos)
+ nDz = ((short)nNewPos) - (short)nOldPos + 1;
+ else
+*/ nDz = ((short)nNewPos) - (short)nOldPos;
+ pTab[nNewPos]->UpdateReference(URM_COPY, 0, 0, nNewPos , MAXCOL, MAXROW,
+ nNewPos, 0, 0, nDz, NULL);
+
+ pTab[nNewPos]->UpdateInsertTabAbs(nNewPos); // alle abs. um eins hoch!!
+ pTab[nOldPos]->UpdateInsertTab(nNewPos);
+
+ pTab[nOldPos]->UpdateCompile();
+ pTab[nNewPos]->UpdateCompile( TRUE ); // #67996# maybe already compiled in Clone, but used names need recompilation
+ SetNoListening( FALSE );
+ pTab[nOldPos]->StartAllListeners();
+ pTab[nNewPos]->StartAllListeners();
+ SetDirty();
+ SetAutoCalc( bOldAutoCalc );
+
+ if (pDrawLayer)
+ DrawCopyPage( nOldPos, nNewPos );
+
+ pTab[nNewPos]->SetPageStyle( pTab[nOldPos]->GetPageStyle() );
+ }
+ else
+ SetAutoCalc( bOldAutoCalc );
+ return bValid;
+}
+
+ULONG ScDocument::TransferTab( ScDocument* pSrcDoc, USHORT nSrcPos,
+ USHORT nDestPos, BOOL bInsertNew,
+ BOOL bResultsOnly )
+{
+ ULONG nRetVal = 1; // 0 => Fehler 1 = ok
+ // 2 => RefBox, 3 => NameBox
+ // 4 => beides
+ BOOL bValid = TRUE;
+ if (bInsertNew) // neu einfuegen
+ {
+ String aName;
+ pSrcDoc->GetName(nSrcPos, aName);
+ CreateValidTabName(aName);
+ bValid = InsertTab(nDestPos, aName);
+ }
+ else // bestehende Tabelle ersetzen
+ {
+ if (VALIDTAB(nDestPos) && pTab[nDestPos])
+ {
+ pTab[nDestPos]->DeleteArea( 0,0, MAXCOL,MAXROW, IDF_ALL );
+// ClearDrawPage(nDestPos);
+ }
+ else
+ bValid = FALSE;
+ }
+
+ if (bValid)
+ {
+ BOOL bOldAutoCalcSrc;
+ BOOL bOldAutoCalc = GetAutoCalc();
+ SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ SetNoListening( TRUE );
+ if ( bResultsOnly )
+ {
+ bOldAutoCalcSrc = pSrcDoc->GetAutoCalc();
+ pSrcDoc->SetAutoCalc( TRUE ); // falls was berechnet werden muss
+ }
+ if (pSrcDoc->pFormTable && pSrcDoc->pFormTable != pFormTable)
+ {
+ SvULONGTable* pExchangeList =
+ pFormTable->MergeFormatter(*(pSrcDoc->pFormTable));
+ if (pExchangeList->Count() > 0)
+ pFormatExchangeList = pExchangeList;
+ }
+ nDestPos = Min(nDestPos, (USHORT)(GetTableCount() - 1));
+ pSrcDoc->pTab[nSrcPos]->CopyToTable(0, 0, MAXCOL, MAXROW,
+ ( bResultsOnly ? IDF_ALL & ~IDF_FORMULA : IDF_ALL),
+ FALSE, pTab[nDestPos] );
+ pFormatExchangeList = NULL;
+ pTab[nDestPos]->SetTabNo(nDestPos);
+
+ if ( !bResultsOnly )
+ {
+ USHORT nSrcRangeNames = pSrcDoc->pRangeName->GetCount();
+ // array containing range names which might need update of indices
+ ScRangeData** pSrcRangeNames = nSrcRangeNames ? new ScRangeData* [nSrcRangeNames] : NULL;
+ // the index mapping thereof
+ ScIndexMap aSrcRangeMap( nSrcRangeNames );
+ BOOL bRangeNameReplace = FALSE;
+
+ for (USHORT i = 0; i < nSrcRangeNames; i++) //! DB-Bereiche Pivot-Bereiche auch !!!
+ {
+ ScRangeData* pSrcData = (*pSrcDoc->pRangeName)[i];
+ USHORT nOldIndex = pSrcData->GetIndex();
+ BOOL bInUse = FALSE;
+ for (USHORT j = 0; !bInUse && (j <= MAXTAB); j++)
+ {
+ if (pSrcDoc->pTab[j])
+ bInUse = pSrcDoc->pTab[j]->IsRangeNameInUse(0, 0, MAXCOL, MAXROW,
+ nOldIndex);
+ }
+ if (bInUse)
+ {
+ ScRangeData* pData = new ScRangeData( *pSrcData );
+ pData->SetDocument(this);
+ if ( pRangeName->FindIndex( pData->GetIndex() ) )
+ pData->SetIndex(0); // need new index, done in Insert
+ if (!pRangeName->Insert(pData))
+ {
+ delete pData;
+ nRetVal += 2;
+ // InfoBox :: Name doppelt
+ pSrcRangeNames[i] = NULL;
+ aSrcRangeMap.SetPair( i, nOldIndex, 0 );
+ bRangeNameReplace = TRUE;
+ }
+ else
+ {
+ pData->TransferTabRef( nSrcPos, nDestPos );
+ pSrcRangeNames[i] = pData;
+ USHORT nNewIndex = pData->GetIndex();
+ aSrcRangeMap.SetPair( i, nOldIndex, nNewIndex );
+ if ( !bRangeNameReplace )
+ bRangeNameReplace = ( nOldIndex != nNewIndex );
+ }
+ }
+ else
+ {
+ pSrcRangeNames[i] = NULL;
+ //aSrcRangeMap.SetPair( i, 0, 0 ); // not needed, defaulted
+ }
+ }
+ if ( bRangeNameReplace )
+ {
+ // first update all inserted named formulas if they contain other
+ // range names and used indices changed
+ for (USHORT i = 0; i < nSrcRangeNames; i++) //! DB-Bereiche Pivot-Bereiche auch
+ {
+ if ( pSrcRangeNames[i] )
+ pSrcRangeNames[i]->ReplaceRangeNamesInUse( aSrcRangeMap );
+ }
+ // then update the formulas, they might need the just updated range names
+ pTab[nDestPos]->ReplaceRangeNamesInUse( 0, 0, MAXCOL, MAXROW, aSrcRangeMap );
+ }
+ if ( pSrcRangeNames )
+ delete [] pSrcRangeNames;
+
+ short nDz = ((short)nDestPos) - (short)nSrcPos;
+ pTab[nDestPos]->UpdateReference(URM_COPY, 0, 0, nDestPos,
+ MAXCOL, MAXROW, nDestPos,
+ 0, 0, nDz, NULL);
+ BOOL bIsAbsRef = pTab[nDestPos]->TestTabRefAbs(nSrcPos); // eigene Ref retten
+ if (bIsAbsRef)
+ {
+ nRetVal += 1;
+ // InfoBox AbsoluteRefs sind möglicherweise nicht mehr korrekt!!
+ }
+ pTab[nDestPos]->CompileAll();
+ }
+
+ SetNoListening( FALSE );
+ if ( !bResultsOnly )
+ pTab[nDestPos]->StartAllListeners();
+ SetDirty(); // ist das wirklich dokumentweit noetig?!?
+ if ( bResultsOnly )
+ pSrcDoc->SetAutoCalc( bOldAutoCalcSrc );
+ SetAutoCalc( bOldAutoCalc );
+
+ // Drawing kopieren
+
+ if (bInsertNew)
+ TransferDrawPage( pSrcDoc, nSrcPos, nDestPos );
+ }
+ if (!bValid)
+ nRetVal = 0;
+ return nRetVal;
+}
+
+// ----------------------------------------------------------------------------
+
+void ScDocument::SetError( USHORT nCol, USHORT nRow, USHORT nTab, const USHORT nError)
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ pTab[nTab]->SetError( nCol, nRow, nError );
+}
+
+void ScDocument::EraseNonUsedSharedNames(USHORT nLevel)
+{
+ for (USHORT i = 0; i < pRangeName->GetCount(); i++)
+ {
+ ScRangeData* pRangeData = (*pRangeName)[i];
+ if (pRangeData && pRangeData->HasType(RT_SHARED))
+ {
+ String aName;
+ pRangeData->GetName(aName);
+ aName.Erase(0, 6); // !!! vgl. Table4, FillFormula !!
+ USHORT nInd = (USHORT) aName.ToInt32();
+ if (nInd <= nLevel)
+ {
+ USHORT nIndex = pRangeData->GetIndex();
+ BOOL bInUse = FALSE;
+ for (USHORT j = 0; !bInUse && (j <= MAXTAB); j++)
+ {
+ if (pTab[j])
+ bInUse = pTab[j]->IsRangeNameInUse(0, 0, MAXCOL-1, MAXROW-1,
+ nIndex);
+ }
+ if (!bInUse)
+ pRangeName->AtFree(i);
+ }
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+void ScDocument::SetConsolidateDlgData( const ScConsolidateParam* pData )
+{
+ delete pConsolidateDlgData;
+
+ if ( pData )
+ pConsolidateDlgData = new ScConsolidateParam( *pData );
+ else
+ pConsolidateDlgData = NULL;
+}
+
+void ScDocument::SetChangeViewSettings(const ScChangeViewSettings& rNew)
+{
+ if (pChangeViewSettings==NULL)
+ pChangeViewSettings = new ScChangeViewSettings;
+
+ DBG_ASSERT( pChangeViewSettings, "Oops. No ChangeViewSettings :-( by!" );
+
+ *pChangeViewSettings=rNew;
+}
+
+
+
+
+
diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx
new file mode 100644
index 000000000000..2707d02563dc
--- /dev/null
+++ b/sc/source/core/data/documen3.cxx
@@ -0,0 +1,1723 @@
+/*************************************************************************
+ *
+ * $RCSfile: documen3.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+// System - Includes -----------------------------------------------------
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#ifdef WIN
+// SFX
+#define _SFXAPPWIN_HXX
+#define _SFX_SAVEOPT_HXX
+//#define _SFX_CHILDWIN_HXX ***
+#define _SFXCTRLITEM_HXX
+#define _SFXPRNMON_HXX
+#define _INTRO_HXX
+#define _SFXMSGDESCR_HXX
+#define _SFXMSGPOOL_HXX
+#define _SFXFILEDLG_HXX
+#define _PASSWD_HXX
+#define _SFXTBXCTRL_HXX
+#define _SFXSTBITEM_HXX
+#define _SFXMNUITEM_HXX
+#define _SFXIMGMGR_HXX
+#define _SFXTBXMGR_HXX
+#define _SFXSTBMGR_HXX
+#define _SFX_MINFITEM_HXX
+#define _SFXEVENT_HXX
+
+//sfxdlg.hxx
+//#define _SFXTABDLG_HXX
+#define _BASEDLGS_HXX
+#define _SFX_DINFDLG_HXX
+#define _SFXDINFEDT_HXX
+#define _SFX_MGETEMPL_HXX
+#define _SFX_TPLPITEM_HXX
+#define _SFX_STYLEDLG_HXX
+#define _NEWSTYLE_HXX
+#define _SFXDOCTEMPL_HXX
+#define _SFXDOCTDLG_HXX
+#define _SFX_TEMPLDLG_HXX
+#define _SFXNEW_HXX
+#define _SFXDOCMAN_HXX
+//#define _SFXDOCKWIN_HXX ***
+
+//sfxdoc.hxx
+//#define _SFX_OBJSH_HXX
+//#define _SFX_CLIENTSH_HXX ***
+//#define _SFXDOCINF_HXX
+#define _SFX_OBJFAC_HXX
+#define _SFX_DOCFILT_HXX
+#define _SFXDOCFILE_HXX
+#define _VIEWFAC_HXX
+#define _SFXVIEWFRM_HXX
+//#define _SFXVIEWSH_HXX ***
+#define _MDIFRM_HXX
+#define _SFX_IPFRM_HXX
+#define _SFX_INTERNO_HXX
+
+#endif //WIN
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <svx/langitem.hxx>
+#include <svx/srchitem.hxx>
+#include <svx/linkmgr.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/objsh.hxx>
+#include <svtools/zforlist.hxx>
+
+#include "document.hxx"
+#include "attrib.hxx"
+#include "cell.hxx"
+#include "table.hxx"
+#include "rangenam.hxx"
+#include "dbcolect.hxx"
+#include "pivot.hxx"
+#include "docpool.hxx"
+#include "autoform.hxx"
+#include "rangelst.hxx"
+#include "chartarr.hxx"
+#include "refupdat.hxx"
+#include "docoptio.hxx"
+#include "viewopti.hxx"
+#include "scextopt.hxx"
+#include "brdcst.hxx"
+#include "bcaslot.hxx"
+#include "tablink.hxx"
+#include "markdata.hxx"
+#include "conditio.hxx"
+#include "dociter.hxx"
+#include "detdata.hxx"
+#include "detfunc.hxx"
+#include "scmod.hxx" // SC_MOD
+#include "inputopt.hxx" // GetExpandRefs
+#include "chartlis.hxx"
+#include "sc.hrc" // SID_LINK
+#include "hints.hxx"
+#include "dpobject.hxx"
+
+//------------------------------------------------------------------------
+
+ScRangeName* ScDocument::GetRangeName()
+{
+ return pRangeName;
+}
+
+void ScDocument::SetRangeName( ScRangeName* pNewRangeName )
+{
+ if (pRangeName)
+ delete pRangeName;
+ pRangeName = pNewRangeName;
+}
+
+ScRangeData* ScDocument::GetRangeAtCursor(USHORT nCol, USHORT nRow, USHORT nTab,
+ BOOL bStartOnly) const
+{
+ if ( pRangeName )
+ return pRangeName->GetRangeAtCursor( ScAddress( nCol, nRow, nTab ), bStartOnly );
+ else
+ return NULL;
+}
+
+ScRangeData* ScDocument::GetRangeAtBlock( const ScRange& rBlock, String* pName ) const
+{
+ ScRangeData* pData = NULL;
+ if ( pRangeName )
+ {
+ pData = pRangeName->GetRangeAtBlock( rBlock );
+ if (pData && pName)
+ *pName = pData->GetName();
+ }
+ return pData;
+}
+
+ScDBCollection* ScDocument::GetDBCollection() const
+{
+ return pDBCollection;
+}
+
+void ScDocument::SetDBCollection( ScDBCollection* pNewDBCollection )
+{
+ if (pDBCollection)
+ delete pDBCollection;
+ pDBCollection = pNewDBCollection;
+}
+
+ScDBData* ScDocument::GetDBAtCursor(USHORT nCol, USHORT nRow, USHORT nTab, BOOL bStartOnly) const
+{
+ if (pDBCollection)
+ return pDBCollection->GetDBAtCursor(nCol, nRow, nTab, bStartOnly);
+ else
+ return NULL;
+}
+
+ScDBData* ScDocument::GetDBAtArea(USHORT nTab, USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2) const
+{
+ if (pDBCollection)
+ return pDBCollection->GetDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2);
+ else
+ return NULL;
+}
+
+ScDPCollection* ScDocument::GetDPCollection()
+{
+ if (!pDPCollection)
+ pDPCollection = new ScDPCollection(this);
+ return pDPCollection;
+}
+
+ScDPObject* ScDocument::GetDPAtCursor(USHORT nCol, USHORT nRow, USHORT nTab) const
+{
+ if (!pDPCollection)
+ return NULL;
+
+ USHORT nCount = pDPCollection->GetCount();
+ ScAddress aPos( nCol, nRow, nTab );
+ for (USHORT i=0; i<nCount; i++)
+ if ( (*pDPCollection)[i]->GetOutRange().In( aPos ) )
+ return (*pDPCollection)[i];
+
+ return NULL;
+}
+
+ScPivotCollection* ScDocument::GetPivotCollection() const
+{
+ return pPivotCollection;
+}
+
+void ScDocument::SetPivotCollection(ScPivotCollection* pNewPivotCollection)
+{
+ if ( pPivotCollection && pNewPivotCollection &&
+ *pPivotCollection == *pNewPivotCollection )
+ {
+ delete pNewPivotCollection;
+ return;
+ }
+
+ if (pPivotCollection)
+ delete pPivotCollection;
+ pPivotCollection = pNewPivotCollection;
+
+ if (pPivotCollection)
+ {
+ USHORT nCount = pPivotCollection->GetCount();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScPivot* pPivot = (*pPivotCollection)[i];
+ if (pPivot->CreateData())
+ pPivot->ReleaseData();
+ }
+ }
+}
+
+ScPivot* ScDocument::GetPivotAtCursor(USHORT nCol, USHORT nRow, USHORT nTab) const
+{
+ if (pPivotCollection)
+ return pPivotCollection->GetPivotAtCursor(nCol, nRow, nTab);
+ else
+ return NULL;
+}
+
+ScChartCollection* ScDocument::GetChartCollection() const
+{
+ return pChartCollection;
+}
+
+void ScDocument::SetChartCollection(ScChartCollection* pNewChartCollection)
+{
+ if (pChartCollection)
+ delete pChartCollection;
+ pChartCollection = pNewChartCollection;
+}
+
+void ScDocument::SetChartListenerCollection(
+ ScChartListenerCollection* pNewChartListenerCollection,
+ BOOL bSetChartRangeLists )
+{
+ ScChartListenerCollection* pOld = pChartListenerCollection;
+ pChartListenerCollection = pNewChartListenerCollection;
+ if ( pChartListenerCollection )
+ {
+ if ( pOld )
+ pChartListenerCollection->SetDiffDirty( *pOld, bSetChartRangeLists );
+ pChartListenerCollection->StartAllListeners();
+ }
+ delete pOld;
+}
+
+void ScDocument::SetScenario( USHORT nTab, BOOL bFlag )
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ pTab[nTab]->SetScenario(bFlag);
+}
+
+BOOL ScDocument::IsScenario( USHORT nTab ) const
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ return pTab[nTab]->IsScenario();
+
+ return FALSE;
+}
+
+void ScDocument::SetScenarioData( USHORT nTab, const String& rComment,
+ const Color& rColor, USHORT nFlags )
+{
+ if (nTab<=MAXTAB && pTab[nTab] && pTab[nTab]->IsScenario())
+ {
+ pTab[nTab]->SetScenarioComment( rComment );
+ pTab[nTab]->SetScenarioColor( rColor );
+ pTab[nTab]->SetScenarioFlags( nFlags );
+ }
+}
+
+void ScDocument::GetScenarioData( USHORT nTab, String& rComment,
+ Color& rColor, USHORT& rFlags ) const
+{
+ if (nTab<=MAXTAB && pTab[nTab] && pTab[nTab]->IsScenario())
+ {
+ pTab[nTab]->GetScenarioComment( rComment );
+ rColor = pTab[nTab]->GetScenarioColor();
+ rFlags = pTab[nTab]->GetScenarioFlags();
+ }
+}
+
+BOOL ScDocument::IsLinked( USHORT nTab ) const
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ return pTab[nTab]->IsLinked();
+ return FALSE;
+}
+
+BOOL ScDocument::GetLinkMode( USHORT nTab ) const
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ return pTab[nTab]->GetLinkMode();
+ return SC_LINK_NONE;
+}
+
+const String& ScDocument::GetLinkDoc( USHORT nTab ) const
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ return pTab[nTab]->GetLinkDoc();
+ return EMPTY_STRING;
+}
+
+const String& ScDocument::GetLinkFlt( USHORT nTab ) const
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ return pTab[nTab]->GetLinkFlt();
+ return EMPTY_STRING;
+}
+
+const String& ScDocument::GetLinkOpt( USHORT nTab ) const
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ return pTab[nTab]->GetLinkOpt();
+ return EMPTY_STRING;
+}
+
+const String& ScDocument::GetLinkTab( USHORT nTab ) const
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ return pTab[nTab]->GetLinkTab();
+ return EMPTY_STRING;
+}
+
+void ScDocument::SetLink( USHORT nTab, BYTE nMode, const String& rDoc,
+ const String& rFilter, const String& rOptions,
+ const String& rTabName )
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ pTab[nTab]->SetLink( nMode, rDoc, rFilter, rOptions, rTabName );
+}
+
+BOOL ScDocument::HasLink( const String& rDoc,
+ const String& rFilter, const String& rOptions ) const
+{
+ USHORT nCount = GetTableCount();
+ for (USHORT i=0; i<nCount; i++)
+ if (pTab[i]->IsLinked()
+ && pTab[i]->GetLinkDoc() == rDoc
+ && pTab[i]->GetLinkFlt() == rFilter
+ && pTab[i]->GetLinkOpt() == rOptions)
+ return TRUE;
+
+ return FALSE;
+}
+
+BOOL ScDocument::LinkEmptyTab( USHORT& rTab, const String& aDocTab,
+ const String& aFileName, const String& aTabName )
+{
+ if ( IsClipboard() )
+ {
+ DBG_ERRORFILE( "LinkExternalTab in Clipboard" );
+ return FALSE;
+ }
+ rTab = 0;
+ String aFilterName; // wird vom Loader gefuellt
+ String aOptions; // Filter-Optionen
+
+ if ( !InsertTab( SC_TAB_APPEND, aDocTab, TRUE ) )
+ {
+ DBG_ERRORFILE("can't insert external document table");
+ return FALSE;
+ }
+ rTab = GetTableCount() - 1;
+
+ BOOL bWasThere = HasLink( aFileName, aFilterName, aOptions );
+ SetLink( rTab, SC_LINK_VALUE, aFileName, aFilterName, aOptions, aTabName );
+ if ( !bWasThere ) // Link pro Quelldokument nur einmal eintragen
+ {
+ ScTableLink* pLink = new ScTableLink( pShell, aFileName, aFilterName, aOptions );
+ pLink->SetInCreate( TRUE );
+ pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, aFileName,
+ &aFilterName );
+ pLink->Update();
+ pLink->SetInCreate( FALSE );
+ SfxBindings& rBindings = SFX_BINDINGS();
+ rBindings.Invalidate( SID_LINKS );
+ }
+ return TRUE;
+}
+
+BOOL ScDocument::LinkExternalTab( USHORT& rTab, const String& aDocTab,
+ const String& aFileName, const String& aTabName )
+{
+ if ( IsClipboard() )
+ {
+ DBG_ERRORFILE( "LinkExternalTab in Clipboard" );
+ return FALSE;
+ }
+ rTab = 0;
+ String aFilterName; // wird vom Loader gefuellt
+ String aOptions; // Filter-Optionen
+ ScDocumentLoader aLoader( aFileName, aFilterName, aOptions,
+ pExtDocOptions ? pExtDocOptions->nLinkCnt + 1 : 1 );
+ if ( aLoader.IsError() )
+ return FALSE;
+ ScDocument* pSrcDoc = aLoader.GetDocument();
+
+ // Tabelle kopieren
+ USHORT nSrcTab;
+ if ( pSrcDoc->GetTable( aTabName, nSrcTab ) )
+ {
+ if ( !InsertTab( SC_TAB_APPEND, aDocTab, TRUE ) )
+ {
+ DBG_ERRORFILE("can't insert external document table");
+ return FALSE;
+ }
+ rTab = GetTableCount() - 1;
+ // nicht neu einfuegen, nur Ergebnisse
+ TransferTab( pSrcDoc, nSrcTab, rTab, FALSE, TRUE );
+ }
+ else
+ return FALSE;
+
+ BOOL bWasThere = HasLink( aFileName, aFilterName, aOptions );
+ SetLink( rTab, SC_LINK_VALUE, aFileName, aFilterName, aOptions, aTabName );
+ if ( !bWasThere ) // Link pro Quelldokument nur einmal eintragen
+ {
+ ScTableLink* pLink = new ScTableLink( pShell, aFileName, aFilterName, aOptions );
+ pLink->SetInCreate( TRUE );
+ pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, aFileName,
+ &aFilterName );
+ pLink->Update();
+ pLink->SetInCreate( FALSE );
+ SfxBindings& rBindings = SFX_BINDINGS();
+ rBindings.Invalidate( SID_LINKS );
+ }
+ return TRUE;
+}
+
+ScOutlineTable* ScDocument::GetOutlineTable( USHORT nTab, BOOL bCreate )
+{
+ ScOutlineTable* pVal = NULL;
+
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ {
+ pVal = pTab[nTab]->GetOutlineTable();
+ if (!pVal)
+ if (bCreate)
+ {
+ pTab[nTab]->StartOutlineTable();
+ pVal = pTab[nTab]->GetOutlineTable();
+ }
+ }
+
+ return pVal;
+}
+
+BOOL ScDocument::SetOutlineTable( USHORT nTab, const ScOutlineTable* pNewOutline )
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ return pTab[nTab]->SetOutlineTable(pNewOutline);
+
+ return FALSE;
+}
+
+void ScDocument::DoAutoOutline( USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow, USHORT nTab )
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ pTab[nTab]->DoAutoOutline( nStartCol, nStartRow, nEndCol, nEndRow );
+}
+
+BOOL ScDocument::TestRemoveSubTotals( USHORT nTab, const ScSubTotalParam& rParam )
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ return pTab[nTab]->TestRemoveSubTotals( rParam );
+
+ return FALSE;
+}
+
+void ScDocument::RemoveSubTotals( USHORT nTab, ScSubTotalParam& rParam )
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ pTab[nTab]->RemoveSubTotals( rParam );
+}
+
+BOOL ScDocument::DoSubTotals( USHORT nTab, ScSubTotalParam& rParam )
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ return pTab[nTab]->DoSubTotals( rParam );
+
+ return FALSE;
+}
+
+// kopiert aus diesem Dokument die Zellen von Positionen, an denen in pPosDoc
+// auch Zellen stehen, nach pDestDoc
+
+void ScDocument::CopyUpdated( ScDocument* pPosDoc, ScDocument* pDestDoc )
+{
+ USHORT nCount = GetTableCount();
+ for (USHORT nTab=0; nTab<nCount; nTab++)
+ if (pTab[nTab] && pPosDoc->pTab[nTab] && pDestDoc->pTab[nTab])
+ pTab[nTab]->CopyUpdated( pPosDoc->pTab[nTab], pDestDoc->pTab[nTab] );
+}
+
+void ScDocument::CopyScenario( USHORT nSrcTab, USHORT nDestTab, BOOL bNewScenario )
+{
+ if (nSrcTab<=MAXTAB && nDestTab<=MAXTAB && pTab[nSrcTab] && pTab[nDestTab])
+ {
+ // Flags fuer aktive Szenarios richtig setzen
+ // und aktuelle Werte in bisher aktive Szenarios zurueckschreiben
+
+ ScRangeList aRanges = *pTab[nSrcTab]->GetScenarioRanges();
+ USHORT nRangeCount = (USHORT)aRanges.Count();
+
+ // nDestTab ist die Zieltabelle
+ for ( USHORT nTab = nDestTab+1;
+ nTab<=MAXTAB && pTab[nTab] && pTab[nTab]->IsScenario();
+ nTab++ )
+ {
+ if ( pTab[nTab]->IsActiveScenario() ) // auch wenn's dasselbe Szenario ist
+ {
+ BOOL bTouched = FALSE;
+ for ( USHORT nR=0; nR<nRangeCount && !bTouched; nR++)
+ {
+ ScRange aRange = *aRanges.GetObject(nR);
+ if ( pTab[nTab]->HasScenarioRange( aRange ) )
+ bTouched = TRUE;
+ }
+ if (bTouched)
+ {
+ pTab[nTab]->SetActiveScenario(FALSE);
+ if ( pTab[nTab]->GetScenarioFlags() & SC_SCENARIO_TWOWAY )
+ pTab[nTab]->CopyScenarioFrom( pTab[nDestTab] );
+ }
+ }
+ }
+
+ pTab[nSrcTab]->SetActiveScenario(TRUE); // da kommt's her...
+ if (!bNewScenario) // Daten aus dem ausgewaehlten Szenario kopieren
+ {
+ BOOL bOldAutoCalc = GetAutoCalc();
+ SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ pTab[nSrcTab]->CopyScenarioTo( pTab[nDestTab] );
+ SetDirty();
+ SetAutoCalc( bOldAutoCalc );
+ }
+ }
+}
+
+void ScDocument::MarkScenario( USHORT nSrcTab, USHORT nDestTab, ScMarkData& rDestMark,
+ BOOL bResetMark, USHORT nNeededBits ) const
+{
+ if (bResetMark)
+ rDestMark.ResetMark();
+
+ if (nSrcTab<=MAXTAB && pTab[nSrcTab])
+ pTab[nSrcTab]->MarkScenarioIn( rDestMark, nNeededBits );
+
+ rDestMark.SetAreaTab( nDestTab );
+}
+
+BOOL ScDocument::HasScenarioRange( USHORT nTab, const ScRange& rRange ) const
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ return pTab[nTab]->HasScenarioRange( rRange );
+
+ return FALSE;
+}
+
+const ScRangeList* ScDocument::GetScenarioRanges( USHORT nTab ) const
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ return pTab[nTab]->GetScenarioRanges();
+
+ return NULL;
+}
+
+BOOL ScDocument::IsActiveScenario( USHORT nTab ) const
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ return pTab[nTab]->IsActiveScenario();
+
+ return FALSE;
+}
+
+void ScDocument::SetActiveScenario( USHORT nTab, BOOL bActive )
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ pTab[nTab]->SetActiveScenario( bActive );
+}
+
+BOOL ScDocument::TestCopyScenario( USHORT nSrcTab, USHORT nDestTab ) const
+{
+ if (nSrcTab<=MAXTAB && nDestTab<=MAXTAB)
+ return pTab[nSrcTab]->TestCopyScenarioTo( pTab[nDestTab] );
+
+ DBG_ERROR("falsche Tabelle bei TestCopyScenario");
+ return FALSE;
+}
+
+void ScDocument::AddUnoObject( SfxListener& rObject )
+{
+ if (!pUnoBroadcaster)
+ pUnoBroadcaster = new SfxBroadcaster;
+
+ rObject.StartListening( *pUnoBroadcaster );
+}
+
+void ScDocument::RemoveUnoObject( SfxListener& rObject )
+{
+ if (pUnoBroadcaster)
+ rObject.EndListening( *pUnoBroadcaster );
+ else
+ DBG_ERROR("kein Uno-Broadcaster??!?");
+}
+
+void ScDocument::BroadcastUno( const SfxHint &rHint )
+{
+ if (pUnoBroadcaster)
+ pUnoBroadcaster->Broadcast( rHint );
+}
+
+void ScDocument::UpdateReference( UpdateRefMode eUpdateRefMode,
+ USHORT nCol1, USHORT nRow1, USHORT nTab1,
+ USHORT nCol2, USHORT nRow2, USHORT nTab2,
+ short nDx, short nDy, short nDz, ScDocument* pUndoDoc )
+{
+ PutInOrder( nCol1, nCol2 );
+ PutInOrder( nRow1, nRow2 );
+ PutInOrder( nTab1, nTab2 );
+ if (VALIDTAB(nTab1) && VALIDTAB(nTab2))
+ {
+ BOOL bExpandRefsOld = IsExpandRefs();
+ if ( eUpdateRefMode == URM_INSDEL && (nDx > 0 || nDy > 0 || nDz > 0) )
+ SetExpandRefs( SC_MOD()->GetInputOptions().GetExpandRefs() );
+ USHORT i;
+ USHORT iMax;
+ if ( eUpdateRefMode == URM_COPY )
+ {
+ i = nTab1;
+ iMax = nTab2;
+ }
+ else
+ {
+ ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ xColNameRanges->UpdateReference( eUpdateRefMode, this, aRange, nDx, nDy, nDz );
+ xRowNameRanges->UpdateReference( eUpdateRefMode, this, aRange, nDx, nDy, nDz );
+ pDBCollection->UpdateReference( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz );
+ pRangeName->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
+ if (pPivotCollection)
+ pPivotCollection->UpdateReference( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz );
+ if ( pDPCollection )
+ pDPCollection->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
+ UpdateChartRef( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz );
+ if ( pCondFormList )
+ pCondFormList->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
+ if ( pDetOpList )
+ pDetOpList->UpdateReference( this, eUpdateRefMode, aRange, nDx, nDy, nDz );
+ if ( pUnoBroadcaster )
+ pUnoBroadcaster->Broadcast( ScUpdateRefHint(
+ eUpdateRefMode, aRange, nDx, nDy, nDz ) );
+ i = 0;
+ iMax = MAXTAB;
+ }
+ for ( ; i<=iMax; i++)
+ if (pTab[i])
+ pTab[i]->UpdateReference(
+ eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz, pUndoDoc );
+
+ if ( bIsEmbedded )
+ {
+ USHORT theCol1, theRow1, theTab1, theCol2, theRow2, theTab2;
+ theCol1 = aEmbedRange.aStart.Col();
+ theRow1 = aEmbedRange.aStart.Row();
+ theTab1 = aEmbedRange.aStart.Tab();
+ theCol2 = aEmbedRange.aEnd.Col();
+ theRow2 = aEmbedRange.aEnd.Row();
+ theTab2 = aEmbedRange.aEnd.Tab();
+ if ( ScRefUpdate::Update( this, eUpdateRefMode, nCol1,nRow1,nTab1, nCol2,nRow2,nTab2,
+ nDx,nDy,nDz, theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ) )
+ {
+ aEmbedRange = ScRange( theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 );
+ }
+ }
+ SetExpandRefs( bExpandRefsOld );
+ // #30428# nach Verschiebungen keine MOVE Anpassungen moeglich!
+ if ( eUpdateRefMode != URM_COPY && ScGlobal::HasClipDoc() )
+ ScGlobal::GetClipDoc()->bCutMode = FALSE;
+ }
+}
+
+void ScDocument::UpdateTranspose( const ScAddress& rDestPos, ScDocument* pClipDoc,
+ const ScMarkData& rMark, ScDocument* pUndoDoc )
+{
+ DBG_ASSERT(pClipDoc->bIsClip, "UpdateTranspose: kein Clip");
+
+ ScRange aSource = pClipDoc->aClipRange; // Tab wird noch angepasst
+ ScAddress aDest = rDestPos;
+
+ USHORT nClipTab = 0;
+ for (USHORT nDestTab=0; nDestTab<=MAXTAB && pTab[nDestTab]; nDestTab++)
+ if (rMark.GetTableSelect(nDestTab))
+ {
+ while (!pClipDoc->pTab[nClipTab]) nClipTab = (nClipTab+1) % (MAXTAB+1);
+ aSource.aStart.SetTab( nClipTab );
+ aSource.aEnd.SetTab( nClipTab );
+ aDest.SetTab( nDestTab );
+
+ // wie UpdateReference
+
+ pRangeName->UpdateTranspose( aSource, aDest ); // vor den Zellen!
+ for (USHORT i=0; i<=MAXTAB; i++)
+ if (pTab[i])
+ pTab[i]->UpdateTranspose( aSource, aDest, pUndoDoc );
+
+ nClipTab = (nClipTab+1) % (MAXTAB+1);
+ }
+}
+
+void ScDocument::UpdateGrow( const ScRange& rArea, USHORT nGrowX, USHORT nGrowY )
+{
+ //! pDBCollection
+ //! pPivotCollection
+ //! UpdateChartRef
+
+ pRangeName->UpdateGrow( rArea, nGrowX, nGrowY );
+ pPivotCollection->UpdateGrow( rArea, nGrowX, nGrowY );
+
+ for (USHORT i=0; i<=MAXTAB && pTab[i]; i++)
+ pTab[i]->UpdateGrow( rArea, nGrowX, nGrowY );
+}
+
+void ScDocument::Fill(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2, const ScMarkData& rMark,
+ USHORT nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
+ double nStepValue, double nMaxValue)
+{
+ PutInOrder( nCol1, nCol2 );
+ PutInOrder( nRow1, nRow2 );
+ for (USHORT i=0; i <= MAXTAB; i++)
+ if (pTab[i])
+ if (rMark.GetTableSelect(i))
+ pTab[i]->Fill(nCol1, nRow1, nCol2, nRow2,
+ nFillCount, eFillDir, eFillCmd, eFillDateCmd,
+ nStepValue, nMaxValue);
+}
+
+String ScDocument::GetAutoFillPreview( const ScRange& rSource, USHORT nEndX, USHORT nEndY )
+{
+ USHORT nTab = rSource.aStart.Tab();
+ if (pTab[nTab])
+ return pTab[nTab]->GetAutoFillPreview( rSource, nEndX, nEndY );
+
+ return EMPTY_STRING;
+}
+
+void ScDocument::AutoFormat( USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow,
+ USHORT nFormatNo, const ScMarkData& rMark )
+{
+ PutInOrder( nStartCol, nEndCol );
+ PutInOrder( nStartRow, nEndRow );
+ for (USHORT i=0; i <= MAXTAB; i++)
+ if (pTab[i])
+ if (rMark.GetTableSelect(i))
+ pTab[i]->AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo );
+}
+
+void ScDocument::GetAutoFormatData(USHORT nTab, USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow,
+ ScAutoFormatData& rData)
+{
+ if (VALIDTAB(nTab))
+ {
+ if (pTab[nTab])
+ {
+ PutInOrder(nStartCol, nEndCol);
+ PutInOrder(nStartRow, nEndRow);
+ pTab[nTab]->GetAutoFormatData(nStartCol, nStartRow, nEndCol, nEndRow, rData);
+ }
+ }
+}
+
+// static
+void ScDocument::GetSearchAndReplaceStart( const SvxSearchItem& rSearchItem,
+ USHORT& rCol, USHORT& rRow )
+{
+ USHORT nCommand = rSearchItem.GetCommand();
+ BOOL bReplace = ( nCommand == SVX_SEARCHCMD_REPLACE ||
+ nCommand == SVX_SEARCHCMD_REPLACE_ALL );
+ if ( rSearchItem.GetBackward() )
+ {
+ if ( rSearchItem.GetRowDirection() )
+ {
+ if ( rSearchItem.GetPattern() )
+ {
+ rCol = MAXCOL;
+ rRow = MAXROW+1;
+ }
+ else if ( bReplace )
+ {
+ rCol = MAXCOL;
+ rRow = MAXROW;
+ }
+ else
+ {
+ rCol = MAXCOL+1;
+ rRow = MAXROW;
+ }
+ }
+ else
+ {
+ if ( rSearchItem.GetPattern() )
+ {
+ rCol = MAXCOL+1;
+ rRow = MAXROW;
+ }
+ else if ( bReplace )
+ {
+ rCol = MAXCOL;
+ rRow = MAXROW;
+ }
+ else
+ {
+ rCol = MAXCOL;
+ rRow = MAXROW+1;
+ }
+ }
+ }
+ else
+ {
+ if ( rSearchItem.GetRowDirection() )
+ {
+ if ( rSearchItem.GetPattern() )
+ {
+ rCol = 0;
+ rRow = (USHORT) -1;
+ }
+ else if ( bReplace )
+ {
+ rCol = 0;
+ rRow = 0;
+ }
+ else
+ {
+ rCol = (USHORT) -1;
+ rRow = 0;
+ }
+ }
+ else
+ {
+ if ( rSearchItem.GetPattern() )
+ {
+ rCol = (USHORT) -1;
+ rRow = 0;
+ }
+ else if ( bReplace )
+ {
+ rCol = 0;
+ rRow = 0;
+ }
+ else
+ {
+ rCol = 0;
+ rRow = (USHORT) -1;
+ }
+ }
+ }
+}
+
+BOOL ScDocument::SearchAndReplace(const SvxSearchItem& rSearchItem,
+ USHORT& rCol, USHORT& rRow, USHORT& rTab,
+ ScMarkData& rMark,
+ String& rUndoStr, ScDocument* pUndoDoc)
+{
+ //! getrennte Markierungen pro Tabelle verwalten !!!!!!!!!!!!!
+
+ rMark.MarkToMulti();
+
+ BOOL bFound = FALSE;
+ if (VALIDTAB(rTab))
+ {
+ USHORT nCol;
+ USHORT nRow;
+ USHORT nTab;
+ USHORT nCommand = rSearchItem.GetCommand();
+ if ( nCommand == SVX_SEARCHCMD_FIND_ALL ||
+ nCommand == SVX_SEARCHCMD_REPLACE_ALL )
+ {
+ for (nTab = 0; nTab <= MAXTAB; nTab++)
+ if (pTab[nTab])
+ {
+ if (rMark.GetTableSelect(nTab))
+ {
+ nCol = 0;
+ nRow = 0;
+ bFound |= pTab[nTab]->SearchAndReplace(
+ rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc );
+ }
+ }
+
+ // Markierung wird innen schon komplett gesetzt
+ }
+ else
+ {
+ nCol = rCol;
+ nRow = rRow;
+ if (rSearchItem.GetBackward())
+ {
+ for (nTab = rTab; ((short)nTab >= 0) && !bFound; nTab--)
+ if (pTab[nTab])
+ {
+ if (rMark.GetTableSelect(nTab))
+ {
+ bFound = pTab[nTab]->SearchAndReplace(
+ rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc );
+ if (bFound)
+ {
+ rCol = nCol;
+ rRow = nRow;
+ rTab = nTab;
+ }
+ else
+ ScDocument::GetSearchAndReplaceStart(
+ rSearchItem, nCol, nRow );
+ }
+ }
+ }
+ else
+ {
+ for (nTab = rTab; (nTab <= MAXTAB) && !bFound; nTab++)
+ if (pTab[nTab])
+ {
+ if (rMark.GetTableSelect(nTab))
+ {
+ bFound = pTab[nTab]->SearchAndReplace(
+ rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc );
+ if (bFound)
+ {
+ rCol = nCol;
+ rRow = nRow;
+ rTab = nTab;
+ }
+ else
+ ScDocument::GetSearchAndReplaceStart(
+ rSearchItem, nCol, nRow );
+ }
+ }
+ }
+ }
+ }
+ return bFound;
+}
+
+BOOL ScDocument::IsFiltered( USHORT nRow, USHORT nTab ) const
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ return pTab[nTab]->IsFiltered( nRow );
+ DBG_ERROR("Falsche Tabellennummer");
+ return 0;
+}
+
+// Outline anpassen
+
+BOOL ScDocument::UpdateOutlineCol( USHORT nStartCol, USHORT nEndCol, USHORT nTab, BOOL bShow )
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ return pTab[nTab]->UpdateOutlineCol( nStartCol, nEndCol, bShow );
+
+ DBG_ERROR("missing tab");
+ return FALSE;
+}
+
+BOOL ScDocument::UpdateOutlineRow( USHORT nStartRow, USHORT nEndRow, USHORT nTab, BOOL bShow )
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ return pTab[nTab]->UpdateOutlineRow( nStartRow, nEndRow, bShow );
+
+ DBG_ERROR("missing tab");
+ return FALSE;
+}
+
+void ScDocument::Sort(USHORT nTab, const ScSortParam& rSortParam, BOOL bKeepQuery)
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ {
+ BOOL bOldDisableIdle = IsIdleDisabled();
+ DisableIdle( TRUE );
+ pTab[nTab]->Sort(rSortParam, bKeepQuery);
+ DisableIdle( bOldDisableIdle );
+ }
+}
+
+USHORT ScDocument::Query(USHORT nTab, const ScQueryParam& rQueryParam, BOOL bKeepSub)
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ return pTab[nTab]->Query((ScQueryParam&)rQueryParam, bKeepSub);
+
+ DBG_ERROR("missing tab");
+ return 0;
+}
+
+
+BOOL ScDocument::ValidQuery( USHORT nRow, USHORT nTab, const ScQueryParam& rQueryParam )
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ return pTab[nTab]->ValidQuery( nRow, rQueryParam );
+
+ DBG_ERROR("missing tab");
+ return FALSE;
+}
+
+
+void ScDocument::GetUpperCellString(USHORT nCol, USHORT nRow, USHORT nTab, String& rStr)
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ pTab[nTab]->GetUpperCellString( nCol, nRow, rStr );
+ else
+ rStr.Erase();
+}
+
+BOOL ScDocument::CreateQueryParam(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2, USHORT nTab, ScQueryParam& rQueryParam)
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ return pTab[nTab]->CreateQueryParam(nCol1, nRow1, nCol2, nRow2, rQueryParam);
+
+ DBG_ERROR("missing tab");
+ return FALSE;
+}
+
+BOOL ScDocument::HasAutoFilter( USHORT nCurCol, USHORT nCurRow, USHORT nCurTab )
+{
+ ScDBData* pDBData = GetDBAtCursor( nCurCol, nCurRow, nCurTab );
+ BOOL bHasAutoFilter = ( pDBData != NULL );
+
+ if ( pDBData )
+ {
+ if ( pDBData->HasHeader() )
+ {
+ USHORT nCol;
+ USHORT nRow;
+ INT16 nFlag;
+
+ ScQueryParam aParam;
+ pDBData->GetQueryParam( aParam );
+ nRow = aParam.nRow1;
+
+ for ( nCol=aParam.nCol1; nCol<=aParam.nCol2 && bHasAutoFilter; nCol++ )
+ {
+ nFlag = ((ScMergeFlagAttr*)
+ GetAttr( nCol, nRow, nCurTab, ATTR_MERGE_FLAG ))->
+ GetValue();
+
+ if ( (nFlag & SC_MF_AUTO) == 0 )
+ bHasAutoFilter = FALSE;
+ }
+ }
+ else
+ bHasAutoFilter = FALSE;
+ }
+
+ return bHasAutoFilter;
+}
+
+BOOL ScDocument::HasColHeader( USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow,
+ USHORT nTab )
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ return pTab[nTab]->HasColHeader( nStartCol, nStartRow, nEndCol, nEndRow );
+
+ return FALSE;
+}
+
+BOOL ScDocument::HasRowHeader( USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow,
+ USHORT nTab )
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ return pTab[nTab]->HasRowHeader( nStartCol, nStartRow, nEndCol, nEndRow );
+
+ return FALSE;
+}
+
+//
+// GetFilterEntries - Eintraege fuer AutoFilter-Listbox
+//
+
+BOOL ScDocument::GetFilterEntries( USHORT nCol, USHORT nRow, USHORT nTab, TypedStrCollection& rStrings )
+{
+ if ( nTab<=MAXTAB && pTab[nTab] && pDBCollection )
+ {
+ ScDBData* pDBData = pDBCollection->GetDBAtCursor(nCol, nRow, nTab, FALSE); //!??
+ if (pDBData)
+ {
+ USHORT nAreaTab;
+ USHORT nStartCol;
+ USHORT nStartRow;
+ USHORT nEndCol;
+ USHORT nEndRow;
+ pDBData->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow );
+ if (pDBData->HasHeader())
+ ++nStartRow;
+
+ ScQueryParam aParam;
+ pDBData->GetQueryParam( aParam );
+ rStrings.SetCaseSensitive( aParam.bCaseSens );
+
+ pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings );
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+//
+// GetFilterEntriesArea - Eintraege fuer Filter-Dialog
+//
+
+BOOL ScDocument::GetFilterEntriesArea( USHORT nCol, USHORT nStartRow, USHORT nEndRow,
+ USHORT nTab, TypedStrCollection& rStrings )
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ {
+ pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings );
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//
+// GetDataEntries - Eintraege fuer Auswahlliste-Listbox (keine Zahlen / Formeln)
+//
+
+BOOL ScDocument::GetDataEntries( USHORT nCol, USHORT nRow, USHORT nTab,
+ TypedStrCollection& rStrings, BOOL bLimit )
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ return pTab[nTab]->GetDataEntries( nCol, nRow, rStrings, bLimit );
+
+ return FALSE;
+}
+
+//
+// GetFormulaEntries - Eintraege fuer Formel-AutoEingabe
+//
+
+// Funktionen werden als 1 schon vom InputHandler eingefuegt
+#define SC_STRTYPE_NAMES 2
+#define SC_STRTYPE_DBNAMES 3
+#define SC_STRTYPE_HEADERS 4
+
+BOOL ScDocument::GetFormulaEntries( TypedStrCollection& rStrings )
+{
+ USHORT i;
+
+ //
+ // Bereichsnamen
+ //
+
+ if ( pRangeName )
+ {
+ USHORT nRangeCount = pRangeName->GetCount();
+ for ( i=0; i<nRangeCount; i++ )
+ {
+ ScRangeData* pData = (*pRangeName)[i];
+ if (pData)
+ {
+ TypedStrData* pNew = new TypedStrData( pData->GetName(), 0.0, SC_STRTYPE_NAMES );
+ if ( !rStrings.Insert(pNew) )
+ delete pNew;
+ }
+ }
+ }
+
+ //
+ // Datenbank-Bereiche
+ //
+
+ if ( pDBCollection )
+ {
+ USHORT nDBCount = pDBCollection->GetCount();
+ for ( i=0; i<nDBCount; i++ )
+ {
+ ScDBData* pData = (*pDBCollection)[i];
+ if (pData)
+ {
+ TypedStrData* pNew = new TypedStrData( pData->GetName(), 0.0, SC_STRTYPE_DBNAMES );
+ if ( !rStrings.Insert(pNew) )
+ delete pNew;
+ }
+ }
+ }
+
+ //
+ // Inhalte von Beschriftungsbereichen
+ //
+
+ ScRangePairList* pLists[2];
+ pLists[0] = GetColNameRanges();
+ pLists[1] = GetRowNameRanges();
+ for (USHORT nListNo=0; nListNo<2; nListNo++)
+ {
+ ScRangePairList* pList = pLists[nListNo];
+ if (pList)
+ for ( ScRangePair* pPair = pList->First(); pPair; pPair = pList->Next() )
+ {
+ ScRange aRange = pPair->GetRange(0);
+ ScCellIterator aIter( this, aRange );
+ for ( ScBaseCell* pCell = aIter.GetFirst(); pCell; pCell = aIter.GetNext() )
+ if ( pCell->HasStringData() )
+ {
+ String aStr = pCell->GetStringData();
+ TypedStrData* pNew = new TypedStrData( aStr, 0.0, SC_STRTYPE_HEADERS );
+ if ( !rStrings.Insert(pNew) )
+ delete pNew;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+BOOL ScDocument::IsEmbedded() const
+{
+ return bIsEmbedded;
+}
+
+void ScDocument::GetEmbedded( ScTripel& rStart, ScTripel& rEnd ) const
+{
+ rStart.Put( aEmbedRange.aStart.Col(), aEmbedRange.aStart.Row(), aEmbedRange.aStart.Tab() );
+ rEnd.Put( aEmbedRange.aEnd.Col(), aEmbedRange.aEnd.Row(), aEmbedRange.aEnd.Tab() );
+}
+
+Rectangle ScDocument::GetEmbeddedRect() const // 1/100 mm
+{
+ Rectangle aRect;
+ ScTable* pTable = pTab[aEmbedRange.aStart.Tab()];
+ if (!pTable)
+ {
+ DBG_ERROR("GetEmbeddedRect ohne Tabelle");
+ }
+ else
+ {
+ USHORT i;
+
+ for (i=0; i<aEmbedRange.aStart.Col(); i++)
+ aRect.Left() += pTable->GetColWidth(i);
+ for (i=0; i<aEmbedRange.aStart.Row(); i++)
+ aRect.Top() += pTable->GetRowHeight(i);
+ aRect.Right() = aRect.Left();
+ for (i=aEmbedRange.aStart.Col(); i<=aEmbedRange.aEnd.Col(); i++)
+ aRect.Right() += pTable->GetColWidth(i);
+ aRect.Bottom() = aRect.Top();
+ for (i=aEmbedRange.aStart.Row(); i<=aEmbedRange.aEnd.Row(); i++)
+ aRect.Bottom() += pTable->GetRowHeight(i);
+
+ aRect.Left() = (long) ( aRect.Left() * HMM_PER_TWIPS );
+ aRect.Right() = (long) ( aRect.Right() * HMM_PER_TWIPS );
+ aRect.Top() = (long) ( aRect.Top() * HMM_PER_TWIPS );
+ aRect.Bottom() = (long) ( aRect.Bottom() * HMM_PER_TWIPS );
+ }
+ return aRect;
+}
+
+void ScDocument::SetEmbedded( const ScTripel& rStart, const ScTripel& rEnd )
+{
+ bIsEmbedded = TRUE;
+ aEmbedRange = ScRange( rStart, rEnd );
+}
+
+void ScDocument::ResetEmbedded()
+{
+ bIsEmbedded = FALSE;
+ aEmbedRange = ScRange();
+}
+
+ScRange ScDocument::GetRange( USHORT nTab, const Rectangle& rMMRect )
+{
+ ScTable* pTable = pTab[nTab];
+ if (!pTable)
+ {
+ DBG_ERROR("GetRange ohne Tabelle");
+ return ScRange();
+ }
+
+ long nSize;
+ long nTwips;
+ long nAdd;
+ BOOL bEnd;
+
+ nSize = 0;
+ nTwips = (long) (rMMRect.Left() / HMM_PER_TWIPS);
+
+ USHORT nX1 = 0;
+ bEnd = FALSE;
+ while (!bEnd)
+ {
+ nAdd = (long) pTable->GetColWidth(nX1);
+ if (nSize+nAdd <= nTwips+1 && nX1<MAXCOL)
+ {
+ nSize += nAdd;
+ ++nX1;
+ }
+ else
+ bEnd = TRUE;
+ }
+
+ nTwips = (long) (rMMRect.Right() / HMM_PER_TWIPS);
+
+ USHORT nX2 = nX1;
+ bEnd = FALSE;
+ while (!bEnd)
+ {
+ nAdd = (long) pTable->GetColWidth(nX2);
+ if (nSize+nAdd < nTwips && nX2<MAXCOL)
+ {
+ nSize += nAdd;
+ ++nX2;
+ }
+ else
+ bEnd = TRUE;
+ }
+
+
+ nSize = 0;
+ nTwips = (long) (rMMRect.Top() / HMM_PER_TWIPS);
+
+ USHORT nY1 = 0;
+ bEnd = FALSE;
+ while (!bEnd)
+ {
+ nAdd = (long) pTable->GetRowHeight(nY1);
+ if (nSize+nAdd <= nTwips+1 && nY1<MAXROW)
+ {
+ nSize += nAdd;
+ ++nY1;
+ }
+ else
+ bEnd = TRUE;
+ }
+
+ nTwips = (long) (rMMRect.Bottom() / HMM_PER_TWIPS);
+
+ USHORT nY2 = nY1;
+ bEnd = FALSE;
+ while (!bEnd)
+ {
+ nAdd = (long) pTable->GetRowHeight(nY2);
+ if (nSize+nAdd < nTwips && nY2<MAXROW)
+ {
+ nSize += nAdd;
+ ++nY2;
+ }
+ else
+ bEnd = TRUE;
+ }
+
+ return ScRange( nX1,nY1,nTab, nX2,nY2,nTab );
+}
+
+void ScDocument::SetEmbedded( const Rectangle& rRect ) // aus VisArea (1/100 mm)
+{
+ bIsEmbedded = TRUE;
+ aEmbedRange = GetRange( nVisibleTab, rRect );
+}
+
+// VisArea auf Zellgrenzen anpassen
+
+void lcl_SnapHor( ScTable* pTable, long& rVal, USHORT& rStartCol )
+{
+ USHORT nCol = 0;
+ long nTwips = (long) (rVal / HMM_PER_TWIPS);
+ long nSnap = 0;
+ while ( nCol<MAXCOL )
+ {
+ long nAdd = pTable->GetColWidth(nCol);
+ if ( nSnap + nAdd/2 < nTwips || nCol < rStartCol )
+ {
+ nSnap += nAdd;
+ ++nCol;
+ }
+ else
+ break;
+ }
+ rVal = (long) ( nSnap * HMM_PER_TWIPS );
+ rStartCol = nCol;
+}
+
+void lcl_SnapVer( ScTable* pTable, long& rVal, USHORT& rStartRow )
+{
+ USHORT nRow = 0;
+ long nTwips = (long) (rVal / HMM_PER_TWIPS);
+ long nSnap = 0;
+ while ( nRow<MAXROW )
+ {
+ long nAdd = pTable->GetRowHeight(nRow);
+ if ( nSnap + nAdd/2 < nTwips || nRow < rStartRow )
+ {
+ nSnap += nAdd;
+ ++nRow;
+ }
+ else
+ break;
+ }
+ rVal = (long) ( nSnap * HMM_PER_TWIPS );
+ rStartRow = nRow;
+}
+
+void ScDocument::SnapVisArea( Rectangle& rRect ) const
+{
+ ScTable* pTable = pTab[nVisibleTab];
+ if (!pTable)
+ {
+ DBG_ERROR("SetEmbedded ohne Tabelle");
+ return;
+ }
+
+ USHORT nCol = 0;
+ lcl_SnapHor( pTable, rRect.Left(), nCol );
+ ++nCol; // mindestens eine Spalte
+ lcl_SnapHor( pTable, rRect.Right(), nCol );
+
+ USHORT nRow = 0;
+ lcl_SnapVer( pTable, rRect.Top(), nRow );
+ ++nRow; // mindestens eine Zeile
+ lcl_SnapVer( pTable, rRect.Bottom(), nRow );
+}
+
+void ScDocument::SetDocProtection( BOOL bProtect, const String& rPasswd )
+{
+ bProtected = bProtect;
+ aProtectPass = rPasswd;
+}
+
+void ScDocument::SetTabProtection( USHORT nTab, BOOL bProtect, const String& rPasswd )
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ pTab[nTab]->SetProtection( bProtect, rPasswd );
+}
+
+BOOL ScDocument::IsDocProtected() const
+{
+ return bProtected;
+}
+
+BOOL ScDocument::IsDocEditable() const
+{
+ return !bProtected && ( !pShell || !pShell->IsReadOnly() );
+}
+
+BOOL ScDocument::IsTabProtected( USHORT nTab ) const
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ return pTab[nTab]->IsProtected();
+
+ DBG_ERROR("Falsche Tabellennummer");
+ return FALSE;
+}
+
+const String& ScDocument::GetDocPassword() const
+{
+ return aProtectPass;
+}
+
+const String& ScDocument::GetTabPassword( USHORT nTab ) const
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ return pTab[nTab]->GetPassword();
+
+ DBG_ERROR("Falsche Tabellennummer");
+ return aProtectPass;
+}
+
+const ScDocOptions& ScDocument::GetDocOptions() const
+{
+ DBG_ASSERT( pDocOptions, "No DocOptions! :-(" );
+ return *pDocOptions;
+}
+
+void ScDocument::SetDocOptions( const ScDocOptions& rOpt )
+{
+ USHORT d,m,y;
+
+ DBG_ASSERT( pDocOptions, "No DocOptions! :-(" );
+ *pDocOptions = rOpt;
+ rOpt.GetDate( d,m,y );
+ pFormTable->ChangeNullDate( d,m,y );
+ pFormTable->ChangeStandardPrec( (USHORT)rOpt.GetStdPrecision() );
+ pFormTable->SetYear2000( rOpt.GetYear2000() );
+}
+
+const ScViewOptions& ScDocument::GetViewOptions() const
+{
+ DBG_ASSERT( pViewOptions, "No ViewOptions! :-(" );
+ return *pViewOptions;
+}
+
+void ScDocument::SetViewOptions( const ScViewOptions& rOpt )
+{
+ DBG_ASSERT( pViewOptions, "No ViewOptions! :-(" );
+ *pViewOptions = rOpt;
+}
+
+LanguageType ScDocument::GetLanguage() const
+{
+ return eLanguage;
+}
+
+void ScDocument::SetLanguage( LanguageType eNewLang )
+{
+ eLanguage = eNewLang;
+ if ( pDocPool )
+ pDocPool->SetPoolDefaultItem( SvxLanguageItem( eLanguage, ATTR_FONT_LANGUAGE ) );
+}
+
+Rectangle ScDocument::GetMMRect( USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow, USHORT nTab )
+{
+ if (nTab > MAXTAB || !pTab[nTab])
+ {
+ DBG_ERROR("GetMMRect: falsche Tabelle");
+ return Rectangle(0,0,0,0);
+ }
+
+ USHORT i;
+ Rectangle aRect;
+
+ for (i=0; i<nStartCol; i++)
+ aRect.Left() += GetColWidth(i,nTab);
+ for (i=0; i<nStartRow; i++)
+ aRect.Top() += FastGetRowHeight(i,nTab);
+
+ aRect.Right() = aRect.Left();
+ aRect.Bottom() = aRect.Top();
+
+ for (i=nStartCol; i<=nEndCol; i++)
+ aRect.Right() += GetColWidth(i,nTab);
+ for (i=nStartRow; i<=nEndRow; i++)
+ aRect.Bottom() += FastGetRowHeight(i,nTab);
+
+ aRect.Left() = (long)(aRect.Left() * HMM_PER_TWIPS);
+ aRect.Right() = (long)(aRect.Right() * HMM_PER_TWIPS);
+ aRect.Top() = (long)(aRect.Top() * HMM_PER_TWIPS);
+ aRect.Bottom() = (long)(aRect.Bottom() * HMM_PER_TWIPS);
+
+ return aRect;
+}
+
+void ScDocument::SetExtDocOptions( ScExtDocOptions* pNewOptions )
+{
+ delete pExtDocOptions;
+ pExtDocOptions = pNewOptions;
+}
+
+void ScDocument::DoMergeContents( USHORT nTab, USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow )
+{
+ String aEmpty;
+ String aTotal;
+ String aCellStr;
+ USHORT nCol;
+ USHORT nRow;
+ ScPostIt aCellNote;
+ String aNoteStr;
+ BOOL bDoNote = FALSE;
+
+ for (nRow=nStartRow; nRow<=nEndRow; nRow++)
+ for (nCol=nStartCol; nCol<=nEndCol; nCol++)
+ {
+ GetString(nCol,nRow,nTab,aCellStr);
+ if (aCellStr.Len())
+ {
+ if (aTotal.Len())
+ aTotal += ' ';
+ aTotal += aCellStr;
+ }
+ if (nCol != nStartCol || nRow != nStartRow)
+ SetString(nCol,nRow,nTab,aEmpty);
+
+ if (GetNote(nCol,nRow,nTab,aCellNote))
+ {
+ if (aNoteStr.Len())
+ aNoteStr += '\n';
+ aNoteStr += aCellNote.GetText();
+
+ if (nCol != nStartCol || nRow != nStartRow)
+ {
+ if (aCellNote.IsShown())
+ ScDetectiveFunc( this, nTab ).HideComment( nCol, nRow );
+ SetNote(nCol,nRow,nTab,ScPostIt());
+ bDoNote = TRUE;
+ }
+ //! Autor/Datum beibehalten, wenn's nur eine Notiz war??
+ }
+ }
+
+ SetString(nStartCol,nStartRow,nTab,aTotal);
+ if (bDoNote)
+ SetNote(nStartCol,nStartRow,nTab,ScPostIt(aNoteStr));
+}
+
+void ScDocument::DoMerge( USHORT nTab, USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow )
+{
+ ScMergeAttr aAttr( nEndCol-nStartCol+1, nEndRow-nStartRow+1 );
+ ApplyAttr( nStartCol, nStartRow, nTab, aAttr );
+
+ if ( nEndCol > nStartCol )
+ ApplyFlagsTab( nStartCol+1, nStartRow, nEndCol, nStartRow, nTab, SC_MF_HOR );
+ if ( nEndRow > nStartRow )
+ ApplyFlagsTab( nStartCol, nStartRow+1, nStartCol, nEndRow, nTab, SC_MF_VER );
+ if ( nEndCol > nStartCol && nEndRow > nStartRow )
+ ApplyFlagsTab( nStartCol+1, nStartRow+1, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
+}
+
+void ScDocument::RemoveMerge( USHORT nCol, USHORT nRow, USHORT nTab )
+{
+ const ScMergeAttr* pAttr = (const ScMergeAttr*)
+ GetAttr( nCol, nRow, nTab, ATTR_MERGE );
+
+ if ( pAttr->GetColMerge() <= 1 && pAttr->GetRowMerge() <= 1 )
+ return;
+
+ USHORT nEndCol = nCol + pAttr->GetColMerge() - 1;
+ USHORT nEndRow = nRow + pAttr->GetRowMerge() - 1;
+
+ RemoveFlagsTab( nCol, nRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
+
+ const ScMergeAttr* pDefAttr = (const ScMergeAttr*)
+ &pDocPool->GetDefaultItem( ATTR_MERGE );
+ ApplyAttr( nCol, nRow, nTab, *pDefAttr );
+}
+
+void ScDocument::ExtendPrintArea( OutputDevice* pDev, USHORT nTab,
+ USHORT nStartCol, USHORT nStartRow, USHORT& rEndCol, USHORT nEndRow )
+{
+ if ( nTab <= MAXTAB && pTab[nTab] )
+ pTab[nTab]->ExtendPrintArea( pDev, nStartCol, nStartRow, rEndCol, nEndRow );
+}
+
+void ScDocument::IncSizeRecalcLevel( USHORT nTab )
+{
+ if ( nTab <= MAXTAB && pTab[nTab] )
+ pTab[nTab]->IncRecalcLevel();
+}
+
+void ScDocument::DecSizeRecalcLevel( USHORT nTab )
+{
+ if ( nTab <= MAXTAB && pTab[nTab] )
+ pTab[nTab]->DecRecalcLevel();
+}
+
+
+
+
diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx
new file mode 100644
index 000000000000..e0b67754a5ed
--- /dev/null
+++ b/sc/source/core/data/documen4.cxx
@@ -0,0 +1,1265 @@
+/*************************************************************************
+ *
+ * $RCSfile: documen4.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <svtools/intitem.hxx>
+#include <svtools/zforlist.hxx>
+#include <vcl/sound.hxx>
+
+#include "document.hxx"
+#include "table.hxx"
+#include "globstr.hrc"
+#include "subtotal.hxx"
+#include "docoptio.hxx"
+#include "interpre.hxx"
+#include "markdata.hxx"
+#include "validat.hxx"
+#include "scitems.hxx"
+#include "stlpool.hxx"
+#include "detdata.hxx"
+#include "patattr.hxx"
+#include "chgtrack.hxx"
+#include "progress.hxx"
+
+// -----------------------------------------------------------------------
+
+// Nach der Regula Falsi Methode
+BOOL ScDocument::Solver(USHORT nFCol, USHORT nFRow, USHORT nFTab,
+ USHORT nVCol, USHORT nVRow, USHORT nVTab,
+ const String& sValStr, double& nX)
+{
+ BOOL bRet = FALSE;
+ nX = 0.0;
+ if (ValidColRow(nFCol, nFRow) && ValidColRow(nVCol, nVRow) &&
+ VALIDTAB(nFTab) && VALIDTAB(nVTab) && pTab[nFTab] && pTab[nVTab])
+ {
+ CellType eFType, eVType;
+ GetCellType(nFCol, nFRow, nFTab, eFType);
+ GetCellType(nVCol, nVRow, nVTab, eVType);
+ // CELLTYPE_NOTE: kein Value aber von Formel referiert
+ if (eFType == CELLTYPE_FORMULA && (eVType == CELLTYPE_VALUE
+ || eVType == CELLTYPE_NOTE) )
+ {
+ SingleRefData aRefData;
+ aRefData.InitFlags();
+ aRefData.nCol = nVCol;
+ aRefData.nRow = nVRow;
+ aRefData.nTab = nVTab;
+
+ ScTokenArray aArr;
+ aArr.AddOpCode( ocBackSolver );
+ aArr.AddOpCode( ocOpen );
+ aArr.AddSingleReference( aRefData );
+ aArr.AddOpCode( ocSep );
+
+ aRefData.nCol = nFCol;
+ aRefData.nRow = nFRow;
+ aRefData.nTab = nFTab;
+
+ aArr.AddSingleReference( aRefData );
+ aArr.AddOpCode( ocSep );
+ aArr.AddString( sValStr.GetBuffer() );
+ aArr.AddOpCode( ocClose );
+ aArr.AddOpCode( ocStop );
+
+ ScFormulaCell* pCell = new ScFormulaCell( this, ScAddress(), &aArr );
+
+ if (pCell)
+ {
+ pCell->Interpret();
+ USHORT nErrCode = pCell->GetErrCode();
+ nX = pCell->GetValue();
+ if (nErrCode == 0) // kein fehler beim Rechnen
+ bRet = TRUE;
+ delete pCell;
+ }
+ }
+ }
+ return bRet;
+}
+
+void ScDocument::InsertMatrixFormula(USHORT nCol1, USHORT nRow1,
+ USHORT nCol2, USHORT nRow2,
+ const ScMarkData& rMark,
+ const String& rFormula,
+ const ScTokenArray* pArr )
+{
+ PutInOrder(nCol1, nCol2);
+ PutInOrder(nRow1, nRow2);
+ USHORT i, j, k, nTab1;
+ i = 0;
+ BOOL bStop = FALSE;
+ while (i <= MAXTAB && !bStop) // erste markierte Tabelle finden
+ {
+ if (pTab[i] && rMark.GetTableSelect(i))
+ bStop = TRUE;
+ else
+ i++;
+ }
+ nTab1 = i;
+ if (i == MAXTAB + 1)
+ {
+ Sound::Beep();
+ DBG_ERROR("ScDocument::InsertMatrixFormula Keine Tabelle markiert");
+ return;
+ }
+ ScFormulaCell* pCell;
+ ScAddress aPos( nCol1, nRow1, nTab1 );
+ if (pArr)
+ pCell = new ScFormulaCell( this, aPos, pArr, MM_FORMULA );
+ else
+ pCell = new ScFormulaCell( this, aPos, rFormula, MM_FORMULA );
+ pCell->SetMatColsRows( nCol2 - nCol1 + 1, nRow2 - nRow1 + 1 );
+ for (i = 0; i <= MAXTAB; i++)
+ {
+ if (pTab[i] && rMark.GetTableSelect(i))
+ {
+ if (i == nTab1)
+ pTab[i]->PutCell(nCol1, nRow1, pCell);
+ else
+ pTab[i]->PutCell(nCol1, nRow1, pCell->Clone(this, ScAddress( nCol1, nRow1, i)));
+ }
+ }
+
+ SingleRefData aRefData;
+ aRefData.InitFlags();
+ aRefData.nCol = nCol1;
+ aRefData.nRow = nRow1;
+ aRefData.nTab = nTab1;
+ aRefData.SetColRel( TRUE );
+ aRefData.SetRowRel( TRUE );
+ aRefData.SetTabRel( TRUE );
+ aRefData.CalcRelFromAbs( ScAddress( nCol1, nRow1, nTab1 ) );
+
+ ScTokenArray aArr;
+ ScToken* t = aArr.AddSingleReference(aRefData);
+ t->NewOpCode( ocMatRef );
+
+ for (i = 0; i <= MAXTAB; i++)
+ {
+ if (pTab[i] && rMark.GetTableSelect(i))
+ {
+ if (i != nTab1)
+ {
+ aRefData.nTab = i;
+ aRefData.nRelTab = i - nTab1;
+ t->SetSingleReference( aRefData );
+ t->NewOpCode( ocMatRef );
+ }
+ for (j = nCol1; j <= nCol2; j++)
+ {
+ for (k = nRow1; k <= nRow2; k++)
+ {
+ if (j != nCol1 || k != nRow1) // nicht in der ersten Zelle
+ {
+ // Array muss geklont werden, damit jede
+ // Zelle ein eigenes Array erhaelt!
+ aPos = ScAddress( j, k, i );
+ t->aRef.CalcRelFromAbs( aPos );
+ pCell = new ScFormulaCell( this, aPos, aArr.Clone(), MM_REFERENCE );
+ pTab[i]->PutCell(j, k, (ScBaseCell*) pCell);
+ }
+ }
+ }
+ }
+ }
+}
+
+void ScDocument::InsertTableOp(const ScTabOpParam& rParam, // Mehrfachoperation
+ USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2,
+ const ScMarkData& rMark)
+{
+ PutInOrder(nCol1, nCol2);
+ PutInOrder(nRow1, nRow2);
+ USHORT i, j, k, nTab1;
+ i = 0;
+ BOOL bStop = FALSE;
+ while (i <= MAXTAB && !bStop) // erste markierte Tabelle finden
+ {
+ if (pTab[i] && rMark.GetTableSelect(i))
+ bStop = TRUE;
+ else
+ i++;
+ }
+ nTab1 = i;
+ if (i == MAXTAB + 1)
+ {
+ Sound::Beep();
+ DBG_ERROR("ScDocument::InsertTableOp: Keine Tabelle markiert");
+ return;
+ }
+ String aForString = '=';
+ if (ScCompiler::pSymbolTableNative)
+ aForString += ScCompiler::pSymbolTableNative[SC_OPCODE_TABLE_OP];
+ aForString += '(';
+ if (rParam.nMode == 0) // nur Spalte
+ {
+ for (i = nCol1+1; i <= nCol2; i++)
+ {
+ k = i - nCol1 - 1;
+ if (rParam.aRefFormulaCell.GetCol()+k <= rParam.aRefFormulaEnd.GetCol())
+ {
+ ScRefTripel aTrip;
+ aTrip.SetCol(rParam.aRefFormulaCell.GetCol()+k);
+ aTrip.SetRow(rParam.aRefFormulaCell.GetRow());
+ aTrip.SetTab(rParam.aRefFormulaCell.GetTab());
+ String aFString = aForString;
+ aFString += aTrip.GetRefString(this, nTab1);
+ aFString += ';';
+ aFString += rParam.aRefColCell.GetRefString(this, nTab1);
+ aFString += ';';
+ for (j = nRow1; j <= nRow2; j++)
+ {
+ aTrip.SetCol(nCol1);
+ aTrip.SetRow(j);
+ aTrip.SetTab(nTab1);
+ aTrip.SetRelCol(TRUE);
+ aTrip.SetRelRow(TRUE);
+ aTrip.SetRelTab(TRUE);
+ String aFormula = aFString;
+ aFormula += aTrip.GetRefString(this, nTab1);
+ aFormula += ')';
+ ScFormulaCell* pCell = new ScFormulaCell(this, ScAddress( i, j, nTab1 ),
+ aFormula, 0l);
+ for (k = 0; k <= MAXTAB; k++)
+ {
+ if (pTab[k] && rMark.GetTableSelect(k))
+ {
+ if (k == nTab1)
+ pTab[k]->PutCell(i, j, pCell);
+ else
+ pTab[k]->PutCell(i, j, pCell->Clone(this, ScAddress( i, j, k)));
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (rParam.nMode == 1) // nur zeilenweise
+ {
+ for (j = nRow1+1; j <= nRow2; j++)
+ {
+ k = j - nRow1 - 1;
+ if (rParam.aRefFormulaCell.GetRow()+k <= rParam.aRefFormulaEnd.GetRow())
+ {
+ ScRefTripel aTrip;
+ aTrip.SetCol(rParam.aRefFormulaCell.GetCol());
+ aTrip.SetRow(rParam.aRefFormulaCell.GetRow()+k);
+ aTrip.SetTab(rParam.aRefFormulaCell.GetTab());
+ String aFString = aForString;
+ aFString += aTrip.GetRefString(this, nTab1);
+ aFString += ';';
+ aFString += rParam.aRefRowCell.GetRefString(this, nTab1);
+ aFString += ';';
+ for (i = nCol1; i <= nCol2; i++)
+ {
+ aTrip.SetCol(i);
+ aTrip.SetRow(nRow1);
+ aTrip.SetTab(nTab1);
+ aTrip.SetRelCol(TRUE);
+ aTrip.SetRelRow(TRUE);
+ aTrip.SetRelTab(TRUE);
+ String aFormula = aFString;
+ aFormula += aTrip.GetRefString(this, nTab1);
+ aFormula += ')';
+ ScFormulaCell* pCell = new ScFormulaCell(this, ScAddress( i, j, nTab1 ),
+ aFormula, 0l);
+ for (k = 0; k <= MAXTAB; k++)
+ {
+ if (pTab[k] && rMark.GetTableSelect(k))
+ {
+ if (k == nTab1)
+ pTab[k]->PutCell(i, j, pCell);
+ else
+ pTab[k]->PutCell(i, j, pCell->Clone(this, ScAddress(i, j, k)));
+ }
+ }
+ }
+ }
+ }
+ }
+ else // beides
+ {
+ for (i = nCol1+1; i <= nCol2; i++)
+ {
+ ScRefTripel aTrip;
+ String aFString = aForString;
+ aFString += rParam.aRefFormulaCell.GetRefString(this, nTab1);
+ aFString += ';';
+ aFString += rParam.aRefColCell.GetRefString(this, nTab1);
+ aFString += ';';
+ for (j = nRow1+1; j <= nRow2; j++)
+ {
+ aTrip.SetCol(nCol1);
+ aTrip.SetRow(j);
+ aTrip.SetTab(nTab1);
+ aTrip.SetRelCol(TRUE);
+ aTrip.SetRelRow(TRUE);
+ aTrip.SetRelTab(TRUE);
+ String aFormula = aFString;
+ aFormula += aTrip.GetRefString(this, nTab1);
+ aFormula += ';';
+ aFormula += rParam.aRefRowCell.GetRefString(this, nTab1);
+ aFormula += ';';
+ aTrip.SetCol(i);
+ aTrip.SetRow(nRow1);
+ aTrip.SetTab(nTab1);
+ aTrip.SetRelCol(TRUE);
+ aTrip.SetRelRow(TRUE);
+ aTrip.SetRelTab(TRUE);
+ aFormula += aTrip.GetRefString(this, nTab1);
+ aFormula += ')';
+ ScFormulaCell* pCell = new ScFormulaCell(this, ScAddress( i, j, nTab1 ),
+ aFormula );
+ for (k = 0; k <= MAXTAB; k++)
+ {
+ if (pTab[k] && rMark.GetTableSelect(k))
+ {
+ if (k == nTab1)
+ pTab[k]->PutCell(i, j, pCell);
+ else
+ pTab[k]->PutCell(i, j, pCell->Clone(this, ScAddress( i, j, k)));
+ }
+ }
+ }
+ }
+ }
+}
+
+USHORT ScDocument::GetErrorData( USHORT nCol, USHORT nRow, USHORT nTab ) const
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ return pTab[nTab]->GetErrorData( nCol, nRow );
+ else
+ return 0;
+}
+
+BOOL ScDocument::GetNextSpellingCell(USHORT& nCol, USHORT& nRow, USHORT nTab,
+ BOOL bInSel, const ScMarkData& rMark) const
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ return pTab[nTab]->GetNextSpellingCell( nCol, nRow, bInSel, rMark );
+ else
+ return FALSE;
+}
+
+BOOL ScDocument::GetNextMarkedCell( USHORT& rCol, USHORT& rRow, USHORT nTab,
+ const ScMarkData& rMark )
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ return pTab[nTab]->GetNextMarkedCell( rCol, rRow, rMark );
+ else
+ return FALSE;
+}
+
+BOOL ScDocument::ReplaceStyle(const SvxSearchItem& rSearchItem,
+ USHORT nCol, USHORT nRow, USHORT nTab,
+ ScMarkData& rMark,
+ BOOL bIsUndo)
+{
+ if (pTab[nTab])
+ return pTab[nTab]->ReplaceStyle(rSearchItem, nCol, nRow, rMark, bIsUndo);
+ else
+ return FALSE;
+}
+
+void ScDocument::CompileDBFormula()
+{
+ for (USHORT i=0; i<=MAXTAB; i++)
+ {
+ if (pTab[i]) pTab[i]->CompileDBFormula();
+ }
+}
+
+void ScDocument::CompileDBFormula( BOOL bCreateFormulaString )
+{
+ for (USHORT i=0; i<=MAXTAB; i++)
+ {
+ if (pTab[i]) pTab[i]->CompileDBFormula( bCreateFormulaString );
+ }
+}
+
+void ScDocument::CompileNameFormula( BOOL bCreateFormulaString )
+{
+ if ( pCondFormList )
+ pCondFormList->CompileAll(); // nach ScNameDlg noetig
+
+ for (USHORT i=0; i<=MAXTAB; i++)
+ {
+ if (pTab[i]) pTab[i]->CompileNameFormula( bCreateFormulaString );
+ }
+}
+
+void ScDocument::CompileColRowNameFormula()
+{
+ for (USHORT i=0; i<=MAXTAB; i++)
+ {
+ if (pTab[i]) pTab[i]->CompileColRowNameFormula();
+ }
+}
+
+void ScDocument::DoColResize( USHORT nTab, USHORT nCol1, USHORT nCol2, USHORT nAdd )
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ pTab[nTab]->DoColResize( nCol1, nCol2, nAdd );
+ else
+ DBG_ERROR("DoColResize: falsche Tabelle");
+}
+
+void ScDocument::InvalidateTableArea()
+{
+ for (USHORT nTab=0; nTab<=MAXTAB && pTab[nTab]; nTab++)
+ {
+ pTab[nTab]->InvalidateTableArea();
+ if ( pTab[nTab]->IsScenario() )
+ pTab[nTab]->InvalidateScenarioRanges();
+ }
+}
+
+xub_StrLen ScDocument::GetMaxStringLen( USHORT nTab, USHORT nCol,
+ USHORT nRowStart, USHORT nRowEnd ) const
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ return pTab[nTab]->GetMaxStringLen( nCol, nRowStart, nRowEnd );
+ else
+ return 0;
+}
+
+xub_StrLen ScDocument::GetMaxNumberStringLen( USHORT& nPrecision, USHORT nTab,
+ USHORT nCol,
+ USHORT nRowStart, USHORT nRowEnd ) const
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ return pTab[nTab]->GetMaxNumberStringLen( nPrecision, nCol,
+ nRowStart, nRowEnd );
+ else
+ return 0;
+}
+
+BOOL ScDocument::GetSelectionFunction( ScSubTotalFunc eFunc,
+ const ScAddress& rCursor, const ScMarkData& rMark,
+ double& rResult )
+{
+ ScFunctionData aData(eFunc);
+
+ ScRange aSingle( rCursor );
+ if ( rMark.IsMarked() )
+ rMark.GetMarkArea(aSingle);
+
+ USHORT nStartCol = aSingle.aStart.Col();
+ USHORT nStartRow = aSingle.aStart.Row();
+ USHORT nEndCol = aSingle.aEnd.Col();
+ USHORT nEndRow = aSingle.aEnd.Row();
+
+ for (USHORT nTab=0; nTab<=MAXTAB && !aData.bError; nTab++)
+ if (pTab[nTab] && rMark.GetTableSelect(nTab))
+ pTab[nTab]->UpdateSelectionFunction( aData,
+ nStartCol, nStartRow, nEndCol, nEndRow, rMark );
+
+ //! rMark an UpdateSelectionFunction uebergeben !!!!!
+
+ if (!aData.bError)
+ switch (eFunc)
+ {
+ case SUBTOTAL_FUNC_SUM:
+ rResult = aData.nVal;
+ break;
+ case SUBTOTAL_FUNC_CNT:
+ case SUBTOTAL_FUNC_CNT2:
+ rResult = aData.nCount;
+ break;
+ case SUBTOTAL_FUNC_AVE:
+ if (aData.nCount)
+ rResult = aData.nVal / (double) aData.nCount;
+ else
+ aData.bError = TRUE;
+ break;
+ case SUBTOTAL_FUNC_MAX:
+ case SUBTOTAL_FUNC_MIN:
+ if (aData.nCount)
+ rResult = aData.nVal;
+ else
+ aData.bError = TRUE;
+ break;
+ }
+
+ if (aData.bError)
+ rResult = 0.0;
+
+ return !aData.bError;
+}
+
+double ScDocument::RoundValueAsShown( double fVal, ULONG nFormat )
+{
+ short nType;
+ if ( (nType = GetFormatTable()->GetType( nFormat )) != NUMBERFORMAT_DATE
+ && nType != NUMBERFORMAT_TIME && nType != NUMBERFORMAT_DATETIME )
+ {
+ short nPrecision;
+ if ( nFormat )
+ {
+ nPrecision = (short)GetFormatTable()->GetFormatPrecision( nFormat );
+ switch ( nType )
+ {
+ case NUMBERFORMAT_PERCENT: // 0,41% == 0,0041
+ nPrecision += 2;
+ break;
+ case NUMBERFORMAT_SCIENTIFIC: // 1,23e-3 == 0,00123
+ {
+ if ( fVal > 0.0 )
+ nPrecision -= (short)floor( log10( fVal ) );
+ else if ( fVal < 0.0 )
+ nPrecision -= (short)floor( log10( -fVal ) );
+ break;
+ }
+ }
+ }
+ else
+ nPrecision = (short)GetDocOptions().GetStdPrecision();
+ double fRound = SolarMath::Round( fVal, nPrecision );
+ if ( SolarMath::ApproxEqual( fVal, fRound ) )
+ return fVal; // durch Rundung hoechstens Fehler
+ else
+ return fRound;
+ }
+ else
+ return fVal;
+}
+
+//
+// bedingte Formate und Gueltigkeitsbereiche
+//
+
+ULONG ScDocument::AddCondFormat( const ScConditionalFormat& rNew )
+{
+ if (rNew.IsEmpty())
+ return 0; // leer ist immer 0
+
+ if (!pCondFormList)
+ pCondFormList = new ScConditionalFormatList;
+
+ ULONG nMax = 0;
+ USHORT nCount = pCondFormList->Count();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ const ScConditionalFormat* pForm = (*pCondFormList)[i];
+ ULONG nKey = pForm->GetKey();
+ if ( pForm->EqualEntries( rNew ) )
+ return nKey;
+ if ( nKey > nMax )
+ nMax = nKey;
+ }
+
+ // Der Aufruf kann aus ScPatternAttr::PutInPool kommen, darum Clone (echte Kopie)
+
+ ULONG nNewKey = nMax + 1;
+ ScConditionalFormat* pInsert = rNew.Clone(this);
+ pInsert->SetKey( nNewKey );
+ pCondFormList->InsertNew( pInsert );
+ return nNewKey;
+}
+
+ULONG ScDocument::AddValidationEntry( const ScValidationData& rNew )
+{
+ if (rNew.IsEmpty())
+ return 0; // leer ist immer 0
+
+ if (!pValidationList)
+ pValidationList = new ScValidationDataList;
+
+ ULONG nMax = 0;
+ USHORT nCount = pValidationList->Count();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ const ScValidationData* pData = (*pValidationList)[i];
+ ULONG nKey = pData->GetKey();
+ if ( pData->EqualEntries( rNew ) )
+ return nKey;
+ if ( nKey > nMax )
+ nMax = nKey;
+ }
+
+ // Der Aufruf kann aus ScPatternAttr::PutInPool kommen, darum Clone (echte Kopie)
+
+ ULONG nNewKey = nMax + 1;
+ ScValidationData* pInsert = rNew.Clone(this);
+ pInsert->SetKey( nNewKey );
+ pValidationList->InsertNew( pInsert );
+ return nNewKey;
+}
+
+const SfxPoolItem* ScDocument::GetEffItem(
+ USHORT nCol, USHORT nRow, USHORT nTab, USHORT nWhich ) const
+{
+ const ScPatternAttr* pPattern = GetPattern( nCol, nRow, nTab );
+ if ( pPattern )
+ {
+ const SfxItemSet& rSet = pPattern->GetItemSet();
+ const SfxPoolItem* pItem;
+ if ( rSet.GetItemState( ATTR_CONDITIONAL, TRUE, &pItem ) == SFX_ITEM_SET )
+ {
+ ULONG nIndex = ((const SfxUInt32Item*)pItem)->GetValue();
+ if (nIndex && pCondFormList)
+ {
+ const ScConditionalFormat* pForm = pCondFormList->GetFormat( nIndex );
+ if ( pForm )
+ {
+ ScBaseCell* pCell = ((ScDocument*)this)->GetCell(ScAddress(nCol,nRow,nTab));
+ String aStyle = pForm->GetCellStyle( pCell, ScAddress(nCol, nRow, nTab) );
+ if (aStyle.Len())
+ {
+ SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyle, SFX_STYLE_FAMILY_PARA );
+ if ( pStyleSheet && pStyleSheet->GetItemSet().GetItemState(
+ nWhich, TRUE, &pItem ) == SFX_ITEM_SET )
+ return pItem;
+ }
+ }
+ }
+ }
+ return &rSet.Get( nWhich );
+ }
+ DBG_ERROR("kein Pattern");
+ return NULL;
+}
+
+const SfxItemSet* ScDocument::GetCondResult( USHORT nCol, USHORT nRow, USHORT nTab ) const
+{
+ const ScConditionalFormat* pForm = GetCondFormat( nCol, nRow, nTab );
+ if ( pForm )
+ {
+ ScBaseCell* pCell = ((ScDocument*)this)->GetCell(ScAddress(nCol,nRow,nTab));
+ String aStyle = pForm->GetCellStyle( pCell, ScAddress(nCol, nRow, nTab) );
+ if (aStyle.Len())
+ {
+ SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyle, SFX_STYLE_FAMILY_PARA );
+ if ( pStyleSheet )
+ return &pStyleSheet->GetItemSet();
+ DBG_ERROR("Style nicht gefunden");
+ }
+ }
+ return NULL;
+}
+
+const ScConditionalFormat* ScDocument::GetCondFormat(
+ USHORT nCol, USHORT nRow, USHORT nTab ) const
+{
+ ULONG nIndex = ((const SfxUInt32Item*)GetAttr(nCol,nRow,nTab,ATTR_CONDITIONAL))->GetValue();
+ if (nIndex)
+ {
+ if (pCondFormList)
+ return pCondFormList->GetFormat( nIndex );
+ else
+ DBG_ERROR("pCondFormList ist 0");
+ }
+
+ return NULL;
+}
+
+const ScValidationData* ScDocument::GetValidationEntry( ULONG nIndex ) const
+{
+ if ( pValidationList )
+ return pValidationList->GetData( nIndex );
+ else
+ return NULL;
+}
+
+void ScDocument::FindConditionalFormat( ULONG nKey, ScRangeList& rRanges )
+{
+ for (USHORT i=0; i<=MAXTAB && pTab[i]; i++)
+ pTab[i]->FindConditionalFormat( nKey, rRanges );
+}
+
+
+void ScDocument::ConditionalChanged( ULONG nKey )
+{
+ if ( nKey && pCondFormList && !bIsClip && !bIsUndo ) // nKey==0 -> noop
+ {
+ ScConditionalFormat* pForm = pCondFormList->GetFormat( nKey );
+ if (pForm)
+ pForm->InvalidateArea();
+ }
+}
+
+void ScDocument::SetConditionalUsed( ULONG nKey ) // aus dem Speichern der Tabellen
+{
+ if ( nKey && pCondFormList ) // nKey==0 -> noop
+ {
+ ScConditionalFormat* pForm = pCondFormList->GetFormat( nKey );
+ if (pForm)
+ pForm->SetUsed(TRUE);
+ }
+}
+
+void ScDocument::SetValidationUsed( ULONG nKey ) // aus dem Speichern der Tabellen
+{
+ if ( nKey && pValidationList ) // nKey==0 -> noop
+ {
+ ScValidationData* pData = pValidationList->GetData( nKey );
+ if (pData)
+ pData->SetUsed(TRUE);
+ }
+}
+
+void ScDocument::SetCondFormList(ScConditionalFormatList* pNew)
+{
+ if (pCondFormList)
+ {
+ pCondFormList->DeleteAndDestroy( 0, pCondFormList->Count() );
+ delete pCondFormList;
+ }
+
+ pCondFormList = pNew;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScDocument::HasDetectiveOperations() const
+{
+ return pDetOpList && pDetOpList->Count();
+}
+
+void ScDocument::AddDetectiveOperation( const ScDetOpData& rData )
+{
+ if (!pDetOpList)
+ pDetOpList = new ScDetOpList;
+
+ pDetOpList->Append( new ScDetOpData( rData ) );
+}
+
+void ScDocument::ClearDetectiveOperations()
+{
+ delete pDetOpList; // loescht auch die Eintraege
+ pDetOpList = NULL;
+}
+
+void ScDocument::SetDetOpList(ScDetOpList* pNew)
+{
+ delete pDetOpList; // loescht auch die Eintraege
+ pDetOpList = pNew;
+}
+
+//------------------------------------------------------------------------
+//
+// Vergleich von Dokumenten
+//
+//------------------------------------------------------------------------
+
+// Pfriemel-Faktoren
+#define SC_DOCCOMP_MAXDIFF 256
+#define SC_DOCCOMP_MINGOOD 128
+#define SC_DOCCOMP_COLUMNS 10
+#define SC_DOCCOMP_ROWS 100
+
+
+USHORT ScDocument::RowDifferences( USHORT nThisRow, USHORT nThisTab,
+ ScDocument& rOtherDoc, USHORT nOtherRow, USHORT nOtherTab,
+ USHORT nMaxCol, USHORT* pOtherCols )
+{
+ USHORT nDif = 0;
+ USHORT nUsed = 0;
+ for (USHORT nThisCol=0; nThisCol<=nMaxCol; nThisCol++)
+ {
+ USHORT nOtherCol;
+ if ( pOtherCols )
+ nOtherCol = pOtherCols[nThisCol];
+ else
+ nOtherCol = nThisCol;
+
+ if (nOtherCol <= MAXCOL) // nur Spalten vergleichen, die in beiden Dateien sind
+ {
+ const ScBaseCell* pThisCell = GetCell( ScAddress( nThisCol, nThisRow, nThisTab ) );
+ const ScBaseCell* pOtherCell = rOtherDoc.GetCell( ScAddress( nOtherCol, nOtherRow, nOtherTab ) );
+ if (!ScBaseCell::CellEqual( pThisCell, pOtherCell ))
+ {
+ if ( pThisCell && pOtherCell )
+ nDif += 3;
+ else
+ nDif += 4; // Inhalt <-> leer zaehlt mehr
+ }
+
+ if ( ( pThisCell && pThisCell->GetCellType()!=CELLTYPE_NOTE ) ||
+ ( pOtherCell && pOtherCell->GetCellType()!=CELLTYPE_NOTE ) )
+ ++nUsed;
+ }
+ }
+
+ if (nUsed)
+ return (nDif*64)/nUsed; // max.256 (SC_DOCCOMP_MAXDIFF)
+
+ DBG_ASSERT(!nDif,"Diff ohne Used");
+ return 0;
+}
+
+USHORT ScDocument::ColDifferences( USHORT nThisCol, USHORT nThisTab,
+ ScDocument& rOtherDoc, USHORT nOtherCol, USHORT nOtherTab,
+ USHORT nMaxRow, USHORT* pOtherRows )
+{
+ //! optimieren mit Iterator oder so
+
+ USHORT nDif = 0;
+ USHORT nUsed = 0;
+ for (USHORT nThisRow=0; nThisRow<=nMaxRow; nThisRow++)
+ {
+ USHORT nOtherRow;
+ if ( pOtherRows )
+ nOtherRow = pOtherRows[nThisRow];
+ else
+ nOtherRow = nThisRow;
+
+ if (nOtherRow <= MAXROW) // nur Zeilen vergleichen, die in beiden Dateien sind
+ {
+ const ScBaseCell* pThisCell = GetCell( ScAddress( nThisCol, nThisRow, nThisTab ) );
+ const ScBaseCell* pOtherCell = rOtherDoc.GetCell( ScAddress( nOtherCol, nOtherRow, nOtherTab ) );
+ if (!ScBaseCell::CellEqual( pThisCell, pOtherCell ))
+ {
+ if ( pThisCell && pOtherCell )
+ nDif += 3;
+ else
+ nDif += 4; // Inhalt <-> leer zaehlt mehr
+ }
+
+ if ( ( pThisCell && pThisCell->GetCellType()!=CELLTYPE_NOTE ) ||
+ ( pOtherCell && pOtherCell->GetCellType()!=CELLTYPE_NOTE ) )
+ ++nUsed;
+ }
+ }
+
+ if (nUsed)
+ return (nDif*64)/nUsed; // max.256
+
+ DBG_ASSERT(!nDif,"Diff ohne Used");
+ return 0;
+}
+
+void ScDocument::FindOrder( USHORT* pOtherRows, USHORT nThisEndRow, USHORT nOtherEndRow,
+ BOOL bColumns, ScDocument& rOtherDoc, USHORT nThisTab, USHORT nOtherTab,
+ USHORT nEndCol, USHORT* pTranslate, ScProgress* pProgress, ULONG nProAdd )
+{
+ // bColumns=TRUE: Zeilen sind Spalten und umgekehrt
+
+ USHORT nMaxCont; // wieviel weiter
+ USHORT nMinGood; // was ist ein Treffer (incl.)
+ if ( bColumns )
+ {
+ nMaxCont = SC_DOCCOMP_COLUMNS; // 10 Spalten
+ nMinGood = SC_DOCCOMP_MINGOOD;
+ //! Extra Durchgang mit nMinGood = 0 ????
+ }
+ else
+ {
+ nMaxCont = SC_DOCCOMP_ROWS; // 100 Zeilen
+ nMinGood = SC_DOCCOMP_MINGOOD;
+ }
+ BOOL bUseTotal = bColumns && !pTranslate; // nur beim ersten Durchgang
+
+
+ USHORT nOtherRow = 0;
+ USHORT nComp;
+ USHORT nThisRow;
+ BOOL bTotal = FALSE; // ueber verschiedene nThisRow beibehalten
+ USHORT nUnknown = 0;
+ for (nThisRow = 0; nThisRow <= nThisEndRow; nThisRow++)
+ {
+ USHORT nTempOther = nOtherRow;
+ BOOL bFound = FALSE;
+ USHORT nBest = SC_DOCCOMP_MAXDIFF;
+ USHORT nMax = Min( nOtherEndRow, (USHORT)( nTempOther + nMaxCont + nUnknown ) );
+ for (USHORT i=nTempOther; i<=nMax && nBest; i++) // bei 0 abbrechen
+ {
+ if (bColumns)
+ nComp = ColDifferences( nThisRow, nThisTab, rOtherDoc, i, nOtherTab, nEndCol, pTranslate );
+ else
+ nComp = RowDifferences( nThisRow, nThisTab, rOtherDoc, i, nOtherTab, nEndCol, pTranslate );
+ if ( nComp < nBest && ( nComp <= nMinGood || bTotal ) )
+ {
+ nTempOther = i;
+ nBest = nComp;
+ bFound = TRUE;
+ }
+ if ( nComp < SC_DOCCOMP_MAXDIFF || bFound )
+ bTotal = FALSE;
+ else if ( i == nTempOther && bUseTotal )
+ bTotal = TRUE; // nur ganz oben
+ }
+ if ( bFound )
+ {
+ pOtherRows[nThisRow] = nTempOther;
+ nOtherRow = nTempOther + 1;
+ nUnknown = 0;
+ }
+ else
+ {
+ pOtherRows[nThisRow] = USHRT_MAX;
+ ++nUnknown;
+ }
+
+ if (pProgress)
+ pProgress->SetStateOnPercent(nProAdd+nThisRow);
+ }
+
+ // Bloecke ohne Uebereinstimmung ausfuellen
+
+ USHORT nFillStart = 0;
+ USHORT nFillPos = 0;
+ BOOL bInFill = FALSE;
+ for (nThisRow = 0; nThisRow <= nThisEndRow+1; nThisRow++)
+ {
+ USHORT nThisOther = ( nThisRow <= nThisEndRow ) ? pOtherRows[nThisRow] : (nOtherEndRow+1);
+ if ( nThisOther <= MAXROW )
+ {
+ if ( bInFill )
+ {
+ if ( nThisOther > nFillStart ) // ist was zu verteilen da?
+ {
+ USHORT nDiff1 = nThisOther - nFillStart;
+ USHORT nDiff2 = nThisRow - nFillPos;
+ USHORT nMinDiff = Min(nDiff1, nDiff2);
+ for (USHORT i=0; i<nMinDiff; i++)
+ pOtherRows[nFillPos+i] = nFillStart+i;
+ }
+
+ bInFill = FALSE;
+ }
+ nFillStart = nThisOther + 1;
+ nFillPos = nThisRow + 1;
+ }
+ else
+ bInFill = TRUE;
+ }
+}
+
+void ScDocument::CompareDocument( ScDocument& rOtherDoc )
+{
+ if (!pChangeTrack)
+ return;
+
+ USHORT nThisCount = GetTableCount();
+ USHORT nOtherCount = rOtherDoc.GetTableCount();
+ USHORT* pOtherTabs = new USHORT[nThisCount];
+ USHORT nThisTab;
+
+ // Tabellen mit gleichen Namen vergleichen
+ String aThisName;
+ String aOtherName;
+ for (nThisTab=0; nThisTab<nThisCount; nThisTab++)
+ {
+ USHORT nOtherTab = USHRT_MAX;
+ if (!IsScenario(nThisTab)) // Szenarien weglassen
+ {
+ GetName( nThisTab, aThisName );
+ for (USHORT nTemp=0; nTemp<nOtherCount && nOtherTab>MAXTAB; nTemp++)
+ if (!rOtherDoc.IsScenario(nTemp))
+ {
+ rOtherDoc.GetName( nTemp, aOtherName );
+ if ( aThisName == aOtherName )
+ nOtherTab = nTemp;
+ }
+ }
+ pOtherTabs[nThisTab] = nOtherTab;
+ }
+ // auffuellen, damit einzeln umbenannte Tabellen nicht wegfallen
+ USHORT nFillStart = 0;
+ USHORT nFillPos = 0;
+ BOOL bInFill = FALSE;
+ for (nThisTab = 0; nThisTab <= nThisCount; nThisTab++)
+ {
+ USHORT nThisOther = ( nThisTab < nThisCount ) ? pOtherTabs[nThisTab] : nOtherCount;
+ if ( nThisOther <= MAXTAB )
+ {
+ if ( bInFill )
+ {
+ if ( nThisOther > nFillStart ) // ist was zu verteilen da?
+ {
+ USHORT nDiff1 = nThisOther - nFillStart;
+ USHORT nDiff2 = nThisTab - nFillPos;
+ USHORT nMinDiff = Min(nDiff1, nDiff2);
+ for (USHORT i=0; i<nMinDiff; i++)
+ if ( !IsScenario(nFillPos+i) && !rOtherDoc.IsScenario(nFillStart+i) )
+ pOtherTabs[nFillPos+i] = nFillStart+i;
+ }
+
+ bInFill = FALSE;
+ }
+ nFillStart = nThisOther + 1;
+ nFillPos = nThisTab + 1;
+ }
+ else
+ bInFill = TRUE;
+ }
+
+ //
+ // Tabellen in der gefundenen Reihenfolge vergleichen
+ //
+
+ for (nThisTab=0; nThisTab<nThisCount; nThisTab++)
+ {
+ USHORT nOtherTab = pOtherTabs[nThisTab];
+ if ( nOtherTab <= MAXTAB )
+ {
+ USHORT nThisEndCol = 0;
+ USHORT nThisEndRow = 0;
+ USHORT nOtherEndCol = 0;
+ USHORT nOtherEndRow = 0;
+ GetCellArea( nThisTab, nThisEndCol, nThisEndRow );
+ rOtherDoc.GetCellArea( nOtherTab, nOtherEndCol, nOtherEndRow );
+ USHORT nEndCol = Max(nThisEndCol, nOtherEndCol);
+ USHORT nEndRow = Max(nThisEndRow, nOtherEndRow);
+ USHORT nThisCol, nThisRow;
+ ULONG n1,n2; // fuer AppendDeleteRange
+
+ //! ein Progress ueber alle Tabellen ???
+ String aTabName;
+ GetName( nThisTab, aTabName );
+ String aTemplate = ScGlobal::GetRscString(STR_PROGRESS_COMPARING);
+ String aProText = aTemplate.GetToken( 0, '#' );
+ aProText += aTabName;
+ aProText += aTemplate.GetToken( 1, '#' );
+ ScProgress aProgress( GetDocumentShell(),
+ aProText, 3*nThisEndRow ); // 2x FindOrder, 1x hier
+ long nProgressStart = 2*nThisEndRow; // start fuer hier
+
+ USHORT* pTempRows = new USHORT[nThisEndRow+1];
+ USHORT* pOtherRows = new USHORT[nThisEndRow+1];
+ USHORT* pOtherCols = new USHORT[nThisEndCol+1];
+
+ // eingefuegte/geloeschte Spalten/Zeilen finden:
+ // Zwei Versuche:
+ // 1) Original Zeilen vergleichen (pTempRows)
+ // 2) Original Spalten vergleichen (pOtherCols)
+ // mit dieser Spaltenreihenfolge Zeilen vergleichen (pOtherRows)
+
+ //! Spalten vergleichen zweimal mit unterschiedlichem nMinGood ???
+
+ // 1
+ FindOrder( pTempRows, nThisEndRow, nOtherEndRow, FALSE,
+ rOtherDoc, nThisTab, nOtherTab, nEndCol, NULL, &aProgress, 0 );
+ // 2
+ FindOrder( pOtherCols, nThisEndCol, nOtherEndCol, TRUE,
+ rOtherDoc, nThisTab, nOtherTab, nEndRow, NULL, NULL, 0 );
+ FindOrder( pOtherRows, nThisEndRow, nOtherEndRow, FALSE,
+ rOtherDoc, nThisTab, nOtherTab, nThisEndCol,
+ pOtherCols, &aProgress, nThisEndRow );
+
+ ULONG nMatch1 = 0; // pTempRows, keine Spalten
+ for (nThisRow = 0; nThisRow<=nThisEndRow; nThisRow++)
+ if (pTempRows[nThisRow] <= MAXROW)
+ nMatch1 += SC_DOCCOMP_MAXDIFF -
+ RowDifferences( nThisRow, nThisTab, rOtherDoc, pTempRows[nThisRow],
+ nOtherTab, nEndCol, NULL );
+
+ ULONG nMatch2 = 0; // pOtherRows, pOtherCols
+ for (nThisRow = 0; nThisRow<=nThisEndRow; nThisRow++)
+ if (pOtherRows[nThisRow] <= MAXROW)
+ nMatch2 += SC_DOCCOMP_MAXDIFF -
+ RowDifferences( nThisRow, nThisTab, rOtherDoc, pOtherRows[nThisRow],
+ nOtherTab, nThisEndCol, pOtherCols );
+
+ if ( nMatch1 >= nMatch2 ) // ohne Spalten ?
+ {
+ // Spalten zuruecksetzen
+ for (nThisCol = 0; nThisCol<=nThisEndCol; nThisCol++)
+ pOtherCols[nThisCol] = nThisCol;
+
+ // Zeilenarrays vertauschen (geloescht werden sowieso beide)
+ USHORT* pSwap = pTempRows;
+ pTempRows = pOtherRows;
+ pOtherRows = pSwap;
+ }
+ else
+ {
+ // bleibt bei pOtherCols, pOtherRows
+ }
+
+
+ // Change-Actions erzeugen
+ // 1) Spalten von rechts
+ // 2) Zeilen von unten
+ // 3) einzelne Zellen in normaler Reihenfolge
+
+ // Actions fuer eingefuegte/geloeschte Spalten
+
+ USHORT nLastOtherCol = nOtherEndCol + 1;
+ // nThisEndCol ... 0
+ for ( nThisCol = nThisEndCol+1; nThisCol > 0; )
+ {
+ --nThisCol;
+ USHORT nOtherCol = pOtherCols[nThisCol];
+ if ( nOtherCol <= MAXCOL && nOtherCol+1 < nLastOtherCol )
+ {
+ // Luecke -> geloescht
+ ScRange aDelRange( nOtherCol+1, 0, nOtherTab,
+ nLastOtherCol-1, MAXROW, nOtherTab );
+ pChangeTrack->AppendDeleteRange( aDelRange, &rOtherDoc, n1, n2 );
+ }
+ if ( nOtherCol > MAXCOL ) // eingefuegt
+ {
+ // zusammenfassen
+ if ( nThisCol == nThisEndCol || pOtherCols[nThisCol+1] <= MAXCOL )
+ {
+ USHORT nFirstNew = nThisCol;
+ while ( nFirstNew > 0 && pOtherCols[nFirstNew-1] > MAXCOL )
+ --nFirstNew;
+ USHORT nDiff = nThisCol - nFirstNew;
+ ScRange aRange( nLastOtherCol, 0, nOtherTab,
+ nLastOtherCol+nDiff, MAXROW, nOtherTab );
+ pChangeTrack->AppendInsert( aRange );
+ }
+ }
+ else
+ nLastOtherCol = nOtherCol;
+ }
+ if ( nLastOtherCol > 0 ) // ganz oben geloescht
+ {
+ ScRange aDelRange( 0, 0, nOtherTab,
+ nLastOtherCol-1, MAXROW, nOtherTab );
+ pChangeTrack->AppendDeleteRange( aDelRange, &rOtherDoc, n1, n2 );
+ }
+
+ // Actions fuer eingefuegte/geloeschte Zeilen
+
+ USHORT nLastOtherRow = nOtherEndRow + 1;
+ // nThisEndRow ... 0
+ for ( nThisRow = nThisEndRow+1; nThisRow > 0; )
+ {
+ --nThisRow;
+ USHORT nOtherRow = pOtherRows[nThisRow];
+ if ( nOtherRow <= MAXROW && nOtherRow+1 < nLastOtherRow )
+ {
+ // Luecke -> geloescht
+ ScRange aDelRange( 0, nOtherRow+1, nOtherTab,
+ MAXCOL, nLastOtherRow-1, nOtherTab );
+ pChangeTrack->AppendDeleteRange( aDelRange, &rOtherDoc, n1, n2 );
+ }
+ if ( nOtherRow > MAXROW ) // eingefuegt
+ {
+ // zusammenfassen
+ if ( nThisRow == nThisEndRow || pOtherRows[nThisRow+1] <= MAXROW )
+ {
+ USHORT nFirstNew = nThisRow;
+ while ( nFirstNew > 0 && pOtherRows[nFirstNew-1] > MAXROW )
+ --nFirstNew;
+ USHORT nDiff = nThisRow - nFirstNew;
+ ScRange aRange( 0, nLastOtherRow, nOtherTab,
+ MAXCOL, nLastOtherRow+nDiff, nOtherTab );
+ pChangeTrack->AppendInsert( aRange );
+ }
+ }
+ else
+ nLastOtherRow = nOtherRow;
+ }
+ if ( nLastOtherRow > 0 ) // ganz oben geloescht
+ {
+ ScRange aDelRange( 0, 0, nOtherTab,
+ MAXCOL, nLastOtherRow-1, nOtherTab );
+ pChangeTrack->AppendDeleteRange( aDelRange, &rOtherDoc, n1, n2 );
+ }
+
+ // Zeilen durchgehen um einzelne Zellen zu finden
+
+ for (nThisRow = 0; nThisRow <= nThisEndRow; nThisRow++)
+ {
+ USHORT nOtherRow = pOtherRows[nThisRow];
+ for (USHORT nThisCol = 0; nThisCol <= nThisEndCol; nThisCol++)
+ {
+ USHORT nOtherCol = pOtherCols[nThisCol];
+ ScAddress aThisPos( nThisCol, nThisRow, nThisTab );
+ const ScBaseCell* pThisCell = GetCell( aThisPos );
+ const ScBaseCell* pOtherCell = NULL;
+ if ( nOtherCol <= MAXCOL && nOtherRow <= MAXROW )
+ {
+ ScAddress aOtherPos( nOtherCol, nOtherRow, nOtherTab );
+ pOtherCell = rOtherDoc.GetCell( aOtherPos );
+ }
+ if ( !ScBaseCell::CellEqual( pThisCell, pOtherCell ) )
+ {
+ ScRange aRange( aThisPos );
+ ScChangeActionContent* pAction = new ScChangeActionContent( aRange );
+ pAction->SetOldValue( pOtherCell, &rOtherDoc, this );
+ pAction->SetNewValue( pThisCell, this );
+ pChangeTrack->Append( pAction );
+ }
+ }
+ aProgress.SetStateOnPercent(nProgressStart+nThisRow);
+ }
+
+ delete[] pOtherCols;
+ delete[] pOtherRows;
+ delete[] pTempRows;
+ }
+ }
+
+ //! Inhalt von eingefuegten / geloeschten Tabellen ???
+ //! Aktionen fuer eingefuegte / geloeschte Tabellen ???
+
+ delete[] pOtherTabs;
+}
+
+
+
+
+
diff --git a/sc/source/core/data/documen5.cxx b/sc/source/core/data/documen5.cxx
new file mode 100644
index 000000000000..9630f25f7ea8
--- /dev/null
+++ b/sc/source/core/data/documen5.cxx
@@ -0,0 +1,709 @@
+/*************************************************************************
+ *
+ * $RCSfile: documen5.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#pragma optimize("",off)
+#pragma optimize("q",off) // p-code off
+
+//------------------------------------------------------------------------
+
+#define _SV_NOXSOUND
+
+#define _BASDLG_HXX
+#define _CACHESTR_HXX
+#define _CURSOR_HXX
+#define _CTRLTOOL_HXX
+#define _DLGCFG_HXX
+#define _EXTATTR_HXX
+#define _FILDLG_HXX
+#define _FRM3D_HXX
+#define _INTRO_HXX
+#define _ISETBWR_HXX
+#define _NO_SVRTF_PARSER_HXX
+#define _MACRODLG_HXX
+#define _MODALDLG_HXX
+#define _MOREBUTTON_HXX
+#define _OUTLINER_HXX
+#define _PASSWD_HXX
+
+#define _PVRWIN_HXX
+
+//#define _PRNDLG_HXX
+//#define _POLY_HXX
+#define _QUEUE_HXX
+#define _RULER_HXX
+#define _SCRWIN_HXX
+#define _SETBRW_HXX
+//#define _STATUS_HXX
+#define _STDMENU_HXX
+#define _TABBAR_HXX
+
+// TOOLS
+#define _BIGINT_HXX
+#define _SFXMULTISEL_HXX
+#define _STACK_HXX
+#define _QUEUE_HXX
+#define _DYNARR_HXX
+//#define _TREELIST_HXX
+#define _CACHESTR_HXX
+
+//SV
+#define _CLIP_HXX
+//#define _CONFIG_HXX
+#define _CURSOR_HXX
+#define _FONTDLG_HXX
+#define _PRVWIN_HXX
+
+#ifndef OS2
+#define _MENUBTN_HXX
+#endif
+
+
+#define _SFX_DOCFILE_HXX
+#define _SFX_DOCFILT_HXX
+#define _SFX_DOCINF_HXX
+#define _SFX_DOCSH_HXX
+#define _SFX_INTERNO_HXX
+#define _SFX_PRNMON_HXX
+#define _SFX_RESMGR_HXX
+#define _SFX_TEMPLDLG_HXX
+#define _SFXAPPWIN_HXX
+#define _SFXBASIC_HXX
+#define _SFXCTRLITEM
+#define _SFXDLGCFG_HXX
+#define _SFXDISPATCH_HXX
+#define _SFXDOCFILE_HXX
+#define _SFXDOCMAN_HXX
+#define _SFXDOCMGR_HXX
+#define _SFXDOCTDLG_HXX
+#define _SFXFILEDLG_HXX
+#define _SFXIMGMGR_HXX
+#define _SFXIPFRM_HXX
+#define _SFX_MACRO_HXX
+#define _SFXMNUITEM_HXX
+#define _SFXMNUMGR_HXX
+#define _SFXMULTISEL_HXX
+#define _SFXMSG_HXX
+#define _SFXMSGDESCR_HXX
+#define _SFXMSGPOOL_HXX
+#define _SFX_MINFITEM_HXX
+#define _SFXOBJFACE_HXX
+#define _SFXOBJFAC_HXX
+#define _SFX_SAVEOPT_HXX
+#define _SFXSTBITEM_HXX
+//#define _SFXSTBMGR_HXX
+#define _SFXTBXCTRL_HXX
+#define _SFXTBXMGR_HXX
+
+#define _SFXGENLINK_HXX
+#define _SFXHINTPOST_HXX
+#define _SFXLINKHDL_HXX
+#define _XTABLE_HXX
+#define SFX_NOCLOOKS
+
+#define _SIDLL_HXX
+#define _SI_NOITEMS_HXX
+#define _SI_NODRW_HXX
+#define _SI_NOCONTROL_HXX
+#define _SI_NOOTHERFORMS_HXX
+#define _SI_NOSBXCONTROLS_HXX
+#define _VCBRW_HXX
+#define _VCTRLS_HXX
+//#define _VCSBX_HXX
+#define _VCONT_HXX
+#define _VDRWOBJ_HXX
+
+#define _SVBOXITM_HXX
+#define _SVCONTNR_HXX
+//#define _SVDATTR_HXX
+#define _SVDXOUT_HXX
+#define _SVDEC_HXX
+#define _SVDIALDLL_HXX
+#define _SVDIO_HXX //*
+//#define _SVDLAYER_HXX ***
+#define _SVDRAG_HXX
+#define _SVINCVW_HXX
+#define _SV_MULTISEL_HXX
+#define _SVRTV_HXX
+#define _SVTABBX_HXX
+#define _SVTREEBOX_HXX
+#define _SVTREELIST_HXX
+
+
+#define _SVX_DAILDLL_HXX
+#define _SVX_HYPHEN_HXX
+#define _SVX_IMPGRF_HXX
+#define _SVX_OPTITEMS_HXX
+#define _SVX_OPTGERL_HXX
+#define _SVX_OPTSAVE_HXX
+#define _SVX_OPTSPELL_HXX
+#define _SVX_OPTPATH_HXX
+#define _SVX_OPTLINGU_HXX
+#define _SVX_RULER_HXX
+#define _SVX_RULRITEM_HXX
+#define _SVX_SPLWRAP_HXX
+#define _SVX_SPLDLG_HXX
+#define _SVX_THESDLG_HXX
+
+//svdraw.hxx
+#define _SDR_NOVIEWMARKER
+#define _SDR_NODRAGMETHODS
+#define _SDR_NOXOUTDEV
+#define _SDR_NOITEMS
+#define _SDR_NOTOUCH
+#define _SDR_NOTRANSFORM // Transformationen, selten verwendet
+#define _SDR_NOTOUCH // Hit-Tests, selten verwendet
+
+#define _SDR_NOEXTDEV // ExtOutputDevice
+//#define _SDR_NOUNDO // Undo-Objekte
+#define _SDR_NOSURROGATEOBJ // SdrObjSurrogate
+#define _SDR_NOPAGEOBJ // SdrPageObj
+#define _SDR_NOVIRTOBJ // SdrVirtObj
+#define _SDR_NOGROUPOBJ // SdrGroupObj
+#define _SDR_NOTEXTOBJ // SdrTextObj
+#define _SDR_NOPATHOBJ // SdrPathObj
+#define _SDR_NOEDGEOBJ // SdrEdgeObj
+#define _SDR_NORECTOBJ // SdrRectObj
+#define _SDR_NOCAPTIONOBJ // SdrCaptionObj
+#define _SDR_NOCIRCLEOBJ // SdrCircleObj
+#define _SDR_NOGRAFOBJ // SdrGrafObj
+#define _SDR_NOOLE2OBJ // SdrOle2Obj
+
+
+
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <sfx2/objsh.hxx>
+#include <svx/svditer.hxx>
+#include <svx/svdoole2.hxx>
+#include <svx/svdpage.hxx>
+#include <sch/schdll.hxx>
+#include <sch/memchrt.hxx>
+#include <sch/schdll0.hxx>
+#include <so3/ipobj.hxx>
+
+#ifndef SO2_DECL_SVINPLACEOBJECT_DEFINED
+#define SO2_DECL_SVINPLACEOBJECT_DEFINED
+SO2_DECL_REF(SvInPlaceObject)
+#endif
+
+#include "document.hxx"
+#include "drwlayer.hxx"
+#include "chartarr.hxx"
+#include "chartlis.hxx"
+#include "refupdat.hxx"
+
+// -----------------------------------------------------------------------
+
+ // Charts aus altem Dokument updaten
+
+void ScDocument::UpdateAllCharts(BOOL bDoUpdate)
+{
+ if (!pDrawLayer)
+ return;
+
+ USHORT nDataCount = pChartCollection->GetCount();
+ if ( !nDataCount )
+ return ; // nothing to do
+
+ USHORT nPos;
+
+ for (USHORT nTab=0; nTab<=MAXTAB; nTab++)
+ {
+ if (pTab[nTab])
+ {
+ SdrPage* pPage = pDrawLayer->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+
+ ScRange aRange;
+ SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ if ( pObject->GetObjIdentifier() == OBJ_OLE2 )
+ {
+ SvInPlaceObjectRef aIPObj = ((SdrOle2Obj*)pObject)->GetObjRef();
+ if (aIPObj.Is())
+ {
+ // String aIPName = aIPObj->GetName()->GetName();
+
+ SvInfoObject* pInfoObj = pShell->Find( aIPObj );
+ String aIPName;
+
+ if ( pInfoObj )
+ aIPName = pInfoObj->GetObjName();
+
+ for (nPos=0; nPos<nDataCount; nPos++)
+ {
+ ScChartArray* pChartObj = (*pChartCollection)[nPos];
+ if (pChartObj->GetName() == aIPName)
+ {
+ if (bDoUpdate)
+ {
+ SchMemChart* pMemChart = pChartObj->CreateMemChart();
+ SchDLL::Update( aIPObj, pMemChart );
+ delete pMemChart;
+ }
+ else // nur Position uebernehmen
+ {
+ SchMemChart* pChartData = SchDLL::GetChartData(aIPObj);
+ if (pChartData)
+ {
+ pChartObj->SetExtraStrings(*pChartData);
+// aIPObj->SetModified( TRUE );
+ }
+ }
+ ScChartListener* pCL = new ScChartListener(
+ aIPName, this, pChartObj->GetRangeList() );
+ pChartListenerCollection->Insert( pCL );
+ pCL->StartListeningTo();
+ }
+ }
+ }
+ }
+ pObject = aIter.Next();
+ }
+ }
+ }
+
+ pChartCollection->FreeAll();
+}
+
+BOOL ScDocument::HasChartAtPoint( USHORT nTab, const Point& rPos, String* pName )
+{
+ if (pDrawLayer && pTab[nTab])
+ {
+ SdrPage* pPage = pDrawLayer->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+
+ SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
+ pObject->GetBoundRect().IsInside(rPos) )
+ {
+ // auch Chart-Objekte die nicht in der Collection sind
+
+ if (IsChart(pObject))
+ {
+ if (pName)
+ *pName = ((SdrOle2Obj*)pObject)->GetName();
+ return TRUE;
+ }
+ }
+ pObject = aIter.Next();
+ }
+ }
+
+ if (pName)
+ pName->Erase();
+ return FALSE; // nix gefunden
+}
+
+void ScDocument::UpdateChartArea( const String& rChartName,
+ const ScRange& rNewArea, BOOL bColHeaders, BOOL bRowHeaders,
+ BOOL bAdd, Window* pWindow )
+{
+ ScRangeListRef aRLR( new ScRangeList );
+ aRLR->Append( rNewArea );
+ UpdateChartArea( rChartName, aRLR, bColHeaders, bRowHeaders, bAdd, pWindow );
+}
+
+void ScDocument::UpdateChartArea( const String& rChartName,
+ const ScRangeListRef& rNewList, BOOL bColHeaders, BOOL bRowHeaders,
+ BOOL bAdd, Window* pWindow )
+{
+ if (!pDrawLayer)
+ return;
+
+ for (USHORT nTab=0; nTab<=MAXTAB && pTab[nTab]; nTab++)
+ {
+ SdrPage* pPage = pDrawLayer->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+
+ SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
+ ((SdrOle2Obj*)pObject)->GetName() == rChartName )
+ {
+ SvInPlaceObjectRef aIPObj = ((SdrOle2Obj*)pObject)->GetObjRef();
+ if (aIPObj.Is())
+ {
+ const SchMemChart* pChartData = SchDLL::GetChartData(aIPObj);
+ if ( pChartData )
+ {
+ ScChartArray aArray( this, *pChartData );
+ if ( bAdd )
+ {
+ // bei bAdd werden Header-Angaben ignoriert
+ aArray.AddToRangeList( rNewList );
+ }
+ else
+ {
+ aArray.SetRangeList( rNewList );
+ aArray.SetHeaders( bColHeaders, bRowHeaders );
+ }
+ pChartListenerCollection->ChangeListening(
+ rChartName, aArray.GetRangeList() );
+
+
+ SchMemChart* pMemChart = aArray.CreateMemChart();
+ ScChartArray::CopySettings( *pMemChart, *pChartData );
+
+ SchDLL::Update( aIPObj, pMemChart, pWindow );
+ delete pMemChart;
+
+ // Dies veranlaesst Chart zum sofortigen Update
+ SvData aEmpty;
+ aIPObj->SendDataChanged( aEmpty );
+ aIPObj->SendViewChanged();
+ pObject->SendRepaintBroadcast();
+
+ return; // nicht weitersuchen
+ }
+ }
+ }
+ pObject = aIter.Next();
+ }
+ }
+}
+
+void ScDocument::UpdateChart( const String& rChartName, Window* pWindow )
+{
+ if (!pDrawLayer || bInDtorClear)
+ return;
+
+ for (USHORT nTab=0; nTab<=MAXTAB && pTab[nTab]; nTab++)
+ {
+ SdrPage* pPage = pDrawLayer->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+
+ SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
+ ((SdrOle2Obj*)pObject)->GetName() == rChartName )
+ {
+ SvInPlaceObjectRef aIPObj = ((SdrOle2Obj*)pObject)->GetObjRef();
+ if (aIPObj.Is())
+ {
+ const SchMemChart* pChartData = SchDLL::GetChartData(aIPObj);
+ if ( pChartData )
+ {
+ ScChartArray aArray( this, *pChartData );
+
+ SchMemChart* pMemChart = aArray.CreateMemChart();
+ ScChartArray::CopySettings( *pMemChart, *pChartData );
+
+ // #57655# Chart-Update ohne geaenderte Einstellungen (MemChart)
+ // soll das Dokument nicht auf modified setzen (z.B. in frisch
+ // geladenem Dokument durch initiales Recalc)
+
+ // #72576# disable SetModified for readonly documents only
+
+ BOOL bEnabled = ( pShell && pShell->IsReadOnly() &&
+ aIPObj->IsEnableSetModified() );
+ if (bEnabled)
+ aIPObj->EnableSetModified(FALSE);
+
+ SchDLL::Update( aIPObj, pMemChart, pWindow );
+ delete pMemChart;
+
+ // Dies veranlaesst Chart zum sofortigen Update
+ SvData aEmpty;
+ aIPObj->SendDataChanged( aEmpty );
+ aIPObj->SendViewChanged();
+ pObject->SendRepaintBroadcast();
+
+ if (bEnabled)
+ aIPObj->EnableSetModified(TRUE);
+
+ return; // nicht weitersuchen
+ }
+ }
+ }
+ pObject = aIter.Next();
+ }
+ }
+}
+
+void ScDocument::UpdateChartRef( UpdateRefMode eUpdateRefMode,
+ USHORT nCol1, USHORT nRow1, USHORT nTab1,
+ USHORT nCol2, USHORT nRow2, USHORT nTab2,
+ short nDx, short nDy, short nDz )
+{
+ if (!pDrawLayer)
+ return;
+
+ USHORT nChartCount = pChartListenerCollection->GetCount();
+ for ( USHORT nIndex = 0; nIndex < nChartCount; nIndex++ )
+ {
+ ScChartListener* pChartListener =
+ (ScChartListener*) (pChartListenerCollection->At(nIndex));
+ ScRangeListRef aRLR( pChartListener->GetRangeList() );
+ ScRangeListRef aNewRLR( new ScRangeList );
+ BOOL bChanged = FALSE;
+ BOOL bDataChanged = FALSE;
+ for ( ScRangePtr pR = aRLR->First(); pR; pR = aRLR->Next() )
+ {
+ USHORT theCol1 = pR->aStart.Col();
+ USHORT theRow1 = pR->aStart.Row();
+ USHORT theTab1 = pR->aStart.Tab();
+ USHORT theCol2 = pR->aEnd.Col();
+ USHORT theRow2 = pR->aEnd.Row();
+ USHORT theTab2 = pR->aEnd.Tab();
+ ScRefUpdateRes eRes = ScRefUpdate::Update(
+ this, eUpdateRefMode,
+ nCol1,nRow1,nTab1, nCol2,nRow2,nTab2,
+ nDx,nDy,nDz,
+ theCol1,theRow1,theTab1,
+ theCol2,theRow2,theTab2 );
+ if ( eRes != UR_NOTHING )
+ {
+ bChanged = TRUE;
+ aNewRLR->Append( ScRange(
+ theCol1, theRow1, theTab1,
+ theCol2, theRow2, theTab2 ));
+ if ( eUpdateRefMode == URM_INSDEL
+ && !bDataChanged
+ && (eRes == UR_INVALID ||
+ ((pR->aEnd.Col() - pR->aStart.Col()
+ != theCol2 - theCol1)
+ || (pR->aEnd.Row() - pR->aStart.Row()
+ != theRow2 - theRow1)
+ || (pR->aEnd.Tab() - pR->aStart.Tab()
+ != theTab2 - theTab1))) )
+ {
+ bDataChanged = TRUE;
+ }
+ }
+ else
+ aNewRLR->Append( *pR );
+ }
+ if ( bChanged )
+ {
+ SetChartRangeList( pChartListener->GetString(), aNewRLR );
+ pChartListener->ChangeListening( aNewRLR, bDataChanged );
+ }
+ }
+}
+
+
+void ScDocument::SetChartRangeList( const String& rChartName,
+ const ScRangeListRef& rNewRangeListRef )
+{
+ SchMemChart* pChartData = FindChartData( rChartName, TRUE );
+ if ( pChartData )
+ {
+ ScChartArray aArray( this, *pChartData );
+ aArray.SetRangeList( rNewRangeListRef );
+ aArray.SetExtraStrings( *pChartData );
+ }
+}
+
+
+BOOL ScDocument::HasData( USHORT nCol, USHORT nRow, USHORT nTab )
+{
+ if (pTab[nTab])
+ return pTab[nTab]->HasData( nCol, nRow );
+ else
+ return FALSE;
+}
+
+SchMemChart* ScDocument::FindChartData(const String& rName, BOOL bForModify)
+{
+ if (!pDrawLayer)
+ return NULL;
+
+ // die Seiten hier vom Draw-Layer nehmen,
+ // weil sie evtl. nicht mit den Tabellen uebereinstimmen
+ // (z.B. Redo von Tabelle loeschen, Draw-Redo passiert vor DeleteTab).
+
+ USHORT nCount = pDrawLayer->GetPageCount();
+ for (USHORT nTab=0; nTab<nCount; nTab++)
+ {
+ SdrPage* pPage = pDrawLayer->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+
+ SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
+ ((SdrOle2Obj*)pObject)->GetName() == rName )
+ {
+ SvInPlaceObjectRef aIPObj = ((SdrOle2Obj*)pObject)->GetObjRef();
+ if ( aIPObj.Is() )
+ {
+ if (bForModify)
+ aIPObj->SetModified( TRUE );
+ return SchDLL::GetChartData( aIPObj );
+ }
+ }
+ pObject = aIter.Next();
+ }
+ }
+
+ return NULL; // nix
+}
+
+
+void ScDocument::UpdateChartListenerCollection()
+{
+ bChartListenerCollectionNeedsUpdate = FALSE;
+ if (!pDrawLayer)
+ return;
+ else
+ {
+ ScRange aRange;
+ // Range fuer Suche unwichtig
+ ScChartListener aCLSearcher( EMPTY_STRING, this, aRange );
+ for (USHORT nTab=0; nTab<=MAXTAB; nTab++)
+ {
+ if (pTab[nTab])
+ {
+ SdrPage* pPage = pDrawLayer->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+
+ SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ if ( pObject->GetObjIdentifier() == OBJ_OLE2 )
+ {
+ aCLSearcher.SetString( ((SdrOle2Obj*)pObject)->GetName() );
+ USHORT nIndex;
+ if ( pChartListenerCollection->Search( &aCLSearcher, nIndex ) )
+ {
+ ((ScChartListener*) (pChartListenerCollection->
+ At( nIndex )))->SetUsed( TRUE );
+ }
+ else
+ {
+ // SchDLL::GetChartData zieht sofort die Chart-DLL an,
+ // darum vorher SchModuleDummy::HasID testen!
+
+ SvInPlaceObjectRef aIPObj = ((SdrOle2Obj*)pObject)->GetObjRef();
+ if ( aIPObj.Is() && SchModuleDummy::HasID( *aIPObj->GetSvFactory() ) )
+ {
+ SchMemChart* pChartData = SchDLL::GetChartData(aIPObj);
+ if ( pChartData )
+ {
+ ScChartArray aArray( this, *pChartData );
+ ScChartListener* pCL = new ScChartListener(
+ ((SdrOle2Obj*)pObject)->GetName(),
+ this, aArray.GetRangeList() );
+ pChartListenerCollection->Insert( pCL );
+ pCL->StartListeningTo();
+ pCL->SetUsed( TRUE );
+
+ // Set ReadOnly flag at MemChart, so Chart knows
+ // about the external data in a freshly loaded document.
+ // #73642# only if the chart really has external data
+ if ( aArray.IsValid() )
+ pChartData->SetReadOnly( TRUE );
+
+#if 1
+// #74046# initially loaded charts need the number formatter standard precision
+ BOOL bEnabled = aIPObj->IsEnableSetModified();
+ if (bEnabled)
+ aIPObj->EnableSetModified(FALSE);
+ pChartData->SetNumberFormatter( GetFormatTable() );
+ SchDLL::Update( aIPObj, pChartData );
+ //! pChartData got deleted, don't use it anymore
+ if (bEnabled)
+ aIPObj->EnableSetModified(TRUE);
+#ifndef PRODUCT
+ static BOOL bShown74046 = 0;
+ if ( !bShown74046 && SOFFICE_FILEFORMAT_NOW > SOFFICE_FILEFORMAT_50 )
+ {
+ bShown74046 = 1;
+ DBG_ERRORFILE( "on incompatible file format save number formatter standard precision in chart" );
+ }
+#endif
+#endif
+ }
+ }
+ }
+ }
+ pObject = aIter.Next();
+ }
+ }
+ }
+ // alle nicht auf SetUsed gesetzten loeschen
+ pChartListenerCollection->FreeUnused();
+ }
+}
+
+
+
+
+
diff --git a/sc/source/core/data/documen6.cxx b/sc/source/core/data/documen6.cxx
new file mode 100644
index 000000000000..c0235d3de393
--- /dev/null
+++ b/sc/source/core/data/documen6.cxx
@@ -0,0 +1,186 @@
+/*************************************************************************
+ *
+ * $RCSfile: documen6.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include <svtools/zforlist.hxx>
+#include <sdb/sdbcol.hxx>
+#include <sdb/variant.hxx>
+#include <vos/xception.hxx>
+
+#include "document.hxx"
+#include "cell.hxx"
+
+//
+// this file is compiled with exceptions enabled
+// put functions here that need exceptions!
+//
+
+// -----------------------------------------------------------------------
+
+void ScDocument::PutVariable( USHORT nCol, USHORT nRow, USHORT nTab,
+ const ODbVariant* pVar, long nType, BOOL* pSimpleFlag )
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ {
+ String aString;
+ double nVal = 0.0;
+ BOOL bValue = FALSE;
+ BOOL bEmptyFlag = FALSE;
+ BOOL bError = FALSE;
+ ULONG nFormatIndex = 0;
+
+ if ( !pVar || pVar->isNull() )
+ bEmptyFlag = TRUE;
+ else
+ {
+ TRY
+ {
+ switch ( (SdbDatabaseType)nType )
+ {
+ case SDB_DBTYPE_CHAR:
+ case SDB_DBTYPE_VARCHAR:
+ case SDB_DBTYPE_LONGVARCHAR:
+ aString = String( pVar->toString() );
+ break;
+
+ case SDB_DBTYPE_DECIMAL:
+ case SDB_DBTYPE_NUMERIC:
+ case SDB_DBTYPE_TINYINT:
+ case SDB_DBTYPE_SMALLINT:
+ case SDB_DBTYPE_INTEGER:
+ case SDB_DBTYPE_BIGINT:
+ case SDB_DBTYPE_REAL:
+ case SDB_DBTYPE_DOUBLE:
+ nVal = pVar->toDouble();
+ bValue = TRUE;
+ break;
+
+ case SDB_DBTYPE_CURRENCY:
+ nFormatIndex = pFormTable->GetStandardFormat(
+ NUMBERFORMAT_CURRENCY, ScGlobal::eLnge );
+ nVal = pVar->toDouble();
+ bValue = TRUE;
+ break;
+
+ case SDB_DBTYPE_BOOLEAN:
+ nFormatIndex = pFormTable->GetStandardFormat(
+ NUMBERFORMAT_LOGICAL, ScGlobal::eLnge );
+ nVal = (pVar->toBOOL() ? 1 : 0);
+ bValue = TRUE;
+ break;
+
+ case SDB_DBTYPE_DATE:
+ //! subtract base date difference if var contains numeric value?
+ nFormatIndex = pFormTable->GetStandardFormat(
+ NUMBERFORMAT_DATE, ScGlobal::eLnge );
+ nVal = pVar->toDate() - *pFormTable->GetNullDate();
+ bValue = TRUE;
+ break;
+
+ default:
+ aString = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("[unknown type]"));
+ }
+ }
+ CATCH_ALL()
+ {
+ bError = TRUE;
+ }
+ END_CATCH
+ }
+
+ ScBaseCell* pCell;
+ if (bEmptyFlag)
+ {
+ pCell = NULL;
+ PutCell( nCol, nRow, nTab, pCell );
+ }
+ else if (bError)
+ {
+ SetError( nCol, nRow, nTab, NOVALUE );
+ }
+ else if (bValue)
+ {
+ pCell = new ScValueCell( nVal );
+ if (nFormatIndex == 0)
+ PutCell( nCol, nRow, nTab, pCell );
+ else
+ PutCell( nCol, nRow, nTab, pCell, nFormatIndex );
+ }
+ else
+ {
+ pCell = ScBaseCell::CreateTextCell( aString, this );
+ if ( pSimpleFlag && pCell->GetCellType() == CELLTYPE_EDIT )
+ *pSimpleFlag = FALSE;
+ PutCell( nCol, nRow, nTab, pCell );
+ }
+ }
+}
+
+
+
+
+
+
diff --git a/sc/source/core/data/documen7.cxx b/sc/source/core/data/documen7.cxx
new file mode 100644
index 000000000000..9e17aa8d11c5
--- /dev/null
+++ b/sc/source/core/data/documen7.cxx
@@ -0,0 +1,509 @@
+/*************************************************************************
+ *
+ * $RCSfile: documen7.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <vcl/svapp.hxx>
+
+#if defined( WNT ) && defined( erBEEP )
+#include <svwin.h>
+#define erBEEPER() Beep( 666, 66 )
+#else
+#define erBEEPER()
+#endif
+
+#include "document.hxx"
+#include "brdcst.hxx"
+#include "bcaslot.hxx"
+#include "cell.hxx"
+#include "compiler.hxx" // errCircularReference
+#include "scerrors.hxx"
+#include "docoptio.hxx"
+#include "refupdat.hxx"
+#include "table.hxx"
+#include "progress.hxx"
+#include "scmod.hxx" // SC_MOD
+#include "inputopt.hxx" // GetExpandRefs
+#include "conditio.hxx"
+#include "bclist.hxx"
+
+#ifndef _SHL_HXX //autogen
+#include <tools/shl.hxx>
+#endif
+
+
+#include "globstr.hrc"
+
+extern const ScFormulaCell* pLastFormulaTreeTop; // cellform.cxx Err527 WorkAround
+
+// STATIC DATA -----------------------------------------------------------
+
+#ifdef erDEBUG
+ULONG erCountBCAInserts = 0;
+ULONG erCountBCAFinds = 0;
+#endif
+
+// -----------------------------------------------------------------------
+
+void ScDocument::StartListeningArea( const ScRange& rRange,
+ SfxListener* pListener
+ )
+{
+ if ( pBASM )
+ pBASM->StartListeningArea( rRange, pListener );
+}
+
+
+void ScDocument::EndListeningArea( const ScRange& rRange,
+ SfxListener* pListener
+ )
+{
+ if ( pBASM )
+ pBASM->EndListeningArea( rRange, pListener );
+}
+
+
+void ScDocument::Broadcast( ULONG nHint, const ScAddress& rAddr,
+ ScBaseCell* pCell
+ )
+{
+ if ( !pBASM )
+ return ; // Clipboard oder Undo
+ if ( !nHardRecalcState )
+ {
+ BOOL bIsBroadcasted = FALSE;
+ ScHint aHint( nHint, rAddr, pCell );
+ if ( pCell )
+ {
+ ScBroadcasterList* pBC;
+ if ( pBC = pCell->GetBroadcaster() )
+ {
+ pBC->Broadcast( aHint );
+ bIsBroadcasted = TRUE;
+ }
+ }
+ if ( pBASM->AreaBroadcast( rAddr, aHint ) || bIsBroadcasted )
+ TrackFormulas();
+ }
+
+ // Repaint fuer bedingte Formate mit relativen Referenzen:
+ if ( pCondFormList && rAddr != BCA_BRDCST_ALWAYS )
+ pCondFormList->SourceChanged( rAddr );
+}
+
+
+void ScDocument::DelBroadcastAreasInRange( const ScRange& rRange )
+{
+ if ( pBASM )
+ pBASM->DelBroadcastAreasInRange( rRange );
+}
+
+void ScDocument::StartListeningCell( const ScAddress& rAddress,
+ SfxListener* pListener )
+{
+ DBG_ASSERT(pListener, "StartListeningCell: pListener Null");
+ USHORT nTab = rAddress.Tab();
+ if (pTab[nTab])
+ pTab[nTab]->StartListening( rAddress, pListener );
+}
+
+void ScDocument::EndListeningCell( const ScAddress& rAddress,
+ SfxListener* pListener )
+{
+ DBG_ASSERT(pListener, "EndListeningCell: pListener Null");
+ USHORT nTab = rAddress.Tab();
+ if (pTab[nTab])
+ pTab[nTab]->EndListening( rAddress, pListener );
+}
+
+
+void ScDocument::PutInFormulaTree( ScFormulaCell* pCell )
+{
+ DBG_ASSERT( pCell, "PutInFormulaTree: pCell Null" );
+ RemoveFromFormulaTree( pCell );
+ // anhaengen
+ if ( pEOFormulaTree )
+ pEOFormulaTree->SetNext( pCell );
+ else
+ pFormulaTree = pCell; // kein Ende, kein Anfang..
+ pCell->SetPrevious( pEOFormulaTree );
+ pCell->SetNext( 0 );
+ pEOFormulaTree = pCell;
+ nFormulaCodeInTree += pCell->GetCode()->GetCodeLen();
+}
+
+
+void ScDocument::RemoveFromFormulaTree( ScFormulaCell* pCell )
+{
+ DBG_ASSERT( pCell, "RemoveFromFormulaTree: pCell Null" );
+ ScFormulaCell* pPrev = pCell->GetPrevious();
+ // wenn die Zelle die erste oder sonstwo ist
+ if ( pPrev || pFormulaTree == pCell )
+ {
+ ScFormulaCell* pNext = pCell->GetNext();
+ if ( pPrev )
+ pPrev->SetNext( pNext ); // gibt Vorlaeufer
+ else
+ pFormulaTree = pNext; // ist erste Zelle
+ if ( pNext )
+ pNext->SetPrevious( pPrev ); // gibt Nachfolger
+ else
+ pEOFormulaTree = pPrev; // ist letzte Zelle
+ pCell->SetPrevious( 0 );
+ pCell->SetNext( 0 );
+ USHORT nRPN = pCell->GetCode()->GetCodeLen();
+ if ( nFormulaCodeInTree >= nRPN )
+ nFormulaCodeInTree -= nRPN;
+ else
+ {
+ DBG_ERRORFILE( "RemoveFromFormulaTree: nFormulaCodeInTree < nRPN" );
+ nFormulaCodeInTree = 0;
+ }
+ }
+ else if ( !pFormulaTree && nFormulaCodeInTree )
+ {
+ DBG_ERRORFILE( "!pFormulaTree && nFormulaCodeInTree != 0" );
+ nFormulaCodeInTree = 0;
+ }
+}
+
+
+BOOL ScDocument::IsInFormulaTree( ScFormulaCell* pCell ) const
+{
+ return pCell->GetPrevious() || pFormulaTree == pCell;
+}
+
+
+void ScDocument::CalcFormulaTree( BOOL bOnlyForced, BOOL bNoProgress )
+{
+ SetForcedFormulaPending( FALSE );
+ BOOL bOldIdleDisabled = IsIdleDisabled();
+ DisableIdle( TRUE );
+ BOOL bOldAutoCalc = GetAutoCalc();
+ //! _nicht_ SetAutoCalc( TRUE ) weil das evtl. CalcFormulaTree( TRUE )
+ //! aufruft, wenn vorher disabled war und bHasForcedFormulas gesetzt ist
+ bAutoCalc = TRUE;
+ if ( nHardRecalcState )
+ CalcAll();
+ else
+ {
+ ScFormulaCell* pCell = pFormulaTree;
+ while ( pCell )
+ {
+ if ( pCell->GetDirty() )
+ pCell = pCell->GetNext(); // alles klar
+ else
+ {
+ if ( pCell->GetCode()->IsRecalcModeAlways() )
+ {
+ // pCell wird im SetDirty neu angehaengt!
+ ScFormulaCell* pNext = pCell->GetNext();
+ pCell->SetDirty();
+ // falls pNext==0 und neue abhaengige hinten angehaengt
+ // wurden, so macht das nichts, da die alle bDirty sind
+ pCell = pNext;
+ }
+ else
+ { // andere simpel berechnen, evtl. auch errInterpOverflow
+ // (Err527) wg. Aufruf aus CellForm dirty setzen
+ pCell->SetDirtyVar();
+ pCell = pCell->GetNext();
+ }
+ }
+ }
+ BOOL bProgress = !bOnlyForced && nFormulaCodeInTree && !bNoProgress;
+ if ( bProgress )
+ ScProgress::CreateInterpretProgress( this, TRUE );
+ ULONG nLastFormulaCodeInTree;
+ BOOL bErr527 = FALSE; // damned maxrecursion
+ do
+ { // while ( bErr527 && nLastFormulaCodeInTree > nFormulaCodeInTree );
+ if ( bErr527 )
+ {
+ bErr527 = FALSE;
+ pLastFormulaTreeTop = 0; // reset fuer CellForm
+ }
+ pCell = pFormulaTree;
+ nLastFormulaCodeInTree = nFormulaCodeInTree;
+ ScFormulaCell* pLastNoGood = 0;
+ while ( pCell )
+ {
+ if ( pCell->GetCode()->GetError() == errInterpOverflow )
+ pCell->SetDirtyVar(); // Err527 wieder dirty
+ // Interpret setzt bDirty zurueck und callt Remove, auch der referierten!
+ // bei maxrecursion (Err527) oder RECALCMODE_ALWAYS bleibt die Zelle
+ if ( bOnlyForced )
+ {
+ if ( pCell->GetCode()->IsRecalcModeForced() )
+ pCell->Interpret();
+ }
+ else
+ {
+ pCell->Interpret();
+ }
+ if ( pCell->GetPrevious() || pCell == pFormulaTree )
+ { // (IsInFormulaTree(pCell)) kein Remove gewesen => next
+ if ( pCell->GetCode()->GetError() == errInterpOverflow )
+ bErr527 = TRUE;
+ pLastNoGood = pCell;
+ pCell = pCell->GetNext();
+ }
+ else
+ {
+ if ( pFormulaTree )
+ {
+ if ( pFormulaTree->GetDirty() && !bOnlyForced )
+ {
+ pCell = pFormulaTree;
+ pLastNoGood = 0;
+ }
+ else
+ {
+ // IsInFormulaTree(pLastNoGood)
+ if ( pLastNoGood && (pLastNoGood->GetPrevious() ||
+ pLastNoGood == pFormulaTree) )
+ pCell = pLastNoGood->GetNext();
+ else
+ {
+ pCell = pFormulaTree;
+ while ( pCell && !pCell->GetDirty() &&
+ pCell->GetCode()->GetError() != errInterpOverflow )
+ pCell = pCell->GetNext();
+ if ( pCell )
+ pLastNoGood = pCell->GetPrevious();
+ }
+ }
+ }
+ else
+ pCell = 0;
+ }
+ if ( ScProgress::IsUserBreak() )
+ {
+ pCell = 0;
+ bErr527 = FALSE;
+ }
+ }
+ } while ( bErr527 && nLastFormulaCodeInTree > nFormulaCodeInTree );
+ if ( bProgress )
+ ScProgress::DeleteInterpretProgress();
+ }
+ bAutoCalc = bOldAutoCalc;
+ DisableIdle( bOldIdleDisabled );
+}
+
+
+void ScDocument::ClearFormulaTree()
+{
+ ScFormulaCell* pCell;
+ ScFormulaCell* pTree = pFormulaTree;
+ while ( pTree )
+ {
+ pCell = pTree;
+ pTree = pCell->GetNext();
+ if ( !pCell->GetCode()->IsRecalcModeAlways() )
+ RemoveFromFormulaTree( pCell );
+ }
+}
+
+
+void ScDocument::AppendToFormulaTrack( ScFormulaCell* pCell )
+{
+ DBG_ASSERT( pCell, "AppendToFormulaTrack: pCell Null" );
+ // Zelle kann nicht in beiden Listen gleichzeitig sein
+ RemoveFromFormulaTrack( pCell );
+ RemoveFromFormulaTree( pCell );
+ if ( pEOFormulaTrack )
+ pEOFormulaTrack->SetNextTrack( pCell );
+ else
+ pFormulaTrack = pCell; // kein Ende, kein Anfang..
+ pCell->SetPreviousTrack( pEOFormulaTrack );
+ pCell->SetNextTrack( 0 );
+ pEOFormulaTrack = pCell;
+ ++nFormulaTrackCount;
+}
+
+
+void ScDocument::RemoveFromFormulaTrack( ScFormulaCell* pCell )
+{
+ DBG_ASSERT( pCell, "RemoveFromFormulaTrack: pCell Null" );
+ ScFormulaCell* pPrev = pCell->GetPreviousTrack();
+ // wenn die Zelle die erste oder sonstwo ist
+ if ( pPrev || pFormulaTrack == pCell )
+ {
+ ScFormulaCell* pNext = pCell->GetNextTrack();
+ if ( pPrev )
+ pPrev->SetNextTrack( pNext ); // gibt Vorlaeufer
+ else
+ pFormulaTrack = pNext; // ist erste Zelle
+ if ( pNext )
+ pNext->SetPreviousTrack( pPrev ); // gibt Nachfolger
+ else
+ pEOFormulaTrack = pPrev; // ist letzte Zelle
+ pCell->SetPreviousTrack( 0 );
+ pCell->SetNextTrack( 0 );
+ --nFormulaTrackCount;
+ }
+}
+
+
+BOOL ScDocument::IsInFormulaTrack( ScFormulaCell* pCell ) const
+{
+ return pCell->GetPreviousTrack() || pFormulaTrack == pCell;
+}
+
+
+/*
+ Der erste wird gebroadcastet,
+ die dadurch entstehenden werden durch das Notify an den Track gehaengt.
+ Der nachfolgende broadcastet wieder usw.
+ View stoesst Interpret an.
+ */
+void ScDocument::TrackFormulas()
+{
+
+ if ( pFormulaTrack )
+ {
+ BOOL bWasWaiting = Application::IsWait();
+ if ( !bWasWaiting )
+ Application::EnterWait();
+ erBEEPER();
+ ScBroadcasterList* pBC;
+ ScFormulaCell* pTrack;
+ ScFormulaCell* pNext;
+ BOOL bIsChanged = TRUE;
+ pTrack = pFormulaTrack;
+ do
+ {
+ ScHint aHint( SC_HINT_DATACHANGED, pTrack->aPos, pTrack );
+ if ( pBC = pTrack->GetBroadcaster() )
+ pBC->Broadcast( aHint );
+ pBASM->AreaBroadcast( pTrack->aPos, aHint );
+ // Repaint fuer bedingte Formate mit relativen Referenzen:
+ if ( pCondFormList )
+ pCondFormList->SourceChanged( pTrack->aPos );
+ pTrack = pTrack->GetNextTrack();
+ } while ( pTrack );
+ pTrack = pFormulaTrack;
+ BOOL bHaveForced = FALSE;
+ do
+ {
+ pNext = pTrack->GetNextTrack();
+ RemoveFromFormulaTrack( pTrack );
+ PutInFormulaTree( pTrack );
+ if ( pTrack->GetCode()->IsRecalcModeForced() )
+ bHaveForced = TRUE;
+ pTrack = pNext;
+ } while ( pTrack );
+ if ( bHaveForced )
+ {
+ SetForcedFormulas( TRUE );
+ if ( bAutoCalc && !IsAutoCalcShellDisabled() )
+ CalcFormulaTree( TRUE );
+ else
+ SetForcedFormulaPending( TRUE );
+ }
+ if ( !bWasWaiting )
+ Application::LeaveWait();
+ }
+ DBG_ASSERT( nFormulaTrackCount==0, "TrackFormulas: nFormulaTrackCount!=0" );
+}
+
+
+void ScDocument::StartAllListeners()
+{
+ for ( USHORT i = 0; i <= MAXTAB; ++i )
+ if ( pTab[i] )
+ pTab[i]->StartAllListeners();
+}
+
+void ScDocument::UpdateBroadcastAreas( UpdateRefMode eUpdateRefMode,
+ const ScRange& rRange, short nDx, short nDy, short nDz
+ )
+{
+ BOOL bExpandRefsOld = IsExpandRefs();
+ if ( eUpdateRefMode == URM_INSDEL && (nDx > 0 || nDy > 0 || nDz > 0) )
+ SetExpandRefs( SC_MOD()->GetInputOptions().GetExpandRefs() );
+ if ( pBASM )
+ pBASM->UpdateBroadcastAreas( eUpdateRefMode, rRange, nDx, nDy, nDz );
+ SetExpandRefs( bExpandRefsOld );
+}
+
+void ScDocument::SetAutoCalc( BOOL bNewAutoCalc )
+{
+ BOOL bOld = bAutoCalc;
+ bAutoCalc = bNewAutoCalc;
+ if ( !bOld && bNewAutoCalc && bHasForcedFormulas )
+ {
+ if ( IsAutoCalcShellDisabled() )
+ SetForcedFormulaPending( TRUE );
+ else
+ CalcFormulaTree( TRUE );
+ }
+}
+
+
+
diff --git a/sc/source/core/data/documen8.cxx b/sc/source/core/data/documen8.cxx
new file mode 100644
index 000000000000..ad91e556e764
--- /dev/null
+++ b/sc/source/core/data/documen8.cxx
@@ -0,0 +1,1356 @@
+/*************************************************************************
+ *
+ * $RCSfile: documen8.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include "scitems.hxx"
+
+#include <tools/string.hxx>
+#include <svx/editobj.hxx>
+#include <svx/editstat.hxx>
+#include <svx/langitem.hxx>
+#include <svx/linkmgr.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/printer.hxx>
+#include <sfx2/viewsh.hxx>
+#include <svtools/flagitem.hxx>
+#include <svtools/intitem.hxx>
+#include <svtools/zforlist.hxx>
+#include <svtools/zformat.hxx>
+#include <offmgr/app.hxx>
+#include <sfx2/misccfg.hxx>
+
+#ifdef ONE_LINGU
+#else
+#include <offmgr/osplcfg.hxx>
+#endif
+
+#include <vcl/msgbox.hxx>
+#include <vcl/system.hxx>
+
+#include "global.hxx"
+#include "table.hxx"
+#include "column.hxx"
+#include "cell.hxx"
+#include "docpool.hxx"
+#include "stlpool.hxx"
+#include "stlsheet.hxx"
+#include "docoptio.hxx"
+#include "viewopti.hxx"
+#include "scextopt.hxx"
+#include "scdebug.hxx"
+#include "rechead.hxx"
+#include "ddelink.hxx"
+#include "arealink.hxx"
+#include "dociter.hxx"
+#include "patattr.hxx"
+#include "hints.hxx"
+#include "editutil.hxx"
+#include "progress.hxx"
+#include "document.hxx"
+#include "chartlis.hxx"
+#include "validat.hxx" // fuer HasMacroCalls
+#include "globstr.hrc"
+#include "sc.hrc"
+
+#define GET_SCALEVALUE(set,id) ((const SfxUInt16Item&)(set.Get( id ))).GetValue()
+
+// states for online spelling in the visible range (0 is set initially)
+#define VSPL_START 0
+#define VSPL_DONE 1
+
+
+// STATIC DATA -----------------------------------------------------------
+
+
+
+//------------------------------------------------------------------------
+
+void ScDocument::ImplLoadDocOptions( SvStream& rStream )
+{
+ USHORT d,m,y;
+
+ DBG_ASSERT( pDocOptions, "No DocOptions to load! :-(" );
+ DBG_ASSERT( pFormTable, "Missing NumberFormatter :-(" );
+
+ pDocOptions->Load( rStream );
+
+ if ( pDocOptions->GetStdPrecision() > 20 ) //!!! ist 20 als Maximum konstant ???
+ {
+ DBG_ERROR( "Document options corrupted. Setting to defaults." );
+ pDocOptions->ResetDocOptions();
+ }
+
+ pDocOptions->GetDate( d,m,y );
+ pFormTable->ChangeNullDate( d,m,y );
+ pFormTable->ChangeStandardPrec( pDocOptions->GetStdPrecision() );
+ pFormTable->SetYear2000( pDocOptions->GetYear2000() );
+}
+
+//------------------------------------------------------------------------
+
+void ScDocument::ImplLoadViewOptions( SvStream& rStream )
+{
+ DBG_ASSERT( pViewOptions, "No ViewOptions to load! :-(" );
+ rStream >> *pViewOptions;
+}
+
+//------------------------------------------------------------------------
+
+void ScDocument::ImplSaveDocOptions( SvStream& rStream ) const
+{
+ DBG_ASSERT( pDocOptions, "No DocOptions to save! :-(" );
+ pDocOptions->Save( rStream );
+}
+
+//------------------------------------------------------------------------
+
+void ScDocument::ImplSaveViewOptions( SvStream& rStream ) const
+{
+ DBG_ASSERT( pViewOptions, "No ViewOptions to save! :-(" );
+ rStream << *pViewOptions;
+}
+
+//------------------------------------------------------------------------
+
+void ScDocument::ImplCreateOptions()
+{
+ pDocOptions = new ScDocOptions();
+ pViewOptions = new ScViewOptions();
+}
+
+//------------------------------------------------------------------------
+
+void ScDocument::ImplDeleteOptions()
+{
+ delete pDocOptions;
+ delete pViewOptions;
+ delete pExtDocOptions;
+}
+
+//------------------------------------------------------------------------
+
+SfxPrinter* ScDocument::GetPrinter()
+{
+ if ( !pPrinter )
+ {
+ SfxItemSet* pSet =
+ new SfxItemSet( *pDocPool,
+ SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN,
+ SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC,
+ NULL );
+
+ OfaMiscCfg* pOffCfg = SFX_APP()->GetMiscConfig();
+ if ( pOffCfg )
+ {
+ USHORT nFlags = 0;
+ if ( pOffCfg->IsPaperBinWarning() )
+ nFlags |= SFX_PRINTER_CHG_ORIENTATION;
+ if ( pOffCfg->IsPaperSizeWarning() )
+ nFlags |= SFX_PRINTER_CHG_SIZE;
+ pSet->Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC, nFlags ) );
+ pSet->Put( SfxBoolItem( SID_PRINTER_NOTFOUND_WARN, pOffCfg->IsNotFoundWarning() ) );
+ }
+
+ pPrinter = new SfxPrinter( pSet );
+ UpdateDrawPrinter();
+ }
+
+ return pPrinter;
+}
+
+//------------------------------------------------------------------------
+
+void ScDocument::SetPrinter( SfxPrinter* pNewPrinter )
+{
+ SfxPrinter* pOld = pPrinter;
+ pPrinter = pNewPrinter;
+ UpdateDrawPrinter();
+ delete pOld;
+ InvalidateTextWidth();
+}
+
+//------------------------------------------------------------------------
+
+void ScDocument::SetPrintOptions()
+{
+ if ( !pPrinter ) GetPrinter(); // setzt pPrinter
+ DBG_ASSERT( pPrinter, "Error in printer creation :-/" );
+
+ if ( pPrinter )
+ {
+ OfaMiscCfg* pOffCfg = SFX_APP()->GetMiscConfig();
+ if ( pOffCfg )
+ {
+ SfxItemSet aOptSet( pPrinter->GetOptions() );
+
+ USHORT nFlags = 0;
+ if ( pOffCfg->IsPaperBinWarning() )
+ nFlags |= SFX_PRINTER_CHG_ORIENTATION;
+ if ( pOffCfg->IsPaperSizeWarning() )
+ nFlags |= SFX_PRINTER_CHG_SIZE;
+ aOptSet.Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC, nFlags ) );
+ aOptSet.Put( SfxBoolItem( SID_PRINTER_NOTFOUND_WARN, pOffCfg->IsNotFoundWarning() ) );
+
+ pPrinter->SetOptions( aOptSet );
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+
+void ScDocument::ModifyStyleSheet( SfxStyleSheetBase& rStyleSheet,
+ const SfxItemSet& rChanges )
+{
+ SfxItemSet& rSet = rStyleSheet.GetItemSet();
+
+ switch ( rStyleSheet.GetFamily() )
+ {
+ case SFX_STYLE_FAMILY_PAGE:
+ {
+ const USHORT nOldScale = GET_SCALEVALUE(rSet,ATTR_PAGE_SCALE);
+ const USHORT nOldScaleToPages = GET_SCALEVALUE(rSet,ATTR_PAGE_SCALETOPAGES);
+ rSet.Put( rChanges );
+ const USHORT nNewScale = GET_SCALEVALUE(rSet,ATTR_PAGE_SCALE);
+ const USHORT nNewScaleToPages = GET_SCALEVALUE(rSet,ATTR_PAGE_SCALETOPAGES);
+
+ if ( (nOldScale != nNewScale) || (nOldScaleToPages != nNewScaleToPages) )
+ InvalidateTextWidth( rStyleSheet.GetName() );
+ }
+ break;
+
+ case SFX_STYLE_FAMILY_PARA:
+ {
+ BOOL bNumFormatChanged;
+ if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
+ rSet, rChanges ) )
+ InvalidateTextWidth( NULL, NULL, bNumFormatChanged );
+ ULONG nOldFormat =
+ ((const SfxUInt32Item*)&rSet.Get(
+ ATTR_VALUE_FORMAT ))->GetValue();
+ ULONG nNewFormat =
+ ((const SfxUInt32Item*)&rChanges.Get(
+ ATTR_VALUE_FORMAT ))->GetValue();
+ LanguageType eNewLang, eOldLang;
+ eNewLang = eOldLang = LANGUAGE_DONTKNOW;
+ if ( nNewFormat != nOldFormat )
+ {
+ SvNumberFormatter* pFormatter = GetFormatTable();
+ eOldLang = pFormatter->GetEntry( nOldFormat )->GetLanguage();
+ eNewLang = pFormatter->GetEntry( nNewFormat )->GetLanguage();
+ }
+
+ // Bedeutung der Items in rChanges:
+ // Item gesetzt - Aenderung uebernehmen
+ // Dontcare - Default setzen
+ // Default - keine Aenderung
+ // ("keine Aenderung" geht nicht mit PutExtended, darum Schleife)
+ for (USHORT nWhich = ATTR_PATTERN_START; nWhich <= ATTR_PATTERN_END; nWhich++)
+ {
+ const SfxPoolItem* pItem;
+ SfxItemState eState = rChanges.GetItemState( nWhich, FALSE, &pItem );
+ if ( eState == SFX_ITEM_SET )
+ rSet.Put( *pItem );
+ else if ( eState == SFX_ITEM_DONTCARE )
+ rSet.ClearItem( nWhich );
+ // bei Default nichts
+ }
+
+ if ( eNewLang != eOldLang )
+ rSet.Put(
+ SvxLanguageItem( eNewLang, ATTR_LANGUAGE_FORMAT ) );
+ }
+ break;
+ }
+}
+
+//------------------------------------------------------------------------
+
+void ScDocument::CopyStdStylesFrom( ScDocument* pSrcDoc )
+{
+ pStylePool->CopyStdStylesFrom( pSrcDoc->pStylePool );
+}
+
+//------------------------------------------------------------------------
+
+void ScDocument::InvalidateTextWidth( const String& rStyleName )
+{
+ const USHORT nCount = GetTableCount();
+ for ( USHORT i=0; i<nCount && pTab[i]; i++ )
+ if ( pTab[i]->GetPageStyle() == rStyleName )
+ InvalidateTextWidth( i );
+}
+
+//------------------------------------------------------------------------
+
+void ScDocument::InvalidateTextWidth( USHORT nTab )
+{
+ ScAddress aAdrFrom( 0, 0, nTab );
+ ScAddress aAdrTo ( MAXCOL, MAXROW, nTab );
+ InvalidateTextWidth( &aAdrFrom, &aAdrTo );
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScDocument::IsPageStyleInUse( const String& rStrPageStyle, USHORT* pInTab )
+{
+ BOOL bInUse = FALSE;
+ const USHORT nCount = GetTableCount();
+
+ for ( USHORT i=0; !bInUse && i<nCount && pTab[i]; i++ )
+ bInUse = ( pTab[i]->GetPageStyle() == rStrPageStyle );
+
+ if ( pInTab )
+ *pInTab = i-1;
+
+ return bInUse;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScDocument::RemovePageStyleInUse( const String& rStyle )
+{
+ BOOL bWasInUse = FALSE;
+ const USHORT nCount = GetTableCount();
+
+ for ( USHORT i=0; i<nCount && pTab[i]; i++ )
+ if ( pTab[i]->GetPageStyle() == rStyle )
+ {
+ bWasInUse = TRUE;
+ pTab[i]->SetPageStyle( STR_STANDARD );
+ }
+
+ return bWasInUse;
+}
+
+BOOL ScDocument::RenamePageStyleInUse( const String& rOld, const String& rNew )
+{
+ BOOL bWasInUse = FALSE;
+ const USHORT nCount = GetTableCount();
+
+ for ( USHORT i=0; i<nCount && pTab[i]; i++ )
+ if ( pTab[i]->GetPageStyle() == rOld )
+ {
+ bWasInUse = TRUE;
+ pTab[i]->SetPageStyle( rNew );
+ }
+
+ return bWasInUse;
+}
+
+//------------------------------------------------------------------------
+
+void ScDocument::InvalidateTextWidth( const ScAddress* pAdrFrom,
+ const ScAddress* pAdrTo,
+ BOOL bBroadcast )
+{
+ bBroadcast = (bBroadcast && GetDocOptions().IsCalcAsShown());
+ if ( pAdrFrom && !pAdrTo )
+ {
+ const USHORT nTab = pAdrFrom->Tab();
+
+ if ( pTab[nTab] )
+ pTab[nTab]->InvalidateTextWidth( pAdrFrom, NULL, bBroadcast );
+ }
+ else
+ {
+ const USHORT nTabStart = pAdrFrom ? pAdrFrom->Tab() : 0;
+ const USHORT nTabEnd = pAdrTo ? pAdrTo->Tab() : MAXTAB;
+
+ for ( USHORT nTab=nTabStart; nTab<=nTabEnd; nTab++ )
+ if ( pTab[nTab] )
+ pTab[nTab]->InvalidateTextWidth( pAdrFrom, pAdrTo, bBroadcast );
+ }
+}
+
+//------------------------------------------------------------------------
+
+#define CALCMAX 1000 // Berechnungen
+#define ABORT_EVENTS (INPUT_ANY & ~INPUT_TIMER & ~INPUT_OTHER)
+
+BOOL ScDocument::IdleCalcTextWidth() // TRUE = demnaechst wieder versuchen
+{
+ if ( bIdleDisabled || IsInLinkUpdate() )
+ return FALSE;
+ bIdleDisabled = TRUE;
+
+// ULONG nMs = 0;
+// USHORT nIter = 0;
+
+ const ULONG nStart = GetSysTicks();
+ double nPPTX = 0.0;
+ double nPPTY = 0.0;
+ OutputDevice* pDev = NULL;
+ MapMode aOldMap;
+ ScStyleSheet* pStyle = NULL;
+ ScColumnIterator* pColIter = NULL;
+ ScTable* pTable = NULL;
+ ScColumn* pColumn = NULL;
+ ScBaseCell* pCell = NULL;
+ USHORT nTab = aCurTextWidthCalcPos.Tab();
+ USHORT nRow = aCurTextWidthCalcPos.Row();
+ short nCol = aCurTextWidthCalcPos.Col();
+ USHORT nRestart = 0;
+ USHORT nZoom = 0;
+ BOOL bNeedMore= FALSE;
+
+ if ( nRow > MAXROW )
+ nRow = 0, nCol--;
+ if ( nCol < 0 )
+ nCol = MAXCOL, nTab++;
+ if ( nTab > MAXTAB || !pTab[nTab] )
+ nTab = 0;
+
+// DBG_ERROR( String("Start = ") + String(nTab) + String(',') + String(nCol) + String(',') + String(nRow) );
+
+ // SearchMask/Family muss gemerkt werden,
+ // damit z.B. der Organizer nicht durcheinanderkommt, wenn zwischendurch eine
+ // Query-Box aufgemacht wird !!!
+
+ USHORT nOldMask = pStylePool->GetSearchMask();
+ SfxStyleFamily eOldFam = pStylePool->GetSearchFamily();
+
+ pTable = pTab[nTab];
+ pStylePool->SetSearchMask( SFX_STYLE_FAMILY_PAGE, SFXSTYLEBIT_ALL );
+ pStyle = (ScStyleSheet*)pStylePool->Find( pTable->aPageStyle,
+ SFX_STYLE_FAMILY_PAGE );
+
+ if ( !pStyle )
+ DBG_ERROR( "Missing StyleSheet :-/" );
+
+
+ BOOL bProgress = FALSE;
+ if ( pStyle && 0 == GET_SCALEVALUE(pStyle->GetItemSet(),ATTR_PAGE_SCALETOPAGES) )
+ {
+ USHORT nCount = 0;
+
+ nZoom = GET_SCALEVALUE(pStyle->GetItemSet(),ATTR_PAGE_SCALE);
+ Fraction aZoomFract( nZoom, 100 );
+ pColumn = &pTable->aCol[nCol];
+ pColIter = new ScColumnIterator( pColumn, nRow, MAXROW );
+
+ while ( (nZoom > 0) && (nCount < CALCMAX) && (nRestart < 2) )
+ {
+ if ( pColIter->Next( nRow, pCell ) )
+ {
+ if ( TEXTWIDTH_DIRTY == pCell->GetTextWidth() )
+ {
+ if ( !pDev )
+ {
+ pDev = GetPrinter();
+ aOldMap = pDev->GetMapMode();
+ pDev->SetMapMode( MAP_PIXEL ); // wichtig fuer GetNeededSize
+
+ Point aPix1000 = pDev->LogicToPixel( Point(1000,1000), MAP_TWIP );
+ nPPTX = aPix1000.X() / 1000.0;
+ nPPTY = aPix1000.Y() / 1000.0;
+ }
+ if ( !bProgress && pCell->GetCellType() == CELLTYPE_FORMULA
+ && ((ScFormulaCell*)pCell)->GetDirty() )
+ {
+ ScProgress::CreateInterpretProgress( this, FALSE );
+ bProgress = TRUE;
+ }
+
+// DBG_ERROR( String("t,c,r = ") + String(nTab) + String(',') + String(nCol) + String(',') + String(nRow) );
+// DBG_ERROR( String("nOldWidth = ") + String(pCell->GetTextWidth()) );
+
+ USHORT nNewWidth = (USHORT)GetNeededSize( nCol, nRow, nTab,
+ pDev, nPPTX, nPPTY,
+ aZoomFract,aZoomFract, TRUE,
+ TRUE ); // bTotalSize
+
+// DBG_ERROR( String("nNewWidth = ") + String(nNewWidth) );
+
+ pCell->SetTextWidth( nNewWidth );
+
+ bNeedMore = TRUE;
+ }
+ }
+ else
+ {
+ BOOL bNewTab = FALSE;
+
+ nRow = 0;
+ nCol--;
+
+ if ( nCol < 0 )
+ {
+ nCol = MAXCOL;
+ nTab++;
+ bNewTab = TRUE;
+ }
+
+ if ( nTab > MAXTAB || !pTab[nTab] )
+ {
+ nTab = 0;
+ nRestart++;
+ bNewTab = TRUE;
+ }
+
+ if ( nRestart < 2 )
+ {
+ if ( bNewTab )
+ {
+ pTable = pTab[nTab];
+ pStyle = (ScStyleSheet*)pStylePool->Find( pTable->aPageStyle,
+ SFX_STYLE_FAMILY_PAGE );
+
+ if ( pStyle )
+ {
+ SfxItemSet& rSet = pStyle->GetItemSet();
+ if ( GET_SCALEVALUE( rSet, ATTR_PAGE_SCALETOPAGES ) == 0 )
+ nZoom = GET_SCALEVALUE(rSet, ATTR_PAGE_SCALE );
+ else
+ nZoom = 0;
+ }
+ else
+ DBG_ERROR( "Missing StyleSheet :-/" );
+ }
+
+ if ( nZoom > 0 )
+ {
+ delete pColIter;
+
+ pColumn = &pTable->aCol[nCol];
+ pColIter = new ScColumnIterator( pColumn, nRow, MAXROW );
+ }
+ else
+ nTab++; // Tabelle nicht mit absolutem Zoom -> naechste
+ }
+ }
+
+// nIter = nCount;
+
+ nCount++;
+
+ // Idle Berechnung abbrechen, wenn Berechnungen laenger als
+ // 50ms dauern, oder nach 32 Berechnungen mal nachschauen, ob
+ // bestimmte Events anstehen, die Beachtung wuenschen:
+
+// nMs = SysTicksToMs( GetSysTicks() - nStart );
+
+ if ( ( 50L < SysTicksToMs( GetSysTicks() - nStart ) )
+ || ( !(nCount&31) && Application::AnyInput( ABORT_EVENTS ) ) )
+ nCount = CALCMAX;
+ }
+ }
+ else
+ nTab++; // Tabelle nicht mit absolutem Zoom -> naechste
+
+ if ( bProgress )
+ ScProgress::DeleteInterpretProgress();
+
+ delete pColIter;
+
+// DBG_ERROR( String(nCount) + String(" End = ") + String(nTab) + String(',') + String(nCol) + String(',') + String(nRow) );
+
+ if (pDev)
+ pDev->SetMapMode(aOldMap);
+
+ aCurTextWidthCalcPos.SetTab( nTab );
+ aCurTextWidthCalcPos.SetRow( nRow );
+ aCurTextWidthCalcPos.SetCol( (USHORT)nCol );
+
+// DBG_ERROR( String(nMs) + String(" ms (") + String(nIter) + String(')') );
+
+ pStylePool->SetSearchMask( eOldFam, nOldMask );
+ bIdleDisabled = FALSE;
+
+ return bNeedMore;
+}
+
+//------------------------------------------------------------------------
+
+class ScSpellStatus
+{
+public:
+ BOOL bModified;
+
+ ScSpellStatus() : bModified(FALSE) {};
+
+ DECL_LINK (EventHdl, EditStatus*);
+};
+
+IMPL_LINK( ScSpellStatus, EventHdl, EditStatus *, pStatus )
+{
+ ULONG nStatus = pStatus->GetStatusWord();
+ if ( nStatus & EE_STAT_WRONGWORDCHANGED )
+ bModified = TRUE;
+
+ return 0;
+}
+
+// SPELL_MAXCELLS muss mindestens 256 sein, solange am Iterator keine
+// Start-Spalte gesetzt werden kann
+
+//! SPELL_MAXTEST fuer Timer und Idle unterschiedlich ???
+
+// SPELL_MAXTEST now divided between visible and rest of document
+
+#define SPELL_MAXTEST_VIS 1
+#define SPELL_MAXTEST_ALL 3
+#define SPELL_MAXCELLS 256
+
+BOOL ScDocument::OnlineSpellInRange( const ScRange& rSpellRange, ScAddress& rSpellPos,
+ USHORT nMaxTest )
+{
+ ScEditEngineDefaulter* pEngine = NULL; //! am Dokument speichern
+ SfxItemSet* pDefaults = NULL;
+ ScSpellStatus aStatus;
+
+ USHORT nCellCount = 0; // Zellen insgesamt
+ USHORT nTestCount = 0; // Aufrufe Spelling
+ BOOL bChanged = FALSE; // Aenderungen?
+
+ USHORT nCol = rSpellRange.aStart.Col(); // iterator always starts on the left edge
+ USHORT nRow = rSpellPos.Row();
+ USHORT nTab = rSpellPos.Tab();
+ if ( !pTab[nTab] ) // sheet deleted?
+ {
+ nTab = rSpellRange.aStart.Tab();
+ nRow = rSpellRange.aStart.Row();
+ if ( !pTab[nTab] )
+ {
+ // may happen for visible range
+ return FALSE;
+ }
+ }
+ ScHorizontalCellIterator aIter( this, nTab,
+ rSpellRange.aStart.Col(), nRow,
+ rSpellRange.aEnd.Col(), rSpellRange.aEnd.Row() );
+ ScBaseCell* pCell = aIter.GetNext( nCol, nRow );
+ // skip everything left of rSpellPos:
+ while ( pCell && nRow == rSpellPos.Row() && nCol < rSpellPos.Col() )
+ pCell = aIter.GetNext( nCol, nRow );
+ while ( pCell )
+ {
+ CellType eType = pCell->GetCellType();
+ if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT )
+ {
+ if (!pEngine)
+ {
+ // #71154# ScTabEditEngine is needed
+ // because MapMode must be set for some old documents
+ pEngine = new ScTabEditEngine( this );
+ pEngine->SetControlWord( pEngine->GetControlWord() |
+ ( EE_CNTRL_ONLINESPELLING | EE_CNTRL_ALLOWBIGOBJS ) );
+ pEngine->SetStatusEventHdl( LINK( &aStatus, ScSpellStatus, EventHdl ) );
+ // Delimiters hier wie in inputhdl.cxx !!!
+ pEngine->SetWordDelimiters(
+ ScEditUtil::ModifyDelimiters( pEngine->GetWordDelimiters() ) );
+ pDefaults = new SfxItemSet( pEngine->GetEmptyItemSet() );
+
+#ifdef ONE_LINGU
+ pEngine->SetSpeller( OFF_APP()->GetSpellChecker() );
+#endif
+ }
+
+ const ScPatternAttr* pPattern = GetPattern( nCol, nRow, nTab );
+ pPattern->FillEditItemSet( pDefaults );
+ pEngine->SetDefaults( pDefaults, FALSE ); //! noetig ?
+
+#ifdef ONE_LINGU
+ USHORT nCellLang = ((const SvxLanguageItem&)
+ pPattern->GetItem(ATTR_FONT_LANGUAGE)).GetValue();
+ if ( nCellLang == LANGUAGE_SYSTEM )
+ nCellLang = System::GetLanguage(); // never use SYSTEM for spelling
+ pEngine->SetDefaultLanguage( nCellLang );
+#else
+ SpellCheck& rSpeller = *OFF_APP()->GetSpellChecker();
+ USHORT nCellLang = ((const SvxLanguageItem&)
+ pPattern->GetItem(ATTR_FONT_LANGUAGE)).GetValue();
+ if ( nCellLang == LANGUAGE_SYSTEM )
+ nCellLang = System::GetLanguage(); // Spelling nie mit SYSTEM
+ rSpeller.SetActualLanguage( nCellLang );
+ pEngine->SetSpeller(&rSpeller);
+#endif
+
+ if ( eType == CELLTYPE_STRING )
+ {
+ String aText;
+ ((ScStringCell*)pCell)->GetString(aText);
+ pEngine->SetText( aText );
+ }
+ else
+ pEngine->SetText( *((ScEditCell*)pCell)->GetData() );
+
+ aStatus.bModified = FALSE;
+ pEngine->CompleteOnlineSpelling();
+ if ( aStatus.bModified ) // Fehler dazu oder weggekommen?
+ {
+ BOOL bNeedEdit = TRUE; // Test auf einfachen Text
+ if ( !pEngine->HasOnlineSpellErrors() )
+ {
+ ScEditAttrTester aTester( pEngine );
+ bNeedEdit = aTester.NeedsObject();
+ }
+
+ if ( bNeedEdit )
+ {
+ EditTextObject* pNewData = pEngine->CreateTextObject();
+ if ( eType == CELLTYPE_EDIT )
+ ((ScEditCell*)pCell)->SetData( pNewData,
+ pEngine->GetEditTextObjectPool() );
+ else
+ PutCell( nCol, nRow, nTab, new ScEditCell( pNewData,
+ this, pEngine->GetEditTextObjectPool() ) );
+ delete pNewData;
+ }
+ else // einfacher String
+ PutCell( nCol, nRow, nTab, new ScStringCell( pEngine->GetText() ) );
+
+ // Paint
+ if (pShell)
+ {
+ // #47751# Seitenvorschau ist davon nicht betroffen
+ // (sollte jedenfalls nicht)
+ ScPaintHint aHint( ScRange( nCol, nRow, nTab ), PAINT_GRID );
+ aHint.SetPrintFlag( FALSE );
+ pShell->Broadcast( aHint );
+ }
+
+ bChanged = TRUE;
+ }
+
+ if ( ++nTestCount >= nMaxTest ) // checked enough text?
+ break;
+ }
+
+ if ( ++nCellCount >= SPELL_MAXCELLS ) // seen enough cells?
+ break;
+
+ pCell = aIter.GetNext( nCol, nRow );
+ }
+
+ if ( pCell )
+ {
+ ++nCol; // continue after last cell
+ if ( nCol > rSpellRange.aEnd.Col() )
+ {
+ nCol = rSpellRange.aStart.Col();
+ ++nRow;
+ if ( nRow > rSpellRange.aEnd.Row() )
+ pCell = NULL;
+ }
+ }
+
+ if (!pCell) // end of range reached -> next sheet
+ {
+ ++nTab;
+ if ( nTab > rSpellRange.aEnd.Tab() || !pTab[nTab] )
+ nTab = rSpellRange.aStart.Tab();
+ nCol = rSpellRange.aStart.Col();
+ nRow = rSpellRange.aStart.Row();
+
+ nVisSpellState = VSPL_DONE; //! only if this is for the visible range
+ }
+ rSpellPos.Set( nCol, nRow, nTab );
+
+ delete pDefaults;
+ delete pEngine; // bevor aStatus out of scope geht
+
+ return bChanged;
+}
+
+
+BOOL ScDocument::ContinueOnlineSpelling()
+{
+ if ( bIdleDisabled || !pDocOptions->IsAutoSpell() || (pShell && pShell->IsReadOnly()) )
+ return FALSE;
+
+ //! use one EditEngine for both calls
+
+ // #41504# first check visible range
+ BOOL bResult = OnlineSpellInRange( aVisSpellRange, aVisSpellPos, SPELL_MAXTEST_VIS );
+
+ // during first pass through visible range, always continue
+ if ( nVisSpellState == VSPL_START )
+ bResult = TRUE;
+
+ if (bResult)
+ {
+ // if errors found, continue there
+ OnlineSpellInRange( aVisSpellRange, aVisSpellPos, SPELL_MAXTEST_ALL );
+ }
+ else
+ {
+ // if nothing found there, continue with rest of document
+ ScRange aTotalRange( 0,0,0, MAXCOL,MAXROW,MAXTAB );
+ bResult = OnlineSpellInRange( aTotalRange, aOnlineSpellPos, SPELL_MAXTEST_ALL );
+ }
+ return bResult;
+}
+
+
+void ScDocument::SetOnlineSpellPos( const ScAddress& rPos )
+{
+ aOnlineSpellPos = rPos;
+
+ // skip visible area for aOnlineSpellPos
+ if ( aVisSpellRange.In( aOnlineSpellPos ) )
+ aOnlineSpellPos = aVisSpellRange.aEnd;
+}
+
+BOOL ScDocument::SetVisibleSpellRange( const ScRange& rNewRange )
+{
+ BOOL bChange = ( aVisSpellRange != rNewRange );
+ if (bChange)
+ {
+ // continue spelling through visible range when scrolling down
+ BOOL bContDown = ( nVisSpellState == VSPL_START && rNewRange.In( aVisSpellPos ) &&
+ rNewRange.aStart.Row() > aVisSpellRange.aStart.Row() &&
+ rNewRange.aStart.Col() == aVisSpellRange.aStart.Col() &&
+ rNewRange.aEnd.Col() == aVisSpellRange.aEnd.Col() );
+
+ aVisSpellRange = rNewRange;
+
+ if ( !bContDown )
+ {
+ aVisSpellPos = aVisSpellRange.aStart;
+ nVisSpellState = VSPL_START;
+ }
+
+ // skip visible area for aOnlineSpellPos
+ if ( aVisSpellRange.In( aOnlineSpellPos ) )
+ aOnlineSpellPos = aVisSpellRange.aEnd;
+ }
+ return bChange;
+}
+
+void ScDocument::RemoveAutoSpellObj()
+{
+ // alle Spelling-Informationen entfernen
+
+ for (USHORT nTab=0; nTab<=MAXTAB && pTab[nTab]; nTab++)
+ pTab[nTab]->RemoveAutoSpellObj();
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScDocument::IdleCheckLinks() // TRUE = demnaechst wieder versuchen
+{
+ BOOL bAnyLeft = FALSE;
+
+ const SvBaseLinks& rLinks = pLinkManager->GetLinks();
+ USHORT nCount = rLinks.Count();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ SvBaseLink* pBase = *rLinks[i];
+ if (pBase->ISA(ScDdeLink))
+ {
+ ScDdeLink* pDdeLink = (ScDdeLink*)pBase;
+ if (pDdeLink->NeedsUpdate())
+ {
+ pDdeLink->TryUpdate();
+ if (pDdeLink->NeedsUpdate()) // war nix?
+ bAnyLeft = TRUE;
+ }
+ }
+ }
+
+ return bAnyLeft;
+}
+
+void ScDocument::SaveDdeLinks(SvStream& rStream) const
+{
+ // bei 4.0-Export alle mit Modus != DEFAULT weglassen
+ BOOL bExport40 = ( rStream.GetVersion() <= SOFFICE_FILEFORMAT_40 );
+
+ const SvBaseLinks& rLinks = pLinkManager->GetLinks();
+ USHORT nCount = rLinks.Count();
+
+ // erstmal zaehlen...
+
+ USHORT nDdeCount = 0;
+ USHORT i;
+ for (i=0; i<nCount; i++)
+ {
+ SvBaseLink* pBase = *rLinks[i];
+ if (pBase->ISA(ScDdeLink))
+ if ( !bExport40 || ((ScDdeLink*)pBase)->GetMode() == SC_DDE_DEFAULT )
+ ++nDdeCount;
+ }
+
+ // Header
+
+ ScMultipleWriteHeader aHdr( rStream );
+ rStream << nDdeCount;
+
+ // Links speichern
+
+ for (i=0; i<nCount; i++)
+ {
+ SvBaseLink* pBase = *rLinks[i];
+ if (pBase->ISA(ScDdeLink))
+ {
+ ScDdeLink* pLink = (ScDdeLink*)pBase;
+ if ( !bExport40 || pLink->GetMode() == SC_DDE_DEFAULT )
+ pLink->Store( rStream, aHdr );
+ }
+ }
+}
+
+void ScDocument::LoadDdeLinks(SvStream& rStream)
+{
+ ScMultipleReadHeader aHdr( rStream );
+
+ USHORT nCount;
+ rStream >> nCount;
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScDdeLink* pLink = new ScDdeLink( this, rStream, aHdr );
+ pLinkManager->InsertDDELink( *pLink,
+ pLink->GetAppl(), pLink->GetTopic(), pLink->GetItem() );
+ }
+}
+
+BOOL ScDocument::HasDdeLinks() const
+{
+ if (pLinkManager) // Clipboard z.B. hat keinen LinkManager
+ {
+ const SvBaseLinks& rLinks = pLinkManager->GetLinks();
+ USHORT nCount = rLinks.Count();
+ for (USHORT i=0; i<nCount; i++)
+ if ((*rLinks[i])->ISA(ScDdeLink))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void ScDocument::SetInLinkUpdate(BOOL bSet)
+{
+ // called from TableLink and AreaLink
+
+ DBG_ASSERT( bInLinkUpdate != bSet, "SetInLinkUpdate twice" );
+ bInLinkUpdate = bSet;
+}
+
+BOOL ScDocument::IsInLinkUpdate() const
+{
+ //! set flag in document from dde link update
+ return bInLinkUpdate || ScDdeLink::IsInUpdate();
+}
+
+void ScDocument::UpdateDdeLinks()
+{
+ const SvBaseLinks& rLinks = pLinkManager->GetLinks();
+ USHORT nCount = rLinks.Count();
+ USHORT i;
+
+ // #49226# falls das Updaten laenger dauert, erstmal alle Werte
+ // zuruecksetzen, damit nichts altes (falsches) stehen bleibt
+ BOOL bAny = FALSE;
+ for (i=0; i<nCount; i++)
+ {
+ SvBaseLink* pBase = *rLinks[i];
+ if (pBase->ISA(ScDdeLink))
+ {
+ ((ScDdeLink*)pBase)->ResetValue();
+ bAny = TRUE;
+ }
+ }
+ if (bAny)
+ {
+ // Formeln berechnen und painten wie im TrackTimeHdl
+ TrackFormulas();
+ pShell->Broadcast( SfxSimpleHint( FID_DATACHANGED ) );
+ ResetChanged( ScRange(0,0,0,MAXCOL,MAXROW,MAXTAB) );
+
+ // wenn FID_DATACHANGED irgendwann mal asynchron werden sollte
+ // (z.B. mit Invalidate am Window), muss hier ein Update erzwungen werden.
+ }
+
+ // nun wirklich updaten...
+ for (i=0; i<nCount; i++)
+ {
+ SvBaseLink* pBase = *rLinks[i];
+ if (pBase->ISA(ScDdeLink))
+ ((ScDdeLink*)pBase)->TryUpdate(); // bei DDE-Links TryUpdate statt Update
+ }
+}
+
+BOOL ScDocument::UpdateDdeLink( const String& rAppl, const String& rTopic, const String& rItem )
+{
+ // fuer refresh() per StarOne Api
+ // ResetValue() fuer einzelnen Link nicht noetig
+ //! wenn's mal alles asynchron wird, aber auch hier
+
+ BOOL bFound = FALSE;
+ const SvBaseLinks& rLinks = pLinkManager->GetLinks();
+ USHORT nCount = rLinks.Count();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ SvBaseLink* pBase = *rLinks[i];
+ if (pBase->ISA(ScDdeLink))
+ {
+ ScDdeLink* pDdeLink = (ScDdeLink*)pBase;
+ if ( pDdeLink->GetAppl() == rAppl &&
+ pDdeLink->GetTopic() == rTopic &&
+ pDdeLink->GetItem() == rItem )
+ {
+ pDdeLink->TryUpdate();
+ bFound = TRUE; // koennen theoretisch mehrere sein (Mode), darum weitersuchen
+ }
+ }
+ }
+ return bFound;
+}
+
+void ScDocument::DisconnectDdeLinks()
+{
+ if (pLinkManager)
+ {
+ const SvBaseLinks& rLinks = pLinkManager->GetLinks();
+ USHORT nCount = rLinks.Count();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ SvBaseLink* pBase = *rLinks[i];
+ if (pBase->ISA(ScDdeLink))
+ pBase->Disconnect(); // bleibt im LinkManager eingetragen
+ }
+ }
+}
+
+void ScDocument::CopyDdeLinks( ScDocument* pDestDoc ) const
+{
+ if (bIsClip) // aus Stream erzeugen
+ {
+ if (pClipData)
+ {
+ pClipData->Seek(0);
+ pDestDoc->LoadDdeLinks(*pClipData);
+ }
+ }
+ else // Links direkt kopieren
+ {
+ const SvBaseLinks& rLinks = pLinkManager->GetLinks();
+ USHORT nCount = rLinks.Count();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ SvBaseLink* pBase = *rLinks[i];
+ if (pBase->ISA(ScDdeLink))
+ {
+ ScDdeLink* pNew = new ScDdeLink( pDestDoc, *(ScDdeLink*)pBase );
+
+ pDestDoc->pLinkManager->InsertDDELink( *pNew,
+ pNew->GetAppl(), pNew->GetTopic(), pNew->GetItem() );
+ }
+ }
+ }
+}
+
+void ScDocument::CreateDdeLink( const String& rAppl, const String& rTopic, const String& rItem )
+{
+ // DDE-Link anlegen und nicht updaten (z.B. fuer Excel-Import,
+ // damit nicht ohne Nachfrage Verbindungen aufgebaut werden)
+
+ BYTE nMode = SC_DDE_DEFAULT;
+
+ // zuerst suchen, ob schon vorhanden
+ //! Dde-Links (zusaetzlich) effizienter am Dokument speichern?
+ const SvBaseLinks& rLinks = pLinkManager->GetLinks();
+ USHORT nCount = rLinks.Count();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ SvBaseLink* pBase = *rLinks[i];
+ if (pBase->ISA(ScDdeLink))
+ {
+ ScDdeLink* pLink = (ScDdeLink*)pBase;
+ if ( pLink->GetAppl() == rAppl &&
+ pLink->GetTopic() == rTopic &&
+ pLink->GetItem() == rItem &&
+ pLink->GetMode() == nMode )
+ return; // dann nichts tun
+ }
+ }
+
+ // neu anlegen, aber kein TryUpdate
+ ScDdeLink* pNew = new ScDdeLink( this, rAppl, rTopic, rItem, nMode );
+ pLinkManager->InsertDDELink( *pNew, rAppl, rTopic, rItem );
+}
+
+USHORT ScDocument::GetDdeLinkCount() const
+{
+ USHORT nDdeCount = 0;
+ if (pLinkManager)
+ {
+ const SvBaseLinks& rLinks = pLinkManager->GetLinks();
+ USHORT nCount = rLinks.Count();
+ for (USHORT i=0; i<nCount; i++)
+ if ((*rLinks[i])->ISA(ScDdeLink))
+ ++nDdeCount;
+ }
+ return nDdeCount;
+}
+
+BOOL ScDocument::GetDdeLinkData( USHORT nPos, String& rAppl, String& rTopic, String& rItem ) const
+{
+ USHORT nDdeCount = 0;
+ if (pLinkManager)
+ {
+ const SvBaseLinks& rLinks = pLinkManager->GetLinks();
+ USHORT nCount = rLinks.Count();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ SvBaseLink* pBase = *rLinks[i];
+ if (pBase->ISA(ScDdeLink))
+ {
+ if ( nDdeCount == nPos )
+ {
+ ScDdeLink* pDde = (ScDdeLink*)pBase;
+ rAppl = pDde->GetAppl();
+ rTopic = pDde->GetTopic();
+ rItem = pDde->GetItem();
+ return TRUE;
+ }
+ ++nDdeCount;
+ }
+ }
+ }
+ return FALSE;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScDocument::HasAreaLinks() const
+{
+ if (pLinkManager) // Clipboard z.B. hat keinen LinkManager
+ {
+ const SvBaseLinks& rLinks = pLinkManager->GetLinks();
+ USHORT nCount = rLinks.Count();
+ for (USHORT i=0; i<nCount; i++)
+ if ((*rLinks[i])->ISA(ScAreaLink))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void ScDocument::UpdateAreaLinks()
+{
+ const SvBaseLinks& rLinks = pLinkManager->GetLinks();
+ USHORT nCount = rLinks.Count();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ SvBaseLink* pBase = *rLinks[i];
+ if (pBase->ISA(ScAreaLink))
+ pBase->Update();
+ }
+}
+
+void ScDocument::SaveAreaLinks(SvStream& rStream) const
+{
+ const SvBaseLinks& rLinks = pLinkManager->GetLinks();
+ USHORT nCount = rLinks.Count();
+
+ // erstmal zaehlen...
+
+ USHORT nAreaCount = 0;
+ USHORT i;
+ for (i=0; i<nCount; i++)
+ if ((*rLinks[i])->ISA(ScAreaLink)) // rLinks[i] = Pointer auf Ref
+ ++nAreaCount;
+
+ // Header
+
+ ScMultipleWriteHeader aHdr( rStream );
+ rStream << nAreaCount;
+
+ // Links speichern
+
+ for (i=0; i<nCount; i++)
+ {
+ SvBaseLink* pBase = *rLinks[i];
+ if (pBase->ISA(ScAreaLink))
+ {
+ ScAreaLink* pLink = (ScAreaLink*)pBase;
+
+ aHdr.StartEntry();
+
+ rStream.WriteByteString( pLink->GetFile(), rStream.GetStreamCharSet() );
+ rStream.WriteByteString( pLink->GetFilter(), rStream.GetStreamCharSet() );
+ rStream.WriteByteString( pLink->GetSource(), rStream.GetStreamCharSet() );
+ rStream << pLink->GetDestArea(); // ScRange
+ rStream.WriteByteString( pLink->GetOptions(), rStream.GetStreamCharSet() );
+ // filter options starting from 336
+
+ aHdr.EndEntry();
+ }
+ }
+}
+
+void ScDocument::LoadAreaLinks(SvStream& rStream)
+{
+ ScMultipleReadHeader aHdr( rStream );
+
+ if (!pShell)
+ {
+ DBG_ERROR("AreaLinks koennen nicht ohne Shell geladen werden");
+ return;
+ }
+
+ String aFile, aFilter, aOptions, aSource;
+ ScRange aDestArea;
+
+ USHORT nCount;
+ rStream >> nCount;
+ for (USHORT i=0; i<nCount; i++)
+ {
+ aHdr.StartEntry();
+
+ rStream.ReadByteString( aFile, rStream.GetStreamCharSet() );
+ rStream.ReadByteString( aFilter, rStream.GetStreamCharSet() );
+ rStream.ReadByteString( aSource, rStream.GetStreamCharSet() );
+ rStream >> aDestArea;
+ if ( aHdr.BytesLeft() ) // Filter-Optionen ab 336
+ rStream.ReadByteString( aOptions, rStream.GetStreamCharSet() );
+ else
+ aOptions.Erase();
+ aHdr.EndEntry();
+
+ ScAreaLink* pLink = new ScAreaLink( pShell, aFile, aFilter, aOptions,
+ aSource, aDestArea.aStart );
+ pLink->SetInCreate( TRUE );
+ pLink->SetDestArea( aDestArea );
+ pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, aFile, &aFilter, &aSource );
+ pLink->Update();
+ pLink->SetInCreate( FALSE );
+ }
+}
+
+
+//------------------------------------------------------------------------
+
+// TimerDelays etc.
+void ScDocument::KeyInput( const KeyEvent& rKEvt )
+{
+ if ( pChartListenerCollection->GetCount() )
+ pChartListenerCollection->StartTimer();
+}
+
+// ----------------------------------------------------------------------------
+//
+// Makro-Warnung:
+// Nur beim Laden von Dokumenten wird der Modus vorher auf ASK gesetzt, wenn
+// es in der EventConfig so eingestellt ist. Beim Ausfuehren waehrend des Ladens
+// wird dann nachgefragt. Nach dem Laden wird nachgeschaut, ob Makro-Aufrufe enthalten
+// sind (Formeln oder Gueltigkeit), und ggf. nachgefragt, sonst auf ALLOWED gesetzt.
+//
+
+BOOL ScDocument::CheckMacroWarn()
+{
+ if ( nMacroCallMode == SC_MACROCALL_ASK )
+ {
+ // Wenn wegen !IsSecure nichts ausgefuehrt wird, braucht auch nicht gefragt zu werden
+ if ( !pShell || !pShell->IsSecure() )
+ return FALSE; // nicht ausfuehren, aber nicht umstellen
+
+ QueryBox aBox( NULL, WinBits(WB_YES_NO | WB_DEF_YES),
+ ScGlobal::GetRscString(STR_MACRO_WARNING) );
+ USHORT nRet = aBox.Execute();
+ if ( nRet == RET_YES )
+ nMacroCallMode = SC_MACROCALL_ALLOWED;
+ else
+ nMacroCallMode = SC_MACROCALL_NOTALLOWED;
+ }
+
+ return ( nMacroCallMode == SC_MACROCALL_ALLOWED );
+}
+
+BOOL ScDocument::HasMacroCallsAfterLoad() // wird direkt nach dem Laden abgefragt
+{
+ // 1. ocMacro in formulas
+ // bHasMacroFunc is set when a formula with ocMacro is loaded
+
+ if ( bHasMacroFunc )
+ return TRUE;
+
+ // 2. Gueltigkeit mit Makro-Aufruf
+ // (direkt nach dem Laden sind nur Eintraege in der Liste, die auch verwendet werden)
+
+ if (pValidationList)
+ {
+ USHORT nCount = pValidationList->Count();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ const ScValidationData* pData = (*pValidationList)[i];
+ if ( pData->HasErrMsg() )
+ {
+ String aTitle, aMsg;
+ ScValidErrorStyle eStyle;
+ if ( pData->GetErrMsg( aTitle, aMsg, eStyle ) && eStyle == SC_VALERR_MACRO )
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE; // nichts gefunden
+}
+
+
+
+
diff --git a/sc/source/core/data/documen9.cxx b/sc/source/core/data/documen9.cxx
new file mode 100644
index 000000000000..dc4476832eaf
--- /dev/null
+++ b/sc/source/core/data/documen9.cxx
@@ -0,0 +1,838 @@
+/*************************************************************************
+ *
+ * $RCSfile: documen9.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <svx/eeitem.hxx>
+#include <svx/fontitem.hxx>
+#include <svx/svdetc.hxx>
+#include <svx/svditer.hxx>
+#include <svx/svdocapt.hxx>
+#include <svx/svdograf.hxx>
+#include <svx/svdoole2.hxx>
+#include <svx/svdouno.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdundo.hxx>
+#include <svx/xtable.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/printer.hxx>
+#include <sfx2/saveopt.hxx>
+#include <so3/ipobj.hxx>
+#include <sch/schdll.hxx>
+#include <sch/schdll0.hxx>
+#include <sch/memchrt.hxx>
+
+#include "document.hxx"
+#include "docoptio.hxx"
+#include "table.hxx"
+#include "drwlayer.hxx"
+#include "markdata.hxx"
+#include "userdat.hxx"
+#include "patattr.hxx"
+#include "rechead.hxx"
+#include "docpool.hxx"
+#include "chartarr.hxx"
+
+
+// -----------------------------------------------------------------------
+
+
+void ScDocument::SetLinkManager( SvxLinkManager* pNew )
+{
+ pLinkManager = pNew;
+ if (pDrawLayer)
+ pDrawLayer->SetLinkManager( pNew );
+}
+
+SfxBroadcaster* ScDocument::GetDrawBroadcaster()
+{
+ return pDrawLayer;
+}
+
+void ScDocument::BeginDrawUndo()
+{
+ if (pDrawLayer)
+ pDrawLayer->BeginCalcUndo();
+}
+
+XColorTable* ScDocument::GetColorTable()
+{
+ if (pDrawLayer)
+ return pDrawLayer->GetColorTable();
+ else
+ {
+ if (!pColorTable)
+ {
+ SfxIniManager* pIni = SFX_APP()->GetIniManager();
+ DBG_ASSERT( pIni, "SfxIniManager ???" );
+ pColorTable = new XColorTable( pIni->Get( SFX_KEY_PALETTE_PATH ) );
+ }
+
+ return pColorTable;
+ }
+}
+
+BOOL lcl_AdjustRanges( ScRangeList& rRanges, USHORT nSource, USHORT nDest, USHORT nTabCount )
+{
+ //! if multiple sheets are copied, update references into the other copied sheets?
+
+ BOOL bChanged = FALSE;
+
+ ULONG nCount = rRanges.Count();
+ for (ULONG i=0; i<nCount; i++)
+ {
+ ScRange* pRange = rRanges.GetObject(i);
+ if ( pRange->aStart.Tab() == nSource && pRange->aEnd.Tab() == nSource )
+ {
+ pRange->aStart.SetTab( nDest );
+ pRange->aEnd.SetTab( nDest );
+ bChanged = TRUE;
+ }
+ if ( pRange->aStart.Tab() >= nTabCount )
+ {
+ pRange->aStart.SetTab( nTabCount ? ( nTabCount - 1 ) : 0 );
+ bChanged = TRUE;
+ }
+ if ( pRange->aEnd.Tab() >= nTabCount )
+ {
+ pRange->aEnd.SetTab( nTabCount ? ( nTabCount - 1 ) : 0 );
+ bChanged = TRUE;
+ }
+ }
+
+ return bChanged;
+}
+
+void ScDocument::TransferDrawPage(ScDocument* pSrcDoc, USHORT nSrcPos, USHORT nDestPos)
+{
+ if (pDrawLayer && pSrcDoc->pDrawLayer)
+ {
+ SdrPage* pOldPage = pSrcDoc->pDrawLayer->GetPage(nSrcPos);
+ SdrPage* pNewPage = pDrawLayer->GetPage(nDestPos);
+
+ if (pOldPage && pNewPage)
+ {
+ SdrObjListIter aIter( *pOldPage, IM_FLAT );
+ SdrObject* pOldObject = aIter.Next();
+ while (pOldObject)
+ {
+ SdrObject* pNewObject = pOldObject->Clone( pNewPage, pDrawLayer );
+ pNewObject->NbcMove(Size(0,0));
+ pNewPage->InsertObject( pNewObject );
+
+ if (pDrawLayer->IsRecording())
+ pDrawLayer->AddCalcUndo( new SdrUndoInsertObj( *pNewObject ) );
+
+ // #71726# if it's a chart, make sure the data references are valid
+ // (this must be after InsertObject!)
+
+ if ( pNewObject->GetObjIdentifier() == OBJ_OLE2 )
+ {
+ // test if it's a chart with HasID, because GetChartData always loads the DLL
+ SvInPlaceObjectRef aIPObj = ((SdrOle2Obj*)pNewObject)->GetObjRef();
+ if ( aIPObj.Is() && SchModuleDummy::HasID( *aIPObj->GetSvFactory() ) )
+ {
+ SchMemChart* pChartData = SchDLL::GetChartData(aIPObj);
+ if ( pChartData )
+ {
+ ScChartArray aArray( this, *pChartData ); // parses range description
+ ScRangeListRef xRanges = aArray.GetRangeList();
+ if ( xRanges.Is() )
+ {
+ ScRangeListRef xNewRanges = new ScRangeList( *xRanges );
+ if ( lcl_AdjustRanges( *xNewRanges,
+ nSrcPos, nDestPos, GetTableCount() ) )
+ {
+ aArray.SetRangeList( xNewRanges );
+ }
+
+ // update all charts, even if the ranges were not changed
+
+ SchMemChart* pMemChart = aArray.CreateMemChart();
+ ScChartArray::CopySettings( *pMemChart, *pChartData );
+ SchDLL::Update( aIPObj, pMemChart );
+ delete pMemChart;
+ }
+ }
+ }
+ }
+
+ pOldObject = aIter.Next();
+ }
+ }
+ }
+}
+
+void ScDocument::ClearDrawPage(USHORT nTab)
+{
+ if (pDrawLayer)
+ {
+ SdrPage* pPage = pDrawLayer->GetPage(nTab);
+ if (pPage)
+ pPage->Clear();
+ else
+ DBG_ERROR("ScDocument::DeleteDrawObjects: pPage ???");
+ }
+}
+
+void ScDocument::InitDrawLayer( SfxObjectShell* pDocShell )
+{
+ if (pDocShell && !pShell)
+ pShell = pDocShell;
+
+// DBG_ASSERT(pShell,"InitDrawLayer ohne Shell");
+
+ if (!pDrawLayer)
+ {
+ if ( !pDocPool ) // der Pool wird fuer den Drucker gebraucht
+ {
+ DBG_ERROR("InitDrawLayer ohne DocPool");
+ return;
+ }
+
+ SdrEngineDefaults::SetFontHeight(423); // 12pt
+ String aName;
+ if (pShell)
+ aName = pShell->GetTitle();
+ pDrawLayer = new ScDrawLayer( this, aName );
+ if (pLinkManager)
+ pDrawLayer->SetLinkManager( pLinkManager );
+
+ // Draw-Pages initialisieren
+
+ for (USHORT nTab=0; nTab<=MAXTAB; nTab++)
+ if (pTab[nTab])
+ {
+ pDrawLayer->ScAddPage( nTab );
+ String aName;
+ pTab[nTab]->GetName(aName);
+ pDrawLayer->ScRenamePage( nTab, aName );
+
+ pTab[nTab]->SetDrawPageSize(); // #54782# sofort die richtige Groesse
+#if 0
+ ULONG nx = (ULONG) ((double) (MAXCOL+1) * STD_COL_WIDTH * HMM_PER_TWIPS );
+ ULONG ny = (ULONG) ((double) (MAXROW+1) * ScGlobal::nStdRowHeight * HMM_PER_TWIPS );
+ pDrawLayer->SetPageSize( nTab, Size( nx, ny ) );
+#endif
+ pDrawLayer->SetDefaultTabulator(
+ GetDocOptions().GetTabDistance());
+ }
+
+ UpdateDrawPrinter();
+ }
+}
+
+void ScDocument::UpdateDrawPrinter()
+{
+ if (pDrawLayer)
+ {
+ OutputDevice* pRefDev = GetPrinter();
+ if ( pPrinter->IsValid() )
+ pRefDev->SetMapMode( MAP_100TH_MM );
+ else
+ pRefDev = Application::GetDefaultDevice(); // should not happen
+ pDrawLayer->SetRefDevice(pRefDev);
+ }
+}
+
+BOOL ScDocument::IsChart( SdrObject* pObject )
+{
+ if ( pObject->GetObjIdentifier() == OBJ_OLE2 )
+ {
+ SvInPlaceObjectRef aIPObj = ((SdrOle2Obj*)pObject)->GetObjRef();
+ if (aIPObj.Is())
+ {
+ SvGlobalName aObjClsId = *aIPObj->GetSvFactory();
+ if (SchModuleDummy::HasID( aObjClsId ))
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+IMPL_LINK_INLINE_START( ScDocument, GetUserDefinedColor, USHORT *, pColorIndex )
+{
+ return (long) &((GetColorTable()->Get(*pColorIndex))->GetColor());
+}
+IMPL_LINK_INLINE_END( ScDocument, GetUserDefinedColor, USHORT *, pColorIndex )
+
+void ScDocument::DeleteDrawLayer()
+{
+ delete pDrawLayer;
+}
+
+void ScDocument::DeleteColorTable()
+{
+ delete pColorTable;
+}
+
+void ScDocument::LoadDrawLayer(SvStream& rStream)
+{
+ InitDrawLayer(); // anlegen
+ pDrawLayer->Load(rStream);
+
+ // nMaxTableNumber ist noch nicht initialisiert
+
+ USHORT nTableCount = 0;
+ while ( nTableCount <= MAXTAB && pTab[nTableCount] )
+ ++nTableCount;
+
+ USHORT nPageCount = pDrawLayer->GetPageCount();
+ if ( nPageCount > nTableCount && nTableCount != 0 )
+ {
+ // Manchmal sind beim Kopieren/Verschieben/Undo von Tabellen zuviele
+ // (leere) Pages in der Tabelle stehengeblieben. Weg damit!
+
+ DBG_ERROR("zuviele Draw-Pages in der Datei");
+
+ for (USHORT i=nTableCount; i<nPageCount; i++)
+ pDrawLayer->DeletePage(nTableCount);
+ }
+
+ // Controls auf richtigen Layer setzen
+ // (zumindest in Dateien aus der 502 koennen sie falsch sein,
+ // wegen des fehlenden Layers in alten Dateien)
+
+ nPageCount = pDrawLayer->GetPageCount();
+ for (USHORT i=0; i<nPageCount; i++)
+ {
+ SdrPage* pPage = pDrawLayer->GetPage(i);
+ SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ if ( pObject->ISA(SdrUnoObj) && pObject->GetLayer() != SC_LAYER_CONTROLS )
+ {
+ pObject->NbcSetLayer(SC_LAYER_CONTROLS);
+ DBG_ERROR("Control war auf falschem Layer");
+ }
+ pObject = aIter.Next();
+ }
+ }
+}
+
+void ScDocument::StoreDrawLayer(SvStream& rStream) const
+{
+ if (pDrawLayer)
+ {
+ // SetSavePortable wird mit VCL nicht mehr gebraucht
+ //BOOL bIndep = SFX_APP()->GetOptions().IsIndepGrfFmt();
+ //pDrawLayer->SetSavePortable( bIndep );
+
+ SfxApplication* pSfxApp = SFX_APP();
+
+ BOOL bCompr = pSfxApp->GetOptions().IsSaveGraphicsCompressed();
+ pDrawLayer->SetSaveCompressed( bCompr );
+
+ BOOL bNative = pSfxApp->GetOptions().IsSaveOriginalGraphics();
+ pDrawLayer->SetSaveNative( bNative );
+
+ pDrawLayer->Store(rStream);
+ }
+}
+
+BOOL ScDocument::DrawGetPrintArea( ScRange& rRange, BOOL bSetHor, BOOL bSetVer ) const
+{
+ return pDrawLayer->GetPrintArea( rRange, bSetHor, bSetVer );
+}
+
+void ScDocument::DrawMovePage( USHORT nOldPos, USHORT nNewPos )
+{
+ pDrawLayer->ScMovePage(nOldPos,nNewPos);
+}
+
+void ScDocument::DrawCopyPage( USHORT nOldPos, USHORT nNewPos )
+{
+ // angelegt wird die Page schon im ScTable ctor
+ pDrawLayer->ScCopyPage( nOldPos, nNewPos, FALSE );
+}
+
+void ScDocument::DeleteObjectsInArea( USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2,
+ const ScMarkData& rMark )
+{
+ if (!pDrawLayer)
+ return;
+
+ USHORT nTabCount = GetTableCount();
+ for (USHORT nTab=0; nTab<=nTabCount; nTab++)
+ if (pTab[nTab] && rMark.GetTableSelect(nTab))
+ pDrawLayer->DeleteObjectsInArea( nTab, nCol1, nRow1, nCol2, nRow2 );
+}
+
+void ScDocument::DeleteObjects( USHORT nTab )
+{
+ if (!pDrawLayer)
+ return;
+
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ pDrawLayer->DeleteObjects( nTab );
+ else
+ DBG_ERROR("DeleteObjects: falsche Tabelle");
+}
+
+void ScDocument::DeleteObjectsInSelection( const ScMarkData& rMark )
+{
+ if (!pDrawLayer)
+ return;
+
+ pDrawLayer->DeleteObjectsInSelection( rMark );
+}
+
+void ScDocument::StopAnimations( USHORT nTab, Window* pWin )
+{
+ if (!pDrawLayer)
+ return;
+ SdrPage* pPage = pDrawLayer->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+ if (!pPage)
+ return;
+
+ SdrObjListIter aIter( *pPage, IM_FLAT );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ if (pObject->ISA(SdrGrafObj))
+ {
+ SdrGrafObj* pGrafObj = (SdrGrafObj*)pObject;
+ if ( pGrafObj->IsAnimated() )
+//! pGrafObj->StopAnimation( pWin );
+ pGrafObj->StopAnimation();
+ }
+ pObject = aIter.Next();
+ }
+}
+
+void ScDocument::StartAnimations( USHORT nTab, Window* pWin )
+{
+ if (!pDrawLayer)
+ return;
+ SdrPage* pPage = pDrawLayer->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+ if (!pPage)
+ return;
+
+ SdrObjListIter aIter( *pPage, IM_FLAT );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ if (pObject->ISA(SdrGrafObj))
+ {
+ SdrGrafObj* pGrafObj = (SdrGrafObj*)pObject;
+ if ( pGrafObj->IsAnimated() )
+ {
+ const Rectangle& rRect = pGrafObj->GetBoundRect();
+ pGrafObj->StartAnimation( pWin, rRect.TopLeft(), rRect.GetSize() );
+ }
+ }
+ pObject = aIter.Next();
+ }
+}
+
+BOOL ScDocument::HasNoteObject( USHORT nCol, USHORT nRow, USHORT nTab ) const
+{
+ if (!pDrawLayer)
+ return FALSE;
+ SdrPage* pPage = pDrawLayer->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+ if (!pPage)
+ return FALSE;
+
+ BOOL bFound = FALSE;
+
+ SdrObjListIter aIter( *pPage, IM_FLAT );
+ SdrObject* pObject = aIter.Next();
+ while (pObject && !bFound)
+ {
+ if ( pObject->GetLayer() == SC_LAYER_INTERN && pObject->ISA( SdrCaptionObj ) )
+ {
+ ScDrawObjData* pData = ScDrawLayer::GetObjData( pObject );
+ if ( pData && nCol == pData->aStt.nCol && nRow == pData->aStt.nRow )
+ bFound = TRUE;
+ }
+ pObject = aIter.Next();
+ }
+
+ return bFound;
+}
+
+void ScDocument::RefreshNoteFlags()
+{
+ if (!pDrawLayer)
+ return;
+
+ USHORT nTab;
+ ScPostIt aNote;
+ for (nTab=0; nTab<=MAXTAB && pTab[nTab]; nTab++)
+ {
+ SdrPage* pPage = pDrawLayer->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+ if (pPage)
+ {
+ SdrObjListIter aIter( *pPage, IM_FLAT );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ if ( pObject->GetLayer() == SC_LAYER_INTERN && pObject->ISA( SdrCaptionObj ) )
+ {
+ ScDrawObjData* pData = ScDrawLayer::GetObjData( pObject );
+ if ( pData )
+ {
+ if ( GetNote( pData->aStt.nCol, pData->aStt.nRow, nTab, aNote ) )
+ if ( !aNote.IsShown() )
+ {
+ aNote.SetShown(TRUE);
+ SetNote( pData->aStt.nCol, pData->aStt.nRow, nTab, aNote );
+ }
+ }
+ }
+ pObject = aIter.Next();
+ }
+ }
+ }
+}
+
+BOOL ScDocument::HasBackgroundDraw( USHORT nTab, const Rectangle& rMMRect )
+{
+ // Gibt es Objekte auf dem Hintergrund-Layer, die (teilweise) von rMMRect
+ // betroffen sind?
+ // (fuer Drawing-Optimierung, vor dem Hintergrund braucht dann nicht geloescht
+ // zu werden)
+
+ if (!pDrawLayer)
+ return FALSE;
+ SdrPage* pPage = pDrawLayer->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+ if (!pPage)
+ return FALSE;
+
+ BOOL bFound = FALSE;
+
+ SdrObjListIter aIter( *pPage, IM_FLAT );
+ SdrObject* pObject = aIter.Next();
+ while (pObject && !bFound)
+ {
+ if ( pObject->GetLayer() == SC_LAYER_BACK && pObject->GetBoundRect().IsOver( rMMRect ) )
+ bFound = TRUE;
+ pObject = aIter.Next();
+ }
+
+ return bFound;
+}
+
+BOOL ScDocument::HasAnyDraw( USHORT nTab, const Rectangle& rMMRect )
+{
+ // Gibt es ueberhaupt Objekte, die (teilweise) von rMMRect
+ // betroffen sind?
+ // (um leere Seiten beim Drucken zu erkennen)
+
+ if (!pDrawLayer)
+ return FALSE;
+ SdrPage* pPage = pDrawLayer->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+ if (!pPage)
+ return FALSE;
+
+ BOOL bFound = FALSE;
+
+ SdrObjListIter aIter( *pPage, IM_FLAT );
+ SdrObject* pObject = aIter.Next();
+ while (pObject && !bFound)
+ {
+ if ( pObject->GetBoundRect().IsOver( rMMRect ) )
+ bFound = TRUE;
+ pObject = aIter.Next();
+ }
+
+ return bFound;
+}
+
+void ScDocument::EnsureGraphicNames()
+{
+ if (pDrawLayer)
+ pDrawLayer->EnsureGraphicNames();
+}
+
+SdrObject* ScDocument::GetObjectAtPoint( USHORT nTab, const Point& rPos )
+{
+ // fuer Drag&Drop auf Zeichenobjekt
+
+ SdrObject* pFound = NULL;
+ if (pDrawLayer && pTab[nTab])
+ {
+ SdrPage* pPage = pDrawLayer->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+ if (pPage)
+ {
+ SdrObjListIter aIter( *pPage, IM_FLAT );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ if ( pObject->GetBoundRect().IsInside(rPos) )
+ {
+ // Intern interessiert gar nicht
+ // Objekt vom Back-Layer nur, wenn kein Objekt von anderem Layer getroffen
+
+ SdrLayerID nLayer = pObject->GetLayer();
+ if ( nLayer != SC_LAYER_INTERN )
+ {
+ if ( nLayer != SC_LAYER_BACK ||
+ !pFound || pFound->GetLayer() == SC_LAYER_BACK )
+ {
+ pFound = pObject;
+ }
+ }
+ }
+ // weitersuchen -> letztes (oberstes) getroffenes Objekt nehmen
+
+ pObject = aIter.Next();
+ }
+ }
+ }
+ return pFound;
+}
+
+BOOL ScDocument::IsPrintEmpty( USHORT nTab, USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow, BOOL bLeftIsEmpty,
+ ScRange* pLastRange, Rectangle* pLastMM ) const
+{
+ if (!IsBlockEmpty( nTab, nStartCol, nStartRow, nEndCol, nEndRow ))
+ return FALSE;
+
+ ScDocument* pThis = (ScDocument*)this; //! GetMMRect / HasAnyDraw etc. const !!!
+
+ Rectangle aMMRect;
+ if ( pLastRange && pLastMM && nTab == pLastRange->aStart.Tab() &&
+ nStartRow == pLastRange->aStart.Row() && nEndRow == pLastRange->aEnd.Row() )
+ {
+ // keep vertical part of aMMRect, only update horizontal position
+ aMMRect = *pLastMM;
+
+ long nLeft = 0;
+ USHORT i;
+ for (i=0; i<nStartCol; i++)
+ nLeft += GetColWidth(i,nTab);
+ long nRight = nLeft;
+ for (i=nStartCol; i<=nEndCol; i++)
+ nRight += GetColWidth(i,nTab);
+
+ aMMRect.Left() = (long)(nLeft * HMM_PER_TWIPS);
+ aMMRect.Right() = (long)(nRight * HMM_PER_TWIPS);
+ }
+ else
+ aMMRect = pThis->GetMMRect( nStartCol, nStartRow, nEndCol, nEndRow, nTab );
+
+ if ( pLastRange && pLastMM )
+ {
+ *pLastRange = ScRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
+ *pLastMM = aMMRect;
+ }
+
+ if ( pThis->HasAnyDraw( nTab, aMMRect ))
+ return FALSE;
+
+ if ( nStartCol > 0 && !bLeftIsEmpty )
+ {
+ // aehnlich wie in ScPrintFunc::AdjustPrintArea
+ //! ExtendPrintArea erst ab Start-Spalte des Druckbereichs
+
+ USHORT nExtendCol = nStartCol - 1;
+ USHORT nTmpRow = nEndRow;
+
+ pThis->ExtendMerge( 0,nStartRow, nExtendCol,nTmpRow, nTab,
+ FALSE, TRUE ); // kein Refresh, incl. Attrs
+
+ OutputDevice* pDev = pThis->GetPrinter();
+ pDev->SetMapMode( MAP_PIXEL ); // wichtig fuer GetNeededSize
+ pThis->ExtendPrintArea( pDev, nTab, 0, nStartRow, nExtendCol, nEndRow );
+ if ( nExtendCol >= nStartCol )
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void ScDocument::Clear()
+{
+ for (USHORT i=0; i<=MAXTAB; i++)
+ if (pTab[i])
+ {
+ delete pTab[i];
+ pTab[i]=NULL;
+ }
+ delete pSelectionAttr;
+ pSelectionAttr = NULL;
+
+ if (pDrawLayer)
+ pDrawLayer->Clear();
+}
+
+BOOL ScDocument::HasControl( USHORT nTab, const Rectangle& rMMRect )
+{
+ BOOL bFound = FALSE;
+
+ if (pDrawLayer)
+ {
+ SdrPage* pPage = pDrawLayer->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+ if (pPage)
+ {
+ SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
+ SdrObject* pObject = aIter.Next();
+ while (pObject && !bFound)
+ {
+ if (pObject->ISA(SdrUnoObj))
+ {
+ Rectangle aObjRect = pObject->GetLogicRect();
+ if ( aObjRect.IsOver( rMMRect ) )
+ bFound = TRUE;
+ }
+
+ pObject = aIter.Next();
+ }
+ }
+ }
+
+ return bFound;
+}
+
+void ScDocument::InvalidateControls( Window* pWin, USHORT nTab, const Rectangle& rMMRect )
+{
+ if (pDrawLayer)
+ {
+ SdrPage* pPage = pDrawLayer->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+ if (pPage)
+ {
+ SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ if (pObject->ISA(SdrUnoObj))
+ {
+ Rectangle aObjRect = pObject->GetLogicRect();
+ if ( aObjRect.IsOver( rMMRect ) )
+ {
+ // Uno-Controls zeichnen sich immer komplett, ohne Ruecksicht
+ // auf ClippingRegions. Darum muss das ganze Objekt neu gepainted
+ // werden, damit die Selektion auf der Tabelle nicht uebermalt wird.
+
+ //pWin->Invalidate( aObjRect.GetIntersection( rMMRect ) );
+ pWin->Invalidate( aObjRect );
+ }
+ }
+
+ pObject = aIter.Next();
+ }
+ }
+ }
+}
+
+void ScDocument::UpdateFontCharSet()
+{
+ // In alten Versionen (bis incl. 4.0 ohne SP) wurden beim Austausch zwischen
+ // Systemen die CharSets in den Font-Attributen nicht angepasst.
+ // Das muss fuer Dokumente bis incl SP2 nun nachgeholt werden:
+ // Alles, was nicht SYMBOL ist, wird auf den System-CharSet umgesetzt.
+ // Bei neuen Dokumenten (Version SC_FONTCHARSET) sollte der CharSet stimmen.
+
+ BOOL bUpdateOld = ( nSrcVer < SC_FONTCHARSET );
+
+ CharSet eSysSet = gsl_getSystemTextEncoding();
+ if ( eSrcSet != eSysSet || bUpdateOld )
+ {
+ USHORT nCount,i;
+ SvxFontItem* pItem;
+
+ nCount = pDocPool->GetItemCount(ATTR_FONT);
+ for (i=0; i<nCount; i++)
+ {
+ pItem = (SvxFontItem*)pDocPool->GetItem(ATTR_FONT, i);
+ if ( pItem && ( pItem->GetCharSet() == eSrcSet ||
+ ( bUpdateOld && pItem->GetCharSet() != RTL_TEXTENCODING_SYMBOL ) ) )
+ pItem->GetCharSet() = eSysSet;
+ }
+
+ if ( pDrawLayer )
+ {
+ SfxItemPool& rDrawPool = pDrawLayer->GetItemPool();
+ nCount = rDrawPool.GetItemCount(EE_CHAR_FONTINFO);
+ for (i=0; i<nCount; i++)
+ {
+ pItem = (SvxFontItem*)rDrawPool.GetItem(EE_CHAR_FONTINFO, i);
+ if ( pItem && ( pItem->GetCharSet() == eSrcSet ||
+ ( bUpdateOld && pItem->GetCharSet() != RTL_TEXTENCODING_SYMBOL ) ) )
+ pItem->GetCharSet() = eSysSet;
+ }
+ }
+ }
+}
+
+
+
+
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
new file mode 100644
index 000000000000..445602dbb513
--- /dev/null
+++ b/sc/source/core/data/document.cxx
@@ -0,0 +1,3900 @@
+/*************************************************************************
+ *
+ * $RCSfile: document.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#define _ZFORLIST_DECLARE_TABLE
+#include "scitems.hxx"
+#include <svx/boxitem.hxx>
+#include <svx/pageitem.hxx>
+#include <svx/editeng.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/saveopt.hxx>
+#include <svtools/poolcach.hxx>
+#include <svtools/zforlist.hxx>
+#include <vcl/system.hxx>
+#include <unotools/charclass.hxx>
+
+#include "document.hxx"
+#include "table.hxx"
+#include "attrib.hxx"
+#include "attarray.hxx"
+#include "markarr.hxx"
+#include "patattr.hxx"
+#include "rangenam.hxx"
+#include "docpool.hxx"
+#include "stlpool.hxx"
+#include "stlsheet.hxx"
+#include "globstr.hrc"
+#include "rechead.hxx"
+#include "dbcolect.hxx"
+#include "pivot.hxx"
+#include "chartlis.hxx"
+#include "rangelst.hxx"
+#include "markdata.hxx"
+#include "conditio.hxx"
+#include "prnsave.hxx"
+#include "chgtrack.hxx"
+#include "sc.hrc"
+#include "scresid.hxx"
+#include "hints.hxx"
+#include "detdata.hxx"
+#include "cell.hxx"
+#include "dpobject.hxx"
+#include "indexmap.hxx"
+
+
+
+void ScDocument::MakeTable( USHORT nTab )
+{
+ if ( nTab<=MAXTAB && !pTab[nTab] )
+ {
+ String aString = ScGlobal::GetRscString(STR_TABLE_DEF); //"Tabelle"
+ aString += String::CreateFromInt32(nTab+1);
+ CreateValidTabName( aString ); // keine doppelten
+
+ pTab[nTab] = new ScTable(this, nTab, aString);
+ ++nMaxTableNumber;
+ }
+}
+
+
+BOOL ScDocument::HasTable( USHORT nTab ) const
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ return TRUE;
+
+ return FALSE;
+}
+
+
+BOOL ScDocument::GetName( USHORT nTab, String& rName ) const
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ {
+ pTab[nTab]->GetName( rName );
+ return TRUE;
+ }
+ rName.Erase();
+ return FALSE;
+}
+
+
+BOOL ScDocument::GetTable( const String& rName, USHORT& rTab ) const
+{
+ String aUpperName = rName;
+ ScGlobal::pCharClass->toUpper(aUpperName);
+ String aCompName;
+
+ for (USHORT i=0; i<=MAXTAB; i++)
+ if (pTab[i])
+ {
+ pTab[i]->GetName( aCompName );
+ ScGlobal::pCharClass->toUpper(aCompName);
+ if (aUpperName == aCompName)
+ {
+ rTab = i;
+ return TRUE;
+ }
+ }
+ rTab = 0;
+ return FALSE;
+}
+
+
+BOOL ScDocument::ValidTabName( const String& rName ) const
+{
+ using namespace ::com::sun::star::lang;
+ sal_Int32 nStartFlags = KParseTokens::ANY_LETTER_OR_NUMBER |
+ KParseTokens::ASC_UNDERSCORE;
+ sal_Int32 nContFlags = nStartFlags;
+ String aContChars( RTL_CONSTASCII_USTRINGPARAM(" ") );
+ ParseResult rRes = ScGlobal::pCharClass->parsePredefinedToken( KParseType::IDENTNAME, rName, 0,
+ nStartFlags, EMPTY_STRING, nContFlags, aContChars );
+ return (rRes.TokenType & KParseType::IDENTNAME) && rRes.EndPos == rName.Len();
+}
+
+
+BOOL ScDocument::ValidNewTabName( const String& rName ) const
+{
+ BOOL bValid = ValidTabName(rName);
+ for (USHORT i=0; (i<=MAXTAB) && bValid; i++)
+ if (pTab[i])
+ {
+ String aOldName;
+ pTab[i]->GetName(aOldName);
+ bValid = !ScGlobal::pScInternational->CompareEqual(
+ rName, aOldName, INTN_COMPARE_IGNORECASE );
+ }
+ return bValid;
+}
+
+
+void ScDocument::CreateValidTabName(String& rName) const
+{
+ if ( !ValidTabName(rName) )
+ {
+ // neu erzeugen
+
+ const String aStrTable( ScResId(SCSTR_TABLE) );
+ BOOL bOk = FALSE;
+
+ // vorneweg testen, ob der Prefix als gueltig erkannt wird
+ // wenn nicht, nur doppelte vermeiden
+ BOOL bPrefix = ValidTabName( aStrTable );
+ DBG_ASSERT(bPrefix, "ungueltiger Tabellenname");
+ USHORT nDummy;
+
+ USHORT nLoops = 0; // "zur Sicherheit"
+ for ( USHORT i = nMaxTableNumber+1; !bOk && nLoops <= MAXTAB; i++ )
+ {
+ rName = aStrTable;
+ rName += String::CreateFromInt32(i);
+ if (bPrefix)
+ bOk = ValidNewTabName( rName );
+ else
+ bOk = !GetTable( rName, nDummy );
+ ++nLoops;
+ }
+
+ DBG_ASSERT(bOk, "kein gueltiger Tabellenname gefunden");
+ if ( !bOk )
+ rName = aStrTable;
+ }
+ else
+ {
+ // uebergebenen Namen ueberpruefen
+
+ if ( !ValidNewTabName(rName) )
+ {
+ USHORT i = 1;
+ String aName;
+ do
+ {
+ i++;
+ aName = rName;
+ aName += '_';
+ aName += String::CreateFromInt32(i);
+ }
+ while (!ValidNewTabName(aName) && (i < MAXTAB+1));
+ rName = aName;
+ }
+ }
+}
+
+
+BOOL ScDocument::InsertTab( USHORT nPos, const String& rName,
+ BOOL bExternalDocument )
+{
+ USHORT nTabCount = GetTableCount();
+ BOOL bValid = (nTabCount <= MAXTAB);
+ if ( !bExternalDocument ) // sonst rName == "'Doc'!Tab", vorher pruefen
+ bValid = (bValid && ValidNewTabName(rName));
+ if (bValid)
+ {
+ if (nPos == SC_TAB_APPEND || nPos == nTabCount)
+ {
+ pTab[nTabCount] = new ScTable(this, nTabCount, rName);
+ ++nMaxTableNumber;
+ if ( bExternalDocument )
+ pTab[nTabCount]->SetVisible( FALSE );
+ }
+ else
+ {
+ if (VALIDTAB(nPos) && (nPos < nTabCount))
+ {
+ ScRange aRange( 0,0,nPos, MAXCOL,MAXROW,MAXTAB );
+ xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,1 );
+ xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,1 );
+ pRangeName->UpdateTabRef( nPos, 1 );
+ pDBCollection->UpdateReference(
+ URM_INSDEL, 0,0,nPos, MAXCOL,MAXROW,MAXTAB, 0,0,1 );
+ if (pPivotCollection)
+ pPivotCollection->UpdateReference(
+ URM_INSDEL, 0,0,nPos, MAXCOL,MAXROW,MAXTAB, 0,0,1 );
+ if (pDPCollection)
+ pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,1 );
+ if (pDetOpList)
+ pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,1 );
+ UpdateChartRef( URM_INSDEL, 0,0,nPos, MAXCOL,MAXROW,MAXTAB, 0,0,1 );
+ if ( pUnoBroadcaster )
+ pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,1 ) );
+
+ USHORT i;
+ for (i = 0; i <= MAXTAB; i++)
+ if (pTab[i])
+ pTab[i]->UpdateInsertTab(nPos);
+ for (i = nTabCount; i > nPos; i--)
+ pTab[i] = pTab[i - 1];
+ pTab[nPos] = new ScTable(this, nPos, rName);
+ ++nMaxTableNumber;
+ for (i = 0; i <= MAXTAB; i++)
+ if (pTab[i])
+ pTab[i]->UpdateCompile();
+ for (i = 0; i <= MAXTAB; i++)
+ if (pTab[i])
+ pTab[i]->StartAllListeners();
+
+ // update conditional formats after table is inserted
+ if ( pCondFormList )
+ pCondFormList->UpdateReference( URM_INSDEL, aRange, 0,0,1 );
+
+ SetDirty();
+ bValid = TRUE;
+ }
+ else
+ bValid = FALSE;
+ }
+ }
+ return bValid;
+}
+
+
+BOOL ScDocument::DeleteTab( USHORT nTab, ScDocument* pRefUndoDoc )
+{
+ BOOL bValid = FALSE;
+ if (VALIDTAB(nTab))
+ {
+ if (pTab[nTab])
+ {
+ USHORT nTabCount = GetTableCount();
+ if (nTabCount > 1)
+ {
+ BOOL bOldAutoCalc = GetAutoCalc();
+ SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ ScRange aRange( 0, 0, nTab, MAXCOL, MAXROW, nTab );
+ DelBroadcastAreasInRange( aRange );
+
+ aRange.aEnd.SetTab( MAXTAB );
+ xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1 );
+ xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1 );
+ pRangeName->UpdateTabRef( nTab, 2 );
+ pDBCollection->UpdateReference(
+ URM_INSDEL, 0,0,nTab, MAXCOL,MAXROW,MAXTAB, 0,0,-1 );
+ if (pPivotCollection)
+ pPivotCollection->UpdateReference(
+ URM_INSDEL, 0,0,nTab, MAXCOL,MAXROW,MAXTAB, 0,0,-1 );
+ if (pDPCollection)
+ pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,-1 );
+ if (pDetOpList)
+ pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,-1 );
+ UpdateChartRef( URM_INSDEL, 0,0,nTab, MAXCOL,MAXROW,MAXTAB, 0,0,-1 );
+ if ( pCondFormList )
+ pCondFormList->UpdateReference( URM_INSDEL, aRange, 0,0,-1 );
+ if ( pUnoBroadcaster )
+ pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,-1 ) );
+
+ USHORT i;
+ for (i=0; i<=MAXTAB; i++)
+ if (pTab[i])
+ pTab[i]->UpdateDeleteTab(nTab,FALSE,
+ pRefUndoDoc ? pRefUndoDoc->pTab[i] : 0);
+ delete pTab[nTab];
+ for (i=nTab + 1; i < nTabCount; i++)
+ pTab[i - 1] = pTab[i];
+ pTab[nTabCount - 1] = NULL;
+ --nMaxTableNumber;
+ for (i = 0; i <= MAXTAB; i++)
+ if (pTab[i])
+ pTab[i]->UpdateCompile();
+ // Excel-Filter loescht einige Tables waehrend des Ladens,
+ // Listener werden erst nach dem Laden aufgesetzt
+ if ( !bInsertingFromOtherDoc )
+ {
+ for (i = 0; i <= MAXTAB; i++)
+ if (pTab[i])
+ pTab[i]->StartAllListeners();
+ SetDirty();
+ }
+ SetAutoCalc( bOldAutoCalc );
+ bValid = TRUE;
+ }
+ }
+ }
+ return bValid;
+}
+
+
+BOOL ScDocument::RenameTab( USHORT nTab, const String& rName, BOOL bUpdateRef,
+ BOOL bExternalDocument )
+{
+ BOOL bValid = FALSE;
+ USHORT i;
+ if VALIDTAB(nTab)
+ if (pTab[nTab])
+ {
+ if ( bExternalDocument )
+ bValid = TRUE; // zusammengesetzter Name
+ else
+ bValid = ValidTabName(rName);
+ for (i=0; (i<=MAXTAB) && bValid; i++)
+ if (pTab[i] && (i != nTab))
+ {
+ String aOldName;
+ pTab[i]->GetName(aOldName);
+ bValid = !ScGlobal::pScInternational->CompareEqual(
+ rName, aOldName, INTN_COMPARE_IGNORECASE );
+ }
+ if (bValid)
+ {
+ pTab[nTab]->SetName(rName);
+/* kann das nicht weg?
+ if (bUpdateRef)
+ {
+ for (i = 0; i <= MAXTAB; i++)
+ if (pTab[i])
+ pTab[i]->UpdateCompile();
+ SetDirty();
+ }
+*/
+ }
+ }
+ return bValid;
+}
+
+
+void ScDocument::SetVisible( USHORT nTab, BOOL bVisible )
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ pTab[nTab]->SetVisible(bVisible);
+}
+
+
+BOOL ScDocument::IsVisible( USHORT nTab ) const
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ return pTab[nTab]->IsVisible();
+
+ return FALSE;
+}
+
+/* ----------------------------------------------------------------------------
+ benutzten Bereich suchen:
+
+ GetCellArea - nur Daten
+ GetTableArea - Daten / Attribute
+ GetPrintArea - beruecksichtigt auch Zeichenobjekte,
+ streicht Attribute bis ganz rechts / unten
+---------------------------------------------------------------------------- */
+
+
+BOOL ScDocument::GetCellArea( USHORT nTab, USHORT& rEndCol, USHORT& rEndRow ) const
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ return pTab[nTab]->GetCellArea( rEndCol, rEndRow );
+
+ rEndCol = 0;
+ rEndRow = 0;
+ return FALSE;
+}
+
+
+BOOL ScDocument::GetTableArea( USHORT nTab, USHORT& rEndCol, USHORT& rEndRow ) const
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ return pTab[nTab]->GetTableArea( rEndCol, rEndRow );
+
+ rEndCol = 0;
+ rEndRow = 0;
+ return FALSE;
+}
+
+
+// zusammenhaengender Bereich
+
+void ScDocument::GetDataArea( USHORT nTab, USHORT& rStartCol, USHORT& rStartRow,
+ USHORT& rEndCol, USHORT& rEndRow, BOOL bIncludeOld )
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ pTab[nTab]->GetDataArea( rStartCol, rStartRow, rEndCol, rEndRow, bIncludeOld );
+}
+
+
+void ScDocument::LimitChartArea( USHORT nTab, USHORT& rStartCol, USHORT& rStartRow,
+ USHORT& rEndCol, USHORT& rEndRow )
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ pTab[nTab]->LimitChartArea( rStartCol, rStartRow, rEndCol, rEndRow );
+}
+
+
+void ScDocument::LimitChartIfAll( ScRangeListRef& rRangeList )
+{
+ ScRangeListRef aNew = new ScRangeList;
+ if (rRangeList.Is())
+ {
+ ULONG nCount = rRangeList->Count();
+ for (ULONG i=0; i<nCount; i++)
+ {
+ ScRange aRange(*rRangeList->GetObject( i ));
+ if ( ( aRange.aStart.Col() == 0 && aRange.aEnd.Col() == MAXCOL ) ||
+ ( aRange.aStart.Row() == 0 && aRange.aEnd.Row() == MAXROW ) )
+ {
+ USHORT nStartCol = aRange.aStart.Col();
+ USHORT nStartRow = aRange.aStart.Row();
+ USHORT nEndCol = aRange.aEnd.Col();
+ USHORT nEndRow = aRange.aEnd.Row();
+ USHORT nTab = aRange.aStart.Tab();
+ if (pTab[nTab])
+ pTab[nTab]->LimitChartArea(nStartCol, nStartRow, nEndCol, nEndRow);
+ aRange.aStart.SetCol( nStartCol );
+ aRange.aStart.SetRow( nStartRow );
+ aRange.aEnd.SetCol( nEndCol );
+ aRange.aEnd.SetRow( nEndRow );
+ }
+ aNew->Append(aRange);
+ }
+ }
+ else
+ DBG_ERROR("LimitChartIfAll: Ref==0");
+ rRangeList = aNew;
+}
+
+
+BOOL ScDocument::CanInsertRow( const ScRange& rRange ) const
+{
+ USHORT nStartCol = rRange.aStart.Col();
+ USHORT nStartRow = rRange.aStart.Row();
+ USHORT nStartTab = rRange.aStart.Tab();
+ USHORT nEndCol = rRange.aEnd.Col();
+ USHORT nEndRow = rRange.aEnd.Row();
+ USHORT nEndTab = rRange.aEnd.Tab();
+ PutInOrder( nStartCol, nEndCol );
+ PutInOrder( nStartRow, nEndRow );
+ PutInOrder( nStartTab, nEndTab );
+ USHORT nSize = nEndRow - nStartRow + 1;
+
+ BOOL bTest = TRUE;
+ for (USHORT i=nStartTab; i<=nEndTab && bTest; i++)
+ if (pTab[i])
+ bTest &= pTab[i]->TestInsertRow( nStartCol, nEndCol, nSize );
+
+ return bTest;
+}
+
+
+BOOL ScDocument::InsertRow( USHORT nStartCol, USHORT nStartTab,
+ USHORT nEndCol, USHORT nEndTab,
+ USHORT nStartRow, USHORT nSize )
+{
+ PutInOrder( nStartCol, nEndCol );
+ PutInOrder( nStartTab, nEndTab );
+
+ BOOL bTest = TRUE;
+ BOOL bRet = FALSE;
+ BOOL bOldAutoCalc = GetAutoCalc();
+ SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ for (USHORT i=nStartTab; i<=nEndTab && bTest; i++)
+ if (pTab[i])
+ bTest &= pTab[i]->TestInsertRow( nStartCol, nEndCol, nSize );
+ if (bTest)
+ {
+ // UpdateBroadcastAreas muss vor UpdateReference gerufen werden, damit nicht
+ // Eintraege verschoben werden, die erst bei UpdateReference neu erzeugt werden
+
+ UpdateBroadcastAreas( URM_INSDEL, ScRange(
+ ScAddress( nStartCol, nStartRow, nStartTab ),
+ ScAddress( nEndCol, MAXROW, nEndTab )), 0, nSize, 0 );
+ UpdateReference( URM_INSDEL, nStartCol, nStartRow, nStartTab,
+ nEndCol, MAXROW, nEndTab,
+ 0, nSize, 0 );
+ for (i=nStartTab; i<=nEndTab; i++)
+ if (pTab[i])
+ pTab[i]->InsertRow( nStartCol, nEndCol, nStartRow, nSize );
+
+ if ( pChangeTrack && pChangeTrack->IsInDeleteUndo() )
+ { // durch Restaurierung von Referenzen auf geloeschte Bereiche ist
+ // ein neues Listening faellig, bisherige Listener wurden in
+ // FormulaCell UpdateReference abgehaengt
+ StartAllListeners();
+ }
+ else
+ { // RelNames wurden in UpdateReference abgehaengt
+ for (i=nStartTab; i<=nEndTab; i++)
+ if (pTab[i])
+ pTab[i]->StartRelNameListeners();
+ // #69592# at least all cells using range names pointing relative to the moved range must recalculate
+ for (i=0; i<=MAXTAB; i++)
+ if (pTab[i])
+ pTab[i]->SetRelNameDirty();
+ }
+ bRet = TRUE;
+ }
+ SetAutoCalc( bOldAutoCalc );
+ if ( bRet )
+ pChartListenerCollection->UpdateDirtyCharts();
+ return bRet;
+}
+
+
+BOOL ScDocument::InsertRow( const ScRange& rRange )
+{
+ return InsertRow( rRange.aStart.Col(), rRange.aStart.Tab(),
+ rRange.aEnd.Col(), rRange.aEnd.Tab(),
+ rRange.aStart.Row(), rRange.aEnd.Row()-rRange.aStart.Row()+1 );
+}
+
+
+void ScDocument::DeleteRow( USHORT nStartCol, USHORT nStartTab,
+ USHORT nEndCol, USHORT nEndTab,
+ USHORT nStartRow, USHORT nSize,
+ ScDocument* pRefUndoDoc, BOOL* pUndoOutline )
+{
+ PutInOrder( nStartCol, nEndCol );
+ PutInOrder( nStartTab, nEndTab );
+
+ BOOL bOldAutoCalc = GetAutoCalc();
+ SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+
+ if ( nStartRow+nSize <= MAXROW )
+ {
+ DelBroadcastAreasInRange( ScRange(
+ ScAddress( nStartCol, nStartRow, nStartTab ),
+ ScAddress( nEndCol, nStartRow+nSize-1, nEndTab ) ) );
+ UpdateBroadcastAreas( URM_INSDEL, ScRange(
+ ScAddress( nStartCol, nStartRow+nSize, nStartTab ),
+ ScAddress( nEndCol, MAXROW, nEndTab )), 0, -(short) nSize, 0 );
+ }
+ else
+ DelBroadcastAreasInRange( ScRange(
+ ScAddress( nStartCol, nStartRow, nStartTab ),
+ ScAddress( nEndCol, MAXROW, nEndTab ) ) );
+
+ if ( nStartRow+nSize <= MAXROW )
+ {
+ UpdateReference( URM_INSDEL, nStartCol, nStartRow+nSize, nStartTab,
+ nEndCol, MAXROW, nEndTab,
+ 0, -(short) nSize, 0, pRefUndoDoc );
+ }
+
+ if (pUndoOutline)
+ *pUndoOutline = FALSE;
+
+ for (USHORT i=nStartTab; i<=nEndTab; i++)
+ if (pTab[i])
+ pTab[i]->DeleteRow( nStartCol, nEndCol, nStartRow, nSize, pUndoOutline );
+
+ if ( nStartRow+nSize <= MAXROW )
+ { // RelNames wurden in UpdateReference abgehaengt
+ for (i=nStartTab; i<=nEndTab; i++)
+ if (pTab[i])
+ pTab[i]->StartRelNameListeners();
+ // #69592# at least all cells using range names pointing relative to the moved range must recalculate
+ for (i=0; i<=MAXTAB; i++)
+ if (pTab[i])
+ pTab[i]->SetRelNameDirty();
+ }
+
+ SetAutoCalc( bOldAutoCalc );
+ pChartListenerCollection->UpdateDirtyCharts();
+}
+
+
+void ScDocument::DeleteRow( const ScRange& rRange, ScDocument* pRefUndoDoc, BOOL* pUndoOutline )
+{
+ DeleteRow( rRange.aStart.Col(), rRange.aStart.Tab(),
+ rRange.aEnd.Col(), rRange.aEnd.Tab(),
+ rRange.aStart.Row(), rRange.aEnd.Row()-rRange.aStart.Row()+1,
+ pRefUndoDoc, pUndoOutline );
+}
+
+
+BOOL ScDocument::CanInsertCol( const ScRange& rRange ) const
+{
+ USHORT nStartCol = rRange.aStart.Col();
+ USHORT nStartRow = rRange.aStart.Row();
+ USHORT nStartTab = rRange.aStart.Tab();
+ USHORT nEndCol = rRange.aEnd.Col();
+ USHORT nEndRow = rRange.aEnd.Row();
+ USHORT nEndTab = rRange.aEnd.Tab();
+ PutInOrder( nStartCol, nEndCol );
+ PutInOrder( nStartRow, nEndRow );
+ PutInOrder( nStartTab, nEndTab );
+ USHORT nSize = nEndCol - nStartCol + 1;
+
+ BOOL bTest = TRUE;
+ for (USHORT i=nStartTab; i<=nEndTab && bTest; i++)
+ if (pTab[i])
+ bTest &= pTab[i]->TestInsertCol( nStartRow, nEndRow, nSize );
+
+ return bTest;
+}
+
+
+BOOL ScDocument::InsertCol( USHORT nStartRow, USHORT nStartTab,
+ USHORT nEndRow, USHORT nEndTab,
+ USHORT nStartCol, USHORT nSize )
+{
+ PutInOrder( nStartRow, nEndRow );
+ PutInOrder( nStartTab, nEndTab );
+
+ BOOL bTest = TRUE;
+ BOOL bRet = FALSE;
+ BOOL bOldAutoCalc = GetAutoCalc();
+ SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ for (USHORT i=nStartTab; i<=nEndTab && bTest; i++)
+ if (pTab[i])
+ bTest &= pTab[i]->TestInsertCol( nStartRow, nEndRow, nSize );
+ if (bTest)
+ {
+ UpdateBroadcastAreas( URM_INSDEL, ScRange(
+ ScAddress( nStartCol, nStartRow, nStartTab ),
+ ScAddress( MAXCOL, nEndRow, nEndTab )), nSize, 0, 0 );
+ UpdateReference( URM_INSDEL, nStartCol, nStartRow, nStartTab,
+ MAXCOL, nEndRow, nEndTab,
+ nSize, 0, 0 );
+ for (i=nStartTab; i<=nEndTab; i++)
+ if (pTab[i])
+ pTab[i]->InsertCol( nStartCol, nStartRow, nEndRow, nSize );
+
+ if ( pChangeTrack && pChangeTrack->IsInDeleteUndo() )
+ { // durch Restaurierung von Referenzen auf geloeschte Bereiche ist
+ // ein neues Listening faellig, bisherige Listener wurden in
+ // FormulaCell UpdateReference abgehaengt
+ StartAllListeners();
+ }
+ else
+ { // RelNames wurden in UpdateReference abgehaengt
+ for (i=nStartTab; i<=nEndTab; i++)
+ if (pTab[i])
+ pTab[i]->StartRelNameListeners();
+ // #69592# at least all cells using range names pointing relative to the moved range must recalculate
+ for (i=0; i<=MAXTAB; i++)
+ if (pTab[i])
+ pTab[i]->SetRelNameDirty();
+ }
+ bRet = TRUE;
+ }
+ SetAutoCalc( bOldAutoCalc );
+ if ( bRet )
+ pChartListenerCollection->UpdateDirtyCharts();
+ return bRet;
+}
+
+
+BOOL ScDocument::InsertCol( const ScRange& rRange )
+{
+ return InsertCol( rRange.aStart.Row(), rRange.aStart.Tab(),
+ rRange.aEnd.Row(), rRange.aEnd.Tab(),
+ rRange.aStart.Col(), rRange.aEnd.Col()-rRange.aStart.Col()+1 );
+}
+
+
+void ScDocument::DeleteCol(USHORT nStartRow, USHORT nStartTab, USHORT nEndRow, USHORT nEndTab,
+ USHORT nStartCol, USHORT nSize, ScDocument* pRefUndoDoc,
+ BOOL* pUndoOutline )
+{
+ PutInOrder( nStartRow, nEndRow );
+ PutInOrder( nStartTab, nEndTab );
+
+ BOOL bOldAutoCalc = GetAutoCalc();
+ SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+
+ if ( nStartCol+nSize <= MAXCOL )
+ {
+ DelBroadcastAreasInRange( ScRange(
+ ScAddress( nStartCol, nStartRow, nStartTab ),
+ ScAddress( nStartCol+nSize-1, nEndRow, nEndTab ) ) );
+ UpdateBroadcastAreas( URM_INSDEL, ScRange(
+ ScAddress( nStartCol+nSize, nStartRow, nStartTab ),
+ ScAddress( MAXCOL, nEndRow, nEndTab )), -(short) nSize, 0, 0 );
+ }
+ else
+ DelBroadcastAreasInRange( ScRange(
+ ScAddress( nStartCol, nStartRow, nStartTab ),
+ ScAddress( MAXCOL, nEndRow, nEndTab ) ) );
+
+ if ( nStartCol+nSize <= MAXCOL )
+ {
+ UpdateReference( URM_INSDEL, nStartCol+nSize, nStartRow, nStartTab,
+ MAXCOL, nEndRow, nEndTab,
+ -(short) nSize, 0, 0, pRefUndoDoc );
+ }
+
+ if (pUndoOutline)
+ *pUndoOutline = FALSE;
+
+ for (USHORT i=nStartTab; i<=nEndTab; i++)
+ if (pTab[i])
+ pTab[i]->DeleteCol( nStartCol, nStartRow, nEndRow, nSize, pUndoOutline );
+
+ if ( nStartCol+nSize <= MAXCOL )
+ { // RelNames wurden in UpdateReference abgehaengt
+ for (i=nStartTab; i<=nEndTab; i++)
+ if (pTab[i])
+ pTab[i]->StartRelNameListeners();
+ // #69592# at least all cells using range names pointing relative to the moved range must recalculate
+ for (i=0; i<=MAXTAB; i++)
+ if (pTab[i])
+ pTab[i]->SetRelNameDirty();
+ }
+
+ SetAutoCalc( bOldAutoCalc );
+ pChartListenerCollection->UpdateDirtyCharts();
+}
+
+
+void ScDocument::DeleteCol( const ScRange& rRange, ScDocument* pRefUndoDoc, BOOL* pUndoOutline )
+{
+ DeleteCol( rRange.aStart.Row(), rRange.aStart.Tab(),
+ rRange.aEnd.Row(), rRange.aEnd.Tab(),
+ rRange.aStart.Col(), rRange.aEnd.Col()-rRange.aStart.Col()+1,
+ pRefUndoDoc, pUndoOutline );
+}
+
+
+// fuer Area-Links: Zellen einuegen/loeschen, wenn sich der Bereich veraendert
+// (ohne Paint)
+
+
+void lcl_GetInsDelRanges( const ScRange& rOld, const ScRange& rNew,
+ ScRange& rColRange, BOOL& rInsCol, BOOL& rDelCol,
+ ScRange& rRowRange, BOOL& rInsRow, BOOL& rDelRow )
+{
+ DBG_ASSERT( rOld.aStart == rNew.aStart, "FitBlock: Anfang unterschiedlich" );
+
+ rInsCol = rDelCol = rInsRow = rDelRow = FALSE;
+
+ USHORT nStartX = rOld.aStart.Col();
+ USHORT nStartY = rOld.aStart.Row();
+ USHORT nOldEndX = rOld.aEnd.Col();
+ USHORT nOldEndY = rOld.aEnd.Row();
+ USHORT nNewEndX = rNew.aEnd.Col();
+ USHORT nNewEndY = rNew.aEnd.Row();
+ USHORT nTab = rOld.aStart.Tab();
+
+ // wenn es mehr Zeilen werden, werden Spalten auf der alten Hoehe eingefuegt/geloescht
+ BOOL bGrowY = ( nNewEndY > nOldEndY );
+ USHORT nColEndY = bGrowY ? nOldEndY : nNewEndY;
+ USHORT nRowEndX = bGrowY ? nNewEndX : nOldEndX;
+
+ // Spalten
+
+ if ( nNewEndX > nOldEndX ) // Spalten einfuegen
+ {
+ rColRange = ScRange( nOldEndX+1, nStartY, nTab, nNewEndX, nColEndY, nTab );
+ rInsCol = TRUE;
+ }
+ else if ( nNewEndX < nOldEndX ) // Spalten loeschen
+ {
+ rColRange = ScRange( nNewEndX+1, nStartY, nTab, nOldEndX, nColEndY, nTab );
+ rDelCol = TRUE;
+ }
+
+ // Zeilen
+
+ if ( nNewEndY > nOldEndY ) // Zeilen einfuegen
+ {
+ rRowRange = ScRange( nStartX, nOldEndY+1, nTab, nRowEndX, nNewEndY, nTab );
+ rInsRow = TRUE;
+ }
+ else if ( nNewEndY < nOldEndY ) // Zeilen loeschen
+ {
+ rRowRange = ScRange( nStartX, nNewEndY+1, nTab, nRowEndX, nOldEndY, nTab );
+ rDelRow = TRUE;
+ }
+}
+
+
+BOOL ScDocument::HasPartOfMerged( const ScRange& rRange )
+{
+ BOOL bPart = FALSE;
+ USHORT nTab = rRange.aStart.Tab();
+
+ USHORT nStartX = rRange.aStart.Col();
+ USHORT nStartY = rRange.aStart.Row();
+ USHORT nEndX = rRange.aEnd.Col();
+ USHORT nEndY = rRange.aEnd.Row();
+
+ if (HasAttrib( nStartX, nStartY, nTab, nEndX, nEndY, nTab,
+ HASATTR_MERGED | HASATTR_OVERLAPPED ))
+ {
+ ExtendMerge( nStartX, nStartY, nEndX, nEndY, nTab );
+ ExtendOverlapped( nStartX, nStartY, nEndX, nEndY, nTab );
+
+ bPart = ( nStartX != rRange.aStart.Col() || nEndX != rRange.aEnd.Col() ||
+ nStartY != rRange.aStart.Row() || nEndY != rRange.aEnd.Row() );
+ }
+ return bPart;
+}
+
+
+BOOL ScDocument::CanFitBlock( const ScRange& rOld, const ScRange& rNew )
+{
+ if ( rOld == rNew )
+ return TRUE;
+
+ USHORT nTab = rOld.aStart.Tab();
+ BOOL bOk = TRUE;
+ BOOL bInsCol,bDelCol,bInsRow,bDelRow;
+ ScRange aColRange,aRowRange;
+ lcl_GetInsDelRanges( rOld, rNew, aColRange,bInsCol,bDelCol, aRowRange,bInsRow,bDelRow );
+
+ if ( bInsCol && !CanInsertCol( aColRange ) ) // Zellen am Rand ?
+ bOk = FALSE;
+ if ( bInsRow && !CanInsertRow( aRowRange ) ) // Zellen am Rand ?
+ bOk = FALSE;
+
+ if ( bInsCol || bDelCol )
+ {
+ aColRange.aEnd.SetCol(MAXCOL);
+ if ( HasPartOfMerged(aColRange) )
+ bOk = FALSE;
+ }
+ if ( bInsRow || bDelRow )
+ {
+ aRowRange.aEnd.SetRow(MAXROW);
+ if ( HasPartOfMerged(aRowRange) )
+ bOk = FALSE;
+ }
+
+ return bOk;
+}
+
+
+void ScDocument::FitBlock( const ScRange& rOld, const ScRange& rNew, BOOL bClear )
+{
+ if (bClear)
+ DeleteAreaTab( rOld, IDF_ALL );
+
+ BOOL bInsCol,bDelCol,bInsRow,bDelRow;
+ ScRange aColRange,aRowRange;
+ lcl_GetInsDelRanges( rOld, rNew, aColRange,bInsCol,bDelCol, aRowRange,bInsRow,bDelRow );
+
+ if ( bInsCol )
+ InsertCol( aColRange ); // Spalten zuerst einfuegen
+ if ( bInsRow )
+ InsertRow( aRowRange );
+
+ if ( bDelRow )
+ DeleteRow( aRowRange ); // Zeilen zuerst loeschen
+ if ( bDelCol )
+ DeleteCol( aColRange );
+
+ // Referenzen um eingefuegte Zeilen erweitern
+
+ if ( bInsCol || bInsRow )
+ {
+ ScRange aGrowSource = rOld;
+ aGrowSource.aEnd.SetCol(Min( rOld.aEnd.Col(), rNew.aEnd.Col() ));
+ aGrowSource.aEnd.SetRow(Min( rOld.aEnd.Row(), rNew.aEnd.Row() ));
+ USHORT nGrowX = bInsCol ? ( rNew.aEnd.Col() - rOld.aEnd.Col() ) : 0;
+ USHORT nGrowY = bInsRow ? ( rNew.aEnd.Row() - rOld.aEnd.Row() ) : 0;
+ UpdateGrow( aGrowSource, nGrowX, nGrowY );
+ }
+}
+
+
+void ScDocument::DeleteArea(USHORT nCol1, USHORT nRow1,
+ USHORT nCol2, USHORT nRow2,
+ const ScMarkData& rMark, USHORT nDelFlag)
+{
+ PutInOrder( nCol1, nCol2 );
+ PutInOrder( nRow1, nRow2 );
+ BOOL bOldAutoCalc = GetAutoCalc();
+ SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ for (USHORT i = 0; i <= MAXTAB; i++)
+ if (pTab[i])
+ if ( rMark.GetTableSelect(i) || bIsUndo )
+ pTab[i]->DeleteArea(nCol1, nRow1, nCol2, nRow2, nDelFlag);
+ SetAutoCalc( bOldAutoCalc );
+}
+
+
+void ScDocument::DeleteAreaTab(USHORT nCol1, USHORT nRow1,
+ USHORT nCol2, USHORT nRow2,
+ USHORT nTab, USHORT nDelFlag)
+{
+ PutInOrder( nCol1, nCol2 );
+ PutInOrder( nRow1, nRow2 );
+ if ( VALIDTAB(nTab) && pTab[nTab] )
+ {
+ BOOL bOldAutoCalc = GetAutoCalc();
+ SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ pTab[nTab]->DeleteArea(nCol1, nRow1, nCol2, nRow2, nDelFlag);
+ SetAutoCalc( bOldAutoCalc );
+ }
+}
+
+
+void ScDocument::DeleteAreaTab( const ScRange& rRange, USHORT nDelFlag )
+{
+ for ( USHORT nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); nTab++ )
+ DeleteAreaTab( rRange.aStart.Col(), rRange.aStart.Row(),
+ rRange.aEnd.Col(), rRange.aEnd.Row(),
+ nTab, nDelFlag );
+}
+
+
+void ScDocument::InitUndo( ScDocument* pSrcDoc, USHORT nTab1, USHORT nTab2,
+ BOOL bColInfo, BOOL bRowInfo )
+{
+ if (bIsUndo)
+ {
+ Clear();
+ DBG_ASSERT( !bOwner, "Pool gehoert Undo-Doc" );
+ bOwner = FALSE;
+ pDocPool = pSrcDoc->pDocPool;
+ pStylePool = pSrcDoc->pStylePool;
+ pFormTable = pSrcDoc->pFormTable;
+ pEditPool = pSrcDoc->pEditPool;
+ pEnginePool = pSrcDoc->pEnginePool;
+
+ String aString;
+ for (USHORT nTab = nTab1; nTab <= nTab2; nTab++)
+ pTab[nTab] = new ScTable(this, nTab, aString, bColInfo, bRowInfo);
+
+ nMaxTableNumber = nTab2 + 1;
+ }
+ else
+ DBG_ERROR("InitUndo");
+}
+
+
+void ScDocument::AddUndoTab( USHORT nTab1, USHORT nTab2, BOOL bColInfo, BOOL bRowInfo )
+{
+ if (bIsUndo)
+ {
+ String aString;
+ for (USHORT nTab = nTab1; nTab <= nTab2; nTab++)
+ if (!pTab[nTab])
+ pTab[nTab] = new ScTable(this, nTab, aString, bColInfo, bRowInfo);
+
+ if ( nMaxTableNumber <= nTab2 )
+ nMaxTableNumber = nTab2 + 1;
+ }
+ else
+ DBG_ERROR("InitUndo");
+}
+
+
+void ScDocument::SetCutMode( BOOL bVal )
+{
+ if (bIsClip)
+ bCutMode = bVal;
+ else
+ {
+ DBG_ERROR("SetCutMode without bIsClip");
+ }
+}
+
+
+BOOL ScDocument::IsCutMode()
+{
+ if (bIsClip)
+ return bCutMode;
+ else
+ {
+ DBG_ERROR("IsCutMode ohne bIsClip");
+ return FALSE;
+ }
+}
+
+
+void ScDocument::CopyToDocument(USHORT nCol1, USHORT nRow1, USHORT nTab1,
+ USHORT nCol2, USHORT nRow2, USHORT nTab2,
+ USHORT nFlags, BOOL bOnlyMarked, ScDocument* pDestDoc,
+ const ScMarkData* pMarks, BOOL bColRowFlags )
+{
+ PutInOrder( nCol1, nCol2 );
+ PutInOrder( nRow1, nRow2 );
+ PutInOrder( nTab1, nTab2 );
+ if( !pDestDoc->aDocName.Len() )
+ pDestDoc->aDocName = aDocName;
+ if (VALIDTAB(nTab1) && VALIDTAB(nTab2))
+ {
+ BOOL bOldAutoCalc = pDestDoc->GetAutoCalc();
+ pDestDoc->SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ for (USHORT i = nTab1; i <= nTab2; i++)
+ {
+ if (pTab[i] && pDestDoc->pTab[i])
+ pTab[i]->CopyToTable( nCol1, nRow1, nCol2, nRow2, nFlags,
+ bOnlyMarked, pDestDoc->pTab[i], pMarks,
+ FALSE, bColRowFlags );
+ }
+ pDestDoc->SetAutoCalc( bOldAutoCalc );
+ }
+}
+
+
+void ScDocument::UndoToDocument(USHORT nCol1, USHORT nRow1, USHORT nTab1,
+ USHORT nCol2, USHORT nRow2, USHORT nTab2,
+ USHORT nFlags, BOOL bOnlyMarked, ScDocument* pDestDoc,
+ const ScMarkData* pMarks)
+{
+ PutInOrder( nCol1, nCol2 );
+ PutInOrder( nRow1, nRow2 );
+ PutInOrder( nTab1, nTab2 );
+ if (VALIDTAB(nTab1) && VALIDTAB(nTab2))
+ {
+ BOOL bOldAutoCalc = pDestDoc->GetAutoCalc();
+ pDestDoc->SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ if (nTab1 > 0)
+ CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTab1-1, IDF_FORMULA, FALSE, pDestDoc, pMarks );
+
+ for (USHORT i = nTab1; i <= nTab2; i++)
+ {
+ if (pTab[i] && pDestDoc->pTab[i])
+ pTab[i]->UndoToTable(nCol1, nRow1, nCol2, nRow2, nFlags,
+ bOnlyMarked, pDestDoc->pTab[i], pMarks);
+ }
+
+ if (nTab2 < MAXTAB)
+ CopyToDocument( 0,0,nTab2+1, MAXCOL,MAXROW,MAXTAB, IDF_FORMULA, FALSE, pDestDoc, pMarks );
+ pDestDoc->SetAutoCalc( bOldAutoCalc );
+ }
+}
+
+
+void ScDocument::CopyToDocument(const ScRange& rRange,
+ USHORT nFlags, BOOL bOnlyMarked, ScDocument* pDestDoc,
+ const ScMarkData* pMarks, BOOL bColRowFlags)
+{
+ ScRange aNewRange = rRange;
+ aNewRange.Justify();
+
+ if( !pDestDoc->aDocName.Len() )
+ pDestDoc->aDocName = aDocName;
+ BOOL bOldAutoCalc = pDestDoc->GetAutoCalc();
+ pDestDoc->SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ for (USHORT i = aNewRange.aStart.Tab(); i <= aNewRange.aEnd.Tab(); i++)
+ if (pTab[i] && pDestDoc->pTab[i])
+ pTab[i]->CopyToTable(aNewRange.aStart.Col(), aNewRange.aStart.Row(),
+ aNewRange.aEnd.Col(), aNewRange.aEnd.Row(),
+ nFlags, bOnlyMarked, pDestDoc->pTab[i],
+ pMarks, FALSE, bColRowFlags);
+ pDestDoc->SetAutoCalc( bOldAutoCalc );
+}
+
+
+void ScDocument::UndoToDocument(const ScRange& rRange,
+ USHORT nFlags, BOOL bOnlyMarked, ScDocument* pDestDoc,
+ const ScMarkData* pMarks)
+{
+ ScRange aNewRange = rRange;
+ aNewRange.Justify();
+ USHORT nTab1 = aNewRange.aStart.Tab();
+ USHORT nTab2 = aNewRange.aEnd.Tab();
+
+ BOOL bOldAutoCalc = pDestDoc->GetAutoCalc();
+ pDestDoc->SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ if (nTab1 > 0)
+ CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTab1-1, IDF_FORMULA, FALSE, pDestDoc, pMarks );
+
+ for (USHORT i = nTab1; i <= nTab2; i++)
+ {
+ if (pTab[i] && pDestDoc->pTab[i])
+ pTab[i]->UndoToTable(aNewRange.aStart.Col(), aNewRange.aStart.Row(),
+ aNewRange.aEnd.Col(), aNewRange.aEnd.Row(),
+ nFlags, bOnlyMarked, pDestDoc->pTab[i], pMarks);
+ }
+
+ if (nTab2 < MAXTAB)
+ CopyToDocument( 0,0,nTab2+1, MAXCOL,MAXROW,MAXTAB, IDF_FORMULA, FALSE, pDestDoc, pMarks );
+ pDestDoc->SetAutoCalc( bOldAutoCalc );
+}
+
+
+void ScDocument::CopyToClip(USHORT nCol1, USHORT nRow1,
+ USHORT nCol2, USHORT nRow2,
+ BOOL bCut, ScDocument* pClipDoc,
+ BOOL bAllTabs, const ScMarkData* pMarks, BOOL bKeepScenarioFlags)
+{
+ DBG_ASSERT( bAllTabs || pMarks, "CopyToClip: ScMarkData fehlt" );
+
+ if (!bIsClip)
+ {
+ PutInOrder( nCol1, nCol2 );
+ PutInOrder( nRow1, nRow2 );
+ if (!pClipDoc)
+ pClipDoc = ScGlobal::GetClipDoc();
+
+ pClipDoc->aDocName = aDocName;
+ pClipDoc->aClipRange = ScRange( nCol1,nRow1,0, nCol2,nRow2,0 );
+ pClipDoc->ResetClip( this, pMarks );
+ USHORT i, j;
+ pClipDoc->pRangeName->FreeAll();
+ for (i = 0; i < pRangeName->GetCount(); i++) //! DB-Bereiche Pivot-Bereiche auch !!!
+ {
+ USHORT nIndex = ((ScRangeData*)((*pRangeName)[i]))->GetIndex();
+ BOOL bInUse = FALSE;
+ for (j = 0; !bInUse && (j <= MAXTAB); j++)
+ {
+ if (pTab[j])
+ bInUse = pTab[j]->IsRangeNameInUse(nCol1, nRow1, nCol2, nRow2,
+ nIndex);
+ }
+ if (bInUse)
+ {
+ ScRangeData* pData = new ScRangeData(*((*pRangeName)[i]));
+ if (!pClipDoc->pRangeName->Insert(pData))
+ delete pData;
+ else
+ pData->SetIndex(nIndex);
+ }
+ }
+ for (i = 0; i <= MAXTAB; i++)
+ if (pTab[i] && pClipDoc->pTab[i])
+ if ( bAllTabs || !pMarks || pMarks->GetTableSelect(i) )
+ pTab[i]->CopyToClip(nCol1, nRow1, nCol2, nRow2, pClipDoc->pTab[i], bKeepScenarioFlags);
+
+ pClipDoc->bCutMode = bCut;
+ }
+}
+
+
+void ScDocument::CopyTabToClip(USHORT nCol1, USHORT nRow1,
+ USHORT nCol2, USHORT nRow2,
+ USHORT nTab, ScDocument* pClipDoc)
+{
+ if (!bIsClip)
+ {
+ PutInOrder( nCol1, nCol2 );
+ PutInOrder( nRow1, nRow2 );
+ if (!pClipDoc)
+ pClipDoc = ScGlobal::GetClipDoc();
+
+ pClipDoc->aDocName = aDocName;
+ pClipDoc->aClipRange = ScRange( nCol1,nRow1,0, nCol2,nRow2,0 );
+ pClipDoc->ResetClip( this, nTab );
+
+ if (pTab[nTab] && pClipDoc->pTab[nTab])
+ pTab[nTab]->CopyToClip(nCol1, nRow1, nCol2, nRow2, pClipDoc->pTab[nTab], FALSE);
+
+ pClipDoc->bCutMode = FALSE;
+ }
+}
+
+
+void ScDocument::TransposeClip( ScDocument* pTransClip, USHORT nFlags, BOOL bAsLink )
+{
+ USHORT i;
+ DBG_ASSERT( bIsClip && pTransClip && pTransClip->bIsClip,
+ "TransposeClip mit falschem Dokument" );
+
+ // initialisieren
+ // -> pTransClip muss vor dem Original-Dokument geloescht werden!
+
+ pTransClip->ResetClip(this, (ScMarkData*)NULL); // alle
+
+ // Bereiche uebernehmen
+
+ pTransClip->pRangeName->FreeAll();
+ for (i = 0; i < pRangeName->GetCount(); i++) //! DB-Bereiche Pivot-Bereiche auch !!!
+ {
+ USHORT nIndex = ((ScRangeData*)((*pRangeName)[i]))->GetIndex();
+ ScRangeData* pData = new ScRangeData(*((*pRangeName)[i]));
+ if (!pTransClip->pRangeName->Insert(pData))
+ delete pData;
+ else
+ pData->SetIndex(nIndex);
+ }
+
+ // Daten
+
+ if ( aClipRange.aEnd.Row()-aClipRange.aStart.Row() <= MAXCOL )
+ {
+ for (i=0; i<=MAXTAB; i++)
+ if (pTab[i])
+ {
+ DBG_ASSERT( pTransClip->pTab[i], "TransposeClip: Tabelle nicht da" );
+ pTab[i]->TransposeClip( aClipRange.aStart.Col(), aClipRange.aStart.Row(),
+ aClipRange.aEnd.Col(), aClipRange.aEnd.Row(),
+ pTransClip->pTab[i], nFlags, bAsLink );
+ }
+
+ pTransClip->aClipRange = ScRange( 0, 0, aClipRange.aStart.Tab(),
+ aClipRange.aEnd.Row() - aClipRange.aStart.Row(),
+ aClipRange.aEnd.Col() - aClipRange.aStart.Col(),
+ aClipRange.aEnd.Tab() );
+ }
+ else
+ DBG_ERROR("TransposeClip: zu gross");
+
+ // Dies passiert erst beim Einfuegen...
+
+ bCutMode = FALSE;
+}
+
+
+BOOL ScDocument::IsClipboardSource() const
+{
+ ScDocument* pClipDoc = ScGlobal::GetClipDoc();
+ return pDocPool == pClipDoc->pDocPool;
+}
+
+
+void ScDocument::StartListeningFromClip( USHORT nCol1, USHORT nRow1,
+ USHORT nCol2, USHORT nRow2,
+ const ScMarkData& rMark, USHORT nInsFlag )
+{
+ if (nInsFlag & IDF_CONTENTS)
+ {
+ for (USHORT i = 0; i <= MAXTAB; i++)
+ if (pTab[i])
+ if (rMark.GetTableSelect(i))
+ pTab[i]->StartListeningInArea( nCol1, nRow1, nCol2, nRow2 );
+ }
+}
+
+
+void ScDocument::BroadcastFromClip( USHORT nCol1, USHORT nRow1,
+ USHORT nCol2, USHORT nRow2,
+ const ScMarkData& rMark, USHORT nInsFlag )
+{
+ if (nInsFlag & IDF_CONTENTS)
+ {
+ USHORT nClipTab = 0;
+ for (USHORT i = 0; i <= MAXTAB; i++)
+ if (pTab[i])
+ if (rMark.GetTableSelect(i))
+ pTab[i]->BroadcastInArea( nCol1, nRow1, nCol2, nRow2 );
+ }
+}
+
+
+void ScDocument::CopyBlockFromClip( USHORT nCol1, USHORT nRow1,
+ USHORT nCol2, USHORT nRow2,
+ const ScMarkData& rMark,
+ short nDx, short nDy,
+ const ScCopyBlockFromClipParams* pCBFCP )
+{
+ ScTable** ppClipTab = pCBFCP->pClipDoc->pTab;
+ USHORT nTabEnd = pCBFCP->nTabEnd;
+ USHORT i;
+ USHORT nClipTab = 0;
+ for (i = pCBFCP->nTabStart; i <= nTabEnd; i++)
+ if (pTab[i])
+ if (rMark.GetTableSelect(i))
+ {
+ while (!ppClipTab[nClipTab]) nClipTab = (nClipTab+1) % (MAXTAB+1);
+ pTab[i]->CopyFromClip(nCol1, nRow1, nCol2, nRow2, nDx, nDy,
+ pCBFCP->nInsFlag, pCBFCP->bAsLink, ppClipTab[nClipTab]);
+ nClipTab = (nClipTab+1) % (MAXTAB+1);
+ }
+ if ( pCBFCP->pClipDoc->bCutMode && (pCBFCP->nInsFlag & IDF_CONTENTS) )
+ {
+ nClipTab = 0;
+ for (i = pCBFCP->nTabStart; i <= nTabEnd; i++)
+ if (pTab[i])
+ if (rMark.GetTableSelect(i))
+ {
+ while (!ppClipTab[nClipTab]) nClipTab = (nClipTab+1) % (MAXTAB+1);
+ short nDz = ((short)i) - nClipTab;
+ UpdateReference(URM_MOVE, nCol1, nRow1, i, nCol2, nRow2, i, nDx, nDy, nDz, pCBFCP->pRefUndoDoc);
+ nClipTab = (nClipTab+1) % (MAXTAB+1);
+ }
+ }
+}
+
+
+void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMark,
+ USHORT nInsFlag,
+ ScDocument* pRefUndoDoc, ScDocument* pClipDoc, BOOL bResetCut,
+ BOOL bAsLink )
+{
+ if (!bIsClip)
+ {
+ if (!pClipDoc)
+ pClipDoc = ScGlobal::GetClipDoc();
+ if (pClipDoc->bIsClip && pClipDoc->GetTableCount())
+ {
+ BOOL bOldAutoCalc = GetAutoCalc();
+ SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ if (pClipDoc->pFormTable && pClipDoc->pFormTable != pFormTable)
+ {
+ SvULONGTable* pExchangeList =
+ pFormTable->MergeFormatter(*(pClipDoc->pFormTable));
+ if (pExchangeList->Count() > 0)
+ pFormatExchangeList = pExchangeList;
+ }
+
+ USHORT nClipRangeNames = pClipDoc->pRangeName->GetCount();
+ // array containing range names which might need update of indices
+ ScRangeData** pClipRangeNames = nClipRangeNames ? new ScRangeData* [nClipRangeNames] : NULL;
+ // the index mapping thereof
+ ScIndexMap aClipRangeMap( nClipRangeNames );
+ BOOL bRangeNameReplace = FALSE;
+
+ USHORT i, k;
+ for (i = 0; i < nClipRangeNames; i++) //! DB-Bereiche Pivot-Bereiche auch
+ {
+ /* Copy only if the name doesn't exist in this document.
+ If it exists we use the already existing name instead,
+ another possibility could be to create new names if
+ documents differ.
+ A proper solution would ask the user how to proceed.
+ The adjustment of the indices in the formulas is done later.
+ */
+ ScRangeData* pClipData = (*pClipDoc->pRangeName)[i];
+ if ( pRangeName->SearchName( pClipData->GetName(), k ) )
+ {
+ pClipRangeNames[i] = NULL; // range name not inserted
+ USHORT nOldIndex = pClipData->GetIndex();
+ USHORT nNewIndex = ((*pRangeName)[k])->GetIndex();
+ aClipRangeMap.SetPair( i, nOldIndex, nNewIndex );
+ if ( !bRangeNameReplace )
+ bRangeNameReplace = ( nOldIndex != nNewIndex );
+ }
+ else
+ {
+ ScRangeData* pData = new ScRangeData( *pClipData );
+ pData->SetDocument(this);
+ if ( pRangeName->FindIndex( pData->GetIndex() ) )
+ pData->SetIndex(0); // need new index, done in Insert
+ if ( pRangeName->Insert( pData ) )
+ {
+ pClipRangeNames[i] = pData;
+ USHORT nOldIndex = pClipData->GetIndex();
+ USHORT nNewIndex = pData->GetIndex();
+ aClipRangeMap.SetPair( i, nOldIndex, nNewIndex );
+ if ( !bRangeNameReplace )
+ bRangeNameReplace = ( nOldIndex != nNewIndex );
+ }
+ else
+ { // must be an overflow
+ delete pData;
+ pClipRangeNames[i] = NULL;
+ aClipRangeMap.SetPair( i, pClipData->GetIndex(), 0 );
+ bRangeNameReplace = TRUE;
+ }
+ }
+ }
+ USHORT nCol1 = rDestRange.aStart.Col();
+ USHORT nRow1 = rDestRange.aStart.Row();
+ USHORT nCol2 = rDestRange.aEnd.Col();
+ USHORT nRow2 = rDestRange.aEnd.Row();
+
+ USHORT nXw = pClipDoc->aClipRange.aEnd.Col();
+ USHORT nYw = pClipDoc->aClipRange.aEnd.Row();
+ pClipDoc->ExtendMerge( pClipDoc->aClipRange.aStart.Col(),
+ pClipDoc->aClipRange.aStart.Row(),
+ nXw, nYw, 0 );
+ nXw -= pClipDoc->aClipRange.aStart.Col();
+ nYw -= pClipDoc->aClipRange.aStart.Row();
+
+ // Inhalte entweder komplett oder gar nicht loeschen:
+ USHORT nDelFlag = IDF_NONE;
+ if ( nInsFlag & IDF_CONTENTS )
+ nDelFlag |= IDF_CONTENTS;
+ if ( nInsFlag & IDF_ATTRIB )
+ nDelFlag |= IDF_ATTRIB;
+ DeleteArea(nCol1, nRow1, nCol2, nRow2, rMark, nDelFlag);
+
+ bInsertingFromOtherDoc = TRUE; // kein Broadcast/Listener aufbauen bei Insert
+ USHORT nC1 = nCol1;
+ USHORT nR1 = nRow1;
+ USHORT nC2 = nC1 + nXw;
+ USHORT nR2 = nR1 + nYw;
+ USHORT nClipStartCol = pClipDoc->aClipRange.aStart.Col();
+ USHORT nClipStartRow = pClipDoc->aClipRange.aStart.Row();
+
+ ScCopyBlockFromClipParams aCBFCP;
+ aCBFCP.pRefUndoDoc = pRefUndoDoc;
+ aCBFCP.pClipDoc = pClipDoc;
+ aCBFCP.nInsFlag = nInsFlag;
+ aCBFCP.bAsLink = bAsLink;
+ aCBFCP.nTabStart = MAXTAB; // wird in der Schleife angepasst
+ aCBFCP.nTabEnd = 0; // wird in der Schleife angepasst
+
+ // Inc/DecRecalcLevel einmal aussen, damit nicht fuer jeden Block
+ // die Draw-Seitengroesse neu berechnet werden muss
+ //! nur wenn ganze Zeilen/Spalten kopiert werden?
+
+ for (i = 0; i <= MAXTAB; i++)
+ if (pTab[i] && rMark.GetTableSelect(i))
+ {
+ if ( i < aCBFCP.nTabStart )
+ aCBFCP.nTabStart = i;
+ aCBFCP.nTabEnd = i;
+ pTab[i]->IncRecalcLevel();
+ }
+
+ // bei mindestens 64 Zeilen wird in ScColumn::CopyFromClip voralloziert
+ BOOL bDoDouble = ( nYw < 64 && nRow2 - nRow1 > 64);
+ BOOL bOldDouble = ScColumn::bDoubleAlloc;
+ if (bDoDouble)
+ ScColumn::bDoubleAlloc = TRUE;
+
+ do
+ {
+ do
+ {
+ short nDx = ((short)nC1) - nClipStartCol;
+ short nDy = ((short)nR1) - nClipStartRow;
+ CopyBlockFromClip( nC1, nR1, nC2, nR2, rMark, nDx, nDy, &aCBFCP );
+ nC1 = nC2 + 1;
+ nC2 = Min((USHORT)(nC1 + nXw), nCol2);
+ }
+ while (nC1 <= nCol2);
+ nC1 = nCol1;
+ nC2 = nC1 + nXw;
+ nR1 = nR2 + 1;
+ nR2 = Min((USHORT)(nR1 + nYw), nRow2);
+ }
+ while (nR1 <= nRow2);
+
+ ScColumn::bDoubleAlloc = bOldDouble;
+
+ for (i = 0; i <= MAXTAB; i++)
+ if (pTab[i] && rMark.GetTableSelect(i))
+ pTab[i]->DecRecalcLevel();
+
+ bInsertingFromOtherDoc = FALSE;
+ pFormatExchangeList = NULL;
+ if ( bRangeNameReplace )
+ {
+ // first update all inserted named formulas if they contain other
+ // range names and used indices changed
+ for (i = 0; i < nClipRangeNames; i++) //! DB-Bereiche Pivot-Bereiche auch
+ {
+ if ( pClipRangeNames[i] )
+ pClipRangeNames[i]->ReplaceRangeNamesInUse( aClipRangeMap );
+ }
+ // then update the formulas, they might need the just updated range names
+ USHORT nC1 = nCol1;
+ USHORT nR1 = nRow1;
+ USHORT nC2 = nC1 + nXw;
+ USHORT nR2 = nR1 + nYw;
+ do
+ {
+ do
+ {
+ for (k = 0; k <= MAXTAB; k++)
+ {
+ if ( pTab[k] && rMark.GetTableSelect(k) )
+ pTab[k]->ReplaceRangeNamesInUse(nC1, nR1,
+ nC2, nR2, aClipRangeMap );
+ }
+ nC1 = nC2 + 1;
+ nC2 = Min((USHORT)(nC1 + nXw), nCol2);
+ } while (nC1 <= nCol2);
+ nC1 = nCol1;
+ nC2 = nC1 + nXw;
+ nR1 = nR2 + 1;
+ nR2 = Min((USHORT)(nR1 + nYw), nRow2);
+ } while (nR1 <= nRow2);
+ }
+ if ( pClipRangeNames )
+ delete [] pClipRangeNames;
+ // Listener aufbauen nachdem alles inserted wurde
+ StartListeningFromClip( nCol1, nRow1, nCol2, nRow2, rMark, nInsFlag );
+ // nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
+ BroadcastFromClip( nCol1, nRow1, nCol2, nRow2, rMark, nInsFlag );
+ if (bResetCut)
+ pClipDoc->bCutMode = FALSE;
+ SetAutoCalc( bOldAutoCalc );
+ }
+ }
+}
+
+
+void ScDocument::SetClipArea( const ScRange& rArea, BOOL bCut )
+{
+ if (bIsClip)
+ {
+ aClipRange = rArea;
+ bCutMode = bCut;
+ }
+ else
+ DBG_ERROR("SetClipArea: kein Clip");
+}
+
+
+void ScDocument::GetClipArea(USHORT& nClipX, USHORT& nClipY)
+{
+ if (bIsClip)
+ {
+ nClipX = aClipRange.aEnd.Col() - aClipRange.aStart.Col();
+ nClipY = aClipRange.aEnd.Row() - aClipRange.aStart.Row();
+ }
+ else
+ DBG_ERROR("GetClipArea: kein Clip");
+}
+
+
+void ScDocument::GetClipStart(USHORT& nClipX, USHORT& nClipY)
+{
+ if (bIsClip)
+ {
+ nClipX = aClipRange.aStart.Col();
+ nClipY = aClipRange.aStart.Row();
+ }
+ else
+ DBG_ERROR("GetClipStart: kein Clip");
+}
+
+
+void ScDocument::MixDocument( const ScRange& rRange, USHORT nFunction, BOOL bSkipEmpty,
+ ScDocument* pSrcDoc )
+{
+ USHORT nTab1 = rRange.aStart.Tab();
+ USHORT nTab2 = rRange.aEnd.Tab();
+ for (USHORT i = nTab1; i <= nTab2; i++)
+ if (pTab[i] && pSrcDoc->pTab[i])
+ pTab[i]->MixData( rRange.aStart.Col(), rRange.aStart.Row(),
+ rRange.aEnd.Col(), rRange.aEnd.Row(),
+ nFunction, bSkipEmpty, pSrcDoc->pTab[i] );
+}
+
+
+void ScDocument::FillTab( const ScRange& rSrcArea, const ScMarkData& rMark,
+ USHORT nFlags, USHORT nFunction,
+ BOOL bSkipEmpty, BOOL bAsLink )
+{
+ USHORT nDelFlags = nFlags;
+ if (nDelFlags & IDF_CONTENTS)
+ nDelFlags |= IDF_CONTENTS; // immer alle Inhalte oder keine loeschen!
+
+ USHORT nSrcTab = rSrcArea.aStart.Tab();
+
+ if (nSrcTab <= MAXTAB && pTab[nSrcTab])
+ {
+ USHORT nStartCol = rSrcArea.aStart.Col();
+ USHORT nStartRow = rSrcArea.aStart.Row();
+ USHORT nEndCol = rSrcArea.aEnd.Col();
+ USHORT nEndRow = rSrcArea.aEnd.Row();
+ ScDocument* pMixDoc = NULL;
+ BOOL bDoMix = ( bSkipEmpty || nFunction ) && ( nFlags & IDF_CONTENTS );
+
+ BOOL bOldAutoCalc = GetAutoCalc();
+ SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+
+ USHORT nCount = GetTableCount();
+ for (USHORT i=0; i<nCount; i++)
+ if ( i!=nSrcTab && pTab[i] && rMark.GetTableSelect(i) )
+ {
+ if (bDoMix)
+ {
+ if (!pMixDoc)
+ {
+ pMixDoc = new ScDocument( SCDOCMODE_UNDO );
+ pMixDoc->InitUndo( this, i, i );
+ }
+ else
+ pMixDoc->AddUndoTab( i, i );
+ pTab[i]->CopyToTable( nStartCol,nStartRow, nEndCol,nEndRow,
+ IDF_CONTENTS, FALSE, pMixDoc->pTab[i] );
+ }
+ pTab[i]->DeleteArea( nStartCol,nStartRow, nEndCol,nEndRow, nDelFlags);
+ pTab[nSrcTab]->CopyToTable( nStartCol,nStartRow, nEndCol,nEndRow,
+ nFlags, FALSE, pTab[i], NULL, bAsLink );
+
+ if (bDoMix)
+ pTab[i]->MixData( nStartCol,nStartRow, nEndCol,nEndRow,
+ nFunction, bSkipEmpty, pMixDoc->pTab[i] );
+ }
+
+ delete pMixDoc;
+
+ SetAutoCalc( bOldAutoCalc );
+ }
+ else
+ DBG_ERROR("falsche Tabelle");
+}
+
+
+void ScDocument::FillTabMarked( USHORT nSrcTab, const ScMarkData& rMark,
+ USHORT nFlags, USHORT nFunction,
+ BOOL bSkipEmpty, BOOL bAsLink )
+{
+ USHORT nDelFlags = nFlags;
+ if (nDelFlags & IDF_CONTENTS)
+ nDelFlags |= IDF_CONTENTS; // immer alle Inhalte oder keine loeschen!
+
+ if (nSrcTab <= MAXTAB && pTab[nSrcTab])
+ {
+ ScDocument* pMixDoc = NULL;
+ BOOL bDoMix = ( bSkipEmpty || nFunction ) && ( nFlags & IDF_CONTENTS );
+
+ BOOL bOldAutoCalc = GetAutoCalc();
+ SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+
+ ScRange aArea;
+ rMark.GetMultiMarkArea( aArea );
+ USHORT nStartCol = aArea.aStart.Col();
+ USHORT nStartRow = aArea.aStart.Row();
+ USHORT nEndCol = aArea.aEnd.Col();
+ USHORT nEndRow = aArea.aEnd.Row();
+
+ USHORT nCount = GetTableCount();
+ for (USHORT i=0; i<nCount; i++)
+ if ( i!=nSrcTab && pTab[i] && rMark.GetTableSelect(i) )
+ {
+ if (bDoMix)
+ {
+ if (!pMixDoc)
+ {
+ pMixDoc = new ScDocument( SCDOCMODE_UNDO );
+ pMixDoc->InitUndo( this, i, i );
+ }
+ else
+ pMixDoc->AddUndoTab( i, i );
+ pTab[i]->CopyToTable( nStartCol,nStartRow, nEndCol,nEndRow,
+ IDF_CONTENTS, TRUE, pMixDoc->pTab[i], &rMark );
+ }
+
+ pTab[i]->DeleteSelection( nDelFlags, rMark );
+ pTab[nSrcTab]->CopyToTable( nStartCol,nStartRow, nEndCol,nEndRow,
+ nFlags, TRUE, pTab[i], &rMark, bAsLink );
+
+ if (bDoMix)
+ pTab[i]->MixMarked( rMark, nFunction, bSkipEmpty, pMixDoc->pTab[i] );
+ }
+
+ delete pMixDoc;
+
+ SetAutoCalc( bOldAutoCalc );
+ }
+ else
+ DBG_ERROR("falsche Tabelle");
+}
+
+
+void ScDocument::PutCell( USHORT nCol, USHORT nRow, USHORT nTab, ScBaseCell* pCell, BOOL bForceTab )
+{
+ if (VALIDTAB(nTab))
+ {
+ if ( bForceTab && !pTab[nTab] )
+ {
+ BOOL bExtras = !bIsUndo; // Spaltenbreiten, Zeilenhoehen, Flags
+
+ pTab[nTab] = new ScTable(this, nTab,
+ String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("temp")),
+ bExtras, bExtras);
+ ++nMaxTableNumber;
+ }
+
+ if (pTab[nTab])
+ pTab[nTab]->PutCell( nCol, nRow, pCell );
+ }
+}
+
+
+void ScDocument::PutCell( const ScAddress& rPos, ScBaseCell* pCell, BOOL bForceTab )
+{
+ USHORT nTab = rPos.Tab();
+ if ( bForceTab && !pTab[nTab] )
+ {
+ BOOL bExtras = !bIsUndo; // Spaltenbreiten, Zeilenhoehen, Flags
+
+ pTab[nTab] = new ScTable(this, nTab,
+ String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("temp")),
+ bExtras, bExtras);
+ ++nMaxTableNumber;
+ }
+
+ if (pTab[nTab])
+ pTab[nTab]->PutCell( rPos, pCell );
+}
+
+
+BOOL ScDocument::SetString( USHORT nCol, USHORT nRow, USHORT nTab, const String& rString )
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ return pTab[nTab]->SetString( nCol, nRow, nTab, rString );
+ else
+ return FALSE;
+}
+
+
+void ScDocument::SetValue( USHORT nCol, USHORT nRow, USHORT nTab, const double& rVal )
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ pTab[nTab]->SetValue( nCol, nRow, rVal );
+}
+
+
+void ScDocument::SetNote( USHORT nCol, USHORT nRow, USHORT nTab, const ScPostIt& rNote )
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ pTab[nTab]->SetNote( nCol, nRow, rNote );
+}
+
+
+void ScDocument::GetString( USHORT nCol, USHORT nRow, USHORT nTab, String& rString )
+{
+ if ( VALIDTAB(nTab) && pTab[nTab] )
+ pTab[nTab]->GetString( nCol, nRow, rString );
+ else
+ rString.Erase();
+}
+
+
+void ScDocument::GetInputString( USHORT nCol, USHORT nRow, USHORT nTab, String& rString )
+{
+ if ( VALIDTAB(nTab) && pTab[nTab] )
+ pTab[nTab]->GetInputString( nCol, nRow, rString );
+ else
+ rString.Erase();
+}
+
+
+void ScDocument::GetValue( USHORT nCol, USHORT nRow, USHORT nTab, double& rValue )
+{
+ if ( VALIDTAB(nTab) && pTab[nTab] )
+ rValue = pTab[nTab]->GetValue( nCol, nRow );
+ else
+ rValue = 0.0;
+}
+
+
+double ScDocument::GetValue( const ScAddress& rPos )
+{
+ USHORT nTab = rPos.Tab();
+ if ( pTab[nTab] )
+ return pTab[nTab]->GetValue( rPos );
+ return 0.0;
+}
+
+
+void ScDocument::GetNumberFormat( USHORT nCol, USHORT nRow, USHORT nTab,
+ ULONG& rFormat )
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ {
+ rFormat = pTab[nTab]->GetNumberFormat( nCol, nRow );
+ return ;
+ }
+ rFormat = 0;
+}
+
+
+ULONG ScDocument::GetNumberFormat( const ScAddress& rPos ) const
+{
+ USHORT nTab = rPos.Tab();
+ if ( pTab[nTab] )
+ return pTab[nTab]->GetNumberFormat( rPos );
+ return 0;
+}
+
+
+void ScDocument::GetNumberFormatInfo( short& nType, ULONG& nIndex,
+ const ScAddress& rPos, const ScFormulaCell& rFCell ) const
+{
+ USHORT nTab = rPos.Tab();
+ if ( pTab[nTab] )
+ {
+ nIndex = pTab[nTab]->GetNumberFormat( rPos );
+ if ( (nIndex % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
+ rFCell.GetFormatInfo( nType, nIndex );
+ else
+ nType = GetFormatTable()->GetType( nIndex );
+ }
+ else
+ {
+ nType = NUMBERFORMAT_UNDEFINED;
+ nIndex = 0;
+ }
+}
+
+
+void ScDocument::GetFormula( USHORT nCol, USHORT nRow, USHORT nTab, String& rFormula,
+ BOOL bAsciiExport ) const
+{
+ if ( VALIDTAB(nTab) && pTab[nTab] )
+ pTab[nTab]->GetFormula( nCol, nRow, rFormula, bAsciiExport );
+ else
+ rFormula.Erase();
+}
+
+
+BOOL ScDocument::GetNote( USHORT nCol, USHORT nRow, USHORT nTab, ScPostIt& rNote )
+{
+ BOOL bHasNote = FALSE;
+
+ if ( VALIDTAB(nTab) && pTab[nTab] )
+ bHasNote = pTab[nTab]->GetNote( nCol, nRow, rNote );
+ else
+ rNote.Clear();
+
+ return bHasNote;
+}
+
+
+CellType ScDocument::GetCellType( const ScAddress& rPos ) const
+{
+ USHORT nTab = rPos.Tab();
+ if ( pTab[nTab] )
+ return pTab[nTab]->GetCellType( rPos );
+ return CELLTYPE_NONE;
+}
+
+
+void ScDocument::GetCellType( USHORT nCol, USHORT nRow, USHORT nTab,
+ CellType& rCellType ) const
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ rCellType = pTab[nTab]->GetCellType( nCol, nRow );
+ else
+ rCellType = CELLTYPE_NONE;
+}
+
+
+void ScDocument::GetCell( USHORT nCol, USHORT nRow, USHORT nTab,
+ ScBaseCell*& rpCell ) const
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ rpCell = pTab[nTab]->GetCell( nCol, nRow );
+ else
+ {
+ DBG_ERROR("GetCell ohne Tabelle");
+ rpCell = NULL;
+ }
+}
+
+
+ScBaseCell* ScDocument::GetCell( const ScAddress& rPos ) const
+{
+ USHORT nTab = rPos.Tab();
+ if ( pTab[nTab] )
+ return pTab[nTab]->GetCell( rPos );
+
+ DBG_ERROR("GetCell ohne Tabelle");
+ return NULL;
+}
+
+
+BOOL ScDocument::HasStringData( USHORT nCol, USHORT nRow, USHORT nTab ) const
+{
+ if ( VALIDTAB(nTab) && pTab[nTab] )
+ return pTab[nTab]->HasStringData( nCol, nRow );
+ else
+ return FALSE;
+}
+
+
+BOOL ScDocument::HasValueData( USHORT nCol, USHORT nRow, USHORT nTab ) const
+{
+ if ( VALIDTAB(nTab) && pTab[nTab] )
+ return pTab[nTab]->HasValueData( nCol, nRow );
+ else
+ return FALSE;
+}
+
+
+BOOL ScDocument::HasStringCells( const ScRange& rRange ) const
+{
+ // TRUE, wenn String- oder Editzellen im Bereich
+
+ USHORT nStartCol = rRange.aStart.Col();
+ USHORT nStartRow = rRange.aStart.Row();
+ USHORT nStartTab = rRange.aStart.Tab();
+ USHORT nEndCol = rRange.aEnd.Col();
+ USHORT nEndRow = rRange.aEnd.Row();
+ USHORT nEndTab = rRange.aEnd.Tab();
+
+ for ( USHORT nTab=nStartTab; nTab<=nEndTab; nTab++ )
+ if ( pTab[nTab] && pTab[nTab]->HasStringCells( nStartCol, nStartRow, nEndCol, nEndRow ) )
+ return TRUE;
+
+ return FALSE;
+}
+
+
+void ScDocument::SetDirtyVar()
+{
+ for (USHORT i=0; i<=MAXTAB; i++)
+ if (pTab[i]) pTab[i]->SetDirtyVar();
+}
+
+
+void ScDocument::SetDirty()
+{
+ BOOL bOldAutoCalc = GetAutoCalc();
+ bAutoCalc = FALSE; // keine Mehrfachberechnung
+ for (USHORT i=0; i<=MAXTAB; i++)
+ if (pTab[i]) pTab[i]->SetDirty();
+
+ // Charts werden zwar auch ohne AutoCalc im Tracking auf Dirty gesetzt,
+ // wenn alle Formeln dirty sind, werden die Charts aber nicht mehr erwischt
+ // (#45205#) - darum alle Charts nochmal explizit
+ if (pChartListenerCollection)
+ pChartListenerCollection->SetDirty();
+
+ SetAutoCalc( bOldAutoCalc );
+}
+
+
+void ScDocument::SetDirty( const ScRange& rRange )
+{
+ BOOL bOldAutoCalc = GetAutoCalc();
+ bAutoCalc = FALSE; // keine Mehrfachberechnung
+ USHORT nTab2 = rRange.aEnd.Tab();
+ for (USHORT i=rRange.aStart.Tab(); i<=nTab2; i++)
+ if (pTab[i]) pTab[i]->SetDirty( rRange );
+ SetAutoCalc( bOldAutoCalc );
+}
+
+
+void ScDocument::CalcAll()
+{
+ BOOL bOldAutoCalc = GetAutoCalc();
+ SetAutoCalc( TRUE );
+ USHORT i;
+ for (i=0; i<=MAXTAB; i++)
+ if (pTab[i]) pTab[i]->SetDirtyVar();
+ for (i=0; i<=MAXTAB; i++)
+ if (pTab[i]) pTab[i]->CalcAll();
+ ClearFormulaTree();
+ SetAutoCalc( bOldAutoCalc );
+}
+
+
+void ScDocument::CompileAll()
+{
+ if ( pCondFormList )
+ pCondFormList->CompileAll();
+
+ for (USHORT i=0; i<=MAXTAB; i++)
+ if (pTab[i]) pTab[i]->CompileAll();
+ SetDirty();
+}
+
+
+void ScDocument::CompileXML()
+{
+ BOOL bOldAutoCalc = GetAutoCalc();
+ SetAutoCalc( FALSE );
+ for (USHORT i=0; i<=MAXTAB; i++)
+ if (pTab[i]) pTab[i]->CompileXML();
+ SetDirty();
+ SetAutoCalc( bOldAutoCalc );
+}
+
+
+void ScDocument::CalcAfterLoad()
+{
+ if (bIsClip) // Excel-Dateien werden aus dem Clipboard in ein Clip-Doc geladen
+ return; // dann wird erst beim Einfuegen in das richtige Doc berechnet
+
+ bCalcingAfterLoad = TRUE;
+ for (USHORT i=0; i<=MAXTAB; i++)
+ if (pTab[i]) pTab[i]->CalcAfterLoad();
+ for (i=0; i<=MAXTAB; i++)
+ if (pTab[i]) pTab[i]->SetDirtyAfterLoad();
+ bCalcingAfterLoad = FALSE;
+
+ SetDetectiveDirty(FALSE); // noch keine wirklichen Aenderungen
+}
+
+
+void ScDocument::GetErrCode( USHORT nCol, USHORT nRow, USHORT nTab, USHORT& rErrCode )
+{
+ if ( VALIDTAB(nTab) && pTab[nTab] )
+ rErrCode = pTab[nTab]->GetErrCode( nCol, nRow );
+ else
+ rErrCode = 0;
+}
+
+
+USHORT ScDocument::GetErrCode( const ScAddress& rPos ) const
+{
+ USHORT nTab = rPos.Tab();
+ if ( pTab[nTab] )
+ return pTab[nTab]->GetErrCode( rPos );
+ return 0;
+}
+
+
+void ScDocument::ResetChanged( const ScRange& rRange )
+{
+ USHORT nStartTab = rRange.aStart.Tab();
+ USHORT nEndTab = rRange.aEnd.Tab();
+ for (USHORT nTab=nStartTab; nTab<=nEndTab; nTab++)
+ if (pTab[nTab])
+ pTab[nTab]->ResetChanged( rRange );
+}
+
+//
+// Spaltenbreiten / Zeilenhoehen --------------------------------------
+//
+
+
+void ScDocument::SetColWidth( USHORT nCol, USHORT nTab, USHORT nNewWidth )
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ pTab[nTab]->SetColWidth( nCol, nNewWidth );
+}
+
+
+void ScDocument::SetRowHeight( USHORT nRow, USHORT nTab, USHORT nNewHeight )
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ pTab[nTab]->SetRowHeight( nRow, nNewHeight );
+}
+
+
+void ScDocument::SetRowHeightRange( USHORT nStartRow, USHORT nEndRow, USHORT nTab, USHORT nNewHeight )
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ pTab[nTab]->SetRowHeightRange
+ ( nStartRow, nEndRow, nNewHeight, 1.0, 1.0 );
+}
+
+
+void ScDocument::SetManualHeight( USHORT nStartRow, USHORT nEndRow, USHORT nTab, BOOL bManual )
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ pTab[nTab]->SetManualHeight( nStartRow, nEndRow, bManual );
+}
+
+
+USHORT ScDocument::GetColWidth( USHORT nCol, USHORT nTab ) const
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ return pTab[nTab]->GetColWidth( nCol );
+ DBG_ERROR("Falsche Tabellennummer");
+ return 0;
+}
+
+
+USHORT ScDocument::GetOriginalWidth( USHORT nCol, USHORT nTab ) const
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ return pTab[nTab]->GetOriginalWidth( nCol );
+ DBG_ERROR("Falsche Tabellennummer");
+ return 0;
+}
+
+
+USHORT ScDocument::GetRowHeight( USHORT nRow, USHORT nTab ) const
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ return pTab[nTab]->GetRowHeight( nRow );
+ DBG_ERROR("Falsche Tabellennummer");
+ return 0;
+}
+
+
+USHORT ScDocument::GetHiddenRowCount( USHORT nRow, USHORT nTab ) const
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ return pTab[nTab]->GetHiddenRowCount( nRow );
+ DBG_ERROR("Falsche Tabellennummer");
+ return 0;
+}
+
+
+ULONG ScDocument::GetColOffset( USHORT nCol, USHORT nTab ) const
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ return pTab[nTab]->GetColOffset( nCol );
+ DBG_ERROR("Falsche Tabellennummer");
+ return 0;
+}
+
+
+ULONG ScDocument::GetRowOffset( USHORT nRow, USHORT nTab ) const
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ return pTab[nTab]->GetRowOffset( nRow );
+ DBG_ERROR("Falsche Tabellennummer");
+ return 0;
+}
+
+
+USHORT ScDocument::GetOptimalColWidth( USHORT nCol, USHORT nTab, OutputDevice* pDev,
+ double nPPTX, double nPPTY,
+ const Fraction& rZoomX, const Fraction& rZoomY,
+ BOOL bFormula, const ScMarkData* pMarkData,
+ BOOL bSimpleTextImport )
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ return pTab[nTab]->GetOptimalColWidth( nCol, pDev, nPPTX, nPPTY,
+ rZoomX, rZoomY, bFormula, pMarkData, bSimpleTextImport );
+ DBG_ERROR("Falsche Tabellennummer");
+ return 0;
+}
+
+
+long ScDocument::GetNeededSize( USHORT nCol, USHORT nRow, USHORT nTab,
+ OutputDevice* pDev,
+ double nPPTX, double nPPTY,
+ const Fraction& rZoomX, const Fraction& rZoomY,
+ BOOL bWidth, BOOL bTotalSize )
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ return pTab[nTab]->GetNeededSize
+ ( nCol, nRow, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bWidth, bTotalSize );
+ DBG_ERROR("Falsche Tabellennummer");
+ return 0;
+}
+
+
+BOOL ScDocument::SetOptimalHeight( USHORT nStartRow, USHORT nEndRow, USHORT nTab, USHORT nExtra,
+ OutputDevice* pDev,
+ double nPPTX, double nPPTY,
+ const Fraction& rZoomX, const Fraction& rZoomY,
+ BOOL bShrink )
+{
+//! MarkToMulti();
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ return pTab[nTab]->SetOptimalHeight( nStartRow, nEndRow, nExtra,
+ pDev, nPPTX, nPPTY, rZoomX, rZoomY, bShrink );
+ DBG_ERROR("Falsche Tabellennummer");
+ return FALSE;
+}
+
+
+//
+// Spalten-/Zeilen-Flags ----------------------------------------------
+//
+
+void ScDocument::ShowCol(USHORT nCol, USHORT nTab, BOOL bShow)
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ pTab[nTab]->ShowCol( nCol, bShow );
+}
+
+
+void ScDocument::ShowRow(USHORT nRow, USHORT nTab, BOOL bShow)
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ pTab[nTab]->ShowRow( nRow, bShow );
+}
+
+
+void ScDocument::ShowRows(USHORT nRow1, USHORT nRow2, USHORT nTab, BOOL bShow)
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ pTab[nTab]->ShowRows( nRow1, nRow2, bShow );
+}
+
+
+void ScDocument::SetColFlags( USHORT nCol, USHORT nTab, BYTE nNewFlags )
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ pTab[nTab]->SetColFlags( nCol, nNewFlags );
+}
+
+
+void ScDocument::SetRowFlags( USHORT nRow, USHORT nTab, BYTE nNewFlags )
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ pTab[nTab]->SetRowFlags( nRow, nNewFlags );
+}
+
+
+BYTE ScDocument::GetColFlags( USHORT nCol, USHORT nTab ) const
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ return pTab[nTab]->GetColFlags( nCol );
+ DBG_ERROR("Falsche Tabellennummer");
+ return 0;
+}
+
+
+BYTE ScDocument::GetRowFlags( USHORT nRow, USHORT nTab ) const
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ return pTab[nTab]->GetRowFlags( nRow );
+ DBG_ERROR("Falsche Tabellennummer");
+ return 0;
+}
+
+
+USHORT ScDocument::GetLastFlaggedCol( USHORT nTab ) const
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ return pTab[nTab]->GetLastFlaggedCol();
+ return 0;
+}
+
+
+USHORT ScDocument::GetLastFlaggedRow( USHORT nTab ) const
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ return pTab[nTab]->GetLastFlaggedRow();
+ return 0;
+}
+
+
+void ScDocument::StripHidden( USHORT& rX1, USHORT& rY1, USHORT& rX2, USHORT& rY2, USHORT nTab )
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ pTab[nTab]->StripHidden( rX1, rY1, rX2, rY2 );
+}
+
+
+void ScDocument::ExtendHidden( USHORT& rX1, USHORT& rY1, USHORT& rX2, USHORT& rY2, USHORT nTab )
+{
+ if ( nTab<=MAXTAB && pTab[nTab] )
+ pTab[nTab]->ExtendHidden( rX1, rY1, rX2, rY2 );
+}
+
+//
+// Attribute ----------------------------------------------------------
+//
+
+const SfxPoolItem* ScDocument::GetAttr( USHORT nCol, USHORT nRow, USHORT nTab, USHORT nWhich ) const
+{
+ if ( nTab <= MAXTAB && pTab[nTab] )
+ {
+ const SfxPoolItem* pTemp = pTab[nTab]->GetAttr( nCol, nRow, nWhich );
+ if (pTemp)
+ return pTemp;
+ else
+ DBG_ERROR( "Attribut Null" );
+ }
+ return &pDocPool->GetDefaultItem( nWhich );
+}
+
+
+const ScPatternAttr* ScDocument::GetPattern( USHORT nCol, USHORT nRow, USHORT nTab ) const
+{
+ if ( nTab <= MAXTAB && pTab[nTab] )
+ return pTab[nTab]->GetPattern( nCol, nRow );
+ return NULL;
+}
+
+
+void ScDocument::ApplyAttr( USHORT nCol, USHORT nRow, USHORT nTab, const SfxPoolItem& rAttr )
+{
+ if ( nTab <= MAXTAB && pTab[nTab] )
+ pTab[nTab]->ApplyAttr( nCol, nRow, rAttr );
+}
+
+
+void ScDocument::ApplyPattern( USHORT nCol, USHORT nRow, USHORT nTab, const ScPatternAttr& rAttr )
+{
+ if ( nTab <= MAXTAB && pTab[nTab] )
+ pTab[nTab]->ApplyPattern( nCol, nRow, rAttr );
+}
+
+
+void ScDocument::ApplyPatternArea( USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow,
+ const ScMarkData& rMark,
+ const ScPatternAttr& rAttr )
+{
+ for (USHORT i=0; i <= MAXTAB; i++)
+ if (pTab[i])
+ if (rMark.GetTableSelect(i))
+ pTab[i]->ApplyPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rAttr );
+}
+
+
+void ScDocument::ApplyPatternAreaTab( USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow, USHORT nTab, const ScPatternAttr& rAttr )
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ pTab[nTab]->ApplyPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rAttr );
+}
+
+void ScDocument::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
+ const ScMarkData& rMark, const ScPatternAttr& rPattern, short nNewType )
+{
+ for (USHORT i=0; i <= MAXTAB; i++)
+ if (pTab[i])
+ if (rMark.GetTableSelect(i))
+ pTab[i]->ApplyPatternIfNumberformatIncompatible( rRange, rPattern, nNewType );
+}
+
+
+void ScDocument::ApplyStyle( USHORT nCol, USHORT nRow, USHORT nTab, const ScStyleSheet& rStyle)
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ pTab[nTab]->ApplyStyle( nCol, nRow, rStyle );
+}
+
+
+void ScDocument::ApplyStyleArea( USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow,
+ const ScMarkData& rMark,
+ const ScStyleSheet& rStyle)
+{
+ for (USHORT i=0; i <= MAXTAB; i++)
+ if (pTab[i])
+ if (rMark.GetTableSelect(i))
+ pTab[i]->ApplyStyleArea( nStartCol, nStartRow, nEndCol, nEndRow, rStyle );
+}
+
+
+void ScDocument::ApplyStyleAreaTab( USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow, USHORT nTab, const ScStyleSheet& rStyle)
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ pTab[nTab]->ApplyStyleArea( nStartCol, nStartRow, nEndCol, nEndRow, rStyle );
+}
+
+
+void ScDocument::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
+{
+ // ApplySelectionStyle needs multi mark
+ if ( rMark.IsMarked() && !rMark.IsMultiMarked() )
+ {
+ ScRange aRange;
+ rMark.GetMarkArea( aRange );
+ ApplyStyleArea( aRange.aStart.Col(), aRange.aStart.Row(),
+ aRange.aEnd.Col(), aRange.aEnd.Row(), rMark, rStyle );
+ }
+ else
+ {
+ for (USHORT i=0; i<=MAXTAB; i++)
+ if ( pTab[i] && rMark.GetTableSelect(i) )
+ pTab[i]->ApplySelectionStyle( rStyle, rMark );
+ }
+}
+
+
+void ScDocument::ApplySelectionLineStyle( const ScMarkData& rMark,
+ const SvxBorderLine* pLine, BOOL bColorOnly )
+{
+ if ( bColorOnly && !pLine )
+ return;
+
+ for (USHORT i=0; i<=MAXTAB; i++)
+ if (pTab[i])
+ if (rMark.GetTableSelect(i))
+ pTab[i]->ApplySelectionLineStyle( rMark, pLine, bColorOnly );
+}
+
+
+const ScStyleSheet* ScDocument::GetStyle( USHORT nCol, USHORT nRow, USHORT nTab ) const
+{
+ if ( VALIDTAB(nTab) && pTab[nTab] )
+ return pTab[nTab]->GetStyle(nCol, nRow);
+ else
+ return NULL;
+}
+
+
+const ScStyleSheet* ScDocument::GetSelectionStyle( const ScMarkData& rMark ) const
+{
+ BOOL bEqual = TRUE;
+ BOOL bFound;
+ USHORT i;
+
+ const ScStyleSheet* pStyle = NULL;
+ const ScStyleSheet* pNewStyle;
+
+ if ( rMark.IsMultiMarked() )
+ for (i=0; i<=MAXTAB && bEqual; i++)
+ if (pTab[i] && rMark.GetTableSelect(i))
+ {
+ pNewStyle = pTab[i]->GetSelectionStyle( rMark, bFound );
+ if (bFound)
+ {
+ if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
+ bEqual = FALSE; // unterschiedliche
+ pStyle = pNewStyle;
+ }
+ }
+ if ( rMark.IsMarked() )
+ {
+ ScRange aRange;
+ rMark.GetMarkArea( aRange );
+ for (i=aRange.aStart.Tab(); i<=aRange.aEnd.Tab() && bEqual; i++)
+ if (pTab[i] && rMark.GetTableSelect(i))
+ {
+ pNewStyle = pTab[i]->GetAreaStyle( bFound,
+ aRange.aStart.Col(), aRange.aStart.Row(),
+ aRange.aEnd.Col(), aRange.aEnd.Row() );
+ if (bFound)
+ {
+ if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
+ bEqual = FALSE; // unterschiedliche
+ pStyle = pNewStyle;
+ }
+ }
+ }
+
+ return bEqual ? pStyle : NULL;
+}
+
+
+void ScDocument::StyleSheetChanged( const SfxStyleSheetBase* pStyleSheet, BOOL bRemoved,
+ OutputDevice* pDev,
+ double nPPTX, double nPPTY,
+ const Fraction& rZoomX, const Fraction& rZoomY )
+{
+ for (USHORT i=0; i <= MAXTAB; i++)
+ if (pTab[i])
+ pTab[i]->StyleSheetChanged
+ ( pStyleSheet, bRemoved, pDev, nPPTX, nPPTY, rZoomX, rZoomY );
+}
+
+
+BOOL ScDocument::IsStyleSheetUsed( const SfxStyleSheetBase& rStyle ) const
+{
+ BOOL bIsUsed = FALSE;
+
+ for ( USHORT i=0; (i<=MAXTAB) && !bIsUsed; i++ )
+ if ( pTab[i] )
+ bIsUsed = pTab[i]->IsStyleSheetUsed( rStyle );
+
+ return bIsUsed;
+}
+
+
+
+BOOL ScDocument::ApplyFlags( USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow,
+ const ScMarkData& rMark,
+ INT16 nFlags )
+{
+ BOOL bChanged = FALSE;
+ for (USHORT i=0; i <= MAXTAB; i++)
+ if (pTab[i])
+ if (rMark.GetTableSelect(i))
+ bChanged |= pTab[i]->ApplyFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags );
+ return bChanged;
+}
+
+
+BOOL ScDocument::ApplyFlagsTab( USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow, USHORT nTab, INT16 nFlags )
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ return pTab[nTab]->ApplyFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags );
+
+ DBG_ERROR("ApplyFlags: falsche Tabelle");
+ return FALSE;
+}
+
+
+BOOL ScDocument::RemoveFlags( USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow,
+ const ScMarkData& rMark,
+ INT16 nFlags )
+{
+ BOOL bChanged = FALSE;
+ for (USHORT i=0; i <= MAXTAB; i++)
+ if (pTab[i])
+ if (rMark.GetTableSelect(i))
+ bChanged |= pTab[i]->RemoveFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags );
+ return bChanged;
+}
+
+
+BOOL ScDocument::RemoveFlagsTab( USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow, USHORT nTab, INT16 nFlags )
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ return pTab[nTab]->RemoveFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags );
+
+ DBG_ERROR("RemoveFlags: falsche Tabelle");
+ return FALSE;
+}
+
+
+void ScDocument::SetPattern( USHORT nCol, USHORT nRow, USHORT nTab, const ScPatternAttr& rAttr,
+ BOOL bPutToPool )
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ pTab[nTab]->SetPattern( nCol, nRow, rAttr, bPutToPool );
+}
+
+
+void ScDocument::SetPattern( const ScAddress& rPos, const ScPatternAttr& rAttr,
+ BOOL bPutToPool )
+{
+ USHORT nTab = rPos.Tab();
+ if (pTab[nTab])
+ pTab[nTab]->SetPattern( rPos, rAttr, bPutToPool );
+}
+
+
+ScPatternAttr* ScDocument::CreateSelectionPattern( const ScMarkData& rMark, BOOL bDeep )
+{
+ SfxItemSet* pSet = NULL;
+ USHORT i;
+
+ if ( rMark.IsMultiMarked() ) // multi selection
+ {
+ for (i=0; i<=MAXTAB; i++)
+ if (pTab[i] && rMark.GetTableSelect(i))
+ pTab[i]->MergeSelectionPattern( &pSet, rMark, bDeep );
+ }
+ if ( rMark.IsMarked() ) // simle selection
+ {
+ ScRange aRange;
+ rMark.GetMarkArea(aRange);
+ for (i=0; i<=MAXTAB; i++)
+ if (pTab[i] && rMark.GetTableSelect(i))
+ pTab[i]->MergePatternArea( &pSet,
+ aRange.aStart.Col(), aRange.aStart.Row(),
+ aRange.aEnd.Col(), aRange.aEnd.Row(), bDeep );
+ }
+
+ DBG_ASSERT( pSet, "SelectionPattern Null" );
+ if (pSet)
+ return new ScPatternAttr( pSet );
+ else
+ return new ScPatternAttr( GetPool() ); // empty
+}
+
+
+const ScPatternAttr* ScDocument::GetSelectionPattern( const ScMarkData& rMark, BOOL bDeep )
+{
+ delete pSelectionAttr;
+ pSelectionAttr = CreateSelectionPattern( rMark, bDeep );
+ return pSelectionAttr;
+}
+
+
+void ScDocument::GetSelectionFrame( const ScMarkData& rMark,
+ SvxBoxItem& rLineOuter,
+ SvxBoxInfoItem& rLineInner )
+{
+ rLineOuter.SetLine(NULL, BOX_LINE_TOP);
+ rLineOuter.SetLine(NULL, BOX_LINE_BOTTOM);
+ rLineOuter.SetLine(NULL, BOX_LINE_LEFT);
+ rLineOuter.SetLine(NULL, BOX_LINE_RIGHT);
+ rLineOuter.SetDistance(0);
+
+ rLineInner.SetLine(NULL, BOXINFO_LINE_HORI);
+ rLineInner.SetLine(NULL, BOXINFO_LINE_VERT);
+ rLineInner.SetTable(TRUE);
+ rLineInner.SetDist((BOOL)FALSE);
+ rLineInner.SetMinDist(FALSE);
+
+ ScLineFlags aFlags;
+
+ if (rMark.IsMarked())
+ {
+ ScRange aRange;
+ rMark.GetMarkArea(aRange);
+ rLineInner.SetTable(aRange.aStart!=aRange.aEnd);
+ for (USHORT i=0; i<=MAXTAB; i++)
+ if (pTab[i] && rMark.GetTableSelect(i))
+ pTab[i]->MergeBlockFrame( &rLineOuter, &rLineInner, aFlags,
+ aRange.aStart.Col(), aRange.aStart.Row(),
+ aRange.aEnd.Col(), aRange.aEnd.Row() );
+ }
+
+ // Don't care Status auswerten
+
+ rLineInner.SetValid( VALID_LEFT, ( aFlags.nLeft != SC_LINE_DONTCARE ) );
+ rLineInner.SetValid( VALID_RIGHT, ( aFlags.nRight != SC_LINE_DONTCARE ) );
+ rLineInner.SetValid( VALID_TOP, ( aFlags.nTop != SC_LINE_DONTCARE ) );
+ rLineInner.SetValid( VALID_BOTTOM, ( aFlags.nBottom != SC_LINE_DONTCARE ) );
+ rLineInner.SetValid( VALID_HORI, ( aFlags.nHori != SC_LINE_DONTCARE ) );
+ rLineInner.SetValid( VALID_VERT, ( aFlags.nVert != SC_LINE_DONTCARE ) );
+}
+
+
+BOOL ScDocument::HasAttrib( USHORT nCol1, USHORT nRow1, USHORT nTab1,
+ USHORT nCol2, USHORT nRow2, USHORT nTab2, USHORT nMask )
+{
+ if ( nMask & HASATTR_ROTATE )
+ {
+ // Attribut im Dokument ueberhaupt verwendet?
+ // (wie in fillinfo)
+
+ BOOL bAnyItem = FALSE;
+ USHORT nRotCount = pDocPool->GetItemCount( ATTR_ROTATE_VALUE );
+ for (USHORT nItem=0; nItem<nRotCount; nItem++)
+ if (pDocPool->GetItem( ATTR_ROTATE_VALUE, nItem ))
+ {
+ bAnyItem = TRUE;
+ break;
+ }
+ if (!bAnyItem)
+ nMask &= ~ATTR_ROTATE_VALUE;
+ }
+
+ if (!nMask)
+ return FALSE;
+
+ BOOL bFound = FALSE;
+ for (USHORT i=nTab1; i<=nTab2 && !bFound; i++)
+ if (pTab[i])
+ bFound |= pTab[i]->HasAttrib( nCol1, nRow1, nCol2, nRow2, nMask );
+
+ return bFound;
+}
+
+BOOL ScDocument::HasAttrib( const ScRange& rRange, USHORT nMask )
+{
+ return HasAttrib( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
+ rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(),
+ nMask );
+}
+
+void ScDocument::FindMaxRotCol( USHORT nTab, RowInfo* pRowInfo, USHORT nArrCount,
+ USHORT nX1, USHORT nX2 ) const
+{
+ if ( nTab <= MAXTAB && pTab[nTab] )
+ pTab[nTab]->FindMaxRotCol( pRowInfo, nArrCount, nX1, nX2 );
+ else
+ DBG_ERRORFILE("FindMaxRotCol: falsche Tabelle");
+}
+
+BOOL ScDocument::HasLines( const ScRange& rRange, Rectangle& rSizes ) const
+{
+ USHORT nTab1 = rRange.aStart.Tab();
+ USHORT nTab2 = rRange.aEnd.Tab();
+ PutInOrder( nTab1, nTab2 );
+ BOOL bFound = FALSE;
+ rSizes = Rectangle(0,0,0,0);
+
+ for (USHORT i=nTab1; i<=nTab2; i++)
+ if (pTab[i])
+ if (pTab[i]->HasLines( rRange, rSizes ))
+ bFound = TRUE;
+
+ return bFound;
+}
+
+void ScDocument::GetBorderLines( USHORT nCol, USHORT nRow, USHORT nTab,
+ const SvxBorderLine** ppLeft, const SvxBorderLine** ppTop,
+ const SvxBorderLine** ppRight, const SvxBorderLine** ppBottom ) const
+{
+ //! Seitengrenzen fuer Druck beruecksichtigen !!!!!
+
+ const SvxBoxItem* pThisAttr = (const SvxBoxItem*) GetEffItem( nCol, nRow, nTab, ATTR_BORDER );
+ DBG_ASSERT(pThisAttr,"wo ist das Attribut?");
+
+ const SvxBorderLine* pLeftLine = pThisAttr->GetLeft();
+ const SvxBorderLine* pTopLine = pThisAttr->GetTop();
+ const SvxBorderLine* pRightLine = pThisAttr->GetRight();
+ const SvxBorderLine* pBottomLine = pThisAttr->GetBottom();
+
+ if ( nCol > 0 )
+ {
+ const SvxBorderLine* pOther = ((const SvxBoxItem*)
+ GetEffItem( nCol-1, nRow, nTab, ATTR_BORDER ))->GetRight();
+ if ( HasPriority( pOther, pLeftLine ) )
+ pLeftLine = pOther;
+ }
+ if ( nRow > 0 )
+ {
+ const SvxBorderLine* pOther = ((const SvxBoxItem*)
+ GetEffItem( nCol, nRow-1, nTab, ATTR_BORDER ))->GetBottom();
+ if ( HasPriority( pOther, pTopLine ) )
+ pTopLine = pOther;
+ }
+ if ( nCol < MAXCOL )
+ {
+ const SvxBorderLine* pOther = ((const SvxBoxItem*)
+ GetEffItem( nCol+1, nRow, nTab, ATTR_BORDER ))->GetLeft();
+ if ( HasPriority( pOther, pRightLine ) )
+ pRightLine = pOther;
+ }
+ if ( nRow < MAXROW )
+ {
+ const SvxBorderLine* pOther = ((const SvxBoxItem*)
+ GetEffItem( nCol, nRow+1, nTab, ATTR_BORDER ))->GetTop();
+ if ( HasPriority( pOther, pBottomLine ) )
+ pBottomLine = pOther;
+ }
+
+ if (ppLeft)
+ *ppLeft = pLeftLine;
+ if (ppTop)
+ *ppTop = pTopLine;
+ if (ppRight)
+ *ppRight = pRightLine;
+ if (ppBottom)
+ *ppBottom = pBottomLine;
+}
+
+BOOL ScDocument::IsBlockEmpty( USHORT nTab, USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow ) const
+{
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ return pTab[nTab]->IsBlockEmpty( nStartCol, nStartRow, nEndCol, nEndRow );
+
+ DBG_ERROR("Falsche Tabellennummer");
+ return FALSE;
+}
+
+
+void ScDocument::LockTable(USHORT nTab)
+{
+ if ( nTab <= MAXTAB && pTab[nTab] )
+ pTab[nTab]->LockTable();
+ else
+ DBG_ERROR("Falsche Tabellennummer");
+}
+
+
+void ScDocument::UnlockTable(USHORT nTab)
+{
+ if ( nTab <= MAXTAB && pTab[nTab] )
+ pTab[nTab]->UnlockTable();
+ else
+ DBG_ERROR("Falsche Tabellennummer");
+}
+
+
+BOOL ScDocument::IsBlockEditable( USHORT nTab, USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow,
+ BOOL* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
+{
+ if ( pShell && pShell->IsReadOnly() )
+ {
+ if ( pOnlyNotBecauseOfMatrix )
+ *pOnlyNotBecauseOfMatrix = FALSE;
+ return FALSE;
+ }
+
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ return pTab[nTab]->IsBlockEditable( nStartCol, nStartRow, nEndCol,
+ nEndRow, pOnlyNotBecauseOfMatrix );
+
+ DBG_ERROR("Falsche Tabellennummer");
+ if ( pOnlyNotBecauseOfMatrix )
+ *pOnlyNotBecauseOfMatrix = FALSE;
+ return FALSE;
+}
+
+
+BOOL ScDocument::IsSelectedBlockEditable( USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow,
+ const ScMarkData& rMark ) const
+{
+ if ( pShell && pShell->IsReadOnly() )
+ return FALSE;
+
+ BOOL bOk = TRUE;
+ for (USHORT i=0; i<=MAXTAB && bOk; i++)
+ if (pTab[i])
+ if (rMark.GetTableSelect(i))
+ if (!pTab[i]->IsBlockEditable( nStartCol, nStartRow, nEndCol, nEndRow ))
+ bOk = FALSE;
+
+ return bOk;
+}
+
+
+BOOL ScDocument::IsSelectionEditable( const ScMarkData& rMark,
+ BOOL* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
+{
+ if ( pShell && pShell->IsReadOnly() )
+ {
+ if ( pOnlyNotBecauseOfMatrix )
+ *pOnlyNotBecauseOfMatrix = FALSE;
+ return FALSE;
+ }
+
+ ScRange aRange;
+ rMark.GetMarkArea(aRange);
+
+ BOOL bOk = TRUE;
+ BOOL bMatrix = ( pOnlyNotBecauseOfMatrix != NULL );
+ for ( USHORT i=0; i<=MAXTAB && (bOk || bMatrix); i++ )
+ {
+ if ( pTab[i] && rMark.GetTableSelect(i) )
+ {
+ if (rMark.IsMarked())
+ {
+ if ( !pTab[i]->IsBlockEditable( aRange.aStart.Col(),
+ aRange.aStart.Row(), aRange.aEnd.Col(),
+ aRange.aEnd.Row(), pOnlyNotBecauseOfMatrix ) )
+ {
+ bOk = FALSE;
+ if ( pOnlyNotBecauseOfMatrix )
+ bMatrix = *pOnlyNotBecauseOfMatrix;
+ }
+ }
+ if (rMark.IsMultiMarked())
+ {
+ if ( !pTab[i]->IsSelectionEditable( rMark, pOnlyNotBecauseOfMatrix ) )
+ {
+ bOk = FALSE;
+ if ( pOnlyNotBecauseOfMatrix )
+ bMatrix = *pOnlyNotBecauseOfMatrix;
+ }
+ }
+ }
+ }
+
+ if ( pOnlyNotBecauseOfMatrix )
+ *pOnlyNotBecauseOfMatrix = ( !bOk && bMatrix );
+
+ return bOk;
+}
+
+
+BOOL ScDocument::IsSelectionOrBlockEditable( USHORT nTab, USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow,
+ const ScMarkData& rMark ) const
+{
+ if ( pShell && pShell->IsReadOnly() )
+ return FALSE;
+
+ BOOL bOk = TRUE;
+ if (VALIDTAB(nTab))
+ {
+ if (pTab[nTab])
+ {
+ if (rMark.IsMarked())
+ {
+ ScRange aRange;
+ rMark.GetMarkArea(aRange);
+ bOk = pTab[nTab]->IsBlockEditable( aRange.aStart.Col(), aRange.aStart.Row(),
+ aRange.aEnd.Col(), aRange.aEnd.Row() );
+ }
+
+ if (bOk && rMark.IsMultiMarked())
+ bOk = pTab[nTab]->IsSelectionEditable( rMark );
+ if ( bOk && !rMark.IsMarked() && !rMark.IsMultiMarked() )
+ bOk = pTab[nTab]->IsBlockEditable( nStartCol, nStartRow, nEndCol, nEndRow );
+ return bOk;
+ }
+ }
+ DBG_ERROR("Falsche Tabellennummer");
+ return FALSE;
+}
+
+
+BOOL ScDocument::IsSelectedOrBlockEditable( USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow,
+ const ScMarkData& rMark ) const
+{
+ if ( pShell && pShell->IsReadOnly() )
+ return FALSE;
+
+ BOOL bOk = TRUE;
+ for (USHORT i=0; i<=MAXTAB && bOk; i++)
+ if (pTab[i])
+ if (rMark.GetTableSelect(i))
+ {
+ if (rMark.IsMarked())
+ {
+ ScRange aRange;
+ rMark.GetMarkArea(aRange);
+ bOk = pTab[i]->IsBlockEditable( aRange.aStart.Col(), aRange.aStart.Row(),
+ aRange.aEnd.Col(), aRange.aEnd.Row() );
+ }
+ if ( bOk && !rMark.IsMarked() )
+ bOk = pTab[i]->IsBlockEditable( nStartCol, nStartRow, nEndCol, nEndRow );
+ }
+
+ return bOk;
+}
+
+
+BOOL ScDocument::HasSelectedBlockMatrixFragment( USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow,
+ const ScMarkData& rMark ) const
+{
+ BOOL bOk = TRUE;
+ for (USHORT i=0; i<=MAXTAB && bOk; i++)
+ if (pTab[i])
+ if (rMark.GetTableSelect(i))
+ if (pTab[i]->HasBlockMatrixFragment( nStartCol, nStartRow, nEndCol, nEndRow ))
+ bOk = FALSE;
+
+ return !bOk;
+}
+
+
+BOOL ScDocument::ExtendOverlapped( USHORT& rStartCol, USHORT& rStartRow,
+ USHORT nEndCol, USHORT nEndRow, USHORT nTab )
+{
+ BOOL bFound = FALSE;
+ if ( ValidColRow(rStartCol,rStartRow) && ValidColRow(nEndCol,nEndRow) && nTab<=MAXTAB )
+ {
+ if (pTab[nTab])
+ {
+ USHORT nCol;
+ USHORT nOldCol = rStartCol;
+ USHORT nOldRow = rStartRow;
+ for (nCol=nOldCol; nCol<=nEndCol; nCol++)
+ while (((ScMergeFlagAttr*)GetAttr(nCol,rStartRow,nTab,ATTR_MERGE_FLAG))->
+ IsVerOverlapped())
+ --rStartRow;
+
+ //! weiterreichen ?
+
+ ScAttrArray* pAttrArray = pTab[nTab]->aCol[nOldCol].pAttrArray;
+ short nIndex;
+ pAttrArray->Search( nOldRow, nIndex );
+ USHORT nAttrPos = nOldRow;
+ while (nAttrPos<=nEndRow)
+ {
+ DBG_ASSERT( nIndex < (short) pAttrArray->nCount, "Falscher Index im AttrArray" );
+
+ if (((ScMergeFlagAttr&)pAttrArray->pData[nIndex].pPattern->
+ GetItem(ATTR_MERGE_FLAG)).IsHorOverlapped())
+ {
+ USHORT nLoopEndRow = Min( nEndRow, pAttrArray->pData[nIndex].nRow );
+ for (USHORT nAttrRow = nAttrPos; nAttrRow <= nLoopEndRow; nAttrRow++)
+ {
+ USHORT nTempCol = nOldCol;
+ do
+ --nTempCol;
+ while (((ScMergeFlagAttr*)GetAttr(nTempCol,nAttrRow,nTab,ATTR_MERGE_FLAG))
+ ->IsHorOverlapped());
+ if (nTempCol < rStartCol)
+ rStartCol = nTempCol;
+ }
+ }
+ nAttrPos = pAttrArray->pData[nIndex].nRow + 1;
+ ++nIndex;
+ }
+ }
+ }
+ else
+ DBG_ERROR("ExtendOverlapped: falscher Bereich");
+
+ return bFound;
+}
+
+
+BOOL ScDocument::ExtendMerge( USHORT nStartCol, USHORT nStartRow,
+ USHORT& rEndCol, USHORT& rEndRow,
+ USHORT nTab, BOOL bRefresh, BOOL bAttrs )
+{
+ BOOL bFound = FALSE;
+ if ( ValidColRow(nStartCol,nStartRow) && ValidColRow(rEndCol,rEndRow) && nTab<=MAXTAB )
+ {
+ if (pTab[nTab])
+ bFound = pTab[nTab]->ExtendMerge( nStartCol, nStartRow, rEndCol, rEndRow, bRefresh, bAttrs );
+
+ if (bRefresh)
+ RefreshAutoFilter( nStartCol, nStartRow, rEndCol, rEndRow, nTab );
+ }
+ else
+ DBG_ERROR("ExtendMerge: falscher Bereich");
+
+ return bFound;
+}
+
+
+BOOL ScDocument::ExtendMerge( ScRange& rRange, BOOL bRefresh, BOOL bAttrs )
+{
+ BOOL bFound = FALSE;
+ USHORT nStartTab = rRange.aStart.Tab();
+ USHORT nEndTab = rRange.aEnd.Tab();
+ USHORT nEndCol = rRange.aEnd.Col();
+ USHORT nEndRow = rRange.aEnd.Row();
+
+ PutInOrder( nStartTab, nEndTab );
+ for (USHORT nTab = nStartTab; nTab <= nEndTab; nTab++ )
+ {
+ USHORT nExtendCol = rRange.aEnd.Col();
+ USHORT nExtendRow = rRange.aEnd.Row();
+ if (ExtendMerge( rRange.aStart.Col(), rRange.aStart.Row(),
+ nExtendCol, nExtendRow,
+ nTab, bRefresh, bAttrs ) )
+ {
+ bFound = TRUE;
+ if (nExtendCol > nEndCol) nEndCol = nExtendCol;
+ if (nExtendRow > nEndRow) nEndRow = nExtendRow;
+ }
+ }
+
+ rRange.aEnd.SetCol(nEndCol);
+ rRange.aEnd.SetRow(nEndRow);
+
+ return bFound;
+}
+
+BOOL ScDocument::ExtendTotalMerge( ScRange& rRange )
+{
+ // Bereich genau dann auf zusammengefasste Zellen erweitern, wenn
+ // dadurch keine neuen nicht-ueberdeckten Zellen getroffen werden
+
+ BOOL bRet = FALSE;
+ ScRange aExt = rRange;
+ if (ExtendMerge(aExt))
+ {
+ if ( aExt.aEnd.Row() > rRange.aEnd.Row() )
+ {
+ ScRange aTest = aExt;
+ aTest.aStart.SetRow( rRange.aEnd.Row() + 1 );
+ if ( HasAttrib( aTest, HASATTR_NOTOVERLAPPED ) )
+ aExt.aEnd.SetRow(rRange.aEnd.Row());
+ }
+ if ( aExt.aEnd.Col() > rRange.aEnd.Col() )
+ {
+ ScRange aTest = aExt;
+ aTest.aStart.SetCol( rRange.aEnd.Col() + 1 );
+ if ( HasAttrib( aTest, HASATTR_NOTOVERLAPPED ) )
+ aExt.aEnd.SetCol(rRange.aEnd.Col());
+ }
+
+ bRet = ( aExt.aEnd != rRange.aEnd );
+ rRange = aExt;
+ }
+ return bRet;
+}
+
+BOOL ScDocument::ExtendOverlapped( ScRange& rRange )
+{
+ BOOL bFound = FALSE;
+ USHORT nStartTab = rRange.aStart.Tab();
+ USHORT nEndTab = rRange.aEnd.Tab();
+ USHORT nStartCol = rRange.aStart.Col();
+ USHORT nStartRow = rRange.aStart.Row();
+
+ PutInOrder( nStartTab, nEndTab );
+ for (USHORT nTab = nStartTab; nTab <= nEndTab; nTab++ )
+ {
+ USHORT nExtendCol = rRange.aStart.Col();
+ USHORT nExtendRow = rRange.aStart.Row();
+ ExtendOverlapped( nExtendCol, nExtendRow,
+ rRange.aEnd.Col(), rRange.aEnd.Row(), nTab );
+ if (nExtendCol < nStartCol)
+ {
+ nStartCol = nExtendCol;
+ bFound = TRUE;
+ }
+ if (nExtendRow < nStartRow)
+ {
+ nStartRow = nExtendRow;
+ bFound = TRUE;
+ }
+ }
+
+ rRange.aStart.SetCol(nStartCol);
+ rRange.aStart.SetRow(nStartRow);
+
+ return bFound;
+}
+
+BOOL ScDocument::RefreshAutoFilter( USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow, USHORT nTab )
+{
+ USHORT nCount = pDBCollection->GetCount();
+ USHORT i;
+ ScDBData* pData;
+ USHORT nDBTab;
+ USHORT nDBStartCol;
+ USHORT nDBStartRow;
+ USHORT nDBEndCol;
+ USHORT nDBEndRow;
+
+ // Autofilter loeschen
+
+ BOOL bChange = RemoveFlagsTab( nStartCol,nStartRow, nEndCol,nEndRow, nTab, SC_MF_AUTO );
+
+ // Autofilter setzen
+
+ for (i=0; i<nCount; i++)
+ {
+ pData = (*pDBCollection)[i];
+ if (pData->HasAutoFilter())
+ {
+ pData->GetArea( nDBTab, nDBStartCol,nDBStartRow, nDBEndCol,nDBEndRow );
+ if ( nDBTab==nTab && nDBStartRow<=nEndRow && nDBEndRow>=nStartRow &&
+ nDBStartCol<=nEndCol && nDBEndCol>=nStartCol )
+ {
+ if (ApplyFlagsTab( nDBStartCol,nDBStartRow, nDBEndCol,nDBStartRow,
+ nDBTab, SC_MF_AUTO ))
+ bChange = TRUE;
+ }
+ }
+ }
+ return bChange;
+}
+
+
+void ScDocument::SetAutoFilterFlags()
+{
+ USHORT nCount = pDBCollection->GetCount();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScDBData* pData = (*pDBCollection)[i];
+ USHORT nDBTab;
+ USHORT nDBStartCol;
+ USHORT nDBStartRow;
+ USHORT nDBEndCol;
+ USHORT nDBEndRow;
+ pData->GetArea( nDBTab, nDBStartCol,nDBStartRow, nDBEndCol,nDBEndRow );
+ pData->SetAutoFilter( HasAttrib( nDBStartCol,nDBStartRow,nDBTab,
+ nDBEndCol,nDBStartRow,nDBTab, HASATTR_AUTOFILTER ) );
+ }
+}
+
+
+BOOL ScDocument::IsOverlapped( USHORT nCol, USHORT nRow, USHORT nTab ) const
+{
+ const ScMergeFlagAttr* pAttr = (const ScMergeFlagAttr*)
+ GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG );
+ if (pAttr)
+ return pAttr->IsOverlapped();
+ else
+ {
+ DBG_ERROR("Overlapped: Attr==0");
+ return FALSE;
+ }
+}
+
+
+BOOL ScDocument::IsHorOverlapped( USHORT nCol, USHORT nRow, USHORT nTab ) const
+{
+ const ScMergeFlagAttr* pAttr = (const ScMergeFlagAttr*)
+ GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG );
+ if (pAttr)
+ return pAttr->IsHorOverlapped();
+ else
+ {
+ DBG_ERROR("Overlapped: Attr==0");
+ return FALSE;
+ }
+}
+
+
+BOOL ScDocument::IsVerOverlapped( USHORT nCol, USHORT nRow, USHORT nTab ) const
+{
+ const ScMergeFlagAttr* pAttr = (const ScMergeFlagAttr*)
+ GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG );
+ if (pAttr)
+ return pAttr->IsVerOverlapped();
+ else
+ {
+ DBG_ERROR("Overlapped: Attr==0");
+ return FALSE;
+ }
+}
+
+
+void ScDocument::ApplySelectionFrame( const ScMarkData& rMark,
+ const SvxBoxItem* pLineOuter,
+ const SvxBoxInfoItem* pLineInner )
+{
+ if (rMark.IsMarked())
+ {
+ ScRange aRange;
+ rMark.GetMarkArea(aRange);
+ for (USHORT i=0; i<=MAXTAB; i++)
+ if (pTab[i])
+ if (rMark.GetTableSelect(i))
+ pTab[i]->ApplyBlockFrame( pLineOuter, pLineInner,
+ aRange.aStart.Col(), aRange.aStart.Row(),
+ aRange.aEnd.Col(), aRange.aEnd.Row() );
+ }
+}
+
+
+void ScDocument::ApplySelectionPattern( const ScPatternAttr& rAttr, const ScMarkData& rMark )
+{
+ const SfxItemSet* pSet = &rAttr.GetItemSet();
+ BOOL bSet = FALSE;
+ USHORT i;
+ for (i=ATTR_PATTERN_START; i<=ATTR_PATTERN_END && !bSet; i++)
+ if (pSet->GetItemState(i) == SFX_ITEM_SET)
+ bSet = TRUE;
+
+ if (bSet)
+ {
+ // ApplySelectionCache needs multi mark
+ if ( rMark.IsMarked() && !rMark.IsMultiMarked() )
+ {
+ ScRange aRange;
+ rMark.GetMarkArea( aRange );
+ ApplyPatternArea( aRange.aStart.Col(), aRange.aStart.Row(),
+ aRange.aEnd.Col(), aRange.aEnd.Row(), rMark, rAttr );
+ }
+ else
+ {
+ SfxItemPoolCache aCache( pDocPool, pSet );
+ for (USHORT i=0; i<=MAXTAB; i++)
+ if (pTab[i])
+ if (rMark.GetTableSelect(i))
+ pTab[i]->ApplySelectionCache( &aCache, rMark );
+ }
+ }
+}
+
+
+void ScDocument::ChangeSelectionIndent( BOOL bIncrement, const ScMarkData& rMark )
+{
+ for (USHORT i=0; i<=MAXTAB; i++)
+ if (pTab[i] && rMark.GetTableSelect(i))
+ pTab[i]->ChangeSelectionIndent( bIncrement, rMark );
+}
+
+
+void ScDocument::ClearSelectionItems( const USHORT* pWhich, const ScMarkData& rMark )
+{
+ for (USHORT i=0; i<=MAXTAB; i++)
+ if (pTab[i] && rMark.GetTableSelect(i))
+ pTab[i]->ClearSelectionItems( pWhich, rMark );
+}
+
+
+void ScDocument::DeleteSelection( USHORT nDelFlag, const ScMarkData& rMark )
+{
+ for (USHORT i=0; i<=MAXTAB; i++)
+ if (pTab[i] && rMark.GetTableSelect(i))
+ pTab[i]->DeleteSelection( nDelFlag, rMark );
+}
+
+
+void ScDocument::DeleteSelectionTab( USHORT nTab, USHORT nDelFlag, const ScMarkData& rMark )
+{
+ if (nTab <= MAXTAB && pTab[nTab])
+ pTab[nTab]->DeleteSelection( nDelFlag, rMark );
+ else
+ DBG_ERROR("Falsche Tabelle");
+}
+
+
+ScPatternAttr* ScDocument::GetDefPattern() const
+{
+ return (ScPatternAttr*) &pDocPool->GetDefaultItem(ATTR_PATTERN);
+}
+
+
+ScDocumentPool* ScDocument::GetPool()
+{
+ return pDocPool;
+}
+
+
+
+ScStyleSheetPool* ScDocument::GetStyleSheetPool() const
+{
+ return pStylePool;
+}
+
+
+USHORT ScDocument::GetEmptyLinesInBlock( USHORT nStartCol, USHORT nStartRow, USHORT nStartTab,
+ USHORT nEndCol, USHORT nEndRow, USHORT nEndTab, ScDirection eDir )
+{
+ PutInOrder(nStartCol, nEndCol);
+ PutInOrder(nStartRow, nEndRow);
+ PutInOrder(nStartTab, nEndTab);
+ if (VALIDTAB(nStartTab))
+ {
+ if (pTab[nStartTab])
+ return pTab[nStartTab]->GetEmptyLinesInBlock(nStartCol, nStartRow, nEndCol, nEndRow, eDir);
+ else
+ return 0;
+ }
+ else
+ return 0;
+}
+
+
+void ScDocument::FindAreaPos( USHORT& rCol, USHORT& rRow, USHORT nTab, short nMovX, short nMovY )
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ pTab[nTab]->FindAreaPos( rCol, rRow, nMovX, nMovY );
+}
+
+
+void ScDocument::GetNextPos( USHORT& rCol, USHORT& rRow, USHORT nTab, short nMovX, short nMovY,
+ BOOL bMarked, BOOL bUnprotected, const ScMarkData& rMark )
+{
+ DBG_ASSERT( !nMovX || !nMovY, "GetNextPos: nur X oder Y" );
+
+ ScMarkData aCopyMark = rMark;
+ aCopyMark.SetMarking(FALSE);
+ aCopyMark.MarkToMulti();
+
+ if (nTab<=MAXTAB && pTab[nTab])
+ pTab[nTab]->GetNextPos( rCol, rRow, nMovX, nMovY, bMarked, bUnprotected, aCopyMark );
+}
+
+//
+// Datei-Operationen
+//
+
+
+void ScDocument::UpdStlShtPtrsFrmNms()
+{
+ ScPatternAttr::pDoc = this;
+
+ USHORT nCount = pDocPool->GetItemCount(ATTR_PATTERN);
+ ScPatternAttr* pPattern;
+ for (USHORT i=0; i<nCount; i++)
+ {
+ pPattern = (ScPatternAttr*)pDocPool->GetItem(ATTR_PATTERN, i);
+ if (pPattern)
+ pPattern->UpdateStyleSheet();
+ }
+ ((ScPatternAttr&)pDocPool->GetDefaultItem(ATTR_PATTERN)).UpdateStyleSheet();
+}
+
+
+void ScDocument::StylesToNames()
+{
+ ScPatternAttr::pDoc = this;
+
+ USHORT nCount = pDocPool->GetItemCount(ATTR_PATTERN);
+ ScPatternAttr* pPattern;
+ for (USHORT i=0; i<nCount; i++)
+ {
+ pPattern = (ScPatternAttr*)pDocPool->GetItem(ATTR_PATTERN, i);
+ if (pPattern)
+ pPattern->StyleToName();
+ }
+ ((ScPatternAttr&)pDocPool->GetDefaultItem(ATTR_PATTERN)).StyleToName();
+}
+
+
+void lcl_RemoveMergeFromStyles( ScStyleSheetPool* pStylePool )
+{
+ pStylePool->SetSearchMask( SFX_STYLE_FAMILY_ALL );
+
+ USHORT nCount = pStylePool->Count();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ // in alten Versionen wurden statt SFXSTYLEBIT_USERDEF alle Bits gesetzt
+ SfxStyleSheetBase* pStyle = (*pStylePool)[i];
+ if ( pStyle->GetMask() & SFXSTYLEBIT_READONLY )
+ pStyle->SetMask( pStyle->GetMask() & ~SFXSTYLEBIT_READONLY );
+
+ SfxItemSet& rSet = pStyle->GetItemSet();
+ rSet.ClearItem( ATTR_MERGE );
+ rSet.ClearItem( ATTR_MERGE_FLAG );
+
+ // Das SvxBoxInfoItem wurde bis zur 358 falsch geladen, so dass
+ // Seitenvorlagen falsche Items mit bDist = FALSE enthalten koennen
+ if ( pStyle->GetFamily() == SFX_STYLE_FAMILY_PAGE )
+ {
+ const SvxBoxInfoItem& rPageInfo = (const SvxBoxInfoItem&)rSet.Get(ATTR_BORDER_INNER);
+ if ( !rPageInfo.IsDist() )
+ {
+ DBG_WARNING("altes SvxBoxInfoItem muss korrigiert werden");
+ SvxBoxInfoItem aNew( rPageInfo );
+ aNew.SetDist( TRUE );
+ rSet.Put( aNew );
+ }
+ // Das gilt fuer alle Hdr/Ftr-SetItems, darum kann das SetItem auch
+ // direkt im Pool geaendert werden (const weggecastet):
+ SfxItemSet& rHdrSet = ((SvxSetItem&)rSet.Get(ATTR_PAGE_HEADERSET)).GetItemSet();
+ const SvxBoxInfoItem& rHdrInfo = (const SvxBoxInfoItem&)rHdrSet.Get(ATTR_BORDER_INNER);
+ if ( !rHdrInfo.IsDist() )
+ {
+ DBG_WARNING("altes SvxBoxInfoItem muss korrigiert werden");
+ SvxBoxInfoItem aNew( rHdrInfo );
+ aNew.SetDist( TRUE );
+ rHdrSet.Put( aNew );
+ }
+ SfxItemSet& rFtrSet = ((SvxSetItem&)rSet.Get(ATTR_PAGE_FOOTERSET)).GetItemSet();
+ const SvxBoxInfoItem& rFtrInfo = (const SvxBoxInfoItem&)rFtrSet.Get(ATTR_BORDER_INNER);
+ if ( !rFtrInfo.IsDist() )
+ {
+ DBG_WARNING("altes SvxBoxInfoItem muss korrigiert werden");
+ SvxBoxInfoItem aNew( rFtrInfo );
+ aNew.SetDist( TRUE );
+ rFtrSet.Put( aNew );
+ }
+ const SfxUInt16Item& rScaleItem = (const SfxUInt16Item&)rSet.Get(ATTR_PAGE_SCALE);
+ USHORT nScale = rScaleItem.GetValue();
+ //! Extra-Konstanten fuer Seitenformat?
+ // 0 ist erlaubt (wird gesetzt bei Scale To Pages)
+ if ( nScale != 0 && ( nScale < MINZOOM || nScale > MAXZOOM ) )
+ {
+ // konnte anscheinend mal irgendwie kaputtgehen (#34508#)
+ DBG_WARNING("kaputter Zoom im Seitenformat muss korrigiert werden");
+ rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALE, 100 ) );
+ }
+ }
+ }
+}
+
+
+BOOL ScDocument::LoadPool( SvStream& rStream, BOOL bLoadRefCounts )
+{
+ // bLoadingDone wird beim Laden des StylePools (ScStyleSheet::GetItemSet) gebraucht
+ bLoadingDone = FALSE;
+
+ USHORT nOldBufSize = rStream.GetBufferSize();
+ rStream.SetBufferSize( 32768 );
+ CharSet eOldSet = rStream.GetStreamCharSet();
+
+ SetPrinter( NULL );
+
+ ScPatternAttr::pDoc = this;
+// pStylePool->Clear();
+// pDocPool->Cleanup();
+
+ ScDocument* pClipDoc = ScGlobal::GetClipDoc();
+ if (bOwner && !bIsClip && pClipDoc->pDocPool == pDocPool)
+ {
+ pClipDoc->bOwner = TRUE;
+ pStylePool->SetDocument(pClipDoc); // #67178# don't keep old document pointer
+ }
+ else
+ {
+ delete pStylePool;
+ delete pDocPool;
+ delete pFormTable;
+ delete pEditPool;
+ delete pEnginePool;
+ }
+ pFormTable = new SvNumberFormatter( ScGlobal::eLnge );
+ pFormTable->SetColorLink(&aColorLink);
+ pFormTable->SetEvalDateFormat( NF_EVALDATEFORMAT_INTL_FORMAT );
+ pDocPool = new ScDocumentPool( NULL, bLoadRefCounts );
+ pDocPool->FreezeIdRanges();
+ pDocPool->SetFileFormatVersion( (USHORT)rStream.GetVersion() );
+ pStylePool = new ScStyleSheetPool( *pDocPool, this );
+ pEditPool = EditEngine::CreatePool();
+ pEditPool->FreezeIdRanges();
+ pEnginePool = EditEngine::CreatePool();
+ pEnginePool->SetDefaultMetric( SFX_MAPUNIT_100TH_MM );
+ pEnginePool->FreezeIdRanges();
+
+ BOOL bStylesFound = FALSE;
+
+ BOOL bRet = FALSE;
+ USHORT nID;
+ rStream >> nID;
+ if (nID == SCID_POOLS || nID == SCID_NEWPOOLS)
+ {
+ ScReadHeader aHdr( rStream );
+ while (aHdr.BytesLeft())
+ {
+ USHORT nSubID;
+ rStream >> nSubID;
+ ScReadHeader aSubHdr( rStream );
+ switch (nSubID)
+ {
+ case SCID_CHARSET:
+ {
+ BYTE cSet, cGUI; // cGUI is dummy, old GUIType
+ rStream >> cGUI >> cSet;
+ eSrcSet = (CharSet) cSet;
+ rStream.SetStreamCharSet( eSrcSet );
+ }
+ break;
+ case SCID_DOCPOOL:
+ pDocPool->Load( rStream );
+ break;
+ case SCID_STYLEPOOL:
+ {
+ // StylePool konvertiert beim Laden selber
+ CharSet eOld = rStream.GetStreamCharSet();
+ rStream.SetStreamCharSet( gsl_getSystemTextEncoding() ); //! ???
+ pStylePool->Load( rStream );
+ rStream.SetStreamCharSet( eOld );
+ lcl_RemoveMergeFromStyles( pStylePool ); // setzt auch ReadOnly zurueck
+ bStylesFound = TRUE;
+ }
+ break;
+ case SCID_EDITPOOL :
+ pEditPool->Load( rStream );
+ break;
+ default:
+ DBG_ERROR("unbekannter Sub-Record in ScDocument::LoadPool");
+ }
+ }
+
+ UpdStlShtPtrsFrmNms();
+ bRet = TRUE;
+ }
+ else
+ DBG_ERROR("LoadPool: SCID_POOLS nicht gefunden");
+
+ if (!bStylesFound)
+ pStylePool->CreateStandardStyles();
+
+ rStream.SetStreamCharSet( eOldSet );
+ rStream.SetBufferSize( nOldBufSize );
+
+ bLoadingDone = TRUE;
+
+ // Das Uno-Objekt merkt sich einen Pointer auf den NumberFormatter
+ // -> mitteilen, dass der alte Pointer ungueltig geworden ist
+ BroadcastUno( ScPointerChangedHint(SC_POINTERCHANGED_NUMFMT) );
+
+ return bRet;
+}
+
+
+BOOL ScDocument::SavePool( SvStream& rStream ) const
+{
+ pDocPool->SetFileFormatVersion( (USHORT)rStream.GetVersion() );
+
+ USHORT nOldBufSize = rStream.GetBufferSize();
+ rStream.SetBufferSize( 32768 );
+ CharSet eOldSet = rStream.GetStreamCharSet();
+ rStream.SetStreamCharSet( gsl_getSystemTextEncoding() );
+
+ // Compress-Mode fuer Grafiken in Brush-Items (Hintergrund im Seitenformat)
+
+ USHORT nComprMode = rStream.GetCompressMode() & ~(COMPRESSMODE_ZBITMAP | COMPRESSMODE_NATIVE);
+ const SfxOptions& rOpt = SFX_APP()->GetOptions();
+ if ( rStream.GetVersion() >= SOFFICE_FILEFORMAT_40 && rOpt.IsSaveGraphicsCompressed() )
+ nComprMode |= COMPRESSMODE_ZBITMAP; // komprimiert ab 4.0
+ if ( rStream.GetVersion() > SOFFICE_FILEFORMAT_40 && rOpt.IsSaveOriginalGraphics() )
+ nComprMode |= COMPRESSMODE_NATIVE; // Originalformat ab 5.0
+ rStream.SetCompressMode( nComprMode );
+
+ {
+ rStream << (USHORT) SCID_NEWPOOLS;
+ ScWriteHeader aHdr( rStream );
+
+ {
+ rStream << (USHORT) SCID_CHARSET;
+ ScWriteHeader aSetHdr( rStream, 2 );
+ rStream << (BYTE) 0 // dummy, old System::GetGUIType()
+ << (BYTE) ::GetStoreCharSet( gsl_getSystemTextEncoding() );
+ }
+
+ {
+ rStream << (USHORT) SCID_DOCPOOL;
+ ScWriteHeader aDocPoolHdr( rStream );
+ pDocPool->Store( rStream );
+ }
+
+ {
+ rStream << (USHORT) SCID_STYLEPOOL;
+ ScWriteHeader aStylePoolHdr( rStream );
+ pStylePool->SetSearchMask( SFX_STYLE_FAMILY_ALL );
+
+ // Um bisherige 5.0 und 5.1 Versionen nicht durcheinander zu bringen,
+ // muss die Standardvorlage unter dem Namen "Standard" in der Datei
+ // stehen, weil bei UpdateStyleSheet sonst die Vorlage fuer das
+ // Default-PatternAttr nicht gefunden wird.
+
+ //! Fuer eine spaetere Dateiversion kann das wegfallen!
+
+ String aFileStdName = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(STRING_STANDARD));
+ if ( aFileStdName != ScGlobal::GetRscString(STR_STYLENAME_STANDARD) )
+ pStylePool->SetForceStdName( &aFileStdName );
+
+ pStylePool->Store( rStream, FALSE );
+
+ pStylePool->SetForceStdName( NULL );
+ }
+
+ if ( rStream.GetVersion() >= SOFFICE_FILEFORMAT_50 )
+ {
+ rStream << (USHORT) SCID_EDITPOOL;
+ ScWriteHeader aEditPoolHdr( rStream );
+ pEditPool->Store( rStream );
+ }
+ }
+
+ rStream.SetStreamCharSet( eOldSet );
+ rStream.SetBufferSize( nOldBufSize );
+ return TRUE;
+}
+
+
+long ScDocument::GetCellCount() const
+{
+ long nCellCount = 0L;
+
+ for ( USHORT nTab=0; nTab<=MAXTAB; nTab++ )
+ if ( pTab[nTab] )
+ nCellCount += pTab[nTab]->GetCellCount();
+
+ return nCellCount;
+}
+
+
+ULONG ScDocument::GetCodeCount() const
+{
+ ULONG nCodeCount = 0;
+
+ for ( USHORT nTab=0; nTab<=MAXTAB; nTab++ )
+ if ( pTab[nTab] )
+ nCodeCount += pTab[nTab]->GetCodeCount();
+
+ return nCodeCount;
+}
+
+
+long ScDocument::GetWeightedCount() const
+{
+ long nCellCount = 0L;
+
+ for ( USHORT nTab=0; nTab<=MAXTAB; nTab++ )
+ if ( pTab[nTab] )
+ nCellCount += pTab[nTab]->GetWeightedCount();
+
+ return nCellCount;
+}
+
+
+void ScDocument::PageStyleModified( USHORT nTab, const String& rNewName )
+{
+ if ( nTab <= MAXTAB && pTab[nTab] )
+ pTab[nTab]->PageStyleModified( rNewName );
+}
+
+
+void ScDocument::SetPageStyle( USHORT nTab, const String& rName )
+{
+ if ( nTab <= MAXTAB && pTab[nTab] )
+ pTab[nTab]->SetPageStyle( rName );
+}
+
+
+const String& ScDocument::GetPageStyle( USHORT nTab ) const
+{
+ if ( nTab <= MAXTAB && pTab[nTab] )
+ return pTab[nTab]->GetPageStyle();
+
+ return EMPTY_STRING;
+}
+
+
+void ScDocument::SetPageSize( USHORT nTab, const Size& rSize )
+{
+ if ( nTab <= MAXTAB && pTab[nTab] )
+ pTab[nTab]->SetPageSize( rSize );
+}
+
+Size ScDocument::GetPageSize( USHORT nTab ) const
+{
+ if ( nTab <= MAXTAB && pTab[nTab] )
+ return pTab[nTab]->GetPageSize();
+
+ DBG_ERROR("falsche Tab");
+ return Size();
+}
+
+
+void ScDocument::SetRepeatArea( USHORT nTab, USHORT nStartCol, USHORT nEndCol, USHORT nStartRow, USHORT nEndRow )
+{
+ if ( nTab <= MAXTAB && pTab[nTab] )
+ pTab[nTab]->SetRepeatArea( nStartCol, nEndCol, nStartRow, nEndRow );
+}
+
+
+void ScDocument::UpdatePageBreaks()
+{
+ for (USHORT i=0; i<=MAXTAB; i++)
+ if (pTab[i])
+ pTab[i]->UpdatePageBreaks( NULL );
+}
+
+
+void ScDocument::UpdatePageBreaks( USHORT nTab, const ScRange* pUserArea )
+{
+ if ( nTab <= MAXTAB && pTab[nTab] )
+ pTab[nTab]->UpdatePageBreaks( pUserArea );
+}
+
+void ScDocument::RemoveManualBreaks( USHORT nTab )
+{
+ if ( nTab <= MAXTAB && pTab[nTab] )
+ pTab[nTab]->RemoveManualBreaks();
+}
+
+BOOL ScDocument::HasManualBreaks( USHORT nTab ) const
+{
+ if ( nTab <= MAXTAB && pTab[nTab] )
+ return pTab[nTab]->HasManualBreaks();
+
+ DBG_ERROR("falsche Tab");
+ return FALSE;
+}
+
+
+void ScDocument::GetDocStat( ScDocStat& rDocStat )
+{
+ rDocStat.nTableCount = GetTableCount();
+ rDocStat.aDocName = aDocName;
+ rDocStat.nCellCount = GetCellCount();
+}
+
+
+BOOL ScDocument::HasPrintRange()
+{
+ BOOL bResult = FALSE;
+
+ for ( USHORT i=0; !bResult && i<nMaxTableNumber; i++ )
+ if ( pTab[i] )
+ bResult = ( pTab[i]->GetPrintRangeCount() > 0 );
+
+ return bResult;
+}
+
+
+USHORT ScDocument::GetPrintRangeCount( USHORT nTab )
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ return pTab[nTab]->GetPrintRangeCount();
+
+ return 0;
+}
+
+
+const ScRange* ScDocument::GetPrintRange( USHORT nTab, USHORT nPos )
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ return pTab[nTab]->GetPrintRange(nPos);
+
+ return NULL;
+}
+
+
+const ScRange* ScDocument::GetRepeatColRange( USHORT nTab )
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ return pTab[nTab]->GetRepeatColRange();
+
+ return NULL;
+}
+
+
+const ScRange* ScDocument::GetRepeatRowRange( USHORT nTab )
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ return pTab[nTab]->GetRepeatRowRange();
+
+ return NULL;
+}
+
+
+// #42845# zeroptimiert
+#if defined(WIN) && defined(MSC)
+#pragma optimize("",off)
+#endif
+void ScDocument::SetPrintRangeCount( USHORT nTab, USHORT nNew )
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ pTab[nTab]->SetPrintRangeCount( nNew );
+}
+#if defined(WIN) && defined(MSC)
+#pragma optimize("",on)
+#endif
+
+
+void ScDocument::SetPrintRange( USHORT nTab, USHORT nPos, const ScRange& rNew )
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ pTab[nTab]->SetPrintRange( nPos, rNew );
+}
+
+
+void ScDocument::SetRepeatColRange( USHORT nTab, const ScRange* pNew )
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ pTab[nTab]->SetRepeatColRange( pNew );
+}
+
+
+void ScDocument::SetRepeatRowRange( USHORT nTab, const ScRange* pNew )
+{
+ if (nTab<=MAXTAB && pTab[nTab])
+ pTab[nTab]->SetRepeatRowRange( pNew );
+}
+
+
+ScPrintRangeSaver* ScDocument::CreatePrintRangeSaver() const
+{
+ USHORT nCount = GetTableCount();
+ ScPrintRangeSaver* pNew = new ScPrintRangeSaver( nCount );
+ for (USHORT i=0; i<nCount; i++)
+ if (pTab[i])
+ pTab[i]->FillPrintSaver( pNew->GetTabData(i) );
+ return pNew;
+}
+
+
+void ScDocument::RestorePrintRanges( const ScPrintRangeSaver& rSaver )
+{
+ USHORT nCount = rSaver.GetTabCount();
+ for (USHORT i=0; i<nCount; i++)
+ if (pTab[i])
+ pTab[i]->RestorePrintRanges( rSaver.GetTabData(i) );
+}
+
+
+BOOL ScDocument::NeedPageResetAfterTab( USHORT nTab ) const
+{
+ // Die Seitennummern-Zaehlung fängt bei einer Tabelle neu an, wenn eine
+ // andere Vorlage als bei der vorherigen gesetzt ist (nur Namen vergleichen)
+ // und eine Seitennummer angegeben ist (nicht 0)
+
+ if ( nTab < MAXTAB && pTab[nTab] && pTab[nTab+1] )
+ {
+ String aNew = pTab[nTab+1]->GetPageStyle();
+ if ( aNew != pTab[nTab]->GetPageStyle() )
+ {
+ SfxStyleSheetBase* pStyle = pStylePool->Find( aNew, SFX_STYLE_FAMILY_PAGE );
+ if ( pStyle )
+ {
+ const SfxItemSet& rSet = pStyle->GetItemSet();
+ USHORT nFirst = ((const SfxUInt16Item&)rSet.Get(ATTR_PAGE_FIRSTPAGENO)).GetValue();
+ if ( nFirst != 0 )
+ return TRUE; // Seitennummer in neuer Vorlage angegeben
+ }
+ }
+ }
+
+ return FALSE; // sonst nicht
+}
+
+
+
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
new file mode 100644
index 000000000000..7b42c6906fe3
--- /dev/null
+++ b/sc/source/core/data/dpobject.cxx
@@ -0,0 +1,1718 @@
+/*************************************************************************
+ *
+ * $RCSfile: dpobject.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "dpobject.hxx"
+#include "dptabsrc.hxx"
+#include "dpsave.hxx"
+#include "dpoutput.hxx"
+#include "dpshttab.hxx"
+#include "dpsdbtab.hxx"
+#include "document.hxx"
+#include "rechead.hxx"
+#include "pivot.hxx" // PIVOT_DATA_FIELD
+#include "dapiuno.hxx" // ScDataPilotConversion
+#include "miscuno.hxx"
+#include "scerrors.hxx"
+#include "refupdat.hxx"
+
+#include <com/sun/star/sheet/GeneralFunction.hpp>
+#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/container/XContentEnumerationAccess.hpp>
+
+#include <unotools/processfactory.hxx>
+#include <tools/debug.hxx>
+#include <svtools/zforlist.hxx> // IsNumberFormat
+#include <vos/xception.hxx>
+
+using namespace com::sun::star;
+
+// -----------------------------------------------------------------------
+
+#define MAX_LABELS 256 //!!! from fieldwnd.hxx, must be moved to global.hxx
+
+// -----------------------------------------------------------------------
+
+#define SCDPSOURCE_SERVICE "com.sun.star.sheet.DataPilotSource"
+
+// -----------------------------------------------------------------------
+
+// incompatible versions of data pilot files
+#define SC_DP_VERSION_CURRENT 6
+
+// type of source data
+#define SC_DP_SOURCE_SHEET 0
+#define SC_DP_SOURCE_DATABASE 1
+#define SC_DP_SOURCE_SERVICE 2
+
+// -----------------------------------------------------------------------
+
+//! move to a header file
+#define DP_PROP_COLUMNGRAND "ColumnGrand"
+#define DP_PROP_FUNCTION "Function"
+#define DP_PROP_IGNOREEMPTY "IgnoreEmptyRows"
+#define DP_PROP_ISDATALAYOUT "IsDataLayoutDimension"
+//#define DP_PROP_ISVISIBLE "IsVisible"
+#define DP_PROP_ORIENTATION "Orientation"
+#define DP_PROP_ORIGINAL "Original"
+#define DP_PROP_POSITION "Position"
+#define DP_PROP_REPEATIFEMPTY "RepeatIfEmpty"
+#define DP_PROP_ROWGRAND "RowGrand"
+#define DP_PROP_SHOWDETAILS "ShowDetails"
+#define DP_PROP_SHOWEMPTY "ShowEmpty"
+#define DP_PROP_SUBTOTALS "SubTotals"
+#define DP_PROP_USEDHIERARCHY "UsedHierarchy"
+
+// -----------------------------------------------------------------------
+
+USHORT lcl_GetDataGetOrientation( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
+{
+ long nRet = sheet::DataPilotFieldOrientation_HIDDEN;
+ if ( xSource.is() )
+ {
+ uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
+ uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
+ long nIntCount = xIntDims->getCount();
+ BOOL bFound = FALSE;
+ for (long nIntDim=0; nIntDim<nIntCount && !bFound; nIntDim++)
+ {
+ uno::Reference<uno::XInterface> xIntDim =
+ ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
+ uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
+ if ( xDimProp.is() )
+ {
+ bFound = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
+ rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT) );
+ //! error checking -- is "IsDataLayoutDimension" property required??
+ if (bFound)
+ nRet = ScUnoHelpFunctions::GetEnumProperty(
+ xDimProp, rtl::OUString::createFromAscii(DP_PROP_ORIENTATION),
+ sheet::DataPilotFieldOrientation_HIDDEN );
+ }
+ }
+ }
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+ScDPObject::ScDPObject( ScDocument* pD ) :
+ pDoc( pD ),
+ bAlive( FALSE ),
+ pSaveData( NULL ),
+ pSheetDesc( NULL ),
+ pImpDesc( NULL ),
+ pServDesc( NULL ),
+ pOutput( NULL ),
+ bSettingsChanged( FALSE )
+{
+}
+
+ScDPObject::ScDPObject(const ScDPObject& r) :
+ pDoc( r.pDoc ),
+ bAlive( FALSE ),
+ pSaveData( NULL ),
+ aTableName( r.aTableName ),
+ aTableTag( r.aTableTag ),
+ aOutRange( r.aOutRange ),
+ pSheetDesc( NULL ),
+ pImpDesc( NULL ),
+ pServDesc( NULL ),
+ pOutput( NULL ),
+ bSettingsChanged( FALSE )
+{
+ if (r.pSaveData)
+ pSaveData = new ScDPSaveData(*r.pSaveData);
+ if (r.pSheetDesc)
+ pSheetDesc = new ScSheetSourceDesc(*r.pSheetDesc);
+ if (r.pImpDesc)
+ pImpDesc = new ScImportSourceDesc(*r.pImpDesc);
+ if (r.pServDesc)
+ pServDesc = new ScDPServiceDesc(*r.pServDesc);
+ // xSource (and pOutput) is not copied
+}
+
+ScDPObject::~ScDPObject()
+{
+ delete pOutput;
+ delete pSaveData;
+ delete pSheetDesc;
+ delete pImpDesc;
+ delete pServDesc;
+}
+
+DataObject* ScDPObject::Clone() const
+{
+ return new ScDPObject(*this);
+}
+
+void ScDPObject::SetAlive(BOOL bSet)
+{
+ bAlive = bSet;
+}
+
+void ScDPObject::SetSaveData(const ScDPSaveData& rData)
+{
+ delete pSaveData;
+ pSaveData = new ScDPSaveData( rData );
+
+ InvalidateData(); // re-init source from SaveData
+}
+
+void ScDPObject::SetOutRange(const ScRange& rRange)
+{
+ aOutRange = rRange;
+
+ if ( pOutput )
+ pOutput->SetPosition( rRange.aStart );
+}
+
+void ScDPObject::SetSheetDesc(const ScSheetSourceDesc& rDesc)
+{
+ if ( pSheetDesc && rDesc == *pSheetDesc )
+ return; // nothing to do
+
+ DELETEZ( pImpDesc );
+ DELETEZ( pServDesc );
+
+ delete pImpDesc;
+ pSheetDesc = new ScSheetSourceDesc(rDesc);
+
+ // make valid QueryParam
+
+ pSheetDesc->aQueryParam.nCol1 = pSheetDesc->aSourceRange.aStart.Col();
+ pSheetDesc->aQueryParam.nRow1 = pSheetDesc->aSourceRange.aStart.Row();
+ pSheetDesc->aQueryParam.nCol2 = pSheetDesc->aSourceRange.aEnd.Col();
+ pSheetDesc->aQueryParam.nRow2 = pSheetDesc->aSourceRange.aEnd.Row();;
+ pSheetDesc->aQueryParam.bHasHeader = TRUE;
+ USHORT nCount = pSheetDesc->aQueryParam.GetEntryCount();
+ for (USHORT i=0; (i<nCount) && (pSheetDesc->aQueryParam.GetEntry(i).bDoQuery); i++)
+ {
+ ScQueryEntry& rEntry = pSheetDesc->aQueryParam.GetEntry(i);
+ ULONG nIndex = 0;
+ rEntry.bQueryByString =
+ !(pDoc->GetFormatTable()->
+ IsNumberFormat(*rEntry.pStr, nIndex, rEntry.nVal));
+ }
+
+ InvalidateSource(); // new source must be created
+}
+
+void ScDPObject::SetImportDesc(const ScImportSourceDesc& rDesc)
+{
+ if ( pImpDesc && rDesc == *pImpDesc )
+ return; // nothing to do
+
+ DELETEZ( pSheetDesc );
+ DELETEZ( pServDesc );
+
+ delete pImpDesc;
+ pImpDesc = new ScImportSourceDesc(rDesc);
+
+ InvalidateSource(); // new source must be created
+}
+
+void ScDPObject::SetServiceData(const ScDPServiceDesc& rDesc)
+{
+ if ( pServDesc && rDesc == *pServDesc )
+ return; // nothing to do
+
+ DELETEZ( pSheetDesc );
+ DELETEZ( pImpDesc );
+
+ delete pServDesc;
+ pServDesc = new ScDPServiceDesc(rDesc);
+
+ InvalidateSource(); // new source must be created
+}
+
+void ScDPObject::WriteSourceDataTo( ScDPObject& rDest ) const
+{
+ if ( pSheetDesc )
+ rDest.SetSheetDesc( *pSheetDesc );
+ else if ( pImpDesc )
+ rDest.SetImportDesc( *pImpDesc );
+ else if ( pServDesc )
+ rDest.SetServiceData( *pServDesc );
+
+ // name/tag are not source data, but needed along with source data
+
+ rDest.aTableName = aTableName;
+ rDest.aTableTag = aTableTag;
+}
+
+BOOL ScDPObject::IsSheetData() const
+{
+ return ( pSheetDesc != NULL );
+}
+
+void ScDPObject::SetName(const String& rNew)
+{
+ aTableName = rNew;
+}
+
+void ScDPObject::SetTag(const String& rNew)
+{
+ aTableTag = rNew;
+}
+
+uno::Reference<sheet::XDimensionsSupplier> ScDPObject::GetSource()
+{
+ CreateObjects();
+ return xSource;
+}
+
+void ScDPObject::CreateOutput()
+{
+ CreateObjects();
+ if (!pOutput)
+ pOutput = new ScDPOutput( pDoc, xSource, aOutRange.aStart, IsSheetData() );
+}
+
+void ScDPObject::CreateObjects()
+{
+ if (!xSource.is())
+ {
+ //! cache DPSource and/or Output?
+
+ DBG_ASSERT( bAlive, "CreateObjects on non-inserted DPObject" );
+
+ DELETEZ( pOutput ); // not valid when xSource is changed
+
+ if ( pImpDesc )
+ {
+ ScDatabaseDPData* pData = new ScDatabaseDPData( *pImpDesc );
+ xSource = new ScDPSource( pData );
+ }
+ else if ( pServDesc )
+ {
+ xSource = CreateSource( *pServDesc );
+ }
+
+ if ( !xSource.is() ) // sheet data or error in above cases
+ {
+ DBG_ASSERT( !pImpDesc && !pServDesc, "DPSource could not be created" );
+ if (!pSheetDesc)
+ {
+ DBG_ERROR("no source descriptor");
+ pSheetDesc = new ScSheetSourceDesc; // dummy defaults
+ }
+ ScSheetDPData* pData = new ScSheetDPData( pDoc, *pSheetDesc );
+ xSource = new ScDPSource( pData );
+ }
+
+ if (pSaveData)
+ pSaveData->WriteToSource( xSource );
+ }
+ else if (bSettingsChanged)
+ {
+ DELETEZ( pOutput ); // not valid when xSource is changed
+
+ uno::Reference<util::XRefreshable> xRef( xSource, uno::UNO_QUERY );
+ if (xRef.is())
+ {
+ TRY
+ {
+ xRef->refresh();
+ }
+ CATCH_ALL()
+ {
+ DBG_ERROR("exception in refresh");
+ }
+ END_CATCH
+ }
+
+ if (pSaveData)
+ pSaveData->WriteToSource( xSource );
+ }
+ bSettingsChanged = FALSE;
+}
+
+void ScDPObject::InvalidateData()
+{
+ bSettingsChanged = TRUE;
+}
+
+void ScDPObject::InvalidateSource()
+{
+ xSource = NULL;
+}
+
+ScRange ScDPObject::GetNewOutputRange()
+{
+ CreateOutput(); // create xSource and pOutput if not already done
+
+ // don't store the result in aOutRange, because nothing has been output yet
+ return pOutput->GetOutputRange();
+}
+
+void ScDPObject::Output()
+{
+ // clear old output area
+ pDoc->DeleteAreaTab( aOutRange.aStart.Col(), aOutRange.aStart.Row(),
+ aOutRange.aEnd.Col(), aOutRange.aEnd.Row(),
+ aOutRange.aStart.Tab(), IDF_ALL );
+
+ CreateOutput(); // create xSource and pOutput if not already done
+
+ pOutput->Output();
+
+ // aOutRange is always the range that was last output to the document
+ aOutRange = pOutput->GetOutputRange();
+}
+
+void ScDPObject::UpdateReference( UpdateRefMode eUpdateRefMode,
+ const ScRange& rRange, short nDx, short nDy, short nDz )
+{
+ // Output area
+
+ USHORT nCol1 = aOutRange.aStart.Col();
+ USHORT nRow1 = aOutRange.aStart.Row();
+ USHORT nTab1 = aOutRange.aStart.Tab();
+ USHORT nCol2 = aOutRange.aEnd.Col();
+ USHORT nRow2 = aOutRange.aEnd.Row();
+ USHORT nTab2 = aOutRange.aEnd.Tab();
+
+ ScRefUpdateRes eRes =
+ ScRefUpdate::Update( pDoc, eUpdateRefMode,
+ rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
+ rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(), nDx, nDy, nDz,
+ nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ if ( eRes != UR_NOTHING )
+ SetOutRange( ScRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ) );
+
+ // sheet source data
+
+ if ( pSheetDesc )
+ {
+ nCol1 = pSheetDesc->aSourceRange.aStart.Col();
+ nRow1 = pSheetDesc->aSourceRange.aStart.Row();
+ nTab1 = pSheetDesc->aSourceRange.aStart.Tab();
+ nCol2 = pSheetDesc->aSourceRange.aEnd.Col();
+ nRow2 = pSheetDesc->aSourceRange.aEnd.Row();
+ nTab2 = pSheetDesc->aSourceRange.aEnd.Tab();
+
+ eRes = ScRefUpdate::Update( pDoc, eUpdateRefMode,
+ rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
+ rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(), nDx, nDy, nDz,
+ nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ if ( eRes != UR_NOTHING )
+ {
+ ScSheetSourceDesc aNewDesc;
+ aNewDesc.aSourceRange = ScRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+
+ short nDiffX = nCol1 - (short) pSheetDesc->aSourceRange.aStart.Col();
+ short nDiffY = nRow1 - (short) pSheetDesc->aSourceRange.aStart.Row();
+
+ aNewDesc.aQueryParam = pSheetDesc->aQueryParam;
+ aNewDesc.aQueryParam.nCol1 += nDiffX;
+ aNewDesc.aQueryParam.nCol2 += nDiffX;
+ aNewDesc.aQueryParam.nRow1 += nDiffY; //! used?
+ aNewDesc.aQueryParam.nRow2 += nDiffY; //! used?
+ USHORT nEC = aNewDesc.aQueryParam.GetEntryCount();
+ for (USHORT i=0; i<nEC; i++)
+ if (aNewDesc.aQueryParam.GetEntry(i).bDoQuery)
+ aNewDesc.aQueryParam.GetEntry(i).nField += nDiffX;
+
+ SetSheetDesc( aNewDesc ); // allocates new pSheetDesc
+ }
+ }
+}
+
+BOOL ScDPObject::RefsEqual( const ScDPObject& r ) const
+{
+ if ( aOutRange != r.aOutRange )
+ return FALSE;
+
+ if ( pSheetDesc && r.pSheetDesc )
+ {
+ if ( pSheetDesc->aSourceRange != r.pSheetDesc->aSourceRange )
+ return FALSE;
+ }
+ else if ( pSheetDesc || r.pSheetDesc )
+ {
+ DBG_ERROR("RefsEqual: SheetDesc set at only one object");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void ScDPObject::WriteRefsTo( ScDPObject& r ) const
+{
+ r.SetOutRange( aOutRange );
+ if ( pSheetDesc )
+ r.SetSheetDesc( *pSheetDesc );
+}
+
+String ScDPObject::GetDimName( long nDim, BOOL& rIsDataLayout )
+{
+ rIsDataLayout = FALSE;
+ String aRet;
+
+ if ( xSource.is() )
+ {
+ uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
+ uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess( xDimsName );
+ long nDimCount = xDims->getCount();
+ if ( nDim < nDimCount )
+ {
+ uno::Reference<uno::XInterface> xIntDim =
+ ScUnoHelpFunctions::AnyToInterface( xDims->getByIndex(nDim) );
+ uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
+ uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
+ if ( xDimName.is() && xDimProp.is() )
+ {
+ BOOL bData = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
+ rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT) );
+ //! error checking -- is "IsDataLayoutDimension" property required??
+
+ rtl::OUString aName;
+ TRY
+ {
+ aName = xDimName->getName();
+ }
+ CATCH_ALL()
+ {
+ }
+ END_CATCH
+ if ( bData )
+ rIsDataLayout = TRUE;
+ else
+ aRet = String( aName );
+ }
+ }
+ }
+
+ return aRet;
+}
+
+void ScDPObject::GetPositionData( ScDPPositionData& rData, const ScAddress& rPos )
+{
+ CreateOutput(); // create xSource and pOutput if not already done
+
+ pOutput->GetPositionData( rData, rPos );
+}
+
+BOOL ScDPObject::IsFilterButton( const ScAddress& rPos )
+{
+ CreateOutput(); // create xSource and pOutput if not already done
+
+ return pOutput->IsFilterButton( rPos );
+}
+
+long ScDPObject::GetHeaderDim( const ScAddress& rPos )
+{
+ CreateOutput(); // create xSource and pOutput if not already done
+
+ return pOutput->GetHeaderDim( rPos );
+}
+
+BOOL ScDPObject::GetHeaderDrag( const ScAddress& rPos, BOOL bMouseLeft, BOOL bMouseTop, long nDragDim,
+ Rectangle& rPosRect, USHORT& rOrient, long& rDimPos )
+{
+ CreateOutput(); // create xSource and pOutput if not already done
+
+ return pOutput->GetHeaderDrag( rPos, bMouseLeft, bMouseTop, nDragDim, rPosRect, rOrient, rDimPos );
+}
+
+void ScDPObject::ToggleDetails( ScDPPositionData& rElemDesc, ScDPObject* pDestObj )
+{
+ CreateObjects(); // create xSource if not already done
+
+ // find dimension name
+
+ uno::Reference<container::XNamed> xDim;
+ uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
+ uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
+ long nIntCount = xIntDims->getCount();
+ if ( rElemDesc.nDimension < nIntCount )
+ {
+ uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface(
+ xIntDims->getByIndex(rElemDesc.nDimension) );
+ xDim = uno::Reference<container::XNamed>( xIntDim, uno::UNO_QUERY );
+ }
+ DBG_ASSERT( xDim.is(), "dimension not found" );
+ if ( !xDim.is() ) return;
+ String aDimName = xDim->getName();
+
+ uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
+ BOOL bDataLayout = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
+ rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT) );
+ if (bDataLayout)
+ {
+ // the elements of the data layout dimension can't be found by their names
+ // -> don't change anything
+ return;
+ }
+
+ // query old state
+
+ long nHierCount = 0;
+ uno::Reference<container::XIndexAccess> xHiers;
+ uno::Reference<sheet::XHierarchiesSupplier> xHierSupp( xDim, uno::UNO_QUERY );
+ if ( xHierSupp.is() )
+ {
+ uno::Reference<container::XNameAccess> xHiersName = xHierSupp->getHierarchies();
+ xHiers = new ScNameToIndexAccess( xHiersName );
+ nHierCount = xHiers->getCount();
+ }
+ uno::Reference<uno::XInterface> xHier;
+ if ( rElemDesc.nHierarchy < nHierCount )
+ xHier = ScUnoHelpFunctions::AnyToInterface( xHiers->getByIndex(rElemDesc.nHierarchy) );
+ DBG_ASSERT( xHier.is(), "hierarchy not found" );
+ if ( !xHier.is() ) return;
+
+ long nLevCount = 0;
+ uno::Reference<container::XIndexAccess> xLevels;
+ uno::Reference<sheet::XLevelsSupplier> xLevSupp( xHier, uno::UNO_QUERY );
+ if ( xLevSupp.is() )
+ {
+ uno::Reference<container::XNameAccess> xLevsName = xLevSupp->getLevels();
+ xLevels = new ScNameToIndexAccess( xLevsName );
+ nLevCount = xLevels->getCount();
+ }
+ uno::Reference<uno::XInterface> xLevel;
+ if ( rElemDesc.nLevel < nLevCount )
+ xLevel = ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex(rElemDesc.nLevel) );
+ DBG_ASSERT( xLevel.is(), "level not found" );
+ if ( !xLevel.is() ) return;
+
+ uno::Reference<container::XNameAccess> xMembers;
+ uno::Reference<sheet::XMembersSupplier> xMbrSupp( xLevel, uno::UNO_QUERY );
+ if ( xMbrSupp.is() )
+ xMembers = xMbrSupp->getMembers();
+
+ BOOL bFound = FALSE;
+ BOOL bShowDetails = TRUE;
+
+ if ( xMembers.is() )
+ {
+ rtl::OUString aName = rElemDesc.aMemberName;
+ if ( xMembers->hasByName( aName ) )
+ {
+ uno::Reference<uno::XInterface> xMemberInt = ScUnoHelpFunctions::AnyToInterface(
+ xMembers->getByName( aName ) );
+ uno::Reference<beans::XPropertySet> xMbrProp( xMemberInt, uno::UNO_QUERY );
+ if ( xMbrProp.is() )
+ {
+ bShowDetails = ScUnoHelpFunctions::GetBoolProperty( xMbrProp,
+ rtl::OUString::createFromAscii(DP_PROP_SHOWDETAILS) );
+ //! don't set bFound if property is unknown?
+ bFound = TRUE;
+ }
+ }
+ }
+
+ DBG_ASSERT( bFound, "member not found" );
+
+ //! use Hierarchy and Level in SaveData !!!!
+
+ // modify pDestObj if set, this object otherwise
+ ScDPSaveData* pModifyData = pDestObj ? ( pDestObj->pSaveData ) : pSaveData;
+ DBG_ASSERT( pModifyData, "no data?" );
+ if ( pModifyData )
+ {
+ pModifyData->GetDimensionByName(aDimName)->
+ GetMemberByName(rElemDesc.aMemberName)->SetShowDetails( !bShowDetails ); // toggle
+
+ if ( pDestObj )
+ pDestObj->InvalidateData(); // re-init source from SaveData
+ else
+ InvalidateData(); // re-init source from SaveData
+ }
+}
+
+long lcl_FindName( const rtl::OUString& rString, const uno::Reference<container::XNameAccess>& xCollection )
+{
+ if ( xCollection.is() )
+ {
+ uno::Sequence<rtl::OUString> aSeq = xCollection->getElementNames();
+ long nCount = aSeq.getLength();
+ const rtl::OUString* pArr = aSeq.getConstArray();
+ for (long nPos=0; nPos<nCount; nPos++)
+ if ( pArr[nPos] == rString )
+ return nPos;
+ }
+ return -1; // not found
+}
+
+USHORT lcl_FirstSubTotal( const uno::Reference<beans::XPropertySet>& xDimProp ) // PIVOT_FUNC mask
+{
+ uno::Reference<sheet::XHierarchiesSupplier> xDimSupp( xDimProp, uno::UNO_QUERY );
+ if ( xDimProp.is() && xDimSupp.is() )
+ {
+ uno::Reference<container::XIndexAccess> xHiers = new ScNameToIndexAccess( xDimSupp->getHierarchies() );
+ long nHierarchy = ScUnoHelpFunctions::GetLongProperty( xDimProp,
+ rtl::OUString::createFromAscii(DP_PROP_USEDHIERARCHY) );
+ if ( nHierarchy >= xHiers->getCount() )
+ nHierarchy = 0;
+
+ uno::Reference<uno::XInterface> xHier = ScUnoHelpFunctions::AnyToInterface(
+ xHiers->getByIndex(nHierarchy) );
+ uno::Reference<sheet::XLevelsSupplier> xHierSupp( xHier, uno::UNO_QUERY );
+ if ( xHierSupp.is() )
+ {
+ uno::Reference<container::XIndexAccess> xLevels = new ScNameToIndexAccess( xHierSupp->getLevels() );
+ uno::Reference<uno::XInterface> xLevel =
+ ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex( 0 ) );
+ uno::Reference<beans::XPropertySet> xLevProp( xLevel, uno::UNO_QUERY );
+ if ( xLevProp.is() )
+ {
+ uno::Any aSubAny;
+ TRY
+ {
+ aSubAny = xLevProp->getPropertyValue(
+ rtl::OUString::createFromAscii(DP_PROP_SUBTOTALS) );
+ }
+ CATCH_ALL()
+ {
+ }
+ END_CATCH
+ uno::Sequence<sheet::GeneralFunction> aSeq;
+ if ( aSubAny >>= aSeq )
+ {
+ USHORT nMask = 0;
+ const sheet::GeneralFunction* pArray = aSeq.getConstArray();
+ long nCount = aSeq.getLength();
+ for (long i=0; i<nCount; i++)
+ nMask |= ScDataPilotConversion::FunctionBit(pArray[i]);
+ return nMask;
+ }
+ }
+ }
+ }
+
+ DBG_ERROR("FirstSubTotal: NULL");
+ return 0;
+}
+
+USHORT lcl_CountBits( USHORT nBits )
+{
+ if (!nBits) return 0;
+
+ USHORT nCount = 0;
+ USHORT nMask = 1;
+ for (USHORT i=0; i<16; i++)
+ {
+ if ( nBits & nMask )
+ ++nCount;
+ nMask <<= 1;
+ }
+ return nCount;
+}
+
+USHORT lcl_FillOldFields( PivotField* pFields,
+ const uno::Reference<sheet::XDimensionsSupplier>& xSource,
+ USHORT nOrient, USHORT nColAdd, BOOL bAddData )
+{
+ USHORT nOutCount = 0;
+ BOOL bDataFound = FALSE;
+
+ //! merge multiple occurences (data field with different functions)
+ //! force data field in one dimension
+
+ long nPos[PIVOT_MAXFIELD];
+
+ uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
+ uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess( xDimsName );
+ long nDimCount = xDims->getCount();
+ for (long nDim=0; nDim < nDimCount && nOutCount < PIVOT_MAXFIELD; nDim++)
+ {
+ uno::Reference<uno::XInterface> xIntDim =
+ ScUnoHelpFunctions::AnyToInterface( xDims->getByIndex(nDim) );
+ uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
+ long nDimOrient = ScUnoHelpFunctions::GetEnumProperty(
+ xDimProp, rtl::OUString::createFromAscii(DP_PROP_ORIENTATION),
+ sheet::DataPilotFieldOrientation_HIDDEN );
+ if ( xDimProp.is() && nDimOrient == nOrient )
+ {
+ USHORT nMask = 0;
+ if ( nOrient == sheet::DataPilotFieldOrientation_DATA )
+ {
+ sheet::GeneralFunction eFunc = (sheet::GeneralFunction)ScUnoHelpFunctions::GetEnumProperty(
+ xDimProp, rtl::OUString::createFromAscii(DP_PROP_FUNCTION),
+ sheet::GeneralFunction_NONE );
+ if ( eFunc == sheet::GeneralFunction_AUTO )
+ {
+ //! test for numeric data
+ eFunc = sheet::GeneralFunction_SUM;
+ }
+ nMask = ScDataPilotConversion::FunctionBit(eFunc);
+ }
+ else
+ nMask = lcl_FirstSubTotal( xDimProp ); // from first hierarchy
+
+ BOOL bDataLayout = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
+ rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT) );
+ uno::Any aOrigAny;
+ TRY
+ {
+ aOrigAny = xDimProp->getPropertyValue(
+ rtl::OUString::createFromAscii(DP_PROP_ORIGINAL) );
+ }
+ CATCH_ALL()
+ {
+ }
+ END_CATCH
+
+ long nDupSource = -1;
+ uno::Reference<uno::XInterface> xIntOrig = ScUnoHelpFunctions::AnyToInterface( aOrigAny );
+ if ( xIntOrig.is() )
+ {
+ uno::Reference<container::XNamed> xNameOrig( xIntOrig, uno::UNO_QUERY );
+ if ( xNameOrig.is() )
+ nDupSource = lcl_FindName( xNameOrig->getName(), xDimsName );
+ }
+
+ BOOL bDupUsed = FALSE;
+ if ( nDupSource >= 0 )
+ {
+ // add function bit to previous entry
+
+ short nCompCol;
+ if ( bDataLayout )
+ nCompCol = PIVOT_DATA_FIELD;
+ else
+ nCompCol = (short)(nDupSource+nColAdd); //! seek source column from name
+
+ for (USHORT nOld=0; nOld<nOutCount; nOld++)
+ if ( pFields[nOld].nCol == nCompCol )
+ {
+ pFields[nOld].nFuncMask |= nMask;
+ pFields[nOld].nFuncCount = lcl_CountBits( pFields[nOld].nFuncMask );
+ bDupUsed = TRUE;
+ }
+ }
+
+ if ( !bDupUsed ) // also for duplicated dim if original has different orientation
+ {
+ if ( bDataLayout )
+ {
+ pFields[nOutCount].nCol = PIVOT_DATA_FIELD;
+ bDataFound = TRUE;
+ }
+ else if ( nDupSource >= 0 ) // if source was not found (different orientation)
+ pFields[nOutCount].nCol = (short)(nDupSource+nColAdd); //! seek from name
+ else
+ pFields[nOutCount].nCol = (short)(nDim+nColAdd); //! seek source column from name
+
+ pFields[nOutCount].nFuncMask = nMask;
+ pFields[nOutCount].nFuncCount = lcl_CountBits( nMask );
+ nPos[nOutCount] = ScUnoHelpFunctions::GetLongProperty( xDimProp,
+ rtl::OUString::createFromAscii(DP_PROP_POSITION) );
+ ++nOutCount;
+ }
+ }
+ }
+
+ // sort by getPosition() value
+
+ for (long i=0; i+1<nOutCount; i++)
+ {
+ for (long j=0; j+i+1<nOutCount; j++)
+ if ( nPos[j+1] < nPos[j] )
+ {
+ long nTemp = nPos[j+1];
+ nPos[j+1] = nPos[j];
+ nPos[j] = nTemp;
+ PivotField aField = pFields[j+1];
+ pFields[j+1] = pFields[j];
+ pFields[j] = aField;
+ }
+ }
+
+ if ( bAddData && !bDataFound )
+ {
+ if ( nOutCount >= PIVOT_MAXFIELD ) // space for data field?
+ --nOutCount; //! error?
+ pFields[nOutCount].nCol = PIVOT_DATA_FIELD;
+ pFields[nOutCount].nFuncMask = 0;
+ pFields[nOutCount].nFuncCount = 0;
+ ++nOutCount;
+ }
+
+ return nOutCount;
+}
+
+void lcl_SaveOldFieldArr( SvStream& rStream,
+ const uno::Reference<sheet::XDimensionsSupplier>& xSource,
+ USHORT nOrient, USHORT nColAdd, BOOL bAddData )
+{
+ // PIVOT_MAXFIELD = max. number in old files
+ PivotField aFields[PIVOT_MAXFIELD];
+ USHORT nOutCount = lcl_FillOldFields( aFields, xSource, nOrient, nColAdd, bAddData );
+
+ rStream << nOutCount;
+ for (USHORT i=0; i<nOutCount; i++)
+ {
+ rStream << (BYTE) 0x00
+ << aFields[i].nCol
+ << aFields[i].nFuncMask
+ << aFields[i].nFuncCount;
+ }
+}
+
+BOOL ScDPObject::StoreNew( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const
+{
+ // save all data
+
+ rHdr.StartEntry();
+
+ if ( pImpDesc )
+ {
+ rStream << (BYTE) SC_DP_SOURCE_DATABASE;
+ rStream.WriteByteString( pImpDesc->aDBName, rStream.GetStreamCharSet() );
+ rStream.WriteByteString( pImpDesc->aObject, rStream.GetStreamCharSet() );
+ rStream << pImpDesc->nType; // USHORT
+ rStream << pImpDesc->bNative;
+ }
+ else if ( pServDesc )
+ {
+ rStream << (BYTE) SC_DP_SOURCE_SERVICE;
+ rStream.WriteByteString( pServDesc->aServiceName, rStream.GetStreamCharSet() );
+ rStream.WriteByteString( pServDesc->aParSource, rStream.GetStreamCharSet() );
+ rStream.WriteByteString( pServDesc->aParName, rStream.GetStreamCharSet() );
+ rStream.WriteByteString( pServDesc->aParUser, rStream.GetStreamCharSet() );
+ rStream.WriteByteString( pServDesc->aParPass, rStream.GetStreamCharSet() );
+ }
+ else
+ {
+ if (!pSheetDesc)
+ {
+ DBG_ERROR("no source descriptor");
+ ((ScDPObject*)this)->pSheetDesc = new ScSheetSourceDesc; // dummy defaults
+ }
+
+ rStream << (BYTE) SC_DP_SOURCE_SHEET;
+ rStream << pSheetDesc->aSourceRange;
+ pSheetDesc->aQueryParam.Store( rStream );
+ }
+
+ rStream << aOutRange;
+
+ DBG_ASSERT(pSaveData, "ScDPObject::StoreNew no SaveData");
+ pSaveData->Store( rStream );
+
+ // additional data starting from 561b
+ rStream.WriteByteString( aTableName, rStream.GetStreamCharSet() );
+ rStream.WriteByteString( aTableTag, rStream.GetStreamCharSet() );
+
+ rHdr.EndEntry();
+ return TRUE;
+}
+
+BOOL ScDPObject::LoadNew(SvStream& rStream, ScMultipleReadHeader& rHdr )
+{
+ rHdr.StartEntry();
+
+ DELETEZ( pImpDesc );
+ DELETEZ( pSheetDesc );
+ DELETEZ( pServDesc );
+
+ BYTE nType;
+ rStream >> nType;
+ switch (nType)
+ {
+ case SC_DP_SOURCE_DATABASE:
+ pImpDesc = new ScImportSourceDesc;
+ rStream.ReadByteString( pImpDesc->aDBName, rStream.GetStreamCharSet() );
+ rStream.ReadByteString( pImpDesc->aObject, rStream.GetStreamCharSet() );
+ rStream >> pImpDesc->nType; // USHORT
+ rStream >> pImpDesc->bNative;
+ break;
+
+ case SC_DP_SOURCE_SHEET:
+ pSheetDesc = new ScSheetSourceDesc;
+ rStream >> pSheetDesc->aSourceRange;
+ pSheetDesc->aQueryParam.Load( rStream );
+ break;
+
+ case SC_DP_SOURCE_SERVICE:
+ {
+ String aServiceName, aParSource, aParName, aParUser, aParPass;
+ rStream.ReadByteString( aServiceName, rStream.GetStreamCharSet() );
+ rStream.ReadByteString( aParSource, rStream.GetStreamCharSet() );
+ rStream.ReadByteString( aParName, rStream.GetStreamCharSet() );
+ rStream.ReadByteString( aParUser, rStream.GetStreamCharSet() );
+ rStream.ReadByteString( aParPass, rStream.GetStreamCharSet() );
+ pServDesc = new ScDPServiceDesc( aServiceName,
+ aParSource, aParName, aParUser, aParPass );
+ }
+ break;
+
+ default:
+ DBG_ERROR("unknown source type");
+ }
+
+ rStream >> aOutRange;
+
+ SetSaveData(ScDPSaveData());
+ pSaveData->Load( rStream );
+
+ if (rHdr.BytesLeft()) // additional data starting from 561b
+ {
+ rStream.ReadByteString( aTableName, rStream.GetStreamCharSet() );
+ rStream.ReadByteString( aTableTag, rStream.GetStreamCharSet() );
+ }
+
+ rHdr.EndEntry();
+ return TRUE;
+}
+
+BOOL ScDPObject::StoreOld( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const
+{
+ // write compatible data for office 5.1 and below
+
+ DBG_ASSERT( pSheetDesc, "StoreOld: !pSheetDesc" );
+ ScRange aStoreRange;
+ ScQueryParam aStoreQuery;
+ if (pSheetDesc)
+ {
+ aStoreRange = pSheetDesc->aSourceRange;
+ aStoreQuery = pSheetDesc->aQueryParam;
+ }
+
+ ((ScDPObject*)this)->CreateObjects(); // xSource is needed for field numbers
+
+ rHdr.StartEntry();
+
+ rStream << (BOOL) TRUE; // bHasHeader
+
+ rStream << aStoreRange.aStart.Col();
+ rStream << aStoreRange.aStart.Row();
+ rStream << aStoreRange.aEnd.Col();
+ rStream << aStoreRange.aEnd.Row();
+ rStream << aStoreRange.aStart.Tab();
+
+ //! make sure aOutRange is initialized
+
+ rStream << aOutRange.aStart.Col();
+ rStream << aOutRange.aStart.Row();
+ rStream << aOutRange.aEnd.Col();
+ rStream << aOutRange.aEnd.Row();
+ rStream << aOutRange.aStart.Tab();
+
+ BOOL bAddData = ( lcl_GetDataGetOrientation( xSource ) == sheet::DataPilotFieldOrientation_HIDDEN );
+
+ lcl_SaveOldFieldArr( rStream, xSource, sheet::DataPilotFieldOrientation_ROW, aStoreRange.aStart.Col(), bAddData );
+ lcl_SaveOldFieldArr( rStream, xSource, sheet::DataPilotFieldOrientation_COLUMN, aStoreRange.aStart.Col(), FALSE );
+ lcl_SaveOldFieldArr( rStream, xSource, sheet::DataPilotFieldOrientation_DATA, aStoreRange.aStart.Col(), FALSE );
+
+ aStoreQuery.Store( rStream );
+
+ BOOL bColumnGrand = TRUE;
+ BOOL bRowGrand = TRUE;
+ BOOL bIgnoreEmpty = FALSE;
+ BOOL bRepeatIfEmpty = FALSE;
+
+ uno::Reference<beans::XPropertySet> xProp( xSource, uno::UNO_QUERY );
+ if (xProp.is())
+ {
+ bColumnGrand = ScUnoHelpFunctions::GetBoolProperty( xProp,
+ rtl::OUString::createFromAscii(DP_PROP_COLUMNGRAND), TRUE );
+ bRowGrand = ScUnoHelpFunctions::GetBoolProperty( xProp,
+ rtl::OUString::createFromAscii(DP_PROP_ROWGRAND), TRUE );
+
+ // following properties may be missing for external sources
+ bIgnoreEmpty = ScUnoHelpFunctions::GetBoolProperty( xProp,
+ rtl::OUString::createFromAscii(DP_PROP_IGNOREEMPTY) );
+ bRepeatIfEmpty = ScUnoHelpFunctions::GetBoolProperty( xProp,
+ rtl::OUString::createFromAscii(DP_PROP_REPEATIFEMPTY) );
+ }
+
+ rStream << bIgnoreEmpty; // bIgnoreEmpty
+ rStream << bRepeatIfEmpty; // bDetectCat
+
+ rStream << bColumnGrand; // bMakeTotalCol
+ rStream << bRowGrand; // bMakeTotalRow
+
+ if( rStream.GetVersion() > SOFFICE_FILEFORMAT_40 )
+ {
+ rStream.WriteByteString( aTableName, rStream.GetStreamCharSet() );
+ rStream.WriteByteString( aTableTag, rStream.GetStreamCharSet() );
+ rStream << (USHORT)0; // nColNameCount
+ }
+
+ rHdr.EndEntry();
+ return TRUE;
+}
+
+BOOL ScDPObject::FillOldParam(ScPivotParam& rParam, BOOL bForFile) const
+{
+ ((ScDPObject*)this)->CreateObjects(); // xSource is needed for field numbers
+
+ rParam.nCol = aOutRange.aStart.Col();
+ rParam.nRow = aOutRange.aStart.Row();
+ rParam.nTab = aOutRange.aStart.Tab();
+ // ppLabelArr / nLabels is not changed
+
+ USHORT nColAdd = 0;
+ if ( bForFile )
+ {
+ // in old file format, columns are within document, not within source range
+
+ DBG_ASSERT( pSheetDesc, "FillOldParam: bForFile, !pSheetDesc" );
+ nColAdd = pSheetDesc->aSourceRange.aStart.Col();
+ }
+
+ BOOL bAddData = ( lcl_GetDataGetOrientation( xSource ) == sheet::DataPilotFieldOrientation_HIDDEN );
+ rParam.nColCount = lcl_FillOldFields( rParam.aColArr,
+ xSource, sheet::DataPilotFieldOrientation_COLUMN, nColAdd, bAddData );
+ rParam.nRowCount = lcl_FillOldFields( rParam.aRowArr,
+ xSource, sheet::DataPilotFieldOrientation_ROW, nColAdd, FALSE );
+ rParam.nDataCount = lcl_FillOldFields( rParam.aDataArr,
+ xSource, sheet::DataPilotFieldOrientation_DATA, nColAdd, FALSE );
+
+ uno::Reference<beans::XPropertySet> xProp( xSource, uno::UNO_QUERY );
+ if (xProp.is())
+ {
+ TRY
+ {
+ rParam.bMakeTotalCol = ScUnoHelpFunctions::GetBoolProperty( xProp,
+ rtl::OUString::createFromAscii(DP_PROP_COLUMNGRAND), TRUE );
+ rParam.bMakeTotalRow = ScUnoHelpFunctions::GetBoolProperty( xProp,
+ rtl::OUString::createFromAscii(DP_PROP_ROWGRAND), TRUE );
+
+ // following properties may be missing for external sources
+ rParam.bIgnoreEmptyRows = ScUnoHelpFunctions::GetBoolProperty( xProp,
+ rtl::OUString::createFromAscii(DP_PROP_IGNOREEMPTY) );
+ rParam.bDetectCategories = ScUnoHelpFunctions::GetBoolProperty( xProp,
+ rtl::OUString::createFromAscii(DP_PROP_REPEATIFEMPTY) );
+ }
+ CATCH_ALL()
+ {
+ // no error
+ }
+ END_CATCH
+ }
+ return TRUE;
+}
+
+BOOL lcl_ShowEmptyFromDim( const uno::Reference<beans::XPropertySet>& xDimProp )
+{
+ BOOL bRet = FALSE;
+
+ uno::Reference<sheet::XHierarchiesSupplier> xDimSupp( xDimProp, uno::UNO_QUERY );
+ if ( xDimProp.is() && xDimSupp.is() )
+ {
+ uno::Reference<container::XIndexAccess> xHiers = new ScNameToIndexAccess( xDimSupp->getHierarchies() );
+ long nHierarchy = ScUnoHelpFunctions::GetLongProperty( xDimProp,
+ rtl::OUString::createFromAscii(DP_PROP_USEDHIERARCHY) );
+ if ( nHierarchy >= xHiers->getCount() )
+ nHierarchy = 0;
+
+ uno::Reference<uno::XInterface> xHier = ScUnoHelpFunctions::AnyToInterface(
+ xHiers->getByIndex(nHierarchy) );
+ uno::Reference<sheet::XLevelsSupplier> xHierSupp( xHier, uno::UNO_QUERY );
+ if ( xHierSupp.is() )
+ {
+ uno::Reference<container::XIndexAccess> xLevels = new ScNameToIndexAccess( xHierSupp->getLevels() );
+ uno::Reference<uno::XInterface> xLevel =
+ ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex( 0 ) );
+ uno::Reference<beans::XPropertySet> xLevProp( xLevel, uno::UNO_QUERY );
+ if ( xLevProp.is() )
+ bRet = ScUnoHelpFunctions::GetBoolProperty( xLevProp,
+ rtl::OUString::createFromAscii(DP_PROP_SHOWEMPTY) );
+ }
+ }
+
+ return bRet;
+}
+
+BOOL ScDPObject::FillLabelData(ScPivotParam& rParam, BOOL* pShowAll, USHORT nShowAllMax) const
+{
+ ((ScDPObject*)this)->CreateObjects();
+
+ uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
+ uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess( xDimsName );
+ long nDimCount = xDims->getCount();
+ if ( nDimCount > MAX_LABELS )
+ nDimCount = MAX_LABELS;
+ if (!nDimCount)
+ return FALSE;
+
+ USHORT nOutCount = 0;
+ LabelData** aLabelArr = new LabelData*[nDimCount];
+ for (long nDim=0; nDim < nDimCount; nDim++)
+ {
+ String aFieldName;
+ uno::Reference<uno::XInterface> xIntDim =
+ ScUnoHelpFunctions::AnyToInterface( xDims->getByIndex(nDim) );
+ uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
+ uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
+
+ if ( xDimName.is() && xDimProp.is() )
+ {
+ BOOL bDuplicated = FALSE;
+ BOOL bData = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
+ rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT) );
+ //! error checking -- is "IsDataLayoutDimension" property required??
+
+ TRY
+ {
+ aFieldName = String( xDimName->getName() );
+
+ uno::Any aOrigAny = xDimProp->getPropertyValue(
+ rtl::OUString::createFromAscii(DP_PROP_ORIGINAL) );
+ uno::Reference<uno::XInterface> xIntOrig;
+ if ( (aOrigAny >>= xIntOrig) && xIntOrig.is() )
+ bDuplicated = TRUE;
+ }
+ CATCH_ALL()
+ {
+ }
+ END_CATCH
+
+ if ( aFieldName.Len() && !bData && !bDuplicated )
+ {
+ BOOL bIsValue = TRUE; //! check
+ USHORT nCol = nDim; //! ???
+
+ aLabelArr[nOutCount] = new LabelData( aFieldName, nCol, bIsValue );
+ if ( pShowAll && nOutCount < nShowAllMax )
+ pShowAll[nOutCount] = lcl_ShowEmptyFromDim( xDimProp );
+
+ ++nOutCount;
+ }
+ }
+ }
+
+ rParam.SetLabelData( aLabelArr, nOutCount );
+
+ for (USHORT i=0; i<nOutCount; i++)
+ delete aLabelArr[i];
+ delete[] aLabelArr;
+
+ return TRUE;
+}
+
+
+//------------------------------------------------------------------------
+// convert old pivot tables into new datapilot tables
+
+String lcl_GetDimName( const uno::Reference<sheet::XDimensionsSupplier>& xSource, long nDim )
+{
+ rtl::OUString aName;
+ if ( xSource.is() )
+ {
+ uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
+ uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess( xDimsName );
+ long nDimCount = xDims->getCount();
+ if ( nDim < nDimCount )
+ {
+ uno::Reference<uno::XInterface> xIntDim =
+ ScUnoHelpFunctions::AnyToInterface( xDims->getByIndex(nDim) );
+ uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
+ if (xDimName.is())
+ {
+ TRY
+ {
+ aName = xDimName->getName();
+ }
+ CATCH_ALL()
+ {
+ }
+ END_CATCH
+ }
+ }
+ }
+ return aName;
+}
+
+// static
+void ScDPObject::ConvertOrientation( ScDPSaveData& rSaveData,
+ PivotField* pFields, USHORT nCount, USHORT nOrient,
+ ScDocument* pDoc, USHORT nRow, USHORT nTab,
+ const uno::Reference<sheet::XDimensionsSupplier>& xSource,
+ BOOL bOldDefaults,
+ PivotField* pRefColFields, USHORT nRefColCount,
+ PivotField* pRefRowFields, USHORT nRefRowCount )
+{
+ // pDoc or xSource must be set
+ DBG_ASSERT( pDoc || xSource.is(), "missing string source" );
+
+ String aDocStr;
+ ScDPSaveDimension* pDim;
+
+ for (USHORT i=0; i<nCount; i++)
+ {
+ USHORT nCol = pFields[i].nCol;
+ USHORT nFuncs = pFields[i].nFuncMask;
+ if ( nCol == PIVOT_DATA_FIELD )
+ pDim = rSaveData.GetDataLayoutDimension();
+ else
+ {
+ if ( pDoc )
+ pDoc->GetString( nCol, nRow, nTab, aDocStr );
+ else
+ aDocStr = lcl_GetDimName( xSource, nCol ); // cols must start at 0
+ //! handle empty strings etc.
+ pDim = rSaveData.GetDimensionByName(aDocStr);
+ }
+
+ if ( nOrient == sheet::DataPilotFieldOrientation_DATA ) // set summary function
+ {
+ // generate an individual entry for each function
+ BOOL bFirst = TRUE;
+
+ // if a dimension is used for column or row and data,
+ // use duplicated dimensions for all data occurrences
+ if (pRefColFields)
+ for (USHORT nRefCol=0; nRefCol<nRefColCount; nRefCol++)
+ if (pRefColFields[nRefCol].nCol == nCol)
+ bFirst = FALSE;
+ if (pRefRowFields)
+ for (USHORT nRefRow=0; nRefRow<nRefRowCount; nRefRow++)
+ if (pRefRowFields[nRefRow].nCol == nCol)
+ bFirst = FALSE;
+
+ USHORT nMask = 1;
+ for (USHORT nBit=0; nBit<16; nBit++)
+ {
+ if ( nFuncs & nMask )
+ {
+ sheet::GeneralFunction eFunc = ScDataPilotConversion::FirstFunc( nMask );
+ if (bFirst)
+ {
+ pDim->SetOrientation( nOrient );
+ pDim->SetFunction( eFunc );
+ bFirst = FALSE;
+ }
+ else
+ {
+ ScDPSaveDimension* pDup = rSaveData.DuplicateDimension(pDim->GetName());
+ pDup->SetOrientation( nOrient );
+ pDup->SetFunction( eFunc );
+ }
+ }
+ nMask *= 2;
+ }
+ }
+ else // set SubTotals
+ {
+ pDim->SetOrientation( nOrient );
+
+ USHORT nFuncArray[16];
+ USHORT nFuncCount = 0;
+ USHORT nMask = 1;
+ for (USHORT nBit=0; nBit<16; nBit++)
+ {
+ if ( nFuncs & nMask )
+ nFuncArray[nFuncCount++] = ScDataPilotConversion::FirstFunc( nMask );
+ nMask *= 2;
+ }
+ pDim->SetSubTotals( nFuncCount, nFuncArray );
+
+ // ShowEmpty was implicit in old tables,
+ // must be set for data layout dimension (not accessible in dialog)
+ if ( bOldDefaults || nCol == PIVOT_DATA_FIELD )
+ pDim->SetShowEmpty( TRUE );
+ }
+ }
+}
+
+void ScDPObject::InitFromOldPivot( const ScPivot& rOld, ScDocument* pDoc, BOOL bSetSource )
+{
+ ScDPSaveData aSaveData;
+
+ ScPivotParam aParam;
+ ScQueryParam aQuery;
+ ScArea aArea;
+ rOld.GetParam( aParam, aQuery, aArea );
+
+ ConvertOrientation( aSaveData, aParam.aColArr, aParam.nColCount,
+ sheet::DataPilotFieldOrientation_COLUMN, pDoc, aArea.nRowStart, aArea.nTab,
+ uno::Reference<sheet::XDimensionsSupplier>(), TRUE );
+ ConvertOrientation( aSaveData, aParam.aRowArr, aParam.nRowCount,
+ sheet::DataPilotFieldOrientation_ROW, pDoc, aArea.nRowStart, aArea.nTab,
+ uno::Reference<sheet::XDimensionsSupplier>(), TRUE );
+ ConvertOrientation( aSaveData, aParam.aDataArr, aParam.nDataCount,
+ sheet::DataPilotFieldOrientation_DATA, pDoc, aArea.nRowStart, aArea.nTab,
+ uno::Reference<sheet::XDimensionsSupplier>(), TRUE,
+ aParam.aColArr, aParam.nColCount, aParam.aRowArr, aParam.nRowCount );
+
+ aSaveData.SetIgnoreEmptyRows( rOld.GetIgnoreEmpty() );
+ aSaveData.SetRepeatIfEmpty( rOld.GetDetectCat() );
+ aSaveData.SetColumnGrand( rOld.GetMakeTotalCol() );
+ aSaveData.SetRowGrand( rOld.GetMakeTotalRow() );
+
+ SetSaveData( aSaveData );
+ if (bSetSource)
+ {
+ ScSheetSourceDesc aDesc;
+ aDesc.aSourceRange = rOld.GetSrcArea();
+ rOld.GetQuery( aDesc.aQueryParam );
+ SetSheetDesc( aDesc );
+ }
+ SetOutRange( rOld.GetDestArea() );
+
+ aTableName = rOld.GetName();
+ aTableTag = rOld.GetTag();
+}
+
+// -----------------------------------------------------------------------
+
+// static
+BOOL ScDPObject::HasRegisteredSources()
+{
+ BOOL bFound = FALSE;
+
+ uno::Reference<lang::XMultiServiceFactory> xManager = utl::getProcessServiceFactory();
+ uno::Reference<container::XContentEnumerationAccess> xEnAc( xManager, uno::UNO_QUERY );
+ if ( xEnAc.is() )
+ {
+ uno::Reference<container::XEnumeration> xEnum = xEnAc->createContentEnumeration(
+ rtl::OUString::createFromAscii( SCDPSOURCE_SERVICE ) );
+ if ( xEnum.is() && xEnum->hasMoreElements() )
+ bFound = TRUE;
+ }
+
+ return bFound;
+}
+
+// static
+uno::Sequence<rtl::OUString> ScDPObject::GetRegisteredSources()
+{
+ long nCount = 0;
+ uno::Sequence<rtl::OUString> aSeq(0);
+
+ // use implementation names...
+
+ uno::Reference<lang::XMultiServiceFactory> xManager = utl::getProcessServiceFactory();
+ uno::Reference<container::XContentEnumerationAccess> xEnAc( xManager, uno::UNO_QUERY );
+ if ( xEnAc.is() )
+ {
+ uno::Reference<container::XEnumeration> xEnum = xEnAc->createContentEnumeration(
+ rtl::OUString::createFromAscii( SCDPSOURCE_SERVICE ) );
+ if ( xEnum.is() )
+ {
+ while ( xEnum->hasMoreElements() )
+ {
+ uno::Any aAddInAny = xEnum->nextElement();
+// if ( aAddInAny.getReflection()->getTypeClass() == TypeClass_INTERFACE )
+ {
+ uno::Reference<uno::XInterface> xIntFac;
+ aAddInAny >>= xIntFac;
+ if ( xIntFac.is() )
+ {
+ uno::Reference<lang::XServiceInfo> xInfo( xIntFac, uno::UNO_QUERY );
+ if ( xInfo.is() )
+ {
+ rtl::OUString sName = xInfo->getImplementationName();
+
+ aSeq.realloc( nCount+1 );
+ aSeq.getArray()[nCount] = sName;
+ ++nCount;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return aSeq;
+}
+
+// static
+uno::Reference<sheet::XDimensionsSupplier> ScDPObject::CreateSource( const ScDPServiceDesc& rDesc )
+{
+ rtl::OUString aImplName = rDesc.aServiceName;
+ uno::Reference<sheet::XDimensionsSupplier> xRet = NULL;
+
+ uno::Reference<lang::XMultiServiceFactory> xManager = utl::getProcessServiceFactory();
+ uno::Reference<container::XContentEnumerationAccess> xEnAc( xManager, uno::UNO_QUERY );
+ if ( xEnAc.is() )
+ {
+ uno::Reference<container::XEnumeration> xEnum = xEnAc->createContentEnumeration(
+ rtl::OUString::createFromAscii( SCDPSOURCE_SERVICE ) );
+ if ( xEnum.is() )
+ {
+ while ( xEnum->hasMoreElements() && !xRet.is() )
+ {
+ uno::Any aAddInAny = xEnum->nextElement();
+// if ( aAddInAny.getReflection()->getTypeClass() == TypeClass_INTERFACE )
+ {
+ uno::Reference<uno::XInterface> xIntFac;
+ aAddInAny >>= xIntFac;
+ if ( xIntFac.is() )
+ {
+ uno::Reference<lang::XServiceInfo> xInfo( xIntFac, uno::UNO_QUERY );
+ uno::Reference<lang::XSingleServiceFactory> xFac( xIntFac, uno::UNO_QUERY );
+ if ( xFac.is() && xInfo.is() && xInfo->getImplementationName() == aImplName )
+ {
+ TRY
+ {
+ uno::Reference<uno::XInterface> xInterface = xFac->createInstance();
+ uno::Reference<lang::XInitialization> xInit( xInterface, uno::UNO_QUERY );
+ if (xInit.is())
+ {
+ // initialize
+ uno::Sequence<uno::Any> aSeq(4);
+ uno::Any* pArray = aSeq.getArray();
+ pArray[0] <<= rtl::OUString( rDesc.aParSource );
+ pArray[1] <<= rtl::OUString( rDesc.aParName );
+ pArray[2] <<= rtl::OUString( rDesc.aParUser );
+ pArray[3] <<= rtl::OUString( rDesc.aParPass );
+ xInit->initialize( aSeq );
+ }
+ xRet = uno::Reference<sheet::XDimensionsSupplier>( xInterface, uno::UNO_QUERY );
+ }
+ CATCH_ALL()
+ {
+ }
+ END_CATCH
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return xRet;
+}
+
+// -----------------------------------------------------------------------
+
+ScDPCollection::ScDPCollection(ScDocument* pDocument) :
+ pDoc( pDocument )
+{
+}
+
+ScDPCollection::ScDPCollection(const ScDPCollection& r) :
+ Collection(r),
+ pDoc(r.pDoc)
+{
+}
+
+ScDPCollection::~ScDPCollection()
+{
+}
+
+DataObject* ScDPCollection::Clone() const
+{
+ return new ScDPCollection(*this);
+}
+
+BOOL ScDPCollection::StoreOld( SvStream& rStream ) const
+{
+ BOOL bSuccess = TRUE;
+
+ USHORT nSheetCount = 0;
+ USHORT i;
+ for (i=0; i<nCount; i++)
+ if ( ((const ScDPObject*)At(i))->IsSheetData() )
+ ++nSheetCount;
+
+ ScMultipleWriteHeader aHdr( rStream );
+
+ rStream << nSheetCount; // only tables from sheet data
+
+ for (i=0; i<nCount && bSuccess; i++)
+ {
+ const ScDPObject* pObj = (const ScDPObject*)At(i);
+ if ( pObj->IsSheetData() )
+ bSuccess = pObj->StoreOld( rStream, aHdr );
+ }
+
+ return bSuccess;
+}
+
+BOOL ScDPCollection::StoreNew( SvStream& rStream ) const
+{
+ BOOL bSuccess = TRUE;
+
+ ScMultipleWriteHeader aHdr( rStream );
+
+ rStream << (long)SC_DP_VERSION_CURRENT;
+ rStream << (long)nCount;
+
+ for (USHORT i=0; i<nCount && bSuccess; i++)
+ bSuccess = ((const ScDPObject*)At(i))->StoreNew( rStream, aHdr );
+
+ return bSuccess;
+}
+
+BOOL ScDPCollection::LoadNew( SvStream& rStream )
+{
+ BOOL bSuccess = TRUE;
+
+ FreeAll();
+ ScMultipleReadHeader aHdr( rStream );
+
+ long nVer;
+ rStream >> nVer;
+
+ // check for all supported versions here..
+
+ if ( nVer != SC_DP_VERSION_CURRENT )
+ {
+ DBG_ERROR("skipping unknown version of data pilot obejct");
+ if ( rStream.GetError() == SVSTREAM_OK )
+ rStream.SetError( SCWARN_IMPORT_INFOLOST );
+ return FALSE;
+ }
+
+ long nNewCount;
+ rStream >> nNewCount;
+ for (long i=0; i<nNewCount; i++)
+ {
+ ScDPObject* pObj = new ScDPObject( pDoc );
+ if ( pObj->LoadNew(rStream, aHdr) )
+ {
+ pObj->SetAlive( TRUE );
+ Insert( pObj );
+ }
+ else
+ delete pObj;
+ }
+
+ return bSuccess;
+}
+
+void ScDPCollection::UpdateReference( UpdateRefMode eUpdateRefMode,
+ const ScRange& r, short nDx, short nDy, short nDz )
+{
+ for (USHORT i=0; i<nCount; i++)
+ ((ScDPObject*)At(i))->UpdateReference( eUpdateRefMode, r, nDx, nDy, nDz );
+}
+
+BOOL ScDPCollection::RefsEqual( const ScDPCollection& r ) const
+{
+ if ( nCount != r.nCount )
+ return FALSE;
+
+ for (USHORT i=0; i<nCount; i++)
+ if ( ! ((const ScDPObject*)At(i))->RefsEqual( *((const ScDPObject*)r.At(i)) ) )
+ return FALSE;
+
+ return TRUE; // all equal
+}
+
+void ScDPCollection::WriteRefsTo( ScDPCollection& r ) const
+{
+ if ( nCount == r.nCount )
+ {
+ //! assert equal names?
+ for (USHORT i=0; i<nCount; i++)
+ ((const ScDPObject*)At(i))->WriteRefsTo( *((ScDPObject*)r.At(i)) );
+ }
+ else
+ DBG_ERROR("WriteRefsTo: different count");
+}
+
+String ScDPCollection::CreateNewName( USHORT nMin ) const
+{
+ String aBase = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("DataPilot"));
+ //! from Resource?
+
+ for (USHORT nAdd=0; nAdd<=nCount; nAdd++) // nCount+1 tries
+ {
+ String aNewName = aBase;
+ aNewName += String::CreateFromInt32( nMin + nAdd );
+ BOOL bFound = FALSE;
+ for (USHORT i=0; i<nCount && !bFound; i++)
+ if (((const ScDPObject*)pItems[i])->GetName() == aNewName)
+ bFound = TRUE;
+ if (!bFound)
+ return aNewName; // found unused Name
+ }
+ return String(); // should not happen
+}
+
+void ScDPCollection::EnsureNames()
+{
+ for (USHORT i=0; i<nCount; i++)
+ if (!((const ScDPObject*)At(i))->GetName().Len())
+ ((ScDPObject*)At(i))->SetName( CreateNewName() );
+}
+
+//------------------------------------------------------------------------
+// convert old pivot tables into new datapilot tables
+
+void ScDPCollection::ConvertOldTables( ScPivotCollection& rOldColl )
+{
+ // convert old pivot tables into new datapilot tables
+
+ USHORT nOldCount = rOldColl.GetCount();
+ for (USHORT i=0; i<nOldCount; i++)
+ {
+ ScDPObject* pNewObj = new ScDPObject(pDoc);
+ pNewObj->InitFromOldPivot( *(rOldColl)[i], pDoc, TRUE );
+ pNewObj->SetAlive( TRUE );
+ Insert( pNewObj );
+ }
+ rOldColl.FreeAll();
+}
+
+
+
+
diff --git a/sc/source/core/data/dpoutput.cxx b/sc/source/core/data/dpoutput.cxx
new file mode 100644
index 000000000000..f83804217fc9
--- /dev/null
+++ b/sc/source/core/data/dpoutput.cxx
@@ -0,0 +1,1003 @@
+/*************************************************************************
+ *
+ * $RCSfile: dpoutput.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <svx/algitem.hxx>
+#include <svx/boxitem.hxx>
+#include <svx/brshitem.hxx>
+#include <svx/wghtitem.hxx>
+#include <vos/xception.hxx>
+
+#include "dpoutput.hxx"
+#include "document.hxx"
+#include "patattr.hxx"
+#include "docpool.hxx"
+#include "markdata.hxx"
+#include "attrib.hxx"
+#include "compiler.hxx" // errNoValue
+#include "miscuno.hxx"
+#include "globstr.hrc"
+#include "stlpool.hxx"
+#include "stlsheet.hxx"
+
+#include <com/sun/star/sheet/XLevelsSupplier.hpp>
+#include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
+#include <com/sun/star/sheet/XDataPilotResults.hpp>
+#include <com/sun/star/sheet/XDataPilotMemberResults.hpp>
+#include <com/sun/star/sheet/DataResultFlags.hpp>
+#include <com/sun/star/sheet/MemberResultFlags.hpp>
+#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+
+using namespace com::sun::star;
+
+// -----------------------------------------------------------------------
+
+//! move to a header file
+#define DP_PROP_ORIENTATION "Orientation"
+#define DP_PROP_POSITION "Position"
+#define DP_PROP_USEDHIERARCHY "UsedHierarchy"
+#define DP_PROP_DATADESCR "DataDescription"
+#define DP_PROP_ISDATALAYOUT "IsDataLayoutDimension"
+#define DP_PROP_NUMBERFORMAT "NumberFormat"
+
+// -----------------------------------------------------------------------
+
+//! dynamic!!!
+#define SC_DPOUT_MAXLEVELS 256
+
+
+struct ScDPOutLevelData
+{
+ long nDim;
+ long nHier;
+ long nLevel;
+ long nDimPos;
+ uno::Sequence<sheet::MemberResult> aResult;
+ String aCaption;
+
+ ScDPOutLevelData() { nDim = nHier = nLevel = nDimPos = -1; }
+
+ BOOL operator<(const ScDPOutLevelData& r) const
+ { return nDimPos<r.nDimPos || ( nDimPos==r.nDimPos && nHier<r.nHier ) ||
+ ( nDimPos==r.nDimPos && nHier==r.nHier && nLevel<r.nLevel ); }
+
+ void Swap(ScDPOutLevelData& r)
+//! { ScDPOutLevelData aTemp = r; r = *this; *this = aTemp; }
+ { ScDPOutLevelData aTemp; aTemp = r; r = *this; *this = aTemp; }
+
+ //! bug (73840) in uno::Sequence - copy and then assign doesn't work!
+};
+
+// -----------------------------------------------------------------------
+
+void lcl_SetStyleById( ScDocument* pDoc, USHORT nTab,
+ USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2,
+ USHORT nStrId )
+{
+ if ( nCol1 > nCol2 || nRow1 > nRow2 )
+ {
+ DBG_ERROR("SetStyleById: invalid range");
+ return;
+ }
+
+ String aStyleName = ScGlobal::GetRscString( nStrId );
+ ScStyleSheetPool* pStlPool = pDoc->GetStyleSheetPool();
+ ScStyleSheet* pStyle = (ScStyleSheet*) pStlPool->Find( aStyleName, SFX_STYLE_FAMILY_PARA );
+ if (!pStyle)
+ {
+ // create new style (was in ScPivot::SetStyle)
+
+ pStyle = (ScStyleSheet*) &pStlPool->Make( aStyleName, SFX_STYLE_FAMILY_PARA,
+ SFXSTYLEBIT_USERDEF );
+ pStyle->SetParent( ScGlobal::GetRscString(STR_STYLENAME_STANDARD) );
+ SfxItemSet& rSet = pStyle->GetItemSet();
+ if ( nStrId==STR_PIVOT_STYLE_RESULT || nStrId==STR_PIVOT_STYLE_TITLE )
+ rSet.Put( SvxWeightItem( WEIGHT_BOLD ) );
+ if ( nStrId==STR_PIVOT_STYLE_CATEGORY || nStrId==STR_PIVOT_STYLE_TITLE )
+ rSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_LEFT ) );
+ }
+
+ pDoc->ApplyStyleAreaTab( nCol1, nRow1, nCol2, nRow2, nTab, *pStyle );
+}
+
+void lcl_SetFrame( ScDocument* pDoc, USHORT nTab,
+ USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2,
+ USHORT nWidth )
+{
+ SvxBorderLine aLine;
+ aLine.SetOutWidth(nWidth);
+ SvxBoxItem aBox;
+ aBox.SetLine(&aLine, BOX_LINE_LEFT);
+ aBox.SetLine(&aLine, BOX_LINE_TOP);
+ aBox.SetLine(&aLine, BOX_LINE_RIGHT);
+ aBox.SetLine(&aLine, BOX_LINE_BOTTOM);
+ SvxBoxInfoItem aBoxInfo;
+ aBoxInfo.SetValid(VALID_HORI,FALSE);
+ aBoxInfo.SetValid(VALID_VERT,FALSE);
+ aBoxInfo.SetValid(VALID_DISTANCE,FALSE);
+
+ ScMarkData aMark;
+ aMark.SelectTable( nTab, TRUE );
+ aMark.SetMarkArea( ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab ) );
+ pDoc->ApplySelectionFrame( aMark, &aBox, &aBoxInfo );
+}
+
+void lcl_AttrArea( ScDocument* pDoc, USHORT nTab,
+ USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2,
+ const SfxPoolItem& rItem )
+{
+ ScPatternAttr aPattern( pDoc->GetPool() );
+ aPattern.GetItemSet().Put( rItem );
+ pDoc->ApplyPatternAreaTab( nCol1,nRow1, nCol2,nRow2, nTab, aPattern );
+}
+
+// -----------------------------------------------------------------------
+
+void lcl_FillNumberFormats( UINT32*& rFormats, long& rCount,
+ const uno::Reference<sheet::XDataPilotMemberResults>& xLevRes,
+ const uno::Reference<container::XIndexAccess>& xDims )
+{
+ if ( rFormats )
+ return; // already set
+
+ // xLevRes is from the data layout dimension
+ //! use result sequence from ScDPOutLevelData!
+
+ uno::Sequence<sheet::MemberResult> aResult = xLevRes->getResults();
+
+ long nSize = aResult.getLength();
+ if (nSize)
+ {
+ // get names/formats for all data dimensions
+ //! merge this with the loop to collect ScDPOutLevelData?
+
+ String aDataNames[SC_DPOUT_MAXLEVELS];
+ UINT32 nDataFormats[SC_DPOUT_MAXLEVELS];
+ long nDataCount = 0;
+ BOOL bAnySet = FALSE;
+
+ long nDimCount = xDims->getCount();
+ for (long nDim=0; nDim<nDimCount; nDim++)
+ {
+ uno::Reference<uno::XInterface> xDim =
+ ScUnoHelpFunctions::AnyToInterface( xDims->getByIndex(nDim) );
+ uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
+ uno::Reference<container::XNamed> xDimName( xDim, uno::UNO_QUERY );
+ if ( xDimProp.is() && xDimName.is() )
+ {
+ sheet::DataPilotFieldOrientation eDimOrient =
+ (sheet::DataPilotFieldOrientation) ScUnoHelpFunctions::GetEnumProperty(
+ xDimProp, rtl::OUString::createFromAscii(DP_PROP_ORIENTATION),
+ sheet::DataPilotFieldOrientation_HIDDEN );
+ if ( eDimOrient == sheet::DataPilotFieldOrientation_DATA )
+ {
+ aDataNames[nDataCount] = String( xDimName->getName() );
+ long nFormat = ScUnoHelpFunctions::GetLongProperty(
+ xDimProp,
+ rtl::OUString::createFromAscii(DP_PROP_NUMBERFORMAT) );
+ nDataFormats[nDataCount] = nFormat;
+ if ( nFormat != 0 )
+ bAnySet = TRUE;
+ ++nDataCount;
+ }
+ }
+ }
+
+ if ( bAnySet ) // forget everything if all formats are 0 (or no data dimensions)
+ {
+ const sheet::MemberResult* pArray = aResult.getConstArray();
+
+ String aName;
+ UINT32* pNumFmt = new UINT32[nSize];
+ if (nDataCount == 1)
+ {
+ // only one data dimension -> use its numberformat everywhere
+ long nFormat = nDataFormats[0];
+ for (long nPos=0; nPos<nSize; nPos++)
+ pNumFmt[nPos] = nFormat;
+ }
+ else
+ {
+ for (long nPos=0; nPos<nSize; nPos++)
+ {
+ // if CONTINUE bit is set, keep previous name
+ //! keep number format instead!
+ if ( !(pArray[nPos].Flags & sheet::MemberResultFlags::CONTINUE) )
+ aName = String( pArray[nPos].Name );
+
+ UINT32 nFormat = 0;
+ for (long i=0; i<nDataCount; i++)
+ if (aName == aDataNames[i]) //! search more efficiently?
+ {
+ nFormat = nDataFormats[i];
+ break;
+ }
+ pNumFmt[nPos] = nFormat;
+ }
+ }
+
+ rFormats = pNumFmt;
+ rCount = nSize;
+ }
+ }
+}
+
+void lcl_SortFields( ScDPOutLevelData* pFields, long nFieldCount )
+{
+ for (long i=0; i+1<nFieldCount; i++)
+ {
+ for (long j=0; j+i+1<nFieldCount; j++)
+ if ( pFields[j+1] < pFields[j] )
+ pFields[j].Swap( pFields[j+1] );
+ }
+}
+
+BOOL lcl_MemberEmpty( const uno::Sequence<sheet::MemberResult>& rSeq )
+{
+ // used to skip levels that have no members
+
+ long nLen = rSeq.getLength();
+ const sheet::MemberResult* pArray = rSeq.getConstArray();
+ for (long i=0; i<nLen; i++)
+ if (pArray[i].Flags & sheet::MemberResultFlags::HASMEMBER)
+ return FALSE;
+
+ return TRUE; // no member data -> empty
+}
+
+ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsSupplier>& xSrc,
+ const ScAddress& rPos, BOOL bFilter ) :
+ pDoc( pD ),
+ xSource( xSrc ),
+ aStartPos( rPos ),
+ bDoFilter( bFilter ),
+ bSizesValid( FALSE ),
+ pColNumFmt( NULL ),
+ pRowNumFmt( NULL ),
+ nColFmtCount( 0 ),
+ nRowFmtCount( 0 )
+{
+ nTabStartCol = nTabStartRow = nMemberStartCol = nMemberStartRow =
+ nDataStartCol = nDataStartRow = nTabEndCol = nTabEndRow = 0;
+
+ pColFields = new ScDPOutLevelData[SC_DPOUT_MAXLEVELS];
+ pRowFields = new ScDPOutLevelData[SC_DPOUT_MAXLEVELS];
+ pPageFields = new ScDPOutLevelData[SC_DPOUT_MAXLEVELS];
+ nColFieldCount = 0;
+ nRowFieldCount = 0;
+ nPageFieldCount = 0;
+
+ uno::Reference<sheet::XDataPilotResults> xResult( xSource, uno::UNO_QUERY );
+ if ( xSource.is() && xResult.is() )
+ {
+ // get dimension results:
+
+ uno::Reference<container::XIndexAccess> xDims =
+ new ScNameToIndexAccess( xSource->getDimensions() );
+ long nDimCount = xDims->getCount();
+ for (long nDim=0; nDim<nDimCount; nDim++)
+ {
+ uno::Reference<uno::XInterface> xDim =
+ ScUnoHelpFunctions::AnyToInterface( xDims->getByIndex(nDim) );
+ uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
+ uno::Reference<sheet::XHierarchiesSupplier> xDimSupp( xDim, uno::UNO_QUERY );
+ if ( xDimProp.is() && xDimSupp.is() )
+ {
+ sheet::DataPilotFieldOrientation eDimOrient =
+ (sheet::DataPilotFieldOrientation) ScUnoHelpFunctions::GetEnumProperty(
+ xDimProp, rtl::OUString::createFromAscii(DP_PROP_ORIENTATION),
+ sheet::DataPilotFieldOrientation_HIDDEN );
+ long nDimPos = ScUnoHelpFunctions::GetLongProperty( xDimProp,
+ rtl::OUString::createFromAscii(DP_PROP_POSITION) );
+ BOOL bIsDataLayout = ScUnoHelpFunctions::GetBoolProperty(
+ xDimProp,
+ rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT) );
+
+ if ( eDimOrient != sheet::DataPilotFieldOrientation_HIDDEN )
+ {
+ uno::Reference<container::XIndexAccess> xHiers =
+ new ScNameToIndexAccess( xDimSupp->getHierarchies() );
+ long nHierarchy = ScUnoHelpFunctions::GetLongProperty(
+ xDimProp,
+ rtl::OUString::createFromAscii(DP_PROP_USEDHIERARCHY) );
+ if ( nHierarchy >= xHiers->getCount() )
+ nHierarchy = 0;
+
+ uno::Reference<uno::XInterface> xHier =
+ ScUnoHelpFunctions::AnyToInterface(
+ xHiers->getByIndex(nHierarchy) );
+ uno::Reference<sheet::XLevelsSupplier> xHierSupp( xHier, uno::UNO_QUERY );
+ if ( xHierSupp.is() )
+ {
+ uno::Reference<container::XIndexAccess> xLevels =
+ new ScNameToIndexAccess( xHierSupp->getLevels() );
+ long nLevCount = xLevels->getCount();
+ for (long nLev=0; nLev<nLevCount; nLev++)
+ {
+ uno::Reference<uno::XInterface> xLevel =
+ ScUnoHelpFunctions::AnyToInterface(
+ xLevels->getByIndex(nLev) );
+ uno::Reference<container::XNamed> xLevNam( xLevel, uno::UNO_QUERY );
+ uno::Reference<sheet::XDataPilotMemberResults> xLevRes(
+ xLevel, uno::UNO_QUERY );
+ if ( xLevNam.is() && xLevRes.is() )
+ {
+ String aCaption = String(xLevNam->getName()); //! Caption...
+ switch ( eDimOrient )
+ {
+ case sheet::DataPilotFieldOrientation_COLUMN:
+ pColFields[nColFieldCount].nDim = nDim;
+ pColFields[nColFieldCount].nHier = nHierarchy;
+ pColFields[nColFieldCount].nLevel = nLev;
+ pColFields[nColFieldCount].nDimPos = nDimPos;
+ pColFields[nColFieldCount].aResult = xLevRes->getResults();
+ pColFields[nColFieldCount].aCaption= aCaption;
+ if (!lcl_MemberEmpty(pColFields[nColFieldCount].aResult))
+ ++nColFieldCount;
+ break;
+ case sheet::DataPilotFieldOrientation_ROW:
+ pRowFields[nRowFieldCount].nDim = nDim;
+ pRowFields[nRowFieldCount].nHier = nHierarchy;
+ pRowFields[nRowFieldCount].nLevel = nLev;
+ pRowFields[nRowFieldCount].nDimPos = nDimPos;
+ pRowFields[nRowFieldCount].aResult = xLevRes->getResults();
+ pRowFields[nRowFieldCount].aCaption= aCaption;
+ if (!lcl_MemberEmpty(pRowFields[nRowFieldCount].aResult))
+ ++nRowFieldCount;
+ break;
+ case sheet::DataPilotFieldOrientation_PAGE:
+ pPageFields[nPageFieldCount].nDim = nDim;
+ pPageFields[nPageFieldCount].nHier = nHierarchy;
+ pPageFields[nPageFieldCount].nLevel = nLev;
+ pPageFields[nPageFieldCount].nDimPos = nDimPos;
+ pPageFields[nPageFieldCount].aResult = xLevRes->getResults();
+ pPageFields[nPageFieldCount].aCaption= aCaption;
+ if (!lcl_MemberEmpty(pPageFields[nPageFieldCount].aResult))
+ ++nPageFieldCount;
+ break;
+ }
+
+ // get number formats from data dimensions
+ if ( bIsDataLayout )
+ {
+ DBG_ASSERT( nLevCount == 1, "data layout: multiple levels?" );
+ if ( eDimOrient == sheet::DataPilotFieldOrientation_COLUMN )
+ lcl_FillNumberFormats( pColNumFmt, nColFmtCount, xLevRes, xDims );
+ else if ( eDimOrient == sheet::DataPilotFieldOrientation_ROW )
+ lcl_FillNumberFormats( pRowNumFmt, nRowFmtCount, xLevRes, xDims );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ lcl_SortFields( pColFields, nColFieldCount );
+ lcl_SortFields( pRowFields, nRowFieldCount );
+ lcl_SortFields( pPageFields, nPageFieldCount );
+
+ // get data results:
+
+ aData = xResult->getResults();
+ }
+
+ // get "DataDescription" property (may be missing in external sources)
+
+ uno::Reference<beans::XPropertySet> xSrcProp( xSource, uno::UNO_QUERY );
+ if ( xSrcProp.is() )
+ {
+ TRY
+ {
+ uno::Any aAny = xSrcProp->getPropertyValue(
+ rtl::OUString::createFromAscii(DP_PROP_DATADESCR) );
+ rtl::OUString aUStr;
+ aAny >>= aUStr;
+ aDataDescription = String( aUStr );
+ }
+ CATCH_ALL()
+ {
+ }
+ END_CATCH
+ }
+}
+
+ScDPOutput::~ScDPOutput()
+{
+ delete[] pColFields;
+ delete[] pRowFields;
+ delete[] pPageFields;
+
+ delete[] pColNumFmt;
+ delete[] pRowNumFmt;
+}
+
+void ScDPOutput::SetPosition( const ScAddress& rPos )
+{
+ aStartPos = rPos;
+ bSizesValid = FALSE;
+}
+
+void ScDPOutput::DataCell( USHORT nCol, USHORT nRow, USHORT nTab, const sheet::DataResult& rData )
+{
+ long nFlags = rData.Flags;
+ if ( nFlags & sheet::DataResultFlags::ERROR )
+ {
+ pDoc->SetError( nCol, nRow, nTab, errNoValue );
+ }
+ else if ( nFlags & sheet::DataResultFlags::HASDATA )
+ {
+ pDoc->SetValue( nCol, nRow, nTab, rData.Value );
+
+ // use number formats from source
+
+ DBG_ASSERT( bSizesValid, "DataCell: !bSizesValid" );
+ UINT32 nFormat = 0;
+ if ( pColNumFmt )
+ {
+ if ( nCol >= nDataStartCol )
+ {
+ long nIndex = nCol - nDataStartCol;
+ if ( nIndex < nColFmtCount )
+ nFormat = pColNumFmt[nIndex];
+ }
+ }
+ else if ( pRowNumFmt )
+ {
+ if ( nRow >= nDataStartRow )
+ {
+ long nIndex = nRow - nDataStartRow;
+ if ( nIndex < nRowFmtCount )
+ nFormat = pRowNumFmt[nIndex];
+ }
+ }
+ if ( nFormat != 0 )
+ pDoc->ApplyAttr( nCol, nRow, nTab, SfxUInt32Item( ATTR_VALUE_FORMAT, nFormat ) );
+ }
+ else
+ {
+ //pDoc->SetString( nCol, nRow, nTab, EMPTY_STRING );
+ }
+
+ // SubTotal formatting is controlled by headers
+}
+
+void ScDPOutput::HeaderCell( USHORT nCol, USHORT nRow, USHORT nTab,
+ const sheet::MemberResult& rData, BOOL bColHeader, long nLevel )
+{
+ long nFlags = rData.Flags;
+ if ( nFlags & sheet::MemberResultFlags::HASMEMBER )
+ {
+ pDoc->SetString( nCol, nRow, nTab, rData.Caption );
+ }
+ else
+ {
+ //pDoc->SetString( nCol, nRow, nTab, EMPTY_STRING );
+ }
+
+ if ( nFlags & sheet::MemberResultFlags::SUBTOTAL )
+ {
+// SvxWeightItem aItem( WEIGHT_BOLD ); // weight is in the style
+
+ //! limit frames to horizontal or vertical?
+ if (bColHeader)
+ {
+// lcl_AttrArea( pDoc,nTab, nCol,nMemberStartRow+(USHORT)nLevel, nCol,nTabEndRow, aItem );
+ lcl_SetFrame( pDoc,nTab, nCol,nMemberStartRow+(USHORT)nLevel, nCol,nTabEndRow, 20 );
+ lcl_SetStyleById( pDoc,nTab, nCol,nMemberStartRow+(USHORT)nLevel, nCol,nDataStartRow-1,
+ STR_PIVOT_STYLE_TITLE );
+ lcl_SetStyleById( pDoc,nTab, nCol,nDataStartRow, nCol,nTabEndRow,
+ STR_PIVOT_STYLE_RESULT );
+ }
+ else
+ {
+// lcl_AttrArea( pDoc,nTab, nMemberStartCol+(USHORT)nLevel,nRow, nTabEndCol,nRow, aItem );
+ lcl_SetFrame( pDoc,nTab, nMemberStartCol+(USHORT)nLevel,nRow, nTabEndCol,nRow, 20 );
+ lcl_SetStyleById( pDoc,nTab, nMemberStartCol+(USHORT)nLevel,nRow, nDataStartCol-1,nRow,
+ STR_PIVOT_STYLE_TITLE );
+ lcl_SetStyleById( pDoc,nTab, nDataStartCol,nRow, nTabEndCol,nRow,
+ STR_PIVOT_STYLE_RESULT );
+ }
+ }
+}
+
+void ScDPOutput::FieldCell( USHORT nCol, USHORT nRow, USHORT nTab, const String& rCaption )
+{
+ pDoc->SetString( nCol, nRow, nTab, rCaption );
+ lcl_SetFrame( pDoc,nTab, nCol,nRow, nCol,nRow, 20 );
+
+ // Button
+ pDoc->ApplyAttr( nCol, nRow, nTab, ScMergeFlagAttr(SC_MF_BUTTON) );
+
+ lcl_SetStyleById( pDoc,nTab, nCol,nRow, nCol,nRow, STR_PIVOT_STYLE_FIELDNAME );
+}
+
+void lcl_DoFilterButton( ScDocument* pDoc, USHORT nCol, USHORT nRow, USHORT nTab )
+{
+ pDoc->SetString( nCol, nRow, nTab, ScGlobal::GetRscString(STR_CELL_FILTER) );
+ pDoc->ApplyAttr( nCol, nRow, nTab, ScMergeFlagAttr(SC_MF_BUTTON) );
+}
+
+void ScDPOutput::CalcSizes()
+{
+ if (!bSizesValid)
+ {
+ // get column size of data from first row
+ //! allow different sizes (and clear following areas) ???
+
+ nRowCount = aData.getLength();
+ const uno::Sequence<sheet::DataResult>* pRowAry = aData.getConstArray();
+ nColCount = nRowCount ? ( pRowAry[0].getLength() ) : 0;
+ nHeaderSize = 1; // one row for field names
+
+ // calculate output positions and sizes
+ //! check for overflow
+
+ long nPageSize = 0; //! use page fields!
+ if ( bDoFilter )
+ nPageSize = 2; // filter button in page field row
+
+ nTabStartCol = aStartPos.Col();
+ nTabStartRow = aStartPos.Row() + (USHORT)nPageSize; // below page fields
+ nMemberStartCol = nTabStartCol;
+ nMemberStartRow = nTabStartRow + (USHORT) nHeaderSize;
+ nDataStartCol = nMemberStartCol + (USHORT)nRowFieldCount;
+ nDataStartRow = nMemberStartRow + (USHORT)nColFieldCount;
+ nTabEndCol = nDataStartCol + (USHORT)nColCount - 1;
+ nTabEndRow = nDataStartRow + (USHORT)nRowCount - 1;
+ bSizesValid = TRUE;
+ }
+}
+
+void ScDPOutput::Output()
+{
+ long nField;
+ USHORT nTab = aStartPos.Tab();
+ const uno::Sequence<sheet::DataResult>* pRowAry = aData.getConstArray();
+
+ // calculate output positions and sizes
+
+ CalcSizes();
+
+ // clear whole (new) output area
+ //! when modifying table, clear old area
+ //! include IDF_OBJECTS ???
+ pDoc->DeleteAreaTab( aStartPos.Col(), aStartPos.Row(), nTabEndCol, nTabEndRow, nTab, IDF_ALL );
+
+ if ( bDoFilter )
+ lcl_DoFilterButton( pDoc, aStartPos.Col(), aStartPos.Row(), nTab );
+
+ // data description
+ // (may get overwritten by first row field)
+
+ String aDesc = aDataDescription;
+ if ( !aDesc.Len() )
+ {
+ //! use default string ("result") ?
+ }
+ pDoc->SetString( nTabStartCol, nTabStartRow, nTab, aDesc );
+
+ // set STR_PIVOT_STYLE_INNER for whole data area (subtotals are overwritten)
+
+ if ( nDataStartRow > nTabStartRow )
+ lcl_SetStyleById( pDoc, nTab, nTabStartCol, nTabStartRow, nTabEndCol, nDataStartRow-1,
+ STR_PIVOT_STYLE_TOP );
+ lcl_SetStyleById( pDoc, nTab, nDataStartCol, nDataStartRow, nTabEndCol, nTabEndRow,
+ STR_PIVOT_STYLE_INNER );
+
+ // output column headers:
+
+ for (nField=0; nField<nColFieldCount; nField++)
+ {
+ USHORT nHdrCol = nDataStartCol + (USHORT)nField; //! check for overflow
+ FieldCell( nHdrCol, nTabStartRow, nTab, pColFields[nField].aCaption );
+
+ USHORT nRowPos = nMemberStartRow + (USHORT)nField; //! check for overflow
+ const uno::Sequence<sheet::MemberResult> rSequence = pColFields[nField].aResult;
+ const sheet::MemberResult* pArray = rSequence.getConstArray();
+ long nThisColCount = rSequence.getLength();
+ DBG_ASSERT( nThisColCount == nColCount, "count mismatch" ); //! ???
+ for (long nCol=0; nCol<nThisColCount; nCol++)
+ {
+ USHORT nColPos = nDataStartCol + (USHORT)nCol; //! check for overflow
+ HeaderCell( nColPos, nRowPos, nTab, pArray[nCol], TRUE, nField );
+ if ( ( pArray[nCol].Flags & sheet::MemberResultFlags::HASMEMBER ) &&
+ !( pArray[nCol].Flags & sheet::MemberResultFlags::SUBTOTAL ) )
+ {
+ if ( nField+1 < nColFieldCount )
+ {
+ long nEnd = nCol;
+ while ( nEnd+1 < nThisColCount && ( pArray[nEnd+1].Flags & sheet::MemberResultFlags::CONTINUE ) )
+ ++nEnd;
+ USHORT nEndColPos = nDataStartCol + (USHORT)nEnd; //! check for overflow
+ lcl_SetFrame( pDoc,nTab, nColPos,nRowPos, nEndColPos,nRowPos, 20 );
+ lcl_SetFrame( pDoc,nTab, nColPos,nRowPos, nEndColPos,nTabEndRow, 20 );
+
+ lcl_SetStyleById( pDoc, nTab, nColPos,nRowPos, nEndColPos,nDataStartRow-1, STR_PIVOT_STYLE_CATEGORY );
+ }
+ else
+ lcl_SetStyleById( pDoc, nTab, nColPos,nRowPos, nColPos,nDataStartRow-1, STR_PIVOT_STYLE_CATEGORY );
+ }
+ }
+ }
+
+ // output row headers:
+
+ for (nField=0; nField<nRowFieldCount; nField++)
+ {
+ USHORT nHdrCol = nTabStartCol + (USHORT)nField; //! check for overflow
+ USHORT nHdrRow = nDataStartRow - 1;
+ FieldCell( nHdrCol, nHdrRow, nTab, pRowFields[nField].aCaption );
+
+ USHORT nColPos = nMemberStartCol + (USHORT)nField; //! check for overflow
+ const uno::Sequence<sheet::MemberResult> rSequence = pRowFields[nField].aResult;
+ const sheet::MemberResult* pArray = rSequence.getConstArray();
+ long nThisRowCount = rSequence.getLength();
+ DBG_ASSERT( nThisRowCount == nRowCount, "count mismatch" ); //! ???
+ for (long nRow=0; nRow<nThisRowCount; nRow++)
+ {
+ USHORT nRowPos = nDataStartRow + (USHORT)nRow; //! check for overflow
+ HeaderCell( nColPos, nRowPos, nTab, pArray[nRow], FALSE, nField );
+ if ( ( pArray[nRow].Flags & sheet::MemberResultFlags::HASMEMBER ) &&
+ !( pArray[nRow].Flags & sheet::MemberResultFlags::SUBTOTAL ) )
+ {
+ if ( nField+1 < nRowFieldCount )
+ {
+ long nEnd = nRow;
+ while ( nEnd+1 < nThisRowCount && ( pArray[nEnd+1].Flags & sheet::MemberResultFlags::CONTINUE ) )
+ ++nEnd;
+ USHORT nEndRowPos = nDataStartRow + (USHORT)nEnd; //! check for overflow
+ lcl_SetFrame( pDoc,nTab, nColPos,nRowPos, nColPos,nEndRowPos, 20 );
+ lcl_SetFrame( pDoc,nTab, nColPos,nRowPos, nTabEndCol,nEndRowPos, 20 );
+
+ lcl_SetStyleById( pDoc, nTab, nColPos,nRowPos, nDataStartCol-1,nEndRowPos, STR_PIVOT_STYLE_CATEGORY );
+ }
+ else
+ lcl_SetStyleById( pDoc, nTab, nColPos,nRowPos, nDataStartCol-1,nRowPos, STR_PIVOT_STYLE_CATEGORY );
+ }
+ }
+ }
+
+ // output data results:
+
+ for (long nRow=0; nRow<nRowCount; nRow++)
+ {
+ USHORT nRowPos = nDataStartRow + (USHORT)nRow; //! check for overflow
+ const sheet::DataResult* pColAry = pRowAry[nRow].getConstArray();
+ long nThisColCount = pRowAry[nRow].getLength();
+ DBG_ASSERT( nThisColCount == nColCount, "count mismatch" ); //! ???
+ for (long nCol=0; nCol<nThisColCount; nCol++)
+ {
+ USHORT nColPos = nDataStartCol + (USHORT)nCol; //! check for overflow
+ DataCell( nColPos, nRowPos, nTab, pColAry[nCol] );
+ }
+ }
+
+ // frame around the whole table
+
+ lcl_SetFrame( pDoc,nTab, nDataStartCol,nDataStartRow, nTabEndCol,nTabEndRow, 20 );
+ if ( nDataStartCol > nMemberStartCol )
+ lcl_SetFrame( pDoc,nTab, nMemberStartCol,nDataStartRow, nDataStartCol-1,nTabEndRow, 20 );
+ if ( nDataStartRow > nMemberStartRow )
+ lcl_SetFrame( pDoc,nTab, nDataStartCol,nMemberStartRow, nTabEndCol,nDataStartRow-1, 20 );
+
+ lcl_SetFrame( pDoc,nTab, nTabStartCol,nTabStartRow, nTabEndCol,nTabEndRow, 40 );
+}
+
+ScRange ScDPOutput::GetOutputRange()
+{
+ CalcSizes();
+
+ USHORT nTab = aStartPos.Tab();
+ return ScRange( aStartPos.Col(), aStartPos.Row(), nTab, nTabEndCol, nTabEndRow, nTab);
+}
+
+//
+// Methods to find specific parts of the table
+//
+
+void ScDPOutput::GetPositionData( ScDPPositionData& rData, const ScAddress& rPos )
+{
+ //! preset rData to "invalid" ?
+
+ USHORT nCol = rPos.Col();
+ USHORT nRow = rPos.Row();
+ USHORT nTab = rPos.Tab();
+ if ( nTab != aStartPos.Tab() )
+ return; // wrong sheet
+
+ // calculate output positions and sizes
+
+ CalcSizes();
+
+ // test for column field
+
+ if ( nRow >= nMemberStartRow && nRow < nMemberStartRow + nColFieldCount )
+ {
+ long nField = nRow - nMemberStartRow;
+ const uno::Sequence<sheet::MemberResult> rSequence = pColFields[nField].aResult;
+ const sheet::MemberResult* pArray = rSequence.getConstArray();
+ long nThisColCount = rSequence.getLength();
+
+ if ( nCol >= nDataStartCol && nCol < nDataStartCol + nThisColCount )
+ {
+ long nItem = nCol - nDataStartCol;
+ // get origin of "continue" fields
+ while ( nItem > 0 && ( pArray[nItem].Flags & sheet::MemberResultFlags::CONTINUE ) )
+ --nItem;
+ rData.aMemberName = String(pArray[nItem].Name);
+ rData.nFlags = pArray[nItem].Flags;
+ rData.nDimension = pColFields[nField].nDim;
+ rData.nHierarchy = pColFields[nField].nHier;
+ rData.nLevel = pColFields[nField].nLevel;
+ return;
+ }
+ }
+
+ // test for row field
+
+ if ( nCol >= nMemberStartCol && nCol < nMemberStartCol + nRowFieldCount )
+ {
+ long nField = nCol - nMemberStartCol;
+ const uno::Sequence<sheet::MemberResult> rSequence = pRowFields[nField].aResult;
+ const sheet::MemberResult* pArray = rSequence.getConstArray();
+ long nThisRowCount = rSequence.getLength();
+
+ if ( nRow >= nDataStartRow && nRow < nDataStartRow + nThisRowCount )
+ {
+ long nItem = nRow - nDataStartRow;
+ // get origin of "continue" fields
+ while ( nItem > 0 && ( pArray[nItem].Flags & sheet::MemberResultFlags::CONTINUE ) )
+ --nItem;
+ rData.aMemberName = String(pArray[nItem].Name);
+ rData.nFlags = pArray[nItem].Flags;
+ rData.nDimension = pRowFields[nField].nDim;
+ rData.nHierarchy = pRowFields[nField].nHier;
+ rData.nLevel = pRowFields[nField].nLevel;
+ return;
+ }
+ }
+}
+
+BOOL ScDPOutput::IsFilterButton( const ScAddress& rPos )
+{
+ USHORT nCol = rPos.Col();
+ USHORT nRow = rPos.Row();
+ USHORT nTab = rPos.Tab();
+ if ( nTab != aStartPos.Tab() || !bDoFilter )
+ return FALSE; // wrong sheet or no button at all
+
+ // filter button is at top left
+ return ( nCol == aStartPos.Col() && nRow == aStartPos.Row() );
+}
+
+long ScDPOutput::GetHeaderDim( const ScAddress& rPos )
+{
+ USHORT nCol = rPos.Col();
+ USHORT nRow = rPos.Row();
+ USHORT nTab = rPos.Tab();
+ if ( nTab != aStartPos.Tab() )
+ return -1; // wrong sheet
+
+ // calculate output positions and sizes
+
+ CalcSizes();
+
+ // test for column header
+
+ if ( nRow == nTabStartRow && nCol >= nDataStartCol && nCol < nDataStartCol + nColFieldCount )
+ {
+ long nField = nCol - nDataStartCol;
+ return pColFields[nField].nDim;
+ }
+
+ // test for row header
+
+ if ( nRow+1 == nDataStartRow && nCol >= nTabStartCol == nCol < nTabStartCol + nRowFieldCount )
+ {
+ long nField = nCol - nTabStartCol;
+ return pRowFields[nField].nDim;
+ }
+
+ //! page fields
+ //! single data field (?)
+
+ return -1; // invalid
+}
+
+BOOL ScDPOutput::GetHeaderDrag( const ScAddress& rPos, BOOL bMouseLeft, BOOL bMouseTop,
+ long nDragDim,
+ Rectangle& rPosRect, USHORT& rOrient, long& rDimPos )
+{
+ // Rectangle instead of ScRange for rPosRect to allow for negative values
+
+ USHORT nCol = rPos.Col();
+ USHORT nRow = rPos.Row();
+ USHORT nTab = rPos.Tab();
+ if ( nTab != aStartPos.Tab() )
+ return FALSE; // wrong sheet
+
+ // calculate output positions and sizes
+
+ CalcSizes();
+
+ // test for column header
+
+ if ( nCol >= nDataStartCol && nCol <= nTabEndCol &&
+ nRow + 1 >= nMemberStartRow && nRow < nMemberStartRow + nColFieldCount )
+ {
+ long nField = nRow - nMemberStartRow;
+ if (nField < 0)
+ {
+ nField = 0;
+ bMouseTop = TRUE;
+ }
+ //! find start of dimension
+
+ rPosRect = Rectangle( nDataStartCol, nMemberStartRow + nField,
+ nTabEndCol, nMemberStartRow + nField -1 );
+
+ BOOL bFound = FALSE; // is this within the same orientation?
+ BOOL bBeforeDrag = FALSE;
+ BOOL bAfterDrag = FALSE;
+ for (long nPos=0; nPos<nColFieldCount && !bFound; nPos++)
+ {
+ if (pColFields[nPos].nDim == nDragDim)
+ {
+ bFound = TRUE;
+ if ( nField < nPos )
+ bBeforeDrag = TRUE;
+ else if ( nField > nPos )
+ bAfterDrag = TRUE;
+ }
+ }
+
+ if ( bFound )
+ {
+ if (!bBeforeDrag)
+ {
+ ++rPosRect.Bottom();
+ if (bAfterDrag)
+ ++rPosRect.Top();
+ }
+ }
+ else
+ {
+ if ( !bMouseTop )
+ {
+ ++rPosRect.Top();
+ ++rPosRect.Bottom();
+ ++nField;
+ }
+ }
+
+ rOrient = sheet::DataPilotFieldOrientation_COLUMN;
+ rDimPos = nField; //!...
+ return TRUE;
+ }
+
+ // test for row header
+
+ // special case if no row fields
+ BOOL bSpecial = ( nRow+1 >= nDataStartRow && nRow <= nTabEndRow &&
+ nRowFieldCount == 0 && nCol == nTabStartCol && bMouseLeft );
+
+ if ( bSpecial || ( nRow+1 >= nDataStartRow && nRow <= nTabEndRow &&
+ nCol + 1 >= nTabStartCol && nCol < nTabStartCol + nRowFieldCount ) )
+ {
+ long nField = nCol - nTabStartCol;
+ //! find start of dimension
+
+ rPosRect = Rectangle( nTabStartCol + nField, nDataStartRow - 1,
+ nTabStartCol + nField - 1, nTabEndRow );
+
+ BOOL bFound = FALSE; // is this within the same orientation?
+ BOOL bBeforeDrag = FALSE;
+ BOOL bAfterDrag = FALSE;
+ for (long nPos=0; nPos<nRowFieldCount && !bFound; nPos++)
+ {
+ if (pRowFields[nPos].nDim == nDragDim)
+ {
+ bFound = TRUE;
+ if ( nField < nPos )
+ bBeforeDrag = TRUE;
+ else if ( nField > nPos )
+ bAfterDrag = TRUE;
+ }
+ }
+
+ if ( bFound )
+ {
+ if (!bBeforeDrag)
+ {
+ ++rPosRect.Right();
+ if (bAfterDrag)
+ ++rPosRect.Left();
+ }
+ }
+ else
+ {
+ if ( !bMouseLeft )
+ {
+ ++rPosRect.Left();
+ ++rPosRect.Right();
+ ++nField;
+ }
+ }
+
+ rOrient = sheet::DataPilotFieldOrientation_ROW;
+ rDimPos = nField; //!...
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
diff --git a/sc/source/core/data/dpsave.cxx b/sc/source/core/data/dpsave.cxx
new file mode 100644
index 000000000000..461928f98235
--- /dev/null
+++ b/sc/source/core/data/dpsave.cxx
@@ -0,0 +1,945 @@
+/*************************************************************************
+ *
+ * $RCSfile: dpsave.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:14 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "dpsave.hxx"
+#include "miscuno.hxx"
+#include "scerrors.hxx"
+
+#include <tools/debug.hxx>
+#include <tools/stream.hxx>
+#include <vos/xception.hxx>
+
+#include <com/sun/star/sheet/GeneralFunction.hpp>
+#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
+#include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
+#include <com/sun/star/sheet/XLevelsSupplier.hpp>
+#include <com/sun/star/sheet/XMembersSupplier.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+
+using namespace com::sun::star;
+
+// -----------------------------------------------------------------------
+
+#define SC_DPSAVEMODE_NO 0
+#define SC_DPSAVEMODE_YES 1
+#define SC_DPSAVEMODE_DONTKNOW 2
+
+// -----------------------------------------------------------------------
+
+//! move to a header file
+#define DP_PROP_COLUMNGRAND "ColumnGrand"
+#define DP_PROP_FUNCTION "Function"
+#define DP_PROP_IGNOREEMPTY "IgnoreEmptyRows"
+#define DP_PROP_ISDATALAYOUT "IsDataLayoutDimension"
+#define DP_PROP_ISVISIBLE "IsVisible"
+#define DP_PROP_ORIENTATION "Orientation"
+#define DP_PROP_REPEATIFEMPTY "RepeatIfEmpty"
+#define DP_PROP_ROWGRAND "RowGrand"
+#define DP_PROP_SHOWDETAILS "ShowDetails"
+#define DP_PROP_SHOWEMPTY "ShowEmpty"
+#define DP_PROP_SUBTOTALS "SubTotals"
+#define DP_PROP_USEDHIERARCHY "UsedHierarchy"
+
+// -----------------------------------------------------------------------
+
+void lcl_SetBoolProperty( const uno::Reference<beans::XPropertySet>& xProp,
+ const rtl::OUString& rName, sal_Bool bValue )
+{
+ //! move to ScUnoHelpFunctions?
+
+ xProp->setPropertyValue( rName, uno::Any( &bValue, getBooleanCppuType() ) );
+}
+
+// -----------------------------------------------------------------------
+
+void lcl_SkipExtra( SvStream& rStream )
+{
+ USHORT nExtra;
+ rStream >> nExtra;
+ if ( nExtra )
+ {
+ rStream.SeekRel( nExtra );
+ if ( rStream.GetError() == SVSTREAM_OK )
+ rStream.SetError( SCWARN_IMPORT_INFOLOST );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ScDPSaveMember::ScDPSaveMember(const String& rName) :
+ aName( rName ),
+ nVisibleMode( SC_DPSAVEMODE_DONTKNOW ),
+ nShowDetailsMode( SC_DPSAVEMODE_DONTKNOW )
+{
+}
+
+ScDPSaveMember::ScDPSaveMember(const ScDPSaveMember& r) :
+ aName( r.aName ),
+ nVisibleMode( r.nVisibleMode ),
+ nShowDetailsMode( r.nShowDetailsMode )
+{
+}
+
+ScDPSaveMember::ScDPSaveMember(SvStream& rStream)
+{
+ rStream.ReadByteString( aName, rStream.GetStreamCharSet() );
+ rStream >> nVisibleMode;
+ rStream >> nShowDetailsMode;
+
+ lcl_SkipExtra( rStream ); // reads at least 1 USHORT
+}
+
+void ScDPSaveMember::Store( SvStream& rStream ) const
+{
+ rStream.WriteByteString( aName, rStream.GetStreamCharSet() );
+ rStream << nVisibleMode;
+ rStream << nShowDetailsMode;
+
+ rStream << (USHORT) 0; // nExtra
+}
+
+ScDPSaveMember::~ScDPSaveMember()
+{
+}
+
+BOOL ScDPSaveMember::operator== ( const ScDPSaveMember& r ) const
+{
+ if ( aName != r.aName ||
+ nVisibleMode != r.nVisibleMode ||
+ nShowDetailsMode != r.nShowDetailsMode )
+ return FALSE;
+
+ return TRUE;
+}
+
+void ScDPSaveMember::SetIsVisible(BOOL bSet)
+{
+ nVisibleMode = bSet;
+}
+
+void ScDPSaveMember::SetShowDetails(BOOL bSet)
+{
+ nShowDetailsMode = bSet;
+}
+
+void ScDPSaveMember::WriteToSource( const uno::Reference<uno::XInterface>& xMember )
+{
+ // nothing to do?
+ if ( nVisibleMode == SC_DPSAVEMODE_DONTKNOW && nShowDetailsMode == SC_DPSAVEMODE_DONTKNOW )
+ return;
+
+ uno::Reference<beans::XPropertySet> xMembProp( xMember, uno::UNO_QUERY );
+ DBG_ASSERT( xMembProp.is(), "no properties at member" );
+ if ( xMembProp.is() )
+ {
+ // exceptions are caught at ScDPSaveData::WriteToSource
+
+ if ( nVisibleMode != SC_DPSAVEMODE_DONTKNOW )
+ lcl_SetBoolProperty( xMembProp,
+ rtl::OUString::createFromAscii(DP_PROP_ISVISIBLE), (BOOL)nVisibleMode );
+
+ if ( nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW )
+ lcl_SetBoolProperty( xMembProp,
+ rtl::OUString::createFromAscii(DP_PROP_SHOWDETAILS), (BOOL)nShowDetailsMode );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ScDPSaveDimension::ScDPSaveDimension(const String& rName, BOOL bDataLayout) :
+ aName( rName ),
+ bIsDataLayout( bDataLayout ),
+ bDupFlag( FALSE ),
+ nOrientation( sheet::DataPilotFieldOrientation_HIDDEN ),
+ bSubTotalDefault( TRUE ),
+ nSubTotalCount( 0 ),
+ pSubTotalFuncs( NULL ),
+ nShowEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
+ nFunction( sheet::GeneralFunction_AUTO ),
+ nUsedHierarchy( -1 ),
+ pLayoutName( NULL )
+{
+}
+
+ScDPSaveDimension::ScDPSaveDimension(const ScDPSaveDimension& r) :
+ aName( r.aName ),
+ bIsDataLayout( r.bIsDataLayout ),
+ bDupFlag( r.bDupFlag ),
+ nOrientation( r.nOrientation ),
+ bSubTotalDefault( r.bSubTotalDefault ),
+ nSubTotalCount( r.nSubTotalCount ),
+ pSubTotalFuncs( NULL ),
+ nShowEmptyMode( r.nShowEmptyMode ),
+ nFunction( r.nFunction ),
+ nUsedHierarchy( r.nUsedHierarchy )
+{
+ if ( nSubTotalCount && r.pSubTotalFuncs )
+ {
+ pSubTotalFuncs = new USHORT[nSubTotalCount];
+ for (long nSub=0; nSub<nSubTotalCount; nSub++)
+ pSubTotalFuncs[nSub] = r.pSubTotalFuncs[nSub];
+ }
+
+ long nCount = r.aMemberList.Count();
+ for (long i=0; i<nCount; i++)
+ {
+ ScDPSaveMember* pNew = new ScDPSaveMember( *(ScDPSaveMember*)r.aMemberList.GetObject(i) );
+ aMemberList.Insert( pNew, LIST_APPEND );
+ }
+ if (r.pLayoutName)
+ pLayoutName = new String( *(r.pLayoutName) );
+ else
+ pLayoutName = NULL;
+}
+
+ScDPSaveDimension::ScDPSaveDimension(SvStream& rStream)
+{
+ long i;
+
+ rStream.ReadByteString( aName, rStream.GetStreamCharSet() );
+ rStream >> bIsDataLayout;
+
+ rStream >> bDupFlag;
+
+ rStream >> nOrientation;
+ rStream >> nFunction; // enum GeneralFunction
+ rStream >> nUsedHierarchy;
+
+ rStream >> nShowEmptyMode; //! at level
+
+ rStream >> bSubTotalDefault; //! at level
+ rStream >> nSubTotalCount;
+ if (nSubTotalCount)
+ {
+ pSubTotalFuncs = new USHORT[nSubTotalCount];
+ for (i=0; i<nSubTotalCount; i++)
+ rStream >> pSubTotalFuncs[i];
+ }
+ else
+ pSubTotalFuncs = NULL;
+
+ lcl_SkipExtra( rStream ); // reads at least 1 USHORT
+
+ long nNewCount;
+ rStream >> nNewCount;
+ for (i=0; i<nNewCount; i++)
+ {
+ ScDPSaveMember* pNew = new ScDPSaveMember( rStream );
+ aMemberList.Insert( pNew, LIST_APPEND );
+ }
+ pLayoutName = NULL;
+}
+
+void ScDPSaveDimension::Store( SvStream& rStream ) const
+{
+ long i;
+
+ rStream.WriteByteString( aName, rStream.GetStreamCharSet() );
+ rStream << bIsDataLayout;
+
+ rStream << bDupFlag;
+
+ rStream << nOrientation;
+ rStream << nFunction; // enum GeneralFunction
+ rStream << nUsedHierarchy;
+
+ rStream << nShowEmptyMode; //! at level
+
+ //! subtotals at level
+ rStream << bSubTotalDefault;
+ long nSubCnt = pSubTotalFuncs ? nSubTotalCount : 0;
+ rStream << nSubCnt;
+ for (i=0; i<nSubCnt; i++)
+ rStream << pSubTotalFuncs[i];
+
+ rStream << (USHORT) 0; // nExtra
+
+ long nCount = aMemberList.Count();
+ rStream << nCount;
+ for (i=0; i<nCount; i++)
+ {
+ const ScDPSaveMember* pMember = (const ScDPSaveMember*)aMemberList.GetObject(i);
+ pMember->Store( rStream );
+ }
+}
+
+ScDPSaveDimension::~ScDPSaveDimension()
+{
+ long nCount = aMemberList.Count();
+ for (long i=0; i<nCount; i++)
+ delete (ScDPSaveMember*)aMemberList.GetObject(i);
+ aMemberList.Clear();
+ if (pLayoutName)
+ delete pLayoutName;
+}
+
+BOOL ScDPSaveDimension::operator== ( const ScDPSaveDimension& r ) const
+{
+ if ( aName != r.aName ||
+ bIsDataLayout != r.bIsDataLayout ||
+ bDupFlag != r.bDupFlag ||
+ nOrientation != r.nOrientation ||
+ nFunction != r.nFunction ||
+ nUsedHierarchy != r.nUsedHierarchy ||
+ nShowEmptyMode != r.nShowEmptyMode ||
+ bSubTotalDefault != r.bSubTotalDefault ||
+ nSubTotalCount != r.nSubTotalCount )
+ return FALSE;
+
+ if ( nSubTotalCount && ( !pSubTotalFuncs || !r.pSubTotalFuncs ) ) // should not happen
+ return FALSE;
+
+ long i;
+ for (i=0; i<nSubTotalCount; i++)
+ if ( pSubTotalFuncs[i] != r.pSubTotalFuncs[i] )
+ return FALSE;
+
+ long nCount = aMemberList.Count();
+ if ( nCount != r.aMemberList.Count() )
+ return FALSE;
+
+ for (i=0; i<nCount; i++)
+ if ( !( *(ScDPSaveMember*)aMemberList.GetObject(i) ==
+ *(ScDPSaveMember*)r.aMemberList.GetObject(i) ) )
+ return FALSE;
+
+ return TRUE;
+}
+
+
+void ScDPSaveDimension::SetOrientation(USHORT nNew)
+{
+ nOrientation = nNew;
+}
+
+void ScDPSaveDimension::SetSubTotals(BOOL bSet)
+{
+ if (bSet)
+ {
+ USHORT nFunc = sheet::GeneralFunction_AUTO;
+ SetSubTotals( 1, &nFunc );
+ }
+ else
+ SetSubTotals( 0, NULL );
+}
+
+void ScDPSaveDimension::SetSubTotals(long nCount, const USHORT* pFuncs)
+{
+ if (pSubTotalFuncs)
+ delete pSubTotalFuncs;
+ nSubTotalCount = nCount;
+ if ( nCount && pFuncs )
+ {
+ pSubTotalFuncs = new USHORT[nCount];
+ for (long i=0; i<nCount; i++)
+ pSubTotalFuncs[i] = pFuncs[i];
+ }
+ else
+ pSubTotalFuncs = NULL;
+
+ bSubTotalDefault = FALSE;
+}
+
+void ScDPSaveDimension::SetShowEmpty(BOOL bSet)
+{
+ nShowEmptyMode = bSet;
+}
+
+void ScDPSaveDimension::SetFunction(USHORT nNew)
+{
+ nFunction = nNew;
+}
+
+void ScDPSaveDimension::SetUsedHierarchy(long nNew)
+{
+ nUsedHierarchy = nNew;
+}
+
+void ScDPSaveDimension::SetLayoutName(const String* pName)
+{
+ if (pName)
+ {
+ if (pLayoutName)
+ delete pLayoutName;
+ pLayoutName = new String( *pName );
+ }
+}
+
+const String& ScDPSaveDimension::GetLayoutName() const
+{
+ if (pLayoutName)
+ return *pLayoutName;
+ return aName;
+}
+
+ScDPSaveMember* ScDPSaveDimension::GetMemberByName(const String& rName)
+{
+ long nCount = aMemberList.Count();
+ for (long i=0; i<nCount; i++)
+ {
+ ScDPSaveMember* pMember = (ScDPSaveMember*)aMemberList.GetObject(i);
+ if ( pMember->GetName() == rName )
+ return pMember;
+ }
+ ScDPSaveMember* pNew = new ScDPSaveMember( rName );
+ aMemberList.Insert( pNew, LIST_APPEND );
+ return pNew;
+}
+
+void ScDPSaveDimension::WriteToSource( const uno::Reference<uno::XInterface>& xDim )
+{
+ uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
+ DBG_ASSERT( xDimProp.is(), "no properties at dimension" );
+ if ( xDimProp.is() )
+ {
+ // exceptions are caught at ScDPSaveData::WriteToSource
+ uno::Any aAny;
+
+ sheet::DataPilotFieldOrientation eOrient = (sheet::DataPilotFieldOrientation)nOrientation;
+ aAny <<= eOrient;
+ xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_ORIENTATION), aAny );
+
+ sheet::GeneralFunction eFunc = (sheet::GeneralFunction)nFunction;
+ aAny <<= eFunc;
+ xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_FUNCTION), aAny );
+
+ if ( nUsedHierarchy >= 0 )
+ {
+ aAny <<= (INT32)nUsedHierarchy;
+ xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_USEDHIERARCHY), aAny );
+ }
+ }
+
+ // Level loop outside of aMemberList loop
+ // because SubTotals have to be set independently of known members
+
+ long nCount = aMemberList.Count();
+
+ long nHierCount = 0;
+ uno::Reference<container::XIndexAccess> xHiers;
+ uno::Reference<sheet::XHierarchiesSupplier> xHierSupp( xDim, uno::UNO_QUERY );
+ if ( xHierSupp.is() )
+ {
+ uno::Reference<container::XNameAccess> xHiersName = xHierSupp->getHierarchies();
+ xHiers = new ScNameToIndexAccess( xHiersName );
+ nHierCount = xHiers->getCount();
+ }
+
+ for (long nHier=0; nHier<nHierCount; nHier++)
+ {
+ uno::Reference<uno::XInterface> xHierarchy = ScUnoHelpFunctions::AnyToInterface( xHiers->getByIndex(nHier) );
+
+ long nLevCount = 0;
+ uno::Reference<container::XIndexAccess> xLevels;
+ uno::Reference<sheet::XLevelsSupplier> xLevSupp( xHierarchy, uno::UNO_QUERY );
+ if ( xLevSupp.is() )
+ {
+ uno::Reference<container::XNameAccess> xLevelsName = xLevSupp->getLevels();
+ xLevels = new ScNameToIndexAccess( xLevelsName );
+ nLevCount = xLevels->getCount();
+ }
+
+ for (long nLev=0; nLev<nLevCount; nLev++)
+ {
+ uno::Reference<uno::XInterface> xLevel = ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex(nLev) );
+ uno::Reference<beans::XPropertySet> xLevProp( xLevel, uno::UNO_QUERY );
+ DBG_ASSERT( xLevProp.is(), "no properties at level" );
+ if ( xLevProp.is() )
+ {
+ if ( !bSubTotalDefault )
+ {
+ if ( !pSubTotalFuncs )
+ nSubTotalCount = 0;
+
+ uno::Sequence<sheet::GeneralFunction> aSeq(nSubTotalCount);
+ sheet::GeneralFunction* pArray = aSeq.getArray();
+ for (long i=0; i<nSubTotalCount; i++)
+ pArray[i] = (sheet::GeneralFunction)pSubTotalFuncs[i];
+ uno::Any aAny;
+ aAny <<= aSeq;
+ xLevProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_SUBTOTALS), aAny );
+ }
+ if ( nShowEmptyMode != SC_DPSAVEMODE_DONTKNOW )
+ lcl_SetBoolProperty( xLevProp,
+ rtl::OUString::createFromAscii(DP_PROP_SHOWEMPTY), (BOOL)nShowEmptyMode );
+
+ // exceptions are caught at ScDPSaveData::WriteToSource
+ }
+
+ if ( nCount > 0 )
+ {
+ uno::Reference<sheet::XMembersSupplier> xMembSupp( xLevel, uno::UNO_QUERY );
+ if ( xMembSupp.is() )
+ {
+ uno::Reference<container::XNameAccess> xMembers = xMembSupp->getMembers();
+ if ( xMembers.is() )
+ {
+ for (long i=0; i<nCount; i++)
+ {
+ ScDPSaveMember* pMember = (ScDPSaveMember*)aMemberList.GetObject(i);
+ rtl::OUString aName = pMember->GetName();
+ if ( xMembers->hasByName( aName ) )
+ {
+ uno::Reference<uno::XInterface> xMemberInt = ScUnoHelpFunctions::AnyToInterface(
+ xMembers->getByName( aName ) );
+ pMember->WriteToSource( xMemberInt );
+ }
+ // missing member is no error
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ScDPSaveData::ScDPSaveData() :
+ nColumnGrandMode( SC_DPSAVEMODE_DONTKNOW ),
+ nRowGrandMode( SC_DPSAVEMODE_DONTKNOW ),
+ nIgnoreEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
+ nRepeatEmptyMode( SC_DPSAVEMODE_DONTKNOW )
+{
+}
+
+ScDPSaveData::ScDPSaveData(const ScDPSaveData& r) :
+ nColumnGrandMode( r.nColumnGrandMode ),
+ nRowGrandMode( r.nRowGrandMode ),
+ nIgnoreEmptyMode( r.nIgnoreEmptyMode ),
+ nRepeatEmptyMode( r.nRepeatEmptyMode )
+{
+ long nCount = r.aDimList.Count();
+ for (long i=0; i<nCount; i++)
+ {
+ ScDPSaveDimension* pNew = new ScDPSaveDimension( *(ScDPSaveDimension*)r.aDimList.GetObject(i) );
+ aDimList.Insert( pNew, LIST_APPEND );
+ }
+}
+
+ScDPSaveData& ScDPSaveData::operator= ( const ScDPSaveData& r )
+{
+ if ( &r != this )
+ {
+ nColumnGrandMode = r.nColumnGrandMode;
+ nRowGrandMode = r.nRowGrandMode;
+ nIgnoreEmptyMode = r.nIgnoreEmptyMode;
+ nRepeatEmptyMode = r.nRepeatEmptyMode;
+
+ // remove old dimensions
+
+ long nCount = aDimList.Count();
+ long i;
+ for (i=0; i<nCount; i++)
+ delete (ScDPSaveDimension*)aDimList.GetObject(i);
+ aDimList.Clear();
+
+ // copy new dimensions
+
+ nCount = r.aDimList.Count();
+ for (i=0; i<nCount; i++)
+ {
+ ScDPSaveDimension* pNew =
+ new ScDPSaveDimension( *(ScDPSaveDimension*)r.aDimList.GetObject(i) );
+ aDimList.Insert( pNew, LIST_APPEND );
+ }
+ }
+ return *this;
+}
+
+BOOL ScDPSaveData::operator== ( const ScDPSaveData& r ) const
+{
+ if ( nColumnGrandMode != r.nColumnGrandMode ||
+ nRowGrandMode != r.nRowGrandMode ||
+ nIgnoreEmptyMode != r.nIgnoreEmptyMode ||
+ nRepeatEmptyMode != r.nRepeatEmptyMode )
+ return FALSE;
+
+ long nCount = aDimList.Count();
+ if ( nCount != r.aDimList.Count() )
+ return FALSE;
+
+ for (long i=0; i<nCount; i++)
+ if ( !( *(ScDPSaveDimension*)aDimList.GetObject(i) ==
+ *(ScDPSaveDimension*)r.aDimList.GetObject(i) ) )
+ return FALSE;
+
+ return TRUE;
+}
+
+ScDPSaveData::~ScDPSaveData()
+{
+ long nCount = aDimList.Count();
+ for (long i=0; i<nCount; i++)
+ delete (ScDPSaveDimension*)aDimList.GetObject(i);
+ aDimList.Clear();
+}
+
+ScDPSaveDimension* ScDPSaveData::GetDimensionByName(const String& rName)
+{
+ long nCount = aDimList.Count();
+ for (long i=0; i<nCount; i++)
+ {
+ ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
+ if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
+ return pDim;
+ }
+ ScDPSaveDimension* pNew = new ScDPSaveDimension( rName, FALSE );
+ aDimList.Insert( pNew, LIST_APPEND );
+ return pNew;
+}
+
+ScDPSaveDimension* ScDPSaveData::GetExistingDimensionByName(const String& rName)
+{
+ long nCount = aDimList.Count();
+ for (long i=0; i<nCount; i++)
+ {
+ ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
+ if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
+ return pDim;
+ }
+ return NULL; // don't create new
+}
+
+ScDPSaveDimension* ScDPSaveData::GetNewDimensionByName(const String& rName)
+{
+ long nCount = aDimList.Count();
+ for (long i=0; i<nCount; i++)
+ {
+ ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
+ if ( pDim->GetName() == rName && !pDim->IsDataLayout() )
+ return DuplicateDimension(rName);
+ }
+ ScDPSaveDimension* pNew = new ScDPSaveDimension( rName, FALSE );
+ aDimList.Insert( pNew, LIST_APPEND );
+ return pNew;
+}
+
+ScDPSaveDimension* ScDPSaveData::GetDataLayoutDimension()
+{
+ long nCount = aDimList.Count();
+ for (long i=0; i<nCount; i++)
+ {
+ ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
+ if ( pDim->IsDataLayout() )
+ return pDim;
+ }
+ ScDPSaveDimension* pNew = new ScDPSaveDimension( String(), TRUE );
+ aDimList.Insert( pNew, LIST_APPEND );
+ return pNew;
+}
+
+ScDPSaveDimension* ScDPSaveData::DuplicateDimension(const String& rName)
+{
+ // always insert new
+ //! check if dimension is there?
+
+ ScDPSaveDimension* pOld = GetDimensionByName( rName );
+ ScDPSaveDimension* pNew = new ScDPSaveDimension( *pOld );
+ pNew->SetDupFlag( TRUE );
+ aDimList.Insert( pNew, LIST_APPEND );
+ return pNew;
+}
+
+void ScDPSaveData::SetPosition( ScDPSaveDimension* pDim, long nNew )
+{
+ // position (nNew) is counted within dimensions of the same orientation
+
+ USHORT nOrient = pDim->GetOrientation();
+
+ aDimList.Remove( pDim );
+ ULONG nCount = aDimList.Count(); // after remove
+
+ ULONG nInsPos = 0;
+ while ( nNew > 0 && nInsPos < nCount )
+ {
+ if ( ((ScDPSaveDimension*)aDimList.GetObject(nInsPos))->GetOrientation() == nOrient )
+ --nNew;
+ ++nInsPos;
+ }
+
+ aDimList.Insert( pDim, nInsPos );
+}
+
+void ScDPSaveData::SetColumnGrand(BOOL bSet)
+{
+ nColumnGrandMode = bSet;
+}
+
+void ScDPSaveData::SetRowGrand(BOOL bSet)
+{
+ nRowGrandMode = bSet;
+}
+
+void ScDPSaveData::SetIgnoreEmptyRows(BOOL bSet)
+{
+ nIgnoreEmptyMode = bSet;
+}
+
+void ScDPSaveData::SetRepeatIfEmpty(BOOL bSet)
+{
+ nRepeatEmptyMode = bSet;
+}
+
+void lcl_ResetOrient( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
+{
+ sheet::DataPilotFieldOrientation eOrient = sheet::DataPilotFieldOrientation_HIDDEN;
+
+ uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
+ uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
+ long nIntCount = xIntDims->getCount();
+ for (long nIntDim=0; nIntDim<nIntCount; nIntDim++)
+ {
+ uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
+ uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
+ if (xDimProp.is())
+ {
+ uno::Any aAny;
+ aAny <<= eOrient;
+ xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_ORIENTATION), aAny );
+ }
+ }
+}
+
+void ScDPSaveData::WriteToSource( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
+{
+ if (!xSource.is())
+ return;
+
+ // source options must be first!
+
+ uno::Reference<beans::XPropertySet> xSourceProp( xSource, uno::UNO_QUERY );
+ DBG_ASSERT( xSourceProp.is(), "no properties at source" );
+ if ( xSourceProp.is() )
+ {
+ // source options are not available for external sources
+ //! use XPropertySetInfo to test for availability?
+
+ TRY
+ {
+ if ( nIgnoreEmptyMode != SC_DPSAVEMODE_DONTKNOW )
+ lcl_SetBoolProperty( xSourceProp,
+ rtl::OUString::createFromAscii(DP_PROP_IGNOREEMPTY), (BOOL)nIgnoreEmptyMode );
+ if ( nRepeatEmptyMode != SC_DPSAVEMODE_DONTKNOW )
+ lcl_SetBoolProperty( xSourceProp,
+ rtl::OUString::createFromAscii(DP_PROP_REPEATIFEMPTY), (BOOL)nRepeatEmptyMode );
+ }
+ CATCH_ALL()
+ {
+ // no error
+ }
+ END_CATCH
+ }
+
+ // exceptions in the other calls are errors
+ TRY
+ {
+ // reset all orientations
+ //! "forgetSettings" or similar at source ?????
+ //! reset all duplicated dimensions, or reuse them below !!!
+
+ lcl_ResetOrient( xSource );
+
+ long nCount = aDimList.Count();
+ for (long i=0; i<nCount; i++)
+ {
+ ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
+ rtl::OUString aName = pDim->GetName();
+ BOOL bData = pDim->IsDataLayout();
+
+ //! getByName for ScDPSource, including DataLayoutDimension !!!!!!!!
+
+ uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
+ uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
+ long nIntCount = xIntDims->getCount();
+ BOOL bFound = FALSE;
+ for (long nIntDim=0; nIntDim<nIntCount && !bFound; nIntDim++)
+ {
+ uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) );
+ if ( bData )
+ {
+ uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
+ if ( xDimProp.is() )
+ {
+ bFound = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
+ rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT) );
+ //! error checking -- is "IsDataLayoutDimension" property required??
+ }
+ }
+ else
+ {
+ uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
+ if ( xDimName.is() && xDimName->getName() == aName )
+ bFound = TRUE;
+ }
+
+ if ( bFound )
+ {
+ if ( pDim->GetDupFlag() )
+ {
+ String aNewName = pDim->GetName();
+
+ // different name for each duplication of a (real) dimension...
+ for (long j=0; j<=i; j++) //! Test !!!!!!
+ aNewName += '*'; //! modify name at creation of SaveDimension
+
+ uno::Reference<util::XCloneable> xCloneable( xIntDim, uno::UNO_QUERY );
+ DBG_ASSERT( xCloneable.is(), "cannot clone dimension" );
+ if (xCloneable.is())
+ {
+ uno::Reference<util::XCloneable> xNew = xCloneable->createClone();
+ uno::Reference<container::XNamed> xNewName( xNew, uno::UNO_QUERY );
+ if (xNewName.is())
+ {
+ xNewName->setName( aNewName );
+ pDim->WriteToSource( xNew );
+ }
+ }
+ }
+ else
+ pDim->WriteToSource( xIntDim );
+ }
+ }
+ DBG_ASSERT(bFound, "WriteToSource: Dimension not found");
+ }
+
+ if ( xSourceProp.is() )
+ {
+ if ( nColumnGrandMode != SC_DPSAVEMODE_DONTKNOW )
+ lcl_SetBoolProperty( xSourceProp,
+ rtl::OUString::createFromAscii(DP_PROP_COLUMNGRAND), (BOOL)nColumnGrandMode );
+ if ( nRowGrandMode != SC_DPSAVEMODE_DONTKNOW )
+ lcl_SetBoolProperty( xSourceProp,
+ rtl::OUString::createFromAscii(DP_PROP_ROWGRAND), (BOOL)nRowGrandMode );
+ }
+ }
+ CATCH_ALL()
+ {
+ DBG_ERROR("exception in WriteToSource");
+ }
+ END_CATCH
+}
+
+void ScDPSaveData::Store( SvStream& rStream ) const
+{
+ //! multi-header for individual entries
+
+ long nCount = aDimList.Count();
+ rStream << nCount;
+ for (long i=0; i<nCount; i++)
+ {
+ const ScDPSaveDimension* pDim = (const ScDPSaveDimension*)aDimList.GetObject(i);
+ pDim->Store( rStream );
+ }
+
+ rStream << nColumnGrandMode;
+ rStream << nRowGrandMode;
+ rStream << nIgnoreEmptyMode;
+ rStream << nRepeatEmptyMode;
+
+ rStream << (USHORT) 0; // nExtra
+}
+
+void ScDPSaveData::Load( SvStream& rStream )
+{
+ //! multi-header for individual entries
+
+ DBG_ASSERT( aDimList.Count()==0, "ScDPSaveData::Load not empty" );
+
+ long nNewCount;
+ rStream >> nNewCount;
+ for (long i=0; i<nNewCount; i++)
+ {
+ ScDPSaveDimension* pNew = new ScDPSaveDimension( rStream );
+ aDimList.Insert( pNew, LIST_APPEND );
+ }
+
+ rStream >> nColumnGrandMode;
+ rStream >> nRowGrandMode;
+ rStream >> nIgnoreEmptyMode;
+ rStream >> nRepeatEmptyMode;
+
+ lcl_SkipExtra( rStream ); // reads at least 1 USHORT
+}
+
+BOOL ScDPSaveData::IsEmpty() const
+{
+ long nCount = aDimList.Count();
+ for (long i=0; i<nCount; i++)
+ {
+ ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i);
+ if ( pDim->GetOrientation() != sheet::DataPilotFieldOrientation_HIDDEN && !pDim->IsDataLayout() )
+ return FALSE;
+ }
+ return TRUE; // no entries that are not hidden
+}
+
+
+
diff --git a/sc/source/core/data/dpsdbtab.cxx b/sc/source/core/data/dpsdbtab.cxx
new file mode 100644
index 000000000000..72568d95d4d1
--- /dev/null
+++ b/sc/source/core/data/dpsdbtab.cxx
@@ -0,0 +1,606 @@
+/*************************************************************************
+ *
+ * $RCSfile: dpsdbtab.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE --------------------------------------------------------------
+
+#include <tools/debug.hxx>
+#include <vcl/msgbox.hxx>
+#include <svtools/zforlist.hxx>
+#include <unotools/processfactory.hxx>
+
+#include <com/sun/star/sheet/DataImportMode.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XRowSet.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+#include "dpsdbtab.hxx"
+#include "collect.hxx"
+#include "global.hxx"
+#include "globstr.hrc"
+
+using namespace com::sun::star;
+
+#define SC_SERVICE_ROWSET "com.sun.star.sdb.RowSet"
+
+//! move to a header file?
+#define SC_DBPROP_DATASOURCENAME "DataSourceName"
+#define SC_DBPROP_COMMAND "Command"
+#define SC_DBPROP_COMMANDTYPE "CommandType"
+
+// -----------------------------------------------------------------------
+
+class ScDatabaseDPData_Impl
+{
+public:
+ ScImportSourceDesc aDesc;
+ long nColCount;
+ BOOL bValid;
+ BOOL bAtStart;
+ String* pTitles;
+ TypedStrCollection** ppStrings;
+ uno::Reference<sdbc::XRowSet> xRowSet;
+ sal_Int32* pTypes;
+ SvNumberFormatter* pFormatter;
+
+ ScDatabaseDPData_Impl() {}
+};
+
+// -----------------------------------------------------------------------
+
+ScDatabaseDPData::ScDatabaseDPData( const ScImportSourceDesc& rImport )
+{
+ pImpl = new ScDatabaseDPData_Impl;
+ pImpl->aDesc = rImport;
+ pImpl->nColCount = 0;
+ pImpl->bValid = FALSE;
+ pImpl->bAtStart = FALSE;
+ pImpl->pTitles = NULL;
+ pImpl->ppStrings = NULL;
+ pImpl->pTypes = NULL;
+ pImpl->pFormatter = NULL; // created on demand
+
+ OpenDatabase();
+}
+
+ScDatabaseDPData::~ScDatabaseDPData()
+{
+ delete[] pImpl->pTypes;
+ if ( pImpl->ppStrings )
+ {
+ for (long i=0; i<pImpl->nColCount; i++)
+ delete pImpl->ppStrings[i];
+ delete[] pImpl->ppStrings;
+ }
+ delete[] pImpl->pTitles;
+ delete pImpl->pFormatter; // NumberFormatter is local for this object
+ delete pImpl;
+}
+
+void ScDatabaseDPData::DisposeData()
+{
+ //! use OpenDatabase here?
+
+ //! column titles ???
+
+ // collections for column entries
+ if ( pImpl->ppStrings )
+ {
+ for (long i=0; i<pImpl->nColCount; i++)
+ {
+ delete pImpl->ppStrings[i];
+ pImpl->ppStrings[i] = NULL;
+ }
+ }
+
+ //! init entries on demand!
+ InitAllColumnEntries(); //! configurable ???
+}
+
+BOOL ScDatabaseDPData::OpenDatabase()
+{
+ sal_Int32 nSdbType = -1;
+ switch ( pImpl->aDesc.nType )
+ {
+ case sheet::DataImportMode_SQL: nSdbType = sdb::CommandType::COMMAND; break;
+ case sheet::DataImportMode_TABLE: nSdbType = sdb::CommandType::TABLE; break;
+ case sheet::DataImportMode_QUERY: nSdbType = sdb::CommandType::QUERY; break;
+ default:
+ return FALSE;
+ }
+
+ BOOL bSuccess = FALSE;
+ try
+ {
+ pImpl->xRowSet = uno::Reference<sdbc::XRowSet>(
+ utl::getProcessServiceFactory()->createInstance(
+ rtl::OUString::createFromAscii( SC_SERVICE_ROWSET ) ),
+ uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xRowProp( pImpl->xRowSet, uno::UNO_QUERY );
+ DBG_ASSERT( xRowProp.is(), "can't get RowSet" );
+ if ( xRowProp.is() )
+ {
+ //
+ // set source parameters
+ //
+
+ uno::Any aAny;
+
+ aAny <<= rtl::OUString( pImpl->aDesc.aDBName );
+ xRowProp->setPropertyValue(
+ rtl::OUString::createFromAscii(SC_DBPROP_DATASOURCENAME), aAny );
+
+ aAny <<= rtl::OUString( pImpl->aDesc.aObject );
+ xRowProp->setPropertyValue(
+ rtl::OUString::createFromAscii(SC_DBPROP_COMMAND), aAny );
+
+ aAny <<= nSdbType;
+ xRowProp->setPropertyValue(
+ rtl::OUString::createFromAscii(SC_DBPROP_COMMANDTYPE), aAny );
+
+ pImpl->xRowSet->execute();
+ pImpl->bAtStart = TRUE;
+
+ //
+ // get column descriptions
+ //
+
+ pImpl->nColCount = 0;
+ uno::Reference<sdbc::XResultSetMetaData> xMeta;
+ uno::Reference<sdbc::XResultSetMetaDataSupplier> xMetaSupp( pImpl->xRowSet, uno::UNO_QUERY );
+ if ( xMetaSupp.is() )
+ xMeta = xMetaSupp->getMetaData();
+ if ( xMeta.is() )
+ pImpl->nColCount = xMeta->getColumnCount(); // this is the number of real columns
+
+ uno::Reference<sdbc::XResultSet> xResSet( pImpl->xRowSet, uno::UNO_QUERY );
+ if ( pImpl->nColCount > 0 && xResSet.is() )
+ {
+ // get column titles
+ pImpl->pTitles = new String[pImpl->nColCount];
+ pImpl->pTypes = new sal_Int32[pImpl->nColCount];
+ for (long nCol=0; nCol<pImpl->nColCount; nCol++)
+ {
+ pImpl->pTitles[nCol] = xMeta->getColumnLabel( nCol+1 );
+ pImpl->pTypes[nCol] = xMeta->getColumnType( nCol+1 );
+ }
+
+ // collections for column entries
+ pImpl->ppStrings = new TypedStrCollection*[pImpl->nColCount];
+ for (long i=0; i<pImpl->nColCount; i++)
+ pImpl->ppStrings[i] = NULL;
+
+ //! init entries on demand!
+ InitAllColumnEntries(); //! configurable ???
+
+ bSuccess = TRUE;
+ }
+ }
+ }
+ catch ( sdbc::SQLException& rError )
+ {
+ //! store error message
+ InfoBox aInfoBox( 0, String(rError.Message) );
+ aInfoBox.Execute();
+ }
+ catch ( uno::Exception& )
+ {
+ DBG_ERROR("Unexpected exception in database");
+ }
+
+
+ if (!bSuccess)
+ pImpl->xRowSet.clear();
+ pImpl->bValid = bSuccess;
+ return bSuccess;
+}
+
+long ScDatabaseDPData::GetColumnCount()
+{
+ return pImpl->nColCount;
+}
+
+void lcl_FillItemData( ScDPItemData& rData,
+ const uno::Reference<sdbc::XRow>& xRow, long nRowPos,
+ long nType, BOOL bStringForVal, ScDatabaseDPData_Impl* pImpl )
+{
+ //! merge with lcl_PutData in dbdocimp.cxx
+
+ rData.aString.Erase();
+ rData.fValue = 0.0;
+ rData.bHasValue = FALSE;
+ short nNumType = NUMBERFORMAT_NUMBER;
+ BOOL bEmptyFlag = FALSE;
+
+ if (!xRow.is())
+ return;
+
+ try
+ {
+ switch ( nType )
+ {
+ case sdbc::DataType::BIT:
+ nNumType = NUMBERFORMAT_LOGICAL;
+ rData.fValue = (xRow->getBoolean(nRowPos) ? 1 : 0);
+ bEmptyFlag = ( rData.fValue == 0.0 ) && xRow->wasNull();
+ rData.bHasValue = TRUE;
+ break;
+
+ case sdbc::DataType::TINYINT:
+ case sdbc::DataType::SMALLINT:
+ case sdbc::DataType::INTEGER:
+ case sdbc::DataType::BIGINT:
+ case sdbc::DataType::FLOAT:
+ case sdbc::DataType::REAL:
+ case sdbc::DataType::DOUBLE:
+ case sdbc::DataType::NUMERIC:
+ case sdbc::DataType::DECIMAL:
+ //! do the conversion here?
+ rData.fValue = xRow->getDouble(nRowPos);
+ bEmptyFlag = ( rData.fValue == 0.0 ) && xRow->wasNull();
+ rData.bHasValue = TRUE;
+ break;
+
+ case sdbc::DataType::CHAR:
+ case sdbc::DataType::VARCHAR:
+ case sdbc::DataType::LONGVARCHAR:
+ rData.aString = xRow->getString(nRowPos);
+ bEmptyFlag = ( rData.aString.Len() == 0 ) && xRow->wasNull();
+ break;
+
+ case sdbc::DataType::DATE:
+ {
+ nNumType = NUMBERFORMAT_DATE;
+
+ if (!pImpl->pFormatter)
+ pImpl->pFormatter = new SvNumberFormatter( ScGlobal::eLnge );
+
+ util::Date aDate = xRow->getDate(nRowPos);
+ rData.fValue = Date( aDate.Day, aDate.Month, aDate.Year ) -
+ *pImpl->pFormatter->GetNullDate();
+ bEmptyFlag = xRow->wasNull();
+ rData.bHasValue = TRUE;
+ }
+ break;
+
+ //! case sdbc::DataType::TIME:
+ //! case sdbc::DataType::TIMESTAMP:
+
+ case sdbc::DataType::SQLNULL:
+ //bEmptyFlag = TRUE;
+ break;
+
+ case sdbc::DataType::BINARY:
+ case sdbc::DataType::VARBINARY:
+ case sdbc::DataType::LONGVARBINARY:
+ default:
+ //bError = TRUE; // unknown type
+ break;
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ //bError = TRUE;
+ }
+
+ if ( bEmptyFlag )
+ rData.bHasValue = FALSE; // empty -> empty string
+
+ if ( rData.bHasValue && bStringForVal )
+ {
+ if (!pImpl->pFormatter)
+ pImpl->pFormatter = new SvNumberFormatter( ScGlobal::eLnge );
+
+ ULONG nIndex = pImpl->pFormatter->GetStandardFormat( NUMBERFORMAT_DATE, ScGlobal::eLnge );
+ pImpl->pFormatter->GetInputLineString( rData.fValue, nIndex, rData.aString );
+ }
+}
+
+void lcl_Reset( const uno::Reference<sdbc::XRowSet>& xRowSet )
+ throw(sdbc::SQLException, uno::RuntimeException)
+{
+ // isBeforeFirst / beforeFirst is not always available
+ //! query if it is allowed
+
+ xRowSet->execute(); // restart
+}
+
+void ScDatabaseDPData::InitAllColumnEntries()
+{
+ DBG_ASSERT( pImpl->ppStrings, "GetColumnEntries: no entries" );
+ long nCol;
+ for ( nCol=0; nCol<pImpl->nColCount; nCol++ )
+ if (!pImpl->ppStrings[nCol])
+ pImpl->ppStrings[nCol] = new TypedStrCollection;
+
+// Sound::Beep(); //! Test !!!
+
+ uno::Reference<sdbc::XRowSet> xRowSet = pImpl->xRowSet;
+ uno::Reference<sdbc::XRow> xRow( xRowSet, uno::UNO_QUERY );
+ if ( xRow.is() )
+ {
+ ScDPItemData aItemData;
+
+ try
+ {
+ if ( !pImpl->bAtStart )
+ lcl_Reset( xRowSet );
+
+ pImpl->bAtStart = FALSE;
+ while ( xRowSet->next() )
+ {
+ for ( nCol=0; nCol<pImpl->nColCount; nCol++ )
+ {
+ //! get string for value data only if value hasn't been inserted yet
+ lcl_FillItemData( aItemData, xRow, nCol+1, pImpl->pTypes[nCol], TRUE, pImpl );
+ TypedStrData* pNew = new TypedStrData(
+ aItemData.aString, aItemData.fValue,
+ aItemData.bHasValue ? SC_STRTYPE_VALUE : SC_STRTYPE_STANDARD );
+ if (!pImpl->ppStrings[nCol]->Insert(pNew))
+ delete pNew;
+ }
+ }
+ }
+ catch ( sdbc::SQLException& rError )
+ {
+ //! store error message
+ InfoBox aInfoBox( 0, String(rError.Message) );
+ aInfoBox.Execute();
+ }
+ catch ( uno::Exception& )
+ {
+ DBG_ERROR("Unexpected exception in database");
+ }
+ }
+}
+
+const TypedStrCollection& ScDatabaseDPData::GetColumnEntries(long nColumn)
+{
+ DBG_ASSERT( pImpl->ppStrings && nColumn < pImpl->nColCount, "GetColumnEntries: no entries" );
+ if (!pImpl->ppStrings[nColumn])
+ {
+ TypedStrCollection* pColl = new TypedStrCollection;
+
+ //! select distinct values directly from database
+
+// Sound::Beep(); //! Test !!!
+
+ uno::Reference<sdbc::XRowSet> xRowSet = pImpl->xRowSet;
+ uno::Reference<sdbc::XRow> xRow( xRowSet, uno::UNO_QUERY );
+ if ( xRow.is() )
+ {
+ ScDPItemData aItemData;
+
+ try
+ {
+ if ( !pImpl->bAtStart )
+ lcl_Reset( xRowSet );
+
+ pImpl->bAtStart = FALSE;
+ while ( xRowSet->next() )
+ {
+ //! get string for value data only if value hasn't been inserted yet
+ lcl_FillItemData( aItemData, xRow, nColumn+1, pImpl->pTypes[nColumn], TRUE, pImpl );
+ TypedStrData* pNew = new TypedStrData(
+ aItemData.aString, aItemData.fValue,
+ aItemData.bHasValue ? SC_STRTYPE_VALUE : SC_STRTYPE_STANDARD );
+ if (!pColl->Insert(pNew))
+ delete pNew;
+ }
+ }
+ catch ( sdbc::SQLException& rError )
+ {
+ //! store error message
+ InfoBox aInfoBox( 0, String(rError.Message) );
+ aInfoBox.Execute();
+ }
+ catch ( uno::Exception& )
+ {
+ DBG_ERROR("Unexpected exception in database");
+ }
+ }
+
+ pImpl->ppStrings[nColumn] = pColl;
+ }
+ return *pImpl->ppStrings[nColumn];
+}
+
+String ScDatabaseDPData::getDimensionName(long nColumn)
+{
+ if (getIsDataLayoutDimension(nColumn))
+ {
+ //! different internal and display names?
+ //return "Data";
+ return ScGlobal::GetRscString(STR_PIVOT_DATA);
+ }
+ else if ( pImpl->pTitles && nColumn < pImpl->nColCount )
+ {
+ return pImpl->pTitles[nColumn];
+ }
+ DBG_ERROR("getDimensionName: invalid dimension");
+ return String();
+}
+
+BOOL ScDatabaseDPData::getIsDataLayoutDimension(long nColumn)
+{
+ return ( nColumn == pImpl->nColCount );
+}
+
+BOOL ScDatabaseDPData::IsDateDimension(long nDim)
+{
+ //! later...
+ return FALSE;
+}
+
+void ScDatabaseDPData::SetEmptyFlags( BOOL bIgnoreEmptyRows, BOOL bRepeatIfEmpty )
+{
+ // not used for database data
+ //! disable flags
+}
+
+void ScDatabaseDPData::ResetIterator()
+{
+ try
+ {
+ uno::Reference<sdbc::XRowSet> xRowSet = pImpl->xRowSet;
+ if ( xRowSet.is() && !pImpl->bAtStart )
+ {
+ lcl_Reset( xRowSet );
+ pImpl->bAtStart = TRUE;
+ }
+ }
+ catch ( sdbc::SQLException& rError )
+ {
+ //! store error message
+ InfoBox aInfoBox( 0, String(rError.Message) );
+ aInfoBox.Execute();
+ }
+ catch ( uno::Exception& )
+ {
+ DBG_ERROR("Unexpected exception in database");
+ }
+
+// Sound::Beep(); //! Test !!!
+}
+
+BOOL ScDatabaseDPData::GetNextRow( const ScDPTableIteratorParam& rParam )
+{
+ BOOL bSuccess = FALSE;
+ uno::Reference<sdbc::XRowSet> xRowSet = pImpl->xRowSet;
+ uno::Reference<sdbc::XRow> xRow( xRowSet, uno::UNO_QUERY );
+
+ try
+ {
+ pImpl->bAtStart = FALSE;
+ if ( xRow.is() && xRowSet->next() )
+ {
+ long i;
+
+ for (i=0; i<rParam.nColCount; i++)
+ {
+ long nDim = rParam.pCols[i];
+ if ( getIsDataLayoutDimension(nDim) )
+ rParam.pColData[i].SetString( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("x")) );
+ else
+ lcl_FillItemData( rParam.pColData[i], xRow, nDim+1, pImpl->pTypes[nDim], FALSE, pImpl );
+ }
+
+ for (i=0; i<rParam.nRowCount; i++)
+ {
+ long nDim = rParam.pRows[i];
+ if ( getIsDataLayoutDimension(nDim) )
+ rParam.pRowData[i].SetString( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("x")) );
+ else
+ lcl_FillItemData( rParam.pRowData[i], xRow, nDim+1, pImpl->pTypes[nDim], FALSE, pImpl );
+ }
+
+ for (i=0; i<rParam.nDatCount; i++)
+ {
+ //! merge this with lcl_FillItemData, distinguish all SC_VALTYPE_... types
+
+ long nDim = rParam.pDats[i];
+
+ double fVal = 0.0;
+ BYTE nType = SC_VALTYPE_EMPTY;
+ try
+ {
+ fVal = xRow->getDouble( nDim+1 );
+ }
+ catch ( uno::Exception& )
+ {
+ // anything that can't be converted to a number is a string
+ nType = SC_VALTYPE_STRING;
+ }
+ rParam.pValues[i].Set( fVal, SC_VALTYPE_VALUE );
+ }
+
+ bSuccess = TRUE;
+ }
+ }
+ catch ( sdbc::SQLException& rError )
+ {
+ //! store error message
+ InfoBox aInfoBox( 0, String(rError.Message) );
+ aInfoBox.Execute();
+ }
+ catch ( uno::Exception& )
+ {
+ DBG_ERROR("Unexpected exception in database");
+ }
+
+ return bSuccess;
+}
+
+// -----------------------------------------------------------------------
+
+
+
+
+
diff --git a/sc/source/core/data/dpshttab.cxx b/sc/source/core/data/dpshttab.cxx
new file mode 100644
index 000000000000..97678dd5ca4a
--- /dev/null
+++ b/sc/source/core/data/dpshttab.cxx
@@ -0,0 +1,422 @@
+/*************************************************************************
+ *
+ * $RCSfile: dpshttab.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE --------------------------------------------------------------
+
+#include <tools/debug.hxx>
+#include <svtools/zforlist.hxx>
+
+#include "dpshttab.hxx"
+#include "document.hxx"
+#include "collect.hxx"
+#include "cell.hxx"
+#include "globstr.hrc"
+
+// -----------------------------------------------------------------------
+
+class ScSheetDPData_Impl
+{
+public:
+ ScDocument* pDoc;
+ ScRange aRange;
+ ScQueryParam aQuery;
+ long nColCount;
+ BOOL bIgnoreEmptyRows;
+ BOOL bRepeatIfEmpty;
+ TypedStrCollection** ppStrings;
+ BOOL* pDateDim;
+ USHORT nNextRow; // for iterator, within range
+
+ ScSheetDPData_Impl() {}
+};
+
+// -----------------------------------------------------------------------
+
+ScSheetDPData::ScSheetDPData( ScDocument* pD, const ScSheetSourceDesc& rDesc )
+{
+ long nCount = rDesc.aSourceRange.aEnd.Col() - rDesc.aSourceRange.aStart.Col() + 1;
+ pImpl = new ScSheetDPData_Impl;
+ pImpl->pDoc = pD;
+ pImpl->aRange = rDesc.aSourceRange;
+ pImpl->aQuery = rDesc.aQueryParam;
+ pImpl->bIgnoreEmptyRows = FALSE;
+ pImpl->bRepeatIfEmpty = FALSE;
+ pImpl->nColCount = nCount;
+ pImpl->ppStrings = new TypedStrCollection*[nCount];
+ pImpl->pDateDim = NULL;
+ for (long i=0; i<nCount; i++)
+ pImpl->ppStrings[i] = NULL;
+
+ pImpl->nNextRow = pImpl->aRange.aStart.Row() + 1;
+}
+
+ScSheetDPData::~ScSheetDPData()
+{
+ for (long i=0; i<pImpl->nColCount; i++)
+ delete pImpl->ppStrings[i];
+ delete[] pImpl->ppStrings;
+ delete[] pImpl->pDateDim;
+ delete pImpl;
+}
+
+void ScSheetDPData::DisposeData()
+{
+ for (long i=0; i<pImpl->nColCount; i++)
+ {
+ delete pImpl->ppStrings[i];
+ pImpl->ppStrings[i] = NULL;
+ }
+}
+
+long ScSheetDPData::GetColumnCount()
+{
+ return pImpl->nColCount;
+}
+
+BOOL lcl_HasQuery( const ScQueryParam& rParam )
+{
+ return rParam.GetEntryCount() > 0 &&
+ rParam.GetEntry(0).bDoQuery;
+}
+
+const TypedStrCollection& ScSheetDPData::GetColumnEntries(long nColumn)
+{
+ DBG_ASSERT(nColumn>=0 && nColumn<pImpl->nColCount, "ScSheetDPData: wrong column");
+
+ if (!pImpl->ppStrings[nColumn])
+ {
+ TypedStrCollection* pColl = new TypedStrCollection;
+
+ //! document must have function to fill collection!!!
+ String aDocStr;
+ USHORT nDocCol = (USHORT)(pImpl->aRange.aStart.Col() + nColumn);
+ USHORT nDocTab = pImpl->aRange.aStart.Tab();
+ USHORT nStartRow = pImpl->aRange.aStart.Row()+1; // start of data
+ USHORT nEndRow = pImpl->aRange.aEnd.Row();
+ USHORT nStartCol = pImpl->aRange.aStart.Col();
+ USHORT nEndCol = pImpl->aRange.aEnd.Col();
+ for (USHORT nRow = nStartRow; nRow <= nEndRow; nRow++)
+ {
+ if ( pImpl->bIgnoreEmptyRows &&
+ pImpl->pDoc->IsBlockEmpty( nDocTab, nStartCol, nRow, nEndCol, nRow ) )
+ {
+ // ignore this (empty) row
+ //! count and skip empty rows?
+ }
+ else if ( pImpl->bRepeatIfEmpty && nRow > nStartRow &&
+ !pImpl->pDoc->HasData( nDocCol, nRow, nDocTab ) )
+ {
+ // ignore empty member (if it's not the first row)
+ }
+ else if ( lcl_HasQuery(pImpl->aQuery) &&
+ !pImpl->pDoc->ValidQuery( nRow, nDocTab, pImpl->aQuery ) )
+ {
+ // this row is filtered out
+ }
+ else
+ {
+ TypedStrData* pNew;
+ pImpl->pDoc->GetString( nDocCol, nRow, nDocTab, aDocStr );
+ if ( pImpl->pDoc->HasValueData( nDocCol, nRow, nDocTab ) )
+ {
+ double fVal = pImpl->pDoc->GetValue(ScAddress(nDocCol, nRow, nDocTab));
+ pNew = new TypedStrData( aDocStr, fVal, SC_STRTYPE_VALUE );
+ }
+ else
+ pNew = new TypedStrData( aDocStr );
+
+ if (!pColl->Insert(pNew))
+ delete pNew;
+ }
+ }
+
+ pImpl->ppStrings[nColumn] = pColl;
+ }
+ return *pImpl->ppStrings[nColumn];
+}
+
+String ScSheetDPData::getDimensionName(long nColumn)
+{
+ if (getIsDataLayoutDimension(nColumn))
+ {
+ //! different internal and display names?
+ //return "Data";
+ return ScGlobal::GetRscString(STR_PIVOT_DATA);
+ }
+ else if ( nColumn >= pImpl->nColCount )
+ {
+ DBG_ERROR("getDimensionName: invalid dimension");
+ return String();
+ }
+ else
+ {
+ USHORT nDocCol = (USHORT)(pImpl->aRange.aStart.Col() + nColumn);
+ USHORT nDocRow = pImpl->aRange.aStart.Row();
+ USHORT nDocTab = pImpl->aRange.aStart.Tab();
+ String aDocStr;
+ pImpl->pDoc->GetString( nDocCol, nDocRow, nDocTab, aDocStr );
+ return aDocStr;
+ }
+}
+
+BOOL lcl_HasDateFormat( ScDocument* pDoc, const ScRange& rRange )
+{
+ //! iterate formats in range?
+
+ ScAddress aPos = rRange.aStart;
+ aPos.SetRow( aPos.Row() + 1 ); // below title
+ ULONG nFormat = pDoc->GetNumberFormat( aPos );
+ SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
+ return ( pFormatter->GetType(nFormat) & NUMBERFORMAT_DATE ) != 0;
+}
+
+BOOL ScSheetDPData::IsDateDimension(long nDim)
+{
+ if (getIsDataLayoutDimension(nDim))
+ {
+ return FALSE;
+ }
+ else if ( nDim >= pImpl->nColCount )
+ {
+ DBG_ERROR("IsDateDimension: invalid dimension");
+ return FALSE;
+ }
+ else
+ {
+ if (!pImpl->pDateDim)
+ {
+ pImpl->pDateDim = new BOOL[pImpl->nColCount];
+ ScRange aTestRange = pImpl->aRange;
+ for (long i=0; i<pImpl->nColCount; i++)
+ {
+ USHORT nCol = (USHORT)( pImpl->aRange.aStart.Col() + i );
+ aTestRange.aStart.SetCol(nCol);
+ aTestRange.aEnd.SetCol(nCol);
+ pImpl->pDateDim[i] = lcl_HasDateFormat( pImpl->pDoc, aTestRange );
+ }
+ }
+ return pImpl->pDateDim[nDim];
+ }
+}
+
+UINT32 ScSheetDPData::GetNumberFormat(long nDim)
+{
+ if (getIsDataLayoutDimension(nDim))
+ {
+ return 0;
+ }
+ else if ( nDim >= pImpl->nColCount )
+ {
+ DBG_ERROR("GetNumberFormat: invalid dimension");
+ return 0;
+ }
+ else
+ {
+ // is queried only once per dimension from ScDPOutput -> no need to cache
+
+ ScAddress aPos = pImpl->aRange.aStart;
+ aPos.SetCol( aPos.Col() + nDim );
+ aPos.SetRow( aPos.Row() + 1 ); // below title
+ return pImpl->pDoc->GetNumberFormat( aPos );
+ }
+}
+
+BOOL ScSheetDPData::getIsDataLayoutDimension(long nColumn)
+{
+ return ( nColumn == pImpl->nColCount );
+}
+
+void ScSheetDPData::SetEmptyFlags( BOOL bIgnoreEmptyRows, BOOL bRepeatIfEmpty )
+{
+ pImpl->bIgnoreEmptyRows = bIgnoreEmptyRows;
+ pImpl->bRepeatIfEmpty = bRepeatIfEmpty;
+}
+
+void ScSheetDPData::ResetIterator()
+{
+ pImpl->nNextRow = pImpl->aRange.aStart.Row() + 1;
+}
+
+void lcl_GetStringOrValue( ScDPItemData& rData, ScDocument* pDoc,
+ USHORT nCol, USHORT nRow, USHORT nTab,
+ BOOL bRepeatIfEmpty, USHORT nFirstDataRow )
+{
+ if ( bRepeatIfEmpty )
+ {
+ // use first non-empty entry
+ //! just keep old ItemData ????
+ //! otherwise count empty cells and subtract!
+
+ while ( !pDoc->HasData( nCol, nRow, nTab ) && nRow > nFirstDataRow )
+ --nRow;
+ }
+
+ BOOL bVal = pDoc->HasValueData( nCol, nRow, nTab );
+ rData.bHasValue = bVal;
+ if (bVal)
+ rData.fValue = pDoc->GetValue( ScAddress( nCol, nRow, nTab ) );
+ else
+ pDoc->GetString( nCol, nRow, nTab, rData.aString );
+}
+
+BOOL ScSheetDPData::GetNextRow( const ScDPTableIteratorParam& rParam )
+{
+ if ( pImpl->nNextRow > pImpl->aRange.aEnd.Row() )
+ return FALSE;
+
+ long i;
+ long nStartCol = pImpl->aRange.aStart.Col();
+ USHORT nDocTab = pImpl->aRange.aStart.Tab();
+ USHORT nFirstDataRow = pImpl->aRange.aStart.Row() + 1;
+
+ BOOL bFilteredOut;
+ do
+ {
+ if ( pImpl->bIgnoreEmptyRows )
+ {
+ USHORT nEndCol = pImpl->aRange.aEnd.Col();
+ while ( pImpl->pDoc->IsBlockEmpty( nDocTab, (USHORT)nStartCol, pImpl->nNextRow,
+ nEndCol, pImpl->nNextRow ) )
+ {
+ ++pImpl->nNextRow;
+ if ( pImpl->nNextRow > pImpl->aRange.aEnd.Row() )
+ return FALSE;
+ }
+ }
+
+ bFilteredOut = ( lcl_HasQuery(pImpl->aQuery) &&
+ !pImpl->pDoc->ValidQuery( pImpl->nNextRow, nDocTab, pImpl->aQuery ) );
+ if ( bFilteredOut )
+ {
+ ++pImpl->nNextRow;
+ if ( pImpl->nNextRow > pImpl->aRange.aEnd.Row() )
+ return FALSE;
+ }
+ }
+ while (bFilteredOut);
+
+ //! use more efficient iterators
+
+ for (i=0; i<rParam.nColCount; i++)
+ {
+ long nDim = rParam.pCols[i];
+ if ( getIsDataLayoutDimension(nDim) )
+ rParam.pColData[i].SetString( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("x")) );
+ else
+ lcl_GetStringOrValue( rParam.pColData[i], pImpl->pDoc,
+ (USHORT)(nStartCol+nDim), pImpl->nNextRow, nDocTab,
+ pImpl->bRepeatIfEmpty, nFirstDataRow );
+ }
+
+ for (i=0; i<rParam.nRowCount; i++)
+ {
+ long nDim = rParam.pRows[i];
+ if ( getIsDataLayoutDimension(nDim) )
+ rParam.pRowData[i].SetString( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("x")) );
+ else
+ lcl_GetStringOrValue( rParam.pRowData[i], pImpl->pDoc,
+ (USHORT)(nStartCol+nDim), pImpl->nNextRow, nDocTab,
+ pImpl->bRepeatIfEmpty, nFirstDataRow );
+ }
+
+ for (i=0; i<rParam.nDatCount; i++)
+ {
+ long nDim = rParam.pDats[i];
+ ScAddress aPos( (USHORT)(nStartCol+nDim), pImpl->nNextRow, nDocTab );
+ ScBaseCell* pCell = pImpl->pDoc->GetCell( aPos );
+ if ( !pCell || pCell->GetCellType() == CELLTYPE_NOTE )
+ rParam.pValues[i].Set( 0.0, SC_VALTYPE_EMPTY );
+ else if ( pCell->GetCellType() == CELLTYPE_FORMULA && ((ScFormulaCell*)pCell)->GetErrCode() )
+ rParam.pValues[i].Set( 0.0, SC_VALTYPE_ERROR );
+ else if ( pCell->HasValueData() )
+ {
+ //! GetValue method at BaseCell?
+ DBG_ASSERT( pCell->GetCellType() == CELLTYPE_VALUE ||
+ pCell->GetCellType() == CELLTYPE_FORMULA, "wrong cell type" );
+ double fVal;
+ if ( pCell->GetCellType() == CELLTYPE_VALUE )
+ fVal = ((ScValueCell*)pCell)->GetValue();
+ else
+ fVal = ((ScFormulaCell*)pCell)->GetValue();
+ rParam.pValues[i].Set( fVal, SC_VALTYPE_VALUE );
+ }
+ else
+ rParam.pValues[i].Set( 0.0, SC_VALTYPE_STRING );
+ }
+
+ pImpl->nNextRow++;
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+
+
+
+
+
+
diff --git a/sc/source/core/data/dptabdat.cxx b/sc/source/core/data/dptabdat.cxx
new file mode 100644
index 000000000000..1222aa9cb464
--- /dev/null
+++ b/sc/source/core/data/dptabdat.cxx
@@ -0,0 +1,173 @@
+/*************************************************************************
+ *
+ * $RCSfile: dptabdat.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <tools/debug.hxx>
+#include <tools/intn.hxx>
+
+#include "dptabdat.hxx"
+#include "global.hxx"
+
+// -----------------------------------------------------------------------
+
+BOOL ScDPItemData::IsCaseInsEqual( const ScDPItemData& r ) const
+{
+ //! ApproxEqual ???
+ //! pass International?
+ //! inline?
+ return bHasValue ? ( r.bHasValue && fValue == r.fValue ) :
+ ( !r.bHasValue && ScGlobal::pScInternational->
+ CompareEqual( aString, r.aString, INTN_COMPARE_IGNORECASE ) );
+}
+
+// -----------------------------------------------------------------------
+
+ScDPTableIteratorParam::ScDPTableIteratorParam(
+ long nCCount, const long* pC, ScDPItemData* pCDat,
+ long nRCount, const long* pR, ScDPItemData* pRDat,
+ long nDCount, const long* pD, ScDPValueData* pV ) :
+ nColCount( (USHORT)nCCount ),
+ pCols ( pC ),
+ pColData ( pCDat ),
+ nRowCount( (USHORT)nRCount ),
+ pRows ( pR ),
+ pRowData ( pRDat ),
+ nDatCount( (USHORT)nDCount ),
+ pDats ( pD ),
+ pValues ( pV )
+{
+}
+
+// -----------------------------------------------------------------------
+
+ScDPTableData::ScDPTableData()
+{
+ nLastDateVal = nLastHier = nLastLevel = nLastRet = -1; // invalid
+
+ //! reset before new calculation (in case the base date is changed)
+}
+
+ScDPTableData::~ScDPTableData()
+{
+}
+
+long ScDPTableData::GetDatePart( long nDateVal, long nHierarchy, long nLevel )
+{
+ if ( nDateVal == nLastDateVal && nHierarchy == nLastHier && nLevel == nLastLevel )
+ return nLastRet;
+
+ Date aDate( 30,12,1899 ); //! get from source data (and cache here)
+ aDate += nDateVal;
+
+ long nRet = 0;
+ switch (nHierarchy)
+ {
+ case SC_DAPI_HIERARCHY_QUARTER:
+ switch (nLevel)
+ {
+ case 0: nRet = aDate.GetYear(); break;
+ case 1: nRet = (aDate.GetMonth()-1) / 3 + 1; break;
+ case 2: nRet = aDate.GetMonth(); break;
+ case 3: nRet = aDate.GetDay(); break;
+ default:
+ DBG_ERROR("GetDatePart: wrong level");
+ }
+ break;
+ case SC_DAPI_HIERARCHY_WEEK:
+ switch (nLevel)
+ {
+ //! use settings for different definitions
+ case 0: nRet = aDate.GetYear(); break; //!...
+ case 1: nRet = aDate.GetWeekOfYear(); break;
+ case 2: nRet = (long)aDate.GetDayOfWeek(); break;
+ default:
+ DBG_ERROR("GetDatePart: wrong level");
+ }
+ break;
+ default:
+ DBG_ERROR("GetDatePart: wrong hierarchy");
+ }
+
+ nLastDateVal = nDateVal;
+ nLastHier = nHierarchy;
+ nLastLevel = nLevel;
+ nLastRet = nRet;
+
+ return nRet;
+}
+
+UINT32 ScDPTableData::GetNumberFormat(long nDim)
+{
+ return 0; // default format
+}
+
+// -----------------------------------------------------------------------
+
+
+
+
diff --git a/sc/source/core/data/dptabres.cxx b/sc/source/core/data/dptabres.cxx
new file mode 100644
index 000000000000..616db9d706a5
--- /dev/null
+++ b/sc/source/core/data/dptabres.cxx
@@ -0,0 +1,1278 @@
+/*************************************************************************
+ *
+ * $RCSfile: dptabres.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <tools/debug.hxx>
+#include <tools/intn.hxx>
+#include <math.h>
+#include <float.h> //! Test !!!
+
+#include "dptabres.hxx"
+#include "dptabsrc.hxx"
+#include "dptabdat.hxx"
+#include "global.hxx"
+#include "subtotal.hxx"
+#include "globstr.hrc"
+#include "datauno.hxx" // ScDataUnoConversion
+
+#include <com/sun/star/sheet/DataResultFlags.hpp>
+#include <com/sun/star/sheet/MemberResultFlags.hpp>
+#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
+
+using namespace com::sun::star;
+
+// -----------------------------------------------------------------------
+
+SV_IMPL_PTRARR( ScDPResultMembers, ScDPResultMemberPtr );
+SV_IMPL_PTRARR( ScDPDataMembers, ScDPDataMemberPtr );
+
+// -----------------------------------------------------------------------
+
+static USHORT nFuncStrIds[12] = // passend zum enum ScSubTotalFunc
+{
+ 0, // SUBTOTAL_FUNC_NONE
+ STR_FUN_TEXT_AVG, // SUBTOTAL_FUNC_AVE
+ STR_FUN_TEXT_COUNT, // SUBTOTAL_FUNC_CNT
+ STR_FUN_TEXT_COUNT, // SUBTOTAL_FUNC_CNT2
+ STR_FUN_TEXT_MAX, // SUBTOTAL_FUNC_MAX
+ STR_FUN_TEXT_MIN, // SUBTOTAL_FUNC_MIN
+ STR_FUN_TEXT_PRODUCT, // SUBTOTAL_FUNC_PROD
+ STR_FUN_TEXT_STDDEV, // SUBTOTAL_FUNC_STD
+ STR_FUN_TEXT_STDDEV, // SUBTOTAL_FUNC_STDP
+ STR_FUN_TEXT_SUM, // SUBTOTAL_FUNC_SUM
+ STR_FUN_TEXT_VAR, // SUBTOTAL_FUNC_VAR
+ STR_FUN_TEXT_VAR // SUBTOTAL_FUNC_VARP
+};
+
+
+//! member of something or pass as arguments !!!!!!!!!!
+static ScSubTotalFunc eColForce = SUBTOTAL_FUNC_NONE;
+static ScSubTotalFunc eRowForce = SUBTOTAL_FUNC_NONE;
+
+static long nColSubTotalFunc = -1;
+static long nRowSubTotalFunc = -1;
+
+// -----------------------------------------------------------------------
+
+void ScDPAggData::Update( const ScDPValueData& rNext, ScSubTotalFunc eFunc )
+{
+ if (nCount<0) // error?
+ return; // nothing more...
+
+ if ( rNext.nType == SC_VALTYPE_EMPTY )
+ return;
+
+ //! Test !!!
+ if ( eColForce != SUBTOTAL_FUNC_NONE && eRowForce != SUBTOTAL_FUNC_NONE && eColForce != eRowForce )
+ return;
+ if ( eColForce != SUBTOTAL_FUNC_NONE ) eFunc = eColForce;
+ if ( eRowForce != SUBTOTAL_FUNC_NONE ) eFunc = eRowForce;
+ //! Test !!!
+
+ if ( eFunc == SUBTOTAL_FUNC_NONE )
+ return;
+
+ if ( eFunc != SUBTOTAL_FUNC_CNT2 ) // CNT2 counts everything, incl. strings and errors
+ {
+ if ( rNext.nType == SC_VALTYPE_ERROR )
+ {
+ nCount = -1; // -1 for error (not for CNT2)
+ return;
+ }
+ if ( rNext.nType == SC_VALTYPE_STRING )
+ return; // ignore
+ }
+
+ ++nCount; // for all functions
+
+ switch (eFunc)
+ {
+ case SUBTOTAL_FUNC_SUM:
+ case SUBTOTAL_FUNC_AVE:
+ if ( !SubTotal::SafePlus( fVal, rNext.fValue ) )
+ nCount = -1; // -1 for error
+ break;
+ case SUBTOTAL_FUNC_PROD:
+ if ( nCount == 1 ) // copy first value (fVal is initialized to 0)
+ fVal = rNext.fValue;
+ else if ( !SubTotal::SafeMult( fVal, rNext.fValue ) )
+ nCount = -1; // -1 for error
+ break;
+ case SUBTOTAL_FUNC_CNT:
+ case SUBTOTAL_FUNC_CNT2:
+ // nothing more than incrementing nCount
+ break;
+ case SUBTOTAL_FUNC_MAX:
+ if ( nCount == 1 || rNext.fValue > fVal )
+ fVal = rNext.fValue;
+ break;
+ case SUBTOTAL_FUNC_MIN:
+ if ( nCount == 1 || rNext.fValue < fVal )
+ fVal = rNext.fValue;
+ break;
+ case SUBTOTAL_FUNC_STD:
+ case SUBTOTAL_FUNC_STDP:
+ case SUBTOTAL_FUNC_VAR:
+ case SUBTOTAL_FUNC_VARP:
+ {
+ if ( !SubTotal::SafePlus( fVal, rNext.fValue ) )
+ nCount = -1; // -1 for error
+ double fAdd = rNext.fValue;
+ if ( !SubTotal::SafeMult( fAdd, rNext.fValue ) ||
+ !SubTotal::SafePlus( fSquare, fAdd ) )
+ nCount = -1; // -1 for error
+ }
+ break;
+ default:
+ DBG_ERROR("invalid function");
+ }
+}
+
+BOOL ScDPAggData::HasError( ScSubTotalFunc eFunc ) const
+{
+ //! Test !!!
+ if ( eColForce != SUBTOTAL_FUNC_NONE ) eFunc = eColForce;
+ if ( eRowForce != SUBTOTAL_FUNC_NONE ) eFunc = eRowForce;
+ //! Test !!!
+
+ switch (eFunc)
+ {
+ case SUBTOTAL_FUNC_SUM:
+ case SUBTOTAL_FUNC_PROD:
+ case SUBTOTAL_FUNC_CNT:
+ case SUBTOTAL_FUNC_CNT2:
+ return ( nCount < 0 ); // only real errors
+
+ case SUBTOTAL_FUNC_AVE:
+ case SUBTOTAL_FUNC_MAX:
+ case SUBTOTAL_FUNC_MIN:
+ case SUBTOTAL_FUNC_STDP:
+ case SUBTOTAL_FUNC_VARP:
+ return ( nCount <= 0 ); // no data is an error
+
+ case SUBTOTAL_FUNC_STD:
+ case SUBTOTAL_FUNC_VAR:
+ return ( nCount < 2 ); // need at least 2 values
+
+ default:
+ DBG_ERROR("invalid function");
+ }
+ return TRUE;
+}
+
+double ScDPAggData::GetResult( ScSubTotalFunc eFunc ) const
+{
+ //! Test !!!
+ if ( eColForce != SUBTOTAL_FUNC_NONE ) eFunc = eColForce;
+ if ( eRowForce != SUBTOTAL_FUNC_NONE ) eFunc = eRowForce;
+ //! Test !!!
+
+ switch (eFunc)
+ {
+ case SUBTOTAL_FUNC_MAX:
+ case SUBTOTAL_FUNC_MIN:
+ case SUBTOTAL_FUNC_SUM:
+ case SUBTOTAL_FUNC_PROD:
+ // different error conditions are handled in HasError
+ return fVal;
+
+ case SUBTOTAL_FUNC_CNT:
+ case SUBTOTAL_FUNC_CNT2:
+ return nCount;
+
+ case SUBTOTAL_FUNC_AVE:
+ if ( nCount > 0 )
+ return fVal / (double) nCount;
+ DBG_ERROR("empty average");
+ break;
+
+ //! use safe mul for fVal * fVal
+
+ case SUBTOTAL_FUNC_STD:
+ if ( nCount >= 2 )
+ return sqrt((fSquare - fVal*fVal/(double)(nCount)) / (double)(nCount-1));
+ DBG_ERROR("empty dev");
+ break;
+ case SUBTOTAL_FUNC_VAR:
+ if ( nCount >= 2 )
+ return (fSquare - fVal*fVal/(double)(nCount)) / (double)(nCount-1);
+ DBG_ERROR("empty var");
+ break;
+ case SUBTOTAL_FUNC_STDP:
+ if ( nCount > 0 )
+ return sqrt((fSquare - fVal*fVal/(double)(nCount)) / (double)nCount);
+ DBG_ERROR("empty devp")
+ break;
+ case SUBTOTAL_FUNC_VARP:
+ if ( nCount > 0 )
+ return (fSquare - fVal*fVal/(double)(nCount)) / (double)nCount;
+ DBG_ERROR("empty devp")
+ break;
+ default:
+ DBG_ERROR("invalid function");
+ }
+ return 0.0;
+}
+
+ScDPAggData* ScDPAggData::GetChild()
+{
+ if (!pChild)
+ pChild = new ScDPAggData;
+ return pChild;
+}
+
+// -----------------------------------------------------------------------
+
+ScSubTotalFunc lcl_GetForceFunc( ScDPLevel* pLevel, long nFuncNo )
+{
+ ScSubTotalFunc eRet = SUBTOTAL_FUNC_NONE;
+ if ( pLevel )
+ {
+ //! direct access via ScDPLevel
+
+ uno::Sequence<sheet::GeneralFunction> aSeq = pLevel->getSubTotals();
+ if ( nFuncNo < aSeq.getLength() )
+ {
+ sheet::GeneralFunction eUser = aSeq.getConstArray()[nFuncNo];
+ if (eUser != sheet::GeneralFunction_AUTO)
+ eRet = ScDataUnoConversion::GeneralToSubTotal( eUser );
+ }
+ }
+ return eRet;
+}
+
+// -----------------------------------------------------------------------
+
+ScDPResultData::ScDPResultData( ScDPSource* pSrc ) : //! Ref
+ pSource( pSrc ),
+ nMeasCount( 0 ),
+ pMeasFuncs( NULL ),
+ pMeasNames( NULL ),
+ bDataAtCol( FALSE ),
+ bDataAtRow( FALSE )
+{
+}
+
+ScDPResultData::~ScDPResultData()
+{
+ delete[] pMeasFuncs;
+ delete[] pMeasNames;
+}
+
+void ScDPResultData::SetMeasureData( long nCount, const ScSubTotalFunc* pFunctions,
+ const String* pNames )
+{
+ delete[] pMeasFuncs;
+ delete[] pMeasNames;
+ if ( nCount )
+ {
+ nMeasCount = nCount;
+ pMeasFuncs = new ScSubTotalFunc[nCount];
+ pMeasNames = new String[nCount];
+ for (long i=0; i<nCount; i++)
+ {
+ pMeasFuncs[i] = pFunctions[i];
+ pMeasNames[i] = pNames[i];
+ }
+ }
+ else
+ {
+ // use one dummy measure
+ nMeasCount = 1;
+ pMeasFuncs = new ScSubTotalFunc[1];
+ pMeasFuncs[0] = SUBTOTAL_FUNC_NONE;
+ pMeasNames = new String[1];
+ pMeasNames[0] = ScGlobal::GetRscString( STR_EMPTYDATA );
+ }
+}
+
+void ScDPResultData::SetDataLayoutOrientation( USHORT nOrient )
+{
+ bDataAtCol = ( nOrient == sheet::DataPilotFieldOrientation_COLUMN );
+ bDataAtRow = ( nOrient == sheet::DataPilotFieldOrientation_ROW );
+}
+
+long ScDPResultData::GetColStartMeasure() const
+{
+ if ( nMeasCount == 1 ) return 0;
+ return bDataAtCol ? SC_DPMEASURE_ALL : SC_DPMEASURE_ANY;
+}
+
+long ScDPResultData::GetRowStartMeasure() const
+{
+ if ( nMeasCount == 1 ) return 0;
+ return bDataAtRow ? SC_DPMEASURE_ALL : SC_DPMEASURE_ANY;
+}
+
+ScSubTotalFunc ScDPResultData::GetMeasureFunction(long nMeasure) const
+{
+ DBG_ASSERT( pMeasFuncs && nMeasure < nMeasCount, "bumm" );
+ return pMeasFuncs[nMeasure];
+}
+
+String ScDPResultData::GetMeasureString(long nMeasure, BOOL bForce, ScSubTotalFunc eForceFunc) const
+{
+ // with bForce==TRUE, return function instead of "result" for single measure
+ // with eForceFunc != SUBTOTAL_FUNC_NONE, always use eForceFunc
+
+ if ( nMeasure < 0 || ( nMeasCount == 1 && !bForce && eForceFunc == SUBTOTAL_FUNC_NONE ) )
+ {
+ // for user-specified subtotal function with all measures,
+ // display only function name
+ if ( eForceFunc != SUBTOTAL_FUNC_NONE )
+ return ScGlobal::GetRscString(nFuncStrIds[eForceFunc]);
+
+ return ScGlobal::GetRscString(STR_TABLE_ERGEBNIS);
+ }
+ else
+ {
+ DBG_ASSERT( pMeasNames && nMeasure < nMeasCount, "bumm" );
+
+ String aRet;
+ ScSubTotalFunc eFunc = ( eForceFunc == SUBTOTAL_FUNC_NONE ) ?
+ GetMeasureFunction(nMeasure) : eForceFunc;
+ USHORT nId = nFuncStrIds[eFunc];
+ if (nId)
+ {
+ aRet += ScGlobal::GetRscString(nId); // function name
+ aRet.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " - " ));
+ }
+ aRet += pMeasNames[nMeasure]; // field name
+
+ return aRet;
+ }
+}
+
+String ScDPResultData::GetMeasureDimensionName(long nMeasure) const
+{
+ if ( nMeasure < 0 )
+ {
+ DBG_ERROR("GetMeasureDimensionName: negative");
+ return String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("***"));
+ }
+
+ return pSource->GetDataDimName( nMeasure );
+}
+
+// -----------------------------------------------------------------------
+
+
+ScDPResultMember::ScDPResultMember( ScDPResultData* pData, ScDPDimension* pDim,
+ ScDPLevel* pLev, ScDPMember* pDesc,
+ BOOL bForceSub ) :
+ pResultData( pData ),
+ pParentDim( pDim ),
+ pParentLevel( pLev ),
+ pMemberDesc( pDesc ),
+ pChildDimension( NULL ),
+ pDataRoot( NULL ),
+ bHasElements( FALSE ),
+ bForceSubTotal( bForceSub )
+{
+ // pParentLevel/pMemberDesc is 0 for root members
+}
+
+ScDPResultMember::~ScDPResultMember()
+{
+ delete pChildDimension;
+ delete pDataRoot;
+}
+
+String ScDPResultMember::GetName() const
+{
+ if (pMemberDesc)
+ return pMemberDesc->GetNameStr();
+ else
+ return ScGlobal::GetRscString(STR_PIVOT_TOTAL); // root member
+}
+
+BOOL ScDPResultMember::IsNamedItem( const ScDPItemData& r ) const
+{
+ //! store ScDPMember pointer instead of ScDPMember ???
+
+ if (pMemberDesc)
+ return ((ScDPMember*)pMemberDesc)->IsNamedItem( r );
+ return FALSE;
+}
+
+void ScDPResultMember::InitFrom( ScDPDimension** ppDim, ScDPLevel** ppLev )
+{
+ // skip child dimension if details are not shown
+ if ( pMemberDesc && !pMemberDesc->getShowDetails() )
+ return;
+
+ if ( *ppDim )
+ {
+ pChildDimension = new ScDPResultDimension( pResultData );
+ pChildDimension->InitFrom( ppDim, ppLev );
+ }
+}
+
+long ScDPResultMember::GetSize(long nMeasure) const
+{
+ if ( !IsVisible() )
+ return 0;
+
+ if ( pChildDimension )
+ {
+ long nSize = pChildDimension->GetSize(nMeasure);
+ long nUserSubCount = GetSubTotalCount();
+ if ( nUserSubCount )
+ {
+ if ( nMeasure == SC_DPMEASURE_ALL )
+ nSize += pResultData->GetMeasureCount() * nUserSubCount;
+ else
+ nSize += nUserSubCount;
+ }
+ return nSize;
+ }
+ else
+ {
+ if ( nMeasure == SC_DPMEASURE_ALL )
+ return pResultData->GetMeasureCount();
+ else
+ return 1;
+ }
+}
+
+BOOL ScDPResultMember::IsVisible() const
+{
+// return bHasElements && IsValid();
+ return ( bHasElements || ( pParentLevel && pParentLevel->getShowEmpty() ) ) && IsValid();
+}
+
+BOOL ScDPResultMember::IsValid() const
+{
+ // non-Valid members are left out of calculation
+
+ // was member set no invisible at the DataPilotSource?
+ if ( pMemberDesc && !pMemberDesc->getIsVisible() )
+ return FALSE;
+
+ return TRUE;
+}
+
+long ScDPResultMember::GetSubTotalCount() const
+{
+ if ( bForceSubTotal ) // set if needed for root members
+ return 1; // grand total is always "automatic"
+ else if ( pParentLevel )
+ {
+ //! direct access via ScDPLevel
+ return pParentLevel->getSubTotals().getLength();
+ }
+ else
+ return 0;
+}
+
+void ScDPResultMember::ProcessData( const ScDPItemData* pChildMembers, ScDPResultDimension* pDataDim,
+ const ScDPItemData* pDataMembers, const ScDPValueData* pValues )
+{
+ SetHasElements();
+
+ if (pChildDimension)
+ pChildDimension->ProcessData( pChildMembers, pDataDim, pDataMembers, pValues );
+
+ if ( pDataMembers )
+ {
+ if ( !pDataRoot )
+ {
+ pDataRoot = new ScDPDataMember( pResultData, NULL );
+ if ( pDataDim )
+ pDataRoot->InitFrom( pDataDim ); // recursive
+ }
+
+ //! Test !!!!
+ ScSubTotalFunc eOld = eRowForce;
+ long nOldSub = nRowSubTotalFunc;
+ //! Test !!!!
+
+ long nUserSubCount = GetSubTotalCount();
+ if ( !nUserSubCount || !pChildDimension ) //! Test
+ nUserSubCount = 1; //! Test
+
+ for (long nUserPos=0; nUserPos<nUserSubCount; nUserPos++)
+ {
+ //! Test !!!!
+ if ( pChildDimension )
+ {
+ nRowSubTotalFunc = nUserPos;
+ eRowForce = lcl_GetForceFunc( pParentLevel, nUserPos );
+ }
+ //! Test !!!!
+
+ pDataRoot->ProcessData( pDataMembers, pValues );
+
+ //! Test !!!!
+ eRowForce = eOld;
+ nRowSubTotalFunc = nOldSub;
+ //! Test !!!!
+ }
+ }
+}
+
+void ScDPResultMember::FillMemberResults( uno::Sequence<sheet::MemberResult>* pSequences,
+ long& rPos, long nMeasure, BOOL bRoot,
+ const String* pMemberName,
+ const String* pMemberCaption )
+{
+ // IsVisible() test is in ScDPResultDimension::FillMemberResults
+ // (not on data layout dimension)
+
+ long nSize = GetSize(nMeasure);
+ sheet::MemberResult* pArray = pSequences->getArray();
+ DBG_ASSERT( rPos+nSize <= pSequences->getLength(), "bumm" );
+
+ String aName;
+ if ( pMemberName ) // if pMemberName != NULL, use instead of real member name
+ aName = *pMemberName;
+ else
+ aName = GetName();
+
+ String aCaption = aName;
+ if ( pMemberCaption ) // use pMemberCaption if != NULL
+ aCaption = *pMemberCaption;
+ if (!aCaption.Len())
+ aCaption = ScGlobal::GetRscString(STR_EMPTYDATA);
+
+ if ( nSize && !bRoot ) // root is overwritten by first dimension
+ {
+ pArray[rPos].Name = rtl::OUString(aName);
+ pArray[rPos].Caption = rtl::OUString(aCaption);
+ pArray[rPos].Flags |= sheet::MemberResultFlags::HASMEMBER;
+
+ // set "continue" flag (removed for subtotals later)
+ for (long i=1; i<nSize; i++)
+ pArray[rPos+i].Flags |= sheet::MemberResultFlags::CONTINUE;
+ }
+
+ BOOL bHasChild = ( pChildDimension != NULL );
+ if (bHasChild)
+ {
+ if (bRoot) // same sequence for root member
+ pChildDimension->FillMemberResults( pSequences, rPos, nMeasure );
+ else
+ pChildDimension->FillMemberResults( pSequences + 1, rPos, nMeasure );
+ }
+
+ rPos += nSize;
+
+ long nUserSubCount = GetSubTotalCount();
+ if ( nUserSubCount && pChildDimension )
+ {
+ long nMemberMeasure = nMeasure;
+ long nSubSize = pResultData->GetCountForMeasure(nMeasure);
+
+ rPos -= nSubSize * nUserSubCount; // GetSize includes space for SubTotal
+
+ for (long nUserPos=0; nUserPos<nUserSubCount; nUserPos++)
+ {
+ for ( long nSubCount=0; nSubCount<nSubSize; nSubCount++ )
+ {
+ if ( nMeasure == SC_DPMEASURE_ALL )
+ nMemberMeasure = nSubCount;
+
+ ScSubTotalFunc eForce = SUBTOTAL_FUNC_NONE;
+ if (bHasChild)
+ eForce = lcl_GetForceFunc( pParentLevel, nUserPos );
+
+ String aSubStr = aName; //! caption?
+ aSubStr += ' ';
+ aSubStr += pResultData->GetMeasureString(nMemberMeasure, FALSE, eForce);
+
+ pArray[rPos].Name = rtl::OUString(aName);
+ pArray[rPos].Caption = rtl::OUString(aSubStr);
+ pArray[rPos].Flags = ( pArray[rPos].Flags |
+ ( sheet::MemberResultFlags::HASMEMBER | sheet::MemberResultFlags::SUBTOTAL) ) &
+ ~sheet::MemberResultFlags::CONTINUE;
+
+ if ( nMeasure == SC_DPMEASURE_ALL )
+ {
+ // data layout dimension is (direct/indirect) child of this.
+ // data layout dimension must have name for all entries.
+
+ uno::Sequence<sheet::MemberResult>* pLayoutSeq = pSequences;
+ if (!bRoot)
+ ++pLayoutSeq;
+ ScDPResultDimension* pLayoutDim = pChildDimension;
+ while ( pLayoutDim && !pLayoutDim->IsDataLayout() )
+ {
+ pLayoutDim = pLayoutDim->GetFirstChildDimension();
+ ++pLayoutSeq;
+ }
+ if ( pLayoutDim )
+ {
+ sheet::MemberResult* pLayoutArray = pLayoutSeq->getArray();
+ String aDataName = pResultData->GetMeasureDimensionName(nMemberMeasure);
+ pLayoutArray[rPos].Name = rtl::OUString(aDataName);
+ }
+ }
+
+ rPos += 1;
+ }
+ }
+ }
+}
+
+void ScDPResultMember::FillDataResults( const ScDPResultMember* pRefMember,
+ uno::Sequence< uno::Sequence<sheet::DataResult> >& rSequence,
+ long& rRow, long nMeasure ) const
+{
+ // IsVisible() test is in ScDPResultDimension::FillDataResults
+ // (not on data layout dimension)
+
+ BOOL bHasChild = ( pChildDimension != NULL );
+ if (bHasChild)
+ {
+ pChildDimension->FillDataResults( pRefMember, rSequence, rRow, nMeasure );
+ rRow += (USHORT) GetSize( nMeasure );
+ }
+
+ long nUserSubCount = GetSubTotalCount();
+ if ( nUserSubCount || !bHasChild )
+ {
+ if ( !nUserSubCount || !bHasChild ) //! Test
+ nUserSubCount = 1; //! Test
+
+ long nMemberMeasure = nMeasure;
+ long nSubSize = pResultData->GetCountForMeasure(nMeasure);
+ if (bHasChild)
+ rRow -= nSubSize * nUserSubCount; // GetSize includes space for SubTotal
+
+ //! Test !!!!
+ ScSubTotalFunc eOld = eRowForce;
+ long nOldSub = nRowSubTotalFunc;
+ //! Test !!!!
+
+ if ( pDataRoot )
+ {
+ for (long nUserPos=0; nUserPos<nUserSubCount; nUserPos++)
+ {
+ //! Test !!!!
+ if ( bHasChild )
+ {
+ nRowSubTotalFunc = nUserPos;
+ eRowForce = lcl_GetForceFunc( pParentLevel, nUserPos );
+ }
+ //! Test !!!!
+
+ for ( long nSubCount=0; nSubCount<nSubSize; nSubCount++ )
+ {
+ if ( nMeasure == SC_DPMEASURE_ALL )
+ nMemberMeasure = nSubCount;
+ else if ( pResultData->GetColStartMeasure() == SC_DPMEASURE_ALL )
+ nMemberMeasure = SC_DPMEASURE_ALL;
+
+ DBG_ASSERT( rRow < rSequence.getLength(), "bumm" );
+ uno::Sequence<sheet::DataResult>& rSubSeq = rSequence.getArray()[rRow];
+ long nSeqCol = 0;
+ pDataRoot->FillDataRow( pRefMember, rSubSeq, nSeqCol, nMemberMeasure, bHasChild );
+
+ rRow += 1;
+ }
+ }
+ }
+ else
+ rRow += nSubSize * nUserSubCount; // empty rows occur when ShowEmpty is true
+
+ //! Test !!!!
+ eRowForce = eOld;
+ nRowSubTotalFunc = nOldSub;
+ //! Test !!!!
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ScDPDataMember::ScDPDataMember( ScDPResultData* pData, ScDPResultMember* pRes ) :
+ pResultData( pData ),
+ pResultMember( pRes ),
+ pChildDimension( NULL )
+{
+ // pResultMember is 0 for root members
+}
+
+ScDPDataMember::~ScDPDataMember()
+{
+ delete pChildDimension;
+}
+
+String ScDPDataMember::GetName() const
+{
+ if (pResultMember)
+ return pResultMember->GetName();
+ else
+ return EMPTY_STRING;
+}
+
+BOOL ScDPDataMember::IsNamedItem( const ScDPItemData& r ) const
+{
+ if (pResultMember)
+ return pResultMember->IsNamedItem(r);
+ else
+ return FALSE;
+}
+
+void ScDPDataMember::InitFrom( ScDPResultDimension* pDim )
+{
+ if ( !pChildDimension )
+ pChildDimension = new ScDPDataDimension(pResultData);
+ pChildDimension->InitFrom(pDim);
+}
+
+long lcl_GetSubTotalPos()
+{
+// return Max( nColSubTotalFunc, nRowSubTotalFunc );
+
+ long nRet = -1;
+ if ( nColSubTotalFunc >= 0 ) nRet = nColSubTotalFunc;
+ if ( nRowSubTotalFunc >= 0 ) nRet = nRowSubTotalFunc;
+ return nRet;
+}
+
+void ScDPDataMember::UpdateValues(const ScDPValueData* pValues)
+{
+ //! find out how many and which subtotals are used
+
+ ScDPAggData* pAgg = &aAggregate;
+
+ long nSubPos = lcl_GetSubTotalPos();
+ if (nSubPos > 0)
+ {
+ long nSkip = nSubPos * pResultData->GetMeasureCount();
+ for (long i=0; i<nSkip; i++)
+ pAgg = pAgg->GetChild(); // created if not there
+ }
+
+ long nCount = pResultData->GetMeasureCount();
+ for (long nPos=0; nPos<nCount; nPos++)
+ {
+ pAgg->Update( *pValues, pResultData->GetMeasureFunction(nPos) );
+ if ( nPos+1 < nCount )
+ {
+ pAgg = pAgg->GetChild(); // created if not there
+ ++pValues; // next value entry
+ }
+ }
+}
+
+void ScDPDataMember::ProcessData( const ScDPItemData* pChildMembers, const ScDPValueData* pValues )
+{
+ //! Test !!!!
+ ScSubTotalFunc eOld = eColForce;
+ long nOldSub = nColSubTotalFunc;
+ //! Test !!!!
+
+ long nUserSubCount = pResultMember ? pResultMember->GetSubTotalCount() : 0;
+ if ( !nUserSubCount || !pChildDimension ) //! Test
+ nUserSubCount = 1; //! Test
+
+ for (long nUserPos=0; nUserPos<nUserSubCount; nUserPos++)
+ {
+ //! Test !!!!
+ if ( pChildDimension )
+ {
+ ScDPLevel* pForceLevel = pResultMember ? pResultMember->GetParentLevel() : NULL;
+ nColSubTotalFunc = nUserPos;
+ eColForce = lcl_GetForceFunc( pForceLevel, nUserPos );
+ }
+ //! Test !!!!
+
+ UpdateValues(pValues);
+ }
+
+ //! Test !!!!
+ eColForce = eOld;
+ nColSubTotalFunc = nOldSub;
+ //! Test !!!!
+
+ if (pChildDimension)
+ pChildDimension->ProcessData( pChildMembers, pValues );
+}
+
+BOOL ScDPDataMember::HasData(long nMeasure) const
+{
+ //! Test !!!
+ if ( eColForce != SUBTOTAL_FUNC_NONE && eRowForce != SUBTOTAL_FUNC_NONE && eColForce != eRowForce )
+ return FALSE;
+ //! Test !!!
+
+ // #74542# HasData can be different between measures!
+
+ DBG_ASSERT( nMeasure >= 0, "HasData: no measure" );
+
+ const ScDPAggData* pAgg = &aAggregate;
+ long nSkip = nMeasure;
+ long nSubPos = lcl_GetSubTotalPos();
+ if (nSubPos > 0)
+ nSkip += nSubPos * pResultData->GetMeasureCount();
+
+ for (long i=0; i<nSkip; i++)
+ {
+ pAgg = pAgg->GetExistingChild();
+//! DBG_ASSERT( pAgg, "AggData not found" );
+ if (!pAgg)
+ return FALSE; //! error?
+ }
+
+ return pAgg->HasData();
+}
+
+BOOL ScDPDataMember::HasError(long nMeasure) const
+{
+ //! merge with GetAggregate?
+
+ DBG_ASSERT( nMeasure >= 0, "GetAggregate: no measure" );
+
+ const ScDPAggData* pAgg = &aAggregate;
+ long nSkip = nMeasure;
+ long nSubPos = lcl_GetSubTotalPos();
+ if (nSubPos > 0)
+ nSkip += nSubPos * pResultData->GetMeasureCount();
+
+ for ( long nPos=0; nPos<nSkip; nPos++ )
+ {
+ pAgg = pAgg->GetExistingChild();
+//! DBG_ASSERT( pAgg, "AggData not found" );
+ if (!pAgg)
+ return TRUE;
+ }
+
+ return pAgg->HasError( pResultData->GetMeasureFunction(nMeasure) );
+}
+
+double ScDPDataMember::GetAggregate( long nMeasure ) const
+{
+ //! allow to return errors
+
+ DBG_ASSERT( nMeasure >= 0, "GetAggregate: no measure" );
+
+ const ScDPAggData* pAgg = &aAggregate;
+ long nSkip = nMeasure;
+ long nSubPos = lcl_GetSubTotalPos();
+ if (nSubPos > 0)
+ nSkip += nSubPos * pResultData->GetMeasureCount();
+
+ for ( long nPos=0; nPos<nSkip; nPos++ )
+ {
+ pAgg = pAgg->GetExistingChild();
+//! DBG_ASSERT( pAgg, "AggData not found" );
+ if (!pAgg)
+ return DBL_MAX; //! error!!!
+ }
+
+ return pAgg->GetResult( pResultData->GetMeasureFunction(nMeasure) );
+}
+
+void ScDPDataMember::FillDataRow( const ScDPResultMember* pRefMember,
+ uno::Sequence<sheet::DataResult>& rSequence,
+ long& rCol, long nMeasure, BOOL bIsSubTotalRow ) const
+{
+ DBG_ASSERT( pRefMember == pResultMember || !pResultMember, "bla" );
+
+ if ( pRefMember->IsVisible() ) //! here or in ScDPDataDimension::FillDataRow ???
+ {
+ const ScDPDataMember* pDataMember = this; //! Test
+
+ const ScDPDataDimension* pDataChild = pDataMember->GetChildDimension();
+ const ScDPResultDimension* pRefChild = pRefMember->GetChildDimension();
+ BOOL bHasChild = ( pDataChild && pRefChild );
+
+ if ( bHasChild )
+ {
+ pDataChild->FillDataRow( pRefChild, rSequence, rCol, nMeasure, bIsSubTotalRow );
+ rCol += (USHORT)pRefMember->GetSize( nMeasure );
+ }
+
+ long nUserSubCount = pRefMember->GetSubTotalCount();
+ if ( nUserSubCount || !bHasChild )
+ {
+ if ( !nUserSubCount || !bHasChild ) //! Test
+ nUserSubCount = 1; //! Test
+
+ //! Test !!!!
+ ScSubTotalFunc eOld = eColForce;
+ long nOldSub = nColSubTotalFunc;
+ //! Test !!!!
+
+ long nMemberMeasure = nMeasure;
+ long nSubSize = pResultData->GetCountForMeasure(nMeasure);
+ if (bHasChild)
+ rCol -= nSubSize * nUserSubCount; // GetSize includes space for SubTotal
+
+ for (long nUserPos=0; nUserPos<nUserSubCount; nUserPos++)
+ {
+ //! Test !!!!
+ if ( pChildDimension )
+ {
+ ScDPLevel* pForceLevel = pResultMember ? pResultMember->GetParentLevel() : NULL;
+ nColSubTotalFunc = nUserPos;
+ eColForce = lcl_GetForceFunc( pForceLevel, nUserPos );
+ }
+ //! Test !!!!
+
+ for ( long nSubCount=0; nSubCount<nSubSize; nSubCount++ )
+ {
+ if ( nMeasure == SC_DPMEASURE_ALL )
+ nMemberMeasure = nSubCount;
+
+ DBG_ASSERT( rCol < rSequence.getLength(), "bumm" );
+ sheet::DataResult& rRes = rSequence.getArray()[rCol];
+
+ if ( pDataMember->HasData(nMemberMeasure) )
+ {
+ if ( pDataMember->HasError(nMemberMeasure) )
+ {
+ rRes.Value = 0;
+ rRes.Flags |= sheet::DataResultFlags::ERROR;
+ }
+ else
+ {
+ rRes.Value = pDataMember->GetAggregate(nMemberMeasure);
+ rRes.Flags |= sheet::DataResultFlags::HASDATA;
+ }
+ }
+
+ if ( bHasChild || bIsSubTotalRow )
+ rRes.Flags |= sheet::DataResultFlags::SUBTOTAL;
+
+ rCol += 1;
+ }
+ }
+
+ //! Test !!!!
+ eColForce = eOld;
+ nColSubTotalFunc = nOldSub;
+ //! Test !!!!
+ }
+ }
+}
+
+
+// -----------------------------------------------------------------------
+
+ScDPResultDimension::ScDPResultDimension( ScDPResultData* pData ) :
+ pResultData( pData ),
+ bIsDataLayout( FALSE )
+{
+}
+
+ScDPResultDimension::~ScDPResultDimension()
+{
+}
+
+void ScDPResultDimension::InitFrom( ScDPDimension** ppDim, ScDPLevel** ppLev )
+{
+ ScDPDimension* pThisDim = *ppDim;
+ ScDPLevel* pThisLevel = *ppLev;
+ if (pThisDim && pThisLevel)
+ {
+ ScDPDimension** ppChildDim = ppDim + 1;
+ ScDPLevel** ppChildLev = ppLev + 1;
+
+ bIsDataLayout = pThisDim->getIsDataLayoutDimension();
+
+ ScDPMembers* pMembers = pThisLevel->GetMembersObject();
+ long nMembCount = pMembers->getCount();
+ for ( long i=0; i<nMembCount; i++ )
+ {
+ ScDPMember* pMember = pMembers->getByIndex(i);
+ ScDPResultMember* pNew = new ScDPResultMember( pResultData, pThisDim,
+ pThisLevel, pMember, FALSE );
+ aMembers.Insert( pNew, aMembers.Count() );
+
+ pNew->InitFrom( ppChildDim, ppChildLev );
+ }
+ }
+}
+
+long ScDPResultDimension::GetSize(long nMeasure) const
+{
+ long nTotal = 0;
+ long nMemberCount = aMembers.Count();
+ if (bIsDataLayout)
+ {
+ DBG_ASSERT(nMeasure == SC_DPMEASURE_ALL || pResultData->GetMeasureCount() == 1,
+ "DataLayout dimension twice?");
+ // repeat first member...
+ nTotal = nMemberCount * aMembers[0]->GetSize(0); // all measures have equal size
+ }
+ else
+ {
+ // add all members
+ for (long nMem=0; nMem<nMemberCount; nMem++)
+ nTotal += aMembers[(USHORT)nMem]->GetSize(nMeasure);
+ }
+ return nTotal;
+}
+
+BOOL ScDPResultDimension::IsValidEntry( const ScDPItemData* pMembers ) const
+{
+ //! pass end-marker behind valid members?
+
+// if (!pMembers->IsEmpty()) //! non-empty sequence..
+ {
+ long nCount = aMembers.Count();
+ for (long i=0; i<nCount; i++)
+ {
+ ScDPResultMember* pMember = aMembers[(USHORT)i];
+ if ( bIsDataLayout || pMember->IsNamedItem( *pMembers ) )
+ {
+ if ( !pMember->IsValid() )
+ return FALSE;
+
+ ScDPResultDimension* pChildDim = pMember->GetChildDimension();
+ if (pChildDim)
+ return pChildDim->IsValidEntry( pMembers + 1 );
+ else
+ return TRUE;
+ }
+ }
+ }
+ DBG_ERROR("IsValidEntry: Member not found");
+ return FALSE;
+}
+
+void ScDPResultDimension::ProcessData( const ScDPItemData* pMembers,
+ ScDPResultDimension* pDataDim, const ScDPItemData* pDataMembers,
+ const ScDPValueData* pValues )
+{
+ //! pass end-marker behind valid members?
+
+// if (!pMembers->IsEmpty()) //! non-empty sequence..
+ {
+ long nCount = aMembers.Count();
+ for (long i=0; i<nCount; i++)
+ {
+ ScDPResultMember* pMember = aMembers[(USHORT)i];
+
+ // always first member for data layout dim
+ if ( bIsDataLayout || pMember->IsNamedItem( *pMembers ) )
+ {
+ pMember->ProcessData( pMembers + 1, pDataDim, pDataMembers, pValues );
+ return;
+ }
+ }
+ }
+ DBG_ERROR("ProcessData: Member not found");
+}
+
+void ScDPResultDimension::FillMemberResults( uno::Sequence<sheet::MemberResult>* pSequences,
+ long nStart, long nMeasure )
+{
+ long nPos = nStart;
+ long nCount = aMembers.Count();
+
+ for (long i=0; i<nCount; i++)
+ {
+ ScDPResultMember* pMember = aMembers[(USHORT)i];
+ // in data layout dimension, use first member with different measures/names
+ if ( bIsDataLayout )
+ {
+ String aMbrName = pResultData->GetMeasureDimensionName( i );
+ String aMbrCapt = pResultData->GetMeasureString( i, FALSE, SUBTOTAL_FUNC_NONE );
+ aMembers[0]->FillMemberResults( pSequences, nPos, i, FALSE, &aMbrName, &aMbrCapt );
+ }
+ else if ( pMember->IsVisible() )
+ pMember->FillMemberResults( pSequences, nPos, nMeasure, FALSE, NULL, NULL );
+ // nPos is modified
+ }
+}
+
+void ScDPResultDimension::FillDataResults( const ScDPResultMember* pRefMember,
+ uno::Sequence< uno::Sequence<sheet::DataResult> >& rSequence,
+ long nRow, long nMeasure ) const
+{
+ long nMemberRow = nRow;
+ long nMemberMeasure = nMeasure;
+ long nCount = aMembers.Count();
+ for (long i=0; i<nCount; i++)
+ {
+ const ScDPResultMember* pMember;
+ if (bIsDataLayout)
+ {
+ DBG_ASSERT(nMeasure == SC_DPMEASURE_ALL || pResultData->GetMeasureCount() == 1,
+ "DataLayout dimension twice?");
+ pMember = aMembers[0];
+ nMemberMeasure = i;
+ }
+ else
+ pMember = aMembers[(USHORT)i];
+
+ if ( pMember->IsVisible() )
+ pMember->FillDataResults( pRefMember, rSequence, nMemberRow, nMemberMeasure );
+ // nMemberRow is modified
+ }
+}
+
+long ScDPResultDimension::GetMemberCount() const
+{
+ return aMembers.Count();
+}
+
+ScDPResultMember* ScDPResultDimension::GetMember(long n) const
+{
+ return aMembers[(USHORT)n];
+}
+
+ScDPResultDimension* ScDPResultDimension::GetFirstChildDimension() const
+{
+ if ( aMembers.Count() > 0 )
+ return aMembers[0]->GetChildDimension();
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ScDPDataDimension::ScDPDataDimension( ScDPResultData* pData ) :
+ pResultData( pData ),
+ bIsDataLayout( FALSE )
+{
+}
+
+ScDPDataDimension::~ScDPDataDimension()
+{
+}
+
+void ScDPDataDimension::InitFrom( ScDPResultDimension* pDim )
+{
+ if (!pDim)
+ return;
+
+ bIsDataLayout = pDim->IsDataLayout();
+
+ long nCount = pDim->GetMemberCount();
+ for (long i=0; i<nCount; i++)
+ {
+ ScDPResultMember* pResMem = pDim->GetMember(i);
+
+ ScDPDataMember* pNew = new ScDPDataMember( pResultData, pResMem );
+ aMembers.Insert( pNew, aMembers.Count() );
+
+ ScDPResultDimension* pChildDim = pResMem->GetChildDimension();
+ if ( pChildDim )
+ pNew->InitFrom( pChildDim );
+ }
+}
+
+void ScDPDataDimension::ProcessData( const ScDPItemData* pDataMembers, const ScDPValueData* pValues )
+{
+ //! pass end-marker behind valid members?
+
+// if (!pDataMembers->IsEmpty()) //! non-empty sequence..
+ {
+ long nCount = aMembers.Count();
+ for (long i=0; i<nCount; i++)
+ {
+ ScDPDataMember* pMember = aMembers[(USHORT)i];
+
+ // always first member for data layout dim
+ if ( bIsDataLayout || pMember->IsNamedItem( *pDataMembers ) )
+ {
+ pMember->ProcessData( pDataMembers + 1, pValues );
+ return;
+ }
+ }
+ }
+ DBG_ERROR("ProcessData: Member not found");
+}
+
+void ScDPDataDimension::FillDataRow( const ScDPResultDimension* pRefDim,
+ uno::Sequence<sheet::DataResult>& rSequence,
+ long nCol, long nMeasure, BOOL bIsSubTotalRow ) const
+{
+ DBG_ASSERT( pRefDim && pRefDim->GetMemberCount() == aMembers.Count(), "dimensions don't match" );
+
+ long nMemberMeasure = nMeasure;
+ long nMemberCol = nCol;
+ long nCount = aMembers.Count();
+ for (long i=0; i<nCount; i++)
+ {
+ long nMemberPos = i;
+ if (bIsDataLayout)
+ {
+ DBG_ASSERT(nMeasure == SC_DPMEASURE_ALL || pResultData->GetMeasureCount() == 1,
+ "DataLayout dimension twice?");
+ nMemberPos = 0;
+ nMemberMeasure = i;
+ }
+
+ const ScDPResultMember* pRefMember = pRefDim->GetMember(nMemberPos);
+ if ( pRefMember->IsVisible() ) //! here or in ScDPDataMember::FillDataRow ???
+ {
+ const ScDPDataMember* pDataMember = aMembers[(USHORT)nMemberPos];
+ pDataMember->FillDataRow( pRefMember, rSequence, nMemberCol, nMemberMeasure, bIsSubTotalRow );
+ // nMemberCol is modified
+ }
+ }
+}
+
+
+
+
diff --git a/sc/source/core/data/dptabsrc.cxx b/sc/source/core/data/dptabsrc.cxx
new file mode 100644
index 000000000000..3cf5ae3c114c
--- /dev/null
+++ b/sc/source/core/data/dptabsrc.cxx
@@ -0,0 +1,2002 @@
+/*************************************************************************
+ *
+ * $RCSfile: dptabsrc.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <tools/debug.hxx>
+#include <tools/intn.hxx>
+#include <tools/solmath.hxx>
+#include <svtools/itemprop.hxx>
+
+#include "dptabsrc.hxx"
+#include "dptabres.hxx"
+#include "dptabdat.hxx"
+#include "global.hxx"
+#include "collect.hxx"
+#include "datauno.hxx" // ScDataUnoConversion
+#include "unoguard.hxx"
+#include "miscuno.hxx"
+#include "unonames.hxx"
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
+
+using namespace com::sun::star;
+
+// -----------------------------------------------------------------------
+
+SC_SIMPLE_SERVICE_INFO( ScDPSource, "ScDPSource", "com.sun.star.sheet.DataPilotSource" )
+SC_SIMPLE_SERVICE_INFO( ScDPDimensions, "ScDPDimensions", "com.sun.star.sheet.DataPilotSourceDimensions" )
+SC_SIMPLE_SERVICE_INFO( ScDPDimension, "ScDPDimension", "com.sun.star.sheet.DataPilotSourceDimension" )
+SC_SIMPLE_SERVICE_INFO( ScDPHierarchies, "ScDPHierarchies", "com.sun.star.sheet.DataPilotSourceHierarcies" )
+SC_SIMPLE_SERVICE_INFO( ScDPHierarchy, "ScDPHierarchy", "com.sun.star.sheet.DataPilotSourceHierarcy" )
+SC_SIMPLE_SERVICE_INFO( ScDPLevels, "ScDPLevels", "com.sun.star.sheet.DataPilotSourceLevels" )
+SC_SIMPLE_SERVICE_INFO( ScDPLevel, "ScDPLevel", "com.sun.star.sheet.DataPilotSourceLevel" )
+SC_SIMPLE_SERVICE_INFO( ScDPMembers, "ScDPMembers", "com.sun.star.sheet.DataPilotSourceMembers" )
+SC_SIMPLE_SERVICE_INFO( ScDPMember, "ScDPMember", "com.sun.star.sheet.DataPilotSourceMember" )
+
+// -----------------------------------------------------------------------
+
+// property maps for PropertySetInfo
+// DataDescription / NumberFormat are internal
+
+// -----------------------------------------------------------------------
+
+//! move to a header?
+BOOL lcl_GetBoolFromAny( const uno::Any& aAny )
+{
+ if ( aAny.getValueTypeClass() == uno::TypeClass_BOOLEAN )
+ return *(sal_Bool*)aAny.getValue();
+ return FALSE;
+}
+
+void lcl_SetBoolInAny( uno::Any& rAny, BOOL bValue )
+{
+ rAny.setValue( &bValue, getBooleanCppuType() );
+}
+
+// -----------------------------------------------------------------------
+
+ScDPSource::ScDPSource( ScDPTableData* pD ) :
+ pData( pD ),
+ pDimensions( NULL ),
+ nColDimCount( 0 ),
+ nRowDimCount( 0 ),
+ nDataDimCount( 0 ),
+ nPageDimCount( 0 ),
+ nDupCount( 0 ),
+ pResData( NULL ),
+ pColResRoot( NULL ),
+ pRowResRoot( NULL ),
+ pColResults( NULL ),
+ pRowResults( NULL ),
+ bColumnGrand( TRUE ), // default is true
+ bRowGrand( TRUE ),
+ bIgnoreEmptyRows( FALSE ),
+ bRepeatIfEmpty( FALSE )
+{
+ pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
+}
+
+ScDPSource::~ScDPSource()
+{
+ delete pData; // ScDPTableData is not ref-counted
+
+ if (pDimensions)
+ pDimensions->release(); // ref-counted
+
+ //! free lists
+
+ delete[] pColResults;
+ delete[] pRowResults;
+
+ delete pColResRoot;
+ delete pRowResRoot;
+ delete pResData;
+}
+
+USHORT ScDPSource::GetOrientation(long nColumn)
+{
+ long i;
+ for (i=0; i<nColDimCount; i++)
+ if (nColDims[i] == nColumn)
+ return sheet::DataPilotFieldOrientation_COLUMN;
+ for (i=0; i<nRowDimCount; i++)
+ if (nRowDims[i] == nColumn)
+ return sheet::DataPilotFieldOrientation_ROW;
+ for (i=0; i<nDataDimCount; i++)
+ if (nDataDims[i] == nColumn)
+ return sheet::DataPilotFieldOrientation_DATA;
+ for (i=0; i<nPageDimCount; i++)
+ if (nPageDims[i] == nColumn)
+ return sheet::DataPilotFieldOrientation_PAGE;
+ return sheet::DataPilotFieldOrientation_HIDDEN;
+}
+
+long ScDPSource::GetDataDimensionCount()
+{
+ return nDataDimCount;
+}
+
+String ScDPSource::GetDataDimName( long nIndex )
+{
+ String aRet;
+ if ( nIndex >= 0 && nIndex < nDataDimCount )
+ {
+ long nDimIndex = nDataDims[nIndex];
+ ScDPDimension* pDim = GetDimensionsObject()->getByIndex(nDimIndex);
+ if (pDim)
+ aRet = String( pDim->getName() );
+ }
+ return aRet;
+}
+
+long ScDPSource::GetPosition(long nColumn)
+{
+ long i;
+ for (i=0; i<nColDimCount; i++)
+ if (nColDims[i] == nColumn)
+ return i;
+ for (i=0; i<nRowDimCount; i++)
+ if (nRowDims[i] == nColumn)
+ return i;
+ for (i=0; i<nDataDimCount; i++)
+ if (nDataDims[i] == nColumn)
+ return i;
+ for (i=0; i<nPageDimCount; i++)
+ if (nPageDims[i] == nColumn)
+ return i;
+ return 0;
+}
+
+BOOL lcl_TestSubTotal( BOOL& rAllowed, long nColumn, long* pArray, long nCount, ScDPSource* pSource )
+{
+ for (long i=0; i<nCount; i++)
+ if (pArray[i] == nColumn)
+ {
+ // no subtotals for data layout dim, no matter where
+ if ( pSource->IsDataLayoutDimension(nColumn) )
+ rAllowed = FALSE;
+ else
+ {
+ // no subtotals if no other dim but data layout follows
+ long nNextIndex = i+1;
+ if ( nNextIndex < nCount && pSource->IsDataLayoutDimension(pArray[nNextIndex]) )
+ ++nNextIndex;
+ if ( nNextIndex >= nCount )
+ rAllowed = FALSE;
+ }
+
+ return TRUE; // found
+ }
+ return FALSE;
+}
+
+BOOL ScDPSource::SubTotalAllowed(long nColumn)
+{
+ //! cache this at ScDPResultData
+ BOOL bAllowed = TRUE;
+ if ( lcl_TestSubTotal( bAllowed, nColumn, nColDims, nColDimCount, this ) )
+ return bAllowed;
+ if ( lcl_TestSubTotal( bAllowed, nColumn, nRowDims, nRowDimCount, this ) )
+ return bAllowed;
+ return bAllowed;
+}
+
+void lcl_RemoveDim( long nRemove, long* pDims, long& rCount )
+{
+ for (long i=0; i<rCount; i++)
+ if ( pDims[i] == nRemove )
+ {
+ for (long j=i; j+1<rCount; j++)
+ pDims[j] = pDims[j+1];
+ --rCount;
+ return;
+ }
+}
+
+void ScDPSource::SetOrientation(long nColumn, USHORT nNew)
+{
+ //! change to no-op if new orientation is equal to old?
+
+ // remove from old list
+ lcl_RemoveDim( nColumn, nColDims, nColDimCount );
+ lcl_RemoveDim( nColumn, nRowDims, nRowDimCount );
+ lcl_RemoveDim( nColumn, nDataDims, nDataDimCount );
+ lcl_RemoveDim( nColumn, nPageDims, nPageDimCount );
+
+ // add to new list
+ switch (nNew)
+ {
+ case sheet::DataPilotFieldOrientation_COLUMN:
+ nColDims[nColDimCount++] = nColumn;
+ break;
+ case sheet::DataPilotFieldOrientation_ROW:
+ nRowDims[nRowDimCount++] = nColumn;
+ break;
+ case sheet::DataPilotFieldOrientation_DATA:
+ nDataDims[nDataDimCount++] = nColumn;
+ break;
+ case sheet::DataPilotFieldOrientation_PAGE:
+ nPageDims[nPageDimCount++] = nColumn;
+ break;
+ }
+}
+
+BOOL ScDPSource::IsDataLayoutDimension(long nDim)
+{
+ return nDim == pData->GetColumnCount();
+}
+
+USHORT ScDPSource::GetDataLayoutOrientation()
+{
+ return GetOrientation(pData->GetColumnCount());
+}
+
+BOOL ScDPSource::IsDateDimension(long nDim)
+{
+ return pData->IsDateDimension(nDim);
+}
+
+ScDPDimensions* ScDPSource::GetDimensionsObject()
+{
+ if (!pDimensions)
+ {
+ pDimensions = new ScDPDimensions(this);
+ pDimensions->acquire(); // ref-counted
+ }
+ return pDimensions;
+}
+
+uno::Reference<container::XNameAccess> SAL_CALL ScDPSource::getDimensions() throw(uno::RuntimeException)
+{
+ return GetDimensionsObject();
+}
+
+void ScDPSource::SetDupCount( long nNew )
+{
+ nDupCount = nNew;
+}
+
+ScDPDimension* ScDPSource::AddDuplicated(long nSource, const String& rNewName)
+{
+ DBG_ASSERT( pDimensions, "AddDuplicated without dimensions?" );
+
+ // re-use
+
+ long nOldDimCount = pDimensions->getCount();
+ for (long i=0; i<nOldDimCount; i++)
+ {
+ ScDPDimension* pDim = pDimensions->getByIndex(i);
+ if (pDim && String(pDim->getName()) == rNewName)
+ {
+ //! test if pDim is a duplicate of source
+ return pDim;
+ }
+ }
+
+ SetDupCount( nDupCount + 1 );
+ pDimensions->CountChanged(); // uses nDupCount
+
+ return pDimensions->getByIndex( pDimensions->getCount() - 1 );
+}
+
+long ScDPSource::GetSourceDim(long nDim)
+{
+ // original source dimension or data layout dimension?
+ if ( nDim <= pData->GetColumnCount() )
+ return nDim;
+
+ if ( nDim < pDimensions->getCount() )
+ {
+ ScDPDimension* pDimObj = pDimensions->getByIndex( nDim );
+ if ( pDimObj )
+ {
+ long nSource = pDimObj->GetSourceDim();
+ if ( nSource >= 0 )
+ return nSource;
+ }
+ }
+
+ DBG_ERROR("GetSourceDim: wrong dim");
+ return nDim;
+}
+
+uno::Sequence< uno::Sequence<sheet::DataResult> > SAL_CALL ScDPSource::getResults()
+ throw(uno::RuntimeException)
+{
+ CreateRes_Impl(); // create pColResRoot and pRowResRoot
+
+ long nColCount = pColResRoot->GetSize(pResData->GetColStartMeasure());
+ long nRowCount = pRowResRoot->GetSize(pResData->GetRowStartMeasure());
+
+ // allocate full sequence
+ //! leave out empty rows???
+
+ uno::Sequence< uno::Sequence<sheet::DataResult> > aSeq( nRowCount );
+ uno::Sequence<sheet::DataResult>* pRowAry = aSeq.getArray();
+ for (long nRow = 0; nRow < nRowCount; nRow++)
+ {
+ uno::Sequence<sheet::DataResult> aColSeq( nColCount );
+ // use default values of DataResult
+ pRowAry[nRow] = aColSeq;
+ }
+
+ long nSeqRow = 0;
+ pRowResRoot->FillDataResults( pColResRoot, aSeq, nSeqRow, pResData->GetRowStartMeasure() );
+
+ return aSeq;
+}
+
+void SAL_CALL ScDPSource::refresh() throw(uno::RuntimeException)
+{
+ disposeData();
+}
+
+void SAL_CALL ScDPSource::addRefreshListener( const uno::Reference<util::XRefreshListener >& l )
+ throw(uno::RuntimeException)
+{
+ DBG_ERROR("not implemented"); //! exception?
+}
+
+void SAL_CALL ScDPSource::removeRefreshListener( const uno::Reference<util::XRefreshListener >& l )
+ throw(uno::RuntimeException)
+{
+ DBG_ERROR("not implemented"); //! exception?
+}
+
+String ScDPSource::getDataDescription()
+{
+ CreateRes_Impl(); // create pResData
+
+ String aRet;
+ if ( pResData->GetMeasureCount() == 1 )
+ aRet = pResData->GetMeasureString( 0, TRUE, SUBTOTAL_FUNC_NONE );
+
+ // empty for more than one measure
+
+ return aRet;
+}
+
+BOOL ScDPSource::getColumnGrand() const
+{
+ return bColumnGrand;
+}
+
+void ScDPSource::setColumnGrand(BOOL bSet)
+{
+ bColumnGrand = bSet;
+}
+
+BOOL ScDPSource::getRowGrand() const
+{
+ return bRowGrand;
+}
+
+void ScDPSource::setRowGrand(BOOL bSet)
+{
+ bRowGrand = bSet;
+}
+
+BOOL ScDPSource::getIgnoreEmptyRows() const
+{
+ return bIgnoreEmptyRows;
+}
+
+void ScDPSource::setIgnoreEmptyRows(BOOL bSet)
+{
+ bIgnoreEmptyRows = bSet;
+ pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
+}
+
+BOOL ScDPSource::getRepeatIfEmpty() const
+{
+ return bRepeatIfEmpty;
+}
+
+void ScDPSource::setRepeatIfEmpty(BOOL bSet)
+{
+ bRepeatIfEmpty = bSet;
+ pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
+}
+
+void ScDPSource::validate() //! ???
+{
+ CreateRes_Impl();
+}
+
+void ScDPSource::disposeData()
+{
+ if ( pResData )
+ {
+ // reset all data...
+
+ DELETEZ(pColResRoot);
+ DELETEZ(pRowResRoot);
+ DELETEZ(pResData);
+ delete[] pColResults;
+ delete[] pRowResults;
+ pColResults = NULL;
+ pRowResults = NULL;
+ aColLevelList.Clear();
+ aRowLevelList.Clear();
+ }
+
+ if ( pDimensions )
+ {
+ pDimensions->release(); // ref-counted
+ pDimensions = NULL; // settings have to be applied (from SaveData) again!
+ }
+ SetDupCount( 0 );
+
+ //! Test ????
+ nColDimCount = nRowDimCount = nDataDimCount = nPageDimCount = 0;
+
+ pData->DisposeData(); // cached entries etc.
+}
+
+void ScDPSource::CreateRes_Impl()
+{
+ if ( !pResData )
+ {
+ USHORT nDataOrient = GetDataLayoutOrientation();
+ if ( nDataDimCount > 1 && nDataOrient == sheet::DataPilotFieldOrientation_HIDDEN )
+ {
+ // if more than one data dimension, data layout orientation must be set
+ SetOrientation( pData->GetColumnCount(), sheet::DataPilotFieldOrientation_ROW );
+ nDataOrient = sheet::DataPilotFieldOrientation_ROW;
+ }
+
+ String* pDataNames = NULL;
+ if (nDataDimCount)
+ pDataNames = new String[nDataDimCount];
+
+ long nDataSrcCols[SC_DAPI_MAXFIELDS];
+
+ long i;
+ for (i=0; i<nDataDimCount; i++)
+ {
+ long nDimIndex = nDataDims[i];
+ ScDPDimension* pDim = GetDimensionsObject()->getByIndex(nDimIndex);
+ sheet::GeneralFunction eUser = (sheet::GeneralFunction)pDim->getFunction();
+ if (eUser == sheet::GeneralFunction_AUTO)
+ {
+ //! test for numeric data
+ eUser = sheet::GeneralFunction_SUM;
+ }
+ eDataFunctions[i] = ScDataUnoConversion::GeneralToSubTotal( eUser );
+ pDataNames[i] = String( pDim->getName() ); //! label?
+
+ // asterisk is added to duplicated dimension names by ScDPSaveData::WriteToSource
+ //! modify user visible strings as in ScDPResultData::GetMeasureString instead!
+
+ pDataNames[i].EraseTrailingChars('*');
+
+ //! if the name is overridden by user, a flag must be set
+ //! so the user defined name replaces the function string and field name.
+
+ //! the complete name (function and field) must be stored at the dimension
+
+ long nSource = ((ScDPDimension*)pDim)->GetSourceDim();
+ if ( nSource >= 0 )
+ nDataSrcCols[i] = nSource;
+ else
+ nDataSrcCols[i] = nDimIndex;
+ }
+
+ pResData = new ScDPResultData( this );
+ pResData->SetMeasureData( nDataDimCount, eDataFunctions, pDataNames );
+ pResData->SetDataLayoutOrientation(nDataOrient);
+
+ delete[] pDataNames;
+
+ pColResRoot = new ScDPResultMember( pResData, NULL, NULL, NULL, bColumnGrand );
+ pRowResRoot = new ScDPResultMember( pResData, NULL, NULL, NULL, bRowGrand );
+
+ ScDPDimension* ppColDim[SC_DAPI_MAXFIELDS]; //! Ref?
+ ScDPLevel* ppColLevel[SC_DAPI_MAXFIELDS]; //! Ref?
+ long nColLevelDims[SC_DAPI_MAXFIELDS];
+ long nColLevelCount = 0;
+ for (i=0; i<nColDimCount; i++)
+ {
+ ScDPDimension* pDim = GetDimensionsObject()->getByIndex( nColDims[i] );
+ long nHierarchy = pDim->getUsedHierarchy();
+ if ( nHierarchy >= pDim->GetHierarchiesObject()->getCount() )
+ nHierarchy = 0;
+ ScDPLevels* pLevels = pDim->GetHierarchiesObject()->getByIndex(nHierarchy)->GetLevelsObject();
+ long nCount = pLevels->getCount();
+
+ //! Test
+ if ( pDim->getIsDataLayoutDimension() && nDataDimCount < 2 )
+ nCount = 0;
+ //! Test
+
+ for (long j=0; j<nCount; j++)
+ {
+ nColLevelDims[nColLevelCount] = nColDims[i];
+ ppColDim[nColLevelCount] = pDim;
+ ppColLevel[nColLevelCount] = pLevels->getByIndex(j);
+ ++nColLevelCount;
+ }
+ }
+ ppColDim[nColLevelCount] = NULL;
+ ppColLevel[nColLevelCount] = NULL;
+
+ pColResRoot->InitFrom( ppColDim, ppColLevel );
+ pColResRoot->SetHasElements();
+
+ ScDPDimension* ppRowDim[SC_DAPI_MAXFIELDS]; //! Ref?
+ ScDPLevel* ppRowLevel[SC_DAPI_MAXFIELDS]; //! Ref?
+ long nRowLevelDims[SC_DAPI_MAXFIELDS];
+ long nRowLevelCount = 0;
+ for (i=0; i<nRowDimCount; i++)
+ {
+ ScDPDimension* pDim = GetDimensionsObject()->getByIndex( nRowDims[i] );
+ long nHierarchy = pDim->getUsedHierarchy();
+ if ( nHierarchy >= pDim->GetHierarchiesObject()->getCount() )
+ nHierarchy = 0;
+ ScDPLevels* pLevels = pDim->GetHierarchiesObject()->getByIndex(nHierarchy)->GetLevelsObject();
+ long nCount = pLevels->getCount();
+
+ //! Test
+ if ( pDim->getIsDataLayoutDimension() && nDataDimCount < 2 )
+ nCount = 0;
+ //! Test
+
+ for (long j=0; j<nCount; j++)
+ {
+ nRowLevelDims[nRowLevelCount] = nRowDims[i];
+ ppRowDim[nRowLevelCount] = pDim;
+ ppRowLevel[nRowLevelCount] = pLevels->getByIndex(j);
+ ++nRowLevelCount;
+ }
+ }
+ ppRowDim[nRowLevelCount] = NULL;
+ ppRowLevel[nRowLevelCount] = NULL;
+
+ pRowResRoot->InitFrom( ppRowDim, ppRowLevel );
+ pRowResRoot->SetHasElements();
+
+ ScDPItemData aColData[SC_DAPI_MAXFIELDS];
+ ScDPItemData aRowData[SC_DAPI_MAXFIELDS];
+ ScDPValueData aValues[SC_DAPI_MAXFIELDS];
+
+ ScDPTableIteratorParam aIterPar(
+ nColLevelCount, nColLevelDims, aColData,
+ nRowLevelCount, nRowLevelDims, aRowData,
+ nDataDimCount, nDataSrcCols, aValues );
+
+ pData->ResetIterator();
+ while ( pData->GetNextRow( aIterPar ) )
+ {
+ // test for filtered entries
+ //! test child dimensions for null !!!
+ if ( ( !pColResRoot->GetChildDimension() || pColResRoot->GetChildDimension()->IsValidEntry( aColData ) ) &&
+ ( !pRowResRoot->GetChildDimension() || pRowResRoot->GetChildDimension()->IsValidEntry( aRowData ) ) )
+ {
+ //! single process method with ColMembers, RowMembers and data !!!
+ if (pColResRoot->GetChildDimension())
+ pColResRoot->GetChildDimension()->ProcessData( aColData, NULL, NULL, aValues );
+
+ pRowResRoot->ProcessData( aRowData, pColResRoot->GetChildDimension(), aColData, aValues );
+ }
+ }
+ }
+}
+
+void ScDPSource::FillLevelList( USHORT nOrientation, List& rList )
+{
+ rList.Clear();
+
+ long nDimCount = 0;
+ long* pDimIndex = NULL;
+ switch (nOrientation)
+ {
+ case sheet::DataPilotFieldOrientation_COLUMN:
+ pDimIndex = nColDims;
+ nDimCount = nColDimCount;
+ break;
+ case sheet::DataPilotFieldOrientation_ROW:
+ pDimIndex = nRowDims;
+ nDimCount = nRowDimCount;
+ break;
+ case sheet::DataPilotFieldOrientation_DATA:
+ pDimIndex = nDataDims;
+ nDimCount = nDataDimCount;
+ break;
+ case sheet::DataPilotFieldOrientation_PAGE:
+ pDimIndex = nPageDims;
+ nDimCount = nPageDimCount;
+ break;
+ }
+ if (!pDimIndex)
+ {
+ DBG_ERROR("invalid orientation")
+ return;
+ }
+
+ ScDPDimensions* pDims = GetDimensionsObject();
+ for (long nDim=0; nDim<nDimCount; nDim++)
+ {
+ ScDPDimension* pDim = pDims->getByIndex(pDimIndex[nDim]);
+ DBG_ASSERT( pDim->getOrientation() == nOrientation, "orientations are wrong" );
+
+ ScDPHierarchies* pHiers = pDim->GetHierarchiesObject();
+ long nHierarchy = pDim->getUsedHierarchy();
+ if ( nHierarchy >= pHiers->getCount() )
+ nHierarchy = 0;
+ ScDPHierarchy* pHier = pHiers->getByIndex(nHierarchy);
+ ScDPLevels* pLevels = pHier->GetLevelsObject();
+ long nLevCount = pLevels->getCount();
+ for (long nLev=0; nLev<nLevCount; nLev++)
+ {
+ ScDPLevel* pLevel = pLevels->getByIndex(nLev);
+ rList.Insert( pLevel, LIST_APPEND );
+ }
+ }
+}
+
+void ScDPSource::FillMemberResults()
+{
+ if ( !pColResults && !pRowResults )
+ {
+ CreateRes_Impl();
+
+ FillLevelList( sheet::DataPilotFieldOrientation_COLUMN, aColLevelList );
+ long nColLevelCount = aColLevelList.Count();
+ if (nColLevelCount)
+ {
+ long nColDimSize = pColResRoot->GetSize(pResData->GetColStartMeasure());
+ pColResults = new uno::Sequence<sheet::MemberResult>[nColLevelCount];
+ for (long i=0; i<nColLevelCount; i++)
+ pColResults[i].realloc(nColDimSize);
+
+ // ScDPResultDimension* pColResDim = pColResRoot->GetChildDimension();
+ // pColResDim->FillMemberResults( pColResults, 0, pResData->GetColStartMeasure() );
+ long nPos = 0;
+ pColResRoot->FillMemberResults( pColResults, nPos, pResData->GetColStartMeasure(),
+ TRUE, NULL, NULL );
+ }
+
+ FillLevelList( sheet::DataPilotFieldOrientation_ROW, aRowLevelList );
+ long nRowLevelCount = aRowLevelList.Count();
+ if (nRowLevelCount)
+ {
+ long nRowDimSize = pRowResRoot->GetSize(pResData->GetRowStartMeasure());
+ pRowResults = new uno::Sequence<sheet::MemberResult>[nRowLevelCount];
+ for (long i=0; i<nRowLevelCount; i++)
+ pRowResults[i].realloc(nRowDimSize);
+
+ // ScDPResultDimension* pRowResDim = pRowResRoot->GetChildDimension();
+ // pRowResDim->FillMemberResults( pRowResults, 0, pResData->GetRowStartMeasure() );
+ long nPos = 0;
+ pRowResRoot->FillMemberResults( pRowResults, nPos, pResData->GetRowStartMeasure(),
+ TRUE, NULL, NULL );
+ }
+ }
+}
+
+const uno::Sequence<sheet::MemberResult>* ScDPSource::GetMemberResults( ScDPLevel* pLevel )
+{
+ FillMemberResults();
+
+ long i;
+ long nColCount = aColLevelList.Count();
+ for (i=0; i<nColCount; i++)
+ {
+ ScDPLevel* pColLevel = (ScDPLevel*)aColLevelList.GetObject(i);
+ if ( pColLevel == pLevel )
+ return pColResults+i;
+ }
+ long nRowCount = aRowLevelList.Count();
+ for (i=0; i<nRowCount; i++)
+ {
+ ScDPLevel* pRowLevel = (ScDPLevel*)aRowLevelList.GetObject(i);
+ if ( pRowLevel == pLevel )
+ return pRowResults+i;
+ }
+ return NULL;
+}
+
+// XPropertySet
+
+uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPSource::getPropertySetInfo()
+ throw(uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+
+ static SfxItemPropertyMap aDPSourceMap_Impl[] =
+ {
+ {MAP_CHAR_LEN(SC_UNO_COLGRAND), 0, &getBooleanCppuType(), 0, 0 },
+ {MAP_CHAR_LEN(SC_UNO_DATADESC), 0, &getCppuType((rtl::OUString*)0), beans::PropertyAttribute::READONLY, 0 },
+ {MAP_CHAR_LEN(SC_UNO_IGNOREEM), 0, &getBooleanCppuType(), 0, 0 }, // for sheet data only
+ {MAP_CHAR_LEN(SC_UNO_REPEATIF), 0, &getBooleanCppuType(), 0, 0 }, // for sheet data only
+ {MAP_CHAR_LEN(SC_UNO_ROWGRAND), 0, &getBooleanCppuType(), 0, 0 },
+ {0,0,0,0}
+ };
+ static uno::Reference<beans::XPropertySetInfo> aRef =
+ new SfxItemPropertySetInfo( aDPSourceMap_Impl );
+ return aRef;
+}
+
+void SAL_CALL ScDPSource::setPropertyValue( const rtl::OUString& aPropertyName, const uno::Any& aValue )
+ throw(beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ String aNameStr = aPropertyName;
+ if ( aNameStr.EqualsAscii( SC_UNO_COLGRAND ) )
+ setColumnGrand( lcl_GetBoolFromAny( aValue ) );
+ else if ( aNameStr.EqualsAscii( SC_UNO_ROWGRAND ) )
+ setRowGrand( lcl_GetBoolFromAny( aValue ) );
+ else if ( aNameStr.EqualsAscii( SC_UNO_IGNOREEM ) )
+ setIgnoreEmptyRows( lcl_GetBoolFromAny( aValue ) );
+ else if ( aNameStr.EqualsAscii( SC_UNO_REPEATIF ) )
+ setRepeatIfEmpty( lcl_GetBoolFromAny( aValue ) );
+ else
+ {
+ DBG_ERROR("unknown property");
+ //! THROW( UnknownPropertyException() );
+ }
+}
+
+uno::Any SAL_CALL ScDPSource::getPropertyValue( const rtl::OUString& aPropertyName )
+ throw(beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ uno::Any aRet;
+ String aNameStr = aPropertyName;
+ if ( aNameStr.EqualsAscii( SC_UNO_COLGRAND ) )
+ lcl_SetBoolInAny( aRet, getColumnGrand() );
+ else if ( aNameStr.EqualsAscii( SC_UNO_ROWGRAND ) )
+ lcl_SetBoolInAny( aRet, getRowGrand() );
+ else if ( aNameStr.EqualsAscii( SC_UNO_IGNOREEM ) )
+ lcl_SetBoolInAny( aRet, getIgnoreEmptyRows() );
+ else if ( aNameStr.EqualsAscii( SC_UNO_REPEATIF ) )
+ lcl_SetBoolInAny( aRet, getRepeatIfEmpty() );
+ else if ( aNameStr.EqualsAscii( SC_UNO_DATADESC ) ) // read-only
+ aRet <<= rtl::OUString( getDataDescription() );
+ else
+ {
+ DBG_ERROR("unknown property");
+ //! THROW( UnknownPropertyException() );
+ }
+ return aRet;
+}
+
+SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPSource )
+
+// -----------------------------------------------------------------------
+
+ScDPDimensions::ScDPDimensions( ScDPSource* pSrc ) :
+ pSource( pSrc ),
+ ppDims( NULL )
+{
+ //! hold pSource
+
+ // include data layout dimension and duplicated dimensions
+ nDimCount = pSource->GetData()->GetColumnCount() + 1 + pSource->GetDupCount();
+}
+
+ScDPDimensions::~ScDPDimensions()
+{
+ //! release pSource
+
+ if (ppDims)
+ {
+ for (long i=0; i<nDimCount; i++)
+ if ( ppDims[i] )
+ ppDims[i]->release(); // ref-counted
+ delete[] ppDims;
+ }
+}
+
+void ScDPDimensions::CountChanged()
+{
+ // include data layout dimension and duplicated dimensions
+ long nNewCount = pSource->GetData()->GetColumnCount() + 1 + pSource->GetDupCount();
+ if ( ppDims )
+ {
+ long i;
+ long nCopy = Min( nNewCount, nDimCount );
+ ScDPDimension** ppNew = new ScDPDimension*[nNewCount];
+
+ for (i=0; i<nCopy; i++) // copy existing dims
+ ppNew[i] = ppDims[i];
+ for (i=nCopy; i<nNewCount; i++) // clear additional pointers
+ ppNew[i] = NULL;
+ for (i=nCopy; i<nDimCount; i++) // delete old dims if count is decreased
+ if ( ppDims[i] )
+ ppDims[i]->release(); // ref-counted
+
+ delete[] ppDims;
+ ppDims = ppNew;
+ }
+ nDimCount = nNewCount;
+}
+
+// very simple XNameAccess implementation using getCount/getByIndex
+
+uno::Any SAL_CALL ScDPDimensions::getByName( const rtl::OUString& aName )
+ throw(container::NoSuchElementException,
+ lang::WrappedTargetException, uno::RuntimeException)
+{
+ long nCount = getCount();
+ for (long i=0; i<nCount; i++)
+ if ( getByIndex(i)->getName() == aName )
+ {
+ uno::Reference<container::XNamed> xNamed = getByIndex(i);
+ uno::Any aRet;
+ aRet <<= xNamed;
+ return aRet;
+ }
+ return uno::Any();
+}
+
+uno::Sequence<rtl::OUString> SAL_CALL ScDPDimensions::getElementNames() throw(uno::RuntimeException)
+{
+ long nCount = getCount();
+ uno::Sequence<rtl::OUString> aSeq(nCount);
+ rtl::OUString* pArr = aSeq.getArray();
+ for (long i=0; i<nCount; i++)
+ pArr[i] = getByIndex(i)->getName();
+ return aSeq;
+}
+
+sal_Bool SAL_CALL ScDPDimensions::hasByName( const rtl::OUString& aName ) throw(uno::RuntimeException)
+{
+ long nCount = getCount();
+ for (long i=0; i<nCount; i++)
+ if ( getByIndex(i)->getName() == aName )
+ return TRUE;
+ return FALSE;
+}
+
+uno::Type SAL_CALL ScDPDimensions::getElementType() throw(uno::RuntimeException)
+{
+ return getCppuType((uno::Reference<container::XNamed>*)0);
+}
+
+sal_Bool SAL_CALL ScDPDimensions::hasElements() throw(uno::RuntimeException)
+{
+ return ( getCount() > 0 );
+}
+
+// end of XNameAccess implementation
+
+long ScDPDimensions::getCount() const
+{
+ // in tabular data, every column of source data is a dimension
+
+ return nDimCount;
+}
+
+ScDPDimension* ScDPDimensions::getByIndex(long nIndex) const
+{
+ if ( nIndex >= 0 && nIndex < nDimCount )
+ {
+ if ( !ppDims )
+ {
+ ((ScDPDimensions*)this)->ppDims = new ScDPDimension*[nDimCount];
+ for (long i=0; i<nDimCount; i++)
+ ppDims[i] = NULL;
+ }
+ if ( !ppDims[nIndex] )
+ {
+ ppDims[nIndex] = new ScDPDimension( pSource, nIndex );
+ ppDims[nIndex]->acquire(); // ref-counted
+ }
+
+ return ppDims[nIndex];
+ }
+
+ return NULL; //! exception?
+}
+
+// -----------------------------------------------------------------------
+
+ScDPDimension::ScDPDimension( ScDPSource* pSrc, long nD ) :
+ pSource( pSrc ),
+ nDim( nD ),
+ pHierarchies( NULL ),
+ nUsedHier( 0 ),
+ nFunction( SUBTOTAL_FUNC_SUM ), // sum is default
+ nSourceDim( -1 )
+{
+ //! hold pSource
+}
+
+ScDPDimension::~ScDPDimension()
+{
+ //! release pSource
+
+ if ( pHierarchies )
+ pHierarchies->release(); // ref-counted
+}
+
+ScDPHierarchies* ScDPDimension::GetHierarchiesObject()
+{
+ if (!pHierarchies)
+ {
+ pHierarchies = new ScDPHierarchies( pSource, nDim );
+ pHierarchies->acquire(); // ref-counted
+ }
+ return pHierarchies;
+}
+
+uno::Reference<container::XNameAccess> SAL_CALL ScDPDimension::getHierarchies()
+ throw(uno::RuntimeException)
+{
+ return GetHierarchiesObject();
+}
+
+::rtl::OUString SAL_CALL ScDPDimension::getName() throw(uno::RuntimeException)
+{
+ if (aName.Len())
+ return aName;
+ else
+ return pSource->GetData()->getDimensionName( nDim );
+}
+
+void SAL_CALL ScDPDimension::setName( const ::rtl::OUString& rNewName ) throw(uno::RuntimeException)
+{
+ // used after cloning
+ aName = String( rNewName );
+}
+
+USHORT ScDPDimension::getOrientation() const
+{
+ return pSource->GetOrientation( nDim );
+}
+
+void ScDPDimension::setOrientation(USHORT nNew)
+{
+ pSource->SetOrientation( nDim, nNew );
+}
+
+long ScDPDimension::getPosition() const
+{
+ return pSource->GetPosition( nDim );
+}
+
+void ScDPDimension::setPosition(long nNew)
+{
+ //! ...
+}
+
+BOOL ScDPDimension::getIsDataLayoutDimension() const
+{
+ return pSource->GetData()->getIsDataLayoutDimension( nDim );
+}
+
+USHORT ScDPDimension::getFunction() const
+{
+ return nFunction;
+}
+
+void ScDPDimension::setFunction(USHORT nNew)
+{
+ nFunction = nNew;
+}
+
+long ScDPDimension::getUsedHierarchy() const
+{
+ return nUsedHier;
+}
+
+void ScDPDimension::setUsedHierarchy(long nNew)
+{
+ nUsedHier = nNew;
+}
+
+ScDPDimension* ScDPDimension::CreateCloneObject()
+{
+ DBG_ASSERT( nSourceDim < 0, "recursive duplicate - not implemented" );
+
+ //! set new name here, or temporary name ???
+ String aNewName = aName;
+
+ ScDPDimension* pNew = pSource->AddDuplicated( nDim, aNewName );
+
+ pNew->aName = aNewName; //! here or in source?
+ pNew->nSourceDim = nDim; //! recursive?
+
+ return pNew;
+}
+
+uno::Reference<util::XCloneable> SAL_CALL ScDPDimension::createClone() throw(uno::RuntimeException)
+{
+ return CreateCloneObject();
+}
+
+BOOL ScDPDimension::isDuplicated() const
+{
+ return (nSourceDim >= 0);
+}
+
+// XPropertySet
+
+uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPDimension::getPropertySetInfo()
+ throw(uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+
+ static SfxItemPropertyMap aDPDimensionMap_Impl[] =
+ {
+ {MAP_CHAR_LEN(SC_UNO_FUNCTION), 0, &getCppuType((sheet::GeneralFunction*)0), 0, 0 },
+ {MAP_CHAR_LEN(SC_UNO_ISDATALA), 0, &getBooleanCppuType(), beans::PropertyAttribute::READONLY, 0 },
+ {MAP_CHAR_LEN(SC_UNO_NUMBERFO), 0, &getCppuType((sal_Int32*)0), beans::PropertyAttribute::READONLY, 0 },
+ {MAP_CHAR_LEN(SC_UNO_ORIENTAT), 0, &getCppuType((sheet::DataPilotFieldOrientation*)0), 0, 0 },
+ {MAP_CHAR_LEN(SC_UNO_ORIGINAL), 0, &getCppuType((uno::Reference<container::XNamed>*)0), beans::PropertyAttribute::READONLY, 0 },
+ {MAP_CHAR_LEN(SC_UNO_POSITION), 0, &getCppuType((sal_Int32*)0), 0, 0 },
+ {MAP_CHAR_LEN(SC_UNO_USEDHIER), 0, &getCppuType((sal_Int32*)0), 0, 0 },
+ {0,0,0,0}
+ };
+ static uno::Reference<beans::XPropertySetInfo> aRef =
+ new SfxItemPropertySetInfo( aDPDimensionMap_Impl );
+ return aRef;
+}
+
+void SAL_CALL ScDPDimension::setPropertyValue( const rtl::OUString& aPropertyName, const uno::Any& aValue )
+ throw(beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ String aNameStr = aPropertyName;
+ if ( aNameStr.EqualsAscii( SC_UNO_POSITION ) )
+ {
+ INT32 nInt;
+ if (aValue >>= nInt)
+ setPosition( nInt );
+ }
+ else if ( aNameStr.EqualsAscii( SC_UNO_USEDHIER ) )
+ {
+ INT32 nInt;
+ if (aValue >>= nInt)
+ setUsedHierarchy( nInt );
+ }
+ else if ( aNameStr.EqualsAscii( SC_UNO_ORIENTAT ) )
+ {
+ sheet::DataPilotFieldOrientation eEnum;
+ if (aValue >>= eEnum)
+ setOrientation( eEnum );
+ }
+ else if ( aNameStr.EqualsAscii( SC_UNO_FUNCTION ) )
+ {
+ sheet::GeneralFunction eEnum;
+ if (aValue >>= eEnum)
+ setFunction( eEnum );
+ }
+ else
+ {
+ DBG_ERROR("unknown property");
+ //! THROW( UnknownPropertyException() );
+ }
+}
+
+uno::Any SAL_CALL ScDPDimension::getPropertyValue( const rtl::OUString& aPropertyName )
+ throw(beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ uno::Any aRet;
+ String aNameStr = aPropertyName;
+ if ( aNameStr.EqualsAscii( SC_UNO_POSITION ) )
+ aRet <<= (sal_Int32) getPosition();
+ else if ( aNameStr.EqualsAscii( SC_UNO_USEDHIER ) )
+ aRet <<= (sal_Int32) getUsedHierarchy();
+ else if ( aNameStr.EqualsAscii( SC_UNO_ORIENTAT ) )
+ {
+ sheet::DataPilotFieldOrientation eVal = (sheet::DataPilotFieldOrientation)getOrientation();
+ aRet <<= eVal;
+ }
+ else if ( aNameStr.EqualsAscii( SC_UNO_FUNCTION ) )
+ {
+ sheet::GeneralFunction eVal = (sheet::GeneralFunction)getFunction();
+ aRet <<= eVal;
+ }
+ else if ( aNameStr.EqualsAscii( SC_UNO_ISDATALA ) ) // read-only properties
+ lcl_SetBoolInAny( aRet, getIsDataLayoutDimension() );
+ else if ( aNameStr.EqualsAscii( SC_UNO_NUMBERFO ) )
+ aRet <<= (sal_Int32) pSource->GetData()->GetNumberFormat(
+ ( nSourceDim >= 0 ) ? nSourceDim : nDim );
+ else if ( aNameStr.EqualsAscii( SC_UNO_ORIGINAL ) )
+ {
+ uno::Reference<container::XNamed> xOriginal;
+ if (nSourceDim >= 0)
+ xOriginal = pSource->GetDimensionsObject()->getByIndex(nSourceDim);
+ aRet <<= xOriginal;
+ }
+ else
+ {
+ DBG_ERROR("unknown property");
+ //! THROW( UnknownPropertyException() );
+ }
+ return aRet;
+}
+
+SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPDimension )
+
+// -----------------------------------------------------------------------
+
+ScDPHierarchies::ScDPHierarchies( ScDPSource* pSrc, long nD ) :
+ pSource( pSrc ),
+ nDim( nD ),
+ ppHiers( NULL )
+{
+ //! hold pSource
+
+ // date columns have 3 hierarchies (flat/quarter/week), other columns only one
+ long nSrcDim = pSource->GetSourceDim( nDim );
+ if ( pSource->IsDateDimension( nSrcDim ) )
+ nHierCount = SC_DAPI_DATE_HIERARCHIES;
+ else
+ nHierCount = 1;
+}
+
+ScDPHierarchies::~ScDPHierarchies()
+{
+ //! release pSource
+
+ if (ppHiers)
+ {
+ for (long i=0; i<nHierCount; i++)
+ if ( ppHiers[i] )
+ ppHiers[i]->release(); // ref-counted
+ delete[] ppHiers;
+ }
+}
+
+// very simple XNameAccess implementation using getCount/getByIndex
+
+uno::Any SAL_CALL ScDPHierarchies::getByName( const rtl::OUString& aName )
+ throw(container::NoSuchElementException,
+ lang::WrappedTargetException, uno::RuntimeException)
+{
+ long nCount = getCount();
+ for (long i=0; i<nCount; i++)
+ if ( getByIndex(i)->getName() == aName )
+ {
+ uno::Reference<container::XNamed> xNamed = getByIndex(i);
+ uno::Any aRet;
+ aRet <<= xNamed;
+ return aRet;
+ }
+ return uno::Any();
+}
+
+uno::Sequence<rtl::OUString> SAL_CALL ScDPHierarchies::getElementNames() throw(uno::RuntimeException)
+{
+ long nCount = getCount();
+ uno::Sequence<rtl::OUString> aSeq(nCount);
+ rtl::OUString* pArr = aSeq.getArray();
+ for (long i=0; i<nCount; i++)
+ pArr[i] = getByIndex(i)->getName();
+ return aSeq;
+}
+
+sal_Bool SAL_CALL ScDPHierarchies::hasByName( const rtl::OUString& aName ) throw(uno::RuntimeException)
+{
+ long nCount = getCount();
+ for (long i=0; i<nCount; i++)
+ if ( getByIndex(i)->getName() == aName )
+ return TRUE;
+ return FALSE;
+}
+
+uno::Type SAL_CALL ScDPHierarchies::getElementType() throw(uno::RuntimeException)
+{
+ return getCppuType((uno::Reference<container::XNamed>*)0);
+}
+
+sal_Bool SAL_CALL ScDPHierarchies::hasElements() throw(uno::RuntimeException)
+{
+ return ( getCount() > 0 );
+}
+
+// end of XNameAccess implementation
+
+long ScDPHierarchies::getCount() const
+{
+ return nHierCount;
+}
+
+ScDPHierarchy* ScDPHierarchies::getByIndex(long nIndex) const
+{
+ // pass hierarchy index to new object in case the implementation
+ // will be extended to more than one hierarchy
+
+ if ( nIndex >= 0 && nIndex < nHierCount )
+ {
+ if ( !ppHiers )
+ {
+ ((ScDPHierarchies*)this)->ppHiers = new ScDPHierarchy*[nHierCount];
+ for (long i=0; i<nHierCount; i++)
+ ppHiers[i] = NULL;
+ }
+ if ( !ppHiers[nIndex] )
+ {
+ ppHiers[nIndex] = new ScDPHierarchy( pSource, nDim, nIndex );
+ ppHiers[nIndex]->acquire(); // ref-counted
+ }
+
+ return ppHiers[nIndex];
+ }
+
+ return NULL; //! exception?
+}
+
+// -----------------------------------------------------------------------
+
+ScDPHierarchy::ScDPHierarchy( ScDPSource* pSrc, long nD, long nH ) :
+ pSource( pSrc ),
+ nDim( nD ),
+ nHier( nH ),
+ pLevels( NULL )
+{
+ //! hold pSource
+}
+
+ScDPHierarchy::~ScDPHierarchy()
+{
+ //! release pSource
+
+ if (pLevels)
+ pLevels->release(); // ref-counted
+}
+
+ScDPLevels* ScDPHierarchy::GetLevelsObject()
+{
+ if (!pLevels)
+ {
+ pLevels = new ScDPLevels( pSource, nDim, nHier );
+ pLevels->acquire(); // ref-counted
+ }
+ return pLevels;
+}
+
+uno::Reference<container::XNameAccess> SAL_CALL ScDPHierarchy::getLevels()
+ throw(uno::RuntimeException)
+{
+ return GetLevelsObject();
+}
+
+::rtl::OUString SAL_CALL ScDPHierarchy::getName() throw(uno::RuntimeException)
+{
+ String aRet; //! globstr-ID !!!!
+ switch (nHier)
+ {
+ case SC_DAPI_HIERARCHY_FLAT:
+ aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("flat"));
+ break; //! name ???????
+ case SC_DAPI_HIERARCHY_QUARTER:
+ aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Quarter"));
+ break; //! name ???????
+ case SC_DAPI_HIERARCHY_WEEK:
+ aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Week"));
+ break; //! name ???????
+ }
+ return aRet;
+}
+
+void SAL_CALL ScDPHierarchy::setName( const ::rtl::OUString& rNewName ) throw(uno::RuntimeException)
+{
+ DBG_ERROR("not implemented"); //! exception?
+}
+
+// -----------------------------------------------------------------------
+
+ScDPLevels::ScDPLevels( ScDPSource* pSrc, long nD, long nH ) :
+ pSource( pSrc ),
+ nDim( nD ),
+ nHier( nH ),
+ ppLevs( NULL )
+{
+ //! hold pSource
+
+ // text columns have only one level
+
+ long nSrcDim = pSource->GetSourceDim( nDim );
+ if ( pSource->IsDateDimension( nSrcDim ) )
+ {
+ switch ( nHier )
+ {
+ case SC_DAPI_HIERARCHY_FLAT: nLevCount = SC_DAPI_FLAT_LEVELS; break;
+ case SC_DAPI_HIERARCHY_QUARTER: nLevCount = SC_DAPI_QUARTER_LEVELS; break;
+ case SC_DAPI_HIERARCHY_WEEK: nLevCount = SC_DAPI_WEEK_LEVELS; break;
+ default:
+ DBG_ERROR("wrong hierarchy");
+ nLevCount = 0;
+ }
+ }
+ else
+ nLevCount = 1;
+}
+
+ScDPLevels::~ScDPLevels()
+{
+ //! release pSource
+
+ if (ppLevs)
+ {
+ for (long i=0; i<nLevCount; i++)
+ if ( ppLevs[i] )
+ ppLevs[i]->release(); // ref-counted
+ delete[] ppLevs;
+ }
+}
+
+// very simple XNameAccess implementation using getCount/getByIndex
+
+uno::Any SAL_CALL ScDPLevels::getByName( const rtl::OUString& aName )
+ throw(container::NoSuchElementException,
+ lang::WrappedTargetException, uno::RuntimeException)
+{
+ long nCount = getCount();
+ for (long i=0; i<nCount; i++)
+ if ( getByIndex(i)->getName() == aName )
+ {
+ uno::Reference<container::XNamed> xNamed = getByIndex(i);
+ uno::Any aRet;
+ aRet <<= xNamed;
+ return aRet;
+ }
+ return uno::Any();
+}
+
+uno::Sequence<rtl::OUString> SAL_CALL ScDPLevels::getElementNames() throw(uno::RuntimeException)
+{
+ long nCount = getCount();
+ uno::Sequence<rtl::OUString> aSeq(nCount);
+ rtl::OUString* pArr = aSeq.getArray();
+ for (long i=0; i<nCount; i++)
+ pArr[i] = getByIndex(i)->getName();
+ return aSeq;
+}
+
+sal_Bool SAL_CALL ScDPLevels::hasByName( const rtl::OUString& aName ) throw(uno::RuntimeException)
+{
+ long nCount = getCount();
+ for (long i=0; i<nCount; i++)
+ if ( getByIndex(i)->getName() == aName )
+ return TRUE;
+ return FALSE;
+}
+
+uno::Type SAL_CALL ScDPLevels::getElementType() throw(uno::RuntimeException)
+{
+ return getCppuType((uno::Reference<container::XNamed>*)0);
+}
+
+sal_Bool SAL_CALL ScDPLevels::hasElements() throw(uno::RuntimeException)
+{
+ return ( getCount() > 0 );
+}
+
+// end of XNameAccess implementation
+
+long ScDPLevels::getCount() const
+{
+ return nLevCount;
+}
+
+ScDPLevel* ScDPLevels::getByIndex(long nIndex) const
+{
+ if ( nIndex >= 0 && nIndex < nLevCount )
+ {
+ if ( !ppLevs )
+ {
+ ((ScDPLevels*)this)->ppLevs = new ScDPLevel*[nLevCount];
+ for (long i=0; i<nLevCount; i++)
+ ppLevs[i] = NULL;
+ }
+ if ( !ppLevs[nIndex] )
+ {
+ ppLevs[nIndex] = new ScDPLevel( pSource, nDim, nHier, nIndex );
+ ppLevs[nIndex]->acquire(); // ref-counted
+ }
+
+ return ppLevs[nIndex];
+ }
+
+ return NULL; //! exception?
+}
+
+// -----------------------------------------------------------------------
+
+ScDPLevel::ScDPLevel( ScDPSource* pSrc, long nD, long nH, long nL ) :
+ pSource( pSrc ),
+ nDim( nD ),
+ nHier( nH ),
+ nLev( nL ),
+ pMembers( NULL ),
+ bShowEmpty( FALSE )
+{
+ //! hold pSource
+ // aSubTotals is empty
+}
+
+ScDPLevel::~ScDPLevel()
+{
+ //! release pSource
+
+ if ( pMembers )
+ pMembers->release(); // ref-counted
+}
+
+ScDPMembers* ScDPLevel::GetMembersObject()
+{
+ if (!pMembers)
+ {
+ pMembers = new ScDPMembers( pSource, nDim, nHier, nLev );
+ pMembers->acquire(); // ref-counted
+ }
+ return pMembers;
+}
+
+uno::Reference<container::XNameAccess> SAL_CALL ScDPLevel::getMembers() throw(uno::RuntimeException)
+{
+ return GetMembersObject();
+}
+
+uno::Sequence<sheet::MemberResult> SAL_CALL ScDPLevel::getResults() throw(uno::RuntimeException)
+{
+ const uno::Sequence<sheet::MemberResult>* pRes = pSource->GetMemberResults( this );
+ if (pRes)
+ return *pRes;
+
+ return uno::Sequence<sheet::MemberResult>(0); //! Error?
+}
+
+::rtl::OUString SAL_CALL ScDPLevel::getName() throw(uno::RuntimeException)
+{
+ long nSrcDim = pSource->GetSourceDim( nDim );
+ if ( pSource->IsDateDimension( nSrcDim ) )
+ {
+ String aRet; //! globstr-ID !!!!
+
+ if ( nHier == SC_DAPI_HIERARCHY_QUARTER )
+ {
+ switch ( nLev )
+ {
+ case SC_DAPI_LEVEL_YEAR:
+ aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Year"));
+ break;
+ case SC_DAPI_LEVEL_QUARTER:
+ aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Quarter"));
+ break;
+ case SC_DAPI_LEVEL_MONTH:
+ aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Month"));
+ break;
+ case SC_DAPI_LEVEL_DAY:
+ aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Day"));
+ break;
+ }
+ }
+ else if ( nHier == SC_DAPI_HIERARCHY_WEEK )
+ {
+ switch ( nLev )
+ {
+ case SC_DAPI_LEVEL_YEAR:
+ aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Year"));
+ break;
+ case SC_DAPI_LEVEL_WEEK:
+ aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Week"));
+ break;
+ case SC_DAPI_LEVEL_WEEKDAY:
+ aRet = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Weekday"));
+ break;
+ }
+ }
+ if (aRet.Len())
+ return aRet;
+ }
+
+ return pSource->GetData()->getDimensionName( nSrcDim ); // (original) dimension name
+}
+
+void SAL_CALL ScDPLevel::setName( const ::rtl::OUString& rNewName ) throw(uno::RuntimeException)
+{
+ DBG_ERROR("not implemented"); //! exception?
+}
+
+uno::Sequence<sheet::GeneralFunction> ScDPLevel::getSubTotals() const
+{
+ //! separate functions for settings and evaluation?
+
+ long nSrcDim = pSource->GetSourceDim( nDim );
+ if ( !pSource->SubTotalAllowed( nSrcDim ) )
+ return uno::Sequence<sheet::GeneralFunction>(0);
+
+ return aSubTotals;
+}
+
+void ScDPLevel::setSubTotals(const uno::Sequence<sheet::GeneralFunction>& rNew)
+{
+ aSubTotals = rNew;
+ //! set "manual change" flag?
+}
+
+BOOL ScDPLevel::getShowEmpty() const
+{
+ return bShowEmpty;
+}
+
+void ScDPLevel::setShowEmpty(BOOL bSet)
+{
+ bShowEmpty = bSet;
+}
+
+// XPropertySet
+
+uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPLevel::getPropertySetInfo()
+ throw(uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+
+ static SfxItemPropertyMap aDPLevelMap_Impl[] =
+ {
+ {MAP_CHAR_LEN(SC_UNO_SHOWEMPT), 0, &getBooleanCppuType(), 0, 0 },
+ {MAP_CHAR_LEN(SC_UNO_SUBTOTAL), 0, &getCppuType((uno::Sequence<sheet::GeneralFunction>*)0), 0, 0 },
+ {0,0,0,0}
+ };
+ static uno::Reference<beans::XPropertySetInfo> aRef =
+ new SfxItemPropertySetInfo( aDPLevelMap_Impl );
+ return aRef;
+}
+
+void SAL_CALL ScDPLevel::setPropertyValue( const rtl::OUString& aPropertyName, const uno::Any& aValue )
+ throw(beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ String aNameStr = aPropertyName;
+ if ( aNameStr.EqualsAscii( SC_UNO_SHOWEMPT ) )
+ setShowEmpty( lcl_GetBoolFromAny( aValue ) );
+ else if ( aNameStr.EqualsAscii( SC_UNO_SUBTOTAL ) )
+ {
+ uno::Sequence<sheet::GeneralFunction> aSeq;
+ if ( aValue >>= aSeq )
+ setSubTotals( aSeq );
+ }
+ else
+ {
+ DBG_ERROR("unknown property");
+ //! THROW( UnknownPropertyException() );
+ }
+}
+
+uno::Any SAL_CALL ScDPLevel::getPropertyValue( const rtl::OUString& aPropertyName )
+ throw(beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ uno::Any aRet;
+ String aNameStr = aPropertyName;
+ if ( aNameStr.EqualsAscii( SC_UNO_SHOWEMPT ) )
+ lcl_SetBoolInAny( aRet, getShowEmpty() );
+ else if ( aNameStr.EqualsAscii( SC_UNO_SUBTOTAL ) )
+ {
+ uno::Sequence<sheet::GeneralFunction> aSeq = getSubTotals(); //! avoid extra copy?
+ aRet <<= aSeq;
+ }
+ else
+ {
+ DBG_ERROR("unknown property");
+ //! THROW( UnknownPropertyException() );
+ }
+ return aRet;
+}
+
+SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPLevel )
+
+// -----------------------------------------------------------------------
+
+USHORT lcl_GetFirstStringPos( const TypedStrCollection& rColl )
+{
+ USHORT nPos = 0;
+ USHORT nCount = rColl.GetCount();
+ while ( nPos < nCount && !rColl[nPos]->IsStrData() )
+ ++nPos;
+ return nPos;
+}
+
+ScDPMembers::ScDPMembers( ScDPSource* pSrc, long nD, long nH, long nL ) :
+ pSource( pSrc ),
+ nDim( nD ),
+ nHier( nH ),
+ nLev( nL ),
+ ppMbrs( NULL )
+{
+ //! hold pSource
+
+ long nSrcDim = pSource->GetSourceDim( nDim );
+ if ( pSource->IsDataLayoutDimension(nSrcDim) )
+ nMbrCount = pSource->GetDataDimensionCount();
+ else if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) )
+ {
+ nMbrCount = 0;
+ if ( nHier == SC_DAPI_HIERARCHY_QUARTER )
+ {
+ switch (nLev)
+ {
+ case SC_DAPI_LEVEL_YEAR:
+ {
+ const TypedStrCollection& rStrings = pSource->GetData()->GetColumnEntries(nSrcDim);
+ USHORT nFirstString = lcl_GetFirstStringPos( rStrings );
+ if ( nFirstString > 0 )
+ {
+ double fFirstVal = rStrings[0]->GetValue();
+ double fLastVal = rStrings[nFirstString-1]->GetValue();
+
+ long nFirstYear = pSource->GetData()->GetDatePart(
+ SolarMath::ApproxFloor( fFirstVal ),
+ nHier, nLev );
+ long nLastYear = pSource->GetData()->GetDatePart(
+ SolarMath::ApproxFloor( fLastVal ),
+ nHier, nLev );
+
+ nMbrCount = nLastYear + 1 - nFirstYear;
+ }
+ else
+ nMbrCount = 0; // no values
+ }
+ break;
+ case SC_DAPI_LEVEL_QUARTER: nMbrCount = 4; break;
+ case SC_DAPI_LEVEL_MONTH: nMbrCount = 12; break;
+ case SC_DAPI_LEVEL_DAY: nMbrCount = 31; break;
+ }
+ }
+ else if ( nHier == SC_DAPI_HIERARCHY_WEEK )
+ {
+ switch (nLev)
+ {
+ case SC_DAPI_LEVEL_YEAR: nMbrCount = 1; break; //! get years from source
+ case SC_DAPI_LEVEL_WEEK: nMbrCount = 53; break;
+ case SC_DAPI_LEVEL_WEEKDAY: nMbrCount = 7; break;
+ }
+ }
+ }
+ else
+ {
+ // StringCollection is cached at TableData
+ const TypedStrCollection& rStrings = pSource->GetData()->GetColumnEntries(nSrcDim);
+ nMbrCount = rStrings.GetCount();
+ }
+}
+
+ScDPMembers::~ScDPMembers()
+{
+ //! release pSource
+
+ if (ppMbrs)
+ {
+ for (long i=0; i<nMbrCount; i++)
+ if ( ppMbrs[i] )
+ ppMbrs[i]->release(); // ref-counted
+ delete[] ppMbrs;
+ }
+}
+
+// very simple XNameAccess implementation using getCount/getByIndex
+
+uno::Any SAL_CALL ScDPMembers::getByName( const rtl::OUString& aName )
+ throw(container::NoSuchElementException,
+ lang::WrappedTargetException, uno::RuntimeException)
+{
+ long nCount = getCount();
+ for (long i=0; i<nCount; i++)
+ if ( getByIndex(i)->getName() == aName )
+ {
+ uno::Reference<container::XNamed> xNamed = getByIndex(i);
+ uno::Any aRet;
+ aRet <<= xNamed;
+ return aRet;
+ }
+ return uno::Any();
+}
+
+uno::Sequence<rtl::OUString> SAL_CALL ScDPMembers::getElementNames() throw(uno::RuntimeException)
+{
+ long nCount = getCount();
+ uno::Sequence<rtl::OUString> aSeq(nCount);
+ rtl::OUString* pArr = aSeq.getArray();
+ for (long i=0; i<nCount; i++)
+ pArr[i] = getByIndex(i)->getName();
+ return aSeq;
+}
+
+sal_Bool SAL_CALL ScDPMembers::hasByName( const rtl::OUString& aName ) throw(uno::RuntimeException)
+{
+ long nCount = getCount();
+ for (long i=0; i<nCount; i++)
+ if ( getByIndex(i)->getName() == aName )
+ return TRUE;
+ return FALSE;
+}
+
+uno::Type SAL_CALL ScDPMembers::getElementType() throw(uno::RuntimeException)
+{
+ return getCppuType((uno::Reference<container::XNamed>*)0);
+}
+
+sal_Bool SAL_CALL ScDPMembers::hasElements() throw(uno::RuntimeException)
+{
+ return ( getCount() > 0 );
+}
+
+// end of XNameAccess implementation
+
+long ScDPMembers::getCount() const
+{
+ return nMbrCount;
+}
+
+ScDPMember* ScDPMembers::getByIndex(long nIndex) const
+{
+ // result of GetColumnEntries must not change between ScDPMembers ctor
+ // and all calls to getByIndex
+
+ if ( nIndex >= 0 && nIndex < nMbrCount )
+ {
+ if ( !ppMbrs )
+ {
+ ((ScDPMembers*)this)->ppMbrs = new ScDPMember*[nMbrCount];
+ for (long i=0; i<nMbrCount; i++)
+ ppMbrs[i] = NULL;
+ }
+ if ( !ppMbrs[nIndex] )
+ {
+ ScDPMember* pNew;
+ long nSrcDim = pSource->GetSourceDim( nDim );
+ if ( pSource->IsDataLayoutDimension(nSrcDim) )
+ {
+ // empty name (never shown, not used for lookup)
+ pNew = new ScDPMember( pSource, nDim, nHier, nLev,
+ String(), 0.0, FALSE );
+ }
+ else if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) )
+ {
+ long nVal = 0;
+ String aName;
+
+ if ( nLev == SC_DAPI_LEVEL_YEAR ) // YEAR is in both hierarchies
+ {
+ //! cache year range here!
+
+ const TypedStrCollection& rStrings = pSource->GetData()->GetColumnEntries(nSrcDim);
+ double fFirstVal = rStrings[0]->GetValue();
+ long nFirstYear = pSource->GetData()->GetDatePart(
+ SolarMath::ApproxFloor( fFirstVal ),
+ nHier, nLev );
+
+ nVal = nFirstYear + nIndex;
+ }
+ else if ( nHier == SC_DAPI_HIERARCHY_WEEK && nLev == SC_DAPI_LEVEL_WEEKDAY )
+ {
+ nVal = nIndex; // enum DayOfWeek is 0-based
+ aName = ScGlobal::pScInternational->GetDayText((DayOfWeek)nVal);
+ }
+ else
+ {
+ nVal = nIndex + 1; // Quarter, Month, Day, Week are 1-based
+ if ( nHier == SC_DAPI_HIERARCHY_QUARTER && nLev == SC_DAPI_LEVEL_MONTH )
+ aName = ScGlobal::pScInternational->GetMonthText(nVal);
+ }
+
+ if ( !aName.Len() )
+ aName = nVal;
+
+ pNew = new ScDPMember( pSource, nDim, nHier, nLev, aName, nVal, TRUE );
+ }
+ else
+ {
+ const TypedStrCollection& rStrings = pSource->GetData()->GetColumnEntries(nSrcDim);
+ const TypedStrData* pData = rStrings[(USHORT)nIndex];
+ pNew = new ScDPMember( pSource, nDim, nHier, nLev,
+ pData->GetString(), pData->GetValue(), !pData->IsStrData() );
+ }
+ pNew->acquire(); // ref-counted
+ ppMbrs[nIndex] = pNew;
+ }
+
+ return ppMbrs[nIndex];
+ }
+
+ return NULL; //! exception?
+}
+
+// -----------------------------------------------------------------------
+
+ScDPMember::ScDPMember( ScDPSource* pSrc, long nD, long nH, long nL,
+ const String& rN, double fV, BOOL bHV ) :
+ pSource( pSrc ),
+ nDim( nD ),
+ nHier( nH ),
+ nLev( nL ),
+ aName( rN ),
+ fValue( fV ),
+ bHasValue( bHV ),
+ bVisible( TRUE ),
+ bShowDet( TRUE )
+{
+ //! hold pSource
+}
+
+ScDPMember::~ScDPMember()
+{
+ //! release pSource
+}
+
+BOOL ScDPMember::IsNamedItem( const ScDPItemData& r ) const
+{
+ long nSrcDim = pSource->GetSourceDim( nDim );
+ if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) && r.bHasValue )
+ {
+ long nComp = pSource->GetData()->GetDatePart(
+ SolarMath::ApproxFloor( r.fValue ),
+ nHier, nLev );
+
+ // fValue is converted from integer, so simple comparison works
+ return nComp == fValue;
+ }
+
+ return r.IsCaseInsEqual( ScDPItemData( aName, fValue, bHasValue ) );
+}
+
+String ScDPMember::GetNameStr() const
+{
+ return aName;
+}
+
+::rtl::OUString SAL_CALL ScDPMember::getName() throw(uno::RuntimeException)
+{
+ return aName;
+}
+
+void SAL_CALL ScDPMember::setName( const ::rtl::OUString& rNewName ) throw(uno::RuntimeException)
+{
+ DBG_ERROR("not implemented"); //! exception?
+}
+
+BOOL ScDPMember::getIsVisible() const
+{
+ return bVisible;
+}
+
+void ScDPMember::setIsVisible(BOOL bSet)
+{
+ bVisible = bSet;
+ //! set "manual change" flag
+}
+
+BOOL ScDPMember::getShowDetails() const
+{
+ return bShowDet;
+}
+
+void ScDPMember::setShowDetails(BOOL bSet)
+{
+ bShowDet = bSet;
+ //! set "manual change" flag
+}
+
+// XPropertySet
+
+uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPMember::getPropertySetInfo()
+ throw(uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+
+ static SfxItemPropertyMap aDPMemberMap_Impl[] =
+ {
+ {MAP_CHAR_LEN(SC_UNO_ISVISIBL), 0, &getBooleanCppuType(), 0, 0 },
+ {MAP_CHAR_LEN(SC_UNO_SHOWDETA), 0, &getBooleanCppuType(), 0, 0 },
+ {0,0,0,0}
+ };
+ static uno::Reference<beans::XPropertySetInfo> aRef =
+ new SfxItemPropertySetInfo( aDPMemberMap_Impl );
+ return aRef;
+}
+
+void SAL_CALL ScDPMember::setPropertyValue( const rtl::OUString& aPropertyName, const uno::Any& aValue )
+ throw(beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ String aNameStr = aPropertyName;
+ if ( aNameStr.EqualsAscii( SC_UNO_ISVISIBL ) )
+ setIsVisible( lcl_GetBoolFromAny( aValue ) );
+ else if ( aNameStr.EqualsAscii( SC_UNO_SHOWDETA ) )
+ setShowDetails( lcl_GetBoolFromAny( aValue ) );
+ else
+ {
+ DBG_ERROR("unknown property");
+ //! THROW( UnknownPropertyException() );
+ }
+}
+
+uno::Any SAL_CALL ScDPMember::getPropertyValue( const rtl::OUString& aPropertyName )
+ throw(beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ uno::Any aRet;
+ String aNameStr = aPropertyName;
+ if ( aNameStr.EqualsAscii( SC_UNO_ISVISIBL ) )
+ lcl_SetBoolInAny( aRet, getIsVisible() );
+ else if ( aNameStr.EqualsAscii( SC_UNO_SHOWDETA ) )
+ lcl_SetBoolInAny( aRet, getShowDetails() );
+ else
+ {
+ DBG_ERROR("unknown property");
+ //! THROW( UnknownPropertyException() );
+ }
+ return aRet;
+}
+
+SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPMember )
+
+
+
diff --git a/sc/source/core/data/drawpage.cxx b/sc/source/core/data/drawpage.cxx
new file mode 100644
index 000000000000..7cac67d4a0de
--- /dev/null
+++ b/sc/source/core/data/drawpage.cxx
@@ -0,0 +1,317 @@
+/*************************************************************************
+ *
+ * $RCSfile: drawpage.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+//------------------------------------------------------------------------
+
+// TOOLS
+#define _BIGINT_HXX
+#define _SFXMULTISEL_HXX
+#define _STACK_HXX
+#define _QUEUE_HXX
+#define _DYNARR_HXX
+#define _TREELIST_HXX
+#define _CACHESTR_HXX
+#define _NEW_HXX
+//#define _SHL_HXX
+//#define _LINK_HXX
+//#define _ERRCODE_HXX
+//#define _GEN_HXX
+//#define _FRACT_HXX
+//#define _STRING_HXX
+//#define _MTF_HXX
+//#define _CONTNR_HXX
+//#define _LIST_HXX
+//#define _TABLE_HXX
+#define _DYNARY_HXX
+//#define _UNQIDX_HXX
+#define _SVMEMPOOL_HXX
+//#define _UNQID_HXX
+//#define _DEBUG_HXX
+//#define _DATE_HXX
+//#define _TIME_HXX
+//#define _DATETIME_HXX
+//#define _INTN_HXX
+//#define _WLDCRD_HXX
+//#define _FSYS_HXX
+//#define _STREAM_HXX
+#define _CACHESTR_HXX
+#define _SV_MULTISEL_HXX
+
+//SV
+//#define _CLIP_HXX ***
+#define _CONFIG_HXX
+#define _CURSOR_HXX
+#define _FONTDLG_HXX
+#define _PRVWIN_HXX
+//#define _COLOR_HXX
+//#define _PAL_HXX
+//#define _BITMAP_HXX
+//#define _GDIOBJ_HXX
+//#define _POINTR_HXX
+//#define _ICON_HXX
+//#define _IMAGE_HXX
+//#define _KEYCOD_HXX
+//#define _EVENT_HXX
+#define _HELP_HXX
+//#define _APP_HXX
+//#define _MDIAPP_HXX
+//#define _TIMER_HXX
+//#define _METRIC_HXX
+//#define _REGION_HXX
+//#define _OUTDEV_HXX
+//#define _SYSTEM_HXX
+//#define _VIRDEV_HXX
+//#define _JOBSET_HXX
+//#define _PRINT_HXX
+//#define _WINDOW_HXX
+//#define _SYSWIN_HXX
+//#define _WRKWIN_HXX
+#define _MDIWIN_HXX
+//#define _FLOATWIN_HXX
+//#define _DOCKWIN_HXX
+//#define _CTRL_HXX
+//#define _SCRBAR_HXX
+//#define _BUTTON_HXX
+//#define _IMAGEBTN_HXX
+//#define _FIXED_HXX
+//#define _GROUP_HXX
+//#define _EDIT_HXX
+//#define _COMBOBOX_HXX
+//#define _LSTBOX_HXX
+//#define _SELENG_HXX ***
+//#define _SPLIT_HXX
+#define _SPIN_HXX
+//#define _FIELD_HXX
+//#define _MOREBTN_HXX ***
+//#define _TOOLBOX_HXX
+//#define _STATUS_HXX ***
+//#define _DIALOG_HXX
+//#define _MSGBOX_HXX
+//#define _SYSDLG_HXX
+//#define _FILDLG_HXX
+//#define _PRNDLG_HXX
+#define _COLDLG_HXX
+//#define _TABDLG_HXX
+//#define _MENU_HXX
+//#define _GDIMTF_HXX
+//#define _POLY_HXX
+//#define _ACCEL_HXX
+//#define _GRAPH_HXX
+#define _SOUND_HXX
+
+#if defined WIN
+#define _MENUBTN_HXX
+#endif
+
+//svtools
+#define _SCRWIN_HXX
+#define _RULER_HXX
+//#define _TABBAR_HXX
+//#define _VALUESET_HXX
+#define _STDMENU_HXX
+//#define _STDCTRL_HXX
+//#define _CTRLBOX_HXX
+#define _CTRLTOOL_HXX
+#define _EXTATTR_HXX
+#define _FRM3D_HXX
+#define _EXTATTR_HXX
+
+//SVTOOLS
+//#define _SVTREELIST_HXX ***
+#define _FILTER_HXX
+//#define _SVLBOXITM_HXX ***
+//#define _SVTREEBOX_HXX ***
+#define _SVICNVW_HXX
+#define _SVTABBX_HXX
+
+//sfxcore.hxx
+//#define _SFXINIMGR_HXX ***
+//#define _SFXCFGITEM_HXX
+//#define _SFX_PRINTER_HXX
+#define _SFXGENLINK_HXX
+#define _SFXHINTPOST_HXX
+#define _SFXDOCINF_HXX
+#define _SFXLINKHDL_HXX
+//#define _SFX_PROGRESS_HXX
+
+//sfxsh.hxx
+//#define _SFX_SHELL_HXX
+//#define _SFXAPP_HXX
+//#define _SFX_BINDINGS_HXX
+//#define _SFXDISPATCH_HXX
+//#define _SFXMSG_HXX ***
+//#define _SFXOBJFACE_HXX ***
+//#define _SFXREQUEST_HXX
+#define _SFXMACRO_HXX
+
+// SFX
+//#define _SFXAPPWIN_HXX ***
+#define _SFX_SAVEOPT_HXX
+//#define _SFX_CHILDWIN_HXX
+//#define _SFXCTRLITEM_HXX
+#define _SFXPRNMON_HXX
+#define _INTRO_HXX
+#define _SFXMSGDESCR_HXX
+#define _SFXMSGPOOL_HXX
+#define _SFXFILEDLG_HXX
+#define _PASSWD_HXX
+#define _SFXTBXCTRL_HXX
+#define _SFXSTBITEM_HXX
+#define _SFXMNUITEM_HXX
+#define _SFXIMGMGR_HXX
+#define _SFXTBXMGR_HXX
+#define _SFXSTBMGR_HXX
+#define _SFX_MINFITEM_HXX
+#define _SFXEVENT_HXX
+
+//sfxdoc.hxx
+//#define _SFX_OBJSH_HXX
+//#define _SFX_CLIENTSH_HXX
+//#define _SFXDOCINF_HXX
+//#define _SFX_OBJFAC_HXX
+#define _SFX_DOCFILT_HXX
+//#define _SFXDOCFILE_HXX ***
+//define _VIEWFAC_HXX
+//#define _SFXVIEWFRM_HXX
+//#define _SFXVIEWSH_HXX
+//#define _MDIFRM_HXX ***
+#define _SFX_IPFRM_HXX
+//#define _SFX_INTERNO_HXX
+
+//sfxdlg.hxx
+//#define _SFXTABDLG_HXX
+//#define _BASEDLGS_HXX ***
+#define _SFX_DINFDLG_HXX
+#define _SFXDINFEDT_HXX
+#define _SFX_MGETEMPL_HXX
+#define _SFX_TPLPITEM_HXX
+//#define _SFX_STYLEDLG_HXX
+#define _NEWSTYLE_HXX
+//#define _SFXDOCTEMPL_HXX ***
+//#define _SFXDOCTDLG_HXX ***
+//#define _SFX_TEMPLDLG_HXX ***
+//#define _SFXNEW_HXX ***
+#define _SFXDOCMAN_HXX
+//#define _SFXDOCKWIN_HXX //*
+
+//sfxitems.hxx
+#define _SFX_WHMAP_HXX
+#define _ARGS_HXX
+//#define _SFXPOOLITEM_HXX
+//#define _SFXINTITEM_HXX
+//#define _SFXENUMITEM_HXX
+#define _SFXFLAGITEM_HXX
+//#define _SFXSTRITEM_HXX
+#define _SFXPTITEM_HXX
+#define _SFXRECTITEM_HXX
+//#define _SFXITEMPOOL_HXX
+//#define _SFXITEMSET_HXX
+#define _SFXITEMITER_HXX
+#define _SFX_WHITER_HXX
+#define _SFXPOOLCACH_HXX
+//#define _AEITEM_HXX
+#define _SFXRNGITEM_HXX
+//#define _SFXSLSTITM_HXX
+//#define _SFXSTYLE_HXX
+
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <sfx2/objsh.hxx>
+
+#include "drawpage.hxx"
+#include "drwlayer.hxx"
+#include "document.hxx"
+
+// STATIC DATA -----------------------------------------------------------
+
+// -----------------------------------------------------------------------
+
+ScDrawPage::ScDrawPage(ScDrawLayer& rNewModel, StarBASIC* pBasic, BOOL bMasterPage) :
+ FmFormPage(rNewModel, pBasic, bMasterPage)
+{
+ SetSize( Size( LONG_MAX, LONG_MAX ) );
+}
+
+// -----------------------------------------------------------------------
+
+__EXPORT ScDrawPage::~ScDrawPage()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void __EXPORT ScDrawPage::RequestBasic()
+{
+ ScDrawLayer* pLayer = (ScDrawLayer*)GetModel();
+ SfxObjectShell* pDocSh = pLayer->GetDocument()->GetDocumentShell();
+ SetBasic(pDocSh->GetBasic());
+}
+
+
+
+
diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx
new file mode 100644
index 000000000000..3be48e71efa8
--- /dev/null
+++ b/sc/source/core/data/drwlayer.cxx
@@ -0,0 +1,2099 @@
+/*************************************************************************
+ *
+ * $RCSfile: drwlayer.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+//------------------------------------------------------------------------
+
+// TOOLS
+#define _BIGINT_HXX
+#define _SFXMULTISEL_HXX
+#define _STACK_HXX
+#define _QUEUE_HXX
+#define _DYNARR_HXX
+#define _TREELIST_HXX
+#define _CACHESTR_HXX
+#define _NEW_HXX
+//#define _SHL_HXX
+//#define _LINK_HXX
+//#define _ERRCODE_HXX
+//#define _GEN_HXX
+//#define _FRACT_HXX
+//#define _STRING_HXX
+//#define _MTF_HXX
+//#define _CONTNR_HXX
+//#define _LIST_HXX
+//#define _TABLE_HXX
+#define _DYNARY_HXX
+//#define _UNQIDX_HXX
+#define _SVMEMPOOL_HXX
+//#define _UNQID_HXX
+//#define _DEBUG_HXX
+//#define _DATE_HXX
+//#define _TIME_HXX
+//#define _DATETIME_HXX
+//#define _INTN_HXX
+//#define _WLDCRD_HXX
+//#define _FSYS_HXX
+//#define _STREAM_HXX
+#define _SV_MULTISEL_HXX
+
+//SV
+//#define _CLIP_HXX ***
+//#define _CONFIG_HXX ***
+#define _CURSOR_HXX
+#define _FONTDLG_HXX
+#define _PRVWIN_HXX
+//#define _COLOR_HXX
+//#define _PAL_HXX
+//#define _BITMAP_HXX
+//#define _GDIOBJ_HXX
+//#define _POINTR_HXX
+//#define _ICON_HXX
+//#define _IMAGE_HXX
+//#define _KEYCOD_HXX
+//#define _EVENT_HXX
+#define _HELP_HXX
+//#define _APP_HXX
+//#define _MDIAPP_HXX
+//#define _TIMER_HXX
+//#define _METRIC_HXX
+//#define _REGION_HXX
+//#define _OUTDEV_HXX
+//#define _SYSTEM_HXX
+//#define _VIRDEV_HXX
+//#define _JOBSET_HXX
+//#define _PRINT_HXX
+//#define _WINDOW_HXX
+//#define _SYSWIN_HXX
+//#define _WRKWIN_HXX
+#define _MDIWIN_HXX
+//#define _FLOATWIN_HXX
+//#define _DOCKWIN_HXX
+//#define _CTRL_HXX
+//#define _SCRBAR_HXX
+//#define _BUTTON_HXX
+//#define _IMAGEBTN_HXX
+//#define _FIXED_HXX
+//#define _GROUP_HXX
+//#define _EDIT_HXX
+//#define _COMBOBOX_HXX
+//#define _LSTBOX_HXX
+//#define _SELENG_HXX ***
+//#define _SPLIT_HXX
+#define _SPIN_HXX
+//#define _FIELD_HXX
+//#define _MOREBTN_HXX ***
+//#define _TOOLBOX_HXX
+//#define _STATUS_HXX ***
+//#define _DIALOG_HXX
+//#define _MSGBOX_HXX
+//#define _SYSDLG_HXX
+#define _FILDLG_HXX
+//#define _PRNDLG_HXX
+#define _COLDLG_HXX
+//#define _TABDLG_HXX
+//#define _MENU_HXX
+//#define _GDIMTF_HXX
+//#define _POLY_HXX
+//#define _ACCEL_HXX
+//#define _GRAPH_HXX
+#define _SOUND_HXX
+
+#if defined WIN
+#define _MENUBTN_HXX
+#endif
+
+//svtools
+#define _SCRWIN_HXX
+#define _RULER_HXX
+//#define _TABBAR_HXX
+//#define _VALUESET_HXX
+#define _STDMENU_HXX
+//#define _STDCTRL_HXX
+//#define _CTRLBOX_HXX
+#define _CTRLTOOL_HXX
+#define _EXTATTR_HXX
+#define _FRM3D_HXX
+#define _EXTATTR_HXX
+
+//SVTOOLS
+//#define _SVTREELIST_HXX ***
+#define _FILTER_HXX
+//#define _SVLBOXITM_HXX ***
+//#define _SVTREEBOX_HXX ***
+#define _SVICNVW_HXX
+#define _SVTABBX_HXX
+
+//sfxcore.hxx
+//#define _SFXINIMGR_HXX ***
+//#define _SFXCFGITEM_HXX
+//#define _SFX_PRINTER_HXX
+#define _SFXGENLINK_HXX
+#define _SFXHINTPOST_HXX
+#define _SFXDOCINF_HXX
+#define _SFXLINKHDL_HXX
+//#define _SFX_PROGRESS_HXX
+
+//sfxsh.hxx
+//#define _SFX_SHELL_HXX
+//#define _SFXAPP_HXX
+//#define _SFX_BINDINGS_HXX
+//#define _SFXDISPATCH_HXX
+//#define _SFXMSG_HXX ***
+//#define _SFXOBJFACE_HXX ***
+//#define _SFXREQUEST_HXX
+#define _SFXMACRO_HXX
+
+// SFX
+//#define _SFXAPPWIN_HXX ***
+#define _SFX_SAVEOPT_HXX
+//#define _SFX_CHILDWIN_HXX
+//#define _SFXCTRLITEM_HXX
+#define _SFXPRNMON_HXX
+#define _INTRO_HXX
+#define _SFXMSGDESCR_HXX
+#define _SFXMSGPOOL_HXX
+#define _SFXFILEDLG_HXX
+#define _PASSWD_HXX
+#define _SFXTBXCTRL_HXX
+#define _SFXSTBITEM_HXX
+#define _SFXMNUITEM_HXX
+#define _SFXIMGMGR_HXX
+#define _SFXTBXMGR_HXX
+#define _SFXSTBMGR_HXX
+#define _SFX_MINFITEM_HXX
+#define _SFXEVENT_HXX
+
+//sfxdoc.hxx
+//#define _SFX_OBJSH_HXX
+//#define _SFX_CLIENTSH_HXX
+//#define _SFXDOCINF_HXX
+//#define _SFX_OBJFAC_HXX
+#define _SFX_DOCFILT_HXX
+//#define _SFXDOCFILE_HXX ***
+//define _VIEWFAC_HXX
+//#define _SFXVIEWFRM_HXX
+//#define _SFXVIEWSH_HXX
+//#define _MDIFRM_HXX ***
+#define _SFX_IPFRM_HXX
+//#define _SFX_INTERNO_HXX
+
+//sfxdlg.hxx
+//#define _SFXTABDLG_HXX
+//#define _BASEDLGS_HXX ***
+#define _SFX_DINFDLG_HXX
+#define _SFXDINFEDT_HXX
+#define _SFX_MGETEMPL_HXX
+#define _SFX_TPLPITEM_HXX
+//#define _SFX_STYLEDLG_HXX
+#define _NEWSTYLE_HXX
+//#define _SFXDOCTEMPL_HXX ***
+//#define _SFXDOCTDLG_HXX ***
+//#define _SFX_TEMPLDLG_HXX ***
+//#define _SFXNEW_HXX ***
+#define _SFXDOCMAN_HXX
+//#define _SFXDOCKWIN_HXX
+
+//sfxitems.hxx
+#define _SFX_WHMAP_HXX
+//#define _ARGS_HXX ***
+//#define _SFXPOOLITEM_HXX
+//#define _SFXINTITEM_HXX
+//#define _SFXENUMITEM_HXX
+#define _SFXFLAGITEM_HXX
+//#define _SFXSTRITEM_HXX
+#define _SFXPTITEM_HXX
+#define _SFXRECTITEM_HXX
+//#define _SFXITEMPOOL_HXX
+//#define _SFXITEMSET_HXX
+#define _SFXITEMITER_HXX
+#define _SFX_WHITER_HXX
+#define _SFXPOOLCACH_HXX
+//#define _AEITEM_HXX
+#define _SFXRNGITEM_HXX
+//#define _SFXSLSTITM_HXX
+//#define _SFXSTYLE_HXX
+
+//xout.hxx
+//#define _XENUM_HXX
+//#define _XPOLY_HXX
+//#define _XATTR_HXX
+//#define _XOUTX_HXX
+//#define _XPOOL_HXX
+//#define _XTABLE_HXX
+
+//svdraw.hxx
+#define _SDR_NOITEMS
+#define _SDR_NOTOUCH
+#define _SDR_NOTRANSFORM
+//#define _SDR_NOOBJECTS
+//#define _SDR_NOVIEWS
+
+//#define SI_NOITEMS
+//#define SI_NODRW
+#define _SI_NOSBXCONTROLS
+//#define _VCATTR_HXX
+#define _VCONT_HXX
+//#define _VCSBX_HXX
+#define _SI_NOOTHERFORMS
+#define _VCTRLS_HXX
+//#define _VCDRWOBJ_HXX
+#define _SI_NOCONTROL
+#define _SETBRW_HXX
+#define _VCBRW_HXX
+#define _SI_NOSBXCONTROLS
+//#define _SIDLL_HXX ***
+
+#define _SVX_DAILDLL_HXX
+#define _SVX_HYPHEN_HXX
+#define _SVX_IMPGRF_HXX
+#define _SVX_OPTITEMS_HXX
+#define _SVX_OPTGERL_HXX
+#define _SVX_OPTSAVE_HXX
+#define _SVX_OPTSPELL_HXX
+#define _SVX_OPTPATH_HXX
+#define _SVX_OPTLINGU_HXX
+#define _SVX_RULER_HXX
+#define _SVX_RULRITEM_HXX
+#define _SVX_SPLWRAP_HXX
+#define _SVX_SPLDLG_HXX
+#define _SVX_THESDLG_HXX
+
+// neu
+#define _BIGINT_HXX
+#define _SFXMULTISEL_HXX
+#define _STACK_HXX
+#define _QUEUE_HXX
+#define _DYNARR_HXX
+#define _TREELIST_HXX
+#define _CACHESTR_HXX
+#define _NEW_HXX
+//#define _SHL_HXX
+//#define _LINK_HXX
+//#define _ERRCODE_HXX
+//#define _GEN_HXX
+//#define _FRACT_HXX
+//#define _STRING_HXX
+//#define _MTF_HXX
+//#define _CONTNR_HXX
+//#define _LIST_HXX
+//#define _TABLE_HXX
+#define _DYNARY_HXX
+//#define _UNQIDX_HXX
+#define _SVMEMPOOL_HXX
+//#define _UNQID_HXX
+//#define _DEBUG_HXX
+//#define _DATE_HXX
+//#define _TIME_HXX
+//#define _DATETIME_HXX
+//#define _INTN_HXX
+//#define _WLDCRD_HXX
+//#define _FSYS_HXX
+//#define _STREAM_HXX
+#define _CACHESTR_HXX
+#define _SV_MULTISEL_HXX
+
+//SV
+//#define _CLIP_HXX ***
+//#define _CONFIG_HXX ***
+#define _CURSOR_HXX
+#define _FONTDLG_HXX
+#define _PRVWIN_HXX
+//#define _COLOR_HXX
+//#define _PAL_HXX
+//#define _BITMAP_HXX
+//#define _GDIOBJ_HXX
+//#define _POINTR_HXX
+//#define _ICON_HXX
+//#define _IMAGE_HXX
+//#define _KEYCOD_HXX
+//#define _EVENT_HXX
+#define _HELP_HXX
+//#define _APP_HXX
+//#define _MDIAPP_HXX
+//#define _TIMER_HXX
+//#define _METRIC_HXX
+//#define _REGION_HXX
+//#define _OUTDEV_HXX
+//#define _SYSTEM_HXX
+//#define _VIRDEV_HXX
+//#define _JOBSET_HXX
+//#define _PRINT_HXX
+//#define _WINDOW_HXX
+//#define _SYSWIN_HXX
+//#define _WRKWIN_HXX
+#define _MDIWIN_HXX
+//#define _FLOATWIN_HXX
+//#define _DOCKWIN_HXX
+//#define _CTRL_HXX
+//#define _SCRBAR_HXX
+//#define _BUTTON_HXX
+//#define _IMAGEBTN_HXX
+//#define _FIXED_HXX
+//#define _GROUP_HXX
+//#define _EDIT_HXX
+//#define _COMBOBOX_HXX
+//#define _LSTBOX_HXX
+//#define _SELENG_HXX ***
+//#define _SPLIT_HXX
+#define _SPIN_HXX
+//#define _FIELD_HXX
+//#define _MOREBTN_HXX ***
+//#define _TOOLBOX_HXX
+//#define _STATUS_HXX ***
+//#define _DIALOG_HXX
+//#define _MSGBOX_HXX
+//#define _SYSDLG_HXX
+#define _FILDLG_HXX
+//#define _PRNDLG_HXX
+#define _COLDLG_HXX
+//#define _TABDLG_HXX
+//#define _MENU_HXX ***
+//#define _GDIMTF_HXX
+//#define _POLY_HXX
+//#define _ACCEL_HXX
+//#define _GRAPH_HXX
+#define _SOUND_HXX
+
+
+
+
+
+#define _BIGINT_HXX
+#define _SFXMULTISEL_HXX
+#define _STACK_HXX
+#define _QUEUE_HXX
+#define _DYNARR_HXX
+#define _TREELIST_HXX
+#define _CACHESTR_HXX
+#define _NEW_HXX
+//#define _SHL_HXX
+//#define _LINK_HXX
+//#define _ERRCODE_HXX
+//#define _GEN_HXX
+//#define _FRACT_HXX
+//#define _STRING_HXX
+//#define _MTF_HXX
+//#define _CONTNR_HXX
+//#define _LIST_HXX
+//#define _TABLE_HXX
+#define _DYNARY_HXX
+//#define _UNQIDX_HXX
+#define _SVMEMPOOL_HXX
+//#define _UNQID_HXX
+//#define _DEBUG_HXX
+//#define _DATE_HXX
+//#define _TIME_HXX
+//#define _DATETIME_HXX
+//#define _INTN_HXX
+//#define _WLDCRD_HXX
+//#define _FSYS_HXX
+//#define _STREAM_HXX
+#define _CACHESTR_HXX
+#define _SV_MULTISEL_HXX
+
+//SV
+//#define _CLIP_HXX ***
+//#define _CONFIG_HXX ***
+#define _CURSOR_HXX
+#define _FONTDLG_HXX
+#define _PRVWIN_HXX
+//#define _COLOR_HXX
+//#define _PAL_HXX
+//#define _BITMAP_HXX
+//#define _GDIOBJ_HXX
+//#define _POINTR_HXX
+//#define _ICON_HXX
+//#define _IMAGE_HXX
+//#define _KEYCOD_HXX
+//#define _EVENT_HXX
+#define _HELP_HXX
+//#define _APP_HXX
+//#define _MDIAPP_HXX
+//#define _TIMER_HXX
+//#define _METRIC_HXX
+//#define _REGION_HXX
+//#define _OUTDEV_HXX
+//#define _SYSTEM_HXX
+//#define _VIRDEV_HXX
+//#define _JOBSET_HXX
+//#define _PRINT_HXX
+//#define _WINDOW_HXX
+//#define _SYSWIN_HXX
+//#define _WRKWIN_HXX
+#define _MDIWIN_HXX
+//#define _FLOATWIN_HXX
+//#define _DOCKWIN_HXX
+//#define _CTRL_HXX
+//#define _SCRBAR_HXX
+//#define _BUTTON_HXX
+//#define _IMAGEBTN_HXX
+//#define _FIXED_HXX
+//#define _GROUP_HXX
+//#define _EDIT_HXX
+//#define _COMBOBOX_HXX
+//#define _LSTBOX_HXX
+//#define _SELENG_HXX ***
+//#define _SPLIT_HXX
+#define _SPIN_HXX
+//#define _FIELD_HXX
+//#define _MOREBTN_HXX ***
+//#define _TOOLBOX_HXX
+//#define _STATUS_HXX ***
+//#define _DIALOG_HXX
+//#define _MSGBOX_HXX
+//#define _SYSDLG_HXX
+//#define _FILDLG_HXX
+//#define _PRNDLG_HXX
+#define _COLDLG_HXX
+//#define _TABDLG_HXX
+//#define _MENU_HXX
+//#define _GDIMTF_HXX
+//#define _POLY_HXX
+//#define _ACCEL_HXX
+//#define _GRAPH_HXX
+#define _SOUND_HXX
+
+#if defined WIN
+#define _MENUBTN_HXX
+#endif
+
+//svtools
+#define _SCRWIN_HXX
+#define _RULER_HXX
+//#define _TABBAR_HXX
+//#define _VALUESET_HXX
+#define _STDMENU_HXX
+//#define _STDCTRL_HXX
+//#define _CTRLBOX_HXX
+#define _CTRLTOOL_HXX
+#define _EXTATTR_HXX
+#define _FRM3D_HXX
+#define _EXTATTR_HXX
+
+//SVTOOLS
+//#define _SVTREELIST_HXX ***
+#define _FILTER_HXX
+//#define _SVLBOXITM_HXX ***
+//#define _SVTREEBOX_HXX ***
+#define _SVICNVW_HXX
+#define _SVTABBX_HXX
+
+//sfxcore.hxx
+//#define _SFXINIMGR_HXX ***
+//#define _SFXCFGITEM_HXX
+//#define _SFX_PRINTER_HXX
+#define _SFXGENLINK_HXX
+#define _SFXHINTPOST_HXX
+#define _SFXDOCINF_HXX
+#define _SFXLINKHDL_HXX
+//#define _SFX_PROGRESS_HXX
+
+//sfxsh.hxx
+//#define _SFX_SHELL_HXX
+//#define _SFXAPP_HXX
+//#define _SFX_BINDINGS_HXX
+//#define _SFXDISPATCH_HXX
+//#define _SFXMSG_HXX ***
+//#define _SFXOBJFACE_HXX ***
+//#define _SFXREQUEST_HXX
+#define _SFXMACRO_HXX
+
+// SFX
+//#define _SFXAPPWIN_HXX ***
+#define _SFX_SAVEOPT_HXX
+//#define _SFX_CHILDWIN_HXX
+//#define _SFXCTRLITEM_HXX
+#define _SFXPRNMON_HXX
+#define _INTRO_HXX
+#define _SFXMSGDESCR_HXX
+#define _SFXMSGPOOL_HXX
+#define _SFXFILEDLG_HXX
+#define _PASSWD_HXX
+#define _SFXTBXCTRL_HXX
+#define _SFXSTBITEM_HXX
+#define _SFXMNUITEM_HXX
+#define _SFXIMGMGR_HXX
+#define _SFXTBXMGR_HXX
+#define _SFXSTBMGR_HXX
+#define _SFX_MINFITEM_HXX
+#define _SFXEVENT_HXX
+
+
+#define _SFXFILEDLG_HXX
+#define _SFXIMGMGR_HXX
+#define _SFXIPFRM_HXX
+#define _SFX_MACRO_HXX
+#define _SFXMNUITEM_HXX
+#define _SFXMNUMGR_HXX
+#define _SFXMULTISEL_HXX
+#define _SFXMSG_HXX
+#define _SFXMSGDESCR_HXX
+#define _SFXMSGPOOL_HXX
+#define _SFX_MINFITEM_HXX
+#define _SFXOBJFACE_HXX
+#define _SFXOBJFAC_HXX
+//#define _SFXREQUEST_HXX
+#define _SFX_SAVEOPT_HXX
+#define _SFXSTBITEM_HXX
+#define _SFXSTBMGR_HXX
+#define _SFXTBXCTRL_HXX
+#define _SFXTBXMGR_HXX
+
+#define _SVX_DAILDLL_HXX
+#define _SVX_HYPHEN_HXX
+#define _SVX_IMPGRF_HXX
+#define _SVX_OPTITEMS_HXX
+#define _SVX_OPTGERL_HXX
+#define _SVX_OPTSAVE_HXX
+#define _SVX_OPTSPELL_HXX
+#define _SVX_OPTPATH_HXX
+#define _SVX_OPTLINGU_HXX
+#define _SVX_RULER_HXX
+#define _SVX_RULRITEM_HXX
+#define _SVX_SPLWRAP_HXX
+#define _SVX_SPLDLG_HXX
+#define _SVX_THESDLG_HXX
+
+
+// INCLUDE ---------------------------------------------------------------
+
+
+#include <svx/objfac3d.hxx>
+#include <svx/svdoutl.hxx>
+#include <svx/svditer.hxx>
+#include <svx/svdocapt.hxx>
+#include <svx/svdocirc.hxx>
+#include <svx/svdoedge.hxx>
+#include <svx/svdograf.hxx>
+#include <svx/svdoole2.hxx>
+#include <svx/svdundo.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/viewsh.hxx>
+#include <so3/ipobj.hxx>
+#include <so3/svstor.hxx>
+#include <svtools/iniman.hxx>
+#include <svtools/itempool.hxx>
+#include <vcl/virdev.hxx>
+#include <tools/shl.hxx>
+
+#include "drwlayer.hxx"
+#include "drawpage.hxx"
+#include "global.hxx"
+#include "document.hxx"
+#include "rechead.hxx"
+#include "userdat.hxx"
+#include "markdata.hxx"
+#include "globstr.hrc"
+#include "scmod.hxx"
+
+#define DET_ARROW_OFFSET 1000
+
+// Abstand zur naechsten Zelle beim Loeschen (bShrink), damit der Anker
+// immer an der richtigen Zelle angezeigt wird
+//#define SHRINK_DIST 3
+// und noch etwas mehr, damit das Objekt auch sichtbar in der Zelle liegt
+#define SHRINK_DIST 25
+
+// -----------------------------------------------------------------------
+//
+// Das Anpassen der Detektiv-UserData muss zusammen mit den Draw-Undo's
+// in der SdrUndoGroup liegen, darum von SdrUndoAction abgeleitet:
+
+class ScUndoObjData : public SdrUndoObj
+{
+private:
+ ScTripel aOldStt;
+ ScTripel aOldEnd;
+ ScTripel aNewStt;
+ ScTripel aNewEnd;
+ BOOL bHasNew;
+public:
+ ScUndoObjData( SdrObject* pObj, const ScTripel& rOS, const ScTripel& rOE,
+ const ScTripel& rNS, const ScTripel& rNE );
+ ~ScUndoObjData();
+
+ virtual void Undo();
+ virtual void Redo();
+};
+
+// -----------------------------------------------------------------------
+
+// STATIC DATA -----------------------------------------------------------
+
+TYPEINIT1(ScTabDeletedHint, SfxHint);
+TYPEINIT1(ScTabSizeChangedHint, SfxHint);
+
+static ScDrawObjFactory* pFac = NULL;
+static E3dObjFactory* pF3d = NULL;
+static USHORT nInst = 0;
+
+SvPersist* ScDrawLayer::pGlobalDrawPersist = NULL;
+
+BOOL bDrawIsInUndo = FALSE; //! Member
+
+// -----------------------------------------------------------------------
+
+ScUndoObjData::ScUndoObjData( SdrObject* pObj, const ScTripel& rOS, const ScTripel& rOE,
+ const ScTripel& rNS, const ScTripel& rNE ) :
+ SdrUndoObj( *pObj ),
+ aOldStt( rOS ),
+ aOldEnd( rOE ),
+ aNewStt( rNS ),
+ aNewEnd( rNE )
+{
+}
+
+__EXPORT ScUndoObjData::~ScUndoObjData()
+{
+}
+
+void __EXPORT ScUndoObjData::Undo()
+{
+ ScDrawObjData* pData = ((ScDrawLayer&)rMod).GetObjData( pObj );
+ DBG_ASSERT(pData,"ScUndoObjData: Daten nicht da");
+ if (pData)
+ {
+ pData->aStt = aOldStt;
+ pData->aEnd = aOldEnd;
+ }
+}
+
+void __EXPORT ScUndoObjData::Redo()
+{
+ ScDrawObjData* pData = ((ScDrawLayer&)rMod).GetObjData( pObj );
+ DBG_ASSERT(pData,"ScUndoObjData: Daten nicht da");
+ if (pData)
+ {
+ pData->aStt = aNewStt;
+ pData->aEnd = aNewEnd;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ScTabDeletedHint::ScTabDeletedHint( USHORT nTabNo ) :
+ nTab( nTabNo )
+{
+}
+
+__EXPORT ScTabDeletedHint::~ScTabDeletedHint()
+{
+}
+
+ScTabSizeChangedHint::ScTabSizeChangedHint( USHORT nTabNo ) :
+ nTab( nTabNo )
+{
+}
+
+__EXPORT ScTabSizeChangedHint::~ScTabSizeChangedHint()
+{
+}
+
+// -----------------------------------------------------------------------
+
+#define MAXMM 10000000
+
+inline void TwipsToMM( long& nVal )
+{
+ nVal = (long) ( nVal * (CM_PER_TWIPS*1000.0) );
+}
+
+// -----------------------------------------------------------------------
+
+
+ScDrawLayer::ScDrawLayer( ScDocument* pDocument, const String& rName ) :
+ FmFormModel( SFX_APP()->GetAppIniManager()->Get( SFX_KEY_PALETTE_PATH ),
+ NULL, // SfxItemPool* Pool
+ pGlobalDrawPersist ?
+ pGlobalDrawPersist :
+ pDocument->GetDocumentShell() // SvPersist* pPers
+ // VCItemPool* pVCPool=NULL
+ ),
+ aName( rName ),
+ pDoc( pDocument ),
+ pUndoGroup( NULL ),
+ bRecording( FALSE ),
+ bAdjustEnabled( TRUE )
+{
+ pGlobalDrawPersist = NULL; // nur einmal benutzen
+
+ SetObjectShell( pDocument->GetDocumentShell() );
+ SetSwapGraphics(TRUE);
+// SetSwapAsynchron(TRUE); // an der View
+
+ SetScaleUnit(MAP_100TH_MM);
+ SfxItemPool& rPool = GetItemPool();
+ rPool.SetDefaultMetric(SFX_MAPUNIT_100TH_MM);
+ rPool.FreezeIdRanges(); // der Pool wird auch direkt verwendet
+
+ SdrLayerAdmin& rAdmin = GetLayerAdmin();
+ rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("vorne")), SC_LAYER_FRONT);
+ rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("hinten")), SC_LAYER_BACK);
+ rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("intern")), SC_LAYER_INTERN);
+ rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Controls")), SC_LAYER_CONTROLS);
+ // "Controls" is new - must also be created when loading
+
+ // Link fuer URL-Fields setzen
+ ScModule* pScMod = SC_MOD();
+ Outliner& rOutliner = GetDrawOutliner();
+ rOutliner.SetCalcFieldValueHdl( LINK( pScMod, ScModule, CalcFieldValueHdl ) );
+
+ Outliner& rHitOutliner = GetHitTestOutliner();
+ rHitOutliner.SetCalcFieldValueHdl( LINK( pScMod, ScModule, CalcFieldValueHdl ) );
+
+ // URL-Buttons haben keinen Handler mehr, machen alles selber
+
+ if( !nInst++ )
+ {
+ pFac = new ScDrawObjFactory;
+ pF3d = new E3dObjFactory;
+ }
+}
+
+__EXPORT ScDrawLayer::~ScDrawLayer()
+{
+ Clear();
+
+ delete pUndoGroup;
+ if( !--nInst )
+ {
+ delete pFac, pFac = NULL;
+ delete pF3d, pF3d = NULL;
+ }
+}
+
+SdrPage* __EXPORT ScDrawLayer::AllocPage(FASTBOOL bMasterPage)
+{
+// StarBASIC* pBasic = pDoc->GetDocumentShell()->GetBasicManager()->GetLib(0);
+
+ StarBASIC* pBasic = NULL;
+ SfxObjectShell* pDocSh = pDoc->GetDocumentShell();
+ if ( pDocSh /* && pDocSh->HasSbxObject() ??? */ )
+ pBasic = pDocSh->GetBasic();
+
+ ScDrawPage* pPage = new ScDrawPage( *this, pBasic, bMasterPage );
+ return pPage;
+}
+
+BOOL ScDrawLayer::HasObjects() const
+{
+ BOOL bFound = FALSE;
+
+ USHORT nCount = GetPageCount();
+ for (USHORT i=0; i<nCount && !bFound; i++)
+ if (GetPage(i)->GetObjCount())
+ bFound = TRUE;
+
+ return bFound;
+}
+
+void ScDrawLayer::UpdateBasic()
+{
+ SfxObjectShell* pDocSh = pDoc->GetDocumentShell();
+ StarBASIC* pBasic = pDocSh ? pDocSh->GetBasic() : 0;
+
+ USHORT nCount = GetPageCount();
+ for (USHORT i=0; i<nCount; i++)
+ ((ScDrawPage*) GetPage(i))->SetBasic(pBasic);
+}
+
+SdrModel* __EXPORT ScDrawLayer::AllocModel() const
+{
+ return new ScDrawLayer( pDoc, aName );
+}
+
+Window* __EXPORT ScDrawLayer::GetCurDocViewWin()
+{
+ SfxViewShell* pViewSh = SfxViewShell::Current();
+ SfxObjectShell* pObjSh = pDoc->GetDocumentShell();
+
+ if (pViewSh && pViewSh->GetObjectShell() == pObjSh)
+ return pViewSh->GetWindow();
+
+ return NULL;
+}
+
+void ScDrawLayer::ScAddPage( USHORT nTab )
+{
+ if (bDrawIsInUndo)
+ return;
+
+ ScDrawPage* pPage = (ScDrawPage*)AllocPage( FALSE );
+ InsertPage(pPage, nTab);
+ if (bRecording)
+ AddCalcUndo(new SdrUndoNewPage(*pPage));
+}
+
+void ScDrawLayer::ScRemovePage( USHORT nTab )
+{
+ if (bDrawIsInUndo)
+ return;
+
+ Broadcast( ScTabDeletedHint( nTab ) );
+ if (bRecording)
+ {
+ SdrPage* pPage = GetPage(nTab);
+ AddCalcUndo(new SdrUndoDelPage(*pPage)); // Undo-Action wird Owner der Page
+ RemovePage( nTab ); // nur austragen, nicht loeschen
+ }
+ else
+ DeletePage( nTab ); // einfach weg damit
+}
+
+void ScDrawLayer::ScRenamePage( USHORT nTab, const String& rNewName )
+{
+ ScDrawPage* pPage = (ScDrawPage*) GetPage(nTab);
+ if (pPage)
+ pPage->SetName(rNewName);
+}
+
+void ScDrawLayer::ScMovePage( USHORT nOldPos, USHORT nNewPos )
+{
+ MovePage( nOldPos, nNewPos );
+}
+
+void ScDrawLayer::ScCopyPage( USHORT nOldPos, USHORT nNewPos, BOOL bAlloc )
+{
+ //! remove argument bAlloc (always FALSE)
+
+ if (bDrawIsInUndo)
+ return;
+
+ SdrPage* pOldPage = GetPage(nOldPos);
+ SdrPage* pNewPage = bAlloc ? AllocPage(FALSE) : GetPage(nNewPos);
+
+ // kopieren
+
+ if (pOldPage && pNewPage)
+ {
+ SdrObjListIter aIter( *pOldPage, IM_FLAT );
+ SdrObject* pOldObject = aIter.Next();
+ while (pOldObject)
+ {
+ SdrObject* pNewObject = pOldObject->Clone( pNewPage, this );
+ pNewObject->NbcMove(Size(0,0));
+ pNewPage->InsertObject( pNewObject );
+ if (bRecording)
+ AddCalcUndo( new SdrUndoInsertObj( *pNewObject ) );
+
+ pOldObject = aIter.Next();
+ }
+ }
+
+ if (bAlloc)
+ InsertPage(pNewPage, nNewPos);
+}
+
+inline BOOL IsInBlock( const ScTripel& rPos, USHORT nCol1,USHORT nRow1, USHORT nCol2,USHORT nRow2 )
+{
+ return rPos.nCol >= nCol1 && rPos.nCol <= nCol2 &&
+ rPos.nRow >= nRow1 && rPos.nRow <= nRow2;
+}
+
+void ScDrawLayer::MoveCells( USHORT nTab, USHORT nCol1,USHORT nRow1, USHORT nCol2,USHORT nRow2,
+ short nDx,short nDy )
+{
+ SdrPage* pPage = GetPage(nTab);
+ DBG_ASSERT(pPage,"Page nicht gefunden");
+ if (!pPage)
+ return;
+
+ ULONG nCount = pPage->GetObjCount();
+ for ( ULONG i = 0; i < nCount; i++ )
+ {
+ SdrObject* pObj = pPage->GetObj( i );
+ ScDrawObjData* pData = GetObjData( pObj );
+ if( pData )
+ {
+ ScTripel aOldStt = pData->aStt;
+ ScTripel aOldEnd = pData->aEnd;
+ BOOL bChange = FALSE;
+ if ( pData->bValidStart && IsInBlock( pData->aStt, nCol1,nRow1, nCol2,nRow2 ) )
+ {
+ pData->aStt.nCol += nDx;
+ pData->aStt.nRow += nDy;
+ bChange = TRUE;
+ }
+ if ( pData->bValidEnd && IsInBlock( pData->aEnd, nCol1,nRow1, nCol2,nRow2 ) )
+ {
+ pData->aEnd.nCol += nDx;
+ pData->aEnd.nRow += nDy;
+ bChange = TRUE;
+ }
+ if (bChange)
+ {
+ if ( pObj->ISA(SdrRectObj) && pData->bValidStart && pData->bValidEnd )
+ {
+ PutInOrder( pData->aStt.nCol, pData->aEnd.nCol );
+ PutInOrder( pData->aStt.nRow, pData->aEnd.nRow );
+ }
+ AddCalcUndo( new ScUndoObjData( pObj, aOldStt, aOldEnd, pData->aStt, pData->aEnd ) );
+ RecalcPos( pObj, pData );
+ }
+ }
+ }
+}
+
+void ScDrawLayer::SetPageSize( USHORT nPageNo, const Size& rSize )
+{
+ SdrPage* pPage = GetPage(nPageNo);
+ if (pPage)
+ {
+ if ( rSize != pPage->GetSize() )
+ {
+ pPage->SetSize( rSize );
+ Broadcast( ScTabSizeChangedHint( nPageNo ) ); // SetWorkArea() an den Views
+ }
+
+ // Detektivlinien umsetzen (an neue Hoehen/Breiten anpassen)
+ // auch wenn Groesse gleich geblieben ist
+ // (einzelne Zeilen/Spalten koennen geaendert sein)
+
+ ULONG nCount = pPage->GetObjCount();
+ for ( ULONG i = 0; i < nCount; i++ )
+ {
+ SdrObject* pObj = pPage->GetObj( i );
+ ScDrawObjData* pData = GetObjData( pObj );
+ if( pData )
+ RecalcPos( pObj, pData );
+ }
+ }
+}
+
+void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData* pData )
+{
+ BOOL bArrow = ( pObj->IsPolyObj() && pObj->GetPointCount()==2 ); // Pfeil ?
+ BOOL bCircle = ( pObj->ISA(SdrCircObj) ); // Kreis (Gueltigkeit)
+ BOOL bCaption = ( pObj->ISA(SdrCaptionObj) ); // Notiz
+
+ if (bCaption)
+ {
+ SdrCaptionObj* pCaptObj = (SdrCaptionObj*) pObj;
+
+ USHORT nCol = pData->aStt.nCol;
+ USHORT nRow = pData->aStt.nRow;
+ USHORT nTab = pData->aStt.nTab;
+ Point aPos( pDoc->GetColOffset( nCol+1, nTab ),
+ pDoc->GetRowOffset( nRow, nTab ) );
+ TwipsToMM( aPos.X() );
+ TwipsToMM( aPos.Y() );
+ aPos.X() -= 10;
+
+ Point aOldTail = pCaptObj->GetTailPos();
+ if ( aOldTail != aPos )
+ {
+ pCaptObj->SetTailPos(aPos);
+
+ // Rest in gleichem Abstand mitverschieben
+
+ Rectangle aOldLogic = pObj->GetLogicRect();
+ long nDiffX = aOldLogic.Left() - aOldTail.X();
+ long nDiffY = aOldLogic.Top() - aOldTail.Y();
+ Point aNewStart( aPos.X() + nDiffX, aPos.Y() + nDiffY );
+ if ( aNewStart.X() < 0 ) aNewStart.X() = 0;
+ if ( aNewStart.Y() < 0 ) aNewStart.Y() = 0;
+ Rectangle aNewLogic( aNewStart, aOldLogic.GetSize() );
+
+ if ( aNewLogic != aOldLogic )
+ {
+ if (bRecording)
+ AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
+ pObj->SetLogicRect(aNewLogic);
+ }
+ }
+ }
+ else if (bCircle) // Kreis (Gueltigkeit)
+ {
+ USHORT nCol = pData->aStt.nCol;
+ USHORT nRow = pData->aStt.nRow;
+ USHORT nTab = pData->aStt.nTab;
+ Point aPos( pDoc->GetColOffset( nCol, nTab ), pDoc->GetRowOffset( nRow, nTab ) );
+ TwipsToMM( aPos.X() );
+ TwipsToMM( aPos.Y() );
+
+ // Berechnung und Werte wie in detfunc.cxx
+
+ Size aSize( (long) ( pDoc->GetColWidth(nCol, nTab) * HMM_PER_TWIPS ),
+ (long) ( pDoc->GetRowHeight(nRow, nTab) * HMM_PER_TWIPS ) );
+ Rectangle aRect( aPos, aSize );
+ aRect.Left() -= 250;
+ aRect.Right() += 250;
+ aRect.Top() -= 70;
+ aRect.Bottom() += 70;
+
+ if ( pObj->GetLogicRect() != aRect )
+ {
+ if (bRecording)
+ AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
+ pObj->SetLogicRect(aRect);
+ }
+ }
+ else if (bArrow) // Pfeil
+ {
+ //! nicht mehrere Undos fuer ein Objekt erzeugen (hinteres kann dann weggelassen werden)
+
+ if( pData->bValidStart )
+ {
+ Point aPos(
+ pDoc->GetColOffset( pData->aStt.nCol, pData->aStt.nTab ),
+ pDoc->GetRowOffset( pData->aStt.nRow, pData->aStt.nTab ) );
+ if( !( pDoc->GetColFlags( pData->aStt.nCol, pData->aStt.nTab )
+ & CR_HIDDEN ) )
+ aPos.X() += pDoc->GetColWidth( pData->aStt.nCol, pData->aStt.nTab ) / 4;
+ if( !( pDoc->GetRowFlags( pData->aStt.nRow, pData->aStt.nTab )
+ & CR_HIDDEN ) )
+ aPos.Y() += pDoc->GetRowHeight( pData->aStt.nRow, pData->aStt.nTab ) / 2;
+ TwipsToMM( aPos.X() );
+ TwipsToMM( aPos.Y() );
+ if ( pObj->GetPoint(0) != aPos )
+ {
+ if (bRecording)
+ AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
+ pObj->SetPoint( aPos, 0 );
+ }
+
+ if( !pData->bValidEnd )
+ {
+ Point aEndPos( aPos.X() + DET_ARROW_OFFSET, aPos.Y() - DET_ARROW_OFFSET );
+ if (aEndPos.Y() < 0)
+ aEndPos.Y() += 2*DET_ARROW_OFFSET;
+ if ( pObj->GetPoint(1) != aEndPos )
+ {
+ if (bRecording)
+ AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
+ pObj->SetPoint( aEndPos, 1 );
+ }
+ }
+ }
+ if( pData->bValidEnd )
+ {
+ Point aPos(
+ pDoc->GetColOffset( pData->aEnd.nCol, pData->aEnd.nTab ),
+ pDoc->GetRowOffset( pData->aEnd.nRow, pData->aEnd.nTab ) );
+ if( !( pDoc->GetColFlags( pData->aEnd.nCol, pData->aEnd.nTab )
+ & CR_HIDDEN ) )
+ aPos.X() += pDoc->GetColWidth( pData->aEnd.nCol, pData->aEnd.nTab ) / 4;
+ if( !( pDoc->GetRowFlags( pData->aEnd.nRow, pData->aEnd.nTab )
+ & CR_HIDDEN ) )
+ aPos.Y() += pDoc->GetRowHeight( pData->aEnd.nRow, pData->aEnd.nTab ) / 2;
+ TwipsToMM( aPos.X() );
+ TwipsToMM( aPos.Y() );
+ if ( pObj->GetPoint(1) != aPos )
+ {
+ if (bRecording)
+ AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
+ pObj->SetPoint( aPos, 1 );
+ }
+
+ if( !pData->bValidStart )
+ {
+ Point aStartPos( aPos.X() - DET_ARROW_OFFSET, aPos.Y() - DET_ARROW_OFFSET );
+ if (aStartPos.X() < 0)
+ aStartPos.X() += 2*DET_ARROW_OFFSET;
+ if (aStartPos.Y() < 0)
+ aStartPos.Y() += 2*DET_ARROW_OFFSET;
+ if ( pObj->GetPoint(0) != aStartPos )
+ {
+ if (bRecording)
+ AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
+ pObj->SetPoint( aStartPos, 0 );
+ }
+ }
+ }
+ }
+ else // Referenz-Rahmen
+ {
+ DBG_ASSERT( pData->bValidStart, "RecalcPos: kein Start" );
+ Point aPos(
+ pDoc->GetColOffset( pData->aStt.nCol, pData->aStt.nTab ),
+ pDoc->GetRowOffset( pData->aStt.nRow, pData->aStt.nTab ) );
+ TwipsToMM( aPos.X() );
+ TwipsToMM( aPos.Y() );
+
+ if( pData->bValidEnd )
+ {
+ Point aEnd(
+ pDoc->GetColOffset( pData->aEnd.nCol+1, pData->aEnd.nTab ),
+ pDoc->GetRowOffset( pData->aEnd.nRow+1, pData->aEnd.nTab ) );
+ TwipsToMM( aEnd.X() );
+ TwipsToMM( aEnd.Y() );
+
+ Rectangle aNew( aPos, aEnd );
+ if ( pObj->GetLogicRect() != aNew )
+ {
+ if (bRecording)
+ AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
+ pObj->SetLogicRect(aNew);
+ }
+ }
+ else
+ if ( pObj->GetRelativePos() != aPos )
+ {
+ if (bRecording)
+ AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
+ pObj->SetRelativePos( aPos );
+ }
+ }
+
+}
+
+void ScDrawLayer::Load( SvStream& rStream )
+{
+ bRecording = FALSE;
+ DELETEZ(pUndoGroup);
+
+ ScReadHeader aHdr( rStream );
+ while (aHdr.BytesLeft())
+ {
+ USHORT nID;
+ rStream >> nID;
+ switch (nID)
+ {
+ case SCID_DRAWPOOL:
+ {
+ ScReadHeader aPoolHdr( rStream );
+ GetItemPool().Load( rStream ); //! in Pool-Stream ?
+ }
+ break;
+ case SCID_DRAWMODEL:
+ {
+ ScReadHeader aDrawHdr( rStream );
+ rStream >> *this;
+
+ // Control-Layer ist nicht in alten Dateien
+ SdrLayerAdmin& rAdmin = GetLayerAdmin();
+ const SdrLayer* pLayer = rAdmin.GetLayerPerID(SC_LAYER_CONTROLS);
+ if (!pLayer)
+ rAdmin.NewLayer(
+ String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Controls")),
+ SC_LAYER_CONTROLS);
+ }
+ break;
+ default:
+ {
+ DBG_ERROR("unbekannter Sub-Record in ScDrawLayer::Load");
+ ScReadHeader aDummyHdr( rStream );
+ }
+ }
+ }
+
+ GetItemPool().LoadCompleted();
+}
+
+void ScDrawLayer::Store( SvStream& rStream ) const
+{
+ ScWriteHeader aHdr( rStream );
+
+ {
+ rStream << (USHORT) SCID_DRAWPOOL;
+ ScWriteHeader aPoolHdr( rStream );
+ GetItemPool().Store( rStream ); //! in Pool-Stream ?
+ }
+
+ {
+ rStream << (USHORT) SCID_DRAWMODEL;
+ ScWriteHeader aDrawHdr( rStream );
+ rStream << *this;
+ }
+}
+
+BOOL ScDrawLayer::GetPrintArea( ScRange& rRange, BOOL bSetHor, BOOL bSetVer ) const
+{
+ USHORT nTab = rRange.aStart.Tab();
+ DBG_ASSERT( rRange.aEnd.Tab() == nTab, "GetPrintArea: Tab unterschiedlich" );
+
+ BOOL bAny = FALSE;
+ long nEndX = 0;
+ long nEndY = 0;
+ long nStartX = LONG_MAX;
+ long nStartY = LONG_MAX;
+ USHORT i;
+
+ // Grenzen ausrechnen
+
+ if (!bSetHor)
+ {
+ nStartX = 0;
+ USHORT nStartCol = rRange.aStart.Col();
+ for (i=0; i<nStartCol; i++)
+ nStartX +=pDoc->GetColWidth(i,nTab);
+ nEndX = nStartX;
+ USHORT nEndCol = rRange.aEnd.Col();
+ for (i=nStartCol; i<=nEndCol; i++)
+ nEndX += pDoc->GetColWidth(i,nTab);
+ nStartX = (long)(nStartX * HMM_PER_TWIPS);
+ nEndX = (long)(nEndX * HMM_PER_TWIPS);
+ }
+ if (!bSetVer)
+ {
+ nStartY = 0;
+ USHORT nStartRow = rRange.aStart.Row();
+ for (i=0; i<nStartRow; i++)
+ nStartY +=pDoc->FastGetRowHeight(i,nTab);
+ nEndY = nStartY;
+ USHORT nEndRow = rRange.aEnd.Row();
+ for (i=nStartRow; i<=nEndRow; i++)
+ nEndY += pDoc->FastGetRowHeight(i,nTab);
+ nStartY = (long)(nStartY * HMM_PER_TWIPS);
+ nEndY = (long)(nEndY * HMM_PER_TWIPS);
+ }
+
+ const SdrPage* pPage = GetPage(nTab);
+ DBG_ASSERT(pPage,"Page nicht gefunden");
+ if (pPage)
+ {
+ SdrObjListIter aIter( *pPage, IM_FLAT );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ //! Flags (ausgeblendet?) testen
+
+ Rectangle aObjRect = pObject->GetBoundRect();
+ BOOL bFit = TRUE;
+ if ( !bSetHor && ( aObjRect.Right() < nStartX || aObjRect.Left() > nEndX ) )
+ bFit = FALSE;
+ if ( !bSetVer && ( aObjRect.Bottom() < nStartY || aObjRect.Top() > nEndY ) )
+ bFit = FALSE;
+ if ( bFit )
+ {
+ if (bSetHor)
+ {
+ if (aObjRect.Left() < nStartX) nStartX = aObjRect.Left();
+ if (aObjRect.Right() > nEndX) nEndX = aObjRect.Right();
+ }
+ if (bSetVer)
+ {
+ if (aObjRect.Top() < nStartY) nStartY = aObjRect.Top();
+ if (aObjRect.Bottom() > nEndY) nEndY = aObjRect.Bottom();
+ }
+ bAny = TRUE;
+ }
+
+ pObject = aIter.Next();
+ }
+ }
+
+ if (bAny)
+ {
+ DBG_ASSERT( nStartX<=nEndX && nStartY<=nEndY, "Start/End falsch in ScDrawLayer::GetPrintArea" );
+
+ if (bSetHor)
+ {
+ nStartX = (long) (nStartX / HMM_PER_TWIPS);
+ nEndX = (long) (nEndX / HMM_PER_TWIPS);
+ long nWidth;
+
+ nWidth = 0;
+ for (i=0; i<MAXCOL && nWidth<=nStartX; i++)
+ nWidth += pDoc->GetColWidth(i,nTab);
+ rRange.aStart.SetCol( i ? (i-1) : 0 );
+
+ nWidth = 0;
+ for (i=0; i<MAXCOL && nWidth<=nEndX; i++) //! bei Start anfangen
+ nWidth += pDoc->GetColWidth(i,nTab);
+ rRange.aEnd.SetCol( i ? (i-1) : 0 );
+ }
+
+ if (bSetVer)
+ {
+ nStartY = (long) (nStartY / HMM_PER_TWIPS);
+ nEndY = (long) (nEndY / HMM_PER_TWIPS);
+ long nHeight;
+
+ nHeight = 0;
+ for (i=0; i<MAXROW && nHeight<=nStartY; i++)
+ nHeight += pDoc->FastGetRowHeight(i,nTab);
+ rRange.aStart.SetRow( i ? (i-1) : 0 );
+
+ nHeight = 0;
+ for (i=0; i<MAXROW && nHeight<=nEndY; i++)
+ nHeight += pDoc->FastGetRowHeight(i,nTab);
+ rRange.aEnd.SetRow( i ? (i-1) : 0 );
+ }
+ }
+ else
+ {
+ if (bSetHor)
+ {
+ rRange.aStart.SetCol(0);
+ rRange.aEnd.SetCol(0);
+ }
+ if (bSetVer)
+ {
+ rRange.aStart.SetRow(0);
+ rRange.aEnd.SetRow(0);
+ }
+ }
+ return bAny;
+}
+
+void ScDrawLayer::AddCalcUndo( SdrUndoAction* pUndo )
+{
+ if (bRecording)
+ {
+ if (!pUndoGroup)
+ pUndoGroup = new SdrUndoGroup(*this);
+
+ pUndoGroup->AddAction( pUndo );
+ }
+ else
+ delete pUndo;
+}
+
+void ScDrawLayer::BeginCalcUndo()
+{
+//! DBG_ASSERT( !bRecording, "BeginCalcUndo ohne GetCalcUndo" );
+
+ DELETEZ(pUndoGroup);
+ bRecording = TRUE;
+}
+
+SdrUndoGroup* ScDrawLayer::GetCalcUndo()
+{
+//! DBG_ASSERT( bRecording, "GetCalcUndo ohne BeginCalcUndo" );
+
+ SdrUndoGroup* pRet = pUndoGroup;
+ pUndoGroup = NULL;
+ bRecording = FALSE;
+ return pRet;
+}
+
+void ScDrawLayer::MoveAreaMM( USHORT nTab, const Rectangle& rArea,
+ const Point& rMove, const Point& rTopLeft )
+{
+ if (!rMove.X() && !rMove.Y())
+ return; // nix
+
+ SdrPage* pPage = GetPage(nTab);
+ DBG_ASSERT(pPage,"Page nicht gefunden");
+ if (!pPage)
+ return;
+
+ Point aNewPos;
+ Rectangle aObjRect;
+
+ // fuer Shrinking!
+ Rectangle aNew( rArea );
+ BOOL bShrink = FALSE;
+ if ( rMove.X() < 0 || rMove.Y() < 0 ) // verkleinern
+ {
+ if ( rTopLeft != rArea.TopLeft() ) // sind gleich beim Verschieben von Zellen
+ {
+ bShrink = TRUE;
+ aNew.Left() = rTopLeft.X();
+ aNew.Top() = rTopLeft.Y();
+ }
+ }
+ SdrObjListIter aIter( *pPage, IM_FLAT );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ if( GetAnchor( pObject ) == SCA_CELL )
+ {
+ if ( GetObjData( pObject ) ) // Detektiv-Pfeil ?
+ {
+ // hier nichts
+ }
+ else if ( pObject->ISA( SdrEdgeObj ) ) // Verbinder?
+ {
+ // hier auch nichts
+ //! nicht verbundene Enden wie bei Linien (s.u.) behandeln?
+ }
+ else if ( pObject->IsPolyObj() && pObject->GetPointCount()==2 )
+ {
+ for (USHORT i=0; i<2; i++)
+ {
+ BOOL bMoved = FALSE;
+ Point aPoint = pObject->GetPoint(i);
+ if (rArea.IsInside(aPoint))
+ {
+ aPoint += rMove; bMoved = TRUE;
+ }
+ else if (bShrink && aNew.IsInside(aPoint))
+ {
+ // Punkt ist in betroffener Zelle - Test auf geloeschten Bereich
+ if ( rMove.X() && aPoint.X() >= rArea.Left() + rMove.X() )
+ {
+ aPoint.X() = rArea.Left() + rMove.X() - SHRINK_DIST;
+ if ( aPoint.X() < 0 ) aPoint.X() = 0;
+ bMoved = TRUE;
+ }
+ if ( rMove.Y() && aPoint.Y() >= rArea.Top() + rMove.Y() )
+ {
+ aPoint.Y() = rArea.Top() + rMove.Y() - SHRINK_DIST;
+ if ( aPoint.Y() < 0 ) aPoint.Y() = 0;
+ bMoved = TRUE;
+ }
+ }
+ if( bMoved )
+ {
+ AddCalcUndo( new SdrUndoGeoObj( *pObject ) );
+ pObject->SetPoint( aPoint, i );
+ }
+ }
+ }
+ else
+ {
+ aObjRect = pObject->GetLogicRect();
+ Point aTopLeft = aObjRect.TopLeft();
+ Size aMoveSize;
+ BOOL bDoMove = FALSE;
+ if (rArea.IsInside(aTopLeft))
+ {
+ aMoveSize = Size(rMove.X(),rMove.Y());
+ bDoMove = TRUE;
+ }
+ else if (bShrink && aNew.IsInside(aTopLeft))
+ {
+ // Position ist in betroffener Zelle - Test auf geloeschten Bereich
+ if ( rMove.X() && aTopLeft.X() >= rArea.Left() + rMove.X() )
+ {
+ aMoveSize.Width() = rArea.Left() + rMove.X() - SHRINK_DIST - aTopLeft.X();
+ bDoMove = TRUE;
+ }
+ if ( rMove.Y() && aTopLeft.Y() >= rArea.Top() + rMove.Y() )
+ {
+ aMoveSize.Height() = rArea.Top() + rMove.Y() - SHRINK_DIST - aTopLeft.Y();
+ bDoMove = TRUE;
+ }
+ }
+ if ( bDoMove )
+ {
+ if ( aTopLeft.X() + aMoveSize.Width() < 0 )
+ aMoveSize.Width() = -aTopLeft.X();
+ if ( aTopLeft.Y() + aMoveSize.Height() < 0 )
+ aMoveSize.Height() = -aTopLeft.Y();
+ AddCalcUndo( new SdrUndoMoveObj( *pObject, aMoveSize ) );
+ pObject->Move( aMoveSize );
+ }
+ else if ( rArea.IsInside(aObjRect.BottomRight()) &&
+ !pObject->IsResizeProtect() )
+ {
+ // geschuetzte Groessen werden nicht veraendert
+ // (Positionen schon, weil sie ja an der Zelle "verankert" sind)
+ AddCalcUndo( new SdrUndoGeoObj( *pObject ) );
+ long nOldSizeX = aObjRect.Right() - aObjRect.Left() + 1;
+ long nOldSizeY = aObjRect.Bottom() - aObjRect.Top() + 1;
+ pObject->Resize( aObjRect.TopLeft(), Fraction( nOldSizeX+rMove.X(), nOldSizeX ),
+ Fraction( nOldSizeY+rMove.Y(), nOldSizeY ) );
+ }
+ }
+ }
+ pObject = aIter.Next();
+ }
+}
+
+void ScDrawLayer::MoveArea( USHORT nTab, USHORT nCol1,USHORT nRow1, USHORT nCol2,USHORT nRow2,
+ short nDx,short nDy, BOOL bInsDel )
+{
+ if (!bAdjustEnabled)
+ return;
+
+ Rectangle aRect = pDoc->GetMMRect( nCol1, nRow1, nCol2, nRow2, nTab );
+
+ short s;
+ Point aMove;
+
+ if (nDx > 0)
+ for (s=0; s<nDx; s++)
+ aMove.X() += pDoc->GetColWidth(s+(short)nCol1,nTab);
+ else
+ for (s=-1; s>=nDx; s--)
+ aMove.X() -= pDoc->GetColWidth(s+(short)nCol1,nTab);
+ if (nDy > 0)
+ for (s=0; s<nDy; s++)
+ aMove.Y() += pDoc->FastGetRowHeight(s+(short)nRow1,nTab);
+ else
+ for (s=-1; s>=nDy; s--)
+ aMove.Y() -= pDoc->FastGetRowHeight(s+(short)nRow1,nTab);
+
+ TwipsToMM( aMove.X() );
+ TwipsToMM( aMove.Y() );
+
+ Point aTopLeft = aRect.TopLeft(); // Anfang beim Verkleinern
+ if (bInsDel)
+ {
+ if ( aMove.X() < 0 )
+ aTopLeft.X() += aMove.X();
+ if ( aMove.Y() < 0 )
+ aTopLeft.Y() += aMove.Y();
+ }
+
+ MoveAreaMM( nTab, aRect, aMove, aTopLeft );
+
+ //
+ // Detektiv-Pfeile: Zellpositionen anpassen
+ //
+
+ MoveCells( nTab, nCol1,nRow1, nCol2,nRow2, nDx,nDy );
+}
+
+void ScDrawLayer::WidthChanged( USHORT nTab, USHORT nCol, long nDifTwips )
+{
+ if (!bAdjustEnabled)
+ return;
+
+ USHORT i;
+ Rectangle aRect;
+ Point aTopLeft;
+
+ for (i=0; i<nCol; i++)
+ aRect.Left() += pDoc->GetColWidth(i,nTab);
+ aTopLeft.X() = aRect.Left();
+ aRect.Left() += pDoc->GetColWidth(nCol,nTab);
+
+ TwipsToMM( aRect.Left() );
+ TwipsToMM( aTopLeft.X() );
+
+ aRect.Right() = MAXMM;
+ aRect.Top() = 0;
+ aRect.Bottom() = MAXMM;
+
+ TwipsToMM( nDifTwips );
+
+ //! aTopLeft ist falsch, wenn mehrere Spalten auf einmal ausgeblendet werden
+
+ MoveAreaMM( nTab, aRect, Point( nDifTwips,0 ), aTopLeft );
+}
+
+void ScDrawLayer::HeightChanged( USHORT nTab, USHORT nRow, long nDifTwips )
+{
+ if (!bAdjustEnabled)
+ return;
+
+ USHORT i;
+ Rectangle aRect;
+ Point aTopLeft;
+
+ for (i=0; i<nRow; i++)
+ aRect.Top() += pDoc->FastGetRowHeight(i,nTab);
+ aTopLeft.Y() = aRect.Top();
+ aRect.Top() += pDoc->FastGetRowHeight(nRow,nTab);
+
+ TwipsToMM( aRect.Top() );
+ TwipsToMM( aTopLeft.Y() );
+
+ aRect.Bottom() = MAXMM;
+ aRect.Left() = 0;
+ aRect.Right() = MAXMM;
+
+ TwipsToMM( nDifTwips );
+
+ //! aTopLeft ist falsch, wenn mehrere Zeilen auf einmal ausgeblendet werden
+
+ MoveAreaMM( nTab, aRect, Point( 0,nDifTwips ), aTopLeft );
+}
+
+BOOL ScDrawLayer::HasObjectsInRows( USHORT nTab, USHORT nStartRow, USHORT nEndRow )
+{
+ Rectangle aTestRect;
+
+ USHORT i;
+ for (i=0; i<nStartRow; i++)
+ aTestRect.Top() += pDoc->FastGetRowHeight(i,nTab);
+
+ if (nEndRow==MAXROW)
+ aTestRect.Bottom() = MAXMM;
+ else
+ {
+ aTestRect.Bottom() = aTestRect.Top();
+ for (i=nStartRow; i<=nEndRow; i++)
+ {
+ aTestRect.Bottom() += pDoc->FastGetRowHeight(i,nTab);
+ }
+ TwipsToMM( aTestRect.Bottom() );
+ }
+
+ TwipsToMM( aTestRect.Top() );
+
+ aTestRect.Left() = 0;
+ aTestRect.Right() = MAXMM;
+
+ SdrPage* pPage = GetPage(nTab);
+ DBG_ASSERT(pPage,"Page nicht gefunden");
+ if (!pPage)
+ return FALSE;
+
+ BOOL bFound = FALSE;
+
+ Rectangle aObjRect;
+ SdrObjListIter aIter( *pPage );
+ SdrObject* pObject = aIter.Next();
+ while ( pObject && !bFound )
+ {
+ aObjRect = pObject->GetSnapRect(); //! GetLogicRect ?
+ if (aTestRect.IsInside(aObjRect.TopLeft()) || aTestRect.IsInside(aObjRect.BottomLeft()))
+ bFound = TRUE;
+
+ pObject = aIter.Next();
+ }
+
+ return bFound;
+}
+
+void ScDrawLayer::DeleteObjects( USHORT nTab )
+{
+ SdrPage* pPage = GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+ if (!pPage)
+ return;
+
+ pPage->RecalcObjOrdNums();
+
+ long nDelCount = 0;
+ ULONG nObjCount = pPage->GetObjCount();
+ if (nObjCount)
+ {
+ SdrObject** ppObj = new SdrObject*[nObjCount];
+
+ SdrObjListIter aIter( *pPage, IM_FLAT );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ // alle loeschen
+ ppObj[nDelCount++] = pObject;
+ pObject = aIter.Next();
+ }
+
+ long i;
+ if (bRecording)
+ for (i=1; i<=nDelCount; i++)
+ AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) );
+
+ for (i=1; i<=nDelCount; i++)
+ pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
+
+ delete[] ppObj;
+ }
+}
+
+void ScDrawLayer::DeleteObjectsInArea( USHORT nTab, USHORT nCol1,USHORT nRow1,
+ USHORT nCol2,USHORT nRow2 )
+{
+ SdrPage* pPage = GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+ if (!pPage)
+ return;
+
+ pPage->RecalcObjOrdNums();
+
+ long nDelCount = 0;
+ ULONG nObjCount = pPage->GetObjCount();
+ if (nObjCount)
+ {
+ Rectangle aDelRect = pDoc->GetMMRect( nCol1, nRow1, nCol2, nRow2, nTab );
+
+ SdrObject** ppObj = new SdrObject*[nObjCount];
+
+ SdrObjListIter aIter( *pPage, IM_FLAT );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ Rectangle aObjRect = pObject->GetBoundRect();
+ if ( aDelRect.IsInside( aObjRect ) )
+ ppObj[nDelCount++] = pObject;
+
+ pObject = aIter.Next();
+ }
+
+ long i;
+ if (bRecording)
+ for (i=1; i<=nDelCount; i++)
+ AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) );
+
+ for (i=1; i<=nDelCount; i++)
+ pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
+
+ delete[] ppObj;
+ }
+}
+
+void ScDrawLayer::DeleteObjectsInSelection( const ScMarkData& rMark )
+{
+ if ( !rMark.IsMultiMarked() )
+ return;
+
+ ScRange aMarkRange;
+ rMark.GetMultiMarkArea( aMarkRange );
+
+ USHORT nTabCount = pDoc->GetTableCount();
+ for (USHORT nTab=0; nTab<=nTabCount; nTab++)
+ if ( rMark.GetTableSelect( nTab ) )
+ {
+ SdrPage* pPage = GetPage(nTab);
+ if (pPage)
+ {
+ pPage->RecalcObjOrdNums();
+ long nDelCount = 0;
+ ULONG nObjCount = pPage->GetObjCount();
+ if (nObjCount)
+ {
+ // Rechteck um die ganze Selektion
+ Rectangle aMarkBound = pDoc->GetMMRect(
+ aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
+ aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), nTab );
+
+ SdrObject** ppObj = new SdrObject*[nObjCount];
+
+ SdrObjListIter aIter( *pPage, IM_FLAT );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ Rectangle aObjRect = pObject->GetBoundRect();
+ if ( aMarkBound.IsInside( aObjRect ) )
+ {
+ ScRange aRange = pDoc->GetRange( nTab, aObjRect );
+ if (rMark.IsAllMarked(aRange))
+ ppObj[nDelCount++] = pObject;
+ }
+
+ pObject = aIter.Next();
+ }
+
+ // Objekte loeschen (rueckwaerts)
+
+ long i;
+ if (bRecording)
+ for (i=1; i<=nDelCount; i++)
+ AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) );
+
+ for (i=1; i<=nDelCount; i++)
+ pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
+
+ delete[] ppObj;
+ }
+ }
+ else
+ DBG_ERROR("pPage?");
+ }
+}
+
+SdrObject* ScDrawLayer::GetNamedObject( const String& rName, USHORT nId, USHORT& rFoundTab ) const
+{
+ USHORT nTabCount = GetPageCount();
+ for (USHORT nTab=0; nTab<nTabCount; nTab++)
+ {
+ const SdrPage* pPage = GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+ if (pPage)
+ {
+ SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ if ( nId == 0 || pObject->GetObjIdentifier() == nId )
+ if ( pObject->GetName() == rName )
+ {
+ rFoundTab = nTab;
+ return pObject;
+ }
+
+ pObject = aIter.Next();
+ }
+ }
+ }
+
+ return NULL;
+}
+
+String ScDrawLayer::GetNewGraphicName() const
+{
+ String aBase = ScGlobal::GetRscString(STR_GRAPHICNAME);
+ aBase += ' ';
+
+ BOOL bThere = TRUE;
+ String aName;
+ USHORT nDummy;
+ long nId = 0;
+ while (bThere)
+ {
+ ++nId;
+ aName = aBase;
+ aName += String::CreateFromInt32( nId );
+ bThere = ( GetNamedObject( aName, 0, nDummy ) != NULL );
+ }
+
+ return aName;
+}
+
+void ScDrawLayer::EnsureGraphicNames()
+{
+ // make sure all graphic objects have names (after Excel import etc.)
+
+ USHORT nTabCount = GetPageCount();
+ for (USHORT nTab=0; nTab<nTabCount; nTab++)
+ {
+ SdrPage* pPage = GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+ if (pPage)
+ {
+ SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ if ( pObject->GetObjIdentifier() == OBJ_GRAF && pObject->GetName().Len() == 0 )
+ pObject->SetName( GetNewGraphicName() );
+
+ pObject = aIter.Next();
+ }
+ }
+ }
+}
+
+ULONG ScDrawLayer::GetDefTextHeight() const
+{
+ return nDefTextHgt; // protected in SdrModel
+}
+
+void ScDrawLayer::SetAnchor( SdrObject* pObj, ScAnchorType eType )
+{
+ // Ein an der Seite verankertes Objekt zeichnet sich durch eine Anker-Pos
+ // von (0,1) aus. Das ist ein shabby Trick, der aber funktioniert!
+ Point aAnchor( 0, eType == SCA_PAGE ? 1 : 0 );
+ pObj->SetAnchorPos( aAnchor );
+}
+
+ScAnchorType ScDrawLayer::GetAnchor( const SdrObject* pObj )
+{
+ Point aAnchor( pObj->GetAnchorPos() );
+ return ( aAnchor.Y() != 0 ) ? SCA_PAGE : SCA_CELL;
+}
+
+ScDrawObjData* ScDrawLayer::GetObjData( SdrObject* pObj, BOOL bCreate ) // static
+{
+ USHORT nCount = pObj->GetUserDataCount();
+ for( USHORT i = 0; i < nCount; i++ )
+ {
+ SdrObjUserData* pData = pObj->GetUserData( i );
+ if( pData && pData->GetInventor() == SC_DRAWLAYER
+ && pData->GetId() == SC_UD_OBJDATA )
+ return (ScDrawObjData*) pData;
+ }
+ if( bCreate )
+ {
+ ScDrawObjData* pData = new ScDrawObjData;
+ pObj->InsertUserData( pData, 0 );
+ return pData;
+ }
+ return NULL;
+}
+
+ScIMapInfo* ScDrawLayer::GetIMapInfo( SdrObject* pObj ) // static
+{
+ USHORT nCount = pObj->GetUserDataCount();
+ for( USHORT i = 0; i < nCount; i++ )
+ {
+ SdrObjUserData* pData = pObj->GetUserData( i );
+ if( pData && pData->GetInventor() == SC_DRAWLAYER
+ && pData->GetId() == SC_UD_IMAPDATA )
+ return (ScIMapInfo*) pData;
+ }
+ return NULL;
+}
+
+Graphic ScDrawLayer::GetGraphicFromOle2Obj( const SdrOle2Obj* pOle2Obj ) // static
+{
+ SvInPlaceObjectRef aIPObjRef = pOle2Obj->GetObjRef();
+ Graphic aGraphic;
+
+ if ( aIPObjRef.Is() )
+ {
+ VirtualDevice aVDev;
+ GDIMetaFile aGDIMtf;
+ const MapMode aMap100( MAP_100TH_MM );
+ const Size& rSize = aIPObjRef->GetVisArea().GetSize();
+
+ aVDev.SetMapMode( aMap100 );
+ aGDIMtf.Record( &aVDev );
+
+ aIPObjRef->DoDraw( &aVDev, Point(), rSize, JobSetup() );
+
+ aGDIMtf.Stop();
+ aGDIMtf.WindStart();
+ aGDIMtf.SetPrefMapMode( aMap100 );
+ aGDIMtf.SetPrefSize( rSize );
+ aGraphic = Graphic( aGDIMtf );
+ }
+
+ return aGraphic;
+}
+
+// static:
+IMapObject* ScDrawLayer::GetHitIMapObject( SdrObject* pObj,
+ const Point& rWinPoint, const Window& rCmpWnd )
+{
+ const MapMode aMap100( MAP_100TH_MM );
+ MapMode aWndMode = rCmpWnd.GetMapMode();
+ Point aRelPoint( rCmpWnd.LogicToLogic( rWinPoint, &aWndMode, &aMap100 ) );
+ Rectangle aLogRect = rCmpWnd.LogicToLogic( pObj->GetLogicRect(), &aWndMode, &aMap100 );
+ ScIMapInfo* pIMapInfo = GetIMapInfo( pObj );
+ IMapObject* pIMapObj = NULL;
+
+ if ( pIMapInfo )
+ {
+ Size aGraphSize;
+ ImageMap& rImageMap = (ImageMap&) pIMapInfo->GetImageMap();
+ Graphic aGraphic;
+ BOOL bObjSupported = FALSE;
+
+ if ( pObj->ISA( SdrGrafObj ) ) // einfaches Grafik-Objekt
+ {
+ const SdrGrafObj* pGrafObj = (const SdrGrafObj*) pObj;
+ const GeoStat& rGeo = pGrafObj->GetGeoStat();
+ const Graphic& rGraphic = pGrafObj->GetGraphic();
+
+ // Drehung rueckgaengig
+ if ( rGeo.nDrehWink )
+ RotatePoint( aRelPoint, aLogRect.TopLeft(), -rGeo.nSin, rGeo.nCos );
+
+ // Spiegelung rueckgaengig
+ if ( ( (const SdrGrafObjGeoData*) pGrafObj->GetGeoData() )->bMirrored )
+ aRelPoint.X() = aLogRect.Right() + aLogRect.Left() - aRelPoint.X();
+
+ // ggf. Unshear:
+ if ( rGeo.nShearWink )
+ ShearPoint( aRelPoint, aLogRect.TopLeft(), -rGeo.nTan );
+
+
+ if ( rGraphic.GetPrefMapMode().GetMapUnit() == MAP_PIXEL )
+ aGraphSize = rCmpWnd.PixelToLogic( rGraphic.GetPrefSize(),
+ aMap100 );
+ else
+ aGraphSize = OutputDevice::LogicToLogic( rGraphic.GetPrefSize(),
+ rGraphic.GetPrefMapMode(),
+ aMap100 );
+
+ bObjSupported = TRUE;
+ }
+ else if ( pObj->ISA( SdrOle2Obj ) ) // OLE-Objekt
+ {
+ SvInPlaceObjectRef aIPObjRef = ( (SdrOle2Obj*) pObj )->GetObjRef();
+
+ if ( aIPObjRef.Is() )
+ {
+ aGraphSize = aIPObjRef->GetVisArea().GetSize();
+ bObjSupported = TRUE;
+ }
+ }
+
+ // hat alles geklappt, dann HitTest ausfuehren
+ if ( bObjSupported )
+ {
+ // relativen Mauspunkt berechnen
+ aRelPoint -= aLogRect.TopLeft();
+ pIMapObj = rImageMap.GetHitIMapObject( aGraphSize, aLogRect.GetSize(), aRelPoint );
+ }
+ }
+
+ return pIMapObj;
+}
+
+void ScDrawLayer::SetGlobalDrawPersist(SvPersist* pPersist) // static
+{
+ DBG_ASSERT(!pGlobalDrawPersist,"SetGlobalDrawPersist mehrfach");
+ pGlobalDrawPersist = pPersist;
+}
+
+void __EXPORT ScDrawLayer::SetChanged( FASTBOOL bFlg /* =TRUE */ )
+{
+ if ( bFlg )
+ pDoc->SetChartListenerCollectionNeedsUpdate( TRUE );
+ FmFormModel::SetChanged( bFlg );
+}
+
+SvStream* __EXPORT ScDrawLayer::GetDocumentStream(FASTBOOL& rbDeleteAfterUse) const
+{
+ rbDeleteAfterUse = FALSE;
+ SvStream* pStream = NULL;
+
+ SfxObjectShell* pDocSh = pDoc->GetDocumentShell();
+ if (pDocSh)
+ {
+ SvStorage* pStor = pDocSh->GetStorage();
+
+ if (pStor)
+ {
+ pStream = pStor->OpenStream(
+ String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(STRING_SCSTREAM)),
+ STREAM_READ | STREAM_WRITE | STREAM_TRUNC);
+ pStream->SetVersion(pStor->GetVersion());
+ pStream->SetKey( pStor->GetKey() ); // Passwort setzen
+ }
+ }
+
+ return pStream;
+}
+
+SdrLayerID __EXPORT ScDrawLayer::GetControlExportLayerId( const SdrObject & ) const
+{
+ // Layer fuer Export von Form-Controls in Versionen vor 5.0 - immer SC_LAYER_FRONT
+ return SC_LAYER_FRONT;
+}
+
+
+
diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx
new file mode 100644
index 000000000000..9338d83aac40
--- /dev/null
+++ b/sc/source/core/data/fillinfo.cxx
@@ -0,0 +1,981 @@
+/*************************************************************************
+ *
+ * $RCSfile: fillinfo.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <svx/boxitem.hxx>
+#include <svx/shaditem.hxx>
+
+#include "document.hxx"
+#include "cell.hxx"
+#include "table.hxx"
+#include "attrib.hxx"
+#include "attarray.hxx"
+#include "markarr.hxx"
+#include "markdata.hxx"
+#include "patattr.hxx"
+#include "docpool.hxx"
+#include "conditio.hxx"
+#include "stlpool.hxx"
+
+
+// -----------------------------------------------------------------------
+
+enum FillInfoLinePos
+ {
+ FILP_TOP,
+ FILP_BOTTOM,
+ FILP_LEFT,
+ FILP_RIGHT
+ };
+
+
+inline const SvxBorderLine* GetNullOrLine( const SvxBoxItem* pBox, FillInfoLinePos eWhich )
+{
+ if (pBox)
+ {
+ if (eWhich==FILP_TOP)
+ return pBox->GetTop();
+ else if (eWhich==FILP_BOTTOM)
+ return pBox->GetBottom();
+ else if (eWhich==FILP_LEFT)
+ return pBox->GetLeft();
+ else
+ return pBox->GetRight();
+ }
+ else
+ return NULL;
+}
+
+// aehnlich wie in output.cxx
+
+void lcl_GetMergeRange( short nX, short nY, USHORT nArrY,
+ ScDocument* pDoc, RowInfo* pRowInfo,
+ USHORT nX1, USHORT nY1, USHORT nX2, USHORT nY2, USHORT nTab,
+ short& rStartX, short& rStartY, short& rEndX, short& rEndY )
+{
+ CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nX+1];
+
+ rStartX = nX;
+ rStartY = nY;
+ BOOL bHOver = pInfo->bHOverlapped;
+ BOOL bVOver = pInfo->bVOverlapped;
+
+ while (bHOver) // nY konstant
+ {
+ --rStartX;
+ if (rStartX >= (short) nX1 && (pDoc->GetColFlags(rStartX,nTab) & CR_HIDDEN) == 0)
+ {
+ bHOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bHOverlapped;
+ bVOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bVOverlapped;
+ }
+ else
+ {
+ USHORT nOverlap = ((ScMergeFlagAttr*)pDoc->GetAttr(
+ rStartX, rStartY, nTab, ATTR_MERGE_FLAG ))->GetValue();
+ bHOver = ((nOverlap & SC_MF_HOR) != 0);
+ bVOver = ((nOverlap & SC_MF_VER) != 0);
+ }
+ }
+
+ while (bVOver)
+ {
+ --rStartY;
+
+ if (nArrY>0)
+ --nArrY; // lokale Kopie !
+
+ if (rStartX >= (short) nX1 && rStartY >= (short) nY1 &&
+ (pDoc->GetColFlags(rStartX,nTab) & CR_HIDDEN) == 0 &&
+ (pDoc->GetRowFlags(rStartY,nTab) & CR_HIDDEN) == 0 &&
+ (short) pRowInfo[nArrY].nRowNo == rStartY)
+ {
+ bHOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bHOverlapped;
+ bVOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bVOverlapped;
+ }
+ else
+ {
+ USHORT nOverlap = ((ScMergeFlagAttr*)pDoc->GetAttr(
+ rStartX, rStartY, nTab, ATTR_MERGE_FLAG ))->GetValue();
+ bHOver = ((nOverlap & SC_MF_HOR) != 0);
+ bVOver = ((nOverlap & SC_MF_VER) != 0);
+ }
+ }
+
+ const ScMergeAttr* pMerge;
+ if (rStartX >= (short) nX1 && rStartY >= (short) nY1 &&
+ (pDoc->GetColFlags(rStartX,nTab) & CR_HIDDEN) == 0 &&
+ (pDoc->GetRowFlags(rStartY,nTab) & CR_HIDDEN) == 0 &&
+ (short) pRowInfo[nArrY].nRowNo == rStartY)
+ {
+ pMerge = (const ScMergeAttr*) &pRowInfo[nArrY].pCellInfo[rStartX+1].pPatternAttr->
+ GetItem(ATTR_MERGE);
+ }
+ else
+ pMerge = (const ScMergeAttr*) pDoc->GetAttr(rStartX,rStartY,nTab,ATTR_MERGE);
+
+ rEndX = rStartX + pMerge->GetColMerge() - 1;
+ rEndY = rStartY + pMerge->GetRowMerge() - 1;
+}
+
+inline BOOL ScDocument::RowHidden( USHORT nRow, USHORT nTab )
+{
+ return ( pTab[nTab]->pRowFlags[nRow] & CR_HIDDEN ) != 0;
+}
+
+
+#define CELLINFO(x,y) pRowInfo[nArrY+y].pCellInfo[nArrX+x]
+
+USHORT ScDocument::FillInfo( RowInfo* pRowInfo, USHORT nX1, USHORT nY1, USHORT nX2, USHORT nY2,
+ USHORT nTab, double nScaleX, double nScaleY,
+ BOOL bPageMode, BOOL bFormulaMode, const ScMarkData* pMarkData )
+{
+ DBG_ASSERT( pTab[nTab], "Tabelle existiert nicht" );
+
+ const SvxBrushItem* pDefBackground =
+ (const SvxBrushItem*) &pDocPool->GetDefaultItem( ATTR_BACKGROUND );
+ const ScMergeAttr* pDefMerge =
+ (const ScMergeAttr*) &pDocPool->GetDefaultItem( ATTR_MERGE );
+ const SvxBoxItem* pDefLines =
+ (const SvxBoxItem*) &pDocPool->GetDefaultItem( ATTR_BORDER );
+ const SvxShadowItem* pDefShadow =
+ (const SvxShadowItem*) &pDocPool->GetDefaultItem( ATTR_SHADOW );
+
+ USHORT nThisRow;
+ USHORT nX;
+ USHORT nY;
+ short nSignedY;
+ USHORT nArrX;
+ USHORT nArrY;
+ USHORT nArrCount;
+ BOOL bAnyLines = FALSE;
+ BOOL bAnyMerged = FALSE;
+ BOOL bAnyShadow = FALSE;
+ BOOL bAnyCondition = FALSE;
+
+ BOOL bTabProtect = IsTabProtected(nTab);
+
+ // fuer Blockmarken von zusammengefassten Zellen mit
+ // versteckter erster Zeile / Spalte
+ BOOL bPaintMarks = FALSE;
+ BOOL bSkipMarks = FALSE;
+ USHORT nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY;
+ if (pMarkData && pMarkData->IsMarked())
+ {
+ ScRange aTmpRange;
+ pMarkData->GetMarkArea(aTmpRange);
+ if ( nTab >= aTmpRange.aStart.Tab() && nTab <= aTmpRange.aEnd.Tab() )
+ {
+ nBlockStartX = aTmpRange.aStart.Col();
+ nBlockStartY = aTmpRange.aStart.Row();
+ nBlockEndX = aTmpRange.aEnd.Col();
+ nBlockEndY = aTmpRange.aEnd.Row();
+ ExtendHidden( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY, nTab ); //? noetig ?
+ if (pMarkData->IsMarkNegative())
+ bSkipMarks = TRUE;
+ else
+ bPaintMarks = TRUE;
+ }
+ }
+
+ // zuerst nur die Eintraege fuer die ganze Spalte
+
+ nArrY=0;
+ USHORT nYExtra = nY2+1;
+ for (nSignedY=((short)nY1)-1; nSignedY<=(short)nYExtra; nSignedY++)
+ {
+ if (nSignedY >= 0)
+ nY = (USHORT) nSignedY;
+ else
+ nY = MAXROW+1; // ungueltig
+
+ USHORT nDocHeight;
+ if (nY <= MAXROW)
+ nDocHeight = GetRowHeight( nY, nTab );
+ else
+ nDocHeight = ScGlobal::nStdRowHeight;
+
+ if ( nArrY==0 || nDocHeight || nY > MAXROW )
+ {
+ RowInfo* pThisRowInfo = &pRowInfo[nArrY];
+ pThisRowInfo->pCellInfo = NULL; // wird unten belegt
+
+ USHORT nHeight = (USHORT) ( nDocHeight * nScaleY );
+ if (!nHeight)
+ nHeight = 1;
+
+ pThisRowInfo->nRowNo = nY; //! Fall < 0 ?
+ pThisRowInfo->nHeight = nHeight;
+ pThisRowInfo->bEmptyBack = TRUE;
+ pThisRowInfo->bEmptyText = TRUE;
+ pThisRowInfo->bChanged = TRUE;
+ pThisRowInfo->bAutoFilter = FALSE;
+ pThisRowInfo->bPushButton = FALSE;
+ pThisRowInfo->nRotMaxCol = SC_ROTMAX_NONE;
+
+ ++nArrY;
+ if (nArrY >= ROWINFO_MAX)
+ {
+ DBG_ERROR("Zu grosser Bereich bei FillInfo" );
+ nYExtra = nSignedY; // Ende
+ nY2 = nYExtra - 1; // Bereich anpassen
+ }
+ }
+ else
+ if (nSignedY==(short) nYExtra) // zusaetzliche Zeile verdeckt ?
+ ++nYExtra;
+ }
+ nArrCount = nArrY; // incl. Dummys
+
+ // rotierter Text...
+
+ // Attribut im Dokument ueberhaupt verwendet?
+ BOOL bAnyItem = FALSE;
+ USHORT nRotCount = pDocPool->GetItemCount( ATTR_ROTATE_VALUE );
+ for (USHORT nItem=0; nItem<nRotCount; nItem++)
+ if (pDocPool->GetItem( ATTR_ROTATE_VALUE, nItem ))
+ {
+ bAnyItem = TRUE;
+ break;
+ }
+
+ USHORT nRotMax = nX2;
+ if ( bAnyItem && HasAttrib( 0,nY1,nTab, MAXCOL,nY2+1,nTab,
+ HASATTR_ROTATE | HASATTR_CONDITIONAL ) )
+ {
+ //! Conditionals auch bei HASATTR_ROTATE abfragen ????
+
+ DBG_ASSERT( nArrCount>2, "nArrCount zu klein" );
+// FindMaxRotCol( nTab, &pRowInfo[1], nArrCount-2, nX1, nX2 );
+ FindMaxRotCol( nTab, &pRowInfo[1], nArrCount-1, nX1, nX2 );
+ // FindMaxRotCol setzt nRotMaxCol
+
+ for (nArrY=0; nArrY<nArrCount; nArrY++)
+ if (pRowInfo[nArrY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nArrY].nRotMaxCol > nRotMax)
+ nRotMax = pRowInfo[nArrY].nRotMaxCol;
+ }
+
+ // Zell-Infos erst nach dem Test auf gedrehte allozieren
+ // bis nRotMax wegen nRotateDir Flag
+
+ for (nArrY=0; nArrY<nArrCount; nArrY++)
+ {
+ RowInfo* pThisRowInfo = &pRowInfo[nArrY];
+ nY = pThisRowInfo->nRowNo;
+ pThisRowInfo->pCellInfo = new CellInfo[ nRotMax+1+2 ]; // vom Aufrufer zu loeschen !
+
+ for (nArrX=0; nArrX<=nRotMax+2; nArrX++) // Zell-Infos vorbelegen
+ {
+ if (nArrX>0)
+ nX = nArrX-1;
+ else
+ nX = MAXCOL+1; // ungueltig
+
+ CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
+ pInfo->bEmptyCellText = TRUE;
+ pInfo->pCell = NULL;
+ if (bPaintMarks)
+ pInfo->bMarked = ( nX >= nBlockStartX && nX <= nBlockEndX
+ && nY >= nBlockStartY && nY <= nBlockEndY );
+ else
+ pInfo->bMarked = FALSE;
+ pInfo->nWidth = 0;
+
+ pInfo->bStandard = FALSE; //! umbenennen in bClipped
+ pInfo->bMerged = FALSE;
+ pInfo->bHOverlapped = FALSE;
+ pInfo->bVOverlapped = FALSE;
+ pInfo->bAutoFilter = FALSE;
+ pInfo->bPushButton = FALSE;
+ pInfo->nRotateDir = SC_ROTDIR_NONE;
+
+ pInfo->bPrinted = FALSE; // view-intern
+ pInfo->bHideGrid = FALSE; // view-intern
+ pInfo->bEditEngine = FALSE; // view-intern
+
+ pInfo->pBackground = NULL; //! weglassen?
+ pInfo->pPatternAttr = NULL;
+ pInfo->pConditionSet= NULL;
+
+ pInfo->pLinesAttr = NULL;
+ pInfo->pRightLine = NULL;
+ pInfo->pBottomLine = NULL;
+
+ pInfo->pShadowAttr = pDefShadow;
+ pInfo->pHShadowOrigin = NULL;
+ pInfo->pVShadowOrigin = NULL;
+ }
+ }
+
+ for (nArrX=nX2+3; nArrX<=nRotMax+2; nArrX++) // restliche Breiten eintragen
+ {
+ nX = nArrX-1;
+ if ( nX <= MAXCOL )
+ {
+ if ( (GetColFlags(nX,nTab) & CR_HIDDEN) == 0 ) // Spalte nicht versteckt
+ {
+ USHORT nThisWidth = (USHORT) (GetColWidth( nX, nTab ) * nScaleX);
+ if (!nThisWidth)
+ nThisWidth = 1;
+
+ pRowInfo[0].pCellInfo[nArrX].nWidth = nThisWidth;
+ }
+ }
+ }
+
+ for (nArrX=0; nArrX<=nX2+2; nArrX++) // links & rechts + 1
+ {
+ nX = (nArrX>0) ? nArrX-1 : MAXCOL+1; // negativ -> ungueltig
+
+ if ( nX <= MAXCOL )
+ {
+ if ( (GetColFlags(nX,nTab) & CR_HIDDEN) == 0 ) // Spalte nicht versteckt
+ {
+ USHORT nThisWidth = (USHORT) (GetColWidth( nX, nTab ) * nScaleX);
+ if (!nThisWidth)
+ nThisWidth = 1;
+
+ pRowInfo[0].pCellInfo[nArrX].nWidth = nThisWidth; //! dies sollte reichen
+
+ ScColumn* pThisCol = &pTab[nTab]->aCol[nX]; // Spalten-Daten
+
+ nArrY = 1;
+ USHORT nUIndex;
+ (void) pThisCol->Search( nY1, nUIndex );
+ while ( nUIndex < pThisCol->nCount &&
+ (nThisRow=pThisCol->pItems[nUIndex].nRow) <= nY2 )
+ {
+ if ( !RowHidden( nThisRow,nTab ) )
+ {
+ while ( pRowInfo[nArrY].nRowNo < nThisRow )
+ ++nArrY;
+ DBG_ASSERT( pRowInfo[nArrY].nRowNo == nThisRow, "Zeile nicht gefunden in FillInfo" );
+
+ RowInfo* pThisRowInfo = &pRowInfo[nArrY];
+ CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
+ pInfo->pCell = pThisCol->pItems[nUIndex].pCell;
+ if (pInfo->pCell->GetCellType() != CELLTYPE_NOTE)
+ {
+ pThisRowInfo->bEmptyText = FALSE; // Zeile nicht leer
+ pInfo->bEmptyCellText = FALSE; // Zelle nicht leer
+ }
+ ++nArrY;
+ }
+ ++nUIndex;
+ }
+
+ if (nX+1 >= nX1) // Attribute/Blockmarken ab nX1-1
+ {
+ ScAttrArray* pThisAttrArr = pThisCol->pAttrArray; // Attribute
+
+ nArrY = 0;
+ const ScPatternAttr* pPattern;
+ USHORT nCurRow=nY1; // einzelne Zeile
+ if (nCurRow>0)
+ --nCurRow; // oben 1 mehr
+ else
+ nArrY = 1;
+ nThisRow=nCurRow; // Ende des Bereichs
+ short nIndex;
+ (void) pThisAttrArr->Search( nCurRow, nIndex );
+
+
+ do
+ {
+ nThisRow=pThisAttrArr->pData[nIndex].nRow; // Ende des Bereichs
+ pPattern=pThisAttrArr->pData[nIndex].pPattern;
+
+ const SvxBrushItem* pBackground = (const SvxBrushItem*)
+ &pPattern->GetItem(ATTR_BACKGROUND);
+ const SvxBoxItem* pLinesAttr = (const SvxBoxItem*)
+ &pPattern->GetItem(ATTR_BORDER);
+ if (pLinesAttr != pDefLines)
+ bAnyLines = TRUE;
+
+ const SvxShadowItem* pShadowAttr = (const SvxShadowItem*)
+ &pPattern->GetItem(ATTR_SHADOW);
+ if (pShadowAttr != pDefShadow)
+ bAnyShadow = TRUE;
+
+ const ScMergeAttr* pMergeAttr = (const ScMergeAttr*)
+ &pPattern->GetItem(ATTR_MERGE);
+ BOOL bMerged = ( pMergeAttr != pDefMerge && *pMergeAttr != *pDefMerge );
+ USHORT nOverlap = ((const ScMergeFlagAttr*) &pPattern->GetItemSet().
+ Get(ATTR_MERGE_FLAG))->GetValue();
+ BOOL bHOverlapped = ((nOverlap & SC_MF_HOR) != 0);
+ BOOL bVOverlapped = ((nOverlap & SC_MF_VER) != 0);
+ BOOL bAutoFilter = ((nOverlap & SC_MF_AUTO) != 0);
+ BOOL bPushButton = ((nOverlap & SC_MF_BUTTON) != 0);
+ BOOL bScenario = ((nOverlap & SC_MF_SCENARIO) != 0);
+ if (bMerged||bHOverlapped||bVOverlapped)
+ bAnyMerged = TRUE; // intern
+
+ BOOL bHidden, bHideFormula;
+ if (bTabProtect)
+ {
+ const ScProtectionAttr& rProtAttr = (const ScProtectionAttr&)
+ pPattern->GetItem(ATTR_PROTECTION);
+ bHidden = rProtAttr.GetHideCell();
+ bHideFormula = rProtAttr.GetHideFormula();
+ }
+ else
+ bHidden = bHideFormula = FALSE;
+
+ ULONG nConditional = ((const SfxUInt32Item&)pPattern->
+ GetItem(ATTR_CONDITIONAL)).GetValue();
+ const ScConditionalFormat* pCondForm = NULL;
+ if ( nConditional && pCondFormList )
+ pCondForm = pCondFormList->GetFormat( nConditional );
+
+ do
+ {
+ if ( nArrY==0 || !RowHidden( nCurRow,nTab ) )
+ {
+ RowInfo* pThisRowInfo = &pRowInfo[nArrY];
+ if (pBackground != pDefBackground) // Spalten-HG == Standard ?
+ pThisRowInfo->bEmptyBack = FALSE;
+ if (bAutoFilter)
+ pThisRowInfo->bAutoFilter = TRUE;
+ if (bPushButton)
+ pThisRowInfo->bPushButton = TRUE;
+
+ CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
+ pInfo->pBackground = pBackground;
+ pInfo->pPatternAttr = pPattern;
+ pInfo->bMerged = bMerged;
+ pInfo->bHOverlapped = bHOverlapped;
+ pInfo->bVOverlapped = bVOverlapped;
+ pInfo->bAutoFilter = bAutoFilter;
+ pInfo->bPushButton = bPushButton;
+ pInfo->pLinesAttr = pLinesAttr;
+ pInfo->pShadowAttr = pShadowAttr;
+ // nWidth wird nicht mehr einzeln gesetzt
+
+ BOOL bEmbed = bIsEmbedded &&
+ nTab >= aEmbedRange.aStart.Tab() &&
+ nTab <= aEmbedRange.aEnd.Tab() &&
+ nX >= aEmbedRange.aStart.Col() &&
+ nX <= aEmbedRange.aEnd.Col() &&
+ nCurRow >= aEmbedRange.aStart.Row() &&
+ nCurRow <= aEmbedRange.aEnd.Row();
+
+ if (bPushButton || bScenario)
+ {
+ pInfo->pBackground = ScGlobal::GetButtonBrushItem();
+ pThisRowInfo->bEmptyBack = FALSE;
+ }
+ else if (bEmbed)
+ {
+ pInfo->pBackground = ScGlobal::GetEmbeddedBrushItem();
+ pThisRowInfo->bEmptyBack = FALSE;
+ }
+
+ if (bHidden || ( bFormulaMode && bHideFormula && pInfo->pCell
+ && pInfo->pCell->GetCellType()
+ == CELLTYPE_FORMULA ))
+ pInfo->bEmptyCellText = TRUE;
+
+ if ( pCondForm )
+ {
+ String aStyle = pCondForm->GetCellStyle( pInfo->pCell,
+ ScAddress( nX, nCurRow, nTab ) );
+ if (aStyle.Len())
+ {
+ SfxStyleSheetBase* pStyleSheet =
+ pStylePool->Find( aStyle, SFX_STYLE_FAMILY_PARA );
+ if ( pStyleSheet )
+ {
+ //! Style-Sets cachen !!!
+ pInfo->pConditionSet = &pStyleSheet->GetItemSet();
+ bAnyCondition = TRUE;
+ }
+ else
+ DBG_ERROR("Style nicht gefunden");
+ }
+ }
+
+ ++nArrY;
+ }
+ ++nCurRow;
+ }
+ while (nCurRow <= nThisRow && nCurRow <= nYExtra);
+ ++nIndex;
+ }
+ while ( nIndex < (short) pThisAttrArr->nCount && nThisRow < nYExtra );
+
+
+ if (pMarkData && pMarkData->IsMultiMarked())
+ {
+ // Blockmarken
+ const ScMarkArray* pThisMarkArr = pMarkData->GetArray()+nX;
+ BOOL bThisMarked;
+ nArrY = 1;
+ nCurRow = nY1; // einzelne Zeile
+ nThisRow = nY1; // Ende des Bereichs
+ (void) pThisMarkArr->Search( nY1, nIndex );
+
+ do
+ {
+ nThisRow=pThisMarkArr->pData[nIndex].nRow; // Ende des Bereichs
+ bThisMarked=pThisMarkArr->pData[nIndex].bMarked;
+
+ do
+ {
+ if ( !RowHidden( nCurRow,nTab ) )
+ {
+ if ( bThisMarked )
+ {
+ BOOL bSkip = bSkipMarks &&
+ nX >= nBlockStartX &&
+ nX <= nBlockEndX &&
+ nCurRow >= nBlockStartY &&
+ nCurRow <= nBlockEndY;
+ if (!bSkip)
+ {
+ RowInfo* pThisRowInfo = &pRowInfo[nArrY];
+ CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
+ pInfo->bMarked = TRUE;
+ }
+ }
+ ++nArrY;
+ }
+ ++nCurRow;
+ }
+ while (nCurRow <= nThisRow && nCurRow <= nY2);
+ ++nIndex;
+ }
+ while ( nIndex < (short) pThisMarkArr->nCount && nThisRow < nY2 );
+ }
+ }
+ else // vordere Spalten
+ {
+ for (nArrY=1; nArrY+1<nArrCount; nArrY++)
+ {
+ RowInfo* pThisRowInfo = &pRowInfo[nArrY];
+ CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
+
+ pInfo->nWidth = nThisWidth; //! oder nur 0 abfragen ??
+ }
+ }
+ }
+ }
+ else
+ pRowInfo[0].pCellInfo[nArrX].nWidth = STD_COL_WIDTH;
+ // STD_COL_WIDTH ganz links und rechts wird fuer DrawExtraShadow gebraucht
+ }
+
+ //-------------------------------------------------------------------------
+ // bedingte Formatierung auswerten
+
+ if (bAnyCondition)
+ {
+ for (nArrY=0; nArrY<nArrCount; nArrY++)
+ {
+ for (nArrX=nX1; nArrX<=nX2+2; nArrX++) // links und rechts einer mehr
+ {
+ CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nArrX];
+ const SfxItemSet* pCondSet = pInfo->pConditionSet;
+ if (pCondSet)
+ {
+ const SfxPoolItem* pItem;
+
+ // Hintergrund
+ if ( pCondSet->GetItemState( ATTR_BACKGROUND, TRUE, &pItem ) == SFX_ITEM_SET )
+ {
+ pInfo->pBackground = (const SvxBrushItem*) pItem;
+ pRowInfo[nArrY].bEmptyBack = FALSE;
+ }
+
+ // Umrandung
+ if ( pCondSet->GetItemState( ATTR_BORDER, TRUE, &pItem ) == SFX_ITEM_SET )
+ {
+ pInfo->pLinesAttr = (const SvxBoxItem*) pItem;
+ bAnyLines = TRUE;
+ }
+
+ // Schatten
+ if ( pCondSet->GetItemState( ATTR_SHADOW, TRUE, &pItem ) == SFX_ITEM_SET )
+ {
+ pInfo->pShadowAttr = (const SvxShadowItem*) pItem;
+ bAnyShadow = TRUE;
+ }
+ }
+ }
+ }
+ }
+
+ // bedingte Formatierung Ende
+ //-------------------------------------------------------------------------
+
+
+ if (bAnyMerged)
+ bAnyLines = TRUE; // Linien koennen aus Merge hereinkommen!
+
+ if (bAnyLines) // vier Seiten suchen
+ {
+ for (nArrY=0; nArrY<nArrCount; nArrY++)
+ {
+// short nY = nArrY ? pRowInfo[nArrY].nRowNo : ((short)nY1)-1;
+
+ for (nArrX=nX1; nArrX<=nX2+2; nArrX++) // links und rechts einer mehr
+ {
+ short nX = ((short) nArrX) - 1;
+ CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nArrX];
+
+ pInfo->pThisBottom = GetNullOrLine( pInfo->pLinesAttr, FILP_BOTTOM );
+ if ( nArrY+1 < nArrCount )
+ pInfo->pNextTop =
+ GetNullOrLine( CELLINFO(0,1).pLinesAttr, FILP_TOP );
+ else
+ pInfo->pNextTop = NULL;
+
+ pInfo->pThisRight = GetNullOrLine( pInfo->pLinesAttr, FILP_RIGHT );
+ if ( nX <= (short) nX2 )
+ pInfo->pNextLeft =
+ GetNullOrLine( CELLINFO(1,0).pLinesAttr, FILP_LEFT );
+ else
+ pInfo->pNextLeft = NULL;
+ }
+ }
+ }
+
+ //
+ // Daten von zusammengefassten Zellen anpassen
+ //
+
+ if (bAnyMerged)
+ {
+ for (nArrY=0; nArrY<nArrCount; nArrY++)
+ {
+ RowInfo* pThisRowInfo = &pRowInfo[nArrY];
+ short nY = nArrY ? pThisRowInfo->nRowNo : ((short)nY1)-1;
+
+ for (nArrX=nX1; nArrX<=nX2+2; nArrX++) // links und rechts einer mehr
+ {
+ short nX = ((short) nArrX) - 1;
+ CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
+
+ if (pInfo->bMerged || pInfo->bHOverlapped || pInfo->bVOverlapped)
+ {
+ short nStartX;
+ short nStartY;
+ short nEndX;
+ short nEndY;
+ lcl_GetMergeRange( nX,nY, nArrY, this,pRowInfo, nX1,nY1,nX2,nY2,nTab,
+ nStartX,nStartY, nEndX,nEndY );
+ const ScPatternAttr* pStartPattern = GetPattern( nStartX,nStartY,nTab );
+ const SfxItemSet* pStartCond = GetCondResult( nStartX,nStartY,nTab );
+ const SfxPoolItem* pItem;
+
+ USHORT nVisStartX = (USHORT) nStartX; // sichtbarer Bereich
+ USHORT nVisStartY = (USHORT) nStartY;
+ USHORT nVisEndX = (USHORT) nEndX;
+ USHORT nVisEndY = (USHORT) nEndY;
+ StripHidden( nVisStartX, nVisStartY, nVisEndX, nVisEndY, nTab );
+
+ if ( nX != (short) nVisStartX && nArrX > 0)
+ pThisRowInfo->pCellInfo[nArrX-1].pNextLeft = NULL;
+ if ( nY != (short) nVisStartY && nArrY > 0)
+ pRowInfo[nArrY-1].pCellInfo[nArrX].pNextTop = NULL;
+
+ if ( nX != (short) nVisEndX ) pInfo->pThisRight = NULL;
+ if ( nY != (short) nVisEndY ) pInfo->pThisBottom = NULL;
+
+ if ( nX == (short) nVisStartX || nY == (short) nVisStartY ||
+ nX == (short) nVisEndX || nY == (short) nVisEndY )
+ {
+ if ( !pStartCond || pStartCond->
+ GetItemState(ATTR_BORDER,TRUE,&pItem) != SFX_ITEM_SET )
+ pItem = &pStartPattern->GetItem(ATTR_BORDER);
+ const SvxBoxItem* pBox = (const SvxBoxItem*) pItem;
+ if ( nX == (short) nVisStartX && nArrX > 0 )
+ pThisRowInfo->pCellInfo[nArrX-1].pNextLeft = pBox->GetLeft();
+ if ( nY == (short) nVisStartY && nArrY > 0)
+ pRowInfo[nArrY-1].pCellInfo[nArrX].pNextTop = pBox->GetTop();
+ if ( nX == (short) nVisEndX )
+ pInfo->pThisRight = pBox->GetRight();
+ if ( nY == (short) nVisEndY )
+ pInfo->pThisBottom = pBox->GetBottom();
+ }
+
+ // Hintergrund kopieren (oder in output.cxx)
+
+ if ( !pStartCond || pStartCond->
+ GetItemState(ATTR_BACKGROUND,TRUE,&pItem) != SFX_ITEM_SET )
+ pItem = &pStartPattern->GetItem(ATTR_BACKGROUND);
+ pInfo->pBackground = (const SvxBrushItem*) pItem;
+ pRowInfo[nArrY].bEmptyBack = FALSE;
+
+ // Schatten
+
+ if ( !pStartCond || pStartCond->
+ GetItemState(ATTR_SHADOW,TRUE,&pItem) != SFX_ITEM_SET )
+ pItem = &pStartPattern->GetItem(ATTR_SHADOW);
+ pInfo->pShadowAttr = (const SvxShadowItem*) pItem;
+ if (pInfo->pShadowAttr != pDefShadow)
+ bAnyShadow = TRUE;
+
+ // Blockmarken - wieder mit Original-Merge-Werten
+
+ BOOL bCellMarked = FALSE;
+ if (bPaintMarks)
+ bCellMarked = ( nStartX >= (short) nBlockStartX
+ && nStartX <= (short) nBlockEndX
+ && nStartY >= (short) nBlockStartY
+ && nStartY <= (short) nBlockEndY );
+ if (pMarkData && pMarkData->IsMultiMarked() && !bCellMarked)
+ {
+ const ScMarkArray* pThisMarkArr = pMarkData->GetArray()+nStartX;
+ short nIndex;
+ (void) pThisMarkArr->Search( nStartY, nIndex );
+ bCellMarked=pThisMarkArr->pData[nIndex].bMarked;
+ }
+
+ pInfo->bMarked = bCellMarked;
+ }
+ }
+ }
+ }
+
+ if (bAnyLines) // nach Merge Linien zusammenfassen
+ {
+ for (nArrY=0; nArrY<nArrCount; nArrY++)
+ {
+ RowInfo* pThisRowInfo = &pRowInfo[nArrY];
+// short nY = nArrY ? pRowInfo[nArrY].nRowNo : ((short)nY1)-1;
+
+ for (nArrX=nX1; nArrX<=nX2+2; nArrX++) // links und rechts einer mehr
+ {
+// short nX = ((short) nArrX) - 1;
+ CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
+
+ if ( pInfo->pThisBottom || pInfo->pNextTop )
+ {
+ if ( bPageMode && nArrY == 0 )
+ pInfo->pBottomLine = pInfo->pNextTop;
+ else if ( bPageMode && nArrY+2 >= nArrCount )
+ pInfo->pBottomLine = pInfo->pThisBottom;
+ else if (HasPriority(pInfo->pThisBottom,pInfo->pNextTop))
+ pInfo->pBottomLine = pInfo->pThisBottom;
+ else
+ pInfo->pBottomLine = pInfo->pNextTop;
+ }
+ else
+ pInfo->pBottomLine = NULL; //! Standard
+
+ if ( pInfo->pThisRight || pInfo->pNextLeft )
+ {
+ if ( bPageMode && nArrX == nX1 )
+ pInfo->pRightLine = pInfo->pNextLeft;
+ else if ( bPageMode && nArrX > nX2 )
+ pInfo->pRightLine = pInfo->pThisRight;
+ else if (HasPriority(pInfo->pThisRight,pInfo->pNextLeft))
+ pInfo->pRightLine = pInfo->pThisRight;
+ else
+ pInfo->pRightLine = pInfo->pNextLeft;
+ }
+ else
+ pInfo->pRightLine = NULL; //! Standard
+ }
+ }
+ }
+
+ if (bAnyShadow) // Schatten verteilen
+ {
+ for (nArrY=0; nArrY<nArrCount; nArrY++)
+ {
+ BOOL bTop = ( nArrY == 0 );
+ BOOL bBottom = ( nArrY+1 == nArrCount );
+
+// short nY = nArrY ? pRowInfo[nArrY].nRowNo : ((short)nY1)-1;
+
+ for (nArrX=nX1; nArrX<=nX2+2; nArrX++) // links und rechts einer mehr
+ {
+ BOOL bLeft = ( nArrX == nX1 );
+ BOOL bRight = ( nArrX == nX2+2 );
+
+// short nX = ((short) nArrX) - 1;
+ CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nArrX];
+ const SvxShadowItem* pThisAttr = pInfo->pShadowAttr;
+ SvxShadowLocation eLoc = pThisAttr ? pThisAttr->GetLocation() : SVX_SHADOW_NONE;
+ if (eLoc != SVX_SHADOW_NONE)
+ {
+ // oder Test auf != eLoc
+
+ short nDxPos = 1;
+ short nDxNeg = -1;
+
+ while ( nArrX+nDxPos < nX2+2 && pRowInfo[0].pCellInfo[nArrX+nDxPos].nWidth == 0 )
+ ++nDxPos;
+ while ( nArrX+nDxNeg > nX1 && pRowInfo[0].pCellInfo[nArrX+nDxNeg].nWidth == 0 )
+ --nDxNeg;
+
+ BOOL bLeftDiff = !bLeft &&
+ CELLINFO(nDxNeg,0).pShadowAttr->GetLocation() == SVX_SHADOW_NONE;
+ BOOL bRightDiff = !bRight &&
+ CELLINFO(nDxPos,0).pShadowAttr->GetLocation() == SVX_SHADOW_NONE;
+ BOOL bTopDiff = !bTop &&
+ CELLINFO(0,-1).pShadowAttr->GetLocation() == SVX_SHADOW_NONE;
+ BOOL bBottomDiff = !bBottom &&
+ CELLINFO(0,1).pShadowAttr->GetLocation() == SVX_SHADOW_NONE;
+
+ switch (eLoc)
+ {
+ case SVX_SHADOW_BOTTOMRIGHT:
+ if (bBottomDiff)
+ {
+ CELLINFO(0,1).pHShadowOrigin = pThisAttr;
+ CELLINFO(0,1).eHShadowPart =
+ bLeftDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ;
+ }
+ if (bRightDiff)
+ {
+ CELLINFO(1,0).pVShadowOrigin = pThisAttr;
+ CELLINFO(1,0).eVShadowPart =
+ bTopDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT;
+ }
+ if (bBottomDiff && bRightDiff)
+ {
+ CELLINFO(1,1).pHShadowOrigin = pThisAttr;
+ CELLINFO(1,1).eHShadowPart = SC_SHADOW_CORNER;
+ }
+ break;
+
+ case SVX_SHADOW_BOTTOMLEFT:
+ if (bBottomDiff)
+ {
+ CELLINFO(0,1).pHShadowOrigin = pThisAttr;
+ CELLINFO(0,1).eHShadowPart =
+ bRightDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ;
+ }
+ if (bLeftDiff)
+ {
+ CELLINFO(-1,0).pVShadowOrigin = pThisAttr;
+ CELLINFO(-1,0).eVShadowPart =
+ bTopDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT;
+ }
+ if (bBottomDiff && bLeftDiff)
+ {
+ CELLINFO(-1,1).pHShadowOrigin = pThisAttr;
+ CELLINFO(-1,1).eHShadowPart = SC_SHADOW_CORNER;
+ }
+ break;
+
+ case SVX_SHADOW_TOPRIGHT:
+ if (bTopDiff)
+ {
+ CELLINFO(0,-1).pHShadowOrigin = pThisAttr;
+ CELLINFO(0,-1).eHShadowPart =
+ bLeftDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ;
+ }
+ if (bRightDiff)
+ {
+ CELLINFO(1,0).pVShadowOrigin = pThisAttr;
+ CELLINFO(1,0).eVShadowPart =
+ bBottomDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT;
+ }
+ if (bTopDiff && bRightDiff)
+ {
+ CELLINFO(1,-1).pHShadowOrigin = pThisAttr;
+ CELLINFO(1,-1).eHShadowPart = SC_SHADOW_CORNER;
+ }
+ break;
+
+ case SVX_SHADOW_TOPLEFT:
+ if (bTopDiff)
+ {
+ CELLINFO(0,-1).pHShadowOrigin = pThisAttr;
+ CELLINFO(0,-1).eHShadowPart =
+ bRightDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ;
+ }
+ if (bLeftDiff)
+ {
+ CELLINFO(-1,0).pVShadowOrigin = pThisAttr;
+ CELLINFO(-1,0).eVShadowPart =
+ bBottomDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT;
+ }
+ if (bTopDiff && bLeftDiff)
+ {
+ CELLINFO(-1,-1).pHShadowOrigin = pThisAttr;
+ CELLINFO(-1,-1).eHShadowPart = SC_SHADOW_CORNER;
+ }
+ break;
+
+ default:
+ DBG_ERROR("falscher Shadow-Enum");
+ }
+ }
+ }
+ }
+ }
+
+ return nArrCount;
+}
+
+
+
diff --git a/sc/source/core/data/global.cxx b/sc/source/core/data/global.cxx
new file mode 100644
index 000000000000..efa90da77c68
--- /dev/null
+++ b/sc/source/core/data/global.cxx
@@ -0,0 +1,1668 @@
+/*************************************************************************
+ *
+ * $RCSfile: global.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <svx/algitem.hxx>
+#include <svx/brshitem.hxx>
+#include <svx/editobj.hxx>
+#include <svx/srchitem.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/inimgr.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/viewsh.hxx>
+#include <svtools/iniman.hxx>
+#include <svtools/stritem.hxx>
+#include <svtools/zforlist.hxx>
+#include <svtools/zformat.hxx>
+#include <vcl/image.hxx>
+#include <vcl/rcid.h>
+#include <vcl/virdev.hxx>
+#include <unotools/charclass.hxx>
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+
+
+#ifndef _ISOLANG_HXX
+#include <tools/isolang.hxx>
+#endif
+#ifndef _COM_SUN_STAR_LANG_LOCALE_HPP_
+#include <com/sun/star/lang/Locale.hpp>
+#endif
+
+#include "global.hxx"
+#include "scresid.hxx"
+#include "autoform.hxx"
+#include "document.hxx"
+#include "patattr.hxx"
+#include "addincol.hxx"
+#include "adiasync.hxx"
+#include "userlist.hxx"
+#include "interpre.hxx"
+#include "strload.hxx"
+#include "docpool.hxx"
+#include "scdll.hxx" // ScLibSignalFunc
+#include "unitconv.hxx"
+#include "globstr.hrc"
+#include "scfuncs.hrc"
+#include "sc.hrc"
+
+// -----------------------------------------------------------------------
+
+#define CLIPST_AVAILABLE 0
+#define CLIPST_CAPTURED 1
+#define CLIPST_DELETE 2
+#define CLIPST_DRAW 3
+
+ScDocument* ScGlobal::pClipDoc = NULL;
+SdrModel* ScGlobal::pClipModel = NULL;
+ScDocShellRef* ScGlobal::pDrawClipDocShellRef = NULL;
+BYTE ScGlobal::nClipState = CLIPST_AVAILABLE;
+SvxSearchItem* ScGlobal::pSearchItem = NULL;
+ScAutoFormat* ScGlobal::pAutoFormat = NULL;
+FuncCollection* ScGlobal::pFuncCollection = NULL;
+ScUnoAddInCollection* ScGlobal::pAddInCollection = NULL;
+ScUserList* ScGlobal::pUserList = NULL;
+String** ScGlobal::ppRscString = NULL;
+LanguageType ScGlobal::eLnge = LANGUAGE_SYSTEM;
+International* ScGlobal::pScInternational = NULL;
+::com::sun::star::lang::Locale* ScGlobal::pLocale = NULL;
+CharClass* ScGlobal::pCharClass = NULL;
+sal_Unicode ScGlobal::cListDelimiter = ',';
+String* ScGlobal::pEmptyString = NULL;
+String* ScGlobal::pStrClipDocName = NULL;
+
+SvxBrushItem* ScGlobal::pEmptyBrushItem = NULL;
+SvxBrushItem* ScGlobal::pButtonBrushItem = NULL;
+SvxBrushItem* ScGlobal::pEmbeddedBrushItem = NULL;
+SvxBrushItem* ScGlobal::pProtectedBrushItem = NULL;
+
+ImageList* ScGlobal::pOutlineBitmaps = NULL;
+
+ScFunctionList* ScGlobal::pStarCalcFunctionList = NULL;
+ScFunctionMgr* ScGlobal::pStarCalcFunctionMgr = NULL;
+
+ScUnitConverter* ScGlobal::pUnitConverter = NULL;
+
+double ScGlobal::nScreenPPTX = 96.0;
+double ScGlobal::nScreenPPTY = 96.0;
+
+USHORT ScGlobal::nDefFontHeight = 240;
+USHORT ScGlobal::nStdRowHeight = 257;
+
+long ScGlobal::nLastRowHeightExtra = 0;
+long ScGlobal::nLastColWidthExtra = STD_EXTRA_WIDTH;
+
+// ... oder so?
+
+BOOL bOderSo;
+
+class SfxViewShell;
+SfxViewShell* pScActiveViewShell = NULL; //! als Member !!!!!
+USHORT nScClickMouseModifier = 0; //! dito
+USHORT nScFillModeMouseModifier = 0; //! dito
+
+// Hack: ScGlobal::GetUserList() muss InitAppOptions in der UI aufrufen,
+// damit UserList aus Cfg geladen wird
+
+void global_InitAppOptions();
+
+// -----------------------------------------------------------------------
+
+String ScTripel::GetText() const
+{
+ String aString('(');
+ aString += String::CreateFromInt32( nCol );
+ aString += ',';
+ aString += String::CreateFromInt32( nRow );
+ aString += ',';
+ aString += String::CreateFromInt32( nTab );
+ aString += ')';
+ return aString;
+}
+
+String ScTripel::GetColRowString( BOOL bAbsolute ) const
+{
+ String aString;
+ if (bAbsolute)
+ aString.Append( '$' );
+
+ if ( nCol < 26 )
+ aString.Append( (sal_Unicode) ( 'A' + nCol ) );
+ else
+ {
+ aString.Append( (sal_Unicode) ( 'A' + ( nCol / 26 ) - 1 ) );
+ aString.Append( (sal_Unicode) ( 'A' + ( nCol % 26 ) ) );
+ }
+
+ if ( bAbsolute )
+ aString.Append( '$' );
+
+ aString += String::CreateFromInt32(nRow+1);
+
+ return aString;
+}
+
+String ScRefTripel::GetRefString(ScDocument* pDoc, USHORT nActTab) const
+{
+ if ( !pDoc )
+ return EMPTY_STRING;
+ if ( nTab+1 > pDoc->GetTableCount() )
+ return ScGlobal::GetRscString( STR_NOREF_STR );
+
+ String aString;
+ if (nActTab != nTab)
+ {
+ if (!bRelTab)
+ aString += '$';
+ String aTabName;
+ pDoc->GetName(nTab, aTabName);
+ aString += aTabName;
+ aString += '.';
+ }
+
+ if (!bRelCol)
+ aString += '$';
+ if ( nCol < 26 )
+ aString += (sal_Unicode) ( 'A' + nCol );
+ else
+ {
+ aString += (sal_Unicode) ( 'A' + ( nCol / 26 ) - 1 );
+ aString += (sal_Unicode) ( 'A' + ( nCol % 26 ) );
+ }
+
+ if ( !bRelRow )
+ aString += '$';
+ aString += String::CreateFromInt32( nRow+1 );
+
+
+ return aString;
+}
+
+
+//========================================================================
+//
+// statische Funktionen
+//
+//========================================================================
+
+BOOL ScGlobal::HasAttrChanged( const SfxItemSet& rNewAttrs,
+ const SfxItemSet& rOldAttrs,
+ const USHORT nWhich )
+{
+ BOOL bInvalidate = FALSE;
+ const SfxItemState eNewState = rNewAttrs.GetItemState( nWhich );
+ const SfxItemState eOldState = rOldAttrs.GetItemState( nWhich );
+
+ //----------------------------------------------------------
+
+ if ( eNewState == eOldState )
+ {
+ // beide Items gesetzt
+ // PoolItems, d.h. Pointer-Vergleich zulaessig
+ if ( SFX_ITEM_SET == eOldState )
+ bInvalidate = (&rNewAttrs.Get( nWhich ) != &rOldAttrs.Get( nWhich ));
+ }
+ else
+ {
+ // ein Default-Item dabei
+ // PoolItems, d.h. Item-Vergleich noetig
+
+ const SfxPoolItem& rOldItem = ( SFX_ITEM_SET == eOldState )
+ ? rOldAttrs.Get( nWhich )
+ : rOldAttrs.GetPool()->GetDefaultItem( nWhich );
+
+ const SfxPoolItem& rNewItem = ( SFX_ITEM_SET == eNewState )
+ ? rNewAttrs.Get( nWhich )
+ : rNewAttrs.GetPool()->GetDefaultItem( nWhich );
+
+ bInvalidate = (rNewItem != rOldItem);
+ }
+
+ return bInvalidate;
+}
+
+ULONG ScGlobal::GetStandardFormat( SvNumberFormatter& rFormatter,
+ ULONG nFormat, short nType )
+{
+ const SvNumberformat* pFormat = rFormatter.GetEntry( nFormat );
+ if ( pFormat )
+ return rFormatter.GetStandardFormat( nFormat, nType, pFormat->GetLanguage() );
+ return rFormatter.GetStandardFormat( nType, eLnge );
+}
+
+ULONG ScGlobal::GetStandardFormat( double fNumber, SvNumberFormatter& rFormatter,
+ ULONG nFormat, short nType )
+{
+ const SvNumberformat* pFormat = rFormatter.GetEntry( nFormat );
+ if ( pFormat )
+ return rFormatter.GetStandardFormat( fNumber, nFormat, nType,
+ pFormat->GetLanguage() );
+ return rFormatter.GetStandardFormat( nType, eLnge );
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScGlobal::CheckWidthInvalidate( BOOL& bNumFormatChanged,
+ const SfxItemSet& rNewAttrs,
+ const SfxItemSet& rOldAttrs )
+{
+ // Ueberpruefen, ob Attributaenderungen in rNewAttrs gegnueber
+ // rOldAttrs die Textbreite an einer Zelle ungueltig machen
+
+ bNumFormatChanged =
+ HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_VALUE_FORMAT );
+ return ( bNumFormatChanged
+ || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_LANGUAGE_FORMAT )
+ || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT )
+ || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_HEIGHT )
+ || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_WEIGHT )
+ || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_POSTURE )
+ || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_UNDERLINE )
+ || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_CROSSEDOUT )
+ || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_CONTOUR )
+ || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_FONT_SHADOWED )
+ || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_ORIENTATION )
+ || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_ROTATE_VALUE )
+ || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_ROTATE_MODE )
+ || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_LINEBREAK )
+ || HasAttrChanged( rNewAttrs, rOldAttrs, ATTR_MARGIN )
+ );
+}
+
+ScDocument* ScGlobal::GetClipDoc()
+{
+ if (!pClipDoc)
+ pClipDoc = new ScDocument( SCDOCMODE_CLIP );
+ return pClipDoc;
+}
+
+BOOL ScGlobal::HasClipDoc()
+{
+ return (pClipDoc != 0);
+}
+
+void ScGlobal::CaptureClip()
+{
+ nClipState = CLIPST_CAPTURED;
+}
+
+void ScGlobal::SetClipDraw(SdrModel* pModel)
+{
+ pClipModel = pModel;
+ if (pClipDoc)
+ pClipDoc->Clear();
+ nClipState = CLIPST_DRAW;
+}
+
+SdrModel* ScGlobal::GetClipModel()
+{
+ return pClipModel;
+}
+
+BOOL ScGlobal::IsClipDraw()
+{
+ return ( nClipState == CLIPST_DRAW );
+}
+
+void ScGlobal::ReleaseClip()
+{
+ if (nClipState == CLIPST_DELETE)
+ {
+ DELETEZ(pClipDoc);
+ }
+ else
+ nClipState = CLIPST_AVAILABLE;
+}
+
+BOOL ScGlobal::IsClipCaptured()
+{
+ return ( nClipState == CLIPST_CAPTURED );
+}
+
+
+const SvxSearchItem& ScGlobal::GetSearchItem()
+{
+ if (!pSearchItem)
+ {
+ pSearchItem = new SvxSearchItem( SID_SEARCH_ITEM );
+ pSearchItem->SetAppFlag( SVX_SEARCHAPP_CALC );
+ }
+ return *pSearchItem;
+}
+
+void ScGlobal::SetSearchItem( const SvxSearchItem& rNew )
+{
+ // Hier waere ein Zuweisungsoperator ganz nett:
+ delete pSearchItem;
+ pSearchItem = (SvxSearchItem*)rNew.Clone();
+
+ pSearchItem->SetWhich( SID_SEARCH_ITEM );
+}
+
+void ScGlobal::ClearAutoFormat()
+{
+ if (pAutoFormat!=NULL)
+ {
+ delete pAutoFormat;
+ pAutoFormat=NULL;
+ }
+}
+
+ScAutoFormat* ScGlobal::GetAutoFormat()
+{
+ if ( !pAutoFormat )
+ {
+ pAutoFormat = new ScAutoFormat;
+ pAutoFormat->Load();
+ }
+
+ return pAutoFormat;
+}
+
+FuncCollection* ScGlobal::GetFuncCollection()
+{
+ if (!pFuncCollection)
+ pFuncCollection = new FuncCollection();
+ return pFuncCollection;
+}
+
+ScUnoAddInCollection* ScGlobal::GetAddInCollection()
+{
+ if (!pAddInCollection)
+ pAddInCollection = new ScUnoAddInCollection();
+ return pAddInCollection;
+}
+
+ScUserList* ScGlobal::GetUserList()
+{
+ // Hack: Cfg-Item an der App ggF. laden
+
+ global_InitAppOptions();
+
+ if (!pUserList)
+ pUserList = new ScUserList();
+ return pUserList;
+}
+
+void ScGlobal::SetUserList( const ScUserList* pNewList )
+{
+ if ( pNewList )
+ {
+ if ( !pUserList )
+ pUserList = new ScUserList( *pNewList );
+ else
+ *pUserList = *pNewList;
+ }
+ else
+ {
+ delete pUserList;
+ pUserList = NULL;
+ }
+}
+
+const String& ScGlobal::GetRscString( USHORT nIndex )
+{
+ DBG_ASSERT( nIndex <= STR_COUNT,
+ "-ScGlobal::GetRscString(): Index zu gross!");
+ if( !ppRscString[ nIndex ] )
+ {
+ ppRscString[ nIndex ] =
+ new String( ScRscStrLoader( RID_GLOBSTR, nIndex ).GetString() );
+ }
+ return *ppRscString[ nIndex ];
+}
+
+String ScGlobal::GetErrorString(USHORT nErrNumber)
+{
+ String sResStr;
+ switch (nErrNumber)
+ {
+ case NOVALUE : nErrNumber = STR_NV_STR; break;
+ case errNoRef : nErrNumber = STR_NO_REF_TABLE; break;
+ case errNoName : nErrNumber = STR_NO_NAME_REF; break;
+ case errDoubleRef:
+ case errNoValue : nErrNumber = STR_NO_VALUE; break;
+
+ default : sResStr = GetRscString(STR_ERROR_STR);
+ sResStr += String::CreateFromInt32( nErrNumber );
+ nErrNumber = 0;
+ break;
+ }
+ if( nErrNumber )
+ sResStr = GetRscString( nErrNumber );
+ return sResStr;
+}
+
+String ScGlobal::GetLongErrorString(USHORT nErrNumber)
+{
+ switch (nErrNumber)
+ {
+ case 0:
+ break;
+ case 1:
+ case errIllegalArgument:
+ nErrNumber = STR_LONG_ERR_ILL_ARG;
+ break;
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case errIllegalFPOperation:
+ nErrNumber = STR_LONG_ERR_ILL_FPO;
+ break;
+ case errIllegalChar:
+ nErrNumber = STR_LONG_ERR_ILL_CHAR;
+ break;
+ case errIllegalParameter:
+ nErrNumber = STR_LONG_ERR_ILL_PAR;
+ break;
+ case errSeparator:
+ nErrNumber = STR_LONG_ERR_ILL_SEP;
+ break;
+ case errPair:
+ case errPairExpected:
+ nErrNumber = STR_LONG_ERR_PAIR;
+ break;
+ case errOperatorExpected:
+ nErrNumber = STR_LONG_ERR_OP_EXP;
+ break;
+ case errVariableExpected:
+ case errParameterExpected:
+ nErrNumber = STR_LONG_ERR_VAR_EXP;
+ break;
+ case errCodeOverflow:
+ nErrNumber = STR_LONG_ERR_CODE_OVF;
+ break;
+ case errStringOverflow:
+ nErrNumber = STR_LONG_ERR_STR_OVF;
+ break;
+ case errStackOverflow:
+ case errInterpOverflow:
+ nErrNumber = STR_LONG_ERR_STACK_OVF;
+ break;
+ case errIllegalJump:
+ case errUnknownState:
+ case errUnknownVariable:
+ case errUnknownOpCode:
+ case errUnknownStackVariable:
+ case errUnknownToken:
+ case errNoCode:
+ case errDoubleRef:
+ nErrNumber = STR_LONG_ERR_SYNTAX;
+ break;
+ case errCircularReference:
+ nErrNumber = STR_LONG_ERR_CIRC_REF;
+ break;
+ case errNoConvergence:
+ nErrNumber = STR_LONG_ERR_NO_CONV;
+ break;
+ case errNoRef:
+ nErrNumber = STR_LONG_ERR_NO_REF;
+ break;
+ case errNoName:
+ nErrNumber = STR_LONG_ERR_NO_NAME;
+ break;
+ case errNoValue:
+ nErrNumber = STR_LONG_ERR_NO_VALUE;
+ break;
+ case NOVALUE:
+ nErrNumber = STR_LONG_ERR_NV;
+ break;
+ default:
+ nErrNumber = STR_ERROR_STR;
+ break;
+ }
+ String aRes( GetRscString( nErrNumber ) );
+ if( bOderSo )
+ {
+ String aOderSo( GetRscString( STR_ODER_SO ) );
+ aOderSo.SearchAndReplace( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("%s")), aRes );
+ aRes = aOderSo;
+ }
+ return aRes;
+}
+
+const String& ScGlobal::GetEmptyString()
+{
+ return *pEmptyString;
+}
+
+ImageList* ScGlobal::GetOutlineBitmaps()
+{
+ if (!pOutlineBitmaps)
+ pOutlineBitmaps = new ImageList( ScResId(RID_OUTLINEBITMAPS) );
+ return pOutlineBitmaps;
+}
+
+void ScGlobal::Init()
+{
+ pEmptyString = new String;
+
+ // Die Default-Sprache fuer Zahlenformate (ScGlobal::eLnge)
+ // muss immer LANGUAGE_SYSTEM sein
+ //! Dann kann auch die Variable raus
+ eLnge = LANGUAGE_SYSTEM;
+
+ //! Wenn Sortierung etc. von der Sprache der installierten Offfice-Version
+ //! abhaengen sollen, hier "Application::GetAppInternational().GetLanguage()"
+ pScInternational = new International(eLnge);
+ String aLanguage, aCountry;
+ ConvertLanguageToIsoNames( International::GetRealLanguage( eLnge ), aLanguage, aCountry );
+ pLocale = new ::com::sun::star::lang::Locale( aLanguage, aCountry, EMPTY_STRING );
+ pCharClass = new CharClass( *pLocale );
+
+ ppRscString = new String *[ STR_COUNT+1 ];
+ for( USHORT nC = 0 ; nC <= STR_COUNT ; nC++ ) ppRscString[ nC ] = NULL;
+
+ pEmptyBrushItem = new SvxBrushItem( Color( COL_TRANSPARENT ) );
+ pButtonBrushItem = new SvxBrushItem( Color( COL_LIGHTGRAY ) );
+ pEmbeddedBrushItem = new SvxBrushItem( Color( COL_LIGHTCYAN ) );
+ pProtectedBrushItem = new SvxBrushItem( Color( COL_LIGHTGRAY ) );
+
+ OutputDevice* pDefaultDev = Application::GetDefaultDevice();
+ Point aPix1000 = pDefaultDev->LogicToPixel( Point(1000,1000), MAP_TWIP );
+ nScreenPPTX = aPix1000.X() / 1000.0;
+ nScreenPPTY = aPix1000.Y() / 1000.0;
+ ScCompiler::Init();
+#if SOMA_FPSIGNAL_JUMP
+ ScInterpreter::pSignalFunc = SC_DLL()->GetSignalFunc();
+#endif
+ srand( (unsigned) time( NULL ) ); // Random Seed Init fuer Interpreter
+
+ InitAddIns();
+
+ pStrClipDocName = new String( ScResId( SCSTR_NONAME ) );
+ *pStrClipDocName += '1';
+
+ // ScDocumentPool::InitVersionMaps() ist schon vorher gerufen worden
+}
+
+const String& ScGlobal::GetClipDocName()
+{
+ return *pStrClipDocName;
+}
+
+void ScGlobal::SetClipDocName( const String& rNew )
+{
+ *pStrClipDocName = rNew;
+}
+
+
+void ScGlobal::InitTextHeight(SfxItemPool* pPool)
+{
+ if (!pPool)
+ {
+ DBG_ERROR("kein Pool bei ScGlobal::InitTextHeight");
+ return;
+ }
+
+ const ScPatternAttr* pPattern = (const ScPatternAttr*)&pPool->GetDefaultItem(ATTR_PATTERN);
+ if (!pPattern)
+ {
+ DBG_ERROR("kein Default-Pattern bei ScGlobal::InitTextHeight");
+ return;
+ }
+
+// String aTestString('X');
+ OutputDevice* pDefaultDev = Application::GetDefaultDevice();
+ VirtualDevice aVirtWindow( *pDefaultDev );
+ aVirtWindow.SetMapMode(MAP_PIXEL);
+ Font aDefFont;
+ pPattern->GetFont(aDefFont, &aVirtWindow);
+ aVirtWindow.SetFont(aDefFont);
+ nDefFontHeight = (USHORT) aVirtWindow.PixelToLogic(Size(0, aVirtWindow.GetTextHeight()),
+ MAP_TWIP).Height();
+
+ const SvxMarginItem* pMargin = (const SvxMarginItem*)&pPattern->GetItem(ATTR_MARGIN);
+
+ nStdRowHeight = (USHORT) ( nDefFontHeight +
+ pMargin->GetTopMargin() + pMargin->GetBottomMargin()
+ - STD_ROWHEIGHT_DIFF );
+}
+
+void ScGlobal::Clear()
+{
+ // asyncs _vor_ ExitExternalFunc zerstoeren!
+ theAddInAsyncTbl.DeleteAndDestroy( 0, theAddInAsyncTbl.Count() );
+ ExitExternalFunc();
+ DELETEZ(pEmptyString);
+ if (nClipState)
+ nClipState = CLIPST_DELETE;
+ else
+ DELETEZ(pClipDoc);
+ DELETEZ(pAutoFormat);
+ DELETEZ(pSearchItem);
+ DELETEZ(pFuncCollection);
+ DELETEZ(pAddInCollection);
+ DELETEZ(pUserList);
+
+ for( USHORT nC = 0 ; nC < STR_COUNT ; nC++ )
+ if( ppRscString ) delete ppRscString[ nC ];
+ delete[] ppRscString;
+ ppRscString = NULL;
+
+ DELETEZ(pStarCalcFunctionList); // vor ResMgr zerstoeren!
+ DELETEZ(pStarCalcFunctionMgr);
+ ScCompiler::DeInit();
+ ScInterpreter::aTableOpList.Clear();
+ ScInterpreter::GlobalExit(); // statischen Stack loeschen
+
+ DELETEZ(pEmptyBrushItem);
+ DELETEZ(pButtonBrushItem);
+ DELETEZ(pEmbeddedBrushItem);
+ DELETEZ(pProtectedBrushItem);
+ DELETEZ(pOutlineBitmaps);
+// DELETEZ(pAnchorBitmap);
+// DELETEZ(pGrayAnchorBitmap);
+ DELETEZ(pCharClass);
+ DELETEZ(pLocale);
+ DELETEZ(pScInternational);
+ DELETEZ(pStrClipDocName);
+
+ DELETEZ(pUnitConverter);
+
+ ScDocumentPool::DeleteVersionMaps();
+}
+
+//------------------------------------------------------------------------
+
+ScFunctionList* ScGlobal::GetStarCalcFunctionList()
+{
+ if ( !pStarCalcFunctionList )
+ pStarCalcFunctionList = new ScFunctionList;
+
+ return pStarCalcFunctionList;
+}
+
+//------------------------------------------------------------------------
+
+ScFunctionMgr* ScGlobal::GetStarCalcFunctionMgr()
+{
+ if ( !pStarCalcFunctionMgr )
+ pStarCalcFunctionMgr = new ScFunctionMgr;
+
+ return pStarCalcFunctionMgr;
+}
+
+//------------------------------------------------------------------------
+
+// static
+ScUnitConverter* ScGlobal::GetUnitConverter()
+{
+ if ( !pUnitConverter )
+ pUnitConverter = new ScUnitConverter;
+
+ return pUnitConverter;
+}
+
+
+//------------------------------------------------------------------------
+
+// static
+const sal_Unicode* ScGlobal::UnicodeStrChr( const sal_Unicode* pStr,
+ sal_Unicode c )
+{
+ if ( !pStr )
+ return NULL;
+ while ( *pStr )
+ {
+ if ( *pStr == c )
+ return pStr;
+ pStr++;
+ }
+ return NULL;
+}
+
+
+//------------------------------------------------------------------------
+
+BOOL ScGlobal::EETextObjEqual( const EditTextObject* pObj1,
+ const EditTextObject* pObj2 )
+{
+ BOOL bEqual = ( pObj1 == pObj2 ); // beide leer oder selbes Objekt
+
+ if ( !bEqual && pObj1 && pObj2 )
+ {
+ SvMemoryStream aStream1;
+ SvMemoryStream aStream2;
+ pObj1->Store( aStream1 );
+ pObj2->Store( aStream2 );
+ ULONG nSize = aStream1.Tell();
+ if ( aStream2.Tell() == nSize )
+ if ( !memcmp( aStream1.GetData(), aStream2.GetData(), (USHORT) nSize ) )
+ bEqual = TRUE;
+ }
+
+ return bEqual;
+}
+
+void ScGlobal::OpenURL( const String& rURL, const String& rTarget )
+{
+ // OpenURL wird immer ueber irgendwelche Umwege durch Mausklicks im GridWindow
+ // aufgerufen, darum stimmen pScActiveViewShell und nScClickMouseModifier.
+
+ SfxStringItem aUrl( SID_FILE_NAME, rURL );
+ SfxStringItem aTarget( SID_TARGETNAME, rTarget );
+
+ if ( nScClickMouseModifier & KEY_MOD1 ) // control-click -> into new window
+ aTarget.SetValue(
+ String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("_blank")) );
+
+ SfxViewFrame* pFrame = NULL;
+ String aReferName;
+ if ( pScActiveViewShell )
+ {
+ pFrame = pScActiveViewShell->GetViewFrame();
+ SfxMedium* pMed = pFrame->GetObjectShell()->GetMedium();
+ if (pMed)
+ aReferName = pMed->GetName();
+ }
+
+ SfxFrameItem aFrm( SID_DOCFRAME, pFrame );
+ SfxStringItem aReferer( SID_REFERER, aReferName );
+
+ SfxBoolItem aNewView( SID_OPEN_NEW_VIEW, FALSE );
+ SfxBoolItem aBrowsing( SID_BROWSING, TRUE );
+
+ // kein SID_SILENT mehr wegen Bug #42525# (war angeblich sowieso falsch)
+
+ SFX_DISPATCHER().Execute( SID_OPENDOC, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD,
+ &aUrl, &aTarget,
+ &aFrm, &aReferer,
+ &aNewView, &aBrowsing,
+ 0L );
+}
+
+
+//===================================================================
+// class ScFormulaUtil - statische Methoden
+//===================================================================
+
+ScFuncDesc aDefaultFuncDesc;
+
+const ScFuncDesc* ScFormulaUtil::GetDefaultFuncDesc()
+{
+ return &aDefaultFuncDesc;
+}
+
+BOOL ScFormulaUtil::GetNextFunc( const String& rFormula,
+ BOOL bBack,
+ xub_StrLen& rFStart, // Ein- und Ausgabe
+ xub_StrLen* pFEnd, // = NULL
+ ScFuncDesc** ppFDesc, // = NULL
+ String*** pppArgs ) // = NULL
+{
+ BOOL bFound = FALSE;
+ xub_StrLen nOldStart = rFStart;
+ String aFname;
+
+ rFStart = GetFunctionStart( rFormula, rFStart, bBack, ppFDesc ? &aFname : NULL );
+ bFound = ( rFStart != FUNC_NOTFOUND );
+
+ if ( bFound )
+ {
+ if ( pFEnd )
+ *pFEnd = GetFunctionEnd( rFormula, rFStart );
+
+ if ( ppFDesc )
+ {
+ ScFunctionMgr* pFuncMgr = ScGlobal::GetStarCalcFunctionMgr();
+ *ppFDesc = pFuncMgr->Get( aFname );
+ if ( *ppFDesc )
+ {
+ if (pppArgs)
+ *pppArgs = GetArgStrings( rFormula, rFStart, (*ppFDesc)->nArgCount );
+ }
+ else
+ {
+ *ppFDesc = &aDefaultFuncDesc;
+ }
+ }
+ }
+ else
+ rFStart = nOldStart;
+
+ return bFound;
+}
+
+//------------------------------------------------------------------------
+
+void ScFormulaUtil::FillArgStrings( const String& rFormula,
+ xub_StrLen nFuncPos,
+ USHORT nArgs,
+ String** aArgArr )
+{
+ if ( !aArgArr ) return;
+
+ xub_StrLen nStart = 0;
+ xub_StrLen nEnd = 0;
+ USHORT i;
+ BOOL bLast = FALSE;
+
+ for ( i=0; i<nArgs && !bLast; i++ )
+ {
+ nStart = GetArgStart( rFormula, nFuncPos, i );
+
+ if ( i+1<nArgs ) // letztes Argument?
+ {
+ nEnd = GetArgStart( rFormula, nFuncPos, i+1 );
+
+ if ( nEnd != nStart )
+ aArgArr[i] = new String( rFormula.Copy( nStart, nEnd-1-nStart ) );
+ else
+ aArgArr[i] = new String, bLast = TRUE;
+ }
+ else
+ {
+ nEnd = GetFunctionEnd( rFormula, nFuncPos )-1;
+ if ( nStart < nEnd )
+ aArgArr[i] = new String( rFormula.Copy( nStart, nEnd-nStart ) );
+ else
+ aArgArr[i] = new String;
+ }
+ }
+
+ if ( bLast )
+ for ( ; i<nArgs; i++ )
+ aArgArr[i] = new String;
+}
+
+//------------------------------------------------------------------------
+
+String** ScFormulaUtil::GetArgStrings( const String& rFormula,
+ xub_StrLen nFuncPos,
+ USHORT nArgs )
+{
+ String** aArgArr = NULL;
+ if (nArgs)
+ {
+ aArgArr = new String*[nArgs];
+ FillArgStrings( rFormula, nFuncPos, nArgs, aArgArr );
+ }
+ return aArgArr;
+}
+
+//------------------------------------------------------------------------
+
+inline BOOL IsFormulaText( const String& rStr, xub_StrLen nPos )
+{
+ // In internationalized versions function names may contain a dot
+
+ return ScGlobal::pCharClass->isLetterNumeric( rStr, nPos ) ||
+ rStr.GetChar(nPos) == '.';
+}
+
+xub_StrLen ScFormulaUtil::GetFunctionStart( const String& rFormula,
+ xub_StrLen nStart,
+ BOOL bBack,
+ String* pFuncName )
+{
+ xub_StrLen nStrLen = rFormula.Len();
+
+ if ( nStrLen < nStart )
+ return nStart;
+
+ xub_StrLen nFStart = FUNC_NOTFOUND;
+ xub_StrLen nParPos = nStart;
+
+ BOOL bRepeat, bFound;
+ do
+ {
+ bFound = FALSE;
+ bRepeat = FALSE;
+
+ if ( bBack )
+ {
+ while ( !bFound && (nParPos > 0) )
+ {
+ if ( rFormula.GetChar(nParPos) == '"' )
+ {
+ nParPos--;
+ while ( (nParPos > 0) && rFormula.GetChar(nParPos) != '"' )
+ nParPos--;
+ if (nParPos > 0)
+ nParPos--;
+ }
+ else if ( !(bFound = ( rFormula.GetChar(nParPos) == '(' ) ) )
+ nParPos--;
+ }
+ }
+ else
+ {
+ while ( !bFound && (nParPos < nStrLen) )
+ {
+ if ( rFormula.GetChar(nParPos) == '"' )
+ {
+ nParPos++;
+ while ( (nParPos < nStrLen) && rFormula.GetChar(nParPos) != '"' )
+ nParPos++;
+ nParPos++;
+ }
+ else if ( !(bFound = ( rFormula.GetChar(nParPos) == '(' ) ) )
+ nParPos++;
+ }
+ }
+
+ if ( bFound && (nParPos > 0) )
+ {
+ nFStart = nParPos-1;
+
+ while ( (nFStart > 0) && IsFormulaText( rFormula, nFStart ))
+ nFStart--;
+ }
+
+ nFStart++;
+
+ if ( bFound )
+ {
+ if ( IsFormulaText( rFormula, nFStart ) )
+ {
+ // Funktion gefunden
+ if ( pFuncName )
+ *pFuncName = rFormula.Copy( nFStart, nParPos-nFStart );
+ }
+ else // Klammern ohne Funktion -> weitersuchen
+ {
+ bRepeat = TRUE;
+ if ( !bBack )
+ nParPos++;
+ else if (nParPos > 0)
+ nParPos--;
+ else
+ bRepeat = FALSE;
+ }
+ }
+ else // keine Klammern gefunden
+ {
+ nFStart = FUNC_NOTFOUND;
+ if ( pFuncName )
+ pFuncName->Erase();
+ }
+ }
+ while(bRepeat);
+
+ return nFStart;
+}
+
+//------------------------------------------------------------------------
+
+xub_StrLen ScFormulaUtil::GetFunctionEnd( const String& rStr, xub_StrLen nStart )
+{
+ xub_StrLen nStrLen = rStr.Len();
+
+ if ( nStrLen < nStart )
+ return nStart;
+
+ short nParCount = 0;
+ BOOL bFound = FALSE;
+
+ while ( !bFound && (nStart < nStrLen) )
+ {
+ sal_Unicode c = rStr.GetChar(nStart);
+
+ if ( c == '"' )
+ {
+ nStart++;
+ while ( (nStart < nStrLen) && rStr.GetChar(nStart) != '"' )
+ nStart++;
+ }
+ else if ( c == '(' )
+ nParCount++;
+ else if ( c == ')' )
+ {
+ nParCount--;
+ if ( nParCount == 0 )
+ bFound = TRUE;
+ else if ( nParCount < 0 )
+ {
+ bFound = TRUE;
+ nStart--; // einen zu weit gelesen
+ }
+ }
+ else if ( c == ';' )
+ {
+ if ( nParCount == 0 )
+ {
+ bFound = TRUE;
+ nStart--; // einen zu weit gelesen
+ }
+ }
+ nStart++; // hinter gefundene Position stellen
+ }
+
+ return nStart;
+}
+
+//------------------------------------------------------------------
+
+xub_StrLen ScFormulaUtil::GetArgStart( const String& rStr, xub_StrLen nStart, USHORT nArg )
+{
+ xub_StrLen nStrLen = rStr.Len();
+
+ if ( nStrLen < nStart )
+ return nStart;
+
+ short nParCount = 0;
+ short nSemiCount = 0;
+ BOOL bFound = FALSE;
+
+ while ( !bFound && (nStart < nStrLen) )
+ {
+ sal_Unicode c = rStr.GetChar(nStart);
+
+ if ( c == '"' )
+ {
+ nStart++;
+ while ( (nStart < nStrLen) && rStr.GetChar(nStart) != '"' )
+ nStart++;
+ }
+ else if ( c == '(' )
+ {
+ bFound = ( nArg == 0 );
+ nParCount++;
+ }
+ else if ( c == ')' )
+ {
+ nParCount--;
+ bFound = ( nParCount == 0 );
+ }
+ else if ( c == ';' )
+ {
+ if ( nParCount == 1 )
+ {
+ nArg--;
+ bFound = ( nArg == 0 );
+ }
+ }
+ nStart++;
+ }
+
+ return nStart;
+}
+
+
+//===================================================================
+// class ScFunctionList:
+//===================================================================
+
+//===================================================================
+// class ScFuncRes
+// fuer temporaere Objekte zum Holen der Resourcen
+
+class ScFuncRes : public Resource
+{
+public:
+ ScFuncRes( ResId&, ScFuncDesc* );
+
+private:
+ USHORT GetNum();
+};
+
+//--------------------------------------------------------------------
+
+ScFuncRes::ScFuncRes( ResId &aRes, ScFuncDesc* pDesc )
+ : Resource(aRes)
+{
+ USHORT nArgs;
+
+ pDesc->nCategory = 1;
+ pDesc->nCategory = GetNum();
+ pDesc->nHelpId = GetNum() + 32768; //! Hack, siehe ScFuncs.src
+ pDesc->nArgCount = GetNum();
+ nArgs = pDesc->nArgCount;
+ if (nArgs >= VAR_ARGS) nArgs = nArgs-VAR_ARGS+1;
+ if (nArgs)
+ {
+ pDesc->aDefArgOpt = new BOOL[nArgs];
+ for (USHORT i = 0; i < nArgs; i++)
+ pDesc->aDefArgOpt[i] = (BOOL)GetNum();
+ }
+
+ pDesc->pFuncName = new String( ScCompiler::pSymbolTableNative[aRes.GetId()] );
+ pDesc->pFuncDesc = new String(ScResId(1));
+
+ if (nArgs)
+ {
+ pDesc->aDefArgNames = new String*[nArgs];
+ pDesc->aDefArgDescs = new String*[nArgs];
+ for (USHORT i = 0; i < nArgs; i++)
+ {
+ pDesc->aDefArgNames[i] = new String(ScResId(2*(i+1) ));
+ pDesc->aDefArgDescs[i] = new String(ScResId(2*(i+1)+1));
+ }
+ }
+
+ FreeResource();
+}
+
+//------------------------------------------------------------------------
+
+USHORT ScFuncRes::GetNum()
+{
+ return ReadShortRes();
+}
+
+//=========================================================================
+
+// um an die protected von Resource ranzukommen
+class ScResourcePublisher : public Resource
+{
+public:
+ ScResourcePublisher( const ScResId& rId ) : Resource( rId ) {}
+ BOOL IsAvailableRes( const ResId& rId ) const
+ { return Resource::IsAvailableRes( rId ); }
+ void FreeResource() { Resource::FreeResource(); }
+};
+
+
+ScFunctionList::ScFunctionList() :
+ nMaxFuncNameLen ( 0 )
+{
+ ScFuncDesc* pDesc = NULL;
+ xub_StrLen nStrLen = 0;
+ FuncCollection* pFuncColl;
+ USHORT i,j;
+ USHORT nDescBlock[] =
+ {
+ RID_SC_FUNCTION_DESCRIPTIONS1,
+ RID_SC_FUNCTION_DESCRIPTIONS2
+ };
+ const USHORT nBlocks = sizeof(nDescBlock) / sizeof(USHORT);
+
+ aFunctionList.Clear();
+
+ for ( USHORT k = 0; k < nBlocks; k++ )
+ {
+ ScResourcePublisher* pBlock =
+ new ScResourcePublisher( ScResId( nDescBlock[k] ) );
+ for (i = 0; i <= SC_OPCODE_LAST_OPCODE_ID; i++)
+ { // Alle moeglichen OpCodes abgrasen.
+ // Das ist zwar nicht das schnellste, aber sonst muessten
+ // die Sub-Ressources innerhalb der Ressource-Bloecke und die
+ // Ressource-Bloecke selber nach OpCodes geordnet sein,
+ // was wohl eher utopisch ist..
+ ScResId aRes(i);
+ aRes.SetRT(RSC_RESOURCE);
+ if (pBlock->IsAvailableRes(aRes))
+ { // Subresource fuer OpCode vorhanden
+ pDesc = new ScFuncDesc;
+ ScFuncRes aSubRes(aRes, pDesc);
+ pDesc->nFIndex = i;
+ aFunctionList.Insert( pDesc, LIST_APPEND );
+
+ nStrLen = (*(pDesc->pFuncName)).Len();
+ if (nStrLen > nMaxFuncNameLen)
+ nMaxFuncNameLen = nStrLen;
+ }
+ }
+ pBlock->FreeResource();
+ delete pBlock;
+ }
+
+ USHORT nNextId = SC_OPCODE_LAST_OPCODE_ID + 1; // FuncID for AddIn functions
+
+ // Auswertung AddIn-Liste
+ String aDefArgNameValue = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("value"));
+ String aDefArgNameString = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("string"));
+ String aDefArgNameValues = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("values"));
+ String aDefArgNameStrings = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("strings"));
+ String aDefArgNameCells = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("cells"));
+ String aDefArgNameNone = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("none"));
+ String aDefArgDescValue = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("a value"));
+ String aDefArgDescString = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("a string"));
+ String aDefArgDescValues = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("array of values"));
+ String aDefArgDescStrings = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("array of strings"));
+ String aDefArgDescCells = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("range of cells"));
+ String aDefArgDescNone = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("none"));
+ String aArgName, aArgDesc;
+ pFuncColl = ScGlobal::GetFuncCollection();
+ for (i = 0; i < pFuncColl->GetCount(); i++)
+ {
+ pDesc = new ScFuncDesc;
+ FuncData *pAddInFuncData = (FuncData*)pFuncColl->At(i);
+ USHORT nArgs = pAddInFuncData->GetParamCount() - 1;
+ pAddInFuncData->GetParamDesc( aArgName, aArgDesc, 0 );
+ pDesc->nFIndex = nNextId++; // ??? OpCode vergeben
+ pDesc->nCategory = ID_FUNCTION_GRP_ADDINS;
+ pDesc->pFuncName = new String(pAddInFuncData->GetInternalName());
+ pDesc->pFuncName->ToUpperAscii();
+ pDesc->pFuncDesc = new String( aArgDesc );
+ *(pDesc->pFuncDesc) += '\n';
+ pDesc->pFuncDesc->AppendAscii(RTL_CONSTASCII_STRINGPARAM( "( AddIn: " ));
+ *(pDesc->pFuncDesc) += pAddInFuncData->GetModuleName();
+ pDesc->pFuncDesc->AppendAscii(RTL_CONSTASCII_STRINGPARAM( " )" ));
+ pDesc->nArgCount = nArgs;
+ if (nArgs)
+ {
+ pDesc->aDefArgOpt = new BOOL[nArgs];
+ pDesc->aDefArgNames = new String*[nArgs];
+ pDesc->aDefArgDescs = new String*[nArgs];
+ for (j = 0; j < nArgs; j++)
+ {
+ pDesc->aDefArgOpt[j] = FALSE;
+ pAddInFuncData->GetParamDesc( aArgName, aArgDesc, j+1 );
+ if ( aArgName.Len() )
+ pDesc->aDefArgNames[j] = new String( aArgName );
+ else
+ {
+ switch (pAddInFuncData->GetParamType(j+1))
+ {
+ case PTR_DOUBLE:
+ pDesc->aDefArgNames[j] = new String( aDefArgNameValue );
+ break;
+ case PTR_STRING:
+ pDesc->aDefArgNames[j] = new String( aDefArgNameString );
+ break;
+ case PTR_DOUBLE_ARR:
+ pDesc->aDefArgNames[j] = new String( aDefArgNameValues );
+ break;
+ case PTR_STRING_ARR:
+ pDesc->aDefArgNames[j] = new String( aDefArgNameStrings );
+ break;
+ case PTR_CELL_ARR:
+ pDesc->aDefArgNames[j] = new String( aDefArgNameCells );
+ break;
+ default:
+ pDesc->aDefArgNames[j] = new String( aDefArgNameNone );
+ break;
+ }
+ }
+ if ( aArgDesc.Len() )
+ pDesc->aDefArgDescs[j] = new String( aArgDesc );
+ else
+ {
+ switch (pAddInFuncData->GetParamType(j+1))
+ {
+ case PTR_DOUBLE:
+ pDesc->aDefArgDescs[j] = new String( aDefArgDescValue );
+ break;
+ case PTR_STRING:
+ pDesc->aDefArgDescs[j] = new String( aDefArgDescString );
+ break;
+ case PTR_DOUBLE_ARR:
+ pDesc->aDefArgDescs[j] = new String( aDefArgDescValues );
+ break;
+ case PTR_STRING_ARR:
+ pDesc->aDefArgDescs[j] = new String( aDefArgDescStrings );
+ break;
+ case PTR_CELL_ARR:
+ pDesc->aDefArgDescs[j] = new String( aDefArgDescCells );
+ break;
+ default:
+ pDesc->aDefArgDescs[j] = new String( aDefArgDescNone );
+ break;
+ }
+ }
+ }
+ }
+// pDesc->nHelpId = 0;
+
+ aFunctionList.Insert(pDesc, LIST_APPEND);
+ nStrLen = (*(pDesc->pFuncName)).Len();
+ if ( nStrLen > nMaxFuncNameLen)
+ nMaxFuncNameLen = nStrLen;
+ }
+
+ // StarOne AddIns
+
+ ScUnoAddInCollection* pUnoAddIns = ScGlobal::GetAddInCollection();
+ long nUnoCount = pUnoAddIns->GetFuncCount();
+ for (long nFunc=0; nFunc<nUnoCount; nFunc++)
+ {
+ pDesc = new ScFuncDesc;
+ pDesc->nFIndex = nNextId++;
+
+ if ( pUnoAddIns->FillFunctionDesc( nFunc, *pDesc ) )
+ {
+ aFunctionList.Insert(pDesc, LIST_APPEND);
+ nStrLen = (*(pDesc->pFuncName)).Len();
+ if (nStrLen > nMaxFuncNameLen)
+ nMaxFuncNameLen = nStrLen;
+ }
+ else
+ delete pDesc;
+ }
+}
+
+//------------------------------------------------------------------------
+
+ScFunctionList::~ScFunctionList()
+{
+ ScFuncDesc* pDesc = (ScFuncDesc*)aFunctionList.First();
+ while (pDesc)
+ {
+ delete pDesc;
+ pDesc = (ScFuncDesc*)aFunctionList.Next();
+ }
+}
+
+
+//========================================================================
+// class ScFuncDesc:
+
+ScFuncDesc::ScFuncDesc()
+ : nFIndex (0),
+ nCategory (0),
+ pFuncName (NULL),
+ pFuncDesc (NULL),
+ nArgCount (0),
+ aDefArgNames (NULL),
+ aDefArgDescs (NULL),
+ aDefArgOpt (NULL),
+ nHelpId (0)
+{}
+
+//------------------------------------------------------------------------
+
+ScFuncDesc::~ScFuncDesc()
+{
+ USHORT nArgs;
+
+ nArgs = nArgCount;
+ if (nArgs >= VAR_ARGS) nArgs -= VAR_ARGS-1;
+ if (nArgs)
+ {
+ for (USHORT i=0; i<nArgs; i++ )
+ {
+ delete aDefArgNames[i];
+ delete aDefArgDescs[i];
+ }
+ delete [] aDefArgNames;
+ delete [] aDefArgDescs;
+ delete [] aDefArgOpt;
+ }
+ if(pFuncName)
+ delete pFuncName;
+
+ if(pFuncDesc)
+ delete pFuncDesc;
+}
+
+//------------------------------------------------------------------------
+
+String ScFuncDesc::GetSignature() const
+{
+ String aSig;
+
+ if(pFuncName)
+ {
+ aSig = *pFuncName;
+ if ( nArgCount > 0 )
+ {
+ aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "( " ));
+ if ( nArgCount < VAR_ARGS )
+ {
+ for ( USHORT i=0; i<nArgCount; i++ )
+ {
+ aSig += *(aDefArgNames[i]);
+ if ( i != nArgCount-1 )
+ aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "; " ));
+ }
+ }
+ else
+ {
+ USHORT nFix = nArgCount - VAR_ARGS;
+ for ( USHORT nArg = 0; nArg < nFix; nArg++ )
+ {
+ aSig += *(aDefArgNames[nArg]);
+ aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "; " ));
+ }
+ aSig += *(aDefArgNames[nFix]);
+ aSig += '1';
+ aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "; " ));
+ aSig += *(aDefArgNames[nFix]);
+ aSig += '2';
+ aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "; ... " ));
+ }
+
+ aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " )" ));
+ }
+ else
+ aSig.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "()" ));
+ }
+ return aSig;
+}
+
+//------------------------------------------------------------------------
+
+String ScFuncDesc::GetFormulaString( String** aArgArr ) const
+{
+ String aFormula;
+
+ if(pFuncName)
+ {
+ aFormula= *pFuncName;
+
+ aFormula += '(';
+
+ if ( nArgCount > 0 && aArgArr )
+ {
+ BOOL bLastArg = ( aArgArr[0]->Len() == 0 );
+
+ if ( !bLastArg )
+ {
+ for ( USHORT i=0; i<nArgCount && !bLastArg; i++ )
+ {
+ aFormula += *(aArgArr[i]);
+
+ if ( i < (nArgCount-1) )
+ {
+ bLastArg = !( aArgArr[i+1]->Len() > 0 );
+ if ( !bLastArg )
+ aFormula += ';';
+ }
+ }
+ }
+ }
+
+ aFormula += ')';
+ }
+ return aFormula;
+}
+
+//========================================================================
+// class ScFunctionMgr:
+
+ScFunctionMgr::ScFunctionMgr()
+ : pFuncList ( ScGlobal::GetStarCalcFunctionList() ),
+ pCurCatList ( NULL )
+{
+ DBG_ASSERT( pFuncList, "Funktionsliste nicht gefunden." );
+ ULONG nCount = pFuncList->GetCount();
+ ScFuncDesc* pDesc;
+ List* pRootList;
+ ULONG n;
+
+ for ( USHORT i=0; i<MAX_FUNCCAT; i++ ) // Kategorie-Listen erstellen
+ aCatLists[i] = new List;
+
+ pRootList = aCatLists[0]; // Gesamtliste ("Alle") erstellen
+ for ( n=0; n<nCount; n++ )
+ {
+ ULONG nTmpCnt=0;
+ pDesc = pFuncList->GetFunction(n);
+ for (nTmpCnt = 0; nTmpCnt < n; nTmpCnt++)
+ {
+ // ist zwar case-sensitiv, aber Umlaute muessen richtig einsortiert werden
+
+ ScFuncDesc* pTmpDesc = (ScFuncDesc*)pRootList->GetObject(nTmpCnt);
+ if ( ScGlobal::pScInternational->Compare(
+ *pDesc->pFuncName, *pTmpDesc->pFuncName ) == COMPARE_LESS )
+ break;
+ }
+ pRootList->Insert(pDesc, nTmpCnt); // Einsortieren
+ }
+
+ for ( n=0; n<nCount; n++ ) // in Gruppenlisten kopieren
+ {
+ pDesc = (ScFuncDesc*)pRootList->GetObject(n);
+ DBG_ASSERT((pDesc->nCategory) < MAX_FUNCCAT, "Unbekannte Kategorie");
+ if ((pDesc->nCategory) < MAX_FUNCCAT)
+ aCatLists[pDesc->nCategory]->Insert(pDesc, LIST_APPEND);
+ }
+}
+
+//------------------------------------------------------------------------
+
+ScFunctionMgr::~ScFunctionMgr()
+{
+ for (USHORT i = 0; i < MAX_FUNCCAT; i++)
+ delete aCatLists[i];
+// delete pFuncList; // Macht später die App
+}
+
+//------------------------------------------------------------------------
+
+ScFuncDesc* ScFunctionMgr::Get( const String& rFName )
+{
+ ScFuncDesc* pDesc = NULL;
+ if (rFName.Len() <= pFuncList->GetMaxFuncNameLen())
+ for (pDesc = First(0); pDesc; pDesc = Next())
+ if (rFName.EqualsIgnoreCaseAscii(*(pDesc->pFuncName)))
+ break;
+ return pDesc;
+}
+
+//------------------------------------------------------------------------
+
+ScFuncDesc* ScFunctionMgr::Get( USHORT nFIndex )
+{
+ ScFuncDesc* pDesc;
+ for (pDesc = First(0); pDesc; pDesc = Next())
+ if (pDesc->nFIndex == nFIndex)
+ break;
+ return pDesc;
+}
+
+//------------------------------------------------------------------------
+
+ScFuncDesc* ScFunctionMgr::First( USHORT nCategory )
+{
+ DBG_ASSERT( nCategory < MAX_FUNCCAT, "Unbekannte Kategorie" );
+
+ if ( nCategory < MAX_FUNCCAT )
+ {
+ pCurCatList = aCatLists[nCategory];
+ return (ScFuncDesc*)pCurCatList->First();
+ }
+ else
+ {
+ pCurCatList = NULL;
+ return NULL;
+ }
+}
+
+//------------------------------------------------------------------------
+
+ScFuncDesc* ScFunctionMgr::Next()
+{
+ if ( pCurCatList )
+ return (ScFuncDesc*)pCurCatList->Next();
+ else
+ return NULL;
+}
+
+//------------------------------------------------------------------------
+
+String ColToAlpha( const USHORT nCol )
+{
+ String aStr;
+
+ if ( nCol < 26 )
+ aStr = (sal_Unicode) ( 'A' + nCol );
+ else
+ {
+ aStr = (sal_Unicode) ( 'A' + ( nCol / 26 ) - 1 );
+ aStr += (sal_Unicode) ( 'A' + ( nCol % 26 ) );
+ }
+
+ return aStr;
+}
+
+CharSet GetCharsetValue(const String& rCharSet)
+{
+ if (rCharSet.EqualsIgnoreCaseAscii("ANSI") ) return RTL_TEXTENCODING_MS_1252;
+ else if (rCharSet.EqualsIgnoreCaseAscii("MAC") ) return RTL_TEXTENCODING_APPLE_ROMAN;
+ else if (rCharSet.EqualsIgnoreCaseAscii("IBMPC") ) return RTL_TEXTENCODING_IBM_850;
+ else if (rCharSet.EqualsIgnoreCaseAscii("IBMPC_437")) return RTL_TEXTENCODING_IBM_437;
+ else if (rCharSet.EqualsIgnoreCaseAscii("IBMPC_850")) return RTL_TEXTENCODING_IBM_850;
+ else if (rCharSet.EqualsIgnoreCaseAscii("IBMPC_860")) return RTL_TEXTENCODING_IBM_860;
+ else if (rCharSet.EqualsIgnoreCaseAscii("IBMPC_861")) return RTL_TEXTENCODING_IBM_861;
+ else if (rCharSet.EqualsIgnoreCaseAscii("IBMPC_863")) return RTL_TEXTENCODING_IBM_863;
+ else if (rCharSet.EqualsIgnoreCaseAscii("IBMPC_865")) return RTL_TEXTENCODING_IBM_865;
+// else if (rCharSet.EqualsIgnoreCaseAscii("SYSTEM") ) return gsl_getSystemTextEncoding();
+ else return gsl_getSystemTextEncoding();
+}
+
+
+
+
diff --git a/sc/source/core/data/global2.cxx b/sc/source/core/data/global2.cxx
new file mode 100644
index 000000000000..bc065a189793
--- /dev/null
+++ b/sc/source/core/data/global2.cxx
@@ -0,0 +1,1993 @@
+/*************************************************************************
+ *
+ * $RCSfile: global2.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <sfx2/docfile.hxx>
+#include <sfx2/inimgr.hxx>
+#include <sfx2/objsh.hxx>
+#include <sdb/sdbstat.hxx> // enum DBObject
+#include <svtools/txtcmp.hxx>
+#include <tools/intn.hxx>
+#include <unotools/charclass.hxx>
+#include <stdlib.h>
+#include <ctype.h>
+
+
+#include "global.hxx"
+#include "document.hxx"
+#include "rangeutl.hxx"
+#include "pivot.hxx"
+#include "rechead.hxx"
+#include "compiler.hxx"
+
+#include "sc.hrc"
+#include "globstr.hrc"
+
+
+// -----------------------------------------------------------------------
+
+
+
+#define MAX_LABELS 256 //!!! aus fieldwnd.hxx, muss noch nach global.hxx ???
+
+//------------------------------------------------------------------------
+// struct ScImportParam:
+
+ScImportParam::ScImportParam() :
+ nCol1(0),
+ nRow1(0),
+ nCol2(0),
+ nRow2(0),
+ bImport(FALSE),
+ bNative(FALSE),
+ bSql(TRUE),
+ nType(dbTable)
+{
+}
+
+ScImportParam::ScImportParam( const ScImportParam& r ) :
+ nCol1 (r.nCol1),
+ nRow1 (r.nRow1),
+ nCol2 (r.nCol2),
+ nRow2 (r.nRow2),
+ bImport (r.bImport),
+ aDBName (r.aDBName),
+ aStatement (r.aStatement),
+ bNative (r.bNative),
+ bSql (r.bSql),
+ nType (r.nType)
+{
+}
+
+ScImportParam::~ScImportParam()
+{
+}
+
+void ScImportParam::Clear()
+{
+ nCol1=nRow1=nCol2=nRow2 = 0;
+ bImport = FALSE;
+ bNative = FALSE;
+ bSql = TRUE;
+ nType = dbTable;
+ aDBName.Erase();
+ aStatement.Erase();
+}
+
+ScImportParam& ScImportParam::operator=( const ScImportParam& r )
+{
+ nCol1 = r.nCol1;
+ nRow1 = r.nRow1;
+ nCol2 = r.nCol2;
+ nRow2 = r.nRow2;
+ bImport = r.bImport;
+ aDBName = r.aDBName;
+ aStatement = r.aStatement;
+ bNative = r.bNative;
+ bSql = r.bSql;
+ nType = r.nType;
+
+ return *this;
+}
+
+BOOL ScImportParam::operator==( const ScImportParam& rOther ) const
+{
+ return( nCol1 == rOther.nCol1 &&
+ nRow1 == rOther.nRow1 &&
+ nCol2 == rOther.nCol2 &&
+ nRow2 == rOther.nRow2 &&
+ bImport == rOther.bImport &&
+ aDBName == rOther.aDBName &&
+ aStatement == rOther.aStatement &&
+ bNative == rOther.bNative &&
+ bSql == rOther.bSql &&
+ nType == rOther.nType );
+
+ //! nQuerySh und pConnection sind gleich ?
+}
+
+
+//========================================================================
+//========================================================================
+// Evtl. in dbdata.cxx auslagern (?):
+
+//------------------------------------------------------------------------
+// struct ScSortParam:
+
+ScSortParam::ScSortParam()
+{
+ Clear();
+}
+
+//------------------------------------------------------------------------
+
+ScSortParam::ScSortParam( const ScSortParam& r ) :
+ nCol1(r.nCol1),nRow1(r.nRow1),nCol2(r.nCol2),nRow2(r.nRow2),
+ bHasHeader(r.bHasHeader),bCaseSens(r.bCaseSens),
+ bByRow(r.bByRow),bUserDef(r.bUserDef),nUserIndex(r.nUserIndex),bIncludePattern(r.bIncludePattern),
+ bInplace(r.bInplace),
+ nDestTab(r.nDestTab),nDestCol(r.nDestCol),nDestRow(r.nDestRow)
+{
+ for (USHORT i=0; i<MAXSORT; i++)
+ {
+ bDoSort[i] = r.bDoSort[i];
+ nField[i] = r.nField[i];
+ bAscending[i] = r.bAscending[i];
+ }
+}
+
+//------------------------------------------------------------------------
+
+void ScSortParam::Clear()
+{
+ nCol1=nRow1=nCol2=nRow2=nDestTab=nDestCol=nDestRow=nUserIndex = 0;
+ bHasHeader=bCaseSens=bUserDef = FALSE;
+ bByRow=bIncludePattern=bInplace = TRUE;
+
+ for (USHORT i=0; i<MAXSORT; i++)
+ {
+ bDoSort[i] = FALSE;
+ nField[i] = 0;
+ bAscending[i] = TRUE;
+ }
+}
+
+//------------------------------------------------------------------------
+
+ScSortParam& ScSortParam::operator=( const ScSortParam& r )
+{
+ nCol1 = r.nCol1;
+ nRow1 = r.nRow1;
+ nCol2 = r.nCol2;
+ nRow2 = r.nRow2;
+ bHasHeader = r.bHasHeader;
+ bCaseSens = r.bCaseSens;
+ bByRow = r.bByRow;
+ bUserDef = r.bUserDef;
+ nUserIndex = r.nUserIndex;
+ bIncludePattern = r.bIncludePattern;
+ bInplace = r.bInplace;
+ nDestTab = r.nDestTab;
+ nDestCol = r.nDestCol;
+ nDestRow = r.nDestRow;
+
+ for (USHORT i=0; i<MAXSORT; i++)
+ {
+ bDoSort[i] = r.bDoSort[i];
+ nField[i] = r.nField[i];
+ bAscending[i] = r.bAscending[i];
+ }
+
+ return *this;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScSortParam::operator==( const ScSortParam& rOther ) const
+{
+ BOOL bEqual = FALSE;
+ // Anzahl der Sorts gleich?
+ USHORT nLast = 0;
+ USHORT nOtherLast = 0;
+ while ( bDoSort[nLast++] && nLast < MAXSORT );
+ while ( rOther.bDoSort[nOtherLast++] && nOtherLast < MAXSORT );
+ nLast--;
+ nOtherLast--;
+ if ( (nLast == nOtherLast)
+ && (nCol1 == rOther.nCol1)
+ && (nRow1 == rOther.nRow1)
+ && (nCol2 == rOther.nCol2)
+ && (nRow2 == rOther.nRow2)
+ && (bHasHeader == rOther.bHasHeader)
+ && (bByRow == rOther.bByRow)
+ && (bCaseSens == rOther.bCaseSens)
+ && (bUserDef == rOther.bUserDef)
+ && (nUserIndex == rOther.nUserIndex)
+ && (bIncludePattern == rOther.bIncludePattern)
+ && (bInplace == rOther.bInplace)
+ && (nDestTab == rOther.nDestTab)
+ && (nDestCol == rOther.nDestCol)
+ && (nDestRow == rOther.nDestRow) )
+ {
+ bEqual = TRUE;
+ for ( USHORT i=0; i<=nLast && bEqual; i++ )
+ {
+ bEqual = (nField[i] == rOther.nField[i]) && (bAscending[i] == rOther.bAscending[i]);
+ }
+ }
+ return bEqual;
+}
+
+//------------------------------------------------------------------------
+
+ScSortParam::ScSortParam( const ScSubTotalParam& rSub, const ScSortParam& rOld ) :
+ nCol1(rSub.nCol1),nRow1(rSub.nRow1),nCol2(rSub.nCol2),nRow2(rSub.nRow2),
+ bHasHeader(TRUE),bCaseSens(rSub.bCaseSens),
+ bByRow(TRUE),bUserDef(rSub.bUserDef),nUserIndex(rSub.nUserIndex),bIncludePattern(rSub.bIncludePattern),
+ bInplace(TRUE),
+ nDestTab(0),nDestCol(0),nDestRow(0)
+{
+ USHORT nNewCount = 0;
+ USHORT i;
+
+ // zuerst die Gruppen aus den Teilergebnissen
+ if (rSub.bDoSort)
+ for (i=0; i<MAXSUBTOTAL; i++)
+ if (rSub.bGroupActive[i])
+ {
+ if (nNewCount < MAXSORT)
+ {
+ bDoSort[nNewCount] = TRUE;
+ nField[nNewCount] = rSub.nField[i];
+ bAscending[nNewCount] = rSub.bAscending;
+ ++nNewCount;
+ }
+ }
+
+ // dann dahinter die alten Einstellungen
+ for (i=0; i<MAXSORT; i++)
+ if (rOld.bDoSort[i])
+ {
+ USHORT nThisField = rOld.nField[i];
+ BOOL bDouble = FALSE;
+ for (USHORT j=0; j<nNewCount; j++)
+ if ( nField[j] == nThisField )
+ bDouble = TRUE;
+ if (!bDouble) // ein Feld nicht zweimal eintragen
+ {
+ if (nNewCount < MAXSORT)
+ {
+ bDoSort[nNewCount] = TRUE;
+ nField[nNewCount] = nThisField;
+ bAscending[nNewCount] = rOld.bAscending[i];
+ ++nNewCount;
+ }
+ }
+ }
+
+ for (i=nNewCount; i<MAXSORT; i++) // Rest loeschen
+ {
+ bDoSort[i] = FALSE;
+ nField[i] = 0;
+ bAscending[i] = TRUE;
+ }
+}
+
+//------------------------------------------------------------------------
+
+ScSortParam::ScSortParam( const ScQueryParam& rParam, USHORT nCol ) :
+ nCol1(nCol),nRow1(rParam.nRow1),nRow2(rParam.nRow2),nCol2(nCol),
+ bHasHeader(rParam.bHasHeader),bCaseSens(rParam.bCaseSens),
+ bByRow(TRUE),bUserDef(FALSE),nUserIndex(0),bIncludePattern(FALSE),
+ bInplace(TRUE),
+ nDestTab(0),nDestCol(0),nDestRow(0)
+{
+ bDoSort[0] = TRUE;
+ nField[0] = nCol;
+ bAscending[0] = TRUE;
+ for (USHORT i=1; i<MAXSORT; i++)
+ {
+ bDoSort[i] = FALSE;
+ nField[i] = 0;
+ bAscending[i] = TRUE;
+ }
+}
+
+//------------------------------------------------------------------------
+
+void ScSortParam::MoveToDest()
+{
+ if (!bInplace)
+ {
+ short nDifX = ((short) nDestCol) - ((short) nCol1);
+ short nDifY = ((short) nDestRow) - ((short) nRow1);
+
+ nCol1 += nDifX;
+ nRow1 += nDifY;
+ nCol2 += nDifX;
+ nRow2 += nDifY;
+ for (USHORT i=0; i<MAXSORT; i++)
+ if (bByRow)
+ nField[i] += nDifX;
+ else
+ nField[i] += nDifY;
+
+ bInplace = TRUE;
+ }
+ else
+ DBG_ERROR("MoveToDest, bInplace == TRUE");
+}
+
+//------------------------------------------------------------------------
+// struct ScQueryParam:
+
+ScQueryEntry::ScQueryEntry()
+{
+ bDoQuery = FALSE;
+ bQueryByString = FALSE;
+ eOp = SC_EQUAL;
+ eConnect = SC_AND;
+ nField = 0;
+ nVal = 0.0;
+ pStr = new String;
+ pSearchParam = NULL;
+ pSearchText = NULL;
+}
+
+ScQueryEntry::ScQueryEntry(const ScQueryEntry& r)
+{
+ bDoQuery = r.bDoQuery;
+ bQueryByString = r.bQueryByString;
+ eOp = r.eOp;
+ eConnect = r.eConnect;
+ nField = r.nField;
+ nVal = r.nVal;
+ pStr = new String(*r.pStr);
+ pSearchParam = NULL;
+ pSearchText = NULL;
+}
+
+ScQueryEntry::~ScQueryEntry()
+{
+ delete pStr;
+ if ( pSearchParam )
+ {
+ delete pSearchParam;
+ delete pSearchText;
+ }
+}
+
+ScQueryEntry& ScQueryEntry::operator=( const ScQueryEntry& r )
+{
+ bDoQuery = r.bDoQuery;
+ bQueryByString = r.bQueryByString;
+ eOp = r.eOp;
+ eConnect = r.eConnect;
+ nField = r.nField;
+ nVal = r.nVal;
+ *pStr = *r.pStr;
+ if ( pSearchParam )
+ {
+ delete pSearchParam;
+ delete pSearchText;
+ }
+ pSearchParam = NULL;
+ pSearchText = NULL;
+
+ return *this;
+}
+
+void ScQueryEntry::Clear()
+{
+ bDoQuery = FALSE;
+ bQueryByString = FALSE;
+ eOp = SC_EQUAL;
+ eConnect = SC_AND;
+ nField = 0;
+ nVal = 0.0;
+ pStr->Erase();
+ if ( pSearchParam )
+ {
+ delete pSearchParam;
+ delete pSearchText;
+ }
+ pSearchParam = NULL;
+ pSearchText = NULL;
+}
+
+BOOL ScQueryEntry::operator==( const ScQueryEntry& r ) const
+{
+ return bDoQuery == r.bDoQuery
+ && bQueryByString == r.bQueryByString
+ && eOp == r.eOp
+ && eConnect == r.eConnect
+ && nField == r.nField
+ && nVal == r.nVal
+ && *pStr == *r.pStr;
+ //! pSearchParam und pSearchText nicht vergleichen
+}
+
+void ScQueryEntry::Load( SvStream& rStream )
+{
+ BYTE cOp, cConnect;
+ rStream >> bDoQuery
+ >> bQueryByString
+ >> cOp
+ >> cConnect
+ >> nField
+ >> nVal;
+ rStream.ReadByteString( *pStr, rStream.GetStreamCharSet() );
+ eOp = (ScQueryOp) cOp;
+ eConnect = (ScQueryConnect) cConnect;
+}
+
+void ScQueryEntry::Store( SvStream& rStream ) const
+{
+ rStream << bDoQuery
+ << bQueryByString
+ << (BYTE) eOp
+ << (BYTE) eConnect
+ << nField
+ << nVal;
+ rStream.WriteByteString( *pStr, rStream.GetStreamCharSet() );
+}
+
+SearchText* ScQueryEntry::GetSearchTextPtr( BOOL bCaseSens )
+{
+ if ( !pSearchParam )
+ {
+ pSearchParam = new SearchParam( *pStr, SearchParam::SRCH_REGEXP,
+ bCaseSens, FALSE, FALSE );
+ pSearchText = new SearchText( *pSearchParam, *ScGlobal::pScInternational );
+ }
+ return pSearchText;
+}
+
+//------------------------------------------------------------------------
+
+ScQueryParam::ScQueryParam()
+{
+ nEntryCount = 0;
+ Clear();
+}
+
+//------------------------------------------------------------------------
+
+ScQueryParam::ScQueryParam( const ScQueryParam& r ) :
+ nCol1(r.nCol1),nRow1(r.nRow1),nCol2(r.nCol2),nRow2(r.nRow2),nTab(r.nTab),
+ nDestTab(r.nDestTab),nDestCol(r.nDestCol),nDestRow(r.nDestRow),
+ bHasHeader(r.bHasHeader),bInplace(r.bInplace),bCaseSens(r.bCaseSens),
+ bRegExp(r.bRegExp),bDuplicate(r.bDuplicate),bByRow(r.bByRow),
+ bDestPers(r.bDestPers)
+{
+ nEntryCount = 0;
+
+ Resize( r.nEntryCount );
+ for (USHORT i=0; i<nEntryCount; i++)
+ pEntries[i] = r.pEntries[i];
+}
+
+//------------------------------------------------------------------------
+
+ScQueryParam::~ScQueryParam()
+{
+ delete[] pEntries;
+}
+
+//------------------------------------------------------------------------
+
+void ScQueryParam::Clear()
+{
+ nCol1=nRow1=nCol2=nRow2=
+ nDestTab=nDestCol=nDestRow = 0;
+ nTab = USHRT_MAX;
+ bHasHeader=bCaseSens=bRegExp = FALSE;
+ bInplace=bByRow=bDuplicate=bDestPers = TRUE;
+
+ Resize( MAXQUERY );
+ for (USHORT i=0; i<MAXQUERY; i++)
+ pEntries[i].Clear();
+}
+
+//------------------------------------------------------------------------
+
+ScQueryParam& ScQueryParam::operator=( const ScQueryParam& r )
+{
+ nCol1 = r.nCol1;
+ nRow1 = r.nRow1;
+ nCol2 = r.nCol2;
+ nRow2 = r.nRow2;
+ nTab = r.nTab;
+ nDestTab = r.nDestTab;
+ nDestCol = r.nDestCol;
+ nDestRow = r.nDestRow;
+ bHasHeader = r.bHasHeader;
+ bInplace = r.bInplace;
+ bCaseSens = r.bCaseSens;
+ bRegExp = r.bRegExp;
+ bDuplicate = r.bDuplicate;
+ bByRow = r.bByRow;
+ bDestPers = r.bDestPers;
+
+ Resize( r.nEntryCount );
+ for (USHORT i=0; i<nEntryCount; i++)
+ pEntries[i] = r.pEntries[i];
+
+ return *this;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScQueryParam::operator==( const ScQueryParam& rOther ) const
+{
+ BOOL bEqual = FALSE;
+
+ // Anzahl der Queries gleich?
+ USHORT nUsed = 0;
+ USHORT nOtherUsed = 0;
+ while ( nUsed<nEntryCount && pEntries[nUsed].bDoQuery ) ++nUsed;
+ while ( nOtherUsed<rOther.nEntryCount && rOther.pEntries[nOtherUsed].bDoQuery )
+ ++nOtherUsed;
+
+ if ( (nUsed == nOtherUsed)
+ && (nCol1 == rOther.nCol1)
+ && (nRow1 == rOther.nRow1)
+ && (nCol2 == rOther.nCol2)
+ && (nRow2 == rOther.nRow2)
+ && (nTab == rOther.nTab)
+ && (bHasHeader == rOther.bHasHeader)
+ && (bByRow == rOther.bByRow)
+ && (bInplace == rOther.bInplace)
+ && (bCaseSens == rOther.bCaseSens)
+ && (bRegExp == rOther.bRegExp)
+ && (bDuplicate == rOther.bDuplicate)
+ && (bDestPers == rOther.bDestPers)
+ && (nDestTab == rOther.nDestTab)
+ && (nDestCol == rOther.nDestCol)
+ && (nDestRow == rOther.nDestRow) )
+ {
+ bEqual = TRUE;
+ for ( USHORT i=0; i<nUsed && bEqual; i++ )
+ bEqual = pEntries[i] == rOther.pEntries[i];
+ }
+ return bEqual;
+}
+
+//------------------------------------------------------------------------
+
+void ScQueryParam::DeleteQuery( USHORT nPos )
+{
+ if (nPos<nEntryCount)
+ {
+ for (USHORT i=nPos; i+1<nEntryCount; i++)
+ pEntries[i] = pEntries[i+1];
+
+ pEntries[nEntryCount-1].Clear();
+ }
+ else
+ DBG_ERROR("Falscher Parameter bei ScQueryParam::DeleteQuery");
+}
+
+//------------------------------------------------------------------------
+
+void ScQueryParam::Resize(USHORT nNew)
+{
+ if ( nNew < MAXQUERY )
+ nNew = MAXQUERY; // nie weniger als MAXQUERY
+
+ ScQueryEntry* pNewEntries = NULL;
+ if ( nNew )
+ pNewEntries = new ScQueryEntry[nNew];
+
+ USHORT nCopy = Min( nEntryCount, nNew );
+ for (USHORT i=0; i<nCopy; i++)
+ pNewEntries[i] = pEntries[i];
+
+ if ( nEntryCount )
+ delete[] pEntries;
+ nEntryCount = nNew;
+ pEntries = pNewEntries;
+}
+
+//------------------------------------------------------------------------
+
+void ScQueryParam::MoveToDest()
+{
+ if (!bInplace)
+ {
+ short nDifX = ((short) nDestCol) - ((short) nCol1);
+ short nDifY = ((short) nDestRow) - ((short) nRow1);
+ short nDifZ = ((short) nDestTab) - ((short) nTab);
+
+ nCol1 += nDifX;
+ nRow1 += nDifY;
+ nCol2 += nDifX;
+ nRow2 += nDifY;
+ nTab += nDifZ;
+ for (USHORT i=0; i<nEntryCount; i++)
+ pEntries[i].nField += nDifX;
+
+ bInplace = TRUE;
+ }
+ else
+ DBG_ERROR("MoveToDest, bInplace == TRUE");
+}
+
+//------------------------------------------------------------------------
+
+void ScQueryParam::FillInExcelSyntax(String& aCellStr, USHORT nIndex)
+{
+ if (aCellStr.Len() > 0)
+ {
+ if ( nIndex >= nEntryCount )
+ Resize( nIndex+1 );
+
+ ScQueryEntry& rEntry = pEntries[nIndex];
+
+ rEntry.bDoQuery = TRUE;
+ // Operatoren herausfiltern
+ if (aCellStr.GetChar(0) == '<')
+ {
+ if (aCellStr.GetChar(1) == '>')
+ {
+ *rEntry.pStr = aCellStr.Copy(2);
+ rEntry.eOp = SC_NOT_EQUAL;
+ }
+ else if (aCellStr.GetChar(1) == '=')
+ {
+ *rEntry.pStr = aCellStr.Copy(2);
+ rEntry.eOp = SC_LESS_EQUAL;
+ }
+ else
+ {
+ *rEntry.pStr = aCellStr.Copy(1);
+ rEntry.eOp = SC_LESS;
+ }
+ }
+ else if (aCellStr.GetChar(0) == '>')
+ {
+ if (aCellStr.GetChar(1) == '=')
+ {
+ *rEntry.pStr = aCellStr.Copy(2);
+ rEntry.eOp = SC_GREATER_EQUAL;
+ }
+ else
+ {
+ *rEntry.pStr = aCellStr.Copy(1);
+ rEntry.eOp = SC_GREATER;
+ }
+ }
+ else
+ {
+ if (aCellStr.GetChar(0) == '=')
+ *rEntry.pStr = aCellStr.Copy(1);
+ else
+ *rEntry.pStr = aCellStr;
+ rEntry.eOp = SC_EQUAL;
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+
+void ScQueryParam::Load( SvStream& rStream ) // z.B. fuer Pivot-Tabelle
+{
+ // bDestPers wird nicht geladen/gespeichert
+
+ ScReadHeader aHdr( rStream );
+
+ rStream >> nCol1
+ >> nRow1
+ >> nCol2
+ >> nRow2
+ >> nDestTab
+ >> nDestCol
+ >> nDestRow
+ >> bHasHeader
+ >> bInplace
+ >> bCaseSens
+ >> bRegExp
+ >> bDuplicate
+ >> bByRow;
+
+ Resize( MAXQUERY );
+
+ for (USHORT i=0; i<MAXQUERY; i++)
+ pEntries[i].Load(rStream);
+}
+
+//------------------------------------------------------------------------
+
+void ScQueryParam::Store( SvStream& rStream ) const // z.B. fuer Pivot-Tabelle
+{
+ // bDestPers wird nicht geladen/gespeichert
+
+ ScWriteHeader aHdr( rStream );
+
+ DBG_ASSERT( nEntryCount <= MAXQUERY || !pEntries[MAXQUERY].bDoQuery,
+ "zuviele Eintraege bei ScQueryParam::Store" );
+
+
+ if ( nEntryCount < MAXQUERY )
+ {
+ DBG_ERROR("ScQueryParam::Store - zuwenig Eintraege");
+ ((ScQueryParam*)this)->Resize( MAXQUERY );
+ }
+
+ rStream << nCol1
+ << nRow1
+ << nCol2
+ << nRow2
+ << nDestTab
+ << nDestCol
+ << nDestRow
+ << bHasHeader
+ << bInplace
+ << bCaseSens
+ << bRegExp
+ << bDuplicate
+ << bByRow;
+
+ for (USHORT i=0; i<MAXQUERY; i++)
+ pEntries[i].Store(rStream);
+}
+
+//------------------------------------------------------------------------
+// struct ScSubTotalParam:
+
+ScSubTotalParam::ScSubTotalParam()
+{
+ for ( USHORT i=0; i<MAXSUBTOTAL; i++ )
+ {
+ nSubTotals[i] = 0;
+ pSubTotals[i] = NULL;
+ pFunctions[i] = NULL;
+ }
+
+ Clear();
+}
+
+//------------------------------------------------------------------------
+
+ScSubTotalParam::ScSubTotalParam( const ScSubTotalParam& r ) :
+ nCol1(r.nCol1),nRow1(r.nRow1),nCol2(r.nCol2),nRow2(r.nRow2),
+ bReplace(r.bReplace),bPagebreak(r.bPagebreak),bCaseSens(r.bCaseSens),
+ bDoSort(r.bDoSort),bAscending(r.bAscending),bUserDef(r.bUserDef),nUserIndex(r.nUserIndex),
+ bIncludePattern(r.bIncludePattern),bRemoveOnly(r.bRemoveOnly)
+{
+ for (USHORT i=0; i<MAXSUBTOTAL; i++)
+ {
+ bGroupActive[i] = r.bGroupActive[i];
+ nField[i] = r.nField[i];
+
+ if ( (r.nSubTotals[i] > 0) && r.pSubTotals[i] && r.pFunctions[i] )
+ {
+ nSubTotals[i] = r.nSubTotals[i];
+ pSubTotals[i] = new USHORT [r.nSubTotals[i]];
+ pFunctions[i] = new ScSubTotalFunc [r.nSubTotals[i]];
+
+ for (USHORT j=0; j<r.nSubTotals[i]; j++)
+ {
+ pSubTotals[i][j] = r.pSubTotals[i][j];
+ pFunctions[i][j] = r.pFunctions[i][j];
+ }
+ }
+ else
+ {
+ nSubTotals[i] = 0;
+ pSubTotals[i] = NULL;
+ pFunctions[i] = NULL;
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+
+void ScSubTotalParam::Clear()
+{
+ nCol1=nRow1=nCol2=nRow2=nUserIndex = 0;
+ bPagebreak=bCaseSens=bUserDef=bIncludePattern=bRemoveOnly = FALSE;
+ bAscending=bReplace=bDoSort = TRUE;
+
+ for (USHORT i=0; i<MAXSUBTOTAL; i++)
+ {
+ bGroupActive[i] = FALSE;
+ nField[i] = 0;
+
+ if ( (nSubTotals[i] > 0) && pSubTotals[i] && pFunctions[i] )
+ {
+ for ( USHORT j=0; j<nSubTotals[i]; j++ )
+ pSubTotals[i][j] = 0;
+ pFunctions[i][j] = SUBTOTAL_FUNC_NONE;
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+
+ScSubTotalParam& ScSubTotalParam::operator=( const ScSubTotalParam& r )
+{
+ nCol1 = r.nCol1;
+ nRow1 = r.nRow1;
+ nCol2 = r.nCol2;
+ nRow2 = r.nRow2;
+ bRemoveOnly = r.bRemoveOnly;
+ bReplace = r.bReplace;
+ bPagebreak = r.bPagebreak;
+ bCaseSens = r.bCaseSens;
+ bDoSort = r.bDoSort;
+ bAscending = r.bAscending;
+ bUserDef = r.bUserDef;
+ nUserIndex = r.nUserIndex;
+ bIncludePattern = r.bIncludePattern;
+
+ for (USHORT i=0; i<MAXSUBTOTAL; i++)
+ {
+ bGroupActive[i] = r.bGroupActive[i];
+ nField[i] = r.nField[i];
+ nSubTotals[i] = r.nSubTotals[i];
+
+ if ( pSubTotals[i] ) delete [] pSubTotals[i];
+ if ( pFunctions[i] ) delete [] pFunctions[i];
+
+ if ( r.nSubTotals[i] > 0 )
+ {
+ pSubTotals[i] = new USHORT [r.nSubTotals[i]];
+ pFunctions[i] = new ScSubTotalFunc [r.nSubTotals[i]];
+
+ for (USHORT j=0; j<r.nSubTotals[i]; j++)
+ {
+ pSubTotals[i][j] = r.pSubTotals[i][j];
+ pFunctions[i][j] = r.pFunctions[i][j];
+ }
+ }
+ else
+ {
+ nSubTotals[i] = 0;
+ pSubTotals[i] = NULL;
+ pFunctions[i] = NULL;
+ }
+ }
+
+ return *this;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScSubTotalParam::operator==( const ScSubTotalParam& rOther ) const
+{
+ BOOL bEqual = (nCol1 == rOther.nCol1)
+ && (nRow1 == rOther.nRow1)
+ && (nCol2 == rOther.nCol2)
+ && (nRow2 == rOther.nRow2)
+ && (bRemoveOnly == rOther.bRemoveOnly)
+ && (bReplace == rOther.bReplace)
+ && (bPagebreak == rOther.bPagebreak)
+ && (bDoSort == rOther.bDoSort)
+ && (bCaseSens == rOther.bCaseSens)
+ && (bAscending == rOther.bAscending)
+ && (bUserDef == rOther.bUserDef)
+ && (nUserIndex == rOther.nUserIndex)
+ && (bIncludePattern== rOther.bIncludePattern);
+
+ if ( bEqual )
+ {
+ bEqual = TRUE;
+ for ( USHORT i=0; i<MAXSUBTOTAL && bEqual; i++ )
+ {
+ bEqual = (bGroupActive[i] == rOther.bGroupActive[i])
+ && (nField[i] == rOther.nField[i])
+ && (nSubTotals[i] == rOther.nSubTotals[i]);
+
+ if ( bEqual && (nSubTotals[i] > 0) )
+ {
+ bEqual = (pSubTotals != NULL) && (pFunctions != NULL);
+
+ for (USHORT j=0; (j<nSubTotals[i]) && bEqual; j++)
+ {
+ bEqual = bEqual
+ && (pSubTotals[i][j] == rOther.pSubTotals[i][j])
+ && (pFunctions[i][j] == rOther.pFunctions[i][j]);
+ }
+ }
+ }
+ }
+
+ return bEqual;
+}
+
+//------------------------------------------------------------------------
+
+void ScSubTotalParam::SetSubTotals( USHORT nGroup,
+ const USHORT* ptrSubTotals,
+ const ScSubTotalFunc* ptrFunctions,
+ USHORT nCount )
+{
+ DBG_ASSERT( (nGroup <= MAXSUBTOTAL),
+ "ScSubTotalParam::SetSubTotals(): nGroup > MAXSUBTOTAL!" );
+ DBG_ASSERT( ptrSubTotals,
+ "ScSubTotalParam::SetSubTotals(): ptrSubTotals == NULL!" );
+ DBG_ASSERT( ptrFunctions,
+ "ScSubTotalParam::SetSubTotals(): ptrFunctions == NULL!" );
+ DBG_ASSERT( (nCount > 0),
+ "ScSubTotalParam::SetSubTotals(): nCount <= 0!" );
+
+ if ( ptrSubTotals && ptrFunctions && (nCount > 0) && (nGroup <= MAXSUBTOTAL) )
+ {
+ // 0 wird als 1 aufgefasst, sonst zum Array-Index dekrementieren
+ if (nGroup != 0)
+ nGroup--;
+
+ delete [] pSubTotals[nGroup];
+ delete [] pFunctions[nGroup];
+
+ pSubTotals[nGroup] = new USHORT [nCount];
+ pFunctions[nGroup] = new ScSubTotalFunc [nCount];
+ nSubTotals[nGroup] = nCount;
+
+ for ( USHORT i=0; i<nCount; i++ )
+ {
+ pSubTotals[nGroup][i] = ptrSubTotals[i];
+ pFunctions[nGroup][i] = ptrFunctions[i];
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+// struct ScConsolidateParam:
+
+ScConsolidateParam::ScConsolidateParam() :
+ ppDataAreas( NULL )
+{
+ Clear();
+}
+
+//------------------------------------------------------------------------
+
+ScConsolidateParam::ScConsolidateParam( const ScConsolidateParam& r ) :
+ ppDataAreas( NULL ),
+ nCol(r.nCol),nRow(r.nRow),nTab(r.nTab),
+ bByCol(r.bByCol),bByRow(r.bByRow),bReferenceData(r.bReferenceData),
+ nDataAreaCount(0),eFunction(r.eFunction)
+{
+ if ( r.nDataAreaCount > 0 )
+ {
+ nDataAreaCount = r.nDataAreaCount;
+ ppDataAreas = new ScArea*[nDataAreaCount];
+ for ( USHORT i=0; i<nDataAreaCount; i++ )
+ ppDataAreas[i] = new ScArea( *(r.ppDataAreas[i]) );
+ }
+}
+
+//------------------------------------------------------------------------
+
+__EXPORT ScConsolidateParam::~ScConsolidateParam()
+{
+ ClearDataAreas();
+}
+
+//------------------------------------------------------------------------
+
+void __EXPORT ScConsolidateParam::ClearDataAreas()
+{
+ if ( ppDataAreas )
+ {
+ for ( USHORT i=0; i<nDataAreaCount; i++ )
+ delete ppDataAreas[i];
+ delete [] ppDataAreas;
+ ppDataAreas = NULL;
+ }
+ nDataAreaCount = 0;
+}
+
+//------------------------------------------------------------------------
+
+void __EXPORT ScConsolidateParam::Clear()
+{
+ ClearDataAreas();
+
+ nCol = nRow = nTab = 0;
+ bByCol = bByRow = bReferenceData = FALSE;
+ eFunction = SUBTOTAL_FUNC_SUM;
+}
+
+//------------------------------------------------------------------------
+
+ScConsolidateParam& __EXPORT ScConsolidateParam::operator=( const ScConsolidateParam& r )
+{
+ nCol = r.nCol;
+ nRow = r.nRow;
+ nTab = r.nTab;
+ bByCol = r.bByCol;
+ bByRow = r.bByRow;
+ bReferenceData = r.bReferenceData;
+ eFunction = r.eFunction;
+ SetAreas( r.ppDataAreas, r.nDataAreaCount );
+
+ return *this;
+}
+
+//------------------------------------------------------------------------
+
+BOOL __EXPORT ScConsolidateParam::operator==( const ScConsolidateParam& r ) const
+{
+ BOOL bEqual = (nCol == r.nCol)
+ && (nRow == r.nRow)
+ && (nTab == r.nTab)
+ && (bByCol == r.bByCol)
+ && (bByRow == r.bByRow)
+ && (bReferenceData == r.bReferenceData)
+ && (nDataAreaCount == r.nDataAreaCount)
+ && (eFunction == r.eFunction);
+
+ if ( nDataAreaCount == 0 )
+ bEqual = bEqual && (ppDataAreas == NULL) && (r.ppDataAreas == NULL);
+ else
+ bEqual = bEqual && (ppDataAreas != NULL) && (r.ppDataAreas != NULL);
+
+ if ( bEqual && (nDataAreaCount > 0) )
+ for ( USHORT i=0; i<nDataAreaCount && bEqual; i++ )
+ bEqual = *(ppDataAreas[i]) == *(r.ppDataAreas[i]);
+
+ return bEqual;
+}
+
+//------------------------------------------------------------------------
+
+void __EXPORT ScConsolidateParam::SetAreas( ScArea* const* ppAreas, USHORT nCount )
+{
+ ClearDataAreas();
+ if ( ppAreas && nCount > 0 )
+ {
+ ppDataAreas = new ScArea*[nCount];
+ for ( USHORT i=0; i<nCount; i++ )
+ ppDataAreas[i] = new ScArea( *(ppAreas[i]) );
+ nDataAreaCount = nCount;
+ }
+}
+
+void ScConsolidateParam::Load( SvStream& rStream )
+{
+ ClearDataAreas();
+
+ ScReadHeader aHdr( rStream );
+
+ BYTE nByte;
+ rStream >> nCol >> nRow >> nTab
+ >> bByCol >> bByRow >> bReferenceData >> nByte;
+ eFunction = (ScSubTotalFunc) nByte;
+
+ rStream >> nDataAreaCount;
+ if ( nDataAreaCount )
+ {
+ ppDataAreas = new ScArea*[nDataAreaCount];
+ for ( USHORT i=0; i<nDataAreaCount; i++ )
+ {
+ ppDataAreas[i] = new ScArea();
+ rStream >> *ppDataAreas[i];
+ }
+ }
+}
+
+void ScConsolidateParam::Store( SvStream& rStream ) const
+{
+ ScWriteHeader aHdr( rStream, 12+10*nDataAreaCount );
+
+ rStream << nCol << nRow << nTab
+ << bByCol << bByRow << bReferenceData << (BYTE) eFunction;
+
+ rStream << nDataAreaCount;
+ for (USHORT i=0; i<nDataAreaCount; i++)
+ rStream << *ppDataAreas[i];
+}
+
+//------------------------------------------------------------------------
+// struct ScPivotParam:
+
+ScPivotParam::ScPivotParam()
+ : nCol(0), nRow(0), nTab(0),
+ ppLabelArr( NULL ), nLabels(0),
+ nColCount(0), nRowCount(0), nDataCount(0),
+ bIgnoreEmptyRows(FALSE), bDetectCategories(FALSE),
+ bMakeTotalCol(TRUE), bMakeTotalRow(TRUE)
+{
+}
+
+//------------------------------------------------------------------------
+
+ScPivotParam::ScPivotParam( const ScPivotParam& r )
+ : nCol( r.nCol ), nRow( r.nRow ), nTab( r.nTab ),
+ bIgnoreEmptyRows(r.bIgnoreEmptyRows),
+ bDetectCategories(r.bDetectCategories),
+ bMakeTotalCol(r.bMakeTotalCol),
+ bMakeTotalRow(r.bMakeTotalRow),
+ ppLabelArr( NULL ), nLabels(0),
+ nColCount(0), nRowCount(0), nDataCount(0)
+{
+ SetLabelData ( r.ppLabelArr, r.nLabels );
+ SetPivotArrays ( r.aColArr, r.aRowArr, r.aDataArr,
+ r.nColCount, r.nRowCount, r.nDataCount );
+}
+
+//------------------------------------------------------------------------
+
+__EXPORT ScPivotParam::~ScPivotParam()
+{
+ ClearLabelData();
+}
+
+//------------------------------------------------------------------------
+
+void __EXPORT ScPivotParam::Clear()
+{
+ nCol = nRow = nTab = 0;
+ bIgnoreEmptyRows = bDetectCategories = FALSE;
+ bMakeTotalCol = bMakeTotalRow = TRUE;
+ ClearLabelData();
+ ClearPivotArrays();
+}
+
+//------------------------------------------------------------------------
+
+void __EXPORT ScPivotParam::ClearLabelData()
+{
+ if ( (nLabels > 0) && ppLabelArr )
+ {
+ for ( USHORT i=0; i<nLabels; i++ )
+ delete ppLabelArr[i];
+ delete [] ppLabelArr;
+ ppLabelArr = NULL;
+ nLabels = 0;
+ }
+}
+
+//------------------------------------------------------------------------
+
+void __EXPORT ScPivotParam::ClearPivotArrays()
+{
+ memset( aColArr, 0, PIVOT_MAXFIELD * sizeof(PivotField) );
+ memset( aRowArr, 0, PIVOT_MAXFIELD * sizeof(PivotField) );
+ memset( aDataArr, 0, PIVOT_MAXFIELD * sizeof(PivotField) );
+ nColCount = nRowCount = nDataCount = 0;
+}
+
+//------------------------------------------------------------------------
+
+void __EXPORT ScPivotParam::SetLabelData( LabelData** pLabArr,
+ USHORT nLab )
+{
+ ClearLabelData();
+
+ if ( (nLab > 0) && pLabArr )
+ {
+ nLabels = (nLab>MAX_LABELS) ? MAX_LABELS : nLab;
+ ppLabelArr = new LabelData*[nLabels];
+ for ( USHORT i=0; i<nLabels; i++ )
+ ppLabelArr[i] = new LabelData( *(pLabArr[i]) );
+ }
+}
+
+//------------------------------------------------------------------------
+
+void __EXPORT ScPivotParam::SetPivotArrays ( const PivotField* pColArr,
+ const PivotField* pRowArr,
+ const PivotField* pDataArr,
+ USHORT nColCnt,
+ USHORT nRowCnt,
+ USHORT nDataCnt )
+{
+ ClearPivotArrays();
+
+ if ( pColArr && pRowArr && pDataArr )
+ {
+ nColCount = (nColCnt>PIVOT_MAXFIELD) ? PIVOT_MAXFIELD : nColCnt;
+ nRowCount = (nRowCnt>PIVOT_MAXFIELD) ? PIVOT_MAXFIELD : nRowCnt;
+ nDataCount = (nDataCnt>PIVOT_MAXFIELD) ? PIVOT_MAXFIELD : nDataCnt;
+
+ memcpy( aColArr, pColArr, nColCount * sizeof(PivotField) );
+ memcpy( aRowArr, pRowArr, nRowCount * sizeof(PivotField) );
+ memcpy( aDataArr, pDataArr, nDataCount * sizeof(PivotField) );
+ }
+}
+
+//------------------------------------------------------------------------
+
+ScPivotParam& __EXPORT ScPivotParam::operator=( const ScPivotParam& r )
+{
+ nCol = r.nCol;
+ nRow = r.nRow;
+ nTab = r.nTab;
+ bIgnoreEmptyRows = r.bIgnoreEmptyRows;
+ bDetectCategories = r.bDetectCategories;
+ bMakeTotalCol = r.bMakeTotalCol;
+ bMakeTotalRow = r.bMakeTotalRow;
+
+ SetLabelData ( r.ppLabelArr, r.nLabels );
+ SetPivotArrays ( r.aColArr, r.aRowArr, r.aDataArr,
+ r.nColCount, r.nRowCount, r.nDataCount );
+
+ return *this;
+}
+
+//------------------------------------------------------------------------
+
+BOOL __EXPORT ScPivotParam::operator==( const ScPivotParam& r ) const
+{
+ BOOL bEqual = (nCol == r.nCol)
+ && (nRow == r.nRow)
+ && (nTab == r.nTab)
+ && (bIgnoreEmptyRows == r.bIgnoreEmptyRows)
+ && (bDetectCategories == r.bDetectCategories)
+ && (bMakeTotalCol == r.bMakeTotalCol)
+ && (bMakeTotalRow == r.bMakeTotalRow)
+ && (nLabels == r.nLabels)
+ && (nColCount == r.nColCount)
+ && (nRowCount == r.nRowCount)
+ && (nDataCount == r.nDataCount);
+
+ if ( bEqual )
+ {
+ USHORT i;
+
+ for ( i=0; i<nColCount && bEqual; i++ )
+ bEqual = ( aColArr[i] == r.aColArr[i] );
+
+ for ( i=0; i<nRowCount && bEqual; i++ )
+ bEqual = ( aRowArr[i] == r.aRowArr[i] );
+
+ for ( i=0; i<nDataCount && bEqual; i++ )
+ bEqual = ( aDataArr[i] == r.aDataArr[i] );
+ }
+
+ return bEqual;
+}
+
+//------------------------------------------------------------------------
+// struct ScSolveParam
+
+ScSolveParam::ScSolveParam()
+ : pStrTargetVal( NULL )
+{
+}
+
+//------------------------------------------------------------------------
+
+ScSolveParam::ScSolveParam( const ScSolveParam& r )
+ : aRefFormulaCell ( r.aRefFormulaCell ),
+ aRefVariableCell( r.aRefVariableCell ),
+ pStrTargetVal ( r.pStrTargetVal
+ ? new String(*r.pStrTargetVal)
+ : NULL )
+{
+}
+
+//------------------------------------------------------------------------
+
+ScSolveParam::ScSolveParam( const ScAddress& rFormulaCell,
+ const ScAddress& rVariableCell,
+ const String& rTargetValStr )
+ : aRefFormulaCell ( rFormulaCell ),
+ aRefVariableCell( rVariableCell ),
+ pStrTargetVal ( new String(rTargetValStr) )
+{
+}
+
+//------------------------------------------------------------------------
+
+ScSolveParam::~ScSolveParam()
+{
+ delete pStrTargetVal;
+}
+
+//------------------------------------------------------------------------
+
+ScSolveParam& __EXPORT ScSolveParam::operator=( const ScSolveParam& r )
+{
+ delete pStrTargetVal;
+
+ aRefFormulaCell = r.aRefFormulaCell;
+ aRefVariableCell = r.aRefVariableCell;
+ pStrTargetVal = r.pStrTargetVal
+ ? new String(*r.pStrTargetVal)
+ : NULL;
+ return *this;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScSolveParam::operator==( const ScSolveParam& r ) const
+{
+ BOOL bEqual = (aRefFormulaCell == r.aRefFormulaCell)
+ && (aRefVariableCell == r.aRefVariableCell);
+
+ if ( bEqual )
+ {
+ if ( !pStrTargetVal && !r.pStrTargetVal )
+ bEqual = TRUE;
+ else if ( !pStrTargetVal || !r.pStrTargetVal )
+ bEqual = FALSE;
+ else if ( pStrTargetVal && r.pStrTargetVal )
+ bEqual = ( *pStrTargetVal == *(r.pStrTargetVal) );
+ }
+
+ return bEqual;
+}
+
+
+//------------------------------------------------------------------------
+// struct ScTabOpParam
+
+ScTabOpParam::ScTabOpParam( const ScTabOpParam& r )
+ : aRefFormulaCell ( r.aRefFormulaCell ),
+ aRefFormulaEnd ( r.aRefFormulaEnd ),
+ aRefRowCell ( r.aRefRowCell ),
+ aRefColCell ( r.aRefColCell ),
+ nMode ( r.nMode )
+{
+}
+
+//------------------------------------------------------------------------
+
+ScTabOpParam::ScTabOpParam( const ScRefTripel& rFormulaCell,
+ const ScRefTripel& rFormulaEnd,
+ const ScRefTripel& rRowCell,
+ const ScRefTripel& rColCell,
+ BYTE nMd)
+ : aRefFormulaCell ( rFormulaCell ),
+ aRefFormulaEnd ( rFormulaEnd ),
+ aRefRowCell ( rRowCell ),
+ aRefColCell ( rColCell ),
+ nMode ( nMd )
+{
+}
+
+//------------------------------------------------------------------------
+
+ScTabOpParam& ScTabOpParam::operator=( const ScTabOpParam& r )
+{
+ aRefFormulaCell = r.aRefFormulaCell;
+ aRefFormulaEnd = r.aRefFormulaEnd;
+ aRefRowCell = r.aRefRowCell;
+ aRefColCell = r.aRefColCell;
+ nMode = r.nMode;
+ return *this;
+}
+
+//------------------------------------------------------------------------
+
+BOOL __EXPORT ScTabOpParam::operator==( const ScTabOpParam& r ) const
+{
+ return ( (aRefFormulaCell == r.aRefFormulaCell)
+ && (aRefFormulaEnd == r.aRefFormulaEnd)
+ && (aRefRowCell == r.aRefRowCell)
+ && (aRefColCell == r.aRefColCell)
+ && (nMode == r.nMode) );
+}
+
+
+//========================================================================
+// class ScPostIt
+//========================================================================
+
+ScPostIt::ScPostIt()
+{
+ bShown = FALSE;
+}
+
+ScPostIt::ScPostIt( const String& rText )
+{
+ AutoSetText( rText );
+ bShown = FALSE;
+}
+
+ScPostIt::ScPostIt( const String& rText, const String& rDate, const String& rAuthor )
+ : aStrText ( rText ),
+ aStrDate ( rDate ),
+ aStrAuthor ( rAuthor )
+{
+ bShown = FALSE;
+}
+
+ScPostIt::ScPostIt( const ScPostIt& rCpy )
+ : aStrText ( rCpy.aStrText ),
+ aStrDate ( rCpy.aStrDate ),
+ aStrAuthor ( rCpy.aStrAuthor )
+{
+ bShown = rCpy.bShown;
+}
+
+__EXPORT ScPostIt::~ScPostIt()
+{
+}
+
+void ScPostIt::AutoSetText( const String& rNewText )
+{
+ aStrText = rNewText;
+ aStrDate = ScGlobal::pScInternational->GetDate( Date() );
+
+ // Der Einheitlichkeit halber das Datum immer ohne Uhrzeit (wie im Writer)
+// aStrDate += ", ";
+// aStrDate += ScGlobal::pScInternational->GetTime( Time() );
+
+ aStrAuthor = SFX_INIMANAGER()->Get( SFX_KEY_USER_ID );
+}
+
+//========================================================================
+
+String ScGlobal::GetAbsDocName( const String& rFileName,
+ SfxObjectShell* pShell )
+{
+ String aAbsName;
+ if ( !pShell->HasName() )
+ { // maybe relative to document path working directory
+ INetURLObject aObj;
+ aObj.SetSmartURL( SFX_INIMANAGER()->Get( SFX_KEY_WORK_PATH ) );
+ aObj.setFinalSlash(); // it IS a path
+ bool bWasAbs = true;
+ aAbsName = aObj.smartRel2Abs( rFileName, bWasAbs ).GetMainURL();
+ }
+ else
+ {
+ const SfxMedium* pMedium = pShell->GetMedium();
+ if ( pMedium )
+ {
+ bool bWasAbs = true;
+ aAbsName = pMedium->GetURLObject().smartRel2Abs( rFileName, bWasAbs ).GetMainURL();
+ }
+ else
+ { // This can't happen, but ...
+ // just to be sure to have the same encoding
+ INetURLObject aObj;
+ aObj.SetSmartURL( aAbsName );
+ aAbsName = aObj.GetMainURL();
+ }
+ }
+ return aAbsName;
+}
+
+
+String ScGlobal::GetDocTabName( const String& rFileName,
+ const String& rTabName )
+{
+ String aDocTab( '\'' );
+ aDocTab += rFileName;
+ xub_StrLen nPos = 1;
+ while( (nPos = aDocTab.Search( '\'', nPos ))
+ != STRING_NOTFOUND )
+ { // escape Quotes
+ aDocTab.Insert( '\\', nPos );
+ nPos += 2;
+ }
+ aDocTab += '\'';
+ aDocTab += SC_COMPILER_FILE_TAB_SEP;
+ aDocTab += rTabName; // "'Doc'#Tab"
+ return aDocTab;
+}
+
+
+USHORT lcl_ConvertSingleRef( BOOL& bExternal, const sal_Unicode* p,
+ ScDocument* pDoc, ScAddress& rAddr )
+{
+ if ( !*p )
+ return 0;
+ USHORT nRes = 0;
+ String aDocName; // der pure Dokumentenname
+ String aDocTab; // zusammengesetzt fuer Table
+ String aTab;
+ BOOL bExtDoc = FALSE;
+ BOOL bNeedExtTab = FALSE;
+
+ if ( *p == '\'' && ScGlobal::UnicodeStrChr( p, SC_COMPILER_FILE_TAB_SEP ) )
+ {
+ BOOL bQuote = TRUE; // Dokumentenname ist immer quoted
+ aDocTab += *p++;
+ while ( bQuote && *p )
+ {
+ if ( *p == '\'' && *(p-1) != '\\' )
+ bQuote = FALSE;
+ else if( !(*p == '\\' && *(p+1) == '\'') )
+ aDocName += *p; // falls escaped Quote: nur Quote in den Namen
+ aDocTab += *p++;
+ }
+ aDocTab += *p; // den SC_COMPILER_FILE_TAB_SEP mitnehmen
+ if( *p++ == SC_COMPILER_FILE_TAB_SEP )
+ bExtDoc = TRUE;
+ else
+ return nRes;
+ }
+
+ USHORT nCol = 0;
+ USHORT nRow = 0;
+ USHORT nTab = 0;
+ USHORT nBits = SCA_VALID_TAB;
+ const sal_Unicode* q;
+ if ( ScGlobal::UnicodeStrChr( p, '.') )
+ {
+ nRes |= SCA_TAB_3D;
+ if ( bExtDoc )
+ nRes |= SCA_TAB_ABSOLUTE;
+ if (*p == '$')
+ nRes |= SCA_TAB_ABSOLUTE, p++;
+ BOOL bQuote = FALSE;
+ if( *p == '\'' )
+ p++, bQuote = TRUE;
+ while (*p && (*p != '.'))
+ {
+ if( bQuote && *p == '\'' )
+ {
+ p++; break;
+ }
+ aTab += *p++;
+ }
+ if( *p++ != '.' )
+ nBits = 0;
+ if ( pDoc )
+ {
+ if ( bExtDoc )
+ {
+ bExternal = TRUE;
+ aDocTab += aTab; // "'Doc'#Tab"
+ if ( !pDoc->GetTable( aDocTab, nTab ) )
+ {
+ if ( pDoc->ValidTabName( aTab ) )
+ {
+ aDocName = ScGlobal::GetAbsDocName( aDocName,
+ pDoc->GetDocumentShell() );
+ aDocTab = ScGlobal::GetDocTabName( aDocName, aTab );
+ if ( !pDoc->GetTable( aDocTab, nTab ) )
+ {
+ // erst einfuegen, wenn Rest der Ref ok
+ bNeedExtTab = TRUE;
+ nBits = 0;
+ }
+ }
+ else
+ nBits = 0;
+ }
+ }
+ else
+ {
+ if ( !pDoc->GetTable( aTab, nTab ) )
+ nBits = 0;
+ }
+ }
+ else
+ nBits = 0;
+ }
+ else
+ {
+ if ( bExtDoc )
+ return nRes; // nach Dokument muss Tabelle folgen
+ nTab = rAddr.Tab();
+ }
+ nRes |= nBits;
+
+ q = p;
+ if (*p)
+ {
+ nBits = SCA_VALID_COL;
+ if (*p == '$')
+ nBits |= SCA_COL_ABSOLUTE, p++;
+ if( CharClass::isAsciiAlpha( *p ) )
+ nCol = toupper( char(*p++) ) - 'A';
+ else
+ nBits = 0;
+ if( CharClass::isAsciiAlpha( *p ) )
+ nCol = ((nCol + 1) * 26) + (toupper( char(*p++) ) - 'A');
+ if( nCol > MAXCOL )
+ nBits = 0;
+ while( CharClass::isAsciiAlpha( *p ) )
+ p++, nBits = 0;
+ nRes |= nBits;
+ if( !nBits )
+ p = q;
+ }
+
+ q = p;
+ if (*p)
+ {
+ nBits = SCA_VALID_ROW;
+ if (*p == '$')
+ nBits |= SCA_ROW_ABSOLUTE, p++;
+ if( !CharClass::isAsciiDigit( *p ) )
+ {
+ nBits = 0;
+ nRow = USHORT(-1);
+ }
+ else
+ {
+ String aTmp( p );
+ long n = aTmp.ToInt32() - 1;
+ while (CharClass::isAsciiDigit( *p ))
+ p++;
+ if( n < 0 || n > MAXROW )
+ nBits = 0;
+ nRow = (USHORT) n;
+ }
+ nRes |= nBits;
+ if( !nBits )
+ p = q;
+ }
+ if ( bNeedExtTab )
+ {
+ if ( (nRes & SCA_VALID_ROW) && (nRes & SCA_VALID_COL)
+ && pDoc->LinkExternalTab( nTab, aDocTab, aDocName, aTab ) )
+ {
+ nRes |= SCA_VALID_TAB;
+ }
+ else
+ nRes = 0; // #NAME? statt #REF!, Dateiname bleibt erhalten
+ }
+ if ( !(nRes & SCA_VALID_ROW) && (nRes & SCA_VALID_COL)
+ && !( (nRes & SCA_TAB_3D) && (nRes & SCA_VALID_TAB)) )
+ { // keine Row, keine Tab, aber Col => DM (...), B (...) o.ae.
+ nRes = 0;
+ }
+ if( !*p )
+ {
+ USHORT nMask = nRes & ( SCA_VALID_ROW | SCA_VALID_COL | SCA_VALID_TAB );
+ if( nMask == ( SCA_VALID_ROW | SCA_VALID_COL | SCA_VALID_TAB ) )
+ nRes |= SCA_VALID;
+ }
+ else
+ nRes = 0;
+ rAddr.Set( nCol, nRow, nTab );
+ return nRes;
+}
+
+
+// ConvertSingleRef mit sal_Unicode* muss vorher stehen!!!
+
+BOOL ConvertSingleRef( ScDocument* pDoc, const String& rRefString,
+ USHORT nDefTab, ScRefTripel& rRefTripel )
+{
+ BOOL bExternal = FALSE;
+ ScAddress aAddr( 0, 0, nDefTab );
+ USHORT nRes = lcl_ConvertSingleRef( bExternal, rRefString.GetBuffer(), pDoc, aAddr );
+ if( nRes & SCA_VALID )
+ {
+ rRefTripel.Put( aAddr.Col(), aAddr.Row(), aAddr.Tab(),
+ BOOL( ( nRes & SCA_COL_ABSOLUTE ) == 0 ),
+ BOOL( ( nRes & SCA_ROW_ABSOLUTE ) == 0 ),
+ BOOL( ( nRes & SCA_TAB_ABSOLUTE ) == 0 ) );
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+
+BOOL ConvertDoubleRef( ScDocument* pDoc, const String& rRefString, USHORT nDefTab,
+ ScRefTripel& rStartRefTripel, ScRefTripel& rEndRefTripel )
+{
+ BOOL bRet = FALSE;
+ xub_StrLen nPos = rRefString.Search(':');
+ if (nPos != STRING_NOTFOUND)
+ {
+ String aTmp( rRefString );
+ sal_Unicode* p = aTmp.GetBufferAccess();
+ p[ nPos ] = 0;
+ if ( ConvertSingleRef( pDoc, p, nDefTab, rStartRefTripel ) )
+ {
+ nDefTab = rStartRefTripel.GetTab();
+ bRet = ConvertSingleRef( pDoc, p + nPos + 1, nDefTab, rEndRefTripel );
+ }
+ }
+ return bRet;
+}
+
+
+USHORT ScAddress::Parse( const String& r, ScDocument* pDoc )
+{
+ BOOL bExternal = FALSE;
+ return lcl_ConvertSingleRef( bExternal, r.GetBuffer(), pDoc, *this );
+}
+
+BOOL ScRange::Intersects( const ScRange& r ) const
+{
+ return !(
+ Min( aEnd.Col(), r.aEnd.Col() ) < Max( aStart.Col(), r.aStart.Col() )
+ || Min( aEnd.Row(), r.aEnd.Row() ) < Max( aStart.Row(), r.aStart.Row() )
+ || Min( aEnd.Tab(), r.aEnd.Tab() ) < Max( aStart.Tab(), r.aStart.Tab() )
+ );
+}
+
+void ScRange::Justify()
+{
+ USHORT nTemp;
+ if ( aEnd.Col() < (nTemp = aStart.Col()) )
+ {
+ aStart.SetCol(aEnd.Col()); aEnd.SetCol(nTemp);
+ }
+ if ( aEnd.Row() < (nTemp = aStart.Row()) )
+ {
+ aStart.SetRow(aEnd.Row()); aEnd.SetRow(nTemp);
+ }
+ if ( aEnd.Tab() < (nTemp = aStart.Tab()) )
+ {
+ aStart.SetTab(aEnd.Tab()); aEnd.SetTab(nTemp);
+ }
+}
+
+void ScRange::ExtendOne()
+{
+ // Range fuer Rahmen etc. in X und Y Richtung um 1 erweitern
+
+ USHORT nVal;
+
+ if ((nVal = aStart.Col()) > 0)
+ aStart.SetCol(nVal-1);
+ if ((nVal = aStart.Row()) > 0)
+ aStart.SetRow(nVal-1);
+
+ if ((nVal = aEnd.Col()) < MAXCOL)
+ aEnd.SetCol(nVal+1);
+ if ((nVal = aEnd.Row()) < MAXROW)
+ aEnd.SetRow(nVal+1);
+}
+
+USHORT ScRange::Parse( const String& r, ScDocument* pDoc )
+{
+ USHORT nRes1 = 0, nRes2 = 0;
+ xub_StrLen nTmp = 0;
+ xub_StrLen nPos = STRING_NOTFOUND;
+ while ( (nTmp = r.Search( ':', nTmp )) != STRING_NOTFOUND )
+ nPos = nTmp++; // der letzte zaehlt, koennte 'd:\...'!a1:a2 sein
+ if (nPos != STRING_NOTFOUND)
+ {
+ String aTmp( r );
+ sal_Unicode* p = aTmp.GetBufferAccess();
+ p[ nPos ] = 0;
+ BOOL bExternal = FALSE;
+ if( nRes1 = lcl_ConvertSingleRef( bExternal, p, pDoc, aStart ) )
+ {
+ aEnd = aStart; // die Tab _muss_ gleich sein, so ist`s weniger Code
+ if ( nRes2 = lcl_ConvertSingleRef( bExternal, p + nPos+ 1, pDoc, aEnd ) )
+ {
+ if ( bExternal && aStart.Tab() != aEnd.Tab() )
+ nRes2 &= ~SCA_VALID_TAB; // #REF!
+ else
+ {
+ // PutInOrder / Justify
+ USHORT nTemp, nMask, nBits1, nBits2;
+ if ( aEnd.Col() < (nTemp = aStart.Col()) )
+ {
+ aStart.SetCol(aEnd.Col()); aEnd.SetCol(nTemp);
+ nMask = (SCA_VALID_COL | SCA_COL_ABSOLUTE);
+ nBits1 = nRes1 & nMask;
+ nBits2 = nRes2 & nMask;
+ nRes1 = (nRes1 & ~nMask) | nBits2;
+ nRes2 = (nRes2 & ~nMask) | nBits1;
+ }
+ if ( aEnd.Row() < (nTemp = aStart.Row()) )
+ {
+ aStart.SetRow(aEnd.Row()); aEnd.SetRow(nTemp);
+ nMask = (SCA_VALID_ROW | SCA_ROW_ABSOLUTE);
+ nBits1 = nRes1 & nMask;
+ nBits2 = nRes2 & nMask;
+ nRes1 = (nRes1 & ~nMask) | nBits2;
+ nRes2 = (nRes2 & ~nMask) | nBits1;
+ }
+ if ( aEnd.Tab() < (nTemp = aStart.Tab()) )
+ {
+ aStart.SetTab(aEnd.Tab()); aEnd.SetTab(nTemp);
+ nMask = (SCA_VALID_TAB | SCA_TAB_ABSOLUTE | SCA_TAB_3D);
+ nBits1 = nRes1 & nMask;
+ nBits2 = nRes2 & nMask;
+ nRes1 = (nRes1 & ~nMask) | nBits2;
+ nRes2 = (nRes2 & ~nMask) | nBits1;
+ }
+ if ( ((nRes1 & ( SCA_TAB_ABSOLUTE | SCA_TAB_3D ))
+ == ( SCA_TAB_ABSOLUTE | SCA_TAB_3D ))
+ && !(nRes2 & SCA_TAB_3D) )
+ nRes2 |= SCA_TAB_ABSOLUTE;
+ }
+ }
+ else
+ nRes1 = 0; // #38840# keine Tokens aus halben Sachen
+ }
+ }
+ nRes1 = ( ( nRes1 | nRes2 ) & SCA_VALID )
+ | nRes1
+ | ( ( nRes2 & 0x070F ) << 4 );
+ return nRes1;
+}
+
+USHORT ScRange::ParseAny( const String& r, ScDocument* pDoc )
+{
+ USHORT nRet = Parse( r, pDoc );
+ const USHORT nValid = SCA_VALID | SCA_VALID_COL2 | SCA_VALID_ROW2 | SCA_VALID_TAB2;
+ if ( (nRet & nValid) != nValid )
+ {
+ ScAddress aAdr;
+ nRet = aAdr.Parse( r, pDoc );
+ if ( nRet & SCA_VALID )
+ aStart = aEnd = aAdr;
+ }
+ return nRet;
+}
+
+void ScAddress::Format( String& r, USHORT nFlags, ScDocument* pDoc ) const
+{
+ USHORT nTab = Tab();
+ USHORT nCol = Col();
+ r.Erase();
+ if( nFlags & SCA_VALID )
+ nFlags |= ( SCA_VALID_ROW | SCA_VALID_COL | SCA_VALID_TAB );
+ if( pDoc && (nFlags & SCA_VALID_TAB ) )
+ {
+ if ( nTab >= pDoc->GetTableCount() )
+ {
+ r = ScGlobal::GetRscString( STR_NOREF_STR );
+ return;
+ }
+// if( nFlags & ( SCA_TAB_ABSOLUTE | SCA_TAB_3D ) )
+ if( nFlags & SCA_TAB_3D )
+ {
+ String aTabName;
+ pDoc->GetName( nTab, aTabName );
+
+ // externe Referenzen (wie in ScCompiler::MakeTabStr)
+ String aDoc;
+ if ( aTabName.GetChar(0) == '\'' )
+ { // "'Doc'#Tab"
+ xub_StrLen nPos, nLen = 1;
+ while( (nPos = aTabName.Search( '\'', nLen ))
+ != STRING_NOTFOUND )
+ nLen = nPos + 1;
+ if ( aTabName.GetChar(nLen) == SC_COMPILER_FILE_TAB_SEP )
+ {
+ aDoc = aTabName.Copy( 0, nLen + 1 );
+ aTabName.Erase( 0, nLen + 1 );
+ }
+ }
+ r += aDoc;
+
+ if( nFlags & SCA_TAB_ABSOLUTE )
+ r += '$';
+ ScCompiler::CheckTabQuotes( aTabName );
+ r += aTabName;
+ r += '.';
+ }
+ }
+ if( nFlags & SCA_VALID_COL )
+ {
+ if( nFlags & SCA_COL_ABSOLUTE )
+ r += '$';
+ if ( nCol < 26 )
+ r += (sal_Unicode) ( 'A' + nCol );
+ else
+ {
+ r += (sal_Unicode) ( 'A' + ( nCol / 26 ) - 1 );
+ r += (sal_Unicode) ( 'A' + ( nCol % 26 ) );
+ }
+ }
+ if( nFlags & SCA_VALID_ROW )
+ {
+ if ( nFlags & SCA_ROW_ABSOLUTE )
+ r += '$';
+ r += String::CreateFromInt32( Row()+1 );
+ }
+}
+
+
+void ScRange::Format( String& r, USHORT nFlags, ScDocument* pDoc ) const
+{
+ if( !( nFlags & SCA_VALID ) )
+ r = ScGlobal::GetRscString( STR_NOREF_STR );
+ else
+ {
+ BOOL bOneTab = (aStart.Tab() == aEnd.Tab());
+ if ( !bOneTab )
+ nFlags |= SCA_TAB_3D;
+ aStart.Format( r, nFlags, pDoc );
+ if( aStart != aEnd )
+ {
+ String aName;
+ nFlags = ( nFlags & SCA_VALID ) | ( ( nFlags >> 4 ) & 0x070F );
+ if ( bOneTab )
+ pDoc = NULL;
+ else
+ nFlags |= SCA_TAB_3D;
+ aEnd.Format( aName, nFlags, pDoc );
+ r += ':';
+ r += aName;
+ }
+ }
+}
+
+BOOL ScAddress::Move( short dx, short dy, short dz, ScDocument* pDoc )
+{
+ short nMaxTab = pDoc ? pDoc->GetTableCount() : MAXTAB+1;
+ dx = Col() + dx;
+ dy = Row() + dy;
+ dz = Tab() + dz;
+ BOOL bValid = TRUE;
+ if( dx < 0 )
+ dx = 0, bValid = FALSE;
+ else if( dx > MAXCOL )
+ dx = MAXCOL, bValid =FALSE;
+ if( dy < 0 )
+ dy = 0, bValid = FALSE;
+ else if( dy > MAXROW )
+ dy = MAXROW, bValid =FALSE;
+ if( dz < 0 )
+ dz = 0, bValid = FALSE;
+ else if( dz >= nMaxTab )
+ dz = nMaxTab-1, bValid =FALSE;
+ Set( dx, dy, dz );
+ return bValid;
+}
+
+BOOL ScRange::Move( short dx, short dy, short dz, ScDocument* pDoc )
+{
+ // Einfahces &, damit beides ausgefuehrt wird!!
+ return aStart.Move( dx, dy, dz, pDoc ) & aEnd.Move( dx, dy, dz, pDoc );
+}
+
+
diff --git a/sc/source/core/data/globalx.cxx b/sc/source/core/data/globalx.cxx
new file mode 100644
index 000000000000..459c076fba80
--- /dev/null
+++ b/sc/source/core/data/globalx.cxx
@@ -0,0 +1,162 @@
+/*************************************************************************
+ *
+ * $RCSfile: globalx.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+
+#include "callform.hxx"
+#include "global.hxx"
+
+#ifndef _SFX_INIMGR_HXX
+#include <sfx2/inimgr.hxx>
+#endif
+#ifndef _URLOBJ_HXX
+#include <tools/urlobj.hxx>
+#endif
+#ifndef _UCBHELPER_CONTENTBROKER_HXX
+#include <ucbhelper/contentbroker.hxx>
+#endif
+#ifndef _UCBHELPER_CONTENT_HXX
+#include <ucbhelper/content.hxx>
+#endif
+
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+#include <com/sun/star/ucb/XContentAccess.hpp>
+
+#pragma hdrstop
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::ucb;
+
+
+// static
+void ScGlobal::InitAddIns()
+{
+ // multi paths separated by semicolons
+ String aMultiPath( SFX_INIMANAGER()->Get( SFX_KEY_ADDINS_PATH ) );
+ if ( aMultiPath.Len() > 0 )
+ {
+ xub_StrLen nTokens = aMultiPath.GetTokenCount( ';' );
+ xub_StrLen nIndex = 0;
+ for ( xub_StrLen j=0; j<nTokens; j++ )
+ {
+ String aPath( aMultiPath.GetToken( 0, ';', nIndex ) );
+ if ( aPath.Len() > 0 )
+ {
+ INetURLObject aObj;
+ aObj.SetSmartURL( aPath );
+ aObj.setFinalSlash();
+ try
+ {
+ ::ucb::Content aCnt( aObj.GetMainURL(),
+ Reference< XCommandEnvironment > () );
+ Reference< sdbc::XResultSet > xResultSet;
+ Sequence< rtl::OUString > aProps;
+ try
+ {
+ xResultSet = aCnt.createCursor(
+ aProps, ::ucb::INCLUDE_DOCUMENTS_ONLY );
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "create cursor failed!" );
+ }
+
+ if ( xResultSet.is() )
+ {
+ Reference< sdbc::XRow > xRow( xResultSet, UNO_QUERY );
+ Reference< XContentAccess >
+ xContentAccess( xResultSet, UNO_QUERY );
+ try
+ {
+ if ( xResultSet->first() )
+ {
+ do
+ {
+ rtl::OUString aId( xContentAccess->queryContentIdentfierString() );
+ InitExternalFunc( aId );
+ }
+ while ( xResultSet->next() );
+ }
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "ResultSetException catched!" );
+ }
+ }
+ }
+ catch ( Exception& )
+ {
+ DBG_ERRORFILE( "Exception catched!" );
+ }
+ catch ( ... )
+ {
+
+ DBG_ERRORFILE( "unexpected exception caught!" );
+ }
+ }
+ }
+ }
+}
+
+
+
diff --git a/sc/source/core/data/makefile.mk b/sc/source/core/data/makefile.mk
new file mode 100644
index 000000000000..3662b25b19c3
--- /dev/null
+++ b/sc/source/core/data/makefile.mk
@@ -0,0 +1,203 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+
+PRJ=..$/..$/..
+
+PRJNAME=sc
+TARGET=data
+
+PROJECTPCH4DLL=TRUE
+PROJECTPCH=core_pch
+PROJECTPCHSOURCE=..\pch\core_pch
+
+AUTOSEG=true
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : scpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sc.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Files --------------------------------------------------------
+
+CXXFILES = \
+ bclist.cxx \
+ bcaslot.cxx \
+ docpool.cxx \
+ column.cxx \
+ column2.cxx \
+ column3.cxx \
+ document.cxx \
+ documen2.cxx \
+ documen3.cxx \
+ documen4.cxx \
+ documen5.cxx \
+ documen6.cxx \
+ documen7.cxx \
+ documen8.cxx \
+ documen9.cxx \
+ fillinfo.cxx \
+ table1.cxx \
+ table2.cxx \
+ table3.cxx \
+ table4.cxx \
+ table5.cxx \
+ table6.cxx \
+ olinetab.cxx \
+ patattr.cxx \
+ cell.cxx \
+ cell2.cxx \
+ attarray.cxx \
+ attrib.cxx \
+ global.cxx \
+ global2.cxx \
+ globalx.cxx \
+ markarr.cxx \
+ markdata.cxx \
+ dociter.cxx \
+ drwlayer.cxx \
+ userdat.cxx \
+ drawpage.cxx \
+ stlsheet.cxx \
+ stlpool.cxx \
+ dptabsrc.cxx \
+ dptabres.cxx \
+ dptabdat.cxx \
+ dpshttab.cxx \
+ dpsdbtab.cxx \
+ dpoutput.cxx \
+ dpobject.cxx \
+ dpsave.cxx \
+ pivot.cxx \
+ pivot2.cxx \
+ pagepar.cxx \
+ conditio.cxx \
+ validat.cxx
+
+SLOFILES = \
+ $(SLO)$/bclist.obj \
+ $(SLO)$/bcaslot.obj \
+ $(SLO)$/docpool.obj \
+ $(SLO)$/column.obj \
+ $(SLO)$/column2.obj \
+ $(SLO)$/column3.obj \
+ $(SLO)$/document.obj \
+ $(SLO)$/documen2.obj \
+ $(SLO)$/documen3.obj \
+ $(SLO)$/documen4.obj \
+ $(SLO)$/documen5.obj \
+ $(SLO)$/documen6.obj \
+ $(SLO)$/documen7.obj \
+ $(SLO)$/documen8.obj \
+ $(SLO)$/documen9.obj \
+ $(SLO)$/fillinfo.obj \
+ $(SLO)$/table1.obj \
+ $(SLO)$/table2.obj \
+ $(SLO)$/table3.obj \
+ $(SLO)$/table4.obj \
+ $(SLO)$/table5.obj \
+ $(SLO)$/table6.obj \
+ $(SLO)$/olinetab.obj \
+ $(SLO)$/patattr.obj \
+ $(SLO)$/cell.obj \
+ $(SLO)$/cell2.obj \
+ $(SLO)$/attarray.obj \
+ $(SLO)$/attrib.obj \
+ $(SLO)$/global.obj \
+ $(SLO)$/global2.obj \
+ $(SLO)$/globalx.obj \
+ $(SLO)$/markarr.obj \
+ $(SLO)$/markdata.obj \
+ $(SLO)$/dociter.obj \
+ $(SLO)$/drwlayer.obj \
+ $(SLO)$/userdat.obj \
+ $(SLO)$/drawpage.obj \
+ $(SLO)$/stlsheet.obj \
+ $(SLO)$/stlpool.obj \
+ $(SLO)$/dptabsrc.obj \
+ $(SLO)$/dptabres.obj \
+ $(SLO)$/dptabdat.obj \
+ $(SLO)$/dpshttab.obj \
+ $(SLO)$/dpsdbtab.obj \
+ $(SLO)$/dpoutput.obj \
+ $(SLO)$/dpobject.obj \
+ $(SLO)$/dpsave.obj \
+ $(SLO)$/pivot.obj \
+ $(SLO)$/pivot2.obj \
+ $(SLO)$/pagepar.obj \
+ $(SLO)$/conditio.obj \
+ $(SLO)$/validat.obj
+
+EXCEPTIONSFILES= \
+ $(SLO)$/documen6.obj \
+ $(SLO)$/dpsdbtab.obj \
+ $(SLO)$/dpobject.obj \
+ $(SLO)$/dpoutput.obj \
+ $(SLO)$/dpsave.obj \
+ $(SLO)$/globalx.obj
+
+# --- Tagets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/sc/source/core/data/markarr.cxx b/sc/source/core/data/markarr.cxx
new file mode 100644
index 000000000000..9615aa644e4f
--- /dev/null
+++ b/sc/source/core/data/markarr.cxx
@@ -0,0 +1,430 @@
+/*************************************************************************
+ *
+ * $RCSfile: markarr.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <tools/debug.hxx>
+
+#include "markarr.hxx"
+#include "global.hxx"
+
+// STATIC DATA -----------------------------------------------------------
+
+//------------------------------------------------------------------------
+
+ScMarkArray::ScMarkArray()
+{
+ nCount = 1;
+ pData = new ScMarkEntry[1];
+ if (pData)
+ {
+ pData[0].nRow = MAXROW;
+ pData[0].bMarked = FALSE;
+ }
+}
+
+//------------------------------------------------------------------------
+
+ScMarkArray::~ScMarkArray()
+{
+ if (pData)
+ delete[] pData;
+}
+
+//------------------------------------------------------------------------
+
+void ScMarkArray::Reset( BOOL bMarked )
+{
+ if (pData)
+ {
+ delete[] pData;
+
+ nCount = 1;
+ pData = new ScMarkEntry[1];
+ if (pData)
+ {
+ pData[0].nRow = MAXROW;
+ pData[0].bMarked = bMarked;
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScMarkArray::Search( USHORT nRow, short& nIndex ) const
+{
+ short nLo = 0;
+ short nHi = ((short) nCount) - 1;
+ short nStartRow = 0;
+ short nEndRow = 0;
+ short i = 0;
+ BOOL bFound = (nCount == 1);
+ if (pData)
+ {
+ while ( !bFound && nLo <= nHi )
+ {
+ i = (nLo + nHi) / 2;
+ if (i > 0)
+ nStartRow = (short) pData[i - 1].nRow;
+ else
+ nStartRow = -1;
+ nEndRow = (short) pData[i].nRow;
+ if (nEndRow < (short) nRow)
+ nLo = ++i;
+ else
+ if (nStartRow >= (short) nRow)
+ nHi = --i;
+ else
+ bFound = TRUE;
+ }
+ }
+ else
+ bFound = FALSE;
+
+ if (bFound)
+ nIndex=i;
+ else
+ nIndex=0;
+ return bFound;
+}
+
+BOOL ScMarkArray::GetMark( USHORT nRow ) const
+{
+ short i;
+ if (Search( nRow, i ))
+ return pData[i].bMarked;
+ else
+ return FALSE;
+
+}
+
+//------------------------------------------------------------------------
+
+void ScMarkArray::SetMark( USHORT nRow, BOOL bMarked )
+{
+ SetMarkArea( nRow, nRow, bMarked );
+}
+
+void ScMarkArray::SetMarkArea( USHORT nStartRow, USHORT nEndRow, BOOL bMarked )
+{
+ if ((nStartRow >= 0 && nStartRow <= MAXROW) && (nEndRow >= 0 && nEndRow <= MAXROW))
+ {
+ if ((nStartRow == 0) && (nEndRow == MAXROW))
+ {
+ Reset(bMarked);
+ }
+ else
+ {
+ USHORT nNewCount = 0;
+ ScMarkEntry* pNewData = new ScMarkEntry[nCount + 2];
+ if (pNewData)
+ {
+ USHORT ni = 0;
+ if (nStartRow > 0)
+ {
+ // Anfangsbereich kopieren
+ while (pData[ni].nRow < nStartRow)
+ {
+ pNewData[ni].nRow = pData[ni].nRow;
+ pNewData[ni].bMarked = pData[ni].bMarked;
+ nNewCount++;
+ ni++;
+ }
+ if ((pData[ni].bMarked != bMarked) &&
+ ((ni==0) ? TRUE : (pData[ni - 1].nRow < nStartRow - 1)))
+ {
+ // Eintrag splitten
+ pNewData[nNewCount].nRow = nStartRow - 1;
+ pNewData[nNewCount].bMarked = pData[ni].bMarked;
+ nNewCount++;
+ ni++;
+ }
+ if (ni > 0)
+ if (pData[ni-1].bMarked == bMarked) // zusammenfassen
+ {
+ ni--;
+ nNewCount--;
+ }
+ } // if StartRow > 0
+
+ // Bereich setzen
+ pNewData[nNewCount].nRow = nEndRow;
+ pNewData[nNewCount].bMarked = bMarked;
+ nNewCount++;
+
+ USHORT nj = 0;
+ if (nEndRow < MAXROW)
+ {
+ // mittleren Bereich ueberspringen
+ while (pData[nj].nRow <= nEndRow) nj++;
+ if (pData[nj].bMarked == bMarked)
+ {
+ // Eintrag zusammenfassen
+ pNewData[nNewCount - 1].nRow = pData[nj].nRow;
+ nj++;
+ }
+ // Den Endbereich kopieren
+ while (nj < nCount)
+ {
+ pNewData[nNewCount].nRow = pData[nj].nRow;
+ pNewData[nNewCount].bMarked = pData[nj].bMarked;
+ nNewCount++;
+ nj++;
+ }
+ } // if EndRow < MaxRow
+ // Zeiger umsetzen
+ delete[] pData;
+ nCount = nNewCount;
+ pData = pNewData;
+ }
+ }
+ }
+// InfoBox(0, String(nCount) + String(" Eintraege") ).Execute();
+}
+
+void ScMarkArray::DeleteArea(USHORT nStartRow, USHORT nEndRow)
+{
+ SetMarkArea(nStartRow, nEndRow, FALSE);
+}
+
+BOOL ScMarkArray::IsAllMarked( USHORT nStartRow, USHORT nEndRow ) const
+{
+ short nStartIndex;
+ short nEndIndex;
+
+ if (Search( nStartRow, nStartIndex ))
+ if (pData[nStartIndex].bMarked)
+ if (Search( nEndRow, nEndIndex ))
+ if (nEndIndex==nStartIndex)
+ return TRUE;
+
+ return FALSE;
+}
+
+BOOL ScMarkArray::HasOneMark( USHORT& rStartRow, USHORT& rEndRow ) const
+{
+ BOOL bRet = FALSE;
+ if ( nCount == 1 )
+ {
+ if ( pData[0].bMarked )
+ {
+ rStartRow = 0;
+ rEndRow = MAXROW;
+ bRet = TRUE;
+ }
+ }
+ else if ( nCount == 2 )
+ {
+ if ( pData[0].bMarked )
+ {
+ rStartRow = 0;
+ rEndRow = pData[0].nRow;
+ }
+ else
+ {
+ rStartRow = pData[0].nRow + 1;
+ rEndRow = MAXROW;
+ }
+ bRet = TRUE;
+ }
+ else if ( nCount == 3 )
+ {
+ if ( pData[1].bMarked )
+ {
+ rStartRow = pData[0].nRow + 1;
+ rEndRow = pData[1].nRow;
+ bRet = TRUE;
+ }
+ }
+ return bRet;
+}
+
+BOOL ScMarkArray::HasMarks() const
+{
+ return ( nCount > 1 || pData[0].bMarked );
+}
+
+void ScMarkArray::SwapCol(ScMarkArray& rMarkArray)
+{
+ USHORT nTemp = rMarkArray.nCount;
+ rMarkArray.nCount = nCount;
+ nCount = nTemp;
+
+ ScMarkEntry* pTemp = rMarkArray.pData;
+ rMarkArray.pData = pData;
+ pData = pTemp;
+}
+
+void ScMarkArray::MoveTo(USHORT nStartRow, USHORT nEndRow, ScMarkArray& rMarkArray)
+{
+ USHORT nStart = nStartRow;
+ for (USHORT i = 0; i < nCount; i++)
+ {
+ if ((pData[i].nRow >= nStartRow) && ((i==0) ? TRUE : pData[i-1].nRow < nEndRow))
+ {
+ rMarkArray.SetMarkArea(nStart, Min(pData[i].nRow,nEndRow), pData[i].bMarked);
+ }
+ nStart = Max((USHORT)nStart, (USHORT)(pData[i].nRow + 1) );
+ }
+ DeleteArea(nStartRow, nEndRow);
+}
+
+void ScMarkArray::CopyMarksTo( ScMarkArray& rDestMarkArray ) const
+{
+ if (rDestMarkArray.pData)
+ delete rDestMarkArray.pData;
+
+ if (pData)
+ {
+ rDestMarkArray.pData = new ScMarkEntry[nCount];
+ memmove( rDestMarkArray.pData, pData, nCount * sizeof(ScMarkEntry) );
+ }
+ else
+ rDestMarkArray.pData = NULL;
+
+ rDestMarkArray.nCount = nCount;
+}
+
+short ScMarkArray::GetNextMarked( short nRow, BOOL bUp ) const
+{
+ short nRet = nRow;
+ if (VALIDROW(nRow))
+ {
+ short nIndex;
+ Search(nRow, nIndex);
+ if (!pData[nIndex].bMarked)
+ {
+ if (bUp)
+ {
+ if (nIndex>0)
+ nRet = pData[nIndex-1].nRow;
+ else
+ nRet = -1;
+ }
+ else
+ nRet = pData[nIndex].nRow + 1;
+ }
+ }
+ return nRet;
+}
+
+USHORT ScMarkArray::GetMarkEnd( USHORT nRow, BOOL bUp ) const
+{
+ USHORT nRet;
+ short nIndex;
+ Search(nRow, nIndex);
+ DBG_ASSERT( pData[nIndex].bMarked, "GetMarkEnd ohne bMarked" );
+ if (bUp)
+ {
+ if (nIndex>0)
+ nRet = pData[nIndex-1].nRow + 1;
+ else
+ nRet = 0;
+ }
+ else
+ nRet = pData[nIndex].nRow;
+
+ return nRet;
+}
+
+//
+// -------------- Iterator ----------------------------------------------
+//
+
+ScMarkArrayIter::ScMarkArrayIter( const ScMarkArray* pNewArray ) :
+ pArray( pNewArray ),
+ nPos( 0 )
+{
+}
+
+ScMarkArrayIter::~ScMarkArrayIter()
+{
+}
+
+BOOL ScMarkArrayIter::Next( USHORT& rTop, USHORT& rBottom )
+{
+ if ( nPos >= pArray->nCount )
+ return FALSE;
+ while (!pArray->pData[nPos].bMarked)
+ {
+ ++nPos;
+ if ( nPos >= pArray->nCount )
+ return FALSE;
+ }
+ rBottom = pArray->pData[nPos].nRow;
+ if (nPos==0)
+ rTop = 0;
+ else
+ rTop = pArray->pData[nPos-1].nRow + 1;
+ ++nPos;
+ return TRUE;
+}
+
+
+
+
+
diff --git a/sc/source/core/data/markdata.cxx b/sc/source/core/data/markdata.cxx
new file mode 100644
index 000000000000..b9a9fb918e9d
--- /dev/null
+++ b/sc/source/core/data/markdata.cxx
@@ -0,0 +1,606 @@
+/*************************************************************************
+ *
+ * $RCSfile: markdata.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <tools/debug.hxx>
+
+#include "markdata.hxx"
+#include "markarr.hxx"
+#include "rangelst.hxx"
+
+// STATIC DATA -----------------------------------------------------------
+
+//------------------------------------------------------------------------
+
+ScMarkData::ScMarkData() :
+ pMultiSel( NULL )
+{
+ for (USHORT i=0; i<=MAXTAB; i++)
+ bTabMarked[i] = FALSE;
+
+ ResetMark();
+}
+
+ScMarkData::ScMarkData(const ScMarkData& rData) :
+ pMultiSel( NULL ),
+ aMarkRange( rData.aMarkRange ),
+ aMultiRange( rData.aMultiRange )
+{
+ bMarked = rData.bMarked;
+ bMultiMarked = rData.bMultiMarked;
+ bMarking = rData.bMarking;
+ bMarkIsNeg = rData.bMarkIsNeg;
+
+ USHORT i;
+ for (i=0; i<=MAXTAB; i++)
+ bTabMarked[i] = rData.bTabMarked[i];
+
+ if (rData.pMultiSel)
+ {
+ pMultiSel = new ScMarkArray[MAXCOL+1];
+ for (i=0; i<=MAXCOL; i++)
+ rData.pMultiSel[i].CopyMarksTo( pMultiSel[i] );
+ }
+}
+
+ScMarkData& ScMarkData::operator=(const ScMarkData& rData)
+{
+ if ( &rData == this )
+ return *this;
+
+ delete[] pMultiSel;
+ pMultiSel = NULL;
+
+ aMarkRange = rData.aMarkRange;
+ aMultiRange = rData.aMultiRange;
+ bMarked = rData.bMarked;
+ bMultiMarked = rData.bMultiMarked;
+ bMarking = rData.bMarking;
+ bMarkIsNeg = rData.bMarkIsNeg;
+
+ USHORT i;
+ for (i=0; i<=MAXTAB; i++)
+ bTabMarked[i] = rData.bTabMarked[i];
+
+ if (rData.pMultiSel)
+ {
+ pMultiSel = new ScMarkArray[MAXCOL+1];
+ for (i=0; i<=MAXCOL; i++)
+ rData.pMultiSel[i].CopyMarksTo( pMultiSel[i] );
+ }
+
+ return *this;
+}
+
+ScMarkData::~ScMarkData()
+{
+ delete[] pMultiSel;
+}
+
+void ScMarkData::ResetMark()
+{
+ delete[] pMultiSel;
+ pMultiSel = NULL;
+
+ bMarked = bMultiMarked = FALSE;
+ bMarking = bMarkIsNeg = FALSE;
+}
+
+void ScMarkData::SetMarkArea( const ScRange& rRange )
+{
+ aMarkRange = rRange;
+ aMarkRange.Justify();
+ if ( !bMarked )
+ {
+ // #77987# Upon creation of a document ScFormatShell GetTextAttrState
+ // may query (default) attributes although no sheet is marked yet.
+ // => mark that one.
+ if ( !GetSelectCount() )
+ bTabMarked[ aMarkRange.aStart.Tab() ] = TRUE;
+ bMarked = TRUE;
+ }
+}
+
+void ScMarkData::GetMarkArea( ScRange& rRange ) const
+{
+ rRange = aMarkRange; //! inline ?
+}
+
+void ScMarkData::GetMultiMarkArea( ScRange& rRange ) const
+{
+ rRange = aMultiRange;
+}
+
+void ScMarkData::SetMultiMarkArea( const ScRange& rRange, BOOL bMark )
+{
+ if (!pMultiSel)
+ pMultiSel = new ScMarkArray[MAXCOL+1];
+
+ USHORT nStartCol = rRange.aStart.Col();
+ USHORT nStartRow = rRange.aStart.Row();
+ USHORT nEndCol = rRange.aEnd.Col();
+ USHORT nEndRow = rRange.aEnd.Row();
+ PutInOrder( nStartRow, nEndRow );
+ PutInOrder( nStartCol, nEndCol );
+
+ USHORT nCol;
+ for (nCol=nStartCol; nCol<=nEndCol; nCol++)
+ pMultiSel[nCol].SetMarkArea( nStartRow, nEndRow, bMark );
+
+ if ( bMultiMarked ) // aMultiRange updaten
+ {
+ if ( nStartCol < aMultiRange.aStart.Col() )
+ aMultiRange.aStart.SetCol( nStartCol );
+ if ( nStartRow < aMultiRange.aStart.Row() )
+ aMultiRange.aStart.SetRow( nStartRow );
+ if ( nEndCol > aMultiRange.aEnd.Col() )
+ aMultiRange.aEnd.SetCol( nEndCol );
+ if ( nEndRow > aMultiRange.aEnd.Row() )
+ aMultiRange.aEnd.SetRow( nEndRow );
+ }
+ else
+ {
+ aMultiRange = rRange; // neu
+ bMultiMarked = TRUE;
+ }
+}
+
+void ScMarkData::SetAreaTab( USHORT nTab )
+{
+ aMarkRange.aStart.SetTab(nTab);
+ aMarkRange.aEnd.SetTab(nTab);
+ aMultiRange.aStart.SetTab(nTab);
+ aMultiRange.aEnd.SetTab(nTab);
+}
+
+void ScMarkData::SelectOneTable( USHORT nTab )
+{
+ for (USHORT i=0; i<=MAXTAB; i++)
+ bTabMarked[i] = ( nTab == i );
+}
+
+USHORT ScMarkData::GetSelectCount() const
+{
+ USHORT nCount = 0;
+ for (USHORT i=0; i<=MAXTAB; i++)
+ if (bTabMarked[i])
+ ++nCount;
+
+ return nCount;
+}
+
+USHORT ScMarkData::GetFirstSelected() const
+{
+ for (USHORT i=0; i<=MAXTAB; i++)
+ if (bTabMarked[i])
+ return i;
+
+ DBG_ERROR("GetFirstSelected: keine markiert");
+ return 0;
+}
+
+void ScMarkData::MarkToMulti()
+{
+ if ( bMarked && !bMarking )
+ {
+ SetMultiMarkArea( aMarkRange, !bMarkIsNeg );
+ bMarked = FALSE;
+ }
+}
+
+void ScMarkData::MarkToSimple()
+{
+ if ( bMultiMarked && !bMarking )
+ {
+ DBG_ASSERT(pMultiSel, "bMultiMarked, aber pMultiSel == 0");
+
+ if (bMarked)
+ MarkToMulti();
+
+ ScRange aNew = aMultiRange;
+
+ BOOL bOk = FALSE;
+ USHORT nStartCol = aNew.aStart.Col();
+ USHORT nEndCol = aNew.aEnd.Col();
+
+ while ( nStartCol < nEndCol && !pMultiSel[nStartCol].HasMarks() )
+ ++nStartCol;
+ while ( nStartCol < nEndCol && !pMultiSel[nEndCol].HasMarks() )
+ --nEndCol;
+
+ // Zeilen werden nur aus MarkArray genommen
+ USHORT nStartRow, nEndRow;
+ if ( pMultiSel[nStartCol].HasOneMark( nStartRow, nEndRow ) )
+ {
+ bOk = TRUE;
+ USHORT nCmpStart, nCmpEnd;
+ for (USHORT nCol=nStartCol+1; nCol<=nEndCol && bOk; nCol++)
+ if ( !pMultiSel[nCol].HasOneMark( nCmpStart, nCmpEnd )
+ || nCmpStart != nStartRow || nCmpEnd != nEndRow )
+ bOk = FALSE;
+ }
+
+ if (bOk)
+ {
+ aNew.aStart.SetCol(nStartCol);
+ aNew.aStart.SetRow(nStartRow);
+ aNew.aEnd.SetCol(nEndCol);
+ aNew.aEnd.SetRow(nEndRow);
+
+ ResetMark();
+ aMarkRange = aNew;
+ bMarked = TRUE;
+ bMarkIsNeg = FALSE;
+ }
+ }
+}
+
+BOOL ScMarkData::IsCellMarked( USHORT nCol, USHORT nRow, BOOL bNoSimple ) const
+{
+ if ( bMarked && !bNoSimple && !bMarkIsNeg )
+ if ( aMarkRange.aStart.Col() <= nCol && aMarkRange.aEnd.Col() >= nCol &&
+ aMarkRange.aStart.Row() <= nRow && aMarkRange.aEnd.Row() >= nRow )
+ return TRUE;
+
+ if (bMultiMarked)
+ {
+ //! hier auf negative Markierung testen ?
+
+ DBG_ASSERT(pMultiSel, "bMultiMarked, aber pMultiSel == 0");
+ return pMultiSel[nCol].GetMark( nRow );
+ }
+
+ return FALSE;
+}
+
+BOOL ScMarkData::IsColumnMarked( USHORT nCol ) const
+{
+ // bMarkIsNeg inzwischen auch fuer Spaltenkoepfe
+ //! GetMarkColumnRanges fuer komplett markierte Spalten
+
+ if ( bMarked && !bMarkIsNeg &&
+ aMarkRange.aStart.Col() <= nCol && aMarkRange.aEnd.Col() >= nCol &&
+ aMarkRange.aStart.Row() == 0 && aMarkRange.aEnd.Row() == MAXROW )
+ return TRUE;
+
+ if ( bMultiMarked && pMultiSel[nCol].IsAllMarked(0,MAXROW) )
+ return TRUE;
+
+ return FALSE;
+}
+
+BOOL ScMarkData::IsRowMarked( USHORT nRow ) const
+{
+ // bMarkIsNeg inzwischen auch fuer Zeilenkoepfe
+ //! GetMarkRowRanges fuer komplett markierte Zeilen
+
+ if ( bMarked && !bMarkIsNeg &&
+ aMarkRange.aStart.Col() == 0 && aMarkRange.aEnd.Col() == MAXCOL &&
+ aMarkRange.aStart.Row() <= nRow && aMarkRange.aEnd.Row() >= nRow )
+ return TRUE;
+
+ if ( bMultiMarked )
+ {
+ DBG_ASSERT(pMultiSel, "bMultiMarked, aber pMultiSel == 0");
+ for (USHORT nCol=0; nCol<=MAXCOL; nCol++)
+ if (!pMultiSel[nCol].GetMark(nRow))
+ return FALSE;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void ScMarkData::MarkFromRangeList( const ScRangeList& rList, BOOL bReset )
+{
+ if (bReset)
+ {
+ for (USHORT i=0; i<=MAXTAB; i++)
+ bTabMarked[i] = FALSE; // Tabellen sind nicht in ResetMark
+ ResetMark();
+ }
+
+ ULONG nCount = rList.Count();
+ if ( nCount == 1 && !bMarked && !bMultiMarked )
+ {
+ ScRange aRange = *rList.GetObject(0);
+ SetMarkArea( aRange );
+ SelectTable( aRange.aStart.Tab(), TRUE );
+ }
+ else
+ {
+ for (ULONG i=0; i<nCount; i++)
+ {
+ ScRange aRange = *rList.GetObject(i);
+ SetMultiMarkArea( aRange, TRUE );
+ SelectTable( aRange.aStart.Tab(), TRUE );
+ }
+ }
+}
+
+void ScMarkData::FillRangeListWithMarks( ScRangeList* pList, BOOL bClear ) const
+{
+ if (!pList)
+ return;
+
+ if (bClear)
+ pList->RemoveAll();
+
+ //! bei mehreren selektierten Tabellen mehrere Ranges eintragen !!!
+
+ if ( bMultiMarked )
+ {
+ DBG_ASSERT(pMultiSel, "bMultiMarked, aber pMultiSel == 0");
+
+ USHORT nTab = aMultiRange.aStart.Tab();
+
+ USHORT nStartCol = aMultiRange.aStart.Col();
+ USHORT nEndCol = aMultiRange.aEnd.Col();
+ for (USHORT nCol=nStartCol; nCol<=nEndCol; nCol++)
+ if (pMultiSel[nCol].HasMarks())
+ {
+ USHORT nTop, nBottom;
+ ScRange aRange( nCol, 0, nTab );
+ ScMarkArrayIter aMarkIter( &pMultiSel[nCol] );
+ while ( aMarkIter.Next( nTop, nBottom ) )
+ {
+ aRange.aStart.SetRow( nTop );
+ aRange.aEnd.SetRow( nBottom );
+ pList->Join( aRange );
+ }
+ }
+ }
+
+ if ( bMarked )
+ pList->Append( aMarkRange );
+}
+
+void ScMarkData::ExtendRangeListTables( ScRangeList* pList ) const
+{
+ if (!pList)
+ return;
+
+ ScRangeList aOldList(*pList);
+ pList->RemoveAll(); //! oder die vorhandenen unten weglassen
+
+ for (USHORT nTab=0; nTab<=MAXTAB; nTab++)
+ if (bTabMarked[nTab])
+ {
+ ULONG nCount = aOldList.Count();
+ for (ULONG i=0; i<nCount; i++)
+ {
+ ScRange aRange = *aOldList.GetObject(i);
+ aRange.aStart.SetTab(nTab);
+ aRange.aEnd.SetTab(nTab);
+ pList->Append( aRange );
+ }
+ }
+}
+
+USHORT ScMarkData::GetMarkColumnRanges( USHORT* pRanges )
+{
+ if (bMarked)
+ MarkToMulti();
+
+ if (!bMultiMarked)
+ return 0;
+
+ DBG_ASSERT(pMultiSel, "bMultiMarked, aber pMultiSel == 0");
+
+ USHORT nRangeCnt = 0;
+ USHORT nStart = 0;
+ while (nStart<=MAXCOL)
+ {
+ while (nStart<MAXCOL && !pMultiSel[nStart].HasMarks())
+ ++nStart;
+ if (pMultiSel[nStart].HasMarks())
+ {
+ USHORT nEnd = nStart;
+ while (nEnd<MAXCOL && pMultiSel[nEnd].HasMarks())
+ ++nEnd;
+ if (!pMultiSel[nEnd].HasMarks())
+ --nEnd;
+ pRanges[2*nRangeCnt ] = nStart;
+ pRanges[2*nRangeCnt+1] = nEnd;
+ ++nRangeCnt;
+ nStart = nEnd+1;
+ }
+ else
+ nStart = MAXCOL+1;
+ }
+
+ return nRangeCnt;
+}
+
+USHORT ScMarkData::GetMarkRowRanges( USHORT* pRanges )
+{
+ if (bMarked)
+ MarkToMulti();
+
+ if (!bMultiMarked)
+ return 0;
+
+ DBG_ASSERT(pMultiSel, "bMultiMarked, aber pMultiSel == 0");
+
+ // Welche Zeilen sind markiert?
+
+ BOOL* bMarked = new BOOL[MAXROW+1];
+ USHORT nRow;
+ USHORT nCol;
+ for (nRow=0; nRow<=MAXROW; nRow++)
+ bMarked[nRow] = FALSE;
+
+ USHORT nTop;
+ USHORT nBottom;
+ for (nCol=0; nCol<=MAXCOL; nCol++)
+ {
+ ScMarkArrayIter aMarkIter( &pMultiSel[nCol] );
+ while (aMarkIter.Next( nTop, nBottom ))
+ for (nRow=nTop; nRow<=nBottom; nRow++)
+ bMarked[nRow] = TRUE;
+ }
+
+ // zu Bereichen zusammenfassen
+
+ USHORT nRangeCnt = 0;
+ USHORT nStart = 0;
+ while (nStart<=MAXROW)
+ {
+ while (nStart<MAXROW && !bMarked[nStart])
+ ++nStart;
+ if (bMarked[nStart])
+ {
+ USHORT nEnd = nStart;
+ while (nEnd<MAXROW && bMarked[nEnd])
+ ++nEnd;
+ if (!bMarked[nEnd])
+ --nEnd;
+ pRanges[2*nRangeCnt ] = nStart;
+ pRanges[2*nRangeCnt+1] = nEnd;
+ ++nRangeCnt;
+ nStart = nEnd+1;
+ }
+ else
+ nStart = MAXROW+1;
+ }
+
+ delete[] bMarked;
+ return nRangeCnt;
+}
+
+BOOL ScMarkData::IsAllMarked( const ScRange& rRange ) const
+{
+ if ( !bMultiMarked )
+ return FALSE;
+
+ DBG_ASSERT(pMultiSel, "bMultiMarked, aber pMultiSel == 0");
+
+ USHORT nStartCol = rRange.aStart.Col();
+ USHORT nStartRow = rRange.aStart.Row();
+ USHORT nEndCol = rRange.aEnd.Col();
+ USHORT nEndRow = rRange.aEnd.Row();
+ BOOL bOk = TRUE;
+ for (USHORT nCol=nStartCol; nCol<=nEndCol && bOk; nCol++)
+ if ( !pMultiSel[nCol].IsAllMarked( nStartRow, nEndRow ) )
+ bOk = FALSE;
+
+ return bOk;
+}
+
+short ScMarkData::GetNextMarked( USHORT nCol, short nRow, BOOL bUp ) const
+{
+ if ( !bMultiMarked )
+ return nRow;
+
+ DBG_ASSERT(pMultiSel, "bMultiMarked, aber pMultiSel == 0");
+
+ return pMultiSel[nCol].GetNextMarked( nRow, bUp );
+}
+
+BOOL ScMarkData::HasMultiMarks( USHORT nCol ) const
+{
+ if ( !bMultiMarked )
+ return FALSE;
+
+ DBG_ASSERT(pMultiSel, "bMultiMarked, aber pMultiSel == 0");
+
+ return pMultiSel[nCol].HasMarks();
+}
+
+BOOL ScMarkData::HasAnyMultiMarks() const
+{
+ if ( !bMultiMarked )
+ return FALSE;
+
+ DBG_ASSERT(pMultiSel, "bMultiMarked, aber pMultiSel == 0");
+
+ for (USHORT nCol=0; nCol<=MAXCOL; nCol++)
+ if ( pMultiSel[nCol].HasMarks() )
+ return TRUE;
+
+ return FALSE; // nix
+}
+
+void ScMarkData::InsertTab( USHORT nTab )
+{
+ for (USHORT i=MAXTAB; i>nTab; i--)
+ bTabMarked[i] = bTabMarked[i-1];
+ bTabMarked[nTab] = FALSE;
+}
+
+void ScMarkData::DeleteTab( USHORT nTab )
+{
+ for (USHORT i=nTab; i<MAXTAB; i++)
+ bTabMarked[i] = bTabMarked[i+1];
+ bTabMarked[MAXTAB] = FALSE;
+}
+
+
+
+
+
diff --git a/sc/source/core/data/olinetab.cxx b/sc/source/core/data/olinetab.cxx
new file mode 100644
index 000000000000..b21331dde4fd
--- /dev/null
+++ b/sc/source/core/data/olinetab.cxx
@@ -0,0 +1,876 @@
+/*************************************************************************
+ *
+ * $RCSfile: olinetab.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+// System - Includes -----------------------------------------------------
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include <tools/debug.hxx>
+#include <limits.h>
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "olinetab.hxx"
+#include "global.hxx"
+#include "rechead.hxx"
+
+//------------------------------------------------------------------------
+
+ScOutlineEntry::ScOutlineEntry( USHORT nNewStart, USHORT nNewSize, BOOL bNewHidden ) :
+ nStart ( nNewStart ),
+ nSize ( nNewSize ),
+ bHidden ( bNewHidden ),
+ bVisible( TRUE )
+{
+}
+
+ScOutlineEntry::ScOutlineEntry( const ScOutlineEntry& rEntry ) :
+ nStart ( rEntry.nStart ),
+ nSize ( rEntry.nSize ),
+ bHidden ( rEntry.bHidden ),
+ bVisible( rEntry.bVisible )
+{
+}
+
+ScOutlineEntry::ScOutlineEntry( SvStream& rStream, ScMultipleReadHeader& rHdr )
+{
+ rHdr.StartEntry();
+
+ rStream >> nStart;
+ rStream >> nSize;
+ rStream >> bHidden;
+ rStream >> bVisible;
+
+ rHdr.EndEntry();
+}
+
+void ScOutlineEntry::Store( SvStream& rStream, ScMultipleWriteHeader& rHdr )
+{
+ rHdr.StartEntry();
+
+ rStream << nStart;
+ rStream << nSize;
+ rStream << bHidden;
+ rStream << bVisible;
+
+ rHdr.EndEntry();
+}
+
+DataObject* ScOutlineEntry::Clone() const
+{
+ return new ScOutlineEntry( *this );
+}
+
+void ScOutlineEntry::Move( short nDelta )
+{
+ short nNewPos = ((short) nStart) + nDelta;
+ if (nNewPos<0)
+ {
+ DBG_ERROR("OutlineEntry < 0");
+ nNewPos = 0;
+ }
+ nStart = (USHORT) nNewPos;
+}
+
+void ScOutlineEntry::SetSize( USHORT nNewSize )
+{
+ if (nNewSize)
+ nSize = nNewSize;
+ else
+ DBG_ERROR("ScOutlineEntry Size == 0");
+}
+
+void ScOutlineEntry::SetPosSize( USHORT nNewPos, USHORT nNewSize )
+{
+ nStart = nNewPos;
+ SetSize( nNewSize );
+}
+
+void ScOutlineEntry::SetHidden( BOOL bNewHidden )
+{
+ bHidden = bNewHidden;
+}
+
+void ScOutlineEntry::SetVisible( BOOL bNewVisible )
+{
+ bVisible = bNewVisible;
+}
+
+//------------------------------------------------------------------------
+
+ScOutlineCollection::ScOutlineCollection() :
+ SortedCollection( 4,4,FALSE )
+{
+}
+
+inline short IntCompare( USHORT nX, USHORT nY )
+{
+ if ( nX==nY ) return 0;
+ else if ( nX<nY ) return -1;
+ else return 1;
+}
+
+short ScOutlineCollection::Compare(DataObject* pKey1, DataObject* pKey2) const
+{
+ return IntCompare( ((ScOutlineEntry*)pKey1)->GetStart(),
+ ((ScOutlineEntry*)pKey2)->GetStart() );
+}
+
+USHORT ScOutlineCollection::FindStart( USHORT nMinStart )
+{
+ //! binaer suchen ?
+
+ USHORT nPos = 0;
+ USHORT nCount = GetCount();
+ while ( (nPos<nCount) ? (((ScOutlineEntry*)At(nPos))->GetStart() < nMinStart) : FALSE )
+ ++nPos;
+
+ return nPos;
+}
+
+//------------------------------------------------------------------------
+
+ScOutlineArray::ScOutlineArray() :
+ nDepth( 0 )
+{
+}
+
+ScOutlineArray::ScOutlineArray( const ScOutlineArray& rArray ) :
+ nDepth( rArray.nDepth )
+{
+ for (USHORT nLevel=0; nLevel<nDepth; nLevel++)
+ {
+ USHORT nCount = rArray.aCollections[nLevel].GetCount();
+ for (USHORT nEntry=0; nEntry<nCount; nEntry++)
+ {
+ ScOutlineEntry* pEntry = (ScOutlineEntry*) rArray.aCollections[nLevel].At(nEntry);
+ aCollections[nLevel].Insert( new ScOutlineEntry( *pEntry ) );
+ }
+ }
+}
+
+void ScOutlineArray::FindEntry( USHORT nSearchPos, USHORT& rFindLevel, USHORT& rFindIndex,
+ USHORT nMaxLevel )
+{
+ rFindLevel = rFindIndex = 0;
+
+ if (nMaxLevel > nDepth)
+ nMaxLevel = nDepth;
+
+ for (USHORT nLevel=0; nLevel<nMaxLevel; nLevel++) //! rueckwaerts suchen ?
+ {
+ ScOutlineCollection* pCollect = &aCollections[nLevel];
+ USHORT nCount = pCollect->GetCount();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScOutlineEntry* pEntry = (ScOutlineEntry*) pCollect->At(i);
+ if ( pEntry->GetStart() <= nSearchPos && pEntry->GetEnd() >= nSearchPos )
+ {
+ rFindLevel = nLevel + 1; // naechster Level (zum Einfuegen)
+ rFindIndex = i;
+ }
+ }
+ }
+}
+
+BOOL ScOutlineArray::Insert( USHORT nStartCol, USHORT nEndCol, BOOL& rSizeChanged,
+ BOOL bHidden, BOOL bVisible )
+{
+ rSizeChanged = FALSE;
+
+ USHORT nStartLevel;
+ USHORT nStartIndex;
+ USHORT nEndLevel;
+ USHORT nEndIndex;
+ BOOL bFound = FALSE;
+
+ BOOL bCont;
+ USHORT nFindMax;
+ FindEntry( nStartCol, nStartLevel, nStartIndex ); // nLevel = neuer Level (alter+1) !!!
+ FindEntry( nEndCol, nEndLevel, nEndIndex );
+ nFindMax = Max(nStartLevel,nEndLevel);
+ do
+ {
+ bCont = FALSE;
+
+ if ( nStartLevel == nEndLevel && nStartIndex == nEndIndex && nStartLevel < SC_OL_MAXDEPTH )
+ bFound = TRUE;
+
+ if (!bFound)
+ {
+ if (nFindMax>0)
+ {
+ --nFindMax;
+ if (nStartLevel)
+ if ( ((ScOutlineEntry*)aCollections[nStartLevel-1].At(nStartIndex))->
+ GetStart() == nStartCol )
+ FindEntry( nStartCol, nStartLevel, nStartIndex, nFindMax );
+ if (nEndLevel)
+ if ( ((ScOutlineEntry*)aCollections[nEndLevel-1].At(nEndIndex))->
+ GetEnd() == nEndCol )
+ FindEntry( nEndCol, nEndLevel, nEndIndex, nFindMax );
+ bCont = TRUE;
+ }
+ }
+ }
+ while ( !bFound && bCont );
+
+ if (!bFound)
+ return FALSE;
+
+ USHORT nLevel = nStartLevel;
+
+ // untere verschieben
+
+ BOOL bNeedSize = FALSE;
+ for ( short nMoveLevel = nDepth-1; nMoveLevel >= (short) nLevel; nMoveLevel-- )
+ {
+ USHORT nCount = aCollections[nMoveLevel].GetCount();
+ BOOL bMoved = FALSE;
+ for ( USHORT i=0; i<nCount; i += bMoved ? 0 : 1 )
+ {
+ ScOutlineEntry* pEntry = (ScOutlineEntry*) aCollections[nMoveLevel].At(i);
+ USHORT nEntryStart = pEntry->GetStart();
+ if ( nEntryStart >= nStartCol && nEntryStart <= nEndCol )
+ {
+ if (nMoveLevel >= SC_OL_MAXDEPTH - 1)
+ {
+ rSizeChanged = FALSE; // kein Platz
+ return FALSE;
+ }
+ aCollections[nMoveLevel+1].Insert( new ScOutlineEntry( *pEntry ) );
+ aCollections[nMoveLevel].AtFree( i );
+ nCount = aCollections[nMoveLevel].GetCount();
+ bMoved = TRUE;
+ if (nMoveLevel == (short) nDepth - 1)
+ bNeedSize = TRUE;
+ }
+ else
+ bMoved = FALSE;
+ }
+ }
+
+ if (bNeedSize)
+ {
+ ++nDepth;
+ rSizeChanged = TRUE;
+ }
+
+ if (nDepth <= nLevel)
+ {
+ nDepth = nLevel+1;
+ rSizeChanged = TRUE;
+ }
+
+/* nicht zusammenfassen!
+
+ // zusammenfassen
+
+ USHORT nCount = aCollections[nLevel].GetCount();
+ USHORT nIndex;
+ bFound = FALSE;
+ for ( nIndex=0; nIndex<nCount && !bFound; nIndex++ )
+ {
+ if ( ((ScOutlineEntry*) aCollections[nLevel].At(nIndex))->GetEnd() + 1 == nStartCol )
+ {
+ nStartCol = ((ScOutlineEntry*) aCollections[nLevel].At(nIndex))->GetStart();
+ aCollections[nLevel].AtFree(nIndex);
+ nCount = aCollections[nLevel].GetCount(); // Daten geaendert
+ bFound = TRUE;
+ }
+ }
+
+ bFound = FALSE;
+ for ( nIndex=0; nIndex<nCount && !bFound; nIndex++ )
+ {
+ if ( ((ScOutlineEntry*) aCollections[nLevel].At(nIndex))->GetStart() == nEndCol + 1 )
+ {
+ nEndCol = ((ScOutlineEntry*) aCollections[nLevel].At(nIndex))->GetEnd();
+ aCollections[nLevel].AtFree(nIndex);
+ bFound = TRUE;
+ }
+ }
+*/
+ ScOutlineEntry* pNewEntry = new ScOutlineEntry( nStartCol, nEndCol+1-nStartCol, bHidden );
+ pNewEntry->SetVisible( bVisible );
+ aCollections[nLevel].Insert( pNewEntry );
+
+ return TRUE;
+}
+
+BOOL ScOutlineArray::FindTouchedLevel( USHORT nBlockStart, USHORT nBlockEnd, USHORT& rFindLevel )
+{
+ BOOL bFound = FALSE;
+ rFindLevel = 0;
+
+ for (USHORT nLevel=0; nLevel<nDepth; nLevel++)
+ {
+ ScOutlineCollection* pCollect = &aCollections[nLevel];
+ USHORT nCount = pCollect->GetCount();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScOutlineEntry* pEntry = (ScOutlineEntry*) pCollect->At(i);
+ USHORT nStart = pEntry->GetStart();
+ USHORT nEnd = pEntry->GetEnd();
+
+ if ( ( nBlockStart>=nStart && nBlockStart<=nEnd ) ||
+ ( nBlockEnd >=nStart && nBlockEnd <=nEnd ) )
+ {
+ rFindLevel = nLevel; // wirklicher Level
+ bFound = TRUE;
+ }
+ }
+ }
+
+ return bFound;
+}
+
+void ScOutlineArray::RemoveSub( USHORT nStartPos, USHORT nEndPos, USHORT nLevel )
+{
+ ScOutlineCollection* pCollect = &aCollections[nLevel];
+ USHORT nCount = pCollect->GetCount();
+ BOOL bFound = FALSE;
+ for ( USHORT i=0; i<nCount; i += ( bFound ? 0 : 1 ) )
+ {
+ bFound = FALSE;
+ ScOutlineEntry* pEntry = (ScOutlineEntry*) pCollect->At(i);
+ USHORT nStart = pEntry->GetStart();
+ USHORT nEnd = pEntry->GetEnd();
+
+ if ( nStart>=nStartPos && nEnd<=nEndPos )
+ {
+ RemoveSub( nStart, nEnd, nLevel+1 );
+ pCollect->AtFree(i);
+ nCount = pCollect->GetCount();
+ bFound = TRUE;
+ }
+ }
+}
+
+void ScOutlineArray::PromoteSub( USHORT nStartPos, USHORT nEndPos, USHORT nStartLevel )
+{
+ if (nStartLevel==0)
+ {
+ DBG_ERROR("PromoteSub mit Level 0");
+ return;
+ }
+
+ for (USHORT nLevel = nStartLevel; nLevel < nDepth; nLevel++)
+ {
+ ScOutlineCollection* pCollect = &aCollections[nLevel];
+ USHORT nCount = pCollect->GetCount();
+ BOOL bFound = FALSE;
+ for ( USHORT i=0; i<nCount; i += ( bFound ? 0 : 1 ) )
+ {
+ bFound = FALSE;
+ ScOutlineEntry* pEntry = (ScOutlineEntry*) pCollect->At(i);
+ USHORT nStart = pEntry->GetStart();
+ USHORT nEnd = pEntry->GetEnd();
+
+ if ( nStart>=nStartPos && nEnd<=nEndPos )
+ {
+ aCollections[nLevel-1].Insert( new ScOutlineEntry( *pEntry ) );
+ pCollect->AtFree(i);
+ nCount = pCollect->GetCount();
+ bFound = TRUE;
+ }
+ }
+ }
+}
+
+BOOL ScOutlineArray::DecDepth() // nDepth auf leere Levels anpassen
+{
+ BOOL bChanged = FALSE;
+ BOOL bCont;
+ do
+ {
+ bCont = FALSE;
+ if (nDepth)
+ if (aCollections[nDepth-1].GetCount() == 0)
+ {
+ --nDepth;
+ bChanged = TRUE;
+ bCont = TRUE;
+ }
+ }
+ while (bCont);
+ return bChanged;
+}
+
+BOOL ScOutlineArray::Remove( USHORT nBlockStart, USHORT nBlockEnd, BOOL& rSizeChanged )
+{
+ USHORT nLevel;
+ FindTouchedLevel( nBlockStart, nBlockEnd, nLevel );
+
+ ScOutlineCollection* pCollect = &aCollections[nLevel];
+ USHORT nCount = pCollect->GetCount();
+ BOOL bFound = FALSE;
+ BOOL bAny = FALSE;
+ for ( USHORT i=0; i<nCount; i += ( bFound ? 0 : 1 ) )
+ {
+ bFound = FALSE;
+ ScOutlineEntry* pEntry = (ScOutlineEntry*) pCollect->At(i);
+ USHORT nStart = pEntry->GetStart();
+ USHORT nEnd = pEntry->GetEnd();
+
+ if ( nBlockStart<=nEnd && nBlockEnd>=nStart )
+ {
+// RemoveSub( nStart, nEnd, nLevel+1 );
+ pCollect->AtFree(i);
+ PromoteSub( nStart, nEnd, nLevel+1 );
+ nCount = pCollect->GetCount();
+ i = pCollect->FindStart( nEnd+1 );
+ bFound = TRUE;
+ bAny = TRUE;
+ }
+ }
+
+ if (bAny) // Depth anpassen
+ if (DecDepth())
+ rSizeChanged = TRUE;
+
+ return bAny;
+}
+
+ScOutlineEntry* ScOutlineArray::GetEntry( USHORT nLevel, USHORT nIndex )
+{
+ return (ScOutlineEntry*) aCollections[nLevel].At(nIndex);
+}
+
+USHORT ScOutlineArray::GetCount( USHORT nLevel )
+{
+ return aCollections[nLevel].GetCount();
+}
+
+ScOutlineEntry* ScOutlineArray::GetEntryByPos( USHORT nLevel, USHORT nPos )
+{
+ USHORT nCount = GetCount( nLevel );
+ ScOutlineEntry* pEntry;
+
+ for (USHORT nIndex = 0; nIndex < nCount; nIndex++)
+ {
+ pEntry = GetEntry( nLevel, nIndex );
+ if ((pEntry->GetStart() <= nPos) && (nPos <= pEntry->GetEnd()))
+ return pEntry;
+ }
+ return NULL;
+}
+
+void ScOutlineArray::SetVisibleBelow( USHORT nLevel, USHORT nEntry, BOOL bValue, BOOL bSkipHidden )
+{
+ ScOutlineEntry* pEntry = (ScOutlineEntry*) aCollections[nLevel].At(nEntry);
+ USHORT nStart = pEntry->GetStart();
+ USHORT nEnd = pEntry->GetEnd();
+
+ for (USHORT nSubLevel=nLevel+1; nSubLevel<nDepth; nSubLevel++)
+ {
+ USHORT i = 0;
+ pEntry = (ScOutlineEntry*) aCollections[nSubLevel].At(i);
+ while (pEntry)
+ {
+ if (pEntry->GetStart() >= nStart && pEntry->GetEnd() <= nEnd)
+ {
+ pEntry->SetVisible(bValue);
+
+ if (bSkipHidden)
+ if (!pEntry->IsHidden())
+ SetVisibleBelow( nSubLevel, i, bValue, TRUE );
+ }
+
+ ++i;
+ pEntry = (ScOutlineEntry*) aCollections[nSubLevel].At(i);
+ }
+
+ if (bSkipHidden)
+ nSubLevel = nDepth; // Abbruch
+ }
+}
+
+void ScOutlineArray::GetRange( USHORT& rStart, USHORT& rEnd )
+{
+ USHORT nCount = aCollections[0].GetCount();
+ if (nCount)
+ {
+ rStart = ((ScOutlineEntry*) aCollections[0].At(0))->GetStart();
+ rEnd = ((ScOutlineEntry*) aCollections[0].At(nCount-1))->GetEnd();
+ }
+ else
+ rStart = rEnd = 0;
+}
+
+void ScOutlineArray::ExtendBlock( USHORT nLevel, USHORT& rBlkStart, USHORT& rBlkEnd )
+{
+ USHORT nCount;
+ USHORT nStart;
+ USHORT nEnd;
+ USHORT i;
+ ScOutlineEntry* pEntry;
+
+ nCount = GetCount(nLevel);
+ for ( i=0; i<nCount; i++ )
+ {
+ pEntry = (ScOutlineEntry*) aCollections[nLevel].At(i);
+ nStart = pEntry->GetStart();
+ nEnd = pEntry->GetEnd();
+
+ if ( rBlkStart<=nEnd && rBlkEnd>=nStart )
+ {
+ if (nStart<rBlkStart) rBlkStart = nStart;
+ if (nEnd>rBlkEnd) rBlkEnd = nEnd;
+ }
+ }
+}
+
+BOOL ScOutlineArray::TestInsertSpace( USHORT nSize, USHORT nMaxVal )
+{
+ USHORT nCount = aCollections[0].GetCount();
+ if (nCount)
+ {
+ USHORT nEnd = ((ScOutlineEntry*) aCollections[0].At(nCount-1))->GetEnd();
+ return ( nEnd+nSize <= nMaxVal );
+ }
+
+ return TRUE;
+}
+
+void ScOutlineArray::InsertSpace( USHORT nStartPos, USHORT nSize )
+{
+ ScSubOutlineIterator aIter( this );
+ ScOutlineEntry* pEntry;
+ while((pEntry=aIter.GetNext())!=NULL)
+ {
+ if ( pEntry->GetStart() >= nStartPos )
+ pEntry->Move(nSize);
+ else
+ {
+ USHORT nEnd = pEntry->GetEnd();
+ // immer erweitern, wenn innerhalb der Gruppe eingefuegt
+ // beim Einfuegen am Ende nur, wenn die Gruppe nicht ausgeblendet ist
+ if ( nEnd >= nStartPos || ( nEnd+1 >= nStartPos && !pEntry->IsHidden() ) )
+ {
+ USHORT nEntrySize = pEntry->GetSize();
+ nEntrySize += nSize;
+ pEntry->SetSize( nEntrySize );
+ }
+ }
+ }
+}
+
+BOOL ScOutlineArray::DeleteSpace( USHORT nStartPos, USHORT nSize )
+{
+ USHORT nEndPos = nStartPos + nSize - 1;
+ BOOL bNeedSave = FALSE; // Original fuer Undo benoetigt?
+ BOOL bChanged = FALSE; // fuer Test auf Level
+
+ ScSubOutlineIterator aIter( this );
+ ScOutlineEntry* pEntry;
+ while((pEntry=aIter.GetNext())!=NULL)
+ {
+ USHORT nEntryStart = pEntry->GetStart();
+ USHORT nEntryEnd = pEntry->GetEnd();
+ USHORT nEntrySize = pEntry->GetSize();
+
+ if ( nEntryEnd >= nStartPos )
+ {
+ if ( nEntryStart > nEndPos ) // rechts
+ pEntry->Move(-(short)nSize);
+ else if ( nEntryStart < nStartPos && nEntryEnd >= nEndPos ) // aussen
+ pEntry->SetSize( nEntrySize-nSize );
+ else
+ {
+ bNeedSave = TRUE;
+ if ( nEntryStart >= nStartPos && nEntryEnd <= nEndPos ) // innen
+ {
+ aIter.DeleteLast();
+ bChanged = TRUE;
+ }
+ else if ( nEntryStart >= nStartPos ) // rechts ueber
+ pEntry->SetPosSize( nStartPos, nEntryEnd-nEndPos );
+ else // links ueber
+ pEntry->SetSize( nStartPos-nEntryStart );
+ }
+ }
+ }
+
+ if (bChanged)
+ DecDepth();
+
+ return bNeedSave;
+}
+
+BOOL ScOutlineArray::ManualAction( USHORT nStartPos, USHORT nEndPos, BOOL bShow, BYTE* pHiddenFlags )
+{
+ BOOL bModified = FALSE;
+ ScSubOutlineIterator aIter( this );
+ ScOutlineEntry* pEntry;
+ while((pEntry=aIter.GetNext())!=NULL)
+ {
+ USHORT nEntryStart = pEntry->GetStart();
+ USHORT nEntryEnd = pEntry->GetEnd();
+
+ if (nEntryEnd>=nStartPos && nEntryStart<=nEndPos)
+ {
+ if ( pEntry->IsHidden() == bShow )
+ {
+ USHORT i;
+ BOOL bToggle = TRUE;
+
+ for (i=nEntryStart; i<=nEntryEnd && bToggle; i++)
+ {
+ BOOL bEntryHidden = (pHiddenFlags[i] & CR_HIDDEN) != 0;
+ if ( bEntryHidden == bShow )
+ bToggle = FALSE;
+ }
+
+ if (bToggle)
+ {
+ pEntry->SetHidden( !bShow );
+ SetVisibleBelow( aIter.LastLevel(), aIter.LastEntry(), bShow, bShow );
+ bModified = TRUE;
+ }
+ }
+ }
+ }
+ return bModified;
+}
+
+void ScOutlineArray::RemoveAll()
+{
+ for (USHORT nLevel=0; nLevel<nDepth; nLevel++)
+ aCollections[nLevel].FreeAll();
+
+ nDepth = 0;
+}
+
+void ScOutlineArray::Load( SvStream& rStream )
+{
+ ScMultipleReadHeader aHdr( rStream );
+
+ rStream >> nDepth;
+ for (USHORT nLevel=0; nLevel<nDepth; nLevel++)
+ {
+ USHORT nCount;
+ rStream >> nCount;
+ for (USHORT nIndex=0; nIndex<nCount; nIndex++)
+ {
+ ScOutlineEntry* pEntry = new ScOutlineEntry( rStream, aHdr );
+ aCollections[nLevel].Insert( pEntry );
+ }
+ }
+}
+
+void ScOutlineArray::Store( SvStream& rStream )
+{
+ ScMultipleWriteHeader aHdr( rStream );
+
+ rStream << nDepth;
+ for (USHORT nLevel=0; nLevel<nDepth; nLevel++)
+ {
+ USHORT nCount = aCollections[nLevel].GetCount();
+ rStream << nCount;
+ for (USHORT nIndex=0; nIndex<nCount; nIndex++)
+ ((ScOutlineEntry*) aCollections[nLevel].At(nIndex))->Store( rStream, aHdr );
+ }
+}
+
+//------------------------------------------------------------------------
+
+ScOutlineTable::ScOutlineTable()
+{
+}
+
+ScOutlineTable::ScOutlineTable( const ScOutlineTable& rOutline ) :
+ aColOutline( rOutline.aColOutline ),
+ aRowOutline( rOutline.aRowOutline )
+{
+}
+
+BOOL ScOutlineTable::TestInsertCol( USHORT nSize )
+{
+ return aColOutline.TestInsertSpace( nSize, MAXCOL );
+}
+
+void ScOutlineTable::InsertCol( USHORT nStartCol, USHORT nSize )
+{
+ aColOutline.InsertSpace( nStartCol, nSize );
+}
+
+BOOL ScOutlineTable::DeleteCol( USHORT nStartCol, USHORT nSize )
+{
+ return aColOutline.DeleteSpace( nStartCol, nSize );
+}
+
+BOOL ScOutlineTable::TestInsertRow( USHORT nSize )
+{
+ return aRowOutline.TestInsertSpace( nSize, MAXROW );
+}
+
+void ScOutlineTable::InsertRow( USHORT nStartRow, USHORT nSize )
+{
+ aRowOutline.InsertSpace( nStartRow, nSize );
+}
+
+BOOL ScOutlineTable::DeleteRow( USHORT nStartRow, USHORT nSize )
+{
+ return aRowOutline.DeleteSpace( nStartRow, nSize );
+}
+
+void ScOutlineTable::Load( SvStream& rStream )
+{
+ DBG_ASSERT( aColOutline.GetDepth()==0 && aRowOutline.GetDepth()==0,
+ "Load auf nicht leere ScOutlineTable" );
+ aColOutline.Load( rStream );
+ aRowOutline.Load( rStream );
+}
+
+void ScOutlineTable::Store( SvStream& rStream )
+{
+ aColOutline.Store( rStream );
+ aRowOutline.Store( rStream );
+}
+
+//------------------------------------------------------------------------
+
+ScSubOutlineIterator::ScSubOutlineIterator( ScOutlineArray* pOutlineArray ) :
+ pArray( pOutlineArray ),
+ nStart( 0 ),
+ nEnd( USHRT_MAX ), // alle durchgehen
+ nSubLevel( 0 ),
+ nSubEntry( 0 )
+{
+ nDepth = pArray->nDepth;
+}
+
+ScSubOutlineIterator::ScSubOutlineIterator( ScOutlineArray* pOutlineArray,
+ USHORT nLevel, USHORT nEntry ) :
+ pArray( pOutlineArray )
+{
+ ScOutlineEntry* pEntry = (ScOutlineEntry*) pArray->aCollections[nLevel].At(nEntry);
+ nStart = pEntry->GetStart();
+ nEnd = pEntry->GetEnd();
+ nSubLevel = nLevel + 1;
+ nSubEntry = 0;
+ nDepth = pArray->nDepth;
+}
+
+ScOutlineEntry* ScSubOutlineIterator::GetNext()
+{
+ ScOutlineEntry* pEntry;
+ BOOL bFound = FALSE;
+ do
+ {
+ if (nSubLevel >= nDepth)
+ return NULL;
+
+ pEntry = (ScOutlineEntry*) pArray->aCollections[nSubLevel].At(nSubEntry);
+ if (!pEntry)
+ {
+ nSubEntry = 0;
+ ++nSubLevel;
+ }
+ else
+ {
+ if ( pEntry->GetStart() >= nStart && pEntry->GetEnd() <= nEnd )
+ bFound = TRUE;
+ ++nSubEntry;
+ }
+ }
+ while (!bFound);
+ return pEntry; // nSubLevel gueltig, wenn pEntry != 0
+}
+
+USHORT ScSubOutlineIterator::LastLevel() const
+{
+ return nSubLevel;
+}
+
+USHORT ScSubOutlineIterator::LastEntry() const
+{
+ if (nSubEntry == 0)
+ {
+ DBG_ERROR("ScSubOutlineIterator::LastEntry vor GetNext");
+ return 0;
+ }
+ return nSubEntry-1;
+}
+
+void ScSubOutlineIterator::DeleteLast()
+{
+ if (nSubLevel >= nDepth)
+ {
+ DBG_ERROR("ScSubOutlineIterator::DeleteLast nach Ende");
+ return;
+ }
+ if (nSubEntry == 0)
+ {
+ DBG_ERROR("ScSubOutlineIterator::DeleteLast vor GetNext");
+ return;
+ }
+
+ --nSubEntry;
+ pArray->aCollections[nSubLevel].AtFree(nSubEntry);
+}
+
+
diff --git a/sc/source/core/data/pagepar.cxx b/sc/source/core/data/pagepar.cxx
new file mode 100644
index 000000000000..3243f2d0df7e
--- /dev/null
+++ b/sc/source/core/data/pagepar.cxx
@@ -0,0 +1,262 @@
+/*************************************************************************
+ *
+ * $RCSfile: pagepar.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+// INCLUDE ---------------------------------------------------------------
+
+// System - Includes -----------------------------------------------------
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include <string.h>
+#include "segmentc.hxx"
+
+#include "pagepar.hxx"
+
+SEG_EOFGLOBALS()
+
+//========================================================================
+// struct ScPageTableParam:
+#pragma SEG_FUNCDEF(pagepar_01)
+
+ScPageTableParam::ScPageTableParam()
+{
+ Reset();
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(pagepar_02)
+
+ScPageTableParam::ScPageTableParam( const ScPageTableParam& r )
+{
+ *this = r;
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(pagepar_03)
+
+__EXPORT ScPageTableParam::~ScPageTableParam()
+{
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(pagepar_04)
+
+void __EXPORT ScPageTableParam::Reset()
+{
+ bNotes=bGrid=bHeaders=bDrawings=
+ bLeftRight=bScaleAll=bScalePageNum=
+ bFormulas=bNullVals=bSkipEmpty = FALSE;
+ bTopDown=bScaleNone=bCharts=bObjects = TRUE;
+ nScaleAll = 100;
+ nScalePageNum = 0;
+ nFirstPageNo = 1;
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(pagepar_05)
+
+ScPageTableParam& __EXPORT ScPageTableParam::operator=( const ScPageTableParam& r )
+{
+ memcpy( this, &r, sizeof(ScPageTableParam) );
+
+ return *this;
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(pagepar_06)
+
+BOOL __EXPORT ScPageTableParam::operator==( const ScPageTableParam& r ) const
+{
+ return ( memcmp( this, &r, sizeof(ScPageTableParam) ) == 0 );
+}
+
+//========================================================================
+// struct ScPageAreaParam:
+#pragma SEG_FUNCDEF(pagepar_07)
+
+ScPageAreaParam::ScPageAreaParam()
+{
+ Reset();
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(pagepar_08)
+
+ScPageAreaParam::ScPageAreaParam( const ScPageAreaParam& r )
+{
+ *this = r;
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(pagepar_09)
+
+__EXPORT ScPageAreaParam::~ScPageAreaParam()
+{
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(pagepar_0a)
+
+void __EXPORT ScPageAreaParam::Reset()
+{
+ bPrintArea = bRepeatRow = bRepeatCol = FALSE;
+
+ memset( &aPrintArea, 0, sizeof(ScRange) );
+ memset( &aRepeatRow, 0, sizeof(ScRange) );
+ memset( &aRepeatCol, 0, sizeof(ScRange) );
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(pagepar_0b)
+
+ScPageAreaParam& __EXPORT ScPageAreaParam::operator=( const ScPageAreaParam& r )
+{
+ bPrintArea = r.bPrintArea;
+ bRepeatRow = r.bRepeatRow;
+ bRepeatCol = r.bRepeatCol;
+
+ memcpy( &aPrintArea, &r.aPrintArea, sizeof(ScRange) );
+ memcpy( &aRepeatRow, &r.aRepeatRow, sizeof(ScRange) );
+ memcpy( &aRepeatCol, &r.aRepeatCol, sizeof(ScRange) );
+
+ return *this;
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(pagepar_0c)
+
+BOOL __EXPORT ScPageAreaParam::operator==( const ScPageAreaParam& r ) const
+{
+ BOOL bEqual =
+ bPrintArea == r.bPrintArea
+ && bRepeatRow == r.bRepeatRow
+ && bRepeatCol == r.bRepeatCol;
+
+ if ( bEqual )
+ if ( bPrintArea )
+ bEqual = bEqual && ( aPrintArea == r.aPrintArea );
+ if ( bEqual )
+ if ( bRepeatRow )
+ bEqual = bEqual && ( aRepeatRow == r.aRepeatRow );
+ if ( bEqual )
+ if ( bRepeatCol )
+ bEqual = bEqual && ( aRepeatCol == r.aRepeatCol );
+
+ return bEqual;
+}
+
+/*------------------------------------------------------------------------
+
+ $Log: not supported by cvs2svn $
+ Revision 1.14 2000/09/17 14:08:37 willem.vandorp
+ OpenOffice header added.
+
+ Revision 1.13 2000/08/31 16:37:58 willem.vandorp
+ Header and footer replaced
+
+ Revision 1.12 1997/11/13 19:58:42 NN
+ ifndef PCH raus
+
+
+ Rev 1.11 13 Nov 1997 20:58:42 NN
+ ifndef PCH raus
+
+ Rev 1.10 06 Nov 1997 19:45:46 NN
+ bSkipEmpty
+
+ Rev 1.9 22 Nov 1995 16:30:54 MO
+ ScAreaItem -> ScRangeItem
+
+ Rev 1.8 10 Oct 1995 11:21:52 MO
+ Formeln/Nullwerte drucken im TableParam, Store/Load entfernt
+
+ Rev 1.7 07 Oct 1995 13:18:28 NN
+ nTabCount, aTabArr raus
+
+ Rev 1.6 21 Jul 1995 09:37:02 WKC
+ memory.h -> string.h
+
+ Rev 1.5 26 Jun 1995 13:59:38 MO
+ bDrawings und nFirstPageNo
+
+ Rev 1.4 11 Jun 1995 20:56:06 NN
+ Objekte/Charts drucken per Default an
+
+ Rev 1.3 15 May 1995 19:08:08 NN
+ Load/Store
+
+ Rev 1.2 09 May 1995 20:00:38 MO
+ AreaParam: RefTripel -> ScArea, Flags, ob Areas vorhanden
+
+ Rev 1.1 09 May 1995 12:19:34 TRI
+ memory.h included
+
+ Rev 1.0 08 May 1995 20:04:16 MO
+ Initial revision.
+
+------------------------------------------------------------------------*/
+
+#pragma SEG_EOFMODULE
+
diff --git a/sc/source/core/data/patattr.cxx b/sc/source/core/data/patattr.cxx
new file mode 100644
index 000000000000..e5e3b505df18
--- /dev/null
+++ b/sc/source/core/data/patattr.cxx
@@ -0,0 +1,943 @@
+/*************************************************************************
+ *
+ * $RCSfile: patattr.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <svx/adjitem.hxx>
+#include <svx/algitem.hxx>
+#include <svx/boxitem.hxx>
+#include <svx/brshitem.hxx>
+#include <svx/cntritem.hxx>
+#include <svx/colritem.hxx>
+#include <svx/crsditem.hxx>
+#include <svx/fhgtitem.hxx>
+#include <svx/fontitem.hxx>
+#include <svx/langitem.hxx>
+#include <svx/postitem.hxx>
+#include <svx/rotmodit.hxx>
+#include <svx/shaditem.hxx>
+#include <svx/shdditem.hxx>
+#include <svx/udlnitem.hxx>
+#include <svx/wghtitem.hxx>
+#include <svtools/intitem.hxx>
+#include <svtools/zforlist.hxx>
+#include <vcl/outdev.hxx>
+
+#include "patattr.hxx"
+#include "docpool.hxx"
+#include "stlsheet.hxx"
+#include "stlpool.hxx"
+#include "document.hxx"
+#include "global.hxx"
+#include "globstr.hrc"
+#include "conditio.hxx"
+#include "validat.hxx"
+
+// STATIC DATA -----------------------------------------------------------
+
+ScDocument* ScPatternAttr::pDoc = NULL;
+
+// -----------------------------------------------------------------------
+
+ScPatternAttr::ScPatternAttr( SfxItemSet* pItemSet, const String& rStyleName )
+ : SfxSetItem ( ATTR_PATTERN, pItemSet ),
+ pName ( new String( rStyleName ) ),
+ pStyle ( NULL )
+{
+}
+
+ScPatternAttr::ScPatternAttr( SfxItemSet* pItemSet, ScStyleSheet* pStyleSheet )
+ : SfxSetItem ( ATTR_PATTERN, pItemSet ),
+ pName ( NULL ),
+ pStyle ( pStyleSheet )
+{
+ if ( pStyleSheet )
+ GetItemSet().SetParent( &pStyleSheet->GetItemSet() );
+}
+
+ScPatternAttr::ScPatternAttr( SfxItemPool* pItemPool )
+ : SfxSetItem ( ATTR_PATTERN, new SfxItemSet( *pItemPool, ATTR_PATTERN_START, ATTR_PATTERN_END ) ),
+ pName ( NULL ),
+ pStyle ( NULL )
+{
+}
+
+ScPatternAttr::ScPatternAttr( const ScPatternAttr& rPatternAttr )
+ : SfxSetItem ( rPatternAttr ),
+ pStyle ( rPatternAttr.pStyle )
+{
+ if (rPatternAttr.pName)
+ pName = new String(*rPatternAttr.pName);
+ else
+ pName = NULL;
+}
+
+__EXPORT ScPatternAttr::~ScPatternAttr()
+{
+ delete pName;
+}
+
+SfxPoolItem* __EXPORT ScPatternAttr::Clone( SfxItemPool *pPool ) const
+{
+ ScPatternAttr* pPattern = new ScPatternAttr( GetItemSet().Clone(TRUE, pPool) );
+
+ pPattern->pStyle = pStyle;
+ pPattern->pName = pName ? new String(*pName) : NULL;
+
+ return pPattern;
+}
+
+inline int StrCmp( const String* pStr1, const String* pStr2 )
+{
+ return ( pStr1 ? ( pStr2 ? ( *pStr1 == *pStr2 ) : FALSE ) : ( pStr2 ? FALSE : TRUE ) );
+}
+
+int __EXPORT ScPatternAttr::operator==( const SfxPoolItem& rCmp ) const
+{
+ return ( SfxSetItem::operator==(rCmp) &&
+ StrCmp( GetStyleName(), ((const ScPatternAttr&)rCmp).GetStyleName() ) );
+}
+
+SfxPoolItem* __EXPORT ScPatternAttr::Create( SvStream& rStream, USHORT nVersion ) const
+{
+ String* pStr;
+ BOOL bHasStyle;
+ short eFamDummy;
+
+ rStream >> bHasStyle;
+
+ if ( bHasStyle )
+ {
+ pStr = new String;
+ rStream.ReadByteString( *pStr, rStream.GetStreamCharSet() );
+ rStream >> eFamDummy; // wg. altem Dateiformat
+ }
+ else
+ pStr = new String( ScGlobal::GetRscString(STR_STYLENAME_STANDARD) );
+
+ SfxItemSet *pSet = new SfxItemSet( *GetItemSet().GetPool(),
+ ATTR_PATTERN_START, ATTR_PATTERN_END );
+ pSet->Load( rStream );
+
+ ScPatternAttr* pPattern = new ScPatternAttr( pSet );
+
+ pPattern->pName = pStr;
+
+ return pPattern;
+}
+
+SvStream& __EXPORT ScPatternAttr::Store(SvStream& rStream, USHORT nItemVersion) const
+{
+ rStream << (BOOL)TRUE;
+
+ if ( pStyle )
+ rStream.WriteByteString( pStyle->GetName(), rStream.GetStreamCharSet() );
+ else if ( pName ) // wenn Style geloescht ist/war
+ rStream.WriteByteString( *pName, rStream.GetStreamCharSet() );
+ else
+ rStream.WriteByteString( ScGlobal::GetRscString(STR_STYLENAME_STANDARD),
+ rStream.GetStreamCharSet() );
+
+ rStream << (short)SFX_STYLE_FAMILY_PARA; // wg. altem Dateiformat
+
+ GetItemSet().Store( rStream );
+
+ return rStream;
+}
+
+void ScPatternAttr::GetFont( Font& rFont, OutputDevice* pOutDev, const Fraction* pScale,
+ const SfxItemSet* pCondSet ) const
+{
+ // Items auslesen
+
+ const SfxItemSet& rMySet = GetItemSet();
+ const SvxFontItem* pFontAttr;
+ UINT32 nFontHeight;
+ FontWeight eWeight;
+ FontItalic eItalic;
+ FontUnderline eUnder;
+ FontStrikeout eStrike;
+ BOOL bOutline;
+ BOOL bShadow;
+ Color aColor;
+
+ if ( pCondSet )
+ {
+ const SfxPoolItem* pItem;
+
+ if ( pCondSet->GetItemState( ATTR_FONT, TRUE, &pItem ) != SFX_ITEM_SET )
+ pItem = &rMySet.Get( ATTR_FONT );
+ pFontAttr = (const SvxFontItem*) pItem;
+
+ if ( pCondSet->GetItemState( ATTR_FONT_HEIGHT, TRUE, &pItem ) != SFX_ITEM_SET )
+ pItem = &rMySet.Get( ATTR_FONT_HEIGHT );
+ nFontHeight = ((const SvxFontHeightItem*)pItem)->GetHeight();
+
+ if ( pCondSet->GetItemState( ATTR_FONT_WEIGHT, TRUE, &pItem ) != SFX_ITEM_SET )
+ pItem = &rMySet.Get( ATTR_FONT_WEIGHT );
+ eWeight = (FontWeight)((const SvxWeightItem*)pItem)->GetValue();
+
+ if ( pCondSet->GetItemState( ATTR_FONT_POSTURE, TRUE, &pItem ) != SFX_ITEM_SET )
+ pItem = &rMySet.Get( ATTR_FONT_POSTURE );
+ eItalic = (FontItalic)((const SvxPostureItem*)pItem)->GetValue();
+
+ if ( pCondSet->GetItemState( ATTR_FONT_UNDERLINE, TRUE, &pItem ) != SFX_ITEM_SET )
+ pItem = &rMySet.Get( ATTR_FONT_UNDERLINE );
+ eUnder = (FontUnderline)((const SvxUnderlineItem*)pItem)->GetValue();
+
+ if ( pCondSet->GetItemState( ATTR_FONT_CROSSEDOUT, TRUE, &pItem ) != SFX_ITEM_SET )
+ pItem = &rMySet.Get( ATTR_FONT_CROSSEDOUT );
+ eStrike = (FontStrikeout)((const SvxCrossedOutItem*)pItem)->GetValue();
+
+ if ( pCondSet->GetItemState( ATTR_FONT_CONTOUR, TRUE, &pItem ) != SFX_ITEM_SET )
+ pItem = &rMySet.Get( ATTR_FONT_CONTOUR );
+ bOutline = ((const SvxContourItem*)pItem)->GetValue();
+
+ if ( pCondSet->GetItemState( ATTR_FONT_SHADOWED, TRUE, &pItem ) != SFX_ITEM_SET )
+ pItem = &rMySet.Get( ATTR_FONT_SHADOWED );
+ bShadow = ((const SvxShadowedItem*)pItem)->GetValue();
+
+ if ( pCondSet->GetItemState( ATTR_FONT_COLOR, TRUE, &pItem ) != SFX_ITEM_SET )
+ pItem = &rMySet.Get( ATTR_FONT_COLOR );
+ aColor = ((const SvxColorItem*)pItem)->GetValue();
+ }
+ else // alles aus rMySet
+ {
+ pFontAttr = &(const SvxFontItem&)rMySet.Get( ATTR_FONT );
+ nFontHeight = ((const SvxFontHeightItem&)
+ rMySet.Get( ATTR_FONT_HEIGHT )).GetHeight();
+ eWeight = (FontWeight)((const SvxWeightItem&)
+ rMySet.Get( ATTR_FONT_WEIGHT )).GetValue();
+ eItalic = (FontItalic)((const SvxPostureItem&)
+ rMySet.Get( ATTR_FONT_POSTURE )).GetValue();
+ eUnder = (FontUnderline)((const SvxUnderlineItem&)
+ rMySet.Get( ATTR_FONT_UNDERLINE )).GetValue();
+ eStrike = (FontStrikeout)((const SvxCrossedOutItem&)
+ rMySet.Get( ATTR_FONT_CROSSEDOUT )).GetValue();
+ bOutline = ((const SvxContourItem&)
+ rMySet.Get( ATTR_FONT_CONTOUR )).GetValue();
+ bShadow = ((const SvxShadowedItem&)
+ rMySet.Get( ATTR_FONT_SHADOWED )).GetValue();
+ aColor = ((const SvxColorItem&)
+ rMySet.Get( ATTR_FONT_COLOR )).GetValue();
+ }
+ DBG_ASSERT(pFontAttr,"nanu?");
+
+ // auswerten
+
+ // FontItem:
+
+ if (rFont.GetName() != pFontAttr->GetFamilyName())
+ rFont.SetName( pFontAttr->GetFamilyName() );
+ if (rFont.GetStyleName() != pFontAttr->GetStyleName())
+ rFont.SetStyleName( pFontAttr->GetStyleName() );
+ if (rFont.GetFamily() != pFontAttr->GetFamily())
+ rFont.SetFamily( pFontAttr->GetFamily() );
+ if (rFont.GetCharSet() != pFontAttr->GetCharSet())
+ rFont.SetCharSet( pFontAttr->GetCharSet() );
+ if (rFont.GetPitch() != pFontAttr->GetPitch())
+ rFont.SetPitch( pFontAttr->GetPitch() );
+
+ // Groesse
+
+ if ( pOutDev != NULL )
+ {
+ Size aEffSize;
+ Fraction aFraction( 1,1 );
+ if (pScale)
+ aFraction = *pScale;
+ Size aSize( 0, (long) nFontHeight );
+ MapMode aDestMode = pOutDev->GetMapMode();
+ MapMode aSrcMode( MAP_TWIP, Point(), aFraction, aFraction );
+ if (aDestMode.GetMapUnit() == MAP_PIXEL)
+ aEffSize = pOutDev->LogicToPixel( aSize, aSrcMode );
+ else
+ {
+ Fraction aFractOne(1,1);
+ aDestMode.SetScaleX( aFractOne );
+ aDestMode.SetScaleY( aFractOne );
+ aEffSize = OutputDevice::LogicToLogic( aSize, aSrcMode, aDestMode );
+ }
+ rFont.SetSize( aEffSize );
+ }
+ else /* if pOutDev != NULL */
+ {
+ rFont.SetSize( Size( 0, (long) nFontHeight ) );
+ }
+
+ // Auszeichnungen
+
+ if (rFont.GetWeight() != eWeight)
+ rFont.SetWeight( eWeight );
+ if (rFont.GetItalic() != eItalic)
+ rFont.SetItalic( eItalic );
+ if (rFont.GetUnderline() != eUnder)
+ rFont.SetUnderline( eUnder );
+ if (rFont.GetStrikeout() != eStrike)
+ rFont.SetStrikeout( eStrike );
+ if (rFont.IsOutline() != bOutline)
+ rFont.SetOutline( bOutline );
+ if (rFont.IsShadow() != bShadow)
+ rFont.SetShadow( bShadow );
+ if (rFont.GetColor() != aColor)
+ rFont.SetColor( aColor );
+ if (!rFont.IsTransparent())
+ rFont.SetTransparent( TRUE );
+}
+
+void ScPatternAttr::FillEditItemSet( SfxItemSet* pEditSet, const SfxItemSet* pCondSet ) const
+{
+ // Items auslesen
+
+ const SfxItemSet& rMySet = GetItemSet();
+
+ SvxColorItem aColorItem(EE_CHAR_COLOR); // Item komplett uebernehmen
+ SvxFontItem aFontItem(EE_CHAR_FONTINFO); // Item komplett uebernehmen
+ long nTHeight; // Twips
+ FontWeight eWeight;
+ FontUnderline eUnder;
+ FontStrikeout eStrike;
+ FontItalic eItalic;
+ BOOL bOutline;
+ BOOL bShadow;
+
+ if ( pCondSet )
+ {
+ const SfxPoolItem* pItem;
+
+ if ( pCondSet->GetItemState( ATTR_FONT_COLOR, TRUE, &pItem ) != SFX_ITEM_SET )
+ pItem = &rMySet.Get( ATTR_FONT_COLOR );
+ aColorItem = *(const SvxColorItem*)pItem;
+
+ if ( pCondSet->GetItemState( ATTR_FONT, TRUE, &pItem ) != SFX_ITEM_SET )
+ pItem = &rMySet.Get( ATTR_FONT );
+ aFontItem = *(const SvxFontItem*)pItem;
+
+ if ( pCondSet->GetItemState( ATTR_FONT_HEIGHT, TRUE, &pItem ) != SFX_ITEM_SET )
+ pItem = &rMySet.Get( ATTR_FONT_HEIGHT );
+ nTHeight = ((const SvxFontHeightItem*)pItem)->GetHeight();
+
+ if ( pCondSet->GetItemState( ATTR_FONT_WEIGHT, TRUE, &pItem ) != SFX_ITEM_SET )
+ pItem = &rMySet.Get( ATTR_FONT_WEIGHT );
+ eWeight = (FontWeight)((const SvxWeightItem*)pItem)->GetValue();
+
+ if ( pCondSet->GetItemState( ATTR_FONT_POSTURE, TRUE, &pItem ) != SFX_ITEM_SET )
+ pItem = &rMySet.Get( ATTR_FONT_POSTURE );
+ eItalic = (FontItalic)((const SvxPostureItem*)pItem)->GetValue();
+
+ if ( pCondSet->GetItemState( ATTR_FONT_UNDERLINE, TRUE, &pItem ) != SFX_ITEM_SET )
+ pItem = &rMySet.Get( ATTR_FONT_UNDERLINE );
+ eUnder = (FontUnderline)((const SvxUnderlineItem*)pItem)->GetValue();
+
+ if ( pCondSet->GetItemState( ATTR_FONT_CROSSEDOUT, TRUE, &pItem ) != SFX_ITEM_SET )
+ pItem = &rMySet.Get( ATTR_FONT_CROSSEDOUT );
+ eStrike = (FontStrikeout)((const SvxCrossedOutItem*)pItem)->GetValue();
+
+ if ( pCondSet->GetItemState( ATTR_FONT_CONTOUR, TRUE, &pItem ) != SFX_ITEM_SET )
+ pItem = &rMySet.Get( ATTR_FONT_CONTOUR );
+ bOutline = ((const SvxContourItem*)pItem)->GetValue();
+
+ if ( pCondSet->GetItemState( ATTR_FONT_SHADOWED, TRUE, &pItem ) != SFX_ITEM_SET )
+ pItem = &rMySet.Get( ATTR_FONT_SHADOWED );
+ bShadow = ((const SvxShadowedItem*)pItem)->GetValue();
+ }
+ else // alles direkt aus Pattern
+ {
+ aColorItem = (const SvxColorItem&) rMySet.Get( ATTR_FONT_COLOR );
+ aFontItem = (const SvxFontItem&) rMySet.Get( ATTR_FONT );
+ nTHeight = ((const SvxFontHeightItem&)
+ rMySet.Get( ATTR_FONT_HEIGHT )).GetHeight();
+ eWeight = (FontWeight)((const SvxWeightItem&)
+ rMySet.Get( ATTR_FONT_WEIGHT )).GetValue();
+ eItalic = (FontItalic)((const SvxPostureItem&)
+ rMySet.Get( ATTR_FONT_POSTURE )).GetValue();
+ eUnder = (FontUnderline)((const SvxUnderlineItem&)
+ rMySet.Get( ATTR_FONT_UNDERLINE )).GetValue();
+ eStrike = (FontStrikeout)((const SvxCrossedOutItem&)
+ rMySet.Get( ATTR_FONT_CROSSEDOUT )).GetValue();
+ bOutline = ((const SvxContourItem&)
+ rMySet.Get( ATTR_FONT_CONTOUR )).GetValue();
+ bShadow = ((const SvxShadowedItem&)
+ rMySet.Get( ATTR_FONT_SHADOWED )).GetValue();
+ }
+
+ // kompatibel zu LogicToLogic rechnen, also 2540/1440 = 127/72, und runden
+
+ long nHeight = (nTHeight * 127 + 36) / 72; // 36==72/2
+
+ // Items in Edit-Set stecken
+
+ pEditSet->Put( aColorItem );
+ pEditSet->Put( aFontItem );
+ pEditSet->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) );
+ pEditSet->Put( SvxWeightItem ( eWeight, EE_CHAR_WEIGHT ) );
+ pEditSet->Put( SvxUnderlineItem ( eUnder, EE_CHAR_UNDERLINE ) );
+ pEditSet->Put( SvxCrossedOutItem( eStrike, EE_CHAR_STRIKEOUT ) );
+ pEditSet->Put( SvxPostureItem ( eItalic, EE_CHAR_ITALIC ) );
+ pEditSet->Put( SvxContourItem ( bOutline, EE_CHAR_OUTLINE ) );
+ pEditSet->Put( SvxShadowedItem ( bShadow, EE_CHAR_SHADOW ) );
+}
+
+void ScPatternAttr::GetFromEditItemSet( const SfxItemSet* pEditSet )
+{
+ SfxItemSet& rMySet = GetItemSet();
+ const SfxPoolItem* pItem;
+
+ if (pEditSet->GetItemState(EE_CHAR_COLOR,TRUE,&pItem) == SFX_ITEM_SET)
+ rMySet.Put( SvxColorItem(ATTR_FONT_COLOR) = *(const SvxColorItem*)pItem );
+ if (pEditSet->GetItemState(EE_CHAR_FONTINFO,TRUE,&pItem) == SFX_ITEM_SET)
+ rMySet.Put( SvxFontItem(ATTR_FONT) = *(const SvxFontItem*)pItem );
+ if (pEditSet->GetItemState(EE_CHAR_FONTHEIGHT,TRUE,&pItem) == SFX_ITEM_SET)
+ {
+ // kompatibel zu LogicToLogic rechnen, also 2540/1440 = 127/72
+
+ long nMHeight = ((const SvxFontHeightItem*)pItem)->GetHeight();
+// long nHeight = ( nMHeight * 72 ) / 127; // Rundungsfehler!
+ long nHeight = (nMHeight * 72 + 63) / 127; // 63==127/2
+ rMySet.Put( SvxFontHeightItem( nHeight, 100, ATTR_FONT_HEIGHT ) );
+ }
+ if (pEditSet->GetItemState(EE_CHAR_WEIGHT,TRUE,&pItem) == SFX_ITEM_SET)
+ rMySet.Put( SvxWeightItem( (FontWeight)((const SvxWeightItem*)pItem)->GetValue(),
+ ATTR_FONT_WEIGHT) );
+ if (pEditSet->GetItemState(EE_CHAR_UNDERLINE,TRUE,&pItem) == SFX_ITEM_SET)
+ rMySet.Put( SvxUnderlineItem( (FontUnderline)((const SvxUnderlineItem*)pItem)->GetValue(),
+ ATTR_FONT_UNDERLINE) );
+ if (pEditSet->GetItemState(EE_CHAR_STRIKEOUT,TRUE,&pItem) == SFX_ITEM_SET)
+ rMySet.Put( SvxCrossedOutItem( (FontStrikeout)((const SvxCrossedOutItem*)pItem)->GetValue(),
+ ATTR_FONT_CROSSEDOUT) );
+ if (pEditSet->GetItemState(EE_CHAR_ITALIC,TRUE,&pItem) == SFX_ITEM_SET)
+ rMySet.Put( SvxPostureItem( (FontItalic)((const SvxPostureItem*)pItem)->GetValue(),
+ ATTR_FONT_POSTURE) );
+ if (pEditSet->GetItemState(EE_CHAR_OUTLINE,TRUE,&pItem) == SFX_ITEM_SET)
+ rMySet.Put( SvxContourItem( ((const SvxContourItem*)pItem)->GetValue(),
+ ATTR_FONT_CONTOUR) );
+ if (pEditSet->GetItemState(EE_CHAR_SHADOW,TRUE,&pItem) == SFX_ITEM_SET)
+ rMySet.Put( SvxShadowedItem( ((const SvxShadowedItem*)pItem)->GetValue(),
+ ATTR_FONT_SHADOWED) );
+ if (pEditSet->GetItemState(EE_PARA_JUST,TRUE,&pItem) == SFX_ITEM_SET)
+ {
+ SvxCellHorJustify eVal;
+ switch ( ((const SvxAdjustItem*)pItem)->GetAdjust() )
+ {
+ case SVX_ADJUST_LEFT:
+ // #30154# EditEngine Default ist bei dem GetAttribs() ItemSet
+ // immer gesetzt!
+ // ob links oder rechts entscheiden wir selbst bei Text/Zahl
+ eVal = SVX_HOR_JUSTIFY_STANDARD;
+ break;
+ case SVX_ADJUST_RIGHT:
+ eVal = SVX_HOR_JUSTIFY_RIGHT;
+ break;
+ case SVX_ADJUST_BLOCK:
+ eVal = SVX_HOR_JUSTIFY_BLOCK;
+ break;
+ case SVX_ADJUST_CENTER:
+ eVal = SVX_HOR_JUSTIFY_CENTER;
+ break;
+ case SVX_ADJUST_BLOCKLINE:
+ eVal = SVX_HOR_JUSTIFY_BLOCK;
+ break;
+ case SVX_ADJUST_END:
+ eVal = SVX_HOR_JUSTIFY_RIGHT;
+ break;
+ default:
+ eVal = SVX_HOR_JUSTIFY_STANDARD;
+ }
+ if ( eVal != SVX_HOR_JUSTIFY_STANDARD )
+ rMySet.Put( SvxHorJustifyItem( eVal, ATTR_HOR_JUSTIFY) );
+ }
+}
+
+void ScPatternAttr::FillEditParaItems( SfxItemSet* pEditSet ) const
+{
+ // in GetFromEditItemSet schon dabei, in FillEditItemSet aber nicht
+ // Hor. Ausrichtung Standard wird immer als "links" umgesetzt
+
+ const SfxItemSet& rMySet = GetItemSet();
+
+ SvxCellHorJustify eHorJust = (SvxCellHorJustify)
+ ((const SvxHorJustifyItem&)rMySet.Get(ATTR_HOR_JUSTIFY)).GetValue();
+
+ SvxAdjust eSvxAdjust;
+ switch (eHorJust)
+ {
+ case SVX_HOR_JUSTIFY_RIGHT: eSvxAdjust = SVX_ADJUST_RIGHT; break;
+ case SVX_HOR_JUSTIFY_CENTER: eSvxAdjust = SVX_ADJUST_CENTER; break;
+ case SVX_HOR_JUSTIFY_BLOCK: eSvxAdjust = SVX_ADJUST_BLOCK; break;
+ default: eSvxAdjust = SVX_ADJUST_LEFT; break;
+ }
+ pEditSet->Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
+}
+
+void ScPatternAttr::DeleteUnchanged( const ScPatternAttr* pOldAttrs )
+{
+ SfxItemSet* pSet = &GetItemSet();
+ const SfxItemSet* pOldSet = &pOldAttrs->GetItemSet();
+
+ for ( USHORT nWhich=ATTR_PATTERN_START; nWhich<=ATTR_PATTERN_END; nWhich++ )
+ {
+ const SfxPoolItem* pItem1 = &pSet->Get( nWhich );
+ const SfxPoolItem* pItem2 = &pOldSet->Get( nWhich );
+ if ( pItem1 == pItem2 )
+ pSet->ClearItem( nWhich );
+ }
+}
+
+BOOL ScPatternAttr::HasItemsSet( const USHORT* pWhich ) const
+{
+ const SfxItemSet& rSet = GetItemSet();
+ for (USHORT i=0; pWhich[i]; i++)
+ if ( rSet.GetItemState( pWhich[i], FALSE ) == SFX_ITEM_SET )
+ return TRUE;
+ return FALSE;
+}
+
+void ScPatternAttr::ClearItems( const USHORT* pWhich )
+{
+ SfxItemSet& rSet = GetItemSet();
+ for (USHORT i=0; pWhich[i]; i++)
+ rSet.ClearItem(pWhich[i]);
+}
+
+SfxStyleSheetBase* lcl_CopyStyleToPool
+ (
+ SfxStyleSheetBase* pSrcStyle,
+ SfxStyleSheetBasePool* pSrcPool,
+ SfxStyleSheetBasePool* pDestPool
+ )
+{
+ if ( !pSrcStyle || !pDestPool || !pSrcPool )
+ {
+ DBG_ERROR( "CopyStyleToPool: Invalid Arguments :-/" );
+ return NULL;
+ }
+
+ //--------------------------------------------------------
+
+ const String aStrSrcStyle = pSrcStyle->GetName();
+ const SfxStyleFamily eFamily = pSrcStyle->GetFamily();
+ SfxStyleSheetBase* pDestStyle = pDestPool->Find( aStrSrcStyle, eFamily );
+
+ if ( !pDestStyle )
+ {
+ const String aStrParent = pSrcStyle->GetParent();
+
+ pDestStyle = &pDestPool->Make( aStrSrcStyle, eFamily, SFXSTYLEBIT_USERDEF );
+ pDestStyle->GetItemSet().Put( pSrcStyle->GetItemSet() );
+
+ // ggF. abgeleitete Styles erzeugen, wenn nicht vorhanden:
+
+ if ( ScGlobal::GetRscString(STR_STYLENAME_STANDARD) != aStrParent &&
+ aStrSrcStyle != aStrParent &&
+ !pDestPool->Find( aStrParent, eFamily ) )
+ {
+ lcl_CopyStyleToPool( pSrcPool->Find( aStrParent, eFamily ),
+ pSrcPool, pDestPool );
+ }
+
+ pDestStyle->SetParent( aStrParent );
+ }
+
+ return pDestStyle;
+}
+
+ScPatternAttr* ScPatternAttr::PutInPool( ScDocument* pDestDoc, ScDocument* pSrcDoc ) const
+{
+ const SfxItemSet* pSrcSet = &GetItemSet();
+
+ ScPatternAttr* pDestPattern = new ScPatternAttr(pDestDoc->GetPool());
+ SfxItemSet* pDestSet = &pDestPattern->GetItemSet();
+
+ // Zellformatvorlage in anderes Dokument kopieren:
+
+ if ( pDestDoc != pSrcDoc )
+ {
+ DBG_ASSERT( pStyle, "Missing Pattern-Style! :-/" );
+
+ // wenn Vorlage im DestDoc vorhanden, dieses benutzen, sonst Style
+ // mit Parent-Vorlagen kopieren/ggF. erzeugen und dem DestDoc hinzufuegen
+
+ SfxStyleSheetBase* pStyleCpy = lcl_CopyStyleToPool( pStyle,
+ pSrcDoc->GetStyleSheetPool(),
+ pDestDoc->GetStyleSheetPool() );
+
+ pDestPattern->SetStyleSheet( (ScStyleSheet*)pStyleCpy );
+ }
+
+ for ( USHORT nAttrId = ATTR_PATTERN_START; nAttrId <= ATTR_PATTERN_END; nAttrId++ )
+ {
+ const SfxPoolItem* pSrcItem;
+ SfxItemState eItemState = pSrcSet->GetItemState( nAttrId, FALSE, &pSrcItem );
+ if (eItemState==SFX_ITEM_ON)
+ {
+ SfxPoolItem* pNewItem = NULL;
+
+ if ( nAttrId == ATTR_CONDITIONAL )
+ {
+ // Bedingte Formate ins neue Dokument kopieren
+
+ ULONG nNewIndex = 0;
+ ScConditionalFormatList* pSrcList = pSrcDoc->GetCondFormList();
+ if ( pSrcList )
+ {
+ ULONG nOldIndex = ((const SfxUInt32Item*)pSrcItem)->GetValue();
+ const ScConditionalFormat* pOldData = pSrcList->GetFormat( nOldIndex );
+ if ( pOldData )
+ {
+ nNewIndex = pDestDoc->AddCondFormat( *pOldData );
+
+ // zugehoerige Styles auch mitkopieren
+ //! nur wenn Format bei Add neu angelegt
+
+ ScStyleSheetPool* pSrcSPool = pSrcDoc->GetStyleSheetPool();
+ ScStyleSheetPool* pDestSPool = pDestDoc->GetStyleSheetPool();
+ USHORT nStlCnt = pOldData->Count();
+ for (USHORT i=0; i<nStlCnt; i++)
+ {
+ String aName = pOldData->GetEntry(i)->GetStyle();
+ SfxStyleSheetBase* pSrcStl =
+ pSrcDoc->GetStyleSheetPool()->Find(aName, SFX_STYLE_FAMILY_PARA);
+ lcl_CopyStyleToPool( pSrcStl, pSrcSPool, pDestSPool );
+ }
+ }
+ }
+ pNewItem = new SfxUInt32Item( ATTR_CONDITIONAL, nNewIndex );
+ }
+ else if ( nAttrId == ATTR_VALIDDATA )
+ {
+ // Gueltigkeit ins neue Dokument kopieren
+
+ ULONG nNewIndex = 0;
+ ScValidationDataList* pSrcList = pSrcDoc->GetValidationList();
+ if ( pSrcList )
+ {
+ ULONG nOldIndex = ((const SfxUInt32Item*)pSrcItem)->GetValue();
+ const ScValidationData* pOldData = pSrcList->GetData( nOldIndex );
+ if ( pOldData )
+ nNewIndex = pDestDoc->AddValidationEntry( *pOldData );
+ }
+ pNewItem = new SfxUInt32Item( ATTR_VALIDDATA, nNewIndex );
+ }
+ else if ( nAttrId == ATTR_VALUE_FORMAT && pDestDoc->GetFormatExchangeList() )
+ {
+ // Zahlformate nach Exchange-Liste
+
+ ULONG nOldFormat = ((const SfxUInt32Item*)pSrcItem)->GetValue();
+ ULONG* pNewFormat = (ULONG*)pDestDoc->GetFormatExchangeList()->Get(nOldFormat);
+ if (pNewFormat)
+ pNewItem = new SfxUInt32Item( ATTR_VALUE_FORMAT, (UINT32) (*pNewFormat) );
+ }
+
+ if ( pNewItem )
+ {
+ pDestSet->Put(*pNewItem);
+ delete pNewItem;
+ }
+ else
+ pDestSet->Put(*pSrcItem);
+ }
+ }
+
+ ScPatternAttr* pPatternAttr =
+ (ScPatternAttr*) &pDestDoc->GetPool()->Put(*pDestPattern);
+ delete pDestPattern;
+ return pPatternAttr;
+}
+
+BOOL ScPatternAttr::IsVisible() const
+{
+ const SfxItemSet& rSet = GetItemSet();
+ const SfxItemPool* pPool = rSet.GetPool();
+
+ const SfxPoolItem* pItem;
+ SfxItemState eState;
+
+ eState = rSet.GetItemState( ATTR_BACKGROUND, TRUE, &pItem );
+ if ( eState == SFX_ITEM_SET )
+ if ( ((SvxBrushItem*)pItem)->GetColor().GetColor() != COL_TRANSPARENT )
+ return TRUE;
+
+ eState = rSet.GetItemState( ATTR_BORDER, TRUE, &pItem );
+ if ( eState == SFX_ITEM_SET )
+ {
+ SvxBoxItem* pBoxItem = (SvxBoxItem*) pItem;
+ if ( pBoxItem->GetTop() || pBoxItem->GetBottom() ||
+ pBoxItem->GetLeft() || pBoxItem->GetRight() )
+ return TRUE;
+ }
+
+ eState = rSet.GetItemState( ATTR_SHADOW, TRUE, &pItem );
+ if ( eState == SFX_ITEM_SET )
+ if ( ((SvxShadowItem*)pItem)->GetLocation() != SVX_SHADOW_NONE )
+ return TRUE;
+
+ return FALSE;
+}
+
+inline BOOL OneEqual( const SfxItemSet& rSet1, const SfxItemSet& rSet2, USHORT nId )
+{
+ const SfxPoolItem* pItem1 = &rSet1.Get(nId);
+ const SfxPoolItem* pItem2 = &rSet2.Get(nId);
+ return ( pItem1 == pItem2 || *pItem1 == *pItem2 );
+}
+
+BOOL ScPatternAttr::IsVisibleEqual( const ScPatternAttr& rOther ) const
+{
+ const SfxItemSet& rThisSet = GetItemSet();
+ const SfxItemSet& rOtherSet = rOther.GetItemSet();
+
+ return OneEqual( rThisSet, rOtherSet, ATTR_BACKGROUND ) &&
+ OneEqual( rThisSet, rOtherSet, ATTR_BORDER ) &&
+ OneEqual( rThisSet, rOtherSet, ATTR_SHADOW );
+
+ //! auch hier nur wirklich sichtbare Werte testen !!!
+}
+
+const String* ScPatternAttr::GetStyleName() const
+{
+ return pName ? pName : ( pStyle ? &pStyle->GetName() : NULL );
+}
+
+
+void ScPatternAttr::SetStyleSheet( ScStyleSheet* pNewStyle )
+{
+ if (pNewStyle)
+ {
+ SfxItemSet& rPatternSet = GetItemSet();
+ const SfxItemSet& rStyleSet = pNewStyle->GetItemSet();
+
+ for (USHORT i=ATTR_PATTERN_START; i<=ATTR_PATTERN_END; i++)
+ {
+ if (rStyleSet.GetItemState(i, TRUE) == SFX_ITEM_SET)
+ rPatternSet.ClearItem(i);
+ }
+ rPatternSet.SetParent(&pNewStyle->GetItemSet());
+ pStyle = pNewStyle;
+ DELETEZ( pName );
+ }
+ else
+ {
+ DBG_ERROR( "ScPatternAttr::SetStyleSheet( NULL ) :-|" );
+ GetItemSet().SetParent(NULL);
+ pStyle = NULL;
+ }
+}
+
+void ScPatternAttr::UpdateStyleSheet()
+{
+ if (pName)
+ {
+ pStyle = (ScStyleSheet*)pDoc->GetStyleSheetPool()->Find(*pName, SFX_STYLE_FAMILY_PARA);
+
+ // wenn Style nicht gefunden, Standard nehmen,
+ // damit keine leere Anzeige im Toolbox-Controller
+ //! es wird vorausgesetzt, dass "Standard" immer der erste Eintrag ist!
+ if (!pStyle)
+ {
+ SfxStyleSheetIterator* pIter = pDoc->GetStyleSheetPool()->CreateIterator(
+ SFX_STYLE_FAMILY_PARA, SFXSTYLEBIT_ALL );
+ pStyle = (ScStyleSheet*)pIter->First();
+ }
+
+ if (pStyle)
+ {
+ GetItemSet().SetParent(&pStyle->GetItemSet());
+ DELETEZ( pName );
+ }
+ }
+ else
+ pStyle = NULL;
+}
+
+void ScPatternAttr::StyleToName()
+{
+ // Style wurde geloescht, Namen merken:
+
+ if ( pStyle )
+ {
+ if ( pName )
+ *pName = pStyle->GetName();
+ else
+ pName = new String( pStyle->GetName() );
+
+ pStyle = NULL;
+ GetItemSet().SetParent( NULL );
+ }
+}
+
+BOOL ScPatternAttr::IsSymbolFont() const
+{
+ const SfxPoolItem* pItem;
+ if( GetItemSet().GetItemState( ATTR_FONT, TRUE, &pItem ) == SFX_ITEM_SET )
+ return BOOL( ((const SvxFontItem*) pItem)->GetCharSet()
+ == RTL_TEXTENCODING_SYMBOL );
+ else
+ return FALSE;
+}
+
+ULONG ScPatternAttr::GetNumberFormat( SvNumberFormatter* pFormatter ) const
+{
+ ULONG nFormat =
+ ((SfxUInt32Item*)&GetItemSet().Get( ATTR_VALUE_FORMAT ))->GetValue();
+ LanguageType eLang =
+ ((SvxLanguageItem*)&GetItemSet().Get( ATTR_LANGUAGE_FORMAT ))->GetLanguage();
+ if ( nFormat < SV_COUNTRY_LANGUAGE_OFFSET && eLang == LANGUAGE_SYSTEM )
+ ; // es bleibt wie es ist
+ else if ( pFormatter )
+ nFormat = pFormatter->GetFormatForLanguageIfBuiltIn( nFormat, eLang );
+ return nFormat;
+}
+
+// dasselbe, wenn bedingte Formatierung im Spiel ist:
+
+ULONG ScPatternAttr::GetNumberFormat( SvNumberFormatter* pFormatter,
+ const SfxItemSet* pCondSet ) const
+{
+ DBG_ASSERT(pFormatter,"GetNumberFormat ohne Formatter");
+
+ const SfxPoolItem* pFormItem;
+ if ( !pCondSet || pCondSet->GetItemState(ATTR_VALUE_FORMAT,TRUE,&pFormItem) != SFX_ITEM_SET )
+ pFormItem = &GetItemSet().Get(ATTR_VALUE_FORMAT);
+
+ const SfxPoolItem* pLangItem;
+ if ( !pCondSet || pCondSet->GetItemState(ATTR_LANGUAGE_FORMAT,TRUE,&pLangItem) != SFX_ITEM_SET )
+ pLangItem = &GetItemSet().Get(ATTR_LANGUAGE_FORMAT);
+
+ return pFormatter->GetFormatForLanguageIfBuiltIn(
+ ((SfxUInt32Item*)pFormItem)->GetValue(),
+ ((SvxLanguageItem*)pLangItem)->GetLanguage() );
+}
+
+const SfxPoolItem& ScPatternAttr::GetItem( USHORT nWhich, const SfxItemSet* pCondSet ) const
+{
+ const SfxPoolItem* pCondItem;
+ if ( pCondSet && pCondSet->GetItemState( nWhich, TRUE, &pCondItem ) == SFX_ITEM_SET )
+ return *pCondItem;
+
+ return GetItemSet().Get(nWhich);
+}
+
+// GetRotateVal testet vorher ATTR_ORIENTATION
+
+long ScPatternAttr::GetRotateVal( const SfxItemSet* pCondSet ) const
+{
+ long nAttrRotate = 0;
+
+ SvxCellOrientation eOrient;
+ const SfxPoolItem* pCondItem;
+ if ( pCondSet && pCondSet->GetItemState( ATTR_ORIENTATION, TRUE, &pCondItem ) == SFX_ITEM_SET )
+ eOrient = (SvxCellOrientation)((const SvxOrientationItem*)pCondItem)->GetValue();
+ else
+ eOrient = (SvxCellOrientation)((const SvxOrientationItem&)
+ GetItem(ATTR_ORIENTATION)).GetValue();
+
+ if ( eOrient == SVX_ORIENTATION_STANDARD )
+ {
+ if ( pCondSet && pCondSet->GetItemState(
+ ATTR_ROTATE_VALUE, TRUE, &pCondItem ) == SFX_ITEM_SET )
+ nAttrRotate = ((const SfxInt32Item*)pCondItem)->GetValue();
+ else
+ nAttrRotate = ((const SfxInt32Item&)GetItem(ATTR_ROTATE_VALUE)).GetValue();
+ }
+
+ return nAttrRotate;
+}
+
+BYTE ScPatternAttr::GetRotateDir( const SfxItemSet* pCondSet ) const
+{
+ BYTE nRet = SC_ROTDIR_NONE;
+
+ long nAttrRotate = GetRotateVal( pCondSet );
+ if ( nAttrRotate )
+ {
+ SvxRotateMode eRotMode = (SvxRotateMode)((const SvxRotateModeItem&)
+ GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue();
+
+ if ( eRotMode == SVX_ROTATE_MODE_STANDARD || nAttrRotate == 18000 )
+ nRet = SC_ROTDIR_STANDARD;
+ else if ( eRotMode == SVX_ROTATE_MODE_CENTER )
+ nRet = SC_ROTDIR_CENTER;
+ else if ( eRotMode == SVX_ROTATE_MODE_TOP || eRotMode == SVX_ROTATE_MODE_BOTTOM )
+ {
+ long nRot180 = nAttrRotate % 18000; // 1/100 Grad
+ if ( nRot180 == 9000 )
+ nRet = SC_ROTDIR_CENTER;
+ else if ( ( eRotMode == SVX_ROTATE_MODE_TOP && nRot180 < 9000 ) ||
+ ( eRotMode == SVX_ROTATE_MODE_BOTTOM && nRot180 > 9000 ) )
+ nRet = SC_ROTDIR_LEFT;
+ else
+ nRet = SC_ROTDIR_RIGHT;
+ }
+ }
+
+ return nRet;
+}
+
+
+
+
diff --git a/sc/source/core/data/pivot.cxx b/sc/source/core/data/pivot.cxx
new file mode 100644
index 000000000000..0caca2462e79
--- /dev/null
+++ b/sc/source/core/data/pivot.cxx
@@ -0,0 +1,2051 @@
+/*************************************************************************
+ *
+ * $RCSfile: pivot.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// -----------------------------------------------------------------------
+
+#pragma optimize("",off)
+#pragma optimize("q",off) // p-code off
+
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <svtools/zforlist.hxx>
+#include <tools/solar.h>
+#include <string.h>
+#include <math.h>
+
+
+#include "globstr.hrc"
+#include "global.hxx"
+#include "subtotal.hxx"
+#include "scitems.hxx"
+#include "attrib.hxx"
+#include "patattr.hxx"
+#include "docpool.hxx"
+#include "document.hxx"
+#include "userlist.hxx"
+#include "pivot.hxx"
+#include "cell.hxx"
+#include "rechead.hxx"
+#include "compiler.hxx" // fuer errNoValue
+#include "progress.hxx"
+
+
+// STATIC DATA -----------------------------------------------------------
+
+//! bei Gelegenheit...
+
+static short nStaticStrRefCount = 0;
+static String* pLabel[PIVOT_MAXFUNC+1]; // incl. "auto"
+static String* pLabelTotal;
+static String* pLabelData;
+
+static USHORT nDataMult = 1;
+
+#define nFirstLine 2
+
+static const USHORT nFuncMaskArr[PIVOT_MAXFUNC+1] =
+ { PIVOT_FUNC_SUM,
+ PIVOT_FUNC_COUNT,
+ PIVOT_FUNC_AVERAGE,
+ PIVOT_FUNC_MAX,
+ PIVOT_FUNC_MIN,
+ PIVOT_FUNC_PRODUCT,
+ PIVOT_FUNC_COUNT_NUM,
+ PIVOT_FUNC_STD_DEV,
+ PIVOT_FUNC_STD_DEVP,
+ PIVOT_FUNC_STD_VAR,
+ PIVOT_FUNC_STD_VARP,
+ PIVOT_FUNC_AUTO }; // automatisch
+
+// -----------------------------------------------------------------------
+
+// 1 Filter-Knopf
+// 2 Feldnamen links
+// 3 "Daten" links
+// 4 Feldnamen oben
+// 5 "Daten" oben
+// 6 einzelne "Gesamt" oben rechts
+// 7 "Gesamt" oben rechts
+// 8 einzelne "Gesamt" unten links
+// 9 "Gesamt" unten links
+// 10 innere Kategorie links
+// 11 Teilergebnis Label einzeln links
+// 12 Teilergebnis Label gesamt links
+// 13 letzte Kategorie links
+// 14 innere Kategorie oben
+// 15 Teilergebnis Label einzeln oben
+// 16 Teilergebnis Label gesamt oben
+// 17 letzte Kategorie oben
+// 18 Werte innen
+// 19 Werte in Teilergebnisspalte
+// 20 Werte in Gesamt-Spalte
+// 21 Werte in einzelnen Gesamt-Spalten
+// 22 Werte in Ergebnis-Zeile Teilergebnis oder Gesamt
+// 23 Kreuzung von Spalte/Zeile (Teilergebnis-Spalte)
+// 24 Kreuzung von Spalte/Zeile (Gesamt-Spalte)
+// 25 wie 24 bei einzelnen "Gesamt"
+
+short lcl_MaskToIndex( USHORT nFuncMask )
+{
+ short i;
+ for (i=0; i<=PIVOT_MAXFUNC; i++)
+ if (nFuncMask == nFuncMaskArr[i])
+ return i;
+
+ DBG_ERROR("Falsche Maske in MaskToIndex");
+ return 0;
+}
+
+BOOL lcl_IsEmptyLine( ScDocument* pDoc, const ScAddress& rPos, USHORT nCol2 )
+{
+ //! ans Document verschieben !!!
+
+ ScAddress aAdr( rPos );
+ for (USHORT nCol=aAdr.Col(); nCol<=nCol2; nCol++)
+ {
+ aAdr.SetCol( nCol );
+ if ( pDoc->GetCell( aAdr ) )
+ return FALSE;
+ }
+ return TRUE;
+}
+
+ScPivot::ScPivot(ScDocument* pDocument) :
+ pDoc (pDocument),
+ aQuery (),
+ bHasHeader (FALSE),
+ bIgnoreEmpty (FALSE),
+ bDetectCat (FALSE),
+ bMakeTotalCol (TRUE),
+ bMakeTotalRow (TRUE),
+ nColNameCount (0),
+ pColNames (NULL),
+ nSrcCol1 (0),
+ nSrcRow1 (0),
+ nSrcCol2 (0),
+ nSrcRow2 (0),
+ nSrcTab (0),
+ nDestCol1 (0),
+ nDestRow1 (0),
+ nDestCol2 (0),
+ nDestRow2 (0),
+ nDestTab (0),
+ nDataStartCol (0),
+ nDataStartRow (0),
+ nColCount (0),
+ nRowCount (0),
+ nDataCount (0),
+ bValidArea (FALSE),
+ bDataAtCol (FALSE)
+{
+ short i;
+ for (i=0; i<PIVOT_MAXFIELD; i++)
+ {
+ pColList[i] = new PivotStrCollection();
+ pRowList[i] = new PivotStrCollection();
+ }
+ pDataList = pColList[0];
+ ppDataArr = NULL;
+ nDataColCount = 0;
+ nDataRowCount = 0;
+ nRecCount = 0;
+ pColRef = NULL;
+
+ // Initialisierung der statischen Strings, wenn noetig
+ nStaticStrRefCount += 1;
+ if ( nStaticStrRefCount < 2 )
+ {
+ pLabelTotal = new String( ScGlobal::GetRscString(STR_PIVOT_TOTAL) );
+ pLabelData = new String( ScGlobal::GetRscString(STR_PIVOT_DATA) );
+
+ for ( i=0; i<=PIVOT_MAXFUNC; i++ ) // incl. "auto"
+ pLabel[i] = new String; // kein Leerzeichen
+
+ *pLabel[ 0] = ScGlobal::GetRscString(STR_FUN_TEXT_SUM);
+ *pLabel[ 1] = ScGlobal::GetRscString(STR_FUN_TEXT_COUNT);
+ *pLabel[ 2] = ScGlobal::GetRscString(STR_FUN_TEXT_AVG);
+ *pLabel[ 3] = ScGlobal::GetRscString(STR_FUN_TEXT_MAX);
+ *pLabel[ 4] = ScGlobal::GetRscString(STR_FUN_TEXT_MIN);
+ *pLabel[ 5] = ScGlobal::GetRscString(STR_FUN_TEXT_PRODUCT);
+ *pLabel[ 6] = ScGlobal::GetRscString(STR_FUN_TEXT_COUNT); // Count2
+ *pLabel[ 7] = ScGlobal::GetRscString(STR_FUN_TEXT_STDDEV);
+ *pLabel[ 8] = ScGlobal::GetRscString(STR_FUN_TEXT_STDDEV); // Stddev2
+ *pLabel[ 9] = ScGlobal::GetRscString(STR_FUN_TEXT_VAR);
+ *pLabel[10] = ScGlobal::GetRscString(STR_FUN_TEXT_VAR); // Var2
+ *pLabel[11] = ScGlobal::GetRscString(STR_TABLE_ERGEBNIS);
+ }
+}
+
+ScPivot::ScPivot(const ScPivot& rPivot):
+ pDoc (rPivot.pDoc),
+ aQuery (rPivot.aQuery),
+ bHasHeader (rPivot.bHasHeader),
+ bIgnoreEmpty (rPivot.bIgnoreEmpty),
+ bDetectCat (rPivot.bDetectCat),
+ bMakeTotalCol (rPivot.bMakeTotalCol),
+ bMakeTotalRow (rPivot.bMakeTotalRow),
+ nColNameCount (0),
+ pColNames (NULL),
+ aName (rPivot.aName),
+ aTag (rPivot.aTag),
+ nSrcCol1 (rPivot.nSrcCol1),
+ nSrcRow1 (rPivot.nSrcRow1),
+ nSrcCol2 (rPivot.nSrcCol2),
+ nSrcRow2 (rPivot.nSrcRow2),
+ nSrcTab (rPivot.nSrcTab),
+ nDestCol1 (rPivot.nDestCol1),
+ nDestRow1 (rPivot.nDestRow1),
+ nDestCol2 (rPivot.nDestCol2),
+ nDestRow2 (rPivot.nDestRow2),
+ nDestTab (rPivot.nDestTab),
+ nDataStartCol (0),
+ nDataStartRow (0),
+ nColCount (0),
+ nRowCount (0),
+ nDataCount (0),
+ bValidArea (FALSE),
+ bDataAtCol (FALSE)
+{
+ if (rPivot.nColNameCount && rPivot.pColNames)
+ {
+ nColNameCount = rPivot.nColNameCount;
+ pColNames = new String[nColNameCount];
+ for (USHORT nCol=0; nCol<nColNameCount; nCol++)
+ pColNames[nCol] = rPivot.pColNames[nCol];
+ }
+
+ short i;
+ for (i=0; i<PIVOT_MAXFIELD; i++)
+ {
+ pColList[i] = new PivotStrCollection();
+ pRowList[i] = new PivotStrCollection();
+ }
+ pDataList = pColList[0];
+ ppDataArr = NULL;
+ nRecCount = 0;
+ pColRef = NULL;
+
+ SetColFields( rPivot.aColArr, rPivot.nColCount );
+ SetRowFields( rPivot.aRowArr, rPivot.nRowCount );
+ SetDataFields( rPivot.aDataArr, rPivot.nDataCount );
+
+ nStaticStrRefCount += 1;
+}
+
+ScPivot::~ScPivot()
+{
+ short i;
+ for (i=0; i<PIVOT_MAXFIELD; i++)
+ {
+ delete pColList[i];
+ delete pRowList[i];
+ }
+ if (ppDataArr)
+ {
+ for (i=0; i<nDataRowCount; i++)
+ delete[] ppDataArr[i];
+ delete[] ppDataArr;
+ ppDataArr = NULL;
+ }
+ delete[] pColRef;
+
+ delete[] pColNames;
+
+ // statische Strings ggF. wieder abraeumen
+ nStaticStrRefCount -= 1;
+ if ( nStaticStrRefCount == 0 )
+ {
+ delete pLabelTotal;
+ delete pLabelData;
+
+ for ( i=0; i<=PIVOT_MAXFUNC; i++ ) // incl. "auto"
+ delete pLabel[i];
+ }
+}
+
+ScPivot* ScPivot::CreateNew() const
+{
+ ScPivot* pNewPivot = new ScPivot( pDoc );
+
+ pNewPivot->SetQuery(aQuery);
+ pNewPivot->SetHeader(bHasHeader);
+ pNewPivot->SetIgnoreEmpty(bIgnoreEmpty);
+ pNewPivot->SetDetectCat(bDetectCat);
+ pNewPivot->SetMakeTotalCol(bMakeTotalCol);
+ pNewPivot->SetMakeTotalRow(bMakeTotalRow);
+
+ pNewPivot->SetSrcArea( nSrcCol1, nSrcRow1, nSrcCol2, nSrcRow2, nSrcTab );
+ pNewPivot->SetDestPos( nDestCol1, nDestRow1, nDestTab );
+
+ return pNewPivot;
+}
+
+void lcl_LoadFieldArr30( SvStream& rStream, PivotField* pField, USHORT nCount )
+{
+ USHORT i;
+
+ for (i=0; i<nCount; i++)
+ {
+ rStream >> pField[i].nCol
+ >> pField[i].nFuncMask
+ >> pField[i].nFuncCount;
+ }
+}
+
+void lcl_LoadFieldArr( SvStream& rStream, PivotField* pField, USHORT nCount )
+{
+ USHORT i;
+
+ for (i=0; i<nCount; i++)
+ {
+ BYTE cData;
+ rStream >> cData;
+ if( cData & 0x0F )
+ rStream.SeekRel( cData & 0x0F );
+ rStream >> pField[i].nCol
+ >> pField[i].nFuncMask
+ >> pField[i].nFuncCount;
+ }
+}
+
+void lcl_SaveFieldArr( SvStream& rStream, const PivotField* pField, USHORT nCount )
+{
+ USHORT i;
+
+ for (i=0; i<nCount; i++)
+ {
+ rStream << (BYTE) 0x00
+ << pField[i].nCol
+ << pField[i].nFuncMask
+ << pField[i].nFuncCount;
+ }
+}
+
+// nach Load muessen Daten neu berechnet werden !
+
+BOOL ScPivot::Load( SvStream& rStream, ScMultipleReadHeader& rHdr )
+{
+ rHdr.StartEntry();
+
+ rStream >> bHasHeader
+
+ >> nSrcCol1
+ >> nSrcRow1
+ >> nSrcCol2
+ >> nSrcRow2
+ >> nSrcTab
+
+ >> nDestCol1
+ >> nDestRow1
+ >> nDestCol2
+ >> nDestRow2
+ >> nDestTab;
+
+ // Arrays immer ueber Set...Fields initalisieren!
+
+ short nCount;
+ PivotFieldArr aFieldArr;
+
+ if( pDoc->GetSrcVersion() >= SC_DATABYTES2 )
+ {
+ rStream >> nCount;
+ lcl_LoadFieldArr( rStream, aFieldArr, nCount );
+ SetColFields(aFieldArr, nCount);
+
+ rStream >> nCount;
+ lcl_LoadFieldArr( rStream, aFieldArr, nCount );
+ SetRowFields(aFieldArr, nCount);
+
+ rStream >> nCount;
+ lcl_LoadFieldArr( rStream, aFieldArr, nCount );
+ SetDataFields(aFieldArr, nCount);
+ }
+ else
+ {
+ rStream >> nCount;
+ lcl_LoadFieldArr30( rStream, aFieldArr, nCount );
+ SetColFields(aFieldArr, nCount);
+
+ rStream >> nCount;
+ lcl_LoadFieldArr30( rStream, aFieldArr, nCount );
+ SetRowFields(aFieldArr, nCount);
+
+ rStream >> nCount;
+ lcl_LoadFieldArr30( rStream, aFieldArr, nCount );
+ SetDataFields(aFieldArr, nCount);
+ }
+
+ aQuery.Load( rStream );
+
+ rStream >> bIgnoreEmpty;
+ rStream >> bDetectCat;
+
+ if (rHdr.BytesLeft())
+ {
+ rStream >> bMakeTotalCol; // ab 355i
+ rStream >> bMakeTotalRow;
+ }
+
+ if (rHdr.BytesLeft()) // ab 500a
+ {
+ rStream.ReadByteString( aName, rStream.GetStreamCharSet() );
+ rStream.ReadByteString( aTag, rStream.GetStreamCharSet() );
+
+ DBG_ASSERT(!pColNames, "Spaltennamen schon gesetzt?")
+ rStream >> nColNameCount;
+ if (nColNameCount)
+ {
+ pColNames = new String[nColNameCount];
+ for (USHORT nCol=0; nCol<nColNameCount; nCol++)
+ rStream.ReadByteString( pColNames[nCol], rStream.GetStreamCharSet() );
+ }
+ }
+ // sonst wird hinterher aus ScPivotCollection::Load ein Name vergeben
+
+ rHdr.EndEntry();
+ return TRUE;
+}
+
+BOOL ScPivot::Store( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const
+{
+ rHdr.StartEntry();
+
+ rStream << bHasHeader
+
+ << nSrcCol1
+ << nSrcRow1
+ << nSrcCol2
+ << nSrcRow2
+ << nSrcTab
+
+ << nDestCol1
+ << nDestRow1
+ << nDestCol2
+ << nDestRow2
+ << nDestTab
+
+ << nColCount;
+ lcl_SaveFieldArr( rStream, aColArr, nColCount );
+ rStream << nRowCount;
+ lcl_SaveFieldArr( rStream, aRowArr, nRowCount );
+ rStream << nDataCount;
+ lcl_SaveFieldArr( rStream, aDataArr, nDataCount );
+
+ aQuery.Store( rStream );
+
+ rStream << bIgnoreEmpty;
+ rStream << bDetectCat;
+
+ rStream << bMakeTotalCol; // ab 355i
+ rStream << bMakeTotalRow;
+
+ if( rStream.GetVersion() > SOFFICE_FILEFORMAT_40 ) // Name/Tag/Spalten ab 5.0
+ {
+ rStream.WriteByteString( aName, rStream.GetStreamCharSet() );
+ rStream.WriteByteString( aTag, rStream.GetStreamCharSet() );
+
+ if (!pColNames) ((ScPivot*)this)->nColNameCount = 0; // soll nicht sein
+ rStream << nColNameCount;
+ for (USHORT nCol=0; nCol<nColNameCount; nCol++)
+ rStream.WriteByteString( pColNames[nCol], rStream.GetStreamCharSet() );
+ }
+
+ rHdr.EndEntry();
+ return TRUE;
+}
+
+void ScPivot::SetQuery(const ScQueryParam& rQuery)
+{
+ aQuery = rQuery;
+
+ USHORT nCount = aQuery.GetEntryCount();
+ for (USHORT i=0; (i<nCount) && (aQuery.GetEntry(i).bDoQuery); i++)
+ {
+ ScQueryEntry& rEntry = aQuery.GetEntry(i);
+
+ ULONG nIndex = 0;
+ rEntry.bQueryByString =
+ !(pDoc->GetFormatTable()->
+ IsNumberFormat(*rEntry.pStr, nIndex, rEntry.nVal));
+ }
+ bValidArea = FALSE;
+}
+
+void ScPivot::GetQuery(ScQueryParam& rQuery) const
+{
+ rQuery = aQuery;
+}
+
+void ScPivot::SetHeader(BOOL bHeader)
+{
+ bHasHeader = bHeader;
+ bValidArea = FALSE;
+}
+
+BOOL ScPivot::GetHeader() const
+{
+ return bHasHeader;
+}
+
+void ScPivot::SetIgnoreEmpty(BOOL bIgnore)
+{
+ bIgnoreEmpty = bIgnore;
+ bValidArea = FALSE;
+}
+
+BOOL ScPivot::GetIgnoreEmpty() const
+{
+ return bIgnoreEmpty;
+}
+
+void ScPivot::SetDetectCat(BOOL bDetect)
+{
+ bDetectCat = bDetect;
+ bValidArea = FALSE;
+}
+
+BOOL ScPivot::GetDetectCat() const
+{
+ return bDetectCat;
+}
+
+void ScPivot::SetMakeTotalCol(BOOL bSet)
+{
+ bMakeTotalCol = bSet;
+ bValidArea = FALSE;
+}
+
+BOOL ScPivot::GetMakeTotalCol() const
+{
+ return bMakeTotalCol;
+}
+
+void ScPivot::SetMakeTotalRow(BOOL bSet)
+{
+ bMakeTotalRow = bSet;
+ bValidArea = FALSE;
+}
+
+BOOL ScPivot::GetMakeTotalRow() const
+{
+ return bMakeTotalRow;
+}
+
+void ScPivot::SetName(const String& rNew)
+{
+ aName = rNew;
+}
+
+const String& ScPivot::GetName() const
+{
+ return aName;
+}
+
+void ScPivot::SetTag(const String& rNew)
+{
+ aTag = rNew;
+}
+
+const String& ScPivot::GetTag() const
+{
+ return aTag;
+}
+
+void ScPivot::SetSrcArea(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2, USHORT nTab)
+{
+ nSrcCol1 = Min(nCol1, (USHORT)MAXCOL);
+ nSrcRow1 = Min(nRow1, (USHORT)MAXROW);
+ nSrcCol2 = Min(nCol2, (USHORT)MAXCOL);
+ nSrcRow2 = Min(nRow2, (USHORT)MAXROW);
+ nSrcTab = nTab;
+ bValidArea = FALSE;
+}
+
+void ScPivot::GetSrcArea(USHORT& rCol1, USHORT& rRow1, USHORT& rCol2, USHORT& rRow2, USHORT& rTab) const
+{
+ rCol1 = nSrcCol1;
+ rRow1 = nSrcRow1;
+ rCol2 = nSrcCol2;
+ rRow2 = nSrcRow2;
+ rTab = nSrcTab;
+}
+
+ScRange ScPivot::GetSrcArea() const
+{
+ return ScRange( nSrcCol1,nSrcRow1,nSrcTab, nSrcCol2,nSrcRow2,nSrcTab );
+}
+
+void ScPivot::SetDestPos(USHORT nCol, USHORT nRow, USHORT nTab)
+{
+ nDestCol1 = nCol;
+ nDestRow1 = nRow;
+ nDestTab = nTab;
+ bValidArea = FALSE;
+}
+
+void ScPivot::GetDestArea(USHORT& rCol1, USHORT& rRow1, USHORT& rCol2, USHORT& rRow2, USHORT& rTab) const
+{
+ rCol1 = nDestCol1;
+ rRow1 = nDestRow1;
+ rTab = nDestTab;
+ if (bValidArea)
+ {
+ rCol2 = nDestCol2;
+ rRow2 = nDestRow2;
+ }
+ else
+ {
+ rCol2 = nDestCol1;
+ rRow2 = nDestRow1;
+ }
+}
+
+ScRange ScPivot::GetDestArea() const
+{
+ ScAddress aStart( nDestCol1, nDestRow1, nDestTab );
+ ScAddress aEnd = aStart;
+ if ( bValidArea )
+ aEnd = ScAddress( nDestCol2, nDestRow2, nDestTab );
+ return ScRange( aStart, aEnd );
+}
+
+void ScPivot::MoveSrcArea( USHORT nNewCol, USHORT nNewRow, USHORT nNewTab )
+{
+ if ( nNewCol != nSrcCol1 || nNewRow != nSrcRow1 || nNewTab != nSrcTab )
+ {
+ USHORT i;
+ short nDiffX = nNewCol - (short) nSrcCol1;
+ short nDiffY = nNewRow - (short) nSrcRow1;
+
+ nSrcTab = nNewTab;
+ nSrcCol1 += nDiffX;
+ nSrcCol2 += nDiffX;
+ nSrcRow1 += nDiffY;
+ nSrcRow2 += nDiffY;
+
+ aQuery.nCol1 += nDiffX;
+ aQuery.nCol2 += nDiffX;
+ aQuery.nRow1 += nDiffY;
+ aQuery.nRow2 += nDiffY;
+
+ USHORT nEC = aQuery.GetEntryCount();
+ for (i=0; i<nEC; i++)
+ if (aQuery.GetEntry(i).bDoQuery)
+ aQuery.GetEntry(i).nField += nDiffX;
+
+ if (bValidArea)
+ {
+ short nC;
+ for (nC=0; nC<nColCount; nC++)
+ if (aColArr[nC].nCol != PIVOT_DATA_FIELD)
+ aColArr[nC].nCol += nDiffX;
+ for (nC=0; nC<nRowCount; nC++)
+ if (aRowArr[nC].nCol != PIVOT_DATA_FIELD)
+ aRowArr[nC].nCol += nDiffX;
+ for (nC=0; nC<nDataCount; nC++)
+ if (aDataArr[nC].nCol != PIVOT_DATA_FIELD)
+ aDataArr[nC].nCol += nDiffX;
+ }
+ }
+}
+
+void ScPivot::ExtendSrcArea( USHORT nNewEndCol, USHORT nNewEndRow )
+{
+ DBG_ASSERT( nNewEndCol >= nSrcCol2 && nNewEndRow >= nSrcRow2, "ExtendSrcArea: zu klein" );
+
+ nSrcCol2 = nNewEndCol;
+ nSrcRow2 = nNewEndRow;
+
+ // alles andere bleibt erhalten
+}
+
+void ScPivot::MoveDestArea( USHORT nNewCol, USHORT nNewRow, USHORT nNewTab )
+{
+ if ( nNewCol != nDestCol1 || nNewRow != nDestRow1 || nNewTab != nDestTab )
+ {
+ short nDiffX = nNewCol - (short) nDestCol1;
+ short nDiffY = nNewRow - (short) nDestRow1;
+
+ nDestTab = nNewTab;
+ nDestCol1 += nDiffX;
+ nDestRow1 += nDiffY;
+
+ if (bValidArea)
+ {
+ nDestCol2 += nDiffX;
+ nDestRow2 += nDiffY;
+
+ nDataStartCol += nDiffX;
+ nDataStartRow += nDiffY;
+ }
+ }
+}
+
+void ScPivot::SetColFields(const PivotField* pFieldArr, short nCount)
+{
+ nColCount = Max((short)0, Min(nCount, (short)PIVOT_MAXFIELD));
+ for (short i = 0; i < nColCount; i++)
+ {
+ aColArr[i] = pFieldArr[i];
+ aColArr[i].nFuncCount = 0;
+ if (aColArr[i].nCol == PIVOT_DATA_FIELD)
+ {
+ aColArr[i].nFuncMask = PIVOT_FUNC_NONE;
+ pDataList = pColList[i];
+ bDataAtCol = TRUE;
+ }
+ else
+ {
+ for (short j=0; j<=PIVOT_MAXFUNC; j++) // incl. "auto"
+ if (aColArr[i].nFuncMask & nFuncMaskArr[j])
+ aColArr[i].nFuncCount++;
+ }
+ }
+ bValidArea = FALSE;
+}
+
+void ScPivot::GetColFields(PivotField* pFieldArr, short& rCount) const
+{
+ for (short i=0; i<nColCount; i++)
+ pFieldArr[i] = aColArr[i];
+ rCount = nColCount;
+}
+
+void ScPivot::SetRowFields(const PivotField* pFieldArr, short nCount)
+{
+ nRowCount = Max((short)0, Min(nCount, (short)PIVOT_MAXFIELD));
+ for (short i = 0; i < nRowCount; i++)
+ {
+ aRowArr[i] = pFieldArr[i];
+ aRowArr[i].nFuncCount = 0;
+ if (aRowArr[i].nCol == PIVOT_DATA_FIELD)
+ {
+ aRowArr[i].nFuncMask = PIVOT_FUNC_NONE;
+ pDataList = pRowList[i];
+ bDataAtCol = FALSE;
+ }
+ else
+ {
+ for (short j=0; j<=PIVOT_MAXFUNC; j++) // incl. "auto"
+ if (aRowArr[i].nFuncMask & nFuncMaskArr[j])
+ aRowArr[i].nFuncCount++;
+ }
+ }
+ bValidArea = FALSE;
+}
+
+void ScPivot::GetRowFields(PivotField* pFieldArr, short& rCount) const
+{
+ for (short i=0; i<nRowCount; i++)
+ pFieldArr[i] = aRowArr[i];
+ rCount = nRowCount;
+}
+
+void ScPivot::SetDataFields(const PivotField* pFieldArr, short nCount)
+{
+ USHORT nFuncNo;
+ short i;
+
+ //
+ // nDataCount vorausberechnen (wie unten)
+ //
+
+ nDataCount = 0;
+ for (i = 0; i < nCount; i++)
+ for (nFuncNo=0; nFuncNo<PIVOT_MAXFUNC; nFuncNo++)
+ if (pFieldArr[i].nFuncMask & nFuncMaskArr[nFuncNo])
+ if (nDataCount+1 < PIVOT_MAXFIELD)
+ ++nDataCount;
+
+ //
+ // Eintraege anpassen
+ //
+
+ if ((nRowCount == 1) && (aRowArr[0].nCol == PIVOT_DATA_FIELD) && (nDataCount == 1))
+ {
+ aColArr[nColCount] = aRowArr[0];
+ pDataList = pColList[nColCount];
+ nColCount++;
+ nRowCount--;
+ bDataAtCol = TRUE;
+ }
+ if ((nColCount == 1) && (aColArr[0].nCol == PIVOT_DATA_FIELD) && (nDataCount == 1))
+ {
+ aRowArr[nRowCount] = aColArr[0];
+ pDataList = pRowList[nRowCount];
+ nRowCount++;
+ nColCount--;
+ bDataAtCol = FALSE;
+ }
+
+ if ((nDataCount == 1)
+ && (aColArr[nColCount-1].nCol != PIVOT_DATA_FIELD)
+ && (aColArr[nRowCount-1].nCol != PIVOT_DATA_FIELD))
+ {
+ if (bDataAtCol)
+ {
+ PivotField aField;
+ short nIndex = PIVOT_MAXFIELD;
+ for (i=0; i<nColCount; i++)
+ {
+ if (aColArr[i].nCol == PIVOT_DATA_FIELD)
+ {
+ aField = aColArr[i];
+ nIndex = i;
+ }
+ }
+ DBG_ASSERT(nIndex < PIVOT_MAXFIELD, "no data field (GPF in old versions!)");
+ if ( nIndex < PIVOT_MAXFIELD )
+ {
+ memcpy(&aColArr[nIndex], &aColArr[nIndex+1], (PIVOT_MAXFIELD - nIndex - 1) * sizeof(PivotField));
+ aColArr[nColCount-1] = aField;
+ pDataList = pColList[nColCount-1];
+ }
+ }
+ else
+ {
+ PivotField aField;
+ short nIndex = PIVOT_MAXFIELD;
+ for (i=0; i<nRowCount; i++)
+ {
+ if (aRowArr[i].nCol == PIVOT_DATA_FIELD)
+ {
+ aField = aRowArr[i];
+ nIndex = i;
+ }
+ }
+ DBG_ASSERT(nIndex < PIVOT_MAXFIELD, "no data field (GPF in old versions!)");
+ if ( nIndex < PIVOT_MAXFIELD )
+ {
+ memcpy(&aRowArr[nIndex], &aRowArr[nIndex+1], (PIVOT_MAXFIELD - nIndex - 1) * sizeof(PivotField));
+ aRowArr[nRowCount-1] = aField;
+ pDataList = pRowList[nRowCount-1];
+ }
+ }
+ }
+
+ //
+ // Datenfelder in Eintraege mit nur einer Funktion aufteilen
+ //
+
+ pDataList->FreeAll();
+ nDataCount = 0;
+ for (i = 0; i < nCount; i++)
+ {
+ for (nFuncNo=0; nFuncNo<PIVOT_MAXFUNC; nFuncNo++)
+ if (pFieldArr[i].nFuncMask & nFuncMaskArr[nFuncNo])
+ if (nDataCount+1 < PIVOT_MAXFIELD)
+ {
+ aDataArr[nDataCount] = pFieldArr[i];
+ aDataArr[nDataCount].nFuncCount = 0;
+ aDataArr[nDataCount].nFuncMask = nFuncMaskArr[nFuncNo];
+
+ String aStr;
+ pDoc->GetString(aDataArr[nDataCount].nCol, nSrcRow1, nSrcTab, aStr);
+ if (aStr.Len() == 0)
+ aStr = ColToAlpha( aDataArr[nDataCount].nCol );
+ TypedStrData* pStrData = new TypedStrData(aStr);
+ if (!(pDataList->AtInsert(pDataList->GetCount(), pStrData)))
+ {
+ delete pStrData;
+ DBG_ERROR("Fehler bei pDataList->AtInsert");
+ }
+
+ ++nDataCount;
+ }
+ }
+
+ //
+ //
+ //
+
+ bValidArea = FALSE;
+}
+
+void ScPivot::GetDataFields(PivotField* pFieldArr, short& rCount) const
+{
+/* for (short i=0; i<nDataCount; i++)
+ pFieldArr[i] = aDataArr[i];
+ rCount = nDataCount;
+*/
+
+ rCount = 0;
+ for (short i=0; i<nDataCount; i++)
+ {
+ BOOL bFound = FALSE;
+ for (short j=0; j<rCount && !bFound; j++)
+ if (pFieldArr[j].nCol == aDataArr[i].nCol)
+ {
+ pFieldArr[j].nFuncMask |= aDataArr[i].nFuncMask;
+ pFieldArr[j].nFuncCount++;
+ bFound = TRUE;
+ }
+ if (!bFound)
+ {
+ pFieldArr[rCount] = aDataArr[i];
+ ++rCount;
+ }
+ }
+}
+
+BOOL ScPivot::CreateData(BOOL bKeepDest)
+{
+ //
+ //
+ //
+
+ USHORT nOldCol2 = nDestCol2;
+ USHORT nOldRow2 = nDestRow2;
+
+ pColRef = new PivotColRef[MAXCOL];
+ aQuery.nCol1 = nSrcCol1;
+ aQuery.nRow1 = nSrcRow1;
+ aQuery.nCol2 = nSrcCol2;
+ aQuery.nRow2 = nSrcRow2;
+ aQuery.bHasHeader = bHasHeader;
+ BOOL bRet = CreateFields();
+ if (bRet)
+ {
+ short i=0; // nDataMult berechnen - nach CreateFields, vor CreateFieldData !!!
+ nDataMult = 1;
+ if (nDataCount > 1)
+ {
+ if (bDataAtCol)
+ {
+ while (i<nColCount && aColArr[i].nCol != PIVOT_DATA_FIELD) i++;
+ i++;
+ while (i<nColCount)
+ nDataMult *= pColList[i++]->GetCount();
+ }
+ else
+ {
+ while (i<nRowCount && aRowArr[i].nCol != PIVOT_DATA_FIELD) i++;
+ i++;
+ while (i<nRowCount)
+ nDataMult *= pRowList[i++]->GetCount();
+ }
+ }
+ DBG_ASSERT(nDataMult,"nDataMult==0");
+
+ CalcArea();
+ if ((nDestCol2 <= MAXCOL) && (nDestRow2 <= MAXROW))
+ {
+ CreateFieldData();
+ bValidArea = TRUE;
+ }
+ else
+ bRet = FALSE;
+ }
+
+ if ( bKeepDest )
+ {
+ bValidArea = TRUE; //! ???
+ nDestCol2 = nOldCol2;
+ nDestRow2 = nOldRow2;
+ }
+
+ return bRet;
+}
+
+void ScPivot::DrawData()
+{
+ ScProgress aProgress( pDoc->GetDocumentShell(), ScGlobal::GetRscString(STR_PIVOT_PROGRESS), nDestRow2-nDestRow1 );
+
+ short i;
+
+ USHORT nCol;
+ USHORT nRow;
+ String aStr;
+ pDoc->pTab[nDestTab]->DeleteArea(nDestCol1, nDestRow1, nDestCol2, nDestRow2, IDF_ALL);
+
+ if ( nDataStartRow > nDestRow1+nFirstLine )
+ SetStyle(nDestCol1, nDestRow1+nFirstLine, nDestCol2, nDataStartRow-1, PIVOT_STYLE_TOP);
+ SetStyle(nDataStartCol, nDataStartRow, nDestCol2, nDestRow2, PIVOT_STYLE_INNER);
+
+ pDoc->SetString(nDestCol1, nDestRow1, nDestTab, ScGlobal::GetRscString(STR_CELL_FILTER));
+ // Kategorie 1
+ SetButton(nDestCol1, nDestRow1, nDestCol1, nDestRow1);
+
+ if (bHasHeader) // Spalten / Zeilennamen ausgeben
+ {
+ if (nColCount != 0)
+ {
+ nCol = nDestCol1;
+ nRow = nDataStartRow - 1;
+ for (i=0; i<nColCount; i++)
+ {
+ if (aColArr[i].nCol != PIVOT_DATA_FIELD)
+ {
+ pDoc->GetString(aColArr[i].nCol, nSrcRow1, nSrcTab, aStr);
+ if ( !aStr.Len() )
+ aStr = ColToAlpha( aColArr[i].nCol );
+ pDoc->SetString(nCol, nRow, nDestTab, aStr);
+ // Kategorie 2
+ nCol++;
+ }
+ else if (nDataCount > 1)
+ {
+ pDoc->SetString(nCol, nRow, nDestTab, *pLabelData);
+ // Kategorie 3
+ nCol++;
+ }
+ }
+ SetButton(nDestCol1, nRow, nCol-1, nRow);
+ SetStyle(nDestCol1, nRow, nCol-1, nRow, PIVOT_STYLE_FIELDNAME);
+ }
+ if (nRowCount != 0)
+ {
+ nCol = nDataStartCol;
+ nRow = nDestRow1 + nFirstLine;
+ for (i=0; i<nRowCount; i++)
+ {
+ if (aRowArr[i].nCol != PIVOT_DATA_FIELD)
+ {
+ pDoc->GetString(aRowArr[i].nCol, nSrcRow1, nSrcTab, aStr);
+ if ( !aStr.Len() )
+ aStr = ColToAlpha( aRowArr[i].nCol );
+ pDoc->SetString(nCol, nRow, nDestTab, aStr);
+ // Kategorie 4
+ nCol++;
+ }
+ else if (nDataCount > 1)
+ {
+ pDoc->SetString(nCol, nRow, nDestTab, *pLabelData);
+ // Kategorie 5
+ nCol++;
+ }
+ }
+ SetButton(nDataStartCol, nRow, nCol-1, nRow);
+ SetStyle(nDataStartCol, nRow, nCol-1, nRow, PIVOT_STYLE_FIELDNAME);
+ }
+ }
+
+ BOOL bNoRows = (nRowCount == 0) || ( nRowCount == 1 && aRowArr[0].nCol == PIVOT_DATA_FIELD );
+ BOOL bNoCols = (nColCount == 0) || ( nColCount == 1 && aColArr[0].nCol == PIVOT_DATA_FIELD );
+ if (!bMakeTotalCol) bNoRows = TRUE;
+ if (!bMakeTotalRow) bNoCols = TRUE;
+
+ USHORT nTotalCol = nDestCol2;
+ USHORT nTotalRow = nDestRow2;
+ if (bDataAtCol)
+ nTotalRow -= nDataCount - 1;
+ else
+ nTotalCol -= nDataCount - 1;
+
+ // Spaltenkoepfe ausgeben und ColRef initialisieren
+ // (String-Collections sind initialisiert)
+ nDataIndex = 0;
+ nColIndex = 0;
+ nCol = nDataStartCol;
+ nRecCount = 0;
+ RowToTable(0, nCol);
+
+ // Zeilenkoepfe und Daten ausgeben
+ // (ruft SetDataLine/SetFuncLine auf)
+ nRowIndex = 0;
+ nRow = nDataStartRow;
+ ColToTable(0, nRow, aProgress);
+
+ // Gesamtergebnis-Zeilen
+
+ if (!bNoCols)
+ {
+ if (bDataAtCol)
+ for (short nTotCnt = 0; nTotCnt<nDataCount; nTotCnt++)
+ SetFuncLine(nDataStartCol, nRow+nTotCnt, nDestTab,
+ aDataArr[nTotCnt].nFuncMask, nTotCnt, 0, nDataRowCount);
+ else
+ SetFuncLine(nDataStartCol, nRow, nDestTab, PIVOT_FUNC_AUTO, 0xffff, 0, nDataRowCount);
+ }
+
+
+ // Rahmen Spaltenergebnis
+
+ if (!bNoRows)
+ {
+ if (!bDataAtCol)
+ {
+ for (short i=0; i<nDataCount; i++)
+ {
+ String aLab = *pLabelTotal;
+ aLab += ' ';
+ aLab += *pLabel[lcl_MaskToIndex( aDataArr[i].nFuncMask )];
+ aLab += ' ';
+ aLab += pDataList->GetString(i);
+ pDoc->SetString(nTotalCol+i, nDestRow1 + nFirstLine, nDestTab, aLab);
+ // Kategorie 6
+ }
+ }
+ else
+ {
+ pDoc->SetString(nTotalCol, nDestRow1 + nFirstLine, nDestTab, *pLabelTotal);
+ // Kategorie 7
+ }
+
+ if ( nDataStartRow )
+ SetStyle(nTotalCol, nDestRow1+nFirstLine, nDestCol2, nDataStartRow-1, PIVOT_STYLE_TITLE);
+ SetStyle(nTotalCol, nDataStartRow, nDestCol2, nDestRow2, PIVOT_STYLE_RESULT);
+ SetFrame(nTotalCol, nDestRow1 + nFirstLine, nDestCol2, nDestRow2);
+ }
+
+ // Rahmen Zeilenergebnis
+
+ if (!bNoCols)
+ {
+ if (bDataAtCol)
+ {
+ for (short i=0; i<nDataCount; i++)
+ {
+ String aLab = *pLabelTotal;
+ aLab += ' ';
+ aLab += *pLabel[lcl_MaskToIndex( aDataArr[i].nFuncMask )];
+ aLab += ' ';
+ aLab += pDataList->GetString(i);
+ pDoc->SetString(nDestCol1, nTotalRow+i, nDestTab, aLab);
+ // Kategorie 8
+ }
+ }
+ else
+ {
+ pDoc->SetString(nDestCol1, nTotalRow, nDestTab, *pLabelTotal);
+ // Kategorie 9
+ }
+
+ if ( nDataStartCol )
+ SetStyle(nDestCol1, nTotalRow, nDataStartCol-1, nDestRow2, PIVOT_STYLE_TITLE);
+ SetStyle(nDataStartCol, nTotalRow, nDestCol2, nDestRow2, PIVOT_STYLE_RESULT);
+ SetFrame(nDestCol1, nTotalRow, nDestCol2, nDestRow2);
+ }
+
+ // Rahmen gesamt
+ SetFrame(nDestCol1, nDestRow1 + nFirstLine, nDestCol2, nDestRow2, 40);
+}
+
+void ScPivot::ReleaseData()
+{
+ short i;
+ for (i = 0; i < PIVOT_MAXFIELD; i++)
+ {
+ pColList[i]->FreeAll();
+ pRowList[i]->FreeAll();
+ }
+ if (ppDataArr)
+ {
+ for (i=0; i<nDataRowCount; i++)
+ delete[] ppDataArr[i];
+ delete[] ppDataArr;
+ ppDataArr = NULL;
+ }
+ nDataColCount = 0;
+ nDataRowCount = 0;
+ delete[] pColRef;
+ pColRef = NULL;
+}
+
+BOOL ScPivot::IsPivotAtCursor(USHORT nCol, USHORT nRow, USHORT nTab) const
+{
+ if (bValidArea)
+ return ( nTab == nDestTab
+ && nCol >= nDestCol1 && nCol <= nDestCol2
+ && nRow >= nDestRow1 && nRow <= nDestRow2 );
+ else
+ return FALSE;
+}
+
+BOOL ScPivot::IsFilterAtCursor(USHORT nCol, USHORT nRow, USHORT nTab) const
+{
+ if (bValidArea)
+ return (nCol == nDestCol1 && nRow == nDestRow1 && nTab == nDestTab);
+ else
+ return FALSE;
+}
+
+BOOL ScPivot::GetColFieldAtCursor(USHORT nCol, USHORT nRow, USHORT nTab, USHORT& rField) const
+{
+ rField = 0;
+ BOOL bRet = FALSE;
+ if (bValidArea)
+ {
+ bRet = ( nCol >= nDestCol1 && nCol < nDataStartCol
+ && nRow == nDataStartRow - 1
+ && nTab == nDestTab );
+ if (bRet)
+ {
+ rField = aColArr[nCol - nDestCol1].nCol;
+ if (rField == PIVOT_DATA_FIELD)
+ bRet = (nDataCount > 1);
+ }
+ }
+ return bRet;
+}
+
+BOOL ScPivot::GetRowFieldAtCursor(USHORT nCol, USHORT nRow, USHORT nTab, USHORT& rField) const
+{
+ rField = 0;
+ BOOL bRet = FALSE;
+ if (bValidArea)
+ {
+ bRet = ( nCol >= nDataStartCol && nCol < nDataStartCol + nRowCount
+ && nRow == nDestRow1 + nFirstLine
+ && nTab == nDestTab );
+ if (bRet)
+ {
+ rField = aRowArr[nCol - nDataStartCol].nCol;
+ if (rField == PIVOT_DATA_FIELD)
+ bRet = (nDataCount > 1);
+ }
+ }
+ return bRet;
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// Private Methoden
+//--------------------------------------------------------------------------------------------------
+
+BOOL ScPivot::CreateFields()
+{
+ short i;
+ USHORT nRow;
+ USHORT nHeader;
+ String aStr;
+ TypedStrData* pStrData;
+ if (bHasHeader)
+ nHeader = 1;
+ else
+ nHeader = 0;
+
+ // Sortieren nach Benutzerdefinierte Listen ??
+ for (i = 0; i < nColCount; i++)
+ {
+ if (aColArr[i].nCol != PIVOT_DATA_FIELD)
+ {
+ pDoc->GetString(aColArr[i].nCol, nSrcRow1 + nHeader, nSrcTab, aStr);
+ pColList[i]->SetUserData(ScGlobal::GetUserList()->GetData(aStr));
+ }
+ else
+ pColList[i]->SetUserData(NULL);
+ }
+ for (i = 0; i < nRowCount; i++)
+ {
+ if (aRowArr[i].nCol != PIVOT_DATA_FIELD)
+ {
+ pDoc->GetString(aRowArr[i].nCol, nSrcRow1 + nHeader, nSrcTab, aStr);
+ pRowList[i]->SetUserData(ScGlobal::GetUserList()->GetData(aStr));
+ }
+ else
+ pRowList[i]->SetUserData(NULL);
+ }
+
+ ScAddress aSrcAdr( nSrcCol1, 0, nSrcTab );
+ for (nRow = nSrcRow1 + nHeader; nRow <= nSrcRow2; nRow++)
+ {
+ BOOL bValidLine = TRUE;
+ if (bIgnoreEmpty)
+ {
+ aSrcAdr.SetRow( nRow );
+ bValidLine = !lcl_IsEmptyLine( pDoc, aSrcAdr, nSrcCol2 );
+ }
+ if (bValidLine)
+ bValidLine = pDoc->pTab[nSrcTab]->ValidQuery(nRow, aQuery);
+ if (bValidLine)
+ {
+ // Sortierte Liste der Felder erzeugen
+ //! statt GetCategoryString leere weglassen !
+
+ for (i = 0; i < nColCount; i++)
+ {
+ if (aColArr[i].nCol != PIVOT_DATA_FIELD)
+ {
+ USHORT nCatRow = bDetectCat ? GetCategoryRow( aColArr[i].nCol, nRow ) : nRow;
+ pStrData = new TypedStrData( pDoc, aColArr[i].nCol, nCatRow, nSrcTab, TRUE );
+ if (!(pColList[i]->Insert(pStrData)))
+ delete pStrData;
+ }
+ }
+ for (i = 0; i < nRowCount; i++)
+ {
+ if (aRowArr[i].nCol != PIVOT_DATA_FIELD)
+ {
+ USHORT nCatRow = bDetectCat ? GetCategoryRow( aRowArr[i].nCol, nRow ) : nRow;
+ pStrData = new TypedStrData( pDoc, aRowArr[i].nCol, nCatRow, nSrcTab, TRUE );
+ if (!(pRowList[i]->Insert(pStrData)))
+ delete pStrData;
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+
+void ScPivot::CreateFieldData()
+{
+ USHORT* pRowListIndex = nRowCount ? new USHORT[nRowCount] : NULL;
+ USHORT* pColListIndex = nColCount ? new USHORT[nColCount] : NULL;
+
+ short i,j,k;
+
+ ppDataArr = new SubTotal*[nDataRowCount];
+ for (i=0; i<nDataRowCount; i++)
+ ppDataArr[i] = new SubTotal[nDataColCount];
+
+ if (bDataAtCol)
+ for (j=0; j<nDataRowCount; j++)
+ for (i=0; i<nDataColCount; i++)
+ ppDataArr[j][i].nIndex = j/nDataMult%nDataCount;
+ else
+ for (j=0; j<nDataRowCount; j++)
+ for (i=0; i<nDataColCount; i++)
+ ppDataArr[j][i].nIndex = i/nDataMult%nDataCount;
+
+ short nHeader;
+ if (bHasHeader)
+ nHeader = 1;
+ else
+ nHeader = 0;
+ ScAddress aSrcAdr( nSrcCol1, 0, nSrcTab );
+ for (USHORT nRow = nSrcRow1 + nHeader; nRow <= nSrcRow2; nRow++)
+ {
+ BOOL bValidLine = TRUE;
+ if (bIgnoreEmpty)
+ {
+ aSrcAdr.SetRow( nRow );
+ bValidLine = !lcl_IsEmptyLine( pDoc, aSrcAdr, nSrcCol2 );
+ }
+ if (bValidLine)
+ bValidLine = pDoc->pTab[nSrcTab]->ValidQuery(nRow, aQuery);
+ if (bValidLine)
+ {
+ // Indizes der Kategorien nur einmal ausserhalb nDataCount
+ for (j=0; j<nRowCount; j++)
+ if (aRowArr[j].nCol != PIVOT_DATA_FIELD)
+ {
+ USHORT nCatRow = bDetectCat ? GetCategoryRow( aRowArr[j].nCol, nRow ) : nRow;
+ TypedStrData aStrData( pDoc, aRowArr[j].nCol, nCatRow, nSrcTab, TRUE );
+ pRowListIndex[j] = pRowList[j]->GetIndex(&aStrData);
+ }
+ for (j=0; j<nColCount; j++)
+ if (aColArr[j].nCol != PIVOT_DATA_FIELD)
+ {
+ USHORT nCatRow = bDetectCat ? GetCategoryRow( aColArr[j].nCol, nRow ) : nRow;
+ TypedStrData aStrData( pDoc, aColArr[j].nCol, nCatRow, nSrcTab, TRUE );
+ pColListIndex[j] = pColList[j]->GetIndex(&aStrData);
+ }
+
+ String aStr;
+ short nCIndex;
+ short nRIndex;
+ short nIndex;
+ ScAddress aAdr( 0, nRow, nSrcTab );
+
+ for (i=0; i<nDataCount; i++)
+ {
+ // ColIndex Berechnen
+ nCIndex = 0;
+ for (j=0; j<nRowCount; j++)
+ {
+ if (aRowArr[j].nCol == PIVOT_DATA_FIELD)
+ nIndex = i;
+ else
+ nIndex = pRowListIndex[j];
+ if (nIndex)
+ {
+ for (k=j+1; k<nRowCount; k++)
+ nIndex *= pRowList[k]->GetCount();
+ nCIndex += nIndex;
+ }
+ }
+ // RowIndex Berechnen
+ nRIndex = 0;
+ for (j=0; j<nColCount; j++)
+ {
+ if (aColArr[j].nCol == PIVOT_DATA_FIELD)
+ nIndex = i;
+ else
+ nIndex = pColListIndex[j];
+ if (nIndex)
+ {
+ for (k=j+1; k<nColCount; k++)
+ nIndex *= pColList[k]->GetCount();
+ nRIndex += nIndex;
+ }
+ }
+ // Daten eintragen
+ if ((nCIndex < nDataColCount) && (nRIndex < nDataRowCount))
+ {
+ DBG_ASSERT((short)ppDataArr[nRIndex][nCIndex].nIndex == i, "falsch init.")
+
+ ppDataArr[nRIndex][nCIndex].nIndex = i;
+ aAdr.SetCol( aDataArr[i].nCol );
+ CellType eCellType = pDoc->GetCellType( aAdr );
+ if ((eCellType != CELLTYPE_NONE) && (eCellType != CELLTYPE_NOTE))
+ {
+ BOOL bValue = (eCellType == CELLTYPE_VALUE);
+ if (eCellType == CELLTYPE_FORMULA)
+ {
+ ScBaseCell* pCell = pDoc->GetCell( aAdr );
+ bValue = ((ScFormulaCell*)pCell)->IsValue();
+ }
+
+ if (bValue)
+ {
+ double nVal = pDoc->GetValue( aAdr );
+ ppDataArr[nRIndex][nCIndex].Update(nVal);
+ }
+ else
+ ppDataArr[nRIndex][nCIndex].UpdateNoVal(); // nur nCount
+ }
+ }
+ }
+ }
+ }
+
+ delete pColListIndex;
+ delete pRowListIndex;
+}
+
+void ScPivot::CalcArea()
+{
+ BOOL bNoRows = (nRowCount == 0) || ( nRowCount == 1 && aRowArr[0].nCol == PIVOT_DATA_FIELD );
+ BOOL bNoCols = (nColCount == 0) || ( nColCount == 1 && aColArr[0].nCol == PIVOT_DATA_FIELD );
+ if (!bMakeTotalCol) bNoRows = TRUE;
+ if (!bMakeTotalRow) bNoCols = TRUE;
+
+ short i;
+ short nDx;
+ // StartSpalte/StartZeile des Datenbereichs berechnen
+ if (bDataAtCol)
+ {
+ if (nDataCount > 1)
+ nDataStartCol = nDestCol1 + nColCount;
+ else
+ nDataStartCol = nDestCol1 + Max(0, nColCount - 1);
+ }
+ else
+ nDataStartCol = nDestCol1 + nColCount;
+ if (!bDataAtCol)
+ {
+ if (nDataCount > 1)
+ nDataStartRow = nDestRow1 + nRowCount + nFirstLine + 1;
+ else
+ nDataStartRow = nDestRow1 + Max(0, nRowCount - 1) + nFirstLine + 1;
+ }
+ else
+ nDataStartRow = nDestRow1 + nRowCount + nFirstLine + 1;
+
+ //
+ // Groesse der PivotTabelle berechnen
+ //
+
+ if (nRowCount == 0 || (nRowCount==1 && aRowArr[0].nCol==PIVOT_DATA_FIELD && nDataCount==1))
+ {
+ nDataColCount = 1;
+ if (nDataCount == 1)
+ nDestCol2 = nDestCol1 + nColCount - 1;
+ else
+ nDestCol2 = nDestCol1 + nColCount;
+ }
+ else
+ {
+ // Anzahl Spalten
+ if ((aRowArr[nRowCount-1].nCol == PIVOT_DATA_FIELD) && (nDataCount == 1))
+ nDx = 2;
+ else
+ nDx = 1;
+ long nColLines = pRowList[nRowCount-nDx]->GetCount(); // long um Ueberlauf zu erkennen
+ nDataColCount = pRowList[nRowCount-nDx]->GetCount();
+ for (i=nRowCount-nDx-1; i >= 0; i--)
+ {
+ nColLines *= pRowList[i]->GetCount();
+ nDataColCount *= pRowList[i]->GetCount();
+ if (!bDataAtCol)
+ nColLines += (pRowList[i]->GetCount() * aRowArr[i].nFuncCount * nDataCount);
+ else
+ nColLines += (pRowList[i]->GetCount() * aRowArr[i].nFuncCount);
+ }
+ /*
+ // Ergebnisspalten des letzten Elements
+ if (aRowArr[nRowCount-1].nCol != PIVOT_DATA_FIELD)
+ nColLines += (pRowList[nRowCount-1]->GetCount() * aRowArr[nRowCount-1].nFuncCount);
+ */
+ if (nColLines > MAXCOL)
+ nDestCol2 = MAXCOL+2; // ungueltig, 1 wird unten abgezogen
+ else if (bDataAtCol)
+ {
+ if (nDataCount > 1)
+ nDestCol2 = nDestCol1 + nColCount + nColLines;
+ else
+ nDestCol2 = nDestCol1 + (nColCount - 1) + nColLines;
+ if (!bMakeTotalCol)
+ --nDestCol2;
+ }
+ else
+ nDestCol2 = nDestCol1 + nColCount + nColLines;
+ }
+
+ if (nColCount == 0 || (nColCount==1 && aColArr[0].nCol==PIVOT_DATA_FIELD && nDataCount==1))
+ {
+ nDataRowCount = 1;
+ if (nDataCount == 1)
+ nDestRow2 = nDestRow1 + (nRowCount - 1) + nFirstLine + 1;
+ else
+ nDestRow2 = nDestRow1 + nRowCount + nFirstLine + 1;
+ }
+ else
+ {
+ // Anzahl Zeilen
+ if ((aColArr[nColCount-1].nCol == PIVOT_DATA_FIELD) && (nDataCount == 1))
+ nDx = 2;
+ else
+ nDx = 1;
+ long nRowLines = pColList[nColCount-nDx]->GetCount(); // long um Ueberlauf zu erkennen
+ nDataRowCount = pColList[nColCount-nDx]->GetCount();
+ for (i=nColCount-nDx-1; i >= 0; i--)
+ {
+ nRowLines *= pColList[i]->GetCount();
+ nDataRowCount *= pColList[i]->GetCount();
+ if (bDataAtCol)
+ nRowLines += (pColList[i]->GetCount() * aColArr[i].nFuncCount * nDataCount);
+ else
+ nRowLines += (pColList[i]->GetCount() * aColArr[i].nFuncCount);
+ }
+ /*
+ // Ergebniszeilen des letzten Elements
+ if (aColArr[nColCount-1].nCol != PIVOT_DATA_FIELD)
+ nRowLines += (pColList[nColCount-1]->GetCount() * aColArr[nColCount-1].nFuncCount);
+ */
+ if (nRowLines > MAXROW)
+ nDestRow2 = MAXROW+2; // ungueltig, 1 wird unten abgezogen
+ else if (!bDataAtCol)
+ {
+ if (nDataCount > 1)
+ nDestRow2 = nDestRow1 + nRowCount + nRowLines + nFirstLine + 1;
+ else
+ nDestRow2 = nDestRow1 + (nRowCount - 1) + nRowLines + nFirstLine + 1;
+ if (!bMakeTotalRow)
+ --nDestRow2;
+ }
+ else
+ nDestRow2 = nDestRow1 + nRowCount + nRowLines + nFirstLine + 1;
+ }
+
+ if (bDataAtCol)
+ {
+ if (!bNoCols)
+ nDestRow2 += nDataCount;
+ nDestRow2 --;
+ }
+ else
+ {
+ if (!bNoRows)
+ nDestCol2 += nDataCount;
+ nDestCol2 --;
+ }
+}
+
+void ScPivot::SetDataLine(USHORT nCol, USHORT nRow, USHORT nTab, USHORT nRIndex)
+{
+ USHORT nCIndex2;
+ short j;
+ short i;
+
+ SubTotal aGrandTotal[PIVOT_MAXFIELD]; // pro Daten-Feld
+
+ for (i=0; i < nColIndex; i++)
+ {
+ USHORT nCIndex = pColRef[i].nDataIndex;
+ if (nCIndex != PIVOT_FUNC_REF)
+ {
+// if ( ppDataArr[nRIndex][nCIndex].GetCount() )
+ {
+ USHORT nDIndex = ppDataArr[nRIndex][nCIndex].nIndex;
+ SetValue( nCol+i, nRow, ppDataArr[nRIndex][nCIndex], aDataArr[nDIndex].nFuncMask );
+ // Kategorie 18
+
+ if (bDataAtCol)
+ aGrandTotal[0].Update(ppDataArr[nRIndex][nCIndex]);
+ else
+ aGrandTotal[nDIndex].Update(ppDataArr[nRIndex][nCIndex]);
+ }
+ }
+ else
+ {
+ SubTotal aTotal;
+ short k = i-1;
+ while ((pColRef[k].nDataIndex == PIVOT_FUNC_REF) && (k > 0)) k--;
+ for (j=k; (j>=0) && (pColRef[j].nRecCount > pColRef[i].nRecCount); j--)
+ {
+ nCIndex2 = pColRef[j].nDataIndex;
+ if (nCIndex2 != PIVOT_FUNC_REF)
+ {
+ if ((pColRef[i].nIndex == ppDataArr[nRIndex][nCIndex2].nIndex) ||
+ (pColRef[i].nIndex == 0xffff))
+ {
+ aTotal.Update( ppDataArr[nRIndex][nCIndex2] );
+ }
+ }
+ }
+
+ USHORT nFunc = pColRef[i].nFuncMask;
+ if (nFunc == PIVOT_FUNC_AUTO)
+ nFunc = aDataArr[nRIndex/nDataMult%nDataCount].nFuncMask;
+ SetValue( nCol+i, nRow, aTotal, nFunc );
+ // Kategorie 19
+ }
+ }
+
+ BOOL bNoRows = (nRowCount == 0) || ( nRowCount == 1 && aRowArr[0].nCol == PIVOT_DATA_FIELD );
+ if (!bMakeTotalCol) bNoRows = TRUE;
+
+ if (!bNoRows)
+ {
+ if (bDataAtCol)
+ {
+ SetValue( nDestCol2, nRow, aGrandTotal[0], aDataArr[nRIndex/nDataMult%nDataCount].nFuncMask );
+ // Kategorie 20
+ }
+ else
+ {
+ USHORT nTotalCol = nDestCol2 - nDataCount + 1;
+ for (short nTotCnt = 0; nTotCnt<nDataCount; nTotCnt++)
+ {
+ SetValue( nTotalCol+nTotCnt, nRow, aGrandTotal[nTotCnt], aDataArr[nTotCnt].nFuncMask );
+ // Kategorie 21
+ }
+ }
+ }
+}
+
+void ScPivot::SetFuncLine(USHORT nCol, USHORT nRow, USHORT nTab, USHORT nFunc, USHORT nIndex, USHORT nStartRIndex, USHORT nEndRIndex)
+{
+ short nSubtCount = 0;
+ SubTotal aGrandTotal[PIVOT_MAXFIELD];
+ USHORT nThisFunc = nFunc;
+
+ for (short i=0; i<nColIndex; i++)
+ {
+ USHORT nCIndex = pColRef[i].nDataIndex;
+ if (nCIndex != PIVOT_FUNC_REF)
+ {
+ SubTotal aTotal;
+ for (USHORT j = nStartRIndex; j < nEndRIndex; j++)
+ {
+ USHORT nDIndex = ppDataArr[j][nCIndex].nIndex;
+ if ((nIndex == nDIndex) || (nIndex == 0xffff))
+ {
+ aTotal.Update( ppDataArr[j][nCIndex] );
+ }
+ }
+
+ if (bDataAtCol)
+ aGrandTotal[0].Update( aTotal );
+ else
+ aGrandTotal[nCIndex/nDataMult%nDataCount].Update( aTotal ); //! immer ?
+
+ if (nFunc == PIVOT_FUNC_AUTO)
+ {
+ if (bDataAtCol)
+ {
+ if ((short)nIndex<nDataCount)
+ nThisFunc = aDataArr[nIndex].nFuncMask;
+ else
+ DBG_ERROR("wat fuer'n Index ???");
+ }
+ else
+ nThisFunc = aDataArr[nCIndex/nDataMult%nDataCount].nFuncMask;
+ }
+ SetValue( nCol+i, nRow, aTotal, nThisFunc );
+ // Kategorie 22
+ }
+ else
+ { // Kreuzungspunkte kompatibel ?
+
+ if ( nFunc == pColRef[i].nFuncMask )
+ {
+ USHORT nEffIndex = nIndex;
+ if (nEffIndex == 0xffff)
+ {
+ nEffIndex = nSubtCount % nDataCount;
+ ++nSubtCount;
+ }
+ SubTotal aTotal;
+
+ short k = i-1;
+ short j;
+ while ((pColRef[k].nDataIndex == PIVOT_FUNC_REF) && (k > 0)) k--;
+ for (j=k; (j>=0) && (pColRef[j].nRecCount > pColRef[i].nRecCount); j--)
+ {
+ nCIndex = pColRef[j].nDataIndex;
+ if (nCIndex != PIVOT_FUNC_REF)
+ {
+ for (USHORT nRIndex = nStartRIndex; nRIndex < nEndRIndex; nRIndex++)
+ {
+ USHORT nDIndex = ppDataArr[nRIndex][nCIndex].nIndex;
+ if (nEffIndex == nDIndex)
+ {
+ aTotal.Update( ppDataArr[nRIndex][nCIndex] );
+ }
+ }
+ }
+ }
+
+ if (nFunc == PIVOT_FUNC_AUTO)
+ {
+ if ((short)nEffIndex<nDataCount)
+ nThisFunc = aDataArr[nEffIndex].nFuncMask;
+ else
+ DBG_ERROR("wat fuer'n Index ???");
+ }
+ SetValue( nCol+i, nRow, aTotal, nThisFunc );
+ // Kategorie 23
+ }
+ }
+ }
+
+ BOOL bNoRows = (nRowCount == 0) || ( nRowCount == 1 && aRowArr[0].nCol == PIVOT_DATA_FIELD );
+ if (!bMakeTotalCol) bNoRows = TRUE;
+
+ if (!bNoRows)
+ {
+ if (bDataAtCol)
+ {
+ if (nFunc == PIVOT_FUNC_AUTO)
+ {
+ if ((short)nIndex<nDataCount)
+ nThisFunc = aDataArr[nIndex].nFuncMask;
+ else
+ DBG_ERROR("wat fuer'n Index ???");
+ }
+ SetValue( nDestCol2, nRow, aGrandTotal[0], nThisFunc );
+ // Kategorie 24
+ }
+ else
+ {
+ USHORT nTotalCol = nDestCol2 - nDataCount + 1;
+ for (short nTotCnt = 0; nTotCnt<nDataCount; nTotCnt++)
+ {
+ if (nFunc == PIVOT_FUNC_AUTO)
+ nThisFunc = aDataArr[nTotCnt%nDataCount].nFuncMask;
+ SetValue( nTotalCol+nTotCnt, nRow, aGrandTotal[nTotCnt], nThisFunc );
+ // Kategorie 25
+ }
+ }
+ }
+}
+
+void ScPivot::ColToTable(short nField, USHORT& nRow, ScProgress& rProgress)
+{
+ USHORT nCol = nDestCol1 + nField;
+ if (nColCount == 0)
+ {
+// SetDataLine(nCol + 1, nRow, nDestTab, nRowIndex);
+ SetDataLine(nCol, nRow, nDestTab, nRowIndex);
+ nRowIndex++;
+ return;
+ }
+
+ USHORT i;
+ short nDx;
+ if ((aColArr[nColCount -1].nCol == PIVOT_DATA_FIELD) && (nDataCount == 1))
+ nDx = 2;
+ else
+ nDx = 1;
+ if (nField < nColCount - nDx)
+ {
+ for (i = 0; i < pColList[nField]->GetCount(); i++)
+ {
+ USHORT nSaveIndex = nRowIndex;
+ String aStr = pColList[nField]->GetString(i);
+ if (!aStr.Len()) aStr = ScGlobal::GetRscString(STR_EMPTYDATA);
+ pDoc->SetString(nCol, nRow, nDestTab, aStr);
+ // Kategorie 10
+ USHORT nSaveRow = nRow;
+ ColToTable(nField + 1, nRow, rProgress);
+ SetStyle(nCol, nSaveRow, nCol, nRow - 1, PIVOT_STYLE_CATEGORY);
+ SetFrame(nCol, nSaveRow, nCol, nRow - 1);
+ if (aColArr[nField].nFuncCount > 0) // Zwischenergebnisse eingestellt?
+ {
+ nSaveRow = nRow;
+ for (short j=0; j<=PIVOT_MAXFUNC; j++) // incl. "auto"
+ {
+ if (aColArr[nField].nFuncMask & nFuncMaskArr[j])
+ {
+ String aLab;
+ if (bDataAtCol)
+ {
+ for (short k=0; k < nDataCount; k++)
+ {
+ String aDataStr = pDataList->GetString(k); // ist immer String
+ aLab = aStr;
+ short nFuncType;
+ if ( j==PIVOT_MAXFUNC )
+ nFuncType = lcl_MaskToIndex( aDataArr[k].nFuncMask );
+ else
+ nFuncType = j;
+ aLab += ' ';
+ aLab += *pLabel[nFuncType];
+ aLab += ' ';
+ aLab += aDataStr;
+ pDoc->SetString(nCol, nRow, nDestTab, aLab);
+ // Kategorie 11
+ SetFuncLine(nDataStartCol, nRow, nDestTab, nFuncMaskArr[j], k, nSaveIndex, nRowIndex);
+ nRow++;
+ }
+ }
+ else
+ {
+ aLab = aStr;
+ aLab += ' ';
+ aLab += *pLabel[j];
+ pDoc->SetString(nCol, nRow, nDestTab, aLab);
+ // Kategorie 12
+ SetFuncLine(nDataStartCol, nRow, nDestTab, nFuncMaskArr[j], 0xffff, nSaveIndex, nRowIndex);
+ nRow++;
+ }
+ }
+ }
+ if ( nDataStartCol )
+ SetStyle(nCol, nSaveRow, nDataStartCol-1, nRow-1, PIVOT_STYLE_TITLE);
+ SetStyle(nDataStartCol, nSaveRow, nDestCol2, nRow-1, PIVOT_STYLE_RESULT);
+ SetFrameHor(nCol, nSaveRow, nDestCol2, nRow-1);
+ }
+ nSaveIndex = nRowIndex;
+ }
+ }
+ else if (nField < nColCount)
+ {
+ USHORT nCatCount = pColList[nField]->GetCount();
+ SetStyle(nCol, nRow, nCol, nRow+nCatCount-1, PIVOT_STYLE_CATEGORY);
+ SetFrame(nCol, nRow, nDestCol2, nRow+nCatCount-1);
+ for (i = 0; i < nCatCount; i++)
+ {
+ String aTmpStr = pColList[nField]->GetString(i);
+ if (!aTmpStr.Len()) aTmpStr = ScGlobal::GetRscString(STR_EMPTYDATA);
+
+ String aPutStr;
+ if (pColList[nField] == pDataList)
+ {
+ short nFuncType = lcl_MaskToIndex( aDataArr[i].nFuncMask );
+ aPutStr = *pLabel[nFuncType];
+ aPutStr += ' ';
+ aPutStr += aTmpStr;
+ }
+ else
+ aPutStr += aTmpStr;
+
+ pDoc->SetString(nCol, nRow, nDestTab, aPutStr);
+ // Kategorie 13
+ SetDataLine(nCol + 1, nRow, nDestTab, nRowIndex);
+ nRowIndex++;
+ nRow++;
+
+ rProgress.SetState( nRow - nDestRow1 );
+ }
+ }
+}
+
+void ScPivot::RowToTable(short nField, USHORT& nCol)
+{
+ nRecCount++;
+ USHORT nRow = nDestRow1 + nFirstLine + nField + 1;
+ USHORT i;
+ if (nRowCount == 0)
+ {
+ pColRef[nColIndex].nDataIndex = nDataIndex;
+ nColIndex++;
+ nDataIndex++;
+ return;
+ }
+
+ short nDx;
+ if ((aRowArr[nRowCount -1].nCol == PIVOT_DATA_FIELD) && (nDataCount == 1))
+ nDx = 2;
+ else
+ nDx = 1;
+
+ if (nField < nRowCount - nDx)
+ {
+ for (i = 0; i < pRowList[nField]->GetCount(); i++)
+ {
+ String aStr = pRowList[nField]->GetString(i);
+ if (!aStr.Len()) aStr = ScGlobal::GetRscString(STR_EMPTYDATA);
+ pDoc->SetString(nCol, nRow, nDestTab, aStr);
+ // Kategorie 14
+ USHORT nSaveCol = nCol;
+ RowToTable(nField + 1, nCol);
+ SetStyle(nSaveCol, nRow, nCol - 1, nRow, PIVOT_STYLE_CATEGORY);
+ SetFrame(nSaveCol, nRow, nCol - 1, nRow);
+ if (aRowArr[nField].nFuncCount > 0)
+ {
+ nSaveCol = nCol;
+ for (USHORT j=0; j<=PIVOT_MAXFUNC; j++) // incl. "auto"
+ {
+ if (aRowArr[nField].nFuncMask & nFuncMaskArr[j])
+ {
+ String aLab;
+ if (!bDataAtCol)
+ {
+ for (short k=0; k < nDataCount; k++)
+ {
+ aLab = aStr;
+ short nFuncType;
+ if ( j==PIVOT_MAXFUNC )
+ nFuncType = lcl_MaskToIndex( aDataArr[k].nFuncMask );
+ else
+ nFuncType = j;
+ aLab += ' ';
+ aLab += *pLabel[nFuncType];
+ aLab += ' ';
+ aLab += pDataList->GetString(k);
+ pDoc->SetString(nCol, nRow, nDestTab, aLab);
+ // Kategorie 15
+ pColRef[nColIndex].nDataIndex = PIVOT_FUNC_REF;
+ pColRef[nColIndex].nRecCount = nRecCount;
+ pColRef[nColIndex].nIndex = k;
+ pColRef[nColIndex].nFuncMask = nFuncMaskArr[j];
+ nColIndex++;
+ nCol++;
+ }
+ }
+ else
+ {
+ aLab = aStr;
+ aLab += ' ';
+ aLab += *pLabel[j];
+ pDoc->SetString(nCol, nRow, nDestTab, aLab);
+ // Kategorie 16
+ pColRef[nColIndex].nDataIndex = PIVOT_FUNC_REF;
+ pColRef[nColIndex].nRecCount = nRecCount;
+ pColRef[nColIndex].nIndex = 0xffff;
+ pColRef[nColIndex].nFuncMask = nFuncMaskArr[j];
+ nColIndex++;
+ nCol++;
+ }
+ }
+ }
+ if ( nDataStartRow )
+ SetStyle(nSaveCol, nRow,
+ nCol-1, nDataStartRow-1, PIVOT_STYLE_TITLE);
+ SetStyle(nSaveCol, nDataStartRow, nCol-1, nDestRow2, PIVOT_STYLE_RESULT);
+ SetFrameVer(nSaveCol, nRow, nCol-1, nDestRow2);
+ }
+ }
+ }
+ else if (nField < nRowCount)
+ {
+ USHORT nCatCount = pRowList[nField]->GetCount();
+ SetStyle(nCol, nRow, nCol+nCatCount-1, nRow, PIVOT_STYLE_CATEGORY);
+ SetFrame(nCol, nRow, nCol+nCatCount-1, nDestRow2);
+ for (i = 0; i < nCatCount; i++)
+ {
+ String aTmpStr = pRowList[nField]->GetString(i);
+ if (!aTmpStr.Len()) aTmpStr = ScGlobal::GetRscString(STR_EMPTYDATA);
+
+ String aPutStr;
+ if (pRowList[nField] == pDataList)
+ {
+ short nFuncType = lcl_MaskToIndex( aDataArr[i].nFuncMask );
+ aPutStr = *pLabel[nFuncType];
+ aPutStr += ' ';
+ aPutStr += aTmpStr;
+ }
+ else
+ aPutStr = aTmpStr;
+
+ pDoc->SetString(nCol, nRow, nDestTab, aPutStr);
+ // Kategorie 17
+ pColRef[nColIndex].nDataIndex = nDataIndex;
+ pColRef[nColIndex].nRecCount = nRecCount;
+ pColRef[nColIndex].nIndex = 0xffff;
+ pColRef[nColIndex].nFuncMask = PIVOT_FUNC_NONE;
+ nColIndex++;
+ nDataIndex++;
+ nCol++;
+ }
+ }
+ nRecCount--;
+}
+
+USHORT ScPivot::GetCategoryRow( USHORT nCol, USHORT nRow )
+{
+ USHORT nMinRow = nSrcRow1;
+ if (bHasHeader) ++nMinRow;
+ BOOL bFound = FALSE;
+ do
+ {
+ if ( !pDoc->HasData( nCol, nRow, nSrcTab ) && nRow>nMinRow )
+ --nRow;
+ else
+ bFound = TRUE;
+ }
+ while (!bFound);
+ return nRow;
+}
+
+
+
diff --git a/sc/source/core/data/pivot2.cxx b/sc/source/core/data/pivot2.cxx
new file mode 100644
index 000000000000..5d610b4cfe02
--- /dev/null
+++ b/sc/source/core/data/pivot2.cxx
@@ -0,0 +1,529 @@
+/*************************************************************************
+ *
+ * $RCSfile: pivot2.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#pragma optimize("",off)
+#pragma optimize("q",off) // p-code off
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <svx/boxitem.hxx>
+#include <svx/wghtitem.hxx>
+#include <svx/algitem.hxx>
+#include <tools/intn.hxx>
+
+#include "globstr.hrc"
+#include "subtotal.hxx"
+#include "rangeutl.hxx"
+#include "attrib.hxx"
+#include "patattr.hxx"
+#include "docpool.hxx"
+#include "document.hxx"
+#include "userlist.hxx"
+#include "pivot.hxx"
+#include "rechead.hxx"
+#include "compiler.hxx" // fuer errNoValue
+#include "refupdat.hxx"
+#include "stlpool.hxx"
+#include "stlsheet.hxx"
+
+
+// STATIC DATA -----------------------------------------------------------
+
+//--------------------------------------------------------------------------------------------------
+// Hilfsmethoden von ScPivot
+//--------------------------------------------------------------------------------------------------
+
+void ScPivot::SetFrame(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2, USHORT nWidth)
+{
+ if (pDoc->pTab[nDestTab])
+ {
+ SvxBorderLine aLine;
+ aLine.SetOutWidth(nWidth);
+ SvxBoxItem aBox;
+ aBox.SetLine(&aLine, BOX_LINE_LEFT);
+ aBox.SetLine(&aLine, BOX_LINE_TOP);
+ aBox.SetLine(&aLine, BOX_LINE_RIGHT);
+ aBox.SetLine(&aLine, BOX_LINE_BOTTOM);
+ SvxBoxInfoItem aBoxInfo;
+ aBoxInfo.SetValid(VALID_HORI,FALSE);
+ aBoxInfo.SetValid(VALID_VERT,FALSE);
+ aBoxInfo.SetValid(VALID_DISTANCE,FALSE);
+ pDoc->pTab[nDestTab]->ApplyBlockFrame(&aBox, &aBoxInfo, nCol1, nRow1, nCol2, nRow2);
+ }
+}
+
+void ScPivot::SetFrameHor(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2)
+{
+ if (pDoc->pTab[nDestTab])
+ {
+ SvxBorderLine aLine;
+ aLine.SetOutWidth(20);
+ SvxBoxItem aBox;
+ aBox.SetLine(&aLine, BOX_LINE_LEFT);
+ aBox.SetLine(&aLine, BOX_LINE_TOP);
+ aBox.SetLine(&aLine, BOX_LINE_RIGHT);
+ aBox.SetLine(&aLine, BOX_LINE_BOTTOM);
+ SvxBoxInfoItem aBoxInfo;
+ aBoxInfo.SetValid(VALID_VERT,FALSE);
+ aBoxInfo.SetValid(VALID_DISTANCE,FALSE);
+ aBoxInfo.SetLine(&aLine, BOXINFO_LINE_HORI);
+ pDoc->pTab[nDestTab]->ApplyBlockFrame(&aBox, &aBoxInfo, nCol1, nRow1, nCol2, nRow2);
+ }
+}
+
+void ScPivot::SetFrameVer(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2)
+{
+ if (pDoc->pTab[nDestTab])
+ {
+ SvxBorderLine aLine;
+ aLine.SetOutWidth(20);
+ SvxBoxItem aBox;
+ aBox.SetLine(&aLine, BOX_LINE_LEFT);
+ aBox.SetLine(&aLine, BOX_LINE_TOP);
+ aBox.SetLine(&aLine, BOX_LINE_RIGHT);
+ aBox.SetLine(&aLine, BOX_LINE_BOTTOM);
+ SvxBoxInfoItem aBoxInfo;
+ aBoxInfo.SetValid(VALID_HORI,FALSE);
+ aBoxInfo.SetValid(VALID_DISTANCE,FALSE);
+ aBoxInfo.SetLine(&aLine, BOXINFO_LINE_VERT);
+ pDoc->pTab[nDestTab]->ApplyBlockFrame(&aBox, &aBoxInfo, nCol1, nRow1, nCol2, nRow2);
+ }
+}
+
+void ScPivot::SetFontBold(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2)
+{
+ if (pDoc->pTab[nDestTab])
+ {
+ ScPatternAttr aPattern( pDoc->GetPool() );
+ aPattern.GetItemSet().Put( SvxWeightItem( WEIGHT_BOLD ) );
+ pDoc->pTab[nDestTab]->ApplyPatternArea(nCol1, nRow1, nCol2, nRow2, aPattern);
+ }
+}
+
+void ScPivot::SetJustifyLeft(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2)
+{
+ if (pDoc->pTab[nDestTab])
+ {
+ ScPatternAttr aPattern( pDoc->GetPool() );
+ aPattern.GetItemSet().Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_LEFT ) );
+ pDoc->pTab[nDestTab]->ApplyPatternArea(nCol1, nRow1, nCol2, nRow2, aPattern);
+ }
+}
+
+void ScPivot::SetJustifyRight(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2)
+{
+ if (pDoc->pTab[nDestTab])
+ {
+ ScPatternAttr aPattern( pDoc->GetPool() );
+ aPattern.GetItemSet().Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_RIGHT ) );
+ pDoc->pTab[nDestTab]->ApplyPatternArea(nCol1, nRow1, nCol2, nRow2, aPattern);
+ }
+}
+
+void ScPivot::SetButton(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2)
+{
+ if (pDoc->pTab[nDestTab])
+ {
+ ScPatternAttr aPattern( pDoc->GetPool() );
+ aPattern.GetItemSet().Put( ScMergeFlagAttr(SC_MF_BUTTON) );
+ pDoc->pTab[nDestTab]->ApplyPatternArea(nCol1, nRow1, nCol2, nRow2, aPattern);
+ }
+}
+
+void ScPivot::SetStyle(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2, USHORT nId)
+{
+ if ( nCol1 > nCol2 || nRow1 > nRow2 )
+ return; // Falls Bereiche leer sind
+
+ USHORT nStringId = 0;
+ switch (nId)
+ {
+ case PIVOT_STYLE_INNER: nStringId = STR_PIVOT_STYLE_INNER; break;
+ case PIVOT_STYLE_RESULT: nStringId = STR_PIVOT_STYLE_RESULT; break;
+ case PIVOT_STYLE_CATEGORY: nStringId = STR_PIVOT_STYLE_CATEGORY; break;
+ case PIVOT_STYLE_TITLE: nStringId = STR_PIVOT_STYLE_TITLE; break;
+ case PIVOT_STYLE_FIELDNAME: nStringId = STR_PIVOT_STYLE_FIELDNAME; break;
+ case PIVOT_STYLE_TOP: nStringId = STR_PIVOT_STYLE_TOP; break;
+ default:
+ DBG_ERROR("falsche ID bei ScPivot::SetStyle");
+ return;
+ }
+ String aStyleName = ScGlobal::GetRscString(nStringId);
+
+ ScStyleSheetPool* pStlPool = pDoc->GetStyleSheetPool();
+ ScStyleSheet* pStyle = (ScStyleSheet*) pStlPool->Find( aStyleName, SFX_STYLE_FAMILY_PARA );
+ if (!pStyle)
+ {
+ // neu anlegen
+
+ pStyle = (ScStyleSheet*) &pStlPool->Make( aStyleName, SFX_STYLE_FAMILY_PARA,
+ SFXSTYLEBIT_USERDEF );
+ pStyle->SetParent( ScGlobal::GetRscString(STR_STYLENAME_STANDARD) );
+ SfxItemSet& rSet = pStyle->GetItemSet();
+ if ( nId==PIVOT_STYLE_RESULT || nId==PIVOT_STYLE_TITLE )
+ rSet.Put( SvxWeightItem( WEIGHT_BOLD ) );
+ if ( nId==PIVOT_STYLE_CATEGORY || nId==PIVOT_STYLE_TITLE )
+ rSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_LEFT ) );
+ }
+
+ pDoc->pTab[nDestTab]->ApplyStyleArea( nCol1, nRow1, nCol2, nRow2, *pStyle );
+}
+
+void ScPivot::SetValue(USHORT nCol, USHORT nRow, const SubTotal& rTotal, USHORT nFunc)
+{
+ if ( rTotal.Valid( nFunc ) == 1)
+ pDoc->SetValue(nCol, nRow, nDestTab, rTotal.Result( nFunc ));
+ else if ( rTotal.Valid( nFunc ) == 0)
+ pDoc->SetError(nCol, nRow, nDestTab, errNoValue);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void ScPivot::GetParam( ScPivotParam& rParam, ScQueryParam& rQuery, ScArea& rSrcArea ) const
+{
+ short nCount;
+ USHORT nDummy;
+ GetDestArea( rParam.nCol,rParam.nRow, nDummy,nDummy, rParam.nTab );
+
+ // Row und Col in der Bedeutung vertauscht:
+ GetRowFields( rParam.aColArr, nCount );
+ rParam.nColCount = (USHORT) nCount;
+ GetColFields( rParam.aRowArr, nCount );
+ rParam.nRowCount = (USHORT) nCount;
+ GetDataFields( rParam.aDataArr, nCount );
+ rParam.nDataCount = (USHORT) nCount;
+
+ rParam.bIgnoreEmptyRows = GetIgnoreEmpty();
+ rParam.bDetectCategories = GetDetectCat();
+ rParam.bMakeTotalCol = GetMakeTotalCol();
+ rParam.bMakeTotalRow = GetMakeTotalRow();
+
+ GetQuery(rQuery);
+ GetSrcArea( rSrcArea.nColStart, rSrcArea.nRowStart,
+ rSrcArea.nColEnd, rSrcArea.nRowEnd, rSrcArea.nTab );
+}
+
+void ScPivot::SetParam( const ScPivotParam& rParam, const ScQueryParam& rQuery,
+ const ScArea& rSrcArea )
+{
+ SetQuery( rQuery );
+ SetHeader( TRUE );
+ SetSrcArea( rSrcArea.nColStart, rSrcArea.nRowStart,
+ rSrcArea.nColEnd, rSrcArea.nRowEnd, rSrcArea.nTab );
+ SetDestPos( rParam.nCol, rParam.nRow, rParam.nTab );
+ SetIgnoreEmpty( rParam.bIgnoreEmptyRows );
+ SetDetectCat( rParam.bDetectCategories );
+ SetMakeTotalCol( rParam.bMakeTotalCol );
+ SetMakeTotalRow( rParam.bMakeTotalRow );
+
+ // Row und Col in der Bedeutung vertauscht:
+ SetRowFields( rParam.aColArr, rParam.nColCount );
+ SetColFields( rParam.aRowArr, rParam.nRowCount );
+ SetDataFields( rParam.aDataArr, rParam.nDataCount );
+}
+
+DataObject* ScPivot::Clone() const
+{
+ return new ScPivot(*this);
+}
+
+//--------------------------------------------------------------------------------------------------
+// PivotStrCollection
+//--------------------------------------------------------------------------------------------------
+
+DataObject* PivotStrCollection::Clone() const
+{
+ return new PivotStrCollection(*this);
+}
+
+short PivotStrCollection::Compare(DataObject* pKey1, DataObject* pKey2) const
+{
+ DBG_ASSERT(pKey1&&pKey2,"0-Zeiger bei PivotStrCollection::Compare");
+
+ short nResult = 0;
+
+ TypedStrData& rData1 = (TypedStrData&)*pKey1;
+ TypedStrData& rData2 = (TypedStrData&)*pKey2;
+
+ if ( rData1.nStrType > rData2.nStrType )
+ nResult = 1;
+ else if ( rData1.nStrType < rData2.nStrType )
+ nResult = -1;
+ else if ( !rData1.nStrType /* && !rData2.nStrType */ )
+ {
+ // Zahlen vergleichen:
+
+ if ( rData1.nValue == rData2.nValue )
+ nResult = 0;
+ else if ( rData1.nValue < rData2.nValue )
+ nResult = -1;
+ else
+ nResult = 1;
+ }
+ else /* if ( rData1.nStrType && rData2.nStrType ) */
+ {
+ // Strings vergleichen:
+
+ StringCompare eComp;
+ if (pUserData)
+ eComp = pUserData->ICompare(rData1.aStrValue, rData2.aStrValue);
+ else
+ {
+ eComp = ScGlobal::pScInternational->Compare(
+ rData1.aStrValue, rData2.aStrValue, INTN_COMPARE_IGNORECASE );
+ }
+
+ if ( eComp == COMPARE_EQUAL )
+ nResult = 0;
+ else if ( eComp == COMPARE_LESS )
+ nResult = -1;
+ else
+ nResult = 1;
+ }
+
+ return nResult;
+}
+
+short PivotStrCollection::GetIndex(TypedStrData* pData) const
+{
+ USHORT nIndex = 0;
+ if (!Search(pData, nIndex))
+ nIndex = 0;
+ return (short)nIndex;
+}
+
+//--------------------------------------------------------------------------------------------------
+// PivotCollection
+//--------------------------------------------------------------------------------------------------
+
+String ScPivotCollection::CreateNewName( USHORT nMin ) const
+{
+ String aBase = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("DataPilot"));
+ //! from Resource?
+
+ for (USHORT nAdd=0; nAdd<=nCount; nAdd++) // nCount+1 Versuche
+ {
+ String aNewName = aBase;
+ aNewName += String::CreateFromInt32( nMin + nAdd );
+ BOOL bFound = FALSE;
+ for (USHORT i=0; i<nCount && !bFound; i++)
+ if (((ScPivot*)pItems[i])->GetName() == aNewName)
+ bFound = TRUE;
+ if (!bFound)
+ return aNewName; // freien Namen gefunden
+ }
+ return String(); // sollte nicht vorkommen
+}
+
+ScPivot* ScPivotCollection::GetPivotAtCursor(USHORT nCol, USHORT nRow, USHORT nTab) const
+{
+ if (pItems)
+ {
+ for (USHORT i = 0; i < nCount; i++)
+ if (((ScPivot*)pItems[i])->IsPivotAtCursor(nCol, nRow, nTab))
+ {
+ return (ScPivot*)pItems[i];
+ }
+ }
+ return NULL;
+}
+
+BOOL ScPivotCollection::Load(SvStream& rStream)
+{
+ BOOL bSuccess = TRUE;
+ USHORT nNewCount, i;
+ FreeAll();
+
+ ScMultipleReadHeader aHdr( rStream );
+
+ rStream >> nNewCount;
+ for (i=0; i<nNewCount && bSuccess; i++)
+ {
+ ScPivot* pPivot = new ScPivot( pDoc );
+ if (pPivot)
+ {
+ bSuccess = pPivot->Load(rStream, aHdr);
+ Insert( pPivot );
+ }
+ else
+ bSuccess = FALSE;
+ }
+
+ // fuer alte Dateien: eindeutige Namen vergeben
+
+ if (bSuccess)
+ for (i=0; i<nCount; i++)
+ if (!((const ScPivot*)At(i))->GetName().Len())
+ ((ScPivot*)At(i))->SetName( CreateNewName() );
+
+ return bSuccess;
+}
+
+BOOL ScPivotCollection::Store(SvStream& rStream) const
+{
+ BOOL bSuccess = TRUE;
+
+ ScMultipleWriteHeader aHdr( rStream );
+
+ rStream << nCount;
+
+ for (USHORT i=0; i<nCount && bSuccess; i++)
+ bSuccess = ((const ScPivot*)At(i))->Store( rStream, aHdr );
+
+ return bSuccess;
+}
+
+void ScPivotCollection::UpdateReference(UpdateRefMode eUpdateRefMode,
+ USHORT nCol1, USHORT nRow1, USHORT nTab1,
+ USHORT nCol2, USHORT nRow2, USHORT nTab2,
+ short nDx, short nDy, short nDz )
+{
+ for (USHORT i=0; i<nCount; i++)
+ {
+ USHORT theCol1;
+ USHORT theRow1;
+ USHORT theTab1;
+ USHORT theCol2;
+ USHORT theRow2;
+ USHORT theTab2;
+ ScRefUpdateRes eRes;
+ ScPivot* pPivot = (ScPivot*)pItems[i];
+
+ // Source
+
+ pPivot->GetSrcArea( theCol1, theRow1, theCol2, theRow2, theTab1 );
+ theTab2 = theTab1;
+
+ eRes = ScRefUpdate::Update( pDoc, eUpdateRefMode,
+ nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, nDx,nDy,nDz,
+ theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 );
+
+ if (eRes != UR_NOTHING)
+ pPivot->MoveSrcArea( theCol1, theRow1, theTab1 );
+
+ // Dest
+
+ pPivot->GetDestArea( theCol1, theRow1, theCol2, theRow2, theTab1 );
+ theTab2 = theTab1;
+
+ eRes = ScRefUpdate::Update( pDoc, eUpdateRefMode,
+ nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, nDx,nDy,nDz,
+ theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 );
+
+ if (eRes != UR_NOTHING)
+ pPivot->MoveDestArea( theCol1, theRow1, theTab1 );
+ }
+}
+
+void ScPivotCollection::UpdateGrow( const ScRange& rArea, USHORT nGrowX, USHORT nGrowY )
+{
+ // nur Quell-Bereich
+
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScPivot* pPivot = (ScPivot*)pItems[i];
+ ScRange aSrc = pPivot->GetSrcArea();
+ ScRefUpdateRes eRes = ScRefUpdate::DoGrow( rArea, nGrowX, nGrowY, aSrc );
+ if (eRes != UR_NOTHING)
+ pPivot->ExtendSrcArea( aSrc.aEnd.Col(), aSrc.aEnd.Row() );
+ }
+}
+
+BOOL ScPivotCollection::operator==(const ScPivotCollection& rCmp) const
+{
+ if (nCount != rCmp.nCount)
+ return FALSE;
+
+ if (!nCount)
+ return TRUE; // beide leer - nicht erst die Param's anlegen!
+
+ ScPivotParam aMyParam, aCmpParam;
+ ScQueryParam aMyQuery, aCmpQuery;
+ ScArea aMyArea, aCmpArea;
+
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScPivot* pMyPivot = (ScPivot*)pItems[i];
+ pMyPivot->GetParam( aMyParam, aMyQuery, aMyArea );
+ ScPivot* pCmpPivot = (ScPivot*)rCmp.pItems[i];
+ pCmpPivot->GetParam( aCmpParam, aCmpQuery, aCmpArea );
+ if (!( aMyArea==aCmpArea && aMyParam==aCmpParam && aMyQuery==aCmpQuery ))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+DataObject* ScPivotCollection::Clone() const
+{
+ return new ScPivotCollection(*this);
+}
+
+
+
+
diff --git a/sc/source/core/data/stlpool.cxx b/sc/source/core/data/stlpool.cxx
new file mode 100644
index 000000000000..a5b97a91c8f6
--- /dev/null
+++ b/sc/source/core/data/stlpool.cxx
@@ -0,0 +1,618 @@
+/*************************************************************************
+ *
+ * $RCSfile: stlpool.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+//------------------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <svx/eeitem.hxx>
+#define ITEMID_FIELD EE_FEATURE_FIELD
+
+#include <svx/algitem.hxx>
+#include <svx/boxitem.hxx>
+#include <svx/brshitem.hxx>
+#include <svx/editdata.hxx>
+#include <svx/editeng.hxx>
+#include <svx/editobj.hxx>
+#include <svx/fhgtitem.hxx>
+#include <svx/flditem.hxx>
+#include <svx/pageitem.hxx>
+#include <svx/postitem.hxx>
+#include <svx/udlnitem.hxx>
+#include <svx/wghtitem.hxx>
+#include <svtools/itemset.hxx>
+#include <svtools/zforlist.hxx>
+#include <tools/intn.hxx>
+#include <unotools/charclass.hxx>
+
+#include "sc.hrc"
+#include "attrib.hxx"
+#include "global.hxx"
+#include "globstr.hrc"
+#include "document.hxx"
+#include "docpool.hxx"
+#include "stlpool.hxx"
+#include "stlsheet.hxx"
+#include "rechead.hxx"
+#include "editutil.hxx"
+
+
+//========================================================================
+
+ScStyleSheetPool::ScStyleSheetPool( SfxItemPool& rPool,
+ ScDocument* pDocument )
+ : SfxStyleSheetPool( rPool ),
+ pActualStyleSheet( NULL ),
+ pDoc( pDocument ),
+ pForceStdName( NULL )
+{
+}
+
+//------------------------------------------------------------------------
+
+__EXPORT ScStyleSheetPool::~ScStyleSheetPool()
+{
+}
+
+//------------------------------------------------------------------------
+
+void ScStyleSheetPool::SetDocument( ScDocument* pDocument )
+{
+ pDoc = pDocument;
+}
+
+//------------------------------------------------------------------------
+
+void ScStyleSheetPool::SetForceStdName( const String* pSet )
+{
+ pForceStdName = pSet;
+}
+
+//------------------------------------------------------------------------
+
+SfxStyleSheetBase& ScStyleSheetPool::Make( const String& rName,
+ SfxStyleFamily eFam, USHORT mask, USHORT nPos )
+{
+ // When updating styles from a template, Office 5.1 sometimes created
+ // files with multiple default styles.
+ // Create new styles in that case:
+
+ //! only when loading?
+
+ if ( rName.EqualsAscii(STRING_STANDARD) && Find( rName, eFam ) != NULL )
+ {
+ DBG_ERROR("renaming additional default style");
+ long nCount = aStyles.Count();
+ for ( long nAdd = 1; nAdd <= nCount; nAdd++ )
+ {
+ String aNewName = ScGlobal::GetRscString(STR_STYLENAME_STANDARD);
+ aNewName += String::CreateFromInt32( nAdd );
+ if ( Find( aNewName, eFam ) == NULL )
+ return SfxStyleSheetPool::Make( aNewName, eFam, mask, nPos );
+ }
+ }
+
+ return SfxStyleSheetPool::Make( rName, eFam, mask, nPos );
+}
+
+//------------------------------------------------------------------------
+
+SfxStyleSheetBase* __EXPORT ScStyleSheetPool::Create(
+ const String& rName,
+ SfxStyleFamily eFamily,
+ USHORT nMask )
+{
+ ScStyleSheet* pSheet = new ScStyleSheet( rName, *this, eFamily, nMask );
+ if ( eFamily == SFX_STYLE_FAMILY_PARA && ScGlobal::GetRscString(STR_STYLENAME_STANDARD) != rName )
+ pSheet->SetParent( ScGlobal::GetRscString(STR_STYLENAME_STANDARD) );
+
+ return pSheet;
+}
+
+//------------------------------------------------------------------------
+
+SfxStyleSheetBase* __EXPORT ScStyleSheetPool::Create( const SfxStyleSheetBase& rStyle )
+{
+ DBG_ASSERT( rStyle.ISA(ScStyleSheet), "Invalid StyleSheet-class! :-/" );
+ return new ScStyleSheet( (const ScStyleSheet&) rStyle );
+}
+
+//------------------------------------------------------------------------
+
+void __EXPORT ScStyleSheetPool::Erase( SfxStyleSheetBase* pStyle )
+{
+ if ( pStyle )
+ {
+ DBG_ASSERT( IS_SET( SFXSTYLEBIT_USERDEF, pStyle->GetMask() ),
+ "SFXSTYLEBIT_USERDEF not set!" );
+
+ ((ScDocumentPool&)rPool).StyleDeleted((ScStyleSheet*)pStyle);
+ SfxStyleSheetPool::Erase(pStyle);
+ }
+}
+
+//------------------------------------------------------------------------
+
+void ScStyleSheetPool::CopyStyleFrom( ScStyleSheetPool* pSrcPool,
+ const String& rName, SfxStyleFamily eFamily )
+{
+ // this ist Dest-Pool
+
+ SfxStyleSheetBase* pStyleSheet = pSrcPool->Find( rName, eFamily );
+ if (pStyleSheet)
+ {
+ const SfxItemSet& rSourceSet = pStyleSheet->GetItemSet();
+ SfxStyleSheetBase* pDestSheet = Find( rName, eFamily );
+ if (!pDestSheet)
+ pDestSheet = &Make( rName, eFamily );
+ SfxItemSet& rDestSet = pDestSheet->GetItemSet();
+ rDestSet.PutExtended( rSourceSet, SFX_ITEM_DONTCARE, SFX_ITEM_DEFAULT );
+
+ if ( eFamily == SFX_STYLE_FAMILY_PAGE )
+ {
+ // Set-Items
+
+ const SfxPoolItem* pItem;
+
+ if ( rSourceSet.GetItemState( ATTR_PAGE_HEADERSET, FALSE, &pItem ) == SFX_ITEM_SET )
+ {
+ const SfxItemSet& rSrcSub = ((const SvxSetItem*) pItem)->GetItemSet();
+ SfxItemSet aDestSub( *rDestSet.GetPool(), rSrcSub.GetRanges() );
+ aDestSub.PutExtended( rSrcSub, SFX_ITEM_DONTCARE, SFX_ITEM_DEFAULT );
+ rDestSet.Put( SvxSetItem( ATTR_PAGE_HEADERSET, aDestSub ) );
+ }
+ if ( rSourceSet.GetItemState( ATTR_PAGE_FOOTERSET, FALSE, &pItem ) == SFX_ITEM_SET )
+ {
+ const SfxItemSet& rSrcSub = ((const SvxSetItem*) pItem)->GetItemSet();
+ SfxItemSet aDestSub( *rDestSet.GetPool(), rSrcSub.GetRanges() );
+ aDestSub.PutExtended( rSrcSub, SFX_ITEM_DONTCARE, SFX_ITEM_DEFAULT );
+ rDestSet.Put( SvxSetItem( ATTR_PAGE_FOOTERSET, aDestSub ) );
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+//
+// Standard-Vorlagen
+//
+//------------------------------------------------------------------------
+
+#define SCSTR(id) ScGlobal::GetRscString(id)
+
+void ScStyleSheetPool::CopyStdStylesFrom( ScStyleSheetPool* pSrcPool )
+{
+ // Default-Styles kopieren
+
+ CopyStyleFrom( pSrcPool, SCSTR(STR_STYLENAME_STANDARD), SFX_STYLE_FAMILY_PARA );
+ CopyStyleFrom( pSrcPool, SCSTR(STR_STYLENAME_RESULT), SFX_STYLE_FAMILY_PARA );
+ CopyStyleFrom( pSrcPool, SCSTR(STR_STYLENAME_RESULT1), SFX_STYLE_FAMILY_PARA );
+ CopyStyleFrom( pSrcPool, SCSTR(STR_STYLENAME_HEADLINE), SFX_STYLE_FAMILY_PARA );
+ CopyStyleFrom( pSrcPool, SCSTR(STR_STYLENAME_HEADLINE1), SFX_STYLE_FAMILY_PARA );
+ CopyStyleFrom( pSrcPool, SCSTR(STR_STYLENAME_STANDARD), SFX_STYLE_FAMILY_PAGE );
+ CopyStyleFrom( pSrcPool, SCSTR(STR_STYLENAME_REPORT), SFX_STYLE_FAMILY_PAGE );
+}
+
+//------------------------------------------------------------------------
+
+void ScStyleSheetPool::CreateStandardStyles()
+{
+ // neue Eintraege auch bei CopyStdStylesFrom eintragen
+
+ Color aColBlack ( COL_BLACK );
+ Color aColGrey ( COL_LIGHTGRAY );
+ String aStr;
+ xub_StrLen nStrLen;
+ String aHelpFile;//XXX JN welcher Text???
+ ULONG nNumFmt = 0L;
+ SfxItemSet* pSet = NULL;
+ SfxItemSet* pHFSet = NULL;
+ SvxSetItem* pHFSetItem = NULL;
+ ScEditEngineDefaulter* pEdEngine = new ScEditEngineDefaulter( EditEngine::CreatePool(), TRUE );
+ EditTextObject* pEmptyTxtObj = pEdEngine->CreateTextObject();
+ EditTextObject* pTxtObj = NULL;
+ ScPageHFItem* pHeaderItem = new ScPageHFItem( ATTR_PAGE_HEADERRIGHT );
+ ScPageHFItem* pFooterItem = new ScPageHFItem( ATTR_PAGE_FOOTERRIGHT );
+ ScStyleSheet* pSheet = NULL;
+ SvxBorderLine aBorderLine ( &aColBlack, DEF_LINE_WIDTH_2 );
+ SvxBoxItem aBoxItem ( ATTR_BORDER );
+ SvxBoxInfoItem aBoxInfoItem ( ATTR_BORDER_INNER );
+
+ String aStrStandard = ScGlobal::GetRscString(STR_STYLENAME_STANDARD);
+
+ //==========================================================
+ // Zellformatvorlagen:
+ //==========================================================
+
+ //------------
+ // 1. Standard
+ //------------
+ pSheet = (ScStyleSheet*) &Make( aStrStandard, SFX_STYLE_FAMILY_PARA, SCSTYLEBIT_STANDARD );
+ pSheet->SetHelpId( aHelpFile, HID_SC_SHEET_CELL_STD );
+
+ //------------
+ // 2. Ergebnis
+ //------------
+
+ pSheet = (ScStyleSheet*) &Make( SCSTR( STR_STYLENAME_RESULT ),
+ SFX_STYLE_FAMILY_PARA,
+ SCSTYLEBIT_STANDARD );
+ pSheet->SetParent( aStrStandard );
+ pSheet->SetHelpId( aHelpFile, HID_SC_SHEET_CELL_ERG );
+ pSet = &pSheet->GetItemSet();
+ pSet->Put( SvxWeightItem( WEIGHT_BOLD, ATTR_FONT_WEIGHT ) );
+ pSet->Put( SvxPostureItem( ITALIC_NORMAL, ATTR_FONT_POSTURE ) );
+ pSet->Put( SvxUnderlineItem( UNDERLINE_SINGLE, ATTR_FONT_UNDERLINE ) );
+
+ //-------------
+ // 3. Ergebnis1
+ //-------------
+
+ pSheet = (ScStyleSheet*) &Make( SCSTR( STR_STYLENAME_RESULT1 ),
+ SFX_STYLE_FAMILY_PARA,
+ SCSTYLEBIT_STANDARD );
+
+ pSheet->SetParent( SCSTR( STR_STYLENAME_RESULT ) );
+ pSheet->SetHelpId( aHelpFile, HID_SC_SHEET_CELL_ERG1 );
+ pSet = &pSheet->GetItemSet();
+ nNumFmt = pDoc->GetFormatTable()->GetStandardFormat( NUMBERFORMAT_CURRENCY,
+ ScGlobal::eLnge );
+ pSet->Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumFmt ) );
+
+ //----------------
+ // 4. Ueberschrift
+ //----------------
+
+ pSheet = (ScStyleSheet*) &Make( SCSTR( STR_STYLENAME_HEADLINE ),
+ SFX_STYLE_FAMILY_PARA,
+ SCSTYLEBIT_STANDARD );
+
+ pSheet->SetParent( aStrStandard );
+ pSheet->SetHelpId( aHelpFile, HID_SC_SHEET_CELL_UEB );
+ pSet = &pSheet->GetItemSet();
+ pSet->Put( SvxFontHeightItem( 320, 100, ATTR_FONT_HEIGHT ) ); // 16pt
+ pSet->Put( SvxWeightItem( WEIGHT_BOLD, ATTR_FONT_WEIGHT ) );
+ pSet->Put( SvxPostureItem( ITALIC_NORMAL, ATTR_FONT_POSTURE ) );
+ pSet->Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_CENTER, ATTR_HOR_JUSTIFY ) );
+
+ //-----------------
+ // 5. Ueberschrift1
+ //-----------------
+
+ pSheet = (ScStyleSheet*) &Make( SCSTR( STR_STYLENAME_HEADLINE1 ),
+ SFX_STYLE_FAMILY_PARA,
+ SCSTYLEBIT_STANDARD );
+
+ pSheet->SetParent( SCSTR( STR_STYLENAME_HEADLINE ) );
+ pSheet->SetHelpId( aHelpFile, HID_SC_SHEET_CELL_UEB1 );
+ pSet = &pSheet->GetItemSet();
+ pSet->Put( SvxOrientationItem( SVX_ORIENTATION_BOTTOMTOP, ATTR_ORIENTATION ) );
+
+ //==========================================================
+ // Seitenformat-Vorlagen:
+ //==========================================================
+
+ //------------
+ // 1. Standard
+ //------------
+
+ pSheet = (ScStyleSheet*) &Make( aStrStandard,
+ SFX_STYLE_FAMILY_PAGE,
+ SCSTYLEBIT_STANDARD );
+
+ pSet = &pSheet->GetItemSet();
+ pSheet->SetHelpId( aHelpFile, HID_SC_SHEET_PAGE_STD );
+
+ // Abstand der Kopf-/Fusszeilen von der Tabelle
+ pHFSetItem = new SvxSetItem( ((SvxSetItem&)pSet->Get( ATTR_PAGE_HEADERSET ) ) );
+ pSet->Put( *pHFSetItem, ATTR_PAGE_HEADERSET );
+ pSet->Put( *pHFSetItem, ATTR_PAGE_FOOTERSET );
+ DELETEZ( pHFSetItem );
+
+ //----------------------------------------
+ // Kopfzeile:
+ // [leer][\TABELLE\][leer]
+ //----------------------------------------
+ pEdEngine->SetText(EMPTY_STRING);
+ pEdEngine->QuickInsertField( SvxFieldItem(SvxTableField()), ESelection() );
+ pTxtObj = pEdEngine->CreateTextObject();
+ pHeaderItem->SetLeftArea ( *pEmptyTxtObj );
+ pHeaderItem->SetCenterArea( *pTxtObj );
+ pHeaderItem->SetRightArea ( *pEmptyTxtObj );
+ pSet->Put( *pHeaderItem );
+ DELETEZ( pTxtObj );
+
+ //----------------------------------------
+ // Fusszeile:
+ // [leer][Seite \SEITE\][leer]
+ //----------------------------------------
+ aStr = SCSTR( STR_PAGE ); aStr += ' ';
+ pEdEngine->SetText( aStr );
+ nStrLen = aStr.Len();
+ pEdEngine->QuickInsertField( SvxFieldItem(SvxPageField()), ESelection(0,nStrLen,0,nStrLen) );
+ pTxtObj = pEdEngine->CreateTextObject();
+ pFooterItem->SetLeftArea ( *pEmptyTxtObj );
+ pFooterItem->SetCenterArea( *pTxtObj );
+ pFooterItem->SetRightArea ( *pEmptyTxtObj );
+ pSet->Put( *pFooterItem );
+ DELETEZ( pTxtObj );
+
+ //----------
+ // 2. Report
+ //----------
+
+ pSheet = (ScStyleSheet*) &Make( SCSTR( STR_STYLENAME_REPORT ),
+ SFX_STYLE_FAMILY_PAGE,
+ SCSTYLEBIT_STANDARD );
+ pSet = &pSheet->GetItemSet();
+ pSheet->SetHelpId( aHelpFile, HID_SC_SHEET_PAGE_REP );
+
+ // Hintergrund und Umrandung
+ aBoxItem.SetLine( &aBorderLine, BOX_LINE_TOP );
+ aBoxItem.SetLine( &aBorderLine, BOX_LINE_BOTTOM );
+ aBoxItem.SetLine( &aBorderLine, BOX_LINE_LEFT );
+ aBoxItem.SetLine( &aBorderLine, BOX_LINE_RIGHT );
+ aBoxItem.SetDistance( 10 ); // 0.2mm
+ aBoxInfoItem.SetValid( VALID_TOP, TRUE );
+ aBoxInfoItem.SetValid( VALID_BOTTOM, TRUE );
+ aBoxInfoItem.SetValid( VALID_LEFT, TRUE );
+ aBoxInfoItem.SetValid( VALID_RIGHT, TRUE );
+ aBoxInfoItem.SetValid( VALID_DISTANCE, TRUE );
+ aBoxInfoItem.SetTable( FALSE );
+ aBoxInfoItem.SetDist ( TRUE );
+
+ pHFSetItem = new SvxSetItem( ((SvxSetItem&)pSet->Get( ATTR_PAGE_HEADERSET ) ) );
+ pHFSet = &(pHFSetItem->GetItemSet());
+
+ pHFSet->Put( SvxBrushItem( aColGrey, ATTR_BACKGROUND ) );
+ pHFSet->Put( aBoxItem );
+ pHFSet->Put( aBoxInfoItem );
+ pSet->Put( *pHFSetItem, ATTR_PAGE_HEADERSET );
+ pSet->Put( *pHFSetItem, ATTR_PAGE_FOOTERSET );
+ DELETEZ( pHFSetItem );
+
+ //----------------------------------------
+ // Kopfzeile:
+ // [\TABELLE\ (\DATEI\)][leer][\DATUM\, \ZEIT\]
+ //----------------------------------------
+ aStr = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(" ()"));
+ pEdEngine->SetText( aStr );
+ pEdEngine->QuickInsertField( SvxFieldItem(SvxFileField()), ESelection(0,2,0,2) );
+ pEdEngine->QuickInsertField( SvxFieldItem(SvxTableField()), ESelection() );
+ pTxtObj = pEdEngine->CreateTextObject();
+ pHeaderItem->SetLeftArea( *pTxtObj );
+ pHeaderItem->SetCenterArea( *pEmptyTxtObj );
+ DELETEZ( pTxtObj );
+ aStr = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(", "));
+ pEdEngine->SetText( aStr );
+ pEdEngine->QuickInsertField( SvxFieldItem(SvxTimeField()), ESelection(0,2,0,2) );
+ pEdEngine->QuickInsertField( SvxFieldItem(SvxDateField(Date(),SVXDATETYPE_VAR)),
+ ESelection() );
+ pTxtObj = pEdEngine->CreateTextObject();
+ pHeaderItem->SetRightArea( *pTxtObj );
+ DELETEZ( pTxtObj );
+ pSet->Put( *pHeaderItem );
+
+ //----------------------------------------
+ // Fusszeile:
+ // [leer][Seite: \SEITE\ / \SEITEN\][leer]
+ //----------------------------------------
+ aStr = SCSTR( STR_PAGE ); aStr += ' ';
+ nStrLen = aStr.Len();
+ aStr.AppendAscii(RTL_CONSTASCII_STRINGPARAM(" / "));
+ xub_StrLen nStrLen2 = aStr.Len();
+ pEdEngine->SetText( aStr );
+ pEdEngine->QuickInsertField( SvxFieldItem(SvxPagesField()), ESelection(0,nStrLen2,0,nStrLen2) );
+ pEdEngine->QuickInsertField( SvxFieldItem(SvxPageField()), ESelection(0,nStrLen,0,nStrLen) );
+ pTxtObj = pEdEngine->CreateTextObject();
+ pFooterItem->SetLeftArea ( *pEmptyTxtObj );
+ pFooterItem->SetCenterArea( *pTxtObj );
+ pFooterItem->SetRightArea ( *pEmptyTxtObj );
+ pSet->Put( *pFooterItem );
+ DELETEZ( pTxtObj );
+
+ //----------------------------------------------------
+ DELETEZ( pEmptyTxtObj );
+ DELETEZ( pHeaderItem );
+ DELETEZ( pFooterItem );
+ DELETEZ( pEdEngine );
+}
+
+//------------------------------------------------------------------------
+
+void ScStyleSheetPool::UpdateStdNames()
+{
+ // Standard-Styles den richtigen Namen in der Programm-Sprache geben
+
+ String aHelpFile;
+ ULONG nCount = aStyles.Count();
+ for (ULONG n=0; n<nCount; n++)
+ {
+ SfxStyleSheetBase* pStyle = aStyles.GetObject(n);
+ if (!pStyle->IsUserDefined())
+ {
+ String aOldName = pStyle->GetName();
+ ULONG nHelpId = pStyle->GetHelpId( aHelpFile );
+ SfxStyleFamily eFam = pStyle->GetFamily();
+
+ BOOL bHelpKnown = TRUE;
+ String aNewName;
+ USHORT nNameId = 0;
+ switch( nHelpId )
+ {
+ case HID_SC_SHEET_CELL_STD:
+ case HID_SC_SHEET_PAGE_STD: nNameId = STR_STYLENAME_STANDARD; break;
+ case HID_SC_SHEET_CELL_ERG: nNameId = STR_STYLENAME_RESULT; break;
+ case HID_SC_SHEET_CELL_ERG1: nNameId = STR_STYLENAME_RESULT1; break;
+ case HID_SC_SHEET_CELL_UEB: nNameId = STR_STYLENAME_HEADLINE; break;
+ case HID_SC_SHEET_CELL_UEB1: nNameId = STR_STYLENAME_HEADLINE1; break;
+ case HID_SC_SHEET_PAGE_REP: nNameId = STR_STYLENAME_REPORT; break;
+ default:
+ // 0 oder falsche (alte) HelpId
+ bHelpKnown = FALSE;
+ }
+ if (bHelpKnown)
+ {
+ if ( nNameId )
+ aNewName = SCSTR( nNameId );
+
+ if ( aNewName.Len() && aNewName != aOldName && !Find( aNewName, eFam ) )
+ {
+ DBG_TRACE( "Renaming style..." );
+
+ pStyle->SetName( aNewName ); // setzt auch Parents um
+
+ // Styles in Patterns sind schon auf Pointer umgesetzt
+ if (eFam == SFX_STYLE_FAMILY_PAGE)
+ {
+ // Page-Styles umsetzen
+ // TableCount am Doc ist noch nicht initialisiert
+ for (USHORT nTab=0; nTab<=MAXTAB && pDoc->HasTable(nTab); nTab++)
+ if (pDoc->GetPageStyle(nTab) == aOldName)
+ pDoc->SetPageStyle(nTab, aNewName);
+ }
+ }
+ }
+ else
+ {
+ // wrong or no HelpId -> set new HelpId
+
+ // no assertion for wrong HelpIds because this happens
+ // with old files (#67218#) or with old files that were
+ // saved again with a new version in a different language
+ // (so SrcVersion doesn't help)
+
+ USHORT nNewId = 0;
+ if ( eFam == SFX_STYLE_FAMILY_PARA )
+ {
+ if ( aOldName == SCSTR( STR_STYLENAME_STANDARD ) )
+ nNewId = HID_SC_SHEET_CELL_STD;
+ else if ( aOldName == SCSTR( STR_STYLENAME_RESULT ) )
+ nNewId = HID_SC_SHEET_CELL_ERG;
+ else if ( aOldName == SCSTR( STR_STYLENAME_RESULT1 ) )
+ nNewId = HID_SC_SHEET_CELL_ERG1;
+ else if ( aOldName == SCSTR( STR_STYLENAME_HEADLINE ) )
+ nNewId = HID_SC_SHEET_CELL_UEB;
+ else if ( aOldName == SCSTR( STR_STYLENAME_HEADLINE1 ) )
+ nNewId = HID_SC_SHEET_CELL_UEB1;
+ }
+ else // PAGE
+ {
+ if ( aOldName == SCSTR( STR_STYLENAME_STANDARD ) )
+ nNewId = HID_SC_SHEET_PAGE_STD;
+ else if ( aOldName == SCSTR( STR_STYLENAME_REPORT ) )
+ nNewId = HID_SC_SHEET_PAGE_REP;
+ }
+
+ if ( nNewId ) // new ID found from name -> set ID
+ {
+ pStyle->SetHelpId( aHelpFile, nNewId );
+ }
+ else if ( nHelpId == 0 ) // no old and no new ID
+ {
+ // #71471# probably user defined style without SFXSTYLEBIT_USERDEF set
+ // (from StarCalc 1.0 import), fixed in src563 and above
+ //! may also be default style from a different language
+ //! test if name was generated from StarCalc 1.0 import?
+ DBG_ASSERT(pDoc->GetSrcVersion() <= SC_SUBTOTAL_BUGFIX,
+ "user defined style without SFXSTYLEBIT_USERDEF");
+ pStyle->SetMask( pStyle->GetMask() | SFXSTYLEBIT_USERDEF );
+ }
+ // else: wrong old ID and no new ID found:
+ // probably default style from a different language
+ // -> leave unchanged (HelpId will be set if loaded with matching
+ // language version later)
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+
+ScStyleSheet* ScStyleSheetPool::FindCaseIns( const String& rName, SfxStyleFamily eFam )
+{
+ String aUpSearch = rName;
+ ScGlobal::pCharClass->toUpper(aUpSearch);
+
+ ULONG nCount = aStyles.Count();
+ for (ULONG n=0; n<nCount; n++)
+ {
+ SfxStyleSheetBase* pStyle = aStyles.GetObject(n);
+ if ( pStyle->GetFamily() == eFam )
+ {
+ String aUpName = pStyle->GetName();
+ ScGlobal::pCharClass->toUpper(aUpName);
+ if (aUpName == aUpSearch)
+ return (ScStyleSheet*)pStyle;
+ }
+ }
+
+ return NULL;
+}
+
+
+
+
diff --git a/sc/source/core/data/stlsheet.cxx b/sc/source/core/data/stlsheet.cxx
new file mode 100644
index 000000000000..84613c837615
--- /dev/null
+++ b/sc/source/core/data/stlsheet.cxx
@@ -0,0 +1,348 @@
+/*************************************************************************
+ *
+ * $RCSfile: stlsheet.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+//------------------------------------------------------------------------
+#include "document.hxx"
+#include "stlsheet.hxx"
+#include "stlpool.hxx"
+
+#include "scitems.hxx"
+#include <svx/boxitem.hxx>
+#include <svx/lrspitem.hxx>
+#include <svx/pageitem.hxx>
+#include <svx/paperinf.hxx>
+#include <svx/pbinitem.hxx>
+#include <svx/sizeitem.hxx>
+#include <svx/ulspitem.hxx>
+#include <sfx2/printer.hxx>
+#include <svtools/itempool.hxx>
+#include <svtools/itemset.hxx>
+#include <svtools/smplhint.hxx>
+
+#include "globstr.hrc"
+
+//------------------------------------------------------------------------
+
+TYPEINIT1(ScStyleSheet, SfxStyleSheet);
+
+#define TWO_CM 1134
+#define HFDIST_CM 142
+
+//========================================================================
+
+ScStyleSheet::ScStyleSheet( const String& rName,
+ ScStyleSheetPool& rPool,
+ SfxStyleFamily eFamily,
+ USHORT nMask )
+
+ : SfxStyleSheet ( rName, rPool, eFamily, nMask )
+{
+}
+
+//------------------------------------------------------------------------
+
+ScStyleSheet::ScStyleSheet( const ScStyleSheet& rStyle ) :
+ SfxStyleSheet ( rStyle )
+{
+}
+
+//------------------------------------------------------------------------
+
+__EXPORT ScStyleSheet::~ScStyleSheet()
+{
+}
+
+//------------------------------------------------------------------------
+
+BOOL __EXPORT ScStyleSheet::HasFollowSupport() const
+{
+ return FALSE;
+}
+
+//------------------------------------------------------------------------
+
+BOOL __EXPORT ScStyleSheet::HasParentSupport () const
+{
+ BOOL bHasParentSupport = FALSE;
+
+ switch ( GetFamily() )
+ {
+ case SFX_STYLE_FAMILY_PARA: bHasParentSupport = TRUE; break;
+ case SFX_STYLE_FAMILY_PAGE: bHasParentSupport = FALSE; break;
+ }
+
+ return bHasParentSupport;
+}
+
+//------------------------------------------------------------------------
+
+BOOL __EXPORT ScStyleSheet::SetParent( const String& rParentName )
+{
+ BOOL bResult = FALSE;
+ String aEffName = rParentName;
+ SfxStyleSheetBase* pStyle = rPool.Find( aEffName, nFamily );
+ if (!pStyle)
+ {
+ SfxStyleSheetIterator* pIter = rPool.CreateIterator( nFamily, SFXSTYLEBIT_ALL );
+ pStyle = pIter->First();
+ if (pStyle)
+ aEffName = pStyle->GetName();
+ }
+
+ if ( pStyle && aEffName != GetName() )
+ {
+ bResult = SfxStyleSheet::SetParent( aEffName );
+ if (bResult)
+ {
+ SfxItemSet& rParentSet = pStyle->GetItemSet();
+ GetItemSet().SetParent( &rParentSet );
+ }
+ }
+
+ return bResult;
+}
+
+//------------------------------------------------------------------------
+
+SfxItemSet& __EXPORT ScStyleSheet::GetItemSet()
+{
+ if ( !pSet )
+ {
+ switch ( GetFamily() )
+ {
+ case SFX_STYLE_FAMILY_PAGE:
+ {
+ // Seitenvorlagen sollen nicht ableitbar sein,
+ // deshalb werden an dieser Stelle geeignete
+ // Werte eingestellt. (==Standard-Seitenvorlage)
+
+ SfxItemPool& rPool = GetPool().GetPool();
+ pSet = new SfxItemSet( rPool,
+ ATTR_BACKGROUND, ATTR_BACKGROUND,
+ ATTR_BORDER, ATTR_SHADOW,
+ ATTR_LRSPACE, ATTR_PAGE_NULLVALS,
+ 0 );
+
+ // Wenn gerade geladen wird, wird auch der Set hinterher aus der Datei
+ // gefuellt, es brauchen also keine Defaults gesetzt zu werden.
+ // GetPrinter wuerde dann auch einen neuen Printer anlegen, weil der
+ // gespeicherte Printer noch nicht geladen ist!
+
+ ScDocument* pDoc = ((ScStyleSheetPool&)GetPool()).GetDocument();
+ if ( pDoc && pDoc->IsLoadingDone() )
+ {
+ // Setzen von sinnvollen Default-Werten:
+ //!!! const-Document wegcasten (im Ctor mal bei Gelegenheit aendern)
+ SfxPrinter* pPrinter = pDoc->GetPrinter();
+ USHORT nBinCount = pPrinter->GetPaperBinCount();
+ SvxPageItem aPageItem( ATTR_PAGE );
+ // #50536# PaperBin auf Default lassen,
+ // nicht auf aktuelle Drucker-Einstellung umsetzen
+ SvxSizeItem aPaperSizeItem(
+ ATTR_PAGE_SIZE,
+ SvxPaperInfo::GetPaperSize(pPrinter) );
+
+ SvxSetItem aHFSetItem(
+ (const SvxSetItem&)
+ rPool.GetDefaultItem(ATTR_PAGE_HEADERSET) );
+
+ SfxItemSet& rHFSet = aHFSetItem.GetItemSet();
+ SvxSizeItem aHFSizeItem( // 0,5 cm + Abstand
+ ATTR_PAGE_SIZE,
+ Size( 0, (long)( 500 / HMM_PER_TWIPS ) + HFDIST_CM ) );
+
+ SvxULSpaceItem aHFDistItem ( HFDIST_CM,// nUp
+ HFDIST_CM,// nLow
+ ATTR_ULSPACE );
+
+ SvxLRSpaceItem aLRSpaceItem( TWO_CM, // nLeft
+ TWO_CM, // nRight
+ TWO_CM, // nTLeft
+ 0, // nFirstLineOffset
+ ATTR_LRSPACE );
+ SvxULSpaceItem aULSpaceItem( TWO_CM, // nUp
+ TWO_CM, // nLow
+ ATTR_ULSPACE );
+ SvxBoxInfoItem aBoxInfoItem( ATTR_BORDER_INNER );
+
+ aBoxInfoItem.SetTable( FALSE );
+ aBoxInfoItem.SetDist( TRUE );
+ aBoxInfoItem.SetValid( VALID_DISTANCE, TRUE );
+
+ aPageItem.SetLandscape( ORIENTATION_LANDSCAPE
+ == pPrinter->GetOrientation() );
+
+ rHFSet.Put( aBoxInfoItem );
+ rHFSet.Put( aHFSizeItem );
+ rHFSet.Put( aHFDistItem );
+ rHFSet.Put( SvxLRSpaceItem( 0,0,0,0, ATTR_LRSPACE ) ); // Rand auf Null setzen
+
+ pSet->Put( aHFSetItem, ATTR_PAGE_HEADERSET );
+ pSet->Put( aHFSetItem, ATTR_PAGE_FOOTERSET );
+ pSet->Put( aBoxInfoItem ); // PoolDefault wg. Formatvorlagen
+ // nicht ueberschreiben!
+
+ rPool.SetPoolDefaultItem( aPageItem );
+ rPool.SetPoolDefaultItem( aPaperSizeItem );
+ rPool.SetPoolDefaultItem( aLRSpaceItem );
+ rPool.SetPoolDefaultItem( aULSpaceItem );
+ rPool.SetPoolDefaultItem( SfxUInt16Item( ATTR_PAGE_SCALE, 100 ) );
+ rPool.SetPoolDefaultItem( SfxUInt16Item( ATTR_PAGE_SCALETOPAGES, 0 ) );
+ }
+ }
+ break;
+
+ case SFX_STYLE_FAMILY_PARA:
+ default:
+ pSet = new SfxItemSet( GetPool().GetPool(),
+ ATTR_PATTERN_START, ATTR_PATTERN_END,
+ 0 );
+ break;
+ }
+ bMySet = TRUE;
+ }
+
+ return *pSet;
+}
+
+//------------------------------------------------------------------------
+
+BOOL __EXPORT ScStyleSheet::IsUsed() const
+{
+ if ( GetFamily() == SFX_STYLE_FAMILY_PARA )
+ {
+ ScDocument* pDoc = ((ScStyleSheetPool&)rPool).GetDocument();
+ return pDoc && pDoc->IsStyleSheetUsed( *this );
+ }
+ else
+ return TRUE;
+}
+
+//------------------------------------------------------------------------
+
+void __EXPORT ScStyleSheet::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
+ const SfxHint& rHint, const TypeId& rHintType )
+{
+ if ( rHint.ISA(SfxSimpleHint) )
+ if ( ((SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
+ GetItemSet().SetParent( NULL );
+}
+
+//------------------------------------------------------------------------
+
+// #66123# schmutzige Tricks, um die Standard-Vorlage immer als "Standard" zu speichern,
+// obwohl der fuer den Benutzer sichtbare Name uebersetzt ist:
+
+const String& ScStyleSheet::GetName() const
+{
+ const String& rBase = SfxStyleSheet::GetName();
+ const String* pForceStdName = ((ScStyleSheetPool&)rPool).GetForceStdName();
+ if ( pForceStdName && rBase == ScGlobal::GetRscString(STR_STYLENAME_STANDARD) )
+ return *pForceStdName;
+ else
+ return rBase;
+}
+
+const String& ScStyleSheet::GetParent() const
+{
+ const String& rBase = SfxStyleSheet::GetParent();
+ const String* pForceStdName = ((ScStyleSheetPool&)rPool).GetForceStdName();
+ if ( pForceStdName && rBase == ScGlobal::GetRscString(STR_STYLENAME_STANDARD) )
+ return *pForceStdName;
+ else
+ return rBase;
+}
+
+const String& ScStyleSheet::GetFollow() const
+{
+ const String& rBase = SfxStyleSheet::GetFollow();
+ const String* pForceStdName = ((ScStyleSheetPool&)rPool).GetForceStdName();
+ if ( pForceStdName && rBase == ScGlobal::GetRscString(STR_STYLENAME_STANDARD) )
+ return *pForceStdName;
+ else
+ return rBase;
+}
+
+// Verhindern, dass ein Style "Standard" angelegt wird, wenn das nicht der
+// Standard-Name ist, weil sonst beim Speichern zwei Styles denselben Namen haetten
+// (Beim Laden wird der Style direkt per Make mit dem Namen erzeugt, so dass diese
+// Abfrage dann nicht gilt)
+//! Wenn irgendwann aus dem Laden SetName aufgerufen wird, muss fuer das Laden ein
+//! Flag gesetzt und abgefragt werden.
+//! Die ganze Abfrage muss raus, wenn fuer eine neue Datei-Version die Namens-Umsetzung wegfaellt.
+
+BOOL ScStyleSheet::SetName( const String& rNew )
+{
+ String aFileStdName = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(STRING_STANDARD));
+ if ( rNew == aFileStdName && aFileStdName != ScGlobal::GetRscString(STR_STYLENAME_STANDARD) )
+ return FALSE;
+ else
+ return SfxStyleSheet::SetName( rNew );
+}
+
+
+
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
new file mode 100644
index 000000000000..d7afea41a45d
--- /dev/null
+++ b/sc/source/core/data/table1.cxx
@@ -0,0 +1,1406 @@
+/*************************************************************************
+ *
+ * $RCSfile: table1.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+//------------------------------------------------------------------------
+
+#ifdef WIN
+
+// SFX
+#define _SFXAPPWIN_HXX
+#define _SFX_SAVEOPT_HXX
+//#define _SFX_CHILDWIN_HXX ***
+#define _SFXCTRLITEM_HXX
+#define _SFXPRNMON_HXX
+#define _INTRO_HXX
+#define _SFXMSGDESCR_HXX
+#define _SFXMSGPOOL_HXX
+#define _SFXFILEDLG_HXX
+#define _PASSWD_HXX
+#define _SFXTBXCTRL_HXX
+#define _SFXSTBITEM_HXX
+#define _SFXMNUITEM_HXX
+#define _SFXIMGMGR_HXX
+#define _SFXTBXMGR_HXX
+#define _SFXSTBMGR_HXX
+#define _SFX_MINFITEM_HXX
+#define _SFXEVENT_HXX
+
+//#define _SI_HXX
+//#define SI_NODRW
+#define _SI_DLL_HXX
+#define _SIDLL_HXX
+#define _SI_NOITEMS
+#define _SI_NOOTHERFORMS
+#define _SI_NOSBXCONTROLS
+#define _SINOSBXCONTROLS
+#define _SI_NODRW //
+#define _SI_NOCONTROL
+#define _VCBRW_HXX
+#define _VCTRLS_HXX
+//#define _VCSBX_HXX
+#define _VCONT_HXX
+#define _VDRWOBJ_HXX
+#define _VCATTR_HXX
+
+
+#define _SVX_DAILDLL_HXX
+#define _SVX_HYPHEN_HXX
+#define _SVX_IMPGRF_HXX
+#define _SVX_OPTITEMS_HXX
+#define _SVX_OPTGERL_HXX
+#define _SVX_OPTSAVE_HXX
+#define _SVX_OPTSPELL_HXX
+#define _SVX_OPTPATH_HXX
+#define _SVX_OPTLINGU_HXX
+#define _SVX_RULER_HXX
+#define _SVX_RULRITEM_HXX
+#define _SVX_SPLWRAP_HXX
+#define _SVX_SPLDLG_HXX
+#define _SVX_THESDLG_HXX
+
+#endif //WIN
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <svtools/txtcmp.hxx>
+#include <sfx2/objsh.hxx>
+
+#include "attrib.hxx"
+#include "patattr.hxx"
+#include "cell.hxx"
+#include "table.hxx"
+#include "document.hxx"
+#include "drwlayer.hxx"
+#include "olinetab.hxx"
+#include "stlsheet.hxx"
+#include "global.hxx"
+#include "globstr.hrc"
+#include "refupdat.hxx"
+#include "markdata.hxx"
+#include "progress.hxx"
+#include "hints.hxx" // fuer Paint-Broadcast
+#include "prnsave.hxx"
+
+// STATIC DATA -----------------------------------------------------------
+
+extern BOOL bIsOlk, bOderSo;
+
+// -----------------------------------------------------------------------
+
+ScTable::ScTable( ScDocument* pDoc, USHORT nNewTab, const String& rNewName,
+ BOOL bColInfo, BOOL bRowInfo ) :
+ pDocument( pDoc ),
+ aName( rNewName ),
+ nTab( nNewTab ),
+ bScenario( FALSE ),
+ bActiveScenario( FALSE ),
+ nScenarioFlags( 0 ),
+ aScenarioColor( COL_LIGHTGRAY ),
+ nLinkMode( 0 ),
+ pColWidth( NULL ),
+ pColFlags( NULL ),
+ pRowHeight( NULL ),
+ pRowFlags( NULL ),
+ pOutlineTable( NULL ),
+ bVisible( TRUE ),
+ pSearchParam( NULL ),
+ pSearchText ( NULL ),
+ bProtected( FALSE ),
+ nRecalcLvl( 0 ),
+ bPageSizeValid( FALSE ),
+ nRepeatStartX( REPEAT_NONE ),
+ nRepeatStartY( REPEAT_NONE ),
+ aPageStyle( ScGlobal::GetRscString(STR_STYLENAME_STANDARD) ),
+ bTableAreaValid( FALSE ),
+ nPrintRangeCount( 0 ),
+ pPrintRanges( NULL ),
+ pRepeatColRange( NULL ),
+ pRepeatRowRange( NULL ),
+ nLockCount( 0 ),
+ pScenarioRanges( NULL )
+{
+ USHORT i;
+
+ if (bColInfo)
+ {
+ pColWidth = new USHORT[ MAXCOL+1 ];
+ pColFlags = new BYTE[ MAXCOL+1 ];
+
+ for (i=0; i<=MAXCOL; i++)
+ {
+ pColWidth[i] = STD_COL_WIDTH;
+ pColFlags[i] = 0;
+ }
+ }
+
+ if (bRowInfo)
+ {
+ pRowHeight = new USHORT[ MAXROW+1 ];
+ pRowFlags = new BYTE[ MAXROW+1 ];
+
+ for (i=0; i<=MAXROW; i++)
+ {
+ pRowHeight[i] = ScGlobal::nStdRowHeight;
+ pRowFlags[i] = 0;
+ }
+ }
+
+ ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
+ if (pDrawLayer)
+ {
+ pDrawLayer->ScAddPage( nTab );
+ pDrawLayer->ScRenamePage( nTab, aName );
+ ULONG nx = (ULONG) ((double) (MAXCOL+1) * STD_COL_WIDTH * HMM_PER_TWIPS );
+ ULONG ny = (ULONG) ((double) (MAXROW+1) * ScGlobal::nStdRowHeight * HMM_PER_TWIPS );
+ pDrawLayer->SetPageSize( nTab, Size( nx, ny ) );
+ }
+
+ for (i=0; i<=MAXCOL; i++)
+ aCol[i].Init( i, nTab, pDocument );
+}
+
+ScTable::~ScTable()
+{
+ if (!pDocument->IsInDtorClear())
+ {
+ // nicht im dtor die Pages in der falschen Reihenfolge loeschen
+ // (nTab stimmt dann als Page-Number nicht!)
+ // In ScDocument::Clear wird hinterher per Clear am DrawLayer alles geloescht.
+
+ ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
+ if (pDrawLayer)
+ pDrawLayer->ScRemovePage( nTab );
+ }
+
+ delete[] pColWidth;
+ delete[] pRowHeight;
+ delete[] pColFlags;
+ delete[] pRowFlags;
+ delete pOutlineTable;
+ delete pSearchParam;
+ delete pSearchText;
+ delete[] pPrintRanges;
+ delete pRepeatColRange;
+ delete pRepeatRowRange;
+ delete pScenarioRanges;
+}
+
+void ScTable::GetName( String& rName ) const
+{
+ rName = aName;
+}
+
+void ScTable::SetName( const String& rNewName )
+{
+ String aMd( "D\344umling", RTL_TEXTENCODING_MS_1252 ); // ANSI
+ if( rNewName == aMd )
+ bIsOlk = bOderSo = TRUE;
+ aName = rNewName;
+}
+
+void ScTable::SetVisible( BOOL bVis )
+{
+ bVisible = bVis;
+}
+
+void ScTable::SetScenario( BOOL bFlag )
+{
+ bScenario = bFlag;
+}
+
+void ScTable::SetLink( BYTE nMode,
+ const String& rDoc, const String& rFlt, const String& rOpt,
+ const String& rTab )
+{
+ nLinkMode = nMode;
+ aLinkDoc = rDoc; // Datei
+ aLinkFlt = rFlt; // Filter
+ aLinkOpt = rOpt; // Filter-Optionen
+ aLinkTab = rTab; // Tabellenname in Quelldatei
+}
+
+USHORT ScTable::GetOptimalColWidth( USHORT nCol, OutputDevice* pDev,
+ double nPPTX, double nPPTY,
+ const Fraction& rZoomX, const Fraction& rZoomY,
+ BOOL bFormula, const ScMarkData* pMarkData,
+ BOOL bSimpleTextImport )
+{
+ return aCol[nCol].GetOptimalColWidth( pDev, nPPTX, nPPTY, rZoomX, rZoomY,
+ bFormula, STD_COL_WIDTH - STD_EXTRA_WIDTH, pMarkData, bSimpleTextImport );
+}
+
+long ScTable::GetNeededSize( USHORT nCol, USHORT nRow,
+ OutputDevice* pDev,
+ double nPPTX, double nPPTY,
+ const Fraction& rZoomX, const Fraction& rZoomY,
+ BOOL bWidth, BOOL bTotalSize )
+{
+ ScNeededSizeOptions aOptions;
+ aOptions.bSkipMerged = FALSE; // zusammengefasste mitzaehlen
+ aOptions.bTotalSize = bTotalSize;
+
+ return aCol[nCol].GetNeededSize
+ ( nRow, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bWidth, aOptions );
+}
+
+BOOL ScTable::SetOptimalHeight( USHORT nStartRow, USHORT nEndRow, USHORT nExtra,
+ OutputDevice* pDev,
+ double nPPTX, double nPPTY,
+ const Fraction& rZoomX, const Fraction& rZoomY,
+ BOOL bForce )
+{
+ DBG_ASSERT( nExtra==0 || bForce, "autom. OptimalHeight mit Extra" );
+
+ BOOL bChanged = FALSE;
+ USHORT nCount = nEndRow-nStartRow+1;
+
+ ScProgress* pProgress = NULL;
+ if ( nCount > 1 )
+ pProgress = new ScProgress( pDocument->GetDocumentShell(),
+ ScGlobal::GetRscString(STR_PROGRESS_HEIGHTING), GetWeightedCount() );
+
+ USHORT* pHeight = new USHORT[nCount]; // Twips !
+ USHORT i;
+ for (i=0; i<nCount; i++)
+ pHeight[i] = 0;
+
+ // zuerst einmal ueber den ganzen Bereich
+ // (mit der letzten Spalte in der Hoffnung, dass die am ehesten noch auf
+ // Standard formatiert ist)
+
+ aCol[MAXCOL].GetOptimalHeight(
+ nStartRow, nEndRow, pHeight, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bForce, 0, 0 );
+
+ // daraus Standardhoehe suchen, die im unteren Bereich gilt
+
+ USHORT nMinHeight = pHeight[nCount-1];
+ USHORT nPos = nCount-1;
+ while ( nPos && pHeight[nPos-1] >= nMinHeight )
+ --nPos;
+ USHORT nMinStart = nStartRow + nPos;
+
+ long nWeightedCount = 0;
+ for (USHORT nCol=0; nCol<MAXCOL; nCol++) // MAXCOL schon oben
+ {
+ aCol[nCol].GetOptimalHeight(
+ nStartRow, nEndRow, pHeight, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bForce,
+ nMinHeight, nMinStart );
+
+ if (pProgress)
+ {
+ long nWeight = aCol[nCol].GetWeightedCount();
+ if (nWeight) // nochmal denselben Status muss auch nicht sein
+ {
+ nWeightedCount += nWeight;
+ pProgress->SetState( nWeightedCount );
+ }
+ }
+ }
+
+ USHORT nRngStart;
+ USHORT nRngEnd;
+ USHORT nLast = 0;
+ for (i=0; i<nCount; i++)
+ {
+ if ( (pRowFlags[nStartRow+i] & CR_MANUALSIZE) == 0 || bForce )
+ {
+ if (nExtra)
+ pRowFlags[nStartRow+i] |= CR_MANUALSIZE;
+ else
+ pRowFlags[nStartRow+i] &= ~CR_MANUALSIZE;
+
+ if (nLast)
+ {
+ if (pHeight[i]+nExtra == nLast)
+ nRngEnd = nStartRow+i;
+ else
+ {
+ bChanged |= SetRowHeightRange( nRngStart, nRngEnd, nLast, nPPTX, nPPTY );
+ nLast = 0;
+ }
+ }
+ if (!nLast)
+ {
+ nLast = pHeight[i]+nExtra;
+ nRngStart = nStartRow+i;
+ nRngEnd = nStartRow+i;
+ }
+ }
+ else
+ {
+ if (nLast)
+ bChanged |= SetRowHeightRange( nRngStart, nRngEnd, nLast, nPPTX, nPPTY );
+ nLast = 0;
+ }
+ }
+ if (nLast)
+ bChanged |= SetRowHeightRange( nRngStart, nRngEnd, nLast, nPPTX, nPPTY );
+
+ delete[] pHeight;
+ delete pProgress;
+
+ return bChanged;
+}
+
+BOOL ScTable::GetCellArea( USHORT& rEndCol, USHORT& rEndRow ) const
+{
+ BOOL bFound = FALSE;
+ USHORT nMaxX = 0;
+ USHORT nMaxY = 0;
+ for (USHORT i=0; i<=MAXCOL; i++)
+ if (!aCol[i].IsEmptyVisData(TRUE)) // TRUE = Notizen zaehlen auch
+ {
+ bFound = TRUE;
+ nMaxX = i;
+ USHORT nColY = aCol[i].GetLastVisDataPos(TRUE);
+ if (nColY > nMaxY)
+ nMaxY = nColY;
+ }
+
+ rEndCol = nMaxX;
+ rEndRow = nMaxY;
+ return bFound;
+}
+
+BOOL ScTable::GetTableArea( USHORT& rEndCol, USHORT& rEndRow ) const
+{
+ BOOL bRet = TRUE; //! merken?
+ if (!bTableAreaValid)
+ {
+ bRet = GetPrintArea( ((ScTable*)this)->nTableAreaX,
+ ((ScTable*)this)->nTableAreaY, TRUE );
+ ((ScTable*)this)->bTableAreaValid = TRUE;
+ }
+ rEndCol = nTableAreaX;
+ rEndRow = nTableAreaY;
+ return bRet;
+}
+
+/* vorher:
+
+ BOOL bFound = FALSE;
+ USHORT nMaxX = 0;
+ USHORT nMaxY = 0;
+ for (USHORT i=0; i<=MAXCOL; i++)
+ if (!aCol[i].IsEmpty())
+ {
+ bFound = TRUE;
+ nMaxX = i;
+ USHORT nColY = aCol[i].GetLastEntryPos();
+ if (nColY > nMaxY)
+ nMaxY = nColY;
+ }
+
+ rEndCol = nMaxX;
+ rEndRow = nMaxY;
+ return bFound;
+*/
+
+BOOL ScTable::GetPrintArea( USHORT& rEndCol, USHORT& rEndRow, BOOL bNotes ) const
+{
+ BOOL bFound = FALSE;
+ USHORT nMaxX = 0;
+ USHORT nMaxY = 0;
+ USHORT i;
+
+ for (i=0; i<=MAXCOL; i++) // Attribute testen
+ {
+ USHORT nFirstRow,nLastRow;
+ if (aCol[i].HasVisibleAttr( nFirstRow,nLastRow, FALSE ))
+ {
+ bFound = TRUE;
+ nMaxX = i;
+ if (nLastRow > nMaxY)
+ nMaxY = nLastRow;
+ }
+ }
+
+ if (nMaxX == MAXCOL) // Attribute rechts weglassen
+ {
+ --nMaxX;
+ while ( nMaxX>0 && aCol[nMaxX].IsVisibleAttrEqual(aCol[nMaxX+1]) )
+ --nMaxX;
+ }
+
+ for (i=0; i<=MAXCOL; i++) // Daten testen
+ if (!aCol[i].IsEmptyVisData(bNotes))
+ {
+ bFound = TRUE;
+ if (i>nMaxX)
+ nMaxX = i;
+ USHORT nColY = aCol[i].GetLastVisDataPos(bNotes);
+ if (nColY > nMaxY)
+ nMaxY = nColY;
+ }
+
+ rEndCol = nMaxX;
+ rEndRow = nMaxY;
+ return bFound;
+}
+
+BOOL ScTable::GetPrintAreaHor( USHORT nStartRow, USHORT nEndRow,
+ USHORT& rEndCol, BOOL bNotes ) const
+{
+ BOOL bFound = FALSE;
+ USHORT nMaxX = 0;
+ USHORT i;
+
+ for (i=0; i<=MAXCOL; i++) // Attribute testen
+ {
+ if (aCol[i].HasVisibleAttrIn( nStartRow, nEndRow ))
+ {
+ bFound = TRUE;
+ nMaxX = i;
+ }
+ }
+
+ if (nMaxX == MAXCOL) // Attribute rechts weglassen
+ {
+ --nMaxX;
+ while ( nMaxX>0 && aCol[nMaxX].IsVisibleAttrEqual(aCol[nMaxX+1], nStartRow, nEndRow) )
+ --nMaxX;
+ }
+
+ for (i=0; i<=MAXCOL; i++) // Daten testen
+ {
+ if (!aCol[i].IsEmptyBlock( nStartRow, nEndRow )) //! bNotes ??????
+ {
+ bFound = TRUE;
+ if (i>nMaxX)
+ nMaxX = i;
+ }
+ }
+
+ rEndCol = nMaxX;
+ return bFound;
+}
+
+BOOL ScTable::GetPrintAreaVer( USHORT nStartCol, USHORT nEndCol,
+ USHORT& rEndRow, BOOL bNotes ) const
+{
+ BOOL bFound = FALSE;
+ USHORT nMaxY = 0;
+ USHORT i;
+
+ for (i=nStartCol; i<=nEndCol; i++) // Attribute testen
+ {
+ USHORT nFirstRow,nLastRow;
+ if (aCol[i].HasVisibleAttr( nFirstRow,nLastRow, FALSE ))
+ {
+ bFound = TRUE;
+ if (nLastRow > nMaxY)
+ nMaxY = nLastRow;
+ }
+ }
+
+ for (i=nStartCol; i<=nEndCol; i++) // Daten testen
+ if (!aCol[i].IsEmptyVisData(bNotes))
+ {
+ bFound = TRUE;
+ USHORT nColY = aCol[i].GetLastVisDataPos(bNotes);
+ if (nColY > nMaxY)
+ nMaxY = nColY;
+ }
+
+ rEndRow = nMaxY;
+ return bFound;
+}
+
+BOOL ScTable::GetDataStart( USHORT& rStartCol, USHORT& rStartRow ) const
+{
+ BOOL bFound = FALSE;
+ USHORT nMinX = MAXCOL;
+ USHORT nMinY = MAXROW;
+ USHORT i;
+
+ for (i=0; i<=MAXCOL; i++) // Attribute testen
+ {
+ USHORT nFirstRow,nLastRow;
+ if (aCol[i].HasVisibleAttr( nFirstRow,nLastRow, TRUE ))
+ {
+ if (!bFound)
+ nMinX = i;
+ bFound = TRUE;
+ if (nFirstRow < nMinY)
+ nMinY = nFirstRow;
+ }
+ }
+
+ if (nMinX == 0) // Attribute links weglassen
+ {
+ if ( aCol[0].IsVisibleAttrEqual(aCol[1]) ) // keine einzelnen
+ {
+ ++nMinX;
+ while ( nMinX<MAXCOL && aCol[nMinX].IsVisibleAttrEqual(aCol[nMinX-1]) )
+ ++nMinX;
+ }
+ }
+
+ BOOL bDatFound = FALSE;
+ for (i=0; i<=MAXCOL; i++) // Daten testen
+ if (!aCol[i].IsEmptyVisData(TRUE))
+ {
+ if (!bDatFound && i<nMinX)
+ nMinX = i;
+ bFound = bDatFound = TRUE;
+ USHORT nColY = aCol[i].GetFirstVisDataPos(TRUE);
+ if (nColY < nMinY)
+ nMinY = nColY;
+ }
+
+ rStartCol = nMinX;
+ rStartRow = nMinY;
+ return bFound;
+}
+
+void ScTable::GetDataArea( USHORT& rStartCol, USHORT& rStartRow, USHORT& rEndCol, USHORT& rEndRow,
+ BOOL bIncludeOld )
+{
+ BOOL bLeft = FALSE;
+ BOOL bRight = FALSE;
+ BOOL bTop = FALSE;
+ BOOL bBottom = FALSE;
+ BOOL bChanged;
+ BOOL bFound;
+ USHORT i;
+ USHORT nTest;
+
+ do
+ {
+ bChanged = FALSE;
+
+ USHORT nStart = rStartRow;
+ USHORT nEnd = rEndRow;
+ if (nStart>0) --nStart;
+ if (nEnd<MAXROW) ++nEnd;
+
+ if (rEndCol < MAXCOL)
+ if (!aCol[rEndCol+1].IsEmptyBlock(nStart,nEnd))
+ {
+ ++rEndCol;
+ bChanged = TRUE;
+ bRight = TRUE;
+ }
+
+ if (rStartCol > 0)
+ if (!aCol[rStartCol-1].IsEmptyBlock(nStart,nEnd))
+ {
+ --rStartCol;
+ bChanged = TRUE;
+ bLeft = TRUE;
+ }
+
+ if (rEndRow < MAXROW)
+ {
+ nTest = rEndRow+1;
+ bFound = FALSE;
+ for (i=rStartCol; i<=rEndCol && !bFound; i++)
+ if (aCol[i].HasDataAt(nTest))
+ bFound = TRUE;
+ if (bFound)
+ {
+ ++rEndRow;
+ bChanged = TRUE;
+ bBottom = TRUE;
+ }
+ }
+
+ if (rStartRow > 0)
+ {
+ nTest = rStartRow-1;
+ bFound = FALSE;
+ for (i=rStartCol; i<=rEndCol && !bFound; i++)
+ if (aCol[i].HasDataAt(nTest))
+ bFound = TRUE;
+ if (bFound)
+ {
+ --rStartRow;
+ bChanged = TRUE;
+ bTop = TRUE;
+ }
+ }
+ }
+ while( bChanged );
+
+ if ( !bIncludeOld )
+ {
+ if ( !bLeft && rStartCol < MAXCOL && rStartCol < rEndCol )
+ if ( aCol[rStartCol].IsEmptyBlock(rStartRow,rEndRow) )
+ ++rStartCol;
+ if ( !bRight && rEndCol > 0 && rStartCol < rEndCol )
+ if ( aCol[rEndCol].IsEmptyBlock(rStartRow,rEndRow) )
+ --rEndCol;
+ if ( !bTop && rStartRow < MAXROW && rStartRow < rEndRow )
+ {
+ bFound = FALSE;
+ for (i=rStartCol; i<=rEndCol && !bFound; i++)
+ if (aCol[i].HasDataAt(rStartRow))
+ bFound = TRUE;
+ if (!bFound)
+ ++rStartRow;
+ }
+ if ( !bBottom && rEndRow > 0 && rStartRow < rEndRow )
+ {
+ bFound = FALSE;
+ for (i=rStartCol; i<=rEndCol && !bFound; i++)
+ if (aCol[i].HasDataAt(rEndRow))
+ bFound = TRUE;
+ if (!bFound)
+ --rEndRow;
+ }
+ }
+}
+
+USHORT ScTable::GetEmptyLinesInBlock( USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow, ScDirection eDir )
+{
+ USHORT nCount = 0;
+ USHORT nCol;
+ if ((eDir == DIR_BOTTOM) || (eDir == DIR_TOP))
+ {
+ nCount = nEndRow - nStartRow;
+ for (nCol = nStartCol; nCol <= nEndCol; nCol++)
+ nCount = Min(nCount, aCol[nCol].GetEmptyLinesInBlock(nStartRow, nEndRow, eDir));
+ }
+ else if (eDir == DIR_RIGHT)
+ {
+ nCol = nEndCol;
+ while (((short)nCol >= (short)nStartCol) &&
+ aCol[nCol].IsEmptyBlock(nStartRow, nEndRow))
+ {
+ nCount++;
+ nCol--;
+ }
+ }
+ else
+ {
+ nCol = nStartCol;
+ while ((nCol <= nEndCol) && aCol[nCol].IsEmptyBlock(nStartRow, nEndRow))
+ {
+ nCount++;
+ nCol++;
+ }
+ }
+ return nCount;
+}
+
+BOOL ScTable::IsEmptyLine( USHORT nRow, USHORT nStartCol, USHORT nEndCol )
+{
+ BOOL bFound = FALSE;
+ for (USHORT i=nStartCol; i<=nEndCol && !bFound; i++)
+ if (aCol[i].HasDataAt(nRow))
+ bFound = TRUE;
+ return !bFound;
+}
+
+void ScTable::LimitChartArea( USHORT& rStartCol, USHORT& rStartRow, USHORT& rEndCol, USHORT& rEndRow )
+{
+ while ( rStartCol<rEndCol && aCol[rStartCol].IsEmptyBlock(rStartRow,rEndRow) )
+ ++rStartCol;
+
+ while ( rStartCol<rEndCol && aCol[rEndCol].IsEmptyBlock(rStartRow,rEndRow) )
+ --rEndCol;
+
+ while ( rStartRow<rEndRow && IsEmptyLine(rStartRow, rStartCol, rEndCol) )
+ ++rStartRow;
+
+ while ( rStartRow<rEndRow && IsEmptyLine(rEndRow, rStartCol, rEndCol) )
+ --rEndRow;
+}
+
+void ScTable::FindAreaPos( USHORT& rCol, USHORT& rRow, short nMovX, short nMovY )
+{
+ if (nMovX)
+ {
+ short nNewCol = (short) rCol;
+ BOOL bThere = aCol[nNewCol].HasVisibleDataAt(rRow);
+ BOOL bFnd;
+ if (bThere)
+ {
+ do
+ {
+ nNewCol += nMovX;
+ bFnd = (nNewCol>=0 && nNewCol<=MAXCOL) ? aCol[nNewCol].HasVisibleDataAt(rRow) : FALSE;
+ }
+ while (bFnd);
+ nNewCol -= nMovX;
+
+ if (nNewCol == (short)rCol)
+ bThere = FALSE;
+ }
+
+ if (!bThere)
+ {
+ do
+ {
+ nNewCol += nMovX;
+ bFnd = (nNewCol>=0 && nNewCol<=MAXCOL) ? aCol[nNewCol].HasVisibleDataAt(rRow) : TRUE;
+ }
+ while (!bFnd);
+ }
+
+ if (nNewCol<0) nNewCol=0;
+ if (nNewCol>MAXCOL) nNewCol=MAXCOL;
+ rCol = (USHORT) nNewCol;
+ }
+
+ if (nMovY)
+ aCol[rCol].FindDataAreaPos(rRow,nMovY);
+}
+
+BOOL ScTable::ValidNextPos( USHORT nCol, USHORT nRow, const ScMarkData& rMark,
+ BOOL bMarked, BOOL bUnprotected )
+{
+ if (nCol > MAXCOL || nRow > MAXROW)
+ return FALSE;
+
+ if (bMarked && !rMark.IsCellMarked(nCol,nRow))
+ return FALSE;
+
+ if (bUnprotected && ((const ScProtectionAttr*)
+ GetAttr(nCol,nRow,ATTR_PROTECTION))->GetProtection())
+ return FALSE;
+
+ if (bMarked || bUnprotected) //! auch sonst ???
+ {
+ // #53697# ausgeblendete muessen uebersprungen werden, weil der Cursor sonst
+ // auf der naechsten Zelle landet, auch wenn die geschuetzt/nicht markiert ist.
+ //! per Extra-Parameter steuern, nur fuer Cursor-Bewegung ???
+
+ if ( pRowFlags && ( pRowFlags[nRow] & CR_HIDDEN ) )
+ return FALSE;
+ if ( pColFlags && ( pColFlags[nCol] & CR_HIDDEN ) )
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void ScTable::GetNextPos( USHORT& rCol, USHORT& rRow, short nMovX, short nMovY,
+ BOOL bMarked, BOOL bUnprotected, const ScMarkData& rMark )
+{
+ if (bUnprotected && !IsProtected()) // Tabelle ueberhaupt geschuetzt?
+ bUnprotected = FALSE;
+
+ USHORT nWrap = 0;
+ short nCol = rCol;
+ short nRow = rRow;
+
+ nCol += nMovX;
+ nRow += nMovY;
+
+ DBG_ASSERT( !nMovY || !bUnprotected,
+ "GetNextPos mit bUnprotected horizontal nicht implementiert" );
+
+ if ( nMovY && bMarked )
+ {
+ BOOL bUp = ( nMovY < 0 );
+ nRow = rMark.GetNextMarked( nCol, nRow, bUp );
+ while ( VALIDROW(nRow) && pRowFlags && (pRowFlags[nRow] & CR_HIDDEN) )
+ {
+ // #53697# ausgeblendete ueberspringen (s.o.)
+ nRow += nMovY;
+ nRow = rMark.GetNextMarked( nCol, nRow, bUp );
+ }
+
+ while ( nRow < 0 || nRow > MAXROW )
+ {
+ nCol += nMovY;
+ while ( VALIDCOL(nCol) && pColFlags && (pColFlags[nCol] & CR_HIDDEN) )
+ nCol += nMovY; // #53697# ausgeblendete ueberspringen (s.o.)
+ if (nCol < 0)
+ {
+ nCol = MAXCOL;
+ if (++nWrap >= 2)
+ return;
+ }
+ else if (nCol > MAXCOL)
+ {
+ nCol = 0;
+ if (++nWrap >= 2)
+ return;
+ }
+ if (nRow < 0)
+ nRow = MAXROW;
+ else if (nRow > MAXROW)
+ nRow = 0;
+ nRow = rMark.GetNextMarked( nCol, nRow, bUp );
+ while ( VALIDROW(nRow) && pRowFlags && (pRowFlags[nRow] & CR_HIDDEN) )
+ {
+ // #53697# ausgeblendete ueberspringen (s.o.)
+ nRow += nMovY;
+ nRow = rMark.GetNextMarked( nCol, nRow, bUp );
+ }
+ }
+ }
+
+ if ( nMovX && ( bMarked || bUnprotected ) )
+ {
+ // initiales Weiterzaehlen wrappen:
+ if (nCol<0)
+ {
+ nCol = MAXCOL;
+ --nRow;
+ if (nRow<0)
+ nRow = MAXROW;
+ }
+ if (nCol>MAXCOL)
+ {
+ nCol = 0;
+ ++nRow;
+ if (nRow>MAXROW)
+ nRow = 0;
+ }
+
+ if ( !ValidNextPos(nCol, nRow, rMark, bMarked, bUnprotected) )
+ {
+ short* pNextRows = new short[MAXCOL+1];
+ USHORT i;
+
+ if ( nMovX > 0 ) // vorwaerts
+ {
+ for (i=0; i<=MAXCOL; i++)
+ pNextRows[i] = (i<nCol) ? (nRow+1) : nRow;
+ do
+ {
+ short nNextRow = pNextRows[nCol] + 1;
+ if ( bMarked )
+ nNextRow = rMark.GetNextMarked( nCol, nNextRow, FALSE );
+ if ( bUnprotected )
+ nNextRow = aCol[nCol].GetNextUnprotected( nNextRow, FALSE );
+ pNextRows[nCol] = nNextRow;
+
+ short nMinRow = MAXROW+1;
+ for (i=0; i<=MAXCOL; i++)
+ if (pNextRows[i] < nMinRow) // bei gleichen den linken
+ {
+ nMinRow = pNextRows[i];
+ nCol = i;
+ }
+ nRow = nMinRow;
+
+ if ( nRow > MAXROW )
+ {
+ if (++nWrap >= 2) break; // ungueltigen Wert behalten
+ nCol = nRow = 0;
+ for (i=0; i<=MAXCOL; i++)
+ pNextRows[i] = 0; // alles ganz von vorne
+ }
+ }
+ while ( !ValidNextPos(nCol, nRow, rMark, bMarked, bUnprotected) );
+ }
+ else // rueckwaerts
+ {
+ for (i=0; i<=MAXCOL; i++)
+ pNextRows[i] = (i>nCol) ? (nRow-1) : nRow;
+ do
+ {
+ short nNextRow = pNextRows[nCol] - 1;
+ if ( bMarked )
+ nNextRow = rMark.GetNextMarked( nCol, nNextRow, TRUE );
+ if ( bUnprotected )
+ nNextRow = aCol[nCol].GetNextUnprotected( nNextRow, TRUE );
+ pNextRows[nCol] = nNextRow;
+
+ short nMaxRow = -1;
+ for (i=0; i<=MAXCOL; i++)
+ if (pNextRows[i] >= nMaxRow) // bei gleichen den rechten
+ {
+ nMaxRow = pNextRows[i];
+ nCol = i;
+ }
+ nRow = nMaxRow;
+
+ if ( nRow < 0 )
+ {
+ if (++nWrap >= 2) break; // ungueltigen Wert behalten
+ nCol = MAXCOL;
+ nRow = MAXROW;
+ for (i=0; i<=MAXCOL; i++)
+ pNextRows[i] = MAXROW; // alles ganz von vorne
+ }
+ }
+ while ( !ValidNextPos(nCol, nRow, rMark, bMarked, bUnprotected) );
+ }
+
+ delete[] pNextRows;
+ }
+ }
+
+ // ungueltige Werte kommen z.b. bei Tab heraus,
+ // wenn nicht markiert und nicht geschuetzt ist (linker / rechter Rand),
+ // dann Werte unveraendert lassen
+
+ if (VALIDCOLROW(nCol,nRow))
+ {
+ rCol = nCol;
+ rRow = nRow;
+ }
+}
+
+BOOL ScTable::GetNextMarkedCell( USHORT& rCol, USHORT& rRow, const ScMarkData& rMark )
+{
+ const ScMarkArray* pMarkArray = rMark.GetArray();
+ DBG_ASSERT(pMarkArray,"GetNextMarkedCell ohne MarkArray");
+ if ( !pMarkArray )
+ return FALSE;
+
+ ++rRow; // naechste Zelle ist gesucht
+
+ while ( rCol <= MAXCOL )
+ {
+ const ScMarkArray& rArray = pMarkArray[rCol];
+ while ( rRow <= MAXROW )
+ {
+ USHORT nStart = (USHORT) rArray.GetNextMarked( (short) rRow, FALSE );
+ if ( nStart <= MAXROW )
+ {
+ USHORT nEnd = rArray.GetMarkEnd( nStart, FALSE );
+ ScColumnIterator aColIter( &aCol[rCol], nStart, nEnd );
+ USHORT nCellRow;
+ ScBaseCell* pCell = NULL;
+ while ( aColIter.Next( nCellRow, pCell ) )
+ {
+ if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE )
+ {
+ rRow = nCellRow;
+ return TRUE; // Zelle gefunden
+ }
+ }
+ rRow = nEnd + 1; // naechsten markierten Bereich suchen
+ }
+ else
+ rRow = MAXROW + 1; // Ende der Spalte
+ }
+ rRow = 0;
+ ++rCol; // naechste Spalte testen
+ }
+
+ return FALSE; // alle Spalten durch
+}
+
+void ScTable::UpdateReference( UpdateRefMode eUpdateRefMode, USHORT nCol1, USHORT nRow1, USHORT nTab1,
+ USHORT nCol2, USHORT nRow2, USHORT nTab2, short nDx, short nDy, short nDz,
+ ScDocument* pUndoDoc )
+{
+ USHORT i;
+ USHORT iMax;
+ if ( eUpdateRefMode == URM_COPY )
+ {
+ i = nCol1;
+ iMax = nCol2;
+ }
+ else
+ {
+ i = 0;
+ iMax = MAXCOL;
+ }
+ for ( ; i<=iMax; i++)
+ aCol[i].UpdateReference( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2,
+ nDx, nDy, nDz, pUndoDoc );
+
+ // Drawing Layer - nCol1 etc werden veraendert!
+
+ if ( nTab >= nTab1 && nTab <= nTab2 && nDz == 0 ) // nur wenn innerhalb der Tabelle
+ {
+ ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
+ if ( eUpdateRefMode != URM_COPY && pDrawLayer )
+ {
+ if ( eUpdateRefMode == URM_MOVE )
+ { // Quellbereich
+ nCol1 -= nDx;
+ nRow1 -= nDy;
+ nCol2 -= nDx;
+ nRow2 -= nDy;
+ }
+ pDrawLayer->MoveArea( nTab, nCol1,nRow1, nCol2,nRow2, nDx,nDy,
+ (eUpdateRefMode == URM_INSDEL) );
+ }
+
+ {
+ // war ScStyleSheetPool::UpdateReference()
+
+ USHORT nSTab,nETab,nSCol,nSRow,nECol,nERow;
+ BOOL bRecalcPages = FALSE;
+
+ if ( pPrintRanges && nPrintRangeCount )
+ for ( i=0; i<nPrintRangeCount; i++ )
+ {
+ nSTab = nETab = pPrintRanges[i].aStart.Tab();
+ nSCol = pPrintRanges[i].aStart.Col();
+ nSRow = pPrintRanges[i].aStart.Row();
+ nECol = pPrintRanges[i].aEnd.Col();
+ nERow = pPrintRanges[i].aEnd.Row();
+
+ if ( ScRefUpdate::Update( pDocument, eUpdateRefMode,
+ nCol1,nRow1,nTab1, nCol2,nRow2,nTab2,
+ nDx,nDy,nDz,
+ nSCol,nSRow,nSTab, nECol,nERow,nETab ) )
+ {
+ pPrintRanges[i] = ScRange( nSCol, nSRow, nSTab, nECol, nERow, nSTab );
+ bRecalcPages = TRUE;
+ }
+ }
+
+ if ( pRepeatColRange )
+ {
+ nSTab = nETab = pRepeatColRange->aStart.Tab();
+ nSCol = pRepeatColRange->aStart.Col();
+ nSRow = pRepeatColRange->aStart.Row();
+ nECol = pRepeatColRange->aEnd.Col();
+ nERow = pRepeatColRange->aEnd.Row();
+
+ if ( ScRefUpdate::Update( pDocument, eUpdateRefMode,
+ nCol1,nRow1,nTab1, nCol2,nRow2,nTab2,
+ nDx,nDy,nDz,
+ nSCol,nSRow,nSTab, nECol,nERow,nETab ) )
+ {
+ *pRepeatColRange = ScRange( nSCol, nSRow, nSTab, nECol, nERow, nSTab );
+ bRecalcPages = TRUE;
+ nRepeatStartX = nSCol; // fuer UpdatePageBreaks
+ nRepeatEndX = nECol;
+ }
+ }
+
+ if ( pRepeatRowRange )
+ {
+ nSTab = nETab = pRepeatRowRange->aStart.Tab();
+ nSCol = pRepeatRowRange->aStart.Col();
+ nSRow = pRepeatRowRange->aStart.Row();
+ nECol = pRepeatRowRange->aEnd.Col();
+ nERow = pRepeatRowRange->aEnd.Row();
+
+ if ( ScRefUpdate::Update( pDocument, eUpdateRefMode,
+ nCol1,nRow1,nTab1, nCol2,nRow2,nTab2,
+ nDx,nDy,nDz,
+ nSCol,nSRow,nSTab, nECol,nERow,nETab ) )
+ {
+ *pRepeatRowRange = ScRange( nSCol, nSRow, nSTab, nECol, nERow, nSTab );
+ bRecalcPages = TRUE;
+ nRepeatStartY = nSRow; // fuer UpdatePageBreaks
+ nRepeatEndY = nERow;
+ }
+ }
+
+ // Umbrueche updaten ist bei mehreren Druckbereichen nicht noetig
+ if ( bRecalcPages && GetPrintRangeCount() <= 1 )
+ {
+ UpdatePageBreaks(NULL);
+
+ SfxObjectShell* pDocSh = pDocument->GetDocumentShell();
+ if (pDocSh)
+ pDocSh->Broadcast( ScPaintHint(
+ ScRange(0,0,nTab,MAXCOL,MAXROW,nTab),
+ PAINT_GRID ) );
+ }
+ }
+ }
+}
+
+void ScTable::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
+ ScDocument* pUndoDoc )
+{
+ for ( USHORT i=0; i<=MAXCOL; i++ )
+ aCol[i].UpdateTranspose( rSource, rDest, pUndoDoc );
+}
+
+void ScTable::UpdateGrow( const ScRange& rArea, USHORT nGrowX, USHORT nGrowY )
+{
+ for ( USHORT i=0; i<=MAXCOL; i++ )
+ aCol[i].UpdateGrow( rArea, nGrowX, nGrowY );
+}
+
+void ScTable::UpdateInsertTab(USHORT nTable)
+{
+ if (nTab >= nTable) nTab++;
+ for (USHORT i=0; i <= MAXCOL; i++) aCol[i].UpdateInsertTab(nTable);
+}
+
+void ScTable::UpdateInsertTabOnlyCells(USHORT nTable)
+{
+ for (USHORT i=0; i <= MAXCOL; i++) aCol[i].UpdateInsertTabOnlyCells(nTable);
+}
+
+void ScTable::UpdateDeleteTab( USHORT nTable, BOOL bIsMove, ScTable* pRefUndo )
+{
+ if (nTab > nTable) nTab--;
+
+ USHORT i;
+ if (pRefUndo)
+ for (i=0; i <= MAXCOL; i++) aCol[i].UpdateDeleteTab(nTable, bIsMove, &pRefUndo->aCol[i]);
+ else
+ for (i=0; i <= MAXCOL; i++) aCol[i].UpdateDeleteTab(nTable, bIsMove, NULL);
+}
+
+void ScTable::UpdateMoveTab( USHORT nOldPos, USHORT nNewPos, USHORT nTabNo,
+ ScProgress& rProgress )
+{
+ nTab = nTabNo;
+ for ( USHORT i=0; i <= MAXCOL; i++ )
+ {
+ aCol[i].UpdateMoveTab( nOldPos, nNewPos, nTabNo );
+ rProgress.SetState( rProgress.GetState() + aCol[i].GetCodeCount() );
+ }
+}
+
+void ScTable::UpdateCompile( BOOL bForceIfNameInUse )
+{
+ for (USHORT i=0; i <= MAXCOL; i++)
+ {
+ aCol[i].UpdateCompile( bForceIfNameInUse );
+ }
+}
+
+void ScTable::SetTabNo(USHORT nNewTab)
+{
+ nTab = nNewTab;
+ for (USHORT i=0; i <= MAXCOL; i++) aCol[i].SetTabNo(nNewTab);
+}
+
+BOOL ScTable::IsRangeNameInUse(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2,
+ USHORT nIndex) const
+{
+ BOOL bInUse = FALSE;
+ for (USHORT i = nCol1; !bInUse && (i <= nCol2) && (i <= MAXCOL); i++)
+ bInUse = aCol[i].IsRangeNameInUse(nRow1, nRow2, nIndex);
+ return bInUse;
+}
+
+void ScTable::ReplaceRangeNamesInUse(USHORT nCol1, USHORT nRow1,
+ USHORT nCol2, USHORT nRow2,
+ const ScIndexMap& rMap )
+{
+ for (USHORT i = nCol1; i <= nCol2 && (i <= MAXCOL); i++)
+ {
+ aCol[i].ReplaceRangeNamesInUse( nRow1, nRow2, rMap );
+ }
+}
+
+void ScTable::ExtendPrintArea( OutputDevice* pDev,
+ USHORT nStartCol, USHORT nStartRow, USHORT& rEndCol, USHORT nEndRow )
+{
+ if ( !pColFlags || !pRowFlags )
+ {
+ DBG_ERROR("keine ColInfo oder RowInfo in ExtendPrintArea");
+ return;
+ }
+
+ Point aPix1000 = pDev->LogicToPixel( Point(1000,1000), MAP_TWIP );
+ double nPPTX = aPix1000.X() / 1000.0;
+ double nPPTY = aPix1000.Y() / 1000.0;
+
+ BOOL bEmpty[MAXCOL+1];
+ for (USHORT i=0; i<=MAXCOL; i++)
+ bEmpty[i] = ( aCol[i].GetCellCount() == 0 );
+
+ USHORT nIndex;
+ USHORT nPrintCol = rEndCol;
+ for (USHORT nRow = nStartRow; nRow<=nEndRow; nRow++)
+ {
+ if ( ( pRowFlags[nRow] & CR_HIDDEN ) == 0 )
+ {
+ USHORT nDataCol = rEndCol;
+ while (nDataCol > 0 && ( bEmpty[nDataCol] || !aCol[nDataCol].Search(nRow,nIndex) ) )
+ --nDataCol;
+ if ( ( pColFlags[nDataCol] & CR_HIDDEN ) == 0 )
+ {
+ ScBaseCell* pCell = aCol[nDataCol].GetCell(nRow);
+ if (pCell)
+ {
+ CellType eType = pCell->GetCellType();
+ if (eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT
+ || (eType == CELLTYPE_FORMULA && !((ScFormulaCell*)pCell)->IsValue()) )
+ {
+ BOOL bFormula = FALSE; //! uebergeben
+ long nPixel = pCell->GetTextWidth();
+
+ // Breite bereits im Idle-Handler berechnet?
+ if ( TEXTWIDTH_DIRTY == nPixel )
+ {
+ ScNeededSizeOptions aOptions;
+ aOptions.bTotalSize = TRUE;
+ aOptions.bFormula = bFormula;
+ aOptions.bSkipMerged = FALSE;
+
+ Fraction aZoom(1,1);
+ nPixel = aCol[nDataCol].GetNeededSize( nRow,
+ pDev,nPPTX,nPPTY,aZoom,aZoom,
+ TRUE, aOptions );
+ pCell->SetTextWidth( (USHORT)nPixel );
+ }
+
+ long nTwips = (long) (nPixel / nPPTX);
+ long nDocW = GetColWidth( nDataCol );
+ USHORT nCol = nDataCol;
+ while (nTwips > nDocW && nCol < MAXCOL)
+ {
+ ++nCol;
+ nDocW += GetColWidth( nCol );
+ }
+ if (nCol>nPrintCol)
+ nPrintCol = nCol;
+ }
+ }
+ }
+ }
+ }
+ rEndCol = nPrintCol;
+}
+
+void ScTable::DoColResize( USHORT nCol1, USHORT nCol2, USHORT nAdd )
+{
+ for (USHORT nCol=nCol1; nCol<=nCol2; nCol++)
+ aCol[nCol].Resize(aCol[nCol].GetCellCount() + nAdd);
+}
+
+#define SET_PRINTRANGE( p1, p2 ) \
+ if ( (p2) ) \
+ { \
+ if ( (p1) ) \
+ *(p1) = *(p2); \
+ else \
+ (p1) = new ScRange( *(p2) ); \
+ } \
+ else \
+ DELETEZ( (p1) )
+
+void ScTable::SetRepeatColRange( const ScRange* pNew )
+{
+ SET_PRINTRANGE( pRepeatColRange, pNew );
+}
+
+void ScTable::SetRepeatRowRange( const ScRange* pNew )
+{
+ SET_PRINTRANGE( pRepeatRowRange, pNew );
+}
+
+// #42845# zeroptimiert
+#if defined(WIN) && defined(MSC)
+#pragma optimize("",off)
+#endif
+void ScTable::SetPrintRangeCount( USHORT nNew )
+{
+ ScRange* pNewRanges;
+ if (nNew)
+ pNewRanges = new ScRange[nNew];
+ else
+ pNewRanges = NULL;
+
+ if ( pPrintRanges && nNew >= nPrintRangeCount ) // Anzahl vergroessert?
+ for ( USHORT i=0; i<nPrintRangeCount; i++ ) // (fuer "Hinzufuegen")
+ pNewRanges[i] = pPrintRanges[i]; // alte Ranges kopieren
+
+ delete[] pPrintRanges;
+ pPrintRanges = pNewRanges;
+ nPrintRangeCount = nNew;
+}
+#if defined(WIN) && defined(MSC)
+#pragma optimize("",on)
+#endif
+
+void ScTable::SetPrintRange( USHORT nPos, const ScRange& rNew )
+{
+ if (nPos < nPrintRangeCount && pPrintRanges)
+ pPrintRanges[nPos] = rNew;
+ else
+ DBG_ERROR("SetPrintRange falsch");
+}
+
+const ScRange* ScTable::GetPrintRange(USHORT nPos) const
+{
+ if (nPos < nPrintRangeCount && pPrintRanges)
+ return pPrintRanges+nPos;
+ else
+ return NULL;
+}
+
+void ScTable::FillPrintSaver( ScPrintSaverTab& rSaveTab ) const
+{
+ rSaveTab.SetAreas( nPrintRangeCount, pPrintRanges );
+ rSaveTab.SetRepeat( pRepeatColRange, pRepeatRowRange );
+}
+
+void ScTable::RestorePrintRanges( const ScPrintSaverTab& rSaveTab )
+{
+ USHORT nNewCount = rSaveTab.GetPrintCount();
+ const ScRange* pNewRanges = rSaveTab.GetPrintRanges();
+
+ SetPrintRangeCount( nNewCount );
+ for (USHORT i=0; i<nNewCount; i++ )
+ SetPrintRange( i, pNewRanges[i] );
+
+ SetRepeatColRange( rSaveTab.GetRepeatCol() );
+ SetRepeatRowRange( rSaveTab.GetRepeatRow() );
+
+ UpdatePageBreaks(NULL);
+}
+
+
+
+
+
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
new file mode 100644
index 000000000000..2257e7d99b1a
--- /dev/null
+++ b/sc/source/core/data/table2.cxx
@@ -0,0 +1,3147 @@
+/*************************************************************************
+ *
+ * $RCSfile: table2.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+//------------------------------------------------------------------------
+
+// TOOLS
+#define _BIGINT_HXX
+#define _SFXMULTISEL_HXX
+#define _STACK_HXX
+#define _QUEUE_HXX
+#define _DYNARR_HXX
+#define _TREELIST_HXX
+#define _CACHESTR_HXX
+#define _NEW_HXX
+#define _DYNARY_HXX
+#define _CACHESTR_HXX
+#define _SV_MULTISEL_HXX
+
+//SV
+#define _CONFIG_HXX
+#define _CURSOR_HXX
+#define _FONTDLG_HXX
+#define _PRVWIN_HXX
+#define _HELP_HXX
+#define _SPIN_HXX
+#define _FILDLG_HXX
+#define _COLDLG_HXX
+#define _SOUND_HXX
+#define _MENUBTN_HXX
+#define _CLIP_HXX //*
+#define _CONFIG_HXX
+#define _CURSOR_HXX
+#define _FONTDLG_HXX
+#define _PRVWIN_HXX
+//#define _COLOR_HXX
+//#define _PAL_HXX
+//#define _BITMAP_HXX
+//#define _GDIOBJ_HXX
+//#define _POINTR_HXX
+//#define _ICON_HXX
+//#define _IMAGE_HXX
+//#define _KEYCOD_HXX
+//#define _EVENT_HXX
+#define _HELP_HXX
+//#define _APP_HXX
+//#define _MDIAPP_HXX
+//#define _TIMER_HXX
+//#define _METRIC_HXX
+//#define _REGION_HXX
+//#define _OUTDEV_HXX
+//#define _SYSTEM_HXX
+//#define _VIRDEV_HXX
+//#define _JOBSET_HXX
+//#define _PRINT_HXX
+//#define _WINDOW_HXX
+//#define _SYSWIN_HXX
+//#define _WRKWIN_HXX
+#define _MDIWIN_HXX
+//#define _FLOATWIN_HXX
+//#define _DOCKWIN_HXX
+//#define _CTRL_HXX
+//#define _SCRBAR_HXX
+//#define _BUTTON_HXX
+//#define _IMAGEBTN_HXX
+//#define _FIXED_HXX
+//#define _GROUP_HXX
+//#define _EDIT_HXX
+//#define _COMBOBOX_HXX
+//#define _LSTBOX_HXX
+//#define _SELENG_HXX ***
+//#define _SPLIT_HXX
+#define _SPIN_HXX
+//#define _FIELD_HXX
+//#define _MOREBTN_HXX ***
+//#define _TOOLBOX_HXX
+//#define _STATUS_HXX ***
+//#define _DIALOG_HXX
+//#define _MSGBOX_HXX
+//#define _SYSDLG_HXX
+#define _FILDLG_HXX
+//#define _PRNDLG_HXX
+#define _COLDLG_HXX
+//#define _TABDLG_HXX
+//#define _MENU_HXX
+//#define _GDIMTF_HXX
+//#define _POLY_HXX
+//#define _ACCEL_HXX
+//#define _GRAPH_HXX
+#define _SOUND_HXX
+
+
+//svtools
+
+#define _SCRWIN_HXX
+#define _RULER_HXX
+//#define _TABBAR_HXX
+//#define _VALUESET_HXX
+#define _STDMENU_HXX
+//#define _STDCTRL_HXX
+//#define _CTRLBOX_HXX
+#define _CTRLTOOL_HXX
+#define _EXTATTR_HXX
+#define _FRM3D_HXX
+#define _EXTATTR_HXX
+//#define _SVTREELIST_HXX ***
+#define _FILTER_HXX
+//#define _SVLBOXITM_HXX ***
+//#define _SVTREEBOX_HXX ***
+#define _SVICNVW_HXX
+#define _SVTABBX_HXX
+#define _SCRWIN_HXX
+#define _RULER_HXX
+#define _STDMENU_HXX
+#define _CTRLTOOL_HXX
+#define _EXTATTR_HXX
+#define _FRM3D_HXX
+#define _EXTATTR_HXX
+#define _FILTER_HXX
+#define _SVICNVW_HXX
+#define _SVTABBX_HXX
+
+//sfxcore.hxx
+#define _SFXGENLINK_HXX
+#define _SFXHINTPOST_HXX
+#define _SFXDOCINF_HXX
+#define _SFXLINKHDL_HXX
+
+//sfxsh.hxx
+#define _SFXMACRO_HXX
+
+// SFX
+#define _SFX_SAVEOPT_HXX
+#define _SFXPRNMON_HXX
+#define _INTRO_HXX
+#define _SFXMSGDESCR_HXX
+#define _SFXMSGPOOL_HXX
+#define _SFXFILEDLG_HXX
+#define _PASSWD_HXX
+#define _SFXTBXCTRL_HXX
+#define _SFXSTBITEM_HXX
+#define _SFXMNUITEM_HXX
+#define _SFXIMGMGR_HXX
+#define _SFXTBXMGR_HXX
+#define _SFXSTBMGR_HXX
+#define _SFX_MINFITEM_HXX
+#define _SFXEVENT_HXX
+
+//sfxdoc.hxx
+//#define _SFX_OBJSH_HXX
+//#define _SFX_CLIENTSH_HXX
+//#define _SFXDOCINF_HXX
+//#define _SFX_OBJFAC_HXX
+#define _SFX_DOCFILT_HXX
+//#define _SFXDOCFILE_HXX ***
+//define _VIEWFAC_HXX
+//#define _SFXVIEWFRM_HXX
+//#define _SFXVIEWSH_HXX
+//#define _MDIFRM_HXX ***
+#define _SFX_IPFRM_HXX
+//#define _SFX_INTERNO_HXX
+
+//sfxdlg.hxx
+//#define _SFXTABDLG_HXX
+//#define _BASEDLGS_HXX ***
+#define _SFX_DINFDLG_HXX
+#define _SFXDINFEDT_HXX
+#define _SFX_MGETEMPL_HXX
+#define _SFX_TPLPITEM_HXX
+//#define _SFX_STYLEDLG_HXX
+#define _NEWSTYLE_HXX
+//#define _SFXDOCTEMPL_HXX ***
+//#define _SFXDOCTDLG_HXX ***
+//#define _SFX_TEMPLDLG_HXX ***
+//#define _SFXNEW_HXX ***
+#define _SFXDOCMAN_HXX
+//#define _SFXDOCKWIN_HXX
+
+//xout.hxx
+//#define _XENUM_HXX
+//#define _XPOLY_HXX
+//#define _XATTR_HXX
+//#define _XOUTX_HXX
+//#define _XPOOL_HXX
+//#define _XTABLE_HXX
+
+//svdraw.hxx
+#define _SDR_NOITEMS
+#define _SDR_NOTOUCH
+#define _SDR_NOTRANSFORM
+#define _SDR_NOOBJECTS
+//#define _SDR_NOVIEWS
+
+//#define SI_NOITEMS //*
+//#define SI_NODRW //*
+#define _SI_NOSBXCONTROLS
+//#define _VCATTR_HXX //*
+#define _VCONT_HXX
+//#define _VCSBX_HXX //*
+#define _SI_NOOTHERFORMS
+#define _VCTRLS_HXX
+//#define _VCDRWOBJ_HXX //*
+#define _SI_NOCONTROL
+#define _SETBRW_HXX
+#define _VCBRW_HXX
+#define _SI_NOSBXCONTROLS
+//#define _SIDLL_HXX //***
+
+#define _SVX_DAILDLL_HXX
+#define _SVX_HYPHEN_HXX
+#define _SVX_IMPGRF_HXX
+#define _SVX_OPTITEMS_HXX
+#define _SVX_OPTGERL_HXX
+#define _SVX_OPTSAVE_HXX
+#define _SVX_OPTSPELL_HXX
+#define _SVX_OPTPATH_HXX
+#define _SVX_OPTLINGU_HXX
+#define _SVX_RULER_HXX
+#define _SVX_RULRITEM_HXX
+#define _SVX_SPLWRAP_HXX
+#define _SVX_SPLDLG_HXX
+#define _SVX_THESDLG_HXX
+
+//inet
+#define _INETINDP_HXX
+#define _INETIMP_HXX
+#define _INETWRAP_HXX
+#define _INETKEEP_HXX
+#define _PLUGMGR_HXX
+//#define _URLOBJ_HXX
+
+#define SFX_NOCLOOKS
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <svx/boxitem.hxx>
+#include <tools/urlobj.hxx>
+#include <svtools/poolcach.hxx>
+#include <unotools/charclass.hxx>
+#include <math.h>
+
+#include "patattr.hxx"
+#include "docpool.hxx"
+#include "cell.hxx"
+#include "document.hxx"
+#include "drwlayer.hxx"
+#include "olinetab.hxx"
+#include "rechead.hxx"
+#include "stlpool.hxx"
+#include "attarray.hxx" // Iterator
+#include "markdata.hxx"
+#include "progress.hxx"
+#include "dociter.hxx"
+#include "conditio.hxx"
+#include "chartlis.hxx"
+#include "globstr.hrc"
+
+// STATIC DATA -----------------------------------------------------------
+
+void lcl_LoadRange( SvStream& rStream, ScRange** ppRange );
+void lcl_SaveRange( SvStream& rStream, ScRange* pRange );
+
+
+
+BOOL ScTable::SetOutlineTable( const ScOutlineTable* pNewOutline )
+{
+ USHORT nOldSizeX = 0;
+ USHORT nOldSizeY = 0;
+ USHORT nNewSizeX = 0;
+ USHORT nNewSizeY = 0;
+
+ if (pOutlineTable)
+ {
+ nOldSizeX = pOutlineTable->GetColArray()->GetDepth();
+ nOldSizeY = pOutlineTable->GetRowArray()->GetDepth();
+ delete pOutlineTable;
+ }
+
+ if (pNewOutline)
+ {
+ pOutlineTable = new ScOutlineTable( *pNewOutline );
+ nNewSizeX = pOutlineTable->GetColArray()->GetDepth();
+ nNewSizeY = pOutlineTable->GetRowArray()->GetDepth();
+ }
+ else
+ pOutlineTable = NULL;
+
+ return ( nNewSizeX != nOldSizeX || nNewSizeY != nOldSizeY ); // Groesse geaendert ?
+}
+
+
+void ScTable::StartOutlineTable()
+{
+ if (!pOutlineTable)
+ pOutlineTable = new ScOutlineTable;
+}
+
+
+BOOL ScTable::TestInsertRow( USHORT nStartCol, USHORT nEndCol, USHORT nSize )
+{
+ BOOL bTest = TRUE;
+
+ if ( nStartCol==0 && nEndCol==MAXCOL && pOutlineTable )
+ bTest = pOutlineTable->TestInsertRow(nSize);
+
+ for (USHORT i=nStartCol; (i<=nEndCol) && bTest; i++)
+ bTest = aCol[i].TestInsertRow( nSize );
+
+ return bTest;
+}
+
+
+void ScTable::InsertRow( USHORT nStartCol, USHORT nEndCol, USHORT nStartRow, USHORT nSize )
+{
+ USHORT i;
+ nRecalcLvl++;
+ if (nStartCol==0 && nEndCol==MAXCOL)
+ {
+ if (pRowHeight && pRowFlags)
+ {
+ for (i=MAXROW; i>=nStartRow+nSize; i--)
+ {
+ pRowHeight[i] = pRowHeight[i-nSize];
+ pRowFlags[i] = pRowFlags[i-nSize];
+ }
+
+ // #67451# copy row height from row above
+ USHORT nSourceRow = ( nStartRow > 0 ) ? ( nStartRow - 1 ) : 0;
+ BYTE nNewFlags = pRowFlags[nSourceRow] & CR_MANUALSIZE;
+ USHORT nNewHeight = pRowHeight[nSourceRow];
+ for (i=nStartRow; i<nStartRow+nSize; i++)
+ {
+ pRowHeight[i] = nNewHeight;
+ pRowFlags[i] = nNewFlags;
+ }
+ }
+ if (pOutlineTable)
+ pOutlineTable->InsertRow( nStartRow, nSize );
+ }
+
+ for (i=nStartCol; i<=nEndCol; i++)
+ aCol[i].InsertRow( nStartRow, nSize );
+ if( !--nRecalcLvl )
+ SetDrawPageSize();
+}
+
+
+void ScTable::DeleteRow( USHORT nStartCol, USHORT nEndCol, USHORT nStartRow, USHORT nSize,
+ BOOL* pUndoOutline )
+{
+ USHORT i;
+ nRecalcLvl++;
+ if (nStartCol==0 && nEndCol==MAXCOL)
+ {
+ if (pRowHeight && pRowFlags)
+ for (i=nStartRow; i+nSize<=MAXROW; i++)
+ {
+ pRowHeight[i] = pRowHeight[i+nSize];
+ pRowFlags[i] = pRowFlags[i+nSize];
+ }
+ if (pOutlineTable)
+ if (pOutlineTable->DeleteRow( nStartRow, nSize ))
+ if (pUndoOutline)
+ *pUndoOutline = TRUE;
+ }
+
+ for (i=nStartCol; i<=nEndCol; i++)
+ aCol[i].DeleteRow( nStartRow, nSize );
+ if( !--nRecalcLvl )
+ SetDrawPageSize();
+}
+
+
+BOOL ScTable::TestInsertCol( USHORT nStartRow, USHORT nEndRow, USHORT nSize )
+{
+ BOOL bTest = TRUE;
+
+ if ( nStartRow==0 && nEndRow==MAXROW && pOutlineTable )
+ bTest = pOutlineTable->TestInsertCol(nSize);
+
+ if ( nSize > MAXCOL )
+ bTest = FALSE;
+
+ for (USHORT i=MAXCOL; (i+nSize>MAXCOL) && bTest; i--)
+ bTest = aCol[i].TestInsertCol(nStartRow, nEndRow);
+
+ return bTest;
+}
+
+
+void ScTable::InsertCol( USHORT nStartCol, USHORT nStartRow, USHORT nEndRow, USHORT nSize )
+{
+ USHORT i;
+ nRecalcLvl++;
+ if (nStartRow==0 && nEndRow==MAXROW)
+ {
+ if (pColWidth && pColFlags)
+ for (i=MAXCOL; i>=nStartCol+nSize; i--)
+ {
+ pColWidth[i] = pColWidth[i-nSize];
+ pColFlags[i] = pColFlags[i-nSize];
+ }
+ if (pOutlineTable)
+ pOutlineTable->InsertCol( nStartCol, nSize );
+ }
+
+
+ if ((nStartRow == 0) && (nEndRow == MAXROW))
+ {
+ for (i=0; i < nSize; i++)
+ for (USHORT nCol = MAXCOL; nCol > nStartCol; nCol--)
+ aCol[nCol].SwapCol(aCol[nCol-1]);
+ }
+ else
+ {
+ for (i=0; i+nSize+nStartCol <= MAXCOL; i++)
+ aCol[MAXCOL - nSize - i].MoveTo(nStartRow, nEndRow, aCol[MAXCOL - i]);
+ }
+
+ if (nStartCol>0) // alte Attribute kopieren
+ for (i=0; i<nSize; i++)
+ {
+ aCol[nStartCol-1].CopyToColumn( nStartRow, nEndRow, IDF_ATTRIB,
+ FALSE, aCol[nStartCol+i] );
+ aCol[nStartCol+i].RemoveFlags( nStartRow, nEndRow,
+ SC_MF_HOR | SC_MF_VER | SC_MF_AUTO );
+ }
+ if( !--nRecalcLvl )
+ SetDrawPageSize();
+}
+
+
+void ScTable::DeleteCol( USHORT nStartCol, USHORT nStartRow, USHORT nEndRow, USHORT nSize,
+ BOOL* pUndoOutline )
+{
+ USHORT i;
+ nRecalcLvl++;
+ if (nStartRow==0 && nEndRow==MAXROW)
+ {
+ if (pColWidth && pColFlags)
+ for (i=nStartCol; i+nSize<=MAXCOL; i++)
+ {
+ pColWidth[i] = pColWidth[i+nSize];
+ pColFlags[i] = pColFlags[i+nSize];
+ }
+ if (pOutlineTable)
+ if (pOutlineTable->DeleteCol( nStartCol, nSize ))
+ if (pUndoOutline)
+ *pUndoOutline = TRUE;
+ }
+
+
+ for (i = 0; i < nSize; i++)
+ aCol[nStartCol + i].DeleteArea(nStartRow, nEndRow, IDF_ALL);
+
+ if ((nStartRow == 0) && (nEndRow == MAXROW))
+ {
+ for (i=0; i < nSize; i++)
+ for (USHORT nCol = nStartCol; nCol < MAXCOL; nCol++)
+ aCol[nCol].SwapCol(aCol[nCol+1]);
+ }
+ else
+ {
+ for (i=0; i+nSize+nStartCol <= MAXCOL; i++)
+ aCol[nStartCol + nSize + i].MoveTo(nStartRow, nEndRow, aCol[nStartCol + i]);
+ }
+ if( !--nRecalcLvl )
+ SetDrawPageSize();
+}
+
+
+void ScTable::DeleteArea(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2, USHORT nDelFlag)
+{
+ if (nCol2 > MAXCOL) nCol2 = MAXCOL;
+ if (nRow2 > MAXROW) nRow2 = MAXROW;
+ if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
+ {
+// nRecalcLvl++;
+
+ for (USHORT i = nCol1; i <= nCol2; i++)
+ aCol[i].DeleteArea(nRow1, nRow2, nDelFlag);
+
+ //
+ // Zellschutz auf geschuetzter Tabelle nicht setzen
+ //
+
+ if ( bProtected && (nDelFlag & IDF_ATTRIB) )
+ {
+ ScPatternAttr aPattern(pDocument->GetPool());
+ aPattern.GetItemSet().Put( ScProtectionAttr( FALSE ) );
+ ApplyPatternArea( nCol1, nRow1, nCol2, nRow2, aPattern );
+ }
+
+/* if( !--nRecalcLvl )
+ SetDrawPageSize();
+*/
+ }
+}
+
+
+void ScTable::DeleteSelection( USHORT nDelFlag, const ScMarkData& rMark )
+{
+ for (USHORT i=0; i<=MAXCOL; i++)
+ aCol[i].DeleteSelection( nDelFlag, rMark );
+
+ //
+ // Zellschutz auf geschuetzter Tabelle nicht setzen
+ //
+
+ if ( bProtected && (nDelFlag & IDF_ATTRIB) )
+ {
+ ScDocumentPool* pPool = pDocument->GetPool();
+ SfxItemSet aSet( *pPool, ATTR_PATTERN_START, ATTR_PATTERN_END );
+ aSet.Put( ScProtectionAttr( FALSE ) );
+ SfxItemPoolCache aCache( pPool, &aSet );
+ ApplySelectionCache( &aCache, rMark );
+ }
+}
+
+
+// pTable = Clipboard
+void ScTable::CopyToClip(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2,
+ ScTable* pTable, BOOL bKeepScenarioFlags)
+{
+ if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
+ {
+ // Inhalte kopieren
+
+ for (USHORT i = nCol1; i <= nCol2; i++)
+ aCol[i].CopyToClip(nRow1, nRow2, pTable->aCol[i], bKeepScenarioFlags);
+
+ // Zeilen-/Spaltenhoehen, und von Flags nur "ausgeblendet" und "manual"
+
+ if (pColFlags && pTable->pColFlags && pColWidth && pTable->pColWidth)
+ for (i=nCol1; i<=nCol2; i++)
+ {
+ pTable->pColFlags[i] = pColFlags[i] & CR_HIDDEN;
+ pTable->pColWidth[i] = pColWidth[i];
+ }
+
+ if (pRowFlags && pTable->pRowFlags && pRowHeight && pTable->pRowHeight)
+ for (i=nRow1; i<=nRow2; i++)
+ {
+ pTable->pRowFlags[i] = pRowFlags[i] & (CR_HIDDEN | CR_MANUALSIZE);
+ pTable->pRowHeight[i] = pRowHeight[i];
+ }
+
+
+ // ggf. Formeln durch Werte ersetzen
+
+ if (bProtected)
+ for (i = nCol1; i <= nCol2; i++)
+ pTable->aCol[i].RemoveProtected(nRow1, nRow2);
+ }
+}
+
+
+void ScTable::CopyFromClip(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2,
+ short nDx, short nDy, USHORT nInsFlag, BOOL bAsLink, ScTable* pTable)
+{
+ if (nCol2 > MAXCOL) nCol2 = MAXCOL;
+ if (nRow2 > MAXROW) nRow2 = MAXROW;
+ if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
+ {
+ nRecalcLvl++;
+ for (USHORT i = nCol1; i <= nCol2; i++)
+ aCol[i].CopyFromClip(nRow1, nRow2, nDy, nInsFlag, bAsLink, pTable->aCol[i - nDx]);
+
+ if ((nInsFlag & IDF_ATTRIB) != 0)
+ {
+ if (nRow1==0 && nRow2==MAXROW && pColWidth && pTable->pColWidth)
+ for (i=nCol1; i<=nCol2; i++)
+ pColWidth[i] = pTable->pColWidth[i-nDx];
+
+ if (nCol1==0 && nCol2==MAXCOL && pRowHeight && pTable->pRowHeight &&
+ pRowFlags && pTable->pRowFlags)
+ for (i=nRow1; i<=nRow2; i++)
+ {
+ pRowHeight[i] = pTable->pRowHeight[i-nDy];
+ // CR_MANUALSIZE Bit muss mitkopiert werden, sonst macht pRowHeight keinen Sinn
+ if ( pTable->pRowFlags[i-nDy] & CR_MANUALSIZE )
+ pRowFlags[i] |= CR_MANUALSIZE;
+ else
+ pRowFlags[i] &= ~CR_MANUALSIZE;
+ }
+
+ //
+ // Zellschutz auf geschuetzter Tabelle nicht setzen
+ //
+
+ if ( bProtected && (nInsFlag & IDF_ATTRIB) )
+ {
+ ScPatternAttr aPattern(pDocument->GetPool());
+ aPattern.GetItemSet().Put( ScProtectionAttr( FALSE ) );
+ ApplyPatternArea( nCol1, nRow1, nCol2, nRow2, aPattern );
+ }
+ }
+ if( !--nRecalcLvl )
+ SetDrawPageSize();
+ }
+}
+
+
+void ScTable::MixData( USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2,
+ USHORT nFunction, BOOL bSkipEmpty, ScTable* pSrcTab )
+{
+ for (USHORT i=nCol1; i<=nCol2; i++)
+ aCol[i].MixData( nRow1, nRow2, nFunction, bSkipEmpty, pSrcTab->aCol[i] );
+}
+
+
+// Markierung von diesem Dokument
+void ScTable::MixMarked( const ScMarkData& rMark, USHORT nFunction,
+ BOOL bSkipEmpty, ScTable* pSrcTab )
+{
+ for (USHORT i=0; i<=MAXCOL; i++)
+ aCol[i].MixMarked( rMark, nFunction, bSkipEmpty, pSrcTab->aCol[i] );
+}
+
+
+void ScTable::TransposeClip( USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2,
+ ScTable* pTransClip, USHORT nFlags, BOOL bAsLink )
+{
+ BOOL bWasCut = pDocument->IsCutMode();
+
+ ScDocument* pDestDoc = pTransClip->pDocument;
+
+ for (USHORT nCol=nCol1; nCol<=nCol2; nCol++)
+ {
+ USHORT nRow;
+ ScBaseCell* pCell;
+
+ if ( bAsLink && nFlags == IDF_ALL )
+ {
+ // #68989# with IDF_ALL, also create links (formulas) for empty cells
+
+ for ( nRow=nRow1; nRow<=nRow2; nRow++ )
+ {
+ // create simple formula, as in ScColumn::CreateRefCell
+
+ ScAddress aDestPos( nRow-nRow1, nCol-nCol1, pTransClip->nTab );
+ SingleRefData aRef;
+ aRef.nCol = nCol;
+ aRef.nRow = nRow;
+ aRef.nTab = nTab;
+ aRef.InitFlags(); // -> all absolute
+ aRef.SetFlag3D(TRUE);
+ aRef.CalcRelFromAbs( aDestPos );
+ ScTokenArray aArr;
+ aArr.AddSingleReference( aRef );
+
+ ScBaseCell* pNew = new ScFormulaCell( pDestDoc, aDestPos, &aArr );
+ pTransClip->PutCell( nRow-nRow1, nCol-nCol1, pNew );
+ }
+ }
+ else
+ {
+ ScColumnIterator aIter( &aCol[nCol], nRow1, nRow2 );
+ while (aIter.Next( nRow, pCell ))
+ {
+ ScBaseCell* pNew;
+ if ( bAsLink ) // Referenz erzeugen ?
+ {
+ pNew = aCol[nCol].CreateRefCell( pDestDoc,
+ ScAddress( nRow-nRow1, nCol-nCol1, pTransClip->nTab ),
+ aIter.GetIndex(), nFlags );
+ }
+ else // kopieren
+ {
+ if (pCell->GetCellType() == CELLTYPE_FORMULA)
+ {
+ pNew = ((ScFormulaCell*)pCell)->Clone( pDestDoc,
+ ScAddress( nRow-nRow1, nCol-nCol1, nTab ) );
+
+ // Referenzen drehen
+ // bei Cut werden Referenzen spaeter per UpdateTranspose angepasst
+
+ if (!bWasCut)
+ ((ScFormulaCell*)pNew)->TransposeReference();
+ }
+ else
+ pNew = pCell->Clone( pDestDoc );
+ }
+ pTransClip->PutCell( nRow-nRow1, nCol-nCol1, pNew );
+ }
+ }
+
+ // Attribute
+
+ USHORT nAttrRow1;
+ USHORT nAttrRow2;
+ const ScPatternAttr* pPattern;
+ ScAttrIterator* pAttrIter = aCol[nCol].CreateAttrIterator( nRow1, nRow2 );
+ while ( (pPattern = pAttrIter->Next( nAttrRow1, nAttrRow2 )) != 0 )
+ {
+ if ( !IsDefaultItem( pPattern ) )
+ {
+ for (nRow = nAttrRow1; nRow<=nAttrRow2; nRow++)
+ pTransClip->SetPattern( nRow-nRow1, nCol-nCol1, *pPattern, TRUE );
+ }
+ }
+
+ delete pAttrIter;
+ }
+}
+
+
+void ScTable::StartAllListeners()
+{
+ for (USHORT i=0; i<=MAXCOL; i++)
+ aCol[i].StartAllListeners();
+}
+
+
+void ScTable::StartRelNameListeners()
+{
+ for (USHORT i=0; i<=MAXCOL; i++)
+ aCol[i].StartRelNameListeners();
+}
+
+
+void ScTable::BroadcastInArea( USHORT nCol1, USHORT nRow1,
+ USHORT nCol2, USHORT nRow2 )
+{
+ if (nCol2 > MAXCOL) nCol2 = MAXCOL;
+ if (nRow2 > MAXROW) nRow2 = MAXROW;
+ if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
+ for (USHORT i = nCol1; i <= nCol2; i++)
+ aCol[i].BroadcastInArea( nRow1, nRow2 );
+}
+
+
+void ScTable::StartListeningInArea( USHORT nCol1, USHORT nRow1,
+ USHORT nCol2, USHORT nRow2 )
+{
+ if (nCol2 > MAXCOL) nCol2 = MAXCOL;
+ if (nRow2 > MAXROW) nRow2 = MAXROW;
+ if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
+ for (USHORT i = nCol1; i <= nCol2; i++)
+ aCol[i].StartListeningInArea( nRow1, nRow2 );
+}
+
+
+void ScTable::CopyToTable(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2,
+ USHORT nFlags, BOOL bMarked, ScTable* pDestTab,
+ const ScMarkData* pMarkData,
+ BOOL bAsLink, BOOL bColRowFlags)
+{
+ if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
+ {
+ USHORT i;
+
+ if (nFlags)
+ for (i = nCol1; i <= nCol2; i++)
+ aCol[i].CopyToColumn(nRow1, nRow2, nFlags, bMarked,
+ pDestTab->aCol[i], pMarkData, bAsLink);
+
+ if (bColRowFlags) // Spaltenbreiten/Zeilenhoehen/Flags
+ {
+ // Charts muessen beim Ein-/Ausblenden angepasst werden
+ ScChartListenerCollection* pCharts = pDestTab->pDocument->GetChartListenerCollection();
+ if ( pCharts && !pCharts->GetCount() )
+ pCharts = NULL;
+
+ if (nRow1==0 && nRow2==MAXROW && pColWidth && pDestTab->pColWidth)
+ for (i=nCol1; i<=nCol2; i++)
+ {
+ BOOL bChange = pCharts &&
+ ( pDestTab->pColFlags[i] & CR_HIDDEN ) != ( pColFlags[i] & CR_HIDDEN );
+ pDestTab->pColWidth[i] = pColWidth[i];
+ pDestTab->pColFlags[i] = pColFlags[i];
+ //! Aenderungen zusammenfassen?
+ if (bChange)
+ pCharts->SetRangeDirty(ScRange( i, 0, nTab, i, MAXROW, nTab ));
+ }
+
+ if (nCol1==0 && nCol2==MAXCOL && pRowHeight && pDestTab->pRowHeight)
+ for (i=nRow1; i<=nRow2; i++)
+ {
+ BOOL bChange = pCharts &&
+ ( pDestTab->pRowFlags[i] & CR_HIDDEN ) != ( pRowFlags[i] & CR_HIDDEN );
+ pDestTab->pRowHeight[i] = pRowHeight[i];
+ pDestTab->pRowFlags[i] = pRowFlags[i];
+ //! Aenderungen zusammenfassen?
+ if (bChange)
+ pCharts->SetRangeDirty(ScRange( 0, i, nTab, MAXCOL, i, nTab ));
+ }
+
+ pDestTab->SetOutlineTable( pOutlineTable ); // auch nur wenn bColRowFlags
+ }
+ }
+}
+
+
+void ScTable::UndoToTable(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2,
+ USHORT nFlags, BOOL bMarked, ScTable* pDestTab,
+ const ScMarkData* pMarkData)
+{
+ if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
+ {
+ BOOL bWidth = (nRow1==0 && nRow2==MAXROW && pColWidth && pDestTab->pColWidth);
+ BOOL bHeight = (nCol1==0 && nCol2==MAXCOL && pRowHeight && pDestTab->pRowHeight);
+
+ if (bWidth||bHeight)
+ nRecalcLvl++;
+
+ for (USHORT i=0; i<=MAXCOL; i++)
+ {
+ if ( i >= nCol1 && i <= nCol2 )
+ aCol[i].UndoToColumn(nRow1, nRow2, nFlags, bMarked, pDestTab->aCol[i],
+ pMarkData);
+ else
+ aCol[i].CopyToColumn(0, MAXROW, IDF_FORMULA, FALSE, pDestTab->aCol[i]);
+ }
+
+ if (bWidth||bHeight)
+ {
+ if (bWidth)
+ for (i=nCol1; i<=nCol2; i++)
+ pDestTab->pColWidth[i] = pColWidth[i];
+ if (bHeight)
+ for (i=nRow1; i<=nRow2; i++)
+ pDestTab->pRowHeight[i] = pRowHeight[i];
+ if( !--nRecalcLvl )
+ SetDrawPageSize();
+ }
+ }
+}
+
+
+void ScTable::CopyUpdated( const ScTable* pPosTab, ScTable* pDestTab ) const
+{
+ for (USHORT i=0; i<=MAXCOL; i++)
+ aCol[i].CopyUpdated( pPosTab->aCol[i], pDestTab->aCol[i] );
+}
+
+void ScTable::CopyScenarioTo( ScTable* pDestTab ) const
+{
+ DBG_ASSERT( bScenario, "bScenario == FALSE" );
+
+ for (USHORT i=0; i<=MAXCOL; i++)
+ aCol[i].CopyScenarioTo( pDestTab->aCol[i] );
+}
+
+void ScTable::CopyScenarioFrom( const ScTable* pSrcTab )
+{
+ DBG_ASSERT( bScenario, "bScenario == FALSE" );
+
+ for (USHORT i=0; i<=MAXCOL; i++)
+ aCol[i].CopyScenarioFrom( pSrcTab->aCol[i] );
+}
+
+void ScTable::MarkScenarioIn( ScMarkData& rDestMark, USHORT nNeededBits ) const
+{
+ DBG_ASSERT( bScenario, "bScenario == FALSE" );
+
+ if ( ( nScenarioFlags & nNeededBits ) != nNeededBits ) // alle Bits gesetzt?
+ return;
+
+ for (USHORT i=0; i<=MAXCOL; i++)
+ aCol[i].MarkScenarioIn( rDestMark );
+}
+
+BOOL ScTable::HasScenarioRange( const ScRange& rRange ) const
+{
+ DBG_ASSERT( bScenario, "bScenario == FALSE" );
+
+// ScMarkData aMark;
+// MarkScenarioIn( aMark, 0 ); //! Bits als Parameter von HasScenarioRange?
+// return aMark.IsAllMarked( rRange );
+
+ ScRange aTabRange = rRange;
+ aTabRange.aStart.SetTab( nTab );
+ aTabRange.aEnd.SetTab( nTab );
+
+ const ScRangeList* pList = GetScenarioRanges();
+// return ( pList && pList->Find( aTabRange ) );
+
+ if (pList)
+ {
+ ULONG nCount = pList->Count();
+ for ( ULONG j = 0; j < nCount; j++ )
+ {
+ ScRange* pR = pList->GetObject( j );
+ if ( pR->Intersects( aTabRange ) )
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+void ScTable::InvalidateScenarioRanges()
+{
+ delete pScenarioRanges;
+ pScenarioRanges = NULL;
+}
+
+const ScRangeList* ScTable::GetScenarioRanges() const
+{
+ DBG_ASSERT( bScenario, "bScenario == FALSE" );
+
+ if (!pScenarioRanges)
+ {
+ ((ScTable*)this)->pScenarioRanges = new ScRangeList;
+ ScMarkData aMark;
+ MarkScenarioIn( aMark, 0 ); // immer
+ aMark.FillRangeListWithMarks( pScenarioRanges, FALSE );
+ }
+ return pScenarioRanges;
+}
+
+BOOL ScTable::TestCopyScenarioTo( const ScTable* pDestTab ) const
+{
+ DBG_ASSERT( bScenario, "bScenario == FALSE" );
+
+ if (!pDestTab->IsProtected())
+ return TRUE;
+
+ BOOL bOk = TRUE;
+ for (USHORT i=0; i<=MAXCOL && bOk; i++)
+ bOk = aCol[i].TestCopyScenarioTo( pDestTab->aCol[i] );
+ return bOk;
+}
+
+void ScTable::PutCell( USHORT nCol, USHORT nRow, ScBaseCell* pCell )
+{
+ if (ValidColRow(nCol,nRow))
+ {
+ if (pCell)
+ aCol[nCol].Insert( nRow, pCell );
+ else
+ aCol[nCol].Delete( nRow );
+ }
+}
+
+
+void ScTable::PutCell( USHORT nCol, USHORT nRow, ULONG nFormatIndex, ScBaseCell* pCell )
+{
+ if (ValidColRow(nCol,nRow))
+ {
+ if (pCell)
+ aCol[nCol].Insert( nRow, nFormatIndex, pCell );
+ else
+ aCol[nCol].Delete( nRow );
+ }
+}
+
+
+void ScTable::PutCell( const ScAddress& rPos, ScBaseCell* pCell )
+{
+ if (pCell)
+ aCol[rPos.Col()].Insert( rPos.Row(), pCell );
+ else
+ aCol[rPos.Col()].Delete( rPos.Row() );
+}
+
+
+void ScTable::PutCell( const ScAddress& rPos, ULONG nFormatIndex, ScBaseCell* pCell )
+{
+ if (pCell)
+ aCol[rPos.Col()].Insert( rPos.Row(), nFormatIndex, pCell );
+ else
+ aCol[rPos.Col()].Delete( rPos.Row() );
+}
+
+
+BOOL ScTable::SetString( USHORT nCol, USHORT nRow, USHORT nTab, const String& rString )
+{
+ if (ValidColRow(nCol,nRow))
+ return aCol[nCol].SetString( nRow, nTab, rString );
+ else
+ return FALSE;
+}
+
+
+void ScTable::SetValue( USHORT nCol, USHORT nRow, const double& rVal )
+{
+ if (ValidColRow(nCol, nRow))
+ aCol[nCol].SetValue( nRow, rVal );
+}
+
+
+void ScTable::SetNote( USHORT nCol, USHORT nRow, const ScPostIt& rNote)
+{
+ if (ValidColRow(nCol, nRow))
+ aCol[nCol].SetNote(nRow, rNote);
+}
+
+
+void ScTable::GetString( USHORT nCol, USHORT nRow, String& rString )
+{
+ if (ValidColRow(nCol,nRow))
+ aCol[nCol].GetString( nRow, rString );
+ else
+ rString.Erase();
+}
+
+
+void ScTable::GetInputString( USHORT nCol, USHORT nRow, String& rString )
+{
+ if (ValidColRow(nCol,nRow))
+ aCol[nCol].GetInputString( nRow, rString );
+ else
+ rString.Erase();
+}
+
+
+double ScTable::GetValue( USHORT nCol, USHORT nRow )
+{
+ if (ValidColRow( nCol, nRow ))
+ return aCol[nCol].GetValue( nRow );
+ return 0.0;
+}
+
+
+void ScTable::GetFormula( USHORT nCol, USHORT nRow, String& rFormula,
+ BOOL bAsciiExport )
+{
+ if (ValidColRow(nCol,nRow))
+ aCol[nCol].GetFormula( nRow, rFormula, bAsciiExport );
+ else
+ rFormula.Erase();
+}
+
+
+BOOL ScTable::GetNote( USHORT nCol, USHORT nRow, ScPostIt& rNote)
+{
+ BOOL bHasNote = FALSE;
+
+ if (ValidColRow(nCol,nRow))
+ bHasNote = aCol[nCol].GetNote( nRow, rNote );
+ else
+ rNote.Clear();
+
+ return bHasNote;
+}
+
+
+CellType ScTable::GetCellType( USHORT nCol, USHORT nRow ) const
+{
+ if (ValidColRow( nCol, nRow ))
+ return aCol[nCol].GetCellType( nRow );
+ return CELLTYPE_NONE;
+}
+
+
+ScBaseCell* ScTable::GetCell( USHORT nCol, USHORT nRow ) const
+{
+ if (ValidColRow( nCol, nRow ))
+ return aCol[nCol].GetCell( nRow );
+
+ DBG_ERROR("GetCell ausserhalb");
+ return NULL;
+}
+
+
+void ScTable::GetLastDataPos(USHORT& rCol, USHORT& rRow) const
+{
+ rCol = MAXCOL;
+ rRow = 0;
+ while (aCol[rCol].IsEmptyData() && (rCol > 0))
+ rCol--;
+ USHORT nCol = rCol;
+ while ((short)nCol >= 0)
+ {
+ rRow = Max(rRow, aCol[nCol].GetLastDataPos());
+ nCol--;
+ }
+}
+
+
+BOOL ScTable::HasData( USHORT nCol, USHORT nRow )
+{
+ if (ValidColRow(nCol,nRow))
+ return aCol[nCol].HasDataAt( nRow );
+ else
+ return FALSE;
+}
+
+
+BOOL ScTable::HasStringData( USHORT nCol, USHORT nRow )
+{
+ if (ValidColRow(nCol,nRow))
+ return aCol[nCol].HasStringData( nRow );
+ else
+ return FALSE;
+}
+
+
+BOOL ScTable::HasValueData( USHORT nCol, USHORT nRow )
+{
+ if (ValidColRow(nCol,nRow))
+ return aCol[nCol].HasValueData( nRow );
+ else
+ return FALSE;
+}
+
+
+BOOL ScTable::HasStringCells( USHORT nStartCol, USHORT nStartRow,
+ USHORT nEndCol, USHORT nEndRow ) const
+{
+ if ( nEndCol <= MAXCOL )
+ for ( USHORT nCol=nStartCol; nCol<=nEndCol; nCol++ )
+ if (aCol[nCol].HasStringCells(nStartRow, nEndRow))
+ return TRUE;
+
+ return FALSE;
+}
+
+
+USHORT ScTable::GetErrCode( USHORT nCol, USHORT nRow ) const
+{
+ if (ValidColRow( nCol, nRow ))
+ return aCol[nCol].GetErrCode( nRow );
+ return 0;
+}
+
+
+void ScTable::SetDirtyVar()
+{
+ for (USHORT i=0; i<=MAXCOL; i++)
+ aCol[i].SetDirtyVar();
+}
+
+
+void ScTable::SetDirty()
+{
+ BOOL bOldAutoCalc = pDocument->GetAutoCalc();
+ pDocument->SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ for (USHORT i=0; i<=MAXCOL; i++)
+ aCol[i].SetDirty();
+ pDocument->SetAutoCalc( bOldAutoCalc );
+}
+
+
+void ScTable::SetDirty( const ScRange& rRange )
+{
+ BOOL bOldAutoCalc = pDocument->GetAutoCalc();
+ pDocument->SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ USHORT nCol2 = rRange.aEnd.Col();
+ for (USHORT i=rRange.aStart.Col(); i<=nCol2; i++)
+ aCol[i].SetDirty( rRange );
+ pDocument->SetAutoCalc( bOldAutoCalc );
+}
+
+
+void ScTable::SetDirtyAfterLoad()
+{
+ BOOL bOldAutoCalc = pDocument->GetAutoCalc();
+ pDocument->SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ for (USHORT i=0; i<=MAXCOL; i++)
+ aCol[i].SetDirtyAfterLoad();
+ pDocument->SetAutoCalc( bOldAutoCalc );
+}
+
+
+void ScTable::SetRelNameDirty()
+{
+ BOOL bOldAutoCalc = pDocument->GetAutoCalc();
+ pDocument->SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ for (USHORT i=0; i<=MAXCOL; i++)
+ aCol[i].SetRelNameDirty();
+ pDocument->SetAutoCalc( bOldAutoCalc );
+}
+
+
+void ScTable::CalcAll()
+{
+ for (USHORT i=0; i<=MAXCOL; i++) aCol[i].CalcAll();
+}
+
+
+void ScTable::CompileAll()
+{
+ for (USHORT i=0; i <= MAXCOL; i++) aCol[i].CompileAll();
+}
+
+
+void ScTable::CompileXML()
+{
+ for (USHORT i=0; i <= MAXCOL; i++)
+ {
+ aCol[i].CompileXML();
+ }
+}
+
+
+void ScTable::CalcAfterLoad()
+{
+ for (USHORT i=0; i <= MAXCOL; i++) aCol[i].CalcAfterLoad();
+}
+
+
+void ScTable::ResetChanged( const ScRange& rRange )
+{
+ USHORT nStartCol = rRange.aStart.Col();
+ USHORT nStartRow = rRange.aStart.Row();
+ USHORT nEndCol = rRange.aEnd.Col();
+ USHORT nEndRow = rRange.aEnd.Row();
+
+ for (USHORT nCol=nStartCol; nCol<=nEndCol; nCol++)
+ aCol[nCol].ResetChanged(nStartRow, nEndRow);
+}
+
+// Attribute
+
+const SfxPoolItem* ScTable::GetAttr( USHORT nCol, USHORT nRow, USHORT nWhich ) const
+{
+ if (ValidColRow(nCol,nRow))
+ return aCol[nCol].GetAttr( nRow, nWhich );
+ else
+ return NULL;
+}
+
+
+ULONG ScTable::GetNumberFormat( USHORT nCol, USHORT nRow ) const
+{
+ if (ValidColRow(nCol,nRow))
+ return aCol[nCol].GetNumberFormat( nRow );
+ else
+ return 0;
+}
+
+
+const ScPatternAttr* ScTable::GetPattern( USHORT nCol, USHORT nRow ) const
+{
+ if (ValidColRow(nCol,nRow))
+ return aCol[nCol].GetPattern( nRow );
+ else
+ return NULL;
+}
+
+
+BOOL ScTable::HasAttrib( USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2, USHORT nMask ) const
+{
+ BOOL bFound=FALSE;
+ for (USHORT i=nCol1; i<=nCol2 && !bFound; i++)
+ bFound |= aCol[i].HasAttrib( nRow1, nRow2, nMask );
+ return bFound;
+}
+
+
+BOOL ScTable::HasLines( const ScRange& rRange, Rectangle& rSizes ) const
+{
+ USHORT nCol1 = rRange.aStart.Col();
+ USHORT nRow1 = rRange.aStart.Row();
+ USHORT nCol2 = rRange.aEnd.Col();
+ USHORT nRow2 = rRange.aEnd.Row();
+ PutInOrder( nCol1, nCol2 );
+ PutInOrder( nRow1, nRow2 );
+
+ BOOL bFound = FALSE;
+ for (USHORT i=nCol1; i<=nCol2; i++)
+ if (aCol[i].HasLines( nRow1, nRow2, rSizes, (i==nCol1), (i==nCol2) ))
+ bFound = TRUE;
+
+ return bFound;
+}
+
+
+BOOL ScTable::HasAttribSelection( const ScMarkData& rMark, USHORT nMask ) const
+{
+ BOOL bFound=FALSE;
+ for (USHORT i=0; i<=MAXCOL && !bFound; i++)
+ bFound |= aCol[i].HasAttribSelection( rMark, nMask );
+ return bFound;
+}
+
+
+BOOL ScTable::ExtendMerge( USHORT nStartCol, USHORT nStartRow,
+ USHORT& rEndCol, USHORT& rEndRow,
+ BOOL bRefresh, BOOL bAttrs )
+{
+ BOOL bFound=FALSE;
+ USHORT nOldEndX = rEndCol;
+ USHORT nOldEndY = rEndRow;
+ for (USHORT i=nStartCol; i<=nOldEndX; i++)
+ bFound |= aCol[i].ExtendMerge( i, nStartRow, nOldEndY, rEndCol, rEndRow, bRefresh, bAttrs );
+ return bFound;
+}
+
+
+BOOL ScTable::IsBlockEmpty( USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2 ) const
+{
+ BOOL bEmpty = TRUE;
+ for (USHORT i=nCol1; i<=nCol2 && bEmpty; i++)
+ bEmpty = aCol[i].IsEmptyBlock( nRow1, nRow2 );
+ return bEmpty;
+}
+
+USHORT ScTable::FillMaxRot( RowInfo* pRowInfo, USHORT nArrCount, USHORT nX1, USHORT nX2,
+ USHORT nCol, USHORT nAttrRow1, USHORT nAttrRow2, USHORT nArrY,
+ const ScPatternAttr* pPattern, const SfxItemSet* pCondSet ) const
+{
+ // Rueckgabe = neues nArrY
+
+ BYTE nRotDir = pPattern->GetRotateDir( pCondSet );
+ if ( nRotDir != SC_ROTDIR_NONE )
+ {
+ BOOL bHit = TRUE;
+ if ( nCol+1 < nX1 ) // links
+ bHit = ( nRotDir != SC_ROTDIR_LEFT );
+ else if ( nCol > nX2+1 ) // rechts
+ bHit = ( nRotDir == SC_ROTDIR_LEFT );
+
+ if ( bHit )
+ {
+ double nFactor = 0.0;
+ if ( nCol > nX2+1 )
+ {
+ long nRotVal = ((const SfxInt32Item&) pPattern->
+ GetItem( ATTR_ROTATE_VALUE, pCondSet )).GetValue();
+ double nRealOrient = nRotVal * F_PI18000; // 1/100 Grad
+ double nCos = cos( nRealOrient );
+ double nSin = sin( nRealOrient );
+ //! begrenzen !!!
+ //! zusaetzlich Faktor fuer unterschiedliche PPT X/Y !!!
+
+ // bei SC_ROTDIR_LEFT kommt immer ein negativer Wert heraus,
+ // wenn der Modus beruecksichtigt wird
+ nFactor = -fabs( nCos / nSin );
+ }
+
+ for ( USHORT nRow = nAttrRow1; nRow <= nAttrRow2; nRow++ )
+ {
+ if ( !(pRowFlags[nRow] & CR_HIDDEN) )
+ {
+ BOOL bHitOne = TRUE;
+ if ( nCol > nX2+1 )
+ {
+ // reicht die gedrehte Zelle bis in den sichtbaren Bereich?
+
+ USHORT nTouchedCol = nCol;
+ long nWidth = (long) ( pRowHeight[nRow] * nFactor );
+ DBG_ASSERT(nWidth <= 0, "Richtung falsch");
+ while ( nWidth < 0 && nTouchedCol > 0 )
+ {
+ --nTouchedCol;
+ nWidth += GetColWidth( nTouchedCol );
+ }
+ if ( nTouchedCol > nX2 )
+ bHitOne = FALSE;
+ }
+
+ if (bHitOne)
+ {
+ while ( nArrY<nArrCount && pRowInfo[nArrY].nRowNo < nRow )
+ ++nArrY;
+ if ( nArrY<nArrCount && pRowInfo[nArrY].nRowNo == nRow )
+ pRowInfo[nArrY].nRotMaxCol = nCol;
+ }
+ }
+ }
+ }
+ }
+
+ return nArrY;
+}
+
+void ScTable::FindMaxRotCol( RowInfo* pRowInfo, USHORT nArrCount, USHORT nX1, USHORT nX2 ) const
+{
+ if ( !pColWidth || !pRowHeight || !pColFlags || !pRowFlags )
+ {
+ DBG_ERROR( "Spalten-/Zeileninfo fehlt" );
+ return;
+ }
+
+ // nRotMaxCol ist auf SC_ROTMAX_NONE initialisiert, nRowNo ist schon gesetzt
+
+ USHORT nY1 = pRowInfo[0].nRowNo;
+ USHORT nY2 = pRowInfo[nArrCount-1].nRowNo;
+
+ for (USHORT nCol=0; nCol<=MAXCOL; nCol++)
+ {
+ if ( !(pColFlags[nCol] & CR_HIDDEN) )
+ {
+ USHORT nArrY = 0;
+ ScDocAttrIterator aIter( pDocument, nTab, nCol, nY1, nCol, nY2 );
+ USHORT nAttrCol, nAttrRow1, nAttrRow2;
+ const ScPatternAttr* pPattern = aIter.GetNext( nAttrCol, nAttrRow1, nAttrRow2 );
+ while ( pPattern )
+ {
+ const SfxPoolItem* pCondItem;
+ if ( pPattern->GetItemSet().GetItemState( ATTR_CONDITIONAL, TRUE, &pCondItem )
+ == SFX_ITEM_SET )
+ {
+ // alle Formate durchgehen, damit die Zellen nicht einzeln
+ // angeschaut werden muessen
+
+ ULONG nIndex = ((const SfxUInt32Item*)pCondItem)->GetValue();
+ ScConditionalFormatList* pList = pDocument->GetCondFormList();
+ ScStyleSheetPool* pStylePool = pDocument->GetStyleSheetPool();
+ if (pList && pStylePool)
+ {
+ const ScConditionalFormat* pFormat = pList->GetFormat(nIndex);
+ if ( pFormat )
+ {
+ USHORT nEntryCount = pFormat->Count();
+ for (USHORT nEntry=0; nEntry<nEntryCount; nEntry++)
+ {
+ String aName = pFormat->GetEntry(nEntry)->GetStyle();
+ if (aName.Len())
+ {
+ SfxStyleSheetBase* pStyleSheet =
+ pStylePool->Find( aName, SFX_STYLE_FAMILY_PARA );
+ if ( pStyleSheet )
+ {
+ FillMaxRot( pRowInfo, nArrCount, nX1, nX2,
+ nCol, nAttrRow1, nAttrRow2,
+ nArrY, pPattern, &pStyleSheet->GetItemSet() );
+ // nArrY nicht veraendern
+ }
+ }
+ }
+ }
+ }
+ }
+
+ nArrY = FillMaxRot( pRowInfo, nArrCount, nX1, nX2,
+ nCol, nAttrRow1, nAttrRow2,
+ nArrY, pPattern, NULL );
+
+ pPattern = aIter.GetNext( nAttrCol, nAttrRow1, nAttrRow2 );
+ }
+ }
+ }
+}
+
+BOOL ScTable::HasBlockMatrixFragment( USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2 ) const
+{
+ // nix:0, mitte:1, unten:2, links:4, oben:8, rechts:16, offen:32
+ USHORT nEdges;
+
+ if ( nCol1 == nCol2 )
+ { // linke und rechte Spalte
+ const USHORT n = 4 | 16;
+ nEdges = aCol[nCol1].GetBlockMatrixEdges( nRow1, nRow2, n );
+ // nicht (4 und 16) oder 1 oder 32
+ if ( nEdges && (((nEdges & n) != n) || (nEdges & 33)) )
+ return TRUE; // linke oder rechte Kante fehlt oder offen
+ }
+ else
+ { // linke Spalte
+ nEdges = aCol[nCol1].GetBlockMatrixEdges( nRow1, nRow2, 4 );
+ // nicht 4 oder 1 oder 32
+ if ( nEdges && (((nEdges & 4) != 4) || (nEdges & 33)) )
+ return TRUE; // linke Kante fehlt oder offen
+ // rechte Spalte
+ nEdges = aCol[nCol2].GetBlockMatrixEdges( nRow1, nRow2, 16 );
+ // nicht 16 oder 1 oder 32
+ if ( nEdges && (((nEdges & 16) != 16) || (nEdges & 33)) )
+ return TRUE; // rechte Kante fehlt oder offen
+ }
+
+ if ( nRow1 == nRow2 )
+ { // obere und untere Zeile
+ USHORT i;
+ BOOL bOpen = FALSE;
+ const USHORT n = 2 | 8;
+ for ( i=nCol1; i<=nCol2; i++)
+ {
+ nEdges = aCol[i].GetBlockMatrixEdges( nRow1, nRow1, n );
+ if ( nEdges )
+ {
+ if ( (nEdges & n) != n )
+ return TRUE; // obere oder untere Kante fehlt
+ if ( nEdges & 4 )
+ bOpen = TRUE; // linke Kante oeffnet, weitersehen
+ else if ( !bOpen )
+ return TRUE; // es gibt was, was nicht geoeffnet wurde
+ if ( nEdges & 16 )
+ bOpen = FALSE; // rechte Kante schliesst
+ }
+ }
+ if ( bOpen )
+ return TRUE; // es geht noch weiter
+ }
+ else
+ {
+ USHORT j, nR, n, i;
+ // erst obere Zeile, dann untere Zeile
+ for ( j=0, nR=nRow1, n=8; j<2; j++, nR=nRow2, n=2 )
+ {
+ BOOL bOpen = FALSE;
+ for ( i=nCol1; i<=nCol2; i++)
+ {
+ nEdges = aCol[i].GetBlockMatrixEdges( nR, nR, n );
+ if ( nEdges )
+ {
+ // in oberere Zeile keine obere Kante bzw.
+ // in unterer Zeile keine untere Kante
+ if ( (nEdges & n) != n )
+ return TRUE;
+ if ( nEdges & 4 )
+ bOpen = TRUE; // linke Kante oeffnet, weitersehen
+ else if ( !bOpen )
+ return TRUE; // es gibt was, was nicht geoeffnet wurde
+ if ( nEdges & 16 )
+ bOpen = FALSE; // rechte Kante schliesst
+ }
+ }
+ if ( bOpen )
+ return TRUE; // es geht noch weiter
+ }
+ }
+ return FALSE;
+}
+
+
+BOOL ScTable::HasSelectionMatrixFragment( const ScMarkData& rMark ) const
+{
+ BOOL bFound=FALSE;
+ for (USHORT i=0; i<=MAXCOL && !bFound; i++)
+ bFound |= aCol[i].HasSelectionMatrixFragment(rMark);
+ return bFound;
+}
+
+
+BOOL ScTable::IsBlockEditable( USHORT nCol1, USHORT nRow1, USHORT nCol2,
+ USHORT nRow2, BOOL* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
+{
+ BOOL bIsEditable;
+ if ( nLockCount )
+ bIsEditable = FALSE;
+ else if ( bProtected )
+ bIsEditable = !HasAttrib( nCol1, nRow1, nCol2, nRow2, HASATTR_PROTECTED );
+ else
+ bIsEditable = TRUE;
+ if ( bIsEditable )
+ {
+ if ( HasBlockMatrixFragment( nCol1, nRow1, nCol2, nRow2 ) )
+ {
+ bIsEditable = FALSE;
+ if ( pOnlyNotBecauseOfMatrix )
+ *pOnlyNotBecauseOfMatrix = TRUE;
+ }
+ else if ( pOnlyNotBecauseOfMatrix )
+ *pOnlyNotBecauseOfMatrix = FALSE;
+ }
+ else if ( pOnlyNotBecauseOfMatrix )
+ *pOnlyNotBecauseOfMatrix = FALSE;
+ return bIsEditable;
+}
+
+
+BOOL ScTable::IsSelectionEditable( const ScMarkData& rMark,
+ BOOL* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
+{
+ BOOL bIsEditable;
+ if ( nLockCount )
+ bIsEditable = FALSE;
+ else if ( bProtected )
+ bIsEditable = !HasAttribSelection( rMark, HASATTR_PROTECTED );
+ else
+ bIsEditable = TRUE;
+ if ( bIsEditable )
+ {
+ if ( HasSelectionMatrixFragment( rMark ) )
+ {
+ bIsEditable = FALSE;
+ if ( pOnlyNotBecauseOfMatrix )
+ *pOnlyNotBecauseOfMatrix = TRUE;
+ }
+ else if ( pOnlyNotBecauseOfMatrix )
+ *pOnlyNotBecauseOfMatrix = FALSE;
+ }
+ else if ( pOnlyNotBecauseOfMatrix )
+ *pOnlyNotBecauseOfMatrix = FALSE;
+ return bIsEditable;
+}
+
+
+
+void ScTable::LockTable()
+{
+ ++nLockCount;
+}
+
+
+void ScTable::UnlockTable()
+{
+ if (nLockCount)
+ --nLockCount;
+ else
+ DBG_ERROR("UnlockTable ohne LockTable");
+}
+
+
+void ScTable::MergeSelectionPattern( SfxItemSet** ppSet, const ScMarkData& rMark, BOOL bDeep ) const
+{
+ for (USHORT i=0; i<=MAXCOL; i++)
+ aCol[i].MergeSelectionPattern( ppSet, rMark, bDeep );
+}
+
+
+void ScTable::MergePatternArea( SfxItemSet** ppSet, USHORT nCol1, USHORT nRow1,
+ USHORT nCol2, USHORT nRow2, BOOL bDeep ) const
+{
+ for (USHORT i=nCol1; i<=nCol2; i++)
+ aCol[i].MergePatternArea( ppSet, nRow1, nRow2, bDeep );
+}
+
+
+void ScTable::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner, ScLineFlags& rFlags,
+ USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow ) const
+{
+ if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
+ {
+ PutInOrder(nStartCol, nEndCol);
+ PutInOrder(nStartRow, nEndRow);
+ for (USHORT i=nStartCol; i<=nEndCol; i++)
+ aCol[i].MergeBlockFrame( pLineOuter, pLineInner, rFlags,
+ nStartRow, nEndRow, (i==nStartCol), nEndCol-i );
+ }
+}
+
+
+void ScTable::ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInfoItem* pLineInner,
+ USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow )
+{
+ if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
+ {
+ PutInOrder(nStartCol, nEndCol);
+ PutInOrder(nStartRow, nEndRow);
+ for (USHORT i=nStartCol; i<=nEndCol; i++)
+ aCol[i].ApplyBlockFrame( pLineOuter, pLineInner,
+ nStartRow, nEndRow, (i==nStartCol), nEndCol-i );
+ }
+}
+
+
+void ScTable::ApplyPattern( USHORT nCol, USHORT nRow, const ScPatternAttr& rAttr )
+{
+ if (ValidColRow(nCol,nRow))
+ aCol[nCol].ApplyPattern( nRow, rAttr );
+}
+
+
+void ScTable::ApplyPatternArea( USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow,
+ const ScPatternAttr& rAttr )
+{
+ if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
+ {
+ PutInOrder(nStartCol, nEndCol);
+ PutInOrder(nStartRow, nEndRow);
+ for (USHORT i = nStartCol; i <= nEndCol; i++)
+ aCol[i].ApplyPatternArea(nStartRow, nEndRow, rAttr);
+ }
+}
+
+void ScTable::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
+ const ScPatternAttr& rPattern, short nNewType )
+{
+ USHORT nEndCol = rRange.aEnd.Col();
+ for ( USHORT nCol = rRange.aStart.Col(); nCol <= nEndCol; nCol++ )
+ {
+ aCol[nCol].ApplyPatternIfNumberformatIncompatible( rRange, rPattern, nNewType );
+ }
+}
+
+
+
+void ScTable::ApplyStyle( USHORT nCol, USHORT nRow, const ScStyleSheet& rStyle )
+{
+ if (ValidColRow(nCol,nRow))
+ aCol[nCol].ApplyStyle( nRow, rStyle );
+}
+
+
+void ScTable::ApplyStyleArea( USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow, const ScStyleSheet& rStyle )
+{
+ if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
+ {
+ PutInOrder(nStartCol, nEndCol);
+ PutInOrder(nStartRow, nEndRow);
+ for (USHORT i = nStartCol; i <= nEndCol; i++)
+ aCol[i].ApplyStyleArea(nStartRow, nEndRow, rStyle);
+ }
+}
+
+
+void ScTable::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
+{
+ for (USHORT i=0; i<=MAXCOL; i++)
+ aCol[i].ApplySelectionStyle( rStyle, rMark );
+}
+
+
+void ScTable::ApplySelectionLineStyle( const ScMarkData& rMark,
+ const SvxBorderLine* pLine, BOOL bColorOnly )
+{
+ if ( bColorOnly && !pLine )
+ return;
+
+ for (USHORT i=0; i<=MAXCOL; i++)
+ aCol[i].ApplySelectionLineStyle( rMark, pLine, bColorOnly );
+}
+
+
+const ScStyleSheet* ScTable::GetStyle( USHORT nCol, USHORT nRow ) const
+{
+ if (ValidColRow(nCol, nRow))
+ return aCol[nCol].GetStyle(nRow);
+ else
+ return NULL;
+}
+
+
+const ScStyleSheet* ScTable::GetSelectionStyle( const ScMarkData& rMark, BOOL& rFound ) const
+{
+ rFound = FALSE;
+
+ BOOL bEqual = TRUE;
+ BOOL bColFound;
+ USHORT i;
+
+ const ScStyleSheet* pStyle = NULL;
+ const ScStyleSheet* pNewStyle;
+
+ for (i=0; i<=MAXCOL && bEqual; i++)
+ if (rMark.HasMultiMarks(i))
+ {
+ pNewStyle = aCol[i].GetSelectionStyle( rMark, bColFound );
+ if (bColFound)
+ {
+ rFound = TRUE;
+ if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
+ bEqual = FALSE; // unterschiedliche
+ pStyle = pNewStyle;
+ }
+ }
+
+ return bEqual ? pStyle : NULL;
+}
+
+
+const ScStyleSheet* ScTable::GetAreaStyle( BOOL& rFound, USHORT nCol1, USHORT nRow1,
+ USHORT nCol2, USHORT nRow2 ) const
+{
+ rFound = FALSE;
+
+ BOOL bEqual = TRUE;
+ BOOL bColFound;
+ USHORT i;
+
+ const ScStyleSheet* pStyle = NULL;
+ const ScStyleSheet* pNewStyle;
+
+ for (i=nCol1; i<=nCol2 && bEqual; i++)
+ {
+ pNewStyle = aCol[i].GetAreaStyle(bColFound, nRow1, nRow2);
+ if (bColFound)
+ {
+ rFound = TRUE;
+ if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
+ bEqual = FALSE; // unterschiedliche
+ pStyle = pNewStyle;
+ }
+ }
+
+ return bEqual ? pStyle : NULL;
+}
+
+
+BOOL ScTable::IsStyleSheetUsed( const SfxStyleSheetBase& rStyle ) const
+{
+ BOOL bIsUsed = FALSE;
+
+ for ( USHORT i=0; (i<=MAXCOL) && !bIsUsed; i++ )
+ bIsUsed = aCol[i].IsStyleSheetUsed( rStyle );
+
+ return bIsUsed;
+}
+
+
+void ScTable::StyleSheetChanged( const SfxStyleSheetBase* pStyleSheet, BOOL bRemoved,
+ OutputDevice* pDev,
+ double nPPTX, double nPPTY,
+ const Fraction& rZoomX, const Fraction& rZoomY )
+{
+ BOOL* pUsed = new BOOL[MAXROW+1];
+ USHORT i;
+ for (i=0; i<=MAXROW; i++)
+ pUsed[i] = FALSE;
+
+ USHORT nCol;
+ for (nCol=0; nCol<=MAXCOL; nCol++)
+ aCol[nCol].FindStyleSheet( pStyleSheet, pUsed, bRemoved );
+
+ BOOL bFound = FALSE;
+ USHORT nStart;
+ USHORT nEnd;
+ for (i=0; i<=MAXROW; i++)
+ {
+ if (pUsed[i])
+ {
+ if (!bFound)
+ {
+ nStart = i;
+ bFound = TRUE;
+ }
+ nEnd = i;
+ }
+ else if (bFound)
+ {
+ SetOptimalHeight( nStart, nEnd, 0, pDev, nPPTX, nPPTY, rZoomX, rZoomY, FALSE );
+ bFound = FALSE;
+ }
+ }
+ if (bFound)
+ SetOptimalHeight( nStart, nEnd, 0, pDev, nPPTX, nPPTY, rZoomX, rZoomY, FALSE );
+
+ delete[] pUsed;
+}
+
+
+BOOL ScTable::ApplyFlags( USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow,
+ INT16 nFlags )
+{
+ BOOL bChanged = FALSE;
+ if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
+ for (USHORT i = nStartCol; i <= nEndCol; i++)
+ bChanged |= aCol[i].ApplyFlags(nStartRow, nEndRow, nFlags);
+ return bChanged;
+}
+
+
+BOOL ScTable::RemoveFlags( USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow,
+ INT16 nFlags )
+{
+ BOOL bChanged = FALSE;
+ if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
+ for (USHORT i = nStartCol; i <= nEndCol; i++)
+ bChanged |= aCol[i].RemoveFlags(nStartRow, nEndRow, nFlags);
+ return bChanged;
+}
+
+
+void ScTable::SetPattern( USHORT nCol, USHORT nRow, const ScPatternAttr& rAttr, BOOL bPutToPool )
+{
+ if (ValidColRow(nCol,nRow))
+ aCol[nCol].SetPattern( nRow, rAttr, bPutToPool );
+}
+
+
+void ScTable::ApplyAttr( USHORT nCol, USHORT nRow, const SfxPoolItem& rAttr )
+{
+ if (ValidColRow(nCol,nRow))
+ aCol[nCol].ApplyAttr( nRow, rAttr );
+}
+
+
+void ScTable::ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark )
+{
+ for (USHORT i=0; i<=MAXCOL; i++)
+ aCol[i].ApplySelectionCache( pCache, rMark );
+}
+
+
+void ScTable::ChangeSelectionIndent( BOOL bIncrement, const ScMarkData& rMark )
+{
+ for (USHORT i=0; i<=MAXCOL; i++)
+ aCol[i].ChangeSelectionIndent( bIncrement, rMark );
+}
+
+
+void ScTable::ClearSelectionItems( const USHORT* pWhich, const ScMarkData& rMark )
+{
+ for (USHORT i=0; i<=MAXCOL; i++)
+ aCol[i].ClearSelectionItems( pWhich, rMark );
+}
+
+
+// Spaltenbreiten / Zeilenhoehen
+
+void ScTable::SetColWidth( USHORT nCol, USHORT nNewWidth )
+{
+ if (VALIDCOL(nCol) && pColWidth)
+ {
+ if (!nNewWidth)
+ {
+// DBG_ERROR("Spaltenbreite 0 in SetColWidth");
+ nNewWidth = STD_COL_WIDTH;
+ }
+
+ if ( nNewWidth != pColWidth[nCol] )
+ {
+ nRecalcLvl++;
+ ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
+ if (pDrawLayer)
+ pDrawLayer->WidthChanged( nTab, nCol, ((long) nNewWidth) - (long) pColWidth[nCol] );
+ pColWidth[nCol] = nNewWidth;
+ if( !--nRecalcLvl )
+ SetDrawPageSize();
+ }
+ }
+ else
+ DBG_ERROR("Falsche Spaltennummer oder keine Breiten");
+}
+
+
+void ScTable::SetRowHeight( USHORT nRow, USHORT nNewHeight )
+{
+ if (VALIDROW(nRow) && pRowHeight)
+ {
+ if (!nNewHeight)
+ {
+ DBG_ERROR("Zeilenhoehe 0 in SetRowHeight");
+ nNewHeight = ScGlobal::nStdRowHeight;
+ }
+
+ if ( nNewHeight != pRowHeight[nRow] )
+ {
+ nRecalcLvl++;
+ ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
+ if (pDrawLayer)
+ pDrawLayer->HeightChanged( nTab, nRow, ((long) nNewHeight) - (long) pRowHeight[nRow] );
+ pRowHeight[nRow] = nNewHeight;
+ if( !--nRecalcLvl )
+ SetDrawPageSize();
+ }
+ }
+ else
+ DBG_ERROR("Falsche Zeilennummer oder keine Hoehen");
+}
+
+
+BOOL ScTable::SetRowHeightRange( USHORT nStartRow, USHORT nEndRow, USHORT nNewHeight,
+ double nPPTX,double nPPTY )
+{
+ BOOL bChanged = FALSE;
+ if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && pRowHeight)
+ {
+ nRecalcLvl++;
+ if (!nNewHeight)
+ {
+ DBG_ERROR("Zeilenhoehe 0 in SetRowHeight");
+ nNewHeight = ScGlobal::nStdRowHeight;
+ }
+
+ long nNewPix = (long) ( nNewHeight * nPPTY );
+
+ BOOL bSingle = FALSE;
+ ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
+ if (pDrawLayer)
+ if (pDrawLayer->HasObjectsInRows( nTab, nStartRow, nEndRow ))
+ bSingle = TRUE;
+
+ USHORT nRow;
+ if (bSingle)
+ {
+ BOOL bDiff = FALSE;
+ for (nRow=nStartRow; nRow<=nEndRow && !bDiff; nRow++)
+ bDiff = ( pRowHeight[nRow] != nNewHeight );
+ if (!bDiff)
+ bSingle = FALSE;
+ }
+ if (bSingle)
+ {
+ if (nEndRow-nStartRow < 20)
+ for (nRow=nStartRow; nRow<=nEndRow; nRow++)
+ {
+ if (!bChanged)
+ if ( pRowHeight[nRow] != nNewHeight )
+ bChanged = ( nNewPix != (long) ( pRowHeight[nRow] * nPPTY ) );
+ SetRowHeight( nRow, nNewHeight );
+ }
+ else
+ {
+ USHORT nMid = (nStartRow+nEndRow) / 2;
+ if (SetRowHeightRange( nStartRow, nMid, nNewHeight, 1.0, 1.0 ))
+ bChanged = TRUE;
+ if (SetRowHeightRange( nMid+1, nEndRow, nNewHeight, 1.0, 1.0 ))
+ bChanged = TRUE;
+ }
+ }
+ else
+ {
+ if (pDrawLayer)
+ {
+ long nHeightDif = 0;
+ for (nRow=nStartRow; nRow<=nEndRow; nRow++)
+ nHeightDif += ((long) nNewHeight) - (long) pRowHeight[nRow];
+ pDrawLayer->HeightChanged( nTab, nEndRow, nHeightDif );
+ }
+ for (nRow=nStartRow; nRow<=nEndRow; nRow++)
+ {
+ if (!bChanged)
+ if ( pRowHeight[nRow] != nNewHeight )
+ bChanged = ( nNewPix != (long) ( pRowHeight[nRow] * nPPTY ) );
+ pRowHeight[nRow] = nNewHeight;
+ }
+ }
+ if( !--nRecalcLvl )
+ SetDrawPageSize();
+ }
+ else
+ DBG_ERROR("Falsche Zeilennummer oder keine Hoehen");
+
+ return bChanged;
+}
+
+
+void ScTable::SetManualHeight( USHORT nStartRow, USHORT nEndRow, BOOL bManual )
+{
+ if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && pRowFlags)
+ {
+ USHORT nRow;
+ if (bManual)
+ for (nRow=nStartRow; nRow<=nEndRow; nRow++)
+ pRowFlags[nRow] |= CR_MANUALSIZE;
+ else
+ for (nRow=nStartRow; nRow<=nEndRow; nRow++)
+ pRowFlags[nRow] &= ~CR_MANUALSIZE;
+ }
+ else
+ DBG_ERROR("Falsche Zeilennummer oder keine Zeilenflags");
+}
+
+
+USHORT ScTable::GetColWidth( USHORT nCol ) const
+{
+ DBG_ASSERT(VALIDCOL(nCol),"Falsche Spaltennummer");
+
+ if (VALIDCOL(nCol) && pColFlags && pColWidth)
+ {
+ if ( pColFlags[nCol] & CR_HIDDEN )
+ return 0;
+ else
+ return pColWidth[nCol];
+ }
+ else
+ return (USHORT) STD_COL_WIDTH;
+}
+
+
+USHORT ScTable::GetOriginalWidth( USHORT nCol ) const // immer die eingestellte
+{
+ DBG_ASSERT(VALIDCOL(nCol),"Falsche Spaltennummer");
+
+ if (VALIDCOL(nCol) && pColWidth)
+ return pColWidth[nCol];
+ else
+ return (USHORT) STD_COL_WIDTH;
+}
+
+
+USHORT ScTable::GetRowHeight( USHORT nRow ) const
+{
+ DBG_ASSERT(VALIDROW(nRow),"Falsche Zeilennummer");
+
+ if (VALIDROW(nRow) && pRowFlags && pRowHeight)
+ {
+ if ( pRowFlags[nRow] & CR_HIDDEN )
+ return 0;
+ else
+ return pRowHeight[nRow];
+ }
+ else
+ return (USHORT) ScGlobal::nStdRowHeight;
+}
+
+// Spalten-/Zeilen-Flags
+
+
+USHORT ScTable::GetHiddenRowCount( USHORT nRow ) const
+{
+ USHORT nEndRow = nRow;
+ if ( pRowFlags )
+ {
+ while ( nEndRow <= MAXROW && ( pRowFlags[nEndRow] & CR_HIDDEN ) )
+ ++nEndRow;
+ }
+ return nEndRow - nRow;
+}
+
+
+//! ShowRows / DBShowRows zusammenfassen
+
+void ScTable::ShowCol(USHORT nCol, BOOL bShow)
+{
+ if (VALIDCOL(nCol) && pColFlags)
+ {
+ BOOL bWasVis = ( pColFlags[nCol] & CR_HIDDEN ) == 0;
+ if (bWasVis != bShow)
+ {
+ nRecalcLvl++;
+ ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
+ if (pDrawLayer)
+ {
+ if (bShow)
+ pDrawLayer->WidthChanged( nTab, nCol, (long) pColWidth[nCol] );
+ else
+ pDrawLayer->WidthChanged( nTab, nCol, -(long) pColWidth[nCol] );
+ }
+
+ if (bShow)
+ pColFlags[nCol] &= ~CR_HIDDEN;
+ else
+ pColFlags[nCol] |= CR_HIDDEN;
+ if( !--nRecalcLvl )
+ SetDrawPageSize();
+
+ ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
+ if ( pCharts && pCharts->GetCount() )
+ pCharts->SetRangeDirty(ScRange( nCol, 0, nTab, nCol, MAXROW, nTab ));
+ }
+ }
+ else
+ DBG_ERROR("Falsche Spaltennummer oder keine Flags");
+}
+
+
+void ScTable::ShowRow(USHORT nRow, BOOL bShow)
+{
+ if (VALIDROW(nRow) && pRowFlags)
+ {
+ BOOL bWasVis = ( pRowFlags[nRow] & CR_HIDDEN ) == 0;
+ if (bWasVis != bShow)
+ {
+ nRecalcLvl++;
+ ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
+ if (pDrawLayer)
+ {
+ if (bShow)
+ pDrawLayer->HeightChanged( nTab, nRow, (long) pRowHeight[nRow] );
+ else
+ pDrawLayer->HeightChanged( nTab, nRow, -(long) pRowHeight[nRow] );
+ }
+
+ if (bShow)
+ pRowFlags[nRow] &= ~(CR_HIDDEN | CR_FILTERED);
+ else
+ pRowFlags[nRow] |= CR_HIDDEN;
+ if( !--nRecalcLvl )
+ SetDrawPageSize();
+
+ ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
+ if ( pCharts && pCharts->GetCount() )
+ pCharts->SetRangeDirty(ScRange( 0, nRow, nTab, MAXCOL, nRow, nTab ));
+ }
+ }
+ else
+ DBG_ERROR("Falsche Zeilennummer oder keine Flags");
+}
+
+
+void ScTable::DBShowRow(USHORT nRow, BOOL bShow)
+{
+ if (VALIDROW(nRow) && pRowFlags)
+ {
+ BOOL bWasVis = ( pRowFlags[nRow] & CR_HIDDEN ) == 0;
+ nRecalcLvl++;
+ if (bWasVis != bShow)
+ {
+ ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
+ if (pDrawLayer)
+ {
+ if (bShow)
+ pDrawLayer->HeightChanged( nTab, nRow, (long) pRowHeight[nRow] );
+ else
+ pDrawLayer->HeightChanged( nTab, nRow, -(long) pRowHeight[nRow] );
+ }
+ }
+
+ // Filter-Flag immer setzen, auch wenn Hidden unveraendert
+ if (bShow)
+ pRowFlags[nRow] &= ~(CR_HIDDEN | CR_FILTERED);
+ else
+ pRowFlags[nRow] |= (CR_HIDDEN | CR_FILTERED);
+ if( !--nRecalcLvl )
+ SetDrawPageSize();
+
+ if (bWasVis != bShow)
+ {
+ ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
+ if ( pCharts && pCharts->GetCount() )
+ pCharts->SetRangeDirty(ScRange( 0, nRow, nTab, MAXCOL, nRow, nTab ));
+ }
+ }
+ else
+ DBG_ERROR("Falsche Zeilennummer oder keine Flags");
+}
+
+
+void ScTable::DBShowRows(USHORT nRow1, USHORT nRow2, BOOL bShow)
+{
+ USHORT i;
+ USHORT nStartRow = nRow1;
+ nRecalcLvl++;
+ while (nStartRow <= nRow2)
+ {
+ USHORT nEndRow = nStartRow;
+ BYTE nOldFlag = pRowFlags[nStartRow] & CR_HIDDEN;
+ while ( nEndRow < nRow2 && (pRowFlags[nEndRow+1] & CR_HIDDEN) == nOldFlag )
+ ++nEndRow;
+
+ BOOL bWasVis = ( nOldFlag == 0 );
+ BOOL bChanged = ( bWasVis != bShow );
+ if ( bChanged )
+ {
+ ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
+ if (pDrawLayer)
+ {
+ long nHeight = 0;
+ for (i=nStartRow; i<=nEndRow; i++)
+ nHeight += pRowHeight[i];
+
+ if (bShow)
+ pDrawLayer->HeightChanged( nTab, nStartRow, nHeight );
+ else
+ pDrawLayer->HeightChanged( nTab, nStartRow, -nHeight );
+ }
+ }
+
+ if (bShow)
+ for (i=nStartRow; i<=nEndRow; i++)
+ pRowFlags[i] &= ~(CR_HIDDEN | CR_FILTERED);
+ else
+ for (i=nStartRow; i<=nEndRow; i++)
+ pRowFlags[i] |= (CR_HIDDEN | CR_FILTERED);
+
+ if ( bChanged )
+ {
+ ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
+ if ( pCharts && pCharts->GetCount() )
+ pCharts->SetRangeDirty(ScRange( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab ));
+ }
+
+ nStartRow = nEndRow + 1;
+ }
+ if( !--nRecalcLvl )
+ SetDrawPageSize();
+}
+
+
+void ScTable::ShowRows(USHORT nRow1, USHORT nRow2, BOOL bShow)
+{
+ USHORT i;
+ USHORT nStartRow = nRow1;
+ nRecalcLvl++;
+ while (nStartRow <= nRow2)
+ {
+ USHORT nEndRow = nStartRow;
+ BYTE nOldFlag = pRowFlags[nStartRow] & CR_HIDDEN;
+ while ( nEndRow < nRow2 && (pRowFlags[nEndRow+1] & CR_HIDDEN) == nOldFlag )
+ ++nEndRow;
+
+ BOOL bWasVis = ( nOldFlag == 0 );
+ BOOL bChanged = ( bWasVis != bShow );
+ if ( bChanged )
+ {
+ ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
+ if (pDrawLayer)
+ {
+ long nHeight = 0;
+ for (i=nStartRow; i<=nEndRow; i++)
+ nHeight += pRowHeight[i];
+
+ if (bShow)
+ pDrawLayer->HeightChanged( nTab, nStartRow, nHeight );
+ else
+ pDrawLayer->HeightChanged( nTab, nStartRow, -nHeight );
+ }
+ }
+
+ if (bShow)
+ for (i=nStartRow; i<=nEndRow; i++)
+ pRowFlags[i] &= ~(CR_HIDDEN | CR_FILTERED);
+ else
+ for (i=nStartRow; i<=nEndRow; i++)
+ pRowFlags[i] |= CR_HIDDEN;
+
+ if ( bChanged )
+ {
+ ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
+ if ( pCharts && pCharts->GetCount() )
+ pCharts->SetRangeDirty(ScRange( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab ));
+ }
+
+ nStartRow = nEndRow + 1;
+ }
+ if( !--nRecalcLvl )
+ SetDrawPageSize();
+}
+
+
+BOOL ScTable::IsFiltered(USHORT nRow) const
+{
+ if (VALIDROW(nRow) && pRowFlags)
+ return ( pRowFlags[nRow] & CR_FILTERED ) != 0;
+
+ DBG_ERROR("Falsche Zeilennummer oder keine Flags");
+ return FALSE;
+}
+
+
+void ScTable::SetColFlags( USHORT nCol, BYTE nNewFlags )
+{
+ if (VALIDCOL(nCol) && pColFlags)
+ pColFlags[nCol] = nNewFlags;
+ else
+ DBG_ERROR("Falsche Spaltennummer oder keine Flags");
+}
+
+
+void ScTable::SetRowFlags( USHORT nRow, BYTE nNewFlags )
+{
+ if (VALIDROW(nRow) && pRowFlags)
+ pRowFlags[nRow] = nNewFlags;
+ else
+ DBG_ERROR("Falsche Zeilennummer oder keine Flags");
+}
+
+
+BYTE ScTable::GetColFlags( USHORT nCol ) const
+{
+ if (VALIDCOL(nCol) && pColFlags)
+ return pColFlags[nCol];
+ else
+ return 0;
+}
+
+
+BYTE ScTable::GetRowFlags( USHORT nRow ) const
+{
+ if (VALIDROW(nRow) && pRowFlags)
+ return pRowFlags[nRow];
+ else
+ return 0;
+}
+
+
+USHORT ScTable::GetLastFlaggedCol() const
+{
+ if ( !pColFlags )
+ return 0;
+
+ USHORT nLastFound = 0;
+ for (USHORT nCol = 1; nCol <= MAXCOL; nCol++)
+ if ((pColFlags[nCol] & ~CR_PAGEBREAK) || (pColWidth[nCol] != STD_COL_WIDTH))
+ nLastFound = nCol;
+
+ return nLastFound;
+}
+
+
+USHORT ScTable::GetLastFlaggedRow() const
+{
+ if ( !pRowFlags )
+ return 0;
+
+ USHORT nLastFound = 0;
+ for (USHORT nRow = 1; nRow <= MAXROW; nRow++)
+ if ((pRowFlags[nRow] & ~CR_PAGEBREAK) || (pRowHeight[nRow] != ScGlobal::nStdRowHeight))
+ nLastFound = nRow;
+
+ return nLastFound;
+}
+
+
+BOOL ScTable::UpdateOutlineCol( USHORT nStartCol, USHORT nEndCol, BOOL bShow )
+{
+ if (pOutlineTable && pColFlags)
+ return pOutlineTable->GetColArray()->ManualAction( nStartCol, nEndCol, bShow, pColFlags );
+ else
+ return FALSE;
+}
+
+
+BOOL ScTable::UpdateOutlineRow( USHORT nStartRow, USHORT nEndRow, BOOL bShow )
+{
+ if (pOutlineTable && pRowFlags)
+ return pOutlineTable->GetRowArray()->ManualAction( nStartRow, nEndRow, bShow, pRowFlags );
+ else
+ return FALSE;
+}
+
+
+void ScTable::ExtendHidden( USHORT& rX1, USHORT& rY1, USHORT& rX2, USHORT& rY2 )
+{
+ if (pColFlags)
+ {
+ while ( rX1>0 ? (pColFlags[rX1-1] & CR_HIDDEN) : FALSE )
+ --rX1;
+ while ( rX2<MAXCOL ? (pColFlags[rX2+1] & CR_HIDDEN) : FALSE )
+ ++rX2;
+ }
+ if (pRowFlags)
+ {
+ while ( rY1>0 ? (pRowFlags[rY1-1] & CR_HIDDEN) : FALSE )
+ --rY1;
+ while ( rY2<MAXROW ? (pRowFlags[rY2+1] & CR_HIDDEN) : FALSE )
+ ++rY2;
+ }
+}
+
+
+void ScTable::StripHidden( USHORT& rX1, USHORT& rY1, USHORT& rX2, USHORT& rY2 )
+{
+ if (pColFlags)
+ {
+ while ( rX2>rX1 && (pColFlags[rX2] & CR_HIDDEN) )
+ --rX2;
+ while ( rX2>rX1 && (pColFlags[rX1] & CR_HIDDEN) )
+ ++rX1;
+ }
+ if (pRowFlags)
+ {
+ while ( rY2>rY1 && (pRowFlags[rY2] & CR_HIDDEN) )
+ --rY2;
+ while ( rY2>rY1 && (pRowFlags[rY1] & CR_HIDDEN) )
+ ++rY1;
+ }
+}
+
+
+// Auto-Outline
+
+inline short DiffSign( USHORT a, USHORT b )
+{
+ return (a<b) ? -1 :
+ (a>b) ? 1 : 0;
+}
+
+
+void ScTable::DoAutoOutline( USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow )
+{
+ BOOL bSizeChanged = FALSE;
+ BOOL bMissed = FALSE;
+
+ USHORT nCol;
+ USHORT nRow;
+ USHORT i;
+ BOOL bFound;
+ ScOutlineArray* pArray;
+ ScBaseCell* pCell;
+ ScRange aRef;
+/* ScPatternAttr aBoldPattern( pDocument->GetPool() ); //! spezielle Format-Vorlage
+ aBoldPattern.GetItemSet().Put( SvxWeightItem( WEIGHT_BOLD ) );
+*/
+
+ StartOutlineTable();
+
+ // Zeilen
+
+ USHORT nCount = nEndRow-nStartRow+1;
+ BOOL* pUsed = new BOOL[nCount];
+ for (i=0; i<nCount; i++)
+ pUsed[i] = FALSE;
+ for (nCol=nStartCol; nCol<=nEndCol; nCol++)
+ if (!aCol[nCol].IsEmptyData())
+ aCol[nCol].FindUsed( nStartRow, nEndRow, pUsed );
+
+ pArray = pOutlineTable->GetRowArray();
+ for (nRow=nStartRow; nRow<=nEndRow; nRow++)
+ if (pUsed[nRow-nStartRow])
+ {
+ bFound = FALSE;
+ for (nCol=nStartCol; nCol<=nEndCol && !bFound; nCol++)
+ if (!aCol[nCol].IsEmptyData())
+ {
+ pCell = aCol[nCol].GetCell( nRow );
+ if (pCell)
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ if (((ScFormulaCell*)pCell)->HasOneReference( aRef ))
+ if ( aRef.aStart.Col() == nCol && aRef.aEnd.Col() == nCol &&
+ aRef.aStart.Tab() == nTab && aRef.aEnd.Tab() == nTab &&
+ DiffSign( aRef.aStart.Row(), nRow ) ==
+ DiffSign( aRef.aEnd.Row(), nRow ) )
+ {
+ if (pArray->Insert( aRef.aStart.Row(), aRef.aEnd.Row(), bSizeChanged ))
+ {
+// ApplyPatternArea( nStartCol, nRow, nEndCol, nRow, aBoldPattern );
+ bFound = TRUE;
+ }
+ else
+ bMissed = TRUE;
+ }
+ }
+ }
+
+ delete[] pUsed;
+
+ // Spalten
+
+ pArray = pOutlineTable->GetColArray();
+ for (nCol=nStartCol; nCol<=nEndCol; nCol++)
+ {
+ if (!aCol[nCol].IsEmptyData())
+ {
+ bFound = FALSE;
+ ScColumnIterator aIter( &aCol[nCol], nStartRow, nEndRow );
+ while ( aIter.Next( nRow, pCell ) && !bFound )
+ {
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ if (((ScFormulaCell*)pCell)->HasOneReference( aRef ))
+ if ( aRef.aStart.Row() == nRow && aRef.aEnd.Row() == nRow &&
+ aRef.aStart.Tab() == nTab && aRef.aEnd.Tab() == nTab &&
+ DiffSign( aRef.aStart.Col(), nCol ) ==
+ DiffSign( aRef.aEnd.Col(), nCol ) )
+ {
+ if (pArray->Insert( aRef.aStart.Col(), aRef.aEnd.Col(), bSizeChanged ))
+ {
+// ApplyPatternArea( nCol, nStartRow, nCol, nEndRow, aBoldPattern );
+ bFound = TRUE;
+ }
+ else
+ bMissed = TRUE;
+ }
+ }
+ }
+ }
+}
+
+//
+// Datei-Operationen
+//
+
+// Laden
+
+BOOL ScTable::Load( SvStream& rStream, USHORT nVersion, ScProgress* pProgress )
+{
+ ScReadHeader aHdr( rStream );
+ USHORT i;
+
+ while (aHdr.BytesLeft() && rStream.GetError() == SVSTREAM_OK)
+ {
+ USHORT nID;
+ rStream >> nID;
+ switch (nID)
+ {
+ case SCID_COLUMNS: // Spalten (Daten)
+ {
+ ScMultipleReadHeader aColHdr( rStream );
+ if( nVersion >= SC_DATABYTES )
+ while( aColHdr.BytesLeft() )
+ {
+ BYTE nCol;
+ rStream >> nCol;
+ aCol[ nCol ].Load(rStream, aColHdr);
+ if (pProgress)
+ pProgress->SetState( rStream.Tell() );
+ }
+ else
+ for (i=0; i<=MAXCOL; i++)
+ {
+ aCol[i].Load(rStream, aColHdr);
+ if (pProgress)
+ pProgress->SetState( rStream.Tell() );
+ }
+ }
+ break;
+ case SCID_COLROWFLAGS: // Spalten-/Zeilenflags
+ {
+ ScReadHeader aFlagsHdr( rStream );
+
+ BYTE nFlags;
+ USHORT nVal;
+ short nRep;
+
+ i=0;
+ while (i<=MAXCOL)
+ {
+ rStream >> nRep;
+ rStream >> nVal;
+ while (nRep-- && i<=MAXCOL)
+ pColWidth[i++] = nVal;
+ }
+ DBG_ASSERT(nRep==-1, "Fehler bei Spaltenbreiten");
+ i=0;
+ while (i<=MAXCOL)
+ {
+ rStream >> nRep;
+ rStream >> nFlags;
+ while (nRep-- && i<=MAXCOL)
+ pColFlags[i++] = nFlags;
+ }
+ DBG_ASSERT(nRep==-1, "Fehler bei Spaltenflags");
+ if (pProgress)
+ pProgress->SetState( rStream.Tell() );
+
+ // aus der Datei immer soviele Zeilen laden, wie gespeichert wurden
+ USHORT nSrcMaxRow = pDocument->GetSrcMaxRow();
+
+ i=0;
+ while (i<=nSrcMaxRow) // nSrcMaxRow und MAXROW evtl. unterschiedlich
+ {
+ rStream >> nRep;
+ rStream >> nVal;
+ while (nRep--)
+ {
+ if (i<=MAXROW)
+ pRowHeight[i] = nVal;
+ ++i;
+ }
+ }
+ DBG_ASSERT(i==nSrcMaxRow+1, "Fehler bei Zeilenhoehen");
+ if (pProgress)
+ pProgress->SetState( rStream.Tell() );
+ i=0;
+ while (i<=nSrcMaxRow) // nSrcMaxRow und MAXROW evtl. unterschiedlich
+ {
+ rStream >> nRep;
+ rStream >> nFlags;
+ while (nRep--)
+ {
+ if (i<=MAXROW)
+ pRowFlags[i] = nFlags;
+ ++i;
+ }
+ }
+ DBG_ASSERT(i==nSrcMaxRow+1, "Fehler bei Zeilenflags");
+ if (pProgress)
+ pProgress->SetState( rStream.Tell() );
+ }
+ break;
+ case SCID_TABOPTIONS: // einzelne Einstellungen
+ {
+ ScReadHeader aFlagsHdr( rStream );
+
+ rStream.ReadByteString( aName, rStream.GetStreamCharSet() );
+
+ rStream >> bScenario;
+ rStream.ReadByteString( aComment, rStream.GetStreamCharSet() );
+
+ rStream >> bProtected;
+ rStream.ReadByteString( aProtectPass, rStream.GetStreamCharSet() );
+
+ BOOL bOutline;
+ rStream >> bOutline;
+ if (bOutline)
+ {
+ StartOutlineTable();
+ pOutlineTable->Load( rStream );
+ }
+
+ if ( aFlagsHdr.BytesLeft() )
+ {
+ SfxStyleSheetBasePool* pStylePool =
+ pDocument->GetStyleSheetPool();
+
+ rStream.ReadByteString( aPageStyle, rStream.GetStreamCharSet() );
+
+ if ( !pStylePool->Find( aPageStyle, SFX_STYLE_FAMILY_PAGE ) )
+ {
+ DBG_TRACE( "PageStyle not found. Using Standard." );
+ aPageStyle = ScGlobal::GetRscString(STR_STYLENAME_STANDARD);
+ }
+ }
+
+ if ( aFlagsHdr.BytesLeft() )
+ {
+ BOOL bOneRange; // einzelner Druckbereich ?
+ rStream >> bOneRange;
+ if ( bOneRange )
+ {
+ ScRange aRange;
+ rStream >> aRange;
+ SetPrintRangeCount( 1 );
+ SetPrintRange( 0, aRange );
+ }
+
+ lcl_LoadRange( rStream, &pRepeatColRange );
+ lcl_LoadRange( rStream, &pRepeatRowRange );
+ }
+
+ if ( aFlagsHdr.BytesLeft() )
+ rStream >> bVisible;
+
+ if ( aFlagsHdr.BytesLeft() ) // Druckbereiche ab Version 314c
+ {
+ USHORT nNewCount;
+ rStream >> nNewCount;
+ if ( nNewCount )
+ {
+ ScRange aTmp;
+ SetPrintRangeCount( nNewCount );
+ for (i=0; i<nNewCount; i++)
+ {
+ rStream >> aTmp;
+ SetPrintRange( i, aTmp );
+ }
+ }
+ }
+
+ if ( aFlagsHdr.BytesLeft() ) // erweiterte Szenario-Flags ab 5.0
+ {
+ rStream >> aScenarioColor;
+ rStream >> nScenarioFlags;
+ rStream >> bActiveScenario;
+ }
+ else if ( bScenario )
+ {
+ // Default fuer Szenarien aus alten Dateien??
+ // Wenn die alten Szenarien wirklich benutzt wurden,
+ // wuerde der Rahmen wahrscheinlich stoeren.
+
+ nScenarioFlags = SC_SCENARIO_COPYALL;
+ }
+
+ if (pProgress)
+ pProgress->SetState( rStream.Tell() );
+ }
+ break;
+ case SCID_TABLINK: // Verknuepfung
+ {
+ ScReadHeader aLinkHdr( rStream );
+
+ rStream >> nLinkMode;
+ rStream.ReadByteString( aLinkDoc, rStream.GetStreamCharSet() );
+ aLinkDoc = INetURLObject::RelToAbs( aLinkDoc );
+ rStream.ReadByteString( aLinkFlt, rStream.GetStreamCharSet() );
+ rStream.ReadByteString( aLinkTab, rStream.GetStreamCharSet() );
+
+ BOOL bRelURL;
+ if ( aLinkHdr.BytesLeft() )
+ rStream >> bRelURL;
+ else
+ bRelURL = FALSE;
+ // externer Tabellenname relativ zu absolut
+ if ( nLinkMode == SC_LINK_VALUE && bRelURL )
+ aName = ScGlobal::GetDocTabName( aLinkDoc, aLinkTab );
+
+ if ( aLinkHdr.BytesLeft() ) // ab 336 auch Filter-Optionen
+ rStream.ReadByteString( aLinkOpt, rStream.GetStreamCharSet() );
+ }
+ break;
+ default:
+ {
+ DBG_ERROR("unbekannter Sub-Record in ScTable::Load");
+ ScReadHeader aDummyHeader( rStream );
+ }
+ }
+ }
+
+ // Neuberechnungen
+
+ ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
+ if (pDrawLayer)
+ pDrawLayer->ScRenamePage( nTab, aName );
+
+ return TRUE;
+}
+
+// Speichern
+
+
+void lcl_SaveValue( SvStream& rStream, USHORT* pValue, USHORT nEnd )
+{
+ USHORT nPos = 0;
+ while (nPos<=nEnd)
+ {
+ USHORT nVal = pValue[nPos];
+ USHORT nNextPos = nPos+1;
+ while (nNextPos<=nEnd && pValue[nNextPos]==nVal)
+ ++nNextPos;
+ rStream << (USHORT)( nNextPos - nPos );
+ rStream << nVal;
+ nPos = nNextPos;
+ }
+}
+
+
+void lcl_SaveFlags( SvStream& rStream, BYTE* pValue, USHORT nEnd )
+{
+ USHORT nPos = 0;
+ while (nPos<=nEnd)
+ {
+ BYTE nVal = pValue[nPos] & CR_SAVEMASK;
+ USHORT nNextPos = nPos+1;
+ while (nNextPos<=nEnd && (pValue[nNextPos] & CR_SAVEMASK)==nVal)
+ ++nNextPos;
+ rStream << (USHORT)( nNextPos - nPos );
+ rStream << nVal;
+ nPos = nNextPos;
+ }
+}
+
+
+void lcl_LoadRange( SvStream& rStream, ScRange** ppRange )
+{
+ BOOL bIsSet = FALSE;
+
+ rStream >> bIsSet;
+
+ if ( bIsSet )
+ {
+ *ppRange = new ScRange;
+ rStream >> **ppRange;
+ }
+ else
+ *ppRange = NULL;
+}
+
+
+void lcl_SaveRange( SvStream& rStream, ScRange* pRange )
+{
+ if ( pRange )
+ {
+ rStream << (BOOL)TRUE;
+ rStream << *pRange;
+ }
+ else
+ rStream << (BOOL)FALSE;
+}
+
+
+BOOL ScTable::Save( SvStream& rStream, long& rSavedDocCells, ScProgress* pProgress ) const
+{
+ ScWriteHeader aHdr( rStream );
+ USHORT i;
+
+ // Spalten (Daten)
+
+ {
+ rStream << (USHORT) SCID_COLUMNS;
+ ScMultipleWriteHeader aColHdr( rStream );
+
+ for (i=0; i<=MAXCOL; i++)
+ {
+ const ScColumn* pCol = &aCol[ i ];
+ if( !pCol->IsEmptyData() || pCol->NoteCount() || !pCol->IsEmptyAttr())
+ {
+ rStream << (BYTE) i;
+ aCol[i].Save(rStream, aColHdr);
+ rSavedDocCells += aCol[i].GetWeightedCount();
+ if (pProgress)
+ pProgress->SetState( rSavedDocCells );
+ }
+ }
+ }
+
+ // Spalten-/Zeilenflags
+
+ {
+ rStream << (USHORT) SCID_COLROWFLAGS;
+ ScWriteHeader aFlagsHdr( rStream );
+
+ USHORT nSaveMaxRow = pDocument->GetSrcMaxRow();
+
+ lcl_SaveValue( rStream, pColWidth, MAXCOL );
+ lcl_SaveFlags( rStream, pColFlags, MAXCOL );
+ lcl_SaveValue( rStream, pRowHeight,nSaveMaxRow );
+ lcl_SaveFlags( rStream, pRowFlags, nSaveMaxRow );
+
+ // wenn dabei weniger Zeilenhoehen als vorhanden gespeichert wurden,
+ // gibt das noch keine Warnung wegen Datenverlust.
+ }
+
+ BOOL bRelURL = FALSE;
+ String aLinkDocSaveName( aLinkDoc );
+ String aSaveName( aName );
+ if ( nLinkMode )
+ {
+ aLinkDocSaveName = INetURLObject::AbsToRel( aLinkDocSaveName );
+ aLinkDocSaveName = INetURLObject::decode( aLinkDocSaveName,
+ INET_HEX_ESCAPE, INetURLObject::DECODE_UNAMBIGUOUS );
+ if ( ScGlobal::pScInternational->CompareEqual(
+ aLinkDocSaveName,
+ INetURLObject::decode( aLinkDoc, INET_HEX_ESCAPE,
+ INetURLObject::DECODE_UNAMBIGUOUS ), INTN_COMPARE_IGNORECASE ) )
+ {
+ aSaveName = INetURLObject::decode( aSaveName,
+ INET_HEX_ESCAPE, INetURLObject::DECODE_UNAMBIGUOUS );
+ }
+ else
+ {
+ bRelURL = TRUE;
+ // Reference to external sheet, only the sheet name is stored
+ // instead of the absolute DocTabName, will be reconcatenated upon
+ // load time.
+ if ( nLinkMode == SC_LINK_VALUE )
+ aSaveName = aLinkTab;
+ }
+ }
+
+ // einzelne Einstellungen
+
+ {
+ rStream << (USHORT) SCID_TABOPTIONS;
+ ScWriteHeader aFlagsHdr( rStream );
+
+ rStream.WriteByteString( aSaveName, rStream.GetStreamCharSet() );
+
+ rStream << bScenario;
+ rStream.WriteByteString( aComment, rStream.GetStreamCharSet() );
+
+ rStream << bProtected;
+ rStream.WriteByteString( aProtectPass, rStream.GetStreamCharSet() );
+
+ BOOL bOutline = ( pOutlineTable != NULL );
+ rStream << bOutline;
+ if (bOutline)
+ pOutlineTable->Store( rStream );
+
+ rStream.WriteByteString( aPageStyle, rStream.GetStreamCharSet() );
+
+ if ( pPrintRanges && nPrintRangeCount == 1 ) // kompatibel zu alten Versionen
+ lcl_SaveRange( rStream, pPrintRanges ); // (nur wenn genau ein Bereich)
+ else
+ lcl_SaveRange( rStream, NULL );
+ lcl_SaveRange( rStream, pRepeatColRange );
+ lcl_SaveRange( rStream, pRepeatRowRange );
+
+ rStream << bVisible;
+
+ if ( pPrintRanges && nPrintRangeCount>1 ) // einzelner Bereich schon oben
+ {
+ rStream << nPrintRangeCount; // ab Version 314c
+ if ( nPrintRangeCount > 1 )
+ for ( i=0; i<nPrintRangeCount; i++)
+ rStream << pPrintRanges[i];
+ }
+ else
+ rStream << (USHORT) 0;
+
+ if( rStream.GetVersion() > SOFFICE_FILEFORMAT_40 ) // erweiterte Szenario-Flags ab 5.0
+ {
+ rStream << aScenarioColor;
+ rStream << nScenarioFlags;
+ rStream << bActiveScenario;
+ }
+ }
+
+ // Verknuepfung
+
+ if (nLinkMode)
+ {
+ rStream << (USHORT) SCID_TABLINK;
+ ScWriteHeader aLinkHdr( rStream );
+
+ // Hack, um verknuepfte Tabellen mit der 3.1 laden zu koennen (#35242#)
+ // bei 3.1 Export Filter von "StarCalc 4.0" auf "StarCalc 3.0" umsetzen
+ // (4.0 Dateien koennen vom Calc 3.1 gelesen werden)
+ String aSaveFlt = aLinkFlt;
+ if ( rStream.GetVersion() == SOFFICE_FILEFORMAT_31 && aSaveFlt.EqualsAscii("StarCalc 4.0") )
+ aSaveFlt.AssignAscii(RTL_CONSTASCII_STRINGPARAM("StarCalc 3.0"));
+
+ rStream << nLinkMode;
+ rStream.WriteByteString( aLinkDocSaveName, rStream.GetStreamCharSet() );
+ rStream.WriteByteString( aSaveFlt, rStream.GetStreamCharSet() );
+ rStream.WriteByteString( aLinkTab, rStream.GetStreamCharSet() );
+ rStream << bRelURL;
+ rStream.WriteByteString( aLinkOpt, rStream.GetStreamCharSet() );
+ }
+
+ return TRUE;
+}
+
+
+ // CopyData - fuer Query in anderen Bereich
+
+void ScTable::CopyData( USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow,
+ USHORT nDestCol, USHORT nDestRow, USHORT nDestTab )
+{
+ //! wenn fuer mehrere Zeilen benutzt, nach Spalten optimieren!
+
+ ScAddress aSrc( nStartCol, nStartRow, nTab );
+ ScAddress aDest( nDestCol, nDestRow, nDestTab );
+ ScRange aRange( aSrc, aDest );
+ BOOL bThisTab = ( nDestTab == nTab );
+ USHORT nDestY = nDestRow;
+ for (USHORT nRow=nStartRow; nRow<=nEndRow; nRow++)
+ {
+ aSrc.SetRow( nRow );
+ aDest.SetRow( nDestY );
+ USHORT nDestX = nDestCol;
+ for (USHORT nCol=nStartCol; nCol<=nEndCol; nCol++)
+ {
+ aSrc.SetCol( nCol );
+ aDest.SetCol( nDestX );
+ ScBaseCell* pCell = GetCell( nCol, nRow );
+ if (pCell)
+ {
+ pCell = pCell->Clone(pDocument);
+ if (pCell->GetCellType() == CELLTYPE_FORMULA)
+ {
+ ((ScFormulaCell*)pCell)->UpdateReference( URM_COPY, aRange,
+ ((short) nDestCol) - ((short) nStartCol),
+ ((short) nDestRow) - ((short) nStartRow),
+ ((short) nDestTab) - ((short) nTab) );
+ ((ScFormulaCell*)pCell)->aPos = aDest;
+ }
+ }
+ if (bThisTab)
+ {
+ PutCell( nDestX, nDestY, pCell );
+ SetPattern( nDestX, nDestY, *GetPattern( nCol, nRow ), TRUE );
+ }
+ else
+ {
+ pDocument->PutCell( aDest, pCell );
+ pDocument->SetPattern( aDest, *GetPattern( nCol, nRow ), TRUE );
+ }
+
+ ++nDestX;
+ }
+ ++nDestY;
+ }
+}
+
+
+BOOL ScTable::RefVisible(ScFormulaCell* pCell)
+{
+ ScRange aRef;
+
+ if (pCell->HasOneReference(aRef))
+ {
+ if (aRef.aStart.Col()==aRef.aEnd.Col() && aRef.aStart.Tab()==aRef.aEnd.Tab() && pRowFlags)
+ {
+ for (USHORT nRow=aRef.aStart.Row(); nRow<=aRef.aEnd.Row(); nRow++)
+ if ( (pRowFlags[nRow] & CR_FILTERED) == 0 )
+ return TRUE; // Teil sichtbar
+ return FALSE; // alles unsichtbar
+ }
+ }
+
+ return TRUE; // irgendwie anders
+}
+
+
+void ScTable::GetUpperCellString(USHORT nCol, USHORT nRow, String& rStr)
+{
+ GetInputString(nCol, nRow, rStr);
+ rStr.EraseTrailingChars();
+ rStr.EraseLeadingChars();
+ ScGlobal::pCharClass->toUpper(rStr);
+}
+
+
+// Berechnen der Groesse der Tabelle und setzen der Groesse an der DrawPage
+
+void ScTable::SetDrawPageSize()
+{
+ ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
+ if( pDrawLayer )
+ {
+ ULONG x = GetColOffset( MAXCOL + 1 );
+ ULONG y = GetRowOffset( MAXROW + 1 );
+ x = (ULONG) ((double) x * HMM_PER_TWIPS);
+ y = (ULONG) ((double) y * HMM_PER_TWIPS);
+ pDrawLayer->SetPageSize( nTab, Size( x, y ) );
+ }
+}
+
+
+ULONG ScTable::GetRowOffset( USHORT nRow ) const
+{
+ ULONG n = 0;
+ if ( pRowFlags && pRowHeight )
+ {
+ USHORT i;
+ BYTE* pFlags = pRowFlags;
+ USHORT* pHeight = pRowHeight;
+ for( i = 0; i < nRow; i++, pFlags++, pHeight++ )
+ if( !( *pFlags & CR_HIDDEN ) )
+ n += *pHeight;
+ }
+ else
+ DBG_ERROR("GetRowOffset: Daten fehlen");
+ return n;
+}
+
+
+ULONG ScTable::GetColOffset( USHORT nCol ) const
+{
+ ULONG n = 0;
+ if ( pColFlags && pColWidth )
+ {
+ USHORT i;
+ BYTE* pFlags = pColFlags;
+ USHORT* pWidth = pColWidth;
+ for( i = 0; i < nCol; i++, pFlags++, pWidth++ )
+ if( !( *pFlags & CR_HIDDEN ) )
+ n += *pWidth;
+ }
+ else
+ DBG_ERROR("GetColumnOffset: Daten fehlen");
+ return n;
+}
+
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
new file mode 100644
index 000000000000..9ee0a48e150d
--- /dev/null
+++ b/sc/source/core/data/table3.cxx
@@ -0,0 +1,1611 @@
+/*************************************************************************
+ *
+ * $RCSfile: table3.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <tools/solmath.hxx>
+#include <svtools/txtcmp.hxx>
+#include <svtools/zforlist.hxx>
+#include <unotools/charclass.hxx>
+#include <stdlib.h>
+
+#include "table.hxx"
+#include "scitems.hxx"
+#include "collect.hxx"
+#include "attrib.hxx"
+#include "cell.hxx"
+#include "document.hxx"
+#include "globstr.hrc"
+#include "global.hxx"
+#include "stlpool.hxx"
+#include "compiler.hxx"
+#include "patattr.hxx"
+#include "subtotal.hxx"
+#include "docoptio.hxx"
+#include "markdata.hxx"
+#include "rangelst.hxx"
+#include "attarray.hxx"
+#include "userlist.hxx"
+#include "progress.hxx"
+
+// STATIC DATA -----------------------------------------------------------
+
+const USHORT nMaxSorts = 3; // maximale Anzahl Sortierkriterien in aSortParam
+
+struct ScSortInfo
+{
+ ScBaseCell* pCell;
+ USHORT nOrg;
+ DECL_FIXEDMEMPOOL_NEWDEL( ScSortInfo );
+};
+const USHORT nMemPoolSortInfo = (0x8000 - 64) / sizeof(ScSortInfo);
+IMPL_FIXEDMEMPOOL_NEWDEL( ScSortInfo, nMemPoolSortInfo, nMemPoolSortInfo );
+
+// END OF STATIC DATA -----------------------------------------------------
+
+
+class ScSortInfoArray
+{
+private:
+ ScSortInfo** pppInfo[nMaxSorts];
+ USHORT nCount;
+ USHORT nStart;
+ USHORT nUsedSorts;
+
+public:
+ ScSortInfoArray( USHORT nSorts, USHORT nInd1, USHORT nInd2 ) :
+ nCount( nInd2 - nInd1 + 1 ), nStart( nInd1 ),
+ nUsedSorts( Min( nSorts, nMaxSorts ) )
+ {
+ for ( USHORT nSort = 0; nSort < nUsedSorts; nSort++ )
+ {
+ ScSortInfo** ppInfo = new ScSortInfo* [nCount];
+ for ( USHORT j = 0; j < nCount; j++ )
+ ppInfo[j] = new ScSortInfo;
+ pppInfo[nSort] = ppInfo;
+ }
+ }
+ ~ScSortInfoArray()
+ {
+ for ( USHORT nSort = 0; nSort < nUsedSorts; nSort++ )
+ {
+ ScSortInfo** ppInfo = pppInfo[nSort];
+ for ( USHORT j = 0; j < nCount; j++ )
+ delete ppInfo[j];
+ delete [] ppInfo;
+ }
+ }
+ ScSortInfo* Get( USHORT nSort, USHORT nInd )
+ { return (pppInfo[nSort])[ nInd - nStart ]; }
+ void Swap( USHORT nInd1, USHORT nInd2 )
+ {
+ USHORT n1 = nInd1 - nStart;
+ USHORT n2 = nInd2 - nStart;
+ for ( USHORT nSort = 0; nSort < nUsedSorts; nSort++ )
+ {
+ ScSortInfo** ppInfo = pppInfo[nSort];
+ ScSortInfo* pTmp = ppInfo[n1];
+ ppInfo[n1] = ppInfo[n2];
+ ppInfo[n2] = pTmp;
+ }
+ }
+ USHORT GetUsedSorts() { return nUsedSorts; }
+ ScSortInfo** GetFirstArray() { return pppInfo[0]; }
+ USHORT GetStart() { return nStart; }
+ USHORT GetCount() { return nCount; }
+};
+
+ScSortInfoArray* ScTable::CreateSortInfoArray( USHORT nInd1, USHORT nInd2 )
+{
+ USHORT nUsedSorts = 1;
+ while ( nUsedSorts < nMaxSorts && aSortParam.bDoSort[nUsedSorts] )
+ nUsedSorts++;
+ ScSortInfoArray* pArray = new ScSortInfoArray( nUsedSorts, nInd1, nInd2 );
+ if ( aSortParam.bByRow )
+ {
+ for ( USHORT nSort = 0; nSort < nUsedSorts; nSort++ )
+ {
+ USHORT nCol = aSortParam.nField[nSort];
+ ScColumn* pCol = &aCol[nCol];
+ for ( USHORT nRow = nInd1; nRow <= nInd2; nRow++ )
+ {
+//2do: FillSortInfo an ScColumn und Array abklappern statt Search in GetCell
+ ScSortInfo* pInfo = pArray->Get( nSort, nRow );
+ pInfo->pCell = pCol->GetCell( nRow );
+ pInfo->nOrg = nRow;
+ }
+ }
+ }
+ else
+ {
+ for ( USHORT nSort = 0; nSort < nUsedSorts; nSort++ )
+ {
+ USHORT nRow = aSortParam.nField[nSort];
+ for ( USHORT nCol = nInd1; nCol <= nInd2; nCol++ )
+ {
+ ScSortInfo* pInfo = pArray->Get( nSort, nCol );
+ pInfo->pCell = GetCell( nCol, nRow );
+ pInfo->nOrg = nCol;
+ }
+ }
+ }
+ return pArray;
+}
+
+void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress& rProgress )
+{
+ BOOL bByRow = aSortParam.bByRow;
+ USHORT nCount = pArray->GetCount();
+ ScSortInfo** ppInfo = pArray->GetFirstArray();
+ Table aTable( nCount );
+ USHORT nPos;
+ for ( nPos = 0; nPos < nCount; nPos++ )
+ {
+ aTable.Insert( ppInfo[nPos]->nOrg, (void*) ppInfo[nPos] );
+ }
+ USHORT nDest = pArray->GetStart();
+ for ( nPos = 0; nPos < nCount; nPos++, nDest++ )
+ {
+ USHORT nOrg = ppInfo[nPos]->nOrg;
+ if ( nDest != nOrg )
+ {
+ if ( bByRow )
+ SwapRow( nDest, nOrg );
+ else
+ SwapCol( nDest, nOrg );
+ // neue Position des weggeswapten eintragen
+ ScSortInfo* p = ppInfo[nPos];
+ p->nOrg = nDest;
+ p = (ScSortInfo*) aTable.Replace( nDest, (void*) p );
+ p->nOrg = nOrg;
+ p = (ScSortInfo*) aTable.Replace( nOrg, (void*) p );
+ DBG_ASSERT( p == ppInfo[nPos], "SortReorder: nOrg MisMatch" );
+ }
+ rProgress.SetStateOnPercent( nPos );
+ }
+}
+
+short ScTable::CompareCell( USHORT nSort,
+ ScBaseCell* pCell1, USHORT nCell1Col, USHORT nCell1Row,
+ ScBaseCell* pCell2, USHORT nCell2Col, USHORT nCell2Row )
+{
+ short nRes = 0;
+
+ CellType eType1, eType2;
+ if (pCell1)
+ {
+ eType1 = pCell1->GetCellType();
+ if (eType1 == CELLTYPE_NOTE)
+ pCell1 = NULL;
+ }
+ if (pCell2)
+ {
+ eType2 = pCell2->GetCellType();
+ if (eType2 == CELLTYPE_NOTE)
+ pCell2 = NULL;
+ }
+
+ if (pCell1)
+ {
+ if (pCell2)
+ {
+ BOOL bStr1 = ( eType1 != CELLTYPE_VALUE );
+ if ( eType1 == CELLTYPE_FORMULA && ((ScFormulaCell*)pCell1)->IsValue() )
+ bStr1 = FALSE;
+ BOOL bStr2 = ( eType2 != CELLTYPE_VALUE );
+ if ( eType2 == CELLTYPE_FORMULA && ((ScFormulaCell*)pCell2)->IsValue() )
+ bStr2 = FALSE;
+
+ if ( bStr1 && bStr2 ) // nur Strings untereinander als String vergleichen!
+ {
+ StringCompare eCompare;
+ String aStr1;
+ String aStr2;
+ if (eType1 == CELLTYPE_STRING)
+ ((ScStringCell*)pCell1)->GetString(aStr1);
+ else
+ GetString(nCell1Col, nCell1Row, aStr1);
+ if (eType2 == CELLTYPE_STRING)
+ ((ScStringCell*)pCell2)->GetString(aStr2);
+ else
+ GetString(nCell2Col, nCell2Row, aStr2);
+ BOOL bUserDef = aSortParam.bUserDef;
+ if (bUserDef)
+ {
+ ScUserListData* pData =
+ (ScUserListData*)(ScGlobal::GetUserList()->At(
+ aSortParam.nUserIndex));
+ if (pData)
+ {
+ if ( aSortParam.bCaseSens )
+ eCompare = pData->Compare(aStr1, aStr2);
+ else
+ eCompare = pData->ICompare(aStr1, aStr2);
+ }
+ else
+ bUserDef = FALSE;
+
+ }
+ if (!bUserDef)
+ {
+ eCompare = ScGlobal::pScInternational->Compare(
+ aStr1, aStr2, (aSortParam.bCaseSens ? 0 : INTN_COMPARE_IGNORECASE) );
+ }
+ if (eCompare == COMPARE_LESS)
+ nRes = -1;
+ else if (eCompare == COMPARE_GREATER)
+ nRes = 1;
+ }
+ else if ( bStr1 ) // String <-> Zahl
+ nRes = 1; // Zahl vorne
+ else if ( bStr2 ) // Zahl <-> String
+ nRes = -1; // Zahl vorne
+ else // Zahlen untereinander
+ {
+ double nVal1;
+ double nVal2;
+ if (eType1 == CELLTYPE_VALUE)
+ nVal1 = ((ScValueCell*)pCell1)->GetValue();
+ else if (eType1 == CELLTYPE_FORMULA)
+ nVal1 = ((ScFormulaCell*)pCell1)->GetValue();
+ else
+ nVal1 = 0;
+ if (eType2 == CELLTYPE_VALUE)
+ nVal2 = ((ScValueCell*)pCell2)->GetValue();
+ else if (eType2 == CELLTYPE_FORMULA)
+ nVal2 = ((ScFormulaCell*)pCell2)->GetValue();
+ else
+ nVal2 = 0;
+ if (nVal1 < nVal2)
+ nRes = -1;
+ else if (nVal1 > nVal2)
+ nRes = 1;
+ }
+ if ( !aSortParam.bAscending[nSort] )
+ nRes = -nRes;
+ }
+ else
+ nRes = -1;
+ }
+ else
+ {
+ if ( pCell2 )
+ nRes = 1;
+ else
+ nRes = 0; // beide leer
+ }
+ return nRes;
+}
+
+short ScTable::Compare( ScSortInfoArray* pArray, USHORT nIndex1, USHORT nIndex2 )
+{
+ short nRes;
+ USHORT nSort = 0;
+ do
+ {
+ ScSortInfo* pInfo1 = pArray->Get( nSort, nIndex1 );
+ ScSortInfo* pInfo2 = pArray->Get( nSort, nIndex2 );
+ if ( aSortParam.bByRow )
+ nRes = CompareCell( nSort,
+ pInfo1->pCell, aSortParam.nField[nSort], pInfo1->nOrg,
+ pInfo2->pCell, aSortParam.nField[nSort], pInfo2->nOrg );
+ else
+ nRes = CompareCell( nSort,
+ pInfo1->pCell, pInfo1->nOrg, aSortParam.nField[nSort],
+ pInfo2->pCell, pInfo2->nOrg, aSortParam.nField[nSort] );
+ } while ( nRes == 0 && ++nSort < pArray->GetUsedSorts() );
+ return nRes;
+}
+
+void ScTable::QuickSort( ScSortInfoArray* pArray, short nLo, short nHi )
+{
+ if ((nHi - nLo) == 1)
+ {
+ if (Compare(pArray, nLo, nHi) > 0)
+ pArray->Swap( nLo, nHi );
+ }
+ else
+ {
+ short ni = nLo;
+ short nj = nHi;
+ do
+ {
+ while ((ni <= nHi) && (Compare(pArray, ni, nLo)) < 0)
+ ni++;
+ while ((nj >= nLo) && (Compare(pArray, nLo, nj)) < 0)
+ nj--;
+ if (ni <= nj)
+ {
+ if (ni != nj)
+ pArray->Swap( ni, nj );
+ ni++;
+ nj--;
+ }
+ } while (ni < nj);
+ if ((nj - nLo) < (nHi - ni))
+ {
+ if (nLo < nj)
+ QuickSort(pArray, nLo, nj);
+ if (ni < nHi)
+ QuickSort(pArray, ni, nHi);
+ }
+ else
+ {
+ if (ni < nHi)
+ QuickSort(pArray, ni, nHi);
+ if (nLo < nj)
+ QuickSort(pArray, nLo, nj);
+ }
+ }
+}
+
+void ScTable::SwapCol(USHORT nCol1, USHORT nCol2)
+{
+ for (USHORT nRow = aSortParam.nRow1; nRow <= aSortParam.nRow2; nRow++)
+ {
+ aCol[nCol1].SwapCell(nRow, aCol[nCol2]);
+ if (aSortParam.bIncludePattern)
+ {
+ const ScPatternAttr* pPat1 = GetPattern(nCol1, nRow);
+ const ScPatternAttr* pPat2 = GetPattern(nCol2, nRow);
+ if (pPat1 != pPat2)
+ {
+ SetPattern(nCol1, nRow, *pPat2, TRUE);
+ SetPattern(nCol2, nRow, *pPat1, TRUE);
+ }
+ }
+ }
+}
+
+void ScTable::SwapRow(USHORT nRow1, USHORT nRow2)
+{
+ for (USHORT nCol = aSortParam.nCol1; nCol <= aSortParam.nCol2; nCol++)
+ {
+ aCol[nCol].SwapRow(nRow1, nRow2);
+ if (aSortParam.bIncludePattern)
+ {
+ const ScPatternAttr* pPat1 = GetPattern(nCol, nRow1);
+ const ScPatternAttr* pPat2 = GetPattern(nCol, nRow2);
+ if (pPat1 != pPat2)
+ {
+ SetPattern(nCol, nRow1, *pPat2, TRUE);
+ SetPattern(nCol, nRow2, *pPat1, TRUE);
+ }
+ }
+ }
+ if (bGlobalKeepQuery && pRowFlags)
+ {
+ BYTE nFlags1 = pRowFlags[nRow1] & ( CR_HIDDEN | CR_FILTERED );
+ BYTE nFlags2 = pRowFlags[nRow2] & ( CR_HIDDEN | CR_FILTERED );
+ pRowFlags[nRow1] = (pRowFlags[nRow1] & ~( CR_HIDDEN | CR_FILTERED )) | nFlags2;
+ pRowFlags[nRow2] = (pRowFlags[nRow2] & ~( CR_HIDDEN | CR_FILTERED )) | nFlags1;
+ }
+}
+
+short ScTable::Compare(USHORT nIndex1, USHORT nIndex2)
+{
+ short nRes;
+ USHORT nSort = 0;
+ if (aSortParam.bByRow)
+ {
+ do
+ {
+ USHORT nCol = aSortParam.nField[nSort];
+ ScBaseCell* pCell1 = aCol[nCol].GetCell( nIndex1 );
+ ScBaseCell* pCell2 = aCol[nCol].GetCell( nIndex2 );
+ nRes = CompareCell( nSort, pCell1, nCol, nIndex1, pCell2, nCol, nIndex2 );
+ } while ( nRes == 0 && ++nSort < nMaxSorts && aSortParam.bDoSort[nSort] );
+ }
+ else
+ {
+ do
+ {
+ USHORT nRow = aSortParam.nField[nSort];
+ ScBaseCell* pCell1 = aCol[nIndex1].GetCell( nRow );
+ ScBaseCell* pCell2 = aCol[nIndex2].GetCell( nRow );
+ nRes = CompareCell( nSort, pCell1, nIndex1, nRow, pCell2, nIndex2, nRow );
+ } while ( nRes == 0 && ++nSort < nMaxSorts && aSortParam.bDoSort[nSort] );
+ }
+ return nRes;
+}
+
+BOOL ScTable::IsSorted( USHORT nStart, USHORT nEnd ) // ueber aSortParam
+{
+ for (USHORT i=nStart; i<nEnd; i++)
+ {
+ if (Compare( i, i+1 ) > 0)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void ScTable::DecoladeRow( ScSortInfoArray* pArray, USHORT nRow1, USHORT nRow2 )
+{
+ USHORT nRow;
+ USHORT nMax = nRow2 - nRow1;
+ for (USHORT i = nRow1; (i + 4) <= nRow2; i += 4)
+ {
+ nRow = rand() % nMax;
+ pArray->Swap(i, nRow1 + nRow);
+ }
+}
+
+void ScTable::Sort(const ScSortParam& rSortParam, BOOL bKeepQuery)
+{
+ memmove( &aSortParam, &rSortParam, sizeof(ScSortParam) );
+ bGlobalKeepQuery = bKeepQuery;
+ if (rSortParam.bByRow)
+ {
+ USHORT nLastRow = 0;
+ for (USHORT nCol = aSortParam.nCol1; nCol <= aSortParam.nCol2; nCol++)
+ nLastRow = Max(nLastRow, aCol[nCol].GetLastDataPos());
+ nLastRow = Min(nLastRow, aSortParam.nRow2);
+ USHORT nRow1 = (rSortParam.bHasHeader ?
+ aSortParam.nRow1 + 1 : aSortParam.nRow1);
+ if (!IsSorted(nRow1, nLastRow))
+ {
+ ScProgress aProgress( pDocument->GetDocumentShell(),
+ ScGlobal::GetRscString(STR_PROGRESS_SORTING), nLastRow - nRow1 );
+ ScSortInfoArray* pArray = CreateSortInfoArray( nRow1, nLastRow );
+ if ( nLastRow - nRow1 > 255 )
+ DecoladeRow( pArray, nRow1, nLastRow );
+ QuickSort( pArray, nRow1, nLastRow );
+ SortReorder( pArray, aProgress );
+ delete pArray;
+ }
+ }
+ else
+ {
+ USHORT nLastCol;
+ for (nLastCol = aSortParam.nCol2;
+ (nLastCol > aSortParam.nCol1) && aCol[nLastCol].IsEmptyBlock(aSortParam.nRow1, aSortParam.nRow2); nLastCol--)
+ {
+ }
+ USHORT nCol1 = (rSortParam.bHasHeader ?
+ aSortParam.nCol1 + 1 : aSortParam.nCol1);
+ if (!IsSorted(nCol1, nLastCol))
+ {
+ ScProgress aProgress( pDocument->GetDocumentShell(),
+ ScGlobal::GetRscString(STR_PROGRESS_SORTING), nLastCol - nCol1 );
+ ScSortInfoArray* pArray = CreateSortInfoArray( nCol1, nLastCol );
+ QuickSort( pArray, nCol1, nLastCol );
+ SortReorder( pArray, aProgress );
+ delete pArray;
+ }
+ }
+}
+
+
+// Testen, ob beim Loeschen von Zwischenergebnissen andere Daten mit geloescht werden
+// (fuer Hinweis-Box)
+
+BOOL ScTable::TestRemoveSubTotals( const ScSubTotalParam& rParam )
+{
+ USHORT nStartCol = rParam.nCol1;
+ USHORT nStartRow = rParam.nRow1 + 1; // Header
+ USHORT nEndCol = rParam.nCol2;
+ USHORT nEndRow = rParam.nRow2;
+
+ USHORT nCol;
+ USHORT nRow;
+ ScBaseCell* pCell;
+
+ BOOL bWillDelete = FALSE;
+ for ( nCol=nStartCol; nCol<=nEndCol && !bWillDelete; nCol++ )
+ {
+ ScColumnIterator aIter( &aCol[nCol],nStartRow,nEndRow );
+ while ( aIter.Next( nRow, pCell ) && !bWillDelete )
+ {
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ if (((ScFormulaCell*)pCell)->IsSubTotal())
+ {
+ for (USHORT nTestCol=0; nTestCol<=MAXCOL; nTestCol++)
+ if (nTestCol<nStartCol || nTestCol>nEndCol)
+ if (aCol[nTestCol].HasDataAt(nRow))
+ bWillDelete = TRUE;
+ }
+ }
+ }
+ return bWillDelete;
+}
+
+// alte Ergebnisse loeschen
+// rParam.nRow2 wird veraendert !
+
+void ScTable::RemoveSubTotals( ScSubTotalParam& rParam )
+{
+ USHORT nStartCol = rParam.nCol1;
+ USHORT nStartRow = rParam.nRow1 + 1; // Header
+ USHORT nEndCol = rParam.nCol2;
+ USHORT nEndRow = rParam.nRow2; // wird veraendert
+
+ USHORT nCol;
+ USHORT nRow;
+ ScBaseCell* pCell;
+
+ for ( nCol=nStartCol; nCol<=nEndCol; nCol++ )
+ {
+ ScColumnIterator aIter( &aCol[nCol],nStartRow,nEndRow );
+ while ( aIter.Next( nRow, pCell ) )
+ {
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ if (((ScFormulaCell*)pCell)->IsSubTotal())
+ {
+ SetRowFlags(nRow+1,GetRowFlags(nRow+1)&(~CR_MANUALBREAK));
+ pDocument->DeleteRow( 0,nTab, MAXCOL,nTab, nRow, 1 );
+ --nEndRow;
+ aIter = ScColumnIterator( &aCol[nCol],nRow,nEndRow );
+ }
+ }
+ }
+
+ rParam.nRow2 = nEndRow; // neues Ende
+}
+
+// harte Zahlenformate loeschen (fuer Ergebnisformeln)
+
+void lcl_RemoveNumberFormat( ScTable* pTab, USHORT nCol, USHORT nRow )
+{
+ const ScPatternAttr* pPattern = pTab->GetPattern( nCol, nRow );
+ if ( pPattern->GetItemSet().GetItemState( ATTR_VALUE_FORMAT, FALSE )
+ == SFX_ITEM_SET )
+ {
+ ScPatternAttr aNewPattern( *pPattern );
+ SfxItemSet& rSet = aNewPattern.GetItemSet();
+ rSet.ClearItem( ATTR_VALUE_FORMAT );
+ rSet.ClearItem( ATTR_LANGUAGE_FORMAT );
+ pTab->SetPattern( nCol, nRow, aNewPattern, TRUE );
+ }
+}
+
+// neue Zwischenergebnisse
+// rParam.nRow2 wird veraendert !
+
+BOOL ScTable::DoSubTotals( ScSubTotalParam& rParam )
+{
+ USHORT nStartCol = rParam.nCol1;
+ USHORT nStartRow = rParam.nRow1 + 1; // Header
+ USHORT nEndCol = rParam.nCol2;
+ USHORT nEndRow = rParam.nRow2; // wird veraendert
+ USHORT i;
+
+ // Leerzeilen am Ende weglassen,
+ // damit alle Ueberlaeufe (MAXROW) bei InsertRow gefunden werden (#35180#)
+ // Wenn sortiert wurde, sind alle Leerzeilen am Ende.
+ USHORT nEmpty = GetEmptyLinesInBlock( nStartCol, nStartRow, nEndCol, nEndRow, DIR_BOTTOM );
+ nEndRow -= nEmpty;
+
+ USHORT nLevelCount = 0; // Anzahl Gruppierungen
+ BOOL bDoThis = TRUE;
+ for (i=0; i<MAXSUBTOTAL && bDoThis; i++)
+ if (rParam.bGroupActive[i])
+ nLevelCount = i+1;
+ else
+ bDoThis = FALSE;
+
+ if (nLevelCount==0) // nichts tun
+ return TRUE;
+
+ USHORT* nGroupCol = rParam.nField; // Spalten nach denen
+ // gruppiert wird
+ USHORT nResCount; // pro Ebene eingestellt
+ USHORT* nResCols; // Ergebnis-Spalten
+ ScSubTotalFunc* eResFunc; // Ergebnis-Funktionen
+
+ // #44444# Durch (leer) als eigene Kategorie muss immer auf
+ // Teilergebniszeilen aus den anderen Spalten getestet werden
+ // (frueher nur, wenn eine Spalte mehrfach vorkam)
+ BOOL bTestPrevSub = ( nLevelCount > 1 );
+
+ USHORT nLevel;
+ BOOL bChanged;
+ USHORT nRow;
+ USHORT nSubStartRow;
+ USHORT nDestRow;
+ USHORT nFuncStart;
+ USHORT nFuncEnd;
+ String aString;
+ String aSubString;
+ String aOutString;
+
+ String *pCompString[MAXSUBTOTAL]; // Pointer wegen Compiler-Problemen
+ for (i=0; i<MAXSUBTOTAL; i++)
+ pCompString[i] = new String;
+
+ //! sortieren?
+
+ ScStyleSheet* pStyle = (ScStyleSheet*) pDocument->GetStyleSheetPool()->Find(
+ ScGlobal::GetRscString(STR_STYLENAME_RESULT), SFX_STYLE_FAMILY_PARA );
+
+ BOOL bSpaceLeft = TRUE; // Erfolg beim Einfuegen?
+
+ for (nLevel=0; nLevel<=nLevelCount && bSpaceLeft; nLevel++) // incl. Gesamtergebnis
+ {
+ BOOL bTotal = ( nLevel == nLevelCount );
+ USHORT nGroupNo = bTotal ? 0 : (nLevelCount-nLevel-1);
+
+ nResCount = rParam.nSubTotals[nGroupNo];
+ nResCols = rParam.pSubTotals[nGroupNo];
+ eResFunc = rParam.pFunctions[nGroupNo];
+
+ if (nResCount) // sonst nur sortieren
+ {
+ for (i=0; i<=nGroupNo; i++)
+ {
+ GetString( nGroupCol[i], nStartRow, aSubString );
+ *pCompString[i] = aSubString;
+ ScGlobal::pCharClass->toUpper( *pCompString[i] );
+ } // aSubString bleibt auf dem letzten stehen
+
+ BOOL bBlockVis = FALSE; // Gruppe eingeblendet?
+ nSubStartRow = nStartRow;
+ for (nRow=nStartRow; nRow<=nEndRow+1 && bSpaceLeft; nRow++)
+ {
+ if (nRow>nEndRow)
+ bChanged = TRUE;
+ else
+ {
+ bChanged = FALSE;
+ if (!bTotal)
+ {
+ for (i=0; i<=nGroupNo && !bChanged; i++)
+ {
+ GetString( nGroupCol[i], nRow, aString );
+ ScGlobal::pCharClass->toUpper( aString );
+ // #41427# wenn sortiert, ist "leer" eine eigene Gruppe
+ // sonst sind leere Zellen unten erlaubt
+ bChanged = ( ( aString.Len() || rParam.bDoSort ) &&
+ aString != *pCompString[i] );
+ }
+ if ( bChanged && bTestPrevSub )
+ {
+ // kein Gruppenwechsel bei Teilergebniszeilen
+
+ ScBaseCell* pCell;
+ for (i=nStartCol; i<=nEndCol && bChanged; i++)
+ {
+ pCell = GetCell( i, nRow );
+ if ( pCell )
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ if (((ScFormulaCell*)pCell)->IsSubTotal())
+ bChanged = FALSE;
+ }
+ }
+ }
+ }
+ if ( bChanged )
+ {
+ nDestRow = nRow;
+ nFuncStart = nSubStartRow;
+ nFuncEnd = nRow-1;
+ ComplRefData aRef;
+ aRef.InitFlags();
+ aRef.Ref1.nTab = nTab;
+ aRef.Ref2.nTab = nTab;
+
+ bSpaceLeft = pDocument->InsertRow( 0,nTab, MAXCOL,nTab, nDestRow, 1 );
+ DBShowRow( nDestRow, bBlockVis );
+ bBlockVis = FALSE;
+ if (rParam.bPagebreak && nRow < MAXROW && nSubStartRow != nStartRow
+ && nLevel == 0)
+ SetRowFlags(nSubStartRow,GetRowFlags(nSubStartRow)|CR_MANUALBREAK);
+ if (bSpaceLeft)
+ {
+ if (bTotal) // "Gesamtergebnis"
+ aOutString = ScGlobal::GetRscString( STR_TABLE_GESAMTERGEBNIS );
+ else
+ { // " Ergebnis"
+ aOutString = aSubString;
+ if (!aOutString.Len())
+ aOutString = ScGlobal::GetRscString( STR_EMPTYDATA );
+ aOutString += ' ';
+ USHORT nStrId = STR_TABLE_ERGEBNIS;
+ if ( nResCount == 1 )
+ switch ( eResFunc[0] )
+ {
+ case SUBTOTAL_FUNC_AVE: nStrId = STR_FUN_TEXT_AVG; break;
+ case SUBTOTAL_FUNC_CNT:
+ case SUBTOTAL_FUNC_CNT2: nStrId = STR_FUN_TEXT_COUNT; break;
+ case SUBTOTAL_FUNC_MAX: nStrId = STR_FUN_TEXT_MAX; break;
+ case SUBTOTAL_FUNC_MIN: nStrId = STR_FUN_TEXT_MIN; break;
+ case SUBTOTAL_FUNC_PROD: nStrId = STR_FUN_TEXT_PRODUCT; break;
+ case SUBTOTAL_FUNC_STD:
+ case SUBTOTAL_FUNC_STDP: nStrId = STR_FUN_TEXT_STDDEV; break;
+ case SUBTOTAL_FUNC_SUM: nStrId = STR_FUN_TEXT_SUM; break;
+ case SUBTOTAL_FUNC_VAR:
+ case SUBTOTAL_FUNC_VARP: nStrId = STR_FUN_TEXT_VAR; break;
+ }
+ aOutString += ScGlobal::GetRscString( nStrId );
+ }
+ SetString( nGroupCol[nGroupNo], nDestRow, nTab, aOutString );
+ ApplyStyle( nGroupCol[nGroupNo], nDestRow, *pStyle );
+
+ for (USHORT i=0; i<nResCount; i++)
+ {
+ aRef.Ref1.nCol = nResCols[i];
+ aRef.Ref1.nRow = nFuncStart;
+ aRef.Ref2.nCol = nResCols[i];
+ aRef.Ref2.nRow = nFuncEnd;
+
+ ScTokenArray aArr;
+ aArr.AddOpCode(ocSubTotal);
+ aArr.AddOpCode(ocOpen);
+ aArr.AddDouble((double) eResFunc[i]);
+ aArr.AddOpCode(ocSep);
+ aArr.AddDoubleReference(aRef);
+ aArr.AddOpCode(ocClose);
+ aArr.AddOpCode(ocStop);
+ ScBaseCell* pCell = new ScFormulaCell
+ ( pDocument, ScAddress( nResCols[i], nDestRow, nTab ), &aArr );
+ PutCell( nResCols[i], nDestRow, pCell );
+
+ if ( nResCols[i] != nGroupCol[nGroupNo] )
+ {
+ ApplyStyle( nResCols[i], nDestRow, *pStyle );
+
+ // Zahlformat loeschen
+ lcl_RemoveNumberFormat( this, nResCols[i], nDestRow );
+ }
+ }
+
+/* if (rParam.bPagebreak && nRow < MAXROW)
+ {
+ BYTE nFlags = GetRowFlags( nRow+1 );
+ nFlags |= CR_MANUALBREAK;
+ SetRowFlags( nRow+1, nFlags );
+ }
+*/
+ ++nRow;
+ ++nEndRow;
+ nSubStartRow = nRow;
+ for (i=0; i<=nGroupNo; i++)
+ {
+ GetString( nGroupCol[i], nRow, aSubString );
+ *pCompString[i] = aSubString;
+ ScGlobal::pCharClass->toUpper( *pCompString[i] );
+ }
+ }
+ }
+ if (!pRowFlags)
+ bBlockVis = TRUE;
+ else
+ if ( (pRowFlags[nRow] & CR_FILTERED) == 0 )
+ bBlockVis = TRUE;
+ }
+ }
+ else
+ {
+// DBG_ERROR( "nSubTotals==0 bei DoSubTotals" );
+ }
+ }
+
+ //! je nach Einstellung Zwischensummen-Zeilen nach oben verschieben ?
+
+ //! Outlines direkt erzeugen?
+
+ if (bSpaceLeft)
+ DoAutoOutline( nStartCol, nStartRow, nEndCol, nEndRow );
+
+ for (i=0; i<MAXSUBTOTAL; i++)
+ delete pCompString[i];
+
+ rParam.nRow2 = nEndRow; // neues Ende
+ return bSpaceLeft;
+}
+
+
+BOOL ScTable::ValidQuery(USHORT nRow, const ScQueryParam& rParam, BOOL* pSpecial)
+{
+ if (!rParam.GetEntry(0).bDoQuery)
+ return TRUE;
+
+ //---------------------------------------------------------------
+
+ const USHORT nFixedBools = 32;
+ BOOL aBool[nFixedBools];
+ USHORT nEntryCount = rParam.GetEntryCount();
+ BOOL* pPasst = ( nEntryCount <= nFixedBools ? &aBool[0] : new BOOL[nEntryCount] );
+
+ short nPos = -1;
+ USHORT i = 0;
+ BOOL bMatchWholeCell = pDocument->GetDocOptions().IsMatchWholeCell();
+ USHORT nCompareFlags = (rParam.bCaseSens ? 0 : INTN_COMPARE_IGNORECASE);
+
+ while ( (i < nEntryCount) && rParam.GetEntry(i).bDoQuery )
+ {
+ ScQueryEntry& rEntry = rParam.GetEntry(i);
+
+ BOOL bOk = FALSE;
+
+ if ( pSpecial && pSpecial[i] )
+ {
+ if (rEntry.nVal == SC_EMPTYFIELDS)
+ bOk = !( aCol[rEntry.nField].HasDataAt( nRow ) );
+ else // if (rEntry.nVal == SC_NONEMPTYFIELDS)
+ bOk = aCol[rEntry.nField].HasDataAt( nRow );
+ }
+ else if (!rEntry.bQueryByString && HasValueData(rEntry.nField, nRow))
+ { // by Value
+ double nCellVal = GetValue(rEntry.nField, nRow);
+ switch (rEntry.eOp)
+ {
+ case SC_EQUAL :
+ bOk = SolarMath::ApproxEqual( nCellVal, rEntry.nVal );
+ break;
+ case SC_LESS :
+ bOk = (nCellVal < rEntry.nVal) && !SolarMath::ApproxEqual( nCellVal, rEntry.nVal );
+ break;
+ case SC_GREATER :
+ bOk = (nCellVal > rEntry.nVal) && !SolarMath::ApproxEqual( nCellVal, rEntry.nVal );
+ break;
+ case SC_LESS_EQUAL :
+ bOk = (nCellVal < rEntry.nVal) || SolarMath::ApproxEqual( nCellVal, rEntry.nVal );
+ break;
+ case SC_GREATER_EQUAL :
+ bOk = (nCellVal > rEntry.nVal) || SolarMath::ApproxEqual( nCellVal, rEntry.nVal );
+ break;
+ case SC_NOT_EQUAL :
+ bOk = !SolarMath::ApproxEqual( nCellVal, rEntry.nVal );
+ break;
+ }
+ }
+ else if ( (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL)
+ || (rEntry.bQueryByString
+ && HasStringData(rEntry.nField, nRow))
+ )
+ { // by String
+ String aCellStr;
+ GetInputString(rEntry.nField, nRow, aCellStr);
+
+ if (rParam.bRegExp && ((rEntry.eOp == SC_EQUAL)
+ || (rEntry.eOp == SC_NOT_EQUAL)) )
+ {
+ xub_StrLen nStart = 0;
+ xub_StrLen nEnd = aCellStr.Len();
+ bOk = (BOOL) rEntry.GetSearchTextPtr( rParam.bCaseSens )
+ ->SearchFrwrd( aCellStr, &nStart, &nEnd );
+ if ( bOk && bMatchWholeCell
+ && (nStart != 0 || nEnd != aCellStr.Len()-1) )
+ bOk = FALSE; // RegExp muss ganze Zelle matchen
+ if ( rEntry.eOp == SC_NOT_EQUAL )
+ bOk = !bOk;
+ }
+ else
+ {
+ if ( rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL )
+ {
+ if ( bMatchWholeCell )
+ bOk = ScGlobal::pScInternational->CompareEqual(
+ aCellStr, *rEntry.pStr, nCompareFlags );
+ else
+ {
+ if ( rParam.bCaseSens )
+ bOk = (aCellStr.Search( *rEntry.pStr ) != STRING_NOTFOUND);
+ else
+ {
+ String aQueryStr( *rEntry.pStr );
+ ScGlobal::pCharClass->toLower( aQueryStr );
+ ScGlobal::pCharClass->toLower( aCellStr );
+ bOk = (aCellStr.Search( aQueryStr ) != STRING_NOTFOUND);
+ }
+ }
+ if ( rEntry.eOp == SC_NOT_EQUAL )
+ bOk = !bOk;
+ }
+ else
+ {
+ StringCompare eCompare =
+ ScGlobal::pScInternational->Compare(
+ aCellStr, *rEntry.pStr, nCompareFlags );
+ switch (rEntry.eOp)
+ {
+ case SC_LESS :
+ bOk = (eCompare == COMPARE_LESS);
+ break;
+ case SC_GREATER :
+ bOk = (eCompare == COMPARE_GREATER);
+ break;
+ case SC_LESS_EQUAL :
+ bOk = (eCompare == COMPARE_LESS) || (eCompare == COMPARE_EQUAL);
+ break;
+ case SC_GREATER_EQUAL :
+ bOk = (eCompare == COMPARE_GREATER) || (eCompare == COMPARE_EQUAL);
+ break;
+ }
+ }
+ }
+ }
+
+ if (nPos == -1)
+ {
+ nPos++;
+ pPasst[nPos] = bOk;
+ }
+ else
+ {
+ if (rEntry.eConnect == SC_AND)
+ pPasst[nPos] = pPasst[nPos] && bOk;
+ else
+ {
+ nPos++;
+ pPasst[nPos] = bOk;
+ }
+ }
+ i++;
+ }
+
+ for ( i=1; (short)i <= nPos; i++ )
+ pPasst[0] = pPasst[0] || pPasst[i];
+
+ BOOL bRet = pPasst[0];
+ if ( pPasst != &aBool[0] )
+ delete [] pPasst;
+
+ return bRet;
+}
+
+void ScTable::TopTenQuery( ScQueryParam& rParam )
+{
+ USHORT nEntryCount = rParam.GetEntryCount();
+ USHORT nRow1 = (rParam.bHasHeader ? rParam.nRow1 + 1 : rParam.nRow1);
+ USHORT nCount = rParam.nRow2 - nRow1 + 1;
+ USHORT i;
+ for ( i=0; (i<nEntryCount) && (rParam.GetEntry(i).bDoQuery); i++ )
+ {
+ ScQueryEntry& rEntry = rParam.GetEntry(i);
+ switch ( rEntry.eOp )
+ {
+ case SC_TOPVAL:
+ case SC_BOTVAL:
+ case SC_TOPPERC:
+ case SC_BOTPERC:
+ {
+ ScSortParam aLocalSortParam( rParam, rEntry.nField );
+ memmove( &aSortParam, &aLocalSortParam, sizeof(ScSortParam) );
+ ScSortInfoArray* pArray = CreateSortInfoArray( nRow1, rParam.nRow2 );
+ DecoladeRow( pArray, nRow1, rParam.nRow2 );
+ QuickSort( pArray, nRow1, rParam.nRow2 );
+ ScSortInfo** ppInfo = pArray->GetFirstArray();
+ USHORT nValidCount = nCount;
+ // keine Note-/Leerzellen zaehlen, sind ans Ende sortiert
+ while ( nValidCount && ppInfo[nValidCount-1]->pCell == NULL )
+ nValidCount--;
+ // keine Strings zaehlen, sind zwischen Value und Leer
+ while ( nValidCount
+ && ppInfo[nValidCount-1]->pCell->HasStringData() )
+ nValidCount--;
+ if ( nValidCount )
+ {
+ if ( rEntry.bQueryByString )
+ { // dat wird nix
+ rEntry.bQueryByString = FALSE;
+ rEntry.nVal = 10; // 10 bzw. 10%
+ }
+ USHORT nVal = (rEntry.nVal >= 1 ? (USHORT)rEntry.nVal : 1);
+ USHORT nOffset = 0;
+ switch ( rEntry.eOp )
+ {
+ case SC_TOPVAL:
+ {
+ rEntry.eOp = SC_GREATER_EQUAL;
+ if ( nVal > nValidCount )
+ nVal = nValidCount;
+ nOffset = nValidCount - nVal; // 1 <= nVal <= nValidCount
+ }
+ break;
+ case SC_BOTVAL:
+ {
+ rEntry.eOp = SC_LESS_EQUAL;
+ if ( nVal > nValidCount )
+ nVal = nValidCount;
+ nOffset = nVal - 1; // 1 <= nVal <= nValidCount
+ }
+ break;
+ case SC_TOPPERC:
+ {
+ rEntry.eOp = SC_GREATER_EQUAL;
+ if ( nVal > 100 )
+ nVal = 100;
+ nOffset = nValidCount -
+ (USHORT)((ULONG)nValidCount * nVal / 100);
+ if ( nOffset >= nValidCount )
+ nOffset = nValidCount - 1;
+ }
+ break;
+ case SC_BOTPERC:
+ {
+ rEntry.eOp = SC_LESS_EQUAL;
+ if ( nVal > 100 )
+ nVal = 100;
+ nOffset =
+ (USHORT)((ULONG)nValidCount * nVal / 100);
+ if ( nOffset >= nValidCount )
+ nOffset = nValidCount - 1;
+ }
+ break;
+ }
+ ScBaseCell* pCell = ppInfo[nOffset]->pCell;
+ if ( pCell->HasValueData() )
+ {
+ if ( pCell->GetCellType() == CELLTYPE_VALUE )
+ rEntry.nVal = ((ScValueCell*)pCell)->GetValue();
+ else
+ rEntry.nVal = ((ScFormulaCell*)pCell)->GetValue();
+ }
+ else
+ {
+ DBG_ERRORFILE( "TopTenQuery: pCell kein ValueData" );
+ rEntry.eOp = SC_GREATER_EQUAL;
+ rEntry.nVal = 0;
+ }
+ }
+ else
+ {
+ rEntry.eOp = SC_GREATER_EQUAL;
+ rEntry.bQueryByString = FALSE;
+ rEntry.nVal = 0;
+ }
+ delete pArray;
+ }
+ }
+ }
+}
+
+USHORT ScTable::Query(ScQueryParam& rParamOrg, BOOL bKeepSub)
+{
+ StrCollection aStrCollection;
+ StrData* pStrData = NULL;
+
+ BOOL bStarted = FALSE;
+ BOOL bOldResult = TRUE;
+ USHORT nOldStart = 0;
+ USHORT nOldEnd = 0;
+
+ USHORT nCount = 0;
+ USHORT nOutRow = 0;
+ USHORT nHeader = rParamOrg.bHasHeader ? 1 : 0;
+ USHORT i = 0;
+
+ USHORT nEntryCount = rParamOrg.GetEntryCount();
+
+ BOOL* pSpecial = new BOOL[nEntryCount];
+ for (i=0; i<nEntryCount; i++)
+ pSpecial[i] = FALSE;
+
+ /*
+ * Dialog liefert die ausgezeichneten Feldwerte "leer"/"nicht leer"
+ * als Konstanten in nVal in Verbindung mit dem Schalter
+ * bQueryByString auf FALSE.
+ */
+
+ BOOL bTopTen = FALSE;
+ for ( i=0; (i<nEntryCount) && (rParamOrg.GetEntry(i).bDoQuery); i++ )
+ {
+ ScQueryEntry& rEntry = rParamOrg.GetEntry(i);
+
+ if ( rEntry.bQueryByString )
+ {
+ ULONG nIndex = 0;
+ rEntry.bQueryByString = !(pDocument->GetFormatTable()->
+ IsNumberFormat( *rEntry.pStr, nIndex, rEntry.nVal ));
+ }
+ else
+ {
+ double nTemp = rEntry.nVal;
+ if (nTemp == SC_EMPTYFIELDS || nTemp == SC_NONEMPTYFIELDS)
+ pSpecial[i] = TRUE;
+ // #58736# QueryParam mit !bQueryByString kann per Uno oder zweitem
+ // Aufruf per AutoFilter kommen - hier keine Assertion mehr
+ }
+ if ( !bTopTen )
+ {
+ switch ( rEntry.eOp )
+ {
+ case SC_TOPVAL:
+ case SC_BOTVAL:
+ case SC_TOPPERC:
+ case SC_BOTPERC:
+ bTopTen = TRUE;
+ }
+ }
+ }
+ ScQueryParam* pTopTenParam;
+ if ( bTopTen )
+ { // original Param erhalten und Kopie anpassen
+ pTopTenParam = new ScQueryParam( rParamOrg );
+ TopTenQuery( *pTopTenParam );
+ }
+ else
+ pTopTenParam = NULL;
+ ScQueryParam& rParam = (bTopTen ? *pTopTenParam : rParamOrg);
+
+ if (!rParam.bInplace)
+ {
+ nOutRow = rParam.nDestRow + nHeader;
+ if (nHeader)
+ CopyData( rParam.nCol1, rParam.nRow1, rParam.nCol2, rParam.nRow1,
+ rParam.nDestCol, rParam.nDestRow, rParam.nDestTab );
+ }
+
+ for (i=rParam.nRow1 + nHeader; i<=rParam.nRow2; i++)
+ {
+ BOOL bResult; // Filterergebnis
+ BOOL bValid = ValidQuery(i, rParam, pSpecial);
+ if (!bValid && bKeepSub) // Subtotals stehenlassen
+ {
+ for (USHORT nCol=rParam.nCol1; nCol<=rParam.nCol2 && !bValid; nCol++)
+ {
+ ScBaseCell* pCell;
+ pCell = GetCell( nCol, i );
+ if ( pCell )
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ if (((ScFormulaCell*)pCell)->IsSubTotal())
+ if (RefVisible((ScFormulaCell*)pCell))
+ bValid = TRUE;
+ }
+ }
+ if (bValid)
+ {
+ if (rParam.bDuplicate)
+ bResult = TRUE;
+ else
+ {
+ String aStr;
+ for (USHORT j=rParam.nCol1; j <= rParam.nCol2; j++)
+ {
+ String aCellStr;
+ GetString(j, i, aCellStr);
+ aStr += aCellStr;
+ aStr += (sal_Unicode)1;
+ }
+ pStrData = new StrData(aStr);
+
+ BOOL bIsUnique = TRUE;
+ if (pStrData)
+ bIsUnique = aStrCollection.Insert(pStrData);
+ if (bIsUnique)
+ bResult = TRUE;
+ else
+ {
+ delete pStrData;
+ bResult = FALSE;
+ }
+ }
+ }
+ else
+ bResult = FALSE;
+
+ if (rParam.bInplace)
+ {
+ if (bResult == bOldResult && bStarted)
+ nOldEnd = i;
+ else
+ {
+ if (bStarted)
+ DBShowRows(nOldStart,nOldEnd, bOldResult);
+ nOldStart = nOldEnd = i;
+ bOldResult = bResult;
+ }
+ bStarted = TRUE;
+ }
+ else
+ {
+ if (bResult)
+ {
+ CopyData( rParam.nCol1,i, rParam.nCol2,i, rParam.nDestCol,nOutRow,rParam.nDestTab );
+ ++nOutRow;
+ }
+ }
+ if (bResult)
+ ++nCount;
+ }
+
+ if (rParam.bInplace && bStarted)
+ DBShowRows(nOldStart,nOldEnd, bOldResult);
+
+ delete[] pSpecial;
+ if ( pTopTenParam )
+ delete pTopTenParam;
+
+ return nCount;
+}
+
+BOOL ScTable::CreateExcelQuery(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2, ScQueryParam& rQueryParam)
+{
+ USHORT i;
+ BOOL bValid = TRUE;
+ USHORT* pFields = new USHORT[nCol2-nCol1+1];
+ String aCellStr;
+ USHORT nCol = nCol1;
+ DBG_ASSERT( rQueryParam.nTab != USHRT_MAX, "rQueryParam.nTab no value, not bad but no good" );
+ USHORT nDBTab = (rQueryParam.nTab == USHRT_MAX ? nTab : rQueryParam.nTab);
+ USHORT nDBRow1 = rQueryParam.nRow1;
+ USHORT nDBCol2 = rQueryParam.nCol2;
+ // Erste Zeile muessen Spaltenkoepfe sein
+ while (bValid && (nCol <= nCol2))
+ {
+ String aQueryStr;
+ GetUpperCellString(nCol, nRow1, aQueryStr);
+ BOOL bFound = FALSE;
+ i = rQueryParam.nCol1;
+ while (!bFound && (i <= nDBCol2))
+ {
+ if ( nTab == nDBTab )
+ GetUpperCellString(i, nDBRow1, aCellStr);
+ else
+ pDocument->GetUpperCellString(i, nDBRow1, nDBTab, aCellStr);
+ bFound = (aCellStr == aQueryStr);
+ if (!bFound) i++;
+ }
+ if (bFound)
+ pFields[nCol - nCol1] = i;
+ else
+ bValid = FALSE;
+ nCol++;
+ }
+ if (bValid)
+ {
+ long nVisible = 0;
+ for ( nCol=nCol1; nCol<=nCol2; nCol++ )
+ nVisible += aCol[nCol].VisibleCount( nRow1+1, nRow2 );
+
+ if ( nVisible > USHRT_MAX / sizeof(void*) )
+ {
+ DBG_ERROR("zu viele Filterkritierien");
+ nVisible = 0;
+ }
+
+ USHORT nNewEntries = (USHORT) nVisible;
+ rQueryParam.Resize( nNewEntries );
+
+ USHORT nIndex = 0;
+ USHORT nRow = nRow1 + 1;
+ while (nRow <= nRow2)
+ {
+ nCol = nCol1;
+ while (nCol <= nCol2)
+ {
+ GetUpperCellString(nCol, nRow, aCellStr);
+ if (aCellStr.Len() > 0)
+ {
+ if (nIndex < nNewEntries)
+ {
+ rQueryParam.GetEntry(nIndex).nField = pFields[nCol - nCol1];
+ rQueryParam.FillInExcelSyntax(aCellStr, nIndex);
+ nIndex++;
+ if (nIndex < nNewEntries)
+ rQueryParam.GetEntry(nIndex).eConnect = SC_AND;
+ }
+ else
+ bValid = FALSE;
+ }
+ nCol++;
+ }
+ nRow++;
+ if (nIndex < nNewEntries)
+ rQueryParam.GetEntry(nIndex).eConnect = SC_OR;
+ }
+ }
+ delete pFields;
+ return bValid;
+}
+
+BOOL ScTable::CreateStarQuery(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2, ScQueryParam& rQueryParam)
+{
+ BOOL bValid;
+ BOOL bFound;
+ String aCellStr;
+ USHORT nIndex = 0;
+ USHORT nRow = nRow1;
+ DBG_ASSERT( rQueryParam.nTab != USHRT_MAX, "rQueryParam.nTab no value, not bad but no good" );
+ USHORT nDBTab = (rQueryParam.nTab == USHRT_MAX ? nTab : rQueryParam.nTab);
+ USHORT nDBRow1 = rQueryParam.nRow1;
+ USHORT nDBCol2 = rQueryParam.nCol2;
+
+ USHORT nNewEntries = nRow2-nRow1+1;
+ rQueryParam.Resize( nNewEntries );
+
+ do
+ {
+ ScQueryEntry& rEntry = rQueryParam.GetEntry(nIndex);
+
+ bValid = FALSE;
+ // Erste Spalte UND/ODER
+ if (nIndex > 0)
+ {
+ GetUpperCellString(nCol1, nRow, aCellStr);
+ if ( aCellStr == ScGlobal::GetRscString(STR_TABLE_UND) )
+ {
+ rEntry.eConnect = SC_AND;
+ bValid = TRUE;
+ }
+ else if ( aCellStr == ScGlobal::GetRscString(STR_TABLE_ODER) )
+ {
+ rEntry.eConnect = SC_OR;
+ bValid = TRUE;
+ }
+ }
+ // Zweite Spalte FeldName
+ if ((nIndex < 1) || bValid)
+ {
+ bFound = FALSE;
+ GetUpperCellString(nCol1 + 1, nRow, aCellStr);
+ for (USHORT i=rQueryParam.nCol1; (i <= nDBCol2) && (!bFound); i++)
+ {
+ String aFieldStr;
+ if ( nTab == nDBTab )
+ GetUpperCellString(i, nDBRow1, aFieldStr);
+ else
+ pDocument->GetUpperCellString(i, nDBRow1, nDBTab, aFieldStr);
+ bFound = (aCellStr == aFieldStr);
+ if (bFound)
+ {
+ rEntry.nField = i;
+ bValid = TRUE;
+ }
+ else
+ bValid = FALSE;
+ }
+ }
+ // Dritte Spalte Operator =<>...
+ if (bValid)
+ {
+ bFound = FALSE;
+ GetUpperCellString(nCol1 + 2, nRow, aCellStr);
+ if (aCellStr.GetChar(0) == '<')
+ {
+ if (aCellStr.GetChar(1) == '>')
+ rEntry.eOp = SC_NOT_EQUAL;
+ else if (aCellStr.GetChar(1) == '=')
+ rEntry.eOp = SC_LESS_EQUAL;
+ else
+ rEntry.eOp = SC_LESS;
+ }
+ else if (aCellStr.GetChar(0) == '>')
+ {
+ if (aCellStr.GetChar(1) == '=')
+ rEntry.eOp = SC_GREATER_EQUAL;
+ else
+ rEntry.eOp = SC_GREATER;
+ }
+ else if (aCellStr.GetChar(0) == '=')
+ rEntry.eOp = SC_EQUAL;
+
+ }
+ // Vierte Spalte Wert
+ if (bValid)
+ {
+ GetString(nCol1 + 3, nRow, *rEntry.pStr);
+ rEntry.bDoQuery = TRUE;
+ }
+ nIndex++;
+ nRow++;
+ }
+ while (bValid && (nRow <= nRow2) /* && (nIndex < MAXQUERY) */ );
+ return bValid;
+}
+
+BOOL ScTable::CreateQueryParam(USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2, ScQueryParam& rQueryParam)
+{
+ USHORT i, nCount;
+ PutInOrder(nCol1, nCol2);
+ PutInOrder(nRow1, nRow2);
+
+ nCount = rQueryParam.GetEntryCount();
+ for (i=0; i < nCount; i++)
+ rQueryParam.GetEntry(i).Clear();
+
+ // Standard QueryTabelle
+ BOOL bValid = CreateStarQuery(nCol1, nRow1, nCol2, nRow2, rQueryParam);
+ // Excel QueryTabelle
+ if (!bValid)
+ bValid = CreateExcelQuery(nCol1, nRow1, nCol2, nRow2, rQueryParam);
+
+ nCount = rQueryParam.GetEntryCount();
+ if (bValid)
+ {
+ // bQueryByString muss gesetzt sein
+ for (i=0; i < nCount; i++)
+ rQueryParam.GetEntry(i).bQueryByString = TRUE;
+ }
+ else
+ {
+ // nix
+ for (i=0; i < nCount; i++)
+ rQueryParam.GetEntry(i).Clear();
+ }
+ return bValid;
+}
+
+BOOL ScTable::HasColHeader( USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow )
+{
+ for (USHORT nCol=nStartCol; nCol<=nEndCol; nCol++)
+ {
+ CellType eType = GetCellType( nCol, nStartRow );
+ if (eType != CELLTYPE_STRING && eType != CELLTYPE_EDIT)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOL ScTable::HasRowHeader( USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow )
+{
+ for (USHORT nRow=nStartRow; nRow<=nEndRow; nRow++)
+ {
+ CellType eType = GetCellType( nStartCol, nRow );
+ if (eType != CELLTYPE_STRING && eType != CELLTYPE_EDIT)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void ScTable::GetFilterEntries(USHORT nCol, USHORT nRow1, USHORT nRow2, TypedStrCollection& rStrings)
+{
+ aCol[nCol].GetFilterEntries( nRow1, nRow2, rStrings );
+}
+
+BOOL ScTable::GetDataEntries(USHORT nCol, USHORT nRow, TypedStrCollection& rStrings, BOOL bLimit)
+{
+ return aCol[nCol].GetDataEntries( nRow, rStrings, bLimit );
+}
+
+long ScTable::GetCellCount() const
+{
+ long nCellCount = 0;
+
+ for ( USHORT nCol=0; nCol<=MAXCOL; nCol++ )
+ nCellCount += aCol[nCol].GetCellCount();
+
+ return nCellCount;
+}
+
+long ScTable::GetWeightedCount() const
+{
+ long nCellCount = 0;
+
+ for ( USHORT nCol=0; nCol<=MAXCOL; nCol++ )
+ if ( aCol[nCol].GetCellCount() ) // GetCellCount ist inline
+ nCellCount += aCol[nCol].GetWeightedCount();
+
+ return nCellCount;
+}
+
+ULONG ScTable::GetCodeCount() const
+{
+ ULONG nCodeCount = 0;
+
+ for ( USHORT nCol=0; nCol<=MAXCOL; nCol++ )
+ if ( aCol[nCol].GetCellCount() ) // GetCellCount ist inline
+ nCodeCount += aCol[nCol].GetCodeCount();
+
+ return nCodeCount;
+}
+
+xub_StrLen ScTable::GetMaxStringLen( USHORT nCol,
+ USHORT nRowStart, USHORT nRowEnd ) const
+{
+ if ( nCol <= MAXCOL )
+ return aCol[nCol].GetMaxStringLen( nRowStart, nRowEnd );
+ else
+ return 0;
+}
+
+xub_StrLen ScTable::GetMaxNumberStringLen( USHORT& nPrecision, USHORT nCol,
+ USHORT nRowStart, USHORT nRowEnd ) const
+{
+ if ( nCol <= MAXCOL )
+ return aCol[nCol].GetMaxNumberStringLen( nPrecision, nRowStart, nRowEnd );
+ else
+ return 0;
+}
+
+void ScTable::UpdateSelectionFunction( ScFunctionData& rData,
+ USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow,
+ const ScMarkData& rMark )
+{
+ // Cursor neben einer Markierung nicht beruecksichtigen:
+ //! nur noch MarkData uebergeben, Cursorposition ggf. hineinselektieren!!!
+ BOOL bSingle = ( rMark.IsMarked() || !rMark.IsMultiMarked() );
+
+ // Mehrfachselektion:
+
+ USHORT nCol;
+ if ( rMark.IsMultiMarked() )
+ for (nCol=0; nCol<=MAXCOL && !rData.bError; nCol++)
+ if ( !pColFlags || !( pColFlags[nCol] & CR_HIDDEN ) )
+ aCol[nCol].UpdateSelectionFunction( rMark, rData, pRowFlags,
+ bSingle && ( nCol >= nStartCol && nCol <= nEndCol ),
+ nStartRow, nEndRow );
+
+ // Einfachselektion (oder Cursor) nur wenn nicht negativ (und s.o.):
+
+ if ( bSingle && !rMark.IsMarkNegative() )
+ for (nCol=nStartCol; nCol<=nEndCol && !rData.bError; nCol++)
+ if ( !pColFlags || !( pColFlags[nCol] & CR_HIDDEN ) )
+ aCol[nCol].UpdateAreaFunction( rData, pRowFlags, nStartRow, nEndRow );
+}
+
+void ScTable::FindConditionalFormat( ULONG nKey, ScRangeList& rList )
+{
+ USHORT nStartRow, nEndRow;
+ for (USHORT nCol=0; nCol<=MAXCOL; nCol++)
+ {
+ ScAttrIterator* pIter = aCol[nCol].CreateAttrIterator( 0, MAXCOL );
+ const ScPatternAttr* pPattern = pIter->Next( nStartRow, nEndRow );
+ while (pPattern)
+ {
+ if (((SfxUInt32Item&)pPattern->GetItem(ATTR_CONDITIONAL)).GetValue() == nKey)
+ rList.Join( ScRange(nCol,nStartRow,nTab, nCol,nEndRow,nTab) );
+ pPattern = pIter->Next( nStartRow, nEndRow );
+ }
+ delete pIter;
+ }
+}
+
+
+
+
diff --git a/sc/source/core/data/table4.cxx b/sc/source/core/data/table4.cxx
new file mode 100644
index 000000000000..cb79f796d2de
--- /dev/null
+++ b/sc/source/core/data/table4.cxx
@@ -0,0 +1,2014 @@
+/*************************************************************************
+ *
+ * $RCSfile: table4.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:16 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+// System - Includes -----------------------------------------------------
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#pragma optimize("",off)
+ // sonst Absturz Win beim Fuellen
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <svx/algitem.hxx>
+#include <svx/boxitem.hxx>
+#include <svx/brshitem.hxx>
+#include <svx/cntritem.hxx>
+#include <svx/colritem.hxx>
+#include <svx/crsditem.hxx>
+#include <svx/fhgtitem.hxx>
+#include <svx/fontitem.hxx>
+#include <svx/langitem.hxx>
+#include <svx/postitem.hxx>
+#include <svx/shdditem.hxx>
+#include <svx/udlnitem.hxx>
+#include <svx/wghtitem.hxx>
+#ifndef _SVX_ROTMODIT_HXX //autogen
+#include <svx/rotmodit.hxx>
+#endif
+#include <svtools/zforlist.hxx>
+#include <vcl/keycodes.hxx>
+#include <tools/intn.hxx>
+#include <tools/solmath.hxx>
+#include <unotools/charclass.hxx>
+#include <math.h>
+
+#include "attrib.hxx"
+#include "patattr.hxx"
+#include "cell.hxx"
+#include "table.hxx"
+#include "globstr.hrc"
+#include "global.hxx"
+#include "document.hxx"
+#include "autoform.hxx"
+#include "userlist.hxx"
+#include "zforauto.hxx"
+#include "subtotal.hxx"
+#include "compiler.hxx"
+#include "rangenam.hxx"
+#include "docpool.hxx"
+#include "progress.hxx"
+
+// STATIC DATA -----------------------------------------------------------
+
+#define _D_MAX_LONG_ (double) 0x7fffffff
+
+extern USHORT nScFillModeMouseModifier; // global.cxx
+
+// -----------------------------------------------------------------------
+
+short lcl_DecompValueString( String& aValue, long& nVal, USHORT* pMinDigits = NULL )
+{
+ if ( !aValue.Len() )
+ {
+ nVal = 0;
+ return 0;
+ }
+ const sal_Unicode* p = aValue.GetBuffer();
+ xub_StrLen nNeg = 0;
+ xub_StrLen nNum = 0;
+ if ( p[nNum] == '-' )
+ nNum = nNeg = 1;
+ while ( CharClass::isAsciiNumeric( p[nNum] ) )
+ nNum++;
+ if ( nNum > nNeg )
+ { // number at the beginning
+ nVal = aValue.Copy( 0, nNum ).ToInt32();
+ // #60893# any number with a leading zero sets the minimum number of digits
+ if ( p[nNeg] == '0' && pMinDigits && ( nNum - nNeg > *pMinDigits ) )
+ *pMinDigits = nNum - nNeg;
+ aValue.Erase( 0, nNum );
+ return -1;
+ }
+ else
+ {
+ nNeg = 0;
+ xub_StrLen nEnd = nNum = aValue.Len() - 1;
+ while ( nNum && CharClass::isAsciiNumeric( p[nNum] ) )
+ nNum--;
+ if ( p[nNum] == '-' )
+ {
+ nNum--;
+ nNeg = 1;
+ }
+ if ( nNum < nEnd - nNeg )
+ { // number at the end
+ nVal = aValue.Copy( nNum + 1 ).ToInt32();
+ // #60893# any number with a leading zero sets the minimum number of digits
+ if ( p[nNum+1+nNeg] == '0' && pMinDigits && ( nEnd - nNum - nNeg > *pMinDigits ) )
+ *pMinDigits = nEnd - nNum - nNeg;
+ aValue.Erase( nNum + 1 );
+ return 1;
+ }
+ }
+ nVal = 0;
+ return 0;
+}
+
+String lcl_ValueString( long nValue, USHORT nMinDigits )
+{
+ if ( nMinDigits <= 1 )
+ return String::CreateFromInt32( nValue ); // simple case...
+ else
+ {
+ String aStr = String::CreateFromInt32( Abs( nValue ) );
+ if ( aStr.Len() < nMinDigits )
+ {
+ String aZero;
+ aZero.Fill( nMinDigits - aStr.Len(), '0' );
+ aStr.Insert( aZero, 0 );
+ }
+ // nMinDigits doesn't include the '-' sign -> add after inserting zeros
+ if ( nValue < 0 )
+ aStr.Insert( '-', 0 );
+ return aStr;
+ }
+}
+
+void ScTable::FillAnalyse( USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2,
+ FillCmd& rCmd, FillDateCmd& rDateCmd,
+ double& rInc, USHORT& rMinDigits,
+ ScUserListData*& rListData, USHORT& rListIndex)
+{
+ DBG_ASSERT( nCol1==nCol2 || nRow1==nRow2, "FillAnalyse: falscher Bereich" );
+
+ rInc = 0.0;
+ rMinDigits = 0;
+ rListData = NULL;
+ rCmd = FILL_SIMPLE;
+ if ( nScFillModeMouseModifier & KEY_MOD1 )
+ return ; // Ctrl-Taste: Copy
+
+ USHORT nAddX;
+ USHORT nAddY;
+ USHORT nCount;
+ if (nCol1 == nCol2)
+ {
+ nAddX = 0;
+ nAddY = 1;
+ nCount = nRow2 - nRow1 + 1;
+ }
+ else
+ {
+ nAddX = 1;
+ nAddY = 0;
+ nCount = nCol2 - nCol1 + 1;
+ }
+
+ USHORT nCol = nCol1;
+ USHORT nRow = nRow1;
+
+ ScBaseCell* pFirstCell = GetCell( nCol, nRow );
+ CellType eCellType = pFirstCell ? pFirstCell->GetCellType() : CELLTYPE_NONE;
+
+ if (eCellType == CELLTYPE_VALUE)
+ {
+ UINT32 nFormat = ((const SfxUInt32Item*)GetAttr(nCol,nRow,ATTR_VALUE_FORMAT))->GetValue();
+ BOOL bDate = ( pDocument->GetFormatTable()->GetType(nFormat) == NUMBERFORMAT_DATE );
+ if (bDate)
+ {
+ if (nCount > 1)
+ {
+ long nCmpInc = 0;
+ double nVal;
+ Date aNullDate = *pDocument->GetFormatTable()->GetNullDate();
+ Date aDate1 = aNullDate;
+ nVal = ((ScValueCell*)pFirstCell)->GetValue();
+ aDate1 += (long)nVal;
+ Date aDate2 = aNullDate;
+ nVal = GetValue(nCol+nAddX, nRow+nAddY);
+ aDate2 += (long)nVal;
+ if ( aDate1 != aDate2 )
+ {
+ FillDateCmd eType;
+ long nDDiff = aDate2.GetDay() - (long) aDate1.GetDay();
+ long nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth();
+ long nYDiff = aDate2.GetYear() - (long) aDate1.GetYear();
+ if ( nDDiff )
+ {
+ eType = FILL_DAY;
+ nCmpInc = aDate2 - aDate1;
+ }
+ else
+ {
+ eType = FILL_MONTH;
+ nCmpInc = nMDiff + 12 * nYDiff;
+ }
+
+ nCol += nAddX; nRow += nAddY;
+ BOOL bVal = TRUE;
+ for (USHORT i=1; i<nCount && bVal; i++)
+ {
+ ScBaseCell* pCell = GetCell(nCol,nRow);
+ if (pCell && pCell->GetCellType() == CELLTYPE_VALUE)
+ {
+ nVal = ((ScValueCell*)pCell)->GetValue();
+ aDate2 = aNullDate + (long) nVal;
+ if ( eType == FILL_DAY )
+ {
+ if ( aDate2-aDate1 != nCmpInc )
+ bVal = FALSE;
+ }
+ else
+ {
+ nDDiff = aDate2.GetDay() - (long) aDate1.GetDay();
+ nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth();
+ nYDiff = aDate2.GetYear() - (long) aDate1.GetYear();
+ if (nDDiff || ( nMDiff + 12 * nYDiff != nCmpInc ))
+ bVal = FALSE;
+ }
+ aDate1 = aDate2;
+ nCol += nAddX; nRow += nAddY;
+ }
+ else
+ bVal = FALSE; // #50965# kein Datum passt auch nicht
+ }
+ if (bVal)
+ {
+ if ( eType == FILL_MONTH && ( nCmpInc % 12 == 0 ) )
+ {
+ eType = FILL_YEAR;
+ nCmpInc /= 12;
+ }
+ rCmd = FILL_DATE;
+ rDateCmd = eType;
+ rInc = nCmpInc;
+ }
+ }
+ }
+ else // einzelnes Datum -> Tage hochzaehlen
+ {
+ rCmd = FILL_DATE;
+ rDateCmd = FILL_DAY;
+ rInc = 1.0;
+ }
+ }
+ else
+ {
+ if (nCount > 1)
+ {
+ double nVal1 = ((ScValueCell*)pFirstCell)->GetValue();
+ double nVal2 = GetValue(nCol+nAddX, nRow+nAddY);
+ rInc = nVal2 - nVal1;
+ nCol += nAddX; nRow += nAddY;
+ BOOL bVal = TRUE;
+ for (USHORT i=1; i<nCount && bVal; i++)
+ {
+ ScBaseCell* pCell = GetCell(nCol,nRow);
+ if (pCell && pCell->GetCellType() == CELLTYPE_VALUE)
+ {
+ nVal2 = ((ScValueCell*)pCell)->GetValue();
+ double nDiff = nVal2 - nVal1;
+ if ( !SolarMath::ApproxEqual( nDiff, rInc ) )
+ bVal = FALSE;
+ nVal1 = nVal2;
+ }
+ else
+ bVal = FALSE;
+ nCol += nAddX; nRow += nAddY;
+ }
+ if (bVal)
+ rCmd = FILL_LINEAR;
+ }
+ }
+ }
+ else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT)
+ {
+ String aStr;
+ GetString(nCol, nRow, aStr);
+ rListData = (ScUserListData*)(ScGlobal::GetUserList()->GetData(aStr));
+ if (rListData)
+ {
+ rListData->GetSubIndex(aStr, rListIndex);
+ nCol += nAddX; nRow += nAddY;
+ for (USHORT i=1; i<nCount && rListData; i++)
+ {
+ GetString(nCol, nRow, aStr);
+ if (!rListData->GetSubIndex(aStr, rListIndex))
+ rListData = NULL;
+ nCol += nAddX; nRow += nAddY;
+ }
+ }
+ else if ( nCount > 1 )
+ {
+ // pass rMinDigits to all DecompValueString calls
+ // -> longest number defines rMinDigits
+
+ long nVal1;
+ short nFlag1 = lcl_DecompValueString( aStr, nVal1, &rMinDigits );
+ if ( nFlag1 )
+ {
+ long nVal2;
+ GetString( nCol+nAddX, nRow+nAddY, aStr );
+ short nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits );
+ if ( nFlag1 == nFlag2 )
+ {
+ rInc = (double)nVal2 - (double)nVal1;
+ nCol += nAddX; nRow += nAddY;
+ BOOL bVal = TRUE;
+ for (USHORT i=1; i<nCount && bVal; i++)
+ {
+ ScBaseCell* pCell = GetCell(nCol,nRow);
+ CellType eType = pCell->GetCellType();
+ if (pCell && (eType == CELLTYPE_STRING
+ || eType == CELLTYPE_EDIT) )
+ {
+ if ( eType == CELLTYPE_STRING )
+ ((ScStringCell*)pCell)->GetString( aStr );
+ else
+ ((ScEditCell*)pCell)->GetString( aStr );
+ nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits );
+ if ( nFlag1 == nFlag2 )
+ {
+ double nDiff = (double)nVal2 - (double)nVal1;
+ if ( !SolarMath::ApproxEqual( nDiff, rInc ) )
+ bVal = FALSE;
+ nVal1 = nVal2;
+ }
+ else
+ bVal = FALSE;
+ }
+ else
+ bVal = FALSE;
+ nCol += nAddX; nRow += nAddY;
+ }
+ if (bVal)
+ rCmd = FILL_LINEAR;
+ }
+ }
+ }
+ else
+ {
+ // call DecompValueString to set rMinDigits
+ long nDummy;
+ lcl_DecompValueString( aStr, nDummy, &rMinDigits );
+ }
+ }
+}
+
+void ScTable::FillFormula(USHORT& nFormulaCounter, BOOL bFirst, ScFormulaCell* pSrcCell,
+ USHORT nDestCol, USHORT nDestRow, BOOL bLast )
+{
+/* USHORT nTokArrLen = pSrcCell->GetTokenArrayLen();
+ if ( nTokArrLen > 15 ) // mehr als =A1 oder =67
+ {
+ ScRangeName* pRangeName = pDocument->GetRangeName();
+ String aName("___SC_"); // Wird dieser String veraendert,
+ // auch in document2 EraseNonUsed...
+ // mitaendern!!
+ aName += pRangeName->GetSharedMaxIndex() + 1;
+ aName += '_';
+ aName += nFormulaCounter;
+ nFormulaCounter++;
+ if (bFirst)
+ {
+ ScRangeData *pAktRange = new ScRangeData(
+ pDocument, aName, pSrcCell->GetTokenArray(), nTokArrLen,
+ pSrcCell->GetCol(), pSrcCell->GetRow(), nTab ,RT_SHARED);
+ if (!pRangeName->Insert( pAktRange ))
+ delete pAktRange;
+ else
+ bSharedNameInserted = TRUE;
+ }
+ USHORT nIndex;
+ pRangeName->SearchName(aName, nIndex);
+ if (!pRangeName)
+ {
+ DBG_ERROR("ScTable::FillFormula: Falscher Name");
+ return;
+ }
+ nIndex = ((ScRangeData*) ((*pRangeName)[nIndex]))->GetIndex();
+ ScTokenArray aArr;
+ aArr.AddName(nIndex);
+ aArr.AddOpCode(ocStop);
+ ScFormulaCell* pDestCell = new ScFormulaCell
+ (pDocument, ScAddress( nDestCol, nDestRow, nTab ), aArr );
+ aCol[nDestCol].Insert(nDestRow, pDestCell);
+ }
+ else
+*/ {
+ pDocument->SetNoListening( TRUE ); // noch falsche Referenzen
+ ScFormulaCell* pDestCell = (ScFormulaCell*) pSrcCell->Clone( pDocument,
+ ScAddress( nDestCol, nDestRow, nTab ), TRUE );
+ aCol[nDestCol].Insert(nDestRow, pDestCell);
+#if 0
+// mit RelRefs unnoetig
+ ScAddress aAddr( nDestCol, nDestRow, nTab );
+ pDestCell->UpdateReference(URM_COPY,
+ ScRange( aAddr, aAddr ),
+ nDestCol - pSrcCell->aPos.Col(),
+ nDestRow - pSrcCell->aPos.Row(), 0);
+#endif
+ if ( bLast && pDestCell->GetMatrixFlag() )
+ {
+ ScAddress aOrg;
+ if ( pDestCell->GetMatrixOrigin( aOrg ) )
+ {
+ if ( nDestCol >= aOrg.Col() && nDestRow >= aOrg.Row() )
+ {
+ ScBaseCell* pOrgCell = pDocument->GetCell( aOrg );
+ if ( pOrgCell && pOrgCell->GetCellType() == CELLTYPE_FORMULA
+ && ((ScFormulaCell*)pOrgCell)->GetMatrixFlag() == MM_FORMULA )
+ {
+ ((ScFormulaCell*)pOrgCell)->SetMatColsRows(
+ nDestCol - aOrg.Col() + 1,
+ nDestRow - aOrg.Row() + 1 );
+ }
+ else
+ {
+ DBG_ERRORFILE( "FillFormula: MatrixOrigin keine Formelzelle mit MM_FORMULA" );
+ }
+ }
+ else
+ {
+ DBG_ERRORFILE( "FillFormula: MatrixOrigin rechts unten" );
+ }
+ }
+ else
+ {
+ DBG_ERRORFILE( "FillFormula: kein MatrixOrigin" );
+ }
+ }
+ pDocument->SetNoListening( FALSE );
+ pDestCell->StartListeningTo( pDocument );
+ }
+}
+
+void ScTable::FillAuto( USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2,
+ USHORT nFillCount, FillDir eFillDir, ScProgress& rProgress )
+{
+ if ( (nFillCount == 0) || !ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2) )
+ return;
+
+ //
+ // Richtung auswerten
+ //
+
+ BOOL bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP);
+ BOOL bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT);
+
+ USHORT nCol;
+ USHORT nRow;
+ USHORT& rInner = bVertical ? nRow : nCol; // Schleifenvariablen
+ USHORT& rOuter = bVertical ? nCol : nRow;
+ USHORT nOStart;
+ USHORT nOEnd;
+ USHORT nIStart;
+ USHORT nIEnd;
+ USHORT nISrcStart;
+ USHORT nISrcEnd;
+
+ if (bVertical)
+ {
+ nOStart = nCol1;
+ nOEnd = nCol2;
+ if (bPositive)
+ {
+ nISrcStart = nRow1;
+ nISrcEnd = nRow2;
+ nIStart = nRow2 + 1;
+ nIEnd = nRow2 + nFillCount;
+ }
+ else
+ {
+ nISrcStart = nRow2;
+ nISrcEnd = nRow1;
+ nIStart = nRow1 - 1;
+ nIEnd = nRow1 - nFillCount;
+ }
+ }
+ else
+ {
+ nOStart = nRow1;
+ nOEnd = nRow2;
+ if (bPositive)
+ {
+ nISrcStart = nCol1;
+ nISrcEnd = nCol2;
+ nIStart = nCol2 + 1;
+ nIEnd = nCol2 + nFillCount;
+ }
+ else
+ {
+ nISrcStart = nCol2;
+ nISrcEnd = nCol1;
+ nIStart = nCol1 - 1;
+ nIEnd = nCol1 - nFillCount;
+ }
+ }
+ USHORT nIMin = nIStart;
+ USHORT nIMax = nIEnd;
+ PutInOrder(nIMin,nIMax);
+ if (bVertical)
+ DeleteArea(nCol1, nIMin, nCol2, nIMax, IDF_ALL);
+ else
+ DeleteArea(nIMin, nRow1, nIMax, nRow2, IDF_ALL);
+
+ ULONG nProgress = rProgress.GetState();
+
+ //
+ // ausfuehren
+ //
+
+ USHORT nActFormCnt = 0;
+ for (rOuter = nOStart; rOuter <= nOEnd; rOuter++)
+ {
+ USHORT nMaxFormCnt = 0; // fuer Formeln
+
+ // Attributierung uebertragen
+
+ const ScPatternAttr* pSrcPattern;
+ USHORT nAtSrc = nISrcStart;
+ ScPatternAttr* pNewPattern = NULL;
+ BOOL bGetPattern = TRUE;
+ for (rInner = nIStart;;)
+ {
+ const ScStyleSheet* pStyleSheet;
+ if ( bGetPattern )
+ {
+ if ( pNewPattern )
+ delete pNewPattern;
+ if (bVertical) // rInner&:=nRow, rOuter&:=nCol
+ pSrcPattern = aCol[nCol].GetPattern(nAtSrc);
+ else // rInner&:=nCol, rOuter&:=nRow
+ pSrcPattern = aCol[nAtSrc].GetPattern(nRow);
+ bGetPattern = FALSE;
+ pStyleSheet = pSrcPattern->GetStyleSheet();
+ // Merge/Mergeflag nicht uebernehmen,
+ const SfxItemSet& rSet = pSrcPattern->GetItemSet();
+ if ( rSet.GetItemState(ATTR_MERGE, FALSE) == SFX_ITEM_SET
+ || rSet.GetItemState(ATTR_MERGE_FLAG, FALSE) == SFX_ITEM_SET )
+ {
+ pNewPattern = new ScPatternAttr( *pSrcPattern );
+ SfxItemSet& rNewSet = pNewPattern->GetItemSet();
+ rNewSet.ClearItem(ATTR_MERGE);
+ rNewSet.ClearItem(ATTR_MERGE_FLAG);
+ }
+ else
+ pNewPattern = NULL;
+ }
+
+ if ( bVertical && nISrcStart == nISrcEnd )
+ {
+ // Attribute komplett am Stueck setzen
+ if (pNewPattern || pSrcPattern != pDocument->GetDefPattern())
+ {
+ // Default steht schon da (DeleteArea)
+ USHORT nY1 = Min( nIStart, nIEnd );
+ USHORT nY2 = Max( nIStart, nIEnd );
+ if ( pStyleSheet )
+ aCol[nCol].ApplyStyleArea( nY1, nY2, *pStyleSheet );
+ if ( pNewPattern )
+ aCol[nCol].ApplyPatternArea( nY1, nY2, *pNewPattern );
+ else
+ aCol[nCol].ApplyPatternArea( nY1, nY2, *pSrcPattern );
+ }
+ break; // Schleife abbrechen
+ }
+
+ if ( pSrcPattern != aCol[nCol].GetPattern( nRow ) )
+ {
+ // Vorlage auch uebernehmen
+ //! am AttrArray mit ApplyPattern zusammenfassen ??
+ if ( pStyleSheet )
+ aCol[nCol].ApplyStyle( nRow, *pStyleSheet );
+
+ // ApplyPattern statt SetPattern um alte MergeFlags stehenzulassen
+ if ( pNewPattern )
+ aCol[nCol].ApplyPattern( nRow, *pNewPattern );
+ else
+ aCol[nCol].ApplyPattern( nRow, *pSrcPattern );
+ }
+
+ if (nAtSrc==nISrcEnd)
+ {
+ if ( nAtSrc != nISrcStart )
+ { // mehr als eine Source-Zelle
+ nAtSrc = nISrcStart;
+ bGetPattern = TRUE;
+ }
+ }
+ else if (bPositive)
+ {
+ ++nAtSrc;
+ bGetPattern = TRUE;
+ }
+ else
+ {
+ --nAtSrc;
+ bGetPattern = TRUE;
+ }
+
+ if (rInner == nIEnd) break;
+ if (bPositive) ++rInner; else --rInner;
+ }
+ if ( pNewPattern )
+ delete pNewPattern;
+
+ // Analyse
+
+ FillCmd eFillCmd;
+ FillDateCmd eDateCmd;
+ double nInc;
+ USHORT nMinDigits;
+ ScUserListData* pListData = NULL;
+ USHORT nListIndex;
+ if (bVertical)
+ FillAnalyse(nCol,nRow1, nCol,nRow2, eFillCmd,eDateCmd, nInc,nMinDigits, pListData,nListIndex);
+ else
+ FillAnalyse(nCol1,nRow, nCol2,nRow, eFillCmd,eDateCmd, nInc,nMinDigits, pListData,nListIndex);
+
+ if (bVertical)
+ aCol[nCol].Resize( aCol[nCol].GetCellCount() + nFillCount );
+
+ if (pListData)
+ {
+ USHORT nListCount = pListData->GetSubCount();
+ if ( !bPositive )
+ {
+ // nListIndex auf FillAnalyse zeigt auf den letzten Eintrag -> anpassen
+ USHORT nSub = nISrcStart - nISrcEnd;
+ for (USHORT i=0; i<nSub; i++)
+ {
+ if (nListIndex == 0) nListIndex = nListCount;
+ --nListIndex;
+ }
+ }
+
+ for (rInner = nIStart;;)
+ {
+ if (bPositive)
+ {
+ ++nListIndex;
+ if (nListIndex >= nListCount) nListIndex = 0;
+ }
+ else
+ {
+ if (nListIndex == 0) nListIndex = nListCount;
+ --nListIndex;
+ }
+ aCol[nCol].Insert(nRow, new ScStringCell(pListData->GetSubStr(nListIndex)));
+
+ if (rInner == nIEnd) break;
+ if (bPositive) ++rInner; else --rInner;
+ }
+ nProgress += nIMax - nIMin + 1;
+ rProgress.SetStateOnPercent( nProgress );
+ }
+ else if (eFillCmd == FILL_SIMPLE) // Auffuellen mit Muster
+ {
+ USHORT nSource = nISrcStart;
+ double nDelta;
+ if ( nScFillModeMouseModifier & KEY_MOD1 )
+ nDelta = 0.0;
+ else if ( bPositive )
+ nDelta = 1.0;
+ else
+ nDelta = -1.0;
+ double nVal;
+ USHORT nFormulaCounter = nActFormCnt;
+ BOOL bFirst = TRUE;
+ BOOL bGetCell = TRUE;
+ USHORT nCellDigits = 0;
+ short nHeadNoneTail = 0;
+ long nStringValue;
+ String aValue;
+ ScBaseCell* pSrcCell;
+ CellType eCellType;
+
+ for (rInner = nIStart;;)
+ {
+ if ( bGetCell )
+ {
+ if (bVertical) // rInner&:=nRow, rOuter&:=nCol
+ pSrcCell = aCol[nCol].GetCell( nSource );
+ else // rInner&:=nCol, rOuter&:=nRow
+ pSrcCell = aCol[nSource].GetCell( nRow );
+ bGetCell = FALSE;
+ if ( pSrcCell )
+ {
+ eCellType = pSrcCell->GetCellType();
+ switch ( eCellType )
+ {
+ case CELLTYPE_VALUE:
+ nVal = ((ScValueCell*)pSrcCell)->GetValue();
+ break;
+ case CELLTYPE_STRING:
+ case CELLTYPE_EDIT:
+ if ( eCellType == CELLTYPE_STRING )
+ ((ScStringCell*)pSrcCell)->GetString( aValue );
+ else
+ ((ScEditCell*)pSrcCell)->GetString( aValue );
+ if ( !(nScFillModeMouseModifier & KEY_MOD1) )
+ {
+ nCellDigits = 0; // look at each source cell individually
+ nHeadNoneTail = lcl_DecompValueString(
+ aValue, nStringValue, &nCellDigits );
+ }
+ break;
+ }
+ }
+ else
+ eCellType = CELLTYPE_NONE;
+ }
+ switch (eCellType)
+ {
+ case CELLTYPE_VALUE:
+ aCol[nCol].Insert(nRow, new ScValueCell(nVal + nDelta));
+ break;
+ case CELLTYPE_STRING:
+ case CELLTYPE_EDIT:
+ if ( nHeadNoneTail )
+ {
+ String aStr;
+ if ( nHeadNoneTail < 0 )
+ {
+ aStr = lcl_ValueString( nStringValue+(long)nDelta, nCellDigits );
+ aStr += aValue;
+ }
+ else
+ {
+ aStr = aValue;
+ aStr += lcl_ValueString( nStringValue+(long)nDelta, nCellDigits );
+ }
+ aCol[nCol].Insert(nRow, new ScStringCell( aStr ) );
+ }
+ else
+ {
+ switch ( eCellType )
+ {
+ case CELLTYPE_STRING:
+ aCol[nCol].Insert(nRow,
+ new ScStringCell(*(ScStringCell*)pSrcCell));
+ break;
+ case CELLTYPE_EDIT:
+ aCol[nCol].Insert(nRow,
+ new ScEditCell( *(ScEditCell*)pSrcCell,
+ pDocument ));
+ break;
+ }
+ }
+ break;
+ case CELLTYPE_FORMULA :
+ FillFormula(nFormulaCounter, bFirst,
+ (ScFormulaCell*) pSrcCell, nCol, nRow,
+ (rInner == nIEnd) );
+ if (nFormulaCounter - nActFormCnt > nMaxFormCnt)
+ nMaxFormCnt = nFormulaCounter - nActFormCnt;
+ break;
+ }
+
+ if (nSource==nISrcEnd)
+ {
+ if ( nSource != nISrcStart )
+ { // mehr als eine Source-Zelle
+ nSource = nISrcStart;
+ bGetCell = TRUE;
+ }
+ if ( !(nScFillModeMouseModifier & KEY_MOD1) )
+ {
+ if ( bPositive )
+ nDelta += 1.0;
+ else
+ nDelta -= 1.0;
+ }
+ nFormulaCounter = nActFormCnt;
+ bFirst = FALSE;
+ }
+ else if (bPositive)
+ {
+ ++nSource;
+ bGetCell = TRUE;
+ }
+ else
+ {
+ --nSource;
+ bGetCell = TRUE;
+ }
+
+ // Progress in der inneren Schleife nur bei teuren Zellen,
+ // und auch dann nicht fuer jede einzelne
+
+ ++nProgress;
+ if ( eCellType == CELLTYPE_FORMULA || eCellType == CELLTYPE_EDIT )
+ rProgress.SetStateOnPercent( nProgress );
+
+ if (rInner == nIEnd) break;
+ if (bPositive) ++rInner; else --rInner;
+ }
+ rProgress.SetStateOnPercent( nProgress );
+ }
+ else
+ {
+ if (!bPositive)
+ nInc = -nInc;
+ double nEndVal = (nInc>=0.0) ? MAXDOUBLE : -MAXDOUBLE;
+ if (bVertical)
+ FillSeries( nCol, nRow1, nCol, nRow2, nFillCount, eFillDir,
+ eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, FALSE, rProgress );
+ else
+ FillSeries( nCol1, nRow, nCol2, nRow, nFillCount, eFillDir,
+ eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, FALSE, rProgress );
+ nProgress = rProgress.GetState();
+ }
+
+ nActFormCnt += nMaxFormCnt;
+ }
+}
+
+String ScTable::GetAutoFillPreview( const ScRange& rSource, USHORT nEndX, USHORT nEndY )
+{
+ String aValue;
+
+ USHORT nCol1 = rSource.aStart.Col();
+ USHORT nRow1 = rSource.aStart.Row();
+ USHORT nCol2 = rSource.aEnd.Col();
+ USHORT nRow2 = rSource.aEnd.Row();
+ BOOL bOk = TRUE;
+ long nIndex;
+ USHORT nSrcCount;
+ FillDir eFillDir;
+ if ( nEndX == nCol2 && nEndY == nRow2 ) // leer
+ bOk = FALSE;
+ else if ( nEndX == nCol2 ) // nach oben/unten
+ {
+ nEndX = nCol2 = nCol1; // nur erste Spalte ansehen
+ nSrcCount = nRow2 - nRow1 + 1;
+ nIndex = ((long)nEndY) - nRow1; // kann negativ werden
+ if ( nEndY >= nRow1 )
+ eFillDir = FILL_TO_BOTTOM;
+ else
+ eFillDir = FILL_TO_TOP;
+ }
+ else if ( nEndY == nRow2 ) // nach links/rechts
+ {
+ nEndY = nRow2 = nRow1; // nur erste Zeile ansehen
+ nSrcCount = nCol2 - nCol1 + 1;
+ nIndex = ((long)nEndX) - nCol1; // kann negativ werden
+ if ( nEndX >= nCol1 )
+ eFillDir = FILL_TO_RIGHT;
+ else
+ eFillDir = FILL_TO_LEFT;
+ }
+ else // Richtung nicht eindeutig
+ bOk = FALSE;
+
+ if ( bOk )
+ {
+ FillCmd eFillCmd;
+ FillDateCmd eDateCmd;
+ double nInc;
+ USHORT nMinDigits;
+ ScUserListData* pListData = NULL;
+ USHORT nListIndex;
+
+ FillAnalyse(nCol1,nRow1, nCol2,nRow2, eFillCmd,eDateCmd, nInc,nMinDigits, pListData,nListIndex);
+
+ if ( pListData ) // benutzerdefinierte Liste
+ {
+ USHORT nListCount = pListData->GetSubCount();
+ if ( nListCount )
+ {
+ USHORT nSub = nSrcCount - 1; // nListIndex ist vom letzten Source-Eintrag
+ while ( nIndex < nSub )
+ nIndex += nListCount;
+ USHORT nPos = ( nListIndex + nIndex - nSub ) % nListCount;
+ aValue = pListData->GetSubStr(nPos);
+ }
+ }
+ else if ( eFillCmd == FILL_SIMPLE ) // Auffuellen mit Muster
+ {
+ long nPosIndex = nIndex;
+ while ( nPosIndex < 0 )
+ nPosIndex += nSrcCount;
+ USHORT nPos = nPosIndex % nSrcCount;
+ USHORT nSrcX = nCol1;
+ USHORT nSrcY = nRow1;
+ if ( eFillDir == FILL_TO_TOP || eFillDir == FILL_TO_BOTTOM )
+ nSrcY += nPos;
+ else
+ nSrcX += nPos;
+
+ ScBaseCell* pCell = GetCell( nSrcX, nSrcY );
+ if ( pCell )
+ {
+ long nDelta;
+ if (nIndex >= 0)
+ nDelta = nIndex / nSrcCount;
+ else
+ nDelta = ( nIndex - nSrcCount + 1 ) / nSrcCount; // -1 -> -1
+
+ CellType eType = pCell->GetCellType();
+ switch ( eType )
+ {
+ case CELLTYPE_STRING:
+ case CELLTYPE_EDIT:
+ {
+ if ( eType == CELLTYPE_STRING )
+ ((ScStringCell*)pCell)->GetString( aValue );
+ else
+ ((ScEditCell*)pCell)->GetString( aValue );
+ if ( !(nScFillModeMouseModifier & KEY_MOD1) )
+ {
+ long nVal;
+ USHORT nCellDigits = 0; // look at each source cell individually
+ short nFlag = lcl_DecompValueString( aValue, nVal, &nCellDigits );
+ if ( nFlag < 0 )
+ aValue.Insert( lcl_ValueString( nVal + nDelta, nCellDigits ), 0 );
+ else if ( nFlag > 0 )
+ aValue += lcl_ValueString( nVal + nDelta, nCellDigits );
+ }
+ }
+ break;
+ case CELLTYPE_VALUE:
+ {
+ // dabei kann's keinen Ueberlauf geben...
+ double nVal = ((ScValueCell*)pCell)->GetValue();
+ if ( !(nScFillModeMouseModifier & KEY_MOD1) )
+ nVal += (double) nDelta;
+
+ Color* pColor;
+ ULONG nNumFmt = GetNumberFormat( nSrcX, nSrcY );
+ pDocument->GetFormatTable()->
+ GetOutputString( nVal, nNumFmt, aValue, &pColor );
+ }
+ break;
+ // Formeln nicht
+ }
+ }
+ }
+ else if ( eFillCmd == FILL_LINEAR || eFillCmd == FILL_DATE ) // Werte
+ {
+ BOOL bOk;
+ double nStart;
+ short nHeadNoneTail = 0;
+ ScBaseCell* pCell = GetCell( nCol1, nRow1 );
+ if ( pCell )
+ {
+ CellType eType = pCell->GetCellType();
+ switch ( eType )
+ {
+ case CELLTYPE_STRING:
+ case CELLTYPE_EDIT:
+ {
+ if ( eType == CELLTYPE_STRING )
+ ((ScStringCell*)pCell)->GetString( aValue );
+ else
+ ((ScEditCell*)pCell)->GetString( aValue );
+ long nVal;
+ nHeadNoneTail = lcl_DecompValueString( aValue, nVal );
+ if ( nHeadNoneTail )
+ nStart = (double)nVal;
+ else
+ nStart = 0.0;
+ }
+ break;
+ case CELLTYPE_VALUE:
+ nStart = ((ScValueCell*)pCell)->GetValue();
+ break;
+ case CELLTYPE_FORMULA:
+ nStart = ((ScFormulaCell*)pCell)->GetValue();
+ break;
+ default:
+ nStart = 0.0;
+ }
+ }
+ else
+ nStart = 0.0;
+ if ( eFillCmd == FILL_LINEAR )
+ {
+ double nAdd = nInc;
+ bOk = ( SubTotal::SafeMult( nAdd, (double) nIndex ) &&
+ SubTotal::SafePlus( nStart, nAdd ) );
+ }
+ else // Datum
+ {
+ bOk = TRUE;
+ USHORT nDayOfMonth = 0;
+ if ( nIndex < 0 )
+ {
+ nIndex = -nIndex;
+ nInc = -nInc;
+ }
+ for (long i=0; i<nIndex; i++)
+ IncDate( nStart, nDayOfMonth, nInc, eDateCmd );
+ }
+
+ if (bOk)
+ {
+ if ( nHeadNoneTail )
+ {
+ if ( nHeadNoneTail < 0 )
+ aValue.Insert( lcl_ValueString( (long)nStart, nMinDigits ), 0 );
+ else
+ aValue += lcl_ValueString( (long)nStart, nMinDigits );
+ }
+ else
+ {
+ //! Zahlformat je nach Index holen?
+ Color* pColor;
+ ULONG nNumFmt = GetNumberFormat( nCol1, nRow1 );
+ pDocument->GetFormatTable()->
+ GetOutputString( nStart, nNumFmt, aValue, &pColor );
+ }
+ }
+ }
+ else
+ DBG_ERROR("GetAutoFillPreview: falscher Modus");
+ }
+
+ return aValue;
+}
+
+void ScTable::IncDate(double& rVal, USHORT& nDayOfMonth, double nStep, FillDateCmd eCmd)
+{
+ if (eCmd == FILL_DAY)
+ {
+ rVal += nStep;
+ return;
+ }
+
+ // class Date Grenzen
+ const USHORT nMinYear = 1583;
+ const USHORT nMaxYear = 9956;
+
+ long nInc = (long) nStep; // nach oben/unten begrenzen ?
+ Date aNullDate = *pDocument->GetFormatTable()->GetNullDate();
+ Date aDate = aNullDate;
+ aDate += (long)rVal;
+ switch (eCmd)
+ {
+ case FILL_WEEKDAY:
+ {
+ aDate += nInc;
+ DayOfWeek eWeekDay = aDate.GetDayOfWeek();
+ if (nInc >= 0)
+ {
+ if (eWeekDay == SATURDAY)
+ aDate += 2;
+ else if (eWeekDay == SUNDAY)
+ aDate += 1;
+ }
+ else
+ {
+ if (eWeekDay == SATURDAY)
+ aDate -= 1;
+ else if (eWeekDay == SUNDAY)
+ aDate -= 2;
+ }
+ }
+ break;
+ case FILL_MONTH:
+ {
+ if ( nDayOfMonth == 0 )
+ nDayOfMonth = aDate.GetDay(); // init
+ long nMonth = aDate.GetMonth();
+ long nYear = aDate.GetYear();
+
+ nMonth += nInc;
+
+ if (nInc >= 0)
+ {
+ if (nMonth > 12)
+ {
+ long nYAdd = (nMonth-1) / 12;
+ nMonth -= nYAdd * 12;
+ nYear += nYAdd;
+ }
+ }
+ else
+ {
+ if (nMonth < 1)
+ {
+ long nYAdd = 1 - nMonth / 12; // positiv
+ nMonth += nYAdd * 12;
+ nYear -= nYAdd;
+ }
+ }
+
+ if ( nYear < nMinYear )
+ aDate = Date( 1,1, nMinYear );
+ else if ( nYear > nMaxYear )
+ aDate = Date( 31,12, nMaxYear );
+ else
+ {
+ aDate.SetMonth((USHORT) nMonth);
+ aDate.SetYear((USHORT) nYear);
+ if ( nDayOfMonth > 28 )
+ aDate.SetDay( Min( aDate.GetDaysInMonth(), nDayOfMonth ) );
+ }
+ }
+ break;
+ case FILL_YEAR:
+ {
+ long nYear = aDate.GetYear();
+ nYear += nInc;
+ if ( nYear < nMinYear )
+ aDate = Date( 1,1, nMinYear );
+ else if ( nYear > nMaxYear )
+ aDate = Date( 31,12, nMaxYear );
+ else
+ aDate.SetYear((USHORT) nYear);
+ }
+ break;
+ }
+
+ rVal = aDate - aNullDate;
+}
+
+void ScTable::FillSeries( USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2,
+ USHORT nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
+ double nStepValue, double nMaxValue, USHORT nArgMinDigits,
+ BOOL bAttribs, ScProgress& rProgress )
+{
+ //
+ // Richtung auswerten
+ //
+
+ BOOL bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP);
+ BOOL bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT);
+
+ USHORT nCol;
+ USHORT nRow;
+ USHORT& rInner = bVertical ? nRow : nCol; // Schleifenvariablen
+ USHORT& rOuter = bVertical ? nCol : nRow;
+ USHORT nOStart;
+ USHORT nOEnd;
+ USHORT nIStart;
+ USHORT nIEnd;
+ USHORT nISource;
+
+ if (bVertical)
+ {
+ nFillCount += (nRow2 - nRow1);
+ if (nFillCount == 0)
+ return;
+ nOStart = nCol1;
+ nOEnd = nCol2;
+ if (bPositive)
+ {
+ nISource = nRow1;
+ nIStart = nRow1 + 1;
+ nIEnd = nRow1 + nFillCount;
+ }
+ else
+ {
+ nISource = nRow2;
+ nIStart = nRow2 - 1;
+ nIEnd = nRow2 - nFillCount;
+ }
+ }
+ else
+ {
+ nFillCount += (nCol2 - nCol1);
+ if (nFillCount == 0)
+ return;
+ nOStart = nRow1;
+ nOEnd = nRow2;
+ if (bPositive)
+ {
+ nISource = nCol1;
+ nIStart = nCol1 + 1;
+ nIEnd = nCol1 + nFillCount;
+ }
+ else
+ {
+ nISource = nCol2;
+ nIStart = nCol2 - 1;
+ nIEnd = nCol2 - nFillCount;
+ }
+ }
+
+ USHORT nIMin = nIStart;
+ USHORT nIMax = nIEnd;
+ PutInOrder(nIMin,nIMax);
+ USHORT nDel = bAttribs ? IDF_ALL : IDF_CONTENTS;
+ if (bVertical)
+ DeleteArea(nCol1, nIMin, nCol2, nIMax, nDel);
+ else
+ DeleteArea(nIMin, nRow1, nIMax, nRow2, nDel);
+
+ ULONG nProgress = rProgress.GetState();
+
+ //
+ // ausfuehren
+ //
+
+ USHORT nActFormCnt = 0;
+ for (rOuter = nOStart; rOuter <= nOEnd; rOuter++)
+ {
+ BOOL bFirst = TRUE;
+ rInner = nISource;
+ ScBaseCell* pSrcCell = aCol[nCol].GetCell(nRow);
+
+ if (bVertical && bAttribs)
+ aCol[nCol].Resize( aCol[nCol].GetCellCount() + nFillCount );
+
+ if (bAttribs)
+ {
+ const ScPatternAttr* pSrcPattern = aCol[nCol].GetPattern(nRow);
+ if (bVertical)
+ aCol[nCol].SetPatternArea( nIMin, nIMax, *pSrcPattern, TRUE );
+ else
+ for (USHORT nAtCol = nIMin; nAtCol <= nIMax; nAtCol++)
+ aCol[nAtCol].SetPattern(nRow, *pSrcPattern, TRUE);
+ }
+
+ if (pSrcCell)
+ {
+ CellType eCellType = pSrcCell->GetCellType();
+
+ if (eFillCmd == FILL_SIMPLE) // kopieren
+ {
+ if (eCellType == CELLTYPE_FORMULA)
+ {
+ for (rInner = nIMin; rInner <= nIMax; rInner++)
+ {
+ USHORT nInd = nActFormCnt;
+ FillFormula(nInd, bFirst, (ScFormulaCell*)pSrcCell,
+ nCol, nRow, (rInner == nIEnd) );
+ bFirst = FALSE;
+ rProgress.SetStateOnPercent( ++nProgress );
+ }
+ }
+ else if (eCellType != CELLTYPE_NOTE)
+ {
+ for (rInner = nIMin; rInner <= nIMax; rInner++)
+ {
+ aCol[nCol].Insert(nRow, pSrcCell->Clone(pDocument));
+ }
+ nProgress += nIMax - nIMin + 1;
+ rProgress.SetStateOnPercent( nProgress );
+ }
+ }
+ else if (eCellType == CELLTYPE_VALUE || eCellType == CELLTYPE_FORMULA)
+ {
+ double nVal;
+ if (eCellType == CELLTYPE_VALUE)
+ nVal = ((ScValueCell*)pSrcCell)->GetValue();
+ else
+ nVal = ((ScFormulaCell*)pSrcCell)->GetValue();
+
+ BOOL bError = FALSE;
+ BOOL bOverflow = FALSE;
+
+ USHORT nDayOfMonth = 0;
+ for (rInner = nIStart;;)
+ {
+ if (!bError && !bOverflow)
+ {
+ switch (eFillCmd)
+ {
+ case FILL_LINEAR:
+ if (!SubTotal::SafePlus(nVal, nStepValue))
+ bError = TRUE;
+ break;
+ case FILL_GROWTH:
+ if (!SubTotal::SafeMult(nVal, nStepValue))
+ bError = TRUE;
+ break;
+ case FILL_DATE:
+ if (fabs(nVal) > _D_MAX_LONG_)
+ bError = TRUE;
+ else
+ IncDate(nVal, nDayOfMonth, nStepValue, eFillDateCmd);
+ break;
+ }
+
+ if (nStepValue >= 0)
+ {
+ if (nVal > nMaxValue) // Zielwert erreicht?
+ {
+ nVal = nMaxValue;
+ bOverflow = TRUE;
+ }
+ }
+ else
+ {
+ if (nVal < nMaxValue)
+ {
+ nVal = nMaxValue;
+ bOverflow = TRUE;
+ }
+ }
+ }
+
+ if (bError)
+ aCol[nCol].SetError(nRow, errNoValue);
+ else if (!bOverflow)
+ aCol[nCol].SetValue(nRow, nVal);
+
+ if (rInner == nIEnd) break;
+ if (bPositive) ++rInner; else --rInner;
+ }
+ nProgress += nIMax - nIMin + 1;
+ rProgress.SetStateOnPercent( nProgress );
+ }
+ else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT)
+ {
+ if ( nStepValue >= 0 )
+ {
+ if ( nMaxValue >= (double)LONG_MAX )
+ nMaxValue = (double)LONG_MAX - 1;
+ }
+ else
+ {
+ if ( nMaxValue <= (double)LONG_MIN )
+ nMaxValue = (double)LONG_MIN + 1;
+ }
+ String aValue;
+ if (eCellType == CELLTYPE_STRING)
+ ((ScStringCell*)pSrcCell)->GetString( aValue );
+ else
+ ((ScEditCell*)pSrcCell)->GetString( aValue );
+ long nStringValue;
+ USHORT nMinDigits = nArgMinDigits;
+ short nHeadNoneTail = lcl_DecompValueString( aValue, nStringValue, &nMinDigits );
+ if ( nHeadNoneTail )
+ {
+ double nVal = (double)nStringValue;
+ BOOL bError = FALSE;
+ BOOL bOverflow = FALSE;
+
+ for (rInner = nIStart;;)
+ {
+ if (!bError && !bOverflow)
+ {
+ switch (eFillCmd)
+ {
+ case FILL_LINEAR:
+ if (!SubTotal::SafePlus(nVal, nStepValue))
+ bError = TRUE;
+ break;
+ case FILL_GROWTH:
+ if (!SubTotal::SafeMult(nVal, nStepValue))
+ bError = TRUE;
+ break;
+ }
+
+ if (nStepValue >= 0)
+ {
+ if (nVal > nMaxValue) // Zielwert erreicht?
+ {
+ nVal = nMaxValue;
+ bOverflow = TRUE;
+ }
+ }
+ else
+ {
+ if (nVal < nMaxValue)
+ {
+ nVal = nMaxValue;
+ bOverflow = TRUE;
+ }
+ }
+ }
+
+ if (bError)
+ aCol[nCol].SetError(nRow, errNoValue);
+ else if (!bOverflow)
+ {
+ nStringValue = (long)nVal;
+ String aStr;
+ if ( nHeadNoneTail < 0 )
+ {
+ aStr = lcl_ValueString( nStringValue, nMinDigits );
+ aStr += aValue;
+ }
+ else
+ {
+ aStr = aValue;
+ aStr += lcl_ValueString( nStringValue, nMinDigits );
+ }
+ ScStringCell* pCell = new ScStringCell( aStr );
+ aCol[nCol].Insert(nRow, pCell);
+ }
+
+ if (rInner == nIEnd) break;
+ if (bPositive) ++rInner; else --rInner;
+ }
+ }
+ nProgress += nIMax - nIMin + 1;
+ rProgress.SetStateOnPercent( nProgress );
+ }
+ }
+ else
+ {
+ nProgress += nIMax - nIMin + 1;
+ rProgress.SetStateOnPercent( nProgress );
+ }
+ ++nActFormCnt;
+ }
+}
+
+void ScTable::Fill( USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2,
+ USHORT nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
+ double nStepValue, double nMaxValue)
+{
+ ULONG nProgCount;
+ if (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP)
+ nProgCount = nCol2 - nCol1 + 1;
+ else
+ nProgCount = nRow2 - nRow1 + 1;
+ nProgCount *= nFillCount;
+ ScProgress aProgress( pDocument->GetDocumentShell(),
+ ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS), nProgCount );
+
+ bSharedNameInserted = FALSE;
+
+ if (eFillCmd == FILL_AUTO)
+ FillAuto(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir, aProgress);
+ else
+ FillSeries(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir,
+ eFillCmd, eFillDateCmd, nStepValue, nMaxValue, 0, TRUE, aProgress);
+
+ if (bSharedNameInserted) // Wurde Shared-Name eingefuegt?
+ pDocument->GetRangeName()->SetSharedMaxIndex(
+ pDocument->GetRangeName()->GetSharedMaxIndex()+1); // dann hochzaehlen
+}
+
+
+void ScTable::AutoFormatArea(USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow,
+ USHORT nIndex, USHORT nFormatNo)
+{
+ ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat();
+ if (pAutoFormat)
+ {
+ ScAutoFormatData* pData = (*pAutoFormat)[nFormatNo];
+ if (pData)
+ {
+ ScPatternAttr aPattern(pDocument->GetPool());
+ if (pData->GetIncludeValueFormat())
+ {
+ ScNumFormatAbbrev aNumFormat;
+ pData->GetNumFormat(nIndex, aNumFormat);
+ SfxUInt32Item aValueFormat( ATTR_VALUE_FORMAT, 0 );
+ aValueFormat.SetValue(aNumFormat.GetFormatIndex(*pDocument->GetFormatTable()));
+ aPattern.GetItemSet().Put(aValueFormat);
+ SvxLanguageItem aLangItem( aNumFormat.GetLanguage(), ATTR_LANGUAGE_FORMAT );
+ aPattern.GetItemSet().Put( aLangItem );
+ }
+ if (pData->GetIncludeFont())
+ {
+
+ SvxFontItem aFont;
+ pData->GetFont(nIndex, aFont);
+ aPattern.GetItemSet().Put(aFont);
+
+ SvxFontHeightItem aFontHeight;
+ pData->GetFontHeight(nIndex, aFontHeight);
+ aPattern.GetItemSet().Put(aFontHeight);
+
+ SvxWeightItem aFontWeight;
+ pData->GetFontWeight(nIndex, aFontWeight);
+ aPattern.GetItemSet().Put(aFontWeight);
+
+ SvxPostureItem aFontPosture;
+ pData->GetFontPosture(nIndex, aFontPosture);
+ aPattern.GetItemSet().Put(aFontPosture);
+
+ SvxUnderlineItem aFontUnderline;
+ pData->GetFontUnderline(nIndex, aFontUnderline);
+ aPattern.GetItemSet().Put(aFontUnderline);
+
+ SvxCrossedOutItem aFontCrossedOut;
+ pData->GetFontCrossedOut(nIndex, aFontCrossedOut);
+ aPattern.GetItemSet().Put(aFontCrossedOut);
+
+ SvxContourItem aFontContour;
+ pData->GetFontContour(nIndex, aFontContour);
+ aPattern.GetItemSet().Put(aFontContour);
+
+ SvxShadowedItem aFontShadowed;
+ pData->GetFontShadowed(nIndex, aFontShadowed);
+ aPattern.GetItemSet().Put(aFontShadowed);
+
+ SvxColorItem aFontColor;
+ pData->GetFontColor(nIndex, aFontColor);
+ aPattern.GetItemSet().Put(aFontColor);
+ }
+ if (pData->GetIncludeJustify())
+ {
+ SvxHorJustifyItem aHorJustify;
+ pData->GetHorJustify(nIndex, aHorJustify);
+ aPattern.GetItemSet().Put(aHorJustify);
+
+ SvxVerJustifyItem aVerJustify;
+ pData->GetVerJustify(nIndex, aVerJustify);
+ aPattern.GetItemSet().Put(aVerJustify);
+
+ SvxOrientationItem aOrientation;
+ pData->GetOrientation(nIndex, aOrientation);
+ aPattern.GetItemSet().Put(aOrientation);
+
+ SfxBoolItem aLinebreak;
+ pData->GetLinebreak(nIndex, aLinebreak);
+ aPattern.GetItemSet().Put(aLinebreak);
+
+ SvxMarginItem aMargin;
+ pData->GetMargin(nIndex, aMargin);
+ aPattern.GetItemSet().Put(aMargin);
+
+ SfxInt32Item aRotateAngle( ATTR_ROTATE_VALUE );
+ pData->GetRotateAngle(nIndex, aRotateAngle);
+ aPattern.GetItemSet().Put(aRotateAngle);
+
+ SvxRotateModeItem aRotateMode( SVX_ROTATE_MODE_STANDARD, ATTR_ROTATE_MODE );
+ pData->GetRotateMode(nIndex, aRotateMode);
+ aPattern.GetItemSet().Put(aRotateMode);
+ }
+ if (pData->GetIncludeFrame())
+ {
+ SvxBoxItem aBox(ATTR_BORDER);
+ pData->GetBox(nIndex, aBox);
+ aPattern.GetItemSet().Put(aBox);
+ }
+ if (pData->GetIncludeBackground())
+ {
+ SvxBrushItem aBackground;
+ pData->GetBackground(nIndex, aBackground);
+ aPattern.GetItemSet().Put(aBackground);
+ }
+ ApplyPatternArea(nStartCol, nStartRow, nEndCol, nEndRow, aPattern);
+ }
+ }
+}
+
+void ScTable::AutoFormat( USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow,
+ USHORT nFormatNo )
+{
+ if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
+ {
+ ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat();
+ if (pAutoFormat)
+ {
+ ScAutoFormatData* pData = (ScAutoFormatData*)(*pAutoFormat)[nFormatNo];
+ if (pData)
+ {
+ USHORT nCol = nStartCol;
+ USHORT nRow = nStartRow;
+ USHORT nIndex = 0;
+ // Linke obere Ecke
+ AutoFormatArea(nCol, nRow, nCol, nRow, nIndex, nFormatNo);
+ // Linke Spalte
+ if (pData->IsEqualData(4, 8))
+ AutoFormatArea(nStartCol, nStartRow + 1, nStartCol, nEndRow - 1, 4, nFormatNo);
+ else
+ {
+ nIndex = 4;
+ for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
+ {
+ AutoFormatArea(nCol, nRow, nCol, nRow, nIndex, nFormatNo);
+ if (nIndex == 4)
+ nIndex = 8;
+ else
+ nIndex = 4;
+ }
+ }
+ // Linke untere Ecke
+ nRow = nEndRow;
+ nIndex = 12;
+ AutoFormatArea(nCol, nRow, nCol, nRow, nIndex, nFormatNo);
+ // Rechte obere Ecke
+ nCol = nEndCol;
+ nRow = nStartRow;
+ nIndex = 3;
+ AutoFormatArea(nCol, nRow, nCol, nRow, nIndex, nFormatNo);
+ // Rechte Spalte
+ if (pData->IsEqualData(7, 11))
+ AutoFormatArea(nEndCol, nStartRow + 1, nEndCol, nEndRow - 1, 7, nFormatNo);
+ else
+ {
+ nIndex = 7;
+ for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
+ {
+ AutoFormatArea(nCol, nRow, nCol, nRow, nIndex, nFormatNo);
+ if (nIndex == 7)
+ nIndex = 11;
+ else
+ nIndex = 7;
+ }
+ }
+ // Rechte untere Ecke
+ nRow = nEndRow;
+ nIndex = 15;
+ AutoFormatArea(nCol, nRow, nCol, nRow, nIndex, nFormatNo);
+ nRow = nStartRow;
+ nIndex = 1;
+ for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
+ {
+ AutoFormatArea(nCol, nRow, nCol, nRow, nIndex, nFormatNo);
+ if (nIndex == 1)
+ nIndex = 2;
+ else
+ nIndex = 1;
+ }
+ // Untere Zeile
+ nRow = nEndRow;
+ nIndex = 13;
+ for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
+ {
+ AutoFormatArea(nCol, nRow, nCol, nRow, nIndex, nFormatNo);
+ if (nIndex == 13)
+ nIndex = 14;
+ else
+ nIndex = 13;
+ }
+ // Boddy
+ if ((pData->IsEqualData(5, 6)) && (pData->IsEqualData(9, 10)) && (pData->IsEqualData(5, 9)))
+ AutoFormatArea(nStartCol + 1, nStartRow + 1, nEndCol-1, nEndRow - 1, 5, nFormatNo);
+ else
+ {
+ if ((pData->IsEqualData(5, 9)) && (pData->IsEqualData(6, 10)))
+ {
+ nIndex = 5;
+ for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
+ {
+ AutoFormatArea(nCol, nStartRow + 1, nCol, nEndRow - 1, nIndex, nFormatNo);
+ if (nIndex == 5)
+ nIndex = 6;
+ else
+ nIndex = 5;
+ }
+ }
+ else
+ {
+ nIndex = 5;
+ for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
+ {
+ for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
+ {
+ AutoFormatArea(nCol, nRow, nCol, nRow, nIndex, nFormatNo);
+ if ((nIndex == 5) || (nIndex == 9))
+ {
+ if (nIndex == 5)
+ nIndex = 9;
+ else
+ nIndex = 5;
+ }
+ else
+ {
+ if (nIndex == 6)
+ nIndex = 10;
+ else
+ nIndex = 6;
+ }
+ } // for nRow
+ if ((nIndex == 5) || (nIndex == 9))
+ nIndex = 6;
+ else
+ nIndex = 5;
+ } // for nCol
+ } // if not equal Column
+ } // if not all equal
+ } // if AutoFormatData != NULL
+ } // if AutoFormat != NULL
+ } // if ValidColRow
+}
+
+void ScTable::GetAutoFormatAttr(USHORT nCol, USHORT nRow, USHORT nIndex, ScAutoFormatData& rData)
+{
+ UINT32 nFormatIndex = GetNumberFormat( nCol, nRow );
+ ScNumFormatAbbrev aNumFormat( nFormatIndex, *pDocument->GetFormatTable() );
+
+ rData.SetNumFormat (nIndex, aNumFormat);
+ rData.SetFont (nIndex, *(SvxFontItem*)GetAttr( nCol, nRow, ATTR_FONT));
+ rData.SetFontHeight (nIndex, *(SvxFontHeightItem*)GetAttr( nCol, nRow, ATTR_FONT_HEIGHT));
+ rData.SetFontWeight (nIndex, *(SvxWeightItem*)GetAttr( nCol, nRow, ATTR_FONT_WEIGHT));
+ rData.SetFontPosture (nIndex, *(SvxPostureItem*)GetAttr( nCol, nRow, ATTR_FONT_POSTURE));
+ rData.SetFontUnderline (nIndex, *(SvxUnderlineItem*)GetAttr( nCol, nRow, ATTR_FONT_UNDERLINE));
+ rData.SetFontCrossedOut (nIndex, *(SvxCrossedOutItem*)GetAttr( nCol, nRow, ATTR_FONT_CROSSEDOUT));
+ rData.SetFontContour (nIndex, *(SvxContourItem*)GetAttr( nCol, nRow, ATTR_FONT_CONTOUR));
+ rData.SetFontShadowed (nIndex, *(SvxShadowedItem*)GetAttr( nCol, nRow, ATTR_FONT_SHADOWED));
+ rData.SetFontColor (nIndex, *(SvxColorItem*)GetAttr( nCol, nRow, ATTR_FONT_COLOR));
+ rData.SetHorJustify (nIndex, *(SvxHorJustifyItem*)GetAttr( nCol, nRow, ATTR_HOR_JUSTIFY));
+ rData.SetVerJustify (nIndex, *(SvxVerJustifyItem*)GetAttr( nCol, nRow, ATTR_VER_JUSTIFY));
+ rData.SetOrientation (nIndex, *(SvxOrientationItem*)GetAttr(nCol, nRow, ATTR_ORIENTATION));
+ rData.SetLinebreak (nIndex, *(SfxBoolItem*)GetAttr( nCol, nRow, ATTR_LINEBREAK));
+ rData.SetMargin (nIndex, *(SvxMarginItem*)GetAttr( nCol, nRow, ATTR_MARGIN));
+ rData.SetBackground (nIndex, *(SvxBrushItem*)GetAttr( nCol, nRow, ATTR_BACKGROUND));
+ rData.SetRotateAngle (nIndex, *(SfxInt32Item*)GetAttr( nCol, nRow, ATTR_ROTATE_VALUE));
+ rData.SetRotateMode (nIndex, *(SvxRotateModeItem*)GetAttr( nCol, nRow, ATTR_ROTATE_MODE));
+}
+
+#define LF_LEFT 1
+#define LF_TOP 2
+#define LF_RIGHT 4
+#define LF_BOTTOM 8
+#define LF_ALL (LF_LEFT | LF_TOP | LF_RIGHT | LF_BOTTOM)
+
+void ScTable::GetAutoFormatFrame(USHORT nCol, USHORT nRow, USHORT nFlags, USHORT nIndex, ScAutoFormatData& rData)
+{
+ const SvxBoxItem* pTheBox = (SvxBoxItem*)GetAttr(nCol, nRow, ATTR_BORDER);
+ const SvxBoxItem* pLeftBox = (SvxBoxItem*)GetAttr(nCol - 1, nRow, ATTR_BORDER);
+ const SvxBoxItem* pTopBox = (SvxBoxItem*)GetAttr(nCol, nRow - 1, ATTR_BORDER);
+ const SvxBoxItem* pRightBox = (SvxBoxItem*)GetAttr(nCol + 1, nRow, ATTR_BORDER);
+ const SvxBoxItem* pBottomBox = (SvxBoxItem*)GetAttr(nCol, nRow + 1, ATTR_BORDER);
+
+ SvxBoxItem aBox;
+ if (nFlags & LF_LEFT)
+ {
+ if (pLeftBox)
+ {
+ if (HasPriority(pTheBox->GetLeft(), pLeftBox->GetRight()))
+ aBox.SetLine(pTheBox->GetLeft(), BOX_LINE_LEFT);
+ else
+ aBox.SetLine(pLeftBox->GetRight(), BOX_LINE_LEFT);
+ }
+ else
+ aBox.SetLine(pTheBox->GetLeft(), BOX_LINE_LEFT);
+ }
+ if (nFlags & LF_TOP)
+ {
+ if (pTopBox)
+ {
+ if (HasPriority(pTheBox->GetTop(), pTopBox->GetBottom()))
+ aBox.SetLine(pTheBox->GetTop(), BOX_LINE_TOP);
+ else
+ aBox.SetLine(pTopBox->GetBottom(), BOX_LINE_TOP);
+ }
+ else
+ aBox.SetLine(pTheBox->GetTop(), BOX_LINE_TOP);
+ }
+ if (nFlags & LF_RIGHT)
+ {
+ if (pRightBox)
+ {
+ if (HasPriority(pTheBox->GetRight(), pRightBox->GetLeft()))
+ aBox.SetLine(pTheBox->GetRight(), BOX_LINE_RIGHT);
+ else
+ aBox.SetLine(pRightBox->GetLeft(), BOX_LINE_RIGHT);
+ }
+ else
+ aBox.SetLine(pTheBox->GetRight(), BOX_LINE_RIGHT);
+ }
+ if (nFlags & LF_BOTTOM)
+ {
+ if (pBottomBox)
+ {
+ if (HasPriority(pTheBox->GetBottom(), pBottomBox->GetTop()))
+ aBox.SetLine(pTheBox->GetBottom(), BOX_LINE_BOTTOM);
+ else
+ aBox.SetLine(pBottomBox->GetTop(), BOX_LINE_BOTTOM);
+ }
+ else
+ aBox.SetLine(pTheBox->GetBottom(), BOX_LINE_BOTTOM);
+ }
+ rData.SetBox(nIndex, aBox);
+}
+
+void ScTable::GetAutoFormatData(USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow, ScAutoFormatData& rData)
+{
+ if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
+ {
+ if ((nEndCol - nStartCol >= 3) && (nEndRow - nStartRow >= 3))
+ {
+ // Linke obere Ecke
+ GetAutoFormatAttr(nStartCol, nStartRow, 0, rData);
+ GetAutoFormatFrame(nStartCol, nStartRow, LF_ALL, 0, rData);
+ // Linke Spalte
+ GetAutoFormatAttr(nStartCol, nStartRow + 1, 4, rData);
+ GetAutoFormatAttr(nStartCol, nStartRow + 2, 8, rData);
+ GetAutoFormatFrame(nStartCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 4, rData);
+ if (nEndRow - nStartRow >= 4)
+ GetAutoFormatFrame(nStartCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 8, rData);
+ else
+ {
+ SvxBoxItem aBox;
+ rData.GetBox(4, aBox);
+ rData.SetBox(8, aBox);
+ }
+ // Linke untere Ecke
+ GetAutoFormatAttr(nStartCol, nEndRow, 12, rData);
+ GetAutoFormatFrame(nStartCol, nEndRow, LF_ALL, 12, rData);
+ // Rechte obere Ecke
+ GetAutoFormatAttr(nEndCol, nStartRow, 3, rData);
+ GetAutoFormatFrame(nEndCol, nStartRow, LF_ALL, 3, rData);
+ // Rechte Spalte
+ GetAutoFormatAttr(nEndCol, nStartRow + 1, 7, rData);
+ GetAutoFormatAttr(nEndCol, nStartRow + 2, 11, rData);
+ GetAutoFormatFrame(nEndCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 7, rData);
+ if (nEndRow - nStartRow >= 4)
+ GetAutoFormatFrame(nEndCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 11, rData);
+ else
+ {
+ SvxBoxItem aBox;
+ rData.GetBox(7, aBox);
+ rData.SetBox(11, aBox);
+ }
+ // Rechte untere Ecke
+ GetAutoFormatAttr(nEndCol, nEndRow, 15, rData);
+ GetAutoFormatFrame(nEndCol, nEndRow, LF_ALL, 15, rData);
+ // Ober Zeile
+ GetAutoFormatAttr(nStartCol + 1, nStartRow, 1, rData);
+ GetAutoFormatAttr(nStartCol + 2, nStartRow, 2, rData);
+ GetAutoFormatFrame(nStartCol + 1, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 1, rData);
+ if (nEndCol - nStartCol >= 4)
+ GetAutoFormatFrame(nStartCol + 2, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 2, rData);
+ else
+ {
+ SvxBoxItem aBox;
+ rData.GetBox(1, aBox);
+ rData.SetBox(2, aBox);
+ }
+ // Untere Zeile
+ GetAutoFormatAttr(nStartCol + 1, nEndRow, 13, rData);
+ GetAutoFormatAttr(nStartCol + 2, nEndRow, 14, rData);
+ GetAutoFormatFrame(nStartCol + 1, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 13, rData);
+ if (nEndCol - nStartCol >= 4)
+ GetAutoFormatFrame(nStartCol + 2, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 14, rData);
+ else
+ {
+ SvxBoxItem aBox;
+ rData.GetBox(13, aBox);
+ rData.SetBox(14, aBox);
+ }
+ // Body
+ GetAutoFormatAttr(nStartCol + 1, nStartRow + 1, 5, rData);
+ GetAutoFormatAttr(nStartCol + 2, nStartRow + 1, 6, rData);
+ GetAutoFormatAttr(nStartCol + 1, nStartRow + 2, 9, rData);
+ GetAutoFormatAttr(nStartCol + 2, nStartRow + 2, 10, rData);
+ GetAutoFormatFrame(nStartCol + 1, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 5, rData);
+ if ((nEndCol - nStartCol >= 4) && (nEndRow - nStartRow >= 4))
+ {
+ GetAutoFormatFrame(nStartCol + 2, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 6, rData);
+ GetAutoFormatFrame(nStartCol + 1, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 9, rData);
+ GetAutoFormatFrame(nStartCol + 2, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 10, rData);
+ }
+ else
+ {
+ SvxBoxItem aBox;
+ rData.GetBox(5, aBox);
+ rData.SetBox(6, aBox);
+ rData.SetBox(9, aBox);
+ rData.SetBox(10, aBox);
+ }
+ }
+ }
+}
+
+void ScTable::SetError( USHORT nCol, USHORT nRow, USHORT nError)
+{
+ if (ValidColRow(nCol, nRow))
+ aCol[nCol].SetError( nRow, nError );
+}
+
+void ScTable::UpdateInsertTabAbs(USHORT nTable)
+{
+ for (USHORT i=0; i <= MAXCOL; i++)
+ aCol[i].UpdateInsertTabAbs(nTable);
+}
+
+USHORT ScTable::GetErrorData( USHORT nCol, USHORT nRow ) const
+{
+ if (ValidColRow(nCol,nRow))
+ return aCol[nCol].GetErrorData( nRow );
+ else
+ return 0;
+}
+
+BOOL ScTable::GetNextSpellingCell(USHORT& rCol, USHORT& rRow, BOOL bInSel,
+ const ScMarkData& rMark) const
+{
+ if (rRow == MAXROW+2) // Tabellenende
+ {
+ rRow = 0;
+ rCol = 0;
+ }
+ else
+ {
+ rRow++;
+ if (rRow == MAXROW+1)
+ {
+ rCol++;
+ rRow = 0;
+ }
+ }
+ if (rCol == MAXCOL+1)
+ return TRUE;
+ else
+ {
+ BOOL bStop = FALSE;
+ while (!bStop)
+ {
+ if (rCol <= MAXCOL)
+ {
+ bStop = aCol[rCol].GetNextSpellingCell(rRow, bInSel, rMark);
+ if (bStop)
+ return TRUE;
+ else /*if (rRow == MAXROW+1) */
+ {
+ rCol++;
+ rRow = 0;
+ }
+ }
+ else
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void ScTable::RemoveAutoSpellObj()
+{
+ for (USHORT i=0; i <= MAXCOL; i++)
+ aCol[i].RemoveAutoSpellObj();
+}
+
+BOOL ScTable::TestTabRefAbs(USHORT nTable)
+{
+ BOOL bRet = FALSE;
+ for (USHORT i=0; i <= MAXCOL; i++)
+ if (aCol[i].TestTabRefAbs(nTable))
+ bRet = TRUE;
+ return bRet;
+}
+
+void ScTable::CompileDBFormula()
+{
+ for (USHORT i=0; i<=MAXCOL; i++) aCol[i].CompileDBFormula();
+}
+
+void ScTable::CompileDBFormula( BOOL bCreateFormulaString )
+{
+ for (USHORT i=0; i<=MAXCOL; i++) aCol[i].CompileDBFormula( bCreateFormulaString );
+}
+
+void ScTable::CompileNameFormula( BOOL bCreateFormulaString )
+{
+ for (USHORT i=0; i<=MAXCOL; i++) aCol[i].CompileNameFormula( bCreateFormulaString );
+}
+
+void ScTable::CompileColRowNameFormula()
+{
+ for (USHORT i=0; i<=MAXCOL; i++) aCol[i].CompileColRowNameFormula();
+}
+
+
+
+
+
+
diff --git a/sc/source/core/data/table5.cxx b/sc/source/core/data/table5.cxx
new file mode 100644
index 000000000000..32f118b1bfd8
--- /dev/null
+++ b/sc/source/core/data/table5.cxx
@@ -0,0 +1,644 @@
+/*************************************************************************
+ *
+ * $RCSfile: table5.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:16 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+//------------------------------------------------------------------------
+
+// TOOLS
+#define _BIGINT_HXX
+#define _SFXMULTISEL_HXX
+#define _STACK_HXX
+#define _QUEUE_HXX
+#define _DYNARR_HXX
+#define _TREELIST_HXX
+#define _CACHESTR_HXX
+#define _NEW_HXX
+#define _DYNARY_HXX
+#define _CACHESTR_HXX
+#define _SV_MULTISEL_HXX
+
+//SV
+#define _CONFIG_HXX
+#define _CURSOR_HXX
+#define _FONTDLG_HXX
+#define _PRVWIN_HXX
+#define _HELP_HXX
+#define _SPIN_HXX
+#define _FILDLG_HXX
+#define _COLDLG_HXX
+#define _SOUND_HXX
+#define _MENUBTN_HXX
+#define _CLIP_HXX //*
+#define _CONFIG_HXX
+#define _CURSOR_HXX
+#define _FONTDLG_HXX
+#define _PRVWIN_HXX
+//#define _COLOR_HXX
+//#define _PAL_HXX
+//#define _BITMAP_HXX
+//#define _GDIOBJ_HXX
+//#define _POINTR_HXX
+//#define _ICON_HXX
+//#define _IMAGE_HXX
+//#define _KEYCOD_HXX
+//#define _EVENT_HXX
+#define _HELP_HXX
+//#define _APP_HXX
+//#define _MDIAPP_HXX
+//#define _TIMER_HXX
+//#define _METRIC_HXX
+//#define _REGION_HXX
+//#define _OUTDEV_HXX
+//#define _SYSTEM_HXX
+//#define _VIRDEV_HXX
+//#define _JOBSET_HXX
+//#define _PRINT_HXX
+//#define _WINDOW_HXX
+//#define _SYSWIN_HXX
+//#define _WRKWIN_HXX
+#define _MDIWIN_HXX
+//#define _FLOATWIN_HXX
+//#define _DOCKWIN_HXX
+//#define _CTRL_HXX
+//#define _SCRBAR_HXX
+//#define _BUTTON_HXX
+//#define _IMAGEBTN_HXX
+//#define _FIXED_HXX
+//#define _GROUP_HXX
+//#define _EDIT_HXX
+//#define _COMBOBOX_HXX
+//#define _LSTBOX_HXX
+//#define _SELENG_HXX ***
+//#define _SPLIT_HXX
+#define _SPIN_HXX
+//#define _FIELD_HXX
+//#define _MOREBTN_HXX ***
+//#define _TOOLBOX_HXX
+//#define _STATUS_HXX ***
+//#define _DIALOG_HXX
+//#define _MSGBOX_HXX
+//#define _SYSDLG_HXX
+#define _FILDLG_HXX
+//#define _PRNDLG_HXX
+#define _COLDLG_HXX
+//#define _TABDLG_HXX
+//#define _MENU_HXX
+//#define _GDIMTF_HXX
+//#define _POLY_HXX
+//#define _ACCEL_HXX
+//#define _GRAPH_HXX
+#define _SOUND_HXX
+
+
+//svtools
+
+#define _SCRWIN_HXX
+#define _RULER_HXX
+//#define _TABBAR_HXX
+//#define _VALUESET_HXX
+#define _STDMENU_HXX
+//#define _STDCTRL_HXX
+//#define _CTRLBOX_HXX
+#define _CTRLTOOL_HXX
+#define _EXTATTR_HXX
+#define _FRM3D_HXX
+#define _EXTATTR_HXX
+//#define _SVTREELIST_HXX ***
+#define _FILTER_HXX
+//#define _SVLBOXITM_HXX ***
+//#define _SVTREEBOX_HXX ***
+#define _SVICNVW_HXX
+#define _SVTABBX_HXX
+#define _SCRWIN_HXX
+#define _RULER_HXX
+#define _STDMENU_HXX
+#define _CTRLTOOL_HXX
+#define _EXTATTR_HXX
+#define _FRM3D_HXX
+#define _EXTATTR_HXX
+#define _FILTER_HXX
+#define _SVICNVW_HXX
+#define _SVTABBX_HXX
+
+//sfxcore.hxx
+#define _SFXGENLINK_HXX
+#define _SFXHINTPOST_HXX
+#define _SFXDOCINF_HXX
+#define _SFXLINKHDL_HXX
+
+//sfxsh.hxx
+#define _SFXMACRO_HXX
+
+// SFX
+#define _SFX_SAVEOPT_HXX
+#define _SFXPRNMON_HXX
+#define _INTRO_HXX
+#define _SFXMSGDESCR_HXX
+#define _SFXMSGPOOL_HXX
+#define _SFXFILEDLG_HXX
+#define _PASSWD_HXX
+#define _SFXTBXCTRL_HXX
+#define _SFXSTBITEM_HXX
+#define _SFXMNUITEM_HXX
+#define _SFXIMGMGR_HXX
+#define _SFXTBXMGR_HXX
+#define _SFXSTBMGR_HXX
+#define _SFX_MINFITEM_HXX
+#define _SFXEVENT_HXX
+
+//sfxdoc.hxx
+//#define _SFX_OBJSH_HXX
+//#define _SFX_CLIENTSH_HXX
+//#define _SFXDOCINF_HXX
+//#define _SFX_OBJFAC_HXX
+#define _SFX_DOCFILT_HXX
+//#define _SFXDOCFILE_HXX ***
+//define _VIEWFAC_HXX
+//#define _SFXVIEWFRM_HXX
+//#define _SFXVIEWSH_HXX
+//#define _MDIFRM_HXX ***
+#define _SFX_IPFRM_HXX
+//#define _SFX_INTERNO_HXX
+
+//sfxdlg.hxx
+//#define _SFXTABDLG_HXX
+//#define _BASEDLGS_HXX ***
+#define _SFX_DINFDLG_HXX
+#define _SFXDINFEDT_HXX
+#define _SFX_MGETEMPL_HXX
+#define _SFX_TPLPITEM_HXX
+//#define _SFX_STYLEDLG_HXX
+#define _NEWSTYLE_HXX
+//#define _SFXDOCTEMPL_HXX ***
+//#define _SFXDOCTDLG_HXX ***
+//#define _SFX_TEMPLDLG_HXX ***
+//#define _SFXNEW_HXX ***
+#define _SFXDOCMAN_HXX
+//#define _SFXDOCKWIN_HXX
+
+//xout.hxx
+//#define _XENUM_HXX
+//#define _XPOLY_HXX
+//#define _XATTR_HXX
+//#define _XOUTX_HXX
+//#define _XPOOL_HXX
+//#define _XTABLE_HXX
+
+//svdraw.hxx
+#define _SDR_NOITEMS
+#define _SDR_NOTOUCH
+#define _SDR_NOTRANSFORM
+#define _SDR_NOOBJECTS
+//#define _SDR_NOVIEWS
+
+//#define SI_NOITEMS //*
+//#define SI_NODRW //*
+#define _SI_NOSBXCONTROLS
+//#define _VCATTR_HXX //*
+#define _VCONT_HXX
+//#define _VCSBX_HXX //*
+#define _SI_NOOTHERFORMS
+#define _VCTRLS_HXX
+//#define _VCDRWOBJ_HXX //*
+#define _SI_NOCONTROL
+#define _SETBRW_HXX
+#define _VCBRW_HXX
+#define _SI_NOSBXCONTROLS
+//#define _SIDLL_HXX //***
+
+#define _SVX_DAILDLL_HXX
+#define _SVX_HYPHEN_HXX
+#define _SVX_IMPGRF_HXX
+#define _SVX_OPTITEMS_HXX
+#define _SVX_OPTGERL_HXX
+#define _SVX_OPTSAVE_HXX
+#define _SVX_OPTSPELL_HXX
+#define _SVX_OPTPATH_HXX
+#define _SVX_OPTLINGU_HXX
+#define _SVX_RULER_HXX
+#define _SVX_RULRITEM_HXX
+#define _SVX_SPLWRAP_HXX
+#define _SVX_SPLDLG_HXX
+#define _SVX_THESDLG_HXX
+
+//inet
+#define _INETINDP_HXX
+#define _INETIMP_HXX
+#define _INETWRAP_HXX
+#define _INETKEEP_HXX
+#define _PLUGMGR_HXX
+#define _URLOBJ_HXX
+
+#define SFX_NOCLOOKS
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "scitems.hxx"
+#include "collect.hxx"
+#include "attrib.hxx"
+#include "patattr.hxx"
+#include "docpool.hxx"
+#include "cell.hxx"
+#include "table.hxx"
+#include "column.hxx"
+#include "document.hxx"
+#include "drwlayer.hxx"
+#include "olinetab.hxx"
+#include "userlist.hxx"
+#include "stlsheet.hxx"
+#include "global.hxx"
+#include "rechead.hxx"
+#include "stlpool.hxx"
+#include "stlsheet.hxx"
+#include "brdcst.hxx"
+#include "globstr.hrc"
+
+// STATIC DATA -----------------------------------------------------------
+
+#define GET_SCALEVALUE(set,id) ((const SfxUInt16Item&)(set.Get( id ))).GetValue()
+
+
+void ScTable::UpdatePageBreaks( const ScRange* pUserArea )
+{
+ if ( !pUserArea && !bPageSizeValid )
+ return;
+
+ SfxStyleSheetBase* pStyle = pDocument->GetStyleSheetPool()->
+ Find( aPageStyle, SFX_STYLE_FAMILY_PAGE );
+ if ( !pStyle )
+ {
+ DBG_ERROR("UpdatePageBreaks: Style nicht gefunden");
+ return;
+ }
+ SfxItemSet* pStyleSet = &pStyle->GetItemSet();
+ const SfxPoolItem* pItem;
+
+ USHORT i;
+ USHORT nX;
+ USHORT nY;
+ USHORT nStartCol = 0;
+ USHORT nStartRow = 0;
+ USHORT nEndCol = MAXCOL;
+ USHORT nEndRow = MAXROW;
+ if (pUserArea)
+ {
+ nStartCol = pUserArea->aStart.Col();
+ nStartRow = pUserArea->aStart.Row();
+ nEndCol = pUserArea->aEnd.Col();
+ nEndRow = pUserArea->aEnd.Row();
+ }
+ else
+ {
+ USHORT nAreaCount = GetPrintRangeCount();
+ if ( nAreaCount > 1 )
+ {
+ // bei mehreren Bereichen nichts anzeigen:
+
+ for (nX=0; nX<MAXCOL; nX++)
+ pColFlags[nX] &= ~CR_PAGEBREAK;
+ for (nY=0; nY<MAXROW; nY++)
+ pRowFlags[nY] &= ~CR_PAGEBREAK;
+
+ return;
+ }
+ else if ( nAreaCount == 1 )
+ {
+ const ScRange* pArea = GetPrintRange( 0 );
+ if (pArea)
+ {
+ nStartCol = pArea->aStart.Col();
+ nStartRow = pArea->aStart.Row();
+ nEndCol = pArea->aEnd.Col();
+ nEndRow = pArea->aEnd.Row();
+ }
+ } // sonst alles
+ }
+
+ // bSkipBreaks holen:
+
+ BOOL bSkipBreaks = FALSE;
+
+ if ( pStyleSet->GetItemState( ATTR_PAGE_SCALETOPAGES, FALSE, &pItem ) == SFX_ITEM_SET )
+ {
+ DBG_ASSERT( pItem->ISA(SfxUInt16Item), "falsches Item" );
+ bSkipBreaks = ( ((const SfxUInt16Item*)pItem)->GetValue() > 0 );
+ }
+
+ //--------------------------------------------------------------------------
+
+ long nPageSizeX = aPageSizeTwips.Width();
+ long nPageSizeY = aPageSizeTwips.Height();
+
+ // Anfang: Breaks loeschen
+
+ for (nX=0; nX<nStartCol; nX++)
+ pColFlags[nX] &= ~CR_PAGEBREAK;
+ for (nY=0; nY<nStartRow; nY++)
+ pRowFlags[nY] &= ~CR_PAGEBREAK;
+
+ if (nStartCol)
+ pColFlags[nStartCol] |= CR_PAGEBREAK; //! AREABREAK
+ if (nStartRow)
+ pRowFlags[nStartRow] |= CR_PAGEBREAK; //! AREABREAK
+
+ // Mittelteil: Breaks verteilen
+
+ BOOL bRepeatCol = ( nRepeatStartX != REPEAT_NONE );
+ BOOL bColFound = FALSE;
+ long nSizeX = 0;
+ for (nX=nStartCol; nX<=nEndCol; nX++)
+ {
+ long nThisX = ( pColFlags[nX] & CR_HIDDEN ) ? 0 : pColWidth[nX];
+ if ( (nSizeX+nThisX > nPageSizeX) || ((pColFlags[nX] & CR_MANUALBREAK) && !bSkipBreaks) )
+ {
+ pColFlags[nX] |= CR_PAGEBREAK;
+ nSizeX = 0;
+ if (bRepeatCol)
+ if (nX>nRepeatStartX && !bColFound)
+ {
+ for (i=nRepeatStartX; i<=nRepeatEndX; i++)
+ nPageSizeX -= ( pColFlags[i] & CR_HIDDEN ) ? 0 : pColWidth[i];
+ while (nX<=nRepeatEndX)
+ pColFlags[++nX] &= ~CR_PAGEBREAK;
+ bColFound = TRUE;
+ }
+ }
+ else if (nX != nStartCol)
+ pColFlags[nX] &= ~CR_PAGEBREAK;
+ nSizeX += nThisX;
+ }
+
+ BOOL bRepeatRow = ( nRepeatStartY != REPEAT_NONE );
+ BOOL bRowFound = FALSE;
+ long nSizeY = 0;
+ for (nY=nStartRow; nY<=nEndRow; nY++)
+ {
+ long nThisY = ( pRowFlags[nY] & CR_HIDDEN ) ? 0 : pRowHeight[nY];
+ if ( (nSizeY+nThisY > nPageSizeY) || ((pRowFlags[nY] & CR_MANUALBREAK) && !bSkipBreaks) )
+ {
+ pRowFlags[nY] |= CR_PAGEBREAK;
+ nSizeY = 0;
+ if (bRepeatRow)
+ if (nY>nRepeatStartY && !bRowFound)
+ {
+ for (i=nRepeatStartY; i<=nRepeatEndY; i++)
+ nPageSizeY -= ( pRowFlags[i] & CR_HIDDEN ) ? 0 : pRowHeight[i];
+ while (nY<=nRepeatEndY)
+ pRowFlags[++nY] &= ~CR_PAGEBREAK;
+ bRowFound = TRUE;
+ }
+ }
+ else if (nY != nStartRow)
+ pRowFlags[nY] &= ~CR_PAGEBREAK;
+ nSizeY += nThisY;
+ }
+
+ // Ende: Breaks loeschen
+
+ if (nEndCol < MAXCOL)
+ {
+ pColFlags[nEndCol+1] |= CR_PAGEBREAK; //! AREABREAK
+ for (nX=nEndCol+2; nX<=MAXCOL; nX++)
+ pColFlags[nX] &= ~CR_PAGEBREAK;
+ }
+ if (nEndRow < MAXROW)
+ {
+ pRowFlags[nEndRow+1] |= CR_PAGEBREAK; //! AREABREAK
+ for (nY=nEndRow+2; nY<=MAXROW; nY++)
+ pRowFlags[nY] &= ~CR_PAGEBREAK;
+ }
+}
+
+void ScTable::RemoveManualBreaks()
+{
+ if (pColFlags)
+ for (USHORT nCol = 0; nCol <= MAXCOL; nCol++)
+ pColFlags[nCol] &= ~CR_MANUALBREAK;
+
+ if (pRowFlags)
+ for (USHORT nRow = 0; nRow <= MAXROW; nRow++)
+ pRowFlags[nRow] &= ~CR_MANUALBREAK;
+}
+
+BOOL ScTable::HasManualBreaks() const
+{
+ if (pColFlags)
+ for (USHORT nCol = 0; nCol <= MAXCOL; nCol++)
+ if ( pColFlags[nCol] & CR_MANUALBREAK )
+ return TRUE;
+
+ if (pRowFlags)
+ for (USHORT nRow = 0; nRow <= MAXROW; nRow++)
+ if ( pRowFlags[nRow] & CR_MANUALBREAK )
+ return TRUE;
+
+ return FALSE;
+}
+
+void ScTable::SetPageSize( const Size& rSize )
+{
+ if ( rSize.Width() != 0 && rSize.Height() != 0 )
+ {
+ bPageSizeValid = TRUE;
+ aPageSizeTwips = rSize;
+ }
+ else
+ bPageSizeValid = FALSE;
+}
+
+Size ScTable::GetPageSize() const
+{
+ if ( bPageSizeValid )
+ return aPageSizeTwips;
+ else
+ return Size(); // leer
+}
+
+void ScTable::SetRepeatArea( USHORT nStartCol, USHORT nEndCol, USHORT nStartRow, USHORT nEndRow )
+{
+ nRepeatStartX = nStartCol;
+ nRepeatEndX = nEndCol;
+ nRepeatStartY = nStartRow;
+ nRepeatEndY = nEndRow;
+}
+
+void ScTable::StartListening( const ScAddress& rAddress, SfxListener* pListener )
+{
+ aCol[rAddress.Col()].StartListening( *pListener, rAddress.Row() );
+}
+
+void ScTable::EndListening( const ScAddress& rAddress, SfxListener* pListener )
+{
+ aCol[rAddress.Col()].EndListening( *pListener, rAddress.Row() );
+}
+
+void ScTable::SetPageStyle( const String& rName )
+{
+ if ( aPageStyle != rName )
+ {
+ String aStrNew = rName;
+ SfxStyleSheetBasePool* pStylePool = pDocument->GetStyleSheetPool();
+ SfxStyleSheetBase* pNewStyle = pStylePool->Find( aStrNew, SFX_STYLE_FAMILY_PAGE );
+
+ if ( !pNewStyle )
+ {
+ aStrNew = ScGlobal::GetRscString(STR_STYLENAME_STANDARD);
+ pNewStyle = pStylePool->Find( aStrNew, SFX_STYLE_FAMILY_PAGE );
+ }
+
+ if ( aPageStyle != aStrNew )
+ {
+ SfxStyleSheetBase* pOldStyle = pStylePool->Find( aPageStyle, SFX_STYLE_FAMILY_PAGE );
+
+ if ( pOldStyle && pNewStyle )
+ {
+ SfxItemSet& rOldSet = pOldStyle->GetItemSet();
+ SfxItemSet& rNewSet = pNewStyle->GetItemSet();
+ const USHORT nOldScale = GET_SCALEVALUE(rOldSet,ATTR_PAGE_SCALE);
+ const USHORT nOldScaleToPages = GET_SCALEVALUE(rOldSet,ATTR_PAGE_SCALETOPAGES);
+ const USHORT nNewScale = GET_SCALEVALUE(rNewSet,ATTR_PAGE_SCALE);
+ const USHORT nNewScaleToPages = GET_SCALEVALUE(rNewSet,ATTR_PAGE_SCALETOPAGES);
+
+ if ( (nOldScale != nNewScale) || (nOldScaleToPages != nNewScaleToPages) )
+ InvalidateTextWidth();
+ }
+
+ if ( pNewStyle ) // auch ohne den alten (fuer UpdateStdNames)
+ aPageStyle = aStrNew;
+ }
+ }
+}
+
+void ScTable::PageStyleModified( const String& rNewName )
+{
+ aPageStyle = rNewName;
+ InvalidateTextWidth(); // man weiss nicht mehr, was vorher drinstand...
+}
+
+void ScTable::InvalidateTextWidth( const ScAddress* pAdrFrom,
+ const ScAddress* pAdrTo,
+ BOOL bBroadcast )
+{
+ if ( pAdrFrom && !pAdrTo )
+ {
+ ScBaseCell* pCell = aCol[pAdrFrom->Col()].GetCell( pAdrFrom->Row() );
+ if ( pCell )
+ {
+ pCell->SetTextWidth( TEXTWIDTH_DIRTY );
+ if ( bBroadcast )
+ { // nur bei CalcAsShown
+ switch ( pCell->GetCellType() )
+ {
+ case CELLTYPE_VALUE :
+ pDocument->Broadcast( SC_HINT_DATACHANGED,
+ ScAddress( pAdrFrom->Col(), pAdrFrom->Row(), nTab ),
+ pCell );
+ break;
+ case CELLTYPE_FORMULA :
+ ((ScFormulaCell*)pCell)->SetDirty();
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ const USHORT nColStart = pAdrFrom ? pAdrFrom->Col() : 0;
+ const USHORT nRowStart = pAdrFrom ? pAdrFrom->Row() : 0;
+ const USHORT nColEnd = pAdrTo ? pAdrTo->Col() : MAXCOL;
+ const USHORT nRowEnd = pAdrTo ? pAdrTo->Row() : MAXROW;
+
+ for ( USHORT nCol=nColStart; nCol<=nColEnd; nCol++ )
+ {
+ ScColumnIterator aIter( &aCol[nCol], nRowStart, nRowEnd );
+ ScBaseCell* pCell = NULL;
+ USHORT nRow = nRowStart;
+
+ while ( aIter.Next( nRow, pCell ) )
+ {
+ pCell->SetTextWidth( TEXTWIDTH_DIRTY );
+ if ( bBroadcast )
+ { // nur bei CalcAsShown
+ switch ( pCell->GetCellType() )
+ {
+ case CELLTYPE_VALUE :
+ pDocument->Broadcast( SC_HINT_DATACHANGED,
+ ScAddress( nCol, nRow, nTab ), pCell );
+ break;
+ case CELLTYPE_FORMULA :
+ ((ScFormulaCell*)pCell)->SetDirty();
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
+
+
diff --git a/sc/source/core/data/table6.cxx b/sc/source/core/data/table6.cxx
new file mode 100644
index 000000000000..80f97e2282a1
--- /dev/null
+++ b/sc/source/core/data/table6.cxx
@@ -0,0 +1,710 @@
+/*************************************************************************
+ *
+ * $RCSfile: table6.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:16 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <svtools/txtcmp.hxx>
+
+#include "table.hxx"
+#include "collect.hxx"
+#include "cell.hxx"
+#include "document.hxx"
+#include "stlpool.hxx"
+#include "markdata.hxx"
+
+#ifndef ITEMID_SEARCH
+#define ITEMID_SEARCH 0
+#endif
+#include <svx/srchitem.hxx>
+
+// STATIC DATA -----------------------------------------------------------
+
+//--------------------------------------------------------------------------
+
+void ScTable::ScReplaceTabsStr( String& rStr, const String& rSrch, const String& rRepl )
+ // von sw (docedt.cxx kopiert, Namen geaendert)
+{
+ xub_StrLen nPos = 0;
+ while( STRING_NOTFOUND != ( nPos = rStr.Search( rSrch, nPos )) )
+ {
+ // wurde das escaped?
+ if( nPos && '\\' == rStr.GetChar(nPos-1) )
+ {
+ // noch nicht am Ende ??
+ rStr.Erase( nPos ); // den \\ noch loeschen
+ if( nPos < rStr.Len() )
+ continue;
+ break;
+ }
+ rStr.Erase( nPos, rSrch.Len() );
+ rStr.Insert( rRepl, nPos );
+ nPos += rRepl.Len();
+ }
+}
+
+BOOL ScTable::SearchCell(const SvxSearchItem& rSearchItem, USHORT nCol, USHORT nRow,
+ const ScMarkData& rMark, String& rUndoStr, ScDocument* pUndoDoc)
+{
+ BOOL bFound = FALSE;
+ BOOL bDoSearch = TRUE;
+ BOOL bDoBack = rSearchItem.GetBackward();
+
+ String aString;
+ ScBaseCell* pCell;
+ if (rSearchItem.GetSelection())
+ bDoSearch = rMark.IsCellMarked(nCol, nRow);
+ if ( bDoSearch && ((pCell = aCol[nCol].GetCell( nRow )) != NULL) )
+ {
+ CellType eCellType = pCell->GetCellType();
+ switch (rSearchItem.GetCellType())
+ {
+ case SVX_SEARCHIN_FORMULA:
+ {
+ if ( eCellType == CELLTYPE_FORMULA )
+ ((ScFormulaCell*)pCell)->GetFormula( aString );
+ else
+ aCol[nCol].GetInputString( nRow, aString );
+ }
+ break;
+ case SVX_SEARCHIN_VALUE:
+ aCol[nCol].GetInputString( nRow, aString );
+ break;
+ case SVX_SEARCHIN_NOTE:
+ {
+ ScPostIt aNote;
+ pCell->GetNote( aNote );
+ aString = aNote.GetText();
+ }
+ break;
+ default:
+ break;
+ }
+ xub_StrLen nStart = 0;
+ xub_StrLen nEnd = aString.Len();
+
+ if (pSearchParam && pSearchText)
+ {
+ if ( bDoBack )
+ {
+ xub_StrLen nTemp=nStart; nStart=nEnd; nEnd=nTemp;
+ bFound = (BOOL)(pSearchText->SearchBkwrd(aString, &nStart, &nEnd));
+ }
+ else
+ bFound = (BOOL)(pSearchText->SearchFrwrd(aString, &nStart, &nEnd));
+
+ if (bFound && rSearchItem.GetWordOnly())
+ bFound = (nStart == 0 && nEnd == aString.Len() - 1);
+ }
+ else
+ {
+ DBG_ERROR("pSearchParam || pSearchText == NULL");
+ return bFound;
+ }
+
+ BYTE cMatrixFlag = MM_NONE;
+ if ( bFound &&
+ ( (rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE)
+ ||(rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE_ALL) ) &&
+ // #60558# Matrix nicht zerreissen, nur Matrixformel ersetzen
+ !( eCellType == CELLTYPE_FORMULA &&
+ ((cMatrixFlag = ((ScFormulaCell*)pCell)->GetMatrixFlag()) == MM_REFERENCE)
+ // kein UndoDoc => Matrix nicht wiederherstellbar => nicht ersetzen
+ || (cMatrixFlag != MM_NONE && !pUndoDoc) )
+ )
+ {
+ if ( cMatrixFlag == MM_NONE && rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE )
+ rUndoStr = aString;
+ else if (pUndoDoc)
+ {
+ ScAddress aAdr( nCol, nRow, nTab );
+ ScBaseCell* pUndoCell = pCell->Clone(pUndoDoc);
+ pUndoDoc->PutCell( aAdr, pUndoCell);
+ }
+ BOOL bRepeat = !rSearchItem.GetWordOnly();
+ do
+ {
+ // wenn der gefundene Text leer ist, nicht weitersuchen,
+ // sonst wuerde man nie mehr aufhoeren (#35410#)
+ if ( nEnd < nStart || nEnd == USHRT_MAX )
+ bRepeat = FALSE;
+
+ String sReplStr = rSearchItem.GetReplaceString();
+ if (rSearchItem.GetRegExp())
+ {
+ String sFndStr = aString.Copy(nStart, nEnd-nStart+1);
+ aString.Erase(nStart, nEnd-nStart+1);
+ ScReplaceTabsStr(sReplStr, '&', sFndStr );
+ ScReplaceTabsStr(sReplStr,
+ String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("\\t")),
+ '\t' );
+ aString.Insert(sReplStr, nStart);
+ }
+ else
+ {
+ aString.Erase(nStart, nEnd - nStart + 1);
+ aString.Insert(rSearchItem.GetReplaceString(), nStart);
+ }
+
+ // Indizes anpassen
+ if (bDoBack)
+ {
+ nEnd = nStart;
+ nStart = 0;
+ }
+ else
+ {
+ nStart += sReplStr.Len();
+ nEnd = aString.Len();
+ }
+
+ // weitersuchen ?
+ if (bRepeat)
+ {
+ if ( rSearchItem.GetCommand() != SVX_SEARCHCMD_REPLACE_ALL || nStart >= nEnd )
+ bRepeat = FALSE;
+ else if (bDoBack)
+ {
+ xub_StrLen nTemp=nStart; nStart=nEnd; nEnd=nTemp;
+ bRepeat = ((BOOL)(pSearchText->SearchBkwrd(aString, &nStart, &nEnd)));
+ }
+ else
+ bRepeat = ((BOOL)(pSearchText->SearchFrwrd(aString, &nStart, &nEnd)));
+ }
+ }
+ while (bRepeat);
+ if (rSearchItem.GetCellType() == SVX_SEARCHIN_NOTE)
+ {
+ ScPostIt aNote;
+ pCell->GetNote( aNote );
+ aNote.SetText(aString);
+ aCol[nCol].SetNote( nRow, aNote );
+ }
+ else if ( cMatrixFlag != MM_NONE )
+ { // #60558# Matrix nicht zerreissen
+ if ( aString.Len() > 2 )
+ { // {} raus, erst hier damit auch "{=" durch "{=..." ersetzt werden kann
+ if ( aString.GetChar( aString.Len()-1 ) == '}' )
+ aString.Erase( aString.Len()-1, 1 );
+ if ( aString.GetChar(0) == '{' )
+ aString.Erase( 0, 1 );
+ }
+ ScAddress aAdr( nCol, nRow, nTab );
+ ScFormulaCell* pFCell = new ScFormulaCell( pDocument, aAdr,
+ aString, cMatrixFlag );
+ USHORT nMatCols, nMatRows;
+ ((ScFormulaCell*)pCell)->GetMatColsRows( nMatCols, nMatRows );
+ pFCell->SetMatColsRows( nMatCols, nMatRows );
+ aCol[nCol].Insert( nRow, pFCell );
+ }
+ else
+ aCol[nCol].SetString(nRow, nTab, aString);
+ //! pCell ist jetzt ungueltig weil deleted
+ }
+ }
+ return bFound;
+}
+
+BOOL ScTable::Search(const SvxSearchItem& rSearchItem, USHORT& rCol, USHORT& rRow,
+ const ScMarkData& rMark, String& rUndoStr, ScDocument* pUndoDoc)
+{
+ BOOL bFound = FALSE;
+ BOOL bAll = (rSearchItem.GetCommand() == SVX_SEARCHCMD_FIND_ALL)
+ ||(rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE_ALL);
+ USHORT nCol = rCol;
+ USHORT nRow = rRow;
+ USHORT nLastCol;
+ USHORT nLastRow;
+ GetLastDataPos(nLastCol, nLastRow);
+ USHORT nType = rSearchItem.GetCellType();
+ if (!bAll && rSearchItem.GetBackward())
+ {
+ nCol = Min(nCol, (USHORT)(nLastCol + 1));
+ nRow = Min(nRow, (USHORT)(nLastRow + 1));
+ if (rSearchItem.GetRowDirection())
+ {
+ nCol--;
+ while (!bFound && ((short)nRow >= 0))
+ {
+ while (!bFound && ((short)nCol >= 0))
+ {
+ bFound = SearchCell(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc);
+ if (!bFound)
+ {
+ BOOL bIsEmpty;
+ do
+ {
+ nCol--;
+ if ((short)nCol >= 0)
+ bIsEmpty = aCol[nCol].IsEmptyData();
+ else
+ bIsEmpty = TRUE;
+ }
+ while (((short)nCol >= 0) && bIsEmpty);
+ }
+ }
+ if (!bFound)
+ {
+ nCol = nLastCol;
+ nRow--;
+ }
+ }
+ }
+ else
+ {
+ nRow--;
+ while (!bFound && ((short)nCol >= 0))
+ {
+ while (!bFound && ((short)nRow >= 0))
+ {
+ bFound = SearchCell(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc);
+ if (!bFound)
+ {
+ if (!aCol[nCol].GetPrevDataPos(nRow))
+ nRow = (USHORT)-1;
+ }
+ }
+ if (!bFound)
+ {
+ BOOL bIsEmpty;
+ nRow = nLastRow;
+ do
+ {
+ nCol--;
+ if ((short)nCol >= 0)
+ bIsEmpty = aCol[nCol].IsEmptyData();
+ else
+ bIsEmpty = TRUE;
+ }
+ while (((short)nCol >= 0) && bIsEmpty);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (!bAll && rSearchItem.GetRowDirection())
+ {
+ nCol++;
+ while (!bFound && (nRow <= nLastRow))
+ {
+ while (!bFound && (nCol <= nLastCol))
+ {
+ bFound = SearchCell(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc);
+ if (!bFound)
+ {
+ nCol++;
+ while ((nCol <= nLastCol) && aCol[nCol].IsEmptyData()) nCol++;
+ }
+ }
+ if (!bFound)
+ {
+ nCol = 0;
+ nRow++;
+ }
+ }
+ }
+ else
+ {
+ nRow++;
+ while (!bFound && (nCol <= nLastCol))
+ {
+ while (!bFound && (nRow <= nLastRow))
+ {
+ bFound = SearchCell(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc);
+ if (!bFound)
+ {
+ if (!aCol[nCol].GetNextDataPos(nRow))
+ nRow = MAXROW + 1;
+ }
+ }
+ if (!bFound)
+ {
+ nRow = 0;
+ nCol++;
+ while ((nCol <= nLastCol) && aCol[nCol].IsEmptyData()) nCol++;
+ }
+ }
+ }
+ }
+ if (bFound)
+ {
+ rCol = nCol;
+ rRow = nRow;
+ }
+ return bFound;
+}
+
+BOOL ScTable::SearchAll(const SvxSearchItem& rSearchItem, ScMarkData& rMark,
+ String& rUndoStr, ScDocument* pUndoDoc)
+{
+ BOOL bFound = TRUE;
+ USHORT nCol = 0;
+ USHORT nRow = (USHORT)-1;
+
+ ScMarkData aNewMark( rMark ); // Tabellen-Markierungen kopieren
+ aNewMark.ResetMark();
+ do
+ {
+ bFound = Search(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc);
+ if (bFound)
+ aNewMark.SetMultiMarkArea( ScRange( nCol, nRow, nTab ) );
+ }
+ while (bFound);
+
+ rMark = aNewMark; // Markierung kopieren
+ //! pro Tabelle
+
+ return (aNewMark.IsMultiMarked());
+}
+
+BOOL ScTable::Replace(const SvxSearchItem& rSearchItem, USHORT& rCol, USHORT& rRow,
+ const ScMarkData& rMark, String& rUndoStr, ScDocument* pUndoDoc)
+{
+ BOOL bFound = FALSE;
+ USHORT nCol = rCol;
+ USHORT nRow = rRow;
+ if (rSearchItem.GetBackward())
+ {
+ if (rSearchItem.GetRowDirection())
+ nCol += 1;
+ else
+ nRow += 1;
+ }
+ else
+ {
+ if (rSearchItem.GetRowDirection())
+ nCol -= 1;
+ else
+ nRow -= 1;
+ }
+ bFound = Search(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc);
+ if (bFound)
+ {
+ rCol = nCol;
+ rRow = nRow;
+ }
+ return bFound;
+}
+
+BOOL ScTable::ReplaceAll(const SvxSearchItem& rSearchItem, ScMarkData& rMark,
+ String& rUndoStr, ScDocument* pUndoDoc)
+{
+ BOOL bOldDouble = ScColumn::bDoubleAlloc; // sollte immer FALSE sein?
+ DBG_ASSERT(!bOldDouble,"bDoubleAlloc ???");
+ ScColumn::bDoubleAlloc = TRUE; // fuer Undo-Doc
+
+ BOOL bFound = TRUE;
+ USHORT nCol = 0;
+ USHORT nRow = (USHORT)-1;
+
+ ScMarkData aNewMark( rMark ); // Tabellen-Markierungen kopieren
+ aNewMark.ResetMark();
+ do
+ {
+ bFound = Search(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc);
+ if (bFound)
+ aNewMark.SetMultiMarkArea( ScRange( nCol, nRow, nTab ) );
+ }
+ while (bFound);
+
+ ScColumn::bDoubleAlloc = bOldDouble;
+
+ rMark = aNewMark; // Markierung kopieren
+ //! pro Tabelle
+
+ return (aNewMark.IsMultiMarked());
+}
+
+BOOL ScTable::SearchStyle(const SvxSearchItem& rSearchItem, USHORT& rCol, USHORT& rRow,
+ ScMarkData& rMark)
+{
+ const ScStyleSheet* pSearchStyle = (const ScStyleSheet*)
+ pDocument->GetStyleSheetPool()->Find(
+ rSearchItem.GetSearchString(), SFX_STYLE_FAMILY_PARA );
+
+ short nCol = (short) rCol;
+ short nRow = (short) rRow;
+ BOOL bFound = FALSE;
+
+ BOOL bSelect = rSearchItem.GetSelection();
+ BOOL bRows = rSearchItem.GetRowDirection();
+ BOOL bBack = rSearchItem.GetBackward();
+ short nAdd = bBack ? -1 : 1;
+
+ if (bRows) // zeilenweise
+ {
+ nRow += nAdd;
+ do
+ {
+ short nNextRow = aCol[nCol].SearchStyle( nRow, pSearchStyle, bBack, bSelect, rMark );
+ if (nNextRow < 0 || nNextRow > MAXROW)
+ {
+ nRow = bBack ? MAXROW : 0;
+ nCol += nAdd;
+ }
+ else
+ {
+ nRow = nNextRow;
+ bFound = TRUE;
+ }
+ }
+ while (!bFound && nCol>=0 && nCol<=MAXCOL);
+ }
+ else // spaltenweise
+ {
+ short nNextRows[MAXCOL+1];
+ short i;
+ for (i=0; i<=MAXCOL; i++)
+ {
+ short nSRow = nRow;
+ if (bBack) { if (i>=nCol) --nSRow; }
+ else { if (i<=nCol) ++nSRow; }
+ nNextRows[i] = aCol[i].SearchStyle( nSRow, pSearchStyle, bBack, bSelect, rMark );
+ }
+ if (bBack) // rueckwaerts
+ {
+ nRow = -1;
+ for (i=MAXCOL; i>=0; i--)
+ if (nNextRows[i]>nRow)
+ {
+ nCol = i;
+ nRow = nNextRows[i];
+ bFound = TRUE;
+ }
+ }
+ else // vorwaerts
+ {
+ nRow = MAXROW+1;
+ for (i=0; i<=MAXCOL; i++)
+ if (nNextRows[i]<nRow)
+ {
+ nCol = i;
+ nRow = nNextRows[i];
+ bFound = TRUE;
+ }
+ }
+ }
+
+ if (bFound)
+ {
+ rCol = (USHORT) nCol;
+ rRow = (USHORT) nRow;
+ }
+ return bFound;
+}
+
+//! einzelnes Pattern fuer Undo zurueckgeben
+
+BOOL ScTable::ReplaceStyle(const SvxSearchItem& rSearchItem, USHORT& rCol, USHORT& rRow,
+ ScMarkData& rMark, BOOL bIsUndo)
+{
+ BOOL bRet;
+ if (bIsUndo)
+ bRet = TRUE;
+ else
+ bRet = SearchStyle(rSearchItem, rCol, rRow, rMark);
+ if (bRet)
+ {
+ const ScStyleSheet* pReplaceStyle = (const ScStyleSheet*)
+ pDocument->GetStyleSheetPool()->Find(
+ rSearchItem.GetReplaceString(), SFX_STYLE_FAMILY_PARA );
+
+ if (pReplaceStyle)
+ ApplyStyle( rCol, rRow, *pReplaceStyle );
+ else
+ DBG_ERROR("pReplaceStyle==0");
+ }
+
+ return bRet;
+}
+
+BOOL ScTable::SearchAllStyle(const SvxSearchItem& rSearchItem, ScMarkData& rMark)
+{
+ const ScStyleSheet* pSearchStyle = (const ScStyleSheet*)
+ pDocument->GetStyleSheetPool()->Find(
+ rSearchItem.GetSearchString(), SFX_STYLE_FAMILY_PARA );
+ BOOL bSelect = rSearchItem.GetSelection();
+ BOOL bBack = rSearchItem.GetBackward();
+
+ ScMarkData aNewMark( rMark ); // Tabellen-Markierungen kopieren
+ aNewMark.ResetMark();
+ USHORT i;
+ for (i=0; i<=MAXCOL; i++)
+ {
+ BOOL bFound = TRUE;
+ short nRow = 0;
+ short nEndRow;
+ while (bFound && nRow <= MAXROW)
+ {
+ bFound = aCol[i].SearchStyleRange( nRow, nEndRow, pSearchStyle, bBack, bSelect, rMark );
+ if (bFound)
+ {
+ if (nEndRow<nRow)
+ {
+ short nTemp = nRow;
+ nRow = nEndRow;
+ nEndRow = nTemp;
+ }
+ aNewMark.SetMultiMarkArea( ScRange( i,nRow,nTab, i,nEndRow,nTab ) );
+ nRow = nEndRow + 1;
+ }
+ }
+ }
+
+ rMark = aNewMark; // Markierung kopieren
+ //! pro Tabelle
+
+ return (aNewMark.IsMultiMarked());
+}
+
+BOOL ScTable::ReplaceAllStyle(const SvxSearchItem& rSearchItem, ScMarkData& rMark,
+ ScDocument* pUndoDoc)
+{
+ BOOL bRet = SearchAllStyle(rSearchItem, rMark);
+ if (bRet)
+ {
+ const ScStyleSheet* pReplaceStyle = (const ScStyleSheet*)
+ pDocument->GetStyleSheetPool()->Find(
+ rSearchItem.GetReplaceString(), SFX_STYLE_FAMILY_PARA );
+
+ if (pReplaceStyle)
+ {
+ if (pUndoDoc)
+ pDocument->CopyToDocument( 0,0,nTab, MAXCOL,MAXROW,nTab,
+ IDF_ATTRIB, TRUE, pUndoDoc, &rMark );
+ ApplySelectionStyle( *pReplaceStyle, rMark );
+ }
+ else
+ DBG_ERROR("pReplaceStyle==0");
+ }
+
+ return bRet;
+}
+
+BOOL ScTable::SearchAndReplace(const SvxSearchItem& rSearchItem,
+ USHORT& rCol, USHORT& rRow, ScMarkData& rMark,
+ String& rUndoStr, ScDocument* pUndoDoc)
+{
+ USHORT nCommand = rSearchItem.GetCommand();
+ BOOL bFound = FALSE;
+ if ( ValidColRow(rCol, rRow) ||
+ ((nCommand == SVX_SEARCHCMD_FIND || nCommand == SVX_SEARCHCMD_REPLACE) &&
+ (((rCol == MAXCOL+1 || rCol == (USHORT)-1) && VALIDROW(rRow)) ||
+ ((rRow == MAXROW+1 || rRow == (USHORT)-1) && VALIDCOL(rCol))
+ )
+ )
+ )
+ {
+ BOOL bStyles = rSearchItem.GetPattern();
+ if (bStyles)
+ {
+ if (nCommand == SVX_SEARCHCMD_FIND)
+ bFound = SearchStyle(rSearchItem, rCol, rRow, rMark);
+ else if (nCommand == SVX_SEARCHCMD_REPLACE)
+ bFound = ReplaceStyle(rSearchItem, rCol, rRow, rMark, FALSE);
+ else if (nCommand == SVX_SEARCHCMD_FIND_ALL)
+ bFound = SearchAllStyle(rSearchItem, rMark);
+ else if (nCommand == SVX_SEARCHCMD_REPLACE_ALL)
+ bFound = ReplaceAllStyle(rSearchItem, rMark, pUndoDoc);
+ }
+ else
+ {
+ if ( rSearchItem.GetRegExp() )
+ pSearchParam = new SearchParam(rSearchItem.GetSearchString(), SearchParam::SRCH_REGEXP, rSearchItem.GetExact(), FALSE, FALSE);
+ else if ( rSearchItem.IsLevenshtein() )
+ {
+ pSearchParam = new SearchParam(rSearchItem.GetSearchString(), SearchParam::SRCH_LEVDIST, rSearchItem.GetExact(), FALSE, FALSE);
+ pSearchParam->SetSrchRelaxed( rSearchItem.IsLEVRelaxed() );
+ pSearchParam->SetLEVOther( rSearchItem.GetLEVOther() );
+ pSearchParam->SetLEVShorter( rSearchItem.GetLEVShorter() );
+ pSearchParam->SetLEVLonger( rSearchItem.GetLEVLonger() );
+ }
+ else
+ pSearchParam = new SearchParam(rSearchItem.GetSearchString(), SearchParam::SRCH_NORMAL, rSearchItem.GetExact(), FALSE, FALSE);
+ pSearchText = new SearchText( *pSearchParam, *ScGlobal::pScInternational );
+ if (nCommand == SVX_SEARCHCMD_FIND)
+ bFound = Search(rSearchItem, rCol, rRow, rMark, rUndoStr, pUndoDoc);
+ else if (nCommand == SVX_SEARCHCMD_FIND_ALL)
+ bFound = SearchAll(rSearchItem, rMark, rUndoStr, pUndoDoc);
+ else if (nCommand == SVX_SEARCHCMD_REPLACE)
+ bFound = Replace(rSearchItem, rCol, rRow, rMark, rUndoStr, pUndoDoc);
+ else if (nCommand == SVX_SEARCHCMD_REPLACE_ALL)
+ bFound = ReplaceAll(rSearchItem, rMark, rUndoStr, pUndoDoc);
+ delete pSearchParam;
+ pSearchParam = NULL;
+ delete pSearchText;
+ pSearchText = NULL;
+ }
+ }
+ return bFound;
+}
+
+
+
+
+
+
diff --git a/sc/source/core/data/userdat.cxx b/sc/source/core/data/userdat.cxx
new file mode 100644
index 000000000000..a87dd978727d
--- /dev/null
+++ b/sc/source/core/data/userdat.cxx
@@ -0,0 +1,755 @@
+/*************************************************************************
+ *
+ * $RCSfile: userdat.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:16 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+//------------------------------------------------------------------------
+
+// TOOLS
+#define _BIGINT_HXX
+#define _SFXMULTISEL_HXX
+#define _STACK_HXX
+#define _QUEUE_HXX
+#define _DYNARR_HXX
+#define _TREELIST_HXX
+#define _CACHESTR_HXX
+#define _NEW_HXX
+//#define _SHL_HXX
+//#define _LINK_HXX
+//#define _ERRCODE_HXX
+//#define _GEN_HXX
+//#define _FRACT_HXX
+//#define _STRING_HXX
+//#define _MTF_HXX
+//#define _CONTNR_HXX
+//#define _LIST_HXX
+//#define _TABLE_HXX
+#define _DYNARY_HXX
+//#define _UNQIDX_HXX
+#define _SVMEMPOOL_HXX
+//#define _UNQID_HXX
+//#define _DEBUG_HXX
+//#define _DATE_HXX
+//#define _TIME_HXX
+//#define _DATETIME_HXX
+//#define _INTN_HXX
+//#define _WLDCRD_HXX
+//#define _FSYS_HXX
+//#define _STREAM_HXX
+#define _SV_MULTISEL_HXX
+
+//SV
+//#define _CLIP_HXX ***
+#define _CONFIG_HXX
+#define _CURSOR_HXX
+#define _FONTDLG_HXX
+#define _PRVWIN_HXX
+//#define _COLOR_HXX
+//#define _PAL_HXX
+//#define _BITMAP_HXX
+//#define _GDIOBJ_HXX
+//#define _POINTR_HXX
+//#define _ICON_HXX
+//#define _IMAGE_HXX
+//#define _KEYCOD_HXX
+//#define _EVENT_HXX
+#define _HELP_HXX
+//#define _APP_HXX
+//#define _MDIAPP_HXX
+//#define _TIMER_HXX
+//#define _METRIC_HXX
+//#define _REGION_HXX
+//#define _OUTDEV_HXX
+//#define _SYSTEM_HXX
+//#define _VIRDEV_HXX
+//#define _JOBSET_HXX
+//#define _PRINT_HXX
+//#define _WINDOW_HXX
+//#define _SYSWIN_HXX
+//#define _WRKWIN_HXX
+#define _MDIWIN_HXX
+//#define _FLOATWIN_HXX
+//#define _DOCKWIN_HXX
+//#define _CTRL_HXX
+//#define _SCRBAR_HXX
+//#define _BUTTON_HXX
+//#define _IMAGEBTN_HXX
+//#define _FIXED_HXX
+//#define _GROUP_HXX
+//#define _EDIT_HXX
+//#define _COMBOBOX_HXX
+//#define _LSTBOX_HXX
+//#define _SELENG_HXX ***
+//#define _SPLIT_HXX
+#define _SPIN_HXX
+//#define _FIELD_HXX
+//#define _MOREBTN_HXX ***
+//#define _TOOLBOX_HXX
+//#define _STATUS_HXX ***
+//#define _DIALOG_HXX
+//#define _MSGBOX_HXX
+//#define _SYSDLG_HXX
+#define _FILDLG_HXX
+//#define _PRNDLG_HXX
+#define _COLDLG_HXX
+//#define _TABDLG_HXX
+//#define _MENU_HXX
+//#define _GDIMTF_HXX
+//#define _POLY_HXX
+//#define _ACCEL_HXX
+//#define _GRAPH_HXX
+#define _SOUND_HXX
+
+#if defined WIN
+#define _MENUBTN_HXX
+#endif
+
+//svtools
+#define _SCRWIN_HXX
+#define _RULER_HXX
+//#define _TABBAR_HXX
+//#define _VALUESET_HXX
+#define _STDMENU_HXX
+//#define _STDCTRL_HXX
+//#define _CTRLBOX_HXX
+#define _CTRLTOOL_HXX
+#define _EXTATTR_HXX
+#define _FRM3D_HXX
+#define _EXTATTR_HXX
+
+//SVTOOLS
+//#define _SVTREELIST_HXX ***
+#define _FILTER_HXX
+//#define _SVLBOXITM_HXX ***
+//#define _SVTREEBOX_HXX ***
+#define _SVICNVW_HXX
+#define _SVTABBX_HXX
+
+//sfxcore.hxx
+//#define _SFXINIMGR_HXX ***
+//#define _SFXCFGITEM_HXX
+//#define _SFX_PRINTER_HXX
+#define _SFXGENLINK_HXX
+#define _SFXHINTPOST_HXX
+#define _SFXDOCINF_HXX
+#define _SFXLINKHDL_HXX
+//#define _SFX_PROGRESS_HXX
+
+//sfxsh.hxx
+//#define _SFX_SHELL_HXX
+//#define _SFXAPP_HXX
+//#define _SFX_BINDINGS_HXX
+//#define _SFXDISPATCH_HXX
+//#define _SFXMSG_HXX ***
+//#define _SFXOBJFACE_HXX ***
+//#define _SFXREQUEST_HXX
+#define _SFXMACRO_HXX
+
+// SFX
+//#define _SFXAPPWIN_HXX ***
+#define _SFX_SAVEOPT_HXX
+//#define _SFX_CHILDWIN_HXX
+//#define _SFXCTRLITEM_HXX
+#define _SFXPRNMON_HXX
+#define _INTRO_HXX
+#define _SFXMSGDESCR_HXX
+#define _SFXMSGPOOL_HXX
+#define _SFXFILEDLG_HXX
+#define _PASSWD_HXX
+#define _SFXTBXCTRL_HXX
+#define _SFXSTBITEM_HXX
+#define _SFXMNUITEM_HXX
+#define _SFXIMGMGR_HXX
+#define _SFXTBXMGR_HXX
+#define _SFXSTBMGR_HXX
+#define _SFX_MINFITEM_HXX
+#define _SFXEVENT_HXX
+
+//sfxdoc.hxx
+//#define _SFX_OBJSH_HXX
+//#define _SFX_CLIENTSH_HXX
+//#define _SFXDOCINF_HXX
+//#define _SFX_OBJFAC_HXX
+#define _SFX_DOCFILT_HXX
+//#define _SFXDOCFILE_HXX ***
+//define _VIEWFAC_HXX
+//#define _SFXVIEWFRM_HXX
+//#define _SFXVIEWSH_HXX
+//#define _MDIFRM_HXX ***
+#define _SFX_IPFRM_HXX
+//#define _SFX_INTERNO_HXX
+
+//sfxdlg.hxx
+//#define _SFXTABDLG_HXX
+//#define _BASEDLGS_HXX ***
+#define _SFX_DINFDLG_HXX
+#define _SFXDINFEDT_HXX
+#define _SFX_MGETEMPL_HXX
+#define _SFX_TPLPITEM_HXX
+//#define _SFX_STYLEDLG_HXX
+#define _NEWSTYLE_HXX
+//#define _SFXDOCTEMPL_HXX ***
+//#define _SFXDOCTDLG_HXX ***
+//#define _SFX_TEMPLDLG_HXX ***
+//#define _SFXNEW_HXX ***
+#define _SFXDOCMAN_HXX
+//#define _SFXDOCKWIN_HXX
+
+//sfxitems.hxx
+#define _SFX_WHMAP_HXX
+#define _ARGS_HXX
+//#define _SFXPOOLITEM_HXX
+//#define _SFXINTITEM_HXX
+//#define _SFXENUMITEM_HXX
+#define _SFXFLAGITEM_HXX
+//#define _SFXSTRITEM_HXX
+#define _SFXPTITEM_HXX
+#define _SFXRECTITEM_HXX
+//#define _SFXITEMPOOL_HXX
+//#define _SFXITEMSET_HXX
+#define _SFXITEMITER_HXX
+#define _SFX_WHITER_HXX
+#define _SFXPOOLCACH_HXX
+//#define _AEITEM_HXX
+#define _SFXRNGITEM_HXX
+//#define _SFXSLSTITM_HXX
+//#define _SFXSTYLE_HXX
+
+//xout.hxx
+//#define _XENUM_HXX
+//#define _XPOLY_HXX
+//#define _XATTR_HXX
+//#define _XOUTX_HXX
+//#define _XPOOL_HXX
+//#define _XTABLE_HXX
+
+//svdraw.hxx
+#define _SDR_NOITEMS
+#define _SDR_NOTOUCH
+#define _SDR_NOTRANSFORM
+//#define _SDR_NOOBJECTS
+//#define _SDR_NOVIEWS
+
+//#define SI_NOITEMS
+//#define SI_NODRW
+#define _SI_NOSBXCONTROLS
+//#define _VCATTR_HXX
+#define _VCONT_HXX
+//#define _VCSBX_HXX
+#define _SI_NOOTHERFORMS
+#define _VCTRLS_HXX
+//#define _VCDRWOBJ_HXX
+#define _SI_NOCONTROL
+#define _SETBRW_HXX
+#define _VCBRW_HXX
+#define _SI_NOSBXCONTROLS
+//#define _SIDLL_HXX ***
+
+#define _SVX_DAILDLL_HXX
+#define _SVX_HYPHEN_HXX
+#define _SVX_IMPGRF_HXX
+#define _SVX_OPTITEMS_HXX
+#define _SVX_OPTGERL_HXX
+#define _SVX_OPTSAVE_HXX
+#define _SVX_OPTSPELL_HXX
+#define _SVX_OPTPATH_HXX
+#define _SVX_OPTLINGU_HXX
+#define _SVX_RULER_HXX
+#define _SVX_RULRITEM_HXX
+#define _SVX_SPLWRAP_HXX
+#define _SVX_SPLDLG_HXX
+#define _SVX_THESDLG_HXX
+
+// neu
+#define _BIGINT_HXX
+#define _SFXMULTISEL_HXX
+#define _STACK_HXX
+#define _QUEUE_HXX
+#define _DYNARR_HXX
+#define _TREELIST_HXX
+#define _CACHESTR_HXX
+#define _NEW_HXX
+//#define _SHL_HXX
+//#define _LINK_HXX
+//#define _ERRCODE_HXX
+//#define _GEN_HXX
+//#define _FRACT_HXX
+//#define _STRING_HXX
+//#define _MTF_HXX
+//#define _CONTNR_HXX
+//#define _LIST_HXX
+//#define _TABLE_HXX
+#define _DYNARY_HXX
+//#define _UNQIDX_HXX
+#define _SVMEMPOOL_HXX
+//#define _UNQID_HXX
+//#define _DEBUG_HXX
+//#define _DATE_HXX
+//#define _TIME_HXX
+//#define _DATETIME_HXX
+//#define _INTN_HXX
+//#define _WLDCRD_HXX
+//#define _FSYS_HXX
+//#define _STREAM_HXX
+#define _CACHESTR_HXX
+#define _SV_MULTISEL_HXX
+
+//SV
+//#define _CLIP_HXX ***
+#define _CONFIG_HXX
+#define _CURSOR_HXX
+#define _FONTDLG_HXX
+#define _PRVWIN_HXX
+//#define _COLOR_HXX
+//#define _PAL_HXX
+//#define _BITMAP_HXX
+//#define _GDIOBJ_HXX
+//#define _POINTR_HXX
+//#define _ICON_HXX
+//#define _IMAGE_HXX
+//#define _KEYCOD_HXX
+//#define _EVENT_HXX
+#define _HELP_HXX
+//#define _APP_HXX
+//#define _MDIAPP_HXX
+//#define _TIMER_HXX
+//#define _METRIC_HXX
+//#define _REGION_HXX
+//#define _OUTDEV_HXX
+//#define _SYSTEM_HXX
+//#define _VIRDEV_HXX
+//#define _JOBSET_HXX
+//#define _PRINT_HXX
+//#define _WINDOW_HXX
+//#define _SYSWIN_HXX
+//#define _WRKWIN_HXX
+#define _MDIWIN_HXX
+//#define _FLOATWIN_HXX
+//#define _DOCKWIN_HXX
+//#define _CTRL_HXX
+//#define _SCRBAR_HXX
+//#define _BUTTON_HXX
+//#define _IMAGEBTN_HXX
+//#define _FIXED_HXX
+//#define _GROUP_HXX
+//#define _EDIT_HXX
+//#define _COMBOBOX_HXX
+//#define _LSTBOX_HXX
+//#define _SELENG_HXX ***
+//#define _SPLIT_HXX
+#define _SPIN_HXX
+//#define _FIELD_HXX
+//#define _MOREBTN_HXX ***
+//#define _TOOLBOX_HXX
+//#define _STATUS_HXX ***
+//#define _DIALOG_HXX
+//#define _MSGBOX_HXX
+//#define _SYSDLG_HXX
+#define _FILDLG_HXX
+//#define _PRNDLG_HXX
+#define _COLDLG_HXX
+//#define _TABDLG_HXX
+//#define _MENU_HXX ***
+//#define _GDIMTF_HXX
+//#define _POLY_HXX
+//#define _ACCEL_HXX
+//#define _GRAPH_HXX
+#define _SOUND_HXX
+
+
+
+
+
+#define _BIGINT_HXX
+#define _SFXMULTISEL_HXX
+#define _STACK_HXX
+#define _QUEUE_HXX
+#define _DYNARR_HXX
+#define _TREELIST_HXX
+#define _CACHESTR_HXX
+#define _NEW_HXX
+//#define _SHL_HXX
+//#define _LINK_HXX
+//#define _ERRCODE_HXX
+//#define _GEN_HXX
+//#define _FRACT_HXX
+//#define _STRING_HXX
+//#define _MTF_HXX
+//#define _CONTNR_HXX
+//#define _LIST_HXX
+//#define _TABLE_HXX
+#define _DYNARY_HXX
+//#define _UNQIDX_HXX
+#define _SVMEMPOOL_HXX
+//#define _UNQID_HXX
+//#define _DEBUG_HXX
+//#define _DATE_HXX
+//#define _TIME_HXX
+//#define _DATETIME_HXX
+//#define _INTN_HXX
+//#define _WLDCRD_HXX
+//#define _FSYS_HXX
+//#define _STREAM_HXX
+#define _CACHESTR_HXX
+#define _SV_MULTISEL_HXX
+
+//SV
+//#define _CLIP_HXX ***
+#define _CONFIG_HXX
+#define _CURSOR_HXX
+#define _FONTDLG_HXX
+#define _PRVWIN_HXX
+//#define _COLOR_HXX
+//#define _PAL_HXX
+//#define _BITMAP_HXX
+//#define _GDIOBJ_HXX
+//#define _POINTR_HXX
+//#define _ICON_HXX
+//#define _IMAGE_HXX
+//#define _KEYCOD_HXX
+//#define _EVENT_HXX
+#define _HELP_HXX
+//#define _APP_HXX
+//#define _MDIAPP_HXX
+//#define _TIMER_HXX
+//#define _METRIC_HXX
+//#define _REGION_HXX
+//#define _OUTDEV_HXX
+//#define _SYSTEM_HXX
+//#define _VIRDEV_HXX
+//#define _JOBSET_HXX
+//#define _PRINT_HXX
+//#define _WINDOW_HXX
+//#define _SYSWIN_HXX
+//#define _WRKWIN_HXX
+#define _MDIWIN_HXX
+//#define _FLOATWIN_HXX
+//#define _DOCKWIN_HXX
+//#define _CTRL_HXX
+//#define _SCRBAR_HXX
+//#define _BUTTON_HXX
+//#define _IMAGEBTN_HXX
+//#define _FIXED_HXX
+//#define _GROUP_HXX
+//#define _EDIT_HXX
+//#define _COMBOBOX_HXX
+//#define _LSTBOX_HXX
+//#define _SELENG_HXX ***
+//#define _SPLIT_HXX
+#define _SPIN_HXX
+//#define _FIELD_HXX
+//#define _MOREBTN_HXX ***
+//#define _TOOLBOX_HXX
+//#define _STATUS_HXX ***
+//#define _DIALOG_HXX
+//#define _MSGBOX_HXX
+//#define _SYSDLG_HXX
+//#define _FILDLG_HXX
+//#define _PRNDLG_HXX
+#define _COLDLG_HXX
+//#define _TABDLG_HXX
+//#define _MENU_HXX
+//#define _GDIMTF_HXX
+//#define _POLY_HXX
+//#define _ACCEL_HXX
+//#define _GRAPH_HXX
+#define _SOUND_HXX
+
+#if defined WIN
+#define _MENUBTN_HXX
+#endif
+
+//svtools
+#define _SCRWIN_HXX
+#define _RULER_HXX
+//#define _TABBAR_HXX
+//#define _VALUESET_HXX
+#define _STDMENU_HXX
+//#define _STDCTRL_HXX
+//#define _CTRLBOX_HXX
+#define _CTRLTOOL_HXX
+#define _EXTATTR_HXX
+#define _FRM3D_HXX
+#define _EXTATTR_HXX
+
+//SVTOOLS
+//#define _SVTREELIST_HXX ***
+#define _FILTER_HXX
+//#define _SVLBOXITM_HXX ***
+//#define _SVTREEBOX_HXX ***
+#define _SVICNVW_HXX
+#define _SVTABBX_HXX
+
+//sfxcore.hxx
+//#define _SFXINIMGR_HXX ***
+//#define _SFXCFGITEM_HXX
+//#define _SFX_PRINTER_HXX
+#define _SFXGENLINK_HXX
+#define _SFXHINTPOST_HXX
+#define _SFXDOCINF_HXX
+#define _SFXLINKHDL_HXX
+//#define _SFX_PROGRESS_HXX
+
+//sfxsh.hxx
+//#define _SFX_SHELL_HXX
+//#define _SFXAPP_HXX
+//#define _SFX_BINDINGS_HXX
+//#define _SFXDISPATCH_HXX
+//#define _SFXMSG_HXX ***
+//#define _SFXOBJFACE_HXX ***
+//#define _SFXREQUEST_HXX
+#define _SFXMACRO_HXX
+
+// SFX
+//#define _SFXAPPWIN_HXX ***
+#define _SFX_SAVEOPT_HXX
+//#define _SFX_CHILDWIN_HXX
+//#define _SFXCTRLITEM_HXX
+#define _SFXPRNMON_HXX
+#define _INTRO_HXX
+#define _SFXMSGDESCR_HXX
+#define _SFXMSGPOOL_HXX
+#define _SFXFILEDLG_HXX
+#define _PASSWD_HXX
+#define _SFXTBXCTRL_HXX
+#define _SFXSTBITEM_HXX
+#define _SFXMNUITEM_HXX
+#define _SFXIMGMGR_HXX
+#define _SFXTBXMGR_HXX
+#define _SFXSTBMGR_HXX
+#define _SFX_MINFITEM_HXX
+#define _SFXEVENT_HXX
+
+
+#define _SFXFILEDLG_HXX
+#define _SFXIMGMGR_HXX
+#define _SFXIPFRM_HXX
+#define _SFX_MACRO_HXX
+#define _SFXMNUITEM_HXX
+#define _SFXMNUMGR_HXX
+#define _SFXMULTISEL_HXX
+#define _SFXMSG_HXX
+#define _SFXMSGDESCR_HXX
+#define _SFXMSGPOOL_HXX
+#define _SFX_MINFITEM_HXX
+#define _SFXOBJFACE_HXX
+#define _SFXOBJFAC_HXX
+//#define _SFXREQUEST_HXX
+#define _SFX_SAVEOPT_HXX
+#define _SFXSTBITEM_HXX
+#define _SFXSTBMGR_HXX
+#define _SFXTBXCTRL_HXX
+#define _SFXTBXMGR_HXX
+
+#define _SVX_DAILDLL_HXX
+#define _SVX_HYPHEN_HXX
+#define _SVX_IMPGRF_HXX
+#define _SVX_OPTITEMS_HXX
+#define _SVX_OPTGERL_HXX
+#define _SVX_OPTSAVE_HXX
+#define _SVX_OPTSPELL_HXX
+#define _SVX_OPTPATH_HXX
+#define _SVX_OPTLINGU_HXX
+#define _SVX_RULER_HXX
+#define _SVX_RULRITEM_HXX
+#define _SVX_SPLWRAP_HXX
+#define _SVX_SPLDLG_HXX
+#define _SVX_THESDLG_HXX
+
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <tools/debug.hxx>
+
+#include "drwlayer.hxx"
+#include "rechead.hxx"
+#include "userdat.hxx"
+
+
+// STATIC DATA -----------------------------------------------------------
+
+
+// -----------------------------------------------------------------------
+
+ScDrawObjFactory::ScDrawObjFactory()
+{
+ SdrObjFactory::InsertMakeUserDataHdl( LINK ( this, ScDrawObjFactory, MakeUserData ) );
+}
+
+ScDrawObjFactory::~ScDrawObjFactory()
+{
+ SdrObjFactory::RemoveMakeUserDataHdl( LINK ( this, ScDrawObjFactory, MakeUserData ) );
+}
+
+IMPL_LINK_INLINE_START( ScDrawObjFactory, MakeUserData, SdrObjFactory *, pObjFactory )
+{
+ if ( pObjFactory->nInventor == SC_DRAWLAYER )
+ {
+ if ( pObjFactory->nIdentifier == SC_UD_OBJDATA )
+ pObjFactory->pNewData = new ScDrawObjData;
+ else if ( pObjFactory->nIdentifier == SC_UD_IMAPDATA )
+ pObjFactory->pNewData = new ScIMapInfo;
+ else
+ DBG_ERROR("MakeUserData: falsche ID");
+ }
+ return 0;
+}
+IMPL_LINK_INLINE_END( ScDrawObjFactory, MakeUserData, SdrObjFactory *, pObjFactory )
+
+//------------------------------------------------------------------------
+
+ScDrawObjData::ScDrawObjData() : SdrObjUserData( SC_DRAWLAYER, SC_UD_OBJDATA, 0 )
+{
+ bValidEnd = FALSE;
+}
+
+ScDrawObjData::ScDrawObjData( const ScDrawObjData& r )
+ : SdrObjUserData( r ), aStt( r.aStt ), aEnd( r.aEnd ),
+ bValidStart( r.bValidStart ), bValidEnd( r.bValidEnd )
+{}
+
+ScDrawObjData::~ScDrawObjData()
+{}
+
+SdrObjUserData* ScDrawObjData::Clone(SdrObject* pObj) const
+{
+ return new ScDrawObjData( *this );
+}
+
+void ScDrawObjData::ReadData( SvStream& r )
+{
+ SdrObjUserData::ReadData( r );
+
+ USHORT n;
+ r >> aStt.nCol >> aStt.nRow >> aStt.nTab
+ >> aEnd.nCol >> aEnd.nRow >> aEnd.nTab
+ >> n;
+ bValidEnd = BOOL( n & 0x0001 );
+ bValidStart = !BOOL( n & 0x0002 ); // Default (0) = bValidStart fuer alte Dokumente
+}
+
+void ScDrawObjData::WriteData( SvStream& r )
+{
+ SdrObjUserData::WriteData( r );
+
+ USHORT n = 0x0000;
+ if (bValidEnd) n |= 0x0001;
+ if (!bValidStart) n |= 0x0002; // Default (0) = bValidStart fuer alte Dokumente
+
+ r << (UINT16) aStt.nCol << (UINT16) aStt.nRow << (UINT16) aStt.nTab
+ << (UINT16) aEnd.nCol << (UINT16) aEnd.nRow << (UINT16) aEnd.nTab
+ << n;
+}
+
+//------------------------------------------------------------------------
+
+ScIMapInfo::ScIMapInfo() :
+ SdrObjUserData( SC_DRAWLAYER, SC_UD_IMAPDATA, 0 )
+{
+}
+
+ScIMapInfo::ScIMapInfo( const ImageMap& rImageMap ) :
+ SdrObjUserData( SC_DRAWLAYER, SC_UD_IMAPDATA, 0 ),
+ aImageMap( rImageMap )
+{
+}
+
+ScIMapInfo::ScIMapInfo( const ScIMapInfo& rIMapInfo ) :
+ SdrObjUserData( rIMapInfo ),
+ aImageMap( rIMapInfo.aImageMap )
+{
+}
+
+__EXPORT ScIMapInfo::~ScIMapInfo()
+{
+}
+
+SdrObjUserData* __EXPORT ScIMapInfo::Clone( SdrObject* pObj ) const
+{
+ return new ScIMapInfo( *this );
+}
+
+void __EXPORT ScIMapInfo::WriteData( SvStream& rOStm )
+{
+ SdrObjUserData::WriteData( rOStm );
+
+ ScWriteHeader aHdr( rOStm );
+
+ rOStm << aImageMap;
+}
+
+void __EXPORT ScIMapInfo::ReadData( SvStream& rIStm )
+{
+ SdrObjUserData::ReadData( rIStm );
+
+ ScReadHeader aHdr( rIStm );
+
+ rIStm >> aImageMap;
+}
+
+
+
+
+
diff --git a/sc/source/core/data/validat.cxx b/sc/source/core/data/validat.cxx
new file mode 100644
index 000000000000..ad653b9496d8
--- /dev/null
+++ b/sc/source/core/data/validat.cxx
@@ -0,0 +1,633 @@
+/*************************************************************************
+ *
+ * $RCSfile: validat.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:16 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <sfx2/app.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/objsh.hxx>
+#include <basic/sbmeth.hxx>
+#include <basic/sbmod.hxx>
+#include <basic/sbstar.hxx>
+#include <svtools/sbx.hxx>
+#include <svtools/zforlist.hxx>
+#include <vcl/msgbox.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/solmath.hxx>
+#include <basctl/basobj.hxx>
+#include <math.h>
+
+
+#include "validat.hxx"
+#include "document.hxx"
+#include "cell.hxx"
+#include "patattr.hxx"
+#include "rechead.hxx"
+#include "globstr.hrc"
+
+//------------------------------------------------------------------------
+
+SV_IMPL_OP_PTRARR_SORT( ScValidationEntries_Impl, ScValidationDataPtr );
+
+//------------------------------------------------------------------------
+
+//
+// Eintrag fuer Gueltigkeit (es gibt nur eine Bedingung)
+//
+
+ScValidationData::ScValidationData( ScValidationMode eMode, ScConditionMode eOper,
+ const String& rExpr1, const String& rExpr2,
+ ScDocument* pDocument, const ScAddress& rPos,
+ BOOL bCompileEnglish ) :
+ ScConditionEntry( eOper, rExpr1, rExpr2, pDocument, rPos, bCompileEnglish ),
+ nKey( 0 ),
+ eDataMode( eMode )
+{
+ bShowInput = bShowError = FALSE;
+ eErrorStyle = SC_VALERR_STOP;
+}
+
+ScValidationData::ScValidationData( const ScValidationData& r ) :
+ ScConditionEntry( r ),
+ nKey( r.nKey ),
+ eDataMode( r.eDataMode ),
+ bShowInput( r.bShowInput ),
+ bShowError( r.bShowError ),
+ eErrorStyle( r.eErrorStyle ),
+ aInputTitle( r.aInputTitle ),
+ aInputMessage( r.aInputMessage ),
+ aErrorTitle( r.aErrorTitle ),
+ aErrorMessage( r.aErrorMessage )
+{
+ // Formeln per RefCount kopiert
+}
+
+ScValidationData::ScValidationData( ScDocument* pDocument, const ScValidationData& r ) :
+ ScConditionEntry( pDocument, r ),
+ nKey( r.nKey ),
+ eDataMode( r.eDataMode ),
+ bShowInput( r.bShowInput ),
+ bShowError( r.bShowError ),
+ eErrorStyle( r.eErrorStyle ),
+ aInputTitle( r.aInputTitle ),
+ aInputMessage( r.aInputMessage ),
+ aErrorTitle( r.aErrorTitle ),
+ aErrorMessage( r.aErrorMessage )
+{
+ // Formeln wirklich kopiert
+}
+
+ScValidationData::ScValidationData( SvStream& rStream, ScMultipleReadHeader& rHdr,
+ ScDocument* pDocument ) :
+ ScConditionEntry( rStream, rHdr, pDocument )
+{
+ // im Datei-Header sind getrennte Eintraege fuer ScConditionEntry und ScValidationData
+
+ rHdr.StartEntry();
+
+ // 1) Key
+ // 2) eDataMode
+ // 3) bShowInput
+ // 4) aInputTitle
+ // 5) aInputMessage
+ // 6) bShowError
+ // 7) aErrorTitle
+ // 8) aErrorMessage
+ // 9) eErrorStyle
+
+ USHORT nDummy;
+ rStream >> nKey;
+ rStream >> nDummy;
+ eDataMode = (ScValidationMode) nDummy;
+ rStream >> bShowInput;
+ rStream.ReadByteString( aInputTitle, rStream.GetStreamCharSet() );
+ rStream.ReadByteString( aInputMessage, rStream.GetStreamCharSet() );
+ rStream >> bShowError;
+ rStream.ReadByteString( aErrorTitle, rStream.GetStreamCharSet() );
+ rStream.ReadByteString( aErrorMessage, rStream.GetStreamCharSet() );
+ rStream >> nDummy;
+ eErrorStyle = (ScValidErrorStyle) nDummy;
+
+ rHdr.EndEntry();
+}
+
+ScValidationData::~ScValidationData()
+{
+}
+
+void ScValidationData::Store(SvStream& rStream, ScMultipleWriteHeader& rHdr) const
+{
+ // im Datei-Header sind getrennte Eintraege fuer ScConditionEntry und ScValidationData
+
+ StoreCondition( rStream, rHdr );
+
+ rHdr.StartEntry();
+
+ // 1) Key
+ // 2) eDataMode
+ // 3) bShowInput
+ // 4) aInputTitle
+ // 5) aInputMessage
+ // 6) bShowError
+ // 7) aErrorTitle
+ // 8) aErrorMessage
+ // 9) eErrorStyle
+
+ rStream << nKey;
+ rStream << (USHORT) eDataMode;
+ rStream << bShowInput;
+ rStream.WriteByteString( aInputTitle, rStream.GetStreamCharSet() );
+ rStream.WriteByteString( aInputMessage, rStream.GetStreamCharSet() );
+ rStream << bShowError;
+ rStream.WriteByteString( aErrorTitle, rStream.GetStreamCharSet() );
+ rStream.WriteByteString( aErrorMessage, rStream.GetStreamCharSet() );
+ rStream << (USHORT) eErrorStyle;
+
+ rHdr.EndEntry();
+}
+
+BOOL ScValidationData::IsEmpty() const
+{
+ return eDataMode == SC_VALID_ANY && !bShowInput && !bShowInput;
+}
+
+BOOL ScValidationData::EqualEntries( const ScValidationData& r ) const
+{
+ // gleiche Parameter eingestellt (ohne Key)
+
+ return ScConditionEntry::operator==(r) &&
+ eDataMode == r.eDataMode &&
+ bShowInput == r.bShowInput &&
+ bShowError == r.bShowError &&
+ eErrorStyle == r.eErrorStyle &&
+ aInputTitle == r.aInputTitle &&
+ aInputMessage == r.aInputMessage &&
+ aErrorTitle == r.aErrorTitle &&
+ aErrorMessage == r.aErrorMessage;
+}
+
+void ScValidationData::ResetInput()
+{
+ bShowInput = FALSE;
+}
+
+void ScValidationData::ResetError()
+{
+ bShowError = FALSE;
+}
+
+void ScValidationData::SetInput( const String& rTitle, const String& rMsg )
+{
+ bShowInput = TRUE;
+ aInputTitle = rTitle;
+ aInputMessage = rMsg;
+}
+
+void ScValidationData::SetError( const String& rTitle, const String& rMsg,
+ ScValidErrorStyle eStyle )
+{
+ bShowError = TRUE;
+ eErrorStyle = eStyle;
+ aErrorTitle = rTitle;
+ aErrorMessage = rMsg;
+}
+
+BOOL ScValidationData::GetErrMsg( String& rTitle, String& rMsg,
+ ScValidErrorStyle& rStyle ) const
+{
+ rTitle = aErrorTitle;
+ rMsg = aErrorMessage;
+ rStyle = eErrorStyle;
+ return bShowError;
+}
+
+ // TRUE -> Abbruch
+
+BOOL ScValidationData::DoMacro( const ScAddress& rPos, const String& rInput,
+ ScFormulaCell* pCell, Window* pParent ) const
+{
+ ScDocument* pDocument = GetDocument();
+ SfxObjectShell* pDocSh = pDocument->GetDocumentShell();
+ if ( !pDocSh || !pDocument->CheckMacroWarn() )
+ return FALSE;
+
+ BOOL bDone = FALSE;
+ BOOL bRet = FALSE; // Standard: kein Abbruch
+ SfxApplication* pSfxApp = SFX_APP();
+ pSfxApp->EnterBasicCall(); // Dok-Basic anlegen etc.
+
+ // Wenn das Dok waehrend eines Basic-Calls geladen wurde,
+ // ist das Sbx-Objekt evtl. nicht angelegt (?)
+// pDocSh->GetSbxObject();
+
+ // keine Sicherheitsabfrage mehr vorneweg (nur CheckMacroWarn), das passiert im CallBasic
+
+#if 0
+ // Makro-Name liegt in folgender Form vor:
+ // "Macroname.Modulname.Libname.Dokumentname" oder
+ // "Macroname.Modulname.Libname.Applikationsname"
+ String aMacroName = aErrorTitle.GetToken(0, '.');
+ String aModulName = aErrorTitle.GetToken(1, '.');
+ String aLibName = aErrorTitle.GetToken(2, '.');
+ String aDocName = aErrorTitle.GetToken(3, '.');
+#endif
+
+ // Funktion ueber den einfachen Namen suchen,
+ // dann aBasicStr, aMacroStr fuer SfxObjectShell::CallBasic zusammenbauen
+
+ StarBASIC* pRoot = pDocSh->GetBasic();
+ SbxVariable* pVar = pRoot->Find( aErrorTitle, SbxCLASS_METHOD );
+ if ( pVar && pVar->ISA(SbMethod) )
+ {
+ SbMethod* pMethod = (SbMethod*)pVar;
+ SbModule* pModule = pMethod->GetModule();
+ SbxObject* pObject = pModule->GetParent();
+ StarBASIC* pBasic = PTR_CAST(StarBASIC,pObject);
+ DBG_ASSERT(pBasic, "Kein Basic gefunden!");
+ String aMacroStr = pObject->GetName();
+ aMacroStr += '.';
+ aMacroStr += pModule->GetName();
+ aMacroStr += '.';
+ aMacroStr += pMethod->GetName();
+ String aBasicStr;
+
+ BasicManager* pAppBasMgr = pSfxApp->GetBasicManager();
+ BasicManager *pBasMgr = pBasic ? BasicIDE::FindBasicManager( pBasic ) : NULL;
+ if ( pBasMgr != pAppBasMgr )
+ aBasicStr = pObject->GetParent()->GetName(); // Dokumentenbasic
+ else
+ aBasicStr = SFX_APP()->GetName(); // Applikationsbasic
+
+ // Parameter fuer Makro
+ SbxArrayRef refPar = new SbxArray;
+
+ // 1) eingegebener / berechneter Wert
+ String aValStr = rInput;
+ double nValue;
+ BOOL bIsValue = FALSE;
+ if ( pCell ) // wenn Zelle gesetzt, aus Interpret gerufen
+ {
+ bIsValue = pCell->IsValue();
+ if ( bIsValue )
+ nValue = pCell->GetValue();
+ else
+ pCell->GetString( aValStr );
+ }
+ if ( bIsValue )
+ refPar->Get(1)->PutDouble( nValue );
+ else
+ refPar->Get(1)->PutString( aValStr );
+
+ // 2) Position der Zelle
+ String aPosStr;
+ rPos.Format( aPosStr, SCA_VALID | SCA_TAB_3D, pDocument );
+ refPar->Get(2)->PutString( aPosStr );
+
+ if ( pCell )
+ pDocument->LockTable( rPos.Tab() );
+ SbxVariableRef refRes = new SbxVariable;
+ ErrCode eRet = pDocSh->CallBasic( aMacroStr, aBasicStr, NULL, refPar, refRes );
+ if ( pCell )
+ pDocument->UnlockTable( rPos.Tab() );
+
+ // Eingabe abbrechen, wenn Basic-Makro FALSE zurueckgibt
+ if ( eRet == ERRCODE_NONE && refRes->GetType() == SbxBOOL && refRes->GetBool() == FALSE )
+ bRet = TRUE;
+ bDone = TRUE;
+ }
+ pSfxApp->LeaveBasicCall();
+
+ if ( !bDone && !pCell ) // Makro nicht gefunden (nur bei Eingabe)
+ {
+ //! andere Fehlermeldung, wenn gefunden, aber nicht bAllowed ??
+
+ ErrorBox aBox( pParent, WinBits(WB_OK),
+ ScGlobal::GetRscString( STR_VALID_MACRONOTFOUND ) );
+ aBox.Execute();
+ }
+
+ return bRet;
+}
+
+void ScValidationData::DoCalcError( ScFormulaCell* pCell ) const
+{
+ if ( eErrorStyle == SC_VALERR_MACRO )
+ DoMacro( pCell->aPos, EMPTY_STRING, pCell, NULL );
+}
+
+ // TRUE -> Abbruch
+
+BOOL ScValidationData::DoError( Window* pParent, const String& rInput,
+ const ScAddress& rPos ) const
+{
+ if ( eErrorStyle == SC_VALERR_MACRO )
+ return DoMacro( rPos, rInput, NULL, pParent );
+
+ // Fehlermeldung ausgeben
+
+ String aTitle = aErrorTitle;
+ if (!aTitle.Len())
+ aTitle = ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ); // application title
+ String aMessage = aErrorMessage;
+ if (!aMessage.Len())
+ aMessage = ScGlobal::GetRscString( STR_VALID_DEFERROR );
+
+ //! ErrorBox / WarningBox / InfoBox ?
+ //! (bei InfoBox immer nur OK-Button)
+
+ WinBits nStyle = 0;
+ switch (eErrorStyle)
+ {
+ case SC_VALERR_STOP:
+ nStyle = WB_OK | WB_DEF_OK;
+ break;
+ case SC_VALERR_WARNING:
+ nStyle = WB_OK_CANCEL | WB_DEF_CANCEL;
+ break;
+ case SC_VALERR_INFO:
+ nStyle = WB_OK_CANCEL | WB_DEF_OK;
+ break;
+ }
+
+ MessBox aBox( pParent, WinBits(nStyle), aTitle, aMessage );
+ USHORT nRet = aBox.Execute();
+
+ return ( eErrorStyle == SC_VALERR_STOP || nRet == RET_CANCEL );
+}
+
+
+BOOL ScValidationData::IsDataValid( const String& rTest, const ScPatternAttr& rPattern,
+ const ScAddress& rPos ) const
+{
+ if ( eDataMode == SC_VALID_ANY )
+ return TRUE; // alles erlaubt
+
+ if ( rTest.GetChar(0) == '=' )
+ return FALSE; // Formeln sind sonst immer ungueltig
+
+ if ( !rTest.Len() )
+ return IsIgnoreBlank(); // leer: wie eingestellt
+
+ SvNumberFormatter* pFormatter = GetDocument()->GetFormatTable();
+
+ // Test, was es denn ist - wie in ScColumn::SetString
+
+ ULONG nFormat = rPattern.GetNumberFormat( pFormatter );
+
+ double nVal;
+ BOOL bIsVal = pFormatter->IsNumberFormat( rTest, nFormat, nVal );
+ ScBaseCell* pCell;
+ if (bIsVal)
+ pCell = new ScValueCell( nVal );
+ else
+ pCell = new ScStringCell( rTest );
+
+ BOOL bRet = IsDataValid( pCell, rPos );
+
+ pCell->Delete();
+ return bRet;
+}
+
+BOOL ScValidationData::IsDataValid( ScBaseCell* pCell, const ScAddress& rPos ) const
+{
+ double nVal = 0.0;
+ String aString;
+ BOOL bIsVal = TRUE;
+
+ switch (pCell->GetCellType())
+ {
+ case CELLTYPE_VALUE:
+ nVal = ((ScValueCell*)pCell)->GetValue();
+ break;
+ case CELLTYPE_STRING:
+ ((ScStringCell*)pCell)->GetString( aString );
+ bIsVal = FALSE;
+ break;
+ case CELLTYPE_EDIT:
+ ((ScEditCell*)pCell)->GetString( aString );
+ bIsVal = FALSE;
+ break;
+ case CELLTYPE_FORMULA:
+ {
+ ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
+ bIsVal = pFCell->IsValue();
+ if ( bIsVal )
+ nVal = pFCell->GetValue();
+ else
+ pFCell->GetString( aString );
+ }
+ break;
+ default: // Notizen, Broadcaster
+ return IsIgnoreBlank(); // wie eingestellt
+ }
+
+ BOOL bOk = TRUE;
+ switch (eDataMode)
+ {
+ // SC_VALID_ANY schon oben
+
+ case SC_VALID_WHOLE:
+ case SC_VALID_DECIMAL:
+ case SC_VALID_DATE: // Date/Time ist nur Formatierung
+ case SC_VALID_TIME:
+ bOk = bIsVal;
+ if ( bOk && eDataMode == SC_VALID_WHOLE )
+ bOk = SolarMath::ApproxEqual( nVal, floor(nVal+0.5) ); // ganze Zahlen
+ if ( bOk )
+ bOk = IsCellValid( pCell, rPos );
+ break;
+
+ case SC_VALID_CUSTOM:
+ // fuer Custom muss eOp == SC_COND_DIRECT sein
+ //! der Wert muss im Dokument stehen !!!!!!!!!!!!!!!!!!!!
+ bOk = IsCellValid( pCell, rPos );
+ break;
+
+ case SC_VALID_TEXTLEN:
+ bOk = !bIsVal; // nur Text
+ if ( bOk )
+ {
+ double nLenVal = (double) aString.Len();
+ ScValueCell aTmpCell( nLenVal );
+ bOk = IsCellValid( &aTmpCell, rPos );
+ }
+ break;
+
+ case SC_VALID_LIST:
+ default:
+ DBG_ERROR("hammanochnich");
+ break;
+ }
+
+ return bOk;
+}
+
+//------------------------------------------------------------------------
+
+ScValidationDataList::ScValidationDataList(const ScValidationDataList& rList)
+{
+ // fuer Ref-Undo - echte Kopie mit neuen Tokens!
+
+ USHORT nCount = rList.Count();
+
+ for (USHORT i=0; i<nCount; i++)
+ InsertNew( rList[i]->Clone() );
+
+ //! sortierte Eintraege aus rList schneller einfuegen ???
+}
+
+ScValidationDataList::ScValidationDataList(ScDocument* pNewDoc,
+ const ScValidationDataList& rList)
+{
+ // fuer neues Dokument - echte Kopie mit neuen Tokens!
+
+ USHORT nCount = rList.Count();
+
+ for (USHORT i=0; i<nCount; i++)
+ InsertNew( rList[i]->Clone(pNewDoc) );
+
+ //! sortierte Eintraege aus rList schneller einfuegen ???
+}
+
+ScValidationData* ScValidationDataList::GetData( ULONG nKey )
+{
+ //! binaer suchen
+
+ USHORT nCount = Count();
+ for (USHORT i=0; i<nCount; i++)
+ if ((*this)[i]->GetKey() == nKey)
+ return (*this)[i];
+
+ DBG_ERROR("ScValidationDataList: Eintrag nicht gefunden");
+ return NULL;
+}
+
+void ScValidationDataList::Load( SvStream& rStream, ScDocument* pDocument )
+{
+ ScMultipleReadHeader aHdr( rStream );
+
+ USHORT nNewCount;
+ rStream >> nNewCount;
+
+ for (USHORT i=0; i<nNewCount; i++)
+ {
+ ScValidationData* pNew = new ScValidationData( rStream, aHdr, pDocument );
+ InsertNew( pNew );
+ }
+}
+
+void ScValidationDataList::Store( SvStream& rStream ) const
+{
+ USHORT i;
+ ScMultipleWriteHeader aHdr( rStream );
+
+ USHORT nCount = Count();
+ USHORT nUsed = 0;
+ for (i=0; i<nCount; i++)
+ if ((*this)[i]->IsUsed())
+ ++nUsed;
+
+ rStream << nUsed; // Anzahl der gespeicherten
+
+ for (i=0; i<nCount; i++)
+ {
+ const ScValidationData* pForm = (*this)[i];
+ if (pForm->IsUsed())
+ pForm->Store( rStream, aHdr );
+ }
+}
+
+void ScValidationDataList::ResetUsed()
+{
+ USHORT nCount = Count();
+ for (USHORT i=0; i<nCount; i++)
+ (*this)[i]->SetUsed(FALSE);
+}
+
+void ScValidationDataList::UpdateReference( UpdateRefMode eUpdateRefMode,
+ const ScRange& rRange, short nDx, short nDy, short nDz )
+{
+ DBG_ERROR("ScValidationDataList::UpdateReference");
+}
+
+BOOL ScValidationDataList::operator==( const ScValidationDataList& r ) const
+{
+ // fuer Ref-Undo - interne Variablen werden nicht verglichen
+
+ USHORT nCount = Count();
+ BOOL bEqual = ( nCount == r.Count() );
+ for (USHORT i=0; i<nCount && bEqual; i++) // Eintraege sind sortiert
+ if ( !(*this)[i]->EqualEntries(*r[i]) ) // Eintraege unterschiedlich ?
+ bEqual = FALSE;
+
+ return bEqual;
+}
+
+
+
+
diff --git a/sc/source/core/inc/addinlis.hxx b/sc/source/core/inc/addinlis.hxx
new file mode 100644
index 000000000000..af34ef2a6cb9
--- /dev/null
+++ b/sc/source/core/inc/addinlis.hxx
@@ -0,0 +1,145 @@
+/*************************************************************************
+ *
+ * $RCSfile: addinlis.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:16 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef SC_ADDINLIS_HXX
+#define SC_ADDINLIS_HXX
+
+#ifndef _SC_ADIASYNC_HXX
+#include "adiasync.hxx" // for ScAddInDocs PtrArr
+#endif
+
+#ifndef _COM_SUN_STAR_SHEET_XRESULTLISTENER_HPP_
+#include <com/sun/star/sheet/XResultListener.hpp>
+#endif
+
+#ifndef _COM_SUN_STAR_SHEET_XVOLATILERESULT_HPP_
+#include <com/sun/star/sheet/XVolatileResult.hpp>
+#endif
+
+#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#endif
+
+#ifndef _CPPUHELPER_IMPLBASE2_HXX_
+#include <cppuhelper/implbase2.hxx>
+#endif
+
+
+
+class ScDocument;
+
+
+class ScAddInListener : public cppu::WeakImplHelper2<
+ com::sun::star::sheet::XResultListener,
+ com::sun::star::lang::XServiceInfo >,
+ public SfxBroadcaster
+{
+private:
+ com::sun::star::uno::Reference<com::sun::star::sheet::XVolatileResult> xVolRes;
+ com::sun::star::uno::Any aResult;
+ ScAddInDocs* pDocs; // documents where this is used
+
+ static List aAllListeners;
+
+ // always allocated via CreateListener
+ ScAddInListener(
+ com::sun::star::uno::Reference<
+ com::sun::star::sheet::XVolatileResult> xVR,
+ ScDocument* pD );
+
+public:
+ virtual ~ScAddInListener();
+
+ // create Listener and put it into global list
+ static ScAddInListener* CreateListener(
+ com::sun::star::uno::Reference<
+ com::sun::star::sheet::XVolatileResult> xVR,
+ ScDocument* pDoc );
+
+ static ScAddInListener* Get( com::sun::star::uno::Reference<
+ com::sun::star::sheet::XVolatileResult> xVR );
+ static void RemoveDocument( ScDocument* pDocument );
+
+ BOOL HasDocument( ScDocument* pDoc ) const { return pDocs->Seek_Entry( pDoc ); }
+ void AddDocument( ScDocument* pDoc ) { pDocs->Insert( pDoc ); }
+ const com::sun::star::uno::Any& GetResult() const { return aResult; }
+
+
+ // XResultListener
+ virtual void SAL_CALL modified( const ::com::sun::star::sheet::ResultEvent& aEvent )
+ throw(::com::sun::star::uno::RuntimeException);
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source )
+ throw(::com::sun::star::uno::RuntimeException);
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName( )
+ throw(::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName )
+ throw(::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( )
+ throw(::com::sun::star::uno::RuntimeException);
+};
+
+
+#endif
+
diff --git a/sc/source/core/inc/adiasync.hxx b/sc/source/core/inc/adiasync.hxx
new file mode 100644
index 000000000000..a51f1dd0aa99
--- /dev/null
+++ b/sc/source/core/inc/adiasync.hxx
@@ -0,0 +1,127 @@
+/*************************************************************************
+ *
+ * $RCSfile: adiasync.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:16 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SC_ADIASYNC_HXX
+#define _SC_ADIASYNC_HXX
+
+#ifndef _SFXBRDCST_HXX //autogen
+#include <svtools/brdcst.hxx>
+#endif
+
+#include "callform.hxx"
+
+extern "C" {
+void CALLTYPE ScAddInAsyncCallBack( double& nHandle, void* pData );
+}
+
+
+class ScAddInAsync;
+typedef ScAddInAsync* ScAddInAsyncPtr;
+SV_DECL_PTRARR_SORT( ScAddInAsyncs, ScAddInAsyncPtr, 4, 4 );
+extern ScAddInAsyncs theAddInAsyncTbl; // in adiasync.cxx
+
+class ScDocument;
+typedef ScDocument* ScAddInDocPtr;
+SV_DECL_PTRARR_SORT( ScAddInDocs, ScAddInDocPtr, 1, 1 );
+
+class String;
+
+class ScAddInAsync : public SfxBroadcaster
+{
+private:
+ union
+ {
+ double nVal; // aktueller Wert
+ String* pStr;
+ };
+ ScAddInDocs* pDocs; // Liste der benutzenden Dokumente
+ FuncData* pFuncData; // Zeiger auf die Daten in der Collection
+ ULONG nHandle; // wird von double auf ULONG gecasted
+ ParamType eType; // PTR_DOUBLE oder PTR_STRING Ergebnis
+ BOOL bValid; // ob Wert gueltig
+
+public:
+ // cTor nur wenn ScAddInAsync::Get fehlschlaegt!
+ // nIndex: Index aus der FunctionCollection
+ ScAddInAsync( ULONG nHandle, USHORT nIndex,
+ ScDocument* pDoc );
+ // default-cTor nur fuer das eine globale aSeekObj !!!
+ ScAddInAsync();
+ virtual ~ScAddInAsync();
+ static ScAddInAsync* Get( ULONG nHandle );
+ static void CallBack( ULONG nHandle, void* pData );
+ static void RemoveDocument( ScDocument* pDocument );
+ BOOL IsValid() const { return bValid; }
+ ParamType GetType() const { return eType; }
+ double GetValue() const { return nVal; }
+ const String& GetString() const { return *pStr; }
+ BOOL HasDocument( ScDocument* pDoc ) const
+ { return pDocs->Seek_Entry( pDoc ); }
+ void AddDocument( ScDocument* pDoc ) { pDocs->Insert( pDoc ); }
+
+ // Vergleichsoperatoren fuer PtrArrSort
+ BOOL operator < ( const ScAddInAsync& r ) { return nHandle < r.nHandle; }
+ BOOL operator ==( const ScAddInAsync& r ) { return nHandle == r.nHandle; }
+};
+
+
+
+#endif
diff --git a/sc/source/core/inc/bcaslot.hxx b/sc/source/core/inc/bcaslot.hxx
new file mode 100644
index 000000000000..3b7d4ec37ab5
--- /dev/null
+++ b/sc/source/core/inc/bcaslot.hxx
@@ -0,0 +1,197 @@
+/*************************************************************************
+ *
+ * $RCSfile: bcaslot.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:16 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SC_BCASLOT_HXX
+#define _SC_BCASLOT_HXX
+
+#ifndef _SFXBRDCST_HXX //autogen
+#include <svtools/brdcst.hxx>
+#endif
+#ifndef _SVARRAY_HXX //autogen
+#include <svtools/svarray.hxx>
+#endif
+
+#include "global.hxx"
+#include "brdcst.hxx"
+
+class ScBroadcastArea;
+class ScBroadcastAreaList;
+
+#define BCA_INITGROWSIZE 16
+typedef ScBroadcastArea* ScBroadcastAreaPtr;
+SV_DECL_PTRARR_SORT( ScBroadcastAreas, ScBroadcastAreaPtr,
+ BCA_INITGROWSIZE, BCA_INITGROWSIZE );
+
+// wird in einem nach Objekten sortierten SV_PTRARR_SORT benutzt
+class ScBroadcastArea : public ScRange, public SfxBroadcaster
+{
+private:
+ ScBroadcastArea* pUpdateChainNext;
+ USHORT nRefCount;
+ BOOL bInUpdateChain;
+
+public:
+ ScBroadcastArea( const ScRange& rRange )
+ : ScRange( rRange ), SfxBroadcaster(), pUpdateChainNext( NULL ),
+ nRefCount( 0 ), bInUpdateChain( FALSE ) {}
+ inline void UpdateRange( const ScRange& rNewRange )
+ { aStart = rNewRange.aStart; aEnd = rNewRange.aEnd; }
+ inline ScAddress GetStart() const { return aStart; }
+ inline ScAddress GetEnd() const { return aEnd; }
+ inline void IncRef() { ++nRefCount; }
+ inline USHORT DecRef() { return --nRefCount; }
+ inline ScBroadcastArea* GetUpdateChainNext() const { return pUpdateChainNext; }
+ inline void SetUpdateChainNext( ScBroadcastArea* p ) { pUpdateChainNext = p; }
+ inline BOOL IsInUpdateChain() const { return bInUpdateChain; }
+ inline void SetInUpdateChain( BOOL b ) { bInUpdateChain = b; }
+
+ // zur Sortierung wird die linke obere Ecke herangezogen,
+ // ist diese gleich, zaehlt auch die rechte untere Ecke
+ BOOL operator < ( const ScBroadcastArea& rArea ) const
+ { return aStart < rArea.aStart ||
+ (aStart == rArea.aStart && aEnd < rArea.aEnd) ; }
+ BOOL operator ==( const ScBroadcastArea& rArea ) const
+ { return aStart == rArea.aStart && aEnd == rArea.aEnd; }
+};
+class ScBroadcastAreaSlotMachine;
+
+// Sammlung von BroadcastAreas
+class ScBroadcastAreaSlot
+{
+private:
+ ScBroadcastAreas* pBroadcastAreaTbl;
+ ScBroadcastArea* pTmpSeekBroadcastArea; // fuer Seek_Entry
+ ScDocument* pDoc;
+ ScBroadcastAreaSlotMachine* pBASM;
+
+ USHORT FindBroadcastArea( const ScRange& rRange ) const;
+ ScBroadcastArea* GetBroadcastArea( const ScRange& rRange ) const;
+
+public:
+ ScBroadcastAreaSlot( ScDocument* pDoc,
+ ScBroadcastAreaSlotMachine* pBASM );
+ ~ScBroadcastAreaSlot();
+ const ScBroadcastAreas& GetBroadcastAreas() const
+ { return *pBroadcastAreaTbl; }
+ void StartListeningArea( const ScRange& rRange,
+ SfxListener* pListener,
+ ScBroadcastArea*& rpArea );
+ void EndListeningArea( const ScRange& rRange,
+ SfxListener* pListener,
+ ScBroadcastArea*& rpArea );
+ BOOL AreaBroadcast( const ScAddress& rAddress,
+ const ScHint& rHint ) const;
+ // return: mindestens ein Broadcast gewesen
+ void DelBroadcastAreasInRange( const ScRange& rRange );
+ void UpdateRemove( UpdateRefMode eUpdateRefMode,
+ const ScRange& rRange,
+ short nDx, short nDy, short nDz );
+ void UpdateInsert( ScBroadcastArea* pArea );
+};
+
+
+/*
+ BroadcastAreaSlots und deren Verwaltung, einmal je Dokument
+
+ +---+---+
+ | 0 | 2 | Anordnung Cols/Rows
+ +---+---+
+ | 1 | 3 |
+ +---+---+
+ */
+
+class ScBroadcastAreaSlotMachine
+{
+private:
+ ScBroadcastAreaSlot** ppSlots;
+ ScDocument* pDoc;
+ ScBroadcastAreaList* pBCAlwaysList; // fuer den RC_ALWAYS Spezialbereich
+ ScBroadcastArea* pUpdateChain;
+ ScBroadcastArea* pEOUpdateChain;
+
+ inline USHORT ComputeSlotOffset( const ScAddress& rAddress ) const;
+ void ComputeAreaPoints( const ScRange& rRange,
+ USHORT& nStart, USHORT& nEnd,
+ USHORT& nRowBreak ) const;
+
+public:
+ ScBroadcastAreaSlotMachine( ScDocument* pDoc );
+ ~ScBroadcastAreaSlotMachine();
+ void StartListeningArea( const ScRange& rRange,
+ SfxListener* pListener );
+ void EndListeningArea( const ScRange& rRange,
+ SfxListener* pListener );
+ BOOL AreaBroadcast( const ScAddress& rAddress,
+ const ScHint& rHint ) const;
+ // return: mindestens ein Broadcast gewesen
+ void DelBroadcastAreasInRange( const ScRange& rRange );
+ void UpdateBroadcastAreas( UpdateRefMode eUpdateRefMode,
+ const ScRange& rRange,
+ short nDx, short nDy, short nDz );
+ inline ScBroadcastArea* GetUpdateChain() const { return pUpdateChain; }
+ inline void SetUpdateChain( ScBroadcastArea* p ) { pUpdateChain = p; }
+ inline ScBroadcastArea* GetEOUpdateChain() const { return pEOUpdateChain; }
+ inline void SetEOUpdateChain( ScBroadcastArea* p ) { pEOUpdateChain = p; }
+};
+
+
+
+#endif
diff --git a/sc/source/core/inc/core_pch.hxx b/sc/source/core/inc/core_pch.hxx
new file mode 100644
index 000000000000..1586a5724e71
--- /dev/null
+++ b/sc/source/core/inc/core_pch.hxx
@@ -0,0 +1,312 @@
+/*************************************************************************
+ *
+ * $RCSfile: core_pch.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:16 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+// ItemID-Defines etc. muessen immer ganz vorne stehen
+
+#include "scitems.hxx"
+#include "eetext.hxx"
+
+#define ITEMID_FIELD EE_FEATURE_FIELD
+
+#define _ZFORLIST_DECLARE_TABLE
+
+#define SC_PROGRESS_CXX
+
+// ab hier automatisch per makepch generiert
+// folgende duerfen nicht aufgenommen werden:
+// setjmp.h
+
+#include <tools/solar.h>
+#include <string.h>
+#include <tools/string.hxx>
+#include <tools/rtti.hxx>
+#include <limits.h>
+#include <tools/ref.hxx>
+#include <tools/list.hxx>
+#include <tools/contnr.hxx>
+#include <tools/link.hxx>
+#include <tools/stream.hxx>
+#include <tools/errinf.hxx>
+#include <tools/errcode.hxx>
+#include <vcl/sv.h>
+#include <global.hxx>
+#include <vcl/color.hxx>
+#include <tools/lang.hxx>
+#include <tools/debug.hxx>
+#include <tools/gen.hxx>
+#include <svtools/svarray.hxx>
+#include <markarr.hxx>
+#include <vcl/timer.hxx>
+#include <rangelst.hxx>
+#include <document.hxx>
+#include <vcl/prntypes.hxx>
+#include <table.hxx>
+#include <column.hxx>
+#include <svtools/hint.hxx>
+#include <svtools/lstner.hxx>
+#include <svtools/args.hxx>
+#include <svtools/poolitem.hxx>
+#include <tools/time.hxx>
+#include <svtools/solar.hrc>
+#include <tools/date.hxx>
+#include <svtools/brdcst.hxx>
+#include <svx/svxids.hrc>
+#include <svtools/memberid.hrc>
+#include <sfx2/sfx.hrc>
+#include <sfx2/sfxsids.hrc>
+#include <svtools/cntwids.hrc>
+#include <tools/intn.hxx>
+#include <tools/resid.hxx>
+#include <tools/table.hxx>
+#include <stdarg.h>
+#include <vcl/rc.hxx>
+#include <tools/rc.hxx>
+#include <tools/resmgr.hxx>
+#include <vcl/resid.hxx>
+#include <tools/unqidx.hxx>
+#include <rsc/rscsfx.hxx>
+#include <svtools/sbxdef.hxx>
+#include <svtools/itemset.hxx>
+#include <stddef.h>
+#include <collect.hxx>
+#include <scitems.hxx>
+#include <tools/globname.hxx>
+#include <tools/fract.hxx>
+#include <sfx2/shell.hxx>
+#include <cell.hxx>
+#include <tools/mempool.hxx>
+#include <vcl/color.hxx>
+#include <vcl/region.hxx>
+#include <vcl/mapmod.hxx>
+#include <vcl/bitmap.hxx>
+#include <svtools/eitem.hxx>
+#include <svtools/intitem.hxx>
+#include <sot/object.hxx>
+#include <sot/factory.hxx>
+#include <sot/sotdata.hxx>
+#include <vcl/keycod.hxx>
+#include <vcl/keycodes.hxx>
+#include <sot/sotref.hxx>
+#include <rechead.hxx>
+#include <tools/unqid.hxx>
+#include <vcl/apptypes.hxx>
+#include <vcl/fonttype.hxx>
+#include <globstr.hrc>
+#include <compiler.hrc>
+#include <tools/shl.hxx>
+#include <compiler.hxx>
+#include <vcl/font.hxx>
+#include <svtools/smplhint.hxx>
+#include <vcl/wall.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/accel.hxx>
+#include <vcl/gdiobj.hxx>
+#include <patattr.hxx>
+#include <svtools/zforlist.hxx>
+#include <tools/pstm.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/pointr.hxx>
+#include <vcl/ptrstyle.hxx>
+#include <vcl/wintypes.hxx>
+#include <vcl/event.hxx>
+#include <sot/dtrans.hxx>
+#include <tools/ownlist.hxx>
+#include <svtools/itempool.hxx>
+#include <tools/datetime.hxx>
+#include <so3/factory.hxx>
+#include <so3/so2dll.hxx>
+#include <so3/iface.hxx>
+#include <attrib.hxx>
+#include <so3/so2ref.hxx>
+#include <so3/persist.hxx>
+#include <docpool.hxx>
+#include <sot/storage.hxx>
+#include <so3/so2defs.hxx>
+#include <sfx2/objsh.hxx>
+#include <vcl/window.hxx>
+#include <sfx2/cfgitem.hxx>
+#include <svtools/confitem.hxx>
+#include <vcl/syswin.hxx>
+#include <sc.hrc>
+#include <svx/dialogs.hrc>
+#include <math.h>
+#include <svtools/style.hxx>
+#include <svtools/style.hrc>
+#include <stdlib.h>
+#include <vcl/prntypes.hxx>
+#include <vcl/jobset.hxx>
+#include <vcl/gdimtf.hxx>
+//#include <setjmp.h>
+#include <tools/urlobj.hxx>
+#include <vcl/print.hxx>
+#include <docoptio.hxx>
+#include <markdata.hxx>
+#include <vcl/system.hxx>
+#include <vcl/wrkwin.hxx>
+#include <stlpool.hxx>
+#include <sfx2/app.hxx>
+#include <svtools/inetmsg.hxx>
+#include <svtools/compat.hxx>
+#include <svtools/inetdef.hxx>
+#include <svtools/inethist.hxx>
+#include <svtools/cancel.hxx>
+#include <vcl/accel.hxx>
+#include <sfx2/sfxdefs.hxx>
+#include <sfx2/module.hxx>
+#include <sfx2/imgdef.hxx>
+#include <segmentc.hxx>
+#include <tcov.hxx>
+#include <vcl/ctrl.hxx>
+#include <vcl/field.hxx>
+#include <vcl/spinfld.hxx>
+#include <vcl/edit.hxx>
+#include <vcl/timer.hxx>
+#include <vcl/combobox.hxx>
+#include <vcl/combobox.h>
+#include <refupdat.hxx>
+#include <svx/boxitem.hxx>
+#include <conditio.hxx>
+#include <brdcst.hxx>
+#include <svx/svxenum.hxx>
+#include <dociter.hxx>
+#include <scdll.hxx>
+#include <stdio.h>
+#include <stlsheet.hxx>
+#include <vcl/gdiobj.hxx>
+#include <vcl/mapmod.hxx>
+#include <progress.hxx>
+#include <sfx2/progress.hxx>
+#include <so3/dtrans.hxx>
+#include <vcl/event.hxx>
+#include <vcl/window.hxx>
+#include <so3/advise.hxx>
+#include <svx/algitem.hxx>
+#include <scspew.hxx>
+#include <vcl/field.hxx>
+#include <svx/svdtypes.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/animate.hxx>
+#include <vcl/graph.h>
+#include <drwlayer.hxx>
+#include <svx/svdmodel.hxx>
+#include <scresid.hxx>
+#include <vcl/print.hxx>
+#include <attarray.hxx>
+#include <so3/pseudo.hxx>
+#include <svtools/ownlist.hxx>
+#include <interpre.hxx>
+#include <subtotal.hxx>
+#include <rangenam.hxx>
+#include <scmatrix.hxx>
+#include <svx/pageitem.hxx>
+#include <dbcolect.hxx>
+#include <userlist.hxx>
+#include <svx/editdata.hxx>
+#include <svtools/sbxvar.hxx>
+#include <svtools/sbxcore.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdsob.hxx>
+#include <svx/svdglue.hxx>
+#include <svx/langitem.hxx>
+#include <svx/eeitem.hxx>
+#include <callform.hxx>
+#include <validat.hxx>
+#include <so3/linkmgr.hxx>
+#include <svx/brshitem.hxx>
+#include <so3/lnkbase.hxx>
+#include <vcl/exchange.hxx>
+#include <sot/exchange.hxx>
+#include <so3/linkname.hxx>
+#include <so3/moniker.hxx>
+#include <svx/editeng.hxx>
+#include <vcl/fonttype.hxx>
+#include <svx/editobj.hxx>
+#include <svx/wghtitem.hxx>
+#include <svx/fhgtitem.hxx>
+#include <svtools/stritem.hxx>
+#include <pivot.hxx>
+#include <vcl/gdimtf.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdlayer.hxx>
+#include <svx/linkmgr.hxx>
+#include <ctype.h>
+#include <vcl/font.hxx>
+#include <svx/fontitem.hxx>
+#include <svx/postitem.hxx>
+#include <so3/protocol.hxx>
+#include <svx/svditer.hxx>
+#include <svx/udlnitem.hxx>
+#include <adiasync.hxx>
+#include <sfx2/bindings.hxx>
+#include <ddelink.hxx>
+#include <chartlis.hxx>
+#include <sfx2/minarray.hxx>
+#include <svtools/iniman.hxx>
+#include <svtools/txtcmp.hxx>
+#include <olinetab.hxx>
+#include <svtools/sbxobj.hxx>
+#include <cfgids.hxx>
+
+
+
+
diff --git a/sc/source/core/inc/ddelink.hxx b/sc/source/core/inc/ddelink.hxx
new file mode 100644
index 000000000000..463a1903cb33
--- /dev/null
+++ b/sc/source/core/inc/ddelink.hxx
@@ -0,0 +1,135 @@
+/*************************************************************************
+ *
+ * $RCSfile: ddelink.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:16 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef SC_DDELINK_HXX
+#define SC_DDELINK_HXX
+
+#ifndef _LNKBASE_HXX //autogen
+#include <so3/lnkbase.hxx>
+#endif
+#ifndef _SFXBRDCST_HXX //autogen
+#include <svtools/brdcst.hxx>
+#endif
+
+class ScDocument;
+class ScMatrix;
+class ScMultipleReadHeader;
+class ScMultipleWriteHeader;
+
+#define SC_DDE_DEFAULT 0
+#define SC_DDE_ENGLISH 1
+#define SC_DDE_TEXT 2
+
+class ScDdeLink : public SvBaseLink, public SfxBroadcaster
+{
+private:
+static BOOL bIsInUpdate;
+
+ ScDocument* pDoc;
+
+ String aAppl; // Verbindungsdaten
+ String aTopic;
+ String aItem;
+ BYTE nMode; // Zahlformat-Modus
+
+ BOOL bNeedUpdate; // wird gesetzt, wenn Update nicht moeglich war
+
+ ScMatrix* pResult; // Ergebnis
+
+public:
+ TYPEINFO();
+
+ ScDdeLink( ScDocument* pD,
+ const String& rA, const String& rT, const String& rI,
+ BYTE nM );
+ ScDdeLink( ScDocument* pD, SvStream& rStream, ScMultipleReadHeader& rHdr );
+ ScDdeLink( ScDocument* pD, const ScDdeLink& rOther );
+ virtual ~ScDdeLink();
+
+ void Store( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const;
+
+ // von SvBaseLink ueberladen:
+ virtual void Closed();
+ virtual void DataChanged( SvData& );
+
+ // von SfxBroadcaster ueberladen:
+ virtual void ListenersGone();
+
+ // fuer Interpreter:
+
+ const ScMatrix* GetResult() const { return pResult; }
+
+ const String& GetAppl() const { return aAppl; }
+ const String& GetTopic() const { return aTopic; }
+ const String& GetItem() const { return aItem; }
+ BYTE GetMode() const { return nMode; }
+
+ void ResetValue(); // Wert zuruecksetzen
+ void TryUpdate();
+
+ BOOL NeedsUpdate() const { return bNeedUpdate; }
+
+ static BOOL IsInUpdate() { return bIsInUpdate; }
+};
+
+
+#endif
+
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
new file mode 100644
index 000000000000..3c8bc3b1b7dd
--- /dev/null
+++ b/sc/source/core/inc/interpre.hxx
@@ -0,0 +1,721 @@
+/*************************************************************************
+ *
+ * $RCSfile: interpre.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:16 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef SC_INTERPRE_HXX
+#define SC_INTERPRE_HXX
+
+#define SC_SPEW_ENABLED 0
+
+#include <math.h>
+
+#include <tools/solmath.hxx> // SOMA_FPSIGNAL_JUMP
+
+#include "compiler.hxx"
+#include "cell.hxx"
+#include "scdll.hxx"
+#if SC_SPEW_ENABLED
+#include "scspew.hxx"
+#endif
+
+class ScDocument;
+class ScMatrix;
+class SbxVariable;
+class ScBaseCell;
+class ScFormulaCell;
+class SvNumberFormatter;
+
+#define MAX_ANZ_MAT 150
+ // Maximale Anzahl fuer Zwischenergebnis
+ // Matrizen
+ // Maximum ca. 85 wird bei Invertierung
+ // von 128 x 128 benoetigt!
+
+
+#ifndef MSC
+ #include <setjmp.h>
+#else
+ extern "C"
+ {
+ #define _JBLEN 9 /* bp, di, si, sp, ret addr, ds */
+ typedef int jmp_buf[_JBLEN];
+ #define _JMP_BUF_DEFINED
+ #define setjmp _setjmp
+ int __cdecl _setjmp(jmp_buf);
+ void __cdecl longjmp(jmp_buf, int);
+ };
+#endif
+
+#ifndef _TABOPLIST_DECLARED
+#define _TABOPLIST_DECLARED
+DECLARE_LIST (TabOpList, USHORT*);
+#endif
+
+struct ScCompare
+{
+ double nVal[2];
+ String* pVal[2];
+ BOOL bVal[2];
+ BOOL bEmpty[2];
+ ScCompare( String* p1, String* p2 )
+ {
+ pVal[ 0 ] = p1;
+ pVal[ 1 ] = p2;
+ bEmpty[0] = FALSE;
+ bEmpty[1] = FALSE;
+ }
+};
+
+struct ScToken;
+
+#define MAXSTACK (4096 / sizeof(ScToken*))
+
+class ScTokenStack
+{
+public:
+ DECL_FIXEDMEMPOOL_NEWDEL( ScTokenStack )
+ ScToken* pPointer[ MAXSTACK ];
+};
+
+class ScErrorStack
+{
+public:
+ DECL_FIXEDMEMPOOL_NEWDEL( ScErrorStack )
+ USHORT pPointer[ MAXSTACK ];
+};
+
+enum ScIterFunc {
+ ifSUM, // Aufsummieren
+ ifSUMSQ, // Quadratsummen
+ ifPRODUCT, // Multiplizieren
+ ifAVERAGE, // Durchschnitt
+ ifCOUNT, // Anzahl Werte
+ ifCOUNT2, // Anzahl Werte (nichtleer)
+ ifMIN, // Minimum
+ ifMAX // Maximum
+};
+
+class ScInterpreter
+{
+public:
+ DECL_FIXEDMEMPOOL_NEWDEL( ScInterpreter )
+#if SOMA_FPSIGNAL_JUMP
+ static jmp_buf* pJumpBuf; // fuer die mySignal-Funktion
+ static ScLibSignalFunc pSignalFunc; // signal() Wrapper der App
+#endif
+ static USHORT nGlobalError; // globale Fehlervariable
+ static ULONG nInterpCount; // Zaehlt aktuelle Interpreteraufrufe
+ static TabOpList aTableOpList; // Liste von Ref-Arrays fuer Mehrfachoperat.
+#if SC_SPEW_ENABLED
+ static ScSpew theSpew;
+#endif
+
+ static void GlobalExit(); // aus ScGlobal::Clear() gerufen
+ static BOOL MayBeRegExp( const String& ); // vielleicht regular expression?
+private:
+ static ScTokenStack* pGlobalStack;
+ static ScErrorStack* pGlobalErrorStack;
+ static BOOL bGlobalStackInUse;
+ static const sal_Unicode cEmptyString; // =0 for return &cEmptyString
+
+ ScTokenIterator aCode;
+ ScAddress aPos;
+ ScTokenArray& rArr;
+ String aResult;
+ ScDocument* pDok; // Pointer aufs Dokument
+ double nResult;
+ ScMatrix* pResult;
+ ScFormulaCell* pMyFormulaCell; // die Zelle mit der Formel
+ SvNumberFormatter* pFormatter;
+ StackVar eResult;
+
+ USHORT nGlobError; // lokale Kopie
+#if SOMA_FPSIGNAL_JUMP
+ jmp_buf* pLocalJumpBuf; // lokale Kopie
+#endif
+ const ScToken* pCur; // aktuelles Token
+ String aTempStr; // fuer GetString()
+ ScTokenStack* pStackObj; // enthaelt den Stack
+ ScToken** pStack; // der Stack
+ ScErrorStack* pErrorStackObj; // enthaelt den ErrorStack
+ USHORT* pErrorStack; // der ErrorStack
+ USHORT sp; // der Stackpointer
+ USHORT maxsp; // der maximale StackPointer
+ double** ppGlobSortArray; // Pointer auf Array zum Sortieren
+ USHORT* pTableOp; // der lokale Pointer auf das aktuelle TableOp
+ ScMatrix** ppTempMatArray; // Array fuer temporaere Matrizen
+ USHORT nMatCount; // dazugehoeriger Zaehler
+ BOOL bMatDel; // und Kontrollvariable
+ USHORT nRetMat; // Index der Return-Matrix
+ ULONG nFuncFmtIndex; // NumberFormatIndex einer Funktion
+ ULONG nCurFmtIndex; // aktueller NumberFormatIndex
+ ULONG nRetFmtIndex; // ggbf. NumberFormatIndex des Ausdrucks
+ short nFuncFmtType; // NumberFormatTyp einer Funktion
+ short nCurFmtType; // aktueller NumberFormatTyp
+ short nRetFmtType; // NumberFormatTyp des Ausdrucks
+ BOOL glSubTotal; // Flag fuer Subtotalfunktionen
+ BYTE cPar; // aktuelle Anzahl Parameter
+ BOOL bCalcAsShown; // Genauigkeit wie angezeigt
+ BOOL bMatrixFormula; // Formelzelle ist Matrixformel
+
+//---------------------------------Funktionen in interpre.cxx---------
+// nMust <= nAct <= nMax ? ok : SetError, PushInt
+inline BOOL MustHaveParamCount( BYTE nAct, BYTE nMust );
+inline BOOL MustHaveParamCount( BYTE nAct, BYTE nMust, BYTE nMax );
+inline BOOL MustHaveParamCountMin( BYTE nAct, BYTE nMin );
+void SetParameterExpected();
+void SetIllegalParameter();
+void SetIllegalArgument();
+void SetNoValue();
+void SetNV();
+//-------------------------------------------------------------------------
+// Funktionen für den Zugriff auf das Document
+//-------------------------------------------------------------------------
+void ReplaceCell( ScAddress& ); // fuer MehrfachOp.
+ULONG GetCellNumberFormat( const ScAddress&, const ScBaseCell* );
+double GetCellValue( const ScAddress&, const ScBaseCell* );
+double GetCellValueOrZero( const ScAddress&, const ScBaseCell* );
+double GetValueCellValue( const ScAddress&, const ScValueCell* );
+ScBaseCell* GetCell( const ScAddress& );
+void GetCellString( String& rStr, const ScBaseCell* pCell );
+USHORT GetCellErrCode( const ScBaseCell* pCell );
+inline CellType GetCellType( const ScBaseCell* pCell )
+ { return pCell ? pCell->GetCellType() : CELLTYPE_NONE; }
+inline BOOL HasCellValueData( const ScBaseCell* pCell )
+ { return pCell ? pCell->HasValueData() : FALSE; }
+inline BOOL HasCellStringData( const ScBaseCell* pCell )
+ { return pCell ? pCell->HasStringData() : FALSE; }
+BOOL CreateDoubleArr(USHORT nCol1, USHORT nRow1, USHORT nTab1,
+ USHORT nCol2, USHORT nRow2, USHORT nTab2, BYTE* pCellArr);
+BOOL CreateStringArr(USHORT nCol1, USHORT nRow1, USHORT nTab1,
+ USHORT nCol2, USHORT nRow2, USHORT nTab2, BYTE* pCellArr);
+BOOL CreateCellArr(USHORT nCol1, USHORT nRow1, USHORT nTab1,
+ USHORT nCol2, USHORT nRow2, USHORT nTab2, BYTE* pCellArr);
+//-----------------------------------------------------------------------------
+// Stackoperationen
+//-----------------------------------------------------------------------------
+void Push( ScToken& r );
+void PushTempToken( const ScToken& );
+void PushTempToken( ScDoubleToken* ); //! see warnings in interpr4.cxx
+void Pop();
+void PopError();
+BYTE PopByte();
+double PopDouble();
+const sal_Unicode* PopString();
+void PopSingleRef( ScAddress& );
+void PopSingleRef(USHORT& rCol, USHORT &rRow, USHORT& rTab);
+void PopDoubleRef( ScRange& );
+void PopDoubleRef(USHORT& rCol1, USHORT &rRow1, USHORT& rTab1,
+ USHORT& rCol2, USHORT &rRow2, USHORT& rTab2);
+BOOL PopDoubleRefOrSingleRef( ScAddress& rAdr );
+void PopDoubleRefPushMatrix();
+inline void MatrixDoubleRefToMatrix(); // wenn MatrixFormula: PopDoubleRefPushMatrix
+ScMatrix* PopMatrix();
+//void PushByte(BYTE nVal);
+void PushDouble(double nVal);
+void PushInt( int nVal );
+void PushString(const sal_Unicode* cString);
+void PushStringObject(const String& aString);
+void PushSingleRef(USHORT nCol, USHORT nRow, USHORT nTab);
+void PushDoubleRef(USHORT nCol1, USHORT nRow1, USHORT nTab1,
+ USHORT nCol2, USHORT nRow2, USHORT nTab2);
+void PushMatrix(ScMatrix* pMat);
+BYTE GetStackType();
+// peek StackType of Parameter, Parameter 1 == TOS, 2 == TOS-1, ...
+StackVar GetStackType( BYTE nParam );
+BYTE GetByte() { return cPar; }
+/*
+short GetShort();
+double GetLong();
+*/
+// generiert aus DoubleRef positionsabhaengige SingleRef
+BOOL DoubleRefToPosSingleRef( const ScRange& rRange, ScAddress& rAdr );
+double GetDouble();
+BOOL GetBool() { return GetDouble() != 0.0; }
+const sal_Unicode* GetString();
+ScMatrix* GetMatrix(USHORT& nMatInd); // in interpr2.cxx
+void ScTableOp(); // Mehrfachoperationen
+void ScErrCell(); // Sonderbehandlung
+ // Fehlerzelle
+void ScDefPar(); // DefaultParameter
+//-----------------------------allgemeine Hilfsfunktionen
+void SetMaxIterationCount(USHORT n);
+inline void CurFmtToFuncFmt()
+ { nFuncFmtType = nCurFmtType; nFuncFmtIndex = nCurFmtIndex; }
+//---------------------------------Funktionen in interpr1.cxx---------
+//-----------------------------Textfunktionen
+void ScIfJump();
+void ScChoseJump();
+short CompareFunc( const ScCompare& rComp );
+short Compare();
+ScMatrix* CompareMat();
+void ScEqual();
+void ScNotEqual();
+void ScLess();
+void ScGreater();
+void ScLessEqual();
+void ScGreaterEqual();
+void ScAnd();
+void ScOr();
+void ScNot();
+void ScNeg();
+void ScIntersect();
+void ScPi();
+void ScRandom();
+void ScTrue();
+void ScFalse();
+void ScDeg();
+void ScRad();
+void ScSin();
+void ScCos();
+void ScTan();
+void ScCot();
+void ScArcSin();
+void ScArcCos();
+void ScArcTan();
+void ScArcCot();
+void ScSinHyp();
+void ScCosHyp();
+void ScTanHyp();
+void ScCotHyp();
+void ScArcSinHyp();
+void ScArcCosHyp();
+void ScArcTanHyp();
+void ScArcCotHyp();
+void ScExp();
+void ScLn();
+void ScLog10();
+void ScSqrt();
+void ScIsEmpty();
+short IsString();
+void ScIsString();
+void ScIsNonString();
+void ScIsLogical(UINT16 aOldNumType);
+void ScType();
+void ScIsRef();
+void ScIsValue();
+void ScIsFormula();
+void ScFormula();
+void ScIsNV();
+void ScIsErr();
+void ScIsError();
+short IsEven();
+void ScIsEven();
+void ScIsOdd();
+void ScN();
+void ScCode();
+void ScTrim();
+void ScUpper();
+void ScPropper();
+void ScLower();
+void ScLen();
+void ScT();
+void ScValue();
+void ScClean();
+void ScChar();
+void ScMin( BOOL bTextAsZero = FALSE );
+void ScMax( BOOL bTextAsZero = FALSE );
+double IterateParameters( ScIterFunc, BOOL bTextAsZero = FALSE );
+void ScSumSQ();
+void ScSum();
+void ScProduct();
+void ScAverage( BOOL bTextAsZero = FALSE );
+void ScCount();
+void ScCount2();
+void GetStVarParams( double& rVal, double& rValCount, BOOL bTextAsZero = FALSE );
+void ScVar( BOOL bTextAsZero = FALSE );
+void ScVarP( BOOL bTextAsZero = FALSE );
+void ScStDev( BOOL bTextAsZero = FALSE );
+void ScStDevP( BOOL bTextAsZero = FALSE );
+void ScColumns();
+void ScRows();
+void ScTables();
+void ScColumn();
+void ScRow();
+void ScTable();
+void ScMatch();
+void ScCountIf();
+void ScSumIf();
+void ScCountEmptyCells();
+void ScLookup();
+void ScHLookup();
+void ScVLookup();
+void ScSubTotal();
+BOOL GetDBParams(USHORT& rTab, ScQueryParam& rParam);
+void DBIterator( ScIterFunc );
+void ScDBSum();
+void ScDBCount();
+void ScDBCount2();
+void ScDBAverage();
+void ScDBGet();
+void ScDBMax();
+void ScDBMin();
+void ScDBProduct();
+ULONG StdDev( double& rSum, double& rSum2 );
+void ScDBStdDev();
+void ScDBStdDevP();
+void ScDBVar();
+void ScDBVarP();
+void ScIndirect();
+void ScAdress();
+void ScOffset();
+void ScIndex();
+void ScMultiArea();
+void ScAreas();
+void ScCurrency();
+void ScReplace();
+void ScFixed();
+void ScFind();
+void ScExact();
+void ScLeft();
+void ScRight();
+void ScSearch();
+void ScMid();
+void ScText();
+void ScSubstitute();
+void ScRept();
+void ScConcat();
+void ScExternal();
+void ScMissing();
+void ScMacro();
+BOOL SetSbxVariable( SbxVariable* pVar, const ScAddress& );
+BOOL SetSbxVariable( SbxVariable* pVar, USHORT nCol, USHORT nRow, USHORT nTab );
+void ScErrorType();
+void ScDBArea();
+void ScColRowNameAuto();
+void ScCalcTeam();
+void ScAnswer();
+void ScTTT();
+void ScSpewFunc();
+void ScGame();
+
+//----------------Funktionen in interpr2.cxx---------------
+double GetDate(INT16 nYear, INT16 nMonth, INT16 nDay);
+void ScGetActDate();
+void ScGetActTime();
+void ScGetYear();
+void ScGetMonth();
+void ScGetDay();
+void ScGetDayOfWeek();
+void ScGetWeekOfYear();
+void ScEasterSunday();
+void ScGetHour();
+void ScGetMin();
+void ScGetSec();
+void ScPlusMinus();
+void ScAbs();
+void ScInt();
+void ScEven();
+void ScOdd();
+void ScCeil();
+void ScFloor();
+void RoundNumber( SolarMathRoundingMode eMode );
+void ScRound();
+void ScRoundUp();
+void ScRoundDown();
+void ScGetDateValue();
+void ScGetTimeValue();
+void ScArcTan2();
+void ScLog();
+void ScGetDate();
+void ScGetTime();
+void ScGetDiffDate();
+void ScGetDiffDate360();
+void ScNBW();
+void ScIKV();
+void ScPower();
+void ScAmpersand();
+void ScAdd();
+void ScSub();
+void ScMul();
+void ScDiv();
+void ScPow();
+void ScCurrent();
+void ScStyle();
+void ScDde();
+void ScBase();
+void ScDecimal();
+void ScConvert();
+
+//----------------------- Finanzfunktionen ------------------------------------
+double ScGetBw(double fZins, double fZzr, double fRmz,
+ double fZw, double fF);
+void ScBW();
+void ScDIA();
+double ScGetGDA(double fWert, double fRest, double fDauer,
+ double fPeriode, double fFaktor);
+void ScGDA();
+void ScGDA2();
+double ScInterVDB(double fWert,double fRest,double fDauer,double fDauer1,
+ double fPeriode,double fFaktor);
+void ScVDB();
+void ScLaufz();
+void ScLIA();
+double ScGetRmz(double fZins, double fZzr, double fBw,
+ double fZw, double fF);
+void ScRMZ();
+void ScZGZ();
+double ScGetZw(double fZins, double fZzr, double fRmz,
+ double fBw, double fF);
+void ScZW();
+void ScZZR();
+double GetZinsIterationEps(double fZzr, double fRmz, double fBw, double fZw,
+ double fF, double& fSchaetzwert);
+void ScZins();
+double ScGetZinsZ(double fZins, double fZr, double fZzr, double fBw,
+ double fZw, double fF, double& fRmz);
+void ScZinsZ();
+void ScKapz();
+void ScKumZinsZ();
+void ScKumKapZ();
+void ScEffektiv();
+void ScNominal();
+void ScMod();
+void ScBackSolver();
+void ScIntercept();
+//-------------------------Funktionen in interpr5.cxx--------------------------
+double ScGetGGT(double fx, double fy);
+void ScGGT();
+void ScKGV();
+//-------------------------- Matrixfunktionen ---------------------------------
+ScMatrix* GetNewMat(USHORT nC, USHORT nR, USHORT& nMatInd);
+void ResetNewMat(USHORT nIndex);
+void ScMatValue();
+void MEMat(ScMatrix* mM, USHORT n);
+void MFastMult(ScMatrix* pA, ScMatrix* pB, ScMatrix* pR, USHORT n, USHORT m, USHORT l);
+void MFastSub(ScMatrix* pA, ScMatrix* pB, ScMatrix* pR, USHORT n, USHORT m);
+void MFastTrans(ScMatrix* pA, ScMatrix* pR, USHORT n, USHORT m);
+BOOL MFastBackSubst(ScMatrix* pA, ScMatrix* pR, USHORT n, BOOL bIsUpper);
+BOOL ScMatLUP(ScMatrix* mA, USHORT m, USHORT p,
+ ScMatrix* mL, ScMatrix* mU, ScMatrix* mP,
+ USHORT& rPermutCounter, BOOL& bIsInvertable);
+void ScMatDet();
+void ScMatInv();
+void ScMatMult();
+void ScMatTrans();
+void ScEMat();
+void ScMatRef();
+ScMatrix* MatAdd(ScMatrix* pMat1, ScMatrix* pMat2);
+ScMatrix* MatSub(ScMatrix* pMat1, ScMatrix* pMat2);
+ScMatrix* MatMul(ScMatrix* pMat1, ScMatrix* pMat2);
+ScMatrix* MatDiv(ScMatrix* pMat1, ScMatrix* pMat2);
+ScMatrix* MatPow(ScMatrix* pMat1, ScMatrix* pMat2);
+ScMatrix* MatConcat(ScMatrix* pMat1, ScMatrix* pMat2);
+void ScSumProduct();
+void ScSumX2MY2();
+void ScSumX2DY2();
+void ScSumXMY2();
+void ScGrowth();
+// multiple Regression: Varianzen der Koeffizienten
+BOOL RGetVariances( ScMatrix* pV, ScMatrix* pX, USHORT nC, USHORT nR,
+ BOOL bSwapColRow, BOOL bZeroConstant );
+void ScRGP();
+void ScRKP();
+void ScForecast();
+//--------------------------------------------------------------------------------
+// Funktionen in interpr3.cxx
+// Statistik:
+void ScNoName();
+double phi(double x);
+double taylor(double* pPolynom, USHORT nMax, double x);
+double gauss(double x);
+double gaussinv(double x);
+double GetGammaDist(double x, double alpha, double beta);
+double GetBetaDist(double x, double alpha, double beta);
+double GetChiDist(double fChi, double fDF);
+double GetFDist(double x, double fF1, double fF2);
+double GetTDist(double T, double fDF);
+double Fakultaet(double x);
+double BinomKoeff(double n, double k);
+double GammaHelp(double& x, BOOL& bReflect);
+double GetGamma(double x);
+double GetLogGamma(double x);
+void ScLogGamma();
+void ScPhi();
+void ScGauss();
+void ScStdNormDist();
+void ScFisher();
+void ScFisherInv();
+void ScFact();
+void ScNormDist();
+void ScGammaDist();
+void ScGammaInv();
+void ScExpDist();
+void ScBinomDist();
+void ScPoissonDist();
+void ScKombin();
+void ScKombin2();
+void ScVariationen();
+void ScVariationen2();
+void ScB();
+void ScHypGeomDist();
+void ScLogNormDist();
+void ScLogNormInv();
+void ScTDist();
+void ScFDist();
+void ScChiDist();
+void ScWeibull();
+void ScBetaDist();
+void ScFInv();
+void ScTInv();
+void ScChiInv();
+void ScBetaInv();
+void ScCritBinom();
+void ScNegBinomDist();
+void ScKurt();
+void ScHarMean();
+void ScGeoMean();
+void ScStandard();
+void ScSkew();
+void ScMedian();
+void GetSortArray(BYTE nParamCount, double** ppSortArray, ULONG& nSize);
+void QuickSort(long nLo, long nHi, double* pSortArr);
+void ScModalValue();
+void ScAveDev();
+void ScDevSq();
+void ScZTest();
+void ScTTest();
+void ScFTest();
+void ScChiTest();
+void ScRank();
+void ScPercentile();
+void ScPercentrank();
+void ScLarge();
+void ScSmall();
+void ScFrequency();
+void ScQuartile();
+void ScNormInv();
+void ScSNormInv();
+void ScConfidence();
+void ScTrimMean();
+void ScProbability();
+void ScCorrel();
+void ScCovar();
+void ScPearson();
+void ScRSQ();
+void ScSTEXY();
+void ScSlope();
+void ScTrend();
+
+
+public:
+ ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc,
+ const ScAddress&, ScTokenArray& );
+ ~ScInterpreter();
+
+ StackVar Interpret();
+
+ static void SetError(USHORT nError)
+ { if (nError && !nGlobalError) nGlobalError = nError; }
+
+ static USHORT GetError() { return nGlobalError; }
+ static void MySigFunc(int sig);
+
+ const String& GetStringResult() { return aResult; }
+ double GetNumResult() { return nResult; }
+ ScMatrix* GetMatrixResult() { return pResult; }
+ StackVar GetResultType() { return eResult; }
+ short GetRetFormatType() { return nRetFmtType; }
+ ULONG GetRetFormatIndex() { return nRetFmtIndex; }
+ BOOL HadMatrix() const { return bMatDel; }
+};
+
+
+inline void ScInterpreter::MatrixDoubleRefToMatrix()
+{
+ if ( bMatrixFormula && GetStackType() == svDoubleRef )
+ PopDoubleRefPushMatrix();
+}
+
+
+inline BOOL ScInterpreter::MustHaveParamCount( BYTE nAct, BYTE nMust )
+{
+ if ( nAct == nMust )
+ return TRUE;
+ if ( nAct < nMust )
+ SetParameterExpected();
+ else
+ SetIllegalParameter();
+ return FALSE;
+}
+
+
+inline BOOL ScInterpreter::MustHaveParamCount( BYTE nAct, BYTE nMust, BYTE nMax )
+{
+ if ( nMust <= nAct && nAct <= nMax )
+ return TRUE;
+ if ( nAct < nMust )
+ SetParameterExpected();
+ else
+ SetIllegalParameter();
+ return FALSE;
+}
+
+
+inline BOOL ScInterpreter::MustHaveParamCountMin( BYTE nAct, BYTE nMin )
+{
+ if ( nAct >= nMin )
+ return TRUE;
+ SetParameterExpected();
+ return FALSE;
+}
+
+
+#endif
diff --git a/sc/source/core/inc/makefile.mk b/sc/source/core/inc/makefile.mk
new file mode 100644
index 000000000000..1bfe37abc598
--- /dev/null
+++ b/sc/source/core/inc/makefile.mk
@@ -0,0 +1,61 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-19 00:16:16 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
diff --git a/sc/source/core/inc/refupdat.hxx b/sc/source/core/inc/refupdat.hxx
new file mode 100644
index 000000000000..ef07d7b8e7bc
--- /dev/null
+++ b/sc/source/core/inc/refupdat.hxx
@@ -0,0 +1,120 @@
+/*************************************************************************
+ *
+ * $RCSfile: refupdat.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:16 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef SC_REFUPDAT_HXX
+#define SC_REFUPDAT_HXX
+
+#include "global.hxx"
+
+class ScDocument;
+class ScBigRange;
+struct ComplRefData;
+
+enum ScRefUpdateRes {
+ UR_NOTHING = 0, // keine Anpassungen
+ UR_UPDATED = 1, // Anpassungen erfolgt
+ UR_INVALID = 2 // Referenz wurde ungueltig
+};
+
+class ScRefUpdate
+{
+public:
+ static ScRefUpdateRes Update
+ ( ScDocument* pDoc, UpdateRefMode eUpdateRefMode,
+ USHORT nCol1, USHORT nRow1, USHORT nTab1,
+ USHORT nCol2, USHORT nRow2, USHORT nTab2,
+ short nDx, short nDy, short nDz,
+ USHORT& theCol1, USHORT& theRow1, USHORT& theTab1,
+ USHORT& theCol2, USHORT& theRow2, USHORT& theTab2 );
+
+ static ScRefUpdateRes Update( UpdateRefMode eUpdateRefMode,
+ const ScBigRange& rWhere,
+ INT32 nDx, INT32 nDy, INT32 nDz,
+ ScBigRange& rWhat );
+
+ static ScRefUpdateRes Update( ScDocument* pDoc,
+ UpdateRefMode eUpdateRefMode,
+ const ScAddress& rPos, const ScRange& rRange,
+ short nDx, short nDy, short nDz,
+ ComplRefData& rRef );
+ static ScRefUpdateRes Move( ScDocument* pDoc, const ScAddress& rPos,
+ short nDx, short nDy, short nDz,
+ ComplRefData& rRef, BOOL bWrap, BOOL bAbsolute );
+ static void MoveRelWrap( ScDocument* pDoc, const ScAddress& rPos,
+ ComplRefData& rRef );
+
+ static ScRefUpdateRes UpdateTranspose( ScDocument* pDoc,
+ const ScRange& rSource, const ScAddress& rDest,
+ ComplRefData& rRef );
+ static void DoTranspose( short& rCol, short& rRow, short& rTab, ScDocument* pDoc,
+ const ScRange& rSource, const ScAddress& rDest );
+
+ static ScRefUpdateRes UpdateGrow(
+ const ScRange& rArea, USHORT nGrowX, USHORT nGrowY,
+ ComplRefData& rRef );
+
+ static ScRefUpdateRes DoGrow( const ScRange& rArea, USHORT nGrowX, USHORT nGrowY,
+ ScRange& rRef );
+};
+
+
+#endif
+
diff --git a/sc/source/core/inc/sctictac.hxx b/sc/source/core/inc/sctictac.hxx
new file mode 100644
index 000000000000..7c34a6d0afba
--- /dev/null
+++ b/sc/source/core/inc/sctictac.hxx
@@ -0,0 +1,164 @@
+/*************************************************************************
+ *
+ * $RCSfile: sctictac.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:16 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef SC_SCTICTAC_HXX
+#define SC_SCTICTAC_HXX
+
+//#define TICTACTOE_MAIN
+#ifdef TICTACTOE_MAIN
+#define TICTACTOE_STDOUT
+#else
+//#define TICTACTOE_STDOUT
+#endif
+#ifndef TICTACTOE_STDOUT
+#define TICTACTOE_SC
+#endif
+
+#ifdef TICTACTOE_SC
+class ScDocument;
+#include "global.hxx"
+#else
+#include <tools/string.hxx>
+#endif
+
+static const int ScTicTacToe_Squares = 9;
+static const int ScTicTacToe_Possible_Wins = 8;
+typedef sal_Unicode Square_Type;
+typedef Square_Type Board_Type[ScTicTacToe_Squares];
+
+class ScTicTacToe
+{
+private:
+ /* Structure to hold a move and its heuristic */
+ typedef struct {
+ int Square;
+ int Heuristic;
+ } Move_Heuristic_Type;
+
+ static const Square_Type Empty;
+ static const Square_Type Human;
+ static const Square_Type Compi;
+ static const int Infinity; /* Higher value than any score */
+ static const int Maximum_Moves; /* Maximum moves in a game */
+
+ Board_Type Board;
+#ifdef TICTACTOE_SC
+ ScAddress aPos; // linke obere Ecke des Boards
+ ScDocument* pDoc;
+#endif
+ ByteString aStdOut;
+ int Total_Nodes; /* Nodes searched with minimax */
+ int nMove;
+ Square_Type aPlayer;
+ BOOL bInitialized;
+
+ /* Array describing the eight combinations of three squares in a row */
+ static const int Three_in_a_Row[ScTicTacToe_Possible_Wins][3];
+
+ /* Array used in heuristic formula for each move. */
+ static const int Heuristic_Array[4][4];
+
+
+ Square_Type Winner();
+ inline Square_Type Other( Square_Type Player );
+ inline void Play( int Square, Square_Type Player );
+ int Evaluate( Square_Type Player );
+ int BestMove( Square_Type Player, int *Square,
+ int Move_Nbr, int Alpha, int Beta );
+ void Describe( int Score );
+ void Move( int& Square );
+ Square_Type TryMove( int& Square ); // return Winner()
+ void PromptHuman();
+#ifdef TICTACTOE_SC
+ // -1 == Fehler/Redraw, 0 == keine Aenderung, >0 == UserMoveSquare+1
+ int GetStatus();
+ void DrawBoard();
+ void DrawPos( int nSquare, const String& rStr );
+#endif
+#ifdef TICTACTOE_STDOUT
+ void Print();
+#endif
+
+ ScTicTacToe( const ScTicTacToe& );
+ ScTicTacToe& operator=( const ScTicTacToe& );
+
+public:
+#ifdef TICTACTOE_SC
+ ScTicTacToe( ScDocument* pDoc, const ScAddress& );
+#else
+ ScTicTacToe();
+#endif
+ ~ScTicTacToe() {}
+ void Initialize( BOOL bHumanFirst );
+ Square_Type GetEmpty() { return Empty; }
+#ifdef TICTACTOE_SC
+ Square_Type CalcMove(); // return Winner()
+#endif
+#ifdef TICTACTOE_STDOUT
+ void Game();
+ void GetOutput( ByteString& rStr );
+#else
+ void GetOutput( String& rStr );
+#endif
+};
+
+#endif
+
diff --git a/sc/source/core/src/compiler.src b/sc/source/core/src/compiler.src
new file mode 100644
index 000000000000..8a485068108b
--- /dev/null
+++ b/sc/source/core/src/compiler.src
@@ -0,0 +1,7409 @@
+/*************************************************************************
+ *
+ * $RCSfile: compiler.src,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:16 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+#include "sc.hrc" // Definition RID_XXX
+#include "compiler.hrc" // Definition SC_OPCODE_XXX (interne OpCodes)
+
+Resource RID_SC_FUNCTION_NAMES
+{
+ String SC_OPCODE_IF
+ {
+ Text = "WENN" ;
+ Text [ english ] = "IF" ;
+ Text [ norwegian ] = "HVIS" ;
+ Text [ italian ] = "SE" ;
+ Text [ portuguese_brazilian ] = "IF" ;
+ Text [ portuguese ] = "SE" ;
+ Text [ finnish ] = "IF" ;
+ Text [ danish ] = "HVIS" ;
+ Text [ french ] = "SI" ;
+ Text [ swedish ] = "OM" ;
+ Text [ dutch ] = "ALS" ;
+ Text [ spanish ] = "SI" ;
+ Text [ english_us ] = "IF" ;
+ Text[ chinese_simplified ] = "IF";
+ Text[ russian ] = "ÅÑËÈ";
+ Text[ polish ] = "GDY";
+ Text[ japanese ] = "IF";
+ Text[ chinese_traditional ] = "IF";
+ Text[ arabic ] = "IF";
+ Text[ dutch ] = "ALS";
+ Text[ chinese_simplified ] = "IF";
+ Text[ greek ] = "IF";
+ Text[ korean ] = "IF";
+ Text[ turkish ] = "IF";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_CHOSE
+ {
+ Text = "WAHL" ;
+ Text [ english ] = "CHOOSE" ;
+ Text [ norwegian ] = "VELG" ;
+ Text [ italian ] = "SCEGLI" ;
+ Text [ portuguese_brazilian ] = "ESCOLHER" ;
+ Text [ portuguese ] = "SELECCIONAR" ;
+ Text [ finnish ] = "CHOSE" ;
+ Text [ danish ] = "VÆLG" ;
+ Text [ french ] = "CHOISIR" ;
+ Text [ swedish ] = "VÄLJ" ;
+ Text [ dutch ] = "KIEZEN" ;
+ Text [ spanish ] = "ELEGIR" ;
+ Text [ english_us ] = "CHOOSE" ;
+ Text[ chinese_simplified ] = "CHOOSE";
+ Text[ russian ] = "ÂÛÁÎÐ";
+ Text[ polish ] = "WYBIERZ";
+ Text[ japanese ] = "CHOOSE";
+ Text[ chinese_traditional ] = "CHOOSE";
+ Text[ arabic ] = "CHOOSE";
+ Text[ dutch ] = "KIEZEN";
+ Text[ chinese_simplified ] = "CHOOSE";
+ Text[ greek ] = "CHOOSE";
+ Text[ korean ] = "CHOOSE";
+ Text[ turkish ] = "CHOOSE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_OPEN { Text = "(" ; };
+ String SC_OPCODE_CLOSE { Text = ")" ; };
+ String SC_OPCODE_SEP { Text = ";" ; };
+ String SC_OPCODE_ADD { Text = "+" ; };
+ String SC_OPCODE_SUB { Text = "-" ; };
+ String SC_OPCODE_MUL { Text = "*" ; };
+ String SC_OPCODE_DIV { Text = "/" ; };
+ String SC_OPCODE_AMPERSAND { Text = "&" ; };
+ String SC_OPCODE_POW { Text = "^" ; };
+ String SC_OPCODE_EQUAL { Text = "=" ; };
+ String SC_OPCODE_NOT_EQUAL { Text = "<>" ; };
+ String SC_OPCODE_LESS { Text = "<" ; };
+ String SC_OPCODE_GREATER { Text = ">" ; };
+ String SC_OPCODE_LESS_EQUAL { Text = "<=" ; };
+ String SC_OPCODE_GREATER_EQUAL { Text = ">=" ; };
+ String SC_OPCODE_AND
+ {
+ Text = "UND" ;
+ Text [ english ] = "AND" ;
+ Text [ norwegian ] = "OG" ;
+ Text [ italian ] = "E" ;
+ Text [ portuguese_brazilian ] = "E" ;
+ Text [ portuguese ] = "E" ;
+ Text [ finnish ] = "AND" ;
+ Text [ danish ] = "OG" ;
+ Text [ french ] = "ET" ;
+ Text [ swedish ] = "OCH" ;
+ Text [ dutch ] = "EN" ;
+ Text [ spanish ] = "Y" ;
+ Text [ english_us ] = "AND" ;
+ Text[ chinese_simplified ] = "AND";
+ Text[ russian ] = "È";
+ Text[ polish ] = "I";
+ Text[ japanese ] = "AND";
+ Text[ chinese_traditional ] = "AND";
+ Text[ arabic ] = "AND";
+ Text[ dutch ] = "EN";
+ Text[ chinese_simplified ] = "AND";
+ Text[ greek ] = "KAI";
+ Text[ korean ] = "AND";
+ Text[ turkish ] = "AND";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_OR
+ {
+ Text = "ODER" ;
+ Text [ english ] = "OR" ;
+ Text [ norwegian ] = "ELLER" ;
+ Text [ italian ] = "O" ;
+ Text [ portuguese_brazilian ] = "OU" ;
+ Text [ portuguese ] = "OU" ;
+ Text [ finnish ] = "OR" ;
+ Text [ danish ] = "ELLER" ;
+ Text [ french ] = "OU" ;
+ Text [ swedish ] = "ELLER" ;
+ Text [ dutch ] = "OF" ;
+ Text [ spanish ] = "O" ;
+ Text [ english_us ] = "OR" ;
+ Text[ chinese_simplified ] = "OR";
+ Text[ russian ] = "ÈËÈ";
+ Text[ polish ] = "LUB";
+ Text[ japanese ] = "OR";
+ Text[ chinese_traditional ] = "OR";
+ Text[ arabic ] = "OR";
+ Text[ dutch ] = "OF";
+ Text[ chinese_simplified ] = "OR";
+ Text[ greek ] = "OR";
+ Text[ korean ] = "OR";
+ Text[ turkish ] = "OR";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_INTERSECT { Text = "!" ; };
+ String SC_OPCODE_UNION { Text = ";" ; };
+ String SC_OPCODE_RANGE { Text = ":" ; };
+ String SC_OPCODE_NOT
+ {
+ Text = "NICHT" ;
+ Text [ english ] = "NOT" ;
+ Text [ norwegian ] = "IKKE" ;
+ Text [ italian ] = "NON" ;
+ Text [ portuguese_brazilian ] = "NãO" ;
+ Text [ portuguese ] = "NÃO" ;
+ Text [ finnish ] = "NOT" ;
+ Text [ danish ] = "IKKE" ;
+ Text [ french ] = "NON" ;
+ Text [ swedish ] = "ICKE" ;
+ Text [ dutch ] = "NIET" ;
+ Text [ spanish ] = "NO" ;
+ Text [ english_us ] = "NOT" ;
+ Text[ chinese_simplified ] = "NOT";
+ Text[ russian ] = "ÍÅ";
+ Text[ polish ] = "NIE";
+ Text[ japanese ] = "NOT";
+ Text[ chinese_traditional ] = "NOT";
+ Text[ arabic ] = "NOT";
+ Text[ dutch ] = "NIET";
+ Text[ chinese_simplified ] = "NOT";
+ Text[ greek ] = "NOT";
+ Text[ korean ] = "NOT";
+ Text[ turkish ] = "NOT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_NEG { Text = "NEG" ; };
+ String SC_OPCODE_NEG_SUB { Text = "-" ; };
+ String SC_OPCODE_PI
+ {
+ Text = "PI" ;
+ Text [ english ] = "PI" ;
+ Text [ norwegian ] = "PI" ;
+ Text [ italian ] = "PI.GRECO" ;
+ // ???
+ Text [ portuguese_brazilian ] = "PI" ;
+ Text [ portuguese ] = "PI" ;
+ Text [ finnish ] = "PI" ;
+ Text [ danish ] = "PI" ;
+ Text [ french ] = "PI" ;
+ Text [ swedish ] = "PI" ;
+ Text [ dutch ] = "PI" ;
+ Text [ spanish ] = "PI" ;
+ Text [ english_us ] = "PI" ;
+ Text[ chinese_simplified ] = "PI";
+ Text[ russian ] = "ÏÈ";
+ Text[ polish ] = "PI";
+ Text[ japanese ] = "PI";
+ Text[ chinese_traditional ] = "PI";
+ Text[ arabic ] = "PI";
+ Text[ dutch ] = "PI";
+ Text[ chinese_simplified ] = "PI";
+ Text[ greek ] = "PI";
+ Text[ korean ] = "PI";
+ Text[ turkish ] = "PI";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_RANDOM
+ {
+ Text = "ZUFALLSZAHL" ;
+ Text [ english ] = "RAND" ;
+ Text [ norwegian ] = "TILFELDIG" ;
+ Text [ italian ] = "CASUALE" ;
+ Text [ portuguese_brazilian ] = "ALEA" ;
+ Text [ portuguese ] = "ALEATÒRIO" ;
+ Text [ finnish ] = "RAND" ;
+ Text [ danish ] = "SLUMP" ;
+ Text [ french ] = "ALEA" ;
+ Text [ swedish ] = "SLUMP" ;
+ Text [ dutch ] = "ASELECT" ;
+ Text [ spanish ] = "ALEATORIO" ;
+ Text [ english_us ] = "RAND" ;
+ Text[ chinese_simplified ] = "RAND";
+ Text[ russian ] = "ÑË×ÈÑ";
+ Text[ polish ] = "LOS";
+ Text[ japanese ] = "RAND";
+ Text[ chinese_traditional ] = "RAND";
+ Text[ arabic ] = "RAND";
+ Text[ dutch ] = "ASELECT";
+ Text[ chinese_simplified ] = "RAND";
+ Text[ greek ] = "RAND";
+ Text[ korean ] = "RAND";
+ Text[ turkish ] = "RAND";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_TRUE
+ {
+ Text = "WAHR" ;
+ Text [ english ] = "TRUE" ;
+ Text [ norwegian ] = "RIKTIG" ;
+ Text [ italian ] = "VERO" ;
+ Text [ portuguese_brazilian ] = "VERDADEIRO" ;
+ Text [ portuguese ] = "VERDADEIRO" ;
+ Text [ finnish ] = "TRUE" ;
+ Text [ danish ] = "SAND" ;
+ Text [ french ] = "VRAI" ;
+ Text [ swedish ] = "SANT" ;
+ Text [ dutch ] = "WAAR" ;
+ Text [ spanish ] = "VERDADERO" ;
+ Text [ english_us ] = "TRUE" ;
+ Text[ chinese_simplified ] = "TRUE";
+ Text[ russian ] = "ÈÑÒÈÍÀ";
+ Text[ polish ] = "PRAWDA";
+ Text[ japanese ] = "TRUE";
+ Text[ chinese_traditional ] = "TRUE";
+ Text[ arabic ] = "TRUE";
+ Text[ dutch ] = "WAAR";
+ Text[ chinese_simplified ] = "TRUE";
+ Text[ greek ] = "TRUE";
+ Text[ korean ] = "TRUE";
+ Text[ turkish ] = "TRUE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_FALSE
+ {
+ Text = "FALSCH" ;
+ Text [ english ] = "FALSE" ;
+ Text [ norwegian ] = "GALT" ;
+ Text [ italian ] = "FALSO" ;
+ Text [ portuguese_brazilian ] = "FALSO" ;
+ Text [ portuguese ] = "FALSO" ;
+ Text [ finnish ] = "FALSE" ;
+ Text [ danish ] = "FALSK" ;
+ Text [ french ] = "FAUX" ;
+ Text [ swedish ] = "FALSKT" ;
+ Text [ dutch ] = "ONWAAR" ;
+ Text [ spanish ] = "FALSO" ;
+ Text [ english_us ] = "FALSE" ;
+ Text[ chinese_simplified ] = "FALSE";
+ Text[ russian ] = "ËÎÆÜ";
+ Text[ polish ] = "FA£SZ";
+ Text[ japanese ] = "FALSE";
+ Text[ chinese_traditional ] = "FALSE";
+ Text[ arabic ] = "FALSE";
+ Text[ dutch ] = "ONWAAR";
+ Text[ chinese_simplified ] = "FALSE";
+ Text[ greek ] = "FALSE";
+ Text[ korean ] = "FALSE";
+ Text[ turkish ] = "FALSE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GET_ACT_DATE
+ {
+ Text = "HEUTE" ;
+ Text [ english ] = "TODAY" ;
+ Text [ norwegian ] = "I.DAG" ;
+ Text [ italian ] = "OGGI" ;
+ Text [ portuguese_brazilian ] = "HOJE" ;
+ Text [ portuguese ] = "HOJE" ;
+ Text [ finnish ] = "TODAY" ;
+ Text [ danish ] = "IDAG" ;
+ Text [ french ] = "AUJOURDHUI" ;
+ Text [ swedish ] = "IDAG" ;
+ Text [ dutch ] = "VANDAAG" ;
+ Text [ spanish ] = "HOY" ;
+ Text [ english_us ] = "TODAY" ;
+ Text[ chinese_simplified ] = "TODAY";
+ Text[ russian ] = "ÑÅÃÎÄÍß";
+ Text[ polish ] = "DZISIAJ";
+ Text[ japanese ] = "TODAY";
+ Text[ chinese_traditional ] = "TODAY";
+ Text[ arabic ] = "TODAY";
+ Text[ dutch ] = "VANDAAG";
+ Text[ chinese_simplified ] = "TODAY";
+ Text[ greek ] = "TODAY";
+ Text[ korean ] = "TODAY";
+ Text[ turkish ] = "TODAY";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GET_ACT_TIME
+ {
+ Text = "JETZT" ;
+ Text [ english ] = "NOW" ;
+ Text [ norwegian ] = "NÅ" ;
+ Text [ italian ] = "ADESSO" ;
+ Text [ portuguese_brazilian ] = "AGORA" ;
+ Text [ portuguese ] = "AGORA" ;
+ Text [ finnish ] = "NOW" ;
+ Text [ danish ] = "NU" ;
+ Text [ french ] = "MAINTENANT" ;
+ Text [ swedish ] = "NU" ;
+ Text [ dutch ] = "NU" ;
+ Text [ spanish ] = "AHORA" ;
+ Text [ english_us ] = "NOW" ;
+ Text[ chinese_simplified ] = "NOW";
+ Text[ russian ] = "ÒÄÀÒÀ";
+ Text[ polish ] = "TERAZ";
+ Text[ japanese ] = "NOW";
+ Text[ chinese_traditional ] = "NOW";
+ Text[ arabic ] = "NOW";
+ Text[ dutch ] = "NU";
+ Text[ chinese_simplified ] = "NOW";
+ Text[ greek ] = "NOW";
+ Text[ korean ] = "NOW";
+ Text[ turkish ] = "NOW";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_NO_VALUE
+ {
+ Text = "NV" ;
+ Text [ english ] = "NA" ;
+ Text [ norwegian ] = "IT" ;
+ Text [ italian ] = "NON.DISP" ;
+ Text [ portuguese_brazilian ] = "NA" ;
+ Text [ portuguese ] = "NA" ;
+ Text [ finnish ] = "NA" ;
+ Text [ danish ] = "IKKE.TILGÆNGELIG" ;
+ Text [ french ] = "NA" ;
+ Text [ swedish ] = "SAKNAS" ;
+ Text [ dutch ] = "NB" ;
+ Text [ spanish ] = "NOD" ;
+ Text [ english_us ] = "NA" ;
+ Text[ chinese_simplified ] = "NA";
+ Text[ russian ] = "ÍÄ";
+ Text[ polish ] = "NA";
+ Text[ japanese ] = "NA";
+ Text[ chinese_traditional ] = "NA";
+ Text[ arabic ] = "NA";
+ Text[ dutch ] = "NB";
+ Text[ chinese_simplified ] = "NA";
+ Text[ greek ] = "NA";
+ Text[ korean ] = "NA";
+ Text[ turkish ] = "NA";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_CURRENT
+ {
+ Text = "AKTUELL" ;
+ Text [ english ] = "CURRENT" ;
+ Text [ norwegian ] = "CURRENT" ;
+ Text [ italian ] = "CURRENT" ;
+ Text [ portuguese_brazilian ] = "CURRENT" ;
+ Text [ portuguese ] = "ACTUAL" ;
+ Text [ finnish ] = "CURRENT" ;
+ Text [ danish ] = "AKTUEL" ;
+ Text [ french ] = "ACTUELLE" ;
+ Text [ swedish ] = "AKTUELL" ;
+ Text [ dutch ] = "ACTUEEL" ;
+ Text [ spanish ] = "ACTUAL" ;
+ Text [ english_us ] = "CURRENT" ;
+ Text[ chinese_simplified ] = "CURRENT";
+ Text[ russian ] = "ÒÅÊÓÙ";
+ Text[ polish ] = "AKTUALNY";
+ Text[ japanese ] = "CURRENT";
+ Text[ chinese_traditional ] = "CURRENT";
+ Text[ arabic ] = "CURRENT";
+ Text[ dutch ] = "ACTUEEL";
+ Text[ chinese_simplified ] = "CURRENT";
+ Text[ greek ] = "CURRENT";
+ Text[ korean ] = "CURRENT";
+ Text[ turkish ] = "CURRENT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_DEG
+ {
+ Text = "DEG" ;
+ Text [ english ] = "DEGREES" ;
+ Text [ norwegian ] = "GRADER" ;
+ Text [ italian ] = "GRADI" ;
+ Text [ portuguese_brazilian ] = "GRAUS" ;
+ Text [ portuguese ] = "GRAUS" ;
+ Text [ finnish ] = "DEGREES" ;
+ Text [ danish ] = "GRADER" ;
+ Text [ french ] = "DEGRES" ;
+ Text [ swedish ] = "GRADER" ;
+ Text [ dutch ] = "GRADEN" ;
+ Text [ spanish ] = "GRADOS" ;
+ Text [ english_us ] = "DEGREES" ;
+ Text[ chinese_simplified ] = "DEGREES";
+ Text[ russian ] = "ÃÐÀÄÓÑÛ";
+ Text[ polish ] = "STOPNIE";
+ Text[ japanese ] = "DEGREES";
+ Text[ chinese_traditional ] = "DEGREES";
+ Text[ arabic ] = "DEGREES";
+ Text[ dutch ] = "GRADEN";
+ Text[ chinese_simplified ] = "DEGREES";
+ Text[ greek ] = "DEGREES";
+ Text[ korean ] = "DEGREES";
+ Text[ turkish ] = "DEGREES";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_RAD
+ {
+ Text = "RAD" ;
+ Text [ english ] = "RADIANS" ;
+ Text [ norwegian ] = "RADIUS" ;
+ Text [ italian ] = "RADIANTI" ;
+ Text [ portuguese_brazilian ] = "RADIANOS" ;
+ Text [ portuguese ] = "RADIANOS" ;
+ Text [ finnish ] = "RADIANS" ;
+ Text [ danish ] = "RADIANER" ;
+ Text [ french ] = "RADIANS" ;
+ Text [ swedish ] = "RADIANER" ;
+ Text [ dutch ] = "RADIALEN" ;
+ Text [ spanish ] = "RADIANES" ;
+ Text [ english_us ] = "RADIANS" ;
+ Text[ chinese_simplified ] = "RADIANS";
+ Text[ russian ] = "ÐÀÄÈÀÍÛ";
+ Text[ polish ] = "RADIANY";
+ Text[ japanese ] = "RADIANS";
+ Text[ chinese_traditional ] = "RADIANS";
+ Text[ arabic ] = "RADIANS";
+ Text[ dutch ] = "RADIALEN";
+ Text[ chinese_simplified ] = "RADIANS";
+ Text[ greek ] = "RADIANS";
+ Text[ korean ] = "RADIANS";
+ Text[ turkish ] = "RADIANS";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_SIN
+ {
+ Text = "SIN" ;
+ Text [ english ] = "SIN" ;
+ Text [ norwegian ] = "SIN" ;
+ Text [ italian ] = "SEN" ;
+ Text [ portuguese_brazilian ] = "SEN" ;
+ Text [ portuguese ] = "SEN" ;
+ Text [ finnish ] = "SIN" ;
+ Text [ danish ] = "SIN" ;
+ Text [ french ] = "SIN" ;
+ Text [ swedish ] = "SIN" ;
+ Text [ dutch ] = "SIN" ;
+ Text [ spanish ] = "SENO" ;
+ Text [ english_us ] = "SIN" ;
+ Text[ chinese_simplified ] = "SIN";
+ Text[ russian ] = "SIN";
+ Text[ polish ] = "SIN";
+ Text[ japanese ] = "SIN";
+ Text[ chinese_traditional ] = "SIN";
+ Text[ arabic ] = "SIN";
+ Text[ dutch ] = "SIN";
+ Text[ chinese_simplified ] = "SIN";
+ Text[ greek ] = "SIN";
+ Text[ korean ] = "SIN";
+ Text[ turkish ] = "SIN";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_COS { Text = "COS" ; };
+ String SC_OPCODE_TAN { Text = "TAN" ; };
+ String SC_OPCODE_COT { Text = "COT" ; };
+ String SC_OPCODE_ARC_SIN
+ {
+ Text = "ARCSIN" ;
+ Text [ english ] = "ASIN" ;
+ Text [ norwegian ] = "ASIN" ;
+ Text [ italian ] = "ARCSEN" ;
+ Text [ portuguese_brazilian ] = "ASEN" ;
+ Text [ portuguese ] = "ASEN" ;
+ Text [ finnish ] = "ASIN" ;
+ Text [ danish ] = "ARCSIN" ;
+ Text [ french ] = "ASIN" ;
+ Text [ swedish ] = "ARCSIN" ;
+ Text [ dutch ] = "BOOGSIN" ;
+ Text [ spanish ] = "ASENO" ;
+ Text [ english_us ] = "ASIN" ;
+ Text[ chinese_simplified ] = "ASIN";
+ Text[ russian ] = "ASIN";
+ Text[ polish ] = "ASIN";
+ Text[ japanese ] = "ASIN";
+ Text[ chinese_traditional ] = "ASIN";
+ Text[ arabic ] = "ASIN";
+ Text[ dutch ] = "BOOGSIN";
+ Text[ chinese_simplified ] = "ASIN";
+ Text[ greek ] = "ASIN";
+ Text[ korean ] = "ASIN";
+ Text[ turkish ] = "ASIN";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ARC_COS
+ {
+ Text = "ARCCOS" ;
+ Text [ english ] = "ACOS" ;
+ Text [ norwegian ] = "ACOS" ;
+ Text [ italian ] = "ARCCOS" ;
+ Text [ portuguese_brazilian ] = "ACOS" ;
+ Text [ portuguese ] = "ACOS" ;
+ Text [ finnish ] = "ACOS" ;
+ Text [ danish ] = "ARCCOS" ;
+ Text [ french ] = "ACOS" ;
+ Text [ swedish ] = "ARCCOS" ;
+ Text [ dutch ] = "BOOGCOS" ;
+ Text [ spanish ] = "ACOS" ;
+ Text [ english_us ] = "ACOS" ;
+ Text[ chinese_simplified ] = "ACOS";
+ Text[ russian ] = "ACOS";
+ Text[ polish ] = "ACOS";
+ Text[ japanese ] = "ACOS";
+ Text[ chinese_traditional ] = "ACOS";
+ Text[ arabic ] = "ACOS";
+ Text[ dutch ] = "BOOGCOS";
+ Text[ chinese_simplified ] = "ACOS";
+ Text[ greek ] = "ACOS";
+ Text[ korean ] = "ACOS";
+ Text[ turkish ] = "ACOS";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ARC_TAN
+ {
+ Text = "ARCTAN" ;
+ Text [ english ] = "ATAN" ;
+ Text [ norwegian ] = "ATAN" ;
+ Text [ italian ] = "ARCTAN" ;
+ Text [ portuguese_brazilian ] = "ATAN" ;
+ Text [ portuguese ] = "ATAN" ;
+ Text [ finnish ] = "ATAN" ;
+ Text [ danish ] = "ARCTAN" ;
+ Text [ french ] = "ATAN" ;
+ Text [ swedish ] = "ARCTAN" ;
+ Text [ dutch ] = "BOOGTAN" ;
+ Text [ spanish ] = "ATAN" ;
+ Text [ english_us ] = "ATAN" ;
+ Text[ chinese_simplified ] = "ATAN";
+ Text[ russian ] = "ATAN";
+ Text[ polish ] = "ATAN";
+ Text[ japanese ] = "ATAN";
+ Text[ chinese_traditional ] = "ATAN";
+ Text[ arabic ] = "ATAN";
+ Text[ dutch ] = "BOOGTAN";
+ Text[ chinese_simplified ] = "ATAN";
+ Text[ greek ] = "ATAN";
+ Text[ korean ] = "ATAN";
+ Text[ turkish ] = "ATAN";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ARC_COT
+ {
+ Text = "ARCCOT" ;
+ Text [ english ] = "ACOT" ;
+ Text [ norwegian ] = "ACOT" ;
+ Text [ italian ] = "ARCCOT" ;
+ Text [ portuguese_brazilian ] = "ACOT" ;
+ Text [ portuguese ] = "ATAN" ;
+ Text [ finnish ] = "ACOT" ;
+ Text [ danish ] = "ARCCOT" ;
+ Text [ french ] = "ACOT" ;
+ Text [ swedish ] = "ARCCOT" ;
+ Text [ dutch ] = "BOOGCOT" ;
+ Text [ spanish ] = "ACOT" ;
+ Text [ english_us ] = "ACOT" ;
+ Text[ chinese_simplified ] = "ACOT";
+ Text[ russian ] = "ACOT";
+ Text[ polish ] = "ACOT";
+ Text[ japanese ] = "ACOT";
+ Text[ chinese_traditional ] = "ACOT";
+ Text[ arabic ] = "ACOT";
+ Text[ dutch ] = "BOOGCOT";
+ Text[ chinese_simplified ] = "ACOT";
+ Text[ greek ] = "ACOT";
+ Text[ korean ] = "ACOT";
+ Text[ turkish ] = "ACOT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_SIN_HYP
+ {
+ Text = "SINHYP" ;
+ Text [ english ] = "SINH" ;
+ Text [ norwegian ] = "SINH" ;
+ Text [ italian ] = "SENH" ;
+ Text [ portuguese_brazilian ] = "SENH" ;
+ Text [ portuguese ] = "SENH" ;
+ Text [ finnish ] = "SINH" ;
+ Text [ danish ] = "SINH" ;
+ Text [ french ] = "SINH" ;
+ Text [ swedish ] = "SINH" ;
+ Text [ dutch ] = "SINH" ;
+ Text [ spanish ] = "SENOH" ;
+ Text [ english_us ] = "SINH" ;
+ Text[ chinese_simplified ] = "SINH";
+ Text[ russian ] = "SINH";
+ Text[ polish ] = "SINH";
+ Text[ japanese ] = "SINH";
+ Text[ chinese_traditional ] = "SINH";
+ Text[ arabic ] = "SINH";
+ Text[ dutch ] = "SINH";
+ Text[ chinese_simplified ] = "SINH";
+ Text[ greek ] = "SINH";
+ Text[ korean ] = "SINH";
+ Text[ turkish ] = "SINH";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_COS_HYP
+ {
+ Text = "COSHYP" ;
+ Text [ english ] = "COSH" ;
+ Text [ norwegian ] = "COSH" ;
+ Text [ italian ] = "COSH" ;
+ Text [ portuguese_brazilian ] = "COSH" ;
+ Text [ portuguese ] = "COSH" ;
+ Text [ finnish ] = "COSH" ;
+ Text [ danish ] = "COSH" ;
+ Text [ french ] = "COSH" ;
+ Text [ swedish ] = "COSH" ;
+ Text [ dutch ] = "COSH" ;
+ Text [ spanish ] = "COSH" ;
+ Text [ english_us ] = "COSH" ;
+ Text[ chinese_simplified ] = "COSH";
+ Text[ russian ] = "COSH";
+ Text[ polish ] = "COSH";
+ Text[ japanese ] = "COSH";
+ Text[ chinese_traditional ] = "COSH";
+ Text[ arabic ] = "COSH";
+ Text[ dutch ] = "COSH";
+ Text[ chinese_simplified ] = "COSH";
+ Text[ greek ] = "COSH";
+ Text[ korean ] = "COSH";
+ Text[ turkish ] = "COSH";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_TAN_HYP
+ {
+ Text = "TANHYP" ;
+ Text [ english ] = "TANH" ;
+ Text [ norwegian ] = "TANH" ;
+ Text [ italian ] = "TANH" ;
+ Text [ portuguese_brazilian ] = "TANH" ;
+ Text [ portuguese ] = "TANH" ;
+ Text [ finnish ] = "TANH" ;
+ Text [ danish ] = "TANH" ;
+ Text [ french ] = "TANH" ;
+ Text [ swedish ] = "TANH" ;
+ Text [ dutch ] = "TANH" ;
+ Text [ spanish ] = "TANH" ;
+ Text [ english_us ] = "TANH" ;
+ Text[ chinese_simplified ] = "TANH";
+ Text[ russian ] = "TANH";
+ Text[ polish ] = "TANH";
+ Text[ japanese ] = "TANH";
+ Text[ chinese_traditional ] = "TANH";
+ Text[ arabic ] = "TANH";
+ Text[ dutch ] = "TANH";
+ Text[ chinese_simplified ] = "TANH";
+ Text[ greek ] = "TANH";
+ Text[ korean ] = "TANH";
+ Text[ turkish ] = "TANH";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_COT_HYP
+ {
+ Text = "COTHYP" ;
+ Text [ english ] = "COTH" ;
+ Text [ norwegian ] = "COTH" ;
+ Text [ italian ] = "COTH" ;
+ Text [ portuguese_brazilian ] = "COTH" ;
+ Text [ portuguese ] = "COTH" ;
+ Text [ finnish ] = "COTH" ;
+ Text [ danish ] = "COTH" ;
+ Text [ french ] = "COTH" ;
+ Text [ swedish ] = "COTH" ;
+ Text [ dutch ] = "COTH" ;
+ Text [ spanish ] = "COTH" ;
+ Text [ english_us ] = "COTH" ;
+ Text[ chinese_simplified ] = "COTH";
+ Text[ russian ] = "COTH";
+ Text[ polish ] = "COTH";
+ Text[ japanese ] = "COTH";
+ Text[ chinese_traditional ] = "COTH";
+ Text[ arabic ] = "COTH";
+ Text[ dutch ] = "COTH";
+ Text[ chinese_simplified ] = "COTH";
+ Text[ greek ] = "COTH";
+ Text[ korean ] = "COTH";
+ Text[ turkish ] = "COTH";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ARC_SIN_HYP
+ {
+ Text = "ARCSINHYP" ;
+ Text [ english ] = "ASINH" ;
+ Text [ norwegian ] = "ASINH" ;
+ Text [ italian ] = "ARCSENH" ;
+ Text [ portuguese_brazilian ] = "ASENH" ;
+ Text [ portuguese ] = "ASENH" ;
+ Text [ finnish ] = "ASINH" ;
+ Text [ danish ] = "ARCSINH" ;
+ Text [ french ] = "ASINH" ;
+ Text [ swedish ] = "ARCSINH" ;
+ Text [ dutch ] = "BOOGSINH" ;
+ Text [ spanish ] = "ASENOH" ;
+ Text [ english_us ] = "ASINH" ;
+ Text[ chinese_simplified ] = "ASINH";
+ Text[ russian ] = "ASINH";
+ Text[ polish ] = "ASINH";
+ Text[ japanese ] = "ASINH";
+ Text[ chinese_traditional ] = "ASINH";
+ Text[ arabic ] = "ASINH";
+ Text[ dutch ] = "BOOGSINH";
+ Text[ chinese_simplified ] = "ASINH";
+ Text[ greek ] = "ASINH";
+ Text[ korean ] = "ASINH";
+ Text[ turkish ] = "ASINH";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ARC_COS_HYP
+ {
+ Text = "ARCCOSHYP" ;
+ Text [ english ] = "ACOSH" ;
+ Text [ norwegian ] = "ACOSH" ;
+ Text [ italian ] = "ARCCOSH" ;
+ Text [ portuguese_brazilian ] = "ACOSH" ;
+ Text [ portuguese ] = "ACOSH" ;
+ Text [ finnish ] = "ACOSH" ;
+ Text [ danish ] = "ARCCOSH" ;
+ Text [ french ] = "ACOSH" ;
+ Text [ swedish ] = "ARCCOSH" ;
+ Text [ dutch ] = "BOOGCOSH" ;
+ Text [ spanish ] = "ACOSH" ;
+ Text [ english_us ] = "ACOSH" ;
+ Text[ chinese_simplified ] = "ACOSH";
+ Text[ russian ] = "ACOSH";
+ Text[ polish ] = "ACOSH";
+ Text[ japanese ] = "ACOSH";
+ Text[ chinese_traditional ] = "ACOSH";
+ Text[ arabic ] = "ACOSH";
+ Text[ dutch ] = "BOOGCOSH";
+ Text[ chinese_simplified ] = "ACOSH";
+ Text[ greek ] = "ACOSH";
+ Text[ korean ] = "ACOSH";
+ Text[ turkish ] = "ACOSH";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ARC_TAN_HYP
+ {
+ Text = "ARCTANHYP" ;
+ Text [ english ] = "ATANH" ;
+ Text [ norwegian ] = "ATANH" ;
+ Text [ italian ] = "ARCTANH" ;
+ Text [ portuguese_brazilian ] = "ATANH" ;
+ Text [ portuguese ] = "ATANH" ;
+ Text [ finnish ] = "ATANH" ;
+ Text [ danish ] = "ARCTANH" ;
+ Text [ french ] = "ATANH" ;
+ Text [ swedish ] = "ARCTANH" ;
+ Text [ dutch ] = "BOOGTANH" ;
+ Text [ spanish ] = "ATANH" ;
+ Text [ english_us ] = "ATANH" ;
+ Text[ chinese_simplified ] = "ATANH";
+ Text[ russian ] = "ATANH";
+ Text[ polish ] = "ATANH";
+ Text[ japanese ] = "ATANH";
+ Text[ chinese_traditional ] = "ATANH";
+ Text[ arabic ] = "ATANH";
+ Text[ dutch ] = "BOOGTANH";
+ Text[ chinese_simplified ] = "ATANH";
+ Text[ greek ] = "ATANH";
+ Text[ korean ] = "ATANH";
+ Text[ turkish ] = "ATANH";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ARC_COT_HYP
+ {
+ Text = "ARCCOTHYP" ;
+ Text [ english ] = "ACOTH" ;
+ Text [ norwegian ] = "ACOTH" ;
+ Text [ italian ] = "ARCCOTH" ;
+ Text [ portuguese_brazilian ] = "ACOTH" ;
+ Text [ portuguese ] = "ATANH" ;
+ Text [ finnish ] = "ACOTH" ;
+ Text [ danish ] = "ARCCOTH" ;
+ Text [ french ] = "ACOTH" ;
+ Text [ swedish ] = "ARCCOTH" ;
+ Text [ dutch ] = "BOOGCOTH" ;
+ Text [ spanish ] = "ACOTH" ;
+ Text [ english_us ] = "ACOTH" ;
+ Text[ chinese_simplified ] = "ACOTH";
+ Text[ russian ] = "ACOTH";
+ Text[ polish ] = "ACOTH";
+ Text[ japanese ] = "ACOTH";
+ Text[ chinese_traditional ] = "ACOTH";
+ Text[ arabic ] = "ACOTH";
+ Text[ dutch ] = "BOOGCOTH";
+ Text[ chinese_simplified ] = "ACOTH";
+ Text[ greek ] = "ACOTH";
+ Text[ korean ] = "ACOTH";
+ Text[ turkish ] = "ACOTH";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_EXP { Text = "EXP" ; };
+ String SC_OPCODE_LN { Text = "LN" ; };
+ String SC_OPCODE_SQRT
+ {
+ Text = "WURZEL" ;
+ Text [ english ] = "SQRT" ;
+ Text [ norwegian ] = "SQRT" ;
+ Text [ italian ] = "RADQ" ;
+ Text [ portuguese_brazilian ] = "SQRT" ;
+ Text [ portuguese ] = "RAÍZ.Q" ;
+ Text [ finnish ] = "SQRT" ;
+ Text [ danish ] = "KVROD" ;
+ Text [ french ] = "RACINE" ;
+ Text [ swedish ] = "ROT" ;
+ Text [ dutch ] = "WORTEL" ;
+ Text [ spanish ] = "RAÍZ" ;
+ Text [ english_us ] = "SQRT" ;
+ Text[ chinese_simplified ] = "SQRT";
+ Text[ russian ] = "ÊÎÐÅÍÜ";
+ Text[ polish ] = "PIERWIASTEK";
+ Text[ japanese ] = "SQRT";
+ Text[ chinese_traditional ] = "SQRT";
+ Text[ arabic ] = "SQRT";
+ Text[ dutch ] = "WORTEL";
+ Text[ chinese_simplified ] = "SQRT";
+ Text[ greek ] = "SQRT";
+ Text[ korean ] = "SQRT";
+ Text[ turkish ] = "SQRT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_FACT
+ {
+ /* ### ACHTUNG: Neuer Text in Resource? FAKULTÄT : FAKULTŽT */
+ Text = "FAKULTÄT" ;
+ Text [ english ] = "FACT" ;
+ Text [ norwegian ] = "FACT" ;
+ Text [ italian ] = "FATTORIALE" ;
+ Text [ portuguese_brazilian ] = "FATORIAL" ;
+ Text [ portuguese ] = "FACT" ;
+ Text [ finnish ] = "FACT" ;
+ Text [ danish ] = "FAKULTET" ;
+ Text [ french ] = "FACT" ;
+ Text [ swedish ] = "FAKULTET" ;
+ Text [ dutch ] = "FACULTEIT" ;
+ Text [ spanish ] = "FACT" ;
+ Text [ english_us ] = "FACT" ;
+ Text[ chinese_simplified ] = "FACT";
+ Text[ russian ] = "ÔÀÊÒÐ";
+ Text[ polish ] = "SILNIA";
+ Text[ japanese ] = "FACT";
+ Text[ chinese_traditional ] = "FACT";
+ Text[ arabic ] = "FACT";
+ Text[ dutch ] = "FACULTEIT";
+ Text[ chinese_simplified ] = "FACT";
+ Text[ greek ] = "FACT";
+ Text[ korean ] = "FACT";
+ Text[ turkish ] = "FACT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GET_YEAR
+ {
+ Text = "JAHR" ;
+ Text [ english ] = "YEAR" ;
+ Text [ norwegian ] = "YEAR" ;
+ Text [ italian ] = "ANNO" ;
+ Text [ portuguese_brazilian ] = "YEAR" ;
+ Text [ portuguese ] = "ANO" ;
+ Text [ finnish ] = "YEAR" ;
+ Text [ danish ] = "ÅR" ;
+ Text [ french ] = "ANNEE" ;
+ Text [ swedish ] = "ÅR" ;
+ Text [ dutch ] = "JAAR" ;
+ Text [ spanish ] = "AÑO" ;
+ Text [ english_us ] = "YEAR" ;
+ Text[ chinese_simplified ] = "YEAR";
+ Text[ russian ] = "ÃÎÄ";
+ Text[ polish ] = "ROK";
+ Text[ japanese ] = "YEAR";
+ Text[ chinese_traditional ] = "YEAR";
+ Text[ arabic ] = "YEAR";
+ Text[ dutch ] = "JAAR";
+ Text[ chinese_simplified ] = "YEAR";
+ Text[ greek ] = "YEAR";
+ Text[ korean ] = "YEAR";
+ Text[ turkish ] = "YEAR";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GET_MONTH
+ {
+ Text = "MONAT" ;
+ Text [ english ] = "MONTH" ;
+ Text [ norwegian ] = "MONTH" ;
+ Text [ italian ] = "MESE" ;
+ Text [ portuguese_brazilian ] = "MONTH" ;
+ Text [ portuguese ] = "MÊS" ;
+ Text [ finnish ] = "MONTH" ;
+ Text [ danish ] = "MÅNED" ;
+ Text [ french ] = "MOIS" ;
+ Text [ swedish ] = "MÅNAD" ;
+ Text [ dutch ] = "MAAND" ;
+ Text [ spanish ] = "MES" ;
+ Text [ english_us ] = "MONTH" ;
+ Text[ chinese_simplified ] = "MONTH";
+ Text[ russian ] = "ÌÅÑßÖ";
+ Text[ polish ] = "MIESI¥C";
+ Text[ japanese ] = "MONTH";
+ Text[ chinese_traditional ] = "MONTH";
+ Text[ arabic ] = "MONTH";
+ Text[ dutch ] = "MAAND";
+ Text[ chinese_simplified ] = "MONTH";
+ Text[ greek ] = "MONTH";
+ Text[ korean ] = "MONTH";
+ Text[ turkish ] = "AY";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GET_DAY
+ {
+ Text = "TAG" ;
+ Text [ english ] = "DAY" ;
+ Text [ norwegian ] = "DAY" ;
+ Text [ italian ] = "GIORNO" ;
+ Text [ portuguese_brazilian ] = "DAY" ;
+ Text [ portuguese ] = "DIA" ;
+ Text [ finnish ] = "DAY" ;
+ Text [ danish ] = "DAG" ;
+ Text [ french ] = "JOUR" ;
+ Text [ swedish ] = "DAG" ;
+ Text [ dutch ] = "DAG" ;
+ Text [ spanish ] = "DÍA" ;
+ Text [ english_us ] = "DAY" ;
+ Text[ chinese_simplified ] = "DAY";
+ Text[ russian ] = "ÄÅÍÜ";
+ Text[ polish ] = "DZIEÑ";
+ Text[ japanese ] = "DAY";
+ Text[ chinese_traditional ] = "DAY";
+ Text[ arabic ] = "DAY";
+ Text[ dutch ] = "DAG";
+ Text[ chinese_simplified ] = "DAY";
+ Text[ greek ] = "DAY";
+ Text[ korean ] = "DAY";
+ Text[ turkish ] = "DAY";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GET_HOUR
+ {
+ Text = "STUNDE" ;
+ Text [ english ] = "HOUR" ;
+ Text [ norwegian ] = "TIME" ;
+ Text [ italian ] = "ORA" ;
+ Text [ portuguese_brazilian ] = "HORA" ;
+ Text [ portuguese ] = "HORA" ;
+ Text [ finnish ] = "HOUR" ;
+ Text [ danish ] = "TIME" ;
+ Text [ french ] = "HEURE" ;
+ Text [ swedish ] = "TIMME" ;
+ Text [ dutch ] = "UUR" ;
+ Text [ spanish ] = "HORA" ;
+ Text [ english_us ] = "HOUR" ;
+ Text[ chinese_simplified ] = "HOUR";
+ Text[ russian ] = "×ÀÑ";
+ Text[ polish ] = "GODZINA";
+ Text[ japanese ] = "HOUR";
+ Text[ chinese_traditional ] = "HOUR";
+ Text[ arabic ] = "HOUR";
+ Text[ dutch ] = "UUR";
+ Text[ chinese_simplified ] = "HOUR";
+ Text[ greek ] = "HOUR";
+ Text[ korean ] = "HOUR";
+ Text[ turkish ] = "HOUR";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GET_MIN
+ {
+ Text = "MINUTE" ;
+ Text [ english ] = "MINUTE" ;
+ Text [ norwegian ] = "MINUTT" ;
+ Text [ italian ] = "MINUTO" ;
+ Text [ portuguese_brazilian ] = "MINUTO" ;
+ Text [ portuguese ] = "MINUTO" ;
+ Text [ finnish ] = "MINUTE" ;
+ Text [ danish ] = "MINUT" ;
+ Text [ french ] = "MINUTE" ;
+ Text [ swedish ] = "MINUT" ;
+ Text [ dutch ] = "MINUUT" ;
+ Text [ spanish ] = "MINUTO" ;
+ Text [ english_us ] = "MINUTE" ;
+ Text[ chinese_simplified ] = "MINUTE";
+ Text[ russian ] = "ÌÈÍÓÒÛ";
+ Text[ polish ] = "MINUTA";
+ Text[ japanese ] = "MINUTE";
+ Text[ chinese_traditional ] = "MINUTE";
+ Text[ arabic ] = "MINUTE";
+ Text[ dutch ] = "MINUUT";
+ Text[ chinese_simplified ] = "MINUTE";
+ Text[ greek ] = "MINUTE";
+ Text[ korean ] = "MINUTE";
+ Text[ turkish ] = "MINUTE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GET_SEC
+ {
+ Text = "SEKUNDE" ;
+ Text [ english ] = "SECOND" ;
+ Text [ norwegian ] = "SEKUND" ;
+ Text [ italian ] = "SECONDO" ;
+ Text [ portuguese_brazilian ] = "SEGUNDO" ;
+ Text [ portuguese ] = "SEGUNDO" ;
+ Text [ finnish ] = "SECOND" ;
+ Text [ danish ] = "SEKUND" ;
+ Text [ french ] = "SECONDE" ;
+ Text [ swedish ] = "SEKUND" ;
+ Text [ dutch ] = "SECONDE" ;
+ Text [ spanish ] = "SEGUNDO" ;
+ Text [ english_us ] = "SECOND" ;
+ Text[ chinese_simplified ] = "SECOND";
+ Text[ russian ] = "ÑÅÊÓÍÄÛ";
+ Text[ polish ] = "SEKUNDA";
+ Text[ japanese ] = "SECOND";
+ Text[ chinese_traditional ] = "SECOND";
+ Text[ arabic ] = "SECOND";
+ Text[ dutch ] = "SECONDE";
+ Text[ chinese_simplified ] = "SECOND";
+ Text[ greek ] = "SECOND";
+ Text[ korean ] = "SECOND";
+ Text[ turkish ] = "SECOND";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_PLUS_MINUS
+ {
+ Text = "VORZEICHEN" ;
+ Text [ english ] = "SIGN" ;
+ Text [ norwegian ] = "SIGNATUR" ;
+ Text [ italian ] = "SEGNO" ;
+ Text [ portuguese_brazilian ] = "SIGN" ;
+ Text [ portuguese ] = "SINAL" ;
+ Text [ finnish ] = "SIGN" ;
+ Text [ danish ] = "FORTEGN" ;
+ Text [ french ] = "SIGNE" ;
+ Text [ swedish ] = "TECKEN" ;
+ Text [ dutch ] = "POS.NEG" ;
+ Text [ spanish ] = "SIGNO" ;
+ Text [ english_us ] = "SIGN" ;
+ Text[ chinese_simplified ] = "SIGN";
+ Text[ russian ] = "ÇÍÀÊ";
+ Text[ polish ] = "ZNAK.LICZBY";
+ Text[ japanese ] = "SIGN";
+ Text[ chinese_traditional ] = "SIGN";
+ Text[ arabic ] = "SIGN";
+ Text[ dutch ] = "POS.NEG";
+ Text[ chinese_simplified ] = "SIGN";
+ Text[ greek ] = "SIGN";
+ Text[ korean ] = "SIGN";
+ Text[ turkish ] = "SIGN";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ABS
+ {
+ Text = "ABS" ;
+ Text [ english ] = "ABS" ;
+ Text [ norwegian ] = "ABS" ;
+ Text [ italian ] = "ASS" ;
+ Text [ portuguese_brazilian ] = "ABS" ;
+ Text [ portuguese ] = "ABS" ;
+ Text [ finnish ] = "ABS" ;
+ Text [ danish ] = "ABS" ;
+ Text [ french ] = "ABS" ;
+ Text [ swedish ] = "ABS" ;
+ Text [ dutch ] = "ABS" ;
+ Text [ spanish ] = "ABS" ;
+ Text [ english_us ] = "ABS" ;
+ Text[ chinese_simplified ] = "ABS";
+ Text[ russian ] = "ABS";
+ Text[ polish ] = "ABS";
+ Text[ japanese ] = "ABS";
+ Text[ chinese_traditional ] = "ABS";
+ Text[ arabic ] = "ABS";
+ Text[ dutch ] = "ABS";
+ Text[ chinese_simplified ] = "ABS";
+ Text[ greek ] = "ABS";
+ Text[ korean ] = "ABS";
+ Text[ turkish ] = "ABS";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_INT
+ {
+ Text = "GANZZAHL" ;
+ Text [ english ] = "INT" ;
+ Text [ norwegian ] = "INT" ;
+ Text [ italian ] = "INT" ;
+ Text [ portuguese_brazilian ] = "INT" ;
+ Text [ portuguese ] = "NÚM.INT" ;
+ Text [ finnish ] = "INT" ;
+ Text [ danish ] = "HELTAL" ;
+ Text [ french ] = "ENT" ;
+ Text [ swedish ] = "HELTAL" ;
+ Text [ dutch ] = "INTEGERSNIJPUNT" ;
+ Text [ spanish ] = "ENTERO" ;
+ Text [ english_us ] = "INT" ;
+ Text[ chinese_simplified ] = "INT";
+ Text[ russian ] = "ÖÅËÎÅ";
+ Text[ polish ] = "ZAOKR.DO.CA£K";
+ Text[ japanese ] = "INT";
+ Text[ chinese_traditional ] = "INT";
+ Text[ arabic ] = "INT";
+ Text[ dutch ] = "INTEGERSNIJPUNT";
+ Text[ chinese_simplified ] = "INT";
+ Text[ greek ] = "INT";
+ Text[ korean ] = "INT";
+ Text[ turkish ] = "INT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_PHI { Text = "PHI" ; };
+ String SC_OPCODE_GAUSS { Text = "GAUSS" ; };
+ String SC_OPCODE_IS_EMPTY
+ {
+ Text = "ISTLEER" ;
+ Text [ english ] = "ISBLANK" ;
+ Text [ norwegian ] = "ERBLANK" ;
+ Text [ italian ] = "VAL.VUOTO" ;
+ Text [ portuguese_brazilian ] = "ISVAZIO" ;
+ Text [ portuguese ] = "É.CÉL.VAZIA" ;
+ Text [ finnish ] = "ISBLANK" ;
+ Text [ danish ] = "ER.TOM" ;
+ Text [ french ] = "ESTVIDE" ;
+ Text [ swedish ] = "ÄRTOM" ;
+ Text [ dutch ] = "ISLEEG" ;
+ Text [ spanish ] = "ESBLANCO" ;
+ Text [ english_us ] = "ISBLANK" ;
+ Text[ chinese_simplified ] = "ISBLANK";
+ Text[ russian ] = "ÅÏÓÑÒÎ";
+ Text[ polish ] = "JESTPUSTY";
+ Text[ japanese ] = "ISBLANK";
+ Text[ chinese_traditional ] = "ISBLANK";
+ Text[ arabic ] = "ISBLANK";
+ Text[ dutch ] = "ISLEEG";
+ Text[ chinese_simplified ] = "ISBLANK";
+ Text[ greek ] = "ISBLANK";
+ Text[ korean ] = "ISBLANK";
+ Text[ turkish ] = "ISTBLANK";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_IS_STRING
+ {
+ Text = "ISTTEXT" ;
+ Text [ english ] = "ISTEXT" ;
+ Text [ norwegian ] = "ERTEKST" ;
+ Text [ italian ] = "VAL.TESTO" ;
+ Text [ portuguese_brazilian ] = "ISTEXTO" ;
+ Text [ portuguese ] = "É.TEXTO" ;
+ Text [ finnish ] = "ISTEXT" ;
+ Text [ danish ] = "ER.TEKST" ;
+ Text [ french ] = "ESTTEXTE" ;
+ Text [ swedish ] = "ÄRTEXT" ;
+ Text [ dutch ] = "ISTEKST" ;
+ Text [ spanish ] = "ESTEXTO" ;
+ Text [ english_us ] = "ISTEXT" ;
+ Text[ chinese_simplified ] = "ISTEXT";
+ Text[ russian ] = "ÅÒÅÊÑÒ";
+ Text[ polish ] = "CZY.TEKST";
+ Text[ japanese ] = "ISTEXT";
+ Text[ chinese_traditional ] = "ISTEXT";
+ Text[ arabic ] = "ISTEXT";
+ Text[ dutch ] = "ISTEKST";
+ Text[ chinese_simplified ] = "ISTEXT";
+ Text[ greek ] = "ISTEXT";
+ Text[ korean ] = "ISTEXT";
+ Text[ turkish ] = "ISTEXT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_IS_NON_STRING
+ {
+ Text = "ISTKTEXT" ;
+ Text [ english ] = "ISNONTEXT" ;
+ Text [ norwegian ] = "ERIKKETEKST" ;
+ Text [ italian ] = "VAL.NON.TESTO" ;
+ Text [ portuguese_brazilian ] = "ISNAOTEXTO" ;
+ Text [ portuguese ] = "É.NÃO.TEXTO" ;
+ Text [ finnish ] = "ISNONTEXT" ;
+ Text [ danish ] = "ER.IKKE.TEKST" ;
+ Text [ french ] = "ESTNONTEXTE" ;
+ Text [ swedish ] = "ÄREJTEXT" ;
+ Text [ dutch ] = "ISGEENTEKST" ;
+ Text [ spanish ] = "ESNOTEXTO" ;
+ Text [ english_us ] = "ISNONTEXT" ;
+ Text[ chinese_simplified ] = "ISNONTEXT";
+ Text[ russian ] = "ÅÍÅÒÅÊÑÒ";
+ Text[ polish ] = "CZY.NIE.TEKST";
+ Text[ japanese ] = "ISNONTEXT";
+ Text[ chinese_traditional ] = "ISNONTEXT";
+ Text[ arabic ] = "ISNONTEXT";
+ Text[ dutch ] = "ISGEENTEKST";
+ Text[ chinese_simplified ] = "ISNONTEXT";
+ Text[ greek ] = "ISNONTEXT";
+ Text[ korean ] = "ISNONTEXT";
+ Text[ turkish ] = "ISNONTEXT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_IS_LOGICAL
+ {
+ Text = "ISTLOG" ;
+ Text [ english ] = "ISLOGICAL" ;
+ Text [ norwegian ] = "ERLOGISK" ;
+ Text [ italian ] = "VAL.LOGICO" ;
+ Text [ portuguese_brazilian ] = "ISLOGICO" ;
+ Text [ portuguese ] = "É.LÓGICO" ;
+ Text [ finnish ] = "ISLOGICAL" ;
+ Text [ danish ] = "ER.LOGISK" ;
+ Text [ french ] = "ESTLOGIQUE" ;
+ Text [ swedish ] = "ÄRLOGISK" ;
+ Text [ dutch ] = "ISLOGISCH" ;
+ Text [ spanish ] = "ESLOGICO" ;
+ Text [ english_us ] = "ISLOGICAL" ;
+ Text[ chinese_simplified ] = "ISLOGICAL";
+ Text[ russian ] = "ÅËÎÃÈ×";
+ Text[ polish ] = "CZY.LOGICZNA";
+ Text[ japanese ] = "ISLOGICAL";
+ Text[ chinese_traditional ] = "ISLOGICAL";
+ Text[ arabic ] = "ISLOGICAL";
+ Text[ dutch ] = "ISLOGISCH";
+ Text[ chinese_simplified ] = "ISLOGICAL";
+ Text[ greek ] = "ISLOGICAL";
+ Text[ korean ] = "ISLOGICAL";
+ Text[ turkish ] = "ISTLOGICAL";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_TYPE
+ {
+ Text = "TYP" ;
+ Text [ english ] = "TYPE" ;
+ Text [ norwegian ] = "TYPE" ;
+ Text [ italian ] = "TIPO" ;
+ Text [ portuguese_brazilian ] = "TIPO" ;
+ Text [ portuguese ] = "TIPO" ;
+ Text [ finnish ] = "TYPE" ;
+ Text [ danish ] = "VÆRDITYPE" ;
+ Text [ french ] = "TYPE" ;
+ Text [ swedish ] = "VÄRDETYP" ;
+ Text [ dutch ] = "TYPE" ;
+ Text [ spanish ] = "TIPO" ;
+ Text [ english_us ] = "TYPE" ;
+ Text[ chinese_simplified ] = "TYPE";
+ Text[ russian ] = "ÒÈÏ";
+ Text[ polish ] = "TYP";
+ Text[ japanese ] = "TYPE";
+ Text[ chinese_traditional ] = "TYPE";
+ Text[ arabic ] = "TYPE";
+ Text[ dutch ] = "TYPE";
+ Text[ chinese_simplified ] = "TYPE";
+ Text[ greek ] = "TYPE";
+ Text[ korean ] = "TYPE";
+ Text[ turkish ] = "TYPE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_IS_REF
+ {
+ Text = "ISTBEZUG" ;
+ Text [ english ] = "ISREF" ;
+ Text [ norwegian ] = "ERREF" ;
+ Text [ italian ] = "VAL.RIF" ;
+ Text [ portuguese_brazilian ] = "ISREF" ;
+ Text [ portuguese ] = "É.REF" ;
+ Text [ finnish ] = "ISREF" ;
+ Text [ danish ] = "ER.REFERENCE" ;
+ Text [ french ] = "ESTREF" ;
+ Text [ swedish ] = "ÄRREF" ;
+ Text [ dutch ] = "ISVERWIJZING" ;
+ Text [ spanish ] = "ESREF" ;
+ Text [ english_us ] = "ISREF" ;
+ Text[ chinese_simplified ] = "ISREF";
+ Text[ russian ] = "ÅÑÑÛËÊÀ";
+ Text[ polish ] = "CZY.ADR";
+ Text[ japanese ] = "ISREF";
+ Text[ chinese_traditional ] = "ISREF";
+ Text[ arabic ] = "ISREF";
+ Text[ dutch ] = "ISVERWIJZING";
+ Text[ chinese_simplified ] = "ISREF";
+ Text[ greek ] = "ISREF";
+ Text[ korean ] = "ISREF";
+ Text[ turkish ] = "ISREF";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_IS_VALUE
+ {
+ Text = "ISTZAHL" ;
+ Text [ english ] = "ISNUMBER" ;
+ Text [ norwegian ] = "ERNUMMER" ;
+ Text [ italian ] = "VAL.NUMERO" ;
+ Text [ portuguese_brazilian ] = "ISNUMERO" ;
+ Text [ portuguese ] = "É.NÚMERO" ;
+ Text [ finnish ] = "ISNUMBER" ;
+ Text [ danish ] = "ER.TAL" ;
+ Text [ french ] = "ESTNUM" ;
+ Text [ swedish ] = "ÄRTAL" ;
+ Text [ dutch ] = "ISGETAL" ;
+ Text [ spanish ] = "ESNÚMERO" ;
+ Text [ english_us ] = "ISNUMBER" ;
+ Text[ chinese_simplified ] = "ISNUMBER";
+ Text[ russian ] = "Å×ÈÑËÎ";
+ Text[ polish ] = "CZY.LICZBA";
+ Text[ japanese ] = "ISNUMBER";
+ Text[ chinese_traditional ] = "ISNUMBER";
+ Text[ arabic ] = "ISNUMBER";
+ Text[ dutch ] = "ISGETAL";
+ Text[ chinese_simplified ] = "ISNUMBER";
+ Text[ greek ] = "ISNUMBER";
+ Text[ korean ] = "ISNUMBER";
+ Text[ turkish ] = "ISNUMBER";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_IS_FORMULA
+ {
+ Text = "ISTFORMEL" ;
+ Text [ english ] = "ISFORMULA" ;
+ Text [ norwegian ] = "ERFORMEL" ;
+ Text [ italian ] = "VAL.FORMULA" ;
+ Text [ portuguese_brazilian ] = "ISFORMULA" ;
+ Text [ portuguese ] = "É.FÓRMULA" ;
+ Text [ finnish ] = "ISFORMULA" ;
+ Text [ danish ] = "ER.FORMEL" ;
+ Text [ french ] = "ESTFORMULE" ;
+ Text [ swedish ] = "ÄRFORMEL" ;
+ Text [ dutch ] = "ISFORMULE" ;
+ Text [ spanish ] = "ESFÓRMULA" ;
+ Text [ english_us ] = "ISFORMULA" ;
+ Text[ chinese_simplified ] = "ISFORMULA";
+ Text[ russian ] = "ÅÔÎÐÌÓËÀ";
+ Text[ polish ] = "JESTFORMU£¥";
+ Text[ japanese ] = "ISFORMULA";
+ Text[ chinese_traditional ] = "ISFORMULA";
+ Text[ arabic ] = "ISFORMULA";
+ Text[ dutch ] = "ISFORMULE";
+ Text[ chinese_simplified ] = "ISFORMULA";
+ Text[ greek ] = "ISFORMULA";
+ Text[ korean ] = "ISFORMULA";
+ Text[ turkish ] = "ISTFORMULA";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_IS_NV
+ {
+ Text = "ISTNV" ;
+ Text [ english ] = "ISNA" ;
+ Text [ norwegian ] = "ERIT" ;
+ Text [ italian ] = "VAL.NON.DISP" ;
+ Text [ portuguese_brazilian ] = "ISNA" ;
+ Text [ portuguese ] = "É.NÃO.DISP" ;
+ Text [ finnish ] = "ISNA" ;
+ Text [ danish ] = "ER.IKKE.TILGÆNGELIG" ;
+ Text [ french ] = "ESTNA" ;
+ Text [ swedish ] = "ÄRSAKNAD" ;
+ Text [ dutch ] = "ISNB" ;
+ Text [ spanish ] = "ESNOD" ;
+ Text [ english_us ] = "ISNA" ;
+ Text[ chinese_simplified ] = "ISNA";
+ Text[ russian ] = "ÅÍÄ";
+ Text[ polish ] = "CZY.BRAK";
+ Text[ japanese ] = "ISNA";
+ Text[ chinese_traditional ] = "ISNA";
+ Text[ arabic ] = "ISNA";
+ Text[ dutch ] = "ISNB";
+ Text[ chinese_simplified ] = "ISNA";
+ Text[ greek ] = "ISNA";
+ Text[ korean ] = "ISNA";
+ Text[ turkish ] = "ISNA";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_IS_ERR
+ {
+ Text = "ISTFEHL" ;
+ Text [ english ] = "ISERR" ;
+ Text [ norwegian ] = "ERFEIL" ;
+ Text [ italian ] = "VAL.ERR" ;
+ Text [ portuguese_brazilian ] = "ISERR" ;
+ Text [ portuguese ] = "É.ERRO" ;
+ Text [ finnish ] = "ISERR" ;
+ Text [ danish ] = "ER.FJL" ;
+ Text [ french ] = "ESTERR" ;
+ Text [ swedish ] = "ÄRF" ;
+ Text [ dutch ] = "ISERR" ;
+ Text [ spanish ] = "ESERR" ;
+ Text [ english_us ] = "ISERR" ;
+ Text[ chinese_simplified ] = "ISERR";
+ Text[ russian ] = "ÅÎØ";
+ Text[ polish ] = "CZY.B£";
+ Text[ japanese ] = "ISERR";
+ Text[ chinese_traditional ] = "ISERR";
+ Text[ arabic ] = "ISERR";
+ Text[ dutch ] = "ISERR";
+ Text[ chinese_simplified ] = "ISERR";
+ Text[ greek ] = "ISERR";
+ Text[ korean ] = "ISERR";
+ Text[ turkish ] = "ISTERR";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_IS_ERROR
+ {
+ Text = "ISTFEHLER" ;
+ Text [ english ] = "ISERROR" ;
+ Text [ norwegian ] = "ERFEIL" ;
+ Text [ italian ] = "VAL.ERRORE" ;
+ Text [ portuguese_brazilian ] = "ISERRO" ;
+ Text [ portuguese ] = "É.ERROS" ;
+ Text [ finnish ] = "ISERROR" ;
+ Text [ danish ] = "ER.FEJL" ;
+ Text [ french ] = "ESTERREUR" ;
+ Text [ swedish ] = "ÄRFEL" ;
+ Text [ dutch ] = "ISFOUT" ;
+ Text [ spanish ] = "ESERROR" ;
+ Text [ english_us ] = "ISERROR" ;
+ Text[ chinese_simplified ] = "ISERROR";
+ Text[ russian ] = "ÅÎØÈÁÊÀ";
+ Text[ polish ] = "CZY.B£¥D";
+ Text[ japanese ] = "ISERROR";
+ Text[ chinese_traditional ] = "ISERROR";
+ Text[ arabic ] = "ISERROR";
+ Text[ dutch ] = "ISFOUT";
+ Text[ chinese_simplified ] = "ISERROR";
+ Text[ greek ] = "ISERROR";
+ Text[ korean ] = "ISERROR";
+ Text[ turkish ] = "ISTERROR";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_IS_EVEN
+ {
+ Text = "ISTGERADE" ;
+ Text [ english ] = "ISEVEN" ;
+ Text [ norwegian ] = "ERPAR" ;
+ Text [ italian ] = "VAL.PARI" ;
+ Text [ portuguese_brazilian ] = "ISPAR" ;
+ Text [ portuguese ] = "É.PAR" ;
+ Text [ finnish ] = "ISEVEN" ;
+ Text [ danish ] = "ER.LIGE" ;
+ Text [ french ] = "ESTPAIR" ;
+ Text [ swedish ] = "ÄRJÄMN" ;
+ Text [ dutch ] = "ISEVEN" ;
+ Text [ spanish ] = "ESPAR" ;
+ Text [ english_us ] = "ISEVEN" ;
+ Text[ chinese_simplified ] = "ISEVEN";
+ Text[ russian ] = "Å×ÅÒÍ";
+ Text[ polish ] = "ZAOKR.DO PARZ";
+ Text[ japanese ] = "ISEVEN";
+ Text[ chinese_traditional ] = "ISEVEN";
+ Text[ arabic ] = "ISEVEN";
+ Text[ dutch ] = "ISEVEN";
+ Text[ chinese_simplified ] = "ISEVEN";
+ Text[ greek ] = "ISEVEN";
+ Text[ korean ] = "ISEVEN";
+ Text[ turkish ] = "ISTEVEN";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_IS_ODD
+ {
+ Text = "ISTUNGERADE" ;
+ Text [ english ] = "ISODD" ;
+ Text [ norwegian ] = "ERODDE" ;
+ Text [ italian ] = "VAL.DISPARI" ;
+ Text [ portuguese_brazilian ] = "ISIMPAR" ;
+ Text [ portuguese ] = "É.ÍMPAR" ;
+ Text [ finnish ] = "ISODD" ;
+ Text [ danish ] = "ER.ULIGE" ;
+ Text [ french ] = "ESTIMPAIR" ;
+ Text [ swedish ] = "ÄRUDDA" ;
+ Text [ dutch ] = "ISONEVEN" ;
+ Text [ spanish ] = "ESIMPAR" ;
+ Text [ english_us ] = "ISODD" ;
+ Text[ chinese_simplified ] = "ISODD";
+ Text[ russian ] = "ÅÍÅ×ÅÒÍ";
+ Text[ polish ] = "JESTNIEPARZYSTY";
+ Text[ japanese ] = "ISODD";
+ Text[ chinese_traditional ] = "ISODD";
+ Text[ arabic ] = "ISODD";
+ Text[ dutch ] = "ISONEVEN";
+ Text[ chinese_simplified ] = "ISODD";
+ Text[ greek ] = "ISODD";
+ Text[ korean ] = "ISODD";
+ Text[ turkish ] = "ISODD";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_N
+ {
+ Text = "N" ;
+ Text [ english ] = "N" ;
+ Text [ norwegian ] = "N" ;
+ Text [ italian ] = "NUM" ;
+ Text [ portuguese_brazilian ] = "N" ;
+ Text [ portuguese ] = "N" ;
+ Text [ finnish ] = "N" ;
+ Text [ danish ] = "N" ;
+ Text [ french ] = "N" ;
+ Text [ swedish ] = "N" ;
+ Text [ dutch ] = "N" ;
+ Text [ spanish ] = "N" ;
+ Text [ english_us ] = "N" ;
+ Text[ chinese_simplified ] = "N";
+ Text[ russian ] = "×";
+ Text[ polish ] = "N";
+ Text[ japanese ] = "N";
+ Text[ chinese_traditional ] = "N";
+ Text[ arabic ] = "N";
+ Text[ dutch ] = "N";
+ Text[ chinese_simplified ] = "N";
+ Text[ greek ] = "N";
+ Text[ korean ] = "N";
+ Text[ turkish ] = "N";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GET_DATE_VALUE
+ {
+ Text = "DATWERT" ;
+ Text [ english ] = "DATEVALUE" ;
+ Text [ norwegian ] = "DATOVERDI" ;
+ Text [ italian ] = "DATA.VALORE" ;
+ Text [ portuguese_brazilian ] = "DATA.VALOR" ;
+ Text [ portuguese ] = "DATA.VALOR" ;
+ Text [ finnish ] = "DATEVALUE" ;
+ Text [ danish ] = "DATOVÆRDI" ;
+ Text [ french ] = "DATEVAL" ;
+ Text [ swedish ] = "DATUMVÄRDE" ;
+ Text [ dutch ] = "DATUMWAARDE" ;
+ Text [ spanish ] = "FECHANÚMERO" ;
+ Text [ english_us ] = "DATEVALUE" ;
+ Text[ chinese_simplified ] = "DATEVALUE";
+ Text[ russian ] = "ÄÀÒÀÇÍÀ×";
+ Text[ polish ] = "DATA.WARTOή";
+ Text[ japanese ] = "DATEVALUE";
+ Text[ chinese_traditional ] = "DATEVALUE";
+ Text[ arabic ] = "DATEVALUE";
+ Text[ dutch ] = "DATUMWAARDE";
+ Text[ chinese_simplified ] = "DATEVALUE";
+ Text[ greek ] = "DATEVALUE";
+ Text[ korean ] = "DATEVALUE";
+ Text[ turkish ] = "DATEVALUE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GET_TIME_VALUE
+ {
+ Text = "ZEITWERT" ;
+ Text [ english ] = "TIMEVALUE" ;
+ Text [ norwegian ] = "TIDSVERDI" ;
+ Text [ italian ] = "ORARIO.VALORE" ;
+ Text [ portuguese_brazilian ] = "VALOR.TEMPO" ;
+ Text [ portuguese ] = "VALOR.TEMPO" ;
+ Text [ finnish ] = "TIMEVALUE" ;
+ Text [ danish ] = "TIDSVÆRDI" ;
+ Text [ french ] = "TEMPSVAL" ;
+ Text [ swedish ] = "TIDVÄRDE" ;
+ Text [ dutch ] = "TIJDWAARDE" ;
+ Text [ spanish ] = "HORANÚMERO" ;
+ Text [ english_us ] = "TIMEVALUE" ;
+ Text[ chinese_simplified ] = "TIMEVALUE";
+ Text[ russian ] = "ÂÐÅÌßÇÍÀ×";
+ Text[ polish ] = "CZAS.WARTOή";
+ Text[ japanese ] = "TIMEVALUE";
+ Text[ chinese_traditional ] = "TIMEVALUE";
+ Text[ arabic ] = "TIMEVALUE";
+ Text[ dutch ] = "TIJDWAARDE";
+ Text[ chinese_simplified ] = "TIMEVALUE";
+ Text[ greek ] = "TIMEVALUE";
+ Text[ korean ] = "TIMEVALUE";
+ Text[ turkish ] = "TIMEVALUE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_CODE
+ {
+ Text = "CODE" ;
+ Text [ english ] = "CODE" ;
+ Text [ norwegian ] = "KODE" ;
+ Text [ italian ] = "CODICE" ;
+ Text [ portuguese_brazilian ] = "CODIGO" ;
+ Text [ portuguese ] = "CÓDIGO" ;
+ Text [ finnish ] = "CODE" ;
+ Text [ danish ] = "KODE" ;
+ Text [ french ] = "CODE" ;
+ Text [ swedish ] = "KOD" ;
+ Text [ dutch ] = "CODE" ;
+ Text [ spanish ] = "CÓDIGO" ;
+ Text [ english_us ] = "CODE" ;
+ Text[ chinese_simplified ] = "CODE";
+ Text[ russian ] = "ÊÎÄÑÈÌÂ";
+ Text[ polish ] = "KOD";
+ Text[ japanese ] = "CODE";
+ Text[ chinese_traditional ] = "CODE";
+ Text[ arabic ] = "CODE";
+ Text[ dutch ] = "CODE";
+ Text[ chinese_simplified ] = "CODE";
+ Text[ greek ] = "CODE";
+ Text[ korean ] = "CODE";
+ Text[ turkish ] = "CODE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_TRIM
+ {
+ /* ### ACHTUNG: Neuer Text in Resource? GLÄTTEN : GLŽTTEN */
+ Text = "GLÄTTEN" ;
+ Text [ english ] = "TRIM" ;
+ Text [ norwegian ] = "TRIM" ;
+ Text [ italian ] = "ANNULLA.SPAZI" ;
+ Text [ portuguese_brazilian ] = "ARRUMAR" ;
+ Text [ portuguese ] = "COMPACTAR" ;
+ Text [ finnish ] = "TRIM" ;
+ Text [ danish ] = "TRIM" ;
+ Text [ french ] = "SUPPRESPACE" ;
+ Text [ swedish ] = "RENSA" ;
+ Text [ dutch ] = "SPATIES.WISSEN" ;
+ Text [ spanish ] = "COMPACTAR" ;
+ Text [ english_us ] = "TRIM" ;
+ Text[ chinese_simplified ] = "TRIM";
+ Text[ russian ] = "ÑÆÏÐÎÁÅËÛ";
+ Text[ polish ] = "USUÑ.ZBÊDNE.ODSTÊPY";
+ Text[ japanese ] = "TRIM";
+ Text[ chinese_traditional ] = "TRIM";
+ Text[ arabic ] = "TRIM";
+ Text[ dutch ] = "SPATIES.WISSEN";
+ Text[ chinese_simplified ] = "TRIM";
+ Text[ greek ] = "TRIM";
+ Text[ korean ] = "TRIM";
+ Text[ turkish ] = "TRIM";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_UPPER
+ {
+ Text = "GROSS" ;
+ Text [ english ] = "UPPER" ;
+ Text [ norwegian ] = "STORE" ;
+ Text [ italian ] = "MAIUSC" ;
+ Text [ portuguese_brazilian ] = "MAIUSCULA" ;
+ Text [ portuguese ] = "MAIÚSCULA" ;
+ Text [ finnish ] = "UPPER" ;
+ Text [ danish ] = "STORE.BOGSTAVER" ;
+ Text [ french ] = "MAJUSCULE" ;
+ Text [ swedish ] = "VERSALER" ;
+ Text [ dutch ] = "HOOFDLETTERS" ;
+ Text [ spanish ] = "MAYÚSC" ;
+ Text [ english_us ] = "UPPER" ;
+ Text[ chinese_simplified ] = "UPPER";
+ Text[ russian ] = "ÏÐÎÏÈÑÍ";
+ Text[ polish ] = "LITERY.WIELKIE";
+ Text[ japanese ] = "UPPER";
+ Text[ chinese_traditional ] = "UPPER";
+ Text[ arabic ] = "UPPER";
+ Text[ dutch ] = "HOOFDLETTERS";
+ Text[ chinese_simplified ] = "UPPER";
+ Text[ greek ] = "UPPER";
+ Text[ korean ] = "UPPER";
+ Text[ turkish ] = "UPPER";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_PROPPER
+ {
+ Text = "GROSS2" ;
+ Text [ english ] = "PROPER" ;
+ Text [ norwegian ] = "PROPER" ;
+ Text [ italian ] = "MAIUSC.INIZ" ;
+ Text [ portuguese_brazilian ] = "PRIMAIUSCULA" ;
+ Text [ portuguese ] = "INICIAL.MAIÚSCULA" ;
+ Text [ finnish ] = "PROPER" ;
+ Text [ danish ] = "STORT.FORBOGSTAV" ;
+ Text [ french ] = "NOMPROPRE" ;
+ Text [ swedish ] = "INITIAL" ;
+ Text [ dutch ] = "BEGINLETTERS" ;
+ Text [ spanish ] = "NOMPROPIO" ;
+ Text [ english_us ] = "PROPER" ;
+ Text[ chinese_simplified ] = "PROPER";
+ Text[ russian ] = "ÏÐÎÏÍÀ×";
+ Text[ polish ] = "Z.WIELKIEJ.LITERY";
+ Text[ japanese ] = "PROPER";
+ Text[ chinese_traditional ] = "PROPER";
+ Text[ arabic ] = "PROPER";
+ Text[ dutch ] = "BEGINLETTERS";
+ Text[ chinese_simplified ] = "PROPER";
+ Text[ greek ] = "PROPER";
+ Text[ korean ] = "PROPER";
+ Text[ turkish ] = "PROPER";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_LOWER
+ {
+ Text = "KLEIN" ;
+ Text [ english ] = "LOWER" ;
+ Text [ norwegian ] = "SMÅ" ;
+ Text [ italian ] = "MINUSC" ;
+ Text [ portuguese_brazilian ] = "MINUSCULA" ;
+ Text [ portuguese ] = "MINÚSCULA" ;
+ Text [ finnish ] = "LOWER" ;
+ Text [ danish ] = "SMÅ.BOGSTAVER" ;
+ Text [ french ] = "MINUSCULE" ;
+ Text [ swedish ] = "GEMENER" ;
+ Text [ dutch ] = "KLEINE.LETTERS" ;
+ Text [ spanish ] = "MINUSC" ;
+ Text [ english_us ] = "LOWER" ;
+ Text[ chinese_simplified ] = "LOWER";
+ Text[ russian ] = "ÑÒÐÎ×Í";
+ Text[ polish ] = "MA£Y";
+ Text[ japanese ] = "LOWER";
+ Text[ chinese_traditional ] = "LOWER";
+ Text[ arabic ] = "LOWER";
+ Text[ dutch ] = "KLEINE.LETTERS";
+ Text[ chinese_simplified ] = "LOWER";
+ Text[ greek ] = "LOWER";
+ Text[ korean ] = "LOWER";
+ Text[ turkish ] = "LOWER";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_LEN
+ {
+ /* ### ACHTUNG: Neuer Text in Resource? LÄNGE : LŽNGE */
+ Text = "LÄNGE" ;
+ Text [ english ] = "LEN" ;
+ Text [ norwegian ] = "LEN" ;
+ Text [ italian ] = "LUNGHEZZA" ;
+ Text [ portuguese_brazilian ] = "NUM.CARACT" ;
+ Text [ portuguese ] = "NÚM.CARACT" ;
+ Text [ finnish ] = "LEN" ;
+ Text [ danish ] = "LÆNGDE" ;
+ Text [ french ] = "NBCAR" ;
+ Text [ swedish ] = "LÄNGD" ;
+ Text [ dutch ] = "LENGTE" ;
+ Text [ spanish ] = "LARGO" ;
+ Text [ english_us ] = "LEN" ;
+ Text[ chinese_simplified ] = "LEG";
+ Text[ russian ] = "ÄËÑÒÐ";
+ Text[ polish ] = "D£UGOŒÆ";
+ Text[ japanese ] = "LEN";
+ Text[ chinese_traditional ] = "LEG";
+ Text[ arabic ] = "LEN";
+ Text[ dutch ] = "LENGTE";
+ Text[ chinese_simplified ] = "LEG";
+ Text[ greek ] = "LEN";
+ Text[ korean ] = "LEN";
+ Text[ turkish ] = "LEN";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_T { Text = "T" ; };
+ String SC_OPCODE_VALUE
+ {
+ Text = "WERT" ;
+ Text [ english ] = "VALUE" ;
+ Text [ norwegian ] = "VERDI" ;
+ Text [ italian ] = "VALORE" ;
+ Text [ portuguese_brazilian ] = "VALOR" ;
+ Text [ portuguese ] = "VALOR" ;
+ Text [ finnish ] = "VALUE" ;
+ Text [ danish ] = "VÆRDI" ;
+ Text [ french ] = "CNUM" ;
+ Text [ swedish ] = "TEXTNUM" ;
+ Text [ dutch ] = "WAARDE" ;
+ Text [ spanish ] = "VALOR" ;
+ Text [ english_us ] = "VALUE" ;
+ Text[ chinese_simplified ] = "VALUE";
+ Text[ russian ] = "ÇÍÀ×ÅÍ";
+ Text[ polish ] = "WARTOή";
+ Text[ japanese ] = "VALUE";
+ Text[ chinese_traditional ] = "VALUE";
+ Text[ arabic ] = "VALUE";
+ Text[ dutch ] = "WAARDE";
+ Text[ chinese_simplified ] = "VALUE";
+ Text[ greek ] = "VALUE";
+ Text[ korean ] = "VALUE";
+ Text[ turkish ] = "VALUE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_CLEAN
+ {
+ /* ### ACHTUNG: Neuer Text in Resource? SÄUBERN : SŽUBERN */
+ Text = "SÄUBERN" ;
+ Text [ english ] = "CLEAN" ;
+ Text [ norwegian ] = "CLEAN" ;
+ Text [ italian ] = "LIBERA" ;
+ Text [ portuguese_brazilian ] = "TIRAR" ;
+ Text [ portuguese ] = "LIMPAR" ;
+ Text [ finnish ] = "CLEAN" ;
+ Text [ danish ] = "RENS" ;
+ Text [ french ] = "EPURAGE" ;
+ Text [ swedish ] = "STÄDA" ;
+ Text [ dutch ] = "WISSEN.CONTROL" ;
+ Text [ spanish ] = "LIMPIAR" ;
+ Text [ english_us ] = "CLEAN" ;
+ Text[ chinese_simplified ] = "CLEAN";
+ Text[ russian ] = "ÏÅ×ÑÈÌÂ";
+ Text[ polish ] = "WYCZYή";
+ Text[ japanese ] = "CLEAN";
+ Text[ chinese_traditional ] = "CLEAN";
+ Text[ arabic ] = "CLEAN";
+ Text[ dutch ] = "WISSEN.CONTROL";
+ Text[ chinese_simplified ] = "CLEAN";
+ Text[ greek ] = "CLEAN";
+ Text[ korean ] = "CLEAN";
+ Text[ turkish ] = "CLEAN";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_CHAR
+ {
+ Text = "ZEICHEN" ;
+ Text [ english ] = "CHAR" ;
+ Text [ norwegian ] = "TEGN" ;
+ Text [ italian ] = "CODICE.CARATT" ;
+ Text [ portuguese_brazilian ] = "CARACT" ;
+ Text [ portuguese ] = "CARACT" ;
+ Text [ finnish ] = "CHAR" ;
+ Text [ danish ] = "TEGN" ;
+ Text [ french ] = "CAR" ;
+ Text [ swedish ] = "TECKENKOD" ;
+ Text [ dutch ] = "TEKEN" ;
+ Text [ spanish ] = "CARÁCTER" ;
+ Text [ english_us ] = "CHAR" ;
+ Text[ chinese_simplified ] = "CHAR";
+ Text[ russian ] = "ÑÈÌÂÎË";
+ Text[ polish ] = "ZNAK";
+ Text[ japanese ] = "CHAR";
+ Text[ chinese_traditional ] = "CHAR";
+ Text[ arabic ] = "CHAR";
+ Text[ dutch ] = "TEKEN";
+ Text[ chinese_simplified ] = "CHAR";
+ Text[ greek ] = "CHAR";
+ Text[ korean ] = "CHAR";
+ Text[ turkish ] = "CHAR";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_LOG10 { Text = "LOG10" ; };
+ String SC_OPCODE_EVEN
+ {
+ Text = "GERADE" ;
+ Text [ english ] = "EVEN" ;
+ Text [ norwegian ] = "PAR" ;
+ Text [ italian ] = "PARI" ;
+ Text [ portuguese_brazilian ] = "PAR" ;
+ Text [ portuguese ] = "PAR" ;
+ Text [ finnish ] = "EVEN" ;
+ Text [ danish ] = "LIGE" ;
+ Text [ french ] = "PAIR" ;
+ Text [ swedish ] = "JÄMN" ;
+ Text [ dutch ] = "EVEN" ;
+ Text [ spanish ] = "REDONDEA.PAR" ;
+ Text [ english_us ] = "EVEN" ;
+ Text[ chinese_simplified ] = "EVEN";
+ Text[ russian ] = "×ÅÒÍ";
+ Text[ polish ] = "ZAOKR.DO.PARZ";
+ Text[ japanese ] = "EVEN";
+ Text[ chinese_traditional ] = "EVEN";
+ Text[ arabic ] = "EVEN";
+ Text[ dutch ] = "EVEN";
+ Text[ chinese_simplified ] = "EVEN";
+ Text[ greek ] = "EVEN";
+ Text[ korean ] = "EVEN";
+ Text[ turkish ] = "EVEN";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ODD
+ {
+ Text = "UNGERADE" ;
+ Text [ english ] = "ODD" ;
+ Text [ norwegian ] = "ODDE" ;
+ Text [ italian ] = "DISPARI" ;
+ Text [ portuguese_brazilian ] = "IMPAR" ;
+ Text [ portuguese ] = "ÍMPAR" ;
+ Text [ finnish ] = "ODD" ;
+ Text [ danish ] = "ULIGE" ;
+ Text [ french ] = "IMPAIR" ;
+ Text [ swedish ] = "UDDA" ;
+ Text [ dutch ] = "ONEVEN" ;
+ Text [ spanish ] = "REDONDEA.IMPAR" ;
+ Text [ english_us ] = "ODD" ;
+ Text[ chinese_simplified ] = "ODD";
+ Text[ russian ] = "ÍÅ×ÅÒ";
+ Text[ polish ] = "ZAOK.DO.NPARZ";
+ Text[ japanese ] = "ODD";
+ Text[ chinese_traditional ] = "ODD";
+ Text[ arabic ] = "ODD";
+ Text[ dutch ] = "ONEVEN";
+ Text[ chinese_simplified ] = "ODD";
+ Text[ greek ] = "ODD";
+ Text[ korean ] = "ODD";
+ Text[ turkish ] = "ODD";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_STD_NORM_DIST
+ {
+ Text = "STANDNORMVERT" ;
+ Text [ english ] = "NORMSDIST" ;
+ Text [ norwegian ] = "NORMSDIST" ;
+ Text [ italian ] = "DISTRIB.NORM.ST" ;
+ Text [ portuguese_brazilian ] = "NORMSDIST" ;
+ Text [ portuguese ] = "DIST.NORM.P" ;
+ Text [ finnish ] = "NORMSDIST" ;
+ Text [ danish ] = "STANDARDNORMFORDELING" ;
+ Text [ french ] = "LOI.NORMALE.STANDARD" ;
+ Text [ swedish ] = "NORMSFÖRD" ;
+ Text [ dutch ] = "STAND.NORM.VERD" ;
+ Text [ spanish ] = "DISTR.NORM.ESTAND" ;
+ Text [ english_us ] = "NORMSDIST" ;
+ Text[ chinese_simplified ] = "NORMSDIST";
+ Text[ russian ] = "ÍÎÐÌÑÒÐÀÑÏ";
+ Text[ polish ] = "ROZK£AD.NORMALNY.S";
+ Text[ japanese ] = "NORMSDIST";
+ Text[ chinese_traditional ] = "NORMSDIST";
+ Text[ arabic ] = "NORMSDIST";
+ Text[ dutch ] = "STAND.NORM.VERD";
+ Text[ chinese_simplified ] = "NORMSDIST";
+ Text[ greek ] = "NORMSDIST";
+ Text[ korean ] = "NORMSDIST";
+ Text[ turkish ] = "STANDNORMDIST";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_FISHER { Text = "FISHER" ; };
+ String SC_OPCODE_FISHER_INV
+ {
+ Text = "FISHERINV" ;
+ Text [ english ] = "FISHERINV" ;
+ Text [ norwegian ] = "FISHERINV" ;
+ Text [ italian ] = "INV.FISHER" ;
+ Text [ portuguese_brazilian ] = "FISHERINV" ;
+ Text [ portuguese ] = "INV.FISHER" ;
+ Text [ finnish ] = "FISHERINV" ;
+ Text [ danish ] = "FISHERINV" ;
+ Text [ french ] = "FISHER.INVERSE" ;
+ Text [ swedish ] = "FISHERINV" ;
+ Text [ dutch ] = "FISHER.INV" ;
+ Text [ spanish ] = "PRUEBA.FISHER.INV" ;
+ Text [ english_us ] = "FISHERINV" ;
+ Text[ chinese_simplified ] = "FISHERINV";
+ Text[ russian ] = "ÔÈØÅÐÎÁÐ";
+ Text[ polish ] = "ROZK£AD.FISHER.ODW.";
+ Text[ japanese ] = "FISHERINV";
+ Text[ chinese_traditional ] = "FISHERINV";
+ Text[ arabic ] = "FISHERINV";
+ Text[ dutch ] = "FISHER.INV";
+ Text[ chinese_simplified ] = "FISHERINV";
+ Text[ greek ] = "FISHERINV";
+ Text[ korean ] = "FISHERINV";
+ Text[ turkish ] = "FISHERINV";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_S_NORM_INV
+ {
+ Text = "STANDNORMINV" ;
+ Text [ english ] = "NORMSINV" ;
+ Text [ norwegian ] = "NORMSINV" ;
+ Text [ italian ] = "INV.NORM.ST" ;
+ Text [ portuguese_brazilian ] = "NORMSINV" ;
+ Text [ portuguese ] = "INV.NORM.P" ;
+ Text [ finnish ] = "NORMSINV" ;
+ Text [ danish ] = "STANDARDNORMINV" ;
+ Text [ french ] = "LOI.NORMALE.STANDARD.INVERSE" ;
+ Text [ swedish ] = "NORMSINV" ;
+ Text [ dutch ] = "STAND.NORM.INV" ;
+ Text [ spanish ] = "DISTR.NORM.ESTAND.INV" ;
+ Text [ english_us ] = "NORMSINV" ;
+ Text[ chinese_simplified ] = "NORMSINV";
+ Text[ russian ] = "ÍÎÐÌÑÒÎÁÐ";
+ Text[ polish ] = "ROZK£AD.NORMALNY.S.ODW";
+ Text[ japanese ] = "NORMSINV";
+ Text[ chinese_traditional ] = "NORMSINV";
+ Text[ arabic ] = "NORMSINV";
+ Text[ dutch ] = "STAND.NORM.INV";
+ Text[ chinese_simplified ] = "NORMSINV";
+ Text[ greek ] = "NORMSINV";
+ Text[ korean ] = "NORMSINV";
+ Text[ turkish ] = "NORMSINV";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GAMMA_LN
+ {
+ Text = "GAMMALN" ;
+ Text [ english ] = "GAMMALN" ;
+ Text [ norwegian ] = "GAMMALN" ;
+ Text [ italian ] = "LN.GAMMA" ;
+ Text [ portuguese_brazilian ] = "GAMMALN" ;
+ Text [ portuguese ] = "LN.GAMMA" ;
+ Text [ finnish ] = "GAMMALN" ;
+ Text [ danish ] = "GAMMALN" ;
+ Text [ french ] = "LNGAMMA" ;
+ Text [ swedish ] = "GAMMALN" ;
+ Text [ dutch ] = "GAMMA.LN" ;
+ Text [ spanish ] = "GAMMA.LN" ;
+ Text [ english_us ] = "GAMMALN" ;
+ Text[ chinese_simplified ] = "GAMMALN";
+ Text[ russian ] = "ÃÀÌÌÀÍËÎÃ";
+ Text[ polish ] = "ROZK£AD.LIN.GAMMA";
+ Text[ japanese ] = "GAMMALN";
+ Text[ chinese_traditional ] = "GAMMALN";
+ Text[ arabic ] = "GAMMALN";
+ Text[ dutch ] = "GAMMA.LN";
+ Text[ chinese_simplified ] = "GAMMALN";
+ Text[ greek ] = "GAMMALN";
+ Text[ korean ] = "GAMMALN";
+ Text[ turkish ] = "GAMMALN";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ERROR_TYPE
+ {
+ Text = "FEHLERTYP" ;
+ Text [ english ] = "ERRORTYPE" ;
+ Text [ norwegian ] = "ERRORTYPE" ;
+ Text [ italian ] = "ERRORE.TIPO" ;
+ Text [ portuguese_brazilian ] = "ERRORTYPE" ;
+ Text [ portuguese ] = "TIPO.ERRO" ;
+ Text [ finnish ] = "ERRORTYPE" ;
+ Text [ danish ] = "FEJLTYPE" ;
+ Text [ french ] = "TYPE.ERREUR" ;
+ Text [ swedish ] = "FELTYP" ;
+ Text [ dutch ] = "TYPE.FOUT" ;
+ Text [ spanish ] = "TIPO.DE.ERROR" ;
+ Text [ english_us ] = "ERRORTYPE" ;
+ Text[ chinese_simplified ] = "ERRORTYPE";
+ Text[ russian ] = "ÒÈÏ.ÎØÈÁÊÈ";
+ Text[ polish ] = "TYP.B£ÊDU";
+ Text[ japanese ] = "ERROR.TYPE";
+ Text[ chinese_traditional ] = "ERRORTYPE";
+ Text[ arabic ] = "ERRORTYPE";
+ Text[ dutch ] = "TYPE.FOUT";
+ Text[ chinese_simplified ] = "ERRORTYPE";
+ Text[ greek ] = "ERRORTYPE";
+ Text[ korean ] = "ERRORTYPE";
+ Text[ turkish ] = "ERRORTYPE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ERR_CELL { Text = "ZellError" ; }; // ?? Text klein, dt. & engl. gemischt ??
+ String SC_OPCODE_FORMULA
+ {
+ Text = "FORMEL";
+ Text [ english ] = "FORMULA" ;
+ Text [ english_us ] = "FORMULA" ;
+ Text[ portuguese ] = "FORMULA";
+ Text[ russian ] = "ÔÎÐÌÓËÀ";
+ Text[ greek ] = "FORMULA";
+ Text[ dutch ] = "FORMULE";
+ Text[ french ] = "FORMULE";
+ Text[ spanish ] = "FORMULA";
+ Text[ italian ] = "FORMULA";
+ Text[ danish ] = "FORMEL";
+ Text[ swedish ] = "FORMEL";
+ Text[ polish ] = "FORMU£A";
+ Text[ portuguese_brazilian ] = "FORMULA";
+ Text[ japanese ] = "FORMULA";
+ Text[ korean ] = "FORMULA";
+ Text[ chinese_simplified ] = "FORMULA";
+ Text[ chinese_traditional ] = "FORMULA";
+ Text[ arabic ] = "FORMULA";
+ Text[ turkish ] = "FORMULA";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ARC_TAN_2
+ {
+ Text = "ARCTAN2" ;
+ Text [ english ] = "ATAN2" ;
+ Text [ norwegian ] = "ATAN2" ;
+ Text [ italian ] = "ARCTAN.2" ;
+ Text [ portuguese_brazilian ] = "ATAN2" ;
+ Text [ portuguese ] = "ATAN2" ;
+ Text [ finnish ] = "ATAN2" ;
+ Text [ danish ] = "ARCTAN2" ;
+ Text [ french ] = "ATAN2" ;
+ Text [ swedish ] = "ARCTAN2" ;
+ Text [ dutch ] = "BOOGTAN2" ;
+ Text [ spanish ] = "ATAN2" ;
+ Text [ english_us ] = "ATAN2" ;
+ Text[ chinese_simplified ] = "ATAN2";
+ Text[ russian ] = "ATAN2";
+ Text[ polish ] = "ATAN2";
+ Text[ japanese ] = "ATAN2";
+ Text[ chinese_traditional ] = "ATAN2";
+ Text[ arabic ] = "ATAN2";
+ Text[ dutch ] = "BOOGTAN2";
+ Text[ chinese_simplified ] = "ATAN2";
+ Text[ greek ] = "ATAN2";
+ Text[ korean ] = "ATAN2";
+ Text[ turkish ] = "ATAN2";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_CEIL
+ {
+ Text = "OBERGRENZE" ;
+ Text [ english ] = "CEILING" ;
+ Text [ norwegian ] = "TAK" ;
+ Text [ italian ] = "ARROTONDA.ECCESSO" ;
+ Text [ portuguese_brazilian ] = "TETO" ;
+ Text [ portuguese ] = "LIMITE.SUPERIOR" ;
+ Text [ finnish ] = "CEILING" ;
+ Text [ danish ] = "AFRUND.LOFT" ;
+ Text [ french ] = "PLAFOND" ;
+ Text [ swedish ] = "RUNDA.UPP" ;
+ Text [ dutch ] = "AFRONDEN.BOVEN" ;
+ Text [ spanish ] = "MÚLTIPLO.SUPERIOR" ;
+ Text [ english_us ] = "CEILING" ;
+ Text[ chinese_simplified ] = "CEILING";
+ Text[ russian ] = "ÎÊÐÂÂÅÐÕ";
+ Text[ polish ] = "ZAOKR.W.GÓRÊ";
+ Text[ japanese ] = "CEILING";
+ Text[ chinese_traditional ] = "CEILING";
+ Text[ arabic ] = "CEILING";
+ Text[ dutch ] = "AFRONDEN.BOVEN";
+ Text[ chinese_simplified ] = "CEILING";
+ Text[ greek ] = "CEILING";
+ Text[ korean ] = "CEILING";
+ Text[ turkish ] = "CEILING";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_FLOOR
+ {
+ Text = "UNTERGRENZE" ;
+ Text [ english ] = "FLOOR" ;
+ Text [ norwegian ] = "GULV" ;
+ Text [ italian ] = "ARROTONDA.DIFETTO" ;
+ Text [ portuguese_brazilian ] = "BASE" ;
+ Text [ portuguese ] = "LIMITE.INFERIOR" ;
+ Text [ finnish ] = "FLOOR" ;
+ Text [ danish ] = "AFRUND.GULV" ;
+ Text [ french ] = "PLANCHER" ;
+ Text [ swedish ] = "RUNDA.NER" ;
+ Text [ dutch ] = "AFRONDEN.BENEDEN" ;
+ Text [ spanish ] = "MÚLTIPLO.INFERIOR" ;
+ Text [ english_us ] = "FLOOR" ;
+ Text[ chinese_simplified ] = "FLOOR";
+ Text[ russian ] = "ÎÊÐÂÍÈÇ";
+ Text[ polish ] = "ZAOKR.W.DÓ£";
+ Text[ japanese ] = "FLOOR";
+ Text[ chinese_traditional ] = "FLOOR";
+ Text[ arabic ] = "FLOOR";
+ Text[ dutch ] = "AFRONDEN.BENEDEN";
+ Text[ chinese_simplified ] = "FLOOR";
+ Text[ greek ] = "FLOOR";
+ Text[ korean ] = "FLOOR";
+ Text[ turkish ] = "FLOOR";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ROUND
+ {
+ Text = "RUNDEN" ;
+ Text [ english ] = "ROUND" ;
+ Text [ norwegian ] = "ROUND" ;
+ Text [ italian ] = "ARROTONDA" ;
+ Text [ portuguese_brazilian ] = "ARREDONDAR" ;
+ Text [ portuguese ] = "ARREDONDAR" ;
+ Text [ finnish ] = "ROUND" ;
+ Text [ danish ] = "AFRUND" ;
+ Text [ french ] = "ARRONDI" ;
+ Text [ swedish ] = "AVRUNDA" ;
+ Text [ dutch ] = "AFRONDEN" ;
+ Text [ spanish ] = "REDONDEAR" ;
+ Text [ english_us ] = "ROUND" ;
+ Text[ chinese_simplified ] = "ROUND";
+ Text[ russian ] = "ÎÊÐÓÃË";
+ Text[ polish ] = "ZAOKR";
+ Text[ japanese ] = "ROUND";
+ Text[ chinese_traditional ] = "ROUND";
+ Text[ arabic ] = "ROUND";
+ Text[ dutch ] = "AFRONDEN";
+ Text[ chinese_simplified ] = "ROUND";
+ Text[ greek ] = "ROUND";
+ Text[ korean ] = "ROUND";
+ Text[ turkish ] = "ROUND";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ROUND_UP
+ {
+ Text = "AUFRUNDEN" ;
+ Text [ english ] = "ROUNDUP" ;
+ Text [ norwegian ] = "ROUNDUP" ;
+ Text [ italian ] = "ARROTONDA.PER.ECC" ;
+ Text [ portuguese_brazilian ] = "ARREDONDARPARACIMA" ;
+ Text [ portuguese ] = "ARRED.PARA.CIMA" ;
+ Text [ finnish ] = "ROUNDUP" ;
+ Text [ danish ] = "RUND.OP" ;
+ Text [ french ] = "ARRONDI.SUP" ;
+ Text [ swedish ] = "AVRUNDA.UPPÅT" ;
+ Text [ dutch ] = "AFRONDEN.NAAR.BOVEN" ;
+ Text [ spanish ] = "REDONDEAR.MAS" ;
+ Text [ english_us ] = "ROUNDUP" ;
+ Text[ chinese_simplified ] = "ROUNDUP";
+ Text[ russian ] = "ÎÊÐÓÃËÂÂÅÐÕ";
+ Text[ polish ] = "ZAOKR.GÓRA";
+ Text[ japanese ] = "ROUNDUP";
+ Text[ chinese_traditional ] = "ROUNDUP";
+ Text[ arabic ] = "ROUNDUP";
+ Text[ dutch ] = "AFRONDEN.NAAR.BOVEN";
+ Text[ chinese_simplified ] = "ROUNDUP";
+ Text[ greek ] = "ROUNDUP";
+ Text[ korean ] = "ROUNDUP";
+ Text[ turkish ] = "ROUNDUP";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ROUND_DOWN
+ {
+ Text = "ABRUNDEN" ;
+ Text [ english ] = "ROUNDDOWN" ;
+ Text [ norwegian ] = "ROUNDDOWN" ;
+ Text [ italian ] = "ARROTONDA.PER.DIF" ;
+ Text [ portuguese_brazilian ] = "ARREDONDARPARABAIXO" ;
+ Text [ portuguese ] = "ARRED.PARA.BAIXO" ;
+ Text [ finnish ] = "ROUNDDOWN" ;
+ Text [ danish ] = "RUND.NED" ;
+ Text [ french ] = "ARRONDI.INF" ;
+ Text [ swedish ] = "AVRUNDA.NEDÅT" ;
+ Text [ dutch ] = "AFRONDEN.NAAR.BENEDEN" ;
+ Text [ spanish ] = "REDONDEAR.MENOS" ;
+ Text [ english_us ] = "ROUNDDOWN" ;
+ Text[ chinese_simplified ] = "ROUNDDOWN";
+ Text[ russian ] = "ÎÊÐÓÃËÂÍÈÇ";
+ Text[ polish ] = "ZAOKR.DÓ£";
+ Text[ japanese ] = "ROUNDDOWN";
+ Text[ chinese_traditional ] = "ROUNDDOWN";
+ Text[ arabic ] = "ROUNDDOWN";
+ Text[ dutch ] = "AFRONDEN.NAAR.BENEDEN";
+ Text[ chinese_simplified ] = "ROUNDDOWN";
+ Text[ greek ] = "ROUNDDOWN";
+ Text[ korean ] = "ROUNDDOWN";
+ Text[ turkish ] = "ROUNDDOWN";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_TRUNC
+ {
+ /* ### ACHTUNG: Neuer Text in Resource? KÜRZEN : KšRZEN */
+ Text = "KÜRZEN" ;
+ Text [ english ] = "TRUNC" ;
+ Text [ norwegian ] = "TRUNC" ;
+ Text [ italian ] = "TRONCA" ;
+ Text [ portuguese_brazilian ] = "TRUNCAR" ;
+ Text [ portuguese ] = "TRUNCAR" ;
+ Text [ finnish ] = "TRUNC" ;
+ Text [ danish ] = "AFKORT" ;
+ Text [ french ] = "TRONQUE" ;
+ Text [ swedish ] = "AVKORTA" ;
+ Text [ dutch ] = "GEHEEL" ;
+ Text [ spanish ] = "TRUNCAR" ;
+ Text [ english_us ] = "TRUNC" ;
+ Text[ chinese_simplified ] = "TRUNC";
+ Text[ russian ] = "ÎÒÁÐ";
+ Text[ polish ] = "LICZBA.CA£K";
+ Text[ japanese ] = "TRUNC";
+ Text[ chinese_traditional ] = "TRUNC";
+ Text[ arabic ] = "TRUNC";
+ Text[ dutch ] = "GEHEEL";
+ Text[ chinese_simplified ] = "TRUNC";
+ Text[ greek ] = "TRUNC";
+ Text[ korean ] = "TRUNC";
+ Text[ turkish ] = "TRUNC";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_LOG { Text = "LOG" ; };
+ String SC_OPCODE_POWER
+ {
+ Text = "POTENZ" ;
+ Text [ english ] = "POWER" ;
+ Text [ norwegian ] = "POWER" ;
+ Text [ italian ] = "POTENZA" ;
+ Text [ portuguese_brazilian ] = "POTENCIA" ;
+ Text [ portuguese ] = "POTÉNCIA" ;
+ Text [ finnish ] = "POWER" ;
+ Text [ danish ] = "POTENS" ;
+ Text [ french ] = "PUISSANCE" ;
+ Text [ swedish ] = "UPPHÖJT.TILL" ;
+ Text [ dutch ] = "MACHT" ;
+ Text [ spanish ] = "POTENCIA" ;
+ Text [ english_us ] = "POWER" ;
+ Text[ chinese_simplified ] = "POWER";
+ Text[ russian ] = "ÑÒÅÏÅÍÜ";
+ Text[ polish ] = "POTÊGA";
+ Text[ japanese ] = "POWER";
+ Text[ chinese_traditional ] = "POWER";
+ Text[ arabic ] = "POWER";
+ Text[ dutch ] = "MACHT";
+ Text[ chinese_simplified ] = "POWER";
+ Text[ greek ] = "POWER";
+ Text[ korean ] = "POWER";
+ Text[ turkish ] = "POWER";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GGT
+ {
+ Text = "GGT" ;
+ Text [ english ] = "GCD" ;
+ Text [ norwegian ] = "GCD" ;
+ Text [ italian ] = "MCD" ;
+ Text [ portuguese_brazilian ] = "GCD" ;
+ Text [ portuguese ] = "MDC" ;
+ Text [ finnish ] = "GCD" ;
+ Text [ danish ] = "STØRSTE.FÆLLES.DIVISOR" ;
+ Text [ french ] = "PGCD" ;
+ Text [ swedish ] = "SGN" ;
+ Text [ dutch ] = "GGD" ;
+ Text [ spanish ] = "M.C.D" ;
+ Text [ english_us ] = "GCD" ;
+ Text[ chinese_simplified ] = "GCD";
+ Text[ russian ] = "ÍÎÄ";
+ Text[ polish ] = "GCD";
+ Text[ japanese ] = "GCD";
+ Text[ chinese_traditional ] = "GCD";
+ Text[ arabic ] = "GCD";
+ Text[ dutch ] = "GGD";
+ Text[ chinese_simplified ] = "GCD";
+ Text[ greek ] = "GCD";
+ Text[ korean ] = "GCD";
+ Text[ turkish ] = "GCD";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_KGV
+ {
+ Text = "KGV" ;
+ Text [ english ] = "LCM" ;
+ Text [ norwegian ] = "LCD" ;
+ Text [ italian ] = "MCM" ;
+ Text [ portuguese_brazilian ] = "LCD" ;
+ Text [ portuguese ] = "MIN.MÚLT.COMUM" ;
+ Text [ finnish ] = "LCD" ;
+ Text [ danish ] = "MINDSTE.FÆLLES.MULTIPLUM" ;
+ Text [ french ] = "PPCM" ;
+ Text [ swedish ] = "MGT" ;
+ Text [ dutch ] = "KGV" ;
+ Text [ spanish ] = "M.C.M" ;
+ Text [ english_us ] = "LCM" ;
+ Text[ chinese_simplified ] = "LCM";
+ Text[ russian ] = "ÍÎÊ";
+ Text[ polish ] = "LCM";
+ Text[ japanese ] = "LCM";
+ Text[ chinese_traditional ] = "LCM";
+ Text[ arabic ] = "LCM";
+ Text[ dutch ] = "KGV";
+ Text[ chinese_simplified ] = "LCM";
+ Text[ greek ] = "LCM";
+ Text[ korean ] = "LCM";
+ Text[ turkish ] = "LCM";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_MOD
+ {
+ Text = "REST" ;
+ Text [ english ] = "MOD" ;
+ Text [ norwegian ] = "MOD" ;
+ Text [ italian ] = "RESTO" ;
+ Text [ portuguese_brazilian ] = "MOD" ;
+ Text [ portuguese ] = "RESTO" ;
+ Text [ finnish ] = "MOD" ;
+ Text [ danish ] = "REST" ;
+ Text [ french ] = "MOD" ;
+ Text [ swedish ] = "REST" ;
+ Text [ dutch ] = "REST" ;
+ Text [ spanish ] = "RESIDUO" ;
+ Text [ english_us ] = "MOD" ;
+ Text[ chinese_simplified ] = "MOD";
+ Text[ russian ] = "ÎÑÒÀÒ";
+ Text[ polish ] = "MOD";
+ Text[ japanese ] = "MOD";
+ Text[ chinese_traditional ] = "MOD";
+ Text[ arabic ] = "MOD";
+ Text[ dutch ] = "REST";
+ Text[ chinese_simplified ] = "MOD";
+ Text[ greek ] = "MOD";
+ Text[ korean ] = "MOD";
+ Text[ turkish ] = "MOD";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_SUM_PRODUCT
+ {
+ Text = "SUMMENPRODUKT" ;
+ Text [ english ] = "SUMPRODUCT" ;
+ Text [ norwegian ] = "SUMPRODUKT" ;
+ Text [ italian ] = "MATR.SOMMA.PRODOTTO" ;
+ Text [ portuguese_brazilian ] = "SOMARPRODUT" ;
+ Text [ portuguese ] = "SOMAR.PRODUTO" ;
+ Text [ finnish ] = "SUMPRODUCT" ;
+ Text [ danish ] = "SUMPRODUKT" ;
+ Text [ french ] = "SOMMEPROD" ;
+ Text [ swedish ] = "PRODUKTSUMMA" ;
+ Text [ dutch ] = "SOMPRODUKT" ;
+ Text [ spanish ] = "SUMA.PRODUCTO" ;
+ Text [ english_us ] = "SUMPRODUCT" ;
+ Text[ chinese_simplified ] = "SUMPRODUCT";
+ Text[ russian ] = "ÑÓÌÌÏÐÎÈÇÂ";
+ Text[ polish ] = "SUMA.ILOCZYNÓW";
+ Text[ japanese ] = "SUMPRODUCT";
+ Text[ chinese_traditional ] = "SUMPRODUCT";
+ Text[ arabic ] = "SUMPRODUCT";
+ Text[ dutch ] = "SOMPRODUKT";
+ Text[ chinese_simplified ] = "SUMPRODUCT";
+ Text[ greek ] = "SUMPRODUCT";
+ Text[ korean ] = "SUMPRODUCT";
+ Text[ turkish ] = "SUMPRODUCT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_SUM_SQ
+ {
+ Text = "QUADRATESUMME" ;
+ Text [ english ] = "SUMSQ" ;
+ Text [ norwegian ] = "SUMSQ" ;
+ Text [ italian ] = "SOMMA.Q" ;
+ Text [ portuguese_brazilian ] = "SOMARSQ" ;
+ Text [ portuguese ] = "SOMARQUAD" ;
+ Text [ finnish ] = "SUMSQ" ;
+ Text [ danish ] = "SUMKV" ;
+ Text [ french ] = "SOMME.CARRES" ;
+ Text [ swedish ] = "KVADRATSUMMA" ;
+ Text [ dutch ] = "KWADRATENSOM" ;
+ Text [ spanish ] = "SUMA.CUADRADOS" ;
+ Text [ english_us ] = "SUMSQ" ;
+ Text[ chinese_simplified ] = "SUMSQ";
+ Text[ russian ] = "ÑÓÌÌÀÊÂ";
+ Text[ polish ] = "SUMA.KWADRATÓW";
+ Text[ japanese ] = "SUMSQ";
+ Text[ chinese_traditional ] = "SUMSQ";
+ Text[ arabic ] = "SUMSQ";
+ Text[ dutch ] = "KWADRATENSOM";
+ Text[ chinese_simplified ] = "SUMSQ";
+ Text[ greek ] = "SUMSQ";
+ Text[ korean ] = "SUMSQ";
+ Text[ turkish ] = "SUMSQ";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_SUM_X2MY2
+ {
+ Text = "SUMMEX2MY2" ;
+ Text [ english ] = "SUMX2MY2" ;
+ Text [ norwegian ] = "SUMX2MY2" ;
+ Text [ italian ] = "SOMMA.DIFF.Q" ;
+ Text [ portuguese_brazilian ] = "SOMARX2MY2" ;
+ Text [ portuguese ] = "SOMA.X2MY2" ;
+ Text [ finnish ] = "SUMX2MY2" ;
+ Text [ danish ] = "SUMX2MY2" ;
+ Text [ french ] = "SOMME.X2MY2" ;
+ Text [ swedish ] = "SUMMAX2MY2" ;
+ Text [ dutch ] = "SOM.X2MINY2" ;
+ Text [ spanish ] = "SUMAX2MENOSY2" ;
+ Text [ english_us ] = "SUMX2MY2" ;
+ Text[ chinese_simplified ] = "SUMX2MY2";
+ Text[ russian ] = "ÑÓÌÌÐÀÇÍÊÂ";
+ Text[ polish ] = "SUMA.X2.M.Y2";
+ Text[ japanese ] = "SUMX2MY2";
+ Text[ chinese_traditional ] = "SUMX2MY2";
+ Text[ arabic ] = "SUMX2MY2";
+ Text[ dutch ] = "SOM.X2MINY2";
+ Text[ chinese_simplified ] = "SUMX2MY2";
+ Text[ greek ] = "SUMX2MY2";
+ Text[ korean ] = "SUMX2MY2";
+ Text[ turkish ] = "SUMX2MY2";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_SUM_X2DY2
+ {
+ Text = "SUMMEX2PY2" ;
+ Text [ english ] = "SUMX2PY2" ;
+ Text [ norwegian ] = "SUMX2DY2" ;
+ Text [ italian ] = "SOMMA.SOMMA.Q" ;
+ Text [ portuguese_brazilian ] = "SOMARX2DY2" ;
+ Text [ portuguese ] = "SOMA.X2PY2" ;
+ Text [ finnish ] = "SUMX2DY2" ;
+ Text [ danish ] = "SUMX2PY2" ;
+ Text [ french ] = "SOMME.X2PY2" ;
+ Text [ swedish ] = "SUMMAX2PY2" ;
+ Text [ dutch ] = "SOM.X2PLUSY2" ;
+ Text [ spanish ] = "SUMAX2MASY2" ;
+ Text [ english_us ] = "SUMX2PY2" ;
+ Text[ chinese_simplified ] = "SUMX2PY2";
+ Text[ russian ] = "ÑÓÌÌÑÓÌÌÊÂ";
+ Text[ polish ] = "SUMA.X2.P.Y2";
+ Text[ japanese ] = "SUMX2PY2";
+ Text[ chinese_traditional ] = "SUMX2PY2";
+ Text[ arabic ] = "SUMX2PY2";
+ Text[ dutch ] = "SOM.X2PLUSY2";
+ Text[ chinese_simplified ] = "SUMX2PY2";
+ Text[ greek ] = "SUMX2PY2";
+ Text[ korean ] = "SUMX2PY2";
+ Text[ turkish ] = "SUMX2PY2";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_SUM_XMY2
+ {
+ Text = "SUMMEXMY2" ;
+ Text [ english ] = "SUMXMY2" ;
+ Text [ norwegian ] = "SUMXMY2" ;
+ Text [ italian ] = "SOMMA.Q.DIFF" ;
+ Text [ portuguese_brazilian ] = "SOMARXMY2" ;
+ Text [ portuguese ] = "SOMA.XMY2" ;
+ Text [ finnish ] = "SUMXMY2" ;
+ Text [ danish ] = "SUMXMY2" ;
+ Text [ french ] = "SOMME.XMY2" ;
+ Text [ swedish ] = "SUMMAXMY2" ;
+ Text [ dutch ] = "SOM.XMINY.2" ;
+ Text [ spanish ] = "SUMAXMENOSY2" ;
+ Text [ english_us ] = "SUMXMY2" ;
+ Text[ chinese_simplified ] = "SUMXMY2";
+ Text[ russian ] = "ÑÓÌÌÊÂÐÀÇÍ";
+ Text[ polish ] = "SUMA.XMY.2";
+ Text[ japanese ] = "SUMXMY2";
+ Text[ chinese_traditional ] = "SUMXMY2";
+ Text[ arabic ] = "SUMXMY2";
+ Text[ dutch ] = "SOM.XMINY.2";
+ Text[ chinese_simplified ] = "SUMXMY2";
+ Text[ greek ] = "SUMXMY2";
+ Text[ korean ] = "SUMXMY2";
+ Text[ turkish ] = "SUMXMY2";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GET_DATE
+ {
+ Text = "DATUM" ;
+ Text [ english ] = "DATE" ;
+ Text [ norwegian ] = "DATO" ;
+ Text [ italian ] = "DATA" ;
+ Text [ portuguese_brazilian ] = "DATA" ;
+ Text [ portuguese ] = "DATA" ;
+ Text [ finnish ] = "DATE" ;
+ Text [ danish ] = "DATO" ;
+ Text [ french ] = "DATE" ;
+ Text [ swedish ] = "DATUM" ;
+ Text [ dutch ] = "DATUM" ;
+ Text [ spanish ] = "FECHA" ;
+ Text [ english_us ] = "DATE" ;
+ Text[ chinese_simplified ] = "DATE";
+ Text[ russian ] = "ÄÀÒÀ";
+ Text[ polish ] = "DATA";
+ Text[ japanese ] = "DATE";
+ Text[ chinese_traditional ] = "DATE";
+ Text[ arabic ] = "DATE";
+ Text[ dutch ] = "DATUM";
+ Text[ chinese_simplified ] = "DATE";
+ Text[ greek ] = "DATE";
+ Text[ korean ] = "DATE";
+ Text[ turkish ] = "DATE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GET_TIME
+ {
+ Text = "ZEIT" ;
+ Text [ english ] = "TIME" ;
+ Text [ norwegian ] = "TID" ;
+ Text [ italian ] = "ORARIO" ;
+ Text [ portuguese_brazilian ] = "HORA" ;
+ Text [ portuguese ] = "TEMPO" ;
+ Text [ finnish ] = "TIME" ;
+ Text [ danish ] = "TID" ;
+ Text [ french ] = "TEMPS" ;
+ Text [ swedish ] = "KLOCKSLAG" ;
+ Text [ dutch ] = "TIJD" ;
+ Text [ spanish ] = "NSHORA" ;
+ Text [ english_us ] = "TIME" ;
+ Text[ chinese_simplified ] = "TIME";
+ Text[ russian ] = "ÂÐÅÌß";
+ Text[ polish ] = "CZAS";
+ Text[ japanese ] = "TIME";
+ Text[ chinese_traditional ] = "TIME";
+ Text[ arabic ] = "TIME";
+ Text[ dutch ] = "TIJD";
+ Text[ chinese_simplified ] = "TIME";
+ Text[ greek ] = "TIME";
+ Text[ korean ] = "TIME";
+ Text[ turkish ] = "TIME";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GET_DIFF_DATE
+ {
+ Text = "TAGE" ;
+ Text [ english ] = "DAYS" ;
+ Text [ norwegian ] = "DAGER" ;
+ Text [ italian ] = "GIORNI" ;
+ Text [ portuguese_brazilian ] = "DIA" ;
+ Text [ portuguese ] = "DIAS" ;
+ Text [ finnish ] = "DAYS" ;
+ Text [ danish ] = "DAGE" ;
+ Text [ french ] = "JOURS" ;
+ Text [ swedish ] = "DAGAR" ;
+ Text [ dutch ] = "DAGEN" ;
+ Text [ spanish ] = "DÍAS" ;
+ Text [ english_us ] = "DAYS" ;
+ Text[ chinese_simplified ] = "DAYS";
+ Text[ russian ] = "ÄÍÅÉ";
+ Text[ polish ] = "DNI";
+ Text[ japanese ] = "DAYS";
+ Text[ chinese_traditional ] = "DAYS";
+ Text[ arabic ] = "DAYS";
+ Text[ dutch ] = "DAGEN";
+ Text[ chinese_simplified ] = "DAYS";
+ Text[ greek ] = "DAYS";
+ Text[ korean ] = "DAYS";
+ Text[ turkish ] = "DAYS";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GET_DIFF_DATE_360
+ {
+ Text = "TAGE360" ;
+ Text [ english ] = "DAYS360" ;
+ Text [ norwegian ] = "DAGER360" ;
+ Text [ italian ] = "GIORNO360" ;
+ Text [ portuguese_brazilian ] = "DIAS360" ;
+ Text [ portuguese ] = "DIAS360" ;
+ Text [ finnish ] = "DAYS360" ;
+ Text [ danish ] = "DAGE360" ;
+ Text [ french ] = "JOURS360" ;
+ Text [ swedish ] = "DAGAR360" ;
+ Text [ dutch ] = "DAGEN360" ;
+ Text [ spanish ] = "DÍAS360" ;
+ Text [ english_us ] = "DAYS360" ;
+ Text[ chinese_simplified ] = "DAYS360";
+ Text[ russian ] = "ÄÍÅÉ360";
+ Text[ polish ] = "DNI360";
+ Text[ japanese ] = "DAYS360";
+ Text[ chinese_traditional ] = "DAYS360";
+ Text[ arabic ] = "DAYS360";
+ Text[ dutch ] = "DAGEN360";
+ Text[ chinese_simplified ] = "DAYS360";
+ Text[ greek ] = "DAYS360";
+ Text[ korean ] = "DAYS360";
+ Text[ turkish ] = "DAYS360";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_MIN
+ {
+ Text = "MIN" ;
+ Text [ english ] = "MIN" ;
+ Text [ norwegian ] = "MIN" ;
+ Text [ italian ] = "MIN" ;
+ Text [ portuguese_brazilian ] = "MIN" ;
+ Text [ portuguese ] = "MÍNIMO" ;
+ Text [ finnish ] = "MIN" ;
+ Text [ danish ] = "MIN" ;
+ Text [ french ] = "MIN" ;
+ Text [ swedish ] = "MIN" ;
+ Text [ dutch ] = "MIN" ;
+ Text [ spanish ] = "MÍN" ;
+ Text [ english_us ] = "MIN" ;
+ Text[ chinese_simplified ] = "MIN";
+ Text[ russian ] = "ÌÈÍ";
+ Text[ polish ] = "MIN";
+ Text[ japanese ] = "MIN";
+ Text[ chinese_traditional ] = "MIN";
+ Text[ arabic ] = "MIN";
+ Text[ dutch ] = "MIN";
+ Text[ chinese_simplified ] = "MIN";
+ Text[ greek ] = "MIN";
+ Text[ korean ] = "MIN";
+ Text[ turkish ] = "MIN";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_MIN_A
+ {
+ Text = "MINA" ;
+ Text [ english ] = "MINA" ;
+ Text [ norwegian ] = "MINA" ;
+ Text [ italian ] = "MIN.VALORI" ;
+ Text [ portuguese_brazilian ] = "MINA" ;
+ Text [ portuguese ] = "MÍNIMOA" ;
+ Text [ finnish ] = "MINA" ;
+ Text [ danish ] = "MINV" ;
+ Text [ french ] = "MINA" ;
+ Text [ swedish ] = "MINA" ;
+ Text [ dutch ] = "MINA" ;
+ Text [ spanish ] = "MÍNA" ;
+ Text [ english_us ] = "MINA" ;
+ Text[ chinese_simplified ] = "MINA";
+ Text[ russian ] = "ÌÈÍÀ";
+ Text[ polish ] = "MIN.A";
+ Text[ japanese ] = "MINA";
+ Text[ chinese_traditional ] = "MINA";
+ Text[ arabic ] = "MINA";
+ Text[ dutch ] = "MINA";
+ Text[ chinese_simplified ] = "MINA";
+ Text[ greek ] = "MINA";
+ Text[ korean ] = "MINA";
+ Text[ turkish ] = "MINA";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_MAX
+ {
+ Text = "MAX" ;
+ Text [ english ] = "MAX" ;
+ Text [ norwegian ] = "MAKS" ;
+ Text [ italian ] = "MAX" ;
+ Text [ portuguese_brazilian ] = "MAX" ;
+ Text [ portuguese ] = "MÁXIMO" ;
+ Text [ finnish ] = "MAX" ;
+ Text [ danish ] = "MAKS" ;
+ Text [ french ] = "MAX" ;
+ Text [ swedish ] = "MAX" ;
+ Text [ dutch ] = "MAX" ;
+ Text [ spanish ] = "MÁX" ;
+ Text [ english_us ] = "MAX" ;
+ Text[ chinese_simplified ] = "MAX";
+ Text[ russian ] = "ÌÀÊÑ";
+ Text[ polish ] = "MAX";
+ Text[ japanese ] = "MAX";
+ Text[ chinese_traditional ] = "MAX";
+ Text[ arabic ] = "MAX";
+ Text[ dutch ] = "MAX";
+ Text[ chinese_simplified ] = "MAX";
+ Text[ greek ] = "MAX";
+ Text[ korean ] = "MAX";
+ Text[ turkish ] = "MAX";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_MAX_A
+ {
+ Text = "MAXA" ;
+ Text [ english ] = "MAXA" ;
+ Text [ norwegian ] = "MAKS" ;
+ Text [ italian ] = "MAX.VALORI" ;
+ Text [ portuguese_brazilian ] = "MAXA" ;
+ Text [ portuguese ] = "MÁXIMOA" ;
+ Text [ finnish ] = "MAXA" ;
+ Text [ danish ] = "MAKSV" ;
+ Text [ french ] = "MAXA" ;
+ Text [ swedish ] = "MAXA" ;
+ Text [ dutch ] = "MAXA" ;
+ Text [ spanish ] = "MÁXA" ;
+ Text [ english_us ] = "MAXA" ;
+ Text[ chinese_simplified ] = "MAXA";
+ Text[ russian ] = "ÌÀÊÑÀ";
+ Text[ polish ] = "MAX.A";
+ Text[ japanese ] = "MAXA";
+ Text[ chinese_traditional ] = "MAXA";
+ Text[ arabic ] = "MAXA";
+ Text[ dutch ] = "MAXA";
+ Text[ chinese_simplified ] = "MAXA";
+ Text[ greek ] = "MAXA";
+ Text[ korean ] = "MAXA";
+ Text[ turkish ] = "MAXA";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_SUM
+ {
+ Text = "SUMME" ;
+ Text [ english ] = "SUM" ;
+ Text [ norwegian ] = "SUM" ;
+ Text [ italian ] = "SOMMA" ;
+ Text [ portuguese_brazilian ] = "SOMA" ;
+ Text [ portuguese ] = "SOMA" ;
+ Text [ finnish ] = "SUM" ;
+ Text [ danish ] = "SUM" ;
+ Text [ french ] = "SOMME" ;
+ Text [ swedish ] = "SUMMA" ;
+ Text [ dutch ] = "SOM" ;
+ Text [ spanish ] = "SUMA" ;
+ Text [ english_us ] = "SUM" ;
+ Text[ chinese_simplified ] = "SUM";
+ Text[ russian ] = "ÑÓÌÌ";
+ Text[ polish ] = "SUMA";
+ Text[ japanese ] = "SUM";
+ Text[ chinese_traditional ] = "SUM";
+ Text[ arabic ] = "SUM";
+ Text[ dutch ] = "SOM";
+ Text[ chinese_simplified ] = "SUM";
+ Text[ greek ] = "SUM";
+ Text[ korean ] = "SUM";
+ Text[ turkish ] = "SUM";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_PRODUCT
+ {
+ Text = "PRODUKT" ;
+ Text [ english ] = "PRODUCT" ;
+ Text [ norwegian ] = "PRODUKT" ;
+ Text [ italian ] = "PRODOTTO" ;
+ Text [ portuguese_brazilian ] = "PRODUTO" ;
+ Text [ portuguese ] = "PRODUTO" ;
+ Text [ finnish ] = "PRODUCT" ;
+ Text [ danish ] = "PRODUKT" ;
+ Text [ french ] = "PRODUIT" ;
+ Text [ swedish ] = "PRODUKT" ;
+ Text [ dutch ] = "PRODUKT" ;
+ Text [ spanish ] = "PRODUCTO" ;
+ Text [ english_us ] = "PRODUCT" ;
+ Text[ chinese_simplified ] = "PRODUCT";
+ Text[ russian ] = "ÏÐÎÈÇÂÅÄÅÍÈÅ";
+ Text[ polish ] = "ILOCZYN";
+ Text[ japanese ] = "PRODUCT";
+ Text[ chinese_traditional ] = "PRODUCT";
+ Text[ arabic ] = "PRODUCT";
+ Text[ dutch ] = "PRODUKT";
+ Text[ chinese_simplified ] = "PRODUCT";
+ Text[ greek ] = "PRODUCT";
+ Text[ korean ] = "PRODUCT";
+ Text[ turkish ] = "PRODUCT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_AVERAGE
+ {
+ Text = "MITTELWERT" ;
+ Text [ english ] = "AVERAGE" ;
+ Text [ norwegian ] = "GJENNOMSNITT" ;
+ Text [ italian ] = "MEDIA" ;
+ Text [ portuguese_brazilian ] = "MÉDIA" ;
+ Text [ portuguese ] = "MÉDIA" ;
+ Text [ finnish ] = "AVERAGE" ;
+ Text [ danish ] = "MIDDEL" ;
+ Text [ french ] = "MOYENNE" ;
+ Text [ swedish ] = "MEDEL" ;
+ Text [ dutch ] = "GEMIDDELDE" ;
+ Text [ spanish ] = "PROMEDIO" ;
+ Text [ english_us ] = "AVERAGE" ;
+ Text[ chinese_simplified ] = "AVERAGE";
+ Text[ russian ] = "ÑÐÇÍÀ×";
+ Text[ polish ] = "ŒREDNIA";
+ Text[ japanese ] = "AVERAGE";
+ Text[ chinese_traditional ] = "AVERAGE";
+ Text[ arabic ] = "AVERAGE";
+ Text[ dutch ] = "GEMIDDELDE";
+ Text[ chinese_simplified ] = "AVERAGE";
+ Text[ greek ] = "AVERAGE";
+ Text[ korean ] = "AVERAGE";
+ Text[ turkish ] = "AVERAGE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_AVERAGE_A
+ {
+ Text = "MITTELWERTA" ;
+ Text [ english ] = "AVERAGEA" ;
+ Text [ norwegian ] = "GJENNOMSNITTA" ;
+ Text [ italian ] = "MEDIA.VALORI" ;
+ Text [ portuguese_brazilian ] = "MÉDIAA" ;
+ Text [ portuguese ] = "MÉDIAA" ;
+ Text [ finnish ] = "AVERAGEA" ;
+ Text [ danish ] = "MIDDELV" ;
+ Text [ french ] = "MOYENNEA" ;
+ Text [ swedish ] = "MEDELA" ;
+ Text [ dutch ] = "GEMIDDELDEA" ;
+ Text [ spanish ] = "PROMEDIOA" ;
+ Text [ english_us ] = "AVERAGEA" ;
+ Text[ chinese_simplified ] = "AVERAGEA";
+ Text[ russian ] = "ÑÐÇÍÀ×À";
+ Text[ polish ] = "ŒREDNIAA";
+ Text[ japanese ] = "AVERAGEA";
+ Text[ chinese_traditional ] = "AVERAGEA";
+ Text[ arabic ] = "AVERAGEA";
+ Text[ dutch ] = "GEMIDDELDEA";
+ Text[ chinese_simplified ] = "AVERAGEA";
+ Text[ greek ] = "AVERAGEA";
+ Text[ korean ] = "AVERAGEA";
+ Text[ turkish ] = "AVERAGEA";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_COUNT
+ {
+ Text = "ANZAHL" ;
+ Text [ english ] = "COUNT" ;
+ Text [ norwegian ] = "COUNT" ;
+ Text [ italian ] = "CONTA.NUMERI" ;
+ Text [ portuguese_brazilian ] = "CONTA" ;
+ Text [ portuguese ] = "CONTAR.NÚMEROS" ;
+ Text [ finnish ] = "COUNT" ;
+ Text [ danish ] = "TÆL" ;
+ Text [ french ] = "NB" ;
+ Text [ swedish ] = "ANTAL" ;
+ Text [ dutch ] = "AANTAL" ;
+ Text [ spanish ] = "CONTAR" ;
+ Text [ english_us ] = "COUNT" ;
+ Text[ chinese_simplified ] = "COUNT";
+ Text[ russian ] = "Ñ×ÅÒ";
+ Text[ polish ] = "ILE.LICZB";
+ Text[ japanese ] = "COUNT";
+ Text[ chinese_traditional ] = "COUNT";
+ Text[ arabic ] = "COUNT";
+ Text[ dutch ] = "AANTAL";
+ Text[ chinese_simplified ] = "COUNT";
+ Text[ greek ] = "COUNT";
+ Text[ korean ] = "COUNT";
+ Text[ turkish ] = "COUNT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_COUNT_2
+ {
+ Text = "ANZAHL2" ;
+ Text [ english ] = "COUNTA" ;
+ Text [ norwegian ] = "COUNTA" ;
+ Text [ italian ] = "CONTA.VALORI" ;
+ Text [ portuguese_brazilian ] = "CONT.VALORES" ;
+ Text [ portuguese ] = "CONTAR.VAL" ;
+ Text [ finnish ] = "COUNTA" ;
+ Text [ danish ] = "TÆLV" ;
+ Text [ french ] = "NBVAL" ;
+ Text [ swedish ] = "ANTALV" ;
+ Text [ dutch ] = "AANTALARG" ;
+ Text [ spanish ] = "CONTARA" ;
+ Text [ english_us ] = "COUNTA" ;
+ Text[ chinese_simplified ] = "COUNTA";
+ Text[ russian ] = "Ñ×ÅÒ2";
+ Text[ polish ] = "ILE.NIEPUSTYCH";
+ Text[ japanese ] = "COUNTA";
+ Text[ chinese_traditional ] = "COUNTA";
+ Text[ arabic ] = "COUNTA";
+ Text[ dutch ] = "AANTALARG";
+ Text[ chinese_simplified ] = "COUNTA";
+ Text[ greek ] = "COUNTA";
+ Text[ korean ] = "COUNTA";
+ Text[ turkish ] = "COUNTA";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_NBW
+ {
+ Text = "NBW" ;
+ Text [ english ] = "NPV" ;
+ Text [ norwegian ] = "NPV" ;
+ Text [ italian ] = "VAN" ;
+ Text [ portuguese_brazilian ] = "VPL" ;
+ Text [ portuguese ] = "VPL" ;
+ Text [ finnish ] = "NPV" ;
+ Text [ danish ] = "NUTIDSVÆRDI" ;
+ Text [ french ] = "VAN" ;
+ Text [ swedish ] = "NETNUVÄRDE" ;
+ Text [ dutch ] = "NHW" ;
+ Text [ spanish ] = "VNA" ;
+ Text [ english_us ] = "NPV" ;
+ Text[ chinese_simplified ] = "NPV";
+ Text[ russian ] = "ÍÏÇ";
+ Text[ polish ] = "NPW";
+ Text[ japanese ] = "NPV";
+ Text[ chinese_traditional ] = "NPV";
+ Text[ arabic ] = "NPV";
+ Text[ dutch ] = "NHW";
+ Text[ chinese_simplified ] = "NPV";
+ Text[ greek ] = "NPV";
+ Text[ korean ] = "NPV";
+ Text[ turkish ] = "NPV";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_IKV
+ {
+ Text = "IKV" ;
+ Text [ english ] = "IRR" ;
+ Text [ norwegian ] = "IRR" ;
+ Text [ italian ] = "TIR.COST" ;
+ Text [ portuguese_brazilian ] = "TIR" ;
+ Text [ portuguese ] = "TIR" ;
+ Text [ finnish ] = "IRR" ;
+ Text [ danish ] = "IA" ;
+ Text [ french ] = "TRI" ;
+ Text [ swedish ] = "IR" ;
+ Text [ dutch ] = "IR" ;
+ Text [ spanish ] = "TIR" ;
+ Text [ english_us ] = "IRR" ;
+ Text[ chinese_simplified ] = "IRR";
+ Text[ russian ] = "ÂÍÄÎÕ";
+ Text[ polish ] = "IRR";
+ Text[ japanese ] = "IRR";
+ Text[ chinese_traditional ] = "IRR";
+ Text[ arabic ] = "IRR";
+ Text[ dutch ] = "IR";
+ Text[ chinese_simplified ] = "IRR";
+ Text[ greek ] = "IRR";
+ Text[ korean ] = "IRR";
+ Text[ turkish ] = "IRR";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_VAR
+ {
+ Text = "VARIANZ" ;
+ Text [ english ] = "VAR" ;
+ Text [ norwegian ] = "VAR" ;
+ Text [ italian ] = "VAR" ;
+ Text [ portuguese_brazilian ] = "VAR" ;
+ Text [ portuguese ] = "VAR" ;
+ Text [ finnish ] = "VAR" ;
+ Text [ danish ] = "VARIANS" ;
+ Text [ french ] = "VAR" ;
+ Text [ swedish ] = "VARIANS" ;
+ Text [ dutch ] = "VAR" ;
+ Text [ spanish ] = "VAR" ;
+ Text [ english_us ] = "VAR" ;
+ Text[ chinese_simplified ] = "VAR";
+ Text[ russian ] = "ÄÈÑÏ";
+ Text[ polish ] = "WARIANCJA";
+ Text[ japanese ] = "VAR";
+ Text[ chinese_traditional ] = "VAR";
+ Text[ arabic ] = "VAR";
+ Text[ dutch ] = "VAR";
+ Text[ chinese_simplified ] = "VAR";
+ Text[ greek ] = "VAR";
+ Text[ korean ] = "VAR";
+ Text[ turkish ] = "VAR";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_VAR_A
+ {
+ Text = "VARIANZA" ;
+ Text [ english ] = "VARA" ;
+ Text [ norwegian ] = "VARA" ;
+ Text [ italian ] = "VAR.VALORI" ;
+ Text [ portuguese_brazilian ] = "VARA" ;
+ Text [ portuguese ] = "VARA" ;
+ Text [ finnish ] = "VARA" ;
+ Text [ danish ] = "VARIANSV" ;
+ Text [ french ] = "VARA" ;
+ Text [ swedish ] = "VARIANSA" ;
+ Text [ dutch ] = "VARA" ;
+ Text [ spanish ] = "VARA" ;
+ Text [ english_us ] = "VARA" ;
+ Text[ chinese_simplified ] = "VARA";
+ Text[ russian ] = "ÄÈÑÏÀ";
+ Text[ polish ] = "WARIANCJA.A";
+ Text[ japanese ] = "VARA";
+ Text[ chinese_traditional ] = "VARA";
+ Text[ arabic ] = "VARA";
+ Text[ dutch ] = "VARA";
+ Text[ chinese_simplified ] = "VARA";
+ Text[ greek ] = "VARA";
+ Text[ korean ] = "VARA";
+ Text[ turkish ] = "VARA";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_VAR_P
+ {
+ Text = "VARIANZEN" ;
+ Text [ english ] = "VARP" ;
+ Text [ norwegian ] = "VARP" ;
+ Text [ italian ] = "VAR.POP" ;
+ Text [ portuguese_brazilian ] = "VARP" ;
+ Text [ portuguese ] = "VARP" ;
+ Text [ finnish ] = "VARP" ;
+ Text [ danish ] = "VARIANSP" ;
+ Text [ french ] = "VAR.P" ;
+ Text [ swedish ] = "VARIANSP" ;
+ Text [ dutch ] = "VARP" ;
+ Text [ spanish ] = "VARP" ;
+ Text [ english_us ] = "VARP" ;
+ Text[ chinese_simplified ] = "VARP";
+ Text[ russian ] = "ÄÈÑÏÐ";
+ Text[ polish ] = "WARIANCJA.POPUL";
+ Text[ japanese ] = "VARP";
+ Text[ chinese_traditional ] = "VARP";
+ Text[ arabic ] = "VARP";
+ Text[ dutch ] = "VARP";
+ Text[ chinese_simplified ] = "VARP";
+ Text[ greek ] = "VARP";
+ Text[ korean ] = "VARP";
+ Text[ turkish ] = "VARP";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_VAR_P_A
+ {
+ Text = "VARIANZENA" ;
+ Text [ english ] = "VARPA" ;
+ Text [ norwegian ] = "VARPA" ;
+ Text [ italian ] = "VAR.POP.VALORI" ;
+ Text [ portuguese_brazilian ] = "VARPA" ;
+ Text [ portuguese ] = "VARPA" ;
+ Text [ finnish ] = "VARPA" ;
+ Text [ danish ] = "VARIANSNV" ;
+ Text [ french ] = "VAR.PA" ;
+ Text [ swedish ] = "VARIANSPA" ;
+ Text [ dutch ] = "VARPA" ;
+ Text [ spanish ] = "VARPA" ;
+ Text [ english_us ] = "VARPA" ;
+ Text[ chinese_simplified ] = "VARPA";
+ Text[ russian ] = "ÄÈÑÏÐÀ";
+ Text[ polish ] = "WARIANCJA.POPUL.A";
+ Text[ japanese ] = "VARPA";
+ Text[ chinese_traditional ] = "VARPA";
+ Text[ arabic ] = "VARPA";
+ Text[ dutch ] = "VARPA";
+ Text[ chinese_simplified ] = "VARPA";
+ Text[ greek ] = "VARPA";
+ Text[ korean ] = "VARPA";
+ Text[ turkish ] = "VARPA";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ST_DEV
+ {
+ Text = "STABW" ;
+ Text [ english ] = "STDEV" ;
+ Text [ norwegian ] = "STAVV" ;
+ Text [ italian ] = "DEV.ST" ;
+ Text [ portuguese_brazilian ] = "DESVPAD" ;
+ Text [ portuguese ] = "DESV.PAD" ;
+ Text [ finnish ] = "STDEV" ;
+ Text [ danish ] = "STDAFV" ;
+ Text [ french ] = "ECARTYPE" ;
+ Text [ swedish ] = "STDAV" ;
+ Text [ dutch ] = "STDEV" ;
+ Text [ spanish ] = "DESVEST" ;
+ Text [ english_us ] = "STDEV" ;
+ Text[ chinese_simplified ] = "STDEV";
+ Text[ russian ] = "ÑÒÀÍÄÎÒÊËÎÍ";
+ Text[ polish ] = "ODCH.STANDARDOWE";
+ Text[ japanese ] = "STDEV";
+ Text[ chinese_traditional ] = "STDEV";
+ Text[ arabic ] = "STDEV";
+ Text[ dutch ] = "STDEV";
+ Text[ chinese_simplified ] = "STDEV";
+ Text[ greek ] = "STDEV";
+ Text[ korean ] = "STDEV";
+ Text[ turkish ] = "STDEV";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ST_DEV_A
+ {
+ Text = "STABWA" ;
+ Text [ english ] = "STDEVA" ;
+ Text [ norwegian ] = "STAVVA" ;
+ Text [ italian ] = "DEV.ST.VALORI" ;
+ Text [ portuguese_brazilian ] = "DESVPADA" ;
+ Text [ portuguese ] = "DESV.PADA" ;
+ Text [ finnish ] = "STDEVA" ;
+ Text [ danish ] = "STDAFVV" ;
+ Text [ french ] = "ECARTYPEA" ;
+ Text [ swedish ] = "STDAVA" ;
+ Text [ dutch ] = "STDEVA" ;
+ Text [ spanish ] = "DESVESTA" ;
+ Text [ english_us ] = "STDEVA" ;
+ Text[ chinese_simplified ] = "STDEVA";
+ Text[ russian ] = "ÑÒÀÍÄÎÒÊËÎÍÀ";
+ Text[ polish ] = "ODCH.STANDARDOWE.A";
+ Text[ japanese ] = "STDEVA";
+ Text[ chinese_traditional ] = "STDEVA";
+ Text[ arabic ] = "STDEVA";
+ Text[ dutch ] = "STDEVA";
+ Text[ chinese_simplified ] = "STDEVA";
+ Text[ greek ] = "STDEVA";
+ Text[ korean ] = "STDEVA";
+ Text[ turkish ] = "STDEVA";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ST_DEV_P
+ {
+ Text = "STABWN" ;
+ Text [ english ] = "STDEVP" ;
+ Text [ norwegian ] = "STAVVP" ;
+ Text [ italian ] = "DEV.ST.POP" ;
+ Text [ portuguese_brazilian ] = "STDEVP" ;
+ Text [ portuguese ] = "DESV.PAD.P" ;
+ Text [ finnish ] = "STDEVP" ;
+ Text [ danish ] = "STDAFVP" ;
+ Text [ french ] = "ECARTYPEP" ;
+ Text [ swedish ] = "STDAVP" ;
+ Text [ dutch ] = "STDEVP" ;
+ Text [ spanish ] = "DESVESTP" ;
+ Text [ english_us ] = "STDEVP" ;
+ Text[ chinese_simplified ] = "STDEVP";
+ Text[ russian ] = "ÑÒÀÍÄÎÒÊËÎÍÏ";
+ Text[ polish ] = "ODCH.STANDARD.POPUL";
+ Text[ japanese ] = "STDEVP";
+ Text[ chinese_traditional ] = "STDEVP";
+ Text[ arabic ] = "STDEVP";
+ Text[ dutch ] = "STDEVP";
+ Text[ chinese_simplified ] = "STDEVP";
+ Text[ greek ] = "STDEVP";
+ Text[ korean ] = "STDEVP";
+ Text[ turkish ] = "STDEVP";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ST_DEV_P_A
+ {
+ Text = "STABWNA" ;
+ Text [ english ] = "STDEVPA" ;
+ Text [ norwegian ] = "STAVVPA" ;
+ Text [ italian ] = "DEV.ST.POP.VALORI" ;
+ Text [ portuguese_brazilian ] = "STDEVPA" ;
+ Text [ portuguese ] = "DESV.PAD.PA" ;
+ Text [ finnish ] = "STDEVPA" ;
+ Text [ danish ] = "STDAFVPV" ;
+ Text [ french ] = "ECARTYPEPA" ;
+ Text [ swedish ] = "STDAVPA" ;
+ Text [ dutch ] = "STDEVPA" ;
+ Text [ spanish ] = "DESVESTPA" ;
+ Text [ english_us ] = "STDEVPA" ;
+ Text[ chinese_simplified ] = "STDEVPA";
+ Text[ russian ] = "ÑÒÀÍÄÎÒÊËÎÍÏÀ";
+ Text[ polish ] = "ODCH.STANDARDOWE.POPUL.A";
+ Text[ japanese ] = "STDEVPA";
+ Text[ chinese_traditional ] = "STDEVPA";
+ Text[ arabic ] = "STDEVPA";
+ Text[ dutch ] = "STDEVPA";
+ Text[ chinese_simplified ] = "STDEVPA";
+ Text[ greek ] = "STDEVPA";
+ Text[ korean ] = "STDEVPA";
+ Text[ turkish ] = "STDEVPA";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_B { Text = "B" ; };
+ String SC_OPCODE_NORM_DIST
+ {
+ Text = "NORMVERT" ;
+ Text [ english ] = "NORMDIST" ;
+ Text [ norwegian ] = "NORMDIST" ;
+ Text [ italian ] = "DISTRIB.NORM" ;
+ Text [ portuguese_brazilian ] = "NORMDIST" ;
+ Text [ portuguese ] = "DIST.NORM" ;
+ Text [ finnish ] = "NORMDIST" ;
+ Text [ danish ] = "NORMFORDELING" ;
+ Text [ french ] = "LOI.NORMALE" ;
+ Text [ swedish ] = "NORMFÖRD" ;
+ Text [ dutch ] = "NORM.VERD" ;
+ Text [ spanish ] = "DISTR.NORM" ;
+ Text [ english_us ] = "NORMDIST" ;
+ Text[ chinese_simplified ] = "NORMDIST";
+ Text[ russian ] = "ÍÎÐÌÐÀÑÏ";
+ Text[ polish ] = "ROZK£AD";
+ Text[ japanese ] = "NORMDIST";
+ Text[ chinese_traditional ] = "NORMDIST";
+ Text[ arabic ] = "NORMDIST";
+ Text[ dutch ] = "NORM.VERD";
+ Text[ chinese_simplified ] = "NORMDIST";
+ Text[ greek ] = "NORMDIST";
+ Text[ korean ] = "NORMDIST";
+ Text[ turkish ] = "NORMDIST";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_EXP_DIST
+ {
+ Text = "EXPONVERT" ;
+ Text [ english ] = "EXPONDIST" ;
+ Text [ norwegian ] = "EXPONDIST" ;
+ Text [ italian ] = "DISTRIB.EXP" ;
+ Text [ portuguese_brazilian ] = "EXPONDIST" ;
+ Text [ portuguese ] = "DIST.EXPON" ;
+ Text [ finnish ] = "EXPONDIST" ;
+ Text [ danish ] = "EKSPFORDELING" ;
+ Text [ french ] = "LOI.EXPONENTIELLE" ;
+ Text [ swedish ] = "EXPONFÖRD" ;
+ Text [ dutch ] = "EXPON.VERD" ;
+ Text [ spanish ] = "DISTR.EXP" ;
+ Text [ english_us ] = "EXPONDIST" ;
+ Text[ chinese_simplified ] = "EXPONDIST";
+ Text[ russian ] = "ÝÊÑÏÐÀÑÏ";
+ Text[ polish ] = "ROZK£AD.EXP";
+ Text[ japanese ] = "EXPONDIST";
+ Text[ chinese_traditional ] = "EXPONDIST";
+ Text[ arabic ] = "EXPONDIST";
+ Text[ dutch ] = "EXPON.VERD";
+ Text[ chinese_simplified ] = "EXPONDIST";
+ Text[ greek ] = "EXPONDIST";
+ Text[ korean ] = "EXPONDIST";
+ Text[ turkish ] = "EXPONDIST";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_BINOM_DIST
+ {
+ Text = "BINOMVERT" ;
+ Text [ english ] = "BINOMDIST" ;
+ Text [ norwegian ] = "BINOMDIST" ;
+ Text [ italian ] = "DISTRIB.BINOM" ;
+ Text [ portuguese_brazilian ] = "BINOMDIST" ;
+ Text [ portuguese ] = "DISTR.BINOM" ;
+ Text [ finnish ] = "BINOMDIST" ;
+ Text [ danish ] = "BINOMINALFORDELING" ;
+ Text [ french ] = "LOI.BINOMIALE" ;
+ Text [ swedish ] = "BINOMFÖRD" ;
+ Text [ dutch ] = "BINOMIALE.VERD" ;
+ Text [ spanish ] = "DISTR.BINOM" ;
+ Text [ english_us ] = "BINOMDIST" ;
+ Text[ chinese_simplified ] = "BINOMDIST";
+ Text[ russian ] = "ÁÈÍÎÌÐÀÑÏ";
+ Text[ polish ] = "ROZK£AD.DWUM";
+ Text[ japanese ] = "BINOMDIST";
+ Text[ chinese_traditional ] = "BINOMDIST";
+ Text[ arabic ] = "BINOMDIST";
+ Text[ dutch ] = "BINOMIALE.VERD";
+ Text[ chinese_simplified ] = "BINOMDIST";
+ Text[ greek ] = "BINOMDIST";
+ Text[ korean ] = "BINOMDIST";
+ Text[ turkish ] = "BINOMDIST";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_POISSON_DIST
+ {
+ Text = "POISSON" ;
+ Text [ english ] = "POISSON" ;
+ Text [ norwegian ] = "POISSON" ;
+ Text [ italian ] = "POISSON" ;
+ Text [ portuguese_brazilian ] = "POISSON" ;
+ Text [ portuguese ] = "POISSON" ;
+ Text [ finnish ] = "POISSON" ;
+ Text [ danish ] = "POISSON" ;
+ Text [ french ] = "LOI.POISSON" ;
+ Text [ swedish ] = "POISSON" ;
+ Text [ dutch ] = "POISSON" ;
+ Text [ spanish ] = "POISSON" ;
+ Text [ english_us ] = "POISSON" ;
+ Text[ chinese_simplified ] = "POISSON";
+ Text[ russian ] = "ÏÓÀÑÑÎÍ";
+ Text[ polish ] = "ROZK£AD.POISSON";
+ Text[ japanese ] = "POISSON";
+ Text[ chinese_traditional ] = "POISSON";
+ Text[ arabic ] = "POISSON";
+ Text[ dutch ] = "POISSON";
+ Text[ chinese_simplified ] = "POISSON";
+ Text[ greek ] = "POISSON";
+ Text[ korean ] = "POISSON";
+ Text[ turkish ] = "POISSON";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_KOMBIN
+ {
+ Text = "KOMBINATIONEN" ;
+ Text [ english ] = "COMBIN" ;
+ Text [ norwegian ] = "COMBIN" ;
+ Text [ italian ] = "COMBINAZIONE" ;
+ Text [ portuguese_brazilian ] = "COMBIN" ;
+ Text [ portuguese ] = "COMBIN" ;
+ Text [ finnish ] = "COMBIN" ;
+ Text [ danish ] = "KOMBIN" ;
+ Text [ french ] = "COMBIN" ;
+ Text [ swedish ] = "KOMBIN" ;
+ Text [ dutch ] = "COMBINATIES" ;
+ Text [ spanish ] = "COMBINAR" ;
+ Text [ english_us ] = "COMBIN" ;
+ Text[ chinese_simplified ] = "COMBIN";
+ Text[ russian ] = "×ÈÑËÊÎÌÁ";
+ Text[ polish ] = "KOMBINACJE";
+ Text[ japanese ] = "COMBIN";
+ Text[ chinese_traditional ] = "COMBIN";
+ Text[ arabic ] = "COMBIN";
+ Text[ dutch ] = "COMBINATIES";
+ Text[ chinese_simplified ] = "COMBIN";
+ Text[ greek ] = "COMBIN";
+ Text[ korean ] = "COMBIN";
+ Text[ turkish ] = "COMBIN";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_KOMBIN_2
+ {
+ Text = "KOMBINATIONEN2" ;
+ Text [ english ] = "COMBINA" ;
+ Text [ norwegian ] = "COMBINA" ;
+ Text [ italian ] = "COMBINA" ;
+ Text [ portuguese_brazilian ] = "COMBINA" ;
+ Text [ portuguese ] = "COMBIN2" ;
+ Text [ finnish ] = "COMBINA" ;
+ Text [ danish ] = "KOMBIN2" ;
+ Text [ french ] = "COMBINA" ;
+ Text [ swedish ] = "KOMBIN2" ;
+ Text [ dutch ] = "COMBINATIES2" ;
+ Text [ spanish ] = "COMBINAR2" ;
+ Text [ english_us ] = "COMBINA" ;
+ Text[ chinese_simplified ] = "COMBINA";
+ Text[ russian ] = "×ÈÑËÊÎÌÁ2";
+ Text[ polish ] = "KOMBINACJE2";
+ Text[ japanese ] = "COMBINA";
+ Text[ chinese_traditional ] = "COMBINA";
+ Text[ arabic ] = "COMBINA";
+ Text[ dutch ] = "COMBINATIES2";
+ Text[ chinese_simplified ] = "COMBINA";
+ Text[ greek ] = "COMBINA";
+ Text[ korean ] = "COMBINA";
+ Text[ turkish ] = "COMBINA";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_VARIATIONEN
+ {
+ Text = "VARIATIONEN" ;
+ Text [ english ] = "PERMUT" ;
+ Text [ norwegian ] = "PERMUT" ;
+ Text [ italian ] = "PERMUTAZIONE" ;
+ Text [ portuguese_brazilian ] = "PERMUT" ;
+ Text [ portuguese ] = "PERMUTAÇÃO" ;
+ Text [ finnish ] = "PERMUT" ;
+ Text [ danish ] = "PERMUT" ;
+ Text [ french ] = "PERMUTATION" ;
+ Text [ swedish ] = "PERMUT" ;
+ Text [ dutch ] = "PERMUTATIES" ;
+ Text [ spanish ] = "PERMUTACIONES" ;
+ Text [ english_us ] = "PERMUT" ;
+ Text[ chinese_simplified ] = "PERMUT";
+ Text[ russian ] = "ÏÅÐÅÑÒ";
+ Text[ polish ] = "PERMUTACJE";
+ Text[ japanese ] = "PERMUT";
+ Text[ chinese_traditional ] = "PERMUT";
+ Text[ arabic ] = "PERMUT";
+ Text[ dutch ] = "PERMUTATIES";
+ Text[ chinese_simplified ] = "PERMUT";
+ Text[ greek ] = "PERMUT";
+ Text[ korean ] = "PERMUT";
+ Text[ turkish ] = "PERMUT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_VARIATIONEN_2
+ {
+ Text = "VARIATIONEN2" ;
+ Text [ english ] = "PERMUTATIONA" ;
+ Text [ norwegian ] = "PERMUTA" ;
+ Text [ italian ] = "PERMUTATIONA" ;
+ Text [ portuguese_brazilian ] = "PERMUTA" ;
+ Text [ portuguese ] = "COMBIN" ;
+ Text [ finnish ] = "PERMUTA" ;
+ Text [ danish ] = "PERMUT2" ;
+ Text [ french ] = "PERMUTATIONA" ;
+ Text [ swedish ] = "PERMUT2" ;
+ Text [ dutch ] = "PERMUTATIES2" ;
+ Text [ spanish ] = "PERMUTACIONESA" ;
+ Text [ english_us ] = "PERMUTATIONA" ;
+ Text[ chinese_simplified ] = "PERMUTATIONA";
+ Text[ russian ] = "ÏÅÐÅÑÒ2";
+ Text[ polish ] = "PERMUTACJE2";
+ Text[ japanese ] = "PERMUTATIONA";
+ Text[ chinese_traditional ] = "PERMUTATIONA";
+ Text[ arabic ] = "PERMUTATIONA";
+ Text[ dutch ] = "PERMUTATIES2";
+ Text[ chinese_simplified ] = "PERMUTATIONA";
+ Text[ greek ] = "PERMUTATIONA";
+ Text[ korean ] = "PERMUTATIONA";
+ Text[ turkish ] = "PERMUTATIONA";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_BW
+ {
+ Text = "BW" ;
+ Text [ english ] = "PV" ;
+ Text [ norwegian ] = "PV" ;
+ Text [ italian ] = "VA" ;
+ Text [ portuguese_brazilian ] = "PV" ;
+ Text [ portuguese ] = "VA" ;
+ Text [ finnish ] = "PV" ;
+ Text [ danish ] = "NV" ;
+ Text [ french ] = "VA" ;
+ Text [ swedish ] = "NUVÄRDE" ;
+ Text [ dutch ] = "HW" ;
+ Text [ spanish ] = "VA" ;
+ Text [ english_us ] = "PV" ;
+ Text[ chinese_simplified ] = "PV";
+ Text[ russian ] = "ÏÇ";
+ Text[ polish ] = "PV";
+ Text[ japanese ] = "PV";
+ Text[ chinese_traditional ] = "PV";
+ Text[ arabic ] = "PV";
+ Text[ dutch ] = "HW";
+ Text[ chinese_simplified ] = "PV";
+ Text[ greek ] = "PV";
+ Text[ korean ] = "PV";
+ Text[ turkish ] = "PV";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_DIA
+ {
+ Text = "DIA" ;
+ Text [ english ] = "SYD" ;
+ Text [ norwegian ] = "SYD" ;
+ Text [ italian ] = "AMMORT.ANNUO" ;
+ Text [ portuguese_brazilian ] = "SDA" ;
+ Text [ portuguese ] = "SYD" ;
+ Text [ finnish ] = "SYD" ;
+ Text [ danish ] = "ÅRSAFSKRIVNING" ;
+ Text [ french ] = "SYD" ;
+ Text [ swedish ] = "ÅRSAVSKR" ;
+ Text [ dutch ] = "SYD" ;
+ Text [ spanish ] = "SYD" ;
+ Text [ english_us ] = "SYD" ;
+ Text[ chinese_simplified ] = "SYD";
+ Text[ russian ] = "ÀÌÃÄ";
+ Text[ polish ] = "SYD";
+ Text[ japanese ] = "SYD";
+ Text[ chinese_traditional ] = "SYD";
+ Text[ arabic ] = "SYD";
+ Text[ dutch ] = "SYD";
+ Text[ chinese_simplified ] = "SYD";
+ Text[ greek ] = "SYD";
+ Text[ korean ] = "SYD";
+ Text[ turkish ] = "SYD";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GDA
+ {
+ Text = "GDA" ;
+ Text [ english ] = "DDB" ;
+ Text [ norwegian ] = "DDB" ;
+ Text [ italian ] = "AMMORT" ;
+ Text [ portuguese_brazilian ] = "BDD" ;
+ Text [ portuguese ] = "BDD" ;
+ Text [ finnish ] = "DDB" ;
+ Text [ danish ] = "DSA" ;
+ Text [ french ] = "DDB" ;
+ Text [ swedish ] = "DEGAVSKR" ;
+ Text [ dutch ] = "DDB" ;
+ Text [ spanish ] = "DDB" ;
+ Text [ english_us ] = "DDB" ;
+ Text[ chinese_simplified ] = "DDB";
+ Text[ russian ] = "ÄÄÎÁ";
+ Text[ polish ] = "DDB";
+ Text[ japanese ] = "DDB";
+ Text[ chinese_traditional ] = "DDB";
+ Text[ arabic ] = "DDB";
+ Text[ dutch ] = "DDB";
+ Text[ chinese_simplified ] = "DDB";
+ Text[ greek ] = "DDB";
+ Text[ korean ] = "DDB";
+ Text[ turkish ] = "DDB";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GDA_2
+ {
+ Text = "GDA2" ;
+ Text [ english ] = "DB" ;
+ Text [ norwegian ] = "DB" ;
+ Text [ italian ] = "AMMORT.FISSO" ;
+ Text [ portuguese_brazilian ] = "BD" ;
+ Text [ portuguese ] = "BD" ;
+ Text [ finnish ] = "DB" ;
+ Text [ danish ] = "DB" ;
+ Text [ french ] = "DB" ;
+ Text [ swedish ] = "DB" ;
+ Text [ dutch ] = "DB" ;
+ Text [ spanish ] = "DB" ;
+ Text [ english_us ] = "DB" ;
+ Text[ chinese_simplified ] = "DB";
+ Text[ russian ] = "ÄÎÁ";
+ Text[ polish ] = "DB";
+ Text[ japanese ] = "DB";
+ Text[ chinese_traditional ] = "DB";
+ Text[ arabic ] = "DB";
+ Text[ dutch ] = "DB";
+ Text[ chinese_simplified ] = "DB";
+ Text[ greek ] = "DB";
+ Text[ korean ] = "DB";
+ Text[ turkish ] = "DB";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_VBD
+ {
+ Text = "VDB" ;
+ Text [ english ] = "VDB" ;
+ Text [ norwegian ] = "VDB" ;
+ Text [ italian ] = "AMMORT.VAR" ;
+ Text [ portuguese_brazilian ] = "BDV" ;
+ Text [ portuguese ] = "BDV" ;
+ Text [ finnish ] = "VDB" ;
+ Text [ danish ] = "VSA" ;
+ Text [ french ] = "VDB" ;
+ Text [ swedish ] = "VDEGAVSKR" ;
+ Text [ dutch ] = "VDB" ;
+ Text [ spanish ] = "DVS" ;
+ Text [ english_us ] = "VDB" ;
+ Text[ chinese_simplified ] = "VDB";
+ Text[ russian ] = "ÏÄÎÁ";
+ Text[ polish ] = "VDB";
+ Text[ japanese ] = "VDB";
+ Text[ chinese_traditional ] = "VDB";
+ Text[ arabic ] = "VDB";
+ Text[ dutch ] = "VDB";
+ Text[ chinese_simplified ] = "VDB";
+ Text[ greek ] = "VDB";
+ Text[ korean ] = "VDB";
+ Text[ turkish ] = "VDB";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_LAUFZ
+ {
+ Text = "LAUFZEIT" ;
+ Text [ english ] = "DURATION" ;
+ Text [ norwegian ] = "VARIGHET" ;
+ Text [ italian ] = "DURATA" ;
+ Text [ portuguese_brazilian ] = "DURATION" ;
+ Text [ portuguese ] = "DURAÇÃO" ;
+ Text [ finnish ] = "DURATION" ;
+ Text [ danish ] = "VARIGHED" ;
+ Text [ french ] = "DUREE" ;
+ Text [ swedish ] = "LÖPTID" ;
+ Text [ dutch ] = "DUUR" ;
+ Text [ spanish ] = "PLAZO" ;
+ Text [ english_us ] = "DURATION" ;
+ Text[ chinese_simplified ] = "DURATION";
+ Text[ russian ] = "ÏÐÎÄÎËÆÈÒ";
+ Text[ polish ] = "CZAS TRWANIA";
+ Text[ japanese ] = "DURATION";
+ Text[ chinese_traditional ] = "DURATION";
+ Text[ arabic ] = "DURATION";
+ Text[ dutch ] = "DUUR";
+ Text[ chinese_simplified ] = "DURATION";
+ Text[ greek ] = "DURATION";
+ Text[ korean ] = "DURATION";
+ Text[ turkish ] = "DURATION";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_LIA
+ {
+ Text = "LIA" ;
+ Text [ english ] = "SLN" ;
+ Text [ norwegian ] = "SLN" ;
+ Text [ italian ] = "AMMORT.COST" ;
+ Text [ portuguese_brazilian ] = "DPD" ;
+ Text [ portuguese ] = "AMORLINC" ;
+ Text [ finnish ] = "SLN" ;
+ Text [ danish ] = "LA" ;
+ Text [ french ] = "AMORLIN" ;
+ Text [ swedish ] = "LINAVSKR" ;
+ Text [ dutch ] = "LIN.AFSCHR" ;
+ Text [ spanish ] = "SLN" ;
+ Text [ english_us ] = "SLN" ;
+ Text[ chinese_simplified ] = "SLN";
+ Text[ russian ] = "ÀÌÐ";
+ Text[ polish ] = "SLN";
+ Text[ japanese ] = "SLN";
+ Text[ chinese_traditional ] = "SLN";
+ Text[ arabic ] = "SLN";
+ Text[ dutch ] = "LIN.AFSCHR";
+ Text[ chinese_simplified ] = "SLN";
+ Text[ greek ] = "SLN";
+ Text[ korean ] = "SLN";
+ Text[ turkish ] = "SLN";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_RMZ
+ {
+ Text = "RMZ" ;
+ Text [ english ] = "PMT" ;
+ Text [ norwegian ] = "PMT" ;
+ Text [ italian ] = "RATA" ;
+ Text [ portuguese_brazilian ] = "PGTO" ;
+ Text [ portuguese ] = "PGTO" ;
+ Text [ finnish ] = "PMT" ;
+ Text [ danish ] = "YDELSE" ;
+ Text [ french ] = "VPM" ;
+ Text [ swedish ] = "BETALNING" ;
+ Text [ dutch ] = "RMB" ;
+ Text [ spanish ] = "PAGO" ;
+ Text [ english_us ] = "PMT" ;
+ Text[ chinese_simplified ] = "PMT";
+ Text[ russian ] = "ÏÏËÀÒ";
+ Text[ polish ] = "PMT";
+ Text[ japanese ] = "PMT";
+ Text[ chinese_traditional ] = "PMT";
+ Text[ arabic ] = "PMT";
+ Text[ dutch ] = "RMB";
+ Text[ chinese_simplified ] = "PMT";
+ Text[ greek ] = "PMT";
+ Text[ korean ] = "PMT";
+ Text[ turkish ] = "PMT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_COLUMNS
+ {
+ Text = "SPALTEN" ;
+ Text [ english ] = "COLUMNS" ;
+ Text [ norwegian ] = "KOLONNER" ;
+ Text [ italian ] = "COLONNE" ;
+ Text [ portuguese_brazilian ] = "COLUNAS" ;
+ Text [ portuguese ] = "COLUNAS" ;
+ Text [ finnish ] = "COLUMNS" ;
+ Text [ danish ] = "KOLONNER" ;
+ Text [ french ] = "COLONNES" ;
+ Text [ swedish ] = "KOLUMNER" ;
+ Text [ dutch ] = "KOLOMMEN" ;
+ Text [ spanish ] = "COLUMNAS" ;
+ Text [ english_us ] = "COLUMNS" ;
+ Text[ chinese_simplified ] = "COLUMNS";
+ Text[ russian ] = "×ÈÑËÑÒÎËÁ";
+ Text[ polish ] = "KOLUMNY";
+ Text[ japanese ] = "COLUMNS";
+ Text[ chinese_traditional ] = "COLUMNS";
+ Text[ arabic ] = "COLUMNS";
+ Text[ dutch ] = "KOLOMMEN";
+ Text[ chinese_simplified ] = "COLUMNS";
+ Text[ greek ] = "COLUMNS";
+ Text[ korean ] = "COLUMNS";
+ Text[ turkish ] = "COLUMNS";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ROWS
+ {
+ Text = "ZEILEN" ;
+ Text [ english ] = "ROWS" ;
+ Text [ norwegian ] = "RADER" ;
+ Text [ italian ] = "RIGHE" ;
+ Text [ portuguese_brazilian ] = "LINHAS" ;
+ Text [ portuguese ] = "LINHAS" ;
+ Text [ finnish ] = "ROWS" ;
+ Text [ danish ] = "RÆKKER" ;
+ Text [ french ] = "LIGNES" ;
+ Text [ swedish ] = "RADER" ;
+ Text [ dutch ] = "RIJEN" ;
+ Text [ spanish ] = "FILAS" ;
+ Text [ english_us ] = "ROWS" ;
+ Text[ chinese_simplified ] = "ROWS";
+ Text[ russian ] = "×ÑÒÐÎÊ";
+ Text[ polish ] = "WIERSZE";
+ Text[ japanese ] = "ROWS";
+ Text[ chinese_traditional ] = "ROWS";
+ Text[ arabic ] = "ROWS";
+ Text[ dutch ] = "RIJEN";
+ Text[ chinese_simplified ] = "ROWS";
+ Text[ greek ] = "ROWS";
+ Text[ korean ] = "ROWS";
+ Text[ turkish ] = "ROWS";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_TABLES
+ {
+ Text = "TABELLEN" ;
+ Text [ english ] = "SHEETS" ;
+ Text [ portuguese ] = "FOLHAS" ;
+ Text [ english_us ] = "SHEETS" ;
+ Text [ portuguese_brazilian ] = "TABELLEN" ;
+ Text [ swedish ] = "TABELLER" ;
+ Text [ danish ] = "TABELLER" ;
+ Text [ italian ] = "TABELLE" ;
+ Text [ spanish ] = "HOJAS" ;
+ Text [ french ] = "FEUILLES" ;
+ Text [ dutch ] = "TABELLEN" ;
+ Text[ chinese_simplified ] = "SHEETS";
+ Text[ russian ] = "ËÈÑÒÛ";
+ Text[ polish ] = "ARKUSZE";
+ Text[ japanese ] = "SHEETS";
+ Text[ chinese_traditional ] = "SHEETS";
+ Text[ arabic ] = "SHEETS";
+ Text[ dutch ] = "TABELLEN";
+ Text[ chinese_simplified ] = "SHEETS";
+ Text[ greek ] = "SHEETS";
+ Text[ korean ] = "SHEETS";
+ Text[ turkish ] = "SHEETS";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_COLUMN
+ {
+ Text = "SPALTE" ;
+ Text [ english ] = "COLUMN" ;
+ Text [ norwegian ] = "KOLONNE" ;
+ Text [ italian ] = "RIF.COLONNA" ;
+ Text [ portuguese_brazilian ] = "COLUNA" ;
+ Text [ portuguese ] = "COLUNA" ;
+ Text [ finnish ] = "COLUMN" ;
+ Text [ danish ] = "KOLONNE" ;
+ Text [ french ] = "COLONNE" ;
+ Text [ swedish ] = "KOLUMN" ;
+ Text [ dutch ] = "KOLOM" ;
+ Text [ spanish ] = "COLUMNA" ;
+ Text [ english_us ] = "COLUMN" ;
+ Text[ chinese_simplified ] = "COLUMN";
+ Text[ russian ] = "ÑÒÎËÁÅÖ";
+ Text[ polish ] = "KOLUMNA";
+ Text[ japanese ] = "COLUMN";
+ Text[ chinese_traditional ] = "COLUMN";
+ Text[ arabic ] = "COLUMN";
+ Text[ dutch ] = "KOLOM";
+ Text[ chinese_simplified ] = "COLUMN";
+ Text[ greek ] = "COLUMN";
+ Text[ korean ] = "COLUMN";
+ Text[ turkish ] = "COLUMN";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ROW
+ {
+ Text = "ZEILE" ;
+ Text [ english ] = "ROW" ;
+ Text [ norwegian ] = "RAD" ;
+ Text [ italian ] = "RIF.RIGA" ;
+ Text [ portuguese_brazilian ] = "LINHA" ;
+ Text [ portuguese ] = "LINHA" ;
+ Text [ finnish ] = "ROW" ;
+ Text [ danish ] = "RÆKKE" ;
+ Text [ french ] = "LIGNE" ;
+ Text [ swedish ] = "RAD" ;
+ Text [ dutch ] = "RIJ" ;
+ Text [ spanish ] = "FILA" ;
+ Text [ english_us ] = "ROW" ;
+ Text[ chinese_simplified ] = "ROW";
+ Text[ russian ] = "ÑÒÐÎÊÀ";
+ Text[ polish ] = "WIERSZ";
+ Text[ japanese ] = "ROW";
+ Text[ chinese_traditional ] = "ROW";
+ Text[ arabic ] = "ROW";
+ Text[ dutch ] = "RIJ";
+ Text[ chinese_simplified ] = "ROW";
+ Text[ greek ] = "ROW";
+ Text[ korean ] = "ROW";
+ Text[ turkish ] = "ROW";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_TABLE
+ {
+ Text = "TABELLE" ;
+ Text [ english ] = "SHEET" ;
+ Text [ portuguese ] = "FOLHA" ;
+ Text [ english_us ] = "SHEET" ;
+ Text [ portuguese_brazilian ] = "TABELLE" ;
+ Text [ swedish ] = "TABELL" ;
+ Text [ danish ] = "TABEL" ;
+ Text [ italian ] = "TABELLA" ;
+ Text [ spanish ] = "HOJA" ;
+ Text [ french ] = "FEUILLE" ;
+ Text [ dutch ] = "TABEL" ;
+ Text[ chinese_simplified ] = "SHEET";
+ Text[ russian ] = "ËÈÑÒ";
+ Text[ polish ] = "ARKUSZ";
+ Text[ japanese ] = "SHEET";
+ Text[ chinese_traditional ] = "SHEET";
+ Text[ arabic ] = "SHEET";
+ Text[ dutch ] = "TABEL";
+ Text[ chinese_simplified ] = "SHEET";
+ Text[ greek ] = "SHEET";
+ Text[ korean ] = "SHEET";
+ Text[ turkish ] = "SHEET";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ZGZ
+ {
+ Text = "ZGZ" ;
+ Text [ english ] = "ZGZ" ;
+ Text [ portuguese ] = "ZGZ" ;
+ Text [ english_us ] = "RRI" ;
+ Text [ portuguese_brazilian ] = "ZGZ" ;
+ Text [ swedish ] = "ZGZ" ;
+ Text [ danish ] = "RRI" ;
+ Text [ italian ] = "ZGZ" ;
+ Text [ spanish ] = "ZGZ" ;
+ Text [ french ] = "RENTINVEST" ;
+ Text [ dutch ] = "ZGZ" ;
+ Text[ chinese_simplified ] = "ZGZ";
+ Text[ russian ] = "ÃÏÑ";
+ Text[ polish ] = "ZGZ";
+ Text[ japanese ] = "ZGZ";
+ Text[ chinese_traditional ] = "ZGZ";
+ Text[ arabic ] = "ZGZ";
+ Text[ dutch ] = "ZGZ";
+ Text[ chinese_simplified ] = "ZGZ";
+ Text[ greek ] = "ZGZ";
+ Text[ korean ] = "ZGZ";
+ Text[ turkish ] = "ZGZ";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ZW
+ {
+ Text = "ZW" ;
+ Text [ english ] = "FV" ;
+ Text [ norwegian ] = "FV" ;
+ Text [ italian ] = "VAL.FUT" ;
+ Text [ portuguese_brazilian ] = "VF" ;
+ Text [ portuguese ] = "VF" ;
+ Text [ finnish ] = "FV" ;
+ Text [ danish ] = "FV" ;
+ Text [ french ] = "VC" ;
+ Text [ swedish ] = "SLUTVÄRDE" ;
+ Text [ dutch ] = "TW" ;
+ Text [ spanish ] = "VF" ;
+ Text [ english_us ] = "FV" ;
+ Text[ chinese_simplified ] = "FV";
+ Text[ russian ] = "ÁÇ";
+ Text[ polish ] = "FV";
+ Text[ japanese ] = "FV";
+ Text[ chinese_traditional ] = "FV";
+ Text[ arabic ] = "FV";
+ Text[ dutch ] = "TW";
+ Text[ chinese_simplified ] = "FV";
+ Text[ greek ] = "FV";
+ Text[ korean ] = "FV";
+ Text[ turkish ] = "FV";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ZZR
+ {
+ Text = "ZZR" ;
+ Text [ english ] = "NPER" ;
+ Text [ norwegian ] = "NPER" ;
+ Text [ italian ] = "NUM.RATE" ;
+ Text [ portuguese_brazilian ] = "NPER" ;
+ Text [ portuguese ] = "NPER" ;
+ Text [ finnish ] = "NPER" ;
+ Text [ danish ] = "NPER" ;
+ Text [ french ] = "NPM" ;
+ Text [ swedish ] = "PERIODER" ;
+ Text [ dutch ] = "NPER" ;
+ Text [ spanish ] = "NPER" ;
+ Text [ english_us ] = "NPER" ;
+ Text[ chinese_simplified ] = "NPER";
+ Text[ russian ] = "ÊÏÅÐ";
+ Text[ polish ] = "LICZBA_RAT";
+ Text[ japanese ] = "NPER";
+ Text[ chinese_traditional ] = "NPER";
+ Text[ arabic ] = "NPER";
+ Text[ dutch ] = "NPER";
+ Text[ chinese_simplified ] = "NPER";
+ Text[ greek ] = "NPER";
+ Text[ korean ] = "NPER";
+ Text[ turkish ] = "NPER";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ZINS
+ {
+ Text = "ZINS" ;
+ Text [ english ] = "RATE" ;
+ Text [ norwegian ] = "RATE" ;
+ Text [ italian ] = "TASSO" ;
+ Text [ portuguese_brazilian ] = "TAXA" ;
+ Text [ portuguese ] = "TAXA" ;
+ Text [ finnish ] = "RATE" ;
+ Text [ danish ] = "RENTE" ;
+ Text [ french ] = "TAUX" ;
+ Text [ swedish ] = "RÄNTA" ;
+ Text [ dutch ] = "RENTE" ;
+ Text [ spanish ] = "TASA" ;
+ Text [ english_us ] = "RATE" ;
+ Text[ chinese_simplified ] = "RATE";
+ Text[ russian ] = "ÍÎÐÌÀ";
+ Text[ polish ] = "RATE";
+ Text[ japanese ] = "RATE";
+ Text[ chinese_traditional ] = "RATE";
+ Text[ arabic ] = "RATE";
+ Text[ dutch ] = "RENTE";
+ Text[ chinese_simplified ] = "RATE";
+ Text[ greek ] = "RATE";
+ Text[ korean ] = "RATE";
+ Text[ turkish ] = "RATE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ZINS_Z
+ {
+ Text = "ZINSZ" ;
+ Text [ english ] = "IPMT" ;
+ Text [ norwegian ] = "PPMT" ;
+ Text [ italian ] = "P.RATA" ;
+ Text [ portuguese_brazilian ] = "PPGTO" ;
+ Text [ portuguese ] = "PPGTO" ;
+ Text [ finnish ] = "PPMT" ;
+ Text [ danish ] = "R.YDELSE" ;
+ Text [ french ] = "INTPER" ;
+ Text [ swedish ] = "RBETALNING" ;
+ Text [ dutch ] = "IBET" ;
+ Text [ spanish ] = "PAGOINT" ;
+ Text [ english_us ] = "IPMT" ;
+ Text[ chinese_simplified ] = "IPMT";
+ Text[ russian ] = "ÏËÏÐÎÖ";
+ Text[ polish ] = "PPMT";
+ Text[ japanese ] = "IPMT";
+ Text[ chinese_traditional ] = "IPMT";
+ Text[ arabic ] = "IPMT";
+ Text[ dutch ] = "IBET";
+ Text[ chinese_simplified ] = "IPMT";
+ Text[ greek ] = "IPMT";
+ Text[ korean ] = "IPMT";
+ Text[ turkish ] = "IPMT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_KAPZ
+ {
+ Text = "KAPZ" ;
+ Text [ english ] = "PPMT" ;
+ Text [ norwegian ] = "IPMT" ;
+ Text [ italian ] = "INTERESSI" ;
+ Text [ portuguese_brazilian ] = "IPGTO" ;
+ Text [ portuguese ] = "IPGTO" ;
+ Text [ finnish ] = "IPMT" ;
+ Text [ danish ] = "H.YDELSE" ;
+ Text [ french ] = "PRINCPER" ;
+ Text [ swedish ] = "AMORT" ;
+ Text [ dutch ] = "PBET" ;
+ Text [ spanish ] = "AMORTIZACION" ;
+ Text [ english_us ] = "PPMT" ;
+ Text[ chinese_simplified ] = "PPMT";
+ Text[ russian ] = "ÎÑÍÏËÀÒ";
+ Text[ polish ] = "IPMT";
+ Text[ japanese ] = "PPMT";
+ Text[ chinese_traditional ] = "PPMT";
+ Text[ arabic ] = "PPMT";
+ Text[ dutch ] = "PBET";
+ Text[ chinese_simplified ] = "PPMT";
+ Text[ greek ] = "PPMT";
+ Text[ korean ] = "PPMT";
+ Text[ turkish ] = "PPMT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_KUM_ZINS_Z
+ {
+ Text = "KUMZINSZ" ;
+ Text [ english ] = "CUMIPMT" ;
+ Text [ norwegian ] = "CUMPPMT" ;
+ Text [ italian ] = "INT.CUMUL" ;
+ Text [ portuguese_brazilian ] = "CUMPPMT" ;
+ Text [ portuguese ] = "PGTO.JUR.ACUM" ;
+ Text [ finnish ] = "CUMPPMT" ;
+ Text [ danish ] = "AKKUM.RENTE" ;
+ Text [ french ] = "CUMUL.INTER" ;
+ Text [ swedish ] = "KUMRÄNTA" ;
+ Text [ dutch ] = "CUM.RENTE" ;
+ Text [ spanish ] = "PAGO.INT.ENTRE" ;
+ Text [ english_us ] = "CUMIPMT" ;
+ Text[ chinese_simplified ] = "CUMIPMT";
+ Text[ russian ] = "ÎÁÙÏËÀÒÀ";
+ Text[ polish ] = "CUMIPMT";
+ Text[ japanese ] = "CUMIPMT";
+ Text[ chinese_traditional ] = "CUMIPMT";
+ Text[ arabic ] = "CUMIPMT";
+ Text[ dutch ] = "CUM.RENTE";
+ Text[ chinese_simplified ] = "CUMIPMT";
+ Text[ greek ] = "CUMIPMT";
+ Text[ korean ] = "CUMIPMT";
+ Text[ turkish ] = "CUMIPMT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_KUM_KAP_Z
+ {
+ Text = "KUMKAPITAL" ;
+ Text [ english ] = "CUMPRINC" ;
+ Text [ norwegian ] = "CUMIPMT" ;
+ Text [ italian ] = "CAP.CUM" ;
+ Text [ portuguese_brazilian ] = "CUMIPMT" ;
+ Text [ portuguese ] = "PGTO.CAP.ACUM" ;
+ Text [ finnish ] = "CUMIPMT" ;
+ Text [ danish ] = "AKKUM.HOVEDSTOL" ;
+ Text [ french ] = "CUMUL.PRINCPER" ;
+ Text [ swedish ] = "KUMKAPITAL" ;
+ Text [ dutch ] = "CUM.HOOFDSOM" ;
+ Text [ spanish ] = "PAGO.PRINC.ENTRE" ;
+ Text [ english_us ] = "CUMPRINC" ;
+ Text[ chinese_simplified ] = "CUMPRINC";
+ Text[ russian ] = "ÎÁÙÄÎÕÎÄ";
+ Text[ polish ] = "CUMIPMT";
+ Text[ japanese ] = "CUMPRINC";
+ Text[ chinese_traditional ] = "CUMPRINC";
+ Text[ arabic ] = "CUMPRINC";
+ Text[ dutch ] = "CUM.HOOFDSOM";
+ Text[ chinese_simplified ] = "CUMPRINC";
+ Text[ greek ] = "CUMPRINC";
+ Text[ korean ] = "CUMPRINC";
+ Text[ turkish ] = "CUMPRINC";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_EFFEKTIV
+ {
+ Text = "EFFEKTIV" ;
+ Text [ english ] = "EFFECTIVE" ;
+ Text [ norwegian ] = "EFFEKTIV" ;
+ Text [ italian ] = "EFFETTIVO" ;
+ Text [ portuguese_brazilian ] = "EFETIVO" ;
+ Text [ portuguese ] = "EFECTIVA" ;
+ Text [ finnish ] = "EFFECTIVE" ;
+ Text [ danish ] = "EFFEKTIV" ;
+ Text [ french ] = "EFFECTIF" ;
+ Text [ swedish ] = "EFFEKTIV" ;
+ Text [ dutch ] = "EFFECT.RENTE" ;
+ Text [ spanish ] = "INT.EFECTIVO" ;
+ Text [ english_us ] = "EFFECTIVE" ;
+ Text[ chinese_simplified ] = "EFFECTIVE";
+ Text[ russian ] = "ÝÔÔÅÊÒÏÐÎÖ";
+ Text[ polish ] = "EFEKTYWNY";
+ Text[ japanese ] = "EFFECTIVE";
+ Text[ chinese_traditional ] = "EFFECTIVE";
+ Text[ arabic ] = "EFFECTIVE";
+ Text[ dutch ] = "EFFECT.RENTE";
+ Text[ chinese_simplified ] = "EFFECTIVE";
+ Text[ greek ] = "EFFECTIVE";
+ Text[ korean ] = "EFFECTIVE";
+ Text[ turkish ] = "EFFECTIVE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_NOMINAL
+ {
+ Text = "NOMINAL" ;
+ Text [ english ] = "NOMINAL" ;
+ Text [ norwegian ] = "NOMINELL" ;
+ Text [ italian ] = "NOMINALE" ;
+ Text [ portuguese_brazilian ] = "NOMINAL" ;
+ Text [ portuguese ] = "NOMINAL" ;
+ Text [ finnish ] = "NOMINAL" ;
+ Text [ danish ] = "NOMINEL" ;
+ Text [ french ] = "NOMINAL" ;
+ Text [ swedish ] = "NOMINAL" ;
+ Text [ dutch ] = "NOMINALE.RENTE" ;
+ Text [ spanish ] = "TASA.NOMINAL" ;
+ Text [ english_us ] = "NOMINAL" ;
+ Text[ chinese_simplified ] = "NOMINAL";
+ Text[ russian ] = "ÍÎÌÈÍÀË";
+ Text[ polish ] = "NOMINALNY";
+ Text[ japanese ] = "NOMINAL";
+ Text[ chinese_traditional ] = "NOMINAL";
+ Text[ arabic ] = "NOMINAL";
+ Text[ dutch ] = "NOMINALE.RENTE";
+ Text[ chinese_simplified ] = "NOMINAL";
+ Text[ greek ] = "NOMINAL";
+ Text[ korean ] = "NOMINAL";
+ Text[ turkish ] = "NOMINAL";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_SUB_TOTAL
+ {
+ Text = "TEILERGEBNIS" ;
+ Text [ english ] = "SUBTOTAL" ;
+ Text [ norwegian ] = "SUM" ;
+ Text [ italian ] = "SUBTOTALE" ;
+ Text [ portuguese_brazilian ] = "SUBTOTAL" ;
+ Text [ portuguese ] = "SUBTOTAL" ;
+ Text [ finnish ] = "SUBTOTAL" ;
+ Text [ danish ] = "SUBTOTAL" ;
+ Text [ french ] = "SOUS.TOTAL" ;
+ Text [ swedish ] = "DELRESULTAT" ;
+ Text [ dutch ] = "SUBTOTAAL" ;
+ Text [ spanish ] = "SUBTOTALES" ;
+ Text [ english_us ] = "SUBTOTAL" ;
+ Text[ chinese_simplified ] = "SUBTOTAL";
+ Text[ russian ] = "ÈÒÎÃ";
+ Text[ polish ] = "SUMY.POŒREDNIE";
+ Text[ japanese ] = "SUBTOTAL";
+ Text[ chinese_traditional ] = "SUBTOTAL";
+ Text[ arabic ] = "SUBTOTAL";
+ Text[ dutch ] = "SUBTOTAAL";
+ Text[ chinese_simplified ] = "SUBTOTAL";
+ Text[ greek ] = "SUBTOTAL";
+ Text[ korean ] = "SUBTOTAL";
+ Text[ turkish ] = "SUBTOTAL";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_DB_SUM
+ {
+ Text = "DBSUMME" ;
+ Text [ english ] = "DSUM" ;
+ Text [ norwegian ] = "DSUM" ;
+ Text [ italian ] = "DB.SOMMA" ;
+ Text [ portuguese_brazilian ] = "BDSOMA" ;
+ Text [ portuguese ] = "BDSOMA" ;
+ Text [ finnish ] = "DSUM" ;
+ Text [ danish ] = "DSUM" ;
+ Text [ french ] = "BDSOMME" ;
+ Text [ swedish ] = "DSUMMA" ;
+ Text [ dutch ] = "DBSOM" ;
+ Text [ spanish ] = "BDSUMA" ;
+ Text [ english_us ] = "DSUM" ;
+ Text[ chinese_simplified ] = "DSUM";
+ Text[ russian ] = "ÁÄÑÓÌÌ";
+ Text[ polish ] = "BD.SUMA";
+ Text[ japanese ] = "DSUM";
+ Text[ chinese_traditional ] = "DSUM";
+ Text[ arabic ] = "DSUM";
+ Text[ dutch ] = "DBSOM";
+ Text[ chinese_simplified ] = "DSUM";
+ Text[ greek ] = "DSUM";
+ Text[ korean ] = "DSUM";
+ Text[ turkish ] = "DSUM";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_DB_COUNT
+ {
+ Text = "DBANZAHL" ;
+ Text [ english ] = "DCOUNT" ;
+ Text [ norwegian ] = "DCOUNT" ;
+ Text [ italian ] = "DB.CONTA.NUMERI" ;
+ Text [ portuguese_brazilian ] = "BDCONTAR" ;
+ Text [ portuguese ] = "BDCONTAR" ;
+ Text [ finnish ] = "DCOUNT" ;
+ Text [ danish ] = "DTÆL" ;
+ Text [ french ] = "BDNB" ;
+ Text [ swedish ] = "DANTAL" ;
+ Text [ dutch ] = "DBAANTAL" ;
+ Text [ spanish ] = "BDCONTAR" ;
+ Text [ english_us ] = "DCOUNT" ;
+ Text[ chinese_simplified ] = "DCOUNT";
+ Text[ russian ] = "ÁÑ×ÅÒ";
+ Text[ polish ] = "BD.ILE.REKORDÓW";
+ Text[ japanese ] = "DCOUNT";
+ Text[ chinese_traditional ] = "DCOUNT";
+ Text[ arabic ] = "DCOUNT";
+ Text[ dutch ] = "DBAANTAL";
+ Text[ chinese_simplified ] = "DCOUNT";
+ Text[ greek ] = "DCOUNT";
+ Text[ korean ] = "DCOUNT";
+ Text[ turkish ] = "DBCOUNT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_DB_COUNT_2
+ {
+ Text = "DBANZAHL2" ;
+ Text [ english ] = "DCOUNTA" ;
+ Text [ norwegian ] = "DCOUNTA" ;
+ Text [ italian ] = "DB.CONTA.VALORI" ;
+ Text [ portuguese_brazilian ] = "DCONTAGEMA" ;
+ Text [ portuguese ] = "BDCONTAR.VAL" ;
+ Text [ finnish ] = "DCOUNTA" ;
+ Text [ danish ] = "DTÆLV" ;
+ Text [ french ] = "BDNBVAL" ;
+ Text [ swedish ] = "DANTALV" ;
+ Text [ dutch ] = "DBAANTALC" ;
+ Text [ spanish ] = "BDCONTARA" ;
+ Text [ english_us ] = "DCOUNTA" ;
+ Text[ chinese_simplified ] = "DCOUNTA";
+ Text[ russian ] = "ÁÑ×ÅÒ2";
+ Text[ polish ] = "BD.ILE.REKORDÓW.A";
+ Text[ japanese ] = "DCOUNTA";
+ Text[ chinese_traditional ] = "DCOUNTA";
+ Text[ arabic ] = "DCOUNTA";
+ Text[ dutch ] = "DBAANTALC";
+ Text[ chinese_simplified ] = "DCOUNTA";
+ Text[ greek ] = "DCOUNTA";
+ Text[ korean ] = "DCOUNTA";
+ Text[ turkish ] = "DCOUNTA";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_DB_AVERAGE
+ {
+ Text = "DBMITTELWERT" ;
+ Text [ english ] = "DAVERAGE" ;
+ Text [ norwegian ] = "DAVERAGE" ;
+ Text [ italian ] = "DB.MEDIA" ;
+ Text [ portuguese_brazilian ] = "BDMÉDIA" ;
+ Text [ portuguese ] = "BDMÉDIA" ;
+ Text [ finnish ] = "DAVERAGE" ;
+ Text [ danish ] = "DMIDDEL" ;
+ Text [ french ] = "BDMOYENNE" ;
+ Text [ swedish ] = "DMEDEL" ;
+ Text [ dutch ] = "DBGEMIDDELDE" ;
+ Text [ spanish ] = "BDPROMEDIO" ;
+ Text [ english_us ] = "DAVERAGE" ;
+ Text[ chinese_simplified ] = "DAVERAGE";
+ Text[ russian ] = "ÄÑÐÇÍÀ×";
+ Text[ polish ] = "BD.ŒREDNIA";
+ Text[ japanese ] = "DAVERAGE";
+ Text[ chinese_traditional ] = "DAVERAGE";
+ Text[ arabic ] = "DAVERAGE";
+ Text[ dutch ] = "DBGEMIDDELDE";
+ Text[ chinese_simplified ] = "DAVERAGE";
+ Text[ greek ] = "DAVERAGE";
+ Text[ korean ] = "DAVERAGE";
+ Text[ turkish ] = "DAVERAGE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_DB_GET
+ {
+ Text = "DBAUSZUG" ;
+ Text [ english ] = "DGET" ;
+ Text [ norwegian ] = "DGET" ;
+ Text [ italian ] = "DB.VALORI" ;
+ Text [ portuguese_brazilian ] = "BDEXTRAIR" ;
+ Text [ portuguese ] = "BDOBTER" ;
+ Text [ finnish ] = "DGET" ;
+ Text [ danish ] = "DHENT" ;
+ Text [ french ] = "BDLIRE" ;
+ Text [ swedish ] = "DHÄMTA" ;
+ Text [ dutch ] = "DBLEZEN" ;
+ Text [ spanish ] = "BDEXTRAER" ;
+ Text [ english_us ] = "DGET" ;
+ Text[ chinese_simplified ] = "DGET";
+ Text[ russian ] = "ÁÈÇÂËÅ×Ü";
+ Text[ polish ] = "BD.POLE";
+ Text[ japanese ] = "DGET";
+ Text[ chinese_traditional ] = "DGET";
+ Text[ arabic ] = "DGET";
+ Text[ dutch ] = "DBLEZEN";
+ Text[ chinese_simplified ] = "DGET";
+ Text[ greek ] = "DGET";
+ Text[ korean ] = "DGET";
+ Text[ turkish ] = "DGET";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_DB_MAX
+ {
+ Text = "DBMAX" ;
+ Text [ english ] = "DMAX" ;
+ Text [ norwegian ] = "DMAX" ;
+ Text [ italian ] = "DB.MAX" ;
+ Text [ portuguese_brazilian ] = "BDMAX" ;
+ Text [ portuguese ] = "BDMÁX" ;
+ Text [ finnish ] = "DMAX" ;
+ Text [ danish ] = "DMAKS" ;
+ Text [ french ] = "BDMAX" ;
+ Text [ swedish ] = "DMAX" ;
+ Text [ dutch ] = "DBMAX" ;
+ Text [ spanish ] = "BDMAX" ;
+ Text [ english_us ] = "DMAX" ;
+ Text[ chinese_simplified ] = "DMAX";
+ Text[ russian ] = "ÄÌÀÊÑ";
+ Text[ polish ] = "BD.MAX";
+ Text[ japanese ] = "DMAX";
+ Text[ chinese_traditional ] = "DMAX";
+ Text[ arabic ] = "DMAX";
+ Text[ dutch ] = "DBMAX";
+ Text[ chinese_simplified ] = "DMAX";
+ Text[ greek ] = "DMAX";
+ Text[ korean ] = "DMAX";
+ Text[ turkish ] = "DMAX";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_DB_MIN
+ {
+ Text = "DBMIN" ;
+ Text [ english ] = "DMIN" ;
+ Text [ norwegian ] = "DMIN" ;
+ Text [ italian ] = "DB.MIN" ;
+ Text [ portuguese_brazilian ] = "BDMIN" ;
+ Text [ portuguese ] = "BDMIN" ;
+ Text [ finnish ] = "DMIN" ;
+ Text [ danish ] = "DMIN" ;
+ Text [ french ] = "BDMIN" ;
+ Text [ swedish ] = "DMIN" ;
+ Text [ dutch ] = "DBMIN" ;
+ Text [ spanish ] = "BDMIN" ;
+ Text [ english_us ] = "DMIN" ;
+ Text[ chinese_simplified ] = "DMIN";
+ Text[ russian ] = "ÄÌÈÍ";
+ Text[ polish ] = "BD.MIN";
+ Text[ japanese ] = "DMIN";
+ Text[ chinese_traditional ] = "DMIN";
+ Text[ arabic ] = "DMIN";
+ Text[ dutch ] = "DBMIN";
+ Text[ chinese_simplified ] = "DMIN";
+ Text[ greek ] = "DMIN";
+ Text[ korean ] = "DMIN";
+ Text[ turkish ] = "DMIN";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_DB_PRODUCT
+ {
+ Text = "DBPRODUKT" ;
+ Text [ english ] = "DPRODUCT" ;
+ Text [ norwegian ] = "DPRODUKT" ;
+ Text [ italian ] = "DB.PRODOTTO" ;
+ Text [ portuguese_brazilian ] = "DMULTIPL" ;
+ Text [ portuguese ] = "DMULTIPL" ;
+ Text [ finnish ] = "DPRODUCT" ;
+ Text [ danish ] = "DPRODUKT" ;
+ Text [ french ] = "BDPRODUIT" ;
+ Text [ swedish ] = "DPRODUKT" ;
+ Text [ dutch ] = "DBPRODUKT" ;
+ Text [ spanish ] = "BDPRODUCTO" ;
+ Text [ english_us ] = "DPRODUCT" ;
+ Text[ chinese_simplified ] = "DPRODUCT";
+ Text[ russian ] = "ÁÄÏÐÎÈÇÂÅÄ";
+ Text[ polish ] = "BD.ILOCZYN";
+ Text[ japanese ] = "DPRODUKT";
+ Text[ chinese_traditional ] = "DPRODUCT";
+ Text[ arabic ] = "DPRODUCT";
+ Text[ dutch ] = "DBPRODUKT";
+ Text[ chinese_simplified ] = "DPRODUCT";
+ Text[ greek ] = "DPRODUCT";
+ Text[ korean ] = "DPRODUCT";
+ Text[ turkish ] = "DPRODUCT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_DB_STD_DEV
+ {
+ Text = "DBSTDABW" ;
+ Text [ english ] = "DSTDEV" ;
+ Text [ norwegian ] = "DSTDEV" ;
+ Text [ italian ] = "DB.DEV.ST" ;
+ Text [ portuguese_brazilian ] = "BDEST" ;
+ Text [ portuguese ] = "BDDESVPAD" ;
+ Text [ finnish ] = "DSTDEV" ;
+ Text [ danish ] = "DSTAFV" ;
+ Text [ french ] = "BDECARTYPE" ;
+ Text [ swedish ] = "DSTDAV" ;
+ Text [ dutch ] = "DBSTDEV" ;
+ Text [ spanish ] = "BDDESVEST" ;
+ Text [ english_us ] = "DSTDEV" ;
+ Text[ chinese_simplified ] = "DSTDEV";
+ Text[ russian ] = "ÄÑÒÀÍÄÎÒÊË";
+ Text[ polish ] = "BD.ODCH.STANDARD";
+ Text[ japanese ] = "DSTDEV";
+ Text[ chinese_traditional ] = "DSTDEV";
+ Text[ arabic ] = "DSTDEV";
+ Text[ dutch ] = "DBSTDEV";
+ Text[ chinese_simplified ] = "DSTDEV";
+ Text[ greek ] = "DSTDEV";
+ Text[ korean ] = "DSTDEV";
+ Text[ turkish ] = "DSTDEV";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_DB_STD_DEV_P
+ {
+ Text = "DBSTDABWN" ;
+ Text [ english ] = "DSTDEVP" ;
+ Text [ norwegian ] = "DSTDEVP" ;
+ Text [ italian ] = "DB.DEV.ST.POP" ;
+ Text [ portuguese_brazilian ] = "BDDESVPA" ;
+ Text [ portuguese ] = "BDDESVPADP" ;
+ Text [ finnish ] = "DSTDEVP" ;
+ Text [ danish ] = "DSTAFVP" ;
+ Text [ french ] = "BDECARTYPEP" ;
+ Text [ swedish ] = "DSTDAVP" ;
+ Text [ dutch ] = "DBSTDEVP" ;
+ Text [ spanish ] = "BDDESVESTP" ;
+ Text [ english_us ] = "DSTDEVP" ;
+ Text[ chinese_simplified ] = "DSTDEVP";
+ Text[ russian ] = "ÄÑÒÀÍÄÎÒÊËÏ";
+ Text[ polish ] = "BD.ODCH.STANDARD.POPUL";
+ Text[ japanese ] = "DSTDEVP";
+ Text[ chinese_traditional ] = "DSTDEVP";
+ Text[ arabic ] = "DSTDEVP";
+ Text[ dutch ] = "DBSTDEVP";
+ Text[ chinese_simplified ] = "DSTDEVP";
+ Text[ greek ] = "DSTDEVP";
+ Text[ korean ] = "DSTDEVP";
+ Text[ turkish ] = "DSTDEVP";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_DB_VAR
+ {
+ Text = "DBVARIANZ" ;
+ Text [ english ] = "DVAR" ;
+ Text [ norwegian ] = "DVAR" ;
+ Text [ italian ] = "DB.VAR" ;
+ Text [ portuguese_brazilian ] = "BDVAREST" ;
+ Text [ portuguese ] = "BDVAR" ;
+ Text [ finnish ] = "DVAR" ;
+ Text [ danish ] = "DVARIANS" ;
+ Text [ french ] = "BDVAR" ;
+ Text [ swedish ] = "DVARIANS" ;
+ Text [ dutch ] = "DBVAR" ;
+ Text [ spanish ] = "BDVAR" ;
+ Text [ english_us ] = "DVAR" ;
+ Text[ chinese_simplified ] = "DVAR";
+ Text[ russian ] = "ÁÄÄÈÑÏ";
+ Text[ polish ] = "BD.WARIANCJA";
+ Text[ japanese ] = "DVAR";
+ Text[ chinese_traditional ] = "DVAR";
+ Text[ arabic ] = "DVAR";
+ Text[ dutch ] = "DBVAR";
+ Text[ chinese_simplified ] = "DVAR";
+ Text[ greek ] = "DVAR";
+ Text[ korean ] = "DVAR";
+ Text[ turkish ] = "DVAR";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_DB_VAR_P
+ {
+ Text = "DBVARIANZEN" ;
+ Text [ english ] = "DVARP" ;
+ Text [ norwegian ] = "DVARP" ;
+ Text [ italian ] = "DB.VAR.POP" ;
+ Text [ portuguese_brazilian ] = "BDVARP" ;
+ Text [ portuguese ] = "BDVARP" ;
+ Text [ finnish ] = "DVARP" ;
+ Text [ danish ] = "DVARIANSP" ;
+ Text [ french ] = "BDVARP" ;
+ Text [ swedish ] = "DVARIANSP" ;
+ Text [ dutch ] = "DBVARP" ;
+ Text [ spanish ] = "BDVARP" ;
+ Text [ english_us ] = "DVARP" ;
+ Text[ chinese_simplified ] = "DVARP";
+ Text[ russian ] = "ÁÄÄÈÑÏÏ";
+ Text[ polish ] = "BD.WARIANCJA.POPUL";
+ Text[ japanese ] = "DVARP";
+ Text[ chinese_traditional ] = "DVARP";
+ Text[ arabic ] = "DVARP";
+ Text[ dutch ] = "DBVARP";
+ Text[ chinese_simplified ] = "DVARP";
+ Text[ greek ] = "DVARP";
+ Text[ korean ] = "DVARP";
+ Text[ turkish ] = "DVARP";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_INDIRECT
+ {
+ Text = "INDIREKT" ;
+ Text [ english ] = "INDIRECT" ;
+ Text [ norwegian ] = "INDIREKT" ;
+ Text [ italian ] = "INDIRETTO" ;
+ Text [ portuguese_brazilian ] = "INDIRETO" ;
+ Text [ portuguese ] = "INDIRECTO" ;
+ Text [ finnish ] = "INDIRECT" ;
+ Text [ danish ] = "INDIREKTE" ;
+ Text [ french ] = "INDIRECT" ;
+ Text [ swedish ] = "INDIREKT" ;
+ Text [ dutch ] = "INDIRECT" ;
+ Text [ spanish ] = "INDIRECTO" ;
+ Text [ english_us ] = "INDIRECT" ;
+ Text[ chinese_simplified ] = "INDIRECT";
+ Text[ russian ] = "INDIREKT";
+ Text[ polish ] = "ADR.POŒR";
+ Text[ japanese ] = "INDIREKT";
+ Text[ chinese_traditional ] = "INDIRECT";
+ Text[ arabic ] = "INDIRECT";
+ Text[ dutch ] = "INDIRECT";
+ Text[ chinese_simplified ] = "INDIRECT";
+ Text[ greek ] = "INDIRECT";
+ Text[ korean ] = "INDIRECT";
+ Text[ turkish ] = "INDIRECT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_ADRESS
+ {
+ Text = "ADRESSE" ;
+ Text [ english ] = "ADDRESS" ;
+ Text [ norwegian ] = "ADRESSE" ;
+ Text [ italian ] = "INDIRIZZO" ;
+ Text [ portuguese_brazilian ] = "ENDEREÇO" ;
+ Text [ portuguese ] = "ENDEREÇO" ;
+ Text [ finnish ] = "ADRESS" ;
+ Text [ danish ] = "ADRESSE" ;
+ Text [ french ] = "ADRESSE" ;
+ Text [ swedish ] = "ADRESS" ;
+ Text [ dutch ] = "ADRES" ;
+ Text [ spanish ] = "DIRECCIÓN" ;
+ Text [ english_us ] = "ADDRESS" ;
+ Text[ chinese_simplified ] = "ADDRESS";
+ Text[ russian ] = "ÀÄÐÅÑ";
+ Text[ polish ] = "ADRES";
+ Text[ japanese ] = "ADDRESS";
+ Text[ chinese_traditional ] = "ADDRESS";
+ Text[ arabic ] = "ADDRESS";
+ Text[ dutch ] = "ADRES";
+ Text[ chinese_simplified ] = "ADDRESS";
+ Text[ greek ] = "ADDRESS";
+ Text[ korean ] = "ÁÖ¼Ò";
+ Text[ turkish ] = "ADDRESS";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_MATCH
+ {
+ Text = "VERGLEICH" ;
+ Text [ english ] = "MATCH" ;
+ Text [ norwegian ] = "MATCH" ;
+ Text [ italian ] = "CONFRONTA" ;
+ Text [ portuguese_brazilian ] = "CORRESP" ;
+ Text [ portuguese ] = "CORRESP" ;
+ Text [ finnish ] = "MATCH" ;
+ Text [ danish ] = "SAMMENLIGN" ;
+ Text [ french ] = "EQUIV" ;
+ Text [ swedish ] = "PASSA" ;
+ Text [ dutch ] = "VERGELIJKEN" ;
+ Text [ spanish ] = "COINCIDIR" ;
+ Text [ english_us ] = "MATCH" ;
+ Text[ chinese_simplified ] = "MATCH";
+ Text[ russian ] = "ÏÎÈÑÊÏÎÇ";
+ Text[ polish ] = "DODAJ.POZYCJÊ";
+ Text[ japanese ] = "MATCH";
+ Text[ chinese_traditional ] = "MATCH";
+ Text[ arabic ] = "MATCH";
+ Text[ dutch ] = "VERGELIJKEN";
+ Text[ chinese_simplified ] = "MATCH";
+ Text[ greek ] = "MATCH";
+ Text[ korean ] = "MATCH";
+ Text[ turkish ] = "MATCH";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_COUNT_EMPTY_CELLS
+ {
+ Text = "ANZAHLLEEREZELLEN" ;
+ Text [ english ] = "COUNTBLANK" ;
+ Text [ norwegian ] = "COUNTBLANK" ;
+ Text [ italian ] = "CONTA.VUOTE" ;
+ Text [ portuguese_brazilian ] = "CONTAR.VAZIO" ;
+ Text [ portuguese ] = "CONTAR.VAZIO" ;
+ Text [ finnish ] = "COUNTBLANK" ;
+ Text [ danish ] = "ANTAL.BLANKE" ;
+ Text [ french ] = "NB.VIDE" ;
+ Text [ swedish ] = "ANTAL.TOMMA" ;
+ Text [ dutch ] = "AANTAL.LEGE.CELLEN" ;
+ Text [ spanish ] = "CONTAR.BLANCO" ;
+ Text [ english_us ] = "COUNTBLANK" ;
+ Text[ chinese_simplified ] = "COUNTBLANK";
+ Text[ russian ] = "Ñ×ÈÒÀÒÜÏÓÑÒÎÒÛ";
+ Text[ polish ] = "LICZ.PUSTE";
+ Text[ japanese ] = "COUNTBLANK";
+ Text[ chinese_traditional ] = "COUNTBLANK";
+ Text[ arabic ] = "COUNTBLANK";
+ Text[ dutch ] = "AANTAL.LEGE.CELLEN";
+ Text[ chinese_simplified ] = "COUNTBLANK";
+ Text[ greek ] = "COUNTBLANK";
+ Text[ korean ] = "COUNTBLANK";
+ Text[ turkish ] = "COUNTBLANK";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_COUNT_IF
+ {
+ /* ### ACHTUNG: Neuer Text in Resource? ZÄHLENWENN : ZŽHLENWENN */
+ Text = "ZÄHLENWENN" ;
+ Text [ english ] = "COUNTIF" ;
+ Text [ norwegian ] = "COUNTIF" ;
+ Text [ italian ] = "CONTA.SE" ;
+ Text [ portuguese_brazilian ] = "CONT.SE" ;
+ Text [ portuguese ] = "CONTAR.SE" ;
+ Text [ finnish ] = "COUNTIF" ;
+ Text [ danish ] = "TÆLHVIS" ;
+ Text [ french ] = "NB.SI" ;
+ Text [ swedish ] = "ANTAL.OM" ;
+ Text [ dutch ] = "AANTAL.ALS" ;
+ Text [ spanish ] = "CONTAR.SI" ;
+ Text [ english_us ] = "COUNTIF" ;
+ Text[ chinese_simplified ] = "COUNTIF";
+ Text[ russian ] = "Ñ×ÅÒÅÑËÈ";
+ Text[ polish ] = "LICZ.JE¯ELI";
+ Text[ japanese ] = "COUNTIF";
+ Text[ chinese_traditional ] = "COUNTIF";
+ Text[ arabic ] = "COUNTIF";
+ Text[ dutch ] = "AANTAL.ALS";
+ Text[ chinese_simplified ] = "COUNTIF";
+ Text[ greek ] = "COUNTIF";
+ Text[ korean ] = "COUNTIF";
+ Text[ turkish ] = "COUNTIF";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_SUM_IF
+ {
+ Text = "SUMMEWENN" ;
+ Text [ english ] = "SUMIF" ;
+ Text [ norwegian ] = "SUMIF" ;
+ Text [ italian ] = "SOMMA.SE" ;
+ Text [ portuguese_brazilian ] = "SOMASE" ;
+ Text [ portuguese ] = "SOMA.SE" ;
+ Text [ finnish ] = "SUMIF" ;
+ Text [ danish ] = "SUM.HVIS" ;
+ Text [ french ] = "SOMME.SI" ;
+ Text [ swedish ] = "SUMMA.OM" ;
+ Text [ dutch ] = "SOM.ALS" ;
+ Text [ spanish ] = "SUMAR.SI" ;
+ Text [ english_us ] = "SUMIF" ;
+ Text[ chinese_simplified ] = "SUMIF";
+ Text[ russian ] = "ÑÓÌÌÅÑËÈ";
+ Text[ polish ] = "SUMA.JE¯ELI";
+ Text[ japanese ] = "SUMIF";
+ Text[ chinese_traditional ] = "SUMIF";
+ Text[ arabic ] = "SUMIF";
+ Text[ dutch ] = "SOM.ALS";
+ Text[ chinese_simplified ] = "SUMIF";
+ Text[ greek ] = "SUMIF";
+ Text[ korean ] = "SUMIF";
+ Text[ turkish ] = "SUMIF";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_LOOKUP
+ {
+ Text = "VERWEIS" ;
+ Text [ english ] = "LOOKUP" ;
+ Text [ norwegian ] = "LOOKUP" ;
+ Text [ italian ] = "CERCA" ;
+ Text [ portuguese_brazilian ] = "PROC" ;
+ Text [ portuguese ] = "REFERÊNCIA" ;
+ Text [ finnish ] = "LOOKUP" ;
+ Text [ danish ] = "SLÅ.OP" ;
+ Text [ french ] = "RECHERCHE" ;
+ Text [ swedish ] = "LETAUPP" ;
+ Text [ dutch ] = "ZOEKEN" ;
+ Text [ spanish ] = "BUSCAR" ;
+ Text [ english_us ] = "LOOKUP" ;
+ Text[ chinese_simplified ] = "LOOKUP";
+ Text[ russian ] = "ÏÐÎÑÌÎÒÐ";
+ Text[ polish ] = "WYSZUKAJ";
+ Text[ japanese ] = "LOOKUP";
+ Text[ chinese_traditional ] = "LOOKUP";
+ Text[ arabic ] = "LOOKUP";
+ Text[ dutch ] = "ZOEKEN";
+ Text[ chinese_simplified ] = "LOOKUP";
+ Text[ greek ] = "LOOKUP";
+ Text[ korean ] = "LOOKUP";
+ Text[ turkish ] = "LOOKUP";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_V_LOOKUP
+ {
+ Text = "SVERWEIS" ;
+ Text [ english ] = "VLOOKUP" ;
+ Text [ norwegian ] = "VLOOKUP" ;
+ Text [ italian ] = "CERCA.VERT" ;
+ Text [ portuguese_brazilian ] = "PROCV" ;
+ Text [ portuguese ] = "PROCV" ;
+ Text [ finnish ] = "VLOOKUP" ;
+ Text [ danish ] = "LOPSLAG" ;
+ Text [ french ] = "RECHERCHEV" ;
+ Text [ swedish ] = "LETARAD" ;
+ Text [ dutch ] = "VERT.ZOEKEN" ;
+ Text [ spanish ] = "BUSCARV" ;
+ Text [ english_us ] = "VLOOKUP" ;
+ Text[ chinese_simplified ] = "VLOOKUP";
+ Text[ russian ] = "ÂÏÐ";
+ Text[ polish ] = "WYSZUKAJ.PIONOWO";
+ Text[ japanese ] = "VLOOKUP";
+ Text[ chinese_traditional ] = "VLOOKUP";
+ Text[ arabic ] = "VLOOKUP";
+ Text[ dutch ] = "VERT.ZOEKEN";
+ Text[ chinese_simplified ] = "VLOOKUP";
+ Text[ greek ] = "VLOOKUP";
+ Text[ korean ] = "VLOOKUP";
+ Text[ turkish ] = "VLOOKUP";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_H_LOOKUP
+ {
+ Text = "WVERWEIS" ;
+ Text [ english ] = "HLOOKUP" ;
+ Text [ norwegian ] = "HLOOKUP" ;
+ Text [ italian ] = "CERCA.ORIZZ" ;
+ Text [ portuguese_brazilian ] = "PROCH" ;
+ Text [ portuguese ] = "PROCH" ;
+ Text [ finnish ] = "HLOOKUP" ;
+ Text [ danish ] = "VOPSLAG" ;
+ Text [ french ] = "RECHERCHEH" ;
+ Text [ swedish ] = "LETAKOLUMN" ;
+ Text [ dutch ] = "HORIZ.ZOEKEN" ;
+ Text [ spanish ] = "BUSCARH" ;
+ Text [ english_us ] = "HLOOKUP" ;
+ Text[ chinese_simplified ] = "HLOOKUP";
+ Text[ russian ] = "ÃÏÐ";
+ Text[ polish ] = "WYSZUKAJ.POZIOMO";
+ Text[ japanese ] = "HLOOKUP";
+ Text[ chinese_traditional ] = "HLOOKUP";
+ Text[ arabic ] = "HLOOKUP";
+ Text[ dutch ] = "HORIZ.ZOEKEN";
+ Text[ chinese_simplified ] = "HLOOKUP";
+ Text[ greek ] = "HLOOKUP";
+ Text[ korean ] = "HLOOKUP";
+ Text[ turkish ] = "HLOOKUP";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_MULTI_AREA
+ {
+ Text = "MULTIBEREICH" ;
+ Text [ english ] = "MULTIRANGE" ;
+ Text [ norwegian ] = "FLERSEKTORMULTIRANGE" ;
+ Text [ italian ] = "MULTIRANGE" ;
+ Text [ portuguese_brazilian ] = "MULTIFAIXAS" ;
+ Text [ portuguese ] = "INTERV.MÚLTIPL." ;
+ Text [ finnish ] = "MULTIRANGE" ;
+ Text [ danish ] = "MULTIOMRÅDE" ;
+ Text [ french ] = "MULTIRANGE" ;
+ Text [ swedish ] = "MULTIOMRÅDE" ;
+ Text [ dutch ] = "MULTIBEREIK" ;
+ Text [ spanish ] = "MULTIRANGO" ;
+ Text [ english_us ] = "MULTIRANGE" ;
+ Text[ chinese_simplified ] = "MULTIRANGE";
+ Text[ russian ] = "ÌÓËÜÒÈÎÁËÀÑÒÜ";
+ Text[ polish ] = "MULTIZAKRES";
+ Text[ japanese ] = "MULTIRANGE";
+ Text[ chinese_traditional ] = "MULTIRANGE";
+ Text[ arabic ] = "MULTIRANGE";
+ Text[ dutch ] = "MULTIBEREIK";
+ Text[ chinese_simplified ] = "MULTIRANGE";
+ Text[ greek ] = "MULTIRANGE";
+ Text[ korean ] = "MULTIRANGE";
+ Text[ turkish ] = "MULTIRANGE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_OFFSET
+ {
+ Text = "VERSCHIEBUNG" ;
+ Text [ english ] = "OFFSET" ;
+ Text [ norwegian ] = "FORSKYVNINGOFFSET" ;
+ Text [ italian ] = "SCARTO" ;
+ Text [ portuguese_brazilian ] = "OFFSET" ;
+ Text [ portuguese ] = "DESLOCAMENTO" ;
+ Text [ finnish ] = "OFFSET" ;
+ Text [ danish ] = "FORSKYDNING" ;
+ Text [ french ] = "DECALER" ;
+ Text [ swedish ] = "FÖRSKJUTA" ;
+ Text [ dutch ] = "VERSCHUIVING" ;
+ Text [ spanish ] = "DESREF" ;
+ Text [ english_us ] = "OFFSET" ;
+ Text[ chinese_simplified ] = "OFFSET";
+ Text[ russian ] = "ÑÌÅÙÅÍÈÅ";
+ Text[ polish ] = "PRZESUNIÊCIE";
+ Text[ japanese ] = "OFFSET";
+ Text[ chinese_traditional ] = "OFFSET";
+ Text[ arabic ] = "OFFSET";
+ Text[ dutch ] = "VERSCHUIVING";
+ Text[ chinese_simplified ] = "OFFSET";
+ Text[ greek ] = "OFFSET";
+ Text[ korean ] = "OFFSET";
+ Text[ turkish ] = "OFFSET";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_INDEX
+ {
+ Text = "INDEX" ;
+ Text [ english ] = "INDEX" ;
+ Text [ norwegian ] = "INDEKS" ;
+ Text [ italian ] = "INDICE" ;
+ Text [ portuguese_brazilian ] = "NDICE" ;
+ // ?? erstes Zeichen = I ??
+ Text [ portuguese ] = "ÍNDICE" ;
+ Text [ finnish ] = "INDEX" ;
+ Text [ danish ] = "INDEKS" ;
+ Text [ french ] = "INDICE" ;
+ Text [ swedish ] = "INDEX" ;
+ Text [ dutch ] = "INDEX" ;
+ Text [ spanish ] = "ÍNDICE" ;
+ Text [ english_us ] = "INDEX" ;
+ Text[ chinese_simplified ] = "INDEX";
+ Text[ russian ] = "ÈÍÄÅÊÑ";
+ Text[ polish ] = "INDEKS";
+ Text[ japanese ] = "INDEX";
+ Text[ chinese_traditional ] = "INDEX";
+ Text[ arabic ] = "INDEX";
+ Text[ dutch ] = "INDEX";
+ Text[ chinese_simplified ] = "INDEX";
+ Text[ greek ] = "INDEX";
+ Text[ korean ] = "INDEX";
+ Text[ turkish ] = "INDEX";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_AREAS
+ {
+ Text = "BEREICHE" ;
+ Text [ english ] = "AREAS" ;
+ Text [ norwegian ] = "OMRÅDER" ;
+ Text [ italian ] = "AREE" ;
+ Text [ portuguese_brazilian ] = "AREAS" ;
+ Text [ portuguese ] = "ÁREAS" ;
+ Text [ finnish ] = "AREAS" ;
+ Text [ danish ] = "OMRÅDER" ;
+ Text [ french ] = "ZONES" ;
+ Text [ swedish ] = "OMRÅDEN" ;
+ Text [ dutch ] = "BEREIKEN" ;
+ Text [ spanish ] = "ÁREAS" ;
+ Text [ english_us ] = "AREAS" ;
+ Text[ chinese_simplified ] = "AREAS";
+ Text[ russian ] = "ÎÁËÀÑÒÈ";
+ Text[ polish ] = "OBSZARY";
+ Text[ japanese ] = "AREAS";
+ Text[ chinese_traditional ] = "AREAS";
+ Text[ arabic ] = "AREAS";
+ Text[ dutch ] = "BEREIKEN";
+ Text[ chinese_simplified ] = "AREAS";
+ Text[ greek ] = "AREAS";
+ Text[ korean ] = "AREAS";
+ Text[ turkish ] = "AREAS";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_CURRENCY
+ {
+ Text = "DM" ;
+ Text [ english ] = "DOLLAR" ;
+ Text [ norwegian ] = "DOLLAR" ;
+ Text [ italian ] = "VALUTA" ;
+ Text [ portuguese_brazilian ] = "DÓLAR" ;
+ Text [ portuguese ] = "MOEDA" ;
+ Text [ finnish ] = "DOLLAR" ;
+ Text [ danish ] = "KR" ;
+ Text [ french ] = "FRANC" ;
+ Text [ swedish ] = "VALUTA" ;
+ Text [ dutch ] = "GULDEN" ;
+ Text [ spanish ] = "MONEDA" ;
+ Text [ english_us ] = "DOLLAR" ;
+ Text[ chinese_simplified ] = "RMB";
+ Text[ russian ] = "ÐÓÁËÜ";
+ Text[ polish ] = "KWOTA";
+ Text[ japanese ] = "YEN";
+ Text[ chinese_traditional ] = "DOLLAR";
+ Text[ arabic ] = "DOLLAR";
+ Text[ dutch ] = "GULDEN";
+ Text[ chinese_simplified ] = "RMB";
+ Text[ greek ] = "DOLLAR";
+ Text[ korean ] = "DOLLAR";
+ Text[ turkish ] = "TL";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_REPLACE
+ {
+ Text = "ERSETZEN" ;
+ Text [ english ] = "REPLACE" ;
+ Text [ norwegian ] = "ERSTATTE" ;
+ Text [ italian ] = "RIMPIAZZA" ;
+ Text [ portuguese_brazilian ] = "SUBSTITUIR" ;
+ Text [ portuguese ] = "SUBSTITUIR" ;
+ Text [ finnish ] = "REPLACE" ;
+ Text [ danish ] = "ERSTAT" ;
+ Text [ french ] = "REMPLACER" ;
+ Text [ swedish ] = "ERSÄTT" ;
+ Text [ dutch ] = "VERVANGEN" ;
+ Text [ spanish ] = "REEMPLAZAR" ;
+ Text [ english_us ] = "REPLACE" ;
+ Text[ chinese_simplified ] = "REPLACE";
+ Text[ russian ] = "ÇÀÌÅÍÈÒÜ";
+ Text[ polish ] = "ZAMIEÑ";
+ Text[ japanese ] = "REPLACE";
+ Text[ chinese_traditional ] = "REPLACE";
+ Text[ arabic ] = "REPLACE";
+ Text[ dutch ] = "VERVANGEN";
+ Text[ chinese_simplified ] = "REPLACE";
+ Text[ greek ] = "REPLACE";
+ Text[ korean ] = "REPLACE";
+ Text[ turkish ] = "REPLACE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_FIXED
+ {
+ Text = "FEST" ;
+ Text [ english ] = "FIXED" ;
+ Text [ norwegian ] = "FIXED" ;
+ Text [ italian ] = "FISSO" ;
+ Text [ portuguese_brazilian ] = "FIXO" ;
+ Text [ portuguese ] = "FIXAR" ;
+ Text [ finnish ] = "FIXED" ;
+ Text [ danish ] = "FAST" ;
+ Text [ french ] = "CTXT" ;
+ Text [ swedish ] = "FASTTAL" ;
+ Text [ dutch ] = "VAST" ;
+ Text [ spanish ] = "DECIMAL" ;
+ Text [ english_us ] = "FIXED" ;
+ Text[ chinese_simplified ] = "FIXED";
+ Text[ russian ] = "ÔÈÊÑÈÐÎÂÀÍÍÛÉ";
+ Text[ polish ] = "ZAOKR.DO.TEKST";
+ Text[ japanese ] = "FIXED";
+ Text[ chinese_traditional ] = "FIXED";
+ Text[ arabic ] = "FIXED";
+ Text[ dutch ] = "VAST";
+ Text[ chinese_simplified ] = "FIXED";
+ Text[ greek ] = "FIXED";
+ Text[ korean ] = "FIXED";
+ Text[ turkish ] = "FIXED";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_FIND
+ {
+ Text = "FINDEN" ;
+ Text [ english ] = "FIND" ;
+ Text [ norwegian ] = "FINN" ;
+ Text [ italian ] = "CERCA1" ;
+ Text [ portuguese_brazilian ] = "ENCONTRAR" ;
+ Text [ portuguese ] = "LOCALIZAR" ;
+ Text [ finnish ] = "FIND" ;
+ Text [ danish ] = "FIND" ;
+ Text [ french ] = "TROUVE" ;
+ Text [ swedish ] = "HITTA" ;
+ Text [ dutch ] = "VIND.ALLES" ;
+ Text [ spanish ] = "ENCONTRAR" ;
+ Text [ english_us ] = "FIND" ;
+ Text[ chinese_simplified ] = "FIND";
+ Text[ russian ] = "ÍÀÉÒÈ";
+ Text[ polish ] = "ZNAJD";
+ Text[ japanese ] = "FIND";
+ Text[ chinese_traditional ] = "FIND";
+ Text[ arabic ] = "FIND";
+ Text[ dutch ] = "VIND.ALLES";
+ Text[ chinese_simplified ] = "FIND";
+ Text[ greek ] = "FIND";
+ Text[ korean ] = "FIND";
+ Text[ turkish ] = "FIND";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_EXACT
+ {
+ Text = "IDENTISCH" ;
+ Text [ english ] = "EXACT" ;
+ Text [ norwegian ] = "EXACT" ;
+ Text [ italian ] = "IDENTICO" ;
+ Text [ portuguese_brazilian ] = "EXATO" ;
+ Text [ portuguese ] = "EXACTO" ;
+ Text [ finnish ] = "EXACT" ;
+ Text [ danish ] = "EKSAKT" ;
+ Text [ french ] = "EXACT" ;
+ Text [ swedish ] = "EXAKT" ;
+ Text [ dutch ] = "GELIJK" ;
+ Text [ spanish ] = "IGUAL" ;
+ Text [ english_us ] = "EXACT" ;
+ Text[ chinese_simplified ] = "EXACT";
+ Text[ russian ] = "ÑÎÂÏÀÄ";
+ Text[ polish ] = "IDENTYCZNY";
+ Text[ japanese ] = "EXACT";
+ Text[ chinese_traditional ] = "EXACT";
+ Text[ arabic ] = "EXACT";
+ Text[ dutch ] = "GELIJK";
+ Text[ chinese_simplified ] = "EXACT";
+ Text[ greek ] = "EXACT";
+ Text[ korean ] = "EXACT";
+ Text[ turkish ] = "EXACT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_LEFT
+ {
+ Text = "LINKS" ;
+ Text [ english ] = "LEFT" ;
+ Text [ norwegian ] = "VENSTRE" ;
+ Text [ italian ] = "SINISTRA" ;
+ Text [ portuguese_brazilian ] = "ESQUERDA" ;
+ Text [ portuguese ] = "ESQUERDA" ;
+ Text [ finnish ] = "LEFT" ;
+ Text [ danish ] = "VENSTRE" ;
+ Text [ french ] = "GAUCHE" ;
+ Text [ swedish ] = "VÄNSTER" ;
+ Text [ dutch ] = "LINKS" ;
+ Text [ spanish ] = "IZQUIERDA" ;
+ Text [ english_us ] = "LEFT" ;
+ Text[ chinese_simplified ] = "LEFT";
+ Text[ russian ] = "ËÅÂÑÈÌÂ";
+ Text[ polish ] = "LEWY";
+ Text[ japanese ] = "LEFT";
+ Text[ chinese_traditional ] = "LEFT";
+ Text[ arabic ] = "LEFT";
+ Text[ dutch ] = "LINKS";
+ Text[ chinese_simplified ] = "LEFT";
+ Text[ greek ] = "LEFT";
+ Text[ korean ] = "LEFT";
+ Text[ turkish ] = "LEFT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_RIGHT
+ {
+ Text = "RECHTS" ;
+ Text [ english ] = "RIGHT" ;
+ Text [ norwegian ] = "HØYRE" ;
+ Text [ italian ] = "DESTRA" ;
+ Text [ portuguese_brazilian ] = "DIREITA" ;
+ Text [ portuguese ] = "DIREITA" ;
+ Text [ finnish ] = "RIGHT" ;
+ Text [ danish ] = "HØJRE" ;
+ Text [ french ] = "DROITE" ;
+ Text [ swedish ] = "HÖGER" ;
+ Text [ dutch ] = "RECHTS" ;
+ Text [ spanish ] = "DERECHA" ;
+ Text [ english_us ] = "RIGHT" ;
+ Text[ chinese_simplified ] = "RIGHT";
+ Text[ russian ] = "ÏÐÀÂÑÈÌÂ";
+ Text[ polish ] = "PRAWY";
+ Text[ japanese ] = "RIGHT";
+ Text[ chinese_traditional ] = "RIGHT";
+ Text[ arabic ] = "RIGHT";
+ Text[ dutch ] = "RECHTS";
+ Text[ chinese_simplified ] = "RIGHT";
+ Text[ greek ] = "ÄÅÎÉÁ";
+ Text[ korean ] = "RIGHT";
+ Text[ turkish ] = "RIGHT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_SEARCH
+ {
+ Text = "SUCHEN" ;
+ Text [ english ] = "SEARCH" ;
+ Text [ norwegian ] = "LET" ;
+ Text [ italian ] = "CERCA2" ;
+ Text [ portuguese_brazilian ] = "PROCURAR" ;
+ Text [ portuguese ] = "PROCURAR" ;
+ Text [ finnish ] = "SEARCH" ;
+ Text [ danish ] = "SØG" ;
+ Text [ french ] = "CHERCHE" ;
+ Text [ swedish ] = "SÖK" ;
+ Text [ dutch ] = "VIND.SPEC" ;
+ Text [ spanish ] = "HALLAR" ;
+ Text [ english_us ] = "SEARCH" ;
+ Text[ chinese_simplified ] = "SEARCH";
+ Text[ russian ] = "ÏÎÈÑÊ";
+ Text[ polish ] = "SZUKAJ";
+ Text[ japanese ] = "SEARCH";
+ Text[ chinese_traditional ] = "SEARCH";
+ Text[ arabic ] = "SEARCH";
+ Text[ dutch ] = "VIND.SPEC";
+ Text[ chinese_simplified ] = "SEARCH";
+ Text[ greek ] = "SEARCH";
+ Text[ korean ] = "SEARCH";
+ Text[ turkish ] = "SEARCH";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_MID
+ {
+ Text = "TEIL" ;
+ Text [ english ] = "MID" ;
+ Text [ norwegian ] = "MID" ;
+ Text [ italian ] = "STRINGA.ESTRAI" ;
+ Text [ portuguese_brazilian ] = "MEIO" ;
+ Text [ portuguese ] = "MÉDIA" ;
+ Text [ finnish ] = "MID" ;
+ Text [ danish ] = "MIDT" ;
+ Text [ french ] = "STXT" ;
+ Text [ swedish ] = "EXTEXT" ;
+ Text [ dutch ] = "DEEL" ;
+ Text [ spanish ] = "EXTRAE" ;
+ Text [ english_us ] = "MID" ;
+ Text[ chinese_simplified ] = "MID";
+ Text[ russian ] = "ÏÑÒÐ";
+ Text[ polish ] = "FRAGMENT.TEKSTU";
+ Text[ japanese ] = "MID";
+ Text[ chinese_traditional ] = "MID";
+ Text[ arabic ] = "MID";
+ Text[ dutch ] = "DEEL";
+ Text[ chinese_simplified ] = "MID";
+ Text[ greek ] = "MID";
+ Text[ korean ] = "MID";
+ Text[ turkish ] = "MID";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_TEXT
+ {
+ Text = "TEXT" ;
+ Text [ english ] = "TEXT" ;
+ Text [ norwegian ] = "TEKST" ;
+ Text [ italian ] = "TESTO" ;
+ Text [ portuguese_brazilian ] = "TEXTO" ;
+ Text [ portuguese ] = "TEXTO" ;
+ Text [ finnish ] = "TEXT" ;
+ Text [ danish ] = "TEKST" ;
+ Text [ french ] = "TEXTE" ;
+ Text [ swedish ] = "TEXT" ;
+ Text [ dutch ] = "TEKST" ;
+ Text [ spanish ] = "TEXTO" ;
+ Text [ english_us ] = "TEXT" ;
+ Text[ chinese_simplified ] = "TEXT";
+ Text[ russian ] = "ÒÅÊÑÒ";
+ Text[ polish ] = "TEKST";
+ Text[ japanese ] = "TEXT";
+ Text[ chinese_traditional ] = "TEXT";
+ Text[ arabic ] = "TEXT";
+ Text[ dutch ] = "TEKST";
+ Text[ chinese_simplified ] = "TEXT";
+ Text[ greek ] = "TEXT";
+ Text[ korean ] = "TEXT";
+ Text[ turkish ] = "TEXT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_SUBSTITUTE
+ {
+ Text = "WECHSELN" ;
+ Text [ english ] = "SUBSTITUTE" ;
+ Text [ norwegian ] = "ERSTATT" ;
+ Text [ italian ] = "SOSTITUISCI" ;
+ Text [ portuguese_brazilian ] = "SUBSTITUIR" ;
+ Text [ portuguese ] = "SUBSTITUIR" ;
+ Text [ finnish ] = "SUBSTITUTE" ;
+ Text [ danish ] = "UDSKIFT" ;
+ Text [ french ] = "SUBSTITUE" ;
+ Text [ swedish ] = "BYT.UT" ;
+ Text [ dutch ] = "SUBSTITUEREN" ;
+ Text [ spanish ] = "SUSTITUIR" ;
+ Text [ english_us ] = "SUBSTITUTE" ;
+ Text[ chinese_simplified ] = "SUBSTITUTE";
+ Text[ russian ] = "ÏÎÄÑÒÀÂÈÒÜ";
+ Text[ polish ] = "PODSTAW";
+ Text[ japanese ] = "SUBSTITUTE";
+ Text[ chinese_traditional ] = "SUBSTITUTE";
+ Text[ arabic ] = "SUBSTITUTE";
+ Text[ dutch ] = "SUBSTITUEREN";
+ Text[ chinese_simplified ] = "SUBSTITUTE";
+ Text[ greek ] = "SUBSTITUTE";
+ Text[ korean ] = "SUBSTITUTE";
+ Text[ turkish ] = "SUBSTITUTE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_REPT
+ {
+ Text = "WIEDERHOLEN" ;
+ Text [ english ] = "REPT" ;
+ Text [ norwegian ] = "REPT" ;
+ Text [ italian ] = "RIPETI" ;
+ Text [ portuguese_brazilian ] = "REPET" ;
+ Text [ portuguese ] = "REPETIR" ;
+ Text [ finnish ] = "REPT" ;
+ Text [ danish ] = "GENTAG" ;
+ Text [ french ] = "REPT" ;
+ Text [ swedish ] = "REP" ;
+ Text [ dutch ] = "HERHALING" ;
+ Text [ spanish ] = "REPETIR" ;
+ Text [ english_us ] = "REPT" ;
+ Text[ chinese_simplified ] = "REPT";
+ Text[ russian ] = "ÏÎÂÒÎÐ";
+ Text[ polish ] = "PONÓW";
+ Text[ japanese ] = "REPT";
+ Text[ chinese_traditional ] = "REPT";
+ Text[ arabic ] = "REPT";
+ Text[ dutch ] = "HERHALING";
+ Text[ chinese_simplified ] = "REPT";
+ Text[ greek ] = "REPT";
+ Text[ korean ] = "REPT";
+ Text[ turkish ] = "REPT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_CONCAT
+ {
+ Text = "VERKETTEN" ;
+ Text [ english ] = "CONCATENATE" ;
+ Text [ norwegian ] = "CONCATENATE" ;
+ Text [ italian ] = "CONCATENA" ;
+ Text [ portuguese_brazilian ] = "CONCATENAR" ;
+ Text [ portuguese ] = "CONCATENAR" ;
+ Text [ finnish ] = "CONCATENATE" ;
+ Text [ danish ] = "SAMMENKÆDNING" ;
+ Text [ french ] = "CONCATENER" ;
+ Text [ swedish ] = "SAMMANFOGA" ;
+ Text [ dutch ] = "TEKST.SAMENVOEGEN" ;
+ Text [ spanish ] = "CONCATENAR" ;
+ Text [ english_us ] = "CONCATENATE" ;
+ Text[ chinese_simplified ] = "CONCATENATE";
+ Text[ russian ] = "ÑÖÅÏÈÒÜ";
+ Text[ polish ] = "Z£¥CZ.TEKSTY";
+ Text[ japanese ] = "CONCATENATE";
+ Text[ chinese_traditional ] = "CONCATENATE";
+ Text[ arabic ] = "CONCATENATE";
+ Text[ dutch ] = "TEKST.SAMENVOEGEN";
+ Text[ chinese_simplified ] = "CONCATENATE";
+ Text[ greek ] = "CONCATENATE";
+ Text[ korean ] = "CONCATENATE";
+ Text[ turkish ] = "CONCATENATE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_MAT_VALUE
+ {
+ Text = "MWERT" ;
+ Text [ english ] = "MVALUE" ;
+ Text [ norwegian ] = "MVALUE" ;
+ Text [ italian ] = "MATR.VALORE" ;
+ Text [ portuguese_brazilian ] = "MVALOR" ;
+ Text [ portuguese ] = "VALOR.MATRIZ" ;
+ Text [ finnish ] = "MVALUE" ;
+ Text [ danish ] = "MVÆRDI" ;
+ Text [ french ] = "MVALUE" ;
+ Text [ swedish ] = "MVÄRDE" ;
+ Text [ dutch ] = "WAARDEMAT" ;
+ Text [ spanish ] = "MVALOR" ;
+ Text [ english_us ] = "MVALUE" ;
+ Text[ chinese_simplified ] = "MVALUE";
+ Text[ russian ] = "ÌÇÍÀ×";
+ Text[ polish ] = "WARTOήM";
+ Text[ japanese ] = "MVALUE";
+ Text[ chinese_traditional ] = "MVALUE";
+ Text[ arabic ] = "MVALUE";
+ Text[ dutch ] = "WAARDEMAT";
+ Text[ chinese_simplified ] = "MVALUE";
+ Text[ greek ] = "MVALUE";
+ Text[ korean ] = "MVALUE";
+ Text[ turkish ] = "MVALUE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_MAT_DET
+ {
+ Text = "MDET" ;
+ Text [ english ] = "MDETERM" ;
+ Text [ norwegian ] = "MDETERM" ;
+ Text [ italian ] = "MATR.DETERM" ;
+ Text [ portuguese_brazilian ] = "MDETERM" ;
+ Text [ portuguese ] = "MATRIZ.DETERM" ;
+ Text [ finnish ] = "MDETERM" ;
+ Text [ danish ] = "MDETERM" ;
+ Text [ french ] = "DETERMAT" ;
+ Text [ swedish ] = "MDETERM" ;
+ Text [ dutch ] = "DETERMINANT.MAT" ;
+ Text [ spanish ] = "MDETERM" ;
+ Text [ english_us ] = "MDETERM" ;
+ Text[ chinese_simplified ] = "MDETERM";
+ Text[ russian ] = "ÌÎÏÐÅÄ";
+ Text[ polish ] = "WYZNACZNIK.MACIERZY";
+ Text[ japanese ] = "MDETERM";
+ Text[ chinese_traditional ] = "MDETERM";
+ Text[ arabic ] = "MDETERM";
+ Text[ dutch ] = "DETERMINANT.MAT";
+ Text[ chinese_simplified ] = "MDETERM";
+ Text[ greek ] = "MDETERM";
+ Text[ korean ] = "MDETERM";
+ Text[ turkish ] = "MDETERM";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_MAT_INV
+ {
+ Text = "MINV" ;
+ Text [ english ] = "MINVERSE" ;
+ Text [ norwegian ] = "MINVERSE" ;
+ Text [ italian ] = "MATR.INVERSA" ;
+ Text [ portuguese_brazilian ] = "MINVERSO" ;
+ Text [ portuguese ] = "MATRIZ.INVERSA" ;
+ Text [ finnish ] = "MINVERSE" ;
+ Text [ danish ] = "MINVERT" ;
+ Text [ french ] = "INVERSEMAT" ;
+ Text [ swedish ] = "MINVERT" ;
+ Text [ dutch ] = "INVERSEMAT" ;
+ Text [ spanish ] = "MINVERSA" ;
+ Text [ english_us ] = "MINVERSE" ;
+ Text[ chinese_simplified ] = "MINVERSE";
+ Text[ russian ] = "ÌÎÁÐ";
+ Text[ polish ] = "MACIERZ.ODW";
+ Text[ japanese ] = "MINVERSE";
+ Text[ chinese_traditional ] = "MINVERSE";
+ Text[ arabic ] = "MINVERSE";
+ Text[ dutch ] = "INVERSEMAT";
+ Text[ chinese_simplified ] = "MINVERSE";
+ Text[ greek ] = "MINVERSE";
+ Text[ korean ] = "MINVERSE";
+ Text[ turkish ] = "MINVERSE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_MAT_MULT
+ {
+ Text = "MMULT" ;
+ Text [ english ] = "MMULT" ;
+ Text [ norwegian ] = "MMULT" ;
+ Text [ italian ] = "MATR.PRODOTTO" ;
+ Text [ portuguese_brazilian ] = "MMULT" ;
+ Text [ portuguese ] = "MATRIZ.MULT" ;
+ Text [ finnish ] = "MMULT" ;
+ Text [ danish ] = "MPRODUKT" ;
+ Text [ french ] = "PRODUITMAT" ;
+ Text [ swedish ] = "MMULT" ;
+ Text [ dutch ] = "PRODUKTMAT" ;
+ Text [ spanish ] = "MMULT" ;
+ Text [ english_us ] = "MMULT" ;
+ Text[ chinese_simplified ] = "MMULT";
+ Text[ russian ] = "ÌÓÌÍÎÆ";
+ Text[ polish ] = "MACIERZ.ILOCZYN";
+ Text[ japanese ] = "MMULT";
+ Text[ chinese_traditional ] = "MMULT";
+ Text[ arabic ] = "MMULT";
+ Text[ dutch ] = "PRODUKTMAT";
+ Text[ chinese_simplified ] = "MMULT";
+ Text[ greek ] = "MMULT";
+ Text[ korean ] = "MMULT";
+ Text[ turkish ] = "MMULT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_MAT_TRANS
+ {
+ Text = "MTRANS" ;
+ Text [ english ] = "TRANSPOSE" ;
+ Text [ norwegian ] = "MTRANS" ;
+ Text [ italian ] = "MATR.TRASPOSTA" ;
+ Text [ portuguese_brazilian ] = "MTRANS" ;
+ Text [ portuguese ] = "TRANSPOR" ;
+ Text [ finnish ] = "MTRANS" ;
+ Text [ danish ] = "TRANSPONER" ;
+ Text [ french ] = "TRANSPOSE" ;
+ Text [ swedish ] = "MTRANS" ;
+ Text [ dutch ] = "TRANSPONEREN" ;
+ Text [ spanish ] = "TRANSPONER" ;
+ Text [ english_us ] = "TRANSPOSE" ;
+ Text[ chinese_simplified ] = "TRANSPOSE";
+ Text[ russian ] = "ÌÒÐÀÍÑ";
+ Text[ polish ] = "TRANSPONUJ";
+ Text[ japanese ] = "TRANSPOSE";
+ Text[ chinese_traditional ] = "TRANSPOSE";
+ Text[ arabic ] = "TRANSPOSE";
+ Text[ dutch ] = "TRANSPONEREN";
+ Text[ chinese_simplified ] = "TRANSPOSE";
+ Text[ greek ] = "TRANSPOSE";
+ Text[ korean ] = "TRANSPOSE";
+ Text[ turkish ] = "TRANSPOSE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_MATRIX_UNIT
+ {
+ Text = "EINHEITSMATRIX" ;
+ Text [ english ] = "MUNIT" ;
+ Text [ norwegian ] = "MUNIT" ;
+ Text [ italian ] = "MUNIT" ;
+ Text [ portuguese_brazilian ] = "MUNIT" ;
+ Text [ portuguese ] = "MATRIZ.UNITÁRIA" ;
+ Text [ finnish ] = "MUNIT" ;
+ Text [ danish ] = "ENHEDSMATRIX" ;
+ Text [ french ] = "MUNIT" ;
+ Text [ swedish ] = "ENHETSMATRIS" ;
+ Text [ dutch ] = "EENHEIDSMAT" ;
+ Text [ spanish ] = "MUNITARIA" ;
+ Text [ english_us ] = "MUNIT" ;
+ Text[ chinese_simplified ] = "MUNIT";
+ Text[ russian ] = "ÅÄÌÀÒÐÈÖÀ";
+ Text[ polish ] = "MACIERZUNITARNA";
+ Text[ japanese ] = "MUNIT";
+ Text[ chinese_traditional ] = "MUNIT";
+ Text[ arabic ] = "MUNIT";
+ Text[ dutch ] = "EENHEIDSMAT";
+ Text[ chinese_simplified ] = "MUNIT";
+ Text[ greek ] = "MUNIT";
+ Text[ korean ] = "MUNIT";
+ Text[ turkish ] = "MUNIT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_BACK_SOLVER
+ {
+ Text = "ZIELWERTSUCHE" ;
+ Text [ english ] = "GOALSEEK" ;
+ Text [ norwegian ] = "MÅLSØK" ;
+ Text [ italian ] = "RICERCA VALORE DESTINAZIONE" ;
+ Text [ portuguese_brazilian ] = "BUSCADEOBJETIVO" ;
+ Text [ portuguese ] = "ATINGIROBJECTIVO" ;
+ Text [ finnish ] = "GOALSEEK" ;
+ Text [ danish ] = "MÅLSØGNING" ;
+ Text [ french ] = "CHERCHEVALCIBLE" ;
+ Text [ swedish ] = "MÅLSÖKNING" ;
+ Text [ dutch ] = "DOELZOEKEN" ;
+ Text [ spanish ] = "VALORPRETENDIDO" ;
+ Text [ english_us ] = "GOALSEEK" ;
+ Text[ chinese_simplified ] = "GOALSEEK";
+ Text[ russian ] = "ÏÎÄÁÎÐÏÀÐ";
+ Text[ polish ] = "SZUKAJ WYNIKU";
+ Text[ japanese ] = "GOALSEEK";
+ Text[ chinese_traditional ] = "GOALSEEK";
+ Text[ arabic ] = "ÇáÈÍË Úä ÇáÞíãÉ ÇáåÏÝ";
+ Text[ dutch ] = "DOELZOEKEN";
+ Text[ chinese_simplified ] = "GOALSEEK";
+ Text[ greek ] = "GOALSEEK";
+ Text[ korean ] = "GOALSEEK";
+ Text[ turkish ] = "GOALSEEK";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_HYP_GEOM_DIST
+ {
+ Text = "HYPGEOMVERT" ;
+ Text [ english ] = "HYPGEOMDIST" ;
+ Text [ norwegian ] = "HYPGEOMDIST" ;
+ Text [ italian ] = "DISTRIB.IPERGEOM" ;
+ Text [ portuguese_brazilian ] = "HYPGEOMDIST" ;
+ Text [ portuguese ] = "DIST.HIPERGEOM" ;
+ Text [ finnish ] = "HYPGEOMDIST" ;
+ Text [ danish ] = "HYPGEOFORDELING" ;
+ Text [ french ] = "LOI.HYPERGEOMETRIQUE" ;
+ Text [ swedish ] = "HYPGEOMFÖRD" ;
+ Text [ dutch ] = "HYPERGEO.VERD" ;
+ Text [ spanish ] = "DISTR.HIPERGEOM" ;
+ Text [ english_us ] = "HYPGEOMDIST" ;
+ Text[ chinese_simplified ] = "HYPGEOMDIST";
+ Text[ russian ] = "ÃÈÏÅÐÃÅÎÌÅÒ";
+ Text[ polish ] = "ROZK£AD.HIPERGEOM";
+ Text[ japanese ] = "HYPGEOMDIST";
+ Text[ chinese_traditional ] = "HYPGEOMDIST";
+ Text[ arabic ] = "HYPGEOMDIST";
+ Text[ dutch ] = "HYPERGEO.VERD";
+ Text[ chinese_simplified ] = "HYPGEOMDIST";
+ Text[ greek ] = "HYPGEOMDIST";
+ Text[ korean ] = "HYPGEOMDIST";
+ Text[ turkish ] = "HYPGEOMDIST";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_LOG_NORM_DIST
+ {
+ Text = "LOGNORMVERT" ;
+ Text [ english ] = "LOGNORMDIST" ;
+ Text [ norwegian ] = "LOGNORMDIST" ;
+ Text [ italian ] = "DISTRIB.LOGNORM" ;
+ Text [ portuguese_brazilian ] = "LOGNORMDIST" ;
+ Text [ portuguese ] = "DIST.NORMAL.LOG" ;
+ Text [ finnish ] = "LOGNORMDIST" ;
+ Text [ danish ] = "LOGNORMFORDELING" ;
+ Text [ french ] = "LOI.LOGNORMALE" ;
+ Text [ swedish ] = "LOGNORMFÖRD" ;
+ Text [ dutch ] = "LOG.NORM.VERD" ;
+ Text [ spanish ] = "DISTR.LOG.NORM" ;
+ Text [ english_us ] = "LOGNORMDIST" ;
+ Text[ chinese_simplified ] = "LOGNORMDIST";
+ Text[ russian ] = "ËÎÃÍÎÐÌÐÀÑÏ";
+ Text[ polish ] = "ROZK£AD.LOG";
+ Text[ japanese ] = "LOGNORMDIST";
+ Text[ chinese_traditional ] = "LOGNORMDIST";
+ Text[ arabic ] = "LOGNORMDIST";
+ Text[ dutch ] = "LOG.NORM.VERD";
+ Text[ chinese_simplified ] = "LOGNORMDIST";
+ Text[ greek ] = "LOGNORMDIST";
+ Text[ korean ] = "LOGNORMDIST";
+ Text[ turkish ] = "LOGNORMDIST";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_T_DIST
+ {
+ Text = "TVERT" ;
+ Text [ english ] = "TDIST" ;
+ Text [ norwegian ] = "TDIST" ;
+ Text [ italian ] = "DISTRIB.T" ;
+ Text [ portuguese_brazilian ] = "TDIST" ;
+ Text [ portuguese ] = "DIST.T" ;
+ Text [ finnish ] = "TDIST" ;
+ Text [ danish ] = "TFORDELING" ;
+ Text [ french ] = "LOI.STUDENT" ;
+ Text [ swedish ] = "TFÖRD" ;
+ Text [ dutch ] = "T.VERD" ;
+ Text [ spanish ] = "DISTR.T" ;
+ Text [ english_us ] = "TDIST" ;
+ Text[ chinese_simplified ] = "TDIST";
+ Text[ russian ] = "ÑÒÜÞÄÐÀÑÏ";
+ Text[ polish ] = "ROZK£AD.T";
+ Text[ japanese ] = "TDIST";
+ Text[ chinese_traditional ] = "TDIST";
+ Text[ arabic ] = "TDIST";
+ Text[ dutch ] = "T.VERD";
+ Text[ chinese_simplified ] = "TDIST";
+ Text[ greek ] = "TDIST";
+ Text[ korean ] = "TDIST";
+ Text[ turkish ] = "TDIST";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_F_DIST
+ {
+ Text = "FVERT" ;
+ Text [ english ] = "FDIST" ;
+ Text [ norwegian ] = "FDIST" ;
+ Text [ italian ] = "DISTRIB.F" ;
+ Text [ portuguese_brazilian ] = "FDIST" ;
+ Text [ portuguese ] = "DIST.F" ;
+ Text [ finnish ] = "FDIST" ;
+ Text [ danish ] = "FFORDELING" ;
+ Text [ french ] = "LOI.F" ;
+ Text [ swedish ] = "FFÖRD" ;
+ Text [ dutch ] = "F.VERDELING" ;
+ Text [ spanish ] = "DISTR.F" ;
+ Text [ english_us ] = "FDIST" ;
+ Text[ chinese_simplified ] = "FDIST";
+ Text[ russian ] = "FÐÀÑÏ";
+ Text[ polish ] = "ROZK£AD.F";
+ Text[ japanese ] = "FDIST";
+ Text[ chinese_traditional ] = "FDIST";
+ Text[ arabic ] = "FDIST";
+ Text[ dutch ] = "F.VERDELING";
+ Text[ chinese_simplified ] = "FDIST";
+ Text[ greek ] = "FDIST";
+ Text[ korean ] = "FDIST";
+ Text[ turkish ] = "FDIST";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_CHI_DIST
+ {
+ Text = "CHIVERT" ;
+ Text [ english ] = "CHIDIST" ;
+ Text [ norwegian ] = "CHIDIST" ;
+ Text [ italian ] = "DISTRIB.CHI" ;
+ Text [ portuguese_brazilian ] = "CHIDIST" ;
+ Text [ portuguese ] = "DIST.CHI" ;
+ Text [ finnish ] = "CHIDIST" ;
+ Text [ danish ] = "CHIFORDELING" ;
+ Text [ french ] = "LOI.KHIDEUX" ;
+ Text [ swedish ] = "CHI2FÖRD" ;
+ Text [ dutch ] = "CHI.KWADRAAT" ;
+ Text [ spanish ] = "DISTR.JI" ;
+ Text [ english_us ] = "CHIDIST" ;
+ Text[ chinese_simplified ] = "CHIDIST";
+ Text[ russian ] = "ÕÈ2ÐÀÑÏ";
+ Text[ polish ] = "ROZK£AD.CHI";
+ Text[ japanese ] = "CHIDIST";
+ Text[ chinese_traditional ] = "CHIDIST";
+ Text[ arabic ] = "CHIDIST";
+ Text[ dutch ] = "CHI.KWADRAAT";
+ Text[ chinese_simplified ] = "CHIDIST";
+ Text[ greek ] = "CHIDIST";
+ Text[ korean ] = "CHIDIST";
+ Text[ turkish ] = "CHIDIST";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_WEIBULL
+ {
+ Text = "WEIBULL" ;
+ Text [ english ] = "WEIBULL" ;
+ Text [ norwegian ] = "WEIBULL" ;
+ Text [ italian ] = "WEIBULL" ;
+ Text [ portuguese_brazilian ] = "WEIBULL" ;
+ Text [ portuguese ] = "WEIBULL" ;
+ Text [ finnish ] = "WEIBULL" ;
+ Text [ danish ] = "WEIBULL" ;
+ Text [ french ] = "LOI.WEIBULL" ;
+ Text [ swedish ] = "WEIBULL" ;
+ Text [ dutch ] = "WEIBULL" ;
+ Text [ spanish ] = "DIST.WEIBULL" ;
+ Text [ english_us ] = "WEIBULL" ;
+ Text[ chinese_simplified ] = "WEIBULL";
+ Text[ russian ] = "ÂÅÉÁÓË";
+ Text[ polish ] = "ROZK£AD.WEIBULL";
+ Text[ japanese ] = "WEIBULL";
+ Text[ chinese_traditional ] = "WEIBULL";
+ Text[ arabic ] = "WEIBULL";
+ Text[ dutch ] = "WEIBULL";
+ Text[ chinese_simplified ] = "WEIBULL";
+ Text[ greek ] = "WEIBULL";
+ Text[ korean ] = "WEIBULL";
+ Text[ turkish ] = "WEIBULL";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_NEG_BINOM_VERT
+ {
+ Text = "NEGBINOMVERT" ;
+ Text [ english ] = "NEGBINOMDIST" ;
+ Text [ norwegian ] = "NEGBINOMDIST" ;
+ Text [ italian ] = "DISTRIB.BINOM.NEG" ;
+ Text [ portuguese_brazilian ] = "NEGBINOMDIST" ;
+ Text [ portuguese ] = "DIST.BINOM.NEG" ;
+ Text [ finnish ] = "NEGBINOMDIST" ;
+ Text [ danish ] = "NEGBINOMFORDELING" ;
+ Text [ french ] = "LOI.BINOMIALE.NEG" ;
+ Text [ swedish ] = "NEGBINOMFÖRD" ;
+ Text [ dutch ] = "NEG.BINOM.VERD" ;
+ Text [ spanish ] = "NEGBINOMDIST" ;
+ Text [ english_us ] = "NEGBINOMDIST" ;
+ Text[ chinese_simplified ] = "NEGBINOMDIST";
+ Text[ russian ] = "ÎÒÐÁÈÍÎÌÐÀÑÏ";
+ Text[ polish ] = "NEG.ROZK£AD.DWUMIANOWY";
+ Text[ japanese ] = "NEGBINOMDIST";
+ Text[ chinese_traditional ] = "NEGBINOMDIST";
+ Text[ arabic ] = "NEGBINOMDIST";
+ Text[ dutch ] = "NEG.BINOM.VERD";
+ Text[ chinese_simplified ] = "NEGBINOMDIST";
+ Text[ greek ] = "NEGBINOMDIST";
+ Text[ korean ] = "NEGBINOMDIST";
+ Text[ turkish ] = "NEGBINOMDIST";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_KRIT_BINOM
+ {
+ Text = "KRITBINOM" ;
+ Text [ english ] = "CRITBINOM" ;
+ Text [ norwegian ] = "CRITBINOM" ;
+ Text [ italian ] = "CRIT.BINOM" ;
+ Text [ portuguese_brazilian ] = "CRITBINOM" ;
+ Text [ portuguese ] = "CRIT.BINOM" ;
+ Text [ finnish ] = "CRITBINOM" ;
+ Text [ danish ] = "KRITBINOM" ;
+ Text [ french ] = "CRITERE.LOI.BINOMIALE" ;
+ Text [ swedish ] = "KRITBINOM" ;
+ Text [ dutch ] = "CRIT.BINOM" ;
+ Text [ spanish ] = "BINOM.CRIT" ;
+ Text [ english_us ] = "CRITBINOM" ;
+ Text[ chinese_simplified ] = "CRITBINOM";
+ Text[ russian ] = "ÊÐÈÒÁÈÍÎÌ";
+ Text[ polish ] = "PRÓG.ROZK£AD.DWUM";
+ Text[ japanese ] = "CRITBINOM";
+ Text[ chinese_traditional ] = "CRITBINOM";
+ Text[ arabic ] = "CRITBINOM";
+ Text[ dutch ] = "CRIT.BINOM";
+ Text[ chinese_simplified ] = "CRITBINOM";
+ Text[ greek ] = "CRITBINOM";
+ Text[ korean ] = "CRITBINOM";
+ Text[ turkish ] = "CRITBINOM";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_KURT
+ {
+ Text = "KURT" ;
+ Text [ english ] = "KURT" ;
+ Text [ norwegian ] = "KURT" ;
+ Text [ italian ] = "CURTOSI" ;
+ Text [ portuguese_brazilian ] = "KURT" ;
+ Text [ portuguese ] = "KURT" ;
+ Text [ finnish ] = "KURT" ;
+ Text [ danish ] = "TOPSTEJL" ;
+ Text [ french ] = "KURTOSIS" ;
+ Text [ swedish ] = "TOPPIGHET" ;
+ Text [ dutch ] = "KURTOSIS" ;
+ Text [ spanish ] = "CURTOSIS" ;
+ Text [ english_us ] = "KURT" ;
+ Text[ chinese_simplified ] = "KURT";
+ Text[ russian ] = "ÝÊÑÖÅÑÑ";
+ Text[ polish ] = "KURTOZA";
+ Text[ japanese ] = "KURT";
+ Text[ chinese_traditional ] = "KURT";
+ Text[ arabic ] = "KURT";
+ Text[ dutch ] = "KURTOSIS";
+ Text[ chinese_simplified ] = "KURT";
+ Text[ greek ] = "KURT";
+ Text[ korean ] = "KURT";
+ Text[ turkish ] = "KURT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_HAR_MEAN
+ {
+ Text = "HARMITTEL" ;
+ Text [ english ] = "HARMEAN" ;
+ Text [ norwegian ] = "HARMEAN" ;
+ Text [ italian ] = "MEDIA.ARMONICA" ;
+ Text [ portuguese_brazilian ] = "HARMEAN" ;
+ Text [ portuguese ] = "MÉDIA.HARMÓNICA" ;
+ Text [ finnish ] = "HARMEAN" ;
+ Text [ danish ] = "HARMIDDELVÆRDI" ;
+ Text [ french ] = "MOYENNE.HARMONIQUE" ;
+ Text [ swedish ] = "HARMMEDEL" ;
+ Text [ dutch ] = "HARM.GEM" ;
+ Text [ spanish ] = "MEDIA.ARMO" ;
+ Text [ english_us ] = "HARMEAN" ;
+ Text[ chinese_simplified ] = "HARMEAN";
+ Text[ russian ] = "ÑÐÃÀÐÌ";
+ Text[ polish ] = "ŒREDNIA.HARMONICZNA";
+ Text[ japanese ] = "HARMEAN";
+ Text[ chinese_traditional ] = "HARMEAN";
+ Text[ arabic ] = "HARMEAN";
+ Text[ dutch ] = "HARM.GEM";
+ Text[ chinese_simplified ] = "HARMEAN";
+ Text[ greek ] = "HARMEAN";
+ Text[ korean ] = "HARMEAN";
+ Text[ turkish ] = "HARMEAN";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GEO_MEAN
+ {
+ Text = "GEOMITTEL" ;
+ Text [ english ] = "GEOMEAN" ;
+ Text [ norwegian ] = "GEOMEAN" ;
+ Text [ italian ] = "MEDIA.GEOMETRICA" ;
+ Text [ portuguese_brazilian ] = "GEOMEAN" ;
+ Text [ portuguese ] = "MÉDIA.GEOMÉTRICA" ;
+ Text [ finnish ] = "GEOMEAN" ;
+ Text [ danish ] = "GEOMIDDELVÆRDI" ;
+ Text [ french ] = "MOYENNE.GEOMETRIQUE" ;
+ Text [ swedish ] = "GEOMEAN" ;
+ Text [ dutch ] = "MEETK.GEM" ;
+ Text [ spanish ] = "MEDIA.GEOM" ;
+ Text [ english_us ] = "GEOMEAN" ;
+ Text[ chinese_simplified ] = "GEOMEAN";
+ Text[ russian ] = "ÑÐÃÅÎÌ";
+ Text[ polish ] = "ŒREDNIA.GEOMETRYCZNA";
+ Text[ japanese ] = "GEOMEAN";
+ Text[ chinese_traditional ] = "GEOMEAN";
+ Text[ arabic ] = "GEOMEAN";
+ Text[ dutch ] = "MEETK.GEM";
+ Text[ chinese_simplified ] = "GEOMEAN";
+ Text[ greek ] = "GEOMEAN";
+ Text[ korean ] = "GEOMEAN";
+ Text[ turkish ] = "GEOMEAN";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_STANDARD
+ {
+ Text = "STANDARDISIERUNG" ;
+ Text [ english ] = "STANDARDIZE" ;
+ Text [ norwegian ] = "STANDARDIZE" ;
+ Text [ italian ] = "NORMALIZZA" ;
+ Text [ portuguese_brazilian ] = "STANDARDIZE" ;
+ Text [ portuguese ] = "NORMALIZAR" ;
+ Text [ finnish ] = "STANDARDIZE" ;
+ Text [ danish ] = "STANDARDISER" ;
+ Text [ french ] = "CENTREE.REDUITE" ;
+ Text [ swedish ] = "STANDARDISERA" ;
+ Text [ dutch ] = "STANDAARDISERING" ;
+ Text [ spanish ] = "NORMALIZACIÓN" ;
+ Text [ english_us ] = "STANDARDIZE" ;
+ Text[ chinese_simplified ] = "STANDARDIZE";
+ Text[ russian ] = "ÍÎÐÌÀËÈÇÀÖÈß";
+ Text[ polish ] = "NORMALIZUJ";
+ Text[ japanese ] = "STANDARDIZE";
+ Text[ chinese_traditional ] = "STANDARDIZE";
+ Text[ arabic ] = "STANDARDIZE";
+ Text[ dutch ] = "STANDAARDISERING";
+ Text[ chinese_simplified ] = "STANDARDIZE";
+ Text[ greek ] = "STANDARDIZE";
+ Text[ korean ] = "STANDARDIZE";
+ Text[ turkish ] = "STANDARDIZE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_AVE_DEV
+ {
+ Text = "MITTELABW" ;
+ Text [ english ] = "AVEDEV" ;
+ Text [ norwegian ] = "AVEDEV" ;
+ Text [ italian ] = "MEDIA.DEV" ;
+ Text [ portuguese_brazilian ] = "AVEDEV" ;
+ Text [ portuguese ] = "DESV.MÉDIO" ;
+ Text [ finnish ] = "AVEDEV" ;
+ Text [ danish ] = "MAD" ;
+ Text [ french ] = "ECART.MOYEN" ;
+ Text [ swedish ] = "MEDELAVV" ;
+ Text [ dutch ] = "GEM.DEVIATIE" ;
+ Text [ spanish ] = "DESVPROM" ;
+ Text [ english_us ] = "AVEDEV" ;
+ Text[ chinese_simplified ] = "AVEDEV";
+ Text[ russian ] = "ÑÐÎÒÊË";
+ Text[ polish ] = "ODCH.ŒREDNIE";
+ Text[ japanese ] = "AVEDEV";
+ Text[ chinese_traditional ] = "AVEDEV";
+ Text[ arabic ] = "AVEDEV";
+ Text[ dutch ] = "GEM.DEVIATIE";
+ Text[ chinese_simplified ] = "AVEDEV";
+ Text[ greek ] = "AVEDEV";
+ Text[ korean ] = "AVEDEV";
+ Text[ turkish ] = "AVEDEV";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_SCHIEFE
+ {
+ Text = "SCHIEFE" ;
+ Text [ english ] = "SKEW" ;
+ Text [ norwegian ] = "SKEW" ;
+ Text [ italian ] = "ASIMMETRIA" ;
+ Text [ portuguese_brazilian ] = "SKEW" ;
+ Text [ portuguese ] = "ASSIMETRIA" ;
+ Text [ finnish ] = "SKEW" ;
+ Text [ danish ] = "SKÆVHED" ;
+ Text [ french ] = "COEFFICIENT.ASYMETRIE" ;
+ Text [ swedish ] = "SNEDHET" ;
+ Text [ dutch ] = "SCHEEFHEID" ;
+ Text [ spanish ] = "COEFICIENTE.ASIMETRIA" ;
+ Text [ english_us ] = "SKEW" ;
+ Text[ chinese_simplified ] = "SKEW";
+ Text[ russian ] = "ÑÊÎÑ";
+ Text[ polish ] = "SKOŒNOŒÆ";
+ Text[ japanese ] = "SKEW";
+ Text[ chinese_traditional ] = "SKEW";
+ Text[ arabic ] = "SKEW";
+ Text[ dutch ] = "SCHEEFHEID";
+ Text[ chinese_simplified ] = "SKEW";
+ Text[ greek ] = "SKEW";
+ Text[ korean ] = "SKEW";
+ Text[ turkish ] = "SKEW";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_DEV_SQ
+ {
+ Text = "SUMQUADABW" ;
+ Text [ english ] = "DEVSQ" ;
+ Text [ norwegian ] = "DEVSQ" ;
+ Text [ italian ] = "DEV.Q" ;
+ Text [ portuguese_brazilian ] = "DEVSQ" ;
+ Text [ portuguese ] = "DEVSQ" ;
+ Text [ finnish ] = "DEVSQ" ;
+ Text [ danish ] = "SAK" ;
+ Text [ french ] = "SOMME.CARRES.ECARTS" ;
+ Text [ swedish ] = "KVADAVV" ;
+ Text [ dutch ] = "DEV.KWAD" ;
+ Text [ spanish ] = "DESVIA2" ;
+ Text [ english_us ] = "DEVSQ" ;
+ Text[ chinese_simplified ] = "DEVSQ";
+ Text[ russian ] = "ÊÂÀÄÐÎÒÊË";
+ Text[ polish ] = "ODCH.KWADRATOWE";
+ Text[ japanese ] = "DEVSQ";
+ Text[ chinese_traditional ] = "DEVSQ";
+ Text[ arabic ] = "DEVSQ";
+ Text[ dutch ] = "DEV.KWAD";
+ Text[ chinese_simplified ] = "DEVSQ";
+ Text[ greek ] = "DEVSQ";
+ Text[ korean ] = "DEVSQ";
+ Text[ turkish ] = "DEVSQ";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_MEDIAN
+ {
+ Text = "MEDIAN" ;
+ Text [ english ] = "MEDIAN" ;
+ Text [ norwegian ] = "MEDIAN" ;
+ Text [ italian ] = "MEDIANA" ;
+ Text [ portuguese_brazilian ] = "MEDIAN" ;
+ Text [ portuguese ] = "MEDIANA" ;
+ Text [ finnish ] = "MEDIAN" ;
+ Text [ danish ] = "MEDIAN" ;
+ Text [ french ] = "MEDIANE" ;
+ Text [ swedish ] = "MEDIAN" ;
+ Text [ dutch ] = "MEDIAAN" ;
+ Text [ spanish ] = "MEDIANA" ;
+ Text [ english_us ] = "MEDIAN" ;
+ Text[ chinese_simplified ] = "MEDIAN";
+ Text[ russian ] = "ÌÅÄÈÀÍÀ";
+ Text[ polish ] = "MEDIANA";
+ Text[ japanese ] = "MEDIAN";
+ Text[ chinese_traditional ] = "MEDIAN";
+ Text[ arabic ] = "MEDIAN";
+ Text[ dutch ] = "MEDIAAN";
+ Text[ chinese_simplified ] = "MEDIAN";
+ Text[ greek ] = "MEDIAN";
+ Text[ korean ] = "MEDIAN";
+ Text[ turkish ] = "MEDIAN";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_MODAL_VALUE
+ {
+ Text = "MODALWERT" ;
+ Text [ english ] = "MODE" ;
+ Text [ norwegian ] = "MODE" ;
+ Text [ italian ] = "MODA" ;
+ Text [ portuguese_brazilian ] = "MODE" ;
+ Text [ portuguese ] = "MODAL" ;
+ Text [ finnish ] = "MODE" ;
+ Text [ danish ] = "HYPPIGST" ;
+ Text [ french ] = "MODE" ;
+ Text [ swedish ] = "TYPVÄRDE" ;
+ Text [ dutch ] = "MODUS" ;
+ Text [ spanish ] = "MODA" ;
+ Text [ english_us ] = "MODE" ;
+ Text[ chinese_simplified ] = "MODE";
+ Text[ russian ] = "ÌÎÄÀ";
+ Text[ polish ] = "WYST.NAJCZÊŒCIEJ";
+ Text[ japanese ] = "MODE";
+ Text[ chinese_traditional ] = "MODE";
+ Text[ arabic ] = "MODE";
+ Text[ dutch ] = "MODUS";
+ Text[ chinese_simplified ] = "MODE";
+ Text[ greek ] = "MODE";
+ Text[ korean ] = "MODE";
+ Text[ turkish ] = "MODE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_Z_TEST
+ {
+ Text = "GTEST" ;
+ Text [ english ] = "ZTEST" ;
+ Text [ norwegian ] = "ZTEST" ;
+ Text [ italian ] = "TEST.Z" ;
+ Text [ portuguese_brazilian ] = "ZTEST" ;
+ Text [ portuguese ] = "TESTEZ" ;
+ Text [ finnish ] = "ZTEST" ;
+ Text [ danish ] = "ZTEST" ;
+ Text [ french ] = "TEST.Z" ;
+ Text [ swedish ] = "ZTEST" ;
+ Text [ dutch ] = "Z.TOETS" ;
+ Text [ spanish ] = "PRUEBA.Z" ;
+ Text [ english_us ] = "ZTEST" ;
+ Text[ chinese_simplified ] = "ZTEST";
+ Text[ russian ] = "ZÒÅÑÒ";
+ Text[ polish ] = "TEST.Z";
+ Text[ japanese ] = "ZTEST";
+ Text[ chinese_traditional ] = "ZTEST";
+ Text[ arabic ] = "ZTEST";
+ Text[ dutch ] = "Z.TOETS";
+ Text[ chinese_simplified ] = "ZTEST";
+ Text[ greek ] = "ZTEST";
+ Text[ korean ] = "ZTEST";
+ Text[ turkish ] = "ZTEST";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_T_TEST
+ {
+ Text = "TTEST" ;
+ Text [ english ] = "TTEST" ;
+ Text [ norwegian ] = "TTEST" ;
+ Text [ italian ] = "TEST.T" ;
+ Text [ portuguese_brazilian ] = "TTEST" ;
+ Text [ portuguese ] = "TESTE.T" ;
+ Text [ finnish ] = "TTEST" ;
+ Text [ danish ] = "TTEST" ;
+ Text [ french ] = "TEST.STUDENT" ;
+ Text [ swedish ] = "TTEST" ;
+ Text [ dutch ] = "T.TOETS" ;
+ Text [ spanish ] = "PRUEBA.T" ;
+ Text [ english_us ] = "TTEST" ;
+ Text[ chinese_simplified ] = "TTEST";
+ Text[ russian ] = "ÒÒÅÑÒ";
+ Text[ polish ] = "TEST.T";
+ Text[ japanese ] = "TTEST";
+ Text[ chinese_traditional ] = "TTEST";
+ Text[ arabic ] = "TTEST";
+ Text[ dutch ] = "T.TOETS";
+ Text[ chinese_simplified ] = "TTEST";
+ Text[ greek ] = "TTEST";
+ Text[ korean ] = "TTEST";
+ Text[ turkish ] = "TTEST";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_RANK
+ {
+ Text = "RANG" ;
+ Text [ english ] = "RANK" ;
+ Text [ norwegian ] = "REKKE" ;
+ Text [ italian ] = "RANGO" ;
+ Text [ portuguese_brazilian ] = "RANK" ;
+ Text [ portuguese ] = "ORDEM" ;
+ Text [ finnish ] = "RANK" ;
+ Text [ danish ] = "PLADS" ;
+ Text [ french ] = "RANG" ;
+ Text [ swedish ] = "RANG" ;
+ Text [ dutch ] = "RANG" ;
+ Text [ spanish ] = "JERARQUÍA" ;
+ Text [ english_us ] = "RANK" ;
+ Text[ chinese_simplified ] = "RANK";
+ Text[ russian ] = "ÐÀÍÃ";
+ Text[ polish ] = "POZYCJA";
+ Text[ japanese ] = "RANK";
+ Text[ chinese_traditional ] = "RANK";
+ Text[ arabic ] = "RANK";
+ Text[ dutch ] = "RANG";
+ Text[ chinese_simplified ] = "RANK";
+ Text[ greek ] = "RANK";
+ Text[ korean ] = "RANK";
+ Text[ turkish ] = "RANK";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_PERCENTILE
+ {
+ Text = "QUANTIL" ;
+ Text [ english ] = "PERCENTILE" ;
+ Text [ norwegian ] = "PERSENTIL" ;
+ Text [ italian ] = "PERCENTILE" ;
+ Text [ portuguese_brazilian ] = "PERCENTILE" ;
+ Text [ portuguese ] = "PERCENTIL" ;
+ Text [ finnish ] = "PERCENTILE" ;
+ Text [ danish ] = "FRAKTIL" ;
+ Text [ french ] = "CENTILE" ;
+ Text [ swedish ] = "PERCENTIL" ;
+ Text [ dutch ] = "PERCENTIEL" ;
+ Text [ spanish ] = "PERCENTIL" ;
+ Text [ english_us ] = "PERCENTILE" ;
+ Text[ chinese_simplified ] = "PERCENTILE";
+ Text[ russian ] = "ÏÅÐÑÅÍÒÈËÜ";
+ Text[ polish ] = "PERCENTYL";
+ Text[ japanese ] = "PERCENTILE";
+ Text[ chinese_traditional ] = "PERCENTILE";
+ Text[ arabic ] = "PERCENTILE";
+ Text[ dutch ] = "PERCENTIEL";
+ Text[ chinese_simplified ] = "PERCENTILE";
+ Text[ greek ] = "PERCENTILE";
+ Text[ korean ] = "PERCENTILE";
+ Text[ turkish ] = "PERCENTILE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_PERCENT_RANK
+ {
+ Text = "QUANTILSRANG" ;
+ Text [ english ] = "PERCENTRANK" ;
+ Text [ norwegian ] = "PROSENTREKKE" ;
+ Text [ italian ] = "PERCENT.RANGO" ;
+ Text [ portuguese_brazilian ] = "PERCENTRANK" ;
+ Text [ portuguese ] = "ORDEM.PERCENTUAL" ;
+ Text [ finnish ] = "PERCENTRANK" ;
+ Text [ danish ] = "PROCENTPLADS" ;
+ Text [ french ] = "RANG.POURCENTAGE" ;
+ Text [ swedish ] = "PROCENTRANG" ;
+ Text [ dutch ] = "PERCENT.RANG" ;
+ Text [ spanish ] = "RANGO.PERCENTIL" ;
+ Text [ english_us ] = "PERCENTRANK" ;
+ Text[ chinese_simplified ] = "PERCENTRANK";
+ Text[ russian ] = "ÏÐÎÖÅÍÒÐÀÍÃ";
+ Text[ polish ] = "PROCENT.POZYCJA";
+ Text[ japanese ] = "PERCENTRANK";
+ Text[ chinese_traditional ] = "PERCENTRANK";
+ Text[ arabic ] = "PERCENTRANK";
+ Text[ dutch ] = "PERCENT.RANG";
+ Text[ chinese_simplified ] = "PERCENTRANK";
+ Text[ greek ] = "PERCENTRANK";
+ Text[ korean ] = "PERCENTRANK";
+ Text[ turkish ] = "PERCENTRANK";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_LARGE
+ {
+ /* ### ACHTUNG: Neuer Text in Resource? KGRÖSSTE : KGRÍSSTE */
+ Text = "KGRÖSSTE" ;
+ Text [ english ] = "LARGE" ;
+ Text [ norwegian ] = "STOR" ;
+ Text [ italian ] = "GRANDE" ;
+ Text [ portuguese_brazilian ] = "LARGE" ;
+ Text [ portuguese ] = "MAIOR" ;
+ Text [ finnish ] = "LARGE" ;
+ Text [ danish ] = "STØRSTE" ;
+ Text [ french ] = "GRANDE.VALEUR" ;
+ Text [ swedish ] = "STÖRSTA" ;
+ Text [ dutch ] = "GROOTSTE" ;
+ Text [ spanish ] = "K.ESIMO.MAYOR" ;
+ Text [ english_us ] = "LARGE" ;
+ Text[ chinese_simplified ] = "LARGE";
+ Text[ russian ] = "ÍÀÈÁÎËÜØÈÉ";
+ Text[ polish ] = "MAX.K";
+ Text[ japanese ] = "LARGE";
+ Text[ chinese_traditional ] = "LARGE";
+ Text[ arabic ] = "LARGE";
+ Text[ dutch ] = "GROOTSTE";
+ Text[ chinese_simplified ] = "LARGE";
+ Text[ greek ] = "LARGE";
+ Text[ korean ] = "LARGE";
+ Text[ turkish ] = "LARGE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_SMALL
+ {
+ Text = "KKLEINSTE" ;
+ Text [ english ] = "SMALL" ;
+ Text [ norwegian ] = "LITEN" ;
+ Text [ italian ] = "PICCOLO" ;
+ Text [ portuguese_brazilian ] = "SMALL" ;
+ Text [ portuguese ] = "MENOR" ;
+ Text [ finnish ] = "SMALL" ;
+ Text [ danish ] = "MINDSTE" ;
+ Text [ french ] = "PETITE.VALEUR" ;
+ Text [ swedish ] = "MINSTA" ;
+ Text [ dutch ] = "KLEINSTE" ;
+ Text [ spanish ] = "K.ESIMO.MENOR" ;
+ Text [ english_us ] = "SMALL" ;
+ Text[ chinese_simplified ] = "SMALL";
+ Text[ russian ] = "ÍÀÈÌÅÍÜØÈÉ";
+ Text[ polish ] = "MIN.K";
+ Text[ japanese ] = "SMALL";
+ Text[ chinese_traditional ] = "SMALL";
+ Text[ arabic ] = "SMALL";
+ Text[ dutch ] = "KLEINSTE";
+ Text[ chinese_simplified ] = "SMALL";
+ Text[ greek ] = "SMALL";
+ Text[ korean ] = "SMALL";
+ Text[ turkish ] = "SMALL";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_FREQUENCY
+ {
+ /* ### ACHTUNG: Neuer Text in Resource? HÄUFIGKEIT : HŽUFIGKEIT */
+ Text = "HÄUFIGKEIT" ;
+ Text [ english ] = "FREQUENCY" ;
+ Text [ norwegian ] = "FREKVENS" ;
+ Text [ italian ] = "FREQUENZA" ;
+ Text [ portuguese_brazilian ] = "FREQUENCY" ;
+ Text [ portuguese ] = "FREQUÊNCIA" ;
+ Text [ finnish ] = "FREQUENCY" ;
+ Text [ danish ] = "FREKVENS" ;
+ Text [ french ] = "FREQUENCE" ;
+ Text [ swedish ] = "FREKVENS" ;
+ Text [ dutch ] = "INTERVAL" ;
+ Text [ spanish ] = "FRECUENCIA" ;
+ Text [ english_us ] = "FREQUENCY" ;
+ Text[ chinese_simplified ] = "FREQUENCY";
+ Text[ russian ] = "×ÀÑÒÎÒÀ";
+ Text[ polish ] = "CZÊSTOŒÆ";
+ Text[ japanese ] = "FREQUENCY";
+ Text[ chinese_traditional ] = "FREQUENCY";
+ Text[ arabic ] = "FREQUENCY";
+ Text[ dutch ] = "INTERVAL";
+ Text[ chinese_simplified ] = "FREQUENCY";
+ Text[ greek ] = "FREQUENCY";
+ Text[ korean ] = "FREQUENCY";
+ Text[ turkish ] = "FREQUENCY";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_QUARTILE
+ {
+ Text = "QUARTILE" ;
+ Text [ english ] = "QUARTILE" ;
+ Text [ norwegian ] = "QUARTILE" ;
+ Text [ italian ] = "QUARTILE" ;
+ Text [ portuguese_brazilian ] = "QUARTILE" ;
+ Text [ portuguese ] = "QUARTIL" ;
+ Text [ finnish ] = "QUARTILE" ;
+ Text [ danish ] = "KVARTILE" ;
+ Text [ french ] = "QUARTILE" ;
+ Text [ swedish ] = "KVARTIL" ;
+ Text [ dutch ] = "KWARTIEL" ;
+ Text [ spanish ] = "CUARTIL" ;
+ Text [ english_us ] = "QUARTILE" ;
+ Text[ chinese_simplified ] = "QUARTILE";
+ Text[ russian ] = "ÊÂÀÐÒÈËÜ";
+ Text[ polish ] = "KWARTYL";
+ Text[ japanese ] = "QUARTILE";
+ Text[ chinese_traditional ] = "QUARTILE";
+ Text[ arabic ] = "QUARTILE";
+ Text[ dutch ] = "KWARTIEL";
+ Text[ chinese_simplified ] = "QUARTILE";
+ Text[ greek ] = "QUARTILE";
+ Text[ korean ] = "QUARTILE";
+ Text[ turkish ] = "QUARTILE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_NORM_INV
+ {
+ Text = "NORMINV" ;
+ Text [ english ] = "NORMINV" ;
+ Text [ norwegian ] = "NORMINV" ;
+ Text [ italian ] = "INV.NORM" ;
+ Text [ portuguese_brazilian ] = "NORMINV" ;
+ Text [ portuguese ] = "INV.NORM" ;
+ Text [ finnish ] = "NORMINV" ;
+ Text [ danish ] = "NORMINV" ;
+ Text [ french ] = "LOI.NORMALE.INVERSE" ;
+ Text [ swedish ] = "NORMINV" ;
+ Text [ dutch ] = "NORM.INV" ;
+ Text [ spanish ] = "DISTR.NORM.INV" ;
+ Text [ english_us ] = "NORMINV" ;
+ Text[ chinese_simplified ] = "NORMINV";
+ Text[ russian ] = "ÍÎÐÌÎÁÐ";
+ Text[ polish ] = "ROZK£AD.NORMALNY.ODW";
+ Text[ japanese ] = "NORMINV";
+ Text[ chinese_traditional ] = "NORMINV";
+ Text[ arabic ] = "NORMINV";
+ Text[ dutch ] = "NORM.INV";
+ Text[ chinese_simplified ] = "NORMINV";
+ Text[ greek ] = "NORMINV";
+ Text[ korean ] = "NORMINV";
+ Text[ turkish ] = "NORMINV";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_CONFIDENCE
+ {
+ Text = "KONFIDENZ" ;
+ Text [ english ] = "CONFIDENCE" ;
+ Text [ norwegian ] = "CONFIDENCE" ;
+ Text [ italian ] = "CONFIDENZA" ;
+ Text [ portuguese_brazilian ] = "CONFIDENCE" ;
+ Text [ portuguese ] = "INT.CONFIANÇA" ;
+ Text [ finnish ] = "CONFIDENCE" ;
+ Text [ danish ] = "KONFIDENSINTERVAL" ;
+ Text [ french ] = "INTERVALLE.CONFIANCE" ;
+ Text [ swedish ] = "KONFIDENS" ;
+ Text [ dutch ] = "BETROUWBAARHEID" ;
+ Text [ spanish ] = "INTERVALO.CONFIANZA" ;
+ Text [ english_us ] = "CONFIDENCE" ;
+ Text[ chinese_simplified ] = "CONFIDENCE";
+ Text[ russian ] = "ÄÎÂÅÐÈÒ";
+ Text[ polish ] = "UFNOή";
+ Text[ japanese ] = "CONFIDENCE";
+ Text[ chinese_traditional ] = "CONFIDENCE";
+ Text[ arabic ] = "CONFIDENCE";
+ Text[ dutch ] = "BETROUWBAARHEID";
+ Text[ chinese_simplified ] = "CONFIDENCE";
+ Text[ greek ] = "CONFIDENCE";
+ Text[ korean ] = "CONFIDENCE";
+ Text[ turkish ] = "CONFIDENCE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_F_TEST
+ {
+ Text = "FTEST" ;
+ Text [ english ] = "FTEST" ;
+ Text [ norwegian ] = "FTEST" ;
+ Text [ italian ] = "TEST.F" ;
+ Text [ portuguese_brazilian ] = "FTEST" ;
+ Text [ portuguese ] = "TESTEF" ;
+ Text [ finnish ] = "FTEST" ;
+ Text [ danish ] = "FTEST" ;
+ Text [ french ] = "TEST.F" ;
+ Text [ swedish ] = "FTEST" ;
+ Text [ dutch ] = "F.TOETS" ;
+ Text [ spanish ] = "PRUEBA.F" ;
+ Text [ english_us ] = "FTEST" ;
+ Text[ chinese_simplified ] = "FTEST";
+ Text[ russian ] = "FÒÅÑÒ";
+ Text[ polish ] = "TEST.F";
+ Text[ japanese ] = "FTEST";
+ Text[ chinese_traditional ] = "FTEST";
+ Text[ arabic ] = "FTEST";
+ Text[ dutch ] = "F.TOETS";
+ Text[ chinese_simplified ] = "FTEST";
+ Text[ greek ] = "FTEST";
+ Text[ korean ] = "FTEST";
+ Text[ turkish ] = "FTEST";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_TRIM_MEAN
+ {
+ Text = "GESTUTZTMITTEL" ;
+ Text [ english ] = "TRIMMEAN" ;
+ Text [ norwegian ] = "TRIMMEAN" ;
+ Text [ italian ] = "MEDIA.TRONCATA" ;
+ Text [ portuguese_brazilian ] = "TRIMMEAN" ;
+ Text [ portuguese ] = "MÉDIA.INTERNA" ;
+ Text [ finnish ] = "TRIMMEAN" ;
+ Text [ danish ] = "TRIMMIDDELVÆRDI" ;
+ Text [ french ] = "MOYENNE.REDUITE" ;
+ Text [ swedish ] = "TRIMMEDEL" ;
+ Text [ dutch ] = "GETRIMD.GEM" ;
+ Text [ spanish ] = "MEDIA.ACOTADA" ;
+ Text [ english_us ] = "TRIMMEAN" ;
+ Text[ chinese_simplified ] = "TRIMMEAN";
+ Text[ russian ] = "ÓÐÅÇÑÐÅÄÍÅÅ";
+ Text[ polish ] = "ŒREDNIA.WEWN";
+ Text[ japanese ] = "TRIMMEAN";
+ Text[ chinese_traditional ] = "TRIMMEAN";
+ Text[ arabic ] = "TRIMMEAN";
+ Text[ dutch ] = "GETRIMD.GEM";
+ Text[ chinese_simplified ] = "TRIMMEAN";
+ Text[ greek ] = "TRIMMEAN";
+ Text[ korean ] = "TRIMMEAN";
+ Text[ turkish ] = "TRIMMEAN";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_PROB
+ {
+ Text = "WAHRSCHBEREICH" ;
+ Text [ english ] = "PROB" ;
+ Text [ norwegian ] = "PROB" ;
+ Text [ italian ] = "PROBABILITÀ" ;
+ Text [ portuguese_brazilian ] = "PROB" ;
+ Text [ portuguese ] = "PROB" ;
+ Text [ finnish ] = "PROB" ;
+ Text [ danish ] = "SANDSYNLIGHED" ;
+ Text [ french ] = "PROBABILITE" ;
+ Text [ swedish ] = "SANNOLIKHET" ;
+ Text [ dutch ] = "KANS" ;
+ Text [ spanish ] = "PROBABILIDAD" ;
+ Text [ english_us ] = "PROB" ;
+ Text[ chinese_simplified ] = "PROB";
+ Text[ russian ] = "ÂÅÐÎßÒÍÎÑÒÜ";
+ Text[ polish ] = "PRAWDPD";
+ Text[ japanese ] = "PROB";
+ Text[ chinese_traditional ] = "PROB";
+ Text[ arabic ] = "PROB";
+ Text[ dutch ] = "KANS";
+ Text[ chinese_simplified ] = "PROB";
+ Text[ greek ] = "PROB";
+ Text[ korean ] = "PROB";
+ Text[ turkish ] = "PROB";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_CORREL
+ {
+ Text = "KORREL" ;
+ Text [ english ] = "CORREL" ;
+ Text [ norwegian ] = "CORREL" ;
+ Text [ italian ] = "CORRELAZIONE" ;
+ Text [ portuguese_brazilian ] = "CORREL" ;
+ Text [ portuguese ] = "CORREL" ;
+ Text [ finnish ] = "CORREL" ;
+ Text [ danish ] = "KORRELATION" ;
+ Text [ french ] = "COEFFICIENT.CORRELATION" ;
+ Text [ swedish ] = "KORREL" ;
+ Text [ dutch ] = "CORRELATIE" ;
+ Text [ spanish ] = "COEF.DE.CORREL" ;
+ Text [ english_us ] = "CORREL" ;
+ Text[ chinese_simplified ] = "CORREL";
+ Text[ russian ] = "ÊÎÐÐÅË";
+ Text[ polish ] = "WSP.KORELACJI";
+ Text[ japanese ] = "CORREL";
+ Text[ chinese_traditional ] = "CORREL";
+ Text[ arabic ] = "CORREL";
+ Text[ dutch ] = "CORRELATIE";
+ Text[ chinese_simplified ] = "CORREL";
+ Text[ greek ] = "CORREL";
+ Text[ korean ] = "CORREL";
+ Text[ turkish ] = "CORREL";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_COVAR
+ {
+ Text = "KOVAR" ;
+ Text [ english ] = "COVAR" ;
+ Text [ norwegian ] = "COVAR" ;
+ Text [ italian ] = "COVARIANZA" ;
+ Text [ portuguese_brazilian ] = "COVAR" ;
+ Text [ portuguese ] = "COVAR" ;
+ Text [ finnish ] = "COVAR" ;
+ Text [ danish ] = "KOVARIANS" ;
+ Text [ french ] = "COVARIANCE" ;
+ Text [ swedish ] = "KOVAR" ;
+ Text [ dutch ] = "COVARIANTIE" ;
+ Text [ spanish ] = "COVAR" ;
+ Text [ english_us ] = "COVAR" ;
+ Text[ chinese_simplified ] = "COVAR";
+ Text[ russian ] = "ÊÎÂÀÐ";
+ Text[ polish ] = "KOWARIANCJA";
+ Text[ japanese ] = "COVAR";
+ Text[ chinese_traditional ] = "COVAR";
+ Text[ arabic ] = "COVAR";
+ Text[ dutch ] = "COVARIANTIE";
+ Text[ chinese_simplified ] = "COVAR";
+ Text[ greek ] = "COVAR";
+ Text[ korean ] = "COVAR";
+ Text[ turkish ] = "COVAR";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_PEARSON
+ {
+ Text = "PEARSON" ;
+ Text [ english ] = "PEARSON" ;
+ Text [ norwegian ] = "PEARSON" ;
+ Text [ italian ] = "PEARSON" ;
+ Text [ portuguese_brazilian ] = "PEARSON" ;
+ Text [ portuguese ] = "PEARSON" ;
+ Text [ finnish ] = "PEARSON" ;
+ Text [ danish ] = "PEARSON" ;
+ Text [ french ] = "PEARSON" ;
+ Text [ swedish ] = "PEARSON" ;
+ Text [ dutch ] = "PEARSON" ;
+ Text [ spanish ] = "PEARSON" ;
+ Text [ english_us ] = "PEARSON" ;
+ Text[ chinese_simplified ] = "PEARSON";
+ Text[ russian ] = "ÏÈÐÑÎÍ";
+ Text[ polish ] = "PEARSON";
+ Text[ japanese ] = "PEARSON";
+ Text[ chinese_traditional ] = "PEARSON";
+ Text[ arabic ] = "PEARSON";
+ Text[ dutch ] = "PEARSON";
+ Text[ chinese_simplified ] = "PEARSON";
+ Text[ greek ] = "PEARSON";
+ Text[ korean ] = "PEARSON";
+ Text[ turkish ] = "PEARSON";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_RSQ
+ {
+ Text = "BESTIMMTHEITSMASS" ;
+ Text [ english ] = "RSQ" ;
+ Text [ norwegian ] = "RSQ" ;
+ Text [ italian ] = "RQ" ;
+ Text [ portuguese_brazilian ] = "RSQ" ;
+ Text [ portuguese ] = "R.QUAD" ;
+ Text [ finnish ] = "RSQ" ;
+ Text [ danish ] = "FORKLARINGSGRAD" ;
+ Text [ french ] = "COEFFICIENT.DETERMINATION" ;
+ Text [ swedish ] = "RKV" ;
+ Text [ dutch ] = "R.KWADRAAT" ;
+ Text [ spanish ] = "COEFICIENTE.R2" ;
+ Text [ english_us ] = "RSQ" ;
+ Text[ chinese_simplified ] = "RSQ";
+ Text[ russian ] = "ÊÂÏÈÐÑÎÍ";
+ Text[ polish ] = "R.KWADRAT";
+ Text[ japanese ] = "RSQ";
+ Text[ chinese_traditional ] = "RSQ";
+ Text[ arabic ] = "RSQ";
+ Text[ dutch ] = "R.KWADRAAT";
+ Text[ chinese_simplified ] = "RSQ";
+ Text[ greek ] = "RSQ";
+ Text[ korean ] = "RSQ";
+ Text[ turkish ] = "RSQ";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_STEYX
+ {
+ Text = "STFEHLERYX" ;
+ Text [ english ] = "STEYX" ;
+ Text [ norwegian ] = "STEYX" ;
+ Text [ italian ] = "ERR.STD.YX" ;
+ Text [ portuguese_brazilian ] = "STEYX" ;
+ Text [ portuguese ] = "ERRO.TIPO.YX" ;
+ Text [ finnish ] = "STEYX" ;
+ Text [ danish ] = "STFYX" ;
+ Text [ french ] = "ERREUR.TYPE.XY" ;
+ Text [ swedish ] = "STDFELYX" ;
+ Text [ dutch ] = "STFOUTYX" ;
+ Text [ spanish ] = "ERROR.TÍPICO.XY" ;
+ Text [ english_us ] = "STEYX" ;
+ Text[ chinese_simplified ] = "STEYX";
+ Text[ russian ] = "ÑÒÎØYX";
+ Text[ polish ] = "REGB£STD";
+ Text[ japanese ] = "STEYX";
+ Text[ chinese_traditional ] = "STEYX";
+ Text[ arabic ] = "STEYX";
+ Text[ dutch ] = "STFOUTYX";
+ Text[ chinese_simplified ] = "STEYX";
+ Text[ greek ] = "STEYX";
+ Text[ korean ] = "STEYX";
+ Text[ turkish ] = "STEYX";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_SLOPE
+ {
+ Text = "STEIGUNG" ;
+ Text [ english ] = "SLOPE" ;
+ Text [ norwegian ] = "SLOPE" ;
+ Text [ italian ] = "PENDENZA" ;
+ Text [ portuguese_brazilian ] = "SLOPE" ;
+ Text [ portuguese ] = "DECLIVE" ;
+ Text [ finnish ] = "SLOPE" ;
+ Text [ danish ] = "STIGNING" ;
+ Text [ french ] = "PENTE" ;
+ Text [ swedish ] = "LUTNING" ;
+ Text [ dutch ] = "STIJGING" ;
+ Text [ spanish ] = "PENDIENTE" ;
+ Text [ english_us ] = "SLOPE" ;
+ Text[ chinese_simplified ] = "SLOPE";
+ Text[ russian ] = "ÍÀÊËÎÍ";
+ Text[ polish ] = "NACHYLENIE";
+ Text[ japanese ] = "SLOPE";
+ Text[ chinese_traditional ] = "SLOPE";
+ Text[ arabic ] = "SLOPE";
+ Text[ dutch ] = "STIJGING";
+ Text[ chinese_simplified ] = "SLOPE";
+ Text[ greek ] = "SLOPE";
+ Text[ korean ] = "SLOPE";
+ Text[ turkish ] = "SLOPE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_INTERCEPT
+ {
+ Text = "ACHSENABSCHNITT" ;
+ Text [ english ] = "INTERCEPT" ;
+ Text [ norwegian ] = "INTERCEPT" ;
+ Text [ italian ] = "INTERCETTA" ;
+ Text [ portuguese_brazilian ] = "INTERCEPT" ;
+ Text [ portuguese ] = "INTERCEPÇÃO" ;
+ Text [ finnish ] = "INTERCEPT" ;
+ Text [ danish ] = "SKÆRING" ;
+ Text [ french ] = "ORDONNEE.ORIGINE" ;
+ Text [ swedish ] = "SKÄRNINGSPUNKT" ;
+ Text [ dutch ] = "SNIJPUNT" ;
+ Text [ spanish ] = "INTERSECCIÓN.EJE" ;
+ Text [ english_us ] = "INTERCEPT" ;
+ Text[ chinese_simplified ] = "INTERCEPT";
+ Text[ russian ] = "ÎÒÐÅÇÎÊ";
+ Text[ polish ] = "ODCIÊTA";
+ Text[ japanese ] = "INTERCEPT";
+ Text[ chinese_traditional ] = "INTERCEPT";
+ Text[ arabic ] = "INTERCEPT";
+ Text[ dutch ] = "SNIJPUNT";
+ Text[ chinese_simplified ] = "INTERCEPT";
+ Text[ greek ] = "INTERCEPT";
+ Text[ korean ] = "INTERCEPT";
+ Text[ turkish ] = "INTERCEPT";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_TREND
+ {
+ Text = "TREND" ;
+ Text [ english ] = "TREND" ;
+ Text [ norwegian ] = "TREND" ;
+ Text [ italian ] = "TENDENZA" ;
+ Text [ portuguese_brazilian ] = "TREND" ;
+ Text [ portuguese ] = "TENDÊNCIA" ;
+ Text [ finnish ] = "TREND" ;
+ Text [ danish ] = "TENDENS" ;
+ Text [ french ] = "TENDANCE" ;
+ Text [ swedish ] = "TREND" ;
+ Text [ dutch ] = "TREND" ;
+ Text [ spanish ] = "TENDENCIA" ;
+ Text [ english_us ] = "TREND" ;
+ Text[ chinese_simplified ] = "TREND";
+ Text[ russian ] = "ÒÅÍÄÅÍÖÈß";
+ Text[ polish ] = "REGLINW";
+ Text[ japanese ] = "TREND";
+ Text[ chinese_traditional ] = "TREND";
+ Text[ arabic ] = "TREND";
+ Text[ dutch ] = "TREND";
+ Text[ chinese_simplified ] = "TREND";
+ Text[ greek ] = "TREND";
+ Text[ korean ] = "TREND";
+ Text[ turkish ] = "TREND";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GROWTH
+ {
+ Text = "VARIATION" ;
+ Text [ english ] = "GROWTH" ;
+ Text [ norwegian ] = "VEKST" ;
+ Text [ italian ] = "CRESCITA" ;
+ Text [ portuguese_brazilian ] = "GROWTH" ;
+ Text [ portuguese ] = "CRESCIMENTO" ;
+ Text [ finnish ] = "GROWTH" ;
+ Text [ danish ] = "FORØGELSE" ;
+ Text [ french ] = "CROISSANCE" ;
+ Text [ swedish ] = "EXPTREND" ;
+ Text [ dutch ] = "GROEI" ;
+ Text [ spanish ] = "CRECIMIENTO" ;
+ Text [ english_us ] = "GROWTH" ;
+ Text[ chinese_simplified ] = "GROWTH";
+ Text[ russian ] = "ÐÎÑÒ";
+ Text[ polish ] = "REGEXPW";
+ Text[ japanese ] = "GROWTH";
+ Text[ chinese_traditional ] = "GROWTH";
+ Text[ arabic ] = "GROWTH";
+ Text[ dutch ] = "GROEI";
+ Text[ chinese_simplified ] = "GROWTH";
+ Text[ greek ] = "GROWTH";
+ Text[ korean ] = "GROWTH";
+ Text[ turkish ] = "GROWTH";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_RGP
+ {
+ Text = "RGP" ;
+ Text [ english ] = "LINEST" ;
+ Text [ norwegian ] = "LINEST" ;
+ Text [ italian ] = "REGR.LIN" ;
+ Text [ portuguese_brazilian ] = "LINEST" ;
+ Text [ portuguese ] = "REGR.LINEAR" ;
+ Text [ finnish ] = "LINEST" ;
+ Text [ danish ] = "LINREGR" ;
+ Text [ french ] = "DROITEREG" ;
+ Text [ swedish ] = "REGR" ;
+ Text [ dutch ] = "LIJNSCH" ;
+ Text [ spanish ] = "ESTIMACIÓN.LINEAL" ;
+ Text [ english_us ] = "LINEST" ;
+ Text[ chinese_simplified ] = "LINEST";
+ Text[ russian ] = "ËÈÍÅÉÍ";
+ Text[ polish ] = "REG.LINP";
+ Text[ japanese ] = "LINEST";
+ Text[ chinese_traditional ] = "LINEST";
+ Text[ arabic ] = "LINEST";
+ Text[ dutch ] = "LIJNSCH";
+ Text[ chinese_simplified ] = "LINEST";
+ Text[ greek ] = "LINEST";
+ Text[ korean ] = "LINEST";
+ Text[ turkish ] = "LINEST";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_RKP
+ {
+ Text = "RKP" ;
+ Text [ english ] = "LOGEST" ;
+ Text [ norwegian ] = "LOGEST" ;
+ Text [ italian ] = "REGR.LOG" ;
+ Text [ portuguese_brazilian ] = "LOGEST" ;
+ Text [ portuguese ] = "LOGEST" ;
+ Text [ finnish ] = "LOGEST" ;
+ Text [ danish ] = "LOGREGR" ;
+ Text [ french ] = "LOGREG" ;
+ Text [ swedish ] = "EXPREGR" ;
+ Text [ dutch ] = "LOGSCH" ;
+ Text [ spanish ] = "ESTIMACIÓN.LOGARÍTMICA" ;
+ Text [ english_us ] = "LOGEST" ;
+ Text[ chinese_simplified ] = "LOGEST";
+ Text[ russian ] = "ËÃÐÔÏÐÈÁË";
+ Text[ polish ] = "REGEXPP";
+ Text[ japanese ] = "LOGEST";
+ Text[ chinese_traditional ] = "LOGEST";
+ Text[ arabic ] = "LOGEST";
+ Text[ dutch ] = "LOGSCH";
+ Text[ chinese_simplified ] = "LOGEST";
+ Text[ greek ] = "LOGEST";
+ Text[ korean ] = "LOGEST";
+ Text[ turkish ] = "LOGEST";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_FORECAST
+ {
+ /* ### ACHTUNG: Neuer Text in Resource? SCHÄTZER : SCHŽTZER */
+ Text = "SCHÄTZER" ;
+ Text [ english ] = "FORECAST" ;
+ Text [ norwegian ] = "FORECAST" ;
+ Text [ italian ] = "PREVISIONE" ;
+ Text [ portuguese_brazilian ] = "FORECAST" ;
+ Text [ portuguese ] = "REGRESSÃO.LINEAR" ;
+ Text [ finnish ] = "FORECAST" ;
+ Text [ danish ] = "PROGNOSE" ;
+ Text [ french ] = "PREVISION" ;
+ Text [ swedish ] = "PREDIKTION" ;
+ Text [ dutch ] = "VOORSPELLEN" ;
+ Text [ spanish ] = "PRONÓSTICO" ;
+ Text [ english_us ] = "FORECAST" ;
+ Text[ chinese_simplified ] = "FORECAST";
+ Text[ russian ] = "ÏÐÅÄÑÊÀÇ";
+ Text[ polish ] = "REGLINX";
+ Text[ japanese ] = "FORECAST";
+ Text[ chinese_traditional ] = "FORECAST";
+ Text[ arabic ] = "FORECAST";
+ Text[ dutch ] = "VOORSPELLEN";
+ Text[ chinese_simplified ] = "FORECAST";
+ Text[ greek ] = "FORECAST";
+ Text[ korean ] = "FORECAST";
+ Text[ turkish ] = "FORECAST";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_CHI_INV
+ {
+ Text = "CHIINV" ;
+ Text [ english ] = "CHIINV" ;
+ Text [ norwegian ] = "CHIINV" ;
+ Text [ italian ] = "INV.CHI" ;
+ Text [ portuguese_brazilian ] = "CHIINV" ;
+ Text [ portuguese ] = "INV.CHI" ;
+ Text [ finnish ] = "CHIINV" ;
+ Text [ danish ] = "CHIINV" ;
+ Text [ french ] = "KHIDEUX.INVERSE" ;
+ Text [ swedish ] = "CHI2INV" ;
+ Text [ dutch ] = "CHI.KWADRAAT.INV" ;
+ Text [ spanish ] = "PRUEBA.JI.INV" ;
+ Text [ english_us ] = "CHIINV" ;
+ Text[ chinese_simplified ] = "CHIINV";
+ Text[ russian ] = "ÕÈ2ÎÁÐ";
+ Text[ polish ] = "ROZK£AD.CHI.ODW";
+ Text[ japanese ] = "CHIINV";
+ Text[ chinese_traditional ] = "CHIINV";
+ Text[ arabic ] = "CHIINV";
+ Text[ dutch ] = "CHI.KWADRAAT.INV";
+ Text[ chinese_simplified ] = "CHIINV";
+ Text[ greek ] = "CHIINV";
+ Text[ korean ] = "CHIINV";
+ Text[ turkish ] = "CHIINV";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GAMMA_DIST
+ {
+ Text = "GAMMAVERT" ;
+ Text [ english ] = "GAMMADIST" ;
+ Text [ norwegian ] = "GAMMADIST" ;
+ Text [ italian ] = "DISTRIB.GAMMA" ;
+ Text [ portuguese_brazilian ] = "GAMMADIST" ;
+ Text [ portuguese ] = "DIST.GAMMA" ;
+ Text [ finnish ] = "GAMMADIST" ;
+ Text [ danish ] = "GAMMAFORDELING" ;
+ Text [ french ] = "LOI.GAMMA" ;
+ Text [ swedish ] = "GAMMAFÖRD" ;
+ Text [ dutch ] = "GAMMA.VERD" ;
+ Text [ spanish ] = "DISTR.GAMMA" ;
+ Text [ english_us ] = "GAMMADIST" ;
+ Text[ chinese_simplified ] = "GAMMADIST";
+ Text[ russian ] = "ÃÀÌÌÀÐÀÑÏ";
+ Text[ polish ] = "ROZK£AD.GAMMA";
+ Text[ japanese ] = "GAMMADIST";
+ Text[ chinese_traditional ] = "GAMMADIST";
+ Text[ arabic ] = "GAMMADIST";
+ Text[ dutch ] = "GAMMA.VERD";
+ Text[ chinese_simplified ] = "GAMMADIST";
+ Text[ greek ] = "GAMMADIST";
+ Text[ korean ] = "GAMMADIST";
+ Text[ turkish ] = "GAMMADIST";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GAMMA_INV
+ {
+ Text = "GAMMAINV" ;
+ Text [ english ] = "GAMMAINV" ;
+ Text [ norwegian ] = "GAMMAINV" ;
+ Text [ italian ] = "INV.GAMMA" ;
+ Text [ portuguese_brazilian ] = "GAMMAINV" ;
+ Text [ portuguese ] = "INV.GAMMA" ;
+ Text [ finnish ] = "GAMMAINV" ;
+ Text [ danish ] = "GAMMAINV" ;
+ Text [ french ] = "LOI.GAMMA.INVERSE" ;
+ Text [ swedish ] = "GAMMAINV" ;
+ Text [ dutch ] = "GAMMA.INV" ;
+ Text [ spanish ] = "DISTR.GAMMA.INV" ;
+ Text [ english_us ] = "GAMMAINV" ;
+ Text[ chinese_simplified ] = "GAMMAINV";
+ Text[ russian ] = "ÃÀÌÌÀÎÁÐ";
+ Text[ polish ] = "ROZK£AD.GAMMA.ODW";
+ Text[ japanese ] = "GAMMAINV";
+ Text[ chinese_traditional ] = "GAMMAINV";
+ Text[ arabic ] = "GAMMAINV";
+ Text[ dutch ] = "GAMMA.INV";
+ Text[ chinese_simplified ] = "GAMMAINV";
+ Text[ greek ] = "GAMMAINV";
+ Text[ korean ] = "GAMMAINV";
+ Text[ turkish ] = "GAMMAINV";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_T_INV
+ {
+ Text = "TINV" ;
+ Text [ english ] = "TINV" ;
+ Text [ norwegian ] = "TINV" ;
+ Text [ italian ] = "INV.T" ;
+ Text [ portuguese_brazilian ] = "TINV" ;
+ Text [ portuguese ] = "INV.T" ;
+ Text [ finnish ] = "TINV" ;
+ Text [ danish ] = "TINV" ;
+ Text [ french ] = "LOI.STUDENT.INVERSE" ;
+ Text [ swedish ] = "TINV" ;
+ Text [ dutch ] = "T.INV" ;
+ Text [ spanish ] = "DISTR.T.INV" ;
+ Text [ english_us ] = "TINV" ;
+ Text[ chinese_simplified ] = "TINV";
+ Text[ russian ] = "ÑÒÜÞÄÐÀÑÏÎÁÐ";
+ Text[ polish ] = "ROZK£AD.T.ODW";
+ Text[ japanese ] = "TINV";
+ Text[ chinese_traditional ] = "TINV";
+ Text[ arabic ] = "TINV";
+ Text[ dutch ] = "T.INV";
+ Text[ chinese_simplified ] = "TINV";
+ Text[ greek ] = "TINV";
+ Text[ korean ] = "TINV";
+ Text[ turkish ] = "TINV";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_F_INV
+ {
+ Text = "FINV" ;
+ Text [ english ] = "FINV" ;
+ Text [ norwegian ] = "FINV" ;
+ Text [ italian ] = "INV.F" ;
+ Text [ portuguese_brazilian ] = "FINV" ;
+ Text [ portuguese ] = "INV.F" ;
+ Text [ finnish ] = "FINV" ;
+ Text [ danish ] = "FINV" ;
+ Text [ french ] = "INVERSE.LOI.F" ;
+ Text [ swedish ] = "FINV" ;
+ Text [ dutch ] = "F.INVERSE" ;
+ Text [ spanish ] = "DISTR.F.INV" ;
+ Text [ english_us ] = "FINV" ;
+ Text[ chinese_simplified ] = "FINV";
+ Text[ russian ] = "FÐÀÑÏÎÁÐ";
+ Text[ polish ] = "ROZK£AD.F.ODW.";
+ Text[ japanese ] = "FINV";
+ Text[ chinese_traditional ] = "FINV";
+ Text[ arabic ] = "FINV";
+ Text[ dutch ] = "F.INVERSE";
+ Text[ chinese_simplified ] = "FINV";
+ Text[ greek ] = "FINV";
+ Text[ korean ] = "FINV";
+ Text[ turkish ] = "FINV";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_CHI_TEST
+ {
+ Text = "CHITEST" ;
+ Text [ english ] = "CHITEST" ;
+ Text [ norwegian ] = "CHITEST" ;
+ Text [ italian ] = "TEST.CHI" ;
+ Text [ portuguese_brazilian ] = "CHITEST" ;
+ Text [ portuguese ] = "TESTE.CHI" ;
+ Text [ finnish ] = "CHITEST" ;
+ Text [ danish ] = "CHITEST" ;
+ Text [ french ] = "TEST.KHIDEUX" ;
+ Text [ swedish ] = "CHI2TEST" ;
+ Text [ dutch ] = "CHI.TOETS" ;
+ Text [ spanish ] = "PRUEBA.JI" ;
+ Text [ english_us ] = "CHITEST" ;
+ Text[ chinese_simplified ] = "CHITEST";
+ Text[ russian ] = "ÕÈ2ÒÅÑÒ";
+ Text[ polish ] = "TEST.CHI";
+ Text[ japanese ] = "CHITEST";
+ Text[ chinese_traditional ] = "CHITEST";
+ Text[ arabic ] = "CHITEST";
+ Text[ dutch ] = "CHI.TOETS";
+ Text[ chinese_simplified ] = "CHITEST";
+ Text[ greek ] = "CHITEST";
+ Text[ korean ] = "CHITEST";
+ Text[ turkish ] = "CHITEST";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_LOG_INV
+ {
+ Text = "LOGINV" ;
+ Text [ english ] = "LOGINV" ;
+ Text [ norwegian ] = "LOGINV" ;
+ Text [ italian ] = "INV.LOGNORM" ;
+ Text [ portuguese_brazilian ] = "LOGINV" ;
+ Text [ portuguese ] = "INV.LOG" ;
+ Text [ finnish ] = "LOGINV" ;
+ Text [ danish ] = "LOGINV" ;
+ Text [ french ] = "LOI.LOGNORMALE.INVERSE" ;
+ Text [ swedish ] = "LOGINV" ;
+ Text [ dutch ] = "LOG.NORM.INV" ;
+ Text [ spanish ] = "INV.LOG" ;
+ Text [ english_us ] = "LOGINV" ;
+ Text[ chinese_simplified ] = "LOGINV";
+ Text[ russian ] = "ËÎÃÍÎÐÌÎÁÐ";
+ Text[ polish ] = "ROZK£AD.LOG.ODW";
+ Text[ japanese ] = "LOGINV";
+ Text[ chinese_traditional ] = "LOGINV";
+ Text[ arabic ] = "LOGINV";
+ Text[ dutch ] = "LOG.NORM.INV";
+ Text[ chinese_simplified ] = "LOGINV";
+ Text[ greek ] = "LOGINV";
+ Text[ korean ] = "LOGINV";
+ Text[ turkish ] = "LOGINV";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_TABLE_OP
+ {
+ Text = "MEHRFACHOPERATION" ;
+ Text [ english ] = "TABLE" ;
+ Text [ norwegian ] = "TABLEOPERATION" ;
+ Text [ italian ] = "OPERAZIONE.MULTIPLA" ;
+ Text [ portuguese_brazilian ] = "TABLEOPERATION" ;
+ Text [ portuguese ] = "OPERAÇÃO.MÚLTIPLA" ;
+ Text [ finnish ] = "TABLEOPERATION" ;
+ Text [ danish ] = "MULTIOPERATION" ;
+ Text [ french ] = "OPERATION.MULTIPLE" ;
+ Text [ swedish ] = "MULTIPEL.OPERATION" ;
+ Text [ dutch ] = "MEERVOUD.OPERATIE" ;
+ Text [ spanish ] = "OPERACIÓN.MÚLTIPLE" ;
+ Text [ english_us ] = "MULTIPLE.OPERATIONS" ;
+ Text[ chinese_simplified ] = "MULTIPLE.OPERATIONS";
+ Text[ russian ] = "ÒÀÁËÏÎÄÑÒÀÍÎÂÎÊ";
+ Text[ polish ] = "OPERACJE.WIELOKROTNE";
+ Text[ japanese ] = "MULTIPLE.OPERATIONS";
+ Text[ chinese_traditional ] = "MULTIPLE.OPERATIONS";
+ Text[ arabic ] = "MULTIPLE OPERATIONS";
+ Text[ dutch ] = "MEERVOUD.OPERATIE";
+ Text[ chinese_simplified ] = "MULTIPLE.OPERATIONS";
+ Text[ greek ] = "MULTIPLE.OPERATIONS";
+ Text[ korean ] = "MULTIPLE.OPERATIONS";
+ Text[ turkish ] = "MULTIPLE OPERATIONS";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_BETA_DIST
+ {
+ Text = "BETAVERT" ;
+ Text [ english ] = "BETADIST" ;
+ Text [ norwegian ] = "BETADIST" ;
+ Text [ italian ] = "DISTRIB.BETA" ;
+ Text [ portuguese_brazilian ] = "BETADIST" ;
+ Text [ portuguese ] = "DIST.BETA" ;
+ Text [ finnish ] = "BETADIST" ;
+ Text [ danish ] = "BETAFORDELING" ;
+ Text [ french ] = "LOI.BETA" ;
+ Text [ swedish ] = "BETAFÖRD" ;
+ Text [ dutch ] = "BETA.VERD" ;
+ Text [ spanish ] = "DISTR.BETA" ;
+ Text [ english_us ] = "BETADIST" ;
+ Text[ chinese_simplified ] = "BETADIST";
+ Text[ russian ] = "ÁÅÒÀÐÀÑÏ";
+ Text[ polish ] = "ROZK£AD.BETA";
+ Text[ japanese ] = "BETADIST";
+ Text[ chinese_traditional ] = "BETADIST";
+ Text[ arabic ] = "BETADIST";
+ Text[ dutch ] = "BETA.VERD";
+ Text[ chinese_simplified ] = "BETADIST";
+ Text[ greek ] = "BETADIST";
+ Text[ korean ] = "BETADIST";
+ Text[ turkish ] = "BETADIST";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_BETA_INV
+ {
+ Text = "BETAINV" ;
+ Text [ english ] = "BETAINV" ;
+ Text [ norwegian ] = "BETAINV" ;
+ Text [ italian ] = "INV.BETA" ;
+ Text [ portuguese_brazilian ] = "BETAINV" ;
+ Text [ portuguese ] = "INV.BETA" ;
+ Text [ finnish ] = "BETAINV" ;
+ Text [ danish ] = "BETAINV" ;
+ Text [ french ] = "BETA.INVERSE" ;
+ Text [ swedish ] = "BETAINV" ;
+ Text [ dutch ] = "BETA.INV" ;
+ Text [ spanish ] = "DISTR.BETA.INV" ;
+ Text [ english_us ] = "BETAINV" ;
+ Text[ chinese_simplified ] = "BETAINV";
+ Text[ russian ] = "ÁÅÒÀÎÁÐ";
+ Text[ polish ] = "ROZK£AD.BETA.ODW";
+ Text[ japanese ] = "BETAINV";
+ Text[ chinese_traditional ] = "BETAINV";
+ Text[ arabic ] = "BETAINV";
+ Text[ dutch ] = "BETA.INV";
+ Text[ chinese_simplified ] = "BETAINV";
+ Text[ greek ] = "BETAINV";
+ Text[ korean ] = "BETAINV";
+ Text[ turkish ] = "BETAINV";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_WEEK
+ {
+ Text = "KALENDERWOCHE" ;
+ Text [ english ] = "WEEKNUM" ;
+ Text [ norwegian ] = "WEEKOFYEAR" ;
+ Text [ italian ] = "NUM.SETTIMANA" ;
+ Text [ portuguese_brazilian ] = "WEEKOFYEAR" ;
+ Text [ portuguese ] = "SEMANACALENDÁRIO" ;
+ Text [ finnish ] = "WEEKOFYEAR" ;
+ Text [ danish ] = "KALENDERUGE" ;
+ Text [ french ] = "NO.SEMAINE" ;
+ Text [ swedish ] = "KALENDERVECKA" ;
+ Text [ dutch ] = "KALENDERWEEK" ;
+ Text [ spanish ] = "SEM.DEL.AÑO" ;
+ Text [ english_us ] = "WEEKNUM" ;
+ Text[ chinese_simplified ] = "WEEKNUM";
+ Text[ russian ] = "ÊÀËÅÍÄ.ÍÅÄÅËß";
+ Text[ polish ] = "TYDZIEÑKALENDARZOWY";
+ Text[ japanese ] = "WEEKNUM";
+ Text[ chinese_traditional ] = "WEEKNUM";
+ Text[ arabic ] = "WEEKNUM";
+ Text[ dutch ] = "KALENDERWEEK";
+ Text[ chinese_simplified ] = "WEEKNUM";
+ Text[ greek ] = "WEEKNUM";
+ Text[ korean ] = "WEEKNUM";
+ Text[ turkish ] = "WEEKNUM";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_EASTERSUNDAY
+ {
+ Text = "OSTERSONNTAG" ;
+ Text [ english ] = "EASTERSUNDAY" ;
+ Text [ english_us ] = "EASTERSUNDAY" ;
+ Text[ portuguese ] = "DOMINGOPÁSCOA";
+ Text[ russian ] = "ÏÀÑÕÀËÜÍÎÅÂÎÑÊÐÅÑÅÍÜÅ";
+ Text[ dutch ] = "EERSTEPAASDAG";
+ Text[ french ] = "DIMANCHEDEPÂQUES";
+ Text[ spanish ] = "DOMINGOPASCUA";
+ Text[ italian ] = "DOMENICADIPASQUA";
+ Text[ danish ] = "PÅSKESØNDAG";
+ Text[ swedish ] = "PÅSKDAGEN";
+ Text[ polish ] = "NIEDZIELAWIELKANOCNA";
+ Text[ portuguese_brazilian ] = "EASTERSUNDAY";
+ Text[ japanese ] = "EASTERSUNDAY";
+ Text[ chinese_simplified ] = "EASTERSUNDAY";
+ Text[ chinese_traditional ] = "EASTERSUNDAY";
+ Text[ arabic ] = "EASTERSUNDAY";
+ Text[ dutch ] = "EERSTEPAASDAG";
+ Text[ chinese_simplified ] = "EASTERSUNDAY";
+ Text[ greek ] = "EASTERSUNDAY";
+ Text[ korean ] = "EASTERSUNDAY";
+ Text[ turkish ] = "EASTERSUNDAY";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_GET_DAY_OF_WEEK
+ {
+ Text = "WOCHENTAG" ;
+ Text [ english ] = "WEEKDAY" ;
+ Text [ norwegian ] = "WEEKDAY" ;
+ Text [ italian ] = "GIORNO.SETTIMANA" ;
+ Text [ portuguese_brazilian ] = "WEEKDAY" ;
+ Text [ portuguese ] = "DIA.SEMANA" ;
+ Text [ finnish ] = "WEEKDAY" ;
+ Text [ danish ] = "UGEDAG" ;
+ Text [ french ] = "JOURSEM" ;
+ Text [ swedish ] = "VECKODAG" ;
+ Text [ dutch ] = "WEEKDAG" ;
+ Text [ spanish ] = "DÍASEM" ;
+ Text [ english_us ] = "WEEKDAY" ;
+ Text[ chinese_simplified ] = "WEEKDAY";
+ Text[ russian ] = "ÄÅÍÜÍÅÄ";
+ Text[ polish ] = "DZIEÑ.TYGODNIA";
+ Text[ japanese ] = "WEEKDAY";
+ Text[ chinese_traditional ] = "WEEKDAY";
+ Text[ arabic ] = "WEEKDAY";
+ Text[ dutch ] = "WEEKDAG";
+ Text[ chinese_simplified ] = "WEEKDAY";
+ Text[ greek ] = "WEEKDAY";
+ Text[ korean ] = "WEEKDAY";
+ Text[ turkish ] = "WEEKDAY";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_NO_NAME
+ {
+ Text = "#NAME!" ;
+ Text [ english ] = "#NAME!" ;
+ Text [ norwegian ] = "#NAVN!" ;
+ Text [ italian ] = "#NOME!" ;
+ Text [ portuguese_brazilian ] = "#NOME!" ;
+ Text [ portuguese ] = "#NOME!" ;
+ Text [ finnish ] = "#NAME!" ;
+ Text [ danish ] = "#NAVN!" ;
+ Text [ french ] = "#NOM!" ;
+ Text [ swedish ] = "#NAMN!" ;
+ Text [ dutch ] = "#NAAM!" ;
+ Text [ spanish ] = "#NOMBRE!" ;
+ Text [ english_us ] = "#NAME!" ;
+ Text[ chinese_simplified ] = "#NAME!";
+ Text[ russian ] = "#ÈÌß!";
+ Text[ polish ] = "#NAZWA!";
+ Text[ japanese ] = "#NAME!";
+ Text[ chinese_traditional ] = "#NAME!";
+ Text[ arabic ] = "#ÇáÇÓã!";
+ Text[ dutch ] = "#NAAM!";
+ Text[ chinese_simplified ] = "#NAME!";
+ Text[ greek ] = "#NAME!";
+ Text[ korean ] = "#NAME!";
+ Text[ turkish ] = "#NAME!";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_STYLE
+ {
+ Text = "VORLAGE" ;
+ Text [ english ] = "STYLE" ;
+ Text [ norwegian ] = "STYLE" ;
+ Text [ italian ] = "MODELLO" ;
+ Text [ portuguese_brazilian ] = "STYLE" ;
+ Text [ portuguese ] = "ESTILO" ;
+ Text [ finnish ] = "STYLE" ;
+ Text [ danish ] = "TYPOGRAFI" ;
+ Text [ french ] = "STYLE" ;
+ Text [ swedish ] = "FORMATMALL" ;
+ Text [ dutch ] = "PROFIEL" ;
+ Text [ spanish ] = "ESTILO" ;
+ Text [ english_us ] = "STYLE" ;
+ Text[ chinese_simplified ] = "STYLE";
+ Text[ russian ] = "ÑÒÈËÜ";
+ Text[ polish ] = "STYL";
+ Text[ japanese ] = "STYLE";
+ Text[ chinese_traditional ] = "STYLE";
+ Text[ arabic ] = "STYLE";
+ Text[ dutch ] = "PROFIEL";
+ Text[ chinese_simplified ] = "STYLE";
+ Text[ greek ] = "STYLE";
+ Text[ korean ] = "STYLE";
+ Text[ turkish ] = "STYLE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_DDE { Text = "DDE" ; };
+ String SC_OPCODE_BASE
+ {
+ Text = "BASIS" ;
+ Text [ english ] = "BASE" ;
+ Text [ portuguese ] = "BASE" ;
+ Text [ english_us ] = "BASE" ;
+ Text [ portuguese_brazilian ] = "BASIS" ;
+ Text [ swedish ] = "BAS" ;
+ Text [ danish ] = "BASIS" ;
+ Text [ italian ] = "BASE" ;
+ Text [ spanish ] = "BASE" ;
+ Text [ french ] = "BASE" ;
+ Text [ dutch ] = "BASIS" ;
+ Text[ chinese_simplified ] = "BASE";
+ Text[ russian ] = "ÁÀÇÈÑ";
+ Text[ polish ] = "BAZA";
+ Text[ japanese ] = "BASE";
+ Text[ chinese_traditional ] = "BASE";
+ Text[ arabic ] = "BASE";
+ Text[ dutch ] = "BASIS";
+ Text[ chinese_simplified ] = "BASE";
+ Text[ greek ] = "BASE";
+ Text[ korean ] = "BASE";
+ Text[ turkish ] = "BASE";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_DECIMAL
+ {
+ Text = "DEZIMAL" ;
+ Text [ english ] = "DECIMAL" ;
+ Text [ english_us ] = "DECIMAL" ;
+ Text[ portuguese ] = "DECIMAL";
+ Text[ russian ] = "ÄÅÑßÒÈ×ÍÛÉ";
+ Text[ dutch ] = "DECIMAAL";
+ Text[ french ] = "DÉCIMAL";
+ Text[ spanish ] = "DECIMAL";
+ Text[ italian ] = "DECIMALE";
+ Text[ danish ] = "DECIMAL";
+ Text[ swedish ] = "DECIMAL";
+ Text[ polish ] = "DZIESIÊTNY";
+ Text[ portuguese_brazilian ] = "DECIMAL";
+ Text[ japanese ] = "DECIMAL";
+ Text[ chinese_simplified ] = "DECIMAL";
+ Text[ chinese_traditional ] = "DECIMAL";
+ Text[ arabic ] = "DECIMAL";
+ Text[ dutch ] = "DECIMAAL";
+ Text[ chinese_simplified ] = "DECIMAL";
+ Text[ greek ] = "DECIMAL";
+ Text[ korean ] = "DECIMAL";
+ Text[ turkish ] = "DECIMAL";
+ Text[ language_user1 ] = " ";
+ };
+ String SC_OPCODE_CONVERT
+ {
+ Text = "UMRECHNEN" ;
+ Text [ english ] = "CONVERT" ;
+ Text[ english_us ] = "CONVERT";
+ Text[ portuguese ] = "CONVERTER";
+ Text[ russian ] = "ÏÐÅÎÁÐÀÇÎÂÀÍÈÅ";
+ Text[ dutch ] = "CONVERTEREN";
+ Text[ french ] = "CONVERTIR";
+ Text[ spanish ] = "CONVERTIR";
+ Text[ italian ] = "CONVERTI";
+ Text[ danish ] = "OMREGN";
+ Text[ swedish ] = "OMRÄKNA";
+ Text[ polish ] = "PRZELICZ";
+ Text[ portuguese_brazilian ] = "CONVERT";
+ Text[ japanese ] = "CONVERT";
+ Text[ chinese_simplified ] = "CONVERT";
+ Text[ chinese_traditional ] = "CONVERT";
+ Text[ arabic ] = "CONVERT";
+ Text[ dutch ] = "CONVERTEREN";
+ Text[ chinese_simplified ] = "CONVERT";
+ Text[ greek ] = "CONVERT";
+ Text[ korean ] = "º¯Çü";
+ Text[ turkish ] = "CONVERT";
+ Text[ language_user1 ] = " ";
+ };
+};
+Resource RID_SC_FUNCTION_NAMES_ENGLISH
+{
+ String SC_OPCODE_IF { Text = "IF" ; };
+ String SC_OPCODE_CHOSE { Text = "CHOOSE" ; };
+ String SC_OPCODE_OPEN { Text = "(" ; };
+ String SC_OPCODE_CLOSE { Text = ")" ; };
+ String SC_OPCODE_SEP { Text = ";" ; };
+ String SC_OPCODE_ADD { Text = "+" ; };
+ String SC_OPCODE_SUB { Text = "-" ; };
+ String SC_OPCODE_MUL { Text = "*" ; };
+ String SC_OPCODE_DIV { Text = "/" ; };
+ String SC_OPCODE_AMPERSAND { Text = "&" ; };
+ String SC_OPCODE_POW { Text = "^" ; };
+ String SC_OPCODE_EQUAL { Text = "=" ; };
+ String SC_OPCODE_NOT_EQUAL { Text = "<>" ; };
+ String SC_OPCODE_LESS { Text = "<" ; };
+ String SC_OPCODE_GREATER { Text = ">" ; };
+ String SC_OPCODE_LESS_EQUAL { Text = "<=" ; };
+ String SC_OPCODE_GREATER_EQUAL { Text = ">=" ; };
+ String SC_OPCODE_AND { Text = "AND" ; };
+ String SC_OPCODE_OR { Text = "OR" ; };
+ String SC_OPCODE_INTERSECT { Text = "!" ; };
+ String SC_OPCODE_UNION { Text = ";" ; };
+ String SC_OPCODE_RANGE { Text = ":" ; };
+ String SC_OPCODE_NOT { Text = "NOT" ; };
+ String SC_OPCODE_NEG { Text = "NEG" ; };
+ String SC_OPCODE_NEG_SUB { Text = "-" ; };
+ String SC_OPCODE_PI { Text = "PI" ; };
+ String SC_OPCODE_RANDOM { Text = "RAND" ; };
+ String SC_OPCODE_TRUE { Text = "TRUE" ; };
+ String SC_OPCODE_FALSE { Text = "FALSE" ; };
+ String SC_OPCODE_GET_ACT_DATE { Text = "TODAY" ; };
+ String SC_OPCODE_GET_ACT_TIME { Text = "NOW" ; };
+ String SC_OPCODE_NO_VALUE { Text = "NA" ; };
+ String SC_OPCODE_CURRENT { Text = "CURRENT" ; };
+ String SC_OPCODE_DEG { Text = "DEGREES" ; };
+ String SC_OPCODE_RAD { Text = "RADIANS" ; };
+ String SC_OPCODE_SIN { Text = "SIN" ; };
+ String SC_OPCODE_COS { Text = "COS" ; };
+ String SC_OPCODE_TAN { Text = "TAN" ; };
+ String SC_OPCODE_COT { Text = "COT" ; };
+ String SC_OPCODE_ARC_SIN { Text = "ASIN" ; };
+ String SC_OPCODE_ARC_COS { Text = "ACOS" ; };
+ String SC_OPCODE_ARC_TAN { Text = "ATAN" ; };
+ String SC_OPCODE_ARC_COT { Text = "ACOT" ; };
+ String SC_OPCODE_SIN_HYP { Text = "SINH" ; };
+ String SC_OPCODE_COS_HYP { Text = "COSH" ; };
+ String SC_OPCODE_TAN_HYP { Text = "TANH" ; };
+ String SC_OPCODE_COT_HYP { Text = "COTH" ; };
+ String SC_OPCODE_ARC_SIN_HYP { Text = "ASINH" ; };
+ String SC_OPCODE_ARC_COS_HYP { Text = "ACOSH" ; };
+ String SC_OPCODE_ARC_TAN_HYP { Text = "ATANH" ; };
+ String SC_OPCODE_ARC_COT_HYP { Text = "ACOTH" ; };
+ String SC_OPCODE_EXP { Text = "EXP" ; };
+ String SC_OPCODE_LN { Text = "LN" ; };
+ String SC_OPCODE_SQRT { Text = "SQRT" ; };
+ String SC_OPCODE_FACT { Text = "FACT" ; };
+ String SC_OPCODE_GET_YEAR { Text = "YEAR" ; };
+ String SC_OPCODE_GET_MONTH { Text = "MONTH" ; };
+ String SC_OPCODE_GET_DAY { Text = "DAY" ; };
+ String SC_OPCODE_GET_HOUR { Text = "HOUR" ; };
+ String SC_OPCODE_GET_MIN { Text = "MINUTE" ; };
+ String SC_OPCODE_GET_SEC { Text = "SECOND" ; };
+ String SC_OPCODE_PLUS_MINUS { Text = "SIGN" ; };
+ String SC_OPCODE_ABS { Text = "ABS" ; };
+ String SC_OPCODE_INT { Text = "INT" ; };
+ String SC_OPCODE_PHI { Text = "PHI" ; };
+ String SC_OPCODE_GAUSS { Text = "GAUSS" ; };
+ String SC_OPCODE_IS_EMPTY { Text = "ISBLANK" ; };
+ String SC_OPCODE_IS_STRING { Text = "ISTEXT" ; };
+ String SC_OPCODE_IS_NON_STRING { Text = "ISNONTEXT" ; };
+ String SC_OPCODE_IS_LOGICAL { Text = "ISLOGICAL" ; };
+ String SC_OPCODE_TYPE { Text = "TYPE" ; };
+ String SC_OPCODE_IS_REF { Text = "ISREF" ; };
+ String SC_OPCODE_IS_VALUE { Text = "ISNUMBER" ; };
+ String SC_OPCODE_IS_FORMULA { Text = "ISFORMULA" ; };
+ String SC_OPCODE_IS_NV { Text = "ISNA" ; };
+ String SC_OPCODE_IS_ERR { Text = "ISERR" ; };
+ String SC_OPCODE_IS_ERROR { Text = "ISERROR" ; };
+ String SC_OPCODE_IS_EVEN { Text = "ISEVEN" ; };
+ String SC_OPCODE_IS_ODD { Text = "ISODD" ; };
+ String SC_OPCODE_N { Text = "N" ; };
+ String SC_OPCODE_GET_DATE_VALUE { Text = "DATEVALUE" ; };
+ String SC_OPCODE_GET_TIME_VALUE { Text = "TIMEVALUE" ; };
+ String SC_OPCODE_CODE { Text = "CODE" ; };
+ String SC_OPCODE_TRIM { Text = "TRIM" ; };
+ String SC_OPCODE_UPPER { Text = "UPPER" ; };
+ String SC_OPCODE_PROPPER { Text = "PROPER" ; };
+ String SC_OPCODE_LOWER { Text = "LOWER" ; };
+ String SC_OPCODE_LEN { Text = "LEN" ; };
+ String SC_OPCODE_T { Text = "T" ; };
+ String SC_OPCODE_VALUE { Text = "VALUE" ; };
+ String SC_OPCODE_CLEAN { Text = "CLEAN" ; };
+ String SC_OPCODE_CHAR { Text = "CHAR" ; };
+ String SC_OPCODE_LOG10 { Text = "LOG10" ; };
+ String SC_OPCODE_EVEN { Text = "EVEN" ; };
+ String SC_OPCODE_ODD { Text = "ODD" ; };
+ String SC_OPCODE_STD_NORM_DIST { Text = "NORMSDIST" ; };
+ String SC_OPCODE_FISHER { Text = "FISHER" ; };
+ String SC_OPCODE_FISHER_INV { Text = "FISHERINV" ; };
+ String SC_OPCODE_S_NORM_INV { Text = "NORMSINV" ; };
+ String SC_OPCODE_GAMMA_LN { Text = "GAMMALN" ; };
+ String SC_OPCODE_ERROR_TYPE { Text = "ERRORTYPE" ; };
+ String SC_OPCODE_ERR_CELL { Text = "ZellError" ; }; // ?? Text klein, dt. & engl. gemischt ??
+ String SC_OPCODE_FORMULA { Text = "FORMULA"; };
+ String SC_OPCODE_ARC_TAN_2 { Text = "ATAN2" ; };
+ String SC_OPCODE_CEIL { Text = "CEILING" ; };
+ String SC_OPCODE_FLOOR { Text = "FLOOR" ; };
+ String SC_OPCODE_ROUND { Text = "ROUND" ; };
+ String SC_OPCODE_ROUND_UP { Text = "ROUNDUP" ; };
+ String SC_OPCODE_ROUND_DOWN { Text = "ROUNDDOWN" ; };
+ String SC_OPCODE_TRUNC { Text = "TRUNC" ; };
+ String SC_OPCODE_LOG { Text = "LOG" ; };
+ String SC_OPCODE_POWER { Text = "POWER" ; };
+ String SC_OPCODE_GGT { Text = "GCD" ; };
+ String SC_OPCODE_KGV { Text = "LCM" ; };
+ String SC_OPCODE_MOD { Text = "MOD" ; };
+ String SC_OPCODE_SUM_PRODUCT { Text = "SUMPRODUCT" ; };
+ String SC_OPCODE_SUM_SQ { Text = "SUMSQ" ; };
+ String SC_OPCODE_SUM_X2MY2 { Text = "SUMX2MY2" ; };
+ String SC_OPCODE_SUM_X2DY2 { Text = "SUMX2PY2" ; };
+ String SC_OPCODE_SUM_XMY2 { Text = "SUMXMY2" ; };
+ String SC_OPCODE_GET_DATE { Text = "DATE" ; };
+ String SC_OPCODE_GET_TIME { Text = "TIME" ; };
+ String SC_OPCODE_GET_DIFF_DATE { Text = "DAYS" ; };
+ String SC_OPCODE_GET_DIFF_DATE_360 { Text = "DAYS360" ; };
+ String SC_OPCODE_MIN { Text = "MIN" ; };
+ String SC_OPCODE_MIN_A { Text = "MINA" ; };
+ String SC_OPCODE_MAX { Text = "MAX" ; };
+ String SC_OPCODE_MAX_A { Text = "MAXA" ; };
+ String SC_OPCODE_SUM { Text = "SUM" ; };
+ String SC_OPCODE_PRODUCT { Text = "PRODUCT" ; };
+ String SC_OPCODE_AVERAGE { Text = "AVERAGE" ; };
+ String SC_OPCODE_AVERAGE_A { Text = "AVERAGEA" ; };
+ String SC_OPCODE_COUNT { Text = "COUNT" ; };
+ String SC_OPCODE_COUNT_2 { Text = "COUNTA" ; };
+ String SC_OPCODE_NBW { Text = "NPV" ; };
+ String SC_OPCODE_IKV { Text = "IRR" ; };
+ String SC_OPCODE_VAR { Text = "VAR" ; };
+ String SC_OPCODE_VAR_A { Text = "VARA" ; };
+ String SC_OPCODE_VAR_P { Text = "VARP" ; };
+ String SC_OPCODE_VAR_P_A { Text = "VARPA" ; };
+ String SC_OPCODE_ST_DEV { Text = "STDEV" ; };
+ String SC_OPCODE_ST_DEV_A { Text = "STDEVA" ; };
+ String SC_OPCODE_ST_DEV_P { Text = "STDEVP" ; };
+ String SC_OPCODE_ST_DEV_P_A { Text = "STDEVPA" ; };
+ String SC_OPCODE_B { Text = "B" ; };
+ String SC_OPCODE_NORM_DIST { Text = "NORMDIST" ; };
+ String SC_OPCODE_EXP_DIST { Text = "EXPONDIST" ; };
+ String SC_OPCODE_BINOM_DIST { Text = "BINOMDIST" ; };
+ String SC_OPCODE_POISSON_DIST { Text = "POISSON" ; };
+ String SC_OPCODE_KOMBIN { Text = "COMBIN" ; };
+ String SC_OPCODE_KOMBIN_2 { Text = "COMBINA" ; };
+ String SC_OPCODE_VARIATIONEN { Text = "PERMUT" ; };
+ String SC_OPCODE_VARIATIONEN_2 { Text = "PERMUTATIONA" ; };
+ String SC_OPCODE_BW { Text = "PV" ; };
+ String SC_OPCODE_DIA { Text = "SYD" ; };
+ String SC_OPCODE_GDA { Text = "DDB" ; };
+ String SC_OPCODE_GDA_2 { Text = "DB" ; };
+ String SC_OPCODE_VBD { Text = "VDB" ; };
+ String SC_OPCODE_LAUFZ { Text = "DURATION" ; };
+ String SC_OPCODE_LIA { Text = "SLN" ; };
+ String SC_OPCODE_RMZ { Text = "PMT" ; };
+ String SC_OPCODE_COLUMNS { Text = "COLUMNS" ; };
+ String SC_OPCODE_ROWS { Text = "ROWS" ; };
+ String SC_OPCODE_TABLES { Text = "SHEETS" ; };
+ String SC_OPCODE_COLUMN { Text = "COLUMN" ; };
+ String SC_OPCODE_ROW { Text = "ROW" ; };
+ String SC_OPCODE_TABLE { Text = "SHEET" ; };
+ String SC_OPCODE_ZGZ { Text = "ZGZ" ; };
+ String SC_OPCODE_ZW { Text = "FV" ; };
+ String SC_OPCODE_ZZR { Text = "NPER" ; };
+ String SC_OPCODE_ZINS { Text = "RATE" ; };
+ String SC_OPCODE_ZINS_Z { Text = "IPMT" ; };
+ String SC_OPCODE_KAPZ { Text = "PPMT" ; };
+ String SC_OPCODE_KUM_ZINS_Z { Text = "CUMIPMT" ; };
+ String SC_OPCODE_KUM_KAP_Z { Text = "CUMPRINC" ; };
+ String SC_OPCODE_EFFEKTIV { Text = "EFFECTIVE" ; };
+ String SC_OPCODE_NOMINAL { Text = "NOMINAL" ; };
+ String SC_OPCODE_SUB_TOTAL { Text = "SUBTOTAL" ; };
+ String SC_OPCODE_DB_SUM { Text = "DSUM" ; };
+ String SC_OPCODE_DB_COUNT { Text = "DCOUNT" ; };
+ String SC_OPCODE_DB_COUNT_2 { Text = "DCOUNTA" ; };
+ String SC_OPCODE_DB_AVERAGE { Text = "DAVERAGE" ; };
+ String SC_OPCODE_DB_GET { Text = "DGET" ; };
+ String SC_OPCODE_DB_MAX { Text = "DMAX" ; };
+ String SC_OPCODE_DB_MIN { Text = "DMIN" ; };
+ String SC_OPCODE_DB_PRODUCT { Text = "DPRODUCT" ; };
+ String SC_OPCODE_DB_STD_DEV { Text = "DSTDEV" ; };
+ String SC_OPCODE_DB_STD_DEV_P { Text = "DSTDEVP" ; };
+ String SC_OPCODE_DB_VAR { Text = "DVAR" ; };
+ String SC_OPCODE_DB_VAR_P { Text = "DVARP" ; };
+ String SC_OPCODE_INDIRECT { Text = "INDIRECT" ; };
+ String SC_OPCODE_ADRESS { Text = "ADDRESS" ; };
+ String SC_OPCODE_MATCH { Text = "MATCH" ; };
+ String SC_OPCODE_COUNT_EMPTY_CELLS { Text = "COUNTBLANK" ; };
+ String SC_OPCODE_COUNT_IF { Text = "COUNTIF" ; };
+ String SC_OPCODE_SUM_IF { Text = "SUMIF" ; };
+ String SC_OPCODE_LOOKUP { Text = "LOOKUP" ; };
+ String SC_OPCODE_V_LOOKUP { Text = "VLOOKUP" ; };
+ String SC_OPCODE_H_LOOKUP { Text = "HLOOKUP" ; };
+ String SC_OPCODE_MULTI_AREA { Text = "MULTIRANGE" ; };
+ String SC_OPCODE_OFFSET { Text = "OFFSET" ; };
+ String SC_OPCODE_INDEX { Text = "INDEX" ; };
+ String SC_OPCODE_AREAS { Text = "AREAS" ; };
+ String SC_OPCODE_CURRENCY { Text = "DOLLAR" ; };
+ String SC_OPCODE_REPLACE { Text = "REPLACE" ; };
+ String SC_OPCODE_FIXED { Text = "FIXED" ; };
+ String SC_OPCODE_FIND { Text = "FIND" ; };
+ String SC_OPCODE_EXACT { Text = "EXACT" ; };
+ String SC_OPCODE_LEFT { Text = "LEFT" ; };
+ String SC_OPCODE_RIGHT { Text = "RIGHT" ; };
+ String SC_OPCODE_SEARCH { Text = "SEARCH" ; };
+ String SC_OPCODE_MID { Text = "MID" ; };
+ String SC_OPCODE_TEXT { Text = "TEXT" ; };
+ String SC_OPCODE_SUBSTITUTE { Text = "SUBSTITUTE" ; };
+ String SC_OPCODE_REPT { Text = "REPT" ; };
+ String SC_OPCODE_CONCAT { Text = "CONCATENATE" ; };
+ String SC_OPCODE_MAT_VALUE { Text = "MVALUE" ; };
+ String SC_OPCODE_MAT_DET { Text = "MDETERM" ; };
+ String SC_OPCODE_MAT_INV { Text = "MINVERSE" ; };
+ String SC_OPCODE_MAT_MULT { Text = "MMULT" ; };
+ String SC_OPCODE_MAT_TRANS { Text = "TRANSPOSE" ; };
+ String SC_OPCODE_MATRIX_UNIT { Text = "MUNIT" ; };
+ String SC_OPCODE_BACK_SOLVER { Text = "GOALSEEK" ; };
+ String SC_OPCODE_HYP_GEOM_DIST { Text = "HYPGEOMDIST" ; };
+ String SC_OPCODE_LOG_NORM_DIST { Text = "LOGNORMDIST" ; };
+ String SC_OPCODE_T_DIST { Text = "TDIST" ; };
+ String SC_OPCODE_F_DIST { Text = "FDIST" ; };
+ String SC_OPCODE_CHI_DIST { Text = "CHIDIST" ; };
+ String SC_OPCODE_WEIBULL { Text = "WEIBULL" ; };
+ String SC_OPCODE_NEG_BINOM_VERT { Text = "NEGBINOMDIST" ; };
+ String SC_OPCODE_KRIT_BINOM { Text = "CRITBINOM" ; };
+ String SC_OPCODE_KURT { Text = "KURT" ; };
+ String SC_OPCODE_HAR_MEAN { Text = "HARMEAN" ; };
+ String SC_OPCODE_GEO_MEAN { Text = "GEOMEAN" ; };
+ String SC_OPCODE_STANDARD { Text = "STANDARDIZE" ; };
+ String SC_OPCODE_AVE_DEV { Text = "AVEDEV" ; };
+ String SC_OPCODE_SCHIEFE { Text = "SKEW" ; };
+ String SC_OPCODE_DEV_SQ { Text = "DEVSQ" ; };
+ String SC_OPCODE_MEDIAN { Text = "MEDIAN" ; };
+ String SC_OPCODE_MODAL_VALUE { Text = "MODE" ; };
+ String SC_OPCODE_Z_TEST { Text = "ZTEST" ; };
+ String SC_OPCODE_T_TEST { Text = "TTEST" ; };
+ String SC_OPCODE_RANK { Text = "RANK" ; };
+ String SC_OPCODE_PERCENTILE { Text = "PERCENTILE" ; };
+ String SC_OPCODE_PERCENT_RANK { Text = "PERCENTRANK" ; };
+ String SC_OPCODE_LARGE { Text = "LARGE" ; };
+ String SC_OPCODE_SMALL { Text = "SMALL" ; };
+ String SC_OPCODE_FREQUENCY { Text = "FREQUENCY" ; };
+ String SC_OPCODE_QUARTILE { Text = "QUARTILE" ; };
+ String SC_OPCODE_NORM_INV { Text = "NORMINV" ; };
+ String SC_OPCODE_CONFIDENCE { Text = "CONFIDENCE" ; };
+ String SC_OPCODE_F_TEST { Text = "FTEST" ; };
+ String SC_OPCODE_TRIM_MEAN { Text = "TRIMMEAN" ; };
+ String SC_OPCODE_PROB { Text = "PROB" ; };
+ String SC_OPCODE_CORREL { Text = "CORREL" ; };
+ String SC_OPCODE_COVAR { Text = "COVAR" ; };
+ String SC_OPCODE_PEARSON { Text = "PEARSON" ; };
+ String SC_OPCODE_RSQ { Text = "RSQ" ; };
+ String SC_OPCODE_STEYX { Text = "STEYX" ; };
+ String SC_OPCODE_SLOPE { Text = "SLOPE" ; };
+ String SC_OPCODE_INTERCEPT { Text = "INTERCEPT" ; };
+ String SC_OPCODE_TREND { Text = "TREND" ; };
+ String SC_OPCODE_GROWTH { Text = "GROWTH" ; };
+ String SC_OPCODE_RGP { Text = "LINEST" ; };
+ String SC_OPCODE_RKP { Text = "LOGEST" ; };
+ String SC_OPCODE_FORECAST { Text = "FORECAST" ; };
+ String SC_OPCODE_CHI_INV { Text = "CHIINV" ; };
+ String SC_OPCODE_GAMMA_DIST { Text = "GAMMADIST" ; };
+ String SC_OPCODE_GAMMA_INV { Text = "GAMMAINV" ; };
+ String SC_OPCODE_T_INV { Text = "TINV" ; };
+ String SC_OPCODE_F_INV { Text = "FINV" ; };
+ String SC_OPCODE_CHI_TEST { Text = "CHITEST" ; };
+ String SC_OPCODE_LOG_INV { Text = "LOGINV" ; };
+ String SC_OPCODE_TABLE_OP { Text = "TABLE" ; };
+ String SC_OPCODE_BETA_DIST { Text = "BETADIST" ; };
+ String SC_OPCODE_BETA_INV { Text = "BETAINV" ; };
+ String SC_OPCODE_WEEK { Text = "WEEKNUM" ; };
+ String SC_OPCODE_EASTERSUNDAY { Text = "EASTERSUNDAY" ; };
+ String SC_OPCODE_GET_DAY_OF_WEEK { Text = "WEEKDAY" ; };
+ String SC_OPCODE_NO_NAME { Text = "#NAME!" ; };
+ String SC_OPCODE_STYLE { Text = "STYLE" ; };
+ String SC_OPCODE_DDE { Text = "DDE" ; };
+ String SC_OPCODE_BASE { Text = "BASE" ; };
+ String SC_OPCODE_DECIMAL { Text = "DECIMAL" ; };
+ String SC_OPCODE_CONVERT { Text = "CONVERT" ; };
+};
diff --git a/sc/source/core/src/makefile.mk b/sc/source/core/src/makefile.mk
new file mode 100644
index 000000000000..23b9d6836293
--- /dev/null
+++ b/sc/source/core/src/makefile.mk
@@ -0,0 +1,86 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-19 00:16:16 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=sc
+TARGET=core
+
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : scpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sc.mk
+
+# --- Rsc-Flags ----------------------------------------------------
+
+#RSCFLAGS=$(RSCFLAGS) -DUPDVER="$(UPD)$(UPDMINOR)"
+
+# --- Files --------------------------------------------------------
+
+SRCFILES = \
+ compiler.src
+# --- Tagets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/sc/source/core/tool/addincol.cxx b/sc/source/core/tool/addincol.cxx
new file mode 100644
index 000000000000..59b04b412ab9
--- /dev/null
+++ b/sc/source/core/tool/addincol.cxx
@@ -0,0 +1,1205 @@
+/*************************************************************************
+ *
+ * $RCSfile: addincol.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include <unotools/processfactory.hxx>
+#include <tools/debug.hxx>
+#include <tools/intn.hxx>
+#include <tools/isolang.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/system.hxx>
+#include <vos/xception.hxx>
+#include <sfx2/objsh.hxx>
+#include <unotools/charclass.hxx>
+
+#include <com/sun/star/container/XContentEnumerationAccess.hpp>
+#include <com/sun/star/lang/XServiceName.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/reflection/XIdlClass.hpp>
+#include <com/sun/star/reflection/XIdlClassProvider.hpp>
+#include <com/sun/star/beans/XIntrospectionAccess.hpp>
+#include <com/sun/star/beans/XIntrospection.hpp>
+#include <com/sun/star/beans/MethodConcept.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/table/XCellRange.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+
+#include "addincol.hxx"
+#include "compiler.hxx"
+#include "scmatrix.hxx"
+#include "addinlis.hxx"
+#include "scfuncs.hrc"
+
+using namespace com::sun::star;
+
+//------------------------------------------------------------------------
+
+#define SC_CALLERPOS_NONE (-1)
+
+#define SCADDINSUPPLIER_SERVICE "com.sun.star.sheet.AddIn"
+
+//------------------------------------------------------------------------
+
+
+#define SC_FUNCGROUP_COUNT ID_FUNCTION_GRP_ADDINS
+
+static const sal_Char* __FAR_DATA aFuncNames[SC_FUNCGROUP_COUNT] =
+ {
+ // array index = ID - 1 (ID starts at 1)
+ // all upper case
+ "Database", // ID_FUNCTION_GRP_DATABASE
+ "Date&Time", // ID_FUNCTION_GRP_DATETIME
+ "Financial", // ID_FUNCTION_GRP_FINANZ
+ "Information", // ID_FUNCTION_GRP_INFO
+ "Logical", // ID_FUNCTION_GRP_LOGIC
+ "Mathematical", // ID_FUNCTION_GRP_MATH
+ "Matrix", // ID_FUNCTION_GRP_MATRIX
+ "Statistical", // ID_FUNCTION_GRP_STATISTIC
+ "Spreadsheet", // ID_FUNCTION_GRP_TABLE
+ "Text", // ID_FUNCTION_GRP_TEXT
+ "Add-In" // ID_FUNCTION_GRP_ADDINS
+ };
+
+
+//------------------------------------------------------------------------
+
+struct ScAddInArgDesc
+{
+ String aName;
+ String aDescription;
+ ScAddInArgumentType eType;
+ BOOL bOptional;
+};
+
+class ScUnoAddInFuncData
+{
+private:
+ String aOriginalName; // kept in formula
+ String aLocalName; // for display
+ String aUpperName; // for entering formulas
+ String aUpperLocal; // for entering formulas
+ String aDescription;
+ uno::Reference<reflection::XIdlMethod> xFunction;
+ uno::Any aObject;
+ long nArgCount;
+ ScAddInArgDesc* pArgDescs;
+ long nCallerPos;
+ USHORT nCategory;
+
+public:
+ ScUnoAddInFuncData( const String& rNam, const String& rLoc,
+ const String& rDesc, USHORT nCat,
+ const uno::Reference<reflection::XIdlMethod>& rFunc,
+ const uno::Any& rO,
+ long nAC, const ScAddInArgDesc* pAD,
+ long nCP );
+ ~ScUnoAddInFuncData();
+
+ const String& GetOriginalName() const { return aOriginalName; }
+ const String& GetLocalName() const { return aLocalName; }
+ const String& GetUpperName() const { return aUpperName; }
+ const String& GetUpperLocal() const { return aUpperLocal; }
+ const uno::Reference<reflection::XIdlMethod>& GetFunction() const
+ { return xFunction; }
+ const uno::Any& GetObject() const { return aObject; }
+ long GetArgumentCount() const { return nArgCount; }
+ const ScAddInArgDesc* GetArguments() const { return pArgDescs; }
+ long GetCallerPos() const { return nCallerPos; }
+ const String& GetDescription() const { return aDescription; }
+ USHORT GetCategory() const { return nCategory; }
+};
+
+//------------------------------------------------------------------------
+
+ScUnoAddInFuncData::ScUnoAddInFuncData( const String& rNam, const String& rLoc,
+ const String& rDesc, USHORT nCat,
+ const uno::Reference<reflection::XIdlMethod>& rFunc,
+ const uno::Any& rO,
+ long nAC, const ScAddInArgDesc* pAD,
+ long nCP ) :
+ aOriginalName( rNam ),
+ aUpperName( rNam ),
+ aLocalName( rLoc ),
+ aUpperLocal( rLoc ),
+ aDescription( rDesc ),
+ nCategory( nCat ),
+ xFunction( rFunc ),
+ aObject( rO ),
+ nArgCount( nAC ),
+ nCallerPos( nCP )
+{
+ if ( nArgCount )
+ {
+ pArgDescs = new ScAddInArgDesc[nArgCount];
+ for (long i=0; i<nArgCount; i++)
+ pArgDescs[i] = pAD[i];
+ }
+ else
+ pArgDescs = NULL;
+
+ ScGlobal::pCharClass->toUpper(aUpperName);
+ ScGlobal::pCharClass->toUpper(aUpperLocal);
+}
+
+ScUnoAddInFuncData::~ScUnoAddInFuncData()
+{
+ delete[] pArgDescs;
+}
+
+//------------------------------------------------------------------------
+
+BOOL lcl_ConvertToDouble( const uno::Any& rAny, double& rOut )
+{
+ BOOL bRet = FALSE;
+ uno::TypeClass eClass = rAny.getValueTypeClass();
+ switch (eClass)
+ {
+ //! extract integer values
+ case uno::TypeClass_ENUM:
+ case uno::TypeClass_BOOLEAN:
+ case uno::TypeClass_CHAR:
+ case uno::TypeClass_BYTE:
+ case uno::TypeClass_SHORT:
+ case uno::TypeClass_UNSIGNED_SHORT:
+ case uno::TypeClass_LONG:
+ case uno::TypeClass_UNSIGNED_LONG:
+ case uno::TypeClass_FLOAT:
+ case uno::TypeClass_DOUBLE:
+ rAny >>= rOut;
+ bRet = TRUE;
+ break;
+ }
+ if (!bRet)
+ rOut = 0.0;
+ return bRet;
+}
+
+//------------------------------------------------------------------------
+
+ScUnoAddInCollection::ScUnoAddInCollection() :
+ nFuncCount( 0 ),
+ ppFuncData( NULL ),
+ bInitialized( FALSE )
+{
+}
+
+ScUnoAddInCollection::~ScUnoAddInCollection()
+{
+ if ( ppFuncData )
+ {
+ for ( long i=0; i<nFuncCount; i++ )
+ delete ppFuncData[i];
+ delete[] ppFuncData;
+ }
+}
+
+void ScUnoAddInCollection::Initialize()
+{
+ DBG_ASSERT( !bInitialized, "Initialize twice?" )
+
+ uno::Reference<lang::XMultiServiceFactory> xManager = utl::getProcessServiceFactory();
+ uno::Reference<container::XContentEnumerationAccess> xEnAc( xManager, uno::UNO_QUERY );
+ if ( xEnAc.is() )
+ {
+ uno::Reference<container::XEnumeration> xEnum =
+ xEnAc->createContentEnumeration(
+ rtl::OUString::createFromAscii(SCADDINSUPPLIER_SERVICE) );
+ if ( xEnum.is() )
+ {
+ // loop through all AddIns
+ while ( xEnum->hasMoreElements() )
+ {
+ uno::Any aAddInAny = xEnum->nextElement();
+//? if ( aAddInAny.getReflection()->getTypeClass() == uno::TypeClass_INTERFACE )
+ {
+ uno::Reference<uno::XInterface> xIntFac;
+ aAddInAny >>= xIntFac;
+ if ( xIntFac.is() )
+ {
+ uno::Reference<lang::XSingleServiceFactory> xFac( xIntFac, uno::UNO_QUERY );
+ if ( xFac.is() )
+ {
+ uno::Reference<uno::XInterface> xInterface = xFac->createInstance();
+ ReadFromAddIn( xInterface );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ bInitialized = TRUE; // with or without functions
+}
+
+USHORT lcl_GetCategory( const String& rName )
+{
+ for (USHORT i=0; i<SC_FUNCGROUP_COUNT; i++)
+ if ( rName.EqualsAscii( aFuncNames[i] ) )
+ return i+1; // IDs start at 1
+
+ return ID_FUNCTION_GRP_ADDINS; // if not found, use Add-In group
+}
+
+inline BOOL IsTypeName( const rtl::OUString& rName, const uno::Type& rType )
+{
+ return rName == rType.getTypeName();
+}
+
+BOOL lcl_ValidReturnType( const uno::Reference<reflection::XIdlClass>& xClass )
+{
+ // this must match with ScUnoAddInCall::SetResult
+
+ if ( !xClass.is() ) return FALSE;
+
+ switch (xClass->getTypeClass())
+ {
+ // case uno::TypeClass_VOID:
+ // ???
+
+ case uno::TypeClass_ANY: // variable type
+ case uno::TypeClass_ENUM: //! ???
+ case uno::TypeClass_BOOLEAN:
+ case uno::TypeClass_CHAR:
+ case uno::TypeClass_BYTE:
+ case uno::TypeClass_SHORT:
+ case uno::TypeClass_UNSIGNED_SHORT:
+ case uno::TypeClass_LONG:
+ case uno::TypeClass_UNSIGNED_LONG:
+ case uno::TypeClass_FLOAT:
+ case uno::TypeClass_DOUBLE:
+ case uno::TypeClass_STRING:
+ return TRUE; // values or string
+
+ case uno::TypeClass_INTERFACE:
+ {
+ // return type XInterface may contain a XVolatileResult
+ //! XIdlClass needs getType() method!
+
+ rtl::OUString sName = xClass->getName();
+ return (
+ IsTypeName( sName, getCppuType((uno::Reference<sheet::XVolatileResult>*)0) ) ||
+ IsTypeName( sName, getCppuType((uno::Reference<uno::XInterface>*)0) ) );
+ }
+
+ default:
+ {
+ // nested sequences for arrays
+ //! XIdlClass needs getType() method!
+
+ rtl::OUString sName = xClass->getName();
+ return (
+ IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<INT32> >*)0) ) ||
+ IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<double> >*)0) ) ||
+ IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<rtl::OUString> >*)0) ) ||
+ IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<uno::Any> >*)0) ) );
+ }
+ }
+ return FALSE;
+}
+
+ScAddInArgumentType lcl_GetArgType( const uno::Reference<reflection::XIdlClass>& xClass )
+{
+ if (!xClass.is())
+ return SC_ADDINARG_NONE;
+
+ uno::TypeClass eType = xClass->getTypeClass();
+
+ if ( eType == uno::TypeClass_LONG ) //! other integer types?
+ return SC_ADDINARG_INTEGER;
+
+ if ( eType == uno::TypeClass_DOUBLE )
+ return SC_ADDINARG_DOUBLE;
+
+ if ( eType == uno::TypeClass_STRING )
+ return SC_ADDINARG_STRING;
+
+ //! XIdlClass needs getType() method!
+ rtl::OUString sName = xClass->getName();
+
+ if (IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<INT32> >*)0) ))
+ return SC_ADDINARG_INTEGER_ARRAY;
+
+ if (IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<double> >*)0) ))
+ return SC_ADDINARG_DOUBLE_ARRAY;
+
+ if (IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<rtl::OUString> >*)0) ))
+ return SC_ADDINARG_STRING_ARRAY;
+
+ if (IsTypeName( sName, getCppuType((uno::Sequence< uno::Sequence<uno::Any> >*)0) ))
+ return SC_ADDINARG_MIXED_ARRAY;
+
+ if (IsTypeName( sName, getCppuType((uno::Any*)0) ))
+ return SC_ADDINARG_VALUE_OR_ARRAY;
+
+ if (IsTypeName( sName, getCppuType((uno::Reference<table::XCellRange>*)0) ))
+ return SC_ADDINARG_CELLRANGE;
+
+ if (IsTypeName( sName, getCppuType((uno::Reference<beans::XPropertySet>*)0) ))
+ return SC_ADDINARG_CALLER;
+
+ if (IsTypeName( sName, getCppuType((uno::Sequence<uno::Any>*)0) ))
+ return SC_ADDINARG_VARARGS;
+
+ return SC_ADDINARG_NONE;
+}
+
+void ScUnoAddInCollection::ReadFromAddIn( const uno::Reference<uno::XInterface>& xInterface )
+{
+ uno::Reference<sheet::XAddIn> xAddIn( xInterface, uno::UNO_QUERY );
+ uno::Reference<lang::XServiceName> xName( xInterface, uno::UNO_QUERY );
+ if ( xAddIn.is() && xName.is() )
+ {
+ // AddIns must use the language for which the office is installed
+ LanguageType eOfficeLang = Application::GetAppInternational().GetLanguage();
+ if ( eOfficeLang == LANGUAGE_SYSTEM )
+ eOfficeLang = System::GetLanguage();
+
+ String aLanguage, aCountry;
+ ConvertLanguageToIsoNames( eOfficeLang, aLanguage, aCountry );
+
+ rtl::OUString aEmpty;
+ lang::Locale aLocale( aLanguage, aCountry, aEmpty );
+ xAddIn->setLocale( aLocale );
+
+ String aServiceName = String( xName->getServiceName() );
+
+ //! pass XIntrospection to ReadFromAddIn
+
+ uno::Reference<lang::XMultiServiceFactory> xManager = utl::getProcessServiceFactory();
+ if ( xManager.is() )
+ {
+ uno::Reference<beans::XIntrospection> xIntro(
+ xManager->createInstance(rtl::OUString::createFromAscii(
+ "com.sun.star.beans.Introspection" )),
+ uno::UNO_QUERY );
+ if ( xIntro.is() )
+ {
+ uno::Any aObject;
+ aObject <<= xAddIn;
+ uno::Reference<beans::XIntrospectionAccess> xAcc = xIntro->inspect(aObject);
+ if (xAcc.is())
+ {
+ uno::Sequence< uno::Reference<reflection::XIdlMethod> > aMethods =
+ xAcc->getMethods( beans::MethodConcept::ALL );
+ long nNewCount = aMethods.getLength();
+ if ( nNewCount )
+ {
+ long nOld = nFuncCount;
+ nFuncCount = nNewCount+nOld;
+ if ( nOld )
+ {
+ ScUnoAddInFuncData** ppNew = new ScUnoAddInFuncData*[nFuncCount];
+ for (long i=0; i<nOld; i++)
+ ppNew[i] = ppFuncData[i];
+ delete[] ppFuncData;
+ ppFuncData = ppNew;
+ }
+ else
+ ppFuncData = new ScUnoAddInFuncData*[nFuncCount];
+
+ const uno::Reference<reflection::XIdlMethod>* pArray = aMethods.getConstArray();
+ for (long nFuncPos=0; nFuncPos<nNewCount; nFuncPos++)
+ {
+ ppFuncData[nFuncPos+nOld] = NULL;
+
+ uno::Reference<reflection::XIdlMethod> xFunc = pArray[nFuncPos];
+ if (xFunc.is())
+ {
+ // leave out internal functions
+ uno::Reference<reflection::XIdlClass> xClass =
+ xFunc->getDeclaringClass();
+ BOOL bSkip = TRUE;
+ if ( xClass.is() )
+ {
+ //! XIdlClass needs getType() method!
+ rtl::OUString sName = xClass->getName();
+ bSkip = (
+ IsTypeName( sName,
+ getCppuType((uno::Reference<uno::XInterface>*)0) ) ||
+ IsTypeName( sName,
+ getCppuType((uno::Reference<reflection::XIdlClassProvider>*)0) ) ||
+ IsTypeName( sName,
+ getCppuType((uno::Reference<lang::XServiceName>*)0) ) ||
+ IsTypeName( sName,
+ getCppuType((uno::Reference<lang::XServiceInfo>*)0) ) ||
+ IsTypeName( sName,
+ getCppuType((uno::Reference<sheet::XAddIn>*)0) ) );
+ }
+ if (!bSkip)
+ {
+ uno::Reference<reflection::XIdlClass> xReturn =
+ xFunc->getReturnType();
+ if ( !lcl_ValidReturnType( xReturn ) )
+ bSkip = TRUE;
+ }
+ if (!bSkip)
+ {
+ rtl::OUString aFuncU = xFunc->getName();
+
+ // stored function name: (service name).(function)
+ String aFuncName = aServiceName;
+ aFuncName += '.';
+ aFuncName += String( aFuncU );
+
+ BOOL bValid = TRUE;
+ long nVisibleCount = 0;
+ long nCallerPos = SC_CALLERPOS_NONE;
+
+ uno::Sequence<reflection::ParamInfo> aParams =
+ xFunc->getParameterInfos();
+ long nParamCount = aParams.getLength();
+ const reflection::ParamInfo* pParArr = aParams.getConstArray();
+ long nParamPos;
+ for (nParamPos=0; nParamPos<nParamCount; nParamPos++)
+ {
+ if ( pParArr[nParamPos].aMode != reflection::ParamMode_IN )
+ bValid = FALSE;
+ uno::Reference<reflection::XIdlClass> xParClass =
+ pParArr[nParamPos].aType;
+ ScAddInArgumentType eArgType = lcl_GetArgType( xParClass );
+ if ( eArgType == SC_ADDINARG_NONE )
+ bValid = FALSE;
+ else if ( eArgType == SC_ADDINARG_CALLER )
+ nCallerPos = nParamPos;
+ else
+ ++nVisibleCount;
+ }
+ if (bValid)
+ {
+ USHORT nCategory = lcl_GetCategory(
+ String(
+ xAddIn->getProgrammaticCategoryName(
+ aFuncU ) ) );
+
+ rtl::OUString aLocalU;
+ TRY
+ {
+ aLocalU = xAddIn->
+ getDisplayFunctionName( aFuncU );
+ }
+ CATCH_ALL()
+ {
+ aLocalU = rtl::OUString::createFromAscii( "###" );
+ }
+ END_CATCH
+ String aLocalName = String( aLocalU );
+
+ rtl::OUString aDescU;
+ TRY
+ {
+ aDescU = xAddIn->
+ getFunctionDescription( aFuncU );
+ }
+ CATCH_ALL()
+ {
+ aDescU = rtl::OUString::createFromAscii( "###" );
+ }
+ END_CATCH
+ String aDescription = String( aDescU );
+
+ ScAddInArgDesc* pVisibleArgs = NULL;
+ if ( nVisibleCount > 0 )
+ {
+ ScAddInArgDesc aDesc;
+ pVisibleArgs = new ScAddInArgDesc[nVisibleCount];
+ long nDestPos = 0;
+ for (nParamPos=0; nParamPos<nParamCount; nParamPos++)
+ {
+ uno::Reference<reflection::XIdlClass> xParClass =
+ pParArr[nParamPos].aType;
+ ScAddInArgumentType eArgType = lcl_GetArgType( xParClass );
+ if ( eArgType != SC_ADDINARG_CALLER )
+ {
+ rtl::OUString aArgName;
+ TRY
+ {
+ aArgName = xAddIn->
+ getDisplayArgumentName( aFuncU, nParamPos );
+ }
+ CATCH_ALL()
+ {
+ aArgName = rtl::OUString::createFromAscii( "###" );
+ }
+ END_CATCH
+ rtl::OUString aArgDesc;
+ TRY
+ {
+ aArgDesc = xAddIn->
+ getArgumentDescription( aFuncU, nParamPos );
+ }
+ CATCH_ALL()
+ {
+ aArgName = rtl::OUString::createFromAscii( "###" );
+ }
+ END_CATCH
+
+ BOOL bOptional =
+ ( eArgType == SC_ADDINARG_VALUE_OR_ARRAY ||
+ eArgType == SC_ADDINARG_VARARGS );
+
+ aDesc.eType = eArgType;
+ aDesc.aName = String( aArgName );
+ aDesc.aDescription = String( aArgDesc );
+ aDesc.bOptional = bOptional;
+
+ pVisibleArgs[nDestPos++] = aDesc;
+ }
+ }
+ DBG_ASSERT( nDestPos==nVisibleCount, "wrong count" );
+ }
+
+ ppFuncData[nFuncPos+nOld] = new ScUnoAddInFuncData(
+ aFuncName, aLocalName, aDescription, nCategory,
+ xFunc, aObject,
+ nVisibleCount, pVisibleArgs, nCallerPos );
+
+ delete[] pVisibleArgs;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+String ScUnoAddInCollection::FindFunction( const String& rName, BOOL bLocalFirst )
+{
+ if (!bInitialized)
+ Initialize();
+
+ if (nFuncCount == 0)
+ return EMPTY_STRING;
+
+ String aUpperCmp = rName;
+ ScGlobal::pCharClass->toUpper(aUpperCmp);
+ long i;
+
+ if ( bLocalFirst )
+ {
+ // first scan all local names (used for entering formulas)
+
+ for (i=0; i<nFuncCount; i++)
+ if ( ppFuncData[i] && ppFuncData[i]->GetUpperLocal() == aUpperCmp )
+ return ppFuncData[i]->GetOriginalName();
+
+#if 0
+ // after that, scan international names (really?)
+
+ for (i=0; i<nFuncCount; i++)
+ if ( ppFuncData[i] && ppFuncData[i]->GetUpperName() == aUpperCmp )
+ return ppFuncData[i]->GetOriginalName();
+#endif
+ }
+ else
+ {
+ // first scan international names (used when calling a function)
+ //! before that, check for exact match???
+
+ for (i=0; i<nFuncCount; i++)
+ if ( ppFuncData[i] && ppFuncData[i]->GetUpperName() == aUpperCmp )
+ return ppFuncData[i]->GetOriginalName();
+
+ // after that, scan all local names (to allow replacing old AddIns with Uno)
+
+ for (i=0; i<nFuncCount; i++)
+ if ( ppFuncData[i] && ppFuncData[i]->GetUpperLocal() == aUpperCmp )
+ return ppFuncData[i]->GetOriginalName();
+ }
+
+ return EMPTY_STRING;
+}
+
+ScUnoAddInFuncData* ScUnoAddInCollection::GetFuncData( const String& rName )
+{
+ if (!bInitialized)
+ Initialize();
+
+ // rName must be the exact internal name
+
+ for (long i=0; i<nFuncCount; i++)
+ if ( ppFuncData[i] && ppFuncData[i]->GetOriginalName() == rName )
+ return ppFuncData[i];
+
+ return NULL;
+}
+
+void ScUnoAddInCollection::LocalizeString( String& rName )
+{
+ if (!bInitialized)
+ Initialize();
+
+ // modify rName - input: exact name
+
+ for (long i=0; i<nFuncCount; i++)
+ if ( ppFuncData[i] && ppFuncData[i]->GetOriginalName() == rName )
+ {
+ rName = ppFuncData[i]->GetUpperLocal(); //! upper?
+ return;
+ }
+}
+
+
+long ScUnoAddInCollection::GetFuncCount()
+{
+ if (!bInitialized)
+ Initialize();
+
+ return nFuncCount;
+}
+
+BOOL ScUnoAddInCollection::FillFunctionDesc( long nFunc, ScFuncDesc& rDesc )
+{
+ // rDesc must me freshly allocated (no arguments set)
+ DBG_ASSERT( !rDesc.aDefArgNames, "FuncDesc is not empty" );
+
+ if (!bInitialized)
+ Initialize();
+
+ if (nFunc >= nFuncCount || !ppFuncData[nFunc])
+ return FALSE;
+
+ long nArgCount = ppFuncData[nFunc]->GetArgumentCount();
+ if ( nArgCount > USHRT_MAX )
+ return FALSE;
+
+ // nFIndex is set from outside
+
+ rDesc.pFuncName = new String( ppFuncData[nFunc]->GetUpperLocal() ); //! upper?
+ rDesc.nCategory = ppFuncData[nFunc]->GetCategory();
+
+ String aDesc = ppFuncData[nFunc]->GetDescription();
+ if (!aDesc.Len())
+ aDesc = ppFuncData[nFunc]->GetLocalName(); // use name if no description is available
+ rDesc.pFuncDesc = new String( aDesc );
+
+ // AddInArgumentType_CALLER is already left out in FuncData
+
+ rDesc.nArgCount = (USHORT)nArgCount;
+ if ( nArgCount )
+ {
+ BOOL bMultiple = FALSE;
+ const ScAddInArgDesc* pArgs = ppFuncData[nFunc]->GetArguments();
+
+ rDesc.aDefArgNames = new String*[nArgCount];
+ rDesc.aDefArgDescs = new String*[nArgCount];
+ rDesc.aDefArgOpt = new BOOL[nArgCount];
+ for ( long nArg=0; nArg<nArgCount; nArg++ )
+ {
+ rDesc.aDefArgNames[nArg] = new String( pArgs[nArg].aName );
+ rDesc.aDefArgDescs[nArg] = new String( pArgs[nArg].aDescription );
+ rDesc.aDefArgOpt[nArg] = pArgs[nArg].bOptional;
+
+ // no empty names...
+ if ( rDesc.aDefArgNames[nArg]->Len() == 0 )
+ {
+ String aDefName( RTL_CONSTASCII_USTRINGPARAM("arg") );
+ aDefName += String::CreateFromInt32( nArg+1 );
+ *rDesc.aDefArgNames[nArg] = aDefName;
+ }
+
+ // last argument repeated?
+ if ( nArg+1 == nArgCount && ( pArgs[nArg].eType == SC_ADDINARG_VARARGS ) )
+ bMultiple = TRUE;
+ }
+
+ if ( bMultiple )
+ rDesc.nArgCount += VAR_ARGS - 1; // VAR_ARGS means just one repeated arg
+ }
+
+ return TRUE;
+}
+
+
+//------------------------------------------------------------------------
+
+ScUnoAddInCall::ScUnoAddInCall( ScUnoAddInCollection& rColl, const String& rName,
+ long nParamCount ) :
+ nErrCode( errNoCode ), // before function was called
+ bHasString( TRUE ),
+ fValue( 0.0 ),
+ pMatrix( NULL ),
+ bValidCount( FALSE )
+{
+ pFuncData = rColl.GetFuncData( rName );
+ DBG_ASSERT( pFuncData, "Function Data missing" );
+ if ( pFuncData )
+ {
+ long nDescCount = pFuncData->GetArgumentCount();
+ const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
+ long nVarCount = 0;
+
+ // is aVarArg sequence needed?
+ if ( nParamCount >= nDescCount && nDescCount > 0 &&
+ pArgs[nDescCount-1].eType == SC_ADDINARG_VARARGS )
+ {
+ long nVarCount = nParamCount - ( nDescCount - 1 ); // size of last argument
+ aVarArg.realloc( nVarCount );
+ bValidCount = TRUE;
+ }
+ else if ( nParamCount <= nDescCount )
+ {
+ // all args behind nParamCount must be optional
+ bValidCount = TRUE;
+ for (long i=nParamCount; i<nDescCount; i++)
+ if ( !pArgs[i].bOptional )
+ bValidCount = FALSE;
+ }
+ // else invalid (too many arguments)
+
+ if ( bValidCount )
+ aArgs.realloc( nDescCount ); // sequence must always match function signature
+ }
+}
+
+ScUnoAddInCall::~ScUnoAddInCall()
+{
+ // pFuncData is deleted with ScUnoAddInCollection
+
+ delete pMatrix;
+}
+
+BOOL ScUnoAddInCall::ValidParamCount()
+{
+ return bValidCount;
+}
+
+ScAddInArgumentType ScUnoAddInCall::GetArgType( long nPos )
+{
+ if ( pFuncData )
+ {
+ long nCount = pFuncData->GetArgumentCount();
+ const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
+
+ // if last arg is sequence, use "any" type
+ if ( nCount > 0 && nPos >= nCount-1 && pArgs[nCount-1].eType == SC_ADDINARG_VARARGS )
+ return SC_ADDINARG_VALUE_OR_ARRAY;
+
+ if ( nPos < nCount )
+ return pArgs[nPos].eType;
+ }
+ return SC_ADDINARG_VALUE_OR_ARRAY; //! error code !!!!
+}
+
+BOOL ScUnoAddInCall::NeedsCaller() const
+{
+ return pFuncData && pFuncData->GetCallerPos() != SC_CALLERPOS_NONE;
+}
+
+void ScUnoAddInCall::SetCaller( const uno::Reference<uno::XInterface>& rInterface )
+{
+ xCaller = rInterface;
+}
+
+void ScUnoAddInCall::SetCallerFromObjectShell( SfxObjectShell* pObjSh )
+{
+ if (pObjSh)
+ {
+ uno::Reference<uno::XInterface> xInt( pObjSh->GetBaseModel(), uno::UNO_QUERY );
+ SetCaller( xInt );
+ }
+}
+
+void ScUnoAddInCall::SetParam( long nPos, const uno::Any& rValue )
+{
+ if ( pFuncData )
+ {
+ long nCount = pFuncData->GetArgumentCount();
+ const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
+ if ( nCount > 0 && nPos >= nCount-1 && pArgs[nCount-1].eType == SC_ADDINARG_VARARGS )
+ {
+ long nVarPos = nPos-(nCount-1);
+ if ( nVarPos < aVarArg.getLength() )
+ aVarArg.getArray()[nVarPos] = rValue;
+ else
+ DBG_ERROR("wrong argument number");
+ }
+ else if ( nPos < aArgs.getLength() )
+ aArgs.getArray()[nPos] = rValue;
+ else
+ DBG_ERROR("wrong argument number");
+ }
+}
+
+void ScUnoAddInCall::ExecuteCall()
+{
+ if ( !pFuncData )
+ return;
+
+ long nCount = pFuncData->GetArgumentCount();
+ const ScAddInArgDesc* pArgs = pFuncData->GetArguments();
+ if ( nCount > 0 && pArgs[nCount-1].eType == SC_ADDINARG_VARARGS )
+ {
+ // insert aVarArg as last argument
+ //! after inserting caller (to prevent copying twice)?
+
+ DBG_ASSERT( aArgs.getLength() == nCount, "wrong argument count" );
+ aArgs.getArray()[nCount-1] <<= aVarArg;
+ }
+
+ if ( pFuncData->GetCallerPos() != SC_CALLERPOS_NONE )
+ {
+ uno::Any aCallerAny;
+ aCallerAny <<= xCaller;
+
+ long nUserLen = aArgs.getLength();
+ long nCallPos = pFuncData->GetCallerPos();
+ if (nCallPos>nUserLen) // should not happen
+ {
+ DBG_ERROR("wrong CallPos");
+ nCallPos = nUserLen;
+ }
+
+ long nDestLen = nUserLen + 1;
+ uno::Sequence<uno::Any> aRealArgs( nDestLen );
+ uno::Any* pDest = aRealArgs.getArray();
+
+ const uno::Any* pSource = aArgs.getConstArray();
+ long nSrcPos = 0;
+
+ for ( long nDestPos = 0; nDestPos < nDestLen; nDestPos++ )
+ {
+ if ( nDestPos == nCallPos )
+ pDest[nDestPos] = aCallerAny;
+ else
+ pDest[nDestPos] = pSource[nSrcPos++];
+ }
+
+ ExecuteCallWithArgs( aRealArgs );
+ }
+ else
+ ExecuteCallWithArgs( aArgs );
+}
+
+void ScUnoAddInCall::ExecuteCallWithArgs(uno::Sequence<uno::Any>& rCallArgs)
+{
+ // rCallArgs may not match argument descriptions (because of caller)
+
+ uno::Reference<reflection::XIdlMethod> xFunction;
+ uno::Any aObject;
+ if ( pFuncData )
+ {
+ xFunction = pFuncData->GetFunction();
+ aObject = pFuncData->GetObject();
+ }
+
+ if ( xFunction.is() )
+ {
+ uno::Any aAny;
+ nErrCode = 0;
+
+ try
+ {
+ aAny = xFunction->invoke( aObject, rCallArgs );
+ }
+ catch(lang::IllegalArgumentException e)
+ {
+ nErrCode = errIllegalArgument;
+ }
+#if 0
+ catch(FloatingPointException e)
+ {
+ nErrCode = errIllegalFPOperation;
+ }
+#endif
+ catch(...)
+ {
+ nErrCode = errNoValue;
+ }
+
+ if (!nErrCode)
+ SetResult( aAny ); // convert result to Calc types
+ }
+}
+
+void ScUnoAddInCall::SetResult( const uno::Any& rNewRes )
+{
+ nErrCode = 0;
+ xVarRes = NULL;
+
+ // Reflection* pRefl = rNewRes.getReflection();
+
+ uno::TypeClass eClass = rNewRes.getValueTypeClass();
+ uno::Type aType = rNewRes.getValueType();
+ switch (eClass)
+ {
+ case uno::TypeClass_VOID:
+ nErrCode = NOVALUE; // #nv
+ break;
+
+ case uno::TypeClass_ENUM:
+ case uno::TypeClass_BOOLEAN:
+ case uno::TypeClass_CHAR:
+ case uno::TypeClass_BYTE:
+ case uno::TypeClass_SHORT:
+ case uno::TypeClass_UNSIGNED_SHORT:
+ case uno::TypeClass_LONG:
+ case uno::TypeClass_UNSIGNED_LONG:
+ case uno::TypeClass_FLOAT:
+ case uno::TypeClass_DOUBLE:
+ lcl_ConvertToDouble( rNewRes, fValue );
+ bHasString = FALSE;
+ break;
+
+ case uno::TypeClass_STRING:
+ {
+ rtl::OUString aUStr;
+ rNewRes >>= aUStr;
+ aString = String( aUStr );
+ bHasString = TRUE;
+ }
+ break;
+
+ case uno::TypeClass_INTERFACE:
+ {
+ //! directly extract XVolatileResult from any?
+ uno::Reference<uno::XInterface> xInterface;
+ rNewRes >>= xInterface;
+ if ( xInterface.is() )
+ xVarRes = uno::Reference<sheet::XVolatileResult>( xInterface, uno::UNO_QUERY );
+
+ if (!xVarRes.is())
+ nErrCode = errNoValue; // unknown interface
+ }
+ break;
+
+ default:
+ if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<INT32> > *)0 ) ) )
+ {
+ const uno::Sequence< uno::Sequence<INT32> >* pRowSeq = NULL;
+
+ //! use pointer from any!
+ uno::Sequence< uno::Sequence<INT32> > aSequence;
+ if ( rNewRes >>= aSequence )
+ pRowSeq = &aSequence;
+
+ if ( pRowSeq )
+ {
+ long nRowCount = pRowSeq->getLength();
+ const uno::Sequence<INT32>* pRowArr = pRowSeq->getConstArray();
+ long nMaxColCount = 0;
+ long nCol, nRow;
+ for (nRow=0; nRow<nRowCount; nRow++)
+ {
+ long nTmp = pRowArr[nRow].getLength();
+ if ( nTmp > nMaxColCount )
+ nMaxColCount = nTmp;
+ }
+ if ( nMaxColCount && nRowCount )
+ {
+ pMatrix = new ScMatrix( nMaxColCount, nRowCount );
+ for (nRow=0; nRow<nRowCount; nRow++)
+ {
+ long nColCount = pRowArr[nRow].getLength();
+ const INT32* pColArr = pRowArr[nRow].getConstArray();
+ for (nCol=0; nCol<nColCount; nCol++)
+ pMatrix->PutDouble( pColArr[nCol], nCol, nRow );
+ for (nCol=nColCount; nCol<nMaxColCount; nCol++)
+ pMatrix->PutDouble( 0.0, nCol, nRow );
+ }
+ }
+ }
+ }
+ else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<double> > *)0 ) ) )
+ {
+ const uno::Sequence< uno::Sequence<double> >* pRowSeq = NULL;
+
+ //! use pointer from any!
+ uno::Sequence< uno::Sequence<double> > aSequence;
+ if ( rNewRes >>= aSequence )
+ pRowSeq = &aSequence;
+
+ if ( pRowSeq )
+ {
+ long nRowCount = pRowSeq->getLength();
+ const uno::Sequence<double>* pRowArr = pRowSeq->getConstArray();
+ long nMaxColCount = 0;
+ long nCol, nRow;
+ for (nRow=0; nRow<nRowCount; nRow++)
+ {
+ long nTmp = pRowArr[nRow].getLength();
+ if ( nTmp > nMaxColCount )
+ nMaxColCount = nTmp;
+ }
+ if ( nMaxColCount && nRowCount )
+ {
+ pMatrix = new ScMatrix( nMaxColCount, nRowCount );
+ for (nRow=0; nRow<nRowCount; nRow++)
+ {
+ long nColCount = pRowArr[nRow].getLength();
+ const double* pColArr = pRowArr[nRow].getConstArray();
+ for (nCol=0; nCol<nColCount; nCol++)
+ pMatrix->PutDouble( pColArr[nCol], nCol, nRow );
+ for (nCol=nColCount; nCol<nMaxColCount; nCol++)
+ pMatrix->PutDouble( 0.0, nCol, nRow );
+ }
+ }
+ }
+ }
+ else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<rtl::OUString> > *)0 ) ) )
+ {
+ const uno::Sequence< uno::Sequence<rtl::OUString> >* pRowSeq = NULL;
+
+ //! use pointer from any!
+ uno::Sequence< uno::Sequence<rtl::OUString> > aSequence;
+ if ( rNewRes >>= aSequence )
+ pRowSeq = &aSequence;
+
+ if ( pRowSeq )
+ {
+ long nRowCount = pRowSeq->getLength();
+ const uno::Sequence<rtl::OUString>* pRowArr = pRowSeq->getConstArray();
+ long nMaxColCount = 0;
+ long nCol, nRow;
+ for (nRow=0; nRow<nRowCount; nRow++)
+ {
+ long nTmp = pRowArr[nRow].getLength();
+ if ( nTmp > nMaxColCount )
+ nMaxColCount = nTmp;
+ }
+ if ( nMaxColCount && nRowCount )
+ {
+ pMatrix = new ScMatrix( nMaxColCount, nRowCount );
+ for (nRow=0; nRow<nRowCount; nRow++)
+ {
+ long nColCount = pRowArr[nRow].getLength();
+ const rtl::OUString* pColArr = pRowArr[nRow].getConstArray();
+ for (nCol=0; nCol<nColCount; nCol++)
+ pMatrix->PutString( String( pColArr[nCol] ),
+ nCol, nRow );
+ for (nCol=nColCount; nCol<nMaxColCount; nCol++)
+ pMatrix->PutString( EMPTY_STRING, nCol, nRow );
+ }
+ }
+ }
+ }
+ else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<uno::Any> > *)0 ) ) )
+ {
+ const uno::Sequence< uno::Sequence<uno::Any> >* pRowSeq = NULL;
+
+ //! use pointer from any!
+ uno::Sequence< uno::Sequence<uno::Any> > aSequence;
+ if ( rNewRes >>= aSequence )
+ pRowSeq = &aSequence;
+
+ if ( pRowSeq )
+ {
+ long nRowCount = pRowSeq->getLength();
+ const uno::Sequence<uno::Any>* pRowArr = pRowSeq->getConstArray();
+ long nMaxColCount = 0;
+ long nCol, nRow;
+ for (nRow=0; nRow<nRowCount; nRow++)
+ {
+ long nTmp = pRowArr[nRow].getLength();
+ if ( nTmp > nMaxColCount )
+ nMaxColCount = nTmp;
+ }
+ if ( nMaxColCount && nRowCount )
+ {
+ rtl::OUString aUStr;
+ pMatrix = new ScMatrix( nMaxColCount, nRowCount );
+ for (nRow=0; nRow<nRowCount; nRow++)
+ {
+ long nColCount = pRowArr[nRow].getLength();
+ const uno::Any* pColArr = pRowArr[nRow].getConstArray();
+ for (nCol=0; nCol<nColCount; nCol++)
+ {
+ //Reflection* pRefl = pColArr[nCol].getReflection();
+ //if ( pRefl->equals( *OUString_getReflection() ) )
+ if ( pColArr[nCol] >>= aUStr )
+ pMatrix->PutString( String( aUStr ),
+ nCol, nRow );
+ else
+ {
+ // try to convert to double, empty if not possible
+
+ double fCellVal;
+ if ( lcl_ConvertToDouble( pColArr[nCol], fCellVal ) )
+ pMatrix->PutDouble( fCellVal, nCol, nRow );
+ else
+ pMatrix->PutEmpty( nCol, nRow );
+ }
+ }
+ for (nCol=nColCount; nCol<nMaxColCount; nCol++)
+ pMatrix->PutString( EMPTY_STRING, nCol, nRow );
+ }
+ }
+ }
+ }
+
+ if (!pMatrix) // no array found
+ nErrCode = errNoValue; //! code for error in return type???
+ }
+}
+
+
+
+//------------------------------------------------------------------------
+
+
+
diff --git a/sc/source/core/tool/addinlis.cxx b/sc/source/core/tool/addinlis.cxx
new file mode 100644
index 000000000000..874257a343f6
--- /dev/null
+++ b/sc/source/core/tool/addinlis.cxx
@@ -0,0 +1,225 @@
+/*************************************************************************
+ *
+ * $RCSfile: addinlis.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include <tools/debug.hxx>
+#include <sfx2/objsh.hxx>
+
+
+#include "addinlis.hxx"
+#include "miscuno.hxx" // SC_IMPL_SERVICE_INFO
+#include "document.hxx"
+#include "brdcst.hxx"
+#include "unoguard.hxx"
+#include "sc.hrc"
+
+using namespace com::sun::star;
+
+//------------------------------------------------------------------------
+
+//SMART_UNO_IMPLEMENTATION( ScAddInListener, UsrObject );
+
+SC_SIMPLE_SERVICE_INFO( ScAddInListener, "ScAddInListener", "stardiv.one.sheet.AddInListener" )
+
+//------------------------------------------------------------------------
+
+List ScAddInListener::aAllListeners;
+
+//------------------------------------------------------------------------
+
+// static
+ScAddInListener* ScAddInListener::CreateListener(
+ uno::Reference<sheet::XVolatileResult> xVR, ScDocument* pDoc )
+{
+ ScAddInListener* pNew = new ScAddInListener( xVR, pDoc );
+
+ pNew->acquire(); // for aAllListeners
+ aAllListeners.Insert( pNew, LIST_APPEND );
+
+ if ( xVR.is() )
+ xVR->addResultListener( pNew ); // after at least 1 ref exists!
+
+ return pNew;
+}
+
+ScAddInListener::ScAddInListener( uno::Reference<sheet::XVolatileResult> xVR, ScDocument* pDoc ) :
+ xVolRes( xVR )
+{
+ pDocs = new ScAddInDocs( 1, 1 );
+ pDocs->Insert( pDoc );
+}
+
+ScAddInListener::~ScAddInListener()
+{
+ delete pDocs;
+}
+
+// static
+ScAddInListener* ScAddInListener::Get( uno::Reference<sheet::XVolatileResult> xVR )
+{
+ sheet::XVolatileResult* pComp = xVR.get();
+
+ ULONG nCount = aAllListeners.Count();
+ for (ULONG nPos=0; nPos<nCount; nPos++)
+ {
+ ScAddInListener* pLst = (ScAddInListener*)aAllListeners.GetObject(nPos);
+ if ( pComp == (sheet::XVolatileResult*)pLst->xVolRes.get() )
+ return pLst;
+ }
+ return NULL; // not found
+}
+
+//! move to some container object?
+// static
+void ScAddInListener::RemoveDocument( ScDocument* pDocumentP )
+{
+ ULONG nPos = aAllListeners.Count();
+ while (nPos)
+ {
+ // loop backwards because elements are removed
+ --nPos;
+ ScAddInListener* pLst = (ScAddInListener*)aAllListeners.GetObject(nPos);
+ ScAddInDocs* p = pLst->pDocs;
+ USHORT nFoundPos;
+ if ( p->Seek_Entry( pDocumentP, &nFoundPos ) )
+ {
+ p->Remove( nFoundPos );
+ if ( p->Count() == 0 )
+ {
+ // this AddIn is no longer used
+ // dont delete, just remove the ref for the list
+
+ aAllListeners.Remove( nPos );
+
+ if ( pLst->xVolRes.is() )
+ pLst->xVolRes->removeResultListener( pLst );
+
+ pLst->release(); // Ref for aAllListeners - pLst may be deleted here
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+
+// XResultListener
+
+void SAL_CALL ScAddInListener::modified( const ::com::sun::star::sheet::ResultEvent& aEvent )
+ throw(::com::sun::star::uno::RuntimeException)
+{
+ ScUnoGuard aGuard; //! or generate a UserEvent
+
+ aResult = aEvent.Value; // store result
+
+ if ( !HasListeners() )
+ {
+ //! remove from list and removeListener, as in RemoveDocument ???
+
+#if 0
+ //! this will crash if called before first StartListening !!!
+ aAllListeners.Remove( this );
+ if ( xVolRes.is() )
+ xVolRes->removeResultListener( this );
+ release(); // Ref for aAllListeners - this may be deleted here
+ return;
+#endif
+ }
+
+ // notify document of changes
+
+ Broadcast( ScHint( SC_HINT_DATACHANGED, ScAddress( 0 ), NULL ) );
+
+ const ScDocument** ppDoc = (const ScDocument**) pDocs->GetData();
+ USHORT nCount = pDocs->Count();
+ for ( USHORT j=0; j<nCount; j++, ppDoc++ )
+ {
+ ScDocument* pDoc = (ScDocument*)*ppDoc;
+ pDoc->TrackFormulas();
+ pDoc->GetDocumentShell()->Broadcast( SfxSimpleHint( FID_DATACHANGED ) );
+ pDoc->ResetChanged( ScRange(0,0,0,MAXCOL,MAXROW,MAXTAB) );
+ }
+}
+
+// XEventListener
+
+void SAL_CALL ScAddInListener::disposing( const ::com::sun::star::lang::EventObject& Source )
+ throw(::com::sun::star::uno::RuntimeException)
+{
+ // hold a ref so this is not deleted at removeResultListener
+ uno::Reference<sheet::XResultListener> xRef( this );
+
+ if ( xVolRes.is() )
+ {
+ xVolRes->removeResultListener( this );
+ xVolRes = NULL;
+ }
+}
+
+
+//------------------------------------------------------------------------
+
+
+
diff --git a/sc/source/core/tool/adiasync.cxx b/sc/source/core/tool/adiasync.cxx
new file mode 100644
index 000000000000..89d242693d7f
--- /dev/null
+++ b/sc/source/core/tool/adiasync.cxx
@@ -0,0 +1,229 @@
+/*************************************************************************
+ *
+ * $RCSfile: adiasync.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+//------------------------------------------------------------------------
+
+#include <sfx2/objsh.hxx>
+
+#include "adiasync.hxx"
+#include "brdcst.hxx"
+#include "global.hxx"
+#include "document.hxx"
+#include "sc.hrc" // FID_DATACHANGED
+
+#ifndef _OSL_THREAD_H_
+#include <osl/thread.h>
+#endif
+
+
+//------------------------------------------------------------------------
+
+#pragma code_seg("SCSTATICS")
+
+ScAddInAsyncs theAddInAsyncTbl;
+static ScAddInAsync aSeekObj;
+
+#pragma code_seg()
+
+
+SV_IMPL_OP_PTRARR_SORT( ScAddInAsyncs, ScAddInAsyncPtr );
+
+SV_IMPL_PTRARR_SORT( ScAddInDocs, ScAddInDocPtr );
+
+extern "C" {
+void CALLTYPE ScAddInAsyncCallBack( double& nHandle, void* pData )
+{
+ ScAddInAsync::CallBack( ULONG( nHandle ), pData );
+}
+}
+
+
+
+ScAddInAsync::ScAddInAsync() :
+ SfxBroadcaster(),
+ nHandle( 0 )
+{ // nur fuer aSeekObj !
+}
+
+
+
+ScAddInAsync::ScAddInAsync( ULONG nHandleP, USHORT nIndex, ScDocument* pDoc ) :
+ SfxBroadcaster(),
+ pStr( NULL ),
+ nHandle( nHandleP ),
+ bValid( FALSE )
+{
+ pDocs = new ScAddInDocs( 1, 1 );
+ pDocs->Insert( pDoc );
+ pFuncData = (FuncData*)ScGlobal::GetFuncCollection()->At(nIndex);
+ eType = pFuncData->GetAsyncType();
+ theAddInAsyncTbl.Insert( this );
+}
+
+
+
+ScAddInAsync::~ScAddInAsync()
+{
+ // aSeekObj hat das alles nicht, Handle 0 gibt es sonst nicht
+ if ( nHandle )
+ {
+ // im dTor wg. theAddInAsyncTbl.DeleteAndDestroy in ScGlobal::Clear
+ pFuncData->Unadvice( (double)nHandle );
+ if ( eType == PTR_STRING && pStr ) // mit Typvergleich wg. Union!
+ delete pStr;
+ delete pDocs;
+ }
+}
+
+
+
+ScAddInAsync* ScAddInAsync::Get( ULONG nHandleP )
+{
+ USHORT nPos;
+ ScAddInAsync* pRet = 0;
+ aSeekObj.nHandle = nHandleP;
+ if ( theAddInAsyncTbl.Seek_Entry( &aSeekObj, &nPos ) )
+ pRet = theAddInAsyncTbl[ nPos ];
+ aSeekObj.nHandle = 0;
+ return pRet;
+}
+
+
+
+void ScAddInAsync::CallBack( ULONG nHandleP, void* pData )
+{
+ ScAddInAsync* p;
+ if ( !(p = Get( nHandleP )) )
+ return;
+ // keiner mehr dran? Unadvice und weg damit
+ if ( !p->HasListeners() )
+ {
+ // nicht im dTor wg. theAddInAsyncTbl.DeleteAndDestroy in ScGlobal::Clear
+ theAddInAsyncTbl.Remove( p );
+ delete p;
+ return ;
+ }
+ switch ( p->eType )
+ {
+ case PTR_DOUBLE :
+ p->nVal = *(double*)pData;
+ break;
+ case PTR_STRING :
+ if ( p->pStr )
+ *p->pStr = String( (sal_Char*)pData, osl_getThreadTextEncoding() );
+ else
+ p->pStr = new String( (sal_Char*)pData, osl_getThreadTextEncoding() );
+ break;
+ default :
+ DBG_ERROR( "unbekannter AsyncType" );
+ return;
+ }
+ p->bValid = TRUE;
+ p->Broadcast( ScHint( SC_HINT_DATACHANGED, ScAddress( 0 ), NULL ) );
+
+ const ScDocument** ppDoc = (const ScDocument**) p->pDocs->GetData();
+ USHORT nCount = p->pDocs->Count();
+ for ( USHORT j=0; j<nCount; j++, ppDoc++ )
+ {
+ ScDocument* pDoc = (ScDocument*)*ppDoc;
+ pDoc->TrackFormulas();
+ pDoc->GetDocumentShell()->Broadcast( SfxSimpleHint( FID_DATACHANGED ) );
+ pDoc->ResetChanged( ScRange(0,0,0,MAXCOL,MAXROW,MAXTAB) );
+ }
+}
+
+
+
+void ScAddInAsync::RemoveDocument( ScDocument* pDocumentP )
+{
+ USHORT nPos = theAddInAsyncTbl.Count();
+ if ( nPos )
+ {
+ const ScAddInAsync** ppAsync =
+ (const ScAddInAsync**) theAddInAsyncTbl.GetData() + nPos - 1;
+ for ( ; nPos-- >0; ppAsync-- )
+ { // rueckwaerts wg. Pointer-Aufrueckerei im Array
+ ScAddInDocs* p = ((ScAddInAsync*)*ppAsync)->pDocs;
+ USHORT nFoundPos;
+ if ( p->Seek_Entry( pDocumentP, &nFoundPos ) )
+ {
+ p->Remove( nFoundPos );
+ if ( p->Count() == 0 )
+ { // dieses AddIn wird nicht mehr benutzt
+ ScAddInAsync* pAsync = (ScAddInAsync*)*ppAsync;
+ theAddInAsyncTbl.Remove( nPos );
+ delete pAsync;
+ ppAsync = (const ScAddInAsync**) theAddInAsyncTbl.GetData()
+ + nPos;
+ }
+ }
+ }
+ }
+}
+
+
+
diff --git a/sc/source/core/tool/appoptio.cxx b/sc/source/core/tool/appoptio.cxx
new file mode 100644
index 000000000000..1184e4701735
--- /dev/null
+++ b/sc/source/core/tool/appoptio.cxx
@@ -0,0 +1,343 @@
+/*************************************************************************
+ *
+ * $RCSfile: appoptio.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+//------------------------------------------------------------------
+
+#include <vcl/svapp.hxx>
+
+#include "cfgids.hxx"
+#include "appoptio.hxx"
+#include "rechead.hxx"
+#include "scresid.hxx"
+#include "global.hxx"
+#include "userlist.hxx"
+#include "sc.hrc"
+#include "compiler.hrc"
+
+// STATIC DATA -----------------------------------------------------------
+
+#define SC_VERSION ((USHORT)304)
+
+//========================================================================
+// ScAppOptions - Applikations-Optionen
+//========================================================================
+
+ScAppOptions::ScAppOptions() : pLRUList( NULL )
+{
+ SetDefaults();
+}
+
+//------------------------------------------------------------------------
+
+ScAppOptions::ScAppOptions( const ScAppOptions& rCpy ) : pLRUList( NULL )
+{
+ *this = rCpy;
+}
+
+//------------------------------------------------------------------------
+
+ScAppOptions::~ScAppOptions()
+{
+ delete [] pLRUList;
+}
+
+//------------------------------------------------------------------------
+
+void ScAppOptions::SetDefaults()
+{
+ MeasurementSystem eSys = Application::GetAppInternational().GetMeasurementSystem();
+ if ( eSys == MEASURE_METRIC )
+ eMetric = FUNIT_CM; // fuer die zivilisierte Welt
+ else
+ eMetric = FUNIT_INCH; // fuer die komischen Amis
+
+ nZoom = 100;
+ eZoomType = SVX_ZOOM_PERCENT;
+ nStatusFunc = SUBTOTAL_FUNC_SUM;
+ bAutoComplete = TRUE;
+ bDetectiveAuto = TRUE;
+
+ delete [] pLRUList;
+ pLRUList = new USHORT[5]; // sinnvoll vorbelegen
+ pLRUList[0] = SC_OPCODE_SUM;
+ pLRUList[1] = SC_OPCODE_AVERAGE;
+ pLRUList[2] = SC_OPCODE_MIN;
+ pLRUList[3] = SC_OPCODE_MAX;
+ pLRUList[4] = SC_OPCODE_IF;
+ nLRUFuncCount = 5;
+
+ nTrackContentColor = COL_TRANSPARENT;
+ nTrackInsertColor = COL_TRANSPARENT;
+ nTrackDeleteColor = COL_TRANSPARENT;
+ nTrackMoveColor = COL_TRANSPARENT;
+ eLinkMode = LM_ON_DEMAND;
+
+}
+
+//------------------------------------------------------------------------
+
+const ScAppOptions& ScAppOptions::operator=( const ScAppOptions& rCpy )
+{
+ eMetric = rCpy.eMetric;
+ eZoomType = rCpy.eZoomType;
+ nZoom = rCpy.nZoom;
+ SetLRUFuncList( rCpy.pLRUList, rCpy.nLRUFuncCount );
+ nStatusFunc = rCpy.nStatusFunc;
+ bAutoComplete = rCpy.bAutoComplete;
+ bDetectiveAuto = rCpy.bDetectiveAuto;
+ nTrackContentColor = rCpy.nTrackContentColor;
+ nTrackInsertColor = rCpy.nTrackInsertColor;
+ nTrackDeleteColor = rCpy.nTrackDeleteColor;
+ nTrackMoveColor = rCpy.nTrackMoveColor;
+ eLinkMode = rCpy.eLinkMode;
+ return *this;
+}
+
+//------------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rStream, ScAppOptions& rOpt )
+{
+ rOpt.SetDefaults();
+
+ ScReadHeader aHdr( rStream );
+
+ BYTE n;
+ rStream >> n; rOpt.eMetric = (FieldUnit)n;
+
+ if ( aHdr.BytesLeft() )
+ {
+ rStream >> n; rOpt.nLRUFuncCount = (USHORT)n;
+
+ delete [] rOpt.pLRUList;
+ rOpt.pLRUList = new USHORT[rOpt.nLRUFuncCount];
+
+ for ( USHORT i=0; i<rOpt.nLRUFuncCount; i++ )
+ rStream >> rOpt.pLRUList[i];
+ }
+
+ // ab 31.10.95: globale benutzerdefinierte Listen einlesen :-/
+ // (kleiner Hack :-/)
+ if ( aHdr.BytesLeft() )
+ {
+ ScUserList* pUserList = ScGlobal::GetUserList();
+ pUserList->Load( rStream );
+ }
+
+ // ab 11.12.95 (304)
+ // Zoom-Faktor
+ if ( aHdr.BytesLeft() )
+ {
+ USHORT e;
+ rStream >> e; rOpt.eZoomType = (SvxZoomType)e;
+ rStream >> rOpt.nZoom;
+ }
+
+ // ab 23.5.96: Funktion fuer Statusbar-Controller, Flag fuer Auto-Eingabe
+ if ( aHdr.BytesLeft() )
+ {
+ rStream >> rOpt.nStatusFunc;
+ rStream >> rOpt.bAutoComplete;
+ }
+
+ // ab 15.3.98: Farben fuer Change-Tracking
+ if ( aHdr.BytesLeft() )
+ {
+ rStream >> rOpt.nTrackContentColor;
+ rStream >> rOpt.nTrackInsertColor;
+ rStream >> rOpt.nTrackDeleteColor;
+ rStream >> rOpt.nTrackMoveColor;
+ }
+
+ // ab 22.6.98: Automatisches Detektiv-Update
+ if ( aHdr.BytesLeft() )
+ rStream >> rOpt.bDetectiveAuto;
+
+ if ( aHdr.BytesLeft() )
+ {
+ BYTE nLinkMode;
+ rStream >> nLinkMode;
+ rOpt.eLinkMode=(ScLkUpdMode) nLinkMode;
+ }
+
+ return rStream;
+}
+
+//------------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rStream, const ScAppOptions& rOpt )
+{
+ ScWriteHeader aHdr( rStream, 25 );
+
+ rStream << (BYTE)rOpt.eMetric;
+ rStream << (BYTE)rOpt.nLRUFuncCount;
+
+ if ( rOpt.nLRUFuncCount > 0 )
+ {
+ for ( USHORT i=0; i<rOpt.nLRUFuncCount; i++ )
+ rStream << rOpt.pLRUList[i];
+ }
+
+ // ab 31.10.95: globale benutzerdefinierte Listen speichern
+ // (kleiner Hack :-/)
+ ScUserList* pUserList = ScGlobal::GetUserList();
+ pUserList->Store( rStream );
+
+ // ab 11.12.95 (304)
+ // Zoom-Faktor
+ rStream << (USHORT)rOpt.eZoomType;
+ rStream << rOpt.nZoom;
+
+ // ab 23.5.96: Funktion fuer Statusbar-Controller, Flag fuer Auto-Eingabe
+ rStream << rOpt.nStatusFunc;
+ rStream << rOpt.bAutoComplete;
+
+ // ab 15.3.98: Farben fuer Change-Tracking
+ rStream << rOpt.nTrackContentColor;
+ rStream << rOpt.nTrackInsertColor;
+ rStream << rOpt.nTrackDeleteColor;
+ rStream << rOpt.nTrackMoveColor;
+
+ // ab 22.6.98: Automatisches Detektiv-Update
+ rStream << rOpt.bDetectiveAuto;
+ rStream << (BYTE) rOpt.eLinkMode;
+
+ return rStream;
+}
+
+//------------------------------------------------------------------------
+
+void ScAppOptions::SetLRUFuncList( const USHORT* pList, const USHORT nCount )
+{
+ delete [] pLRUList;
+
+ nLRUFuncCount = nCount;
+
+ if ( nLRUFuncCount > 0 )
+ {
+ pLRUList = new USHORT[nLRUFuncCount];
+
+ for ( USHORT i=0; i<nLRUFuncCount; i++ )
+ pLRUList[i] = pList[i];
+ }
+ else
+ pLRUList = NULL;
+}
+
+//==================================================================
+// CfgItem fuer App-Optionen
+//==================================================================
+
+ScAppCfg::ScAppCfg() : SfxConfigItem( SCCFG_APP )
+{
+}
+
+//------------------------------------------------------------------------
+
+int __EXPORT ScAppCfg::Load( SvStream& rStream )
+{
+ USHORT nVersion;
+
+ rStream >> nVersion;
+ rStream >> (ScAppOptions&)*this;
+
+ SetDefault( FALSE );
+
+ return ( nVersion == SC_VERSION )
+ ? SfxConfigItem::ERR_OK
+ : SfxConfigItem::WARNING_VERSION;
+}
+
+//------------------------------------------------------------------------
+
+BOOL __EXPORT ScAppCfg::Store( SvStream& rStream)
+{
+ rStream << SC_VERSION;
+ rStream << *this;
+
+ SetDefault( FALSE );
+
+ return SfxConfigItem::ERR_OK;
+}
+
+//------------------------------------------------------------------------
+
+void __EXPORT ScAppCfg::UseDefault()
+{
+ SetDefaults();
+ SetDefault( TRUE );
+}
+
+
+//------------------------------------------------------------------------
+
+String __EXPORT ScAppCfg::GetName() const
+{
+ return String( ScResId( SCSTR_CFG_APP ) );
+}
+
+
+
diff --git a/sc/source/core/tool/autoform.cxx b/sc/source/core/tool/autoform.cxx
new file mode 100644
index 000000000000..2a9224e06f5a
--- /dev/null
+++ b/sc/source/core/tool/autoform.cxx
@@ -0,0 +1,1215 @@
+/*************************************************************************
+ *
+ * $RCSfile: autoform.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+
+/*------------------------------------------------------------------------
+
+ $Author: hr $ $Date: 2000-09-19 00:16:17 $ $Revision: 1.1.1.1 $
+ $Logfile: T:/sc/source/core/tool/autoform.cxv $ $Workfile: autoform.cxx $
+ (c) Copyright 1989 - 1994, Star Division GmbH, Hamburg
+
+------------------------------------------------------------------------*/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#define READ_OLDVERS
+
+#include "scitems.hxx"
+#include <svx/adjitem.hxx>
+#include <svx/algitem.hxx>
+#include <svx/boxitem.hxx>
+#include <svx/brshitem.hxx>
+#include <svx/cntritem.hxx>
+#include <svx/colritem.hxx>
+#include <svx/crsditem.hxx>
+#include <svx/fhgtitem.hxx>
+#include <svx/fontitem.hxx>
+#include <svx/postitem.hxx>
+#include <svx/shdditem.hxx>
+#include <svx/udlnitem.hxx>
+#include <svx/wghtitem.hxx>
+#ifndef _SVX_ROTMODIT_HXX //autogen
+#include <svx/rotmodit.hxx>
+#endif
+#include <sfx2/app.hxx>
+#ifndef _SFXINTITEM_HXX //autogen
+#include <svtools/intitem.hxx>
+#endif
+#include <svtools/iniman.hxx>
+#ifndef _SHL_HXX
+#include <tools/shl.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <vcl/svapp.hxx>
+#endif
+#include <vcl/system.hxx>
+#ifndef _SVX_DIALMGR_HXX
+#include <svx/dialmgr.hxx>
+#endif
+#ifndef _SVX_DIALOGS_HRC
+#include <svx/dialogs.hrc>
+#endif
+#ifndef _URLOBJ_HXX
+#include <tools/urlobj.hxx>
+#endif
+#ifndef _SFXDOCFILE_HXX
+#include <sfx2/docfile.hxx>
+#endif
+
+#include "autoform.hxx"
+#include "zforauto.hxx"
+#include "globstr.hrc"
+
+//------------------------------------------------------------------------
+
+sal_Char *linker_dummy = "";
+
+// Standard-Name ist jetzt STR_STYLENAME_STANDARD (wie Vorlagen)
+//static const sal_Char __FAR_DATA cStandardName[] = "Standard";
+
+static const sal_Char __FAR_DATA sAutoTblFmtName[] = "autotbl.fmt";
+
+// bis SO5PF
+const USHORT AUTOFORMAT_ID_X = 9501;
+const USHORT AUTOFORMAT_ID_358 = 9601;
+const USHORT AUTOFORMAT_DATA_ID_X = 9502;
+
+// ab SO5
+//! in nachfolgenden Versionen muss der Betrag dieser IDs groesser sein
+const USHORT AUTOFORMAT_ID_504 = 9801;
+const USHORT AUTOFORMAT_DATA_ID_504 = 9802;
+
+const USHORT AUTOFORMAT_ID_552 = 9901;
+const USHORT AUTOFORMAT_DATA_ID_552 = 9902;
+
+// aktuelle Version
+const USHORT AUTOFORMAT_ID = AUTOFORMAT_ID_552;
+const USHORT AUTOFORMAT_DATA_ID = AUTOFORMAT_DATA_ID_552;
+
+
+#ifdef READ_OLDVERS
+const USHORT AUTOFORMAT_OLD_ID_OLD = 4201;
+const USHORT AUTOFORMAT_OLD_DATA_ID = 4202;
+const USHORT AUTOFORMAT_OLD_ID_NEW = 4203;
+#endif
+
+
+// Struct mit Versionsnummern der Items
+
+struct ScAfVersions
+{
+public:
+ USHORT nFontVersion;
+ USHORT nFontHeightVersion;
+ USHORT nWeightVersion;
+ USHORT nPostureVersion;
+ USHORT nUnderlineVersion;
+ USHORT nCrossedOutVersion;
+ USHORT nContourVersion;
+ USHORT nShadowedVersion;
+ USHORT nColorVersion;
+ USHORT nBoxVersion;
+ USHORT nBrushVersion;
+
+ USHORT nAdjustVersion;
+
+ USHORT nHorJustifyVersion;
+ USHORT nVerJustifyVersion;
+ USHORT nOrientationVersion;
+ USHORT nMarginVersion;
+ USHORT nBoolVersion;
+ USHORT nInt32Version;
+ USHORT nRotateModeVersion;
+
+ USHORT nNumFmtVersion;
+
+ ScAfVersions();
+ void Load( SvStream& rStream, USHORT nVer );
+ static void Write(SvStream& rStream);
+};
+
+ScAfVersions::ScAfVersions() :
+ nFontVersion(0),
+ nFontHeightVersion(0),
+ nWeightVersion(0),
+ nPostureVersion(0),
+ nUnderlineVersion(0),
+ nCrossedOutVersion(0),
+ nContourVersion(0),
+ nShadowedVersion(0),
+ nColorVersion(0),
+ nBoxVersion(0),
+ nBrushVersion(0),
+ nAdjustVersion(0),
+ nHorJustifyVersion(0),
+ nVerJustifyVersion(0),
+ nOrientationVersion(0),
+ nMarginVersion(0),
+ nBoolVersion(0),
+ nInt32Version(0),
+ nRotateModeVersion(0),
+ nNumFmtVersion(0)
+{
+}
+
+void ScAfVersions::Load( SvStream& rStream, USHORT nVer )
+{
+ rStream >> nFontVersion;
+ rStream >> nFontHeightVersion;
+ rStream >> nWeightVersion;
+ rStream >> nPostureVersion;
+ rStream >> nUnderlineVersion;
+ rStream >> nCrossedOutVersion;
+ rStream >> nContourVersion;
+ rStream >> nShadowedVersion;
+ rStream >> nColorVersion;
+ rStream >> nBoxVersion;
+ rStream >> nBrushVersion;
+ rStream >> nAdjustVersion;
+ rStream >> nHorJustifyVersion;
+ rStream >> nVerJustifyVersion;
+ rStream >> nOrientationVersion;
+ rStream >> nMarginVersion;
+ rStream >> nBoolVersion;
+ if ( nVer >= AUTOFORMAT_ID_504 )
+ {
+ rStream >> nInt32Version;
+ rStream >> nRotateModeVersion;
+ }
+ rStream >> nNumFmtVersion;
+}
+
+void ScAfVersions::Write(SvStream& rStream)
+{
+ rStream << SvxFontItem().GetVersion(SOFFICE_FILEFORMAT_40);
+ rStream << SvxFontHeightItem().GetVersion(SOFFICE_FILEFORMAT_40);
+ rStream << SvxWeightItem().GetVersion(SOFFICE_FILEFORMAT_40);
+ rStream << SvxPostureItem().GetVersion(SOFFICE_FILEFORMAT_40);
+ rStream << SvxUnderlineItem().GetVersion(SOFFICE_FILEFORMAT_40);
+ rStream << SvxCrossedOutItem().GetVersion(SOFFICE_FILEFORMAT_40);
+ rStream << SvxContourItem().GetVersion(SOFFICE_FILEFORMAT_40);
+ rStream << SvxShadowedItem().GetVersion(SOFFICE_FILEFORMAT_40);
+ rStream << SvxColorItem().GetVersion(SOFFICE_FILEFORMAT_40);
+ rStream << SvxBoxItem().GetVersion(SOFFICE_FILEFORMAT_40);
+ rStream << SvxBrushItem().GetVersion(SOFFICE_FILEFORMAT_40);
+
+ rStream << SvxAdjustItem().GetVersion(SOFFICE_FILEFORMAT_40);
+
+ rStream << SvxHorJustifyItem().GetVersion(SOFFICE_FILEFORMAT_40);
+ rStream << SvxVerJustifyItem().GetVersion(SOFFICE_FILEFORMAT_40);
+ rStream << SvxOrientationItem().GetVersion(SOFFICE_FILEFORMAT_40);
+ rStream << SvxMarginItem().GetVersion(SOFFICE_FILEFORMAT_40);
+ rStream << SfxBoolItem(ATTR_LINEBREAK).GetVersion(SOFFICE_FILEFORMAT_40);
+ rStream << SfxInt32Item(ATTR_ROTATE_VALUE).GetVersion(SOFFICE_FILEFORMAT_40);
+ rStream << SvxRotateModeItem(SVX_ROTATE_MODE_STANDARD,0).GetVersion(SOFFICE_FILEFORMAT_40);
+
+ rStream << (USHORT)0; // Num-Format
+}
+
+// ---------------------------------------------------------------------------
+
+ScAutoFormatData::ScAutoFormatData()
+{
+ nStrResId = USHRT_MAX;
+
+ bIncludeValueFormat =
+ bIncludeFont =
+ bIncludeJustify =
+ bIncludeFrame =
+ bIncludeBackground =
+ bIncludeWidthHeight = TRUE;
+ for (USHORT i = 0; i < 16; i++)
+ {
+ pFont[i] = new SvxFontItem;
+ pFontHeight[i] = new SvxFontHeightItem;
+ pFontWeight[i] = new SvxWeightItem;
+ pFontPosture[i] = new SvxPostureItem;
+ pFontUnderline[i] = new SvxUnderlineItem;
+ pFontCrossedOut[i] = new SvxCrossedOutItem;
+ pFontContour[i] = new SvxContourItem;
+ pFontShadowed[i] = new SvxShadowedItem;
+ pFontColor[i] = new SvxColorItem;
+ pBox[i] = new SvxBoxItem;
+ pBackground[i] = new SvxBrushItem;
+
+ pAdjust[i] = new SvxAdjustItem;
+
+ pHorJustify[i] = new SvxHorJustifyItem;
+ pVerJustify[i] = new SvxVerJustifyItem;
+ pOrientation[i] = new SvxOrientationItem;
+ pMargin[i] = new SvxMarginItem;
+ pLinebreak[i] = new SfxBoolItem( ATTR_LINEBREAK );
+ pRotateAngle[i] = new SfxInt32Item( ATTR_ROTATE_VALUE );
+ pRotateMode[i] = new SvxRotateModeItem( SVX_ROTATE_MODE_STANDARD, ATTR_ROTATE_MODE );
+
+ pNumFormat[i] = new ScNumFormatAbbrev;
+ }
+}
+
+ScAutoFormatData::ScAutoFormatData( const ScAutoFormatData& rData ) :
+ aName( rData.aName ),
+ nStrResId( rData.nStrResId ),
+ bIncludeValueFormat( rData.bIncludeValueFormat ),
+ bIncludeFont( rData.bIncludeFont ),
+ bIncludeJustify( rData.bIncludeJustify ),
+ bIncludeFrame( rData.bIncludeFrame ),
+ bIncludeBackground( rData.bIncludeBackground ),
+ bIncludeWidthHeight( rData.bIncludeWidthHeight )
+{
+ for (USHORT i = 0; i < 16; i++)
+ {
+ pFont[i] = new SvxFontItem(*rData.pFont[i]);
+ pFontHeight[i] = new SvxFontHeightItem(*rData.pFontHeight[i]);
+ pFontWeight[i] = new SvxWeightItem(*rData.pFontWeight[i]);
+ pFontPosture[i] = new SvxPostureItem(*rData.pFontPosture[i]);
+ pFontUnderline[i] = new SvxUnderlineItem(*rData.pFontUnderline[i]);
+ pFontCrossedOut[i] = new SvxCrossedOutItem(*rData.pFontCrossedOut[i]);
+ pFontContour[i] = new SvxContourItem(*rData.pFontContour[i]);
+ pFontShadowed[i] = new SvxShadowedItem(*rData.pFontShadowed[i]);
+ pFontColor[i] = new SvxColorItem(*rData.pFontColor[i]);
+ pBox[i] = new SvxBoxItem(*rData.pBox[i]);
+ pBackground[i] = new SvxBrushItem(*rData.pBackground[i]);
+
+ pAdjust[ i ] = new SvxAdjustItem( *rData.pAdjust[ i ] );
+
+ pHorJustify[i] = new SvxHorJustifyItem(*rData.pHorJustify[i]);
+ pVerJustify[i] = new SvxVerJustifyItem(*rData.pVerJustify[i]);
+ pOrientation[i] = new SvxOrientationItem(*rData.pOrientation[i]);
+ pMargin[i] = new SvxMarginItem(*rData.pMargin[i]);
+ pLinebreak[i] = new SfxBoolItem(*rData.pLinebreak[i]);
+ pRotateAngle[i] = new SfxInt32Item(*rData.pRotateAngle[i]);
+ pRotateMode[i] = new SvxRotateModeItem(*rData.pRotateMode[i]);
+
+ pNumFormat[i] = new ScNumFormatAbbrev(*rData.pNumFormat[i]);
+ }
+}
+
+ScAutoFormatData::~ScAutoFormatData()
+{
+ for (USHORT i = 0; i < 16; i++)
+ {
+ delete pFont[i];
+ delete pFontHeight[i];
+ delete pFontWeight[i];
+ delete pFontPosture[i];
+ delete pFontUnderline[i];
+ delete pFontCrossedOut[i];
+ delete pFontContour[i];
+ delete pFontShadowed[i];
+ delete pFontColor[i];
+ delete pBox[i];
+ delete pBackground[i];
+
+ delete pAdjust[i];
+
+ delete pHorJustify[i];
+ delete pVerJustify[i];
+ delete pOrientation[i];
+ delete pMargin[i];
+ delete pLinebreak[i];
+ delete pRotateAngle[i];
+ delete pRotateMode[i];
+
+ delete pNumFormat[i];
+ }
+}
+
+//---------------------------------------------------------------------------------------
+
+void ScAutoFormatData::GetNumFormat(USHORT nIndex, ScNumFormatAbbrev& rNumFormat) const
+{
+ rNumFormat = *pNumFormat[nIndex];
+}
+
+void ScAutoFormatData::SetNumFormat(USHORT nIndex, const ScNumFormatAbbrev& rNumFormat)
+{
+ *pNumFormat[nIndex] = rNumFormat;
+}
+
+//---------------------------------------------------------------------------------------
+
+void ScAutoFormatData::GetFont(USHORT nIndex, SvxFontItem& rFont) const
+{
+ rFont = *pFont[nIndex];
+}
+
+void ScAutoFormatData::SetFont(USHORT nIndex, const SvxFontItem& rFont)
+{
+ *pFont[nIndex] = rFont;
+}
+
+//---------------------------------------------------------------------------------------
+
+void ScAutoFormatData::GetFontHeight(USHORT nIndex, SvxFontHeightItem& rFontHeight) const
+{
+ rFontHeight = *pFontHeight[nIndex];
+}
+
+void ScAutoFormatData::SetFontHeight(USHORT nIndex, const SvxFontHeightItem& rFontHeight)
+{
+ *pFontHeight[nIndex] = rFontHeight;
+}
+
+//---------------------------------------------------------------------------------------
+
+void ScAutoFormatData::GetFontWeight(USHORT nIndex, SvxWeightItem& rFontWeight) const
+{
+ rFontWeight = *pFontWeight[nIndex];
+}
+
+void ScAutoFormatData::SetFontWeight(USHORT nIndex, const SvxWeightItem& rFontWeight)
+{
+ *pFontWeight[nIndex] = rFontWeight;
+}
+
+void ScAutoFormatData::GetFontPosture(USHORT nIndex, SvxPostureItem& rFontPosture) const
+{
+ rFontPosture = *pFontPosture[nIndex];
+}
+
+void ScAutoFormatData::SetFontPosture(USHORT nIndex, const SvxPostureItem& rFontPosture)
+{
+ *pFontPosture[nIndex] = rFontPosture;
+}
+
+//---------------------------------------------------------------------------------------
+
+void ScAutoFormatData::GetFontUnderline(USHORT nIndex, SvxUnderlineItem& rFontUnderline) const
+{
+ rFontUnderline = *pFontUnderline[nIndex];
+}
+
+void ScAutoFormatData::SetFontUnderline(USHORT nIndex, const SvxUnderlineItem& rFontUnderline)
+{
+ *pFontUnderline[nIndex] = rFontUnderline;
+}
+
+//---------------------------------------------------------------------------------------
+
+void ScAutoFormatData::GetFontCrossedOut(USHORT nIndex, SvxCrossedOutItem& rFontCrossedOut) const
+{
+ rFontCrossedOut = *pFontCrossedOut[nIndex];
+}
+
+void ScAutoFormatData::SetFontCrossedOut(USHORT nIndex, const SvxCrossedOutItem& rFontCrossedOut)
+{
+ *pFontCrossedOut[nIndex] = rFontCrossedOut;
+}
+
+//---------------------------------------------------------------------------------------
+
+void ScAutoFormatData::GetFontContour(USHORT nIndex, SvxContourItem& rFontContour) const
+{
+ rFontContour = *pFontContour[nIndex];
+}
+
+void ScAutoFormatData::SetFontContour(USHORT nIndex, const SvxContourItem& rFontContour)
+{
+ *pFontContour[nIndex] = rFontContour;
+}
+
+//---------------------------------------------------------------------------------------
+
+void ScAutoFormatData::GetFontShadowed(USHORT nIndex, SvxShadowedItem& rFontShadowed) const
+{
+ rFontShadowed = *pFontShadowed[nIndex];
+}
+
+void ScAutoFormatData::SetFontShadowed(USHORT nIndex, const SvxShadowedItem& rFontShadowed)
+{
+ *pFontShadowed[nIndex] = rFontShadowed;
+}
+
+//---------------------------------------------------------------------------------------
+
+void ScAutoFormatData::GetFontColor(USHORT nIndex, SvxColorItem& rFontColor) const
+{
+ rFontColor = *pFontColor[nIndex];
+}
+
+void ScAutoFormatData::SetFontColor(USHORT nIndex, const SvxColorItem& rFontColor)
+{
+ *pFontColor[nIndex] = rFontColor;
+}
+
+//---------------------------------------------------------------------------------------
+
+void ScAutoFormatData::GetHorJustify(USHORT nIndex, SvxHorJustifyItem& rHorJustify) const
+{
+ rHorJustify = *pHorJustify[nIndex];
+}
+
+void ScAutoFormatData::SetHorJustify(USHORT nIndex, const SvxHorJustifyItem& rHorJustify)
+{
+ *pHorJustify[nIndex] = rHorJustify;
+}
+
+//---------------------------------------------------------------------------------------
+
+void ScAutoFormatData::GetVerJustify(USHORT nIndex, SvxVerJustifyItem& rVerJustify) const
+{
+ rVerJustify = *pVerJustify[nIndex];
+}
+
+void ScAutoFormatData::SetVerJustify(USHORT nIndex, const SvxVerJustifyItem& rVerJustify)
+{
+ *pVerJustify[nIndex] = rVerJustify;
+}
+
+//---------------------------------------------------------------------------------------
+
+void ScAutoFormatData::GetOrientation(USHORT nIndex, SvxOrientationItem& rOrientation) const
+{
+ rOrientation = *pOrientation[nIndex];
+}
+
+void ScAutoFormatData::SetOrientation(USHORT nIndex, const SvxOrientationItem& rOrientation)
+{
+ *pOrientation[nIndex] = rOrientation;
+}
+
+//---------------------------------------------------------------------------------------
+
+void ScAutoFormatData::GetLinebreak(USHORT nIndex, SfxBoolItem& rLinebreak) const
+{
+ rLinebreak.SetValue( pLinebreak[nIndex]->GetValue() );
+}
+
+void ScAutoFormatData::SetLinebreak(USHORT nIndex, const SfxBoolItem& rLinebreak)
+{
+ pLinebreak[nIndex]->SetValue( rLinebreak.GetValue() );
+}
+
+//---------------------------------------------------------------------------------------
+
+void ScAutoFormatData::GetMargin(USHORT nIndex, SvxMarginItem& rMargin) const
+{
+ rMargin = *pMargin[nIndex];
+}
+
+void ScAutoFormatData::SetMargin(USHORT nIndex, const SvxMarginItem& rMargin)
+{
+ *pMargin[nIndex] = rMargin;
+}
+
+//---------------------------------------------------------------------------------------
+
+void ScAutoFormatData::GetBox(USHORT nIndex, SvxBoxItem& rBox) const
+{
+ rBox = *pBox[nIndex];
+}
+
+void ScAutoFormatData::SetBox(USHORT nIndex, const SvxBoxItem& rBox)
+{
+ *pBox[nIndex] = rBox;
+}
+
+//---------------------------------------------------------------------------------------
+
+void ScAutoFormatData::GetBackground(USHORT nIndex, SvxBrushItem& rBackground) const
+{
+ rBackground = *pBackground[nIndex];
+}
+
+void ScAutoFormatData::SetBackground(USHORT nIndex, const SvxBrushItem& rBackground)
+{
+ *pBackground[nIndex] = rBackground;
+}
+
+//---------------------------------------------------------------------------------------
+
+void ScAutoFormatData::GetRotateAngle( USHORT nIndex, SfxInt32Item& rRotateAngle ) const
+{
+ rRotateAngle.SetValue( pRotateAngle[nIndex]->GetValue() );
+}
+
+void ScAutoFormatData::SetRotateAngle( USHORT nIndex, const SfxInt32Item& rRotateAngle )
+{
+ pRotateAngle[nIndex]->SetValue( rRotateAngle.GetValue() );
+}
+
+//---------------------------------------------------------------------------------------
+
+void ScAutoFormatData::GetRotateMode( USHORT nIndex, SvxRotateModeItem& rRotateMode ) const
+{
+ rRotateMode.SetValue( pRotateMode[nIndex]->GetValue() );
+}
+
+void ScAutoFormatData::SetRotateMode( USHORT nIndex, const SvxRotateModeItem& rRotateMode )
+{
+ pRotateMode[nIndex]->SetValue( rRotateMode.GetValue() );
+}
+
+//---------------------------------------------------------------------------------------
+
+const SfxPoolItem* ScAutoFormatData::GetItem( USHORT nIndex, USHORT nWhich ) const
+{
+ switch (nWhich)
+ {
+ case ATTR_FONT: return pFont[nIndex];
+ case ATTR_FONT_HEIGHT: return pFontHeight[nIndex];
+ case ATTR_FONT_WEIGHT: return pFontWeight[nIndex];
+ case ATTR_FONT_POSTURE: return pFontPosture[nIndex];
+ case ATTR_FONT_UNDERLINE: return pFontUnderline[nIndex];
+ case ATTR_FONT_CROSSEDOUT: return pFontCrossedOut[nIndex];
+ case ATTR_FONT_CONTOUR: return pFontContour[nIndex];
+ case ATTR_FONT_SHADOWED: return pFontShadowed[nIndex];
+ case ATTR_FONT_COLOR: return pFontColor[nIndex];
+ case ATTR_BORDER: return pBox[nIndex];
+ case ATTR_BACKGROUND: return pBackground[nIndex];
+ case ATTR_HOR_JUSTIFY: return pHorJustify[nIndex];
+ case ATTR_VER_JUSTIFY: return pVerJustify[nIndex];
+ case ATTR_ORIENTATION: return pOrientation[nIndex];
+ case ATTR_MARGIN: return pMargin[nIndex];
+ case ATTR_LINEBREAK: return pLinebreak[nIndex];
+ case ATTR_ROTATE_VALUE: return pRotateAngle[nIndex];
+ case ATTR_ROTATE_MODE: return pRotateMode[nIndex];
+ }
+ return NULL;
+}
+
+void ScAutoFormatData::PutItem( USHORT nIndex, const SfxPoolItem& rItem )
+{
+ switch (rItem.Which())
+ {
+ case ATTR_FONT:
+ *pFont[nIndex] = (const SvxFontItem&)rItem;
+ break;
+ case ATTR_FONT_HEIGHT:
+ *pFontHeight[nIndex] = (const SvxFontHeightItem&)rItem;
+ break;
+ case ATTR_FONT_WEIGHT:
+ *pFontWeight[nIndex] = (const SvxWeightItem&)rItem;
+ break;
+ case ATTR_FONT_POSTURE:
+ *pFontPosture[nIndex] = (const SvxPostureItem&)rItem;
+ break;
+ case ATTR_FONT_UNDERLINE:
+ *pFontUnderline[nIndex] = (const SvxUnderlineItem&)rItem;
+ break;
+ case ATTR_FONT_CROSSEDOUT:
+ *pFontCrossedOut[nIndex] = (const SvxCrossedOutItem&)rItem;
+ break;
+ case ATTR_FONT_CONTOUR:
+ *pFontContour[nIndex] = (const SvxContourItem&)rItem;
+ break;
+ case ATTR_FONT_SHADOWED:
+ *pFontShadowed[nIndex] = (const SvxShadowedItem&)rItem;
+ break;
+ case ATTR_FONT_COLOR:
+ *pFontColor[nIndex] = (const SvxColorItem&)rItem;
+ break;
+ case ATTR_BORDER:
+ *pBox[nIndex] = (const SvxBoxItem&)rItem;
+ break;
+ case ATTR_BACKGROUND:
+ *pBackground[nIndex] = (const SvxBrushItem&)rItem;
+ break;
+ case ATTR_HOR_JUSTIFY:
+ *pHorJustify[nIndex] = (const SvxHorJustifyItem&)rItem;
+ break;
+ case ATTR_VER_JUSTIFY:
+ *pVerJustify[nIndex] = (const SvxVerJustifyItem&)rItem;
+ break;
+ case ATTR_ORIENTATION:
+ *pOrientation[nIndex] = (const SvxOrientationItem&)rItem;
+ break;
+ case ATTR_MARGIN:
+ *pMargin[nIndex] = (const SvxMarginItem&)rItem;
+ break;
+ case ATTR_LINEBREAK:
+ pLinebreak[nIndex]->SetValue( ((const SfxBoolItem&)rItem).GetValue() );
+ break;
+ case ATTR_ROTATE_VALUE:
+ pRotateAngle[nIndex]->SetValue( ((const SfxInt32Item&)rItem).GetValue() );
+ break;
+ case ATTR_ROTATE_MODE:
+ pRotateMode[nIndex]->SetValue( ((const SvxRotateModeItem&)rItem).GetValue() );
+ break;
+ }
+}
+
+//---------------------------------------------------------------------------------------
+
+BOOL ScAutoFormatData::IsEqualData(USHORT nIndex1, USHORT nIndex2)
+{
+ BOOL bEqual = TRUE;
+ if (bIncludeValueFormat)
+ {
+ bEqual = (bEqual && (*pNumFormat[nIndex1] == *pNumFormat[nIndex2]));
+ }
+ if (bIncludeFont)
+ {
+ bEqual = (bEqual && (*pFont[nIndex1] == *pFont[nIndex2]));
+ bEqual = (bEqual && (*pFontHeight[nIndex1] == *pFontHeight[nIndex2]));
+ bEqual = (bEqual && (*pFontWeight[nIndex1] == *pFontWeight[nIndex2]));
+ bEqual = (bEqual && (*pFontPosture[nIndex1] == *pFontPosture[nIndex2]));
+ bEqual = (bEqual && (*pFontUnderline[nIndex1] == *pFontUnderline[nIndex2]));
+ bEqual = (bEqual && (*pFontCrossedOut[nIndex1] == *pFontCrossedOut[nIndex2]));
+ bEqual = (bEqual && (*pFontContour[nIndex1] == *pFontContour[nIndex2]));
+ bEqual = (bEqual && (*pFontShadowed[nIndex1] == *pFontShadowed[nIndex2]));
+ bEqual = (bEqual && (*pFontColor[nIndex1] == *pFontColor[nIndex2]));
+ }
+ if (bIncludeJustify)
+ {
+ bEqual = (bEqual && (*pHorJustify[nIndex1] == *pHorJustify[nIndex2]));
+ bEqual = (bEqual && (*pVerJustify[nIndex1] == *pVerJustify[nIndex2]));
+ bEqual = (bEqual && (*pOrientation[nIndex1] == *pOrientation[nIndex2]));
+ bEqual = (bEqual && (*pLinebreak[nIndex1] == *pLinebreak[nIndex2]));
+ bEqual = (bEqual && (*pMargin[nIndex1] == *pMargin[nIndex2]));
+ bEqual = (bEqual && (*pRotateAngle[nIndex1] == *pRotateAngle[nIndex2]));
+ bEqual = (bEqual && (*pRotateMode[nIndex1] == *pRotateMode[nIndex2]));
+ }
+ if (bIncludeFrame)
+ bEqual = (bEqual && (*pBox[nIndex1] == *pBox[nIndex2]));
+ if (bIncludeBackground)
+ bEqual = (bEqual && (*pBackground[nIndex1] == *pBackground[nIndex2]));
+ return bEqual;
+}
+
+#define READ( i, aItem, aItemType, nVers )\
+ pNew = aItem[i]->Create(rStream, nVers ); \
+ *aItem[i] = *(aItemType*)pNew; \
+ delete pNew;
+
+BOOL ScAutoFormatData::Load(SvStream& rStream, const ScAfVersions& rVersions)
+{
+ BOOL bRet = TRUE;
+ USHORT nVal = 0;
+ rStream >> nVal;
+ bRet = 0 == rStream.GetError();
+ if( bRet && (nVal == AUTOFORMAT_DATA_ID_X ||
+ (AUTOFORMAT_DATA_ID_504 <= nVal && nVal <= AUTOFORMAT_DATA_ID)) )
+ {
+ CharSet eSysSet = gsl_getSystemTextEncoding();
+ CharSet eSrcSet = rStream.GetStreamCharSet();
+
+ BOOL b;
+ rStream.ReadByteString( aName, eSrcSet );
+ if( AUTOFORMAT_DATA_ID_552 <= nVal )
+ {
+ rStream >> nStrResId;
+ USHORT nId = RID_SVXSTR_TBLAFMT_BEGIN + nStrResId;
+ if( RID_SVXSTR_TBLAFMT_BEGIN <= nId &&
+ nId < RID_SVXSTR_TBLAFMT_END )
+ {
+ aName = SVX_RESSTR( nId );
+ }
+ else
+ nStrResId = USHRT_MAX;
+ }
+
+ rStream >> b; bIncludeFont = b;
+ rStream >> b; bIncludeJustify = b;
+ rStream >> b; bIncludeFrame = b;
+ rStream >> b; bIncludeBackground = b;
+ rStream >> b; bIncludeValueFormat = b;
+ rStream >> b; bIncludeWidthHeight = b;
+
+ SfxPoolItem* pNew;
+ bRet = 0 == rStream.GetError();
+ for( USHORT i = 0; bRet && i < 16; ++i )
+ {
+ READ( i, pFont, SvxFontItem , rVersions.nFontVersion)
+ READ( i, pFontHeight, SvxFontHeightItem , rVersions.nFontHeightVersion)
+ READ( i, pFontWeight, SvxWeightItem , rVersions.nWeightVersion)
+ READ( i, pFontPosture, SvxPostureItem , rVersions.nPostureVersion)
+ READ( i, pFontUnderline, SvxUnderlineItem , rVersions.nUnderlineVersion)
+ READ( i, pFontCrossedOut, SvxCrossedOutItem , rVersions.nCrossedOutVersion)
+ READ( i, pFontContour, SvxContourItem , rVersions.nContourVersion)
+ READ( i, pFontShadowed, SvxShadowedItem , rVersions.nShadowedVersion)
+ READ( i, pFontColor, SvxColorItem , rVersions.nColorVersion)
+ READ( i, pBox, SvxBoxItem , rVersions.nBoxVersion)
+ READ( i, pBackground, SvxBrushItem , rVersions.nBrushVersion)
+
+ pNew = pAdjust[i]->Create(rStream, rVersions.nAdjustVersion );
+ ((SvxAdjustItem*)pAdjust[i])->SetAdjust( ((SvxAdjustItem*)pNew)->GetAdjust() );
+ ((SvxAdjustItem*)pAdjust[i])->SetOneWord( ((SvxAdjustItem*)pNew)->GetOneWord() );
+ ((SvxAdjustItem*)pAdjust[i])->SetLastBlock( ((SvxAdjustItem*)pNew)->GetLastBlock() );
+ delete pNew;
+
+ READ( i, pHorJustify, SvxHorJustifyItem, rVersions.nHorJustifyVersion)
+ READ( i, pVerJustify, SvxVerJustifyItem, rVersions.nVerJustifyVersion)
+ READ( i, pOrientation, SvxOrientationItem, rVersions.nOrientationVersion)
+ READ( i, pMargin, SvxMarginItem, rVersions.nMarginVersion)
+
+ pNew = pLinebreak[i]->Create(rStream, rVersions.nBoolVersion );
+ pLinebreak[i]->SetValue( ((SfxBoolItem*)pNew)->GetValue() );
+ delete pNew;
+
+ if ( nVal >= AUTOFORMAT_DATA_ID_504 )
+ {
+ pNew = pRotateAngle[i]->Create( rStream, rVersions.nInt32Version );
+ pRotateAngle[i]->SetValue( ((SfxInt32Item*)pNew)->GetValue() );
+ delete pNew;
+ pNew = pRotateMode[i]->Create( rStream, rVersions.nRotateModeVersion );
+ pRotateMode[i]->SetValue( ((SvxRotateModeItem*)pNew)->GetValue() );
+ delete pNew;
+ }
+
+ if( 0 == rVersions.nNumFmtVersion )
+ pNumFormat[i]->Load( rStream );
+
+ // CharSet in Font anpassen
+ if ( eSrcSet != eSysSet && pFont[i]->GetCharSet() == eSrcSet )
+ pFont[i]->GetCharSet() = eSysSet;
+
+ bRet = 0 == rStream.GetError();
+ }
+ }
+ else
+ bRet = FALSE;
+ return bRet;
+}
+
+#ifdef READ_OLDVERS
+
+BOOL ScAutoFormatData::LoadOld(SvStream& rStream, const ScAfVersions& rVersions)
+{
+ BOOL bRet = TRUE;
+ USHORT nVal = 0;
+ rStream >> nVal;
+ bRet = (rStream.GetError() == 0);
+ if (bRet && (nVal == AUTOFORMAT_OLD_DATA_ID))
+ {
+ rStream.ReadByteString( aName, rStream.GetStreamCharSet() );
+ BOOL b;
+ rStream >> b; bIncludeFont = b;
+ rStream >> b; bIncludeJustify = b;
+ rStream >> b; bIncludeFrame = b;
+ rStream >> b; bIncludeBackground = b;
+ rStream >> b; bIncludeValueFormat = b;
+ rStream >> b; bIncludeWidthHeight = b;
+
+ bRet = 0 == rStream.GetError();
+ SfxPoolItem* pNew;
+ for (USHORT i=0; bRet && i < 16; i++)
+ {
+ pNumFormat[i]->Load(rStream);
+
+ READ( i, pFont, SvxFontItem , rVersions.nFontVersion)
+ READ( i, pFontHeight, SvxFontHeightItem , rVersions.nFontHeightVersion)
+ READ( i, pFontWeight, SvxWeightItem , rVersions.nWeightVersion)
+ READ( i, pFontPosture, SvxPostureItem , rVersions.nPostureVersion)
+ READ( i, pFontUnderline, SvxUnderlineItem , rVersions.nUnderlineVersion)
+ READ( i, pFontCrossedOut, SvxCrossedOutItem , rVersions.nCrossedOutVersion)
+ READ( i, pFontContour, SvxContourItem , rVersions.nContourVersion)
+ READ( i, pFontShadowed, SvxShadowedItem , rVersions.nShadowedVersion)
+ READ( i, pFontColor, SvxColorItem , rVersions.nColorVersion)
+ READ( i, pHorJustify, SvxHorJustifyItem, rVersions.nHorJustifyVersion)
+ READ( i, pVerJustify, SvxVerJustifyItem, rVersions.nVerJustifyVersion)
+ READ( i, pOrientation, SvxOrientationItem, rVersions.nOrientationVersion)
+ pNew = pLinebreak[i]->Create(rStream, rVersions.nBoolVersion );
+ pLinebreak[i]->SetValue( ((SfxBoolItem*)pNew)->GetValue() );
+ delete pNew;
+ READ( i, pMargin, SvxMarginItem, rVersions.nMarginVersion)
+ READ( i, pBox, SvxBoxItem , rVersions.nBoxVersion)
+ READ( i, pBackground, SvxBrushItem , rVersions.nBrushVersion)
+
+ bRet = (rStream.GetError() == 0);
+ }
+ }
+ else
+ bRet = FALSE;
+ return bRet;
+}
+
+#endif
+
+BOOL ScAutoFormatData::Save(SvStream& rStream)
+{
+ USHORT nVal = AUTOFORMAT_DATA_ID;
+ BOOL b;
+ rStream << nVal;
+ rStream.WriteByteString( aName, rStream.GetStreamCharSet() );
+ if ( USHRT_MAX == nStrResId )
+ {
+ String aIniVal( SFX_APP()->GetIniManager()->Get(
+ SFX_GROUP_WORKINGSET_IMPL,
+ String( RTL_CONSTASCII_USTRINGPARAM( "SaveTableAutoFmtNameId" ))));
+ if( 0 != aIniVal.ToInt32() )
+ {
+ // check Name for ResId
+ for( USHORT nId = RID_SVXSTR_TBLAFMT_BEGIN;
+ RID_SVXSTR_TBLAFMT_END > nId; ++nId )
+ {
+ String s( SVX_RES( nId ) );
+ if( s == aName )
+ {
+ nStrResId = nId - RID_SVXSTR_TBLAFMT_BEGIN;
+ break;
+ }
+ }
+ }
+ }
+
+ rStream << nStrResId;
+ rStream << ( b = bIncludeFont );
+ rStream << ( b = bIncludeJustify );
+ rStream << ( b = bIncludeFrame );
+ rStream << ( b = bIncludeBackground );
+ rStream << ( b = bIncludeValueFormat );
+ rStream << ( b = bIncludeWidthHeight );
+ BOOL bRet = 0 == rStream.GetError();
+ for (USHORT i = 0; bRet && (i < 16); i++)
+ {
+ pFont[i]->Store(rStream, pFont[i]->GetVersion(SOFFICE_FILEFORMAT_40));
+ pFontHeight[i]->Store(rStream, pFontHeight[i]->GetVersion(SOFFICE_FILEFORMAT_40));
+ pFontWeight[i]->Store(rStream, pFontWeight[i]->GetVersion(SOFFICE_FILEFORMAT_40));
+ pFontPosture[i]->Store(rStream, pFontPosture[i]->GetVersion(SOFFICE_FILEFORMAT_40));
+ pFontUnderline[i]->Store(rStream, pFontUnderline[i]->GetVersion(SOFFICE_FILEFORMAT_40));
+ pFontCrossedOut[i]->Store(rStream, pFontCrossedOut[i]->GetVersion(SOFFICE_FILEFORMAT_40));
+ pFontContour[i]->Store(rStream, pFontContour[i]->GetVersion(SOFFICE_FILEFORMAT_40));
+ pFontShadowed[i]->Store(rStream, pFontShadowed[i]->GetVersion(SOFFICE_FILEFORMAT_40));
+ pFontColor[i]->Store(rStream, pFontColor[i]->GetVersion(SOFFICE_FILEFORMAT_40));
+ pBox[i]->Store(rStream, pBox[i]->GetVersion(SOFFICE_FILEFORMAT_40));
+ pBackground[i]->Store(rStream, pBackground[i]->GetVersion(SOFFICE_FILEFORMAT_40));
+
+ pAdjust[i]->Store(rStream, pAdjust[i]->GetVersion(SOFFICE_FILEFORMAT_40));
+
+ pHorJustify[i]->Store(rStream, pHorJustify[i]->GetVersion(SOFFICE_FILEFORMAT_40));
+ pVerJustify[i]->Store(rStream, pVerJustify[i]->GetVersion(SOFFICE_FILEFORMAT_40));
+ pOrientation[i]->Store(rStream, pOrientation[i]->GetVersion(SOFFICE_FILEFORMAT_40));
+ pMargin[i]->Store(rStream, pMargin[i]->GetVersion(SOFFICE_FILEFORMAT_40));
+ pLinebreak[i]->Store(rStream, pLinebreak[i]->GetVersion(SOFFICE_FILEFORMAT_40));
+ // Rotation ab SO5
+ pRotateAngle[i]->Store(rStream, pRotateAngle[i]->GetVersion(SOFFICE_FILEFORMAT_40));
+ pRotateMode[i]->Store(rStream, pRotateMode[i]->GetVersion(SOFFICE_FILEFORMAT_40));
+
+ pNumFormat[i]->Save(rStream);
+ bRet = (rStream.GetError() == 0);
+ }
+ return bRet;
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+ScAutoFormat::ScAutoFormat(USHORT nLim, USHORT nDel, BOOL bDup):
+ SortedCollection (nLim, nDel, bDup),
+ bSaveLater (FALSE)
+{
+ // Default "Standard" Format anlegen
+ ScAutoFormatData* pData = new ScAutoFormatData();
+ String aName(ScGlobal::GetRscString(STR_STYLENAME_STANDARD));
+ pData->SetName(aName);
+
+ // Default-Font und Groesse
+ Font aStdFont = System::GetStandardFont( STDFONT_SWISS );
+ SvxFontItem aFontItem( aStdFont.GetFamily(), aStdFont.GetName(), aStdFont.GetStyleName(),
+ aStdFont.GetPitch(), aStdFont.GetCharSet() );
+ SvxFontHeightItem aHeight( 200 ); // 10 pt;
+
+ // schwarze duenne Umrandung
+ Color aBlack( COL_BLACK );
+ SvxBorderLine aLine( &aBlack, DEF_LINE_WIDTH_0 );
+ SvxBoxItem aBox;
+ aBox.SetLine(&aLine, BOX_LINE_LEFT);
+ aBox.SetLine(&aLine, BOX_LINE_TOP);
+ aBox.SetLine(&aLine, BOX_LINE_RIGHT);
+ aBox.SetLine(&aLine, BOX_LINE_BOTTOM);
+
+ Color aWhite(COL_WHITE);
+ Color aBlue(COL_BLUE);
+ SvxColorItem aWhiteText( aWhite );
+ SvxColorItem aBlackText( aBlack );
+ SvxBrushItem aBlueBack( aBlue );
+ SvxBrushItem aWhiteBack( aWhite );
+ SvxBrushItem aGray70Back( Color(0x4d, 0x4d, 0x4d) );
+ SvxBrushItem aGray20Back( Color(0xcc, 0xcc, 0xcc) );
+
+ for (USHORT i=0; i<16; i++)
+ {
+ pData->SetBox( i, aBox );
+ pData->SetFont( i, aFontItem );
+ pData->SetFontHeight( i, aHeight );
+ if (i<4) // oben: weiss auf blau
+ {
+ pData->SetFontColor( i, aWhiteText );
+ pData->SetBackground( i, aBlueBack );
+ }
+ else if ( i%4 == 0 ) // links: weiss auf grau70
+ {
+ pData->SetFontColor( i, aWhiteText );
+ pData->SetBackground( i, aGray70Back );
+ }
+ else if ( i%4 == 3 || i >= 12 ) // rechts & unten: schwarz auf grau20
+ {
+ pData->SetFontColor( i, aBlackText );
+ pData->SetBackground( i, aGray20Back );
+ }
+ else // Mitte: schwarz auf weiss
+ {
+ pData->SetFontColor( i, aBlackText );
+ pData->SetBackground( i, aWhiteBack );
+ }
+ }
+
+ Insert(pData);
+}
+
+ScAutoFormat::ScAutoFormat(const ScAutoFormat& rAutoFormat) :
+ SortedCollection (rAutoFormat),
+ bSaveLater (FALSE)
+{}
+
+ScAutoFormat::~ScAutoFormat()
+{
+ // Bei Aenderungen per StarOne wird nicht sofort gespeichert, sondern zuerst nur
+ // das SaveLater Flag gesetzt. Wenn das Flag noch gesetzt ist, jetzt speichern.
+
+ if (bSaveLater)
+ Save();
+}
+
+void ScAutoFormat::SetSaveLater( BOOL bSet )
+{
+ bSaveLater = bSet;
+}
+
+short ScAutoFormat::Compare(DataObject* pKey1, DataObject* pKey2) const
+{
+ StringCompare eComp;
+ String aStr1;
+ String aStr2;
+ ((ScAutoFormatData*)pKey1)->GetName(aStr1);
+ ((ScAutoFormatData*)pKey2)->GetName(aStr2);
+ String aStrStandard = ScGlobal::GetRscString(STR_STYLENAME_STANDARD);
+ if ( ScGlobal::pScInternational->CompareEqual( aStr1, aStrStandard, INTN_COMPARE_IGNORECASE ) )
+ return -1;
+ if ( ScGlobal::pScInternational->CompareEqual( aStr2, aStrStandard, INTN_COMPARE_IGNORECASE ) )
+ return 1;
+ eComp = ScGlobal::pScInternational->Compare( aStr2, aStr1, INTN_COMPARE_IGNORECASE );
+ if (eComp == COMPARE_EQUAL)
+ return 0;
+ else if (eComp == COMPARE_LESS)
+ return -1;
+ else
+ return 1;
+}
+
+BOOL ScAutoFormat::Load()
+{
+ BOOL bRet = TRUE;
+
+ INetURLObject aURL;
+ aURL.SetSmartURL( SFX_APP()->GetAppIniManager()->Get( SFX_KEY_USERCONFIG_PATH ) );
+ aURL.setFinalSlash();
+ aURL.Append( String( RTL_CONSTASCII_USTRINGPARAM( sAutoTblFmtName ) ) );
+
+ SfxMedium aMedium( aURL.GetMainURL(), STREAM_READ, TRUE );
+ SvStream* pStream = aMedium.GetInStream();
+ bRet = (pStream && pStream->GetError() == 0);
+ if (bRet)
+ {
+ SvStream& rStream = *pStream;
+ // Achtung hier muss ein allgemeiner Header gelesen werden
+ USHORT nVal = 0;
+ rStream >> nVal;
+ bRet = 0 == rStream.GetError();
+
+ ScAfVersions aVersions;
+
+ if (bRet)
+ {
+ if( nVal == AUTOFORMAT_ID_358 ||
+ (AUTOFORMAT_ID_504 <= nVal && nVal <= AUTOFORMAT_ID) )
+ {
+ UINT16 nFileVers = SOFFICE_FILEFORMAT_40;
+ BYTE nChrSet, nCnt;
+ long nPos = rStream.Tell();
+ rStream >> nCnt >> nChrSet;
+// if( 4 <= nCnt )
+// rStream >> nFileVers;
+ if( rStream.Tell() != ULONG(nPos + nCnt) )
+ {
+ DBG_ERRORFILE( "Der Header enthaelt mehr/neuere Daten" );
+ rStream.Seek( nPos + nCnt );
+ }
+ rStream.SetStreamCharSet( (CharSet)nChrSet );
+ rStream.SetVersion( nFileVers );
+ }
+
+ if( nVal == AUTOFORMAT_ID_358 || nVal == AUTOFORMAT_ID_X ||
+ (AUTOFORMAT_ID_504 <= nVal && nVal <= AUTOFORMAT_ID) )
+ {
+ aVersions.Load( rStream, nVal ); // Item-Versionen
+
+ ScAutoFormatData* pData;
+ USHORT nAnz = 0;
+ rStream >> nAnz;
+ bRet = (rStream.GetError() == 0);
+ for (USHORT i=0; bRet && (i < nAnz); i++)
+ {
+ pData = new ScAutoFormatData();
+ bRet = pData->Load(rStream, aVersions);
+ Insert(pData);
+ }
+ }
+#ifdef READ_OLDVERS
+ else
+ {
+ if( AUTOFORMAT_OLD_ID_NEW == nVal )
+ {
+ // alte Version der Versions laden
+ rStream >> aVersions.nFontVersion;
+ rStream >> aVersions.nFontHeightVersion;
+ rStream >> aVersions.nWeightVersion;
+ rStream >> aVersions.nPostureVersion;
+ rStream >> aVersions.nUnderlineVersion;
+ rStream >> aVersions.nCrossedOutVersion;
+ rStream >> aVersions.nContourVersion;
+ rStream >> aVersions.nShadowedVersion;
+ rStream >> aVersions.nColorVersion;
+ rStream >> aVersions.nHorJustifyVersion;
+ rStream >> aVersions.nVerJustifyVersion;
+ rStream >> aVersions.nOrientationVersion;
+ rStream >> aVersions.nBoolVersion;
+ rStream >> aVersions.nMarginVersion;
+ rStream >> aVersions.nBoxVersion;
+ rStream >> aVersions.nBrushVersion;
+ }
+ if( AUTOFORMAT_OLD_ID_OLD == nVal ||
+ AUTOFORMAT_OLD_ID_NEW == nVal )
+ {
+ ScAutoFormatData* pData;
+ USHORT nAnz = 0;
+ rStream >> nAnz;
+ bRet = 0 == rStream.GetError();
+ for( USHORT i=0; bRet && (i < nAnz); ++i )
+ {
+ pData = new ScAutoFormatData();
+ bRet = pData->LoadOld( rStream, aVersions );
+ Insert( pData );
+ }
+ }
+ else
+ bRet = FALSE;
+ }
+#endif
+ }
+ }
+ bSaveLater = FALSE;
+ return bRet;
+}
+
+BOOL ScAutoFormat::Save()
+{
+ BOOL bRet = TRUE;
+
+ INetURLObject aURL;
+ aURL.SetSmartURL( SFX_APP()->GetAppIniManager()->Get( SFX_KEY_USERCONFIG_PATH ) );
+ aURL.setFinalSlash();
+ aURL.Append( String( RTL_CONSTASCII_USTRINGPARAM( sAutoTblFmtName ) ) );
+
+ SfxMedium aMedium( aURL.GetMainURL(), STREAM_WRITE, TRUE );
+ SvStream* pStream = aMedium.GetOutStream();
+ bRet = (pStream && pStream->GetError() == 0);
+ if (bRet)
+ {
+ SvStream& rStream = *pStream;
+ rStream.SetVersion( SOFFICE_FILEFORMAT_40 );
+
+ // Achtung hier muss ein allgemeiner Header gespeichert werden
+ USHORT nVal = AUTOFORMAT_ID;
+ rStream << nVal
+ << (BYTE)2 // Anzahl von Zeichen des Headers incl. diesem
+ << (BYTE)::GetStoreCharSet( gsl_getSystemTextEncoding() );
+// << (BYTE)4 // Anzahl von Zeichen des Headers incl. diesem
+// << (BYTE)::GetStoreCharSet(::GetSystemCharSet())
+// << (UNIT16)SOFFICE_FILEFORMAT_NOW;
+ ScAfVersions::Write(rStream); // Item-Versionen
+
+ bRet = (rStream.GetError() == 0);
+ //-----------------------------------------------------------
+ rStream << (USHORT)(nCount - 1);
+ bRet = (rStream.GetError() == 0);
+ for (USHORT i=1; bRet && (i < nCount); i++)
+ bRet = ((ScAutoFormatData*)pItems[i])->Save(rStream);
+ rStream.Flush();
+ }
+ bSaveLater = FALSE;
+ return bRet;
+}
+
+USHORT ScAutoFormat::FindIndexPerName( const String& rName ) const
+{
+ String aName;
+
+ for( USHORT i=0; i<nCount ; i++ )
+ {
+ ScAutoFormatData* pItem = (ScAutoFormatData*)pItems[i];
+ pItem->GetName( aName );
+
+ if( aName == rName )
+ return i;
+ }
+
+ return 0;
+}
+
+
+
+
diff --git a/sc/source/core/tool/callform.cxx b/sc/source/core/tool/callform.cxx
new file mode 100644
index 000000000000..b1635c08daf2
--- /dev/null
+++ b/sc/source/core/tool/callform.cxx
@@ -0,0 +1,554 @@
+/*************************************************************************
+ *
+ * $RCSfile: callform.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <svtools/libcall.hxx>
+#include <tools/intn.hxx>
+#ifndef _SV_SVAPP_HXX //autogen
+#include <vcl/svapp.hxx>
+#endif
+#ifndef _SV_SYSTEM_HXX //autogen
+#include <vcl/system.hxx>
+#endif
+#ifndef _VOS_MODULE_HXX_
+#include <vos/module.hxx>
+#endif
+#ifndef _OSL_FILE_HXX_
+#include <osl/file.hxx>
+#endif
+
+#include "callform.hxx"
+#include "global.hxx"
+#include "adiasync.hxx"
+
+using namespace ::vos;
+
+//------------------------------------------------------------------------
+
+extern "C" {
+
+typedef void (CALLTYPE* ExFuncPtr1)(void*);
+typedef void (CALLTYPE* ExFuncPtr2)(void*, void*);
+typedef void (CALLTYPE* ExFuncPtr3)(void*, void*, void*);
+typedef void (CALLTYPE* ExFuncPtr4)(void*, void*, void*, void*);
+typedef void (CALLTYPE* ExFuncPtr5)(void*, void*, void*, void*, void*);
+typedef void (CALLTYPE* ExFuncPtr6)(void*, void*, void*, void*, void*, void*);
+typedef void (CALLTYPE* ExFuncPtr7)(void*, void*, void*, void*, void*, void*, void*);
+typedef void (CALLTYPE* ExFuncPtr8)(void*, void*, void*, void*, void*, void*, void*, void*);
+typedef void (CALLTYPE* ExFuncPtr9)(void*, void*, void*, void*, void*, void*, void*, void*, void*);
+typedef void (CALLTYPE* ExFuncPtr10)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*);
+typedef void (CALLTYPE* ExFuncPtr11)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*);
+typedef void (CALLTYPE* ExFuncPtr12)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*);
+typedef void (CALLTYPE* ExFuncPtr13)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*);
+typedef void (CALLTYPE* ExFuncPtr14)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*);
+typedef void (CALLTYPE* ExFuncPtr15)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*);
+typedef void (CALLTYPE* ExFuncPtr16)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*);
+
+typedef void (CALLTYPE* GetFuncCountPtr)(USHORT& nCount);
+typedef void (CALLTYPE* GetFuncDataPtr)
+ (USHORT& nNo, sal_Char* pFuncName, USHORT& nParamCount, ParamType* peType, sal_Char* pInternalName);
+
+typedef void (CALLTYPE* SetLanguagePtr)( USHORT& nLanguage );
+typedef void (CALLTYPE* GetParamDesc)
+ (USHORT& nNo, USHORT& nParam, sal_Char* pName, sal_Char* pDesc );
+
+typedef void (CALLTYPE* IsAsync) ( USHORT& nNo,
+ ParamType* peType );
+typedef void (CALLTYPE* Advice) ( USHORT& nNo,
+ AdvData& pfCallback );
+typedef void (CALLTYPE* Unadvice)( double& nHandle );
+
+typedef void (CALLTYPE* FARPROC) ( void );
+
+}
+
+#if defined(OS2) && defined(BLC)
+#define GETFUNCTIONCOUNT "_GetFunctionCount"
+#define GETFUNCTIONDATA "_GetFunctionData"
+#define SETLANGUAGE "_SetLanguage"
+#define GETPARAMDESC "_GetParameterDescription"
+#define ISASYNC "_IsAsync"
+#define ADVICE "_Advice"
+#define UNADVICE "_Unadvice"
+#else // Pascal oder extern "C"
+#define GETFUNCTIONCOUNT "GetFunctionCount"
+#define GETFUNCTIONDATA "GetFunctionData"
+#define SETLANGUAGE "SetLanguage"
+#define GETPARAMDESC "GetParameterDescription"
+#define ISASYNC "IsAsync"
+#define ADVICE "Advice"
+#define UNADVICE "Unadvice"
+#endif
+
+#define LIBFUNCNAME( name ) \
+ (String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( name ) ))
+
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+FuncData::FuncData(const String& rIName) :
+ pModuleData (NULL),
+ aInternalName (rIName),
+// aFuncName (""),
+ nNumber (0),
+ nParamCount (0),
+ eAsyncType (NONE)
+{
+ for (USHORT i = 0; i < MAXFUNCPARAM; i++)
+ eParamType[i] = PTR_DOUBLE;
+}
+
+//------------------------------------------------------------------------
+
+FuncData::FuncData(const ModuleData*pModule,
+ const String& rIName,
+ const String& rFName,
+ USHORT nNo,
+ USHORT nCount,
+ const ParamType* peType,
+ ParamType eType) :
+ pModuleData (pModule),
+ aInternalName (rIName),
+ aFuncName (rFName),
+ nNumber (nNo),
+ nParamCount (nCount),
+ eAsyncType (eType)
+{
+ for (USHORT i = 0; i < MAXFUNCPARAM; i++)
+ eParamType[i] = peType[i];
+}
+
+//------------------------------------------------------------------------
+
+FuncData::FuncData(const FuncData& rData) :
+ pModuleData (rData.pModuleData),
+ aInternalName (rData.aInternalName),
+ aFuncName (rData.aFuncName),
+ nNumber (rData.nNumber),
+ nParamCount (rData.nParamCount),
+ eAsyncType (rData.eAsyncType)
+{
+ for (USHORT i = 0; i < MAXFUNCPARAM; i++)
+ eParamType[i] = rData.eParamType[i];
+}
+
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+short FuncCollection::Compare(DataObject* pKey1, DataObject* pKey2) const
+{
+ StringCompare eComp = ScGlobal::pScInternational->Compare(
+ ((FuncData*)pKey1)->aInternalName, ((FuncData*)pKey2)->aInternalName,
+ INTN_COMPARE_IGNORECASE );
+ if (eComp == COMPARE_EQUAL)
+ return 0;
+ else if (eComp == COMPARE_LESS)
+ return -1;
+ else
+ return 1;
+}
+
+//------------------------------------------------------------------------
+
+BOOL FuncCollection::SearchFunc( const String& rName, USHORT& rIndex ) const
+{
+ FuncData aDataObj(rName);
+ return Search( &aDataObj, rIndex );
+}
+
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+class ModuleData : public DataObject
+{
+friend class ModuleCollection;
+ String aName;
+ OModule* pInstance;
+public:
+ ModuleData(const String& rStr, OModule* pInst) : aName (rStr), pInstance (pInst) {}
+ ModuleData(const ModuleData& rData) : aName (rData.aName) {pInstance = new OModule(aName);}
+ ~ModuleData() { delete pInstance; }
+ virtual DataObject* Clone() const { return new ModuleData(*this); }
+
+ const String& GetName() const { return aName; }
+ OModule* GetInstance() const { return pInstance; }
+ void FreeInstance() { delete pInstance; pInstance = 0; }
+};
+
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+class ModuleCollection : public SortedCollection
+{
+public:
+ ModuleCollection(USHORT nLim = 4, USHORT nDel = 4, BOOL bDup = FALSE) : SortedCollection ( nLim, nDel, bDup ) {}
+ ModuleCollection(const ModuleCollection& rModuleCollection) : SortedCollection ( rModuleCollection ) {}
+
+ virtual DataObject* Clone() const { return new ModuleCollection(*this); }
+ ModuleData* operator[]( const USHORT nIndex) const {return (ModuleData*)At(nIndex);}
+ virtual short Compare(DataObject* pKey1, DataObject* pKey2) const;
+ BOOL SearchModule( const String& rName,
+ const ModuleData*& rpModule ) const;
+};
+
+#pragma code_seg("SCSTATICS")
+
+static ModuleCollection aModuleCollection;
+
+#pragma code_seg()
+
+//------------------------------------------------------------------------
+
+short ModuleCollection::Compare(DataObject* pKey1, DataObject* pKey2) const
+{
+ StringCompare eComp = ScGlobal::pScInternational->Compare(
+ ((ModuleData*)pKey1)->aName, ((ModuleData*)pKey2)->aName,
+ INTN_COMPARE_IGNORECASE );
+ if (eComp == COMPARE_EQUAL)
+ return 0;
+ else if (eComp == COMPARE_LESS)
+ return -1;
+ else
+ return 1;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ModuleCollection::SearchModule( const String& rName,
+ const ModuleData*& rpModule ) const
+{
+ USHORT nIndex;
+ ModuleData aSearchModule(rName, 0);
+ BOOL bFound = Search( &aSearchModule, nIndex );
+ if (bFound)
+ rpModule = (ModuleData*)At(nIndex);
+ else
+ rpModule = 0;
+ return bFound;
+}
+
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+BOOL InitExternalFunc(const rtl::OUString& rModuleName)
+{
+ String aModuleName( rModuleName );
+
+ // Module schon geladen?
+ const ModuleData* pTemp;
+ if (aModuleCollection.SearchModule(aModuleName, pTemp))
+ return FALSE;
+
+ rtl::OUString aNP;
+ if ( osl::FileBase::getNormalizedPathFromFileURL( rModuleName, aNP ) != osl::FileBase::E_None )
+ return FALSE;
+
+ BOOL bRet = FALSE;
+ OModule* pLib = new OModule( aNP );
+ if (pLib->isLoaded())
+ {
+ FARPROC fpGetCount = (FARPROC)pLib->getSymbol(LIBFUNCNAME(GETFUNCTIONCOUNT));
+ FARPROC fpGetData = (FARPROC)pLib->getSymbol(LIBFUNCNAME(GETFUNCTIONDATA));
+ if ((fpGetCount != NULL) && (fpGetData != NULL))
+ {
+ FARPROC fpIsAsync = (FARPROC)pLib->getSymbol(LIBFUNCNAME(ISASYNC));
+ FARPROC fpAdvice = (FARPROC)pLib->getSymbol(LIBFUNCNAME(ADVICE));
+ FARPROC fpSetLanguage = (FARPROC)pLib->getSymbol(LIBFUNCNAME(SETLANGUAGE));
+ if ( fpSetLanguage )
+ {
+ LanguageType eLanguage =
+ Application::GetAppInternational().GetLanguage();
+ if ( (eLanguage == LANGUAGE_SYSTEM) ||
+ (eLanguage == LANGUAGE_DONTKNOW) )
+ eLanguage = System::GetLanguage();
+ USHORT nLanguage = (USHORT) eLanguage;
+ (*((SetLanguagePtr)fpSetLanguage))( nLanguage );
+ }
+
+ // Module in die Collection aufnehmen
+ ModuleData* pModuleData = new ModuleData(aModuleName, pLib);
+ aModuleCollection.Insert(pModuleData);
+
+ // Schnittstelle initialisieren
+ AdvData pfCallBack = &ScAddInAsyncCallBack;
+ FuncData* pFuncData;
+ FuncCollection* pFuncCol = ScGlobal::GetFuncCollection();
+ USHORT nCount;
+ (*((GetFuncCountPtr)fpGetCount))(nCount);
+ for (USHORT i=0; i < nCount; i++)
+ {
+ sal_Char cFuncName[256];
+ sal_Char cInternalName[256];
+ USHORT nParamCount;
+ ParamType eParamType[MAXFUNCPARAM];
+ ParamType eAsyncType = NONE;
+ // #62113# alles initialisieren, falls das AddIn sich schlecht verhaelt
+ cFuncName[0] = 0;
+ cInternalName[0] = 0;
+ nParamCount = 0;
+ for ( USHORT j=0; j<MAXFUNCPARAM; j++ )
+ {
+ eParamType[j] = NONE;
+ }
+ (*((GetFuncDataPtr)fpGetData))(i, cFuncName, nParamCount,
+ eParamType, cInternalName);
+ if( fpIsAsync )
+ {
+ (*((IsAsync)fpIsAsync))(i, &eAsyncType);
+ if ( fpAdvice && eAsyncType != NONE )
+ (*((Advice)fpAdvice))( i, pfCallBack );
+ }
+ String aInternalName( cInternalName, osl_getThreadTextEncoding() );
+ String aFuncName( cFuncName, osl_getThreadTextEncoding() );
+ pFuncData = new FuncData( pModuleData,
+ aInternalName,
+ aFuncName,
+ i,
+ nParamCount,
+ eParamType,
+ eAsyncType );
+ pFuncCol->Insert(pFuncData);
+ }
+ bRet = TRUE;
+ }
+ else
+ delete pLib;
+ }
+ else
+ delete pLib;
+ return bRet;
+}
+
+//------------------------------------------------------------------------
+
+void ExitExternalFunc()
+{
+ USHORT nCount = aModuleCollection.GetCount();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ModuleData* pData = aModuleCollection[i];
+ pData->FreeInstance();
+ }
+}
+
+//------------------------------------------------------------------------
+
+BOOL FuncData::Call(void** ppParam)
+{
+ BOOL bRet = FALSE;
+ OModule* pLib = pModuleData->GetInstance();
+ FARPROC fProc = (FARPROC)pLib->getSymbol(aFuncName);
+ if (fProc != NULL)
+ {
+ switch (nParamCount)
+ {
+ case 1 :
+ (*((ExFuncPtr1)fProc))(ppParam[0]);
+ bRet = TRUE;
+ break;
+ case 2 :
+ (*((ExFuncPtr2)fProc))(ppParam[0], ppParam[1]);
+ bRet = TRUE;
+ break;
+ case 3 :
+ (*((ExFuncPtr3)fProc))(ppParam[0], ppParam[1], ppParam[2]);
+ bRet = TRUE;
+ break;
+ case 4 :
+ (*((ExFuncPtr4)fProc))(ppParam[0], ppParam[1], ppParam[2], ppParam[3]);
+ bRet = TRUE;
+ break;
+ case 5 :
+ (*((ExFuncPtr5)fProc))(ppParam[0], ppParam[1], ppParam[2], ppParam[3], ppParam[4]);
+ bRet = TRUE;
+ break;
+ case 6 :
+ (*((ExFuncPtr6)fProc))(ppParam[0], ppParam[1], ppParam[2], ppParam[3], ppParam[4], ppParam[5]);
+ bRet = TRUE;
+ break;
+ case 7 :
+ (*((ExFuncPtr7)fProc))( ppParam[0], ppParam[1], ppParam[2], ppParam[3], ppParam[4], ppParam[5],
+ ppParam[6]);
+ bRet = TRUE;
+ break;
+ case 8 :
+ (*((ExFuncPtr8)fProc))( ppParam[0], ppParam[1], ppParam[2], ppParam[3], ppParam[4], ppParam[5],
+ ppParam[6], ppParam[7]);
+ bRet = TRUE;
+ break;
+ case 9 :
+ (*((ExFuncPtr9)fProc))( ppParam[0], ppParam[1], ppParam[2], ppParam[3], ppParam[4], ppParam[5],
+ ppParam[6], ppParam[7], ppParam[8]);
+ bRet = TRUE;
+ break;
+ case 10 :
+ (*((ExFuncPtr10)fProc))( ppParam[0], ppParam[1], ppParam[2], ppParam[3], ppParam[4], ppParam[5],
+ ppParam[6], ppParam[7], ppParam[8], ppParam[9]);
+ bRet = TRUE;
+ break;
+ case 11 :
+ (*((ExFuncPtr11)fProc))( ppParam[0], ppParam[1], ppParam[2], ppParam[3], ppParam[4], ppParam[5],
+ ppParam[6], ppParam[7], ppParam[8], ppParam[9], ppParam[10]);
+ bRet = TRUE;
+ break;
+ case 12:
+ (*((ExFuncPtr12)fProc))( ppParam[0], ppParam[1], ppParam[2], ppParam[3], ppParam[4], ppParam[5],
+ ppParam[6], ppParam[7], ppParam[8], ppParam[9], ppParam[10], ppParam[11]);
+ bRet = TRUE;
+ break;
+ case 13:
+ (*((ExFuncPtr13)fProc))( ppParam[0], ppParam[1], ppParam[2], ppParam[3], ppParam[4], ppParam[5],
+ ppParam[6], ppParam[7], ppParam[8], ppParam[9], ppParam[10], ppParam[11],
+ ppParam[12]);
+ bRet = TRUE;
+ break;
+ case 14 :
+ (*((ExFuncPtr14)fProc))( ppParam[0], ppParam[1], ppParam[2], ppParam[3], ppParam[4], ppParam[5],
+ ppParam[6], ppParam[7], ppParam[8], ppParam[9], ppParam[10], ppParam[11],
+ ppParam[12], ppParam[13]);
+ bRet = TRUE;
+ break;
+ case 15 :
+ (*((ExFuncPtr15)fProc))( ppParam[0], ppParam[1], ppParam[2], ppParam[3], ppParam[4], ppParam[5],
+ ppParam[6], ppParam[7], ppParam[8], ppParam[9], ppParam[10], ppParam[11],
+ ppParam[12], ppParam[13], ppParam[14]);
+ bRet = TRUE;
+ break;
+ case 16 :
+ (*((ExFuncPtr16)fProc))( ppParam[0], ppParam[1], ppParam[2], ppParam[3], ppParam[4], ppParam[5],
+ ppParam[6], ppParam[7], ppParam[8], ppParam[9], ppParam[10], ppParam[11],
+ ppParam[12], ppParam[13], ppParam[14], ppParam[15]);
+ bRet = TRUE;
+ break;
+ default : break;
+ }
+ }
+ return bRet;
+}
+
+//------------------------------------------------------------------------
+
+BOOL FuncData::Advice( AdvData pfCallback )
+{
+ BOOL bRet = FALSE;
+ OModule* pLib = pModuleData->GetInstance();
+ FARPROC fProc = (FARPROC)pLib->getSymbol(LIBFUNCNAME(ADVICE));
+ if (fProc != NULL)
+ {
+ ((::Advice)fProc)(nNumber, pfCallback);
+ bRet = TRUE;
+ }
+ return bRet;
+}
+
+//------------------------------------------------------------------------
+
+BOOL FuncData::Unadvice( double nHandle )
+{
+ BOOL bRet = FALSE;
+ OModule* pLib = pModuleData->GetInstance();
+ FARPROC fProc = (FARPROC)pLib->getSymbol(LIBFUNCNAME(UNADVICE));
+ if (fProc != NULL)
+ {
+ ((::Unadvice)fProc)(nHandle);
+ bRet = TRUE;
+ }
+ return bRet;
+}
+
+//------------------------------------------------------------------------
+
+const String& FuncData::GetModuleName() const
+{
+ // DBG_ASSERT( pModuleData, "Keine Arme, keine Kekse" ):
+ return pModuleData->GetName();
+}
+
+//------------------------------------------------------------------------
+
+BOOL FuncData::GetParamDesc( String& aName, String& aDesc, USHORT nParam )
+{
+ BOOL bRet = FALSE;
+ if ( nParam <= nParamCount )
+ {
+ OModule* pLib = pModuleData->GetInstance();
+ FARPROC fProc = (FARPROC) pLib->getSymbol( LIBFUNCNAME(GETPARAMDESC) );
+ if ( fProc != NULL )
+ {
+ sal_Char pcName[256];
+ sal_Char pcDesc[256];
+ *pcName = *pcDesc = 0;
+ USHORT nFuncNo = nNumber; // nicht per Reference versauen lassen..
+ ((::GetParamDesc)fProc)( nFuncNo, nParam, pcName, pcDesc );
+ aName = String( pcName, osl_getThreadTextEncoding() );
+ aDesc = String( pcDesc, osl_getThreadTextEncoding() );
+ bRet = TRUE;
+ }
+ }
+ if ( !bRet )
+ {
+ aName.Erase();
+ aDesc.Erase();
+ }
+ return bRet;
+}
+
+
diff --git a/sc/source/core/tool/cellform.cxx b/sc/source/core/tool/cellform.cxx
new file mode 100644
index 000000000000..1a25b6131900
--- /dev/null
+++ b/sc/source/core/tool/cellform.cxx
@@ -0,0 +1,272 @@
+/*************************************************************************
+ *
+ * $RCSfile: cellform.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <sfx2/objsh.hxx>
+#include <svtools/smplhint.hxx>
+#include <svtools/zforlist.hxx>
+
+#include "cellform.hxx"
+#include "cell.hxx"
+#include "compiler.hxx"
+#include "document.hxx"
+#include "sc.hrc"
+
+// STATIC DATA -----------------------------------------------------------
+
+// Err527 Workaround
+const ScFormulaCell* pLastFormulaTreeTop = 0;
+
+// -----------------------------------------------------------------------
+
+void ScCellFormat::GetString( ScBaseCell* pCell, ULONG nFormat, String& rString,
+ Color** ppColor, SvNumberFormatter& rFormatter,
+ BOOL bNullVals,
+ BOOL bFormula,
+ ScForceTextFmt eForceTextFmt )
+{
+ *ppColor = NULL;
+ if (&rFormatter==NULL)
+ {
+ rString.Erase();
+ return;
+ }
+
+ CellType eType = pCell->GetCellType();
+ switch(eType)
+ {
+ case CELLTYPE_STRING:
+ {
+ String aCellString;
+ ((ScStringCell*)pCell)->GetString( aCellString );
+ rFormatter.GetOutputString( aCellString, nFormat, rString, ppColor );
+ }
+ break;
+ case CELLTYPE_EDIT:
+ {
+ String aCellString;
+ ((ScEditCell*)pCell)->GetString( aCellString );
+ rFormatter.GetOutputString( aCellString, nFormat, rString, ppColor );
+ }
+ break;
+ case CELLTYPE_VALUE:
+ {
+ double nValue = ((ScValueCell*)pCell)->GetValue();
+ if ( !bNullVals && nValue == 0.0 )
+ rString.Erase();
+ else
+ {
+ if( eForceTextFmt == ftCheck )
+ {
+ if( nFormat && rFormatter.IsTextFormat( nFormat ) )
+ eForceTextFmt = ftForce;
+ }
+ if( eForceTextFmt == ftForce )
+ {
+ String aTemp;
+ rFormatter.GetOutputString( nValue, 0, aTemp, ppColor );
+ rFormatter.GetOutputString( aTemp, nFormat, rString, ppColor );
+ }
+ else
+ rFormatter.GetOutputString( nValue, nFormat, rString, ppColor );
+ }
+ }
+ break;
+ case CELLTYPE_FORMULA:
+ {
+ ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
+ if ( bFormula )
+ pFCell->GetFormula( rString );
+ else
+ {
+ // #62160# Ein via Interpreter gestartetes Makro, das hart
+ // auf Formelzellen zugreift, bekommt einen CellText, auch
+ // wenn dadurch ein weiterer Interpreter gestartet wird,
+ // aber nicht wenn diese Zelle gerade interpretiert wird.
+ // IdleCalc startet generell keine weiteren Interpreter,
+ // um keine Err522 (zirkulaer) zu bekommen.
+ if ( pFCell->GetDocument()->IsInInterpreter() &&
+ (!pFCell->GetDocument()->GetMacroInterpretLevel()
+ || pFCell->IsRunning()) )
+ {
+ rString.AssignAscii( RTL_CONSTASCII_STRINGPARAM("...") );
+ }
+ else
+ {
+ USHORT nErrCode = pFCell->GetErrCode();
+ if ( nErrCode == errInterpOverflow )
+ { // maxrecursion ausbuegeln, Err527 Workaround
+ ScDocument* pDoc = pFCell->GetDocument();
+ // z.B. nach Import von Fremdformaten FormulaTree
+ // aufbauen
+ if ( !pDoc->IsInFormulaTree( pFCell ) )
+ pFCell->SetDirty();
+ if ( pDoc->GetAutoCalc()
+ && !pDoc->GetHardRecalcState()
+ && pLastFormulaTreeTop != pDoc->GetFormulaTree() )
+ {
+ pLastFormulaTreeTop = pDoc->GetFormulaTree();
+ // ohne ProgressBar falls fehlendes Repaint:
+ // pDoc->CalcFormulaTree( FALSE, TRUE );
+ //! austesten
+ pDoc->CalcFormulaTree( FALSE, FALSE );
+ nErrCode = pFCell->GetErrCode();
+ if ( nErrCode != errInterpOverflow )
+ { // von hinten durch die Brust ins Auge ...
+ pDoc->GetDocumentShell()->Broadcast( SfxSimpleHint( FID_DATACHANGED ) );
+ pDoc->ResetChanged( ScRange(0,0,0,MAXCOL,MAXROW,MAXTAB) );
+ }
+ }
+ }
+
+ // erst nach dem Interpretieren (GetErrCode) das Zahlformat holen:
+ if ( (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
+ nFormat = pFCell->GetStandardFormat( rFormatter,
+ nFormat );
+
+ if (nErrCode != 0)
+ rString = ScGlobal::GetErrorString(nErrCode);
+ else if ( pFCell->IsValue() )
+ {
+ double fValue = pFCell->GetValue();
+ if ( !bNullVals && fValue == 0.0 )
+ rString.Erase();
+ else
+ rFormatter.GetOutputString( fValue, nFormat, rString, ppColor );
+ }
+ else
+ {
+ String aCellString;
+ pFCell->GetString( aCellString );
+ rFormatter.GetOutputString( aCellString, nFormat, rString, ppColor );
+ }
+ }
+ }
+ }
+ break;
+ default:
+ rString.Erase();
+ break;
+ }
+}
+
+void ScCellFormat::GetInputString( ScBaseCell* pCell, ULONG nFormat, String& rString,
+ SvNumberFormatter& rFormatter )
+{
+ if (&rFormatter==NULL)
+ {
+ rString.Erase();
+ return;
+ }
+
+ CellType eType = pCell->GetCellType();
+ switch(eType)
+ {
+ case CELLTYPE_STRING:
+ {
+ ((ScStringCell*)pCell)->GetString( rString );
+ }
+ break;
+ case CELLTYPE_EDIT:
+ {
+ ((ScEditCell*)pCell)->GetString( rString );
+ }
+ break;
+ case CELLTYPE_VALUE:
+ {
+ double nValue = ((ScValueCell*)pCell)->GetValue();
+ rFormatter.GetInputLineString( nValue, nFormat, rString );
+ }
+ break;
+ case CELLTYPE_FORMULA:
+ {
+ if (((ScFormulaCell*)pCell)->IsValue())
+ {
+ double nValue = ((ScFormulaCell*)pCell)->GetValue();
+ rFormatter.GetInputLineString( nValue, nFormat, rString );
+ }
+ else
+ {
+ ((ScFormulaCell*)pCell)->GetString( rString );
+ }
+
+ USHORT nErrCode = ((ScFormulaCell*)pCell)->GetErrCode();
+ if (nErrCode != 0)
+ {
+ rString.Erase();
+ }
+ }
+ break;
+ default:
+ rString.Erase();
+ break;
+ }
+}
+
+
+
diff --git a/sc/source/core/tool/chartarr.cxx b/sc/source/core/tool/chartarr.cxx
new file mode 100644
index 000000000000..a83adae60e66
--- /dev/null
+++ b/sc/source/core/tool/chartarr.cxx
@@ -0,0 +1,1394 @@
+/*************************************************************************
+ *
+ * $RCSfile: chartarr.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <svtools/intitem.hxx>
+#include <svtools/zforlist.hxx>
+#include <sch/schdll.hxx>
+#include <sch/memchrt.hxx>
+#include <float.h> // DBL_MIN
+
+#include "chartarr.hxx"
+#include "document.hxx"
+#include "rechead.hxx"
+#include "globstr.hrc"
+#include "cell.hxx"
+#include "docoptio.hxx"
+
+#ifndef _COM_SUN_STAR_CHART_CHARTSERIESADDRESS_HPP_
+#include <com/sun/star/chart/ChartSeriesAddress.hpp>
+#endif
+
+
+// -----------------------------------------------------------------------
+
+// static
+void ScChartArray::CopySettings( SchMemChart& rDest, const SchMemChart& rSource )
+{
+ rDest.SetMainTitle( rSource.GetMainTitle() );
+ rDest.SetSubTitle( rSource.GetSubTitle() );
+ rDest.SetXAxisTitle( rSource.GetXAxisTitle() );
+ rDest.SetYAxisTitle( rSource.GetYAxisTitle() );
+ rDest.SetZAxisTitle( rSource.GetZAxisTitle() );
+
+ const long* pArr;
+ if ( rSource.GetRowCount() == rDest.GetRowCount() &&
+ rSource.GetColCount() == rDest.GetColCount() )
+ {
+ // don't copy column/row number formats here (are set in new MemChart object)
+
+ if ( (pArr = rSource.GetRowTranslation()) ) rDest.SetRowTranslation( pArr );
+ if ( (pArr = rSource.GetColTranslation()) ) rDest.SetColTranslation( pArr );
+ rDest.SetTranslation( rSource.GetTranslation() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ScChartArray::ScChartArray( ScDocument* pDoc, USHORT nTab,
+ USHORT nStartCol, USHORT nStartRow, USHORT nEndCol, USHORT nEndRow,
+ const String& rChartName ) :
+ aName( rChartName ),
+ pDocument( pDoc ),
+ pPositionMap( NULL ),
+ eGlue( SC_CHARTGLUE_NA ),
+ nStartCol(0),
+ nStartRow(0),
+ bColHeaders( FALSE ),
+ bRowHeaders( FALSE ),
+ bDummyUpperLeft( FALSE ),
+ bValid( TRUE )
+{
+ SetRangeList( ScRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab ) );
+ CheckColRowHeaders();
+}
+
+ScChartArray::ScChartArray( ScDocument* pDoc, const ScRangeListRef& rRangeList,
+ const String& rChartName ) :
+ aRangeListRef( rRangeList ),
+ aName( rChartName ),
+ pDocument( pDoc ),
+ pPositionMap( NULL ),
+ eGlue( SC_CHARTGLUE_NA ),
+ nStartCol(0),
+ nStartRow(0),
+ bColHeaders( FALSE ),
+ bRowHeaders( FALSE ),
+ bDummyUpperLeft( FALSE ),
+ bValid( TRUE )
+{
+ if ( aRangeListRef.Is() )
+ CheckColRowHeaders();
+}
+
+ScChartArray::ScChartArray( const ScChartArray& rArr ) :
+ aRangeListRef( rArr.aRangeListRef ),
+ aName(rArr.aName),
+ pDocument(rArr.pDocument),
+ pPositionMap( NULL ),
+ eGlue(rArr.eGlue),
+ nStartCol(rArr.nStartCol),
+ nStartRow(rArr.nStartRow),
+ bColHeaders(rArr.bColHeaders),
+ bRowHeaders(rArr.bRowHeaders),
+ bDummyUpperLeft( rArr.bDummyUpperLeft ),
+ bValid(rArr.bValid)
+{
+}
+
+ScChartArray::ScChartArray( ScDocument* pDoc, SvStream& rStream, ScMultipleReadHeader& rHdr ) :
+ pDocument( pDoc ),
+ pPositionMap( NULL ),
+ eGlue( SC_CHARTGLUE_NONE ),
+ bDummyUpperLeft( FALSE ),
+ bValid( TRUE )
+{
+ USHORT nCol2, nRow2, nTable;
+
+ rHdr.StartEntry();
+
+ rStream >> nTable;
+ rStream >> nStartCol;
+ rStream >> nStartRow;
+ rStream >> nCol2;
+ rStream >> nRow2;
+ rStream.ReadByteString( aName, rStream.GetStreamCharSet() );
+ rStream >> bColHeaders;
+ rStream >> bRowHeaders;
+
+ rHdr.EndEntry();
+
+ SetRangeList( ScRange( nStartCol, nStartRow, nTable, nCol2, nRow2, nTable ) );
+}
+
+ScChartArray::ScChartArray( ScDocument* pDoc, const SchMemChart& rData ) :
+ pDocument( pDoc ),
+ pPositionMap( NULL )
+{
+ const sal_Unicode cTok = ';';
+ BOOL bInitOk = FALSE;
+ xub_StrLen nToken;
+ String aPos = ((SchMemChart&)rData).SomeData1();
+ if ( (nToken = aPos.GetTokenCount( cTok )) >= 5)
+ {
+ String aOpt = ((SchMemChart&)rData).SomeData2();
+ xub_StrLen nOptToken = aOpt.GetTokenCount( cTok );
+ BOOL bNewChart = (nOptToken >= 4); // ab 341/342
+ aRangeListRef.Clear();
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ xub_StrLen nInd = 0;
+ for ( xub_StrLen j=0; j < nToken; j+=5 )
+ {
+ xub_StrLen nInd2 = nInd;
+ nTab1 = (USHORT) aPos.GetToken( 0, cTok, nInd ).ToInt32();
+ // damit alte Versionen (<341/342) das ueberlesen ist der nTab2
+ // Token Separator ein ','
+ if ( bNewChart )
+ nTab2 = (USHORT) aPos.GetToken( 1, ',', nInd2 ).ToInt32();
+ else
+ nTab2 = nTab1;
+ nCol1 = (USHORT) aPos.GetToken( 0, cTok, nInd ).ToInt32();
+ nRow1 = (USHORT) aPos.GetToken( 0, cTok, nInd ).ToInt32();
+ nCol2 = (USHORT) aPos.GetToken( 0, cTok, nInd ).ToInt32();
+ nRow2 = (USHORT) aPos.GetToken( 0, cTok, nInd ).ToInt32();
+ AddToRangeList( ScRange( nCol1, nRow1, nTab1,
+ nCol2, nRow2, nTab2 ) );
+ }
+ bValid = TRUE;
+
+ if (aOpt.Len() >= 2)
+ {
+ bColHeaders = ( aOpt.GetChar(0) != '0' );
+ bRowHeaders = ( aOpt.GetChar(1) != '0' );
+ if ( aOpt.Len() >= 3 )
+ {
+ if ( bNewChart )
+ {
+ bDummyUpperLeft = ( aOpt.GetChar(2) != '0' );
+ xub_StrLen nInd = 4; // 111;
+ eGlue = (ScChartGlue) aOpt.GetToken( 0, cTok, nInd ).ToInt32();
+ nStartCol = (USHORT) aOpt.GetToken( 0, cTok, nInd ).ToInt32();
+ nStartRow = (USHORT) aOpt.GetToken( 0, cTok, nInd ).ToInt32();
+ bInitOk = TRUE;
+ }
+ }
+ }
+ else
+ bColHeaders = bRowHeaders = FALSE;
+ }
+ else
+ {
+ SetRangeList( ScRange() );
+ bColHeaders = bRowHeaders = bValid = FALSE;
+ }
+ if ( !bInitOk )
+ { // muessen in GlueState neu berechnet werden
+ InvalidateGlue();
+ nStartCol = nStartRow = 0;
+ bDummyUpperLeft = FALSE;
+ }
+}
+
+ScChartArray::~ScChartArray()
+{
+ delete pPositionMap;
+}
+
+DataObject* ScChartArray::Clone() const
+{
+ return new ScChartArray(*this);
+}
+
+BOOL ScChartArray::operator==(const ScChartArray& rCmp) const
+{
+ return bColHeaders == rCmp.bColHeaders
+ && bRowHeaders == rCmp.bRowHeaders
+ && aName == rCmp.aName
+ && *aRangeListRef == *rCmp.aRangeListRef;
+}
+
+BOOL ScChartArray::IsAtCursor(const ScAddress& rPos) const
+{
+ for ( ScRangePtr pR = aRangeListRef->First(); pR;
+ pR = aRangeListRef->Next() )
+ {
+ if ( pR->In( rPos ) )
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void ScChartArray::SetRangeList( const ScRange& rRange )
+{
+ aRangeListRef = new ScRangeList(); // handelt auch ReleaseRef / AddRef
+ aRangeListRef->Append( rRange );
+ InvalidateGlue();
+}
+
+void ScChartArray::AddToRangeList( const ScRange& rRange )
+{
+ if ( aRangeListRef.Is() )
+ aRangeListRef->Append( rRange );
+ else
+ SetRangeList( rRange );
+ InvalidateGlue();
+}
+
+void ScChartArray::AddToRangeList( const ScRangeListRef& rAdd )
+{
+ if ( aRangeListRef.Is() )
+ {
+ ULONG nCount = rAdd->Count();
+ for (ULONG i=0; i<nCount; i++)
+ aRangeListRef->Join( *rAdd->GetObject(i) );
+ }
+ else
+ SetRangeList( rAdd );
+ InvalidateGlue();
+}
+
+void ScChartArray::GlueState()
+{
+ if ( eGlue != SC_CHARTGLUE_NA )
+ return;
+ bDummyUpperLeft = FALSE;
+ ScRangePtr pR;
+ if ( aRangeListRef->Count() <= 1 )
+ {
+ if ( pR = aRangeListRef->First() )
+ {
+ if ( pR->aStart.Tab() == pR->aEnd.Tab() )
+ eGlue = SC_CHARTGLUE_NONE;
+ else
+ eGlue = SC_CHARTGLUE_COLS; // mehrere Tabellen spaltenweise
+ nStartCol = pR->aStart.Col();
+ nStartRow = pR->aStart.Row();
+ }
+ else
+ {
+ InvalidateGlue();
+ nStartCol = nStartRow = 0;
+ }
+ return;
+ }
+ ULONG nOldPos = aRangeListRef->GetCurPos();
+
+ pR = aRangeListRef->First();
+ nStartCol = pR->aStart.Col();
+ nStartRow = pR->aStart.Row();
+ USHORT nMaxCols, nMaxRows, nEndCol, nEndRow;
+ nMaxCols = nMaxRows = nEndCol = nEndRow = 0;
+ do
+ { // umspannenden Bereich etc. feststellen
+ USHORT nTmp, n1, n2;
+ if ( (n1 = pR->aStart.Col()) < nStartCol )
+ nStartCol = n1;
+ if ( (n2 = pR->aEnd.Col()) > nEndCol )
+ nEndCol = n2;
+ if ( (nTmp = n2 - n1 + 1) > nMaxCols )
+ nMaxCols = nTmp;
+ if ( (n1 = pR->aStart.Row()) < nStartRow )
+ nStartRow = n1;
+ if ( (n2 = pR->aEnd.Row()) > nEndRow )
+ nEndRow = n2;
+ if ( (nTmp = n2 - n1 + 1) > nMaxRows )
+ nMaxRows = nTmp;
+ } while ( pR = aRangeListRef->Next() );
+ USHORT nC = nEndCol - nStartCol + 1;
+ if ( nC == 1 )
+ {
+ eGlue = SC_CHARTGLUE_ROWS;
+ return;
+ }
+ USHORT nR = nEndRow - nStartRow + 1;
+ if ( nR == 1 )
+ {
+ eGlue = SC_CHARTGLUE_COLS;
+ return;
+ }
+ ULONG nCR = (ULONG)nC * nR;
+//2do:
+/*
+ Erstmal simpel ohne Bitmaskiererei, maximal koennten so 8MB alloziert
+ werden (256 Cols mal 32000 Rows), das liesse sich mit 2 Bit je Eintrag
+ auf 2MB reduzieren, andererseits ist es so schneller.
+ Weitere Platz-Optimierung waere, in dem Array nur die wirklich benutzten
+ Zeilen/Spalten abzulegen, wuerde aber ein weiteres durchlaufen der
+ RangeList und indirekten Zugriff auf das Array bedeuten.
+ */
+ const BYTE nHole = 0;
+ const BYTE nOccu = 1;
+ const BYTE nFree = 2;
+ const BYTE nGlue = 3;
+#ifdef WIN
+ // we hate 16bit, don't we?
+ BYTE huge* p;
+ BYTE huge* pA = (BYTE huge*) SvMemAlloc( nCR );
+ if ( nCR > (ULONG)((USHORT)~0) )
+ { // in 32k Bloecken initialisieren
+ ULONG j;
+ for ( j=0; j<nCR; j+=0x8000 )
+ {
+ memset( pA+j, nHole, Min( (ULONG)0x8000, nCR-j ) );
+ }
+ }
+ else
+ memset( pA, nHole, nCR * sizeof(BYTE) );
+#else
+ BYTE* p;
+ BYTE* pA = new BYTE[ nCR ];
+ memset( pA, 0, nCR * sizeof(BYTE) );
+#endif
+
+ USHORT nCol, nRow, nCol1, nRow1, nCol2, nRow2;
+ for ( pR = aRangeListRef->First(); pR; pR = aRangeListRef->Next() )
+ { // Selektionen 2D als belegt markieren
+ nCol1 = pR->aStart.Col() - nStartCol;
+ nCol2 = pR->aEnd.Col() - nStartCol;
+ nRow1 = pR->aStart.Row() - nStartRow;
+ nRow2 = pR->aEnd.Row() - nStartRow;
+ for ( nCol = nCol1; nCol <= nCol2; nCol++ )
+ {
+ p = pA + (ULONG)nCol * nR + nRow1;
+ for ( nRow = nRow1; nRow <= nRow2; nRow++, p++ )
+ *p = nOccu;
+ }
+ }
+ BOOL bGlue = TRUE;
+
+ BOOL bGlueCols = FALSE;
+ for ( nCol = 0; bGlue && nCol < nC; nCol++ )
+ { // Spalten probieren durchzugehen und als frei markieren
+ p = pA + (ULONG)nCol * nR;
+ for ( nRow = 0; bGlue && nRow < nR; nRow++, p++ )
+ {
+ if ( *p == nOccu )
+ { // Wenn einer mittendrin liegt ist keine Zusammenfassung
+ // moeglich. Am Rand koennte ok sein, wenn in dieser Spalte
+ // in jeder belegten Zeile einer belegt ist.
+ if ( nRow > 0 && nCol > 0 )
+ bGlue = FALSE; // nCol==0 kann DummyUpperLeft sein
+ else
+ nRow = nR;
+ }
+ else
+ *p = nFree;
+ }
+ if ( bGlue && *(p = (pA + ((((ULONG)nCol+1) * nR) - 1))) == nFree )
+ { // Spalte als komplett frei markieren
+ *p = nGlue;
+ bGlueCols = TRUE; // mindestens eine freie Spalte
+ }
+ }
+
+ BOOL bGlueRows = FALSE;
+ for ( nRow = 0; bGlue && nRow < nR; nRow++ )
+ { // Zeilen probieren durchzugehen und als frei markieren
+ p = pA + nRow;
+ for ( nCol = 0; bGlue && nCol < nC; nCol++, p+=nR )
+ {
+ if ( *p == nOccu )
+ {
+ if ( nCol > 0 && nRow > 0 )
+ bGlue = FALSE; // nRow==0 kann DummyUpperLeft sein
+ else
+ nCol = nC;
+ }
+ else
+ *p = nFree;
+ }
+ if ( bGlue && *(p = (pA + ((((ULONG)nC-1) * nR) + nRow))) == nFree )
+ { // Zeile als komplett frei markieren
+ *p = nGlue;
+ bGlueRows = TRUE; // mindestens eine freie Zeile
+ }
+ }
+
+ // n=1: die linke obere Ecke koennte bei Beschriftung automagisch
+ // hinzugezogen werden
+ p = pA + 1;
+ for ( ULONG n = 1; bGlue && n < nCR; n++, p++ )
+ { // ein unberuehrtes Feld heisst, dass es weder spaltenweise noch
+ // zeilenweise zu erreichen war, also nichts zusamenzufassen
+ if ( *p == nHole )
+ bGlue = FALSE;
+ }
+ if ( bGlue )
+ {
+ if ( bGlueCols && bGlueRows )
+ eGlue = SC_CHARTGLUE_BOTH;
+ else if ( bGlueRows )
+ eGlue = SC_CHARTGLUE_ROWS;
+ else
+ eGlue = SC_CHARTGLUE_COLS;
+ if ( *pA != nOccu )
+ bDummyUpperLeft = TRUE;
+ }
+ else
+ {
+ eGlue = SC_CHARTGLUE_NONE;
+ }
+
+#ifdef WIN
+ SvMemFree( pA );
+#else
+ delete [] pA;
+#endif
+}
+
+void ScChartArray::CheckColRowHeaders()
+{
+ USHORT i, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+
+ BOOL bColStrings = TRUE;
+ BOOL bRowStrings = TRUE;
+ GlueState();
+ if ( aRangeListRef->Count() == 1 )
+ {
+ aRangeListRef->First()->GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ // Beschriftungen auch nach hidden Cols/Rows finden
+ while ( nCol1 <= nCol2 && (pDocument->GetColFlags(
+ nCol1, nTab1) & CR_HIDDEN) != 0 )
+ nCol1++;
+ while ( nRow1 <= nRow2 && (pDocument->GetRowFlags(
+ nRow1, nTab1) & CR_HIDDEN) != 0 )
+ nRow1++;
+ if ( nCol1 > nCol2 || nRow1 > nRow2 )
+ bColStrings = bRowStrings = FALSE;
+ else
+ {
+ for (i=nCol1; i<=nCol2 && bColStrings; i++)
+ {
+ if ( i==nCol1 || (pDocument->GetColFlags( i, nTab1) & CR_HIDDEN) == 0 )
+ if (pDocument->HasValueData( i, nRow1, nTab1 ))
+ bColStrings = FALSE;
+ }
+ for (i=nRow1; i<=nRow2 && bRowStrings; i++)
+ {
+ if ( i==nRow1 || (pDocument->GetRowFlags( i, nTab1) & CR_HIDDEN) == 0 )
+ if (pDocument->HasValueData( nCol1, i, nTab1 ))
+ bRowStrings = FALSE;
+ }
+ }
+ }
+ else
+ {
+ BOOL bVert = (eGlue == SC_CHARTGLUE_NONE || eGlue == SC_CHARTGLUE_ROWS);
+ for ( ScRangePtr pR = aRangeListRef->First();
+ pR && (bColStrings || bRowStrings);
+ pR = aRangeListRef->Next() )
+ {
+ pR->GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ BOOL bTopRow = (nRow1 == nStartRow);
+ BOOL bHidOk;
+ if ( bRowStrings && (bVert || nCol1 == nStartCol) )
+ { // NONE oder ROWS: RowStrings in jeder Selektion moeglich
+ // COLS oder BOTH: nur aus der ersten Spalte
+ while ( nCol1 <= nCol2 && (pDocument->GetColFlags(
+ nCol1, nTab1) & CR_HIDDEN) != 0 )
+ nCol1++;
+ while ( nRow1 <= nRow2 && (pDocument->GetRowFlags(
+ nRow1, nTab1) & CR_HIDDEN) != 0 )
+ nRow1++;
+ if ( nCol1 <= nCol2 )
+ for (i=nRow1; i<=nRow2 && bRowStrings; i++)
+ {
+ if ( i==nRow1 || (pDocument->GetRowFlags( i, nTab1) & CR_HIDDEN) == 0 )
+ if (pDocument->HasValueData( nCol1, i, nTab1 ))
+ bRowStrings = FALSE;
+ }
+ bHidOk = TRUE;
+ }
+ else
+ bHidOk = FALSE;
+ if ( bColStrings && bTopRow )
+ { // ColStrings nur aus der ersten Zeile
+ if ( !bHidOk )
+ {
+ while ( nCol1 <= nCol2 && (pDocument->GetColFlags(
+ nCol1, nTab1) & CR_HIDDEN) != 0 )
+ nCol1++;
+ while ( nRow1 <= nRow2 && (pDocument->GetRowFlags(
+ nRow1, nTab1) & CR_HIDDEN) != 0 )
+ nRow1++;
+ }
+ if ( nRow1 <= nRow2 )
+ for (i=nCol1; i<=nCol2 && bColStrings; i++)
+ {
+ if ( i==nCol1 || (pDocument->GetColFlags( i, nTab1) & CR_HIDDEN) == 0 )
+ if (pDocument->HasValueData( i, nRow1, nTab1 ))
+ bColStrings = FALSE;
+ }
+ }
+ }
+ }
+ bColHeaders = bColStrings;
+ bRowHeaders = bRowStrings;
+}
+
+#ifdef WNT
+#pragma optimize("",off)
+#endif
+
+SchMemChart* ScChartArray::CreateMemChart()
+{
+ ULONG nCount = aRangeListRef->Count();
+ if ( nCount > 1 )
+ return CreateMemChartMulti();
+ else if ( nCount == 1 )
+ {
+ ScRange* pR = aRangeListRef->First();
+ if ( pR->aStart.Tab() != pR->aEnd.Tab() )
+ return CreateMemChartMulti();
+ else
+ return CreateMemChartSingle();
+ }
+ else
+ return CreateMemChartMulti(); // kann 0 Range besser ab als Single
+}
+
+SchMemChart* ScChartArray::CreateMemChartSingle() const
+{
+ USHORT i,nCol,nRow;
+
+ //
+ // wirkliche Groesse (ohne versteckte Zeilen/Spalten)
+ //
+
+ USHORT nColAdd = bRowHeaders ? 1 : 0;
+ USHORT nRowAdd = bColHeaders ? 1 : 0;
+
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ aRangeListRef->First()->GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+
+ USHORT nStrCol = nCol1; // fuer Beschriftung merken
+ USHORT nStrRow = nRow1;
+ // Beschriftungen auch nach HiddenCols finden
+ while ( (pDocument->GetColFlags( nCol1, nTab1) & CR_HIDDEN) != 0 )
+ nCol1++;
+ while ( (pDocument->GetRowFlags( nRow1, nTab1) & CR_HIDDEN) != 0 )
+ nRow1++;
+ // falls alles hidden ist, bleibt die Beschriftung am Anfang
+ if ( nCol1 <= nCol2 )
+ {
+ nStrCol = nCol1;
+ nCol1 += nColAdd;
+ }
+ if ( nRow1 <= nRow2 )
+ {
+ nStrRow = nRow1;
+ nRow1 += nRowAdd;
+ }
+
+ USHORT nTotalCols = ( nCol1 <= nCol2 ? nCol2 - nCol1 + 1 : 0 );
+ USHORT* pCols = new USHORT[nTotalCols ? nTotalCols : 1];
+ USHORT nColCount = 0;
+ for (i=0; i<nTotalCols; i++)
+ if ((pDocument->GetColFlags(nCol1+i,nTab1)&CR_HIDDEN)==0)
+ pCols[nColCount++] = nCol1+i;
+
+ USHORT nTotalRows = ( nRow1 <= nRow2 ? nRow2 - nRow1 + 1 : 0 );
+ USHORT* pRows = new USHORT[nTotalRows ? nTotalRows : 1];
+ USHORT nRowCount = 0;
+ for (i=0; i<nTotalRows; i++)
+ if ((pDocument->GetRowFlags(nRow1+i,nTab1)&CR_HIDDEN)==0)
+ pRows[nRowCount++] = nRow1+i;
+
+ BOOL bValidData = TRUE;
+ if ( !nColCount )
+ {
+ bValidData = FALSE;
+ nColCount = 1;
+ pCols[0] = nStrCol;
+ }
+ if ( !nRowCount )
+ {
+ bValidData = FALSE;
+ nRowCount = 1;
+ pRows[0] = nStrRow;
+ }
+
+ //
+ // Daten
+ //
+
+ SchMemChart* pMemChart = SchDLL::NewMemChart( nColCount, nRowCount );
+ if (pMemChart)
+ {
+ ScRangeListRef xRL = new ScRangeList;
+ SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
+ pMemChart->SetNumberFormatter( pFormatter );
+ if ( bValidData )
+ {
+ com::sun::star::uno::Sequence<
+ com::sun::star::chart::ChartSeriesAddress > aSeriesSeq( nColCount );
+ BOOL bCalcAsShown = pDocument->GetDocOptions().IsCalcAsShown();
+ ScBaseCell* pCell;
+ for (nCol=0; nCol<nColCount; nCol++)
+ {
+ xRL->RemoveAll();
+ for (nRow=0; nRow<nRowCount; nRow++)
+ {
+ xRL->Join( ScAddress( pCols[nCol], pRows[nRow], nTab1 ) );
+
+ double nVal = DBL_MIN; // Hack fuer Chart, um leere Zellen zu erkennen
+
+ pDocument->GetCell( pCols[nCol], pRows[nRow], nTab1, pCell );
+ if (pCell)
+ {
+ CellType eType = pCell->GetCellType();
+ if (eType == CELLTYPE_VALUE)
+ {
+ nVal = ((ScValueCell*)pCell)->GetValue();
+ if ( bCalcAsShown && nVal != 0.0 )
+ {
+ ULONG nFormat;
+ pDocument->GetNumberFormat( pCols[nCol],
+ pRows[nRow], nTab1, nFormat );
+ nVal = pDocument->RoundValueAsShown( nVal, nFormat );
+ }
+ }
+ else if (eType == CELLTYPE_FORMULA)
+ {
+ ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
+ if ( (pFCell->GetErrCode() == 0) && pFCell->IsValue() )
+ nVal = pFCell->GetValue();
+ }
+ }
+ pMemChart->SetData(nCol, nRow, nVal);
+ }
+ com::sun::star::chart::ChartSeriesAddress aSeries;
+ String aStr;
+ xRL->Format( aStr, SCR_ABS_3D, pDocument );
+ aSeries.DataRangeAddress = aStr;
+ if ( bColHeaders )
+ {
+ ScAddress aAddr( pCols[nCol], nStrRow, nTab1 );
+ aAddr.Format( aStr, SCR_ABS_3D, pDocument );
+ aSeries.LabelAddress = aStr;
+ }
+ aSeriesSeq[nCol] = aSeries;
+ }
+ pMemChart->SetSeriesAddresses( aSeriesSeq );
+ }
+ else
+ {
+ //! Flag, dass Daten ungueltig ??
+
+ for (nCol=0; nCol<nColCount; nCol++)
+ for (nRow=0; nRow<nRowCount; nRow++)
+ pMemChart->SetData( nCol, nRow, DBL_MIN );
+ }
+
+ //
+ // Spalten-Header
+ //
+
+ for (nCol=0; nCol<nColCount; nCol++)
+ {
+ String aString;
+ if (bColHeaders)
+ pDocument->GetString( pCols[nCol], nStrRow, nTab1, aString );
+ if ( !aString.Len() )
+ {
+ aString = ScGlobal::GetRscString(STR_COLUMN);
+ aString += ' ';
+ aString += String::CreateFromInt32( pCols[nCol]+1 );
+ }
+ pMemChart->SetColText(nCol, aString);
+
+ ULONG nNumberAttr = pDocument->GetNumberFormat( ScAddress(
+ pCols[nCol], nRow1, nTab1 ) );
+ pMemChart->SetNumFormatIdCol( nCol, nNumberAttr );
+ }
+
+ //
+ // Zeilen-Header
+ //
+
+ xRL->RemoveAll();
+ for (nRow=0; nRow<nRowCount; nRow++)
+ {
+ String aString;
+ if (bRowHeaders)
+ {
+ ScAddress aAddr( nStrCol, pRows[nRow], nTab1 );
+ xRL->Join( aAddr );
+ pDocument->GetString( nStrCol, pRows[nRow], nTab1, aString );
+ }
+ if ( !aString.Len() )
+ {
+ aString = ScGlobal::GetRscString(STR_ROW);
+ aString += ' ';
+ aString += String::CreateFromInt32( pRows[nRow]+1 );
+ }
+ pMemChart->SetRowText(nRow, aString);
+
+ ULONG nNumberAttr = pDocument->GetNumberFormat( ScAddress(
+ nCol1, pRows[nRow], nTab1 ) );
+ pMemChart->SetNumFormatIdRow( nRow, nNumberAttr );
+ }
+ String aCategoriesStr;
+ xRL->Format( aCategoriesStr, SCR_ABS_3D, pDocument );
+ pMemChart->SetCategoriesRangeAddress( aCategoriesStr );
+
+ //
+ // Titel
+ //
+
+ pMemChart->SetMainTitle(ScGlobal::GetRscString(STR_CHART_MAINTITLE));
+ pMemChart->SetSubTitle(ScGlobal::GetRscString(STR_CHART_SUBTITLE));
+ pMemChart->SetXAxisTitle(ScGlobal::GetRscString(STR_CHART_XTITLE));
+ pMemChart->SetYAxisTitle(ScGlobal::GetRscString(STR_CHART_YTITLE));
+ pMemChart->SetZAxisTitle(ScGlobal::GetRscString(STR_CHART_ZTITLE));
+
+ //
+ // Zahlen-Typ
+ //
+
+ ULONG nNumberAttr = pDocument->GetNumberFormat( ScAddress(
+ nCol1, nRow1, nTab1 ) );
+ if (pFormatter)
+ pMemChart->SetDataType(pFormatter->GetType( nNumberAttr ));
+
+ //
+ // Parameter-Strings
+ //
+
+ SetExtraStrings(*pMemChart);
+ }
+ else
+ DBG_ERROR("SchDLL::NewMemChart gibt 0 zurueck!");
+
+ // Aufraeumen
+
+ delete[] pRows;
+ delete[] pCols;
+
+ return pMemChart;
+}
+
+SchMemChart* ScChartArray::CreateMemChartMulti()
+{
+ CreatePositionMap();
+ USHORT nColCount = pPositionMap->GetColCount();
+ USHORT nRowCount = pPositionMap->GetRowCount();
+
+ USHORT nCol, nRow;
+
+ //
+ // Daten
+ //
+
+ SchMemChart* pMemChart = SchDLL::NewMemChart( nColCount, nRowCount );
+ if (pMemChart)
+ {
+ ScRangeListRef xRL = new ScRangeList;
+ com::sun::star::uno::Sequence<
+ com::sun::star::chart::ChartSeriesAddress > aSeriesSeq( nColCount );
+ pMemChart->SetNumberFormatter( pDocument->GetFormatTable() );
+ BOOL bCalcAsShown = pDocument->GetDocOptions().IsCalcAsShown();
+ ULONG nIndex = 0;
+ for ( nCol = 0; nCol < nColCount; nCol++ )
+ {
+ xRL->RemoveAll();
+ for ( nRow = 0; nRow < nRowCount; nRow++, nIndex++ )
+ {
+ double nVal = DBL_MIN; // Hack fuer Chart, um leere Zellen zu erkennen
+ const ScAddress* pPos = pPositionMap->GetPosition( nIndex );
+ if ( pPos )
+ { // sonst: Luecke
+ xRL->Join( *pPos );
+ ScBaseCell* pCell = pDocument->GetCell( *pPos );
+ if (pCell)
+ {
+ CellType eType = pCell->GetCellType();
+ if (eType == CELLTYPE_VALUE)
+ {
+ nVal = ((ScValueCell*)pCell)->GetValue();
+ if ( bCalcAsShown && nVal != 0.0 )
+ {
+ ULONG nFormat = pDocument->GetNumberFormat( *pPos );
+ nVal = pDocument->RoundValueAsShown( nVal, nFormat );
+ }
+ }
+ else if (eType == CELLTYPE_FORMULA)
+ {
+ ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
+ if ( (pFCell->GetErrCode() == 0) && pFCell->IsValue() )
+ nVal = pFCell->GetValue();
+ }
+ }
+ }
+ pMemChart->SetData(nCol, nRow, nVal);
+ }
+ com::sun::star::chart::ChartSeriesAddress aSeries;
+ String aStr;
+ xRL->Format( aStr, SCR_ABS_3D, pDocument );
+ aSeries.DataRangeAddress = aStr;
+ if ( bColHeaders )
+ {
+ const ScAddress* pPos = pPositionMap->GetColHeaderPosition( nCol );
+ if ( pPos )
+ {
+ pPos->Format( aStr, SCR_ABS_3D, pDocument );
+ aSeries.LabelAddress = aStr;
+ }
+ }
+ aSeriesSeq[nCol] = aSeries;
+ }
+ pMemChart->SetSeriesAddresses( aSeriesSeq );
+
+//2do: Beschriftung bei Luecken
+
+ //
+ // Spalten-Header
+ //
+
+ USHORT nPosCol = 0;
+ for ( nCol = 0; nCol < nColCount; nCol++ )
+ {
+ String aString;
+ const ScAddress* pPos = pPositionMap->GetColHeaderPosition( nCol );
+ if ( bColHeaders && pPos )
+ pDocument->GetString(
+ pPos->Col(), pPos->Row(), pPos->Tab(), aString );
+ if ( !aString.Len() )
+ {
+ aString = ScGlobal::GetRscString(STR_COLUMN);
+ aString += ' ';
+ if ( pPos )
+ nPosCol = pPos->Col() + 1;
+ else
+ nPosCol++;
+ aString += String::CreateFromInt32( nPosCol );
+ }
+ pMemChart->SetColText(nCol, aString);
+
+ ULONG nNumberAttr = 0;
+ pPos = pPositionMap->GetPosition( nCol, 0 );
+ if ( pPos )
+ nNumberAttr = pDocument->GetNumberFormat( *pPos );
+ pMemChart->SetNumFormatIdCol( nCol, nNumberAttr );
+ }
+
+ //
+ // Zeilen-Header
+ //
+
+ xRL->RemoveAll();
+ USHORT nPosRow = 0;
+ for ( nRow = 0; nRow < nRowCount; nRow++ )
+ {
+ String aString;
+ const ScAddress* pPos = pPositionMap->GetRowHeaderPosition( nRow );
+ if ( bRowHeaders && pPos )
+ {
+ xRL->Join( *pPos );
+ pDocument->GetString(
+ pPos->Col(), pPos->Row(), pPos->Tab(), aString );
+ }
+ if ( !aString.Len() )
+ {
+ aString = ScGlobal::GetRscString(STR_ROW);
+ aString += ' ';
+ if ( pPos )
+ nPosRow = pPos->Row() + 1;
+ else
+ nPosRow++;
+ aString += String::CreateFromInt32( nPosRow );
+ }
+ pMemChart->SetRowText(nRow, aString);
+
+ ULONG nNumberAttr = 0;
+ pPos = pPositionMap->GetPosition( 0, nRow );
+ if ( pPos )
+ nNumberAttr = pDocument->GetNumberFormat( *pPos );
+ pMemChart->SetNumFormatIdRow( nRow, nNumberAttr );
+ }
+ String aCategoriesStr;
+ xRL->Format( aCategoriesStr, SCR_ABS_3D, pDocument );
+ pMemChart->SetCategoriesRangeAddress( aCategoriesStr );
+
+ //
+ // Titel
+ //
+
+ pMemChart->SetMainTitle(ScGlobal::GetRscString(STR_CHART_MAINTITLE));
+ pMemChart->SetSubTitle(ScGlobal::GetRscString(STR_CHART_SUBTITLE));
+ pMemChart->SetXAxisTitle(ScGlobal::GetRscString(STR_CHART_XTITLE));
+ pMemChart->SetYAxisTitle(ScGlobal::GetRscString(STR_CHART_YTITLE));
+ pMemChart->SetZAxisTitle(ScGlobal::GetRscString(STR_CHART_ZTITLE));
+
+ //
+ // Zahlen-Typ
+ //
+
+ SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
+ if (pFormatter)
+ {
+ ULONG nIndex = 0;
+ ULONG nCount = pPositionMap->GetCount();
+ const ScAddress* pPos;
+ do
+ {
+ pPos = pPositionMap->GetPosition( nIndex );
+ } while ( !pPos && ++nIndex < nCount );
+ ULONG nFormat = ( pPos ? pDocument->GetNumberFormat( *pPos ) : 0 );
+ pMemChart->SetDataType( pFormatter->GetType( nFormat ) );
+ }
+
+ //
+ // Parameter-Strings
+ //
+
+ SetExtraStrings(*pMemChart);
+ }
+ else
+ DBG_ERROR("SchDLL::NewMemChart gibt 0 zurueck!");
+
+ return pMemChart;
+}
+
+void ScChartArray::SetExtraStrings(SchMemChart& rMem) const
+{
+ const sal_Unicode cTok = ';';
+ String aRef;
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ BOOL bFirst = TRUE;
+ for ( ScRangePtr pR = aRangeListRef->First(); pR; pR = aRangeListRef->Next() )
+ {
+ pR->GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ if ( bFirst )
+ bFirst = FALSE;
+ else
+ aRef += cTok;
+ aRef += String::CreateFromInt32( nTab1 );
+ // hier ',' als TokenSep damit alte Versionen (<341/342) das ueberlesen
+ aRef += ','; aRef += String::CreateFromInt32( nTab2 );
+ aRef += cTok; aRef += String::CreateFromInt32( nCol1 );
+ aRef += cTok; aRef += String::CreateFromInt32( nRow1 );
+ aRef += cTok; aRef += String::CreateFromInt32( nCol2 );
+ aRef += cTok; aRef += String::CreateFromInt32( nRow2 );
+ }
+
+ String aFlags = bColHeaders ? '1' : '0';
+ aFlags += bRowHeaders ? '1' : '0';
+ aFlags += bDummyUpperLeft ? '1' : '0';
+ aFlags += cTok;
+ aFlags += String::CreateFromInt32( eGlue );
+ aFlags += cTok;
+ aFlags += String::CreateFromInt32( nStartCol );
+ aFlags += cTok;
+ aFlags += String::CreateFromInt32( nStartRow );
+
+ rMem.SomeData1() = aRef;
+ rMem.SomeData2() = aFlags;
+
+ rMem.SetReadOnly( TRUE ); // Daten nicht im Chart per Daten-Fenster veraendern
+}
+
+#ifdef WNT
+#pragma optimize("",on)
+#endif
+
+
+const ScChartPositionMap* ScChartArray::GetPositionMap()
+{
+ if ( !pPositionMap )
+ CreatePositionMap();
+ return pPositionMap;
+}
+
+
+void ScChartArray::CreatePositionMap()
+{
+ if ( eGlue == SC_CHARTGLUE_NA && pPositionMap )
+ {
+ delete pPositionMap;
+ pPositionMap = NULL;
+ }
+
+ if ( pPositionMap )
+ return ;
+
+ USHORT nColAdd = bRowHeaders ? 1 : 0;
+ USHORT nRowAdd = bColHeaders ? 1 : 0;
+
+ USHORT nCol, nRow, nTab, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+
+ //
+ // wirkliche Groesse (ohne versteckte Zeilen/Spalten)
+ //
+
+ USHORT nColCount, nRowCount;
+ nColCount = nRowCount = 0;
+
+ GlueState();
+
+ BOOL bNoGlue = (eGlue == SC_CHARTGLUE_NONE);
+ Table* pCols = new Table;
+ Table* pNewRowTable = new Table;
+ ScAddress* pNewAddress = new ScAddress;
+ ScRangePtr pR;
+ Table* pCol;
+ ScAddress* pPos;
+ USHORT nNoGlueRow = 0;
+ for ( pR = aRangeListRef->First(); pR; pR = aRangeListRef->Next() )
+ {
+ pR->GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ for ( nTab = nTab1; nTab <= nTab2; nTab++ )
+ {
+ // nTab im ColKey, um gleiche Col/Row in anderer Table haben zu koennen
+ ScAddress aInsCol( (bNoGlue ? 0 : nCol1), 0, nTab );
+ for ( nCol = nCol1; nCol <= nCol2; nCol++, aInsCol.IncCol() )
+ {
+ if ( (pDocument->GetColFlags( nCol, nTab) & CR_HIDDEN) == 0 )
+ {
+ ULONG nInsCol = (ULONG)(UINT32) aInsCol;
+ if ( bNoGlue || eGlue == SC_CHARTGLUE_ROWS )
+ { // meistens gleiche Cols
+ if ( !(pCol = (Table*) pCols->Get( nInsCol )) )
+ {
+ pCols->Insert( nInsCol, pNewRowTable );
+ pCol = pNewRowTable;
+ pNewRowTable = new Table;
+ }
+ }
+ else
+ { // meistens neue Cols
+ if ( pCols->Insert( nInsCol, pNewRowTable ) )
+ {
+ pCol = pNewRowTable;
+ pNewRowTable = new Table;
+ }
+ else
+ pCol = (Table*) pCols->Get( nInsCol );
+ }
+ // bei anderer Tabelle wurde bereits neuer ColKey erzeugt,
+ // die Zeilen muessen fuer's Dummy fuellen gleich sein!
+ ULONG nInsRow = (bNoGlue ? nNoGlueRow : nRow1);
+ for ( nRow = nRow1; nRow <= nRow2; nRow++, nInsRow++ )
+ {
+ if ( (pDocument->GetRowFlags( nRow, nTab) & CR_HIDDEN) == 0 )
+ {
+ if ( pCol->Insert( nInsRow, pNewAddress ) )
+ {
+ pNewAddress->Set( nCol, nRow, nTab );
+ pNewAddress = new ScAddress;
+ }
+ }
+ }
+ }
+ }
+ }
+ // bei NoGlue werden zusammengehoerige Tabellen als ColGlue dargestellt
+ nNoGlueRow += nRow2 - nRow1 + 1;
+ }
+ delete pNewAddress;
+ delete pNewRowTable;
+
+ // Anzahl der Daten
+ nColCount = (USHORT) pCols->Count();
+ if ( pCol = (Table*) pCols->First() )
+ {
+ if ( bDummyUpperLeft )
+ pCol->Insert( 0, (void*)0 ); // Dummy fuer Beschriftung
+ nRowCount = (USHORT) pCol->Count();
+ }
+ else
+ nRowCount = 0;
+ if ( nColCount )
+ nColCount -= nColAdd;
+ if ( nRowCount )
+ nRowCount -= nRowAdd;
+
+ if ( nColCount==0 || nRowCount==0 )
+ { // einen Eintrag ohne Daten erzeugen
+ pR = aRangeListRef->First();
+ if ( pCols->Count() > 0 )
+ pCol = (Table*) pCols->First();
+ else
+ {
+ pCol = new Table;
+ pCols->Insert( 0, pCol );
+ }
+ nColCount = 1;
+ if ( pCol->Count() > 0 )
+ { // kann ja eigentlich nicht sein, wenn nColCount==0 || nRowCount==0
+ pPos = (ScAddress*) pCol->First();
+ if ( pPos )
+ {
+ delete pPos;
+ pCol->Replace( pCol->GetCurKey(), (void*)0 );
+ }
+ }
+ else
+ pCol->Insert( 0, (void*)0 );
+ nRowCount = 1;
+ nColAdd = 0;
+ nRowAdd = 0;
+ }
+ else
+ {
+ if ( bNoGlue )
+ { // Luecken mit Dummies fuellen, erste Spalte ist Master
+ Table* pFirstCol = (Table*) pCols->First();
+ ULONG nCount = pFirstCol->Count();
+ pFirstCol->First();
+ for ( ULONG n = 0; n < nCount; n++, pFirstCol->Next() )
+ {
+ ULONG nKey = pFirstCol->GetCurKey();
+ pCols->First();
+ while ( pCol = (Table*) pCols->Next() )
+ pCol->Insert( nKey, (void*)0 ); // keine Daten
+ }
+ }
+ }
+
+ pPositionMap = new ScChartPositionMap( nColCount, nRowCount,
+ nColAdd, nRowAdd, *pCols );
+
+ // Aufraeumen
+ for ( pCol = (Table*) pCols->First(); pCol; pCol = (Table*) pCols->Next() )
+ { //! nur Tables loeschen, nicht die ScAddress*
+ delete pCol;
+ }
+ delete pCols;
+}
+
+
+ScChartPositionMap::ScChartPositionMap( USHORT nChartCols, USHORT nChartRows,
+ USHORT nColAdd, USHORT nRowAdd, Table& rCols ) :
+ nCount( (ULONG) nChartCols * nChartRows ),
+ nColCount( nChartCols ),
+ nRowCount( nChartRows ),
+ ppData( new ScAddress* [ nChartCols * nChartRows ] ),
+ ppColHeader( new ScAddress* [ nChartCols ] ),
+ ppRowHeader( new ScAddress* [ nChartRows ] )
+{
+ DBG_ASSERT( nColCount && nRowCount, "ScChartPositionMap without dimension" );
+#ifdef WIN
+#error ScChartPositionMap not implemented for 16-bit dumdums
+#endif
+
+ ScAddress* pPos;
+ USHORT nCol, nRow;
+
+ Table* pCol = (Table*) rCols.First();
+
+ // Zeilen-Header
+ pPos = (ScAddress*) pCol->First();
+ if ( nRowAdd )
+ pPos = (ScAddress*) pCol->Next();
+ if ( nColAdd )
+ { // eigenstaendig
+ for ( nRow = 0; nRow < nRowCount; nRow++ )
+ {
+ ppRowHeader[ nRow ] = pPos;
+ pPos = (ScAddress*) pCol->Next();
+ }
+ }
+ else
+ { // Kopie
+ for ( nRow = 0; nRow < nRowCount; nRow++ )
+ {
+ ppRowHeader[ nRow ] = ( pPos ? new ScAddress( *pPos ) : NULL );
+ pPos = (ScAddress*) pCol->Next();
+ }
+ }
+ if ( nColAdd )
+ pCol = (Table*) rCols.Next();
+
+ // Daten spaltenweise und Spalten-Header
+ ULONG nIndex = 0;
+ for ( nCol = 0; nCol < nColCount; nCol++ )
+ {
+ if ( pCol )
+ {
+ pPos = (ScAddress*) pCol->First();
+ if ( nRowAdd )
+ {
+ ppColHeader[ nCol ] = pPos; // eigenstaendig
+ pPos = (ScAddress*) pCol->Next();
+ }
+ else
+ ppColHeader[ nCol ] = ( pPos ? new ScAddress( *pPos ) : NULL );
+ for ( USHORT nRow = 0; nRow < nRowCount; nRow++, nIndex++ )
+ {
+ ppData[ nIndex ] = pPos;
+ pPos = (ScAddress*) pCol->Next();
+ }
+ }
+ else
+ {
+ ppColHeader[ nCol ] = NULL;
+ for ( nRow = 0; nRow < nRowCount; nRow++, nIndex++ )
+ {
+ ppData[ nIndex ] = NULL;
+ }
+ }
+ pCol = (Table*) rCols.Next();
+ }
+}
+
+
+ScChartPositionMap::~ScChartPositionMap()
+{
+ USHORT j;
+ for ( j=0; j < nCount; j++ )
+ {
+ delete ppData[j];
+ }
+ delete [] ppData;
+ for ( j=0; j < nColCount; j++ )
+ {
+ delete ppColHeader[j];
+ }
+ delete [] ppColHeader;
+ for ( j=0; j < nRowCount; j++ )
+ {
+ delete ppRowHeader[j];
+ }
+ delete [] ppRowHeader;
+}
+
+
+ScRangeListRef ScChartPositionMap::GetColRanges( USHORT nChartCol ) const
+{
+ ScRangeListRef xRangeList = new ScRangeList;
+ if ( nChartCol < nColCount )
+ {
+ ULONG nStop = GetIndex( nChartCol, nRowCount );
+ for ( ULONG nIndex = GetIndex( nChartCol, 0 ); nIndex < nStop; nIndex++ )
+ {
+ if ( ppData[ nIndex ] )
+ xRangeList->Join( *ppData[ nIndex ] );
+ }
+ }
+ return xRangeList;
+}
+
+
+ScRangeListRef ScChartPositionMap::GetRowRanges( USHORT nChartRow ) const
+{
+ ScRangeListRef xRangeList = new ScRangeList;
+ if ( nChartRow < nRowCount )
+ {
+ ULONG nStop = GetIndex( nColCount, nChartRow );
+ for ( ULONG nIndex = GetIndex( 0, nChartRow ); nIndex < nStop;
+ nIndex += nRowCount )
+ {
+ if ( ppData[ nIndex ] )
+ xRangeList->Join( *ppData[ nIndex ] );
+ }
+ }
+ return xRangeList;
+}
+
+
+//
+// Collection
+//
+
+DataObject* ScChartCollection::Clone() const
+{
+ return new ScChartCollection(*this);
+}
+
+BOOL ScChartCollection::operator==(const ScChartCollection& rCmp) const
+{
+ if (nCount != rCmp.nCount)
+ return FALSE;
+
+ for (USHORT i=0; i<nCount; i++)
+ if (!((*(const ScChartArray*)pItems[i]) == (*(const ScChartArray*)rCmp.pItems[i])))
+ return FALSE;
+
+ return TRUE;
+}
+
+BOOL ScChartCollection::Load( ScDocument* pDoc, SvStream& rStream )
+{
+ BOOL bSuccess = TRUE;
+ USHORT nNewCount;
+ FreeAll();
+
+ ScMultipleReadHeader aHdr( rStream );
+
+ rStream >> nNewCount;
+
+ for (USHORT i=0; i<nNewCount && bSuccess; i++)
+ {
+ ScChartArray* pObject = new ScChartArray( pDoc, rStream, aHdr );
+ bSuccess = Insert( pObject );
+ }
+ return bSuccess;
+}
+
diff --git a/sc/source/core/tool/chartlis.cxx b/sc/source/core/tool/chartlis.cxx
new file mode 100644
index 000000000000..353832b86a19
--- /dev/null
+++ b/sc/source/core/tool/chartlis.cxx
@@ -0,0 +1,468 @@
+/*************************************************************************
+ *
+ * $RCSfile: chartlis.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include <vcl/svapp.hxx>
+
+#include "chartlis.hxx"
+#include "brdcst.hxx"
+#include "document.hxx"
+
+using namespace com::sun::star;
+
+
+//2do: DocOption TimeOut?
+#define SC_CHARTTIMEOUT 1000 // eine Sekunde keine Aenderung/KeyEvent
+
+
+// ====================================================================
+
+class ScChartUnoData
+{
+ uno::Reference< chart::XChartDataChangeEventListener > xListener;
+ uno::Reference< chart::XChartData > xSource;
+
+public:
+ ScChartUnoData( const uno::Reference< chart::XChartDataChangeEventListener >& rL,
+ const uno::Reference< chart::XChartData >& rS ) :
+ xListener( rL ), xSource( rS ) {}
+ ~ScChartUnoData() {}
+
+ const uno::Reference< chart::XChartDataChangeEventListener >& GetListener() const { return xListener; }
+ const uno::Reference< chart::XChartData >& GetSource() const { return xSource; }
+};
+
+
+// === ScChartListener ================================================
+
+ScChartListener::ScChartListener( const String& rName, ScDocument* pDocP,
+ const ScRange& rRange ) :
+ StrData( rName ),
+ pDoc( pDocP ),
+ pUnoData( NULL ),
+ bUsed( FALSE ),
+ bDirty( FALSE )
+{
+ SetRangeList( rRange );
+}
+
+ScChartListener::ScChartListener( const String& rName, ScDocument* pDocP,
+ const ScRangeListRef& rRangeList ) :
+ StrData( rName ),
+ aRangeListRef( rRangeList ),
+ pDoc( pDocP ),
+ pUnoData( NULL ),
+ bUsed( FALSE ),
+ bDirty( FALSE )
+{
+}
+
+ScChartListener::ScChartListener( const ScChartListener& r ) :
+ StrData( r ),
+ pDoc( r.pDoc ),
+ pUnoData( NULL ),
+ bUsed( FALSE ),
+ bDirty( r.bDirty )
+{
+ if ( r.pUnoData )
+ pUnoData = new ScChartUnoData( *r.pUnoData );
+ if ( r.aRangeListRef.Is() )
+ aRangeListRef = new ScRangeList( *r.aRangeListRef );
+}
+
+ScChartListener::~ScChartListener()
+{
+ if ( GetBroadcasterCount() )
+ EndListeningTo();
+ delete pUnoData;
+}
+
+DataObject* ScChartListener::Clone() const
+{
+ return new ScChartListener( *this );
+}
+
+void ScChartListener::SetUno(
+ const uno::Reference< chart::XChartDataChangeEventListener >& rListener,
+ const uno::Reference< chart::XChartData >& rSource )
+{
+// DBG_ASSERT( rListener.is() && rSource.is(), "Nullpointer bei SetUno" );
+ delete pUnoData;
+ pUnoData = new ScChartUnoData( rListener, rSource );
+}
+
+uno::Reference< chart::XChartDataChangeEventListener > ScChartListener::GetUnoListener() const
+{
+ if ( pUnoData )
+ return pUnoData->GetListener();
+ return uno::Reference< chart::XChartDataChangeEventListener >();
+}
+
+uno::Reference< chart::XChartData > ScChartListener::GetUnoSource() const
+{
+ if ( pUnoData )
+ return pUnoData->GetSource();
+ return uno::Reference< chart::XChartData >();
+}
+
+void __EXPORT ScChartListener::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
+{
+ const ScHint* p = PTR_CAST( ScHint, &rHint );
+ if( p && (p->GetId() & (SC_HINT_DATACHANGED | SC_HINT_DYING)) )
+ {
+ bDirty = TRUE;
+ pDoc->GetChartListenerCollection()->StartTimer();
+ }
+}
+
+void ScChartListener::Update()
+{
+ if ( pDoc->IsInInterpreter() )
+ { // #73482# If interpreting do nothing and restart timer so we don't
+ // interfere with interpreter and don't produce an Err522 or similar.
+ // This may happen if we are rescheduled via Basic function.
+ pDoc->GetChartListenerCollection()->StartTimer();
+ return ;
+ }
+ if ( pUnoData )
+ {
+ bDirty = FALSE;
+ //! irgendwann mal erkennen, was sich innerhalb des Charts geaendert hat
+ chart::ChartDataChangeEvent aEvent( pUnoData->GetSource(),
+#ifdef TF_ONE51
+ chart::ChartDataChangeType_ALL,
+#else
+ CHARTDATACHANGETYPE_ALL,
+#endif
+ 0, 0, 0, 0 );
+ pUnoData->GetListener()->chartDataChanged( aEvent );
+ }
+ else if ( pDoc->GetAutoCalc() )
+ {
+ bDirty = FALSE;
+ pDoc->UpdateChart( GetString(), NULL );
+ }
+}
+
+void ScChartListener::StartListeningTo()
+{
+ if ( aRangeListRef.Is() )
+ for ( ScRangePtr pR = aRangeListRef->First(); pR;
+ pR = aRangeListRef->Next() )
+ {
+ if ( pR->aStart == pR->aEnd )
+ pDoc->StartListeningCell( pR->aStart, this );
+ else
+ pDoc->StartListeningArea( *pR, this );
+ }
+}
+
+void ScChartListener::EndListeningTo()
+{
+ if ( aRangeListRef.Is() )
+ for ( ScRangePtr pR = aRangeListRef->First(); pR;
+ pR = aRangeListRef->Next() )
+ {
+ if ( pR->aStart == pR->aEnd )
+ pDoc->EndListeningCell( pR->aStart, this );
+ else
+ pDoc->EndListeningArea( *pR, this );
+ }
+}
+
+
+void ScChartListener::ChangeListening( const ScRangeListRef& rRangeListRef,
+ BOOL bDirtyP )
+{
+ EndListeningTo();
+ SetRangeList( rRangeListRef );
+ StartListeningTo();
+ if ( bDirtyP )
+ SetDirty( TRUE );
+}
+
+
+void ScChartListener::SetRangeList( const ScRange& rRange )
+{
+ aRangeListRef = new ScRangeList;
+ aRangeListRef->Append( rRange );
+}
+
+
+BOOL ScChartListener::operator==( const ScChartListener& r )
+{
+ BOOL b1 = aRangeListRef.Is();
+ BOOL b2 = r.aRangeListRef.Is();
+ return
+ pDoc == r.pDoc &&
+ bUsed == r.bUsed &&
+ bDirty == r.bDirty &&
+ GetString() == r.GetString() &&
+ b1 == b2 &&
+ ((!b1 && !b2) || (*aRangeListRef == *r.aRangeListRef))
+ ;
+}
+
+
+// === ScChartListenerCollection ======================================
+
+ScChartListenerCollection::ScChartListenerCollection( ScDocument* pDocP ) :
+ StrCollection( 4, 4, FALSE ),
+ pDoc( pDocP )
+{
+ aTimer.SetTimeoutHdl( LINK( this, ScChartListenerCollection, TimerHdl ) );
+}
+
+ScChartListenerCollection::ScChartListenerCollection(
+ const ScChartListenerCollection& rColl ) :
+ StrCollection( rColl ),
+ pDoc( rColl.pDoc )
+{
+ aTimer.SetTimeoutHdl( LINK( this, ScChartListenerCollection, TimerHdl ) );
+}
+
+DataObject* ScChartListenerCollection::Clone() const
+{
+ return new ScChartListenerCollection( *this );
+}
+
+void ScChartListenerCollection::StartAllListeners()
+{
+ for ( USHORT nIndex = 0; nIndex < nCount; nIndex++ )
+ {
+ ((ScChartListener*) pItems[ nIndex ])->StartListeningTo();
+ }
+}
+
+void ScChartListenerCollection::ChangeListening( const String& rName,
+ const ScRangeListRef& rRangeListRef, BOOL bDirty )
+{
+ ScChartListener aCLSearcher( rName, pDoc, rRangeListRef );
+ ScChartListener* pCL;
+ USHORT nIndex;
+ if ( Search( &aCLSearcher, nIndex ) )
+ {
+ pCL = (ScChartListener*) pItems[ nIndex ];
+ pCL->EndListeningTo();
+ pCL->SetRangeList( rRangeListRef );
+ }
+ else
+ {
+ pCL = new ScChartListener( aCLSearcher );
+ Insert( pCL );
+ }
+ pCL->StartListeningTo();
+ if ( bDirty )
+ pCL->SetDirty( TRUE );
+}
+
+void ScChartListenerCollection::FreeUnused()
+{
+ // rueckwaerts wg. Pointer-Aufrueckerei im Array
+ for ( USHORT nIndex = nCount; nIndex-- >0; )
+ {
+ ScChartListener* pCL = (ScChartListener*) pItems[ nIndex ];
+ // Uno-Charts nicht rauskicken
+ // (werden per FreeUno von aussen geloescht)
+ if ( !pCL->IsUno() )
+ {
+ if ( pCL->IsUsed() )
+ pCL->SetUsed( FALSE );
+ else
+ Free( pCL );
+ }
+ }
+}
+
+void ScChartListenerCollection::FreeUno( const uno::Reference< chart::XChartDataChangeEventListener >& rListener,
+ const uno::Reference< chart::XChartData >& rSource )
+{
+ // rueckwaerts wg. Pointer-Aufrueckerei im Array
+ for ( USHORT nIndex = nCount; nIndex-- >0; )
+ {
+ ScChartListener* pCL = (ScChartListener*) pItems[ nIndex ];
+ if ( pCL->IsUno() &&
+ pCL->GetUnoListener() == rListener &&
+ pCL->GetUnoSource() == rSource )
+ {
+ Free( pCL );
+ }
+ //! sollte nur einmal vorkommen?
+ }
+}
+
+void ScChartListenerCollection::StartTimer()
+{
+ aTimer.SetTimeout( SC_CHARTTIMEOUT );
+ aTimer.Start();
+}
+
+IMPL_LINK( ScChartListenerCollection, TimerHdl, Timer*, pTimer )
+{
+ if ( Application::AnyInput( INPUT_KEYBOARD ) )
+ {
+ aTimer.Start();
+ return 0;
+ }
+ UpdateDirtyCharts();
+ return 0;
+}
+
+void ScChartListenerCollection::UpdateDirtyCharts()
+{
+ for ( USHORT nIndex = 0; nIndex < nCount; nIndex++ )
+ {
+ ScChartListener* pCL = (ScChartListener*) pItems[ nIndex ];
+ if ( pCL->IsDirty() )
+ pCL->Update();
+ if ( aTimer.IsActive() )
+ break; // da kam einer dazwischen
+ }
+}
+
+
+void ScChartListenerCollection::SetDirty()
+{
+ for ( USHORT nIndex = 0; nIndex < nCount; nIndex++ )
+ {
+ ScChartListener* pCL = (ScChartListener*) pItems[ nIndex ];
+ pCL->SetDirty( TRUE );
+ }
+ StartTimer();
+}
+
+
+void ScChartListenerCollection::SetDiffDirty(
+ const ScChartListenerCollection& rCmp, BOOL bSetChartRangeLists )
+{
+ BOOL bDirty = FALSE;
+ for ( USHORT nIndex = 0; nIndex < nCount; nIndex++ )
+ {
+ ScChartListener* pCL = (ScChartListener*) pItems[ nIndex ];
+ USHORT nFound;
+ BOOL bFound = rCmp.Search( pCL, nFound );
+ if ( !bFound || (*pCL != *((const ScChartListener*) rCmp.pItems[ nFound ])) )
+ {
+ if ( bSetChartRangeLists )
+ {
+ if ( bFound )
+ {
+ const ScRangeListRef& rList1 = pCL->GetRangeList();
+ const ScRangeListRef& rList2 =
+ ((const ScChartListener*) rCmp.pItems[ nFound ])->GetRangeList();
+ BOOL b1 = rList1.Is();
+ BOOL b2 = rList2.Is();
+ if ( b1 != b2 || (b1 && b2 && (*rList1 != *rList2)) )
+ pDoc->SetChartRangeList( pCL->GetString(), rList1 );
+ }
+ else
+ pDoc->SetChartRangeList( pCL->GetString(), pCL->GetRangeList() );
+ }
+ bDirty = TRUE;
+ pCL->SetDirty( TRUE );
+ }
+ }
+ if ( bDirty )
+ StartTimer();
+}
+
+
+void ScChartListenerCollection::SetRangeDirty( const ScRange& rRange )
+{
+ BOOL bDirty = FALSE;
+ for ( USHORT nIndex = 0; nIndex < nCount; nIndex++ )
+ {
+ ScChartListener* pCL = (ScChartListener*) pItems[ nIndex ];
+ const ScRangeListRef& rList = pCL->GetRangeList();
+ if ( rList.Is() && rList->Intersects( rRange ) )
+ {
+ bDirty = TRUE;
+ pCL->SetDirty( TRUE );
+ }
+ }
+ if ( bDirty )
+ StartTimer();
+}
+
+
+BOOL ScChartListenerCollection::operator==( const ScChartListenerCollection& r )
+{
+ // hier nicht StrCollection::operator==() verwenden, der umstaendlich via
+ // IsEqual und Compare laeuft, stattdessen ScChartListener::operator==()
+ if ( pDoc != r.pDoc || nCount != r.nCount )
+ return FALSE;
+ for ( USHORT nIndex = 0; nIndex < nCount; nIndex++ )
+ {
+ if ( *((ScChartListener*) pItems[ nIndex ]) !=
+ *((ScChartListener*) r.pItems[ nIndex ]) )
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+
+
diff --git a/sc/source/core/tool/chgtrack.cxx b/sc/source/core/tool/chgtrack.cxx
new file mode 100644
index 000000000000..6114e49fa54b
--- /dev/null
+++ b/sc/source/core/tool/chgtrack.cxx
@@ -0,0 +1,4543 @@
+/*************************************************************************
+ *
+ * $RCSfile: chgtrack.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#pragma hdrstop
+
+#ifndef _TOOLS_DEBUG_HXX //autogen
+#include <tools/debug.hxx>
+#endif
+#ifndef _SHL_HXX //autogen
+#include <tools/shl.hxx> // SHL_CALC
+#endif
+#ifndef _STACK_HXX //autogen
+#include <tools/stack.hxx>
+#endif
+#ifndef _RTTI_HXX //autogen
+#include <tools/rtti.hxx>
+#endif
+#ifndef _ZFORLIST_HXX //autogen
+#include <svtools/zforlist.hxx>
+#endif
+#ifndef _SFXITEMSET_HXX //autogen
+#include <svtools/itemset.hxx>
+#endif
+#ifndef _SFXISETHINT_HXX //autogen
+#include <svtools/isethint.hxx>
+#endif
+#ifndef _SFXITEMPOOL_HXX //autogen
+#include <svtools/itempool.hxx>
+#endif
+#ifndef _SFXAPP_HXX //autogen
+#include <sfx2/app.hxx>
+#endif
+#ifndef _SFX_INIMGR_HXX //autogen
+#include <sfx2/inimgr.hxx>
+#endif
+#ifndef _SFXSIDS_HRC //autogen
+#include <sfx2/sfxsids.hrc>
+#endif
+#ifndef _SVX_ADRITEM_HXX //autogen
+#include <svx/adritem.hxx>
+#endif
+
+#include "cell.hxx"
+#include "document.hxx"
+#include "dociter.hxx"
+#include "global.hxx"
+#include "rechead.hxx"
+#include "scerrors.hxx"
+#include "scmod.hxx" // SC_MOD
+#include "inputopt.hxx" // GetExpandRefs
+#include "patattr.hxx"
+
+#include "globstr.hrc"
+
+#define SC_CHGTRACK_CXX
+#include "chgtrack.hxx"
+
+DECLARE_STACK( ScChangeActionStack, ScChangeAction* );
+
+const USHORT nMemPoolChangeActionLinkEntry = (0x8000 - 64) / sizeof(ScChangeActionLinkEntry);
+IMPL_FIXEDMEMPOOL_NEWDEL( ScChangeActionLinkEntry, nMemPoolChangeActionLinkEntry, nMemPoolChangeActionLinkEntry );
+
+// loaded MSB > eigenes => inkompatibel
+#define SC_CHGTRACK_FILEFORMAT_FIRST 0x0001
+#define SC_CHGTRACK_FILEFORMAT 0x0001
+
+// --- ScChangeActionCellListEntry -----------------------------------------
+
+class ScChangeActionCellListEntry
+{
+ friend class ScChangeAction;
+ friend class ScChangeActionDel;
+ friend class ScChangeActionMove;
+ friend class ScChangeTrack;
+
+ ScChangeActionCellListEntry* pNext;
+ ScChangeActionContent* pContent;
+
+ ScChangeActionCellListEntry(
+ ScChangeActionContent* pContentP,
+ ScChangeActionCellListEntry* pNextP )
+ : pContent( pContentP ),
+ pNext( pNextP )
+ {}
+
+public:
+
+ DECL_FIXEDMEMPOOL_NEWDEL( ScChangeActionCellListEntry )
+};
+
+const USHORT nMemPoolChangeActionCellListEntry = (0x2000 - 64) / sizeof(ScChangeActionCellListEntry);
+IMPL_FIXEDMEMPOOL_NEWDEL( ScChangeActionCellListEntry, nMemPoolChangeActionCellListEntry, nMemPoolChangeActionCellListEntry );
+
+
+// --- ScChangeAction ------------------------------------------------------
+
+ScChangeAction::ScChangeAction( ScChangeActionType eTypeP, const ScRange& rRange )
+ :
+ aBigRange( rRange ),
+ pNext( NULL ),
+ pPrev( NULL ),
+ pLinkAny( NULL ),
+ pLinkDeletedIn( NULL ),
+ pLinkDeleted( NULL ),
+ pLinkDependent( NULL ),
+ nAction( 0 ),
+ nRejectAction( 0 ),
+ eType( eTypeP ),
+ eState( SC_CAS_VIRGIN )
+{
+ aDateTime.ConvertToUTC();
+}
+
+
+ScChangeAction::ScChangeAction( SvStream& rStrm, ScMultipleReadHeader& rHdr,
+ ScChangeTrack* pTrack )
+ :
+ pNext( NULL ),
+ pPrev( NULL ),
+ pLinkAny( NULL ),
+ pLinkDeletedIn( NULL ),
+ pLinkDeleted( NULL ),
+ pLinkDependent( NULL )
+{
+ // ScChangeTrack speichert aUser als Index auf Collection und eType selber
+ UINT32 n32;
+ UINT16 n16;
+ rStrm >> aBigRange;
+ rStrm >> n32; aDateTime.SetDate( n32 );
+ rStrm >> n32; aDateTime.SetTime( n32 );
+ rStrm >> n32; nAction = n32;
+ rStrm >> n32; nRejectAction = n32;
+ rStrm >> n16; eState = (ScChangeActionState) n16;
+ rStrm.ReadByteString( aComment, rStrm.GetStreamCharSet() );
+ // LinkEntries in zweiter Runde
+}
+
+
+ScChangeAction::~ScChangeAction()
+{
+ RemoveAllLinks();
+}
+
+
+BOOL ScChangeAction::Store( SvStream& rStrm, ScMultipleWriteHeader& rHdr ) const
+{
+ // ScChangeTrack speichert aUser als Index auf Collection und eType selber
+ rStrm << aBigRange;
+ rStrm << (UINT32) aDateTime.GetDate();
+ rStrm << (UINT32) aDateTime.GetTime();
+ rStrm << (UINT32) nAction;
+ rStrm << (UINT32) nRejectAction;
+ rStrm << (UINT16) eState;
+ rStrm.WriteByteString( aComment, rStrm.GetStreamCharSet() );
+ // LinkEntries in zweiter Runde
+
+ return TRUE;
+}
+
+
+BOOL ScChangeAction::StoreLinks( SvStream& rStrm ) const
+{
+ BOOL bOk = ScChangeAction::StoreLinkChain( pLinkDeleted, rStrm );
+ bOk &= ScChangeAction::StoreLinkChain( pLinkDependent, rStrm );
+ return bOk;
+}
+
+
+BOOL ScChangeAction::LoadLinks( SvStream& rStrm, ScChangeTrack* pTrack )
+{
+ BOOL bOk = ScChangeAction::LoadLinkChain( this, &pLinkDeleted, rStrm,
+ pTrack, TRUE );
+ bOk &= ScChangeAction::LoadLinkChain( this, &pLinkDependent, rStrm,
+ pTrack, FALSE );
+ return bOk;
+}
+
+
+BOOL ScChangeAction::IsVisible() const
+{
+ //! Reihenfolge ist wichtig
+ if ( IsRejected() || GetType() == SC_CAT_DELETE_TABS || IsDeletedIn() )
+ return FALSE;
+ if ( GetType() == SC_CAT_CONTENT )
+ return ((ScChangeActionContent*)this)->IsTopContent();
+ return TRUE;
+}
+
+
+BOOL ScChangeAction::IsTouchable() const
+{
+ //! Reihenfolge ist wichtig
+ if ( IsRejected() || GetType() == SC_CAT_REJECT || IsDeletedIn() )
+ return FALSE;
+ // Content kann rejecten und touchable sein, wenn on top
+ if ( GetType() == SC_CAT_CONTENT )
+ return ((ScChangeActionContent*)this)->IsTopContent();
+ if ( IsRejecting() )
+ return FALSE;
+ return TRUE;
+}
+
+
+BOOL ScChangeAction::IsClickable() const
+{
+ //! Reihenfolge ist wichtig
+ if ( !IsVirgin() )
+ return FALSE;
+ if ( IsDeletedIn() )
+ return FALSE;
+ if ( GetType() == SC_CAT_CONTENT )
+ return TRUE; // fuer Select muss es nicht anfassbar sein
+ return IsTouchable(); // Accept/Reject nur auf anfassbaren
+}
+
+
+BOOL ScChangeAction::IsRejectable() const
+{
+ //! Reihenfolge ist wichtig
+ if ( !IsClickable() )
+ return FALSE;
+ if ( GetType() == SC_CAT_CONTENT )
+ {
+ ScChangeActionContent* pNextContent =
+ ((ScChangeActionContent*)this)->GetNextContent();
+ if ( pNextContent == NULL )
+ return TRUE; // this ist TopContent
+ return pNextContent->IsRejected(); // this ist naechster rejectable
+ }
+ return IsTouchable();
+}
+
+
+BOOL ScChangeAction::IsDialogRoot() const
+{
+ return IsRejectable(); // nur Rejectables in der Root
+}
+
+
+BOOL ScChangeAction::IsDialogParent() const
+{
+ if ( GetType() == SC_CAT_CONTENT )
+ {
+ if ( !IsDialogRoot() )
+ return FALSE;
+ ScChangeActionContent* pPrevContent =
+ ((ScChangeActionContent*)this)->GetPrevContent();
+ return pPrevContent && pPrevContent->IsVirgin();
+ }
+ if ( HasDependent() )
+ return IsDeleteType() ? TRUE : !IsDeletedIn();
+ if ( HasDeleted() )
+ {
+ if ( IsDeleteType() )
+ {
+ if ( IsDialogRoot() )
+ return TRUE;
+ ScChangeActionLinkEntry* pL = pLinkDeleted;
+ while ( pL )
+ {
+ ScChangeAction* p = pL->GetAction();
+ if ( p && p->GetType() != eType )
+ return TRUE;
+ pL = pL->GetNext();
+ }
+ }
+ else
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+BOOL ScChangeAction::IsMasterDelete() const
+{
+ if ( !IsDeleteType() )
+ return FALSE;
+ ScChangeActionDel* pDel = (ScChangeActionDel*) this;
+ return pDel->IsMultiDelete() && (pDel->IsTopDelete() || pDel->IsRejectable());
+}
+
+
+void ScChangeAction::RemoveAllLinks()
+{
+ RemoveAllAnyLinks();
+ RemoveAllDeletedIn();
+ RemoveAllDeleted();
+ RemoveAllDependent();
+}
+
+
+void ScChangeAction::RemoveLink( ScChangeAction* p )
+{
+ ScChangeActionLinkEntry* pL = pLinkAny;
+ while ( pL )
+ {
+ ScChangeActionLinkEntry* pNextLink = pL->GetNext();
+ if ( pL->GetAction() == p )
+ delete pL;
+ pL = pNextLink;
+ }
+}
+
+
+void ScChangeAction::RemoveAllAnyLinks()
+{
+ while ( pLinkAny )
+ delete pLinkAny; // rueckt sich selbst hoch
+}
+
+
+BOOL ScChangeAction::DependsOn( ScChangeAction* p ) const
+{
+ ScChangeActionLinkEntry* pL = pLinkAny;
+ while ( pL )
+ {
+ if ( pL->GetAction() == p )
+ return TRUE;
+ pL = pL->GetNext();
+ }
+ return FALSE;
+}
+
+
+BOOL ScChangeAction::RemoveDeletedIn( const ScChangeAction* p )
+{
+ BOOL bRemoved = FALSE;
+ ScChangeActionLinkEntry* pL = GetDeletedIn();
+ while ( pL )
+ {
+ ScChangeActionLinkEntry* pNextLink = pL->GetNext();
+ if ( pL->GetAction() == p )
+ {
+ delete pL;
+ bRemoved = TRUE;
+ }
+ pL = pNextLink;
+ }
+ return bRemoved;
+}
+
+
+BOOL ScChangeAction::IsDeletedIn( const ScChangeAction* p ) const
+{
+ ScChangeActionLinkEntry* pL = GetDeletedIn();
+ while ( pL )
+ {
+ if ( pL->GetAction() == p )
+ return TRUE;
+ pL = pL->GetNext();
+ }
+ return FALSE;
+}
+
+
+void ScChangeAction::RemoveAllDeletedIn()
+{
+ //! nicht vom evtl. TopContent sondern wirklich dieser
+ while ( pLinkDeletedIn )
+ delete pLinkDeletedIn; // rueckt sich selbst hoch
+}
+
+
+BOOL ScChangeAction::IsDeletedInDelType( ScChangeActionType eDelType ) const
+{
+ ScChangeAction* p;
+ ScChangeActionLinkEntry* pL = GetDeletedIn();
+ if ( pL )
+ {
+ // InsertType fuer MergePrepare/MergeOwn
+ ScChangeActionType eInsType;
+ switch ( eDelType )
+ {
+ case SC_CAT_DELETE_COLS :
+ eInsType = SC_CAT_INSERT_COLS;
+ break;
+ case SC_CAT_DELETE_ROWS :
+ eInsType = SC_CAT_INSERT_ROWS;
+ break;
+ case SC_CAT_DELETE_TABS :
+ eInsType = SC_CAT_INSERT_TABS;
+ break;
+ default:
+ eInsType = SC_CAT_NONE;
+ }
+ while ( pL )
+ {
+ if ( (p = pL->GetAction()) &&
+ (p->GetType() == eDelType || p->GetType() == eInsType) )
+ return TRUE;
+ pL = pL->GetNext();
+ }
+ }
+ return FALSE;
+}
+
+
+void ScChangeAction::SetDeletedIn( ScChangeAction* p )
+{
+ ScChangeActionLinkEntry* pLink1 = AddDeletedIn( p );
+ ScChangeActionLinkEntry* pLink2;
+ if ( GetType() == SC_CAT_CONTENT )
+ pLink2 = p->AddDeleted( ((ScChangeActionContent*)this)->GetTopContent() );
+ else
+ pLink2 = p->AddDeleted( this );
+ pLink1->SetLink( pLink2 );
+}
+
+
+BOOL ScChangeAction::RemoveDeleted( const ScChangeAction* p )
+{
+ BOOL bRemoved = FALSE;
+ ScChangeActionLinkEntry* pL = pLinkDeleted;
+ while ( pL )
+ {
+ ScChangeActionLinkEntry* pNextLink = pL->GetNext();
+ if ( pL->GetAction() == p )
+ {
+ delete pL;
+ bRemoved = TRUE;
+ }
+ pL = pNextLink;
+ }
+ return bRemoved;
+}
+
+
+void ScChangeAction::RemoveAllDeleted()
+{
+ while ( pLinkDeleted )
+ delete pLinkDeleted; // rueckt sich selbst hoch
+}
+
+
+void ScChangeAction::RemoveDependent( ScChangeAction* p )
+{
+ ScChangeActionLinkEntry* pL = pLinkDependent;
+ while ( pL )
+ {
+ ScChangeActionLinkEntry* pNextLink = pL->GetNext();
+ if ( pL->GetAction() == p )
+ delete pL;
+ pL = pNextLink;
+ }
+}
+
+
+void ScChangeAction::RemoveAllDependent()
+{
+ while ( pLinkDependent )
+ delete pLinkDependent; // rueckt sich selbst hoch
+}
+
+
+DateTime ScChangeAction::GetDateTime() const
+{
+ DateTime aDT( aDateTime );
+ aDT.ConvertToLocalTime();
+ return aDT;
+}
+
+
+void ScChangeAction::UpdateReference( const ScChangeTrack* pTrack,
+ UpdateRefMode eMode, const ScBigRange& rRange,
+ INT32 nDx, INT32 nDy, INT32 nDz )
+{
+ ScRefUpdate::Update( eMode, rRange, nDx, nDy, nDz, GetBigRange() );
+}
+
+
+String ScChangeAction::GetRefString( const ScBigRange& rRange,
+ ScDocument* pDoc, BOOL bFlag3D ) const
+{
+ String aStr;
+ USHORT nFlags = ( rRange.IsValid( pDoc ) ? SCA_VALID : 0 );
+ if ( !nFlags )
+ aStr = ScGlobal::GetRscString( STR_NOREF_STR );
+ else
+ {
+ ScRange aTmpRange( rRange.MakeRange() );
+ switch ( GetType() )
+ {
+ case SC_CAT_INSERT_COLS :
+ case SC_CAT_DELETE_COLS :
+ if ( bFlag3D )
+ {
+ pDoc->GetName( aTmpRange.aStart.Tab(), aStr );
+ aStr += '.';
+ }
+ aStr += ::ColToAlpha( aTmpRange.aStart.Col() );
+ aStr += ':';
+ aStr += ::ColToAlpha( aTmpRange.aEnd.Col() );
+ break;
+ case SC_CAT_INSERT_ROWS :
+ case SC_CAT_DELETE_ROWS :
+ if ( bFlag3D )
+ {
+ pDoc->GetName( aTmpRange.aStart.Tab(), aStr );
+ aStr += '.';
+ }
+ aStr += String::CreateFromInt32( aTmpRange.aStart.Row() + 1 );
+ aStr += ':';
+ aStr += String::CreateFromInt32( aTmpRange.aEnd.Row() + 1 );
+ break;
+ default:
+ if ( bFlag3D || GetType() == SC_CAT_INSERT_TABS )
+ nFlags |= SCA_TAB_3D;
+ aTmpRange.Format( aStr, nFlags, pDoc );
+ }
+ if ( (bFlag3D && IsDeleteType()) || IsDeletedIn() )
+ {
+ aStr.Insert( '(', 0 );
+ aStr += ')';
+ }
+ }
+ return aStr;
+}
+
+
+void ScChangeAction::GetRefString( String& rStr, ScDocument* pDoc,
+ BOOL bFlag3D ) const
+{
+ rStr = GetRefString( GetBigRange(), pDoc, bFlag3D );
+}
+
+
+void ScChangeAction::Accept()
+{
+ if ( IsVirgin() )
+ {
+ SetState( SC_CAS_ACCEPTED );
+ DeleteCellEntries();
+ }
+}
+
+
+void ScChangeAction::SetRejected()
+{
+ if ( IsVirgin() )
+ {
+ SetState( SC_CAS_REJECTED );
+ RemoveAllLinks();
+ DeleteCellEntries();
+ }
+}
+
+
+void ScChangeAction::RejectRestoreContents( ScChangeTrack* pTrack,
+ short nDx, short nDy )
+{
+ // Liste der Contents aufbauen
+ ScChangeActionCellListEntry* pListContents = NULL;
+ for ( ScChangeActionLinkEntry* pL = pLinkDeleted; pL; pL = pL->GetNext() )
+ {
+ ScChangeAction* p = pL->GetAction();
+ if ( p && p->GetType() == SC_CAT_CONTENT )
+ {
+ ScChangeActionCellListEntry* pE = new ScChangeActionCellListEntry(
+ (ScChangeActionContent*) p, pListContents );
+ pListContents = pE;
+ }
+ }
+ SetState( SC_CAS_REJECTED ); // vor UpdateReference fuer Move
+ pTrack->UpdateReference( this, TRUE ); // LinkDeleted freigeben
+ DBG_ASSERT( !pLinkDeleted, "ScChangeAction::RejectRestoreContents: pLinkDeleted != NULL" );
+ // Liste der Contents abarbeiten und loeschen
+ ScDocument* pDoc = pTrack->GetDocument();
+ ScChangeActionCellListEntry* pE = pListContents;
+ while ( pE )
+ {
+ if ( !pE->pContent->IsDeletedIn() &&
+ pE->pContent->GetBigRange().aStart.IsValid( pDoc ) )
+ pE->pContent->PutNewValueToDoc( pDoc, nDx, nDy );
+ ScChangeActionCellListEntry* pNext;
+ pNext = pE->pNext;
+ delete pE;
+ pE = pNext;
+ }
+ DeleteCellEntries(); // weg mit den generierten
+}
+
+
+// static
+void ScChangeAction::StoreCell( ScBaseCell* pCell, SvStream& rStrm,
+ ScMultipleWriteHeader& rHdr )
+{
+ if ( pCell )
+ {
+ CellType eCellType = pCell->GetCellType();
+ switch( eCellType )
+ {
+ case CELLTYPE_VALUE:
+ rStrm << (BYTE) eCellType;
+ ((ScValueCell*)pCell)->Save( rStrm );
+ break;
+ case CELLTYPE_STRING:
+ rStrm << (BYTE) eCellType;
+ ((ScStringCell*)pCell)->Save( rStrm );
+ break;
+ case CELLTYPE_EDIT:
+ rStrm << (BYTE) eCellType;
+ ((ScEditCell*)pCell)->Save( rStrm );
+ break;
+ case CELLTYPE_FORMULA:
+ rStrm << (BYTE) eCellType;
+ rStrm << ((ScFormulaCell*)pCell)->aPos;
+ ((ScFormulaCell*)pCell)->Save( rStrm, rHdr );
+ break;
+ default:
+ DBG_ERROR( "ScChangeAction::StoreCell: unknown CellType" );
+ rStrm << (BYTE) CELLTYPE_NONE;
+ }
+ }
+ else
+ rStrm << (BYTE) CELLTYPE_NONE;
+}
+
+
+// static
+ScBaseCell* ScChangeAction::LoadCell( SvStream& rStrm,
+ ScMultipleReadHeader& rHdr, ScDocument* pDoc, USHORT nVer )
+{
+ ScBaseCell* pCell;
+ BYTE nByte;
+ rStrm >> nByte;
+ switch ( (CellType) nByte )
+ {
+ case CELLTYPE_VALUE:
+ {
+ pCell = new ScValueCell( rStrm, nVer );
+ }
+ break;
+ case CELLTYPE_STRING:
+ {
+ pCell = new ScStringCell( rStrm, nVer );
+ }
+ break;
+ case CELLTYPE_EDIT:
+ {
+ pCell = new ScEditCell( rStrm, nVer, pDoc );
+ }
+ break;
+ case CELLTYPE_FORMULA:
+ {
+ ScAddress aPos;
+ rStrm >> aPos;
+ pCell = new ScFormulaCell( pDoc, aPos, rStrm, rHdr );
+ ((ScFormulaCell*)pCell)->SetInChangeTrack( TRUE );
+ }
+ break;
+ case CELLTYPE_NONE :
+ pCell = NULL;
+ break;
+ default:
+ DBG_ERROR( "ScChangeAction::LoadCell: unknown CellType" );
+ rStrm.SetError( SVSTREAM_FILEFORMAT_ERROR );
+ pCell = NULL;
+ }
+ return pCell;
+}
+
+
+// static
+BOOL ScChangeAction::StoreLinkChain( ScChangeActionLinkEntry* pLinkFirst,
+ SvStream& rStrm )
+{
+ BOOL bOk = TRUE;
+ UINT32 nCount = 0;
+ if ( pLinkFirst )
+ {
+ // rueckwaerts speichern, damit onLoad mit Insert die Reihenfolge wieder stimmt
+ Stack* pStack = new Stack;
+ for ( ScChangeActionLinkEntry* pL = pLinkFirst; pL; pL = pL->GetNext() )
+ {
+ ++nCount;
+ pStack->Push( pL );
+ }
+ rStrm << nCount;
+ ScChangeActionLinkEntry* pHere;
+ while ( pHere = (ScChangeActionLinkEntry*) pStack->Pop() )
+ {
+ ScChangeAction* p = pHere->GetAction();
+ rStrm << (UINT32) ( p ? p->GetActionNumber() : 0 );
+ }
+ delete pStack;
+ }
+ else
+ rStrm << nCount;
+ return bOk;
+}
+
+
+// static
+BOOL ScChangeAction::LoadLinkChain( ScChangeAction* pOfAction,
+ ScChangeActionLinkEntry** ppLinkFirst, SvStream& rStrm,
+ ScChangeTrack* pTrack, BOOL bLinkDeleted )
+{
+ BOOL bOk = TRUE;
+ UINT32 nCount;
+ rStrm >> nCount;
+ for ( UINT32 j = 0; j < nCount; j++ )
+ {
+ ScChangeAction* pAct = NULL;
+ UINT32 nAct;
+ rStrm >> nAct;
+ if ( nAct )
+ {
+ pAct = pTrack->GetActionOrGenerated( nAct );
+ DBG_ASSERT( pAct, "ScChangeAction::LoadLinkChain: missing Action" );
+ }
+ if ( bLinkDeleted )
+ {
+ if ( pAct )
+ pAct->SetDeletedIn( pOfAction );
+ }
+ else
+ {
+ ScChangeActionLinkEntry* pLink = new ScChangeActionLinkEntry(
+ ppLinkFirst, pAct );
+ if ( pAct )
+ pAct->AddLink( pOfAction, pLink );
+ }
+ }
+ return bOk;
+}
+
+
+// static
+BOOL ScChangeAction::StoreCellList( ScChangeActionCellListEntry* pFirstCell,
+ SvStream& rStrm )
+{
+ UINT32 nCount = 0;
+ for ( const ScChangeActionCellListEntry* pE = pFirstCell; pE;
+ pE = pE->pNext )
+ ++nCount;
+ rStrm << nCount;
+
+ if ( nCount )
+ {
+ for ( const ScChangeActionCellListEntry* pE = pFirstCell; pE;
+ pE = pE->pNext )
+ { // Store/Load vertauscht die Reihenfolge, aber das ist hierbei egal
+ rStrm << (UINT32) pE->pContent->GetActionNumber();
+ }
+ }
+ return TRUE;
+}
+
+
+BOOL ScChangeAction::LoadCellList( ScChangeAction* pOfAction,
+ ScChangeActionCellListEntry*& pFirstCell, SvStream& rStrm,
+ ScChangeTrack* pTrack )
+{
+ UINT32 nCount;
+ rStrm >> nCount;
+ if ( nCount )
+ {
+ for ( UINT32 j = 0; j < nCount; j++ )
+ {
+ ScChangeActionContent* pContent;
+ UINT32 nContent;
+ rStrm >> nContent;
+ pContent = (ScChangeActionContent*) pTrack->GetActionOrGenerated( nContent );
+ if ( pContent )
+ pOfAction->AddContent( pContent );
+ else
+ DBG_ERROR( "ScChangeActionDel::LoadLinks: missing Content" );
+ }
+ }
+ return TRUE;
+}
+
+
+// --- ScChangeActionIns ---------------------------------------------------
+
+ScChangeActionIns::ScChangeActionIns( const ScRange& rRange )
+ : ScChangeAction( SC_CAT_NONE, rRange )
+{
+ if ( rRange.aStart.Col() == 0 && rRange.aEnd.Col() == MAXCOL )
+ {
+ aBigRange.aStart.SetCol( nInt32Min );
+ aBigRange.aEnd.SetCol( nInt32Max );
+ if ( rRange.aStart.Row() == 0 && rRange.aEnd.Row() == MAXROW )
+ {
+ SetType( SC_CAT_INSERT_TABS );
+ aBigRange.aStart.SetRow( nInt32Min );
+ aBigRange.aEnd.SetRow( nInt32Max );
+ }
+ else
+ SetType( SC_CAT_INSERT_ROWS );
+ }
+ else if ( rRange.aStart.Row() == 0 && rRange.aEnd.Row() == MAXROW )
+ {
+ SetType( SC_CAT_INSERT_COLS );
+ aBigRange.aStart.SetRow( nInt32Min );
+ aBigRange.aEnd.SetRow( nInt32Max );
+ }
+ else
+ DBG_ERROR( "ScChangeActionIns: Block not supported!" );
+}
+
+
+ScChangeActionIns::ScChangeActionIns( SvStream& rStrm,
+ ScMultipleReadHeader& rHdr, ScChangeTrack* pTrack )
+ :
+ ScChangeAction( rStrm, rHdr, pTrack )
+{
+}
+
+
+ScChangeActionIns::~ScChangeActionIns()
+{
+}
+
+
+BOOL ScChangeActionIns::Store( SvStream& rStrm, ScMultipleWriteHeader& rHdr ) const
+{
+ BOOL bOk = ScChangeAction::Store( rStrm, rHdr );
+ return bOk;
+}
+
+
+void ScChangeActionIns::GetDescription( String& rStr, ScDocument* pDoc,
+ BOOL bSplitRange ) const
+{
+ USHORT nWhatId;
+ switch ( GetType() )
+ {
+ case SC_CAT_INSERT_COLS :
+ nWhatId = STR_COLUMN;
+ break;
+ case SC_CAT_INSERT_ROWS :
+ nWhatId = STR_ROW;
+ break;
+ default:
+ nWhatId = STR_AREA;
+ }
+
+ String aRsc( ScGlobal::GetRscString( STR_CHANGED_INSERT ) );
+ xub_StrLen nPos = aRsc.SearchAscii( "#1" );
+ rStr += aRsc.Copy( 0, nPos );
+ rStr += ScGlobal::GetRscString( nWhatId );
+ rStr += ' ';
+ rStr += GetRefString( GetBigRange(), pDoc );
+ rStr += aRsc.Copy( nPos+2 );
+}
+
+
+BOOL ScChangeActionIns::Reject( ScDocument* pDoc )
+{
+ if ( !aBigRange.IsValid( pDoc ) )
+ return FALSE;
+
+ ScRange aRange( aBigRange.MakeRange() );
+ if ( !pDoc->IsBlockEditable( aRange.aStart.Tab(), aRange.aStart.Col(),
+ aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row() ) )
+ return FALSE;
+
+ switch ( GetType() )
+ {
+ case SC_CAT_INSERT_COLS :
+ pDoc->DeleteCol( aRange );
+ break;
+ case SC_CAT_INSERT_ROWS :
+ pDoc->DeleteRow( aRange );
+ break;
+ case SC_CAT_INSERT_TABS :
+ pDoc->DeleteTab( aRange.aStart.Tab() );
+ break;
+ }
+ SetState( SC_CAS_REJECTED );
+ RemoveAllLinks();
+ return TRUE;
+}
+
+
+// --- ScChangeActionDel ---------------------------------------------------
+
+ScChangeActionDel::ScChangeActionDel( const ScRange& rRange,
+ short nDxP, short nDyP, ScChangeTrack* pTrackP )
+ :
+ ScChangeAction( SC_CAT_NONE, rRange ),
+ pTrack( pTrackP ),
+ pFirstCell( NULL ),
+ pLinkMove( NULL ),
+ pCutOff( NULL ),
+ nCutOff( 0 ),
+ nDx( nDxP ),
+ nDy( nDyP )
+{
+ if ( rRange.aStart.Col() == 0 && rRange.aEnd.Col() == MAXCOL )
+ {
+ aBigRange.aStart.SetCol( nInt32Min );
+ aBigRange.aEnd.SetCol( nInt32Max );
+ if ( rRange.aStart.Row() == 0 && rRange.aEnd.Row() == MAXROW )
+ {
+ SetType( SC_CAT_DELETE_TABS );
+ aBigRange.aStart.SetRow( nInt32Min );
+ aBigRange.aEnd.SetRow( nInt32Max );
+ }
+ else
+ SetType( SC_CAT_DELETE_ROWS );
+ }
+ else if ( rRange.aStart.Row() == 0 && rRange.aEnd.Row() == MAXROW )
+ {
+ SetType( SC_CAT_DELETE_COLS );
+ aBigRange.aStart.SetRow( nInt32Min );
+ aBigRange.aEnd.SetRow( nInt32Max );
+ }
+ else
+ DBG_ERROR( "ScChangeActionDel: Block not supported!" );
+}
+
+
+ScChangeActionDel::ScChangeActionDel( SvStream& rStrm,
+ ScMultipleReadHeader& rHdr, ScDocument* pDoc, USHORT nVer,
+ ScChangeTrack* pTrackP )
+ :
+ ScChangeAction( rStrm, rHdr, pTrackP ),
+ pTrack( pTrackP ),
+ pFirstCell( NULL ),
+ pLinkMove( NULL )
+{
+ UINT32 n32;
+ INT16 n16s;
+ rStrm >> n32; pCutOff = (ScChangeActionIns*)(ULONG) n32;
+ rStrm >> n16s; nCutOff = n16s;
+ rStrm >> n16s; nDx = n16s;
+ rStrm >> n16s; nDy = n16s;
+}
+
+
+ScChangeActionDel::~ScChangeActionDel()
+{
+ DeleteCellEntries();
+ while ( pLinkMove )
+ delete pLinkMove;
+}
+
+
+BOOL ScChangeActionDel::Store( SvStream& rStrm, ScMultipleWriteHeader& rHdr ) const
+{
+ BOOL bOk = ScChangeAction::Store( rStrm, rHdr );
+ rStrm << (UINT32) ( pCutOff ? pCutOff->GetActionNumber() : 0 );
+ rStrm << (INT16) nCutOff;
+ rStrm << (INT16) nDx;
+ rStrm << (INT16) nDy;
+ return bOk;
+}
+
+
+BOOL ScChangeActionDel::StoreLinks( SvStream& rStrm ) const
+{
+ BOOL bOk = ScChangeAction::StoreLinks( rStrm );
+ UINT32 nCount = 0;
+ if ( pLinkMove )
+ {
+ // rueckwaerts speichern, damit onLoad mit Insert die Reihenfolge wieder stimmt
+ Stack* pStack = new Stack;
+ for ( ScChangeActionDelMoveEntry* pL = pLinkMove; pL; pL = pL->GetNext() )
+ {
+ ++nCount;
+ pStack->Push( pL );
+ }
+ rStrm << nCount;
+ ScChangeActionDelMoveEntry* pHere;
+ while ( pHere = (ScChangeActionDelMoveEntry*) pStack->Pop() )
+ {
+ ScChangeAction* p = pHere->GetAction();
+ rStrm << (UINT32) ( p ? p->GetActionNumber() : 0 );
+ rStrm << (INT16) pHere->GetCutOffFrom();
+ rStrm << (INT16) pHere->GetCutOffTo();
+ }
+ delete pStack;
+ }
+ else
+ rStrm << nCount;
+
+ bOk &= ScChangeAction::StoreCellList( pFirstCell, rStrm );
+
+ return bOk;
+}
+
+
+BOOL ScChangeActionDel::LoadLinks( SvStream& rStrm, ScChangeTrack* pTrack )
+{
+ BOOL bOk = ScChangeAction::LoadLinks( rStrm, pTrack );
+ UINT32 nCount;
+ rStrm >> nCount;
+ for ( UINT32 j = 0; j < nCount; j++ )
+ {
+ ScChangeActionMove* pAct = NULL;
+ UINT32 nAct;
+ rStrm >> nAct;
+ if ( nAct )
+ {
+ pAct = (ScChangeActionMove*) pTrack->GetAction( nAct );
+ DBG_ASSERT( pAct, "ScChangeActionDel::LoadLinks: missing Move" );
+ }
+ INT16 nFrom, nTo;
+ rStrm >> nFrom >> nTo;
+ ScChangeActionDelMoveEntry* pLink = new ScChangeActionDelMoveEntry(
+ &pLinkMove, pAct, nFrom, nTo );
+ if ( pAct )
+ pAct->AddLink( this, pLink );
+ }
+ if ( pCutOff )
+ {
+ pCutOff = (ScChangeActionIns*) pTrack->GetAction( (ULONG) pCutOff );
+ DBG_ASSERT( pCutOff, "ScChangeActionDel::LoadLinks: missing Insert" );
+ }
+
+ bOk &= ScChangeAction::LoadCellList( this, pFirstCell, rStrm, pTrack );
+
+ return bOk;
+}
+
+
+void ScChangeActionDel::AddContent( ScChangeActionContent* pContent )
+{
+ ScChangeActionCellListEntry* pE = new ScChangeActionCellListEntry(
+ pContent, pFirstCell );
+ pFirstCell = pE;
+}
+
+
+void ScChangeActionDel::DeleteCellEntries()
+{
+ pTrack->DeleteCellEntries( pFirstCell, this );
+}
+
+
+BOOL ScChangeActionDel::IsBaseDelete() const
+{
+ return !GetDx() && !GetDy();
+}
+
+
+BOOL ScChangeActionDel::IsTopDelete() const
+{
+ const ScChangeAction* p = GetNext();
+ if ( !p || p->GetType() != GetType() )
+ return TRUE;
+ return ((ScChangeActionDel*)p)->IsBaseDelete();
+}
+
+
+BOOL ScChangeActionDel::IsMultiDelete() const
+{
+ if ( GetDx() || GetDy() )
+ return TRUE;
+ const ScChangeAction* p = GetNext();
+ if ( !p || p->GetType() != GetType() )
+ return FALSE;
+ const ScChangeActionDel* pDel = (const ScChangeActionDel*) p;
+ if ( (pDel->GetDx() > GetDx() || pDel->GetDy() > GetDy()) &&
+ pDel->GetBigRange() == aBigRange )
+ return TRUE;
+ return FALSE;
+}
+
+
+BOOL ScChangeActionDel::IsTabDeleteCol() const
+{
+ if ( GetType() != SC_CAT_DELETE_COLS )
+ return FALSE;
+ const ScChangeAction* p = this;
+ while ( p && p->GetType() == SC_CAT_DELETE_COLS &&
+ !((const ScChangeActionDel*)p)->IsTopDelete() )
+ p = p->GetNext();
+ return p && p->GetType() == SC_CAT_DELETE_TABS;
+}
+
+
+void ScChangeActionDel::UpdateReference( const ScChangeTrack* pTrack,
+ UpdateRefMode eMode, const ScBigRange& rRange,
+ INT32 nDx, INT32 nDy, INT32 nDz )
+{
+ ScRefUpdate::Update( eMode, rRange, nDx, nDy, nDz, GetBigRange() );
+ if ( !IsDeletedIn() )
+ return ;
+ // evtl. in "druntergerutschten" anpassen
+ for ( ScChangeActionLinkEntry* pL = pLinkDeleted; pL; pL = pL->GetNext() )
+ {
+ ScChangeAction* p = pL->GetAction();
+ if ( p && p->GetType() == SC_CAT_CONTENT &&
+ !GetBigRange().In( p->GetBigRange() ) )
+ {
+ switch ( GetType() )
+ {
+ case SC_CAT_DELETE_COLS :
+ p->GetBigRange().aStart.SetCol( GetBigRange().aStart.Col() );
+ p->GetBigRange().aEnd.SetCol( GetBigRange().aStart.Col() );
+ break;
+ case SC_CAT_DELETE_ROWS :
+ p->GetBigRange().aStart.SetRow( GetBigRange().aStart.Row() );
+ p->GetBigRange().aEnd.SetRow( GetBigRange().aStart.Row() );
+ break;
+ case SC_CAT_DELETE_TABS :
+ p->GetBigRange().aStart.SetTab( GetBigRange().aStart.Tab() );
+ p->GetBigRange().aEnd.SetTab( GetBigRange().aStart.Tab() );
+ break;
+ }
+ }
+ }
+}
+
+
+ScBigRange ScChangeActionDel::GetOverAllRange() const
+{
+ ScBigRange aTmpRange( GetBigRange() );
+ aTmpRange.aEnd.SetCol( aTmpRange.aEnd.Col() + GetDx() );
+ aTmpRange.aEnd.SetRow( aTmpRange.aEnd.Row() + GetDy() );
+ return aTmpRange;
+}
+
+
+void ScChangeActionDel::GetDescription( String& rStr, ScDocument* pDoc,
+ BOOL bSplitRange ) const
+{
+ USHORT nWhatId;
+ switch ( GetType() )
+ {
+ case SC_CAT_DELETE_COLS :
+ nWhatId = STR_COLUMN;
+ break;
+ case SC_CAT_DELETE_ROWS :
+ nWhatId = STR_ROW;
+ break;
+ default:
+ nWhatId = STR_AREA;
+ }
+
+ ScBigRange aTmpRange( GetBigRange() );
+ if ( !IsRejected() )
+ {
+ if ( bSplitRange )
+ {
+ aTmpRange.aStart.SetCol( aTmpRange.aStart.Col() + GetDx() );
+ aTmpRange.aStart.SetRow( aTmpRange.aStart.Row() + GetDy() );
+ }
+ aTmpRange.aEnd.SetCol( aTmpRange.aEnd.Col() + GetDx() );
+ aTmpRange.aEnd.SetRow( aTmpRange.aEnd.Row() + GetDy() );
+ }
+
+ String aRsc( ScGlobal::GetRscString( STR_CHANGED_DELETE ) );
+ xub_StrLen nPos = aRsc.SearchAscii( "#1" );
+ rStr += aRsc.Copy( 0, nPos );
+ rStr += ScGlobal::GetRscString( nWhatId );
+ rStr += ' ';
+ rStr += GetRefString( aTmpRange, pDoc );
+ rStr += aRsc.Copy( nPos+2 );
+}
+
+
+BOOL ScChangeActionDel::Reject( ScDocument* pDoc )
+{
+ if ( !aBigRange.IsValid( pDoc ) && GetType() != SC_CAT_DELETE_TABS )
+ return FALSE;
+
+ BOOL bOk = TRUE;
+
+ if ( IsTopDelete() )
+ { // den kompletten Bereich in einem Rutsch restaurieren
+ ScBigRange aTmpRange( GetOverAllRange() );
+ if ( !aTmpRange.IsValid( pDoc ) )
+ {
+ if ( GetType() == SC_CAT_DELETE_TABS )
+ { // wird Tab angehaengt?
+ if ( aTmpRange.aStart.Tab() > pDoc->GetMaxTableNumber() )
+ bOk = FALSE;
+ }
+ else
+ bOk = FALSE;
+ }
+ if ( bOk )
+ {
+ ScRange aRange( aTmpRange.MakeRange() );
+ // InDelete... fuer Formel UpdateReference in Document
+ pTrack->SetInDeleteRange( aRange );
+ pTrack->SetInDeleteTop( TRUE );
+ pTrack->SetInDeleteUndo( TRUE );
+ pTrack->SetInDelete( TRUE );
+ switch ( GetType() )
+ {
+ case SC_CAT_DELETE_COLS :
+ if ( !(aRange.aStart.Col() == 0 && aRange.aEnd.Col() == MAXCOL) )
+ { // nur wenn nicht TabDelete
+ if ( bOk = pDoc->CanInsertCol( aRange ) )
+ bOk = pDoc->InsertCol( aRange );
+ }
+ break;
+ case SC_CAT_DELETE_ROWS :
+ if ( bOk = pDoc->CanInsertRow( aRange ) )
+ bOk = pDoc->InsertRow( aRange );
+ break;
+ case SC_CAT_DELETE_TABS :
+ {
+//2do: Tabellennamen merken?
+ String aName;
+ pDoc->CreateValidTabName( aName );
+ if ( bOk = pDoc->ValidNewTabName( aName ) )
+ bOk = pDoc->InsertTab( aRange.aStart.Tab(), aName );
+ }
+ break;
+ }
+ pTrack->SetInDelete( FALSE );
+ pTrack->SetInDeleteUndo( FALSE );
+ }
+ if ( !bOk )
+ {
+ pTrack->SetInDeleteTop( FALSE );
+ return FALSE;
+ }
+ // InDeleteTop fuer UpdateReference-Undo behalten
+ }
+
+ // setzt rejected und ruft UpdateReference-Undo und DeleteCellEntries
+ RejectRestoreContents( pTrack, GetDx(), GetDy() );
+
+ pTrack->SetInDeleteTop( FALSE );
+ RemoveAllLinks();
+ return TRUE;
+}
+
+
+void ScChangeActionDel::UndoCutOffMoves()
+{ // abgeschnittene Moves wiederherstellen, Entries/Links deleten
+ while ( pLinkMove )
+ {
+ ScChangeActionMove* pMove = pLinkMove->GetMove();
+ short nFrom = pLinkMove->GetCutOffFrom();
+ short nTo = pLinkMove->GetCutOffTo();
+ switch ( GetType() )
+ {
+ case SC_CAT_DELETE_COLS :
+ if ( nFrom > 0 )
+ pMove->GetFromRange().aStart.IncCol( -nFrom );
+ else if ( nFrom < 0 )
+ pMove->GetFromRange().aEnd.IncCol( -nFrom );
+ if ( nTo > 0 )
+ pMove->GetBigRange().aStart.IncCol( -nTo );
+ else if ( nTo < 0 )
+ pMove->GetBigRange().aEnd.IncCol( -nTo );
+ break;
+ case SC_CAT_DELETE_ROWS :
+ if ( nFrom > 0 )
+ pMove->GetFromRange().aStart.IncRow( -nFrom );
+ else if ( nFrom < 0 )
+ pMove->GetFromRange().aEnd.IncRow( -nFrom );
+ if ( nTo > 0 )
+ pMove->GetBigRange().aStart.IncRow( -nTo );
+ else if ( nTo < 0 )
+ pMove->GetBigRange().aEnd.IncRow( -nTo );
+ break;
+ case SC_CAT_DELETE_TABS :
+ if ( nFrom > 0 )
+ pMove->GetFromRange().aStart.IncTab( -nFrom );
+ else if ( nFrom < 0 )
+ pMove->GetFromRange().aEnd.IncTab( -nFrom );
+ if ( nTo > 0 )
+ pMove->GetBigRange().aStart.IncTab( -nTo );
+ else if ( nTo < 0 )
+ pMove->GetBigRange().aEnd.IncTab( -nTo );
+ break;
+ }
+ delete pLinkMove; // rueckt sich selbst hoch
+ }
+}
+
+void ScChangeActionDel::UndoCutOffInsert()
+{ // abgeschnittenes Insert wiederherstellen
+ if ( pCutOff )
+ {
+ switch ( pCutOff->GetType() )
+ {
+ case SC_CAT_INSERT_COLS :
+ if ( nCutOff < 0 )
+ pCutOff->GetBigRange().aEnd.IncCol( -nCutOff );
+ else
+ pCutOff->GetBigRange().aStart.IncCol( -nCutOff );
+ break;
+ case SC_CAT_INSERT_ROWS :
+ if ( nCutOff < 0 )
+ pCutOff->GetBigRange().aEnd.IncRow( -nCutOff );
+ else
+ pCutOff->GetBigRange().aStart.IncRow( -nCutOff );
+ break;
+ case SC_CAT_INSERT_TABS :
+ if ( nCutOff < 0 )
+ pCutOff->GetBigRange().aEnd.IncTab( -nCutOff );
+ else
+ pCutOff->GetBigRange().aStart.IncTab( -nCutOff );
+ break;
+ }
+ SetCutOffInsert( NULL, 0 );
+ }
+}
+
+
+// --- ScChangeActionMove --------------------------------------------------
+
+ScChangeActionMove::ScChangeActionMove( SvStream& rStrm,
+ ScMultipleReadHeader& rHdr, ScChangeTrack* pTrackP )
+ :
+ ScChangeAction( rStrm, rHdr, pTrackP ),
+ pTrack( pTrackP ),
+ pFirstCell( NULL ),
+ nStartLastCut(0),
+ nEndLastCut(0)
+{
+ rStrm >> aFromRange;
+}
+
+
+ScChangeActionMove::~ScChangeActionMove()
+{
+ DeleteCellEntries();
+}
+
+
+BOOL ScChangeActionMove::Store( SvStream& rStrm, ScMultipleWriteHeader& rHdr ) const
+{
+ BOOL bOk = ScChangeAction::Store( rStrm, rHdr );
+ rStrm << aFromRange;
+ return bOk;
+}
+
+
+BOOL ScChangeActionMove::StoreLinks( SvStream& rStrm ) const
+{
+ BOOL bOk = ScChangeAction::StoreLinks( rStrm );
+ bOk &= ScChangeAction::StoreCellList( pFirstCell, rStrm );
+ return bOk;
+}
+
+
+BOOL ScChangeActionMove::LoadLinks( SvStream& rStrm, ScChangeTrack* pTrack )
+{
+ BOOL bOk = ScChangeAction::LoadLinks( rStrm, pTrack );
+ bOk &= ScChangeAction::LoadCellList( this, pFirstCell, rStrm, pTrack );
+ return bOk;
+}
+
+
+void ScChangeActionMove::AddContent( ScChangeActionContent* pContent )
+{
+ ScChangeActionCellListEntry* pE = new ScChangeActionCellListEntry(
+ pContent, pFirstCell );
+ pFirstCell = pE;
+}
+
+
+void ScChangeActionMove::DeleteCellEntries()
+{
+ pTrack->DeleteCellEntries( pFirstCell, this );
+}
+
+
+void ScChangeActionMove::UpdateReference( const ScChangeTrack* pTrack,
+ UpdateRefMode eMode, const ScBigRange& rRange,
+ INT32 nDx, INT32 nDy, INT32 nDz )
+{
+ ScRefUpdate::Update( eMode, rRange, nDx, nDy, nDz, aFromRange );
+ ScRefUpdate::Update( eMode, rRange, nDx, nDy, nDz, GetBigRange() );
+}
+
+
+void ScChangeActionMove::GetDelta( INT32& nDx, INT32& nDy, INT32& nDz ) const
+{
+ const ScBigAddress& rToPos = GetBigRange().aStart;
+ const ScBigAddress& rFromPos = GetFromRange().aStart;
+ nDx = rToPos.Col() - rFromPos.Col();
+ nDy = rToPos.Row() - rFromPos.Row();
+ nDz = rToPos.Tab() - rFromPos.Tab();
+}
+
+
+void ScChangeActionMove::GetDescription( String& rStr, ScDocument* pDoc,
+ BOOL bSplitRange ) const
+{
+ BOOL bFlag3D = ( GetFromRange().aStart.Tab() != GetBigRange().aStart.Tab() );
+
+ String aRsc( ScGlobal::GetRscString( STR_CHANGED_MOVE ) );
+
+ xub_StrLen nPos = 0;
+ String aTmpStr = ScChangeAction::GetRefString( GetFromRange(), pDoc, bFlag3D );
+ nPos = aRsc.SearchAscii( "#1", nPos );
+ aRsc.Erase( nPos, 2 );
+ aRsc.Insert( aTmpStr, nPos );
+ nPos += aTmpStr.Len();
+
+ aTmpStr = ScChangeAction::GetRefString( GetBigRange(), pDoc, bFlag3D );
+ nPos = aRsc.SearchAscii( "#2", nPos );
+ aRsc.Erase( nPos, 2 );
+ aRsc.Insert( aTmpStr, nPos );
+ nPos += aTmpStr.Len();
+
+ rStr += aRsc;
+}
+
+
+void ScChangeActionMove::GetRefString( String& rStr, ScDocument* pDoc,
+ BOOL bFlag3D ) const
+{
+ if ( !bFlag3D )
+ bFlag3D = ( GetFromRange().aStart.Tab() != GetBigRange().aStart.Tab() );
+ rStr = ScChangeAction::GetRefString( GetFromRange(), pDoc, bFlag3D );
+ rStr += ',';
+ rStr += ' ';
+ rStr += ScChangeAction::GetRefString( GetBigRange(), pDoc, bFlag3D );
+}
+
+
+BOOL ScChangeActionMove::Reject( ScDocument* pDoc )
+{
+ if ( !(aBigRange.IsValid( pDoc ) && aFromRange.IsValid( pDoc )) )
+ return FALSE;
+
+ ScRange aToRange( aBigRange.MakeRange() );
+ ScRange aFrmRange( aFromRange.MakeRange() );
+
+ BOOL bOk = pDoc->IsBlockEditable( aToRange.aStart.Tab(),
+ aToRange.aStart.Col(), aToRange.aStart.Row(),
+ aToRange.aEnd.Col(), aToRange.aEnd.Row() );
+ if ( bOk )
+ bOk = pDoc->IsBlockEditable( aFrmRange.aStart.Tab(),
+ aFrmRange.aStart.Col(), aFrmRange.aStart.Row(),
+ aFrmRange.aEnd.Col(), aFrmRange.aEnd.Row() );
+ if ( !bOk )
+ return FALSE;
+
+ pTrack->LookUpContents( aToRange, pDoc, 0, 0, 0 ); // zu movende Contents
+
+ pDoc->DeleteAreaTab( aToRange, IDF_ALL );
+ pDoc->DeleteAreaTab( aFrmRange, IDF_ALL );
+ // Formeln im Dokument anpassen
+ pDoc->UpdateReference( URM_MOVE,
+ aFrmRange.aStart.Col(), aFrmRange.aStart.Row(), aFrmRange.aStart.Tab(),
+ aFrmRange.aEnd.Col(), aFrmRange.aEnd.Row(), aFrmRange.aEnd.Tab(),
+ (short) aFrmRange.aStart.Col() - aToRange.aStart.Col(),
+ (short) aFrmRange.aStart.Row() - aToRange.aStart.Row(),
+ (short) aFrmRange.aStart.Tab() - aToRange.aStart.Tab(), NULL );
+
+ // LinkDependent freigeben, nachfolgendes UpdateReference-Undo setzt
+ // ToRange->FromRange Dependents
+ RemoveAllDependent();
+
+ // setzt rejected und ruft UpdateReference-Undo und DeleteCellEntries
+ RejectRestoreContents( pTrack, 0, 0 );
+
+ while ( pLinkDependent )
+ {
+ ScChangeAction* p = pLinkDependent->GetAction();
+ if ( p && p->GetType() == SC_CAT_CONTENT )
+ {
+ ScChangeActionContent* pContent = (ScChangeActionContent*) p;
+ if ( !pContent->IsDeletedIn() &&
+ pContent->GetBigRange().aStart.IsValid( pDoc ) )
+ pContent->PutNewValueToDoc( pDoc, 0, 0 );
+ // in LookUpContents generierte loeschen
+ if ( pTrack->IsGenerated( pContent->GetActionNumber() ) &&
+ !pContent->IsDeletedIn() )
+ {
+ pLinkDependent->UnLink(); //! sonst wird der mitgeloescht
+ pTrack->DeleteGeneratedDelContent( pContent );
+ }
+ }
+ delete pLinkDependent;
+ }
+
+ RemoveAllLinks();
+ return TRUE;
+}
+
+
+// --- ScChangeActionContent -----------------------------------------------
+
+const USHORT nMemPoolChangeActionContent = (0x8000 - 64) / sizeof(ScChangeActionContent);
+IMPL_FIXEDMEMPOOL_NEWDEL( ScChangeActionContent, nMemPoolChangeActionContent, nMemPoolChangeActionContent );
+
+
+ScChangeActionContent::ScChangeActionContent( SvStream& rStrm,
+ ScMultipleReadHeader& rHdr, ScDocument* pDoc, USHORT nVer,
+ ScChangeTrack* pTrack )
+ :
+ ScChangeAction( rStrm, rHdr, pTrack ),
+ pNextInSlot( NULL ),
+ ppPrevInSlot( NULL )
+{
+ UINT32 n32;
+ rStrm.ReadByteString( aOldValue, rStrm.GetStreamCharSet() );
+ rStrm.ReadByteString( aNewValue, rStrm.GetStreamCharSet() );
+ rStrm >> n32; pNextContent = (ScChangeActionContent*)(ULONG) n32;
+ rStrm >> n32; pPrevContent = (ScChangeActionContent*)(ULONG) n32;
+
+ {
+ ScMultipleReadHeader aDataHdr( rStrm );
+ pOldCell = ScChangeAction::LoadCell( rStrm, aDataHdr, pDoc, nVer );
+ pNewCell = ScChangeAction::LoadCell( rStrm, aDataHdr, pDoc, nVer );
+ }
+}
+
+
+ScChangeActionContent::~ScChangeActionContent()
+{
+ ClearTrack();
+}
+
+
+void ScChangeActionContent::ClearTrack()
+{
+ RemoveFromSlot();
+ if ( pPrevContent )
+ pPrevContent->pNextContent = pNextContent;
+ if ( pNextContent )
+ pNextContent->pPrevContent = pPrevContent;
+}
+
+
+BOOL ScChangeActionContent::Store( SvStream& rStrm, ScMultipleWriteHeader& rHdr ) const
+{
+ BOOL bOk = ScChangeAction::Store( rStrm, rHdr );
+ rStrm.WriteByteString( aOldValue, rStrm.GetStreamCharSet() );
+ rStrm.WriteByteString( aNewValue, rStrm.GetStreamCharSet() );
+ rStrm << (UINT32) ( pNextContent ? pNextContent->GetActionNumber() : 0 );
+ rStrm << (UINT32) ( pPrevContent ? pPrevContent->GetActionNumber() : 0 );
+
+ {
+ ScMultipleWriteHeader aDataHdr( rStrm );
+ ScChangeAction::StoreCell( pOldCell, rStrm, aDataHdr );
+ ScChangeAction::StoreCell( pNewCell, rStrm, aDataHdr );
+ }
+
+ return bOk;
+}
+
+
+BOOL ScChangeActionContent::StoreLinks( SvStream& rStrm ) const
+{
+ BOOL bOk = ScChangeAction::StoreLinks( rStrm );
+ return bOk;
+}
+
+
+BOOL ScChangeActionContent::LoadLinks( SvStream& rStrm, ScChangeTrack* pTrack )
+{
+ BOOL bOk = ScChangeAction::LoadLinks( rStrm, pTrack );
+ if ( pNextContent )
+ {
+ pNextContent = (ScChangeActionContent*) pTrack->GetAction(
+ (ULONG) pNextContent );
+ DBG_ASSERT( pNextContent,
+ "ScChangeActionContent::LoadLinks: missing NextContent" );
+ }
+ if ( pPrevContent )
+ {
+ pPrevContent = (ScChangeActionContent*) pTrack->GetAction(
+ (ULONG) pPrevContent );
+ DBG_ASSERT( pPrevContent,
+ "ScChangeActionContent::LoadLinks: missing PrevContent" );
+ }
+ return bOk;
+}
+
+
+ScChangeActionContent* ScChangeActionContent::GetTopContent() const
+{
+ if ( pNextContent )
+ {
+ ScChangeActionContent* pContent = pNextContent;
+ while ( pContent->pNextContent )
+ pContent = pContent->pNextContent;
+ return pContent;
+ }
+ return (ScChangeActionContent*) this;
+}
+
+
+ScChangeActionLinkEntry* ScChangeActionContent::GetDeletedIn() const
+{
+ if ( pNextContent )
+ return GetTopContent()->pLinkDeletedIn;
+ return pLinkDeletedIn;
+}
+
+
+ScChangeActionLinkEntry** ScChangeActionContent::GetDeletedInAddress()
+{
+ if ( pNextContent )
+ return GetTopContent()->GetDeletedInAddress();
+ return &pLinkDeletedIn;
+}
+
+
+void ScChangeActionContent::SetOldValue( const ScBaseCell* pCell,
+ const ScDocument* pFromDoc, ScDocument* pToDoc, ULONG nFormat )
+{
+ ScChangeActionContent::SetValue( aOldValue, pOldCell,
+ nFormat, pCell, pFromDoc, pToDoc );
+}
+
+
+void ScChangeActionContent::SetOldValue( const ScBaseCell* pCell,
+ const ScDocument* pFromDoc, ScDocument* pToDoc )
+{
+ ScChangeActionContent::SetValue( aOldValue, pOldCell,
+ aBigRange.aStart.MakeAddress(), pCell, pFromDoc, pToDoc );
+}
+
+
+void ScChangeActionContent::SetNewValue( const ScBaseCell* pCell,
+ ScDocument* pDoc )
+{
+ ScChangeActionContent::SetValue( aNewValue, pNewCell,
+ aBigRange.aStart.MakeAddress(), pCell, pDoc, pDoc );
+}
+
+
+void ScChangeActionContent::SetValueString( String& rValue, ScBaseCell*& pCell,
+ const String& rStr, ScDocument* pDoc )
+{
+ if ( pCell )
+ {
+ pCell->Delete();
+ pCell = NULL;
+ }
+ if ( rStr.Len() > 1 && rStr.GetChar(0) == '=' )
+ {
+ rValue.Erase();
+ pCell = new ScFormulaCell(
+ pDoc, aBigRange.aStart.MakeAddress(), rStr );
+ ((ScFormulaCell*)pCell)->SetInChangeTrack( TRUE );
+ }
+ else
+ rValue = rStr;
+}
+
+
+void ScChangeActionContent::SetOldValue( const String& rOld, ScDocument* pDoc )
+{
+ SetValueString( aOldValue, pOldCell, rOld, pDoc );
+}
+
+
+void ScChangeActionContent::SetNewValue( const String& rNew, ScDocument* pDoc )
+{
+ SetValueString( aNewValue, pNewCell, rNew, pDoc );
+}
+
+
+void ScChangeActionContent::GetOldString( String& rStr ) const
+{
+ GetValueString( rStr, aOldValue, pOldCell );
+}
+
+
+void ScChangeActionContent::GetNewString( String& rStr ) const
+{
+ GetValueString( rStr, aNewValue, pNewCell );
+}
+
+
+void ScChangeActionContent::GetDescription( String& rStr, ScDocument* pDoc,
+ BOOL bSplitRange ) const
+{
+
+ String aRsc( ScGlobal::GetRscString( STR_CHANGED_CELL ) );
+
+ String aTmpStr;
+ GetRefString( aTmpStr, pDoc );
+
+ xub_StrLen nPos = 0;
+ nPos = aRsc.SearchAscii( "#1", nPos );
+ aRsc.Erase( nPos, 2 );
+ aRsc.Insert( aTmpStr, nPos );
+ nPos += aTmpStr.Len();
+
+ GetOldString( aTmpStr );
+ if ( !aTmpStr.Len() )
+ aTmpStr = ScGlobal::GetRscString( STR_CHANGED_BLANK );
+ nPos = aRsc.SearchAscii( "#2", nPos );
+ aRsc.Erase( nPos, 2 );
+ aRsc.Insert( aTmpStr, nPos );
+ nPos += aTmpStr.Len();
+
+ GetNewString( aTmpStr );
+ if ( !aTmpStr.Len() )
+ aTmpStr = ScGlobal::GetRscString( STR_CHANGED_BLANK );
+ nPos = aRsc.SearchAscii( "#3", nPos );
+ aRsc.Erase( nPos, 2 );
+ aRsc.Insert( aTmpStr, nPos );
+
+ rStr += aRsc;
+}
+
+
+void ScChangeActionContent::GetRefString( String& rStr, ScDocument* pDoc,
+ BOOL bFlag3D ) const
+{
+ USHORT nFlags = ( GetBigRange().IsValid( pDoc ) ? SCA_VALID : 0 );
+ if ( nFlags )
+ {
+ ScAddress aTmpAddress( GetBigRange().aStart.MakeAddress() );
+ if ( bFlag3D )
+ nFlags |= SCA_TAB_3D;
+ aTmpAddress.Format( rStr, nFlags, pDoc );
+ if ( IsDeletedIn() )
+ {
+ rStr.Insert( '(', 0 );
+ rStr += ')';
+ }
+ }
+ else
+ rStr = ScGlobal::GetRscString( STR_NOREF_STR );
+}
+
+
+BOOL ScChangeActionContent::Reject( ScDocument* pDoc )
+{
+ if ( !aBigRange.IsValid( pDoc ) )
+ return FALSE;
+
+ PutOldValueToDoc( pDoc, 0, 0 );
+
+ SetState( SC_CAS_REJECTED );
+ RemoveAllLinks();
+
+ return TRUE;
+}
+
+
+BOOL ScChangeActionContent::Select( ScDocument* pDoc, ScChangeTrack* pTrack,
+ BOOL bOldest )
+{
+ if ( !aBigRange.IsValid( pDoc ) )
+ return FALSE;
+
+ ScChangeActionContent* pContent = this;
+ // vorherige Werte akzeptieren
+ while ( (pContent = pContent->pPrevContent) && pContent->IsVirgin() )
+ pContent->SetState( SC_CAS_ACCEPTED );
+ ScChangeActionContent* pEnd = pContent = this;
+ // nachfolgende Werte ablehnen
+ while ( pContent = pContent->pNextContent )
+ {
+ pContent->SetRejected();
+ pEnd = pContent;
+ }
+
+ if ( bOldest || pEnd != this )
+ { // wenn nicht aeltester: ist es ueberhaupt ein anderer als der letzte?
+ ScRange aRange( aBigRange.aStart.MakeAddress() );
+ const ScAddress& rPos = aRange.aStart;
+
+ ScChangeActionContent* pNew = new ScChangeActionContent( aRange );
+ pNew->SetOldValue( pDoc->GetCell( rPos ), pDoc, pDoc );
+
+ if ( bOldest )
+ PutOldValueToDoc( pDoc, 0, 0 );
+ else
+ PutNewValueToDoc( pDoc, 0, 0 );
+
+ pNew->SetNewValue( pDoc->GetCell( rPos ), pDoc );
+ pNew->SetRejectAction( bOldest ? GetActionNumber() : pEnd->GetActionNumber() );
+ pNew->SetState( SC_CAS_ACCEPTED );
+ pTrack->Append( pNew );
+ }
+
+ if ( bOldest )
+ SetRejected();
+ else
+ SetState( SC_CAS_ACCEPTED );
+
+ return TRUE;
+}
+
+
+// static
+void ScChangeActionContent::GetStringOfCell( String& rStr,
+ const ScBaseCell* pCell, const ScDocument* pDoc, const ScAddress& rPos )
+{
+ if ( pCell )
+ {
+ if ( ScChangeActionContent::NeedsNumberFormat( pCell ) )
+ GetStringOfCell( rStr, pCell, pDoc, pDoc->GetNumberFormat( rPos ) );
+ else
+ GetStringOfCell( rStr, pCell, pDoc, 0 );
+ }
+ else
+ rStr.Erase();
+}
+
+
+// static
+void ScChangeActionContent::GetStringOfCell( String& rStr,
+ const ScBaseCell* pCell, const ScDocument* pDoc, ULONG nFormat )
+{
+ if ( ScChangeActionContent::IsContentCellType( pCell ) )
+ {
+ switch ( pCell->GetCellType() )
+ {
+ case CELLTYPE_VALUE :
+ {
+ double nValue = ((ScValueCell*)pCell)->GetValue();
+ pDoc->GetFormatTable()->GetInputLineString( nValue, nFormat,
+ rStr );
+ }
+ break;
+ case CELLTYPE_STRING :
+ ((ScStringCell*)pCell)->GetString( rStr );
+ break;
+ case CELLTYPE_EDIT :
+ ((ScEditCell*)pCell)->GetString( rStr );
+ break;
+ case CELLTYPE_FORMULA :
+ ((ScFormulaCell*)pCell)->GetFormula( rStr );
+ break;
+ default:
+ rStr.Erase();
+ }
+ }
+ else
+ rStr.Erase();
+}
+
+
+// static
+BOOL ScChangeActionContent::IsContentCellType( const ScBaseCell* pCell )
+{
+ if ( pCell )
+ {
+ switch ( pCell->GetCellType() )
+ {
+ case CELLTYPE_VALUE :
+ case CELLTYPE_STRING :
+ case CELLTYPE_EDIT :
+ case CELLTYPE_FORMULA :
+ return TRUE;
+ break;
+ default:
+ return FALSE;
+ }
+ }
+ return FALSE;
+}
+
+
+// static
+BOOL ScChangeActionContent::NeedsNumberFormat( const ScBaseCell* pCell )
+{
+ return pCell && pCell->GetCellType() == CELLTYPE_VALUE;
+}
+
+
+// static
+void ScChangeActionContent::SetValue( String& rStr, ScBaseCell*& pCell,
+ const ScAddress& rPos, const ScBaseCell* pOrgCell,
+ const ScDocument* pFromDoc, ScDocument* pToDoc )
+{
+ if ( ScChangeActionContent::NeedsNumberFormat( pOrgCell ) )
+ ScChangeActionContent::SetValue( rStr, pCell,
+ pFromDoc->GetNumberFormat( rPos ), pOrgCell, pFromDoc, pToDoc );
+ else
+ ScChangeActionContent::SetValue( rStr, pCell,
+ 0, pOrgCell, pFromDoc, pToDoc );
+}
+
+
+// static
+void ScChangeActionContent::SetValue( String& rStr, ScBaseCell*& pCell,
+ ULONG nFormat, const ScBaseCell* pOrgCell,
+ const ScDocument* pFromDoc, ScDocument* pToDoc )
+{
+ rStr.Erase();
+ if ( pCell )
+ pCell->Delete();
+ if ( ScChangeActionContent::IsContentCellType( pOrgCell ) )
+ {
+ pCell = pOrgCell->Clone( pToDoc );
+ switch ( pOrgCell->GetCellType() )
+ {
+ case CELLTYPE_VALUE :
+ { // z.B. Datum auch als solches merken
+ double nValue = ((ScValueCell*)pOrgCell)->GetValue();
+ pFromDoc->GetFormatTable()->GetInputLineString( nValue,
+ nFormat, rStr );
+ }
+ break;
+ case CELLTYPE_FORMULA :
+ ((ScFormulaCell*)pCell)->SetInChangeTrack( TRUE );
+ break;
+ }
+ }
+ else
+ pCell = NULL;
+}
+
+
+void ScChangeActionContent::GetValueString( String& rStr,
+ const String& rValue, const ScBaseCell* pCell ) const
+{
+ if ( !rValue.Len() )
+ {
+ if ( pCell )
+ {
+ switch ( pCell->GetCellType() )
+ {
+ case CELLTYPE_STRING :
+ ((ScStringCell*)pCell)->GetString( rStr );
+ break;
+ case CELLTYPE_EDIT :
+ ((ScEditCell*)pCell)->GetString( rStr );
+ break;
+ case CELLTYPE_VALUE : // ist immer in rValue
+ rStr = rValue;
+ break;
+ case CELLTYPE_FORMULA :
+ GetFormulaString( rStr, (ScFormulaCell*) pCell );
+ break;
+ }
+ }
+ else
+ rStr.Erase();
+ }
+ else
+ rStr = rValue;
+}
+
+
+void ScChangeActionContent::GetFormulaString( String& rStr,
+ const ScFormulaCell* pCell ) const
+{
+ ScAddress aPos( aBigRange.aStart.MakeAddress() );
+ if ( aPos == pCell->aPos )
+ pCell->GetFormula( rStr );
+ else
+ {
+ DBG_ERROR( "ScChangeActionContent::GetFormulaString: aPos != pCell->aPos" );
+ ScFormulaCell* pNew = (ScFormulaCell*) pCell->Clone(
+ pCell->GetDocument(), aPos, TRUE ); // TRUE: bNoListening
+ pNew->GetFormula( rStr );
+ delete pNew;
+ }
+}
+
+
+void ScChangeActionContent::PutOldValueToDoc( ScDocument* pDoc,
+ short nDx, short nDy ) const
+{
+ PutValueToDoc( pOldCell, aOldValue, pDoc, nDx, nDy );
+}
+
+
+void ScChangeActionContent::PutNewValueToDoc( ScDocument* pDoc,
+ short nDx, short nDy ) const
+{
+ PutValueToDoc( pNewCell, aNewValue, pDoc, nDx, nDy );
+}
+
+
+void ScChangeActionContent::PutValueToDoc( ScBaseCell* pCell,
+ const String& rValue, ScDocument* pDoc, short nDx, short nDy ) const
+{
+ ScAddress aPos( aBigRange.aStart.MakeAddress() );
+ if ( nDx )
+ aPos.IncCol( nDx );
+ if ( nDy )
+ aPos.IncRow( nDy );
+ if ( !rValue.Len() )
+ {
+ if ( pCell )
+ {
+ switch ( pCell->GetCellType() )
+ {
+ case CELLTYPE_VALUE : // ist immer in rValue
+ pDoc->SetString( aPos.Col(), aPos.Row(), aPos.Tab(), rValue );
+ break;
+ default:
+ pDoc->PutCell( aPos, pCell->Clone( pDoc ) );
+ }
+ }
+ else
+ pDoc->PutCell( aPos, NULL );
+ }
+ else
+ pDoc->SetString( aPos.Col(), aPos.Row(), aPos.Tab(), rValue );
+}
+
+
+void lcl_InvalidateReference( ComplRefData& rRef, const ScBigAddress& rPos )
+{
+ if ( rPos.Col() < 0 || MAXCOL < rPos.Col() )
+ {
+ rRef.Ref1.nCol = (INT16)(~0);
+ rRef.Ref1.nRelCol = (INT16)(~0);
+ rRef.Ref1.SetColDeleted( TRUE );
+ rRef.Ref2.nCol = (INT16)(~0);
+ rRef.Ref2.nRelCol = (INT16)(~0);
+ rRef.Ref2.SetColDeleted( TRUE );
+ }
+ if ( rPos.Row() < 0 || MAXROW < rPos.Row() )
+ {
+ rRef.Ref1.nRow = (INT16)(~0);
+ rRef.Ref1.nRelRow = (INT16)(~0);
+ rRef.Ref1.SetRowDeleted( TRUE );
+ rRef.Ref2.nRow = (INT16)(~0);
+ rRef.Ref2.nRelRow = (INT16)(~0);
+ rRef.Ref2.SetRowDeleted( TRUE );
+ }
+ if ( rPos.Tab() < 0 || MAXTAB < rPos.Tab() )
+ {
+ rRef.Ref1.nTab = (INT16)(~0);
+ rRef.Ref1.nRelTab = (INT16)(~0);
+ rRef.Ref1.SetTabDeleted( TRUE );
+ rRef.Ref2.nTab = (INT16)(~0);
+ rRef.Ref2.nRelTab = (INT16)(~0);
+ rRef.Ref2.SetTabDeleted( TRUE );
+ }
+}
+
+
+void ScChangeActionContent::UpdateReference( const ScChangeTrack* pTrack,
+ UpdateRefMode eMode, const ScBigRange& rRange,
+ INT32 nDx, INT32 nDy, INT32 nDz )
+{
+ USHORT nOldSlot = ScChangeTrack::ComputeContentSlot( aBigRange.aStart.Row() );
+ ScRefUpdate::Update( eMode, rRange, nDx, nDy, nDz, aBigRange );
+ USHORT nNewSlot = ScChangeTrack::ComputeContentSlot( aBigRange.aStart.Row() );
+ if ( nNewSlot != nOldSlot )
+ {
+ RemoveFromSlot();
+ InsertInSlot( &(pTrack->GetContentSlots()[nNewSlot]) );
+ }
+
+ if ( pTrack->IsInDelete() && !pTrack->IsInDeleteTop() )
+ return ; // Formeln nur kompletten Bereich updaten
+
+ BOOL bOldFormula = ( pOldCell && pOldCell->GetCellType() == CELLTYPE_FORMULA );
+ BOOL bNewFormula = ( pNewCell && pNewCell->GetCellType() == CELLTYPE_FORMULA );
+ if ( bOldFormula || bNewFormula )
+ { // via ScFormulaCell UpdateReference anpassen (dort)
+ if ( pTrack->IsInDelete() )
+ {
+ const ScRange& rDelRange = pTrack->GetInDeleteRange();
+ if ( nDx > 0 )
+ nDx = rDelRange.aEnd.Col() - rDelRange.aStart.Col() + 1;
+ else if ( nDx < 0 )
+ nDx = -(rDelRange.aEnd.Col() - rDelRange.aStart.Col() + 1);
+ if ( nDy > 0 )
+ nDy = rDelRange.aEnd.Row() - rDelRange.aStart.Row() + 1;
+ else if ( nDy < 0 )
+ nDy = -(rDelRange.aEnd.Row() - rDelRange.aStart.Row() + 1);
+ if ( nDz > 0 )
+ nDz = rDelRange.aEnd.Tab() - rDelRange.aStart.Tab() + 1;
+ else if ( nDz < 0 )
+ nDz = -(rDelRange.aEnd.Tab() - rDelRange.aStart.Tab() + 1);
+ }
+ ScBigRange aTmpRange( rRange );
+ switch ( eMode )
+ {
+ case URM_INSDEL :
+ if ( nDx < 0 || nDy < 0 || nDz < 0 )
+ { // Delete startet dort hinter geloeschtem Bereich,
+ // Position wird dort angepasst.
+ if ( nDx )
+ aTmpRange.aStart.IncCol( -nDx );
+ if ( nDy )
+ aTmpRange.aStart.IncRow( -nDy );
+ if ( nDz )
+ aTmpRange.aStart.IncTab( -nDz );
+ }
+ break;
+ case URM_MOVE :
+ // Move ist hier Quelle, dort Ziel,
+ // Position muss vorher angepasst sein.
+ if ( bOldFormula )
+ ((ScFormulaCell*)pOldCell)->aPos = aBigRange.aStart.MakeAddress();
+ if ( bNewFormula )
+ ((ScFormulaCell*)pNewCell)->aPos = aBigRange.aStart.MakeAddress();
+ if ( nDx )
+ {
+ aTmpRange.aStart.IncCol( nDx );
+ aTmpRange.aEnd.IncCol( nDx );
+ }
+ if ( nDy )
+ {
+ aTmpRange.aStart.IncRow( nDy );
+ aTmpRange.aEnd.IncRow( nDy );
+ }
+ if ( nDz )
+ {
+ aTmpRange.aStart.IncTab( nDz );
+ aTmpRange.aEnd.IncTab( nDz );
+ }
+ break;
+ }
+ ScRange aRange( aTmpRange.MakeRange() );
+ if ( bOldFormula )
+ ((ScFormulaCell*)pOldCell)->UpdateReference( eMode, aRange,
+ (short) nDx, (short) nDy, (short) nDz, NULL );
+ if ( bNewFormula )
+ ((ScFormulaCell*)pNewCell)->UpdateReference( eMode, aRange,
+ (short) nDx, (short) nDy, (short) nDz, NULL );
+ if ( !aBigRange.aStart.IsValid( pTrack->GetDocument() ) )
+ { //! HACK!
+ //! UpdateReference kann nicht mit Positionen ausserhalb des
+ //! Dokuments umgehen, deswegen alles auf #REF! setzen
+//2do: make it possible! das bedeutet grossen Umbau von ScAddress etc.!
+ const ScBigAddress& rPos = aBigRange.aStart;
+ if ( bOldFormula )
+ {
+ ScToken* t;
+ ScTokenArray* pArr = ((ScFormulaCell*)pOldCell)->GetCode();
+ pArr->Reset();
+ while ( t = pArr->GetNextReference() )
+ lcl_InvalidateReference( t->aRef, rPos );
+ pArr->Reset();
+ while ( t = pArr->GetNextReferenceRPN() )
+ lcl_InvalidateReference( t->aRef, rPos );
+ }
+ if ( bNewFormula )
+ {
+ ScToken* t;
+ ScTokenArray* pArr = ((ScFormulaCell*)pNewCell)->GetCode();
+ pArr->Reset();
+ while ( t = pArr->GetNextReference() )
+ lcl_InvalidateReference( t->aRef, rPos );
+ pArr->Reset();
+ while ( t = pArr->GetNextReferenceRPN() )
+ lcl_InvalidateReference( t->aRef, rPos );
+ }
+ }
+ }
+}
+
+
+// --- ScChangeActionReject ------------------------------------------------
+
+ScChangeActionReject::ScChangeActionReject( SvStream& rStrm,
+ ScMultipleReadHeader& rHdr, ScChangeTrack* pTrack )
+ :
+ ScChangeAction( rStrm, rHdr, pTrack )
+{
+}
+
+
+BOOL ScChangeActionReject::Store( SvStream& rStrm, ScMultipleWriteHeader& rHdr ) const
+{
+ BOOL bOk = ScChangeAction::Store( rStrm, rHdr );
+ return TRUE;
+}
+
+
+// --- ScChangeTrack -------------------------------------------------------
+
+IMPL_FIXEDMEMPOOL_NEWDEL( ScChangeTrackMsgInfo, 16, 16 );
+
+const USHORT ScChangeTrack::nContentRowsPerSlot = InitContentRowsPerSlot();
+const USHORT ScChangeTrack::nContentSlots =
+ (MAXROW+1) / InitContentRowsPerSlot() + 2;
+
+// static
+USHORT ScChangeTrack::InitContentRowsPerSlot()
+{
+ const USHORT nMaxSlots = 0xffe0 / sizeof( ScChangeActionContent* ) - 2;
+ USHORT nRowsPerSlot = (MAXROW+1) / nMaxSlots;
+ if ( nRowsPerSlot * nMaxSlots < (MAXROW+1) )
+ ++nRowsPerSlot;
+ return nRowsPerSlot;
+}
+
+
+ScChangeTrack::ScChangeTrack( ScDocument* pDocP ) :
+ pDoc( pDocP )
+{
+ Init();
+ StartListening( *SfxGetpApp() );
+ ppContentSlots = new ScChangeActionContent* [ nContentSlots ];
+ memset( ppContentSlots, 0, nContentSlots * sizeof( ScChangeActionContent* ) );
+}
+
+
+ScChangeTrack::~ScChangeTrack()
+{
+ DtorClear();
+ delete ppContentSlots;
+}
+
+
+void ScChangeTrack::Init()
+{
+ pFirst = NULL;
+ pLast = NULL;
+ pFirstGeneratedDelContent = NULL;
+ pLastCutMove = NULL;
+ pLinkInsertCol = NULL;
+ pLinkInsertRow = NULL;
+ pLinkInsertTab = NULL;
+ pLinkMove = NULL;
+ pBlockModifyMsg = NULL;
+ nActionMax = 0;
+ nGeneratedMin = SC_CHGTRACK_GENERATED_START;
+ nMarkLastSaved = 0;
+ nStartLastCut = 0;
+ nEndLastCut = 0;
+ nLastMerge = 0;
+ eMergeState = SC_CTMS_NONE;
+ nLoadedFileFormatVersion = SC_CHGTRACK_FILEFORMAT;
+ bLoadSave = FALSE;
+ bInDelete = FALSE;
+ bInDeleteTop = FALSE;
+ bInDeleteUndo = FALSE;
+ bInPasteCut = FALSE;
+ bUseFixDateTime = FALSE;
+
+ aUser = SFX_INIMANAGER()->Get( SFX_KEY_USER_FIRSTNAME );
+ aUser += ' ';
+ aUser += SFX_INIMANAGER()->Get( SFX_KEY_USER_NAME );
+ aUserCollection.Insert( new StrData( aUser ) );
+}
+
+
+void ScChangeTrack::DtorClear()
+{
+ ScChangeAction* p;
+ ScChangeAction* pNext;
+ for ( p = GetFirst(); p; p = pNext )
+ {
+ pNext = p->GetNext();
+ delete p;
+ }
+ for ( p = pFirstGeneratedDelContent; p; p = pNext )
+ {
+ pNext = p->GetNext();
+ delete p;
+ }
+ for ( p = aPasteCutTable.First(); p; p = aPasteCutTable.Next() )
+ {
+ delete p;
+ }
+ delete pLastCutMove;
+ ClearMsgQueue();
+}
+
+
+void ScChangeTrack::ClearMsgQueue()
+{
+ if ( pBlockModifyMsg )
+ {
+ delete pBlockModifyMsg;
+ pBlockModifyMsg = NULL;
+ }
+ ScChangeTrackMsgInfo* pMsgInfo;
+ while ( pMsgInfo = aMsgStackTmp.Pop() )
+ delete pMsgInfo;
+ while ( pMsgInfo = aMsgStackFinal.Pop() )
+ delete pMsgInfo;
+ while ( pMsgInfo = aMsgQueue.Get() )
+ delete pMsgInfo;
+}
+
+
+void ScChangeTrack::Clear()
+{
+ DtorClear();
+ aTable.Clear();
+ aGeneratedTable.Clear();
+ aPasteCutTable.Clear();
+ aUserCollection.FreeAll();
+ aUser.Erase();
+ Init();
+}
+
+
+void __EXPORT ScChangeTrack::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
+{
+ if ( !pDoc->IsInDtorClear() )
+ {
+ const SfxItemSetHint* pHint = PTR_CAST( SfxItemSetHint, &rHint );
+ if ( pHint )
+ {
+ const SfxItemSet& rSet = pHint->GetItemSet();
+ const SfxPoolItem* pItem;
+ if ( rSet.GetItemState(
+ rSet.GetPool()->GetWhich( SID_ATTR_ADDRESS ),
+ TRUE, &pItem ) == SFX_ITEM_SET )
+ {
+ String aStr( ((SvxAddressItem*)pItem)->GetFirstName() );
+ aStr += ' ';
+ aStr += ((SvxAddressItem*)pItem)->GetName();
+ SetUser( aStr );
+ }
+ }
+ }
+}
+
+
+void ScChangeTrack::SetUser( const String& rUser )
+{
+ if ( IsLoadSave() )
+ return ; // nicht die Collection zerschiessen
+
+ aUser = rUser;
+ StrData* pStrData = new StrData( aUser );
+ if ( !aUserCollection.Insert( pStrData ) )
+ delete pStrData;
+}
+
+
+void ScChangeTrack::StartBlockModify( ScChangeTrackMsgType eMsgType,
+ ULONG nStartAction )
+{
+ if ( aModifiedLink.IsSet() )
+ {
+ if ( pBlockModifyMsg )
+ aMsgStackTmp.Push( pBlockModifyMsg ); // Block im Block
+ pBlockModifyMsg = new ScChangeTrackMsgInfo;
+ pBlockModifyMsg->eMsgType = eMsgType;
+ pBlockModifyMsg->nStartAction = nStartAction;
+ }
+}
+
+
+void ScChangeTrack::EndBlockModify( ULONG nEndAction )
+{
+ if ( aModifiedLink.IsSet() )
+ {
+ if ( pBlockModifyMsg )
+ {
+ if ( pBlockModifyMsg->nStartAction <= nEndAction )
+ {
+ pBlockModifyMsg->nEndAction = nEndAction;
+ // Blocks in Blocks aufgeloest
+ aMsgStackFinal.Push( pBlockModifyMsg );
+ }
+ else
+ delete pBlockModifyMsg;
+ pBlockModifyMsg = aMsgStackTmp.Pop(); // evtl. Block im Block
+ }
+ if ( !pBlockModifyMsg )
+ {
+ BOOL bNew = FALSE;
+ ScChangeTrackMsgInfo* pMsg;
+ while ( pMsg = aMsgStackFinal.Pop() )
+ {
+ aMsgQueue.Put( pMsg );
+ bNew = TRUE;
+ }
+ if ( bNew )
+ aModifiedLink.Call( this );
+ }
+ }
+}
+
+
+void ScChangeTrack::NotifyModified( ScChangeTrackMsgType eMsgType,
+ ULONG nStartAction, ULONG nEndAction )
+{
+ if ( aModifiedLink.IsSet() )
+ {
+ if ( !pBlockModifyMsg || pBlockModifyMsg->eMsgType != eMsgType ||
+ (IsGenerated( nStartAction ) &&
+ (eMsgType == SC_CTM_APPEND || eMsgType == SC_CTM_REMOVE)) )
+ { // Append innerhalb von Append z.B. nicht
+ StartBlockModify( eMsgType, nStartAction );
+ EndBlockModify( nEndAction );
+ }
+ }
+}
+
+
+BOOL ScChangeTrack::Load( SvStream& rStrm, USHORT nVer )
+{
+ BOOL bOk = TRUE;
+ SetLoadSave( TRUE );
+
+ ScReadHeader aGlobalHdr( rStrm );
+
+ BYTE n8;
+ UINT16 n16;
+ UINT32 n32;
+
+ rStrm >> n16; nLoadedFileFormatVersion = n16;
+ if ( (nLoadedFileFormatVersion & 0xFF00) > (SC_CHGTRACK_FILEFORMAT & 0xFF00) )
+ { // inkompatible neuere Version
+ Clear();
+ rStrm.SetError( SCWARN_IMPORT_INFOLOST );
+ return FALSE;
+ }
+
+ aUserCollection.Load( rStrm );
+
+ ULONG nCount, nLastAction, nGeneratedCount;
+ rStrm >> n32; nCount = n32;
+ rStrm >> n32; nActionMax = n32;
+ rStrm >> n32; nLastAction = n32;
+
+ rStrm >> n32; nGeneratedCount = n32;
+
+ // GeneratedDelContents laden
+ {
+ ScMultipleReadHeader aHdr( rStrm );
+ for ( ULONG j = 0; j < nGeneratedCount && bOk; j++ )
+ {
+ ScChangeActionContent* pAct;
+
+ aHdr.StartEntry();
+
+ ScChangeActionType eType;
+ rStrm >> n8; eType = (ScChangeActionType) n8;
+
+ switch ( eType )
+ {
+ case SC_CAT_CONTENT :
+ pAct = new ScChangeActionContent( rStrm, aHdr, pDoc, nVer, this );
+ break;
+ default:
+ DBG_ERROR( "ScChangeTrack::Load: unknown GeneratedType" );
+ pAct = NULL;
+ bOk = FALSE;
+ }
+
+ aHdr.EndEntry();
+
+ if ( pAct )
+ {
+ pAct->SetType( eType );
+ if ( pFirstGeneratedDelContent )
+ pFirstGeneratedDelContent->pPrev = pAct;
+ pAct->pNext = pFirstGeneratedDelContent;
+ pFirstGeneratedDelContent = pAct;
+ aGeneratedTable.Insert( pAct->GetActionNumber(), pAct );
+ }
+ }
+ rStrm >> n32; nGeneratedMin = n32;
+ }
+
+ if ( bOk )
+ bOk = ( nGeneratedCount == aGeneratedTable.Count() );
+ DBG_ASSERT( bOk, "ScChangeTrack::Load: Generated failed" );
+
+
+ // erste Runde: Actions laden
+ {
+ ScMultipleReadHeader aHdr( rStrm );
+ for ( ULONG j = 0; j < nCount && bOk; j++ )
+ {
+ ScChangeAction* pAct;
+
+ aHdr.StartEntry();
+
+ USHORT nUserIndex;
+ rStrm >> n16; nUserIndex = n16;
+
+ ScChangeActionType eType;
+ rStrm >> n8; eType = (ScChangeActionType) n8;
+
+ switch ( eType )
+ {
+ case SC_CAT_INSERT_COLS :
+ case SC_CAT_INSERT_ROWS :
+ case SC_CAT_INSERT_TABS :
+ pAct = new ScChangeActionIns( rStrm, aHdr, this );
+ break;
+ case SC_CAT_DELETE_COLS :
+ case SC_CAT_DELETE_ROWS :
+ case SC_CAT_DELETE_TABS :
+ pAct = new ScChangeActionDel( rStrm, aHdr, pDoc, nVer, this );
+ break;
+ case SC_CAT_MOVE :
+ pAct = new ScChangeActionMove( rStrm, aHdr, this );
+ break;
+ case SC_CAT_CONTENT :
+ pAct = new ScChangeActionContent( rStrm, aHdr, pDoc, nVer, this );
+ break;
+ case SC_CAT_REJECT :
+ pAct = new ScChangeActionReject( rStrm, aHdr, this );
+ break;
+ default:
+ DBG_ERROR( "ScChangeTrack::Load: unknown ScChangeActionType" );
+ pAct = NULL;
+ bOk = FALSE;
+ }
+
+ aHdr.EndEntry();
+
+ if ( pAct )
+ {
+ pAct->SetType( eType );
+ if ( nUserIndex != 0xffff )
+ {
+ StrData* pUser = (StrData*) aUserCollection.At( nUserIndex );
+ if ( pUser )
+ pAct->SetUser( pUser->GetString() );
+ }
+ AppendLoaded( pAct );
+ }
+ }
+ }
+
+ if ( pLast )
+ nMarkLastSaved = pLast->GetActionNumber();
+
+ if ( bOk )
+ bOk = ( nMarkLastSaved == nLastAction && nCount == aTable.Count() );
+ DBG_ASSERT( bOk, "ScChangeTrack::Load: failed" );
+
+ // zweite Runde: Links laden und alles verpointern
+ {
+ ScMultipleReadHeader aHdr( rStrm );
+ for ( ScChangeAction* p = GetFirst(); p && bOk; p = p->GetNext() )
+ {
+ aHdr.StartEntry();
+ bOk = p->LoadLinks( rStrm, this );
+ aHdr.EndEntry();
+ }
+ }
+
+ SetLoadSave( FALSE );
+
+ // den aktuellen User erst einfuegen, wenn die Actions bereits ihre User haben
+ SetUser( aUser );
+
+ if ( !bOk )
+ {
+ Clear(); // eindeutiger Zustand
+ rStrm.SetError( SCWARN_IMPORT_INFOLOST );
+ }
+
+ return bOk;
+}
+
+
+BOOL ScChangeTrack::Store( SvStream& rStrm )
+{
+ BOOL bOk = TRUE;
+ SetLoadSave( TRUE );
+
+ ScWriteHeader aGlobalHdr( rStrm );
+
+ rStrm << (UINT16) SC_CHGTRACK_FILEFORMAT;
+
+ aUserCollection.Store( rStrm );
+
+ ULONG nCount = aTable.Count();
+ ULONG nLastAction = ( pLast ? pLast->GetActionNumber() : 0 );
+ ULONG nGeneratedCount = aGeneratedTable.Count();
+ rStrm << (UINT32) nCount << (UINT32) nActionMax << (UINT32) nLastAction;
+ rStrm << (UINT32) nGeneratedCount;
+
+ // GeneratedDelContents speichern
+ ULONG nSave = 0;
+ {
+ ScMultipleWriteHeader aHdr( rStrm );
+ ULONG nNewGeneratedMin = SC_CHGTRACK_GENERATED_START;
+ for ( ScChangeAction* p = pFirstGeneratedDelContent; p && bOk;
+ p = p->GetNext() )
+ {
+ ++nSave;
+ aHdr.StartEntry();
+ rStrm << (BYTE) p->GetType();
+ bOk = p->Store( rStrm, aHdr );
+ aHdr.EndEntry();
+ ULONG nAct = p->GetActionNumber();
+ if ( nNewGeneratedMin > nAct )
+ nNewGeneratedMin = nAct;
+ }
+ nGeneratedMin = nNewGeneratedMin; // evtl. unbenutzten Bereich freigeben
+ rStrm << (UINT32) nGeneratedMin;
+ }
+
+ if ( bOk )
+ bOk = ( nGeneratedCount == nSave );
+ DBG_ASSERT( bOk, "ScChangeTrack::Store: failed" );
+
+ // erste Runde: Actions speichern
+ nSave = 0;
+ {
+ ScMultipleWriteHeader aHdr( rStrm );
+ StrData* pUserSearch = new StrData( aUser );
+ USHORT nUserIndex;
+ for ( ScChangeAction* p = GetFirst(); p && bOk; p = p->GetNext() )
+ {
+ ++nSave;
+ aHdr.StartEntry();
+
+ pUserSearch->SetString( p->GetUser() );
+ if ( aUserCollection.Search( pUserSearch, nUserIndex ) )
+ rStrm << (UINT16) nUserIndex;
+ else
+ rStrm << (UINT16) 0xffff;
+ rStrm << (BYTE) p->GetType();
+
+ bOk = p->Store( rStrm, aHdr );
+
+ aHdr.EndEntry();
+ }
+ delete pUserSearch;
+ }
+
+ if ( pLast )
+ nMarkLastSaved = pLast->GetActionNumber();
+
+ if ( bOk )
+ bOk = ( nCount == nSave );
+ DBG_ASSERT( bOk, "ScChangeTrack::Store: failed" );
+
+ // zweite Runde: Links speichern
+ {
+ ScMultipleWriteHeader aHdr( rStrm );
+ for ( ScChangeAction* p = GetFirst(); p && bOk; p = p->GetNext() )
+ {
+ aHdr.StartEntry();
+ bOk = p->StoreLinks( rStrm );
+ aHdr.EndEntry();
+ }
+ }
+
+ SetLoadSave( FALSE );
+ return bOk;
+}
+
+
+void ScChangeTrack::MasterLinks( ScChangeAction* pAppend )
+{
+ ScChangeActionType eType = pAppend->GetType();
+
+ if ( eType == SC_CAT_CONTENT )
+ {
+ if ( !IsGenerated( pAppend->GetActionNumber() ) )
+ {
+ USHORT nSlot = ComputeContentSlot(
+ pAppend->GetBigRange().aStart.Row() );
+ ((ScChangeActionContent*)pAppend)->InsertInSlot(
+ &ppContentSlots[nSlot] );
+ }
+ return ;
+ }
+
+ if ( pAppend->IsRejecting() )
+ return ; // Rejects haben keine Abhaengigkeiten
+
+ switch ( eType )
+ {
+ case SC_CAT_INSERT_COLS :
+ {
+ ScChangeActionLinkEntry* pLink = new ScChangeActionLinkEntry(
+ &pLinkInsertCol, pAppend );
+ pAppend->AddLink( NULL, pLink );
+ }
+ break;
+ case SC_CAT_INSERT_ROWS :
+ {
+ ScChangeActionLinkEntry* pLink = new ScChangeActionLinkEntry(
+ &pLinkInsertRow, pAppend );
+ pAppend->AddLink( NULL, pLink );
+ }
+ break;
+ case SC_CAT_INSERT_TABS :
+ {
+ ScChangeActionLinkEntry* pLink = new ScChangeActionLinkEntry(
+ &pLinkInsertTab, pAppend );
+ pAppend->AddLink( NULL, pLink );
+ }
+ break;
+ case SC_CAT_MOVE :
+ {
+ ScChangeActionLinkEntry* pLink = new ScChangeActionLinkEntry(
+ &pLinkMove, pAppend );
+ pAppend->AddLink( NULL, pLink );
+ }
+ break;
+ }
+}
+
+
+void ScChangeTrack::AppendLoaded( ScChangeAction* pAppend )
+{
+ aTable.Insert( pAppend->GetActionNumber(), pAppend );
+ if ( !pLast )
+ pFirst = pLast = pAppend;
+ else
+ {
+ pLast->pNext = pAppend;
+ pAppend->pPrev = pLast;
+ pLast = pAppend;
+ }
+ MasterLinks( pAppend );
+}
+
+
+void ScChangeTrack::Append( ScChangeAction* pAppend, ULONG nAction )
+{
+ if ( nActionMax < nAction )
+ nActionMax = nAction;
+ pAppend->SetUser( aUser );
+ if ( bUseFixDateTime )
+ pAppend->SetDateTimeUTC( aFixDateTime );
+ pAppend->SetActionNumber( nAction );
+ aTable.Insert( nAction, pAppend );
+ // UpdateReference Inserts vor Dependencies.
+ // Delete rejectendes Insert hatte UpdateReference mit Delete-Undo.
+ // UpdateReference auch wenn pLast==NULL, weil pAppend ein Delete sein
+ // kann, dass DelContents generiert haben kann
+ if ( pAppend->IsInsertType() && !pAppend->IsRejecting() )
+ UpdateReference( pAppend, FALSE );
+ if ( !pLast )
+ pFirst = pLast = pAppend;
+ else
+ {
+ pLast->pNext = pAppend;
+ pAppend->pPrev = pLast;
+ pLast = pAppend;
+ Dependencies( pAppend );
+ }
+ // UpdateReference Inserts nicht nach Dependencies.
+ // Move rejectendes Move hatte UpdateReference mit Move-Undo, Inhalt in
+ // ToRange nicht deleten.
+ if ( !pAppend->IsInsertType() &&
+ !(pAppend->GetType() == SC_CAT_MOVE && pAppend->IsRejecting()) )
+ UpdateReference( pAppend, FALSE );
+ MasterLinks( pAppend );
+
+ if ( aModifiedLink.IsSet() )
+ {
+ NotifyModified( SC_CTM_APPEND, nAction, nAction );
+ if ( pAppend->GetType() == SC_CAT_CONTENT )
+ {
+ ScChangeActionContent* pContent = (ScChangeActionContent*) pAppend;
+ if ( pContent = pContent->GetPrevContent() )
+ {
+ ULONG nMod = pContent->GetActionNumber();
+ NotifyModified( SC_CTM_CHANGE, nMod, nMod );
+ }
+ }
+ else
+ NotifyModified( SC_CTM_CHANGE, pFirst->GetActionNumber(),
+ pLast->GetActionNumber() );
+ }
+}
+
+
+void ScChangeTrack::Append( ScChangeAction* pAppend )
+{
+ Append( pAppend, ++nActionMax );
+}
+
+
+void ScChangeTrack::AppendDeleteRange( const ScRange& rRange,
+ ScDocument* pRefDoc, ULONG& nStartAction, ULONG& nEndAction, short nDz )
+{
+ nStartAction = GetActionMax() + 1;
+ AppendDeleteRange( rRange, pRefDoc, nDz, 0 );
+ nEndAction = GetActionMax();
+}
+
+
+void ScChangeTrack::AppendDeleteRange( const ScRange& rRange,
+ ScDocument* pRefDoc, short nDz, ULONG nRejectingInsert )
+{
+ SetInDeleteRange( rRange );
+ StartBlockModify( SC_CTM_APPEND, GetActionMax() + 1 );
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ rRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ for ( USHORT nTab = nTab1; nTab <= nTab2; nTab++ )
+ {
+ if ( !pRefDoc || nTab < pRefDoc->GetTableCount() )
+ {
+ if ( nCol1 == 0 && nCol2 == MAXCOL )
+ { // ganze Zeilen und/oder Tabellen
+ if ( nRow1 == 0 && nRow2 == MAXROW )
+ { // ganze Tabellen
+//2do: geht nicht auch komplette Tabelle als ganzes?
+ ScRange aRange( 0, 0, nTab, 0, MAXROW, nTab );
+ for ( USHORT nCol = nCol1; nCol <= nCol2; nCol++ )
+ { // spaltenweise ist weniger als zeilenweise
+ aRange.aStart.SetCol( nCol );
+ aRange.aEnd.SetCol( nCol );
+ if ( nCol == nCol2 )
+ SetInDeleteTop( TRUE );
+ AppendOneDeleteRange( aRange, pRefDoc, nCol-nCol1, 0,
+ nTab-nTab1 + nDz, nRejectingInsert );
+ }
+ //! immer noch InDeleteTop
+ AppendOneDeleteRange( rRange, pRefDoc, 0, 0,
+ nTab-nTab1 + nDz, nRejectingInsert );
+ }
+ else
+ { // ganze Zeilen
+ ScRange aRange( 0, 0, nTab, MAXCOL, 0, nTab );
+ for ( USHORT nRow = nRow1; nRow <= nRow2; nRow++ )
+ {
+ aRange.aStart.SetRow( nRow );
+ aRange.aEnd.SetRow( nRow );
+ if ( nRow == nRow2 )
+ SetInDeleteTop( TRUE );
+ AppendOneDeleteRange( aRange, pRefDoc, 0, nRow-nRow1,
+ 0, nRejectingInsert );
+ }
+ }
+ }
+ else if ( nRow1 == 0 && nRow2 == MAXROW )
+ { // ganze Spalten
+ ScRange aRange( 0, 0, nTab, 0, MAXROW, nTab );
+ for ( USHORT nCol = nCol1; nCol <= nCol2; nCol++ )
+ {
+ aRange.aStart.SetCol( nCol );
+ aRange.aEnd.SetCol( nCol );
+ if ( nCol == nCol2 )
+ SetInDeleteTop( TRUE );
+ AppendOneDeleteRange( aRange, pRefDoc, nCol-nCol1, 0,
+ 0, nRejectingInsert );
+ }
+ }
+ else
+ DBG_ERROR( "ScChangeTrack::AppendDeleteRange: Block not supported!" );
+ SetInDeleteTop( FALSE );
+ }
+ }
+ EndBlockModify( GetActionMax() );
+}
+
+
+void ScChangeTrack::AppendOneDeleteRange( const ScRange& rOrgRange,
+ ScDocument* pRefDoc, short nDx, short nDy, short nDz,
+ ULONG nRejectingInsert )
+{
+ ScRange aTrackRange( rOrgRange );
+ if ( nDx )
+ {
+ aTrackRange.aStart.IncCol( -nDx );
+ aTrackRange.aEnd.IncCol( -nDx );
+ }
+ if ( nDy )
+ {
+ aTrackRange.aStart.IncRow( -nDy );
+ aTrackRange.aEnd.IncRow( -nDy );
+ }
+ if ( nDz )
+ {
+ aTrackRange.aStart.IncTab( -nDz );
+ aTrackRange.aEnd.IncTab( -nDz );
+ }
+ ScChangeActionDel* pAct = new ScChangeActionDel( aTrackRange, nDx, nDy,
+ this );
+ // TabDelete keine Contents, sind in einzelnen Spalten
+ if ( !(rOrgRange.aStart.Col() == 0 && rOrgRange.aStart.Row() == 0 &&
+ rOrgRange.aEnd.Col() == MAXCOL && rOrgRange.aEnd.Row() == MAXROW) )
+ LookUpContents( rOrgRange, pRefDoc, -nDx, -nDy, -nDz );
+ if ( nRejectingInsert )
+ {
+ pAct->SetRejectAction( nRejectingInsert );
+ pAct->SetState( SC_CAS_ACCEPTED );
+ }
+ Append( pAct );
+}
+
+
+void ScChangeTrack::LookUpContents( const ScRange& rOrgRange,
+ ScDocument* pRefDoc, short nDx, short nDy, short nDz )
+{
+ if ( pRefDoc )
+ {
+ ScAddress aPos;
+ ScBigAddress aBigPos;
+ ScCellIterator aIter( pRefDoc, rOrgRange );
+ ScBaseCell* pCell = aIter.GetFirst();
+ while ( pCell )
+ {
+ if ( ScChangeActionContent::IsContentCellType( pCell ) )
+ {
+ aBigPos.Set( aIter.GetCol() + nDx, aIter.GetRow() + nDy,
+ aIter.GetTab() + nDz );
+ ScChangeActionContent* pContent = SearchContentAt( aBigPos, NULL );
+ if ( !pContent )
+ { // nicht getrackte Contents
+ aPos.Set( aIter.GetCol() + nDx, aIter.GetRow() + nDy,
+ aIter.GetTab() + nDz );
+ GenerateDelContent( aPos, pCell, pRefDoc );
+ //! der Content wird hier _nicht_ per AddContent hinzugefuegt,
+ //! sondern in UpdateReference, um z.B. auch kreuzende Deletes
+ //! korrekt zu erfassen
+ }
+ }
+ pCell = aIter.GetNext();
+ }
+ }
+}
+
+
+void ScChangeTrack::AppendMove( const ScRange& rFromRange,
+ const ScRange& rToRange, ScDocument* pRefDoc )
+{
+ ScChangeActionMove* pAct = new ScChangeActionMove( rFromRange, rToRange, this );
+ LookUpContents( rToRange, pRefDoc, 0, 0, 0 ); // ueberschriebene Contents
+ Append( pAct );
+}
+
+
+void ScChangeTrack::AppendContent( const ScAddress& rPos,
+ const String& rNewValue )
+{
+ ScBaseCell* pCell = pDoc->GetCell( rPos );
+ AppendContent( rPos, rNewValue, pCell );
+}
+
+
+void ScChangeTrack::AppendContent( const ScAddress& rPos,
+ const String& rNewValue, ScBaseCell* pOldCell )
+{
+ String aOldValue;
+ ScChangeActionContent::GetStringOfCell( aOldValue, pOldCell, pDoc, rPos );
+ if ( aOldValue != rNewValue )
+ { // nur wirkliche Aenderung tracken
+ ScRange aRange( rPos );
+ ScChangeActionContent* pAct = new ScChangeActionContent( aRange );
+ pAct->SetOldValue( pOldCell, pDoc, pDoc );
+ pAct->SetNewValue( rNewValue, pDoc );
+ Append( pAct );
+ }
+}
+
+
+void ScChangeTrack::AppendContent( const ScAddress& rPos,
+ const ScBaseCell* pOldCell )
+{
+ if ( ScChangeActionContent::NeedsNumberFormat( pOldCell ) )
+ AppendContent( rPos, pOldCell, pDoc->GetNumberFormat( rPos ), pDoc );
+ else
+ AppendContent( rPos, pOldCell, 0, pDoc );
+}
+
+
+void ScChangeTrack::AppendContent( const ScAddress& rPos,
+ const ScBaseCell* pOldCell, ScDocument* pRefDoc )
+{
+ if ( ScChangeActionContent::NeedsNumberFormat( pOldCell ) )
+ AppendContent( rPos, pOldCell, pRefDoc->GetNumberFormat( rPos ), pRefDoc );
+ else
+ AppendContent( rPos, pOldCell, 0, pRefDoc );
+}
+
+
+void ScChangeTrack::AppendContent( const ScAddress& rPos,
+ const ScBaseCell* pOldCell, ULONG nOldFormat, ScDocument* pRefDoc )
+{
+ if ( !pRefDoc )
+ pRefDoc = pDoc;
+ String aOldValue;
+ ScChangeActionContent::GetStringOfCell( aOldValue, pOldCell, pRefDoc, nOldFormat );
+ String aNewValue;
+ ScBaseCell* pNewCell = pDoc->GetCell( rPos );
+ ScChangeActionContent::GetStringOfCell( aNewValue, pNewCell, pDoc, rPos );
+ if ( aOldValue != aNewValue )
+ { // nur wirkliche Aenderung tracken
+ ScRange aRange( rPos );
+ ScChangeActionContent* pAct = new ScChangeActionContent( aRange );
+ pAct->SetOldValue( pOldCell, pRefDoc, pDoc, nOldFormat );
+ pAct->SetNewValue( pNewCell, pDoc );
+ Append( pAct );
+ }
+}
+
+
+void ScChangeTrack::AppendContent( const ScAddress& rPos,
+ ScDocument* pRefDoc )
+{
+ String aOldValue;
+ ScBaseCell* pOldCell = pRefDoc->GetCell( rPos );
+ ScChangeActionContent::GetStringOfCell( aOldValue, pOldCell, pRefDoc, rPos );
+ String aNewValue;
+ ScBaseCell* pNewCell = pDoc->GetCell( rPos );
+ ScChangeActionContent::GetStringOfCell( aNewValue, pNewCell, pDoc, rPos );
+ if ( aOldValue != aNewValue )
+ { // nur wirkliche Aenderung tracken
+ ScRange aRange( rPos );
+ ScChangeActionContent* pAct = new ScChangeActionContent( aRange );
+ pAct->SetOldValue( pOldCell, pRefDoc, pDoc );
+ pAct->SetNewValue( pNewCell, pDoc );
+ Append( pAct );
+ }
+}
+
+
+void ScChangeTrack::SetLastCutMoveRange( const ScRange& rRange,
+ ScDocument* pRefDoc )
+{
+ if ( pLastCutMove )
+ {
+ // ToRange nicht mit Deletes linken und nicht in der Groesse aendern,
+ // eigentlich unnoetig, da ein Delete vorher in
+ // ScViewFunc::PasteFromClip ein ResetLastCut ausloest
+ ScBigRange& r = pLastCutMove->GetBigRange();
+ r.aEnd.SetCol( -1 );
+ r.aEnd.SetRow( -1 );
+ r.aEnd.SetTab( -1 );
+ r.aStart.SetCol( -1 - (rRange.aEnd.Col() - rRange.aStart.Col()) );
+ r.aStart.SetRow( -1 - (rRange.aEnd.Row() - rRange.aStart.Row()) );
+ r.aStart.SetTab( -1 - (rRange.aEnd.Tab() - rRange.aStart.Tab()) );
+ // zu ueberschreibende Contents im FromRange
+ LookUpContents( rRange, pRefDoc, 0, 0, 0 );
+ }
+}
+
+
+void ScChangeTrack::AppendContentRange( const ScRange& rRange,
+ ScDocument* pRefDoc, ULONG& nStartAction, ULONG& nEndAction,
+ ScChangeActionClipMode eClipMode )
+{
+ if ( eClipMode == SC_CACM_CUT )
+ {
+ ResetLastCut();
+ pLastCutMove = new ScChangeActionMove( rRange, rRange, this );
+ SetLastCutMoveRange( rRange, pRefDoc );
+ }
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ rRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ BOOL bDoContents;
+ if ( eClipMode == SC_CACM_PASTE && HasLastCut() )
+ {
+ bDoContents = FALSE;
+ SetInPasteCut( TRUE );
+ // Paste und Cut abstimmen, Paste kann groesserer Range sein
+ ScRange aRange( rRange );
+ ScBigRange& r = pLastCutMove->GetBigRange();
+ USHORT nTmp;
+ if ( (nTmp = (USHORT) (r.aEnd.Col() - r.aStart.Col())) != (nCol2 - nCol1) )
+ {
+ aRange.aEnd.SetCol( aRange.aStart.Col() + nTmp );
+ nCol1 += nTmp + 1;
+ bDoContents = TRUE;
+ }
+ if ( (nTmp = (USHORT) (r.aEnd.Row() - r.aStart.Row())) != (nRow2 - nRow1) )
+ {
+ aRange.aEnd.SetRow( aRange.aStart.Row() + nTmp );
+ nRow1 += nTmp + 1;
+ bDoContents = TRUE;
+ }
+ if ( (nTmp = (USHORT) (r.aEnd.Tab() - r.aStart.Tab())) != (nTab2 - nTab1) )
+ {
+ aRange.aEnd.SetTab( aRange.aStart.Tab() + nTmp );
+ nTab1 += nTmp + 1;
+ bDoContents = TRUE;
+ }
+ r = aRange;
+ Undo( nStartLastCut, nEndLastCut ); // hier werden sich die Cuts gemerkt
+ //! StartAction erst nach Undo
+ nStartAction = GetActionMax() + 1;
+ StartBlockModify( SC_CTM_APPEND, nStartAction );
+ // zu ueberschreibende Contents im ToRange
+ LookUpContents( aRange, pRefDoc, 0, 0, 0 );
+ pLastCutMove->SetStartLastCut( nStartLastCut );
+ pLastCutMove->SetEndLastCut( nEndLastCut );
+ Append( pLastCutMove );
+ pLastCutMove = NULL;
+ ResetLastCut();
+ SetInPasteCut( FALSE );
+ }
+ else
+ {
+ bDoContents = TRUE;
+ nStartAction = GetActionMax() + 1;
+ StartBlockModify( SC_CTM_APPEND, nStartAction );
+ }
+ if ( bDoContents )
+ {
+ ScAddress aPos;
+ for ( USHORT nTab = nTab1; nTab <= nTab2; nTab++ )
+ {
+ aPos.SetTab( nTab );
+ for ( USHORT nCol = nCol1; nCol <= nCol2; nCol++ )
+ {
+ aPos.SetCol( nCol );
+ for ( USHORT nRow = nRow1; nRow <= nRow2; nRow++ )
+ {
+ aPos.SetRow( nRow );
+ AppendContent( aPos, pRefDoc );
+ }
+ }
+ }
+ }
+ nEndAction = GetActionMax();
+ EndBlockModify( nEndAction );
+ if ( eClipMode == SC_CACM_CUT )
+ {
+ nStartLastCut = nStartAction;
+ nEndLastCut = nEndAction;
+ }
+}
+
+
+void ScChangeTrack::AppendContentsIfInRefDoc( ScDocument* pRefDoc,
+ ULONG& nStartAction, ULONG& nEndAction )
+{
+ ScDocumentIterator aIter( pRefDoc, 0, MAXTAB );
+ if ( aIter.GetFirst() )
+ {
+ nStartAction = GetActionMax() + 1;
+ StartBlockModify( SC_CTM_APPEND, nStartAction );
+ SvNumberFormatter* pFormatter = pRefDoc->GetFormatTable();
+ do
+ {
+ USHORT nCol, nRow, nTab;
+ aIter.GetPos( nCol, nRow, nTab );
+ ScAddress aPos( nCol, nRow, nTab );
+ AppendContent( aPos, aIter.GetCell(),
+ aIter.GetPattern()->GetNumberFormat( pFormatter ), pRefDoc );
+ } while ( aIter.GetNext() );
+ nEndAction = GetActionMax();
+ EndBlockModify( nEndAction );
+ }
+ else
+ nStartAction = nEndAction = 0;
+}
+
+
+void ScChangeTrack::AppendInsert( const ScRange& rRange )
+{
+ ScChangeActionIns* pAct = new ScChangeActionIns( rRange );
+ Append( pAct );
+}
+
+
+void ScChangeTrack::DeleteCellEntries( ScChangeActionCellListEntry*& pCellList,
+ ScChangeAction* pDeletor )
+{
+ ScChangeActionCellListEntry* pE = pCellList;
+ while ( pE )
+ {
+ ScChangeActionCellListEntry* pNext = pE->pNext;
+ pE->pContent->RemoveDeletedIn( pDeletor );
+ if ( IsGenerated( pE->pContent->GetActionNumber() ) &&
+ !pE->pContent->IsDeletedIn() )
+ DeleteGeneratedDelContent( pE->pContent );
+ delete pE;
+ pE = pNext;
+ }
+ pCellList = NULL;
+}
+
+
+ScChangeActionContent* ScChangeTrack::GenerateDelContent(
+ const ScAddress& rPos, const ScBaseCell* pCell,
+ const ScDocument* pFromDoc )
+{
+ ScChangeActionContent* pContent = new ScChangeActionContent(
+ ScRange( rPos ) );
+ pContent->SetActionNumber( --nGeneratedMin );
+ // nur NewValue
+ ScChangeActionContent::SetValue( pContent->aNewValue, pContent->pNewCell,
+ rPos, pCell, pFromDoc, pDoc );
+ // pNextContent und pPrevContent werden nicht gesetzt
+ if ( pFirstGeneratedDelContent )
+ { // vorne reinhaengen
+ pFirstGeneratedDelContent->pPrev = pContent;
+ pContent->pNext = pFirstGeneratedDelContent;
+ }
+ pFirstGeneratedDelContent = pContent;
+ aGeneratedTable.Insert( nGeneratedMin, pContent );
+ NotifyModified( SC_CTM_APPEND, nGeneratedMin, nGeneratedMin );
+ return pContent;
+}
+
+
+void ScChangeTrack::DeleteGeneratedDelContent( ScChangeActionContent* pContent )
+{
+ ULONG nAct = pContent->GetActionNumber();
+ aGeneratedTable.Remove( nAct );
+ if ( pFirstGeneratedDelContent == pContent )
+ pFirstGeneratedDelContent = (ScChangeActionContent*) pContent->pNext;
+ if ( pContent->pNext )
+ pContent->pNext->pPrev = pContent->pPrev;
+ if ( pContent->pPrev )
+ pContent->pPrev->pNext = pContent->pNext;
+ delete pContent;
+ NotifyModified( SC_CTM_REMOVE, nAct, nAct );
+ if ( nAct == nGeneratedMin )
+ ++nGeneratedMin; //! erst nach NotifyModified wg. IsGenerated
+}
+
+
+ScChangeActionContent* ScChangeTrack::SearchGeneratedDelContentAt(
+ const ScBigAddress& rPos, ScChangeActionType eNotInDelType ) const
+{
+ for ( ScChangeAction* p = pFirstGeneratedDelContent; p; p = p->GetNext() )
+ {
+ if ( p->GetType() == SC_CAT_CONTENT && p->GetBigRange().aStart == rPos
+ && !p->IsDeletedInDelType( eNotInDelType ) )
+ {
+ return (ScChangeActionContent*) p;
+ }
+ }
+ return NULL;
+}
+
+
+ScChangeActionContent* ScChangeTrack::SearchContentAt(
+ const ScBigAddress& rPos, ScChangeAction* pButNotThis ) const
+{
+ USHORT nSlot = ComputeContentSlot( rPos.Row() );
+ for ( ScChangeActionContent* p = ppContentSlots[nSlot]; p;
+ p = p->GetNextInSlot() )
+ {
+ if ( p != pButNotThis && !p->IsDeletedIn() &&
+ p->GetBigRange().aStart == rPos )
+ {
+ ScChangeActionContent* pContent = p->GetTopContent();
+ if ( !pContent->IsDeletedIn() )
+ return pContent;
+ }
+ }
+ return NULL;
+}
+
+
+void ScChangeTrack::AddDependentWithNotify( ScChangeAction* pParent,
+ ScChangeAction* pDependent )
+{
+ ScChangeActionLinkEntry* pLink = pParent->AddDependent( pDependent );
+ pDependent->AddLink( pParent, pLink );
+ if ( aModifiedLink.IsSet() )
+ {
+ ULONG nMod = pParent->GetActionNumber();
+ NotifyModified( SC_CTM_PARENT, nMod, nMod );
+ }
+}
+
+
+void ScChangeTrack::Dependencies( ScChangeAction* pAct )
+{
+ // Finde die letzte Abhaengigkeit fuer jeweils Col/Row/Tab.
+ // Content an gleicher Position verketten.
+ // Move Abhaengigkeiten.
+ ScChangeActionType eActType = pAct->GetType();
+ if ( eActType == SC_CAT_REJECT ||
+ (eActType == SC_CAT_MOVE && pAct->IsRejecting()) )
+ return ; // diese Rejects sind nicht abhaengig
+
+ if ( eActType == SC_CAT_CONTENT &&
+ !(((ScChangeActionContent*)pAct)->GetNextContent() ||
+ ((ScChangeActionContent*)pAct)->GetPrevContent()) )
+ { // Contents an gleicher Position verketten
+ ScChangeActionContent* pContent = SearchContentAt(
+ pAct->GetBigRange().aStart, pAct );
+ if ( pContent )
+ {
+ pContent->SetNextContent( (ScChangeActionContent*) pAct );
+ ((ScChangeActionContent*)pAct)->SetPrevContent( pContent );
+ }
+ }
+
+ if ( !(pLinkInsertCol || pLinkInsertRow || pLinkInsertTab || pLinkMove) )
+ return ; // keine Dependencies
+ if ( pAct->IsRejecting() )
+ return ; // ausser Content keine Dependencies
+
+ // Insert in einem entsprechenden Insert haengt davon ab, sonst muesste
+ // der vorherige Insert gesplittet werden.
+ // Sich kreuzende Inserts und Deletes sind nicht abhaengig.
+ // Alles andere ist abhaengig.
+
+ // Der zuletzt eingelinkte Insert steht am Anfang einer Kette,
+ // also genau richtig
+
+ const ScBigRange& rRange = pAct->GetBigRange();
+ BOOL bActNoInsert = !pAct->IsInsertType();
+ BOOL bActColDel = ( eActType == SC_CAT_DELETE_COLS );
+ BOOL bActRowDel = ( eActType == SC_CAT_DELETE_ROWS );
+ BOOL bActTabDel = ( eActType == SC_CAT_DELETE_TABS );
+
+ if ( pLinkInsertCol && (eActType == SC_CAT_INSERT_COLS ||
+ (bActNoInsert && !bActRowDel && !bActTabDel)) )
+ {
+ for ( ScChangeActionLinkEntry* pL = pLinkInsertCol; pL; pL = pL->GetNext() )
+ {
+ ScChangeActionIns* pTest = (ScChangeActionIns*) pL->GetAction();
+ if ( !pTest->IsRejected() &&
+ pTest->GetBigRange().Intersects( rRange ) )
+ {
+ AddDependentWithNotify( pTest, pAct );
+ break; // for
+ }
+ }
+ }
+ if ( pLinkInsertRow && (eActType == SC_CAT_INSERT_ROWS ||
+ (bActNoInsert && !bActColDel && !bActTabDel)) )
+ {
+ for ( ScChangeActionLinkEntry* pL = pLinkInsertRow; pL; pL = pL->GetNext() )
+ {
+ ScChangeActionIns* pTest = (ScChangeActionIns*) pL->GetAction();
+ if ( !pTest->IsRejected() &&
+ pTest->GetBigRange().Intersects( rRange ) )
+ {
+ AddDependentWithNotify( pTest, pAct );
+ break; // for
+ }
+ }
+ }
+ if ( pLinkInsertTab && (eActType == SC_CAT_INSERT_TABS ||
+ (bActNoInsert && !bActColDel && !bActRowDel)) )
+ {
+ for ( ScChangeActionLinkEntry* pL = pLinkInsertTab; pL; pL = pL->GetNext() )
+ {
+ ScChangeActionIns* pTest = (ScChangeActionIns*) pL->GetAction();
+ if ( !pTest->IsRejected() &&
+ pTest->GetBigRange().Intersects( rRange ) )
+ {
+ AddDependentWithNotify( pTest, pAct );
+ break; // for
+ }
+ }
+ }
+
+ if ( pLinkMove )
+ {
+ if ( eActType == SC_CAT_CONTENT )
+ { // Content ist von FromRange abhaengig
+ const ScBigAddress& rPos = rRange.aStart;
+ for ( ScChangeActionLinkEntry* pL = pLinkMove; pL; pL = pL->GetNext() )
+ {
+ ScChangeActionMove* pTest = (ScChangeActionMove*) pL->GetAction();
+ if ( !pTest->IsRejected() &&
+ pTest->GetFromRange().In( rPos ) )
+ {
+ AddDependentWithNotify( pTest, pAct );
+ }
+ }
+ }
+ else if ( eActType == SC_CAT_MOVE )
+ { // Move FromRange ist von ToRange abhaengig
+ const ScBigRange& rFromRange = ((ScChangeActionMove*)pAct)->GetFromRange();
+ for ( ScChangeActionLinkEntry* pL = pLinkMove; pL; pL = pL->GetNext() )
+ {
+ ScChangeActionMove* pTest = (ScChangeActionMove*) pL->GetAction();
+ if ( !pTest->IsRejected() &&
+ pTest->GetBigRange().Intersects( rFromRange ) )
+ {
+ AddDependentWithNotify( pTest, pAct );
+ }
+ }
+ }
+ else
+ { // Inserts und Deletes sind abhaengig, sobald sie FromRange oder
+ // ToRange kreuzen
+ for ( ScChangeActionLinkEntry* pL = pLinkMove; pL; pL = pL->GetNext() )
+ {
+ ScChangeActionMove* pTest = (ScChangeActionMove*) pL->GetAction();
+ if ( !pTest->IsRejected() &&
+ (pTest->GetFromRange().Intersects( rRange ) ||
+ pTest->GetBigRange().Intersects( rRange )) )
+ {
+ AddDependentWithNotify( pTest, pAct );
+ }
+ }
+ }
+ }
+}
+
+
+void ScChangeTrack::Remove( ScChangeAction* pRemove )
+{
+ // aus Track ausklinken
+ ULONG nAct = pRemove->GetActionNumber();
+ aTable.Remove( nAct );
+ if ( nAct == nActionMax )
+ --nActionMax;
+ if ( pRemove == pLast )
+ pLast = pRemove->pPrev;
+ if ( pRemove == pFirst )
+ pFirst = pRemove->pNext;
+ if ( nAct == nMarkLastSaved )
+ nMarkLastSaved =
+ ( pRemove->pPrev ? pRemove->pPrev->GetActionNumber() : 0 );
+
+ // aus der globalen Kette ausklinken
+ if ( pRemove->pNext )
+ pRemove->pNext->pPrev = pRemove->pPrev;
+ if ( pRemove->pPrev )
+ pRemove->pPrev->pNext = pRemove->pNext;
+
+ // Dependencies nicht loeschen, passiert on delete automatisch durch
+ // LinkEntry, ohne Listen abzuklappern
+
+ if ( aModifiedLink.IsSet() )
+ {
+ NotifyModified( SC_CTM_REMOVE, nAct, nAct );
+ if ( pRemove->GetType() == SC_CAT_CONTENT )
+ {
+ ScChangeActionContent* pContent = (ScChangeActionContent*) pRemove;
+ if ( pContent = pContent->GetPrevContent() )
+ {
+ ULONG nMod = pContent->GetActionNumber();
+ NotifyModified( SC_CTM_CHANGE, nMod, nMod );
+ }
+ }
+ else if ( pLast )
+ NotifyModified( SC_CTM_CHANGE, pFirst->GetActionNumber(),
+ pLast->GetActionNumber() );
+ }
+
+ if ( IsInPasteCut() && pRemove->GetType() == SC_CAT_CONTENT )
+ { //! Content wird wiederverwertet
+ ScChangeActionContent* pContent = (ScChangeActionContent*) pRemove;
+ pContent->RemoveAllLinks();
+ pContent->ClearTrack();
+ pContent->pNext = pContent->pPrev = NULL;
+ pContent->pNextContent = pContent->pPrevContent = NULL;
+ }
+}
+
+
+void ScChangeTrack::Undo( ULONG nStartAction, ULONG nEndAction )
+{
+ if ( nStartAction == 0 )
+ ++nStartAction;
+ if ( nEndAction > nActionMax )
+ nEndAction = nActionMax;
+ if ( nEndAction && nStartAction <= nEndAction )
+ {
+ if ( nStartAction == nStartLastCut && nEndAction == nEndLastCut &&
+ !IsInPasteCut() )
+ ResetLastCut();
+ StartBlockModify( SC_CTM_REMOVE, nStartAction );
+ for ( ULONG j = nEndAction; j >= nStartAction; --j )
+ { // rueckwaerts um evtl. nActionMax zu recyclen und schnelleren
+ // Zugriff via pLast, Deletes in richtiger Reihenfolge
+ ScChangeAction* pAct = ( (j == nActionMax && pLast &&
+ pLast->GetActionNumber() == j) ? pLast : GetAction( j ) );
+ if ( pAct )
+ {
+ if ( pAct->IsDeleteType() )
+ {
+ if ( j == nEndAction || (pAct != pLast &&
+ ((ScChangeActionDel*)pAct)->IsTopDelete()) )
+ {
+ SetInDeleteTop( TRUE );
+ SetInDeleteRange( ((ScChangeActionDel*)pAct)->
+ GetOverAllRange().MakeRange() );
+ }
+ }
+ UpdateReference( pAct, TRUE );
+ SetInDeleteTop( FALSE );
+ Remove( pAct );
+ if ( IsInPasteCut() )
+ aPasteCutTable.Insert( pAct->GetActionNumber(), pAct );
+ else
+ {
+ if ( j == nStartAction && pAct->GetType() == SC_CAT_MOVE )
+ {
+ ScChangeActionMove* pMove = (ScChangeActionMove*) pAct;
+ ULONG nStart = pMove->GetStartLastCut();
+ ULONG nEnd = pMove->GetEndLastCut();
+ if ( nStart && nStart <= nEnd )
+ { // LastCut wiederherstellen
+ //! Links vor Cut-Append aufloesen
+ pMove->RemoveAllLinks();
+ StartBlockModify( SC_CTM_APPEND, nStart );
+ for ( ULONG nCut = nStart; nCut <= nEnd; nCut++ )
+ {
+ ScChangeAction* pCut = aPasteCutTable.Remove( nCut );
+ if ( pCut )
+ {
+ DBG_ASSERT( !aTable.Get( nCut ), "ScChangeTrack::Undo: nCut dup" );
+ Append( pCut, nCut );
+ }
+ else
+ DBG_ERROR( "ScChangeTrack::Undo: nCut not found" );
+ }
+ EndBlockModify( nEnd );
+ ResetLastCut();
+ nStartLastCut = nStart;
+ nEndLastCut = nEnd;
+ pLastCutMove = pMove;
+ SetLastCutMoveRange(
+ pMove->GetFromRange().MakeRange(), pDoc );
+ }
+ else
+ delete pMove;
+ }
+ else
+ delete pAct;
+ }
+ }
+ }
+ EndBlockModify( nEndAction );
+ }
+}
+
+
+// static
+BOOL ScChangeTrack::MergeIgnore( const ScChangeAction& rAction, ULONG nFirstMerge )
+{
+ if ( rAction.IsRejected() )
+ return TRUE; // da kommt noch eine passende Reject-Action
+
+ if ( rAction.IsRejecting() && rAction.GetRejectAction() >= nFirstMerge )
+ return TRUE; // da ist sie
+
+ return FALSE; // alles andere
+}
+
+
+void ScChangeTrack::MergePrepare( ScChangeAction* pFirstMerge )
+{
+ SetMergeState( SC_CTMS_PREPARE );
+ ULONG nFirstMerge = pFirstMerge->GetActionNumber();
+ ScChangeAction* pAct = GetLast();
+ if ( pAct )
+ {
+ SetLastMerge( pAct->GetActionNumber() );
+ while ( pAct )
+ { // rueckwaerts, Deletes in richtiger Reihenfolge
+ if ( !ScChangeTrack::MergeIgnore( *pAct, nFirstMerge ) )
+ {
+ if ( pAct->IsDeleteType() )
+ {
+ if ( ((ScChangeActionDel*)pAct)->IsTopDelete() )
+ {
+ SetInDeleteTop( TRUE );
+ SetInDeleteRange( ((ScChangeActionDel*)pAct)->
+ GetOverAllRange().MakeRange() );
+ }
+ }
+ UpdateReference( pAct, TRUE );
+ SetInDeleteTop( FALSE );
+ pAct->DeleteCellEntries(); // sonst GPF bei Track Clear()
+ }
+ pAct = ( pAct == pFirstMerge ? NULL : pAct->GetPrev() );
+ }
+ }
+ SetMergeState( SC_CTMS_OTHER ); //! nachfolgende per default MergeOther
+}
+
+
+void ScChangeTrack::MergeOwn( ScChangeAction* pAct, ULONG nFirstMerge )
+{
+ if ( !ScChangeTrack::MergeIgnore( *pAct, nFirstMerge ) )
+ {
+ SetMergeState( SC_CTMS_OWN );
+ if ( pAct->IsDeleteType() )
+ {
+ if ( ((ScChangeActionDel*)pAct)->IsTopDelete() )
+ {
+ SetInDeleteTop( TRUE );
+ SetInDeleteRange( ((ScChangeActionDel*)pAct)->
+ GetOverAllRange().MakeRange() );
+ }
+ }
+ UpdateReference( pAct, FALSE );
+ SetInDeleteTop( FALSE );
+ SetMergeState( SC_CTMS_OTHER ); //! nachfolgende per default MergeOther
+ }
+}
+
+
+void ScChangeTrack::UpdateReference( ScChangeAction* pAct, BOOL bUndo )
+{
+ ScChangeActionType eActType = pAct->GetType();
+ if ( eActType == SC_CAT_CONTENT || eActType == SC_CAT_REJECT )
+ return ;
+
+ //! Formelzellen haengen nicht im Dokument
+ BOOL bOldAutoCalc = pDoc->GetAutoCalc();
+ pDoc->SetAutoCalc( FALSE );
+ BOOL bOldNoListening = pDoc->GetNoListening();
+ pDoc->SetNoListening( TRUE );
+ //! Formelzellen ExpandRefs synchronisiert zu denen im Dokument
+ BOOL bOldExpandRefs = pDoc->IsExpandRefs();
+ if ( (!bUndo && pAct->IsInsertType()) || (bUndo && pAct->IsDeleteType()) )
+ pDoc->SetExpandRefs( SC_MOD()->GetInputOptions().GetExpandRefs() );
+
+ if ( pAct->IsDeleteType() )
+ {
+ SetInDeleteUndo( bUndo );
+ SetInDelete( TRUE );
+ }
+ else if ( GetMergeState() == SC_CTMS_OWN )
+ {
+ // Referenzen von Formelzellen wiederherstellen,
+ // vorheriges MergePrepare war bei einem Insert wie ein Delete
+ if ( pAct->IsInsertType() )
+ SetInDeleteUndo( TRUE );
+ }
+
+ //! erst die generated, als waeren sie vorher getrackt worden
+ if ( pFirstGeneratedDelContent )
+ UpdateReference( (ScChangeAction**)&pFirstGeneratedDelContent, pAct,
+ bUndo );
+ UpdateReference( &pFirst, pAct, bUndo );
+
+ SetInDelete( FALSE );
+ SetInDeleteUndo( FALSE );
+
+ pDoc->SetExpandRefs( bOldExpandRefs );
+ pDoc->SetNoListening( bOldNoListening );
+ pDoc->SetAutoCalc( bOldAutoCalc );
+}
+
+
+void ScChangeTrack::UpdateReference( ScChangeAction** ppFirstAction,
+ ScChangeAction* pAct, BOOL bUndo )
+{
+ ScChangeActionType eActType = pAct->GetType();
+ BOOL bGeneratedDelContents =
+ ( ppFirstAction == (ScChangeAction**)&pFirstGeneratedDelContent );
+ const ScBigRange& rOrgRange = pAct->GetBigRange();
+ ScBigRange aRange( rOrgRange );
+ ScBigRange aDelRange( rOrgRange );
+ INT32 nDx, nDy, nDz;
+ nDx = nDy = nDz = 0;
+ UpdateRefMode eMode = URM_INSDEL;
+ BOOL bDel = FALSE;
+ switch ( eActType )
+ {
+ case SC_CAT_INSERT_COLS :
+ aRange.aEnd.SetCol( nInt32Max );
+ nDx = rOrgRange.aEnd.Col() - rOrgRange.aStart.Col() + 1;
+ break;
+ case SC_CAT_INSERT_ROWS :
+ aRange.aEnd.SetRow( nInt32Max );
+ nDy = rOrgRange.aEnd.Row() - rOrgRange.aStart.Row() + 1;
+ break;
+ case SC_CAT_INSERT_TABS :
+ aRange.aEnd.SetTab( nInt32Max );
+ nDz = rOrgRange.aEnd.Tab() - rOrgRange.aStart.Tab() + 1;
+ break;
+ case SC_CAT_DELETE_COLS :
+ aRange.aEnd.SetCol( nInt32Max );
+ nDx = -(rOrgRange.aEnd.Col() - rOrgRange.aStart.Col() + 1);
+ aDelRange.aEnd.SetCol( aDelRange.aStart.Col() - nDx - 1 );
+ bDel = TRUE;
+ break;
+ case SC_CAT_DELETE_ROWS :
+ aRange.aEnd.SetRow( nInt32Max );
+ nDy = -(rOrgRange.aEnd.Row() - rOrgRange.aStart.Row() + 1);
+ aDelRange.aEnd.SetRow( aDelRange.aStart.Row() - nDy - 1 );
+ bDel = TRUE;
+ break;
+ case SC_CAT_DELETE_TABS :
+ aRange.aEnd.SetTab( nInt32Max );
+ nDz = -(rOrgRange.aEnd.Tab() - rOrgRange.aStart.Tab() + 1);
+ aDelRange.aEnd.SetTab( aDelRange.aStart.Tab() - nDz - 1 );
+ bDel = TRUE;
+ break;
+ case SC_CAT_MOVE :
+ eMode = URM_MOVE;
+ ((ScChangeActionMove*)pAct)->GetDelta( nDx, nDy, nDz );
+ break;
+ default:
+ DBG_ERROR( "ScChangeTrack::UpdateReference: unknown Type" );
+ }
+ if ( bUndo )
+ {
+ nDx = -nDx;
+ nDy = -nDy;
+ nDz = -nDz;
+ }
+ if ( bDel )
+ { //! fuer diesen Mechanismus gilt:
+ //! es gibt nur ganze, einfache geloeschte Spalten/Zeilen
+ ScChangeActionDel* pActDel = (ScChangeActionDel*) pAct;
+ if ( !bUndo )
+ { // Delete
+ ScChangeActionType eInsType; // fuer Insert-Undo-"Deletes"
+ switch ( eActType )
+ {
+ case SC_CAT_DELETE_COLS :
+ eInsType = SC_CAT_INSERT_COLS;
+ break;
+ case SC_CAT_DELETE_ROWS :
+ eInsType = SC_CAT_INSERT_ROWS;
+ break;
+ case SC_CAT_DELETE_TABS :
+ eInsType = SC_CAT_INSERT_TABS;
+ break;
+ }
+ for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() )
+ {
+ if ( p == pAct )
+ continue; // for
+ BOOL bUpdate = TRUE;
+ if ( GetMergeState() == SC_CTMS_OTHER &&
+ p->GetActionNumber() <= GetLastMerge() )
+ { // Delete in mergendem Dokument, Action im zu mergenden
+ if ( p->IsInsertType() )
+ {
+ // Bei Insert Referenzen nur anpassen, wenn das Delete
+ // das Insert nicht schneidet.
+ if ( !aDelRange.Intersects( p->GetBigRange() ) )
+ p->UpdateReference( this, eMode, aRange, nDx, nDy, nDz );
+ bUpdate = FALSE;
+ }
+ else if ( p->GetType() == SC_CAT_CONTENT &&
+ p->IsDeletedInDelType( eInsType ) )
+ { // Content in Insert-Undo-"Delete"
+ // Nicht anpassen, wenn dieses Delete in dem
+ // Insert-"Delete" sein wuerde (ist nur verschoben).
+ if ( aDelRange.In( p->GetBigRange().aStart ) )
+ bUpdate = FALSE;
+ else
+ {
+ const ScChangeActionLinkEntry* pLink = p->GetDeletedIn();
+ while ( pLink && bUpdate )
+ {
+ const ScChangeAction* pDel = pLink->GetAction();
+ if ( pDel && pDel->GetType() == eInsType &&
+ pDel->GetBigRange().In( aDelRange ) )
+ bUpdate = FALSE;
+ pLink = pLink->GetNext();
+ }
+ }
+ }
+ if ( !bUpdate )
+ continue; // for
+ }
+ if ( aDelRange.In( p->GetBigRange() ) )
+ {
+ // Innerhalb eines gerade geloeschten Bereiches nicht
+ // anpassen, stattdessen dem Bereich zuordnen.
+ // Mehrfache geloeschte Bereiche "stapeln".
+ // Kreuzende Deletes setzen mehrfach geloescht.
+ if ( !p->IsDeletedInDelType( eActType ) )
+ {
+ p->SetDeletedIn( pActDel );
+ // GeneratedDelContent in zu loeschende Liste aufnehmen
+ if ( bGeneratedDelContents )
+ pActDel->AddContent( (ScChangeActionContent*) p );
+ }
+ bUpdate = FALSE;
+ }
+ else
+ {
+ // Eingefuegte Bereiche abschneiden, wenn Start/End im
+ // Delete liegt, aber das Insert nicht komplett innerhalb
+ // des Delete liegt bzw. das Delete nicht komplett im
+ // Insert. Das Delete merkt sich, welchem Insert es was
+ // abgeschnitten hat, es kann auch nur ein einziges Insert
+ // sein (weil Delete einspaltig/einzeilig ist).
+ // Abgeschnittene Moves kann es viele geben.
+ //! Ein Delete ist immer einspaltig/einzeilig, deswegen 1
+ //! ohne die Ueberlappung auszurechnen.
+ switch ( p->GetType() )
+ {
+ case SC_CAT_INSERT_COLS :
+ if ( eActType == SC_CAT_DELETE_COLS )
+ {
+ if ( aDelRange.In( p->GetBigRange().aStart ) )
+ {
+ pActDel->SetCutOffInsert(
+ (ScChangeActionIns*) p, 1 );
+ p->GetBigRange().aStart.IncCol( 1 );
+ }
+ else if ( aDelRange.In( p->GetBigRange().aEnd ) )
+ {
+ pActDel->SetCutOffInsert(
+ (ScChangeActionIns*) p, -1 );
+ p->GetBigRange().aEnd.IncCol( -1 );
+ }
+ }
+ break;
+ case SC_CAT_INSERT_ROWS :
+ if ( eActType == SC_CAT_DELETE_ROWS )
+ {
+ if ( aDelRange.In( p->GetBigRange().aStart ) )
+ {
+ pActDel->SetCutOffInsert(
+ (ScChangeActionIns*) p, 1 );
+ p->GetBigRange().aStart.IncRow( 1 );
+ }
+ else if ( aDelRange.In( p->GetBigRange().aEnd ) )
+ {
+ pActDel->SetCutOffInsert(
+ (ScChangeActionIns*) p, -1 );
+ p->GetBigRange().aEnd.IncRow( -1 );
+ }
+ }
+ break;
+ case SC_CAT_INSERT_TABS :
+ if ( eActType == SC_CAT_DELETE_TABS )
+ {
+ if ( aDelRange.In( p->GetBigRange().aStart ) )
+ {
+ pActDel->SetCutOffInsert(
+ (ScChangeActionIns*) p, 1 );
+ p->GetBigRange().aStart.IncTab( 1 );
+ }
+ else if ( aDelRange.In( p->GetBigRange().aEnd ) )
+ {
+ pActDel->SetCutOffInsert(
+ (ScChangeActionIns*) p, -1 );
+ p->GetBigRange().aEnd.IncTab( -1 );
+ }
+ }
+ break;
+ case SC_CAT_MOVE :
+ {
+ ScChangeActionMove* pMove = (ScChangeActionMove*) p;
+ short nFrom = 0;
+ short nTo = 0;
+ if ( aDelRange.In( pMove->GetBigRange().aStart ) )
+ nTo = 1;
+ else if ( aDelRange.In( pMove->GetBigRange().aEnd ) )
+ nTo = -1;
+ if ( aDelRange.In( pMove->GetFromRange().aStart ) )
+ nFrom = 1;
+ else if ( aDelRange.In( pMove->GetFromRange().aEnd ) )
+ nFrom = -1;
+ if ( nFrom )
+ {
+ switch ( eActType )
+ {
+ case SC_CAT_DELETE_COLS :
+ if ( nFrom > 0 )
+ pMove->GetFromRange().aStart.IncCol( nFrom );
+ else
+ pMove->GetFromRange().aEnd.IncCol( nFrom );
+ break;
+ case SC_CAT_DELETE_ROWS :
+ if ( nFrom > 0 )
+ pMove->GetFromRange().aStart.IncRow( nFrom );
+ else
+ pMove->GetFromRange().aEnd.IncRow( nFrom );
+ break;
+ case SC_CAT_DELETE_TABS :
+ if ( nFrom > 0 )
+ pMove->GetFromRange().aStart.IncTab( nFrom );
+ else
+ pMove->GetFromRange().aEnd.IncTab( nFrom );
+ break;
+ }
+ }
+ if ( nTo )
+ {
+ switch ( eActType )
+ {
+ case SC_CAT_DELETE_COLS :
+ if ( nTo > 0 )
+ pMove->GetBigRange().aStart.IncCol( nTo );
+ else
+ pMove->GetBigRange().aEnd.IncCol( nTo );
+ break;
+ case SC_CAT_DELETE_ROWS :
+ if ( nTo > 0 )
+ pMove->GetBigRange().aStart.IncRow( nTo );
+ else
+ pMove->GetBigRange().aEnd.IncRow( nTo );
+ break;
+ case SC_CAT_DELETE_TABS :
+ if ( nTo > 0 )
+ pMove->GetBigRange().aStart.IncTab( nTo );
+ else
+ pMove->GetBigRange().aEnd.IncTab( nTo );
+ break;
+ }
+ }
+ if ( nFrom || nTo )
+ {
+ ScChangeActionDelMoveEntry* pLink =
+ pActDel->AddCutOffMove( pMove, nFrom, nTo );
+ pMove->AddLink( pActDel, pLink );
+ }
+ }
+ break;
+ }
+ }
+ if ( bUpdate )
+ {
+ p->UpdateReference( this, eMode, aRange, nDx, nDy, nDz );
+ if ( p->GetType() == eActType && !p->IsRejected() &&
+ !pActDel->IsDeletedIn() &&
+ p->GetBigRange().In( aDelRange ) )
+ pActDel->SetDeletedIn( p ); // "druntergerutscht"
+ }
+ }
+ }
+ else
+ { // Undo Delete
+ ScChangeAction* pNextAction = NULL;
+ for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() )
+ {
+ if ( p == pAct )
+ continue; // for
+ BOOL bUpdate = TRUE;
+ if ( aDelRange.In( p->GetBigRange() ) )
+ {
+ if ( p->IsDeletedInDelType( eActType ) )
+ {
+ if ( p->IsDeletedIn( pActDel ) )
+ {
+ if ( p->GetType() != SC_CAT_CONTENT ||
+ ((ScChangeActionContent*)p)->IsTopContent() )
+ { // erst der TopContent wird wirklich entfernt
+ p->RemoveDeletedIn( pActDel );
+ // GeneratedDelContent _nicht_ aus Liste loeschen,
+ // wir brauchen ihn evtl. noch fuer Reject,
+ // geloescht wird in DeleteCellEntries
+ }
+ }
+ bUpdate = FALSE;
+ }
+ else if ( eActType != SC_CAT_DELETE_TABS &&
+ p->IsDeletedInDelType( SC_CAT_DELETE_TABS ) )
+ { // in geloeschten Tabellen nicht updaten,
+ // ausser wenn Tabelle verschoben wird
+ bUpdate = FALSE;
+ }
+ if ( p->GetType() == eActType && pActDel->IsDeletedIn( p ) )
+ {
+ pActDel->RemoveDeletedIn( p ); // "druntergerutscht"
+ bUpdate = TRUE;
+ }
+ }
+ if ( bUpdate )
+ p->UpdateReference( this, eMode, aRange, nDx, nDy, nDz );
+ }
+ if ( !bGeneratedDelContents )
+ { // die werden sonst noch fuer das echte Undo gebraucht
+ pActDel->UndoCutOffInsert();
+ pActDel->UndoCutOffMoves();
+ }
+ }
+ }
+ else if ( eActType == SC_CAT_MOVE )
+ {
+ ScChangeActionMove* pActMove = (ScChangeActionMove*) pAct;
+ BOOL bLastCutMove = ( pActMove == pLastCutMove );
+ const ScBigRange& rTo = pActMove->GetBigRange();
+ const ScBigRange& rFrom = pActMove->GetFromRange();
+ if ( !bUndo )
+ { // Move
+ for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() )
+ {
+ if ( p == pAct )
+ continue; // for
+ if ( p->GetType() == SC_CAT_CONTENT )
+ {
+ // Inhalt in Ziel deleten (Inhalt in Quelle moven)
+ if ( rTo.In( p->GetBigRange() ) )
+ {
+ if ( !p->IsDeletedIn( pActMove ) )
+ {
+ p->SetDeletedIn( pActMove );
+ // GeneratedDelContent in zu loeschende Liste aufnehmen
+ if ( bGeneratedDelContents )
+ pActMove->AddContent( (ScChangeActionContent*) p );
+ }
+ }
+ else if ( bLastCutMove &&
+ p->GetActionNumber() > nEndLastCut &&
+ rFrom.In( p->GetBigRange() ) )
+ { // Paste Cut: neuer Content nach Cut eingefuegt, bleibt.
+ // Aufsplitten der ContentChain
+ ScChangeActionContent *pHere, *pTmp;
+ pHere = (ScChangeActionContent*) p;
+ while ( (pTmp = pHere->GetPrevContent()) &&
+ pTmp->GetActionNumber() > nEndLastCut )
+ pHere = pTmp;
+ if ( pTmp )
+ { // wird TopContent des Move
+ pTmp->SetNextContent( NULL );
+ pHere->SetPrevContent( NULL );
+ }
+ do
+ { // Abhaengigkeit vom FromRange herstellen
+ AddDependentWithNotify( pActMove, pHere );
+ } while ( pHere = pHere->GetNextContent() );
+ }
+ else
+ p->UpdateReference( this, eMode, rFrom, nDx, nDy, nDz );
+ }
+ }
+ }
+ else
+ { // Undo Move
+ BOOL bActRejected = pActMove->IsRejected();
+ for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() )
+ {
+ if ( p == pAct )
+ continue; // for
+ if ( p->GetType() == SC_CAT_CONTENT )
+ {
+ // Inhalt in Ziel moven, wenn nicht deleted, sonst undelete
+ if ( p->IsDeletedIn( pActMove ) )
+ {
+ if ( ((ScChangeActionContent*)p)->IsTopContent() )
+ { // erst der TopContent wird wirklich entfernt
+ p->RemoveDeletedIn( pActMove );
+ // GeneratedDelContent _nicht_ aus Liste loeschen,
+ // wir brauchen ihn evtl. noch fuer Reject,
+ // geloescht wird in DeleteCellEntries
+ }
+ }
+ else
+ p->UpdateReference( this, eMode, rTo, nDx, nDy, nDz );
+ if ( bActRejected &&
+ ((ScChangeActionContent*)p)->IsTopContent() &&
+ rFrom.In( p->GetBigRange() ) )
+ { // Abhaengigkeit herstellen, um Content zu schreiben
+ ScChangeActionLinkEntry* pLink =
+ pActMove->AddDependent( p );
+ p->AddLink( pActMove, pLink );
+ }
+ }
+ }
+ }
+ }
+ else
+ { // Insert / Undo Insert
+ switch ( GetMergeState() )
+ {
+ case SC_CTMS_NONE :
+ case SC_CTMS_OTHER :
+ {
+ for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() )
+ {
+ if ( p == pAct )
+ continue; // for
+ p->UpdateReference( this, eMode, aRange, nDx, nDy, nDz );
+ }
+ }
+ break;
+ case SC_CTMS_PREPARE :
+ {
+ // in Insert-Undo "Deleten"
+ const ScChangeActionLinkEntry* pLink = pAct->GetFirstDependentEntry();
+ while ( pLink )
+ {
+ ScChangeAction* p = (ScChangeAction*) pLink->GetAction();
+ if ( p )
+ p->SetDeletedIn( pAct );
+ pLink = pLink->GetNext();
+ }
+ for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() )
+ {
+ if ( p == pAct )
+ continue; // for
+ if ( !p->IsDeletedIn( pAct ) )
+ p->UpdateReference( this, eMode, aRange, nDx, nDy, nDz );
+ }
+ }
+ break;
+ case SC_CTMS_OWN :
+ {
+ for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() )
+ {
+ if ( p == pAct )
+ continue; // for
+ if ( !p->IsDeletedIn( pAct ) )
+ p->UpdateReference( this, eMode, aRange, nDx, nDy, nDz );
+ }
+ // in Insert-Undo "Delete" rueckgaengig
+ const ScChangeActionLinkEntry* pLink = pAct->GetFirstDependentEntry();
+ while ( pLink )
+ {
+ ScChangeAction* p = (ScChangeAction*) pLink->GetAction();
+ if ( p )
+ p->RemoveDeletedIn( pAct );
+ pLink = pLink->GetNext();
+ }
+ }
+ break;
+ }
+ }
+}
+
+
+void ScChangeTrack::GetDependents( ScChangeAction* pAct,
+ ScChangeActionTable& rTable, BOOL bListMasterDelete, BOOL bAllFlat )
+{
+ //! bAllFlat==TRUE: intern aus Accept oder Reject gerufen,
+ //! => Generated werden nicht aufgenommen
+
+ BOOL bIsDelete = pAct->IsDeleteType();
+ BOOL bIsMasterDelete = ( bListMasterDelete && pAct->IsMasterDelete() );
+
+ ScChangeAction* pCur = pAct;
+ ScChangeActionStack* pStack = new ScChangeActionStack;
+ do
+ {
+ if ( pCur->IsInsertType() )
+ {
+ const ScChangeActionLinkEntry* pL = pCur->GetFirstDependentEntry();
+ while ( pL )
+ {
+ ScChangeAction* p = (ScChangeAction*) pL->GetAction();
+ if ( p != pAct )
+ {
+ if ( bAllFlat )
+ {
+ ULONG n = p->GetActionNumber();
+ if ( !IsGenerated( n ) && rTable.Insert( n, p ) )
+ if ( p->HasDependent() )
+ pStack->Push( p );
+ }
+ else
+ {
+ if ( p->GetType() == SC_CAT_CONTENT )
+ {
+ if ( ((ScChangeActionContent*)p)->IsTopContent() )
+ rTable.Insert( p->GetActionNumber(), p );
+ }
+ else
+ rTable.Insert( p->GetActionNumber(), p );
+ }
+ }
+ pL = pL->GetNext();
+ }
+ }
+ else if ( pCur->IsDeleteType() )
+ {
+ if ( bIsDelete )
+ { // Inhalte geloeschter Bereiche interessieren nur bei Delete
+ ScChangeActionDel* pDel = (ScChangeActionDel*) pCur;
+ if ( !bAllFlat && bIsMasterDelete && pCur == pAct )
+ {
+ // zu diesem Delete gehoerende Deletes in gleiche Ebene,
+ // wenn dieses Delete das momentan oberste einer Reihe ist,
+ ScChangeActionType eType = pDel->GetType();
+ ScChangeAction* p = pDel;
+ while ( (p = p->GetPrev()) && p->GetType() == eType &&
+ !((ScChangeActionDel*)p)->IsTopDelete() )
+ rTable.Insert( p->GetActionNumber(), p );
+ // dieses Delete auch in Table!
+ rTable.Insert( pAct->GetActionNumber(), pAct );
+ }
+ else
+ {
+ const ScChangeActionLinkEntry* pL = pCur->GetFirstDeletedEntry();
+ while ( pL )
+ {
+ ScChangeAction* p = (ScChangeAction*) pL->GetAction();
+ if ( p != pAct )
+ {
+ if ( bAllFlat )
+ {
+ // nur ein TopContent einer Kette ist in LinkDeleted
+ ULONG n = p->GetActionNumber();
+ if ( !IsGenerated( n ) && rTable.Insert( n, p ) )
+ if ( p->HasDeleted() ||
+ p->GetType() == SC_CAT_CONTENT )
+ pStack->Push( p );
+ }
+ else
+ {
+ if ( p->IsDeleteType() )
+ { // weiteres TopDelete in gleiche Ebene,
+ // es ist nicht rejectable
+ if ( ((ScChangeActionDel*)p)->IsTopDelete() )
+ rTable.Insert( p->GetActionNumber(), p );
+ }
+ else
+ rTable.Insert( p->GetActionNumber(), p );
+ }
+ }
+ pL = pL->GetNext();
+ }
+ }
+ }
+ }
+ else if ( pCur->GetType() == SC_CAT_MOVE )
+ {
+ // geloeschte Contents im ToRange
+ const ScChangeActionLinkEntry* pL = pCur->GetFirstDeletedEntry();
+ while ( pL )
+ {
+ ScChangeAction* p = (ScChangeAction*) pL->GetAction();
+ if ( p != pAct && rTable.Insert( p->GetActionNumber(), p ) )
+ {
+ // nur ein TopContent einer Kette ist in LinkDeleted
+ if ( bAllFlat && (p->HasDeleted() ||
+ p->GetType() == SC_CAT_CONTENT) )
+ pStack->Push( p );
+ }
+ pL = pL->GetNext();
+ }
+ // neue Contents im FromRange oder neuer FromRange im ToRange
+ // oder Inserts/Deletes in FromRange/ToRange
+ pL = pCur->GetFirstDependentEntry();
+ while ( pL )
+ {
+ ScChangeAction* p = (ScChangeAction*) pL->GetAction();
+ if ( p != pAct )
+ {
+ if ( bAllFlat )
+ {
+ ULONG n = p->GetActionNumber();
+ if ( !IsGenerated( n ) && rTable.Insert( n, p ) )
+ if ( p->HasDependent() || p->HasDeleted() )
+ pStack->Push( p );
+ }
+ else
+ {
+ if ( p->GetType() == SC_CAT_CONTENT )
+ {
+ if ( ((ScChangeActionContent*)p)->IsTopContent() )
+ rTable.Insert( p->GetActionNumber(), p );
+ }
+ else
+ rTable.Insert( p->GetActionNumber(), p );
+ }
+ }
+ pL = pL->GetNext();
+ }
+ }
+ else if ( pCur->GetType() == SC_CAT_CONTENT )
+ { // alle Aenderungen an gleicher Position
+ ScChangeActionContent* pContent = (ScChangeActionContent*) pCur;
+ // alle vorherigen
+ while ( pContent = pContent->GetPrevContent() )
+ {
+ if ( !pContent->IsRejected() )
+ rTable.Insert( pContent->GetActionNumber(), pContent );
+ }
+ pContent = (ScChangeActionContent*) pCur;
+ // alle nachfolgenden
+ while ( pContent = pContent->GetNextContent() )
+ {
+ if ( !pContent->IsRejected() )
+ rTable.Insert( pContent->GetActionNumber(), pContent );
+ }
+ }
+ else if ( pCur->GetType() == SC_CAT_REJECT )
+ {
+ if ( bAllFlat )
+ {
+ ScChangeAction* p = GetAction(
+ ((ScChangeActionReject*)pCur)->GetRejectAction() );
+ if ( p != pAct && !rTable.Get( p->GetActionNumber() ) )
+ pStack->Push( p );
+ }
+ }
+ } while ( pCur = pStack->Pop() );
+ delete pStack;
+}
+
+
+BOOL ScChangeTrack::SelectContent( ScChangeAction* pAct, BOOL bOldest )
+{
+ if ( pAct->GetType() != SC_CAT_CONTENT )
+ return FALSE;
+
+ ScChangeActionContent* pContent = (ScChangeActionContent*) pAct;
+ if ( bOldest )
+ {
+ pContent = pContent->GetTopContent();
+ ScChangeActionContent* pPrevContent;
+ while ( (pPrevContent = pContent->GetPrevContent()) &&
+ pPrevContent->IsVirgin() )
+ pContent = pPrevContent;
+ }
+
+ if ( !pContent->IsClickable() )
+ return FALSE;
+
+ return pContent->Select( pDoc, this, bOldest );
+}
+
+
+void ScChangeTrack::AcceptAll()
+{
+ for ( ScChangeAction* p = GetFirst(); p; p = p->GetNext() )
+ {
+ p->Accept();
+ }
+}
+
+
+BOOL ScChangeTrack::Accept( ScChangeAction* pAct )
+{
+ if ( !pAct->IsClickable() )
+ return FALSE;
+
+ if ( pAct->IsDeleteType() || pAct->GetType() == SC_CAT_CONTENT )
+ {
+ ScChangeActionTable* pTable = new ScChangeActionTable;
+ GetDependents( pAct, *pTable, FALSE, TRUE );
+ for ( ScChangeAction* p = pTable->First(); p; p = pTable->Next() )
+ {
+ p->Accept();
+ }
+ delete pTable;
+ }
+ pAct->Accept();
+ return TRUE;
+}
+
+
+BOOL ScChangeTrack::RejectAll()
+{
+ BOOL bOk = TRUE;
+ for ( ScChangeAction* p = GetLast(); p && bOk; p = p->GetPrev() )
+ { //! rueckwaerts, weil abhaengige hinten und RejectActions angehaengt
+ if ( p->IsRejectable() )
+ bOk = Reject( p );
+ }
+ return bOk;
+}
+
+
+BOOL ScChangeTrack::Reject( ScChangeAction* pAct )
+{
+ if ( !pAct->IsRejectable() )
+ return FALSE;
+
+ ScChangeActionTable* pTable = NULL;
+ if ( pAct->HasDependent() )
+ {
+ pTable = new ScChangeActionTable;
+ GetDependents( pAct, *pTable, FALSE, TRUE );
+ }
+ BOOL bRejected = Reject( pAct, pTable, FALSE );
+ if ( pTable )
+ delete pTable;
+ return bRejected;
+}
+
+
+BOOL ScChangeTrack::Reject( ScChangeAction* pAct, ScChangeActionTable* pTable,
+ BOOL bRecursion )
+{
+ if ( !pAct->IsRejectable() )
+ return FALSE;
+
+ BOOL bOk = TRUE;
+ BOOL bRejected = FALSE;
+ if ( pAct->IsInsertType() )
+ {
+ if ( pAct->HasDependent() && !bRecursion )
+ {
+ const ScBigRange& rRange = pAct->GetBigRange();
+ DBG_ASSERT( pTable, "ScChangeTrack::Reject: Insert ohne Table" );
+ for ( ScChangeAction* p = pTable->Last(); p && bOk; p = pTable->Prev() )
+ {
+ // keine Contents restoren, die eh geloescht werden wuerden
+ if ( p->GetType() == SC_CAT_CONTENT )
+ p->SetRejected();
+ else if ( p->IsDeleteType() )
+ p->Accept(); // geloeschtes ins Nirvana
+ else
+ bOk = Reject( p, NULL, TRUE ); //! rekursiv
+ }
+ }
+ if ( bOk && (bRejected = pAct->Reject( pDoc )) )
+ {
+ // pRefDoc NULL := geloeschte Zellen nicht speichern
+ AppendDeleteRange( pAct->GetBigRange().MakeRange(), NULL, (short) 0,
+ pAct->GetActionNumber() );
+ }
+ }
+ else if ( pAct->IsDeleteType() )
+ {
+ DBG_ASSERT( !pTable, "ScChangeTrack::Reject: Delete mit Table" );
+ ScBigRange aDelRange;
+ ULONG nRejectAction = pAct->GetActionNumber();
+ BOOL bTabDel, bTabDelOk;
+ if ( pAct->GetType() == SC_CAT_DELETE_TABS )
+ {
+ bTabDel = TRUE;
+ aDelRange = pAct->GetBigRange();
+ bOk = bTabDelOk = pAct->Reject( pDoc );
+ if ( bOk )
+ {
+ pAct = pAct->GetPrev();
+ bOk = ( pAct && pAct->GetType() == SC_CAT_DELETE_COLS );
+ }
+ }
+ else
+ bTabDel = bTabDelOk = FALSE;
+ ScChangeActionDel* pDel = (ScChangeActionDel*) pAct;
+ if ( bOk )
+ {
+ aDelRange = pDel->GetOverAllRange();
+ bOk = aDelRange.IsValid( pDoc );
+ }
+ BOOL bOneOk = FALSE;
+ if ( bOk )
+ {
+ ScChangeActionType eActType = pAct->GetType();
+ switch ( eActType )
+ {
+ case SC_CAT_DELETE_COLS :
+ aDelRange.aStart.SetCol( aDelRange.aEnd.Col() );
+ break;
+ case SC_CAT_DELETE_ROWS :
+ aDelRange.aStart.SetRow( aDelRange.aEnd.Row() );
+ break;
+ case SC_CAT_DELETE_TABS :
+ aDelRange.aStart.SetTab( aDelRange.aEnd.Tab() );
+ break;
+ }
+ ScChangeAction* p = pAct;
+ BOOL bLoop = TRUE;
+ do
+ {
+ pDel = (ScChangeActionDel*) p;
+ bOk = pDel->Reject( pDoc );
+ if ( bOk )
+ {
+ if ( bOneOk )
+ {
+ switch ( pDel->GetType() )
+ {
+ case SC_CAT_DELETE_COLS :
+ aDelRange.aStart.IncCol( -1 );
+ break;
+ case SC_CAT_DELETE_ROWS :
+ aDelRange.aStart.IncRow( -1 );
+ break;
+ case SC_CAT_DELETE_TABS :
+ aDelRange.aStart.IncTab( -1 );
+ break;
+ }
+ }
+ else
+ bOneOk = TRUE;
+ }
+ if ( pDel->IsBaseDelete() )
+ bLoop = FALSE;
+ else
+ p = p->GetPrev();
+ } while ( bOk && bLoop && p && p->GetType() == eActType &&
+ !((ScChangeActionDel*)p)->IsTopDelete() );
+ }
+ bRejected = bOk;
+ if ( bOneOk || (bTabDel && bTabDelOk) )
+ {
+ // Delete-Reject machte UpdateReference Undo
+ ScChangeActionIns* pReject = new ScChangeActionIns(
+ aDelRange.MakeRange() );
+ pReject->SetRejectAction( nRejectAction );
+ pReject->SetState( SC_CAS_ACCEPTED );
+ Append( pReject );
+ }
+ }
+ else if ( pAct->GetType() == SC_CAT_MOVE )
+ {
+ if ( pAct->HasDependent() && !bRecursion )
+ {
+ const ScBigRange& rRange = pAct->GetBigRange();
+ DBG_ASSERT( pTable, "ScChangeTrack::Reject: Move ohne Table" );
+ for ( ScChangeAction* p = pTable->Last(); p && bOk; p = pTable->Prev() )
+ {
+ bOk = Reject( p, NULL, TRUE ); //! rekursiv
+ }
+ }
+ if ( bOk && (bRejected = pAct->Reject( pDoc )) )
+ {
+ ScChangeActionMove* pReject = new ScChangeActionMove(
+ pAct->GetBigRange().MakeRange(),
+ ((ScChangeActionMove*)pAct)->GetFromRange().MakeRange(), this );
+ pReject->SetRejectAction( pAct->GetActionNumber() );
+ pReject->SetState( SC_CAS_ACCEPTED );
+ Append( pReject );
+ }
+ }
+ else if ( pAct->GetType() == SC_CAT_CONTENT )
+ {
+ ScRange aRange;
+ ScChangeActionContent* pReject;
+ if ( bRecursion )
+ pReject = NULL;
+ else
+ {
+ aRange = pAct->GetBigRange().aStart.MakeAddress();
+ pReject = new ScChangeActionContent( aRange );
+ pReject->SetOldValue( pDoc->GetCell( aRange.aStart ), pDoc, pDoc );
+ }
+ if ( (bRejected = pAct->Reject( pDoc )) && !bRecursion )
+ {
+ pReject->SetNewValue( pDoc->GetCell( aRange.aStart ), pDoc );
+ pReject->SetRejectAction( pAct->GetActionNumber() );
+ pReject->SetState( SC_CAS_ACCEPTED );
+ Append( pReject );
+ }
+ else if ( pReject )
+ delete pReject;
+ }
+ else
+ DBG_ERROR( "ScChangeTrack::Reject: say what?" );
+
+ return bRejected;
+}
+
+
diff --git a/sc/source/core/tool/chgviset.cxx b/sc/source/core/tool/chgviset.cxx
new file mode 100644
index 000000000000..f67d793cc4f7
--- /dev/null
+++ b/sc/source/core/tool/chgviset.cxx
@@ -0,0 +1,226 @@
+/*************************************************************************
+ *
+ * $RCSfile: chgviset.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include <svtools/txtcmp.hxx>
+
+#include "chgviset.hxx"
+#include "rechead.hxx"
+
+// -----------------------------------------------------------------------
+ScChangeViewSettings::~ScChangeViewSettings()
+{
+ if(pCommentSearcher!=NULL)
+ delete pCommentSearcher;
+}
+
+ScChangeViewSettings::ScChangeViewSettings( const ScChangeViewSettings& r )
+{
+ SetTheComment(r.aComment);
+
+ aFirstDateTime =r.aFirstDateTime;
+ aLastDateTime =r.aLastDateTime;
+ aAuthorToShow =r.aAuthorToShow;
+ aRangeList =r.aRangeList;
+ eDateMode =r.eDateMode;
+ bShowIt =r.bShowIt;
+ bIsDate =r.bIsDate;
+ bIsAuthor =r.bIsAuthor;
+ bIsComment =r.bIsComment;
+ bIsRange =r.bIsRange;
+ bEveryoneButMe =r.bEveryoneButMe;
+ bShowAccepted =r.bShowAccepted;
+ bShowRejected =r.bShowRejected;
+
+}
+
+ScChangeViewSettings& ScChangeViewSettings::operator=( const ScChangeViewSettings& r )
+{
+ SetTheComment(r.aComment);
+
+ aFirstDateTime =r.aFirstDateTime;
+ aLastDateTime =r.aLastDateTime;
+ aAuthorToShow =r.aAuthorToShow;
+ aRangeList =r.aRangeList;
+ eDateMode =r.eDateMode;
+ bShowIt =r.bShowIt;
+ bIsDate =r.bIsDate;
+ bIsAuthor =r.bIsAuthor;
+ bIsComment =r.bIsComment;
+ bIsRange =r.bIsRange;
+ bEveryoneButMe =r.bEveryoneButMe;
+ bShowAccepted =r.bShowAccepted;
+ bShowRejected =r.bShowRejected;
+
+ return *this;
+}
+
+BOOL ScChangeViewSettings::IsValidComment(const String* pCommentStr) const
+{
+ BOOL nTheFlag=TRUE;
+
+ if(pCommentSearcher!=NULL)
+ {
+ xub_StrLen nStartPos = 0;
+ xub_StrLen nEndPos = pCommentStr->Len();
+
+ nTheFlag=pCommentSearcher->SearchFrwrd( *pCommentStr, &nStartPos, &nEndPos);
+ }
+ return nTheFlag;
+}
+
+void ScChangeViewSettings::SetTheComment(const String& rString)
+{
+ aComment=rString;
+ if(pCommentSearcher!=NULL)
+ {
+ delete pCommentSearcher;
+ pCommentSearcher=NULL;
+ }
+
+ if(rString.Len()>0)
+ {
+ SearchParam aSearchParam( rString,
+ SearchParam::SRCH_REGEXP,FALSE,FALSE,FALSE );
+
+ pCommentSearcher=new SearchText( aSearchParam, *ScGlobal::pScInternational );
+ }
+}
+
+void ScChangeViewSettings::Load( SvStream& rStream, USHORT nVer )
+{
+ ScReadHeader aHdr( rStream );
+
+ BYTE nByte;
+ UINT32 nDT;
+ rStream >> bShowIt;
+ rStream >> bIsDate;
+ rStream >> nByte; eDateMode = (ScChgsDateMode)nByte;
+ rStream >> nDT; aFirstDateTime.SetDate( nDT );
+ rStream >> nDT; aFirstDateTime.SetTime( nDT );
+ rStream >> nDT; aLastDateTime.SetDate( nDT );
+ rStream >> nDT; aLastDateTime.SetTime( nDT );
+ rStream >> bIsAuthor;
+ rStream >> bEveryoneButMe;
+ rStream.ReadByteString( aAuthorToShow, rStream.GetStreamCharSet() );
+ rStream >> bIsRange;
+ aRangeList.Load( rStream, nVer );
+ if ( aHdr.BytesLeft() )
+ {
+ rStream >> bShowAccepted;
+ rStream >> bShowRejected;
+ }
+ else
+ {
+ bShowAccepted = FALSE;
+ bShowRejected = FALSE;
+ }
+
+ // Zusaetzlich Kommentar-Informationen lesen (src509)
+ if ( aHdr.BytesLeft() ) //#59103#
+ {
+ rStream >> bIsComment;
+ rStream.ReadByteString( aComment, rStream.GetStreamCharSet() );
+ }
+ else
+ {
+ bIsComment = FALSE;
+ aComment.Erase();
+ }
+ SetTheComment(aComment);
+}
+
+void ScChangeViewSettings::Store( SvStream& rStream ) const
+{
+ ScWriteHeader aHdr( rStream, 42 ); // Groesse, wenn String und RangeList leer sind
+
+ rStream << bShowIt;
+ rStream << bIsDate;
+ rStream << (BYTE) eDateMode;
+ rStream << (UINT32) aFirstDateTime.GetDate();
+ rStream << (UINT32) aFirstDateTime.GetTime();
+ rStream << (UINT32) aLastDateTime.GetDate();
+ rStream << (UINT32) aLastDateTime.GetTime();
+ rStream << bIsAuthor;
+ rStream << bEveryoneButMe;
+ rStream.WriteByteString( aAuthorToShow, rStream.GetStreamCharSet() );
+ rStream << bIsRange;
+ aRangeList.Store( rStream );
+ rStream << bShowAccepted;
+ rStream << bShowRejected;
+
+ // Zusaetzlich Kommentar-Informationen schreiben (src509)
+ if(bIsComment || aComment.Len()>0) //#59103#
+ {
+ rStream << bIsComment;
+ rStream.WriteByteString( aComment, rStream.GetStreamCharSet() );
+ }
+}
+
+
+
+
+
diff --git a/sc/source/core/tool/collect.cxx b/sc/source/core/tool/collect.cxx
new file mode 100644
index 000000000000..8aab10f2274b
--- /dev/null
+++ b/sc/source/core/tool/collect.cxx
@@ -0,0 +1,562 @@
+/*************************************************************************
+ *
+ * $RCSfile: collect.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include <string.h>
+
+#ifndef _TOOLS_INTN_HXX //autogen
+#include <tools/intn.hxx>
+#endif
+#ifndef _STREAM_HXX //autogen
+#include <tools/stream.hxx>
+#endif
+
+#include "rechead.hxx"
+#include "collect.hxx"
+#include "document.hxx" // fuer TypedStrData Konstruktor
+
+// -----------------------------------------------------------------------
+
+DataObject::~DataObject()
+{
+}
+
+//------------------------------------------------------------------------
+// Collection
+//------------------------------------------------------------------------
+
+void lcl_DeleteDataObjects( DataObject** p, USHORT nCount )
+{
+ if ( p )
+ {
+ for (USHORT i = 0; i < nCount; i++) delete p[i];
+ delete[] p;
+ p = NULL;
+ }
+}
+
+Collection::Collection(USHORT nLim, USHORT nDel) :
+ nCount ( 0 ),
+ nLimit ( nLim ),
+ nDelta ( nDel ),
+ pItems ( NULL )
+{
+ if (nDelta > MAXDELTA)
+ nDelta = MAXDELTA;
+ else if (nDelta == 0)
+ nDelta = 1;
+ if (nLimit > MAXCOLLECTIONSIZE)
+ nLimit = MAXCOLLECTIONSIZE;
+ else if (nLimit < nDelta)
+ nLimit = nDelta;
+ pItems = new DataObject*[nLimit];
+}
+
+Collection::Collection(const Collection& rCollection)
+ : nCount ( 0 ),
+ nLimit ( 0 ),
+ nDelta ( 0 ),
+ pItems ( NULL )
+{
+ *this = rCollection;
+}
+
+//------------------------------------------------------------------------
+
+Collection::~Collection()
+{
+ lcl_DeleteDataObjects( pItems, nCount );
+}
+
+//------------------------------------------------------------------------
+
+void Collection::AtFree(USHORT nIndex)
+{
+ if ((pItems) && (nIndex < nCount))
+ {
+ delete pItems[nIndex];
+ memmove ( &pItems[nIndex], &pItems[nIndex + 1], (nCount - nIndex) * sizeof(DataObject*));
+ --nCount;
+ pItems[nCount] = NULL;
+ }
+}
+
+//------------------------------------------------------------------------
+
+void Collection::Free(DataObject* pDataObject)
+{
+ AtFree(IndexOf(pDataObject));
+}
+
+//------------------------------------------------------------------------
+
+void Collection::FreeAll()
+{
+ lcl_DeleteDataObjects( pItems, nCount );
+ nCount = 0;
+ pItems = new DataObject*[nLimit];
+}
+
+//------------------------------------------------------------------------
+
+BOOL Collection::AtInsert(USHORT nIndex, DataObject* pDataObject)
+{
+ if ((nCount < MAXCOLLECTIONSIZE) && (nIndex <= nCount) && pItems)
+ {
+ if (nCount == nLimit)
+ {
+ DataObject** pNewItems = new DataObject*[nLimit + nDelta];
+ if (!pNewItems)
+ return FALSE;
+ nLimit += nDelta;
+ memmove(pNewItems, pItems, nCount * sizeof(DataObject*));
+ delete[] pItems;
+ pItems = pNewItems;
+ }
+ if (nCount > nIndex)
+ memmove(&pItems[nIndex + 1], &pItems[nIndex], (nCount - nIndex) * sizeof(DataObject*));
+ pItems[nIndex] = pDataObject;
+ nCount++;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+//------------------------------------------------------------------------
+
+BOOL Collection::Insert(DataObject* pDataObject)
+{
+ return AtInsert(nCount, pDataObject);
+}
+
+//------------------------------------------------------------------------
+
+DataObject* Collection::At(USHORT nIndex) const
+{
+ if (nIndex < nCount)
+ return pItems[nIndex];
+ else
+ return NULL;
+}
+
+//------------------------------------------------------------------------
+
+USHORT Collection::IndexOf(DataObject* pDataObject) const
+{
+ USHORT nIndex = 0xffff;
+ for (USHORT i = 0; ((i < nCount) && (nIndex == 0xffff)); i++)
+ {
+ if (pItems[i] == pDataObject) nIndex = i;
+ }
+ return nIndex;
+}
+
+//------------------------------------------------------------------------
+
+Collection& Collection::operator=( const Collection& r )
+{
+ lcl_DeleteDataObjects( pItems, nCount );
+
+ nCount = r.nCount;
+ nLimit = r.nLimit;
+ nDelta = r.nDelta;
+ pItems = new DataObject*[nLimit];
+ for ( USHORT i=0; i<nCount; i++ )
+ pItems[i] = r.pItems[i]->Clone();
+
+ return *this;
+}
+
+//------------------------------------------------------------------------
+
+DataObject* Collection::Clone() const
+{
+ return new Collection(*this);
+}
+
+//------------------------------------------------------------------------
+// SortedCollection
+//------------------------------------------------------------------------
+
+SortedCollection::SortedCollection(USHORT nLim, USHORT nDel, BOOL bDup) :
+ Collection (nLim, nDel),
+ bDuplicates ( bDup)
+{
+}
+
+//------------------------------------------------------------------------
+
+USHORT SortedCollection::IndexOf(DataObject* pDataObject) const
+{
+ USHORT nIndex;
+ if (Search(pDataObject, nIndex))
+ return nIndex;
+ else
+ return 0xffff;
+}
+
+//------------------------------------------------------------------------
+
+BOOL SortedCollection::Search(DataObject* pDataObject, USHORT& rIndex) const
+{
+ rIndex = nCount;
+ BOOL bFound = FALSE;
+ short nLo = 0;
+ short nHi = nCount - 1;
+ short nIndex;
+ short nCompare;
+ while (nLo <= nHi)
+ {
+ nIndex = (nLo + nHi) / 2;
+ nCompare = Compare(pItems[nIndex], pDataObject);
+ if (nCompare < 0)
+ nLo = nIndex + 1;
+ else
+ {
+ nHi = nIndex - 1;
+ if (nCompare == 0)
+ {
+ bFound = TRUE;
+ nLo = nIndex;
+ }
+ }
+ }
+ rIndex = nLo;
+ return bFound;
+}
+
+//------------------------------------------------------------------------
+
+BOOL SortedCollection::Insert(DataObject* pDataObject)
+{
+ USHORT nIndex;
+ BOOL bFound = Search(pDataObject, nIndex);
+ if (bFound)
+ {
+ if (bDuplicates)
+ return AtInsert(nIndex, pDataObject);
+ else
+ return FALSE;
+ }
+ else
+ return AtInsert(nIndex, pDataObject);
+}
+
+//------------------------------------------------------------------------
+
+BOOL SortedCollection::InsertPos(DataObject* pDataObject, USHORT& nIndex)
+{
+ BOOL bFound = Search(pDataObject, nIndex);
+ if (bFound)
+ {
+ if (bDuplicates)
+ return AtInsert(nIndex, pDataObject);
+ else
+ return FALSE;
+ }
+ else
+ return AtInsert(nIndex, pDataObject);
+}
+
+//------------------------------------------------------------------------
+
+BOOL SortedCollection::operator==(const SortedCollection& rCmp) const
+{
+ if ( nCount != rCmp.nCount )
+ return FALSE;
+ for (USHORT i=0; i<nCount; i++)
+ if ( !IsEqual(pItems[i],rCmp.pItems[i]) )
+ return FALSE;
+ return TRUE;
+}
+
+//------------------------------------------------------------------------
+
+// IsEqual - komplette Inhalte vergleichen
+
+BOOL SortedCollection::IsEqual(DataObject* pKey1, DataObject* pKey2) const
+{
+ return ( Compare(pKey1, pKey2) == 0 ); // Default: nur Index vergleichen
+}
+
+//------------------------------------------------------------------------
+
+DataObject* StrData::Clone() const
+{
+ return new StrData(*this);
+}
+
+//------------------------------------------------------------------------
+
+short StrCollection::Compare(DataObject* pKey1, DataObject* pKey2) const
+{
+ StringCompare eComp = ((StrData*)pKey2)->aStr.CompareTo(((StrData*)pKey1)->aStr);
+ if (eComp == COMPARE_EQUAL)
+ return 0;
+ else if (eComp == COMPARE_LESS)
+ return -1;
+ else
+ return 1;
+}
+
+//------------------------------------------------------------------------
+
+DataObject* StrCollection::Clone() const
+{
+ return new StrCollection(*this);
+}
+
+//------------------------------------------------------------------------
+
+void StrCollection::Load( SvStream& rStream )
+{
+ ScReadHeader aHdr( rStream );
+ lcl_DeleteDataObjects( pItems, nCount );
+ BOOL bDups;
+ rStream >> bDups;
+ SetDups( bDups );
+ rStream >> nCount >> nLimit >> nDelta;
+ pItems = new DataObject*[nLimit];
+ String aStr;
+ rtl_TextEncoding eSet = rStream.GetStreamCharSet();
+ for ( USHORT i=0; i<nCount; i++ )
+ {
+ rStream.ReadByteString( aStr, eSet );
+ pItems[i] = new StrData( aStr );
+ }
+}
+
+void StrCollection::Store( SvStream& rStream ) const
+{
+ ScWriteHeader aHdr( rStream );
+ BOOL bDups = IsDups();
+ rStream << bDups << nCount << nLimit << nDelta;
+ rtl_TextEncoding eSet = rStream.GetStreamCharSet();
+ for ( USHORT i=0; i<nCount; i++ )
+ {
+ rStream.WriteByteString( ((StrData*)pItems[i])->GetString(), eSet );
+ }
+}
+
+//------------------------------------------------------------------------
+// TypedStrCollection
+//------------------------------------------------------------------------
+
+TypedStrData::TypedStrData( ScDocument* pDoc, USHORT nCol, USHORT nRow, USHORT nTab,
+ BOOL bAllStrings )
+{
+ if ( pDoc->HasValueData( nCol, nRow, nTab ) )
+ {
+ pDoc->GetValue( nCol, nRow, nTab, nValue );
+ if (bAllStrings)
+ pDoc->GetString( nCol, nRow, nTab, aStrValue );
+ nStrType = 0;
+ }
+ else
+ {
+ pDoc->GetString( nCol, nRow, nTab, aStrValue );
+ nValue = 0.0;
+ nStrType = 1; //! Typ uebergeben ?
+ }
+}
+
+DataObject* TypedStrData::Clone() const
+{
+ return new TypedStrData(*this);
+}
+
+DataObject* TypedStrCollection::Clone() const
+{
+ return new TypedStrCollection(*this);
+}
+
+short TypedStrCollection::Compare( DataObject* pKey1, DataObject* pKey2 ) const
+{
+ short nResult = 0;
+
+ if ( pKey1 && pKey2 )
+ {
+ TypedStrData& rData1 = (TypedStrData&)*pKey1;
+ TypedStrData& rData2 = (TypedStrData&)*pKey2;
+
+ if ( rData1.nStrType > rData2.nStrType )
+ nResult = 1;
+ else if ( rData1.nStrType < rData2.nStrType )
+ nResult = -1;
+ else if ( !rData1.nStrType /* && !rData2.nStrType */ )
+ {
+ //--------------------
+ // Zahlen vergleichen:
+ //--------------------
+ if ( rData1.nValue == rData2.nValue )
+ nResult = 0;
+ else if ( rData1.nValue < rData2.nValue )
+ nResult = -1;
+ else
+ nResult = 1;
+ }
+ else /* if ( rData1.nStrType && rData2.nStrType ) */
+ {
+ //---------------------
+ // Strings vergleichen:
+ //---------------------
+ StringCompare eComp = ScGlobal::pScInternational->Compare(
+ rData1.aStrValue, rData2.aStrValue,
+ bCaseSensitive ? 0 : INTN_COMPARE_IGNORECASE );
+
+ if ( eComp == COMPARE_EQUAL )
+ nResult = 0;
+ else if ( eComp == COMPARE_LESS )
+ nResult = -1;
+ else
+ nResult = 1;
+ }
+ }
+
+ return nResult;
+}
+
+BOOL TypedStrCollection::FindText( const String& rStart, String& rResult,
+ USHORT& rPos, BOOL bBack ) const
+{
+ // Die Collection ist nach String-Vergleichen sortiert, darum muss hier
+ // alles durchsucht werden
+
+ International* pInt = ScGlobal::pScInternational;
+
+ xub_StrLen nCmpLen = rStart.Len();
+ BOOL bFound = FALSE;
+
+ if ( bBack ) // rueckwaerts
+ {
+ USHORT nStartPos = nCount;
+ if ( rPos != SCPOS_INVALID )
+ nStartPos = rPos; // weitersuchen...
+
+ for ( USHORT i=nStartPos; i>0; )
+ {
+ --i;
+ TypedStrData* pData = (TypedStrData*) pItems[i];
+ if (pData->nStrType)
+ {
+ String aCmp = pData->aStrValue.Copy(0,nCmpLen);
+ if ( pInt->CompareEqual( aCmp, rStart, INTN_COMPARE_IGNORECASE ) )
+ {
+ rResult = pData->aStrValue;
+ rPos = i;
+ bFound = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ else // vorwaerts
+ {
+ USHORT nStartPos = 0;
+ if ( rPos != SCPOS_INVALID )
+ nStartPos = rPos + 1; // weitersuchen...
+
+ for ( USHORT i=nStartPos; i<nCount; i++ )
+ {
+ TypedStrData* pData = (TypedStrData*) pItems[i];
+ if (pData->nStrType)
+ {
+ String aCmp = pData->aStrValue.Copy(0,nCmpLen);
+ if ( pInt->CompareEqual( aCmp, rStart, INTN_COMPARE_IGNORECASE ) )
+ {
+ rResult = pData->aStrValue;
+ rPos = i;
+ bFound = TRUE;
+ break;
+ }
+ }
+ }
+ }
+
+ return bFound;
+}
+
+ // Gross-/Kleinschreibung anpassen
+
+BOOL TypedStrCollection::GetExactMatch( String& rString ) const
+{
+ International* pInt = ScGlobal::pScInternational;
+ for (USHORT i=0; i<nCount; i++)
+ {
+ TypedStrData* pData = (TypedStrData*) pItems[i];
+ if ( pData->nStrType &&
+ pInt->CompareEqual( pData->aStrValue, rString, INTN_COMPARE_IGNORECASE ) )
+ {
+ rString = pData->aStrValue; // String anpassen
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
new file mode 100644
index 000000000000..edbece11d7b5
--- /dev/null
+++ b/sc/source/core/tool/compiler.cxx
@@ -0,0 +1,3468 @@
+/*************************************************************************
+ *
+ * $RCSfile: compiler.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <sfx2/app.hxx>
+#include <sfx2/objsh.hxx>
+#include <basic/sbmeth.hxx>
+#include <basic/sbstar.hxx>
+#include <svtools/zforlist.hxx>
+#include <vcl/rcid.h>
+#include <tools/intn.hxx>
+#include <tools/rc.hxx>
+#include <tools/solar.h>
+#include <unotools/charclass.hxx>
+#ifndef _URLOBJ_HXX
+#include <tools/urlobj.hxx>
+#endif
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "compiler.hxx"
+#include "rangenam.hxx"
+#include "dbcolect.hxx"
+#include "document.hxx"
+#include "callform.hxx"
+#include "addincol.hxx"
+#include "refupdat.hxx"
+#include "scresid.hxx"
+#include "sc.hrc"
+#include "globstr.hrc"
+#include "cell.hxx"
+#include "dociter.hxx"
+#include "docoptio.hxx"
+
+
+String* ScCompiler::pSymbolTableNative = NULL; // Liste der Symbole
+String* ScCompiler::pSymbolTableEnglish = NULL; // Liste der Symbole English
+USHORT ScCompiler::nAnzStrings = 0; // Anzahl der Symbole
+USHORT* ScCompiler::pCharTable = 0;
+
+enum ScanState
+{
+ ssGetChar, ssGetBool, ssGetString,
+ ssSkipString, ssStop
+};
+
+struct ScArrayStack
+{
+ ScArrayStack* pNext;
+ ScTokenArray* pArr;
+ BOOL bTemp;
+};
+
+static sal_Char* pInternal[ 5 ] = { "GAME", "SPEW", "TTT", "STARCALCTEAM", "ANTWORT" };
+
+
+/////////////////////////////////////////////////////////////////////////
+
+short lcl_GetRetFormat( OpCode eOpCode )
+{
+ switch (eOpCode)
+ {
+ case ocEqual:
+ case ocNotEqual:
+ case ocLess:
+ case ocGreater:
+ case ocLessEqual:
+ case ocGreaterEqual:
+ case ocAnd:
+ case ocOr:
+ case ocNot:
+ case ocTrue:
+ case ocFalse:
+ case ocIsEmpty:
+ case ocIsString:
+ case ocIsNonString:
+ case ocIsLogical:
+ case ocIsRef:
+ case ocIsValue:
+ case ocIsFormula:
+ case ocIsNV:
+ case ocIsErr:
+ case ocIsError:
+ case ocIsEven:
+ case ocIsOdd:
+ case ocExact:
+ return NUMBERFORMAT_LOGICAL;
+ case ocGetActDate:
+ case ocGetDate:
+ case ocEasterSunday :
+ return NUMBERFORMAT_DATE;
+ case ocGetActTime:
+ return NUMBERFORMAT_DATETIME;
+ case ocGetTime:
+ return NUMBERFORMAT_TIME;
+ case ocNBW:
+ case ocBW:
+ case ocDIA:
+ case ocGDA:
+ case ocGDA2:
+ case ocVBD:
+ case ocLIA:
+ case ocRMZ:
+ case ocZW:
+ case ocZinsZ:
+ case ocKapz:
+ case ocKumZinsZ:
+ case ocKumKapZ:
+ return NUMBERFORMAT_CURRENCY;
+ case ocZins:
+ case ocIKV:
+ case ocZGZ:
+ case ocEffektiv:
+ case ocNominal:
+ return NUMBERFORMAT_PERCENT;
+// case ocSum:
+// case ocSumSQ:
+// case ocProduct:
+// case ocAverage:
+// return -1;
+ default:
+ return NUMBERFORMAT_NUMBER;
+ }
+ return NUMBERFORMAT_NUMBER;
+}
+
+/////////////////////////////////////////////////////////////////////////
+
+class ScOpCodeList : public Resource // temp object fuer Resource
+{
+public:
+ ScOpCodeList( USHORT, String[] );
+};
+
+ScOpCodeList::ScOpCodeList( USHORT nRID, String pSymbolTable[] )
+ :
+ Resource( ScResId( nRID ) )
+{
+ for (USHORT i = 0; i <= SC_OPCODE_LAST_OPCODE_ID; i++)
+ {
+ ScResId aRes(i);
+ aRes.SetRT(RSC_STRING);
+ if (IsAvailableRes(aRes))
+ pSymbolTable[i] = aRes;
+ }
+ FreeResource();
+}
+
+
+void ScCompiler::Init()
+{
+ pSymbolTableNative = new String[SC_OPCODE_LAST_OPCODE_ID+1];
+ ScOpCodeList aOpCodeListNative( RID_SC_FUNCTION_NAMES, pSymbolTableNative );
+ nAnzStrings = SC_OPCODE_LAST_OPCODE_ID+1;
+
+ pCharTable = new USHORT [128];
+ USHORT i;
+ for (i = 0; i < 128; i++)
+ pCharTable[i] = SC_COMPILER_C_ILLEGAL;
+ /* */ pCharTable[32] = SC_COMPILER_C_CHAR_DONTCARE | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+ /* ! */ pCharTable[33] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+ /* " */ pCharTable[34] = SC_COMPILER_C_CHAR_STRING | SC_COMPILER_C_STRING_SEP;
+ /* # */ pCharTable[35] = SC_COMPILER_C_WORD_SEP;
+ /* $ */ pCharTable[36] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD;
+ /* % */ pCharTable[37] = SC_COMPILER_C_VALUE;
+ /* & */ pCharTable[38] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+ /* ' */ pCharTable[39] = SC_COMPILER_C_NAME_SEP;
+ /* ( */ pCharTable[40] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+ /* ) */ pCharTable[41] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+ /* * */ pCharTable[42] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+ /* + */ pCharTable[43] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_EXP | SC_COMPILER_C_VALUE_SIGN;
+ /* , */ pCharTable[44] = SC_COMPILER_C_CHAR_VALUE | SC_COMPILER_C_VALUE;
+ /* - */ pCharTable[45] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_EXP | SC_COMPILER_C_VALUE_SIGN;
+ /* . */ pCharTable[46] = SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_VALUE | SC_COMPILER_C_VALUE;
+ /* / */ pCharTable[47] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+ for (i = 48; i < 58; i++)
+ /* 0-9 */ pCharTable[i] = SC_COMPILER_C_CHAR_VALUE | SC_COMPILER_C_WORD | SC_COMPILER_C_VALUE
+ | SC_COMPILER_C_VALUE_EXP | SC_COMPILER_C_VALUE_VALUE;
+ /* : */ pCharTable[58] = SC_COMPILER_C_WORD;
+ /* ; */ pCharTable[59] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+ /* < */ pCharTable[60] = SC_COMPILER_C_CHAR_BOOL | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+ /* = */ pCharTable[61] = SC_COMPILER_C_CHAR | SC_COMPILER_C_BOOL | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+ /* > */ pCharTable[62] = SC_COMPILER_C_CHAR_BOOL | SC_COMPILER_C_BOOL | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+ /* ? */ pCharTable[63] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD;
+ /* @ */ // FREI
+ for (i = 65; i < 91; i++)
+ /* A-Z */ pCharTable[i] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD;
+ /* [ */ // FREI
+ /* \ */ // FREI
+ /* ] */ // FREI
+ /* ^ */ pCharTable[94] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+ /* _ */ pCharTable[95] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD;
+ /* ` */ // FREI
+ for (i = 97; i < 123; i++)
+ /* a-z */ pCharTable[i] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD;
+ /* { */ // FREI
+ /* | */ // FREI
+ /* } */ // FREI
+ /* ~ */ // FREI
+ /* 127 */ // FREI
+}
+
+void ScCompiler::DeInit()
+{
+ if (pSymbolTableNative)
+ {
+ delete [] pSymbolTableNative;
+ pSymbolTableNative = NULL;
+ }
+ if (pSymbolTableEnglish)
+ {
+ delete [] pSymbolTableEnglish;
+ pSymbolTableEnglish = NULL;
+ }
+ delete [] pCharTable;
+ pCharTable = NULL;
+}
+
+void ScCompiler::SetCompileEnglish( BOOL bCompileEnglish )
+{
+ if ( bCompileEnglish )
+ {
+ if ( !pSymbolTableEnglish )
+ {
+ pSymbolTableEnglish = new String[SC_OPCODE_LAST_OPCODE_ID+1];
+ ScOpCodeList aOpCodeListEnglish( RID_SC_FUNCTION_NAMES_ENGLISH,
+ pSymbolTableEnglish );
+ }
+ pSymbolTable = pSymbolTableEnglish;
+ }
+ else
+ pSymbolTable = pSymbolTableNative;
+}
+
+//-----------------------Funktionen der Klasse ScCompiler----------------------
+
+ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos,
+ const ScTokenArray& rArr )
+ :
+ aPos( rPos ),
+ pSymbolTable( pSymbolTableNative ),
+ nRecursion(0),
+ bAutoCorrect( FALSE ),
+ bCorrected( FALSE ),
+ bCompileForFAP( FALSE ),
+ bIgnoreErrors( FALSE ),
+ bCompileXML( FALSE ),
+ bImportXML ( FALSE )
+{
+ if (!nAnzStrings)
+ Init();
+ pArr = (ScTokenArray*) &rArr;
+ pDoc = pDocument;
+ nMaxTab = pDoc->GetTableCount() - 1;
+ pStack = NULL;
+ nNumFmt = NUMBERFORMAT_UNDEFINED;
+}
+
+ScCompiler::ScCompiler(ScDocument* pDocument, const ScAddress& rPos )
+ :
+ aPos( rPos ),
+ pSymbolTable( pSymbolTableNative ),
+ nRecursion(0),
+ bAutoCorrect( FALSE ),
+ bCorrected( FALSE ),
+ bCompileForFAP( FALSE ),
+ bIgnoreErrors( FALSE ),
+ bCompileXML( FALSE ),
+ bImportXML ( FALSE )
+{
+ if (!nAnzStrings)
+ Init();
+ pDoc = pDocument;
+ nMaxTab = pDoc->GetTableCount() - 1;
+ pStack = NULL;
+ nNumFmt = NUMBERFORMAT_UNDEFINED;
+}
+
+
+String ScCompiler::MakeColStr( USHORT nCol )
+{
+ if ( nCol > MAXCOL )
+ return ScGlobal::GetRscString(STR_NO_REF_TABLE);
+ else
+ {
+ if (nCol < 26)
+ return String( 'A' + (sal_uChar) nCol ) ;
+ else
+ {
+ String aString;
+ sal_Unicode* pCol = aString.AllocBuffer( 3 );
+ USHORT nLoCol = nCol % 26;
+ USHORT nHiCol = (nCol / 26) - 1;
+ pCol[0] = 'A' + (sal_uChar)nHiCol;
+ pCol[1] = 'A' + (sal_uChar)nLoCol;
+ pCol[2] = 0;
+ return aString;
+ }
+ }
+}
+
+String ScCompiler::MakeRowStr( USHORT nRow )
+{
+ if ( nRow > MAXROW )
+ return ScGlobal::GetRscString(STR_NO_REF_TABLE);
+ else
+ return String::CreateFromInt32( nRow + 1 );
+}
+
+String ScCompiler::MakeTabStr( USHORT nTab, String& aDoc )
+{
+ String aString;
+ if (!pDoc->GetName(nTab, aString))
+ aString = ScGlobal::GetRscString(STR_NO_REF_TABLE);
+ else
+ {
+ if ( aString.GetChar(0) == '\'' )
+ { // "'Doc'#Tab"
+ xub_StrLen nPos, nLen = 1;
+ while( (nPos = aString.Search( '\'', nLen )) != STRING_NOTFOUND )
+ nLen = nPos + 1;
+ if ( aString.GetChar(nLen) == SC_COMPILER_FILE_TAB_SEP )
+ {
+ aDoc = aString.Copy( 0, nLen + 1 );
+ aString.Erase( 0, nLen + 1 );
+ aDoc = INetURLObject::decode( aDoc, INET_HEX_ESCAPE,
+ INetURLObject::DECODE_UNAMBIGUOUS );
+ }
+ else
+ aDoc.Erase();
+ }
+ else
+ aDoc.Erase();
+ CheckTabQuotes( aString );
+ }
+ aString += '.';
+ return aString;
+}
+
+void ScCompiler::CheckTabQuotes( String& rString )
+{
+ register const sal_Unicode* p = rString.GetBuffer();
+ register const sal_Unicode* const pEnd = p + rString.Len();
+ while ( p < pEnd )
+ {
+ if( !IsWordChar( *p ) )
+ {
+ rString.Insert( '\'', 0 );
+ rString += '\'';
+ break;
+ }
+ p++;
+ }
+}
+
+String ScCompiler::MakeRefStr( ComplRefData& rRef, BOOL bSingleRef )
+{
+ String aNewRef;
+ if (bCompileXML)
+ aNewRef = '[';
+ ComplRefData aRef( rRef );
+ // falls abs/rel nicht separat: Relativ- in Abs-Referenzen wandeln!
+// AdjustReference( aRef.Ref1 );
+// if( !bSingleRef )
+// AdjustReference( aRef.Ref2 );
+ aRef.Ref1.CalcAbsIfRel( aPos );
+ if( !bSingleRef )
+ aRef.Ref2.CalcAbsIfRel( aPos );
+ if( aRef.Ref1.IsFlag3D() )
+ {
+ if (aRef.Ref1.IsTabDeleted())
+ {
+ if (!aRef.Ref1.IsTabRel())
+ aNewRef += '$';
+ aNewRef += ScGlobal::GetRscString(STR_NO_REF_TABLE);
+ aNewRef += '.';
+ }
+ else
+ {
+ String aDoc;
+ String aRefStr( MakeTabStr( aRef.Ref1.nTab, aDoc ) );
+ aNewRef += aDoc;
+ if (!aRef.Ref1.IsTabRel()) aNewRef += '$';
+ aNewRef += aRefStr;
+ }
+ }
+ else if (bCompileXML)
+ aNewRef += '.';
+ if (!aRef.Ref1.IsColRel())
+ aNewRef += '$';
+ if ( aRef.Ref1.IsColDeleted() )
+ aNewRef += ScGlobal::GetRscString(STR_NO_REF_TABLE);
+ else
+ aNewRef += MakeColStr( aRef.Ref1.nCol );
+ if (!aRef.Ref1.IsRowRel())
+ aNewRef += '$';
+ if ( aRef.Ref1.IsRowDeleted() )
+ aNewRef += ScGlobal::GetRscString(STR_NO_REF_TABLE);
+ else
+ aNewRef += MakeRowStr( aRef.Ref1.nRow );
+ if (!bSingleRef)
+ {
+ aNewRef += ':';
+ if (aRef.Ref2.IsFlag3D() || aRef.Ref2.nTab != aRef.Ref1.nTab)
+ {
+ if (aRef.Ref2.IsTabDeleted())
+ {
+ if (!aRef.Ref2.IsTabRel())
+ aNewRef += '$';
+ aNewRef += ScGlobal::GetRscString(STR_NO_REF_TABLE);
+ aNewRef += '.';
+ }
+ else
+ {
+ String aDoc;
+ String aRefStr( MakeTabStr( aRef.Ref2.nTab, aDoc ) );
+ aNewRef += aDoc;
+ if (!aRef.Ref2.IsTabRel())
+ aNewRef += '$';
+ aNewRef += aRefStr;
+ }
+ }
+ else if (bCompileXML)
+ aNewRef += '.';
+ if (!aRef.Ref2.IsColRel())
+ aNewRef += '$';
+ if ( aRef.Ref2.IsColDeleted() )
+ aNewRef += ScGlobal::GetRscString(STR_NO_REF_TABLE);
+ else
+ aNewRef += MakeColStr( aRef.Ref2.nCol );
+ if (!aRef.Ref2.IsRowRel())
+ aNewRef += '$';
+ if ( aRef.Ref2.IsRowDeleted() )
+ aNewRef += ScGlobal::GetRscString(STR_NO_REF_TABLE);
+ else
+ aNewRef += MakeRowStr( aRef.Ref2.nRow );
+ }
+ if (bCompileXML)
+ aNewRef += ']';
+ return aNewRef;
+}
+
+//---------------------------------------------------------------------------
+
+void ScCompiler::SetError(USHORT nError)
+{
+ if( !pArr->GetError() )
+ pArr->nError = nError;
+}
+
+
+sal_Unicode* lcl_UnicodeStrNCpy( sal_Unicode* pDst, const sal_Unicode* pSrc, xub_StrLen nMax )
+{
+ const sal_Unicode* const pStop = pDst + nMax;
+ while ( *pSrc && pDst < pStop )
+ {
+ *pDst++ = *pSrc++;
+ }
+ *pDst = 0;
+ return pDst;
+}
+
+
+//---------------------------------------------------------------------------
+// NextSymbol
+//---------------------------------------------------------------------------
+// Zerlegt die Formel in einzelne Symbole fuer die weitere
+// Verarbeitung (Turing-Maschine).
+//---------------------------------------------------------------------------
+// Ausgangs Zustand = GetChar
+//---------------+-------------------+-----------------------+---------------
+// Alter Zustand | gelesenes Zeichen | Aktion | Neuer Zustand
+//---------------+-------------------+-----------------------+---------------
+// GetChar | ;()+-*/^=& | Symbol=Zeichen | Stop
+// | <> | Symbol=Zeichen | GetBool
+// | $ Buchstabe | Symbol=Zeichen | GetWord
+// | Ziffer | Symbol=Zeichen | GetValue
+// | " | Keine | GetString
+// | Sonst | Keine | GetChar
+//---------------+-------------------+-----------------------+---------------
+// GetBool | => | Symbol=Symbol+Zeichen | Stop
+// | Sonst | Dec(CharPos) | Stop
+//---------------+-------------------+-----------------------+---------------
+// GetWord | SepSymbol | Dec(CharPos) | Stop
+// | ()+-*/^=<>&~ | |
+// | Leerzeichen | Dec(CharPos) | Stop
+// | $_:. | |
+// | Buchstabe,Ziffer | Symbol=Symbol+Zeichen | GetWord
+// | Sonst | Fehler | Stop
+//---------------|-------------------+-----------------------+---------------
+// GetValue | ;()*/^=<>& | |
+// | Leerzeichen | Dec(CharPos) | Stop
+// | Ziffer E+-%,. | Symbol=Symbol+Zeichen | GetValue
+// | Sonst | Fehler | Stop
+//---------------+-------------------+-----------------------+---------------
+// GetString | " | Keine | Stop
+// | Sonst | Symbol=Symbol+Zeichen | GetString
+//---------------+-------------------+-----------------------+---------------
+
+xub_StrLen ScCompiler::NextSymbol()
+{
+ cSymbol[MAXSTRLEN-1] = 0; // Stopper
+ sal_Unicode* pSym = cSymbol;
+ const sal_Unicode* const pStart = aFormula.GetBuffer();
+ const sal_Unicode* pSrc = pStart + nSrcPos;
+ BOOL bi18n = FALSE;
+ sal_Unicode c = *pSrc;
+ sal_Unicode cLast = 0;
+ BOOL bQuote = FALSE;
+ ScanState eState = ssGetChar;
+ xub_StrLen nSpaces = 0;
+ // try to parse simple tokens before calling i18n parser
+ while ((c != 0) && (eState != ssStop) )
+ {
+ pSrc++;
+ USHORT nMask = GetCharTableFlags( c );
+ switch (eState)
+ {
+ case ssGetChar :
+ {
+ if( nMask & SC_COMPILER_C_CHAR )
+ {
+ *pSym++ = c;
+ eState = ssStop;
+ }
+ else if( nMask & SC_COMPILER_C_CHAR_BOOL )
+ {
+ *pSym++ = c;
+ eState = ssGetBool;
+ }
+ else if( nMask & SC_COMPILER_C_CHAR_STRING )
+ {
+ *pSym++ = c;
+ eState = ssGetString;
+ }
+ else if( nMask & SC_COMPILER_C_CHAR_DONTCARE )
+ {
+ nSpaces++;
+ }
+ else
+ {
+ bi18n = TRUE;
+ eState = ssStop;
+ }
+ }
+ break;
+ case ssGetBool :
+ {
+ if( nMask & SC_COMPILER_C_BOOL )
+ {
+ *pSym++ = c;
+ eState = ssStop;
+ }
+ else
+ {
+ pSrc--;
+ eState = ssStop;
+ }
+ }
+ break;
+ case ssGetString :
+ {
+ if( nMask & SC_COMPILER_C_STRING_SEP )
+ {
+ if ( !bQuote )
+ {
+ if ( *pSrc == '"' )
+ bQuote = TRUE; // "" => literal "
+ else
+ eState = ssStop;
+ }
+ else
+ bQuote = FALSE;
+ }
+ if ( !bQuote )
+ {
+ if( pSym == &cSymbol[ MAXSTRLEN-1 ] )
+ {
+ SetError(errStringOverflow);
+ eState = ssSkipString;
+ }
+ else
+ *pSym++ = c;
+ }
+ }
+ break;
+ case ssSkipString:
+ if( nMask & SC_COMPILER_C_STRING_SEP )
+ eState = ssStop;
+ break;
+ }
+ cLast = c;
+ c = *pSrc;
+ }
+ if ( bi18n )
+ {
+ using namespace ::com::sun::star::lang;
+ nSrcPos += nSpaces;
+ sal_Int32 nStartFlags = KParseTokens::ANY_LETTER_OR_NUMBER |
+ KParseTokens::ASC_UNDERSCORE | KParseTokens::ASC_DOLLAR;
+ sal_Int32 nContFlags = nStartFlags | KParseTokens::ASC_DOT |
+ KParseTokens::ASC_COLON;
+ // '?' allowed in range names because of Xcl :-/
+ String aAddAllowed( '?' );
+ String aSymbol;
+ USHORT nErr = 0;
+ do
+ {
+ bi18n = FALSE;
+ // special case $'sheetname'
+ if ( pStart[nSrcPos] == '$' && pStart[nSrcPos+1] == '\'' )
+ aSymbol += pStart[nSrcPos++];
+
+ ParseResult aRes = ScGlobal::pCharClass->parseAnyToken( aFormula,
+ nSrcPos, nStartFlags, aAddAllowed, nContFlags, aAddAllowed );
+
+ if ( !aRes.TokenType )
+ SetError( nErr = errIllegalChar ); // parsed chars as string
+ if ( aRes.EndPos <= nSrcPos )
+ { // ?!?
+ SetError( nErr = errIllegalChar );
+ nSrcPos = aFormula.Len();
+ aSymbol.Erase();
+ }
+ else
+ {
+ aSymbol.Append( pStart + nSrcPos, aRes.EndPos - nSrcPos );
+ nSrcPos = aRes.EndPos;
+ if ( aRes.TokenType & KParseType::SINGLE_QUOTE_NAME )
+ { // special cases 'sheetname'. 'filename'#
+ c = pStart[nSrcPos];
+ bi18n = (c == '.' || c == SC_COMPILER_FILE_TAB_SEP);
+ if ( bi18n )
+ aSymbol += pStart[nSrcPos++];
+ }
+ else if ( aRes.TokenType & KParseType::IDENTNAME )
+ { // special cases reference:[$]'sheetname'
+ c = aSymbol.GetChar( aSymbol.Len()-1 );
+ bi18n = ((c == ':' || c == '$') && pStart[nSrcPos] == '\'');
+ }
+ }
+ } while ( bi18n && !nErr );
+ xub_StrLen nLen = aSymbol.Len();
+ if ( nLen >= MAXSTRLEN )
+ {
+ SetError( errStringOverflow );
+ nLen = MAXSTRLEN-1;
+ }
+ lcl_UnicodeStrNCpy( cSymbol, aSymbol.GetBuffer(), nLen );
+ }
+ else
+ {
+ nSrcPos = pSrc - pStart;
+ *pSym = 0;
+ }
+ if ( bAutoCorrect )
+ aCorrectedSymbol = cSymbol;
+ return nSpaces;
+}
+
+//---------------------------------------------------------------------------
+// Symbol in Token Umwandeln
+//---------------------------------------------------------------------------
+
+BOOL ScCompiler::IsOpCode( const String& rName )
+{
+ BOOL bFound = FALSE;
+
+ for( USHORT i = 0; i < nAnzStrings && !bFound; i++ )
+ bFound = (pSymbolTable[i] == rName);
+
+ if (bFound)
+ {
+ ScToken aToken;
+ aToken.SetOpCode( (OpCode) --i );
+ pToken = aToken.Clone();
+ }
+ else
+ {
+ USHORT nIndex;
+ bFound = ScGlobal::GetFuncCollection()->SearchFunc(cSymbol, nIndex);
+ if( bFound )
+ {
+ ScToken aToken;
+ aToken.SetExternal( cSymbol );
+ pToken = aToken.Clone();
+ }
+ else
+ {
+ // bLocalFirst=FALSE for english
+ String aIntName = ScGlobal::GetAddInCollection()->
+ FindFunction( cSymbol, ( pSymbolTable != pSymbolTableEnglish ) );
+ if (aIntName.Len())
+ {
+ ScToken aToken;
+ aToken.SetExternal( aIntName.GetBuffer() ); // international name
+ pToken = aToken.Clone();
+ bFound = TRUE;
+ }
+ }
+ }
+ if ( bFound && pToken->GetOpCode() == ocSub &&
+ (eLastOp == ocOpen || eLastOp == ocSep ||
+ (eLastOp > ocEndDiv && eLastOp < ocEndBinOp /*ocEndUnOp*/)))
+ pToken->eOp = ocNegSub;
+ return bFound;
+}
+
+BOOL ScCompiler::IsOpCode2( const String& rName )
+{
+ BOOL bFound = FALSE;
+
+ for( USHORT i = ocInternalBegin; i <= ocInternalEnd && !bFound; i++ )
+ bFound = rName.EqualsAscii( pInternal[ i-ocInternalBegin ] );
+
+ if (bFound)
+ {
+ ScToken aToken;
+ aToken.SetOpCode( (OpCode) --i );
+ pToken = aToken.Clone();
+ }
+ return bFound;
+}
+
+BOOL ScCompiler::IsValue( const String& rSym )
+{
+ double fVal;
+ ULONG nIndex = ( pSymbolTable == pSymbolTableEnglish ?
+ pDoc->GetFormatTable()->GetStandardIndex( LANGUAGE_ENGLISH_US ) : 0 );
+// ULONG nIndex = 0;
+//// ULONG nIndex = pDoc->GetFormatTable()->GetStandardIndex(ScGlobal::eLnge);
+ if (pDoc->GetFormatTable()->IsNumberFormat( rSym, nIndex, fVal ) )
+ {
+ USHORT nType = pDoc->GetFormatTable()->GetType(nIndex);
+ const sal_Unicode* p = aFormula.GetBuffer() + nSrcPos;
+ while( *p == ' ' )
+ p++;
+ if ( *p == '(' && nType == NUMBERFORMAT_LOGICAL)
+ return FALSE;
+ else if( aFormula.GetChar(nSrcPos) == '.' )
+ // Numerischer Tabellenname?
+ return FALSE;
+ else
+ {
+ if( nType == NUMBERFORMAT_TEXT )
+ // HACK: Die Zahl ist zu gross!
+ SetError( errIllegalArgument );
+ ScToken aToken;
+ aToken.SetDouble( fVal );
+ pToken = aToken.Clone();
+ return TRUE;
+ }
+ }
+ else
+ return FALSE;
+}
+
+BOOL ScCompiler::IsString()
+{
+ register const sal_Unicode* p = cSymbol;
+ while ( *p )
+ p++;
+ xub_StrLen nLen = p - cSymbol - 1;
+ BOOL bQuote = ((cSymbol[0] == '"') && (cSymbol[nLen] == '"'));
+ if ((bQuote ? nLen-2 : nLen) > MAXSTRLEN-1)
+ {
+ SetError(errStringOverflow);
+ return FALSE;
+ }
+ if ( bQuote )
+ {
+ cSymbol[nLen] = '\0';
+ ScToken aToken;
+ aToken.SetString( cSymbol+1 );
+ pToken = aToken.Clone();
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL ScCompiler::IsReference( const String& rName )
+{
+ // wird jetzt vor IsValue aufgerufen, kein #REF! aus Zahlen machen
+ // numerischer Tabellenname muss allerdings durchgehen
+ // englisches 1.E2 oder 1.E+2 ist wiederum Zahl 100, 1.E-2 ist 0,01
+ sal_Unicode ch1 = rName.GetChar(0);
+ sal_Unicode cDecSep = ( pSymbolTable == pSymbolTableEnglish ? '.' :
+ ScGlobal::pScInternational->GetNumDecimalSep() );
+ if ( ch1 == cDecSep )
+ return FALSE;
+ BOOL bMyAlpha;
+ sal_Unicode ch2;
+ xub_StrLen nPos = rName.Search( '.' );
+ const sal_Unicode* pTabSep = (nPos == STRING_NOTFOUND ? NULL :
+ rName.GetBuffer() + nPos);
+ if ( pTabSep )
+ {
+ ch2 = pTabSep[1]; // vielleicht Col-Bezeichner
+ bMyAlpha = CharClass::isAsciiAlpha( rName.GetChar( nPos+1 ) ) || ch2 == '$';
+ }
+ else
+ {
+ ch2 = 0;
+ bMyAlpha = FALSE;
+ }
+ // welcher Hirni hat bloss den . zum Tabellenseparator gemacht!?!
+ BOOL bDigit1 = CharClass::isAsciiNumeric( ch1 );
+ if ( cDecSep == '.' )
+ {
+ if ( ( bDigit1 && ( pTabSep ?
+ (!bMyAlpha || ((ch2 == 'E' || ch2 == 'e') // E + - digit
+ && (GetCharTableFlags( pTabSep[2] ) & SC_COMPILER_C_VALUE_EXP))) :
+ TRUE ) ) )
+ return FALSE;
+ }
+ else
+ {
+ if ( bDigit1 && (pTabSep ? !bMyAlpha : TRUE) )
+ return FALSE;
+ }
+ ScRange aRange( aPos, aPos );
+ USHORT nFlags = aRange.Parse( rName, pDoc );
+ if( nFlags & SCA_VALID )
+ {
+ ScToken aToken;
+ ComplRefData aRef;
+ aRef.InitRange( aRange );
+ aRef.Ref1.SetColRel( (nFlags & SCA_COL_ABSOLUTE) == 0 );
+ aRef.Ref1.SetRowRel( (nFlags & SCA_ROW_ABSOLUTE) == 0 );
+ aRef.Ref1.SetTabRel( (nFlags & SCA_TAB_ABSOLUTE) == 0 );
+ if ( !(nFlags & SCA_VALID_TAB) )
+ aRef.Ref1.SetTabDeleted( TRUE ); // #REF!
+ aRef.Ref1.SetFlag3D( ( nFlags & SCA_TAB_3D ) != 0 );
+ aRef.Ref2.SetColRel( (nFlags & SCA_COL2_ABSOLUTE) == 0 );
+ aRef.Ref2.SetRowRel( (nFlags & SCA_ROW2_ABSOLUTE) == 0 );
+ aRef.Ref2.SetTabRel( (nFlags & SCA_TAB2_ABSOLUTE) == 0 );
+ if ( !(nFlags & SCA_VALID_TAB2) )
+ aRef.Ref2.SetTabDeleted( TRUE ); // #REF!
+ aRef.Ref2.SetFlag3D( ( nFlags & SCA_TAB2_3D ) != 0 );
+ aRef.CalcRelFromAbs( aPos );
+ aToken.SetDoubleReference( aRef );
+ pToken = aToken.Clone();
+ }
+ else
+ {
+ ScAddress aAddr( aPos );
+ nFlags = aAddr.Parse( rName, pDoc );
+ // Irgend etwas muss gueltig sein,
+ // damit Tabelle1.blah oder blah.a1 als (falsche) ref erkannt wird
+ if( nFlags & ( SCA_VALID_COL|SCA_VALID_ROW|SCA_VALID_TAB ) )
+ {
+ ScToken aToken;
+ SingleRefData aRef;
+ aRef.InitAddress( aAddr );
+ aRef.SetColRel( (nFlags & SCA_COL_ABSOLUTE) == 0 );
+ aRef.SetRowRel( (nFlags & SCA_ROW_ABSOLUTE) == 0 );
+ aRef.SetTabRel( (nFlags & SCA_TAB_ABSOLUTE) == 0 );
+ aRef.SetFlag3D( ( nFlags & SCA_TAB_3D ) != 0 );
+ // Die Referenz ist wirklich ungueltig!
+ if( !( nFlags & SCA_VALID ) )
+ {
+ if( !( nFlags & SCA_VALID_COL ) )
+ aRef.nCol = MAXCOL+1;
+ if( !( nFlags & SCA_VALID_ROW ) )
+ aRef.nRow = MAXROW+1;
+ if( !( nFlags & SCA_VALID_TAB ) )
+ aRef.nTab = MAXTAB+3;
+ nFlags |= SCA_VALID;
+ }
+ aRef.CalcRelFromAbs( aPos );
+ aToken.SetSingleReference( aRef );
+ pToken = aToken.Clone();
+ }
+ }
+ return ( nFlags & SCA_VALID ) != 0;
+}
+
+BOOL ScCompiler::IsMacro( const String& rName )
+{
+ StarBASIC* pObj = 0;
+ SfxObjectShell* pDocSh = pDoc->GetDocumentShell();
+
+ SfxApplication* pSfxApp = SFX_APP();
+ pSfxApp->EnterBasicCall(); // Dok-Basic anlegen etc.
+
+ if( pDocSh )//XXX
+ pObj = pDocSh->GetBasic();
+ else
+ pObj = pSfxApp->GetBasic();
+
+ SbxMethod* pMeth = (SbxMethod*) pObj->Find( rName, SbxCLASS_METHOD );
+ if( !pMeth )
+ {
+ pSfxApp->LeaveBasicCall();
+ return FALSE;
+ }
+ // Es sollte schon eine BASIC-Function sein!
+ if( pMeth->GetType() == SbxVOID
+ || ( pMeth->IsFixed() && pMeth->GetType() == SbxEMPTY )
+ || !pMeth->ISA(SbMethod) )
+ {
+ pSfxApp->LeaveBasicCall();
+ return FALSE;
+ }
+ ScToken aToken;
+ aToken.SetExternal( rName.GetBuffer() );
+ aToken.eOp = ocMacro;
+ pToken = aToken.Clone();
+ pSfxApp->LeaveBasicCall();
+ return TRUE;
+}
+
+BOOL ScCompiler::IsNamedRange( const String& rName )
+{
+ USHORT n;
+ ScRangeName* pRangeName = pDoc->GetRangeName();
+ if (pRangeName->SearchName( rName, n ) )
+ {
+ ScRangeData* pData = (*pRangeName)[n];
+ ScToken aToken;
+ aToken.SetName( pData->GetIndex() );
+ pToken = aToken.Clone();
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+BOOL ScCompiler::IsDBRange( const String& rName )
+{
+ USHORT n;
+ ScDBCollection* pDBColl = pDoc->GetDBCollection();
+ if (pDBColl->SearchName( rName, n ) )
+ {
+ ScDBData* pData = (*pDBColl)[n];
+ ScToken aToken;
+ aToken.SetName( pData->GetIndex() );
+ aToken.eOp = ocDBArea;
+ pToken = aToken.Clone();
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+BOOL ScCompiler::IsColRowName( const String& rName )
+{
+ BOOL bInList = FALSE;
+ BOOL bFound = FALSE;
+ SingleRefData aRef;
+ String aName( rName );
+ DeQuote( aName );
+ USHORT nThisTab = aPos.Tab();
+ for ( short jThisTab = 1; jThisTab >= 0 && !bInList; jThisTab-- )
+ { // #50300# zuerst Bereiche auf dieser Tabelle pruefen, falls doppelte Namen
+ for ( short jRow=0; jRow<2 && !bInList; jRow++ )
+ {
+ ScRangePairList* pRL;
+ if ( !jRow )
+ pRL = pDoc->GetColNameRanges();
+ else
+ pRL = pDoc->GetRowNameRanges();
+ for ( ScRangePair* pR = pRL->First(); pR && !bInList; pR = pRL->Next() )
+ {
+ const ScRange& rNameRange = pR->GetRange(0);
+ if ( jThisTab && !(rNameRange.aStart.Tab() <= nThisTab &&
+ nThisTab <= rNameRange.aEnd.Tab()) )
+ continue; // for
+ ScCellIterator aIter( pDoc, rNameRange );
+ for ( ScBaseCell* pCell = aIter.GetFirst(); pCell && !bInList;
+ pCell = aIter.GetNext() )
+ {
+ // GPF wenn Zelle via CompileNameFormula auf Zelle ohne Code
+ // trifft und HasStringData/Interpret/Compile ausgefuehrt wird
+ // und das ganze dann auch noch rekursiv..
+ // ausserdem wird *diese* Zelle hier nicht angefasst, da noch
+ // kein RPN existiert
+ CellType eType = pCell->GetCellType();
+ BOOL bOk = (eType == CELLTYPE_FORMULA ?
+ ((ScFormulaCell*)pCell)->GetCode()->GetCodeLen() > 0
+ && ((ScFormulaCell*)pCell)->aPos != aPos // noIter
+ : TRUE );
+ if ( bOk && pCell->HasStringData() )
+ {
+ String aStr;
+ switch ( eType )
+ {
+ case CELLTYPE_STRING:
+ ((ScStringCell*)pCell)->GetString( aStr );
+ break;
+ case CELLTYPE_FORMULA:
+ ((ScFormulaCell*)pCell)->GetString( aStr );
+ break;
+ case CELLTYPE_EDIT:
+ ((ScEditCell*)pCell)->GetString( aStr );
+ break;
+ }
+ if ( ScGlobal::pScInternational->CompareEqual(
+ aStr, aName, INTN_COMPARE_IGNORECASE ) )
+ {
+ aRef.InitFlags();
+ aRef.nCol = aIter.GetCol();
+ aRef.nRow = aIter.GetRow();
+ aRef.nTab = aIter.GetTab();
+ if ( !jRow )
+ aRef.SetColRel( TRUE ); // ColName
+ else
+ aRef.SetRowRel( TRUE ); // RowName
+ aRef.CalcRelFromAbs( aPos );
+ bInList = bFound = TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+ if ( !bInList && pDoc->GetDocOptions().IsLookUpColRowNames() )
+ { // in der aktuellen Tabelle suchen
+ long nDistance, nMax;
+ long nMyCol = (long) aPos.Col();
+ long nMyRow = (long) aPos.Row();
+ BOOL bTwo = FALSE;
+ ScAddress aOne( 0, 0, aPos.Tab() );
+ ScAddress aTwo( MAXCOL, MAXROW, aPos.Tab() );
+ ScCellIterator aIter( pDoc, ScRange( aOne, aTwo ) );
+ for ( ScBaseCell* pCell = aIter.GetFirst(); pCell; pCell = aIter.GetNext() )
+ {
+ if ( bFound )
+ { // aufhoeren wenn alles andere weiter liegt
+ if ( nMax < (long)aIter.GetCol() )
+ break; // aIter
+ }
+ CellType eType = pCell->GetCellType();
+ BOOL bOk = (eType == CELLTYPE_FORMULA ?
+ ((ScFormulaCell*)pCell)->GetCode()->GetCodeLen() > 0
+ && ((ScFormulaCell*)pCell)->aPos != aPos // noIter
+ : TRUE );
+ if ( bOk && pCell->HasStringData() )
+ {
+ String aStr;
+ switch ( eType )
+ {
+ case CELLTYPE_STRING:
+ ((ScStringCell*)pCell)->GetString( aStr );
+ break;
+ case CELLTYPE_FORMULA:
+ ((ScFormulaCell*)pCell)->GetString( aStr );
+ break;
+ case CELLTYPE_EDIT:
+ ((ScEditCell*)pCell)->GetString( aStr );
+ break;
+ }
+ if ( ScGlobal::pScInternational->CompareEqual(
+ aStr, aName, INTN_COMPARE_IGNORECASE ) )
+ {
+ USHORT nCol = aIter.GetCol();
+ USHORT nRow = aIter.GetRow();
+ long nC = nMyCol - nCol;
+ long nR = nMyRow - nRow;
+ if ( bFound )
+ {
+ long nD = nC * nC + nR * nR;
+ if ( nD < nDistance )
+ {
+ if ( nC < 0 || nR < 0 )
+ { // rechts oder unterhalb
+ bTwo = TRUE;
+ aTwo.Set( nCol, nRow, aIter.GetTab() );
+ nMax = Max( nMyCol + Abs( nC ), nMyRow + Abs( nR ) );
+ nDistance = nD;
+ }
+ else if ( !(nRow < aOne.Row() && nMyRow >= (long)aOne.Row()) )
+ { // links oben, nur wenn nicht weiter oberhalb
+ // des bisherigen und nMyRow darunter
+ // (CellIter geht spaltenweise!)
+ bTwo = FALSE;
+ aOne.Set( nCol, nRow, aIter.GetTab() );
+ nMax = Max( nMyCol + nC, nMyRow + nR );
+ nDistance = nD;
+ }
+ }
+ }
+ else
+ {
+ aOne.Set( nCol, nRow, aIter.GetTab() );
+ nDistance = nC * nC + nR * nR;
+ nMax = Max( nMyCol + Abs( nC ), nMyRow + Abs( nR ) );
+ }
+ bFound = TRUE;
+ }
+ }
+ }
+ if ( bFound )
+ {
+ ScAddress aAdr;
+ if ( bTwo )
+ {
+ if ( nMyCol >= (long)aOne.Col() && nMyRow >= (long)aOne.Row() )
+ aAdr = aOne; // links oben hat Vorrang
+ else
+ {
+ if ( nMyCol < (long)aOne.Col() )
+ { // zwei rechts
+ if ( nMyRow >= (long)aTwo.Row() )
+ aAdr = aTwo; // direkt rechts
+ else
+ aAdr = aOne;
+ }
+ else
+ { // zwei unten oder unten und rechts, der naechstgelegene
+ long nC1 = nMyCol - aOne.Col();
+ long nR1 = nMyRow - aOne.Row();
+ long nC2 = nMyCol - aTwo.Col();
+ long nR2 = nMyRow - aTwo.Row();
+ if ( nC1 * nC1 + nR1 * nR1 <= nC2 * nC2 + nR2 * nR2 )
+ aAdr = aOne;
+ else
+ aAdr = aTwo;
+ }
+ }
+ }
+ else
+ aAdr = aOne;
+ aRef.InitAddress( aAdr );
+ if ( (aRef.nRow != MAXROW && pDoc->HasStringData(
+ aRef.nCol, aRef.nRow + 1, aRef.nTab ))
+ || (aRef.nRow != 0 && pDoc->HasStringData(
+ aRef.nCol, aRef.nRow - 1, aRef.nTab )) )
+ aRef.SetRowRel( TRUE ); // RowName
+ else
+ aRef.SetColRel( TRUE ); // ColName
+ aRef.CalcRelFromAbs( aPos );
+ }
+ }
+ if ( bFound )
+ {
+ ScToken aToken;
+ aToken.SetSingleReference( aRef );
+ aToken.eOp = ocColRowName;
+ pToken = aToken.Clone();
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+
+void ScCompiler::AutoCorrectParsedSymbol()
+{
+ xub_StrLen nPos = aCorrectedSymbol.Len();
+ if ( nPos )
+ {
+ nPos--;
+ const sal_Unicode cQuote = '\"';
+ const sal_Unicode cx = 'x';
+ const sal_Unicode cX = 'X';
+ sal_Unicode c1 = aCorrectedSymbol.GetChar( 0 );
+ sal_Unicode c2 = aCorrectedSymbol.GetChar( nPos );
+ if ( c1 == cQuote && c2 != cQuote )
+ { // "...
+ // was kein Wort bildet gehoert nicht dazu.
+ // Don't be pedantic: c < 128 should be sufficient here.
+ while ( nPos && ((aCorrectedSymbol.GetChar(nPos) < 128) &&
+ ((GetCharTableFlags( aCorrectedSymbol.GetChar(nPos) ) &
+ (SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_DONTCARE)) == 0)) )
+ nPos--;
+ if ( nPos == MAXSTRLEN - 2 )
+ aCorrectedSymbol.SetChar( nPos, cQuote ); // '"' als 255. Zeichen
+ else
+ aCorrectedSymbol.Insert( cQuote, nPos + 1 );
+ bCorrected = TRUE;
+ }
+ else if ( c1 != cQuote && c2 == cQuote )
+ { // ..."
+ aCorrectedSymbol.Insert( cQuote, 0 );
+ bCorrected = TRUE;
+ }
+ else if ( nPos == 0 && (c1 == cx || c1 == cX) )
+ { // x => *
+ aCorrectedSymbol = pSymbolTable[ocMul];
+ bCorrected = TRUE;
+ }
+ else if ( (GetCharTableFlags( c1 ) & SC_COMPILER_C_CHAR_VALUE)
+ && (GetCharTableFlags( c2 ) & SC_COMPILER_C_CHAR_VALUE) )
+ {
+ xub_StrLen nXcount;
+ if ( (nXcount = aCorrectedSymbol.GetTokenCount( cx )) > 1 )
+ { // x => *
+ xub_StrLen nIndex = 0;
+ sal_Unicode c = pSymbolTable[ocMul].GetChar(0);
+ while ( (nIndex = aCorrectedSymbol.SearchAndReplace(
+ cx, c, nIndex )) != STRING_NOTFOUND )
+ nIndex++;
+ bCorrected = TRUE;
+ }
+ if ( (nXcount = aCorrectedSymbol.GetTokenCount( cX )) > 1 )
+ { // X => *
+ xub_StrLen nIndex = 0;
+ sal_Unicode c = pSymbolTable[ocMul].GetChar(0);
+ while ( (nIndex = aCorrectedSymbol.SearchAndReplace(
+ cX, c, nIndex )) != STRING_NOTFOUND )
+ nIndex++;
+ bCorrected = TRUE;
+ }
+ }
+ else
+ {
+ String aSymbol( aCorrectedSymbol );
+ String aDoc;
+ xub_StrLen nPos;
+ if ( aSymbol.GetChar(0) == '\''
+ && ((nPos = aSymbol.SearchAscii( "'#" )) != STRING_NOTFOUND) )
+ { // 'Doc'# abspalten, kann d:\... und sonstwas sein
+ aDoc = aSymbol.Copy( 0, nPos + 2 );
+ aSymbol.Erase( 0, nPos + 2 );
+ }
+ xub_StrLen nRefs = aSymbol.GetTokenCount( ':' );
+ BOOL bColons;
+ if ( nRefs > 2 )
+ { // doppelte oder zuviele ':'? B:2::C10 => B2:C10
+ bColons = TRUE;
+ xub_StrLen nIndex = 0;
+ String aTmp1( aSymbol.GetToken( 0, ':', nIndex ) );
+ xub_StrLen nLen1 = aTmp1.Len();
+ String aSym, aTmp2;
+ BOOL bLastAlp, bNextNum;
+ bLastAlp = bNextNum = TRUE;
+ xub_StrLen nStrip = 0;
+ xub_StrLen nCount = nRefs;
+ for ( xub_StrLen j=1; j<nCount; j++ )
+ {
+ aTmp2 = aSymbol.GetToken( 0, ':', nIndex );
+ xub_StrLen nLen2 = aTmp2.Len();
+ if ( nLen1 || nLen2 )
+ {
+ if ( nLen1 )
+ {
+ aSym += aTmp1;
+ bLastAlp = CharClass::isAsciiAlpha( aTmp1 );
+ }
+ if ( nLen2 )
+ {
+ bNextNum = CharClass::isAsciiNumeric( aTmp2 );
+ if ( bLastAlp == bNextNum && nStrip < 1 )
+ { // muss abwechselnd nur Zahl/String sein,
+ // nur innerhalb einer Ref strippen
+ nRefs--;
+ nStrip++;
+ }
+ else
+ {
+ xub_StrLen nSymLen = aSym.Len();
+ if ( nSymLen
+ && (aSym.GetChar( nSymLen - 1 ) != ':') )
+ aSym += ':';
+ nStrip = 0;
+ }
+ bLastAlp = !bNextNum;
+ }
+ else
+ { // ::
+ nRefs--;
+ if ( nLen1 )
+ { // B10::C10 ? naechste Runde ':' anhaengen
+ if ( !bLastAlp && !CharClass::isAsciiNumeric( aTmp1 ) )
+ nStrip++;
+ }
+ bNextNum = !bLastAlp;
+ }
+ aTmp1 = aTmp2;
+ nLen1 = nLen2;
+ }
+ else
+ nRefs--;
+ }
+ aSymbol = aSym;
+ aSymbol += aTmp1;
+ }
+ else
+ bColons = FALSE;
+ if ( nRefs && nRefs <= 2 )
+ { // Referenzdreher? 4A => A4 etc.
+ String aTab[2], aRef[2];
+ if ( nRefs == 2 )
+ {
+ aRef[0] = aSymbol.GetToken( 0, ':' );
+ aRef[1] = aSymbol.GetToken( 1, ':' );
+ }
+ else
+ aRef[0] = aSymbol;
+
+ BOOL bChanged = FALSE;
+ BOOL bOk = TRUE;
+ USHORT nMask = SCA_VALID | SCA_VALID_COL | SCA_VALID_ROW;
+ for ( int j=0; j<nRefs; j++ )
+ {
+ xub_StrLen nTmp = 0;
+ xub_StrLen nPos = STRING_NOTFOUND;
+ while ( (nTmp = aRef[j].Search( '.', nTmp )) != STRING_NOTFOUND )
+ nPos = nTmp++; // der letzte zaehlt
+ if ( nPos != STRING_NOTFOUND )
+ {
+ aTab[j] = aRef[j].Copy( 0, nPos + 1 ); // mit '.'
+ aRef[j].Erase( 0, nPos + 1 );
+ }
+ String aOld( aRef[j] );
+ String aStr2;
+ const sal_Unicode* p = aRef[j].GetBuffer();
+ while ( *p && CharClass::isAsciiNumeric( *p ) )
+ aStr2 += *p++;
+ aRef[j] = String( p );
+ aRef[j] += aStr2;
+ if ( bColons || aRef[j] != aOld )
+ {
+ bChanged = TRUE;
+ ScAddress aAdr;
+ bOk &= ((aAdr.Parse( aRef[j], pDoc ) & nMask) == nMask);
+ }
+ }
+ if ( bChanged && bOk )
+ {
+ aCorrectedSymbol = aDoc;
+ aCorrectedSymbol += aTab[0];
+ aCorrectedSymbol += aRef[0];
+ if ( nRefs == 2 )
+ {
+ aCorrectedSymbol += ':';
+ aCorrectedSymbol += aTab[1];
+ aCorrectedSymbol += aRef[1];
+ }
+ bCorrected = TRUE;
+ }
+ }
+ }
+ }
+}
+
+BOOL ScCompiler::NextNewToken()
+{
+ xub_StrLen nSpaces = NextSymbol();
+ ScToken aToken;
+ if( cSymbol[0] )
+ {
+ if( nSpaces )
+ {
+ aToken.SetOpCode( ocSpaces );
+ aToken.cByte = (BYTE) ( nSpaces > 255 ? 255 : nSpaces );
+ if( !pArr->AddToken( aToken ) )
+ {
+ SetError(errCodeOverflow); return FALSE;
+ }
+ }
+ if( !IsString() )
+ {
+ String aTmpStr( cSymbol[0] );
+ BOOL bMayBeFuncName;
+ if ( ScGlobal::pCharClass->isLetter( aTmpStr, 0 ) )
+ { // Einem Namen muss eine Klammer folgen
+ const sal_Unicode* p = aFormula.GetBuffer() + nSrcPos;
+ while( *p == ' ' )
+ p++;
+ bMayBeFuncName = ( *p == '(' );
+ }
+ else
+ bMayBeFuncName = TRUE; // Operatoren etc.
+ String aOrg( cSymbol ); // evtl. Dateinamen in IsReference erhalten
+ String aUpper( aOrg );
+ ScGlobal::pCharClass->toUpper( aUpper );
+ // Spalte DM konnte nicht referiert werden, IsReference vor IsValue
+ // #42016# italian ARCTAN.2 gab #REF! => IsOpCode vor IsReference
+ if ( !(bMayBeFuncName && IsOpCode( aUpper ))
+ && !IsReference( aOrg )
+ && !IsValue( aUpper )
+ && !IsNamedRange( aUpper )
+ && !IsDBRange( aUpper )
+ && !IsColRowName( aUpper )
+ && !(bMayBeFuncName && IsMacro( aUpper ))
+ && !(bMayBeFuncName && IsOpCode2( aUpper )) )
+ {
+ SetError( errNoName );
+ ScGlobal::pCharClass->toLower( aUpper );
+ aToken.SetString( aUpper.GetBuffer() );
+ aToken.eOp = ocBad;
+ pToken = aToken.Clone();
+ if ( bAutoCorrect )
+ AutoCorrectParsedSymbol();
+ }
+ }
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+ScTokenArray* ScCompiler::CompileString( const String& rFormula )
+{
+ ScTokenArray aArr;
+ pArr = &aArr;
+ aFormula = rFormula;
+ aFormula.EraseLeadingChars();
+ aFormula.EraseTrailingChars();
+ nSrcPos = 0;
+ bCorrected = FALSE;
+ if ( bAutoCorrect )
+ {
+ aCorrectedFormula.Erase();
+ aCorrectedSymbol.Erase();
+ }
+ BYTE nForced = 0; // ==Formel forciert Recalc auch wenn nicht sichtbar
+ if( aFormula.GetChar(nSrcPos) == '=' )
+ {
+ nSrcPos++;
+ nForced++;
+ if ( bAutoCorrect )
+ aCorrectedFormula += '=';
+ }
+ if( aFormula.GetChar(nSrcPos) == '=' )
+ {
+ nSrcPos++;
+ nForced++;
+ if ( bAutoCorrect )
+ aCorrectedFormula += '=';
+ }
+ short nBrackets = 0;
+ eLastOp = ocOpen;
+ while( NextNewToken() )
+ {
+ if( pToken->GetOpCode() == ocOpen )
+ nBrackets++;
+ else if( pToken->GetOpCode() == ocClose )
+ {
+ if( !nBrackets )
+ {
+ SetError( errPairExpected );
+ if ( bAutoCorrect )
+ {
+ bCorrected = TRUE;
+ aCorrectedSymbol.Erase();
+ }
+ }
+ else
+ nBrackets--;
+ }
+ if( !pArr->Add( pToken ) )
+ {
+ SetError(errCodeOverflow); break;
+ }
+ eLastOp = pToken->GetOpCode();
+ if ( bAutoCorrect )
+ aCorrectedFormula += aCorrectedSymbol;
+ }
+ if ( eLastOp != ocBad )
+ { // bei ocBad ist der Rest der Formel String, es wuerden zuviele
+ // Klammern erscheinen
+ ScToken aToken;
+ aToken.SetOpCode( ocClose );
+ while( nBrackets-- )
+ {
+ if( !pArr->AddToken( aToken ) )
+ {
+ SetError(errCodeOverflow); break;
+ }
+ if ( bAutoCorrect )
+ aCorrectedFormula += pSymbolTable[ocClose];
+ }
+ }
+ if ( nForced >= 2 )
+ pArr->SetRecalcModeForced();
+ // pArr merken, falls danach CompileTokenArray() kommt
+ return pArr = new ScTokenArray( aArr );
+}
+
+void ScCompiler::PushTokenArray( ScTokenArray* pa, BOOL bTemp )
+{
+ if ( bAutoCorrect && !pStack )
+ { // #61426# don't merge stacked subroutine code into entered formula
+ aCorrectedFormula += aCorrectedSymbol;
+ aCorrectedSymbol.Erase();
+ }
+ ScArrayStack* p = new ScArrayStack;
+ p->pNext = pStack;
+ p->pArr = pArr;
+ p->bTemp = bTemp;
+ pStack = p;
+ pArr = pa;
+}
+
+void ScCompiler::PopTokenArray()
+{
+ if( pStack )
+ {
+ ScArrayStack* p = pStack;
+ pStack = p->pNext;
+ p->pArr->nRefs += pArr->nRefs;
+ // special RecalcMode aus SharedFormula uebernehmen
+ if ( pArr->IsRecalcModeAlways() )
+ p->pArr->SetRecalcModeAlways();
+ else if ( !pArr->IsRecalcModeNormal() && p->pArr->IsRecalcModeNormal() )
+ p->pArr->SetMaskedRecalcMode( pArr->GetRecalcMode() );
+ p->pArr->SetCombinedBitsRecalcMode( pArr->GetRecalcMode() );
+ if( p->bTemp )
+ delete pArr;
+ pArr = p->pArr;
+ delete p;
+ }
+}
+
+BOOL ScCompiler::GetToken()
+{
+ if ( bAutoCorrect && !pStack )
+ { // #61426# don't merge stacked subroutine code into entered formula
+ aCorrectedFormula += aCorrectedSymbol;
+ aCorrectedSymbol.Erase();
+ }
+ BOOL bStop = FALSE;
+ if( pArr->GetError() && !bIgnoreErrors )
+ bStop = TRUE;
+ else
+ {
+ short nWasColRowName;
+ if ( pArr->nIndex
+ && pArr->pCode[ pArr->nIndex-1 ]->GetOpCode() == ocColRowName )
+ nWasColRowName = 1;
+ else
+ nWasColRowName = 0;
+ pToken = pArr->Next();
+ while( pToken && pToken->GetOpCode() == ocSpaces )
+ {
+ if ( nWasColRowName )
+ nWasColRowName++;
+ if ( bAutoCorrect && !pStack )
+ CreateStringFromToken( aCorrectedFormula, pToken, FALSE );
+ pToken = pArr->Next();
+ }
+ if ( bAutoCorrect && !pStack && pToken )
+ CreateStringFromToken( aCorrectedSymbol, pToken, FALSE );
+ if( !pToken )
+ {
+ if( pStack )
+ {
+ PopTokenArray();
+ return GetToken();
+ }
+ else
+ bStop = TRUE;
+ }
+ else
+ {
+ if ( nWasColRowName >= 2 && pToken->GetOpCode() == ocColRowName )
+ { // aus einem ocSpaces ein ocIntersect im RPN machen
+ ScToken* pRawToken = new ScToken;
+ pRawToken->SetOpCode( ocIntersect );
+ pToken = pRawToken->Clone();
+ delete pRawToken;
+ pArr->nIndex--; // ganz schweinisch..
+ }
+ }
+ }
+ if( bStop )
+ {
+ ScToken* pRawToken = new ScToken;
+ pRawToken->SetOpCode( ocStop );
+ pToken = pRawToken->Clone();
+ delete pRawToken;
+ return FALSE;
+ }
+ if( pToken->GetOpCode() == ocSubTotal )
+ glSubTotal = TRUE;
+ else if( pToken->GetOpCode() == ocName )
+ {
+ ScRangeData* pRangeData = pDoc->GetRangeName()->FindIndex( pToken->nIndex);
+ if (pRangeData)
+ {
+ USHORT nErr = pRangeData->GetErrCode();
+ if( nErr )
+ SetError( errNoName );
+ else if ( !bCompileForFAP )
+ {
+ ScTokenArray* pNew;
+ // #35168# Bereichsformel klammern
+ // #37680# aber nur wenn nicht schon Klammern da,
+ // geklammerte ocSep geht nicht, z.B. SUMME((...;...))
+ // und wenn nicht direkt zwischen ocSep/Klammer,
+ // z.B. SUMME(...;(...;...)) nicht, SUMME(...;(...)*3) ja
+ // kurz: wenn kein eigenstaendiger Ausdruck
+ ScToken* p1 = pArr->PeekPrevNoSpaces();
+ ScToken* p2 = pArr->PeekNextNoSpaces();
+ OpCode eOp1 = (p1 ? p1->GetOpCode() : ocSep);
+ OpCode eOp2 = (p2 ? p2->GetOpCode() : ocSep);
+ BOOL bBorder1 = (eOp1 == ocSep || eOp1 == ocOpen);
+ BOOL bBorder2 = (eOp2 == ocSep || eOp2 == ocClose);
+ BOOL bAddPair = !(bBorder1 && bBorder2);
+ if ( bAddPair )
+ {
+ pNew = new ScTokenArray;
+ pNew->AddOpCode( ocClose );
+ PushTokenArray( pNew, TRUE );
+ pNew->Reset();
+ }
+ pNew = pRangeData->GetCode()->Clone();
+ PushTokenArray( pNew, TRUE );
+ if( pRangeData->HasReferences() )
+ {
+ SetRelNameReference();
+ MoveRelWrap();
+ }
+ pNew->Reset();
+ if ( bAddPair )
+ {
+ pNew = new ScTokenArray;
+ pNew->AddOpCode( ocOpen );
+ PushTokenArray( pNew, TRUE );
+ pNew->Reset();
+ }
+ return GetToken();
+ }
+ }
+ else
+ SetError(errNoName);
+ }
+ else if( pToken->GetOpCode() == ocColRowName )
+ {
+ SingleRefData& rRef = pToken->aRef.Ref1;
+ rRef.CalcAbsIfRel( aPos );
+ if ( !rRef.Valid() )
+ {
+ SetError( errNoRef );
+ return TRUE;
+ }
+ USHORT nCol = rRef.nCol;
+ USHORT nRow = rRef.nRow;
+ USHORT nTab = rRef.nTab;
+ ScAddress aLook( nCol, nRow, nTab );
+ BOOL bColName = rRef.IsColRel();
+ USHORT nMyCol = aPos.Col();
+ USHORT nMyRow = aPos.Row();
+ BOOL bInList = FALSE;
+ BOOL bValidName = FALSE;
+ ScRangePairList* pRL = (bColName ?
+ pDoc->GetColNameRanges() : pDoc->GetRowNameRanges());
+ ScRange aRange;
+ for ( ScRangePair* pR = pRL->First(); pR; pR = pRL->Next() )
+ {
+ if ( pR->GetRange(0).In( aLook ) )
+ {
+ bInList = bValidName = TRUE;
+ aRange = pR->GetRange(1);
+ if ( bColName )
+ {
+ aRange.aStart.SetCol( nCol );
+ aRange.aEnd.SetCol( nCol );
+ }
+ else
+ {
+ aRange.aStart.SetRow( nRow );
+ aRange.aEnd.SetRow( nRow );
+ }
+ break; // for
+ }
+ }
+ if ( !bInList && pDoc->GetDocOptions().IsLookUpColRowNames() )
+ { // automagically oder durch kopieren entstanden und NamePos nicht in Liste
+ BOOL bString = pDoc->HasStringData( nCol, nRow, nTab );
+ if ( !bString && !pDoc->GetCell( aLook ) )
+ bString = TRUE; // leere Zelle ist ok
+ if ( bString )
+ { //! korrespondiert mit ScInterpreter::ScColRowNameAuto
+ bValidName = TRUE;
+ if ( bColName )
+ { // ColName
+ USHORT nStartRow = nRow + 1;
+ if ( nStartRow > MAXROW )
+ nStartRow = MAXROW;
+ USHORT nMaxRow = MAXROW;
+ if ( nMyCol == nCol )
+ { // Formelzelle in gleicher Col
+ if ( nMyRow == nStartRow )
+ { // direkt unter dem Namen den Rest nehmen
+ nStartRow++;
+ if ( nStartRow > MAXROW )
+ nStartRow = MAXROW;
+ }
+ else if ( nMyRow > nStartRow )
+ { // weiter unten vom Namen bis zur Formelzelle
+ nMaxRow = nMyRow - 1;
+ }
+ }
+ for ( ScRangePair* pR = pRL->First(); pR; pR = pRL->Next() )
+ { // naechster definierter ColNameRange unten ist Row-Begrenzung
+ const ScRange& rRange = pR->GetRange(1);
+ if ( rRange.aStart.Col() <= nCol && nCol <= rRange.aEnd.Col() )
+ { // gleicher Col Bereich
+ USHORT nTmp = rRange.aStart.Row();
+ if ( nStartRow < nTmp && nTmp <= nMaxRow )
+ nMaxRow = nTmp - 1;
+ }
+ }
+ aRange.aStart.Set( nCol, nStartRow, nTab );
+ aRange.aEnd.Set( nCol, nMaxRow, nTab );
+ }
+ else
+ { // RowName
+ USHORT nStartCol = nCol + 1;
+ if ( nStartCol > MAXCOL )
+ nStartCol = MAXCOL;
+ USHORT nMaxCol = MAXCOL;
+ if ( nMyRow == nRow )
+ { // Formelzelle in gleicher Row
+ if ( nMyCol == nStartCol )
+ { // direkt neben dem Namen den Rest nehmen
+ nStartCol++;
+ if ( nStartCol > MAXCOL )
+ nStartCol = MAXCOL;
+ }
+ else if ( nMyCol > nStartCol )
+ { // weiter rechts vom Namen bis zur Formelzelle
+ nMaxCol = nMyCol - 1;
+ }
+ }
+ for ( ScRangePair* pR = pRL->First(); pR; pR = pRL->Next() )
+ { // naechster definierter RowNameRange rechts ist Col-Begrenzung
+ const ScRange& rRange = pR->GetRange(1);
+ if ( rRange.aStart.Row() <= nRow && nRow <= rRange.aEnd.Row() )
+ { // gleicher Row Bereich
+ USHORT nTmp = rRange.aStart.Col();
+ if ( nStartCol < nTmp && nTmp <= nMaxCol )
+ nMaxCol = nTmp - 1;
+ }
+ }
+ aRange.aStart.Set( nStartCol, nRow, nTab );
+ aRange.aEnd.Set( nMaxCol, nRow, nTab );
+ }
+ }
+ }
+ if ( bValidName )
+ {
+ // Und nun der Zauber zur Unterscheidung zwischen
+ // Bereich und einer einzelnen Zelle daraus, die
+ // positionsabhaengig von der Formelzelle gewaehlt wird.
+ // Ist ein direkter Nachbar ein binaerer Operator (ocAdd etc.)
+ // so wird eine SingleRef passend zur Col/Row generiert,
+ // ocColRowName bzw. ocIntersect als Nachbar => Range.
+ // Spezialfall: Beschriftung gilt fuer eine einzelne Zelle,
+ // dann wird eine positionsunabhaengige SingleRef generiert.
+ BOOL bSingle = (aRange.aStart == aRange.aEnd);
+ BOOL bFound;
+ if ( bSingle )
+ bFound = TRUE;
+ else
+ {
+ ScToken* p1 = pArr->PeekPrevNoSpaces();
+ ScToken* p2 = pArr->PeekNextNoSpaces();
+ // Anfang/Ende einer Formel => Single
+ OpCode eOp1 = p1 ? p1->GetOpCode() : ocAdd;
+ OpCode eOp2 = p2 ? p2->GetOpCode() : ocAdd;
+ if ( eOp1 != ocColRowName && eOp1 != ocIntersect
+ && eOp2 != ocColRowName && eOp2 != ocIntersect )
+ {
+ if ( (ocEndDiv < eOp1 && eOp1 < ocEndBinOp)
+ || (ocEndDiv < eOp2 && eOp2 < ocEndBinOp) )
+ bSingle = TRUE;
+ }
+ if ( bSingle )
+ { // Col bzw. Row muss zum Range passen
+ if ( bColName )
+ {
+ bFound = (aRange.aStart.Row() <= nMyRow
+ && nMyRow <= aRange.aEnd.Row());
+ if ( bFound )
+ aRange.aStart.SetRow( nMyRow );
+ }
+ else
+ {
+ bFound = (aRange.aStart.Col() <= nMyCol
+ && nMyCol <= aRange.aEnd.Col());
+ if ( bFound )
+ aRange.aStart.SetCol( nMyCol );
+ }
+ }
+ else
+ bFound = TRUE;
+ }
+ if ( !bFound )
+ SetError(errNoRef);
+ else if ( !bCompileForFAP )
+ {
+ ScTokenArray* pNew = new ScTokenArray;
+ if ( bSingle )
+ {
+ SingleRefData aRefData;
+ aRefData.InitAddress( aRange.aStart );
+ if ( bColName )
+ aRefData.SetColRel( TRUE );
+ else
+ aRefData.SetRowRel( TRUE );
+ aRefData.CalcRelFromAbs( aPos );
+ pNew->AddSingleReference( aRefData );
+ }
+ else
+ {
+ ComplRefData aRefData;
+ aRefData.InitRange( aRange );
+ if ( bColName )
+ {
+ aRefData.Ref1.SetColRel( TRUE );
+ aRefData.Ref2.SetColRel( TRUE );
+ }
+ else
+ {
+ aRefData.Ref1.SetRowRel( TRUE );
+ aRefData.Ref2.SetRowRel( TRUE );
+ }
+ aRefData.CalcRelFromAbs( aPos );
+ if ( bInList )
+ pNew->AddDoubleReference( aRefData );
+ else
+ { // automagically
+ ScToken* pRawToken = new ScToken;
+ pRawToken->SetDoubleReference( aRefData );
+ pRawToken->eOp = ocColRowNameAuto;
+ pNew->AddToken( *pRawToken );
+ delete pRawToken;
+ }
+ }
+ PushTokenArray( pNew, TRUE );
+ pNew->Reset();
+ return GetToken();
+ }
+ }
+ else
+ SetError(errNoName);
+ }
+ else if( pToken->GetOpCode() == ocDBArea )
+ {
+ ScDBData* pDBData = pDoc->GetDBCollection()->FindIndex( pToken->nIndex);
+ if ( !pDBData )
+ SetError(errNoName);
+ else if ( !bCompileForFAP )
+ {
+ ComplRefData aRefData;
+ aRefData.InitFlags();
+ pDBData->GetArea( (USHORT&) aRefData.Ref1.nTab,
+ (USHORT&) aRefData.Ref1.nCol,
+ (USHORT&) aRefData.Ref1.nRow,
+ (USHORT&) aRefData.Ref2.nCol,
+ (USHORT&) aRefData.Ref2.nRow);
+ aRefData.Ref2.nTab = aRefData.Ref1.nTab;
+ aRefData.CalcRelFromAbs( aPos );
+ ScTokenArray* pNew = new ScTokenArray;
+ pNew->AddDoubleReference( aRefData );
+ PushTokenArray( pNew, TRUE );
+ pNew->Reset();
+ return GetToken();
+ }
+ }
+ else if( pToken->GetType() == svSingleRef )
+ {
+// if (!pDoc->HasTable( pToken->aRef.Ref1.nTab ) )
+// SetError(errNoRef);
+ pArr->nRefs++;
+ }
+ else if( pToken->GetType() == svDoubleRef )
+ {
+// if (!pDoc->HasTable( pToken->aRef.Ref1.nTab ) ||
+// !pDoc->HasTable( pToken->aRef.Ref2.nTab ))
+// SetError(errNoRef);
+ pArr->nRefs++;
+ }
+ return TRUE;
+}
+
+OpCode ScCompiler::NextToken()
+{
+ if( !GetToken() )
+ return ocStop;
+ OpCode eOp = pToken->GetOpCode();
+ // #38815# CompileTokenArray mit zurueckgesetztem Fehler gibt wieder Fehler
+ if ( eOp == ocBad )
+ SetError( errNoName );
+ // Vor einem Push muss ein Operator kommen
+ if ( (eOp == ocPush || eOp == ocColRowNameAuto) &&
+ !( (eLastOp == ocOpen) || (eLastOp == ocSep) ||
+ ((eLastOp > ocEndDiv) && (eLastOp < ocEndUnOp))) )
+ SetError(errOperatorExpected);
+ // Operator und Plus = Operator
+ BOOL bLastOp = ( eLastOp == ocOpen || eLastOp == ocSep ||
+ (eLastOp > ocEndDiv && eLastOp < ocEndUnOp)
+ );
+ if( bLastOp && eOp == ocAdd )
+ eOp = NextToken();
+ else
+ {
+ // Vor einem Operator darf kein weiterer Operator stehen
+ // Aber AND, OR ist OK
+ if ( eOp != ocAnd && eOp != ocOr
+ && ( eOp > ocEndDiv && eOp < ocEndBinOp )
+ && ( eLastOp == ocOpen || eLastOp == ocSep
+ || (eLastOp > ocEndDiv && eLastOp < ocEndUnOp)) )
+ {
+ SetError(errVariableExpected);
+ if ( bAutoCorrect && !pStack )
+ {
+ if ( eOp == eLastOp || eLastOp == ocOpen )
+ { // doppelten Operator verwerfen
+ aCorrectedSymbol.Erase();
+ bCorrected = TRUE;
+ }
+ else
+ {
+ xub_StrLen nPos = aCorrectedFormula.Len();
+ if ( nPos )
+ {
+ nPos--;
+ sal_Unicode c = aCorrectedFormula.GetChar( nPos );
+ switch ( eOp )
+ { // Operatoren vertauschen
+ case ocGreater:
+ if ( c == pSymbolTable[ocEqual].GetChar(0) )
+ { // >= ist richtig statt =>
+ aCorrectedFormula.SetChar( nPos,
+ pSymbolTable[ocGreater].GetChar(0) );
+ aCorrectedSymbol = c;
+ bCorrected = TRUE;
+ }
+ break;
+ case ocLess:
+ if ( c == pSymbolTable[ocEqual].GetChar(0) )
+ { // <= ist richtig statt =<
+ aCorrectedFormula.SetChar( nPos,
+ pSymbolTable[ocLess].GetChar(0) );
+ aCorrectedSymbol = c;
+ bCorrected = TRUE;
+ }
+ else if ( c == pSymbolTable[ocGreater].GetChar(0) )
+ { // <> ist richtig statt ><
+ aCorrectedFormula.SetChar( nPos,
+ pSymbolTable[ocLess].GetChar(0) );
+ aCorrectedSymbol = c;
+ bCorrected = TRUE;
+ }
+ break;
+ case ocMul:
+ if ( c == pSymbolTable[ocSub].GetChar(0) )
+ { // *- statt -*
+ aCorrectedFormula.SetChar( nPos,
+ pSymbolTable[ocMul].GetChar(0) );
+ aCorrectedSymbol = c;
+ bCorrected = TRUE;
+ }
+ break;
+ case ocDiv:
+ if ( c == pSymbolTable[ocSub].GetChar(0) )
+ { // /- statt -/
+ aCorrectedFormula.SetChar( nPos,
+ pSymbolTable[ocDiv].GetChar(0) );
+ aCorrectedSymbol = c;
+ bCorrected = TRUE;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ eLastOp = eOp;
+ }
+ return eOp;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL ScCompiler::CompileTokenArray()
+{
+ glSubTotal = FALSE;
+ bCorrected = FALSE;
+ if( !pArr->nError || bIgnoreErrors )
+ {
+ if ( bAutoCorrect )
+ {
+ aCorrectedFormula.Erase();
+ aCorrectedSymbol.Erase();
+ }
+ pArr->nRefs = 0; // wird neu gezaehlt
+ pArr->DelRPN();
+ pStack = NULL;
+ ScToken* pData[ MAXCODE ];
+ pCode = pData;
+ BOOL bWasForced = pArr->IsRecalcModeForced();
+ if ( bWasForced )
+ {
+ if ( bAutoCorrect )
+ aCorrectedFormula = '=';
+ }
+ pArr->ClearRecalcMode();
+ pArr->Reset();
+ eLastOp = ocOpen;
+ pc = 0;
+ NextToken();
+ Expression();
+
+ USHORT nErrorBeforePop = pArr->nError;
+
+ while( pStack )
+ PopTokenArray();
+ if( pc )
+ {
+ pArr->pRPN = new ScToken*[ pc ];
+ pArr->nRPN = pc;
+ memcpy( pArr->pRPN, pData, pc * sizeof( ScToken* ) );
+ }
+
+ if( !pArr->nError && nErrorBeforePop )
+ pArr->nError = nErrorBeforePop; // einmal Fehler, immer Fehler
+
+ if( pArr->nError && !bIgnoreErrors )
+ pArr->DelRPN();
+
+ if ( bWasForced )
+ pArr->SetRecalcModeForced();
+ }
+ if( nNumFmt == NUMBERFORMAT_UNDEFINED )
+ nNumFmt = NUMBERFORMAT_NUMBER;
+ return glSubTotal;
+}
+
+//---------------------------------------------------------------------------
+// Token in den Code Eintragen
+//---------------------------------------------------------------------------
+
+void ScCompiler::PutCode( ScToken* p )
+{
+ if( pc >= MAXCODE )
+ SetError(errCodeOverflow);
+ if( pArr->GetError() && !bCompileForFAP )
+ return;
+ *pCode++ = p; pc++;
+ p->IncRef();
+}
+
+//---------------------------------------------------------------------------
+// UPN-Erzeugung (durch Rekursion)
+//---------------------------------------------------------------------------
+
+void ScCompiler::Factor()
+{
+ if ( pArr->GetError() && !bIgnoreErrors )
+ return;
+ ScTokenRef pFacToken;
+ OpCode eOp = pToken->GetOpCode();
+ if( eOp == ocPush || eOp == ocColRowNameAuto || eOp == ocMatRef ||
+ eOp == ocDBArea
+ || (bCompileForFAP && ((eOp == ocName) || (eOp == ocDBArea)
+ || (eOp == ocColRowName) || (eOp == ocBad)))
+ )
+ {
+ PutCode( pToken );
+ eOp = NextToken();
+ if( eOp == ocOpen )
+ {
+ // PUSH( ist ein Fehler, der durch eine unbekannte
+ // Funktion hervorgerufen wird.
+ SetError(
+ ( pToken->GetType() == svString
+ || pToken->GetType() == svSingleRef )
+ ? errNoName : errOperatorExpected );
+ if ( bAutoCorrect && !pStack )
+ { // Multiplikation annehmen
+ aCorrectedFormula += pSymbolTable[ocMul];
+ bCorrected = TRUE;
+ NextToken();
+ eOp = Expression();
+ if( eOp != ocClose )
+ SetError(errPairExpected);
+ else
+ eOp = NextToken();
+ }
+ }
+ }
+ else if( eOp == ocOpen )
+ {
+ NextToken();
+ eOp = Expression();
+ if( eOp != ocClose )
+ SetError(errPairExpected);
+ else
+ eOp = NextToken();
+ }
+ else
+ {
+ if( nNumFmt == NUMBERFORMAT_UNDEFINED )
+ nNumFmt = lcl_GetRetFormat( eOp );
+ if( eOp > ocEndUnOp && eOp < ocEndNoPar)
+ {
+ // Diese Funktionen muessen immer neu berechnet werden
+ switch( eOp )
+ {
+ case ocRandom:
+ case ocGetActDate:
+ case ocGetActTime:
+ pArr->SetRecalcModeAlways();
+ break;
+ }
+ pFacToken = pToken;
+ eOp = NextToken();
+ if (eOp != ocOpen)
+ {
+ SetError(errPairExpected);
+ PutCode( pFacToken );
+ }
+ else
+ {
+ eOp = NextToken();
+ if (eOp != ocClose)
+ SetError(errPairExpected);
+ PutCode(pFacToken);
+ eOp = NextToken();
+ }
+ }
+ // Spezialfall NICHT() und NEG()
+ else if( eOp == ocNot || eOp == ocNeg
+ || ( eOp > ocEndNoPar && eOp < ocEnd1Par) )
+ {
+ pFacToken = pToken;
+ eOp = NextToken();
+ if( nNumFmt == NUMBERFORMAT_UNDEFINED && eOp == ocNot )
+ nNumFmt = NUMBERFORMAT_LOGICAL;
+ if (eOp == ocOpen)
+ {
+ NextToken();
+ eOp = Expression();
+ }
+ else
+ SetError(errPairExpected);
+ if (eOp != ocClose)
+ SetError(errPairExpected);
+ PutCode( pFacToken );
+ eOp = NextToken();
+ }
+ else if ((eOp > ocEnd1Par && eOp < ocEnd2Par)
+ || eOp == ocExternal
+ || eOp == ocMacro
+ || eOp == ocAnd
+ || eOp == ocOr
+ || ( eOp >= ocInternalBegin && eOp <= ocInternalEnd )
+ || (bCompileForFAP && ((eOp == ocIf) || (eOp == ocChose)))
+ )
+ {
+ OpCode eFuncOp = eOp;
+ pFacToken = pToken;
+ eOp = NextToken();
+ BOOL bNoParam = FALSE;
+ BOOL bNoPair = FALSE;
+ BYTE nMultiAreaSep = 0;
+ if (eOp == ocOpen)
+ {
+ eOp = NextToken();
+ if ( eFuncOp == ocIndex && eOp == ocOpen )
+ { // Mehrfachbereiche
+ BYTE SepCount = 0;
+ do
+ {
+ eOp = NextToken();
+ if ( eOp != ocClose )
+ {
+ SepCount++;
+ eOp = Expression();
+ }
+ } while ( (eOp == ocSep) && (!pArr->GetError() || bIgnoreErrors) );
+ if ( eOp != ocClose )
+ SetError(errPairExpected);
+ eOp = NextToken();
+ if ( eOp == ocSep )
+ {
+ nMultiAreaSep = 1;
+ eOp = NextToken();
+ }
+ if ( SepCount == 0 )
+ {
+ if ( eOp == ocClose )
+ bNoParam = TRUE;
+ }
+ else
+ {
+ ScToken* pRawToken = new ScToken;
+ pRawToken->SetByte( SepCount );
+ ScTokenRef pSepToken = pRawToken->Clone();
+ delete pRawToken;
+ PutCode( pSepToken );
+ if ( eOp != ocClose )
+ eOp = Expression();
+ }
+ }
+ else
+ {
+ if (eOp == ocClose)
+ bNoParam = TRUE;
+ else
+ eOp = Expression();
+ }
+ }
+ else
+ {
+ if (pFacToken->GetOpCode() == ocMultiArea)
+ {
+ bNoPair = TRUE;
+ NextToken();
+ eOp = Expression();
+ }
+ else
+ SetError(errPairExpected);
+ }
+ BYTE SepCount = nMultiAreaSep;
+ if( !bNoParam )
+ {
+ SepCount++;
+ while ( (eOp == ocSep) && (!pArr->GetError() || bIgnoreErrors) )
+ {
+ SepCount++;
+ NextToken();
+ eOp = Expression();
+ }
+ }
+ if ((eOp != ocClose) && !bNoPair )
+ SetError(errPairExpected);
+ else
+ eOp = NextToken();
+ pFacToken->cByte = SepCount;
+ PutCode( pFacToken );
+ // Diese Funktionen muessen immer neu berechnet werden
+ switch( eFuncOp )
+ {
+ // ocIndirect muesste sonst bei jedem Interpret StopListening
+ // und StartListening fuer ein RefTripel ausfuehren
+ case ocIndirect:
+ // ocOffset und ocIndex liefern indirekte Refs
+ case ocOffset:
+ case ocIndex:
+ pArr->SetRecalcModeAlways();
+ break;
+ // Functions recalculated on every document load.
+ // Don't use SetRecalcModeOnLoad which would override ModeAlways
+ case ocConvert :
+ pArr->AddRecalcMode( RECALCMODE_ONLOAD );
+ break;
+ // wird die referierte verschoben, aendert sich der Wert
+ case ocColumn :
+ case ocRow :
+ pArr->SetRecalcModeOnRefMove();
+ break;
+ }
+ }
+ else if (eOp == ocIf || eOp == ocChose)
+ {
+ // Die PC-Staende sind -1
+ pFacToken = pToken;
+ if ( eOp == ocIf )
+ pFacToken->nJump[ 0 ] = 3; // if, else, behind
+ else
+ pFacToken->nJump[ 0 ] = MAXJUMPCOUNT+1;
+ eOp = NextToken();
+ if (eOp == ocOpen)
+ {
+ NextToken();
+ eOp = Expression();
+ }
+ else
+ SetError(errPairExpected);
+ short nJumpCount = 0;
+ PutCode( pFacToken );
+ // #36253# bei AutoCorrect (da pArr->nError ignoriert wird)
+ // unbegrenztes ocIf gibt GPF weil ScToken::Clone den JumpBuffer
+ // anhand von nJump[0]*2+2 alloziert, was bei ocIf 3*2+2 ist
+ const short nJumpMax =
+ (pFacToken->GetOpCode() == ocIf ? 3 : MAXJUMPCOUNT);
+ while ( (nJumpCount < (MAXJUMPCOUNT - 1)) && (eOp == ocSep)
+ && (!pArr->GetError() || bIgnoreErrors) )
+ {
+ if ( ++nJumpCount <= nJumpMax )
+ pFacToken->nJump[nJumpCount] = pc-1;
+ NextToken();
+ eOp = Expression();
+ PutCode( pToken ); // Als Terminator des Teilausdrucks
+ }
+ if (eOp != ocClose)
+ SetError(errPairExpected);
+ else
+ {
+ eOp = NextToken();
+ // auch ohne AutoCorrect gibt es hier ohne nJumpMax bei
+ // mehr als 3 Parametern in ocIf einen Ueberschreiber,
+ // das war auch schon in der 312 so (jaja, die Tester..)
+ if ( ++nJumpCount <= nJumpMax )
+ pFacToken->nJump[ nJumpCount ] = pc-1;
+ if ((pFacToken->GetOpCode() == ocIf && (nJumpCount > 3)) ||
+ (nJumpCount >= MAXJUMPCOUNT))
+ SetError(errIllegalParameter);
+ else
+ pFacToken->nJump[ 0 ] = nJumpCount;
+ }
+ }
+ else if ( eOp == ocBad )
+ {
+ SetError( errNoName );
+ }
+ else if ( eOp == ocClose )
+ {
+ SetError( errParameterExpected );
+ }
+ else
+ {
+ SetError( errUnknownToken );
+ if ( bAutoCorrect && !pStack )
+ {
+ if ( eOp == ocStop )
+ { // trailing operator w/o operand
+ xub_StrLen nLen = aCorrectedFormula.Len();
+ if ( nLen )
+ aCorrectedFormula.Erase( nLen - 1 );
+ aCorrectedSymbol.Erase();
+ bCorrected = TRUE;
+ }
+ }
+ }
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void ScCompiler::Unary()
+{
+ if( pToken->GetOpCode() == ocAdd )
+ GetToken();
+ else if ( pToken->GetOpCode() > ocNot && pToken->GetOpCode() < ocEndUnOp )
+ {
+ ScTokenRef p = pToken;
+ NextToken();
+ Factor();
+ PutCode( p );
+ }
+ else
+ Factor();
+}
+
+void ScCompiler::PowLine()
+{
+ Unary();
+ while (pToken->GetOpCode() == ocPow)
+ {
+ ScTokenRef p = pToken;
+ NextToken();
+ Unary();
+ PutCode(p);
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void ScCompiler::UnionCutLine()
+{
+ PowLine();
+ while (pToken->GetOpCode() == ocIntersect)
+ {
+ ScTokenRef p = pToken;
+ NextToken();
+ PowLine();
+ PutCode(p);
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void ScCompiler::MulDivLine()
+{
+ UnionCutLine();
+ while (pToken->GetOpCode() == ocMul || pToken->GetOpCode() == ocDiv)
+ {
+ ScTokenRef p = pToken;
+ NextToken();
+ UnionCutLine();
+ PutCode(p);
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void ScCompiler::AddSubLine()
+{
+ MulDivLine();
+ while (pToken->GetOpCode() == ocAdd || pToken->GetOpCode() == ocSub
+ || pToken->GetOpCode() == ocAmpersand)
+ {
+ ScTokenRef p = pToken;
+ NextToken();
+ MulDivLine();
+ PutCode(p);
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void ScCompiler::CompareLine()
+{
+ AddSubLine();
+ while (pToken->GetOpCode() >= ocEqual && pToken->GetOpCode() <= ocGreaterEqual)
+ {
+ ScTokenRef p = pToken;
+ NextToken();
+ AddSubLine();
+ PutCode(p);
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void ScCompiler::NotLine()
+{
+ CompareLine();
+ while (pToken->GetOpCode() == ocNot)
+ {
+ ScTokenRef p = pToken;
+ NextToken();
+ CompareLine();
+ PutCode(p);
+ }
+}
+
+//---------------------------------------------------------------------------
+
+OpCode ScCompiler::Expression()
+{
+ static const short nRecursionMax = 42;
+ if ( ++nRecursion > nRecursionMax )
+ {
+ SetError( errStackOverflow );
+ return ocStop; //! stattdessen Token generieren?
+ }
+ NotLine();
+ while (pToken->GetOpCode() == ocAnd || pToken->GetOpCode() == ocOr)
+ {
+ ScTokenRef p = pToken;
+ pToken->cByte = 2; // 2 Parameter!
+ NextToken();
+ NotLine();
+ PutCode(p);
+ }
+ --nRecursion;
+ return pToken->GetOpCode();
+}
+
+//-----------------------------------------------------------------------------
+
+BOOL ScCompiler::HasModifiedRange()
+{
+ pArr->Reset();
+ for ( ScToken* t = pArr->Next(); t; t = pArr->Next() )
+ {
+ OpCode eOpCode = t->GetOpCode();
+ if ( eOpCode == ocName )
+ {
+ ScRangeData* pRangeData = pDoc->GetRangeName()->FindIndex(t->nIndex);
+
+ if (pRangeData && pRangeData->IsModified())
+ return TRUE;
+ }
+ else if ( eOpCode == ocDBArea )
+ {
+ ScDBData* pDBData = pDoc->GetDBCollection()->FindIndex(t->nIndex);
+
+ if (pDBData && pDBData->IsModified())
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+
+short lcl_adjval( short n, short pos, short max, BOOL bRel )
+{
+ max++;
+ if( bRel ) n += pos;
+ if( n < 0 ) n += max;
+ else
+ if( n >= max ) n -= max;
+ if( bRel ) n -= pos;
+ return n;
+}
+
+void ScCompiler::AdjustReference( SingleRefData& r )
+{
+ if( r.IsColRel() )
+ r.nCol = lcl_adjval( r.nCol, aPos.Col(), MAXCOL, r.IsColRel() );
+ if( r.IsRowRel() )
+ r.nRow = lcl_adjval( r.nRow, aPos.Row(), MAXROW, r.IsRowRel() );
+ if( r.IsTabRel() )
+ r.nTab = lcl_adjval( r.nTab, aPos.Tab(), nMaxTab,r.IsTabRel() );
+}
+
+// Referenz aus benanntem Bereich mit relativen Angaben
+
+void ScCompiler::SetRelNameReference()
+{
+ pArr->Reset();
+ for( ScToken* t = pArr->GetNextReference(); t;
+ t = pArr->GetNextReference() )
+ {
+ if ( t->aRef.Ref1.IsColRel() || t->aRef.Ref1.IsRowRel() || t->aRef.Ref1.IsTabRel() )
+ t->aRef.Ref1.SetRelName( TRUE );
+ if ( t->aRef.Ref2.IsColRel() || t->aRef.Ref2.IsRowRel() || t->aRef.Ref2.IsTabRel() )
+ t->aRef.Ref2.SetRelName( TRUE );
+ }
+}
+
+// nur relative aus RangeName mit Wrap an Position anpassen
+void ScCompiler::MoveRelWrap()
+{
+ pArr->Reset();
+ for( ScToken* t = pArr->GetNextReference(); t;
+ t = pArr->GetNextReference() )
+ ScRefUpdate::MoveRelWrap( pDoc, aPos, t->aRef );
+}
+
+// static
+// nur relative aus RangeName mit Wrap an Position anpassen
+void ScCompiler::MoveRelWrap( ScTokenArray& rArr, ScDocument* pDoc,
+ const ScAddress& rPos )
+{
+ rArr.Reset();
+ for( ScToken* t = rArr.GetNextReference(); t;
+ t = rArr.GetNextReference() )
+ ScRefUpdate::MoveRelWrap( pDoc, rPos, t->aRef );
+}
+
+ScRangeData* ScCompiler::UpdateReference(UpdateRefMode eUpdateRefMode,
+ const ScAddress& rOldPos, const ScRange& r,
+ short nDx, short nDy, short nDz,
+ BOOL& rChanged)
+{
+ rChanged = FALSE;
+ if ( eUpdateRefMode == URM_COPY )
+ return NULL; // mit RelRefs ok, auch SharedFormulas
+ else
+ {
+ ScRangeData* pRangeData = NULL;
+ ScToken* t;
+ pArr->Reset();
+ for( t = pArr->GetNextReferenceOrName(); t;
+ t = pArr->GetNextReferenceOrName() )
+ {
+ if( t->GetOpCode() == ocName )
+ {
+ ScRangeData* pName = pDoc->GetRangeName()->FindIndex( t->nIndex );
+ if (pName && pName->HasType(RT_SHAREDMOD))
+ {
+ pRangeData = pName; // => neu kompilieren etc.
+ rChanged = TRUE;
+ }
+ }
+ else if( t->GetType() != svIndex ) // es kann ein DB-Bereich sein !!!
+ {
+ t->aRef.CalcAbsIfRel( rOldPos );
+ if ( ScRefUpdate::Update( pDoc, eUpdateRefMode, aPos,
+ r, nDx, nDy, nDz, t->aRef )
+ != UR_NOTHING
+ )
+ rChanged = TRUE;
+ }
+ }
+ pArr->Reset();
+ for( t = pArr->GetNextReferenceRPN(); t;
+ t = pArr->GetNextReferenceRPN() )
+ {
+ if ( t->GetRef() == 1 )
+ { // bei nRefCnt>1 bereits im Code angepasst
+ if ( t->aRef.Ref1.IsRelName() || t->aRef.Ref2.IsRelName() )
+ {
+ ScRefUpdate::MoveRelWrap( pDoc, aPos, t->aRef );
+ rChanged = TRUE;
+ }
+ else
+ {
+ t->aRef.CalcAbsIfRel( rOldPos );
+ if ( ScRefUpdate::Update( pDoc, eUpdateRefMode, aPos,
+ r, nDx, nDy, nDz, t->aRef )
+ != UR_NOTHING
+ )
+ rChanged = TRUE;
+ }
+ }
+ }
+ return pRangeData;
+ }
+}
+
+BOOL ScCompiler::UpdateNameReference(UpdateRefMode eUpdateRefMode,
+ const ScRange& r,
+ short nDx, short nDy, short nDz,
+ BOOL& rChanged)
+{
+ BOOL bRet = FALSE; // wird gesetzt, wenn rel-Ref
+ rChanged = FALSE;
+ pArr->Reset();
+ for( ScToken* t = pArr->GetNextReference(); t;
+ t = pArr->GetNextReference() )
+ {
+ ComplRefData& rRef = t->aRef;
+ if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() &&
+ (!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) &&
+ ( t->GetType() == svSingleRef ||
+ (!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() &&
+ (!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel()))))
+ {
+ if (ScRefUpdate::Update( pDoc, eUpdateRefMode, aPos,
+ r, nDx, nDy, nDz, rRef ) != UR_NOTHING )
+ rChanged = TRUE;
+ }
+ else
+ bRet = TRUE;
+ }
+ return bRet;
+}
+
+
+void ScCompiler::UpdateSharedFormulaReference( UpdateRefMode eUpdateRefMode,
+ const ScAddress& rOldPos, const ScRange& r,
+ short nDx, short nDy, short nDz )
+{
+ if ( eUpdateRefMode == URM_COPY )
+ return ;
+ else
+ {
+ ScToken* t;
+ pArr->Reset();
+ for( t = pArr->GetNextReference(); t;
+ t = pArr->GetNextReference() )
+ {
+ if( t->GetType() != svIndex ) // es kann ein DB-Bereich sein !!!
+ {
+ t->aRef.CalcAbsIfRel( rOldPos );
+ // Absolute references have been already adjusted in the named
+ // shared formula itself prior to breaking the shared formula
+ // and calling this function. Don't readjust them again.
+ ComplRefData aBkp = t->aRef;
+ ScRefUpdate::Update( pDoc, eUpdateRefMode, aPos,
+ r, nDx, nDy, nDz, t->aRef );
+ // restore absolute parts
+ if ( !aBkp.Ref1.IsColRel() )
+ {
+ t->aRef.Ref1.nCol = aBkp.Ref1.nCol;
+ t->aRef.Ref1.nRelCol = aBkp.Ref1.nRelCol;
+ t->aRef.Ref1.SetColDeleted( aBkp.Ref1.IsColDeleted() );
+ }
+ if ( !aBkp.Ref1.IsRowRel() )
+ {
+ t->aRef.Ref1.nRow = aBkp.Ref1.nRow;
+ t->aRef.Ref1.nRelRow = aBkp.Ref1.nRelRow;
+ t->aRef.Ref1.SetRowDeleted( aBkp.Ref1.IsRowDeleted() );
+ }
+ if ( !aBkp.Ref1.IsTabRel() )
+ {
+ t->aRef.Ref1.nTab = aBkp.Ref1.nTab;
+ t->aRef.Ref1.nRelTab = aBkp.Ref1.nRelTab;
+ t->aRef.Ref1.SetTabDeleted( aBkp.Ref1.IsTabDeleted() );
+ }
+ if ( !aBkp.Ref2.IsColRel() )
+ {
+ t->aRef.Ref2.nCol = aBkp.Ref2.nCol;
+ t->aRef.Ref2.nRelCol = aBkp.Ref2.nRelCol;
+ t->aRef.Ref2.SetColDeleted( aBkp.Ref2.IsColDeleted() );
+ }
+ if ( !aBkp.Ref2.IsRowRel() )
+ {
+ t->aRef.Ref2.nRow = aBkp.Ref2.nRow;
+ t->aRef.Ref2.nRelRow = aBkp.Ref2.nRelRow;
+ t->aRef.Ref2.SetRowDeleted( aBkp.Ref2.IsRowDeleted() );
+ }
+ if ( !aBkp.Ref2.IsTabRel() )
+ {
+ t->aRef.Ref2.nTab = aBkp.Ref2.nTab;
+ t->aRef.Ref2.nRelTab = aBkp.Ref2.nRelTab;
+ t->aRef.Ref2.SetTabDeleted( aBkp.Ref2.IsTabDeleted() );
+ }
+ }
+ }
+ }
+}
+
+
+ScRangeData* ScCompiler::UpdateInsertTab( USHORT nTable, BOOL bIsName )
+{
+ ScRangeData* pRangeData = NULL;
+ USHORT nTab;
+ USHORT nPosTab = aPos.Tab(); // _nach_ evtl. Increment!
+ USHORT nOldPosTab = ((nPosTab > nTable) ? (nPosTab - 1) : nPosTab);
+ BOOL bIsRel = FALSE;
+ ScToken* t;
+ pArr->Reset();
+ if (bIsName)
+ t = pArr->GetNextReference();
+ else
+ t = pArr->GetNextReferenceOrName();
+ while( t )
+ {
+ if( t->GetOpCode() == ocName )
+ {
+ if (!bIsName)
+ {
+ ScRangeData* pName = pDoc->GetRangeName()->FindIndex(t->nIndex);
+ if (pName && pName->HasType(RT_SHAREDMOD))
+ pRangeData = pName;
+ }
+ }
+ else if( t->GetType() != svIndex ) // es kann ein DB-Bereich sein !!!
+ {
+ if ( !(bIsName && t->aRef.Ref1.IsTabRel()) )
+ { // Namen nur absolute anpassen
+ SingleRefData& rRef = t->aRef.Ref1;
+ if ( rRef.IsTabRel() )
+ nTab = rRef.nRelTab + nOldPosTab;
+ else
+ nTab = rRef.nTab;
+ if ( nTable <= nTab )
+ rRef.nTab = nTab + 1;
+ rRef.nRelTab = rRef.nTab - nPosTab;
+ if( t->GetType() == svSingleRef )
+ {
+ t->aRef.Ref2.nTab = rRef.nTab;
+ t->aRef.Ref2.nRelTab = rRef.nRelTab;
+ }
+ }
+ else
+ bIsRel = TRUE;
+ if ( t->GetType() == svDoubleRef )
+ {
+ if ( !(bIsName && t->aRef.Ref2.IsTabRel()) )
+ { // Namen nur absolute anpassen
+ SingleRefData& rRef = t->aRef.Ref2;
+ if ( rRef.IsTabRel() )
+ nTab = rRef.nRelTab + nOldPosTab;
+ else
+ nTab = rRef.nTab;
+ if ( nTable <= nTab )
+ rRef.nTab = nTab + 1;
+ rRef.nRelTab = rRef.nTab - nPosTab;
+ }
+ else
+ bIsRel = TRUE;
+ }
+ if ( bIsName && bIsRel )
+ pRangeData = (ScRangeData*) this; // wird in rangenam nicht dereferenziert
+ }
+ if (bIsName)
+ t = pArr->GetNextReference();
+ else
+ t = pArr->GetNextReferenceOrName();
+ }
+ if ( !bIsName )
+ {
+ pArr->Reset();
+ for ( t = pArr->GetNextReferenceRPN(); t;
+ t = pArr->GetNextReferenceRPN() )
+ {
+ if ( t->GetRef() == 1 )
+ {
+ if ( !(t->aRef.Ref1.IsRelName() && t->aRef.Ref1.IsTabRel()) )
+ { // Namen nur absolute anpassen
+ SingleRefData& rRef = t->aRef.Ref1;
+ if ( rRef.IsTabRel() )
+ nTab = rRef.nRelTab + nOldPosTab;
+ else
+ nTab = rRef.nTab;
+ if ( nTable <= nTab )
+ rRef.nTab = nTab + 1;
+ rRef.nRelTab = rRef.nTab - nPosTab;
+ if( t->GetType() == svSingleRef )
+ {
+ t->aRef.Ref2.nTab = rRef.nTab;
+ t->aRef.Ref2.nRelTab = rRef.nRelTab;
+ }
+ }
+ if ( t->GetType() == svDoubleRef )
+ {
+ if ( !(t->aRef.Ref2.IsRelName() && t->aRef.Ref2.IsTabRel()) )
+ { // Namen nur absolute anpassen
+ SingleRefData& rRef = t->aRef.Ref2;
+ if ( rRef.IsTabRel() )
+ nTab = rRef.nRelTab + nOldPosTab;
+ else
+ nTab = rRef.nTab;
+ if ( nTable <= nTab )
+ rRef.nTab = nTab + 1;
+ rRef.nRelTab = rRef.nTab - nPosTab;
+ }
+ }
+ }
+ }
+ }
+ return pRangeData;
+}
+
+ScRangeData* ScCompiler::UpdateDeleteTab(USHORT nTable, BOOL bIsMove, BOOL bIsName,
+ BOOL& rChanged)
+{
+ ScRangeData* pRangeData = NULL;
+ USHORT nTab, nTab2;
+ USHORT nPosTab = aPos.Tab(); // _nach_ evtl. Decrement!
+ USHORT nOldPosTab = ((nPosTab >= nTable) ? (nPosTab + 1) : nPosTab);
+ rChanged = FALSE;
+ BOOL bIsRel = FALSE;
+ ScToken* t;
+ pArr->Reset();
+ if (bIsName)
+ t = pArr->GetNextReference();
+ else
+ t = pArr->GetNextReferenceOrName();
+ while( t )
+ {
+ if( t->GetOpCode() == ocName )
+ {
+ if (!bIsName)
+ {
+ ScRangeData* pName = pDoc->GetRangeName()->FindIndex(t->nIndex);
+ if (pName && pName->HasType(RT_SHAREDMOD))
+ pRangeData = pName;
+ }
+ rChanged = TRUE;
+ }
+ else if( t->GetType() != svIndex ) // es kann ein DB-Bereich sein !!!
+ {
+ if ( !(bIsName && t->aRef.Ref1.IsTabRel()) )
+ { // Namen nur absolute anpassen
+ SingleRefData& rRef = t->aRef.Ref1;
+ if ( rRef.IsTabRel() )
+ nTab = rRef.nRelTab + nOldPosTab;
+ else
+ nTab = rRef.nTab;
+ if ( nTable < nTab )
+ {
+ rRef.nTab = nTab - 1;
+ rChanged = TRUE;
+ }
+ else if ( nTable == nTab )
+ {
+ if ( t->GetType() == svDoubleRef )
+ {
+ if ( t->aRef.Ref2.IsTabRel() )
+ nTab2 = t->aRef.Ref2.nRelTab + nOldPosTab;
+ else
+ nTab2 = t->aRef.Ref2.nTab;
+ if ( nTab == nTab2
+ || (nTab+1) >= pDoc->GetTableCount() )
+ {
+ rRef.nTab = MAXTAB+1;
+ rRef.SetTabDeleted( TRUE );
+ }
+ // else: nTab zeigt spaeter auf jetziges nTable+1
+ // => Bereich verkleinert
+ }
+ else
+ {
+ rRef.nTab = MAXTAB+1;
+ rRef.SetTabDeleted( TRUE );
+ }
+ rChanged = TRUE;
+ }
+ rRef.nRelTab = rRef.nTab - nPosTab;
+ if( t->GetType() == svSingleRef )
+ {
+ t->aRef.Ref2.nTab = rRef.nTab;
+ t->aRef.Ref2.nRelTab = rRef.nRelTab;
+ }
+ }
+ else
+ bIsRel = TRUE;
+ if ( t->GetType() == svDoubleRef )
+ {
+ if ( !(bIsName && t->aRef.Ref2.IsTabRel()) )
+ { // Namen nur absolute anpassen
+ SingleRefData& rRef = t->aRef.Ref2;
+ if ( rRef.IsTabRel() )
+ nTab = rRef.nRelTab + nOldPosTab;
+ else
+ nTab = rRef.nTab;
+ if ( nTable < nTab )
+ {
+ rRef.nTab = nTab - 1;
+ rChanged = TRUE;
+ }
+ else if ( nTable == nTab )
+ {
+ if ( !t->aRef.Ref1.IsTabDeleted() )
+ rRef.nTab = nTab - 1; // Bereich verkleinern
+ else
+ {
+ rRef.nTab = MAXTAB+1;
+ rRef.SetTabDeleted( TRUE );
+ }
+ rChanged = TRUE;
+ }
+ rRef.nRelTab = rRef.nTab - nPosTab;
+ }
+ else
+ bIsRel = TRUE;
+ }
+ if ( bIsName && bIsRel )
+ pRangeData = (ScRangeData*) this; // wird in rangenam nicht dereferenziert
+ }
+ if (bIsName)
+ t = pArr->GetNextReference();
+ else
+ t = pArr->GetNextReferenceOrName();
+ }
+ if ( !bIsName )
+ {
+ pArr->Reset();
+ for ( t = pArr->GetNextReferenceRPN(); t;
+ t = pArr->GetNextReferenceRPN() )
+ {
+ if ( t->GetRef() == 1 )
+ {
+ if ( !(t->aRef.Ref1.IsRelName() && t->aRef.Ref1.IsTabRel()) )
+ { // Namen nur absolute anpassen
+ SingleRefData& rRef = t->aRef.Ref1;
+ if ( rRef.IsTabRel() )
+ nTab = rRef.nRelTab + nOldPosTab;
+ else
+ nTab = rRef.nTab;
+ if ( nTable < nTab )
+ {
+ rRef.nTab = nTab - 1;
+ rChanged = TRUE;
+ }
+ else if ( nTable == nTab )
+ {
+ if ( t->GetType() == svDoubleRef )
+ {
+ if ( t->aRef.Ref2.IsTabRel() )
+ nTab2 = t->aRef.Ref2.nRelTab + nOldPosTab;
+ else
+ nTab2 = t->aRef.Ref2.nTab;
+ if ( nTab == nTab2
+ || (nTab+1) >= pDoc->GetTableCount() )
+ {
+ rRef.nTab = MAXTAB+1;
+ rRef.SetTabDeleted( TRUE );
+ }
+ // else: nTab zeigt spaeter auf jetziges nTable+1
+ // => Bereich verkleinert
+ }
+ else
+ {
+ rRef.nTab = MAXTAB+1;
+ rRef.SetTabDeleted( TRUE );
+ }
+ rChanged = TRUE;
+ }
+ rRef.nRelTab = rRef.nTab - nPosTab;
+ if( t->GetType() == svSingleRef )
+ {
+ t->aRef.Ref2.nTab = rRef.nTab;
+ t->aRef.Ref2.nRelTab = rRef.nRelTab;
+ }
+ }
+ if ( t->GetType() == svDoubleRef )
+ {
+ if ( !(t->aRef.Ref2.IsRelName() && t->aRef.Ref2.IsTabRel()) )
+ { // Namen nur absolute anpassen
+ SingleRefData& rRef = t->aRef.Ref2;
+ if ( rRef.IsTabRel() )
+ nTab = rRef.nRelTab + nOldPosTab;
+ else
+ nTab = rRef.nTab;
+ if ( nTable < nTab )
+ {
+ rRef.nTab = nTab - 1;
+ rChanged = TRUE;
+ }
+ else if ( nTable == nTab )
+ {
+ if ( !t->aRef.Ref1.IsTabDeleted() )
+ rRef.nTab = nTab - 1; // Bereich verkleinern
+ else
+ {
+ rRef.nTab = MAXTAB+1;
+ rRef.SetTabDeleted( TRUE );
+ }
+ rChanged = TRUE;
+ }
+ rRef.nRelTab = rRef.nTab - nPosTab;
+ }
+ }
+ }
+ }
+ }
+ return pRangeData;
+}
+
+// aPos.Tab() muss bereits angepasst sein!
+ScRangeData* ScCompiler::UpdateMoveTab( USHORT nOldTab, USHORT nNewTab,
+ BOOL bIsName )
+{
+ ScRangeData* pRangeData = NULL;
+ INT16 nTab;
+
+ USHORT nStart, nEnd;
+ short nDir; // Richtung, die die anderen wandern
+ if ( nOldTab < nNewTab )
+ {
+ nDir = -1;
+ nStart = nOldTab;
+ nEnd = nNewTab;
+ }
+ else
+ {
+ nDir = 1;
+ nStart = nNewTab;
+ nEnd = nOldTab;
+ }
+ USHORT nPosTab = aPos.Tab(); // aktuelle Tabelle
+ USHORT nOldPosTab; // vorher war's die
+ if ( nPosTab == nNewTab )
+ nOldPosTab = nOldTab; // look, it's me!
+ else if ( nPosTab < nStart || nEnd < nPosTab )
+ nOldPosTab = nPosTab; // wurde nicht bewegt
+ else
+ nOldPosTab = nPosTab - nDir; // einen verschoben
+
+ BOOL bIsRel = FALSE;
+ ScToken* t;
+ pArr->Reset();
+ if (bIsName)
+ t = pArr->GetNextReference();
+ else
+ t = pArr->GetNextReferenceOrName();
+ while( t )
+ {
+ if( t->GetOpCode() == ocName )
+ {
+ if (!bIsName)
+ {
+ ScRangeData* pName = pDoc->GetRangeName()->FindIndex(t->nIndex);
+ if (pName && pName->HasType(RT_SHAREDMOD))
+ pRangeData = pName;
+ }
+ }
+ else if( t->GetType() != svIndex ) // es kann ein DB-Bereich sein !!!
+ {
+ if ( !(bIsName && t->aRef.Ref1.IsTabRel()) )
+ { // Namen nur absolute anpassen
+ SingleRefData& rRef = t->aRef.Ref1;
+ if ( rRef.IsTabRel() )
+ nTab = rRef.nRelTab + nOldPosTab;
+ else
+ nTab = rRef.nTab;
+ if ( nTab == nOldTab )
+ rRef.nTab = nNewTab;
+ else if ( nStart <= nTab && nTab <= nEnd )
+ rRef.nTab = nTab + nDir;
+ rRef.nRelTab = rRef.nTab - nPosTab;
+ if( t->GetType() == svSingleRef )
+ {
+ t->aRef.Ref2.nTab = rRef.nTab;
+ t->aRef.Ref2.nRelTab = rRef.nRelTab;
+ }
+ }
+ else
+ bIsRel = TRUE;
+ if ( t->GetType() == svDoubleRef )
+ {
+ if ( !(bIsName && t->aRef.Ref2.IsTabRel()) )
+ { // Namen nur absolute anpassen
+ SingleRefData& rRef = t->aRef.Ref2;
+ if ( rRef.IsTabRel() )
+ nTab = rRef.nRelTab + nOldPosTab;
+ else
+ nTab = rRef.nTab;
+ if ( nTab == nOldTab )
+ rRef.nTab = nNewTab;
+ else if ( nStart <= nTab && nTab <= nEnd )
+ rRef.nTab = nTab + nDir;
+ rRef.nRelTab = rRef.nTab - nPosTab;
+ }
+ else
+ bIsRel = TRUE;
+ INT16 nTab1, nTab2;
+ if ( t->aRef.Ref1.IsTabRel() )
+ nTab1 = t->aRef.Ref1.nRelTab + nPosTab;
+ else
+ nTab1 = t->aRef.Ref1.nTab;
+ if ( t->aRef.Ref2.IsTabRel() )
+ nTab2 = t->aRef.Ref2.nRelTab + nPosTab;
+ else
+ nTab2 = t->aRef.Ref1.nTab;
+ if ( nTab2 < nTab1 )
+ { // PutInOrder
+ t->aRef.Ref1.nTab = nTab2;
+ t->aRef.Ref2.nTab = nTab1;
+ t->aRef.Ref1.nRelTab = t->aRef.Ref1.nTab - nPosTab;
+ t->aRef.Ref2.nRelTab = t->aRef.Ref2.nTab - nPosTab;
+ }
+ }
+ if ( bIsName && bIsRel )
+ pRangeData = (ScRangeData*) this; // wird in rangenam nicht dereferenziert
+ }
+ if (bIsName)
+ t = pArr->GetNextReference();
+ else
+ t = pArr->GetNextReferenceOrName();
+ }
+ if ( !bIsName )
+ {
+ short nMaxTabMod = (short) pDoc->GetTableCount();
+ pArr->Reset();
+ for ( t = pArr->GetNextReferenceRPN(); t;
+ t = pArr->GetNextReferenceRPN() )
+ {
+ if ( t->GetRef() == 1 )
+ {
+ SingleRefData& rRef = t->aRef.Ref1;
+ if ( rRef.IsRelName() && rRef.IsTabRel() )
+ { // RelName evtl. wrappen, wie lcl_MoveItWrap in refupdat.cxx
+ nTab = rRef.nRelTab + nPosTab;
+ if ( nTab < 0 )
+ nTab += nMaxTabMod;
+ else if ( nTab > nMaxTab )
+ nTab -= nMaxTabMod;
+ rRef.nRelTab = nTab - nPosTab;
+ }
+ else
+ {
+ if ( rRef.IsTabRel() )
+ nTab = rRef.nRelTab + nOldPosTab;
+ else
+ nTab = rRef.nTab;
+ if ( nTab == nOldTab )
+ rRef.nTab = nNewTab;
+ else if ( nStart <= nTab && nTab <= nEnd )
+ rRef.nTab = nTab + nDir;
+ rRef.nRelTab = rRef.nTab - nPosTab;
+ }
+ if( t->GetType() == svSingleRef )
+ {
+ t->aRef.Ref2.nTab = rRef.nTab;
+ t->aRef.Ref2.nRelTab = rRef.nRelTab;
+ }
+ else // svDoubleRef
+ {
+ SingleRefData& rRef = t->aRef.Ref2;
+ if ( rRef.IsRelName() && rRef.IsTabRel() )
+ { // RelName evtl. wrappen, wie lcl_MoveItWrap in refupdat.cxx
+ nTab = rRef.nRelTab + nPosTab;
+ if ( nTab < 0 )
+ nTab += nMaxTabMod;
+ else if ( nTab > nMaxTab )
+ nTab -= nMaxTabMod;
+ rRef.nRelTab = nTab - nPosTab;
+ }
+ else
+ {
+ if ( rRef.IsTabRel() )
+ nTab = rRef.nRelTab + nOldPosTab;
+ else
+ nTab = rRef.nTab;
+ if ( nTab == nOldTab )
+ rRef.nTab = nNewTab;
+ else if ( nStart <= nTab && nTab <= nEnd )
+ rRef.nTab = nTab + nDir;
+ rRef.nRelTab = rRef.nTab - nPosTab;
+ }
+ INT16 nTab1, nTab2;
+ if ( t->aRef.Ref1.IsTabRel() )
+ nTab1 = t->aRef.Ref1.nRelTab + nPosTab;
+ else
+ nTab1 = t->aRef.Ref1.nTab;
+ if ( t->aRef.Ref2.IsTabRel() )
+ nTab2 = t->aRef.Ref2.nRelTab + nPosTab;
+ else
+ nTab2 = t->aRef.Ref1.nTab;
+ if ( nTab2 < nTab1 )
+ { // PutInOrder
+ t->aRef.Ref1.nTab = nTab2;
+ t->aRef.Ref2.nTab = nTab1;
+ t->aRef.Ref1.nRelTab = t->aRef.Ref1.nTab - nPosTab;
+ t->aRef.Ref2.nRelTab = t->aRef.Ref2.nTab - nPosTab;
+ }
+ }
+ }
+ }
+ }
+ return pRangeData;
+}
+
+
+ScToken* ScCompiler::CreateStringFromToken( String& rFormula, ScToken* pToken,
+ BOOL bAllowArrAdvance )
+{
+ BOOL bNext = TRUE;
+ BOOL bSpaces = FALSE;
+ ScToken* t = pToken;
+ OpCode eOp = t->GetOpCode();
+ if( eOp >= ocAnd && eOp <= ocOr )
+ {
+ // AND, OR infix?
+ if ( bAllowArrAdvance )
+ t = pArr->Next();
+ else
+ t = pArr->PeekNext();
+ bNext = FALSE;
+ bSpaces = ( !t || t->GetOpCode() != ocOpen );
+ }
+ if( bSpaces )
+ rFormula += ' ';
+
+ if( eOp == ocSpaces )
+ rFormula.Expand( rFormula.Len() + t->cByte );
+ else if( eOp >= ocInternalBegin && eOp <= ocInternalEnd )
+ rFormula.AppendAscii( pInternal[ eOp - ocInternalBegin ] );
+ else if( (USHORT) eOp < nAnzStrings) // Keyword:
+ rFormula += pSymbolTable[eOp];
+ else
+ {
+ DBG_ERROR("Unbekannter OpCode");
+ rFormula += ScGlobal::GetRscString(STR_NO_NAME_REF);
+ }
+ if( bNext ) switch( t->GetType() )
+ {
+ case svDouble:
+ {
+ String aStr;
+ ULONG nIndex = ( pSymbolTable == pSymbolTableEnglish ?
+ pDoc->GetFormatTable()->GetStandardIndex( LANGUAGE_ENGLISH_US ) : 0 );
+ pDoc->GetFormatTable()->
+ GetInputLineString(t->nValue,nIndex,aStr);
+ rFormula += aStr;
+ }
+ break;
+ case svString:
+ if( eOp == ocBad )
+ rFormula += t->cStr;
+ else
+ {
+ if (bImportXML)
+ rFormula += t->cStr;
+ else
+ {
+ rFormula += '"';
+ if ( ScGlobal::UnicodeStrChr( t->cStr, '"' ) == NULL )
+ rFormula += t->cStr;
+ else
+ {
+ String aStr( t->cStr );
+ xub_StrLen nPos = 0;
+ while ( (nPos = aStr.Search( '"', nPos)) != STRING_NOTFOUND )
+ {
+ aStr.Insert( '"', nPos );
+ nPos += 2;
+ }
+ rFormula += aStr;
+ }
+ rFormula += '"';
+ }
+ }
+ break;
+ case svSingleRef:
+ if ( eOp == ocColRowName )
+ { // hier kein t->GetReference() weil nicht ocPush oder ocColRowNameAuto
+ SingleRefData& rRef = t->aRef.Ref1;
+ rRef.CalcAbsIfRel( aPos );
+ if ( pDoc->HasStringData( rRef.nCol, rRef.nRow, rRef.nTab ) )
+ {
+ String aStr;
+ pDoc->GetString( rRef.nCol, rRef.nRow, rRef.nTab, aStr );
+ EnQuote( aStr );
+ rFormula += aStr;
+ }
+ else
+ {
+ rFormula += ScGlobal::GetRscString(STR_NO_NAME_REF);
+ rFormula += MakeRefStr( t->aRef, TRUE );
+ }
+ }
+ else
+ {
+ rFormula += MakeRefStr( t->GetReference(), TRUE );
+ }
+ break;
+ case svDoubleRef:
+ rFormula += MakeRefStr( t->GetReference(), FALSE );
+ break;
+ case svIndex:
+ {
+ String aStr;
+ switch ( eOp )
+ {
+ case ocName:
+ {
+ ScRangeData* pData = pDoc->GetRangeName()->FindIndex(t->nIndex);
+ if (pData)
+ {
+ if (pData->HasType(RT_SHARED))
+ pData->UpdateSymbol( aStr, aPos );
+ else
+ pData->GetName(aStr);
+ }
+ }
+ break;
+ case ocDBArea:
+ {
+ ScDBData* pDBData = pDoc->GetDBCollection()->FindIndex(t->nIndex);
+ if (pDBData)
+ pDBData->GetName(aStr);
+ }
+ break;
+ }
+ if ( !aStr.Len() )
+ rFormula += ScGlobal::GetRscString(STR_NO_NAME_REF);
+ else
+ rFormula += aStr;
+ break;
+ }
+ case svExternal:
+ // Byte 0 ist Parameter-Count!!
+ {
+ // show translated name of StarOne AddIns
+ String aAddIn( t->cStr+1 );
+ if ( pSymbolTable != pSymbolTableEnglish )
+ ScGlobal::GetAddInCollection()->LocalizeString( aAddIn );
+ rFormula += aAddIn;
+ }
+ break;
+ case svByte:
+ case svJump:
+ case svMissing:
+ break; // Opcodes
+ default:
+ DBG_ERROR("ScCompiler:: GetStringFromToken errUnknownVariable");
+ } // of switch
+ if( bSpaces )
+ rFormula += ' ';
+ if ( bAllowArrAdvance )
+ {
+ if( bNext )
+ t = pArr->Next();
+ return t;
+ }
+ return pToken;
+}
+
+
+void ScCompiler::CreateStringFromTokenArray( String& rFormula )
+{
+ rFormula.Erase();
+ if( !pArr->GetLen() )
+ return;
+ if ( pArr->IsRecalcModeForced() )
+ rFormula += '=';
+ ScToken* t = pArr->First();
+ while( t )
+ t = CreateStringFromToken( rFormula, t, TRUE );
+}
+
+
+BOOL ScCompiler::EnQuote( String& rStr )
+{
+ sal_Int32 nType = ScGlobal::pCharClass->getStringType( rStr, 0, rStr.Len() );
+ if ( !CharClass::isNumericType( nType )
+ && CharClass::isAlphaNumericType( nType ) )
+ return FALSE;
+ xub_StrLen nPos = 0;
+ while ( (nPos = rStr.Search( '\'', nPos)) != STRING_NOTFOUND )
+ {
+ rStr.Insert( '\\', nPos );
+ nPos += 2;
+ }
+ rStr.Insert( '\'', 0 );
+ rStr += '\'';
+ return TRUE;
+}
+
+
+BOOL ScCompiler::DeQuote( String& rStr )
+{
+ xub_StrLen nLen = rStr.Len();
+ if ( nLen > 1 && rStr.GetChar(0) == '\'' && rStr.GetChar( nLen-1 ) == '\'' )
+ {
+ rStr.Erase( nLen-1, 1 );
+ rStr.Erase( 0, 1 );
+ xub_StrLen nPos = 0;
+ while ( (nPos = rStr.SearchAscii( "\\\'", nPos)) != STRING_NOTFOUND )
+ {
+ rStr.Erase( nPos, 1 );
+ ++nPos;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
diff --git a/sc/source/core/tool/consoli.cxx b/sc/source/core/tool/consoli.cxx
new file mode 100644
index 000000000000..fffea8773a8a
--- /dev/null
+++ b/sc/source/core/tool/consoli.cxx
@@ -0,0 +1,886 @@
+/*************************************************************************
+ *
+ * $RCSfile: consoli.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <tools/debug.hxx>
+#include <math.h>
+#include <string.h>
+#include "consoli.hxx"
+#include "document.hxx"
+#include "olinetab.hxx"
+#include "globstr.hrc"
+#include "subtotal.hxx"
+#include "compiler.hxx" // fuer errNoValue
+#include "cell.hxx"
+
+#define SC_CONS_NOTFOUND 0xFFFF
+
+// STATIC DATA -----------------------------------------------------------
+
+/* Strings bei Gelegenheit ganz raus...
+static USHORT nFuncRes[] = { // Reihenfolge wie bei enum ScSubTotalFunc
+ 0, // none
+ STR_PIVOTFUNC_AVG,
+ STR_PIVOTFUNC_COUNT,
+ STR_PIVOTFUNC_COUNT2,
+ STR_PIVOTFUNC_MAX,
+ STR_PIVOTFUNC_MIN,
+ STR_PIVOTFUNC_PROD,
+ STR_PIVOTFUNC_STDDEV,
+ STR_PIVOTFUNC_STDDEV2,
+ STR_PIVOTFUNC_SUM,
+ STR_PIVOTFUNC_VAR,
+ STR_PIVOTFUNC_VAR2 };
+*/
+
+static OpCode eOpCodeTable[] = { // Reihenfolge wie bei enum ScSubTotalFunc
+ ocBad, // none
+ ocAverage,
+ ocCount,
+ ocCount2,
+ ocMax,
+ ocMin,
+ ocProduct,
+ ocStDev,
+ ocStDevP,
+ ocSum,
+ ocVar,
+ ocVarP };
+
+// -----------------------------------------------------------------------
+
+void ScReferenceList::AddEntry( USHORT nCol, USHORT nRow, USHORT nTab )
+{
+ ScReferenceEntry* pOldData = pData;
+ pData = new ScReferenceEntry[ nFullSize+1 ];
+ if (pOldData)
+ {
+ memmove( pData, pOldData, nCount * sizeof(ScReferenceEntry) );
+ delete[] pOldData;
+ }
+ while (nCount < nFullSize)
+ {
+ pData[nCount].nCol = SC_CONS_NOTFOUND;
+ pData[nCount].nRow = SC_CONS_NOTFOUND;
+ pData[nCount].nTab = SC_CONS_NOTFOUND;
+ ++nCount;
+ }
+ pData[nCount].nCol = nCol;
+ pData[nCount].nRow = nRow;
+ pData[nCount].nTab = nTab;
+ ++nCount;
+ nFullSize = nCount;
+}
+
+void lcl_AddString( String**& pData, USHORT& nCount, const String& rInsert )
+{
+ String** pOldData = pData;
+ pData = new String*[ nCount+1 ];
+ if (pOldData)
+ {
+ memmove( pData, pOldData, nCount * sizeof(String*) );
+ delete[] pOldData;
+ }
+ pData[nCount] = new String(rInsert);
+ ++nCount;
+}
+
+// -----------------------------------------------------------------------
+
+ScConsData::ScConsData() :
+ eFunction(SUBTOTAL_FUNC_SUM),
+ bReference(FALSE),
+ bColByName(FALSE),
+ bRowByName(FALSE),
+ bSubTitles(FALSE),
+ nColCount(0),
+ ppColHeaders(NULL),
+ nRowCount(0),
+ ppRowHeaders(NULL),
+ ppCount(NULL),
+ ppSum(NULL),
+ ppSumSqr(NULL),
+ ppRefs(NULL),
+ ppUsed(NULL),
+ nDataCount(0),
+ nTitleCount(0),
+ ppTitles(NULL),
+ ppTitlePos(NULL),
+ bCornerUsed(FALSE)
+{
+}
+
+ScConsData::~ScConsData()
+{
+ DeleteData();
+}
+
+
+#define DELETEARR(ppArray,nCount) \
+{ \
+ USHORT i; \
+ if (ppArray) \
+ for(i=0; i<nCount; i++) \
+ delete[] ppArray[i]; \
+ delete[] ppArray; \
+ ppArray = NULL; \
+}
+
+#define DELETESTR(ppArray,nCount) \
+{ \
+ USHORT i; \
+ if (ppArray) \
+ for(i=0; i<nCount; i++) \
+ delete ppArray[i]; \
+ delete[] ppArray; \
+ ppArray = NULL; \
+}
+
+void ScConsData::DeleteData()
+{
+ USHORT i;
+
+ if (ppRefs)
+ for (i=0; i<nColCount; i++)
+ {
+ for (USHORT j=0; j<nRowCount; j++)
+ if (ppUsed[i][j])
+ ppRefs[i][j].Clear();
+ delete[] ppRefs[i];
+ }
+ delete[] ppRefs;
+ ppRefs = NULL;
+
+// DELETEARR( ppData1, nColCount );
+// DELETEARR( ppData2, nColCount );
+ DELETEARR( ppCount, nColCount );
+ DELETEARR( ppSum, nColCount );
+ DELETEARR( ppSumSqr,nColCount );
+ DELETEARR( ppUsed, nColCount ); // erst nach ppRefs !!!
+ DELETEARR( ppTitlePos, nRowCount );
+ DELETESTR( ppColHeaders, nColCount );
+ DELETESTR( ppRowHeaders, nRowCount );
+ DELETESTR( ppTitles, nTitleCount );
+ nTitleCount = 0;
+ nDataCount = 0;
+
+ if (bColByName) nColCount = 0; // sonst stimmt ppColHeaders nicht
+ if (bRowByName) nRowCount = 0;
+
+ bCornerUsed = FALSE;
+ aCornerText.Erase();
+}
+
+#undef DELETEARR
+#undef DELETESTR
+
+void ScConsData::InitData( BOOL bDelete )
+{
+ USHORT i;
+ if (bDelete)
+ DeleteData();
+
+ if (bReference && nColCount && !ppRefs)
+ {
+ ppRefs = new ScReferenceList*[nColCount];
+ for (i=0; i<nColCount; i++)
+ ppRefs[i] = new ScReferenceList[nRowCount];
+ }
+ else if (nColCount && !ppCount)
+ {
+ ppCount = new double*[nColCount];
+ ppSum = new double*[nColCount];
+ ppSumSqr = new double*[nColCount];
+ for (i=0; i<nColCount; i++)
+ {
+ ppCount[i] = new double[nRowCount];
+ ppSum[i] = new double[nRowCount];
+ ppSumSqr[i] = new double[nRowCount];
+ }
+ }
+
+ if (nColCount && !ppUsed)
+ {
+ ppUsed = new BOOL*[nColCount];
+ for (i=0; i<nColCount; i++)
+ {
+ ppUsed[i] = new BOOL[nRowCount];
+ memset( ppUsed[i], 0, nRowCount * sizeof(BOOL) );
+ }
+ }
+
+ if (nRowCount && nDataCount && !ppTitlePos)
+ {
+ ppTitlePos = new USHORT*[nRowCount];
+ for (i=0; i<nRowCount; i++)
+ {
+ ppTitlePos[i] = new USHORT[nDataCount];
+ memset( ppTitlePos[i], 0, nDataCount * sizeof(USHORT) ); //! unnoetig ?
+ }
+ }
+
+ // CornerText: einzelner String
+}
+
+void ScConsData::DoneFields()
+{
+ InitData(FALSE);
+}
+
+void ScConsData::SetSize( USHORT nCols, USHORT nRows )
+{
+ DeleteData();
+ nColCount = nCols;
+ nRowCount = nRows;
+}
+
+void ScConsData::GetSize( USHORT& rCols, USHORT& rRows ) const
+{
+ rCols = nColCount;
+ rRows = nRowCount;
+}
+
+void ScConsData::SetFlags( ScSubTotalFunc eFunc, BOOL bColName, BOOL bRowName, BOOL bRef )
+{
+ DeleteData();
+ bReference = bRef;
+ bColByName = bColName;
+ if (bColName) nColCount = 0;
+ bRowByName = bRowName;
+ if (bRowName) nRowCount = 0;
+ eFunction = eFunc;
+}
+
+void ScConsData::AddFields( ScDocument* pSrcDoc, USHORT nTab,
+ USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2 )
+{
+ ++nDataCount;
+
+ String aTitle;
+
+ USHORT nStartCol = nCol1;
+ USHORT nStartRow = nRow1;
+ if (bColByName) ++nStartRow;
+ if (bRowByName) ++nStartCol;
+
+ if (bColByName)
+ {
+ for (USHORT nCol=nStartCol; nCol<=nCol2; nCol++)
+ {
+ pSrcDoc->GetString( nCol, nRow1, nTab, aTitle );
+ if (aTitle.Len())
+ {
+ BOOL bFound = FALSE;
+ for (USHORT i=0; i<nColCount && !bFound; i++)
+ if ( *ppColHeaders[i] == aTitle )
+ bFound = TRUE;
+ if (!bFound)
+ lcl_AddString( ppColHeaders, nColCount, aTitle );
+ }
+ }
+ }
+
+ if (bRowByName)
+ {
+ for (USHORT nRow=nStartRow; nRow<=nRow2; nRow++)
+ {
+ pSrcDoc->GetString( nCol1, nRow, nTab, aTitle );
+ if (aTitle.Len())
+ {
+ BOOL bFound = FALSE;
+ for (USHORT i=0; i<nRowCount && !bFound; i++)
+ if ( *ppRowHeaders[i] == aTitle )
+ bFound = TRUE;
+ if (!bFound)
+ lcl_AddString( ppRowHeaders, nRowCount, aTitle );
+ }
+ }
+ }
+}
+
+void ScConsData::AddName( const String& rName )
+{
+ USHORT nArrX;
+ USHORT nArrY;
+
+ if (bReference)
+ {
+ lcl_AddString( ppTitles, nTitleCount, rName );
+
+ for (nArrY=0; nArrY<nRowCount; nArrY++)
+ {
+ // Daten auf gleiche Laenge bringen
+
+ USHORT nMax = 0;
+ for (nArrX=0; nArrX<nColCount; nArrX++)
+ if (ppUsed[nArrX][nArrY])
+ nMax = Max( nMax, ppRefs[nArrX][nArrY].GetCount() );
+
+ for (nArrX=0; nArrX<nColCount; nArrX++)
+ {
+ if (!ppUsed[nArrX][nArrY])
+ {
+ ppUsed[nArrX][nArrY] = TRUE;
+ ppRefs[nArrX][nArrY].Init();
+ }
+ ppRefs[nArrX][nArrY].SetFullSize(nMax);
+ }
+
+ // Positionen eintragen
+
+ if (ppTitlePos)
+ if (nTitleCount < nDataCount)
+ ppTitlePos[nArrY][nTitleCount] = nMax;
+ }
+ }
+}
+
+ // rCount < 0 <=> Fehler aufgetreten
+
+void lcl_UpdateArray( ScSubTotalFunc eFunc,
+ double& rCount, double& rSum, double& rSumSqr, double nVal )
+{
+ if (rCount < 0.0)
+ return;
+ switch (eFunc)
+ {
+ case SUBTOTAL_FUNC_SUM:
+ if (!SubTotal::SafePlus(rSum, nVal))
+ rCount = -MAXDOUBLE;
+ break;
+ case SUBTOTAL_FUNC_PROD:
+ if (!SubTotal::SafeMult(rSum, nVal))
+ rCount = -MAXDOUBLE;
+ break;
+ case SUBTOTAL_FUNC_CNT:
+ case SUBTOTAL_FUNC_CNT2:
+ rCount += 1.0;
+ break;
+ case SUBTOTAL_FUNC_AVE:
+ if (!SubTotal::SafePlus(rSum, nVal))
+ rCount = -MAXDOUBLE;
+ else
+ rCount += 1.0;
+ break;
+ case SUBTOTAL_FUNC_MAX:
+ if (nVal > rSum)
+ rSum = nVal;
+ break;
+ case SUBTOTAL_FUNC_MIN:
+ if (nVal < rSum)
+ rSum = nVal;
+ break;
+ case SUBTOTAL_FUNC_STD:
+ case SUBTOTAL_FUNC_STDP:
+ case SUBTOTAL_FUNC_VAR:
+ case SUBTOTAL_FUNC_VARP:
+ {
+ BOOL bOk = SubTotal::SafePlus(rSum, nVal);
+ bOk = bOk && SubTotal::SafeMult(nVal, nVal);
+ bOk = bOk && SubTotal::SafePlus(rSumSqr, nVal);
+ if (!bOk)
+ rCount = -MAXDOUBLE;
+ else
+ rCount += 1.0;
+ break;
+ }
+ }
+}
+
+void lcl_InitArray( ScSubTotalFunc eFunc,
+ double& rCount, double& rSum, double& rSumSqr, double nVal )
+{
+ rCount = 1.0;
+ switch (eFunc)
+ {
+ case SUBTOTAL_FUNC_SUM:
+ case SUBTOTAL_FUNC_MAX:
+ case SUBTOTAL_FUNC_MIN:
+ case SUBTOTAL_FUNC_PROD:
+ case SUBTOTAL_FUNC_AVE:
+ rSum = nVal;
+ break;
+ case SUBTOTAL_FUNC_STD:
+ case SUBTOTAL_FUNC_STDP:
+ case SUBTOTAL_FUNC_VAR:
+ case SUBTOTAL_FUNC_VARP:
+ {
+ rSum = nVal;
+ BOOL bOk = SubTotal::SafeMult(nVal, nVal);
+ if (bOk)
+ rSumSqr = nVal;
+ else
+ rCount = -MAXDOUBLE;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+double lcl_CalcData( ScSubTotalFunc eFunc,
+ double fCount, double fSum, double fSumSqr)
+{
+ if (fCount < 0.0)
+ return 0.0;
+ double fVal = 0.0;
+ switch (eFunc)
+ {
+ case SUBTOTAL_FUNC_CNT:
+ case SUBTOTAL_FUNC_CNT2:
+ fVal = fCount;
+ break;
+ case SUBTOTAL_FUNC_SUM:
+ case SUBTOTAL_FUNC_MAX:
+ case SUBTOTAL_FUNC_MIN:
+ case SUBTOTAL_FUNC_PROD:
+ fVal = fSum;
+ break;
+ case SUBTOTAL_FUNC_AVE:
+ if (fCount > 0.0)
+ fVal = fSum / fCount;
+ else
+ fCount = -MAXDOUBLE;
+ break;
+ case SUBTOTAL_FUNC_STD:
+ {
+ if (fCount > 1 && SubTotal::SafeMult(fSum, fSum))
+ fVal = sqrt((fSumSqr - fSum/fCount)/(fCount-1.0));
+ else
+ fCount = -MAXDOUBLE;
+ }
+ break;
+ case SUBTOTAL_FUNC_STDP:
+ {
+ if (fCount > 0 && SubTotal::SafeMult(fSum, fSum))
+ fVal = sqrt((fSumSqr - fSum/fCount)/fCount);
+ else
+ fCount = -MAXDOUBLE;
+ }
+ break;
+ case SUBTOTAL_FUNC_VAR:
+ {
+ if (fCount > 1 && SubTotal::SafeMult(fSum, fSum))
+ fVal = (fSumSqr - fSum/fCount)/(fCount-1.0);
+ else
+ fCount = -MAXDOUBLE;
+ }
+ break;
+ case SUBTOTAL_FUNC_VARP:
+ {
+ if (fCount > 0 && SubTotal::SafeMult(fSum, fSum))
+ fVal = (fSumSqr - fSum/fCount)/fCount;
+ else
+ fCount = -MAXDOUBLE;
+ }
+ break;
+ default:
+ {
+ DBG_ERROR("unbekannte Funktion bei Consoli::CalcData");
+ fCount = -MAXDOUBLE;
+ }
+ break;
+ }
+ return fVal;
+}
+
+void ScConsData::AddData( ScDocument* pSrcDoc, USHORT nTab,
+ USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2 )
+{
+ PutInOrder(nCol1,nCol2);
+ PutInOrder(nRow1,nRow2);
+ if ( nCol2 >= nCol1 + nColCount && !bColByName )
+ {
+ DBG_ASSERT(0,"Bereich zu gross");
+ nCol2 = nCol1 + nColCount - 1;
+ }
+ if ( nRow2 >= nRow1 + nRowCount && !bRowByName )
+ {
+ DBG_ASSERT(0,"Bereich zu gross");
+ nRow2 = nRow1 + nRowCount - 1;
+ }
+
+ USHORT nCol;
+ USHORT nRow;
+
+ // Ecke links oben
+
+ if ( bColByName && bRowByName )
+ {
+ String aThisCorner;
+ pSrcDoc->GetString(nCol1,nRow1,nTab,aThisCorner);
+ if (bCornerUsed)
+ {
+ if (aCornerText != aThisCorner)
+ aCornerText.Erase();
+ }
+ else
+ {
+ aCornerText = aThisCorner;
+ bCornerUsed = TRUE;
+ }
+ }
+
+ // Titel suchen
+
+ USHORT nStartCol = nCol1;
+ USHORT nStartRow = nRow1;
+ if (bColByName) ++nStartRow;
+ if (bRowByName) ++nStartCol;
+ String aTitle;
+ USHORT* pDestCols = NULL;
+ USHORT* pDestRows = NULL;
+ if (bColByName)
+ {
+ pDestCols = new USHORT[nCol2-nStartCol+1];
+ for (nCol=nStartCol; nCol<=nCol2; nCol++)
+ {
+ pSrcDoc->GetString(nCol,nRow1,nTab,aTitle);
+ USHORT nPos = SC_CONS_NOTFOUND;
+ if (aTitle.Len())
+ {
+ BOOL bFound = FALSE;
+ for (USHORT i=0; i<nColCount && !bFound; i++)
+ if ( *ppColHeaders[i] == aTitle )
+ {
+ nPos = i;
+ bFound = TRUE;
+ }
+ DBG_ASSERT(bFound, "Spalte nicht gefunden");
+ }
+ pDestCols[nCol-nStartCol] = nPos;
+ }
+ }
+ if (bRowByName)
+ {
+ pDestRows = new USHORT[nRow2-nStartRow+1];
+ for (nRow=nStartRow; nRow<=nRow2; nRow++)
+ {
+ pSrcDoc->GetString(nCol1,nRow,nTab,aTitle);
+ USHORT nPos = SC_CONS_NOTFOUND;
+ if (aTitle.Len())
+ {
+ BOOL bFound = FALSE;
+ for (USHORT i=0; i<nRowCount && !bFound; i++)
+ if ( *ppRowHeaders[i] == aTitle )
+ {
+ nPos = i;
+ bFound = TRUE;
+ }
+ DBG_ASSERT(bFound, "Zeile nicht gefunden");
+ }
+ pDestRows[nRow-nStartRow] = nPos;
+ }
+ }
+ nCol1 = nStartCol;
+ nRow1 = nStartRow;
+
+ // Daten
+
+ BOOL bAnyCell = ( eFunction == SUBTOTAL_FUNC_CNT2 );
+ for (nCol=nCol1; nCol<=nCol2; nCol++)
+ {
+ USHORT nArrX = nCol-nCol1;
+ if (bColByName) nArrX = pDestCols[nArrX];
+ if (nArrX != SC_CONS_NOTFOUND)
+ {
+ for (nRow=nRow1; nRow<=nRow2; nRow++)
+ {
+ USHORT nArrY = nRow-nRow1;
+ if (bRowByName) nArrY = pDestRows[nArrY];
+ if ( nArrY != SC_CONS_NOTFOUND && (
+ bAnyCell ? pSrcDoc->HasData( nCol, nRow, nTab )
+ : pSrcDoc->HasValueData( nCol, nRow, nTab ) ) )
+ {
+ if (bReference)
+ {
+ if (ppUsed[nArrX][nArrY])
+ ppRefs[nArrX][nArrY].AddEntry( nCol, nRow, nTab );
+ else
+ {
+ ppUsed[nArrX][nArrY] = TRUE;
+ ppRefs[nArrX][nArrY].Init();
+ ppRefs[nArrX][nArrY].AddEntry( nCol, nRow, nTab );
+ }
+ }
+ else
+ {
+ double nVal;
+ pSrcDoc->GetValue( nCol, nRow, nTab, nVal );
+ if (ppUsed[nArrX][nArrY])
+ lcl_UpdateArray( eFunction, ppCount[nArrX][nArrY],
+ ppSum[nArrX][nArrY], ppSumSqr[nArrX][nArrY],
+ nVal);
+ else
+ {
+ ppUsed[nArrX][nArrY] = TRUE;
+ lcl_InitArray( eFunction, ppCount[nArrX][nArrY],
+ ppSum[nArrX][nArrY],
+ ppSumSqr[nArrX][nArrY], nVal );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ delete[] pDestCols;
+ delete[] pDestRows;
+}
+
+// vorher testen, wieviele Zeilen eingefuegt werden (fuer Undo)
+
+USHORT ScConsData::GetInsertCount() const
+{
+ USHORT nInsert = 0;
+ USHORT nArrX;
+ USHORT nArrY;
+ if ( ppRefs && ppUsed )
+ {
+ for (nArrY=0; nArrY<nRowCount; nArrY++)
+ {
+ USHORT nNeeded = 0;
+ for (nArrX=0; nArrX<nColCount; nArrX++)
+ if (ppUsed[nArrX][nArrY])
+ nNeeded = Max( nNeeded, ppRefs[nArrX][nArrY].GetCount() );
+
+ nInsert += nNeeded;
+ }
+ }
+ return nInsert;
+}
+
+// fertige Daten ins Dokument schreiben
+//! optimieren nach Spalten?
+
+void ScConsData::OutputToDocument( ScDocument* pDestDoc, USHORT nCol, USHORT nRow, USHORT nTab )
+{
+ OpCode eOpCode = eOpCodeTable[eFunction];
+
+ USHORT nArrX;
+ USHORT nArrY;
+ USHORT nCount;
+ USHORT nPos;
+ USHORT i;
+
+ // Ecke links oben
+
+ if ( bColByName && bRowByName && aCornerText.Len() )
+ pDestDoc->SetString( nCol, nRow, nTab, aCornerText );
+
+ // Titel
+
+ USHORT nStartCol = nCol;
+ USHORT nStartRow = nRow;
+ if (bColByName) ++nStartRow;
+ if (bRowByName) ++nStartCol;
+
+ if (bColByName)
+ for (i=0; i<nColCount; i++)
+ pDestDoc->SetString( nStartCol+i, nRow, nTab, *ppColHeaders[i] );
+ if (bRowByName)
+ for (i=0; i<nRowCount; i++)
+ pDestDoc->SetString( nCol, nStartRow+i, nTab, *ppRowHeaders[i] );
+
+ nCol = nStartCol;
+ nRow = nStartRow;
+
+ // Daten
+
+ if ( ppCount && ppUsed ) // Werte direkt einfuegen
+ {
+ for (nArrX=0; nArrX<nColCount; nArrX++)
+ for (nArrY=0; nArrY<nRowCount; nArrY++)
+ if (ppUsed[nArrX][nArrY])
+ {
+ double fVal = lcl_CalcData( eFunction, ppCount[nArrX][nArrY],
+ ppSum[nArrX][nArrY],
+ ppSumSqr[nArrX][nArrY]);
+ if (ppCount[nArrX][nArrY] < 0.0)
+ pDestDoc->SetError( nCol+nArrX, nRow+nArrY, nTab, errNoValue );
+ else
+ pDestDoc->SetValue( nCol+nArrX, nRow+nArrY, nTab, fVal );
+ }
+ }
+
+ if ( ppRefs && ppUsed ) // Referenzen einfuegen
+ {
+ //! unterscheiden, ob nach Kategorien aufgeteilt
+ String aString;
+
+ SingleRefData aSRef; // Daten fuer Referenz-Formelzellen
+ aSRef.InitFlags();
+ aSRef.SetFlag3D(TRUE);
+
+ ComplRefData aCRef; // Daten fuer Summen-Zellen
+ aCRef.InitFlags();
+ aCRef.Ref1.SetColRel(TRUE); aCRef.Ref1.SetRowRel(TRUE); aCRef.Ref1.SetTabRel(TRUE);
+ aCRef.Ref2.SetColRel(TRUE); aCRef.Ref2.SetRowRel(TRUE); aCRef.Ref2.SetTabRel(TRUE);
+
+ for (nArrY=0; nArrY<nRowCount; nArrY++)
+ {
+ USHORT nNeeded = 0;
+ for (nArrX=0; nArrX<nColCount; nArrX++)
+ if (ppUsed[nArrX][nArrY])
+ nNeeded = Max( nNeeded, ppRefs[nArrX][nArrY].GetCount() );
+
+ if (nNeeded)
+ {
+ pDestDoc->InsertRow( 0,nTab, MAXCOL,nTab, nRow+nArrY, nNeeded );
+
+ for (nArrX=0; nArrX<nColCount; nArrX++)
+ if (ppUsed[nArrX][nArrY])
+ {
+ ScReferenceList& rList = ppRefs[nArrX][nArrY];
+ nCount = rList.GetCount();
+ if (nCount)
+ {
+ for (nPos=0; nPos<nCount; nPos++)
+ {
+ ScReferenceEntry aRef = rList.GetEntry(nPos);
+ if (aRef.nTab != SC_CONS_NOTFOUND)
+ {
+ // Referenz einfuegen (absolut, 3d)
+
+ aSRef.nCol = aRef.nCol;
+ aSRef.nRow = aRef.nRow;
+ aSRef.nTab = aRef.nTab;
+
+ ScTokenArray aRefArr;
+ aRefArr.AddSingleReference(aSRef);
+ aRefArr.AddOpCode(ocStop);
+ ScAddress aDest( nCol+nArrX, nRow+nArrY+nPos, nTab );
+ ScBaseCell* pCell = new ScFormulaCell( pDestDoc, aDest, &aRefArr );
+ pDestDoc->PutCell( aDest.Col(), aDest.Row(), aDest.Tab(), pCell );
+ }
+ }
+
+ // Summe einfuegen (relativ, nicht 3d)
+
+ ScAddress aDest( nCol+nArrX, nRow+nArrY+nNeeded, nTab );
+
+ aCRef.Ref1.nTab = aCRef.Ref2.nTab = nTab;
+ aCRef.Ref1.nCol = aCRef.Ref2.nCol = nCol+nArrX;
+ aCRef.Ref1.nRow = nRow+nArrY;
+ aCRef.Ref2.nRow = nRow+nArrY+nNeeded-1;
+ aCRef.CalcRelFromAbs( aDest );
+
+ ScTokenArray aArr;
+ aArr.AddOpCode(eOpCode); // ausgewaehlte Funktion
+ aArr.AddOpCode(ocOpen);
+ aArr.AddDoubleReference(aCRef);
+ aArr.AddOpCode(ocClose);
+ aArr.AddOpCode(ocStop);
+ ScBaseCell* pCell = new ScFormulaCell( pDestDoc, aDest, &aArr );
+ pDestDoc->PutCell( aDest.Col(), aDest.Row(), aDest.Tab(), pCell );
+ }
+ }
+
+ // Gliederung einfuegen
+
+ ScOutlineArray* pOutArr = pDestDoc->GetOutlineTable( nTab, TRUE )->GetRowArray();
+ USHORT nOutStart = nRow+nArrY;
+ USHORT nOutEnd = nRow+nArrY+nNeeded-1;
+ BOOL bSize = FALSE;
+ pOutArr->Insert( nOutStart, nOutEnd, bSize );
+ for (USHORT nOutRow=nOutStart; nOutRow<=nOutEnd; nOutRow++)
+ pDestDoc->ShowRow( nOutRow, nTab, FALSE );
+ pDestDoc->UpdateOutlineRow( nOutStart, nOutEnd, nTab, FALSE );
+
+ // Zwischentitel
+
+ if (ppTitlePos && ppTitles && ppRowHeaders)
+ {
+ String aDelim( RTL_CONSTASCII_USTRINGPARAM(" / ") );
+ for (nPos=0; nPos<nDataCount; nPos++)
+ {
+ USHORT nTPos = ppTitlePos[nArrY][nPos];
+ BOOL bDo = TRUE;
+ if (nPos+1<nDataCount)
+ if (ppTitlePos[nArrY][nPos+1] == nTPos)
+ bDo = FALSE; // leer
+ if ( bDo && nTPos < nNeeded )
+ {
+ aString = *ppRowHeaders[nArrY];
+ aString += aDelim;
+ aString += *ppTitles[nPos];
+ pDestDoc->SetString( nCol-1, nRow+nArrY+nTPos, nTab, aString );
+ }
+ }
+ }
+
+ nRow += nNeeded;
+ }
+ }
+ }
+}
+
+
+
+
+
diff --git a/sc/source/core/tool/dbcolect.cxx b/sc/source/core/tool/dbcolect.cxx
new file mode 100644
index 000000000000..513a4f59c015
--- /dev/null
+++ b/sc/source/core/tool/dbcolect.cxx
@@ -0,0 +1,1223 @@
+/*************************************************************************
+ *
+ * $RCSfile: dbcolect.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include <tools/debug.hxx>
+#include <tools/intn.hxx>
+#include <sdb/sdbstat.hxx> // enum DBObject
+
+#include "dbcolect.hxx"
+#include "global.hxx"
+#include "refupdat.hxx"
+#include "rechead.hxx"
+#include "document.hxx"
+#include "globstr.hrc"
+
+
+//---------------------------------------------------------------------------------------
+
+ScDBData::ScDBData( const String& rName,
+ USHORT nTab,
+ USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2,
+ BOOL bByR, BOOL bHasH) :
+ aName (rName),
+ nTable (nTab),
+ nStartCol (nCol1),
+ nStartRow (nRow1),
+ nEndCol (nCol2),
+ nEndRow (nRow2),
+ bByRow (bByR),
+ bDoSize (FALSE),
+ bKeepFmt (FALSE),
+ bStripData (FALSE),
+ bHasHeader (bHasH),
+ bDBSelection(FALSE),
+ nIndex (0),
+ nExportIndex(0),
+ bIsAdvanced (FALSE),
+ bAutoFilter (FALSE),
+ bModified (FALSE)
+{
+ USHORT i;
+
+ ScSortParam aSortParam;
+ ScQueryParam aQueryParam;
+ ScSubTotalParam aSubTotalParam;
+ ScImportParam aImportParam;
+
+ for (i=0; i<MAXQUERY; i++)
+ pQueryStr[i] = new String;
+
+ for (i=0; i<MAXSUBTOTAL; i++)
+ {
+ nSubTotals[i] = 0;
+ pSubTotals[i] = NULL;
+ pFunctions[i] = NULL;
+ }
+
+ SetSortParam( aSortParam );
+ SetQueryParam( aQueryParam );
+ SetSubTotalParam( aSubTotalParam );
+ SetImportParam( aImportParam );
+}
+
+ScDBData::ScDBData( SvStream& rStream, ScMultipleReadHeader& rHdr ) :
+ // nicht in der Datei:
+ bAutoFilter (FALSE),
+ bModified (FALSE),
+ nExportIndex (0),
+ // nicht in alten Versionen:
+ bDoSize (FALSE),
+ bKeepFmt (FALSE),
+ bStripData (FALSE),
+ nIndex (0),
+ bIsAdvanced (FALSE),
+ bDBSelection (FALSE),
+ bDBSql (TRUE),
+ nDBType (dbTable),
+ nSubUserIndex (0),
+ bSortUserDef (FALSE),
+ nSortUserIndex (0)
+{
+ rHdr.StartEntry();
+
+ USHORT i;
+ USHORT j;
+ BYTE nDummy;
+ rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
+
+ rStream.ReadByteString( aName, eCharSet );
+ rStream >> nTable;
+ rStream >> nStartCol;
+ rStream >> nStartRow;
+ rStream >> nEndCol;
+ rStream >> nEndRow;
+ rStream >> bByRow;
+ rStream >> bHasHeader;
+ rStream >> bSortCaseSens;
+ rStream >> bIncludePattern;
+ rStream >> bSortInplace;
+ rStream >> nSortDestTab;
+ rStream >> nSortDestCol;
+ rStream >> nSortDestRow;
+ rStream >> bQueryInplace;
+ rStream >> bQueryCaseSens;
+ rStream >> bQueryRegExp;
+ rStream >> bQueryDuplicate;
+ rStream >> nQueryDestTab;
+ rStream >> nQueryDestCol;
+ rStream >> nQueryDestRow;
+ rStream >> bSubRemoveOnly;
+ rStream >> bSubReplace;
+ rStream >> bSubPagebreak;
+ rStream >> bSubCaseSens;
+ rStream >> bSubDoSort;
+ rStream >> bSubAscending;
+ rStream >> bSubIncludePattern;
+ rStream >> bSubUserDef;
+ rStream >> bDBImport;
+
+ rStream.ReadByteString( aDBName, eCharSet );
+ rStream.ReadByteString( aDBStatement, eCharSet );
+ rStream >> bDBNative;
+
+ for (i=0; i<MAXSORT; i++)
+ {
+ rStream >> bDoSort[i];
+ rStream >> nSortField[i];
+ rStream >> bAscending[i];
+ }
+ for (i=0; i<MAXQUERY; i++)
+ {
+ rStream >> bDoQuery[i];
+ rStream >> nQueryField[i];
+ rStream >> nDummy; eQueryOp[i] = (ScQueryOp) nDummy;
+ rStream >> bQueryByString[i];
+ pQueryStr[i] = new String;
+ rStream.ReadByteString( *pQueryStr[i], eCharSet );
+ rStream >> nQueryVal[i];
+ rStream >> nDummy; eQueryConnect[i] = (ScQueryConnect) nDummy;
+ }
+ for (i=0; i<MAXSUBTOTAL; i++)
+ {
+ rStream >> bDoSubTotal[i];
+ rStream >> nSubField[i];
+
+ USHORT nCount;
+ rStream >> nCount;
+ nSubTotals[i] = nCount;
+
+ pSubTotals[i] = nCount ? new USHORT [nCount] : NULL;
+ pFunctions[i] = nCount ? new ScSubTotalFunc [nCount] : NULL;
+
+ for (j=0; j<nCount; j++)
+ {
+ rStream >> pSubTotals[i][j];
+ rStream >> nDummy; pFunctions[i][j] = (ScSubTotalFunc)nDummy;
+ }
+ }
+
+ if (rHdr.BytesLeft())
+ rStream >> nIndex;
+
+ if (rHdr.BytesLeft())
+ rStream >> bDBSelection;
+
+ if (rHdr.BytesLeft())
+ rStream >> bDBSql; // Default = TRUE
+
+ if (rHdr.BytesLeft())
+ {
+ rStream >> nSubUserIndex;
+ rStream >> bSortUserDef;
+ rStream >> nSortUserIndex;
+ }
+
+ if (rHdr.BytesLeft())
+ {
+ rStream >> bDoSize;
+ rStream >> bKeepFmt;
+ }
+
+ if (rHdr.BytesLeft())
+ rStream >> bStripData;
+
+ if (rHdr.BytesLeft())
+ rStream >> nDBType; // Default = dbTable
+
+ if (rHdr.BytesLeft())
+ {
+ rStream >> bIsAdvanced; // Default = FALSE
+ if (bIsAdvanced)
+ rStream >> aAdvSource;
+ }
+
+ rHdr.EndEntry();
+
+ // #43070# rottes Dokument?!?
+ // nEndCol war 258
+ // und auch die CellInfo pPattern in ScOutputData FindRotated waren NULL
+ if ( nStartCol > MAXCOL )
+ {
+ DBG_ERRORFILE( "nStartCol > MAXCOL" );
+ nStartCol = MAXCOL;
+ }
+ if ( nStartRow > MAXROW )
+ {
+ DBG_ERRORFILE( "nStartRow > MAXROW" );
+ nStartRow = MAXROW;
+ }
+ if ( nEndCol > MAXCOL )
+ {
+ DBG_ERRORFILE( "nEndCol > MAXCOL" );
+ nEndCol = MAXCOL;
+ }
+ if ( nEndRow > MAXROW )
+ {
+ DBG_ERRORFILE( "nEndRow > MAXROW" );
+ nEndRow = MAXROW;
+ }
+ if ( nQueryDestCol > MAXCOL )
+ {
+ DBG_ERRORFILE( "nQueryDestCol > MAXCOL" );
+ nQueryDestCol = MAXCOL;
+ }
+ if ( nQueryDestRow > MAXROW )
+ {
+ DBG_ERRORFILE( "nQueryDestRow > MAXROW" );
+ nQueryDestRow = MAXROW;
+ }
+}
+
+BOOL ScDBData::Store( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const
+{
+ rHdr.StartEntry();
+
+ USHORT i;
+ USHORT j;
+ rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
+
+ rStream.WriteByteString( aName, eCharSet );
+ rStream << nTable;
+ rStream << nStartCol;
+ rStream << nStartRow;
+ rStream << nEndCol;
+ rStream << nEndRow;
+ rStream << bByRow;
+ rStream << bHasHeader;
+ rStream << bSortCaseSens;
+ rStream << bIncludePattern;
+ rStream << bSortInplace;
+ rStream << nSortDestTab;
+ rStream << nSortDestCol;
+ rStream << nSortDestRow;
+ rStream << bQueryInplace;
+ rStream << bQueryCaseSens;
+ rStream << bQueryRegExp;
+ rStream << bQueryDuplicate;
+ rStream << nQueryDestTab;
+ rStream << nQueryDestCol;
+ rStream << nQueryDestRow;
+ rStream << bSubRemoveOnly;
+ rStream << bSubReplace;
+ rStream << bSubPagebreak;
+ rStream << bSubCaseSens;
+ rStream << bSubDoSort;
+ rStream << bSubAscending;
+ rStream << bSubIncludePattern;
+ rStream << bSubUserDef;
+ rStream << bDBImport;
+
+ rStream.WriteByteString( aDBName, eCharSet );
+ rStream.WriteByteString( aDBStatement, eCharSet );
+ rStream << bDBNative;
+
+ for (i=0; i<MAXSORT; i++)
+ {
+ rStream << bDoSort[i];
+ rStream << nSortField[i];
+ rStream << bAscending[i];
+ }
+ for (i=0; i<MAXQUERY; i++)
+ {
+ rStream << bDoQuery[i];
+ rStream << nQueryField[i];
+ rStream << (BYTE) eQueryOp[i];
+ rStream << bQueryByString[i];
+ rStream.WriteByteString( *pQueryStr[i], eCharSet );
+ rStream << nQueryVal[i];
+ rStream << (BYTE) eQueryConnect[i];
+ }
+ for (i=0; i<MAXSUBTOTAL; i++)
+ {
+ rStream << bDoSubTotal[i];
+ rStream << nSubField[i];
+
+ USHORT nCount = nSubTotals[i];
+ rStream << nCount;
+ for (j=0; j<nCount; j++)
+ {
+ rStream << pSubTotals[i][j];
+ rStream << (BYTE)pFunctions[i][j];
+ }
+ }
+ rStream << nIndex; // seit 24.10.95
+
+ rStream << bDBSelection;
+
+ rStream << bDBSql; // seit 4.2.97
+
+ rStream << nSubUserIndex; // seit 5.2.97
+ rStream << bSortUserDef;
+ rStream << nSortUserIndex;
+
+ rStream << bDoSize; // seit 13.2.97
+ rStream << bKeepFmt;
+
+ rStream << bStripData; // seit 23.2.97
+
+ if( rStream.GetVersion() > SOFFICE_FILEFORMAT_40 )
+ {
+ // folgendes gab's in der 4.0 noch nicht
+
+ // alte Versionen suchen immer nach Tables und Queries
+ rStream << nDBType; // seit 20.11.97
+
+ // starting from 591, store advanced filter source range
+ // only if set, to avoid unneccessary warnings
+ if (bIsAdvanced)
+ {
+ rStream << (BOOL) TRUE;
+ rStream << aAdvSource;
+ }
+ }
+
+ rHdr.EndEntry();
+ return TRUE;
+}
+
+ScDBData::ScDBData( const ScDBData& rData ) :
+ aName (rData.aName),
+ nTable (rData.nTable),
+ nStartCol (rData.nStartCol),
+ nStartRow (rData.nStartRow),
+ nEndCol (rData.nEndCol),
+ nEndRow (rData.nEndRow),
+ bByRow (rData.bByRow),
+ bHasHeader (rData.bHasHeader),
+ bDoSize (rData.bDoSize),
+ bKeepFmt (rData.bKeepFmt),
+ bStripData (rData.bStripData),
+ bSortCaseSens (rData.bSortCaseSens),
+ bIncludePattern (rData.bIncludePattern),
+ bSortInplace (rData.bSortInplace),
+ nSortDestTab (rData.nSortDestTab),
+ nSortDestCol (rData.nSortDestCol),
+ nSortDestRow (rData.nSortDestRow),
+ bSortUserDef (rData.bSortUserDef),
+ nSortUserIndex (rData.nSortUserIndex),
+ bQueryInplace (rData.bQueryInplace),
+ bQueryCaseSens (rData.bQueryCaseSens),
+ bQueryRegExp (rData.bQueryRegExp),
+ bQueryDuplicate (rData.bQueryDuplicate),
+ nQueryDestTab (rData.nQueryDestTab),
+ nQueryDestCol (rData.nQueryDestCol),
+ nQueryDestRow (rData.nQueryDestRow),
+ bIsAdvanced (rData.bIsAdvanced),
+ aAdvSource (rData.aAdvSource),
+ bSubRemoveOnly (rData.bSubRemoveOnly),
+ bSubReplace (rData.bSubReplace),
+ bSubPagebreak (rData.bSubPagebreak),
+ bSubCaseSens (rData.bSubCaseSens),
+ bSubDoSort (rData.bSubDoSort),
+ bSubAscending (rData.bSubAscending),
+ bSubIncludePattern (rData.bSubIncludePattern),
+ bSubUserDef (rData.bSubUserDef),
+ nSubUserIndex (rData.nSubUserIndex),
+ bDBImport (rData.bDBImport),
+ aDBName (rData.aDBName),
+ aDBStatement (rData.aDBStatement),
+ bDBNative (rData.bDBNative),
+ bDBSelection (rData.bDBSelection),
+ bDBSql (rData.bDBSql),
+ nDBType (rData.nDBType),
+ nIndex (rData.nIndex),
+ nExportIndex (rData.nExportIndex),
+ bAutoFilter (rData.bAutoFilter),
+ bModified (rData.bModified)
+{
+ USHORT i;
+ USHORT j;
+
+ for (i=0; i<MAXSORT; i++)
+ {
+ bDoSort[i] = rData.bDoSort[i];
+ nSortField[i] = rData.nSortField[i];
+ bAscending[i] = rData.bAscending[i];
+ }
+ for (i=0; i<MAXQUERY; i++)
+ {
+ bDoQuery[i] = rData.bDoQuery[i];
+ nQueryField[i] = rData.nQueryField[i];
+ eQueryOp[i] = rData.eQueryOp[i];
+ bQueryByString[i] = rData.bQueryByString[i];
+ pQueryStr[i] = new String( *(rData.pQueryStr[i]) );
+ nQueryVal[i] = rData.nQueryVal[i];
+ eQueryConnect[i] = rData.eQueryConnect[i];
+ }
+ for (i=0; i<MAXSUBTOTAL; i++)
+ {
+ bDoSubTotal[i] = rData.bDoSubTotal[i];
+ nSubField[i] = rData.nSubField[i];
+
+ USHORT nCount = rData.nSubTotals[i];
+ nSubTotals[i] = nCount;
+ pFunctions[i] = nCount ? new ScSubTotalFunc [nCount] : NULL;
+ pSubTotals[i] = nCount ? new USHORT [nCount] : NULL;
+
+ for (j=0; j<nCount; j++)
+ {
+ pSubTotals[i][j] = rData.pSubTotals[i][j];
+ pFunctions[i][j] = rData.pFunctions[i][j];
+ }
+ }
+}
+
+ScDBData& ScDBData::operator= (const ScDBData& rData)
+{
+ USHORT i;
+ USHORT j;
+
+ aName = rData.aName;
+ nTable = rData.nTable;
+ nStartCol = rData.nStartCol;
+ nStartRow = rData.nStartRow;
+ nEndCol = rData.nEndCol;
+ nEndRow = rData.nEndRow;
+ bByRow = rData.bByRow;
+ bHasHeader = rData.bHasHeader;
+ bDoSize = rData.bDoSize;
+ bKeepFmt = rData.bKeepFmt;
+ bStripData = rData.bStripData;
+ bSortCaseSens = rData.bSortCaseSens;
+ bIncludePattern = rData.bIncludePattern;
+ bSortInplace = rData.bSortInplace;
+ nSortDestTab = rData.nSortDestTab;
+ nSortDestCol = rData.nSortDestCol;
+ nSortDestRow = rData.nSortDestRow;
+ bSortUserDef = rData.bSortUserDef;
+ nSortUserIndex = rData.nSortUserIndex;
+ bQueryInplace = rData.bQueryInplace;
+ bQueryCaseSens = rData.bQueryCaseSens;
+ bQueryRegExp = rData.bQueryRegExp;
+ bQueryDuplicate = rData.bQueryDuplicate;
+ nQueryDestTab = rData.nQueryDestTab;
+ nQueryDestCol = rData.nQueryDestCol;
+ nQueryDestRow = rData.nQueryDestRow;
+ bIsAdvanced = rData.bIsAdvanced;
+ aAdvSource = rData.aAdvSource;
+ bSubRemoveOnly = rData.bSubRemoveOnly;
+ bSubReplace = rData.bSubReplace;
+ bSubPagebreak = rData.bSubPagebreak;
+ bSubCaseSens = rData.bSubCaseSens;
+ bSubDoSort = rData.bSubDoSort;
+ bSubAscending = rData.bSubAscending;
+ bSubIncludePattern = rData.bSubIncludePattern;
+ bSubUserDef = rData.bSubUserDef;
+ nSubUserIndex = rData.nSubUserIndex;
+ bDBImport = rData.bDBImport;
+ aDBName = rData.aDBName;
+ aDBStatement = rData.aDBStatement;
+ bDBNative = rData.bDBNative;
+ bDBSelection = rData.bDBSelection;
+ bDBSql = rData.bDBSql;
+ nDBType = rData.nDBType;
+ nIndex = rData.nIndex;
+ nExportIndex = rData.nExportIndex;
+
+ for (i=0; i<MAXSORT; i++)
+ {
+ bDoSort[i] = rData.bDoSort[i];
+ nSortField[i] = rData.nSortField[i];
+ bAscending[i] = rData.bAscending[i];
+ }
+ for (i=0; i<MAXQUERY; i++)
+ {
+ bDoQuery[i] = rData.bDoQuery[i];
+ nQueryField[i] = rData.nQueryField[i];
+ eQueryOp[i] = rData.eQueryOp[i];
+ bQueryByString[i] = rData.bQueryByString[i];
+ *pQueryStr[i] = *rData.pQueryStr[i];
+ nQueryVal[i] = rData.nQueryVal[i];
+ eQueryConnect[i] = rData.eQueryConnect[i];
+ }
+ for (i=0; i<MAXSUBTOTAL; i++)
+ {
+ bDoSubTotal[i] = rData.bDoSubTotal[i];
+ nSubField[i] = rData.nSubField[i];
+ USHORT nCount = rData.nSubTotals[i];
+ nSubTotals[i] = nCount;
+
+ delete[] pSubTotals[i];
+ delete[] pFunctions[i];
+
+ pSubTotals[i] = nCount ? new USHORT [nCount] : NULL;
+ pFunctions[i] = nCount ? new ScSubTotalFunc [nCount] : NULL;
+ for (j=0; j<nCount; j++)
+ {
+ pSubTotals[i][j] = rData.pSubTotals[i][j];
+ pFunctions[i][j] = rData.pFunctions[i][j];
+ }
+ }
+
+ return *this;
+}
+
+BOOL ScDBData::operator== (const ScDBData& rData) const
+{
+ // Daten, die nicht in den Params sind
+
+ if ( nTable != rData.nTable ||
+ bDoSize != rData.bDoSize ||
+ bKeepFmt != rData.bKeepFmt ||
+ bIsAdvanced!= rData.bIsAdvanced||
+ bStripData != rData.bStripData )
+ return FALSE;
+
+ if ( bIsAdvanced && aAdvSource != rData.aAdvSource )
+ return FALSE;
+
+ ScSortParam aSort1, aSort2;
+ GetSortParam(aSort1);
+ rData.GetSortParam(aSort2);
+ if (!(aSort1 == aSort2))
+ return FALSE;
+
+ ScQueryParam aQuery1, aQuery2;
+ GetQueryParam(aQuery1);
+ rData.GetQueryParam(aQuery2);
+ if (!(aQuery1 == aQuery2))
+ return FALSE;
+
+ ScSubTotalParam aSubTotal1, aSubTotal2;
+ GetSubTotalParam(aSubTotal1);
+ rData.GetSubTotalParam(aSubTotal2);
+ if (!(aSubTotal1 == aSubTotal2))
+ return FALSE;
+
+ ScImportParam aImport1, aImport2;
+ GetImportParam(aImport1);
+ rData.GetImportParam(aImport2);
+ if (!(aImport1 == aImport2))
+ return FALSE;
+
+ return TRUE;
+}
+
+ScDBData::~ScDBData()
+{
+ USHORT i;
+
+ for (i=0; i<MAXQUERY; i++)
+ delete pQueryStr[i];
+ for (i=0; i<MAXSUBTOTAL; i++)
+ {
+ delete[] pSubTotals[i];
+ delete[] pFunctions[i];
+ }
+}
+
+BOOL ScDBData::IsBeyond(USHORT nMaxRow) const
+{
+ return ( nStartRow > nMaxRow ||
+ nEndRow > nMaxRow ||
+ nQueryDestRow > nMaxRow );
+}
+
+String ScDBData::GetSourceString() const
+{
+ String aVal;
+ if (bDBImport)
+ {
+ aVal = aDBName;
+ aVal += '/';
+ aVal += aDBStatement;
+ }
+ return aVal;
+}
+
+String ScDBData::GetOperations() const
+{
+ String aVal;
+ if (bDoQuery[0])
+ aVal = ScGlobal::GetRscString(STR_OPERATION_FILTER);
+
+ if (bDoSort[0])
+ {
+ if (aVal.Len())
+ aVal.AppendAscii( RTL_CONSTASCII_STRINGPARAM(", ") );
+ aVal += ScGlobal::GetRscString(STR_OPERATION_SORT);
+ }
+
+ if (bDoSubTotal[0] && !bSubRemoveOnly)
+ {
+ if (aVal.Len())
+ aVal.AppendAscii( RTL_CONSTASCII_STRINGPARAM(", ") );
+ aVal += ScGlobal::GetRscString(STR_OPERATION_SUBTOTAL);
+ }
+
+ if (!aVal.Len())
+ aVal = ScGlobal::GetRscString(STR_OPERATION_NONE);
+
+ return aVal;
+}
+
+void ScDBData::GetArea(USHORT& rTab, USHORT& rCol1, USHORT& rRow1, USHORT& rCol2, USHORT& rRow2) const
+{
+ rTab = nTable;
+ rCol1 = nStartCol;
+ rRow1 = nStartRow;
+ rCol2 = nEndCol;
+ rRow2 = nEndRow;
+}
+
+void ScDBData::GetArea(ScRange& rRange) const
+{
+ rRange = ScRange( nStartCol,nStartRow,nTable, nEndCol,nEndRow,nTable );
+}
+
+void ScDBData::SetArea(USHORT nTab, USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2)
+{
+ nTable = nTab;
+ nStartCol = nCol1;
+ nStartRow = nRow1;
+ nEndCol = nCol2;
+ nEndRow = nRow2;
+}
+
+void ScDBData::MoveTo(USHORT nTab, USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2)
+{
+ USHORT i;
+ short nDifX = ((short) nCol1) - ((short) nStartCol);
+ short nDifY = ((short) nRow1) - ((short) nStartRow);
+
+ short nSortDif = bByRow ? nDifX : nDifY;
+ USHORT nSortEnd = bByRow ? nCol2 : nRow2;
+
+ for (i=0; i<MAXSORT; i++)
+ {
+ nSortField[i] += nSortDif;
+ if (nSortField[i] > nSortEnd)
+ {
+ nSortField[i] = 0;
+ bDoSort[i] = FALSE;
+ }
+ }
+ for (i=0; i<MAXQUERY; i++)
+ {
+ nQueryField[i] += nDifX;
+ if (nQueryField[i] > nCol2)
+ {
+ nQueryField[i] = 0;
+ bDoQuery[i] = FALSE;
+ }
+ }
+ for (i=0; i<MAXSUBTOTAL; i++)
+ {
+ nSubField[i] += nDifX;
+ if (nSubField[i] > nCol2)
+ {
+ nSubField[i] = 0;
+ bDoSubTotal[i] = FALSE;
+ }
+ }
+
+ SetArea( nTab, nCol1, nRow1, nCol2, nRow2 );
+}
+
+void ScDBData::GetSortParam( ScSortParam& rSortParam ) const
+{
+ rSortParam.nCol1 = nStartCol;
+ rSortParam.nRow1 = nStartRow;
+ rSortParam.nCol2 = nEndCol;
+ rSortParam.nRow2 = nEndRow;
+ rSortParam.bByRow = bByRow;
+ rSortParam.bHasHeader = bHasHeader;
+ rSortParam.bCaseSens = bSortCaseSens;
+ rSortParam.bInplace = bSortInplace;
+ rSortParam.nDestTab = nSortDestTab;
+ rSortParam.nDestCol = nSortDestCol;
+ rSortParam.nDestRow = nSortDestRow;
+ rSortParam.bIncludePattern = bIncludePattern;
+ rSortParam.bUserDef = bSortUserDef;
+ rSortParam.nUserIndex = nSortUserIndex;
+ for (USHORT i=0; i<MAXSORT; i++)
+ {
+ rSortParam.bDoSort[i] = bDoSort[i];
+ rSortParam.nField[i] = nSortField[i];
+ rSortParam.bAscending[i] = bAscending[i];
+ }
+}
+
+void ScDBData::SetSortParam( const ScSortParam& rSortParam )
+{
+ bSortCaseSens = rSortParam.bCaseSens;
+ bIncludePattern = rSortParam.bIncludePattern;
+ bSortInplace = rSortParam.bInplace;
+ nSortDestTab = rSortParam.nDestTab;
+ nSortDestCol = rSortParam.nDestCol;
+ nSortDestRow = rSortParam.nDestRow;
+ bSortUserDef = rSortParam.bUserDef;
+ nSortUserIndex = rSortParam.nUserIndex;
+ for (USHORT i=0; i<MAXSORT; i++)
+ {
+ bDoSort[i] = rSortParam.bDoSort[i];
+ nSortField[i] = rSortParam.nField[i];
+ bAscending[i] = rSortParam.bAscending[i];
+ }
+}
+
+void ScDBData::GetQueryParam( ScQueryParam& rQueryParam ) const
+{
+ rQueryParam.nCol1 = nStartCol;
+ rQueryParam.nRow1 = nStartRow;
+ rQueryParam.nCol2 = nEndCol;
+ rQueryParam.nRow2 = nEndRow;
+ rQueryParam.nTab = nTable;
+ rQueryParam.bByRow = bByRow;
+ rQueryParam.bHasHeader = bHasHeader;
+ rQueryParam.bInplace = bQueryInplace;
+ rQueryParam.bCaseSens = bQueryCaseSens;
+ rQueryParam.bRegExp = bQueryRegExp;
+ rQueryParam.bDuplicate = bQueryDuplicate;
+ rQueryParam.nDestTab = nQueryDestTab;
+ rQueryParam.nDestCol = nQueryDestCol;
+ rQueryParam.nDestRow = nQueryDestRow;
+
+ rQueryParam.Resize( MAXQUERY );
+ for (USHORT i=0; i<MAXQUERY; i++)
+ {
+ ScQueryEntry& rEntry = rQueryParam.GetEntry(i);
+
+ rEntry.bDoQuery = bDoQuery[i];
+ rEntry.nField = nQueryField[i];
+ rEntry.eOp = eQueryOp[i];
+ rEntry.bQueryByString = bQueryByString[i];
+ *rEntry.pStr = *pQueryStr[i];
+ rEntry.nVal = nQueryVal[i];
+ rEntry.eConnect = eQueryConnect[i];
+ }
+}
+
+void ScDBData::SetQueryParam(const ScQueryParam& rQueryParam)
+{
+ DBG_ASSERT( rQueryParam.GetEntryCount() <= MAXQUERY ||
+ !rQueryParam.GetEntry(MAXQUERY).bDoQuery,
+ "zuviele Eintraege bei ScDBData::SetQueryParam" );
+
+ // set bIsAdvanced to FALSE for everything that is not from the
+ // advanced filter dialog
+ bIsAdvanced = FALSE;
+
+ bQueryInplace = rQueryParam.bInplace;
+ bQueryCaseSens = rQueryParam.bCaseSens;
+ bQueryRegExp = rQueryParam.bRegExp;
+ bQueryDuplicate = rQueryParam.bDuplicate;
+ nQueryDestTab = rQueryParam.nDestTab;
+ nQueryDestCol = rQueryParam.nDestCol;
+ nQueryDestRow = rQueryParam.nDestRow;
+ for (USHORT i=0; i<MAXQUERY; i++)
+ {
+ ScQueryEntry& rEntry = rQueryParam.GetEntry(i);
+
+ bDoQuery[i] = rEntry.bDoQuery;
+ nQueryField[i] = rEntry.nField;
+ eQueryOp[i] = rEntry.eOp;
+ bQueryByString[i] = rEntry.bQueryByString;
+ *pQueryStr[i] = *rEntry.pStr;
+ nQueryVal[i] = rEntry.nVal;
+ eQueryConnect[i] = rEntry.eConnect;
+ }
+}
+
+void ScDBData::SetAdvancedQuerySource(const ScRange* pSource)
+{
+ if (pSource)
+ {
+ aAdvSource = *pSource;
+ bIsAdvanced = TRUE;
+ }
+ else
+ bIsAdvanced = FALSE;
+}
+
+BOOL ScDBData::GetAdvancedQuerySource(ScRange& rSource) const
+{
+ rSource = aAdvSource;
+ return bIsAdvanced;
+}
+
+void ScDBData::GetSubTotalParam(ScSubTotalParam& rSubTotalParam) const
+{
+ USHORT i;
+ USHORT j;
+
+ rSubTotalParam.nCol1 = nStartCol;
+ rSubTotalParam.nRow1 = nStartRow;
+ rSubTotalParam.nCol2 = nEndCol;
+ rSubTotalParam.nRow2 = nEndRow;
+
+ rSubTotalParam.bRemoveOnly = bSubRemoveOnly;
+ rSubTotalParam.bReplace = bSubReplace;
+ rSubTotalParam.bPagebreak = bSubPagebreak;
+ rSubTotalParam.bCaseSens = bSubCaseSens;
+ rSubTotalParam.bDoSort = bSubDoSort;
+ rSubTotalParam.bAscending = bSubAscending;
+ rSubTotalParam.bIncludePattern = bSubIncludePattern;
+ rSubTotalParam.bUserDef = bSubUserDef;
+ rSubTotalParam.nUserIndex = nSubUserIndex;
+
+ for (i=0; i<MAXSUBTOTAL; i++)
+ {
+ rSubTotalParam.bGroupActive[i] = bDoSubTotal[i];
+ rSubTotalParam.nField[i] = nSubField[i];
+ USHORT nCount = nSubTotals[i];
+
+ rSubTotalParam.nSubTotals[i] = nCount;
+ delete[] rSubTotalParam.pSubTotals[i];
+ delete[] rSubTotalParam.pFunctions[i];
+ rSubTotalParam.pSubTotals[i] = nCount ? new USHORT[nCount] : NULL;
+ rSubTotalParam.pFunctions[i] = nCount ? new ScSubTotalFunc[nCount]
+ : NULL;
+ for (j=0; j<nCount; j++)
+ {
+ rSubTotalParam.pSubTotals[i][j] = pSubTotals[i][j];
+ rSubTotalParam.pFunctions[i][j] = pFunctions[i][j];
+ }
+ }
+}
+
+void ScDBData::SetSubTotalParam(const ScSubTotalParam& rSubTotalParam)
+{
+ USHORT i;
+ USHORT j;
+
+ bSubRemoveOnly = rSubTotalParam.bRemoveOnly;
+ bSubReplace = rSubTotalParam.bReplace;
+ bSubPagebreak = rSubTotalParam.bPagebreak;
+ bSubCaseSens = rSubTotalParam.bCaseSens;
+ bSubDoSort = rSubTotalParam.bDoSort;
+ bSubAscending = rSubTotalParam.bAscending;
+ bSubIncludePattern = rSubTotalParam.bIncludePattern;
+ bSubUserDef = rSubTotalParam.bUserDef;
+ nSubUserIndex = rSubTotalParam.nUserIndex;
+
+ for (i=0; i<MAXSUBTOTAL; i++)
+ {
+ bDoSubTotal[i] = rSubTotalParam.bGroupActive[i];
+ nSubField[i] = rSubTotalParam.nField[i];
+ USHORT nCount = rSubTotalParam.nSubTotals[i];
+
+ nSubTotals[i] = nCount;
+ delete[] pSubTotals[i];
+ delete[] pFunctions[i];
+ pSubTotals[i] = nCount ? new USHORT [nCount] : NULL;
+ pFunctions[i] = nCount ? new ScSubTotalFunc [nCount] : NULL;
+ for (j=0; j<nCount; j++)
+ {
+ pSubTotals[i][j] = rSubTotalParam.pSubTotals[i][j];
+ pFunctions[i][j] = rSubTotalParam.pFunctions[i][j];
+ }
+ }
+}
+
+void ScDBData::GetImportParam(ScImportParam& rImportParam) const
+{
+ rImportParam.nCol1 = nStartCol;
+ rImportParam.nRow1 = nStartRow;
+ rImportParam.nCol2 = nEndCol;
+ rImportParam.nRow2 = nEndRow;
+
+ rImportParam.bImport = bDBImport;
+ rImportParam.aDBName = aDBName;
+ rImportParam.aStatement = aDBStatement;
+ rImportParam.bNative = bDBNative;
+ rImportParam.bSql = bDBSql;
+ rImportParam.nType = nDBType;
+}
+
+void ScDBData::SetImportParam(const ScImportParam& rImportParam)
+{
+ bDBImport = rImportParam.bImport;
+ aDBName = rImportParam.aDBName;
+ aDBStatement = rImportParam.aStatement;
+ bDBNative = rImportParam.bNative;
+ bDBSql = rImportParam.bSql;
+ nDBType = rImportParam.nType;
+}
+
+BOOL ScDBData::IsDBAtCursor(USHORT nCol, USHORT nRow, USHORT nTab, BOOL bStartOnly) const
+{
+ if (nTab == nTable)
+ {
+ if ( bStartOnly )
+ return ( nCol == nStartCol && nRow == nStartRow );
+ else
+ return ( nCol >= nStartCol && nCol <= nEndCol &&
+ nRow >= nStartRow && nRow <= nEndRow );
+ }
+
+ return FALSE;
+}
+
+BOOL ScDBData::IsDBAtArea(USHORT nTab, USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2) const
+{
+ return (BOOL)((nTab == nTable)
+ && (nCol1 == nStartCol) && (nRow1 == nStartRow)
+ && (nCol2 == nEndCol) && (nRow2 == nEndRow));
+}
+
+String ScDBData::GetTargetName(const String& rDocName) const
+{
+ String aTargetName(rDocName);
+ aTargetName += '.';
+ aTargetName += aName;
+ return aTargetName;
+}
+
+DataObject* ScDBData::Clone() const
+{
+ return new ScDBData(*this);
+}
+
+//---------------------------------------------------------------------------------------
+// Compare zum Sortieren
+
+short ScDBCollection::Compare(DataObject* pKey1, DataObject* pKey2) const
+{
+ const String& rStr1 = ((ScDBData*)pKey1)->GetName();
+ const String& rStr2 = ((ScDBData*)pKey2)->GetName();
+ StringCompare eComp = ScGlobal::pScInternational->Compare(
+ rStr1, rStr2, INTN_COMPARE_IGNORECASE );
+ if (eComp == COMPARE_EQUAL)
+ return 0;
+ else if (eComp == COMPARE_LESS)
+ return -1;
+ else
+ return 1;
+}
+
+// IsEqual - alles gleich
+
+BOOL ScDBCollection::IsEqual(DataObject* pKey1, DataObject* pKey2) const
+{
+ return *(ScDBData*)pKey1 == *(ScDBData*)pKey2;
+}
+
+ScDBData* ScDBCollection::GetDBAtCursor(USHORT nCol, USHORT nRow, USHORT nTab, BOOL bStartOnly) const
+{
+ ScDBData* pNoNameData = NULL;
+ if (pItems)
+ {
+ const String& rNoName = ScGlobal::GetRscString( STR_DB_NONAME );
+
+ for (USHORT i = 0; i < nCount; i++)
+ if (((ScDBData*)pItems[i])->IsDBAtCursor(nCol, nRow, nTab, bStartOnly))
+ {
+ ScDBData* pDB = (ScDBData*)pItems[i];
+ if ( pDB->GetName() == rNoName )
+ pNoNameData = pDB;
+ else
+ return pDB;
+ }
+ }
+ return pNoNameData; // "unbenannt" nur zurueck, wenn sonst nichts gefunden
+}
+
+ScDBData* ScDBCollection::GetDBAtArea(USHORT nTab, USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2) const
+{
+ ScDBData* pNoNameData = NULL;
+ if (pItems)
+ {
+ const String& rNoName = ScGlobal::GetRscString( STR_DB_NONAME );
+
+ for (USHORT i = 0; i < nCount; i++)
+ if (((ScDBData*)pItems[i])->IsDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2))
+ {
+ ScDBData* pDB = (ScDBData*)pItems[i];
+ if ( pDB->GetName() == rNoName )
+ pNoNameData = pDB;
+ else
+ return pDB;
+ }
+ }
+ return pNoNameData; // "unbenannt" nur zurueck, wenn sonst nichts gefunden
+}
+
+BOOL ScDBCollection::SearchName( const String& rName, USHORT& rIndex ) const
+{
+ ScDBData aDataObj( rName, 0,0,0,0,0 );
+ return Search( &aDataObj, rIndex );
+}
+
+BOOL ScDBCollection::Load( SvStream& rStream )
+{
+ BOOL bSuccess = TRUE;
+ USHORT nNewCount;
+
+ while( nCount > 0 )
+ AtFree(0); // alles loeschen
+
+ ScMultipleReadHeader aHdr( rStream );
+
+ rStream >> nNewCount;
+ for (USHORT i=0; i<nNewCount && bSuccess; i++)
+ {
+ ScDBData* pData = new ScDBData( rStream, aHdr );
+ Insert( pData );
+ }
+ if (aHdr.BytesLeft()) // ... Erweiterungen
+ rStream >> nEntryIndex;
+ return bSuccess;
+}
+
+BOOL ScDBCollection::Store( SvStream& rStream ) const
+{
+ ScMultipleWriteHeader aHdr( rStream );
+
+ USHORT i;
+ USHORT nSaveCount = nCount;
+ USHORT nSaveMaxRow = pDoc->GetSrcMaxRow();
+ if ( nSaveMaxRow < MAXROW )
+ {
+ nSaveCount = 0;
+ for (i=0; i<nCount; i++)
+ if ( !((const ScDBData*)At(i))->IsBeyond(nSaveMaxRow) )
+ ++nSaveCount;
+
+ if ( nSaveCount < nCount )
+ pDoc->SetLostData(); // Warnung ausgeben
+ }
+
+ rStream << nSaveCount;
+
+ BOOL bSuccess = TRUE;
+ for (i=0; i<nCount && bSuccess; i++)
+ {
+ const ScDBData* pDBData = (const ScDBData*)At(i);
+ if ( nSaveMaxRow == MAXROW || !pDBData->IsBeyond(nSaveMaxRow) )
+ bSuccess = pDBData->Store( rStream, aHdr );
+ }
+
+ rStream << nEntryIndex; // seit 24.10.95
+
+ return bSuccess;
+}
+
+void ScDBCollection::UpdateReference(UpdateRefMode eUpdateRefMode,
+ USHORT nCol1, USHORT nRow1, USHORT nTab1,
+ USHORT nCol2, USHORT nRow2, USHORT nTab2,
+ short nDx, short nDy, short nDz )
+{
+ for (USHORT i=0; i<nCount; i++)
+ {
+ USHORT theCol1;
+ USHORT theRow1;
+ USHORT theTab1;
+ USHORT theCol2;
+ USHORT theRow2;
+ USHORT theTab2;
+ ((ScDBData*)pItems[i])->GetArea( theTab1, theCol1, theRow1, theCol2, theRow2 );
+ theTab2 = theTab1;
+
+ BOOL bDoUpdate = ScRefUpdate::Update( pDoc, eUpdateRefMode,
+ nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, nDx,nDy,nDz,
+ theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 );
+ if (bDoUpdate)
+ ((ScDBData*)pItems[i])->MoveTo( theTab1, theCol1, theRow1, theCol2, theRow2 );
+
+ ScRange aAdvSource;
+ if ( ((ScDBData*)pItems[i])->GetAdvancedQuerySource(aAdvSource) )
+ {
+ aAdvSource.GetVars( theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 );
+ if ( ScRefUpdate::Update( pDoc, eUpdateRefMode,
+ nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, nDx,nDy,nDz,
+ theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ) )
+ {
+ aAdvSource.aStart.Set( theCol1,theRow1,theTab1 );
+ aAdvSource.aEnd.Set( theCol2,theRow2,theTab2 );
+ ((ScDBData*)pItems[i])->SetAdvancedQuerySource( &aAdvSource );
+
+ bDoUpdate = TRUE; // DBData is modified
+ }
+ }
+
+ ((ScDBData*)pItems[i])->SetModified(bDoUpdate);
+
+ //! Testen, ob mitten aus dem Bereich geloescht/eingefuegt wurde !!!
+ }
+}
+
+
+void ScDBCollection::UpdateMoveTab( USHORT nOldPos, USHORT nNewPos )
+{
+ // wenn nOldPos vor nNewPos liegt, ist nNewPos schon angepasst
+
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScRange aRange;
+ ScDBData* pData = (ScDBData*)pItems[i];
+ pData->GetArea( aRange );
+ USHORT nTab = aRange.aStart.Tab(); // hat nur eine Tabelle
+
+ // anpassen wie die aktuelle Tabelle bei ScTablesHint (tabvwsh5.cxx)
+
+ if ( nTab == nOldPos ) // verschobene Tabelle
+ nTab = nNewPos;
+ else if ( nOldPos < nNewPos ) // nach hinten verschoben
+ {
+ if ( nTab > nOldPos && nTab <= nNewPos ) // nachrueckender Bereich
+ --nTab;
+ }
+ else // nach vorne verschoben
+ {
+ if ( nTab >= nNewPos && nTab < nOldPos ) // nachrueckender Bereich
+ ++nTab;
+ }
+
+ BOOL bChanged = ( nTab != aRange.aStart.Tab() );
+ if (bChanged)
+ pData->SetArea( nTab, aRange.aStart.Col(), aRange.aStart.Row(),
+ aRange.aEnd.Col(),aRange.aEnd .Row() );
+
+ // MoveTo ist nicht noetig, wenn nur die Tabelle geaendert ist
+
+ pData->SetModified(bChanged);
+ }
+}
+
+
+ScDBData* ScDBCollection::FindIndex(USHORT nIndex)
+{
+ USHORT i = 0;
+ while (i < nCount)
+ {
+ if ((*this)[i]->GetIndex() == nIndex)
+ return (*this)[i];
+ i++;
+ }
+ return NULL;
+}
+
+BOOL ScDBCollection::Insert(DataObject* pDataObject)
+{
+ if (!((ScDBData*)pDataObject)->GetIndex()) // schon gesetzt?
+ ((ScDBData*)pDataObject)->SetIndex(nEntryIndex++);
+ return SortedCollection::Insert(pDataObject);
+}
+
+
+
+
diff --git a/sc/source/core/tool/ddelink.cxx b/sc/source/core/tool/ddelink.cxx
new file mode 100644
index 000000000000..92a2c1ba42a2
--- /dev/null
+++ b/sc/source/core/tool/ddelink.cxx
@@ -0,0 +1,315 @@
+/*************************************************************************
+ *
+ * $RCSfile: ddelink.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#ifndef _LIST_HXX //autogen
+#include <tools/list.hxx>
+#endif
+#include <svx/linkmgr.hxx>
+#include <sfx2/bindings.hxx>
+#include <svtools/zforlist.hxx>
+
+#include "ddelink.hxx"
+#include "brdcst.hxx"
+#include "document.hxx"
+#include "scmatrix.hxx"
+#include "patattr.hxx"
+#include "rechead.hxx"
+#include "sc.hrc"
+#include "hints.hxx"
+
+TYPEINIT2(ScDdeLink,SvBaseLink,SfxBroadcaster);
+
+BOOL ScDdeLink::bIsInUpdate = FALSE;
+
+//------------------------------------------------------------------------
+
+ScDdeLink::ScDdeLink( ScDocument* pD, const String& rA, const String& rT, const String& rI,
+ BYTE nM ) :
+ SvBaseLink(LINKUPDATE_ALWAYS,FORMAT_STRING),
+ pDoc( pD ),
+ aAppl( rA ),
+ aTopic( rT ),
+ aItem( rI ),
+ nMode( nM ),
+ pResult( NULL ),
+ bNeedUpdate( FALSE )
+{
+}
+
+__EXPORT ScDdeLink::~ScDdeLink()
+{
+ // Verbindung aufheben
+
+ delete pResult;
+}
+
+ScDdeLink::ScDdeLink( ScDocument* pD, const ScDdeLink& rOther ) :
+ SvBaseLink(LINKUPDATE_ALWAYS,FORMAT_STRING),
+ pDoc ( pD ),
+ aAppl ( rOther.aAppl ),
+ aTopic ( rOther.aTopic ),
+ aItem ( rOther.aItem ),
+ nMode ( rOther.nMode ),
+ pResult ( NULL ),
+ bNeedUpdate( FALSE )
+{
+ if (rOther.pResult)
+ pResult = rOther.pResult->Clone();
+}
+
+ScDdeLink::ScDdeLink( ScDocument* pD, SvStream& rStream, ScMultipleReadHeader& rHdr ) :
+ SvBaseLink(LINKUPDATE_ALWAYS,FORMAT_STRING),
+ pDoc( pD ),
+ pResult( NULL ),
+ bNeedUpdate( FALSE )
+{
+ rHdr.StartEntry();
+
+ rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
+ rStream.ReadByteString( aAppl, eCharSet );
+ rStream.ReadByteString( aTopic, eCharSet );
+ rStream.ReadByteString( aItem, eCharSet );
+
+ BOOL bHasValue;
+ rStream >> bHasValue;
+ if ( bHasValue )
+ pResult = new ScMatrix( rStream );
+
+ if (rHdr.BytesLeft()) // neu in 388b und der 364w (RealTime-Client) Version
+ rStream >> nMode;
+ else
+ nMode = SC_DDE_DEFAULT;
+
+ rHdr.EndEntry();
+}
+
+void ScDdeLink::Store( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const
+{
+ rHdr.StartEntry();
+
+ rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
+ rStream.WriteByteString( aAppl, eCharSet );
+ rStream.WriteByteString( aTopic, eCharSet );
+ rStream.WriteByteString( aItem, eCharSet );
+
+ BOOL bHasValue = ( pResult != NULL );
+ rStream << bHasValue;
+ if (bHasValue)
+ pResult->Store( rStream );
+
+ if( rStream.GetVersion() > SOFFICE_FILEFORMAT_40 ) // nicht bei 4.0 Export
+ rStream << nMode; // seit 388b
+
+ // Links mit Mode != SC_DDE_DEFAULT werden bei 4.0 Export komplett weggelassen
+ // (aus ScDocument::SaveDdeLinks)
+
+ rHdr.EndEntry();
+}
+
+void __EXPORT ScDdeLink::DataChanged(SvData& rData)
+{
+ // wir koennen nur Strings...
+
+ if ( rData.GetFormat() != FORMAT_STRING )
+ return;
+
+ String aLinkStr;
+ rData.GetData( aLinkStr );
+ aLinkStr.ConvertLineEnd(LINEEND_LF);
+
+ // wenn String mit Zeilenende aufhoert, streichen:
+
+ xub_StrLen nLen = aLinkStr.Len();
+ if (nLen && aLinkStr.GetChar(nLen-1) == '\n')
+ aLinkStr.Erase(nLen-1);
+
+ String aLine;
+ USHORT nCols = 1; // Leerstring -> eine leere Zelle
+ USHORT nRows = 1;
+ if (aLinkStr.Len())
+ {
+ nRows = (USHORT) aLinkStr.GetTokenCount( '\n' );
+ aLine = aLinkStr.GetToken( 0, '\n' );
+ if (aLine.Len())
+ nCols = (USHORT) aLine.GetTokenCount( '\t' );
+ }
+
+ if (!nRows || !nCols) // keine Daten
+ {
+ DELETEZ(pResult);
+ }
+ else // Daten aufteilen
+ {
+ // Matrix immer neu anlegen, damit bIsString nicht durcheinanderkommt
+ delete pResult;
+ pResult = new ScMatrix( nCols, nRows );
+
+ SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
+
+ // nMode bestimmt, wie der Text interpretiert wird (#44455#/#49783#):
+ // SC_DDE_DEFAULT - Zahlformat aus Zellvorlage "Standard"
+ // SC_DDE_ENGLISH - Standard-Zahlformat fuer English/US
+ // SC_DDE_TEXT - ohne NumberFormatter direkt als String
+ ULONG nStdFormat = 0;
+ if ( nMode == SC_DDE_DEFAULT )
+ {
+ ScPatternAttr* pDefPattern = pDoc->GetDefPattern(); // enthaelt Standard-Vorlage
+ if ( pDefPattern )
+ nStdFormat = pDefPattern->GetNumberFormat( pFormatter );
+ }
+ else if ( nMode == SC_DDE_ENGLISH )
+ nStdFormat = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
+
+ String aEntry;
+ for (USHORT nR=0; nR<nRows; nR++)
+ {
+ aLine = aLinkStr.GetToken( (xub_StrLen) nR, '\n' );
+ for (USHORT nC=0; nC<nCols; nC++)
+ {
+ aEntry = aLine.GetToken( (xub_StrLen) nC, '\t' );
+ ULONG nIndex = nStdFormat;
+ double fVal;
+ if ( nMode != SC_DDE_TEXT && pFormatter->IsNumberFormat( aEntry, nIndex, fVal ) )
+ pResult->PutDouble( fVal, nC, nR );
+ else
+ pResult->PutString( aEntry, nC, nR );
+ }
+ }
+ }
+
+ // Es hat sich was getan...
+
+ if (HasListeners())
+ {
+ Broadcast( ScHint( SC_HINT_DATACHANGED, ScAddress( 0 ), NULL ) );
+ pDoc->TrackFormulas(); // muss sofort passieren
+ pDoc->StartTrackTimer();
+
+ // StartTrackTimer ruft asynchron TrackFormulas, Broadcast(FID_DATACHANGED),
+ // ResetChanged, SetModified und Invalidate(SID_SAVEDOC/SID_DOC_MODIFIED)
+ // TrackFormulas zusaetzlich nochmal sofort, damit nicht z.B. durch IdleCalc
+ // eine Formel berechnet wird, die noch im FormulaTrack steht (#61676#)
+
+ // notify Uno objects (for XRefreshListener)
+ // must be after TrackFormulas
+ //! do this asynchronously?
+ ScLinkRefreshedHint aHint;
+ aHint.SetDdeLink( aAppl, aTopic, aItem, nMode );
+ pDoc->BroadcastUno( aHint );
+ }
+}
+
+void ScDdeLink::ResetValue()
+{
+ DELETEZ(pResult);
+
+ // Es hat sich was getan...
+ // Tracking, FID_DATACHANGED etc. passiert von aussen
+
+ if (HasListeners())
+ Broadcast( ScHint( SC_HINT_DATACHANGED, ScAddress( 0 ), NULL ) );
+}
+
+void __EXPORT ScDdeLink::Closed()
+{
+ SvBaseLink::Closed();
+}
+
+void __EXPORT ScDdeLink::ListenersGone()
+{
+ BOOL bWas = bIsInUpdate;
+ bIsInUpdate = TRUE; // Remove() kann Reschedule ausloesen??!?
+
+ SvxLinkManager* pLinkMgr = pDoc->GetLinkManager();
+ pLinkMgr->Remove(*this);
+
+ if ( !pLinkMgr->GetLinks().Count() ) // letzten geloescht ?
+ {
+ SfxBindings& rBind = SFX_BINDINGS();
+ rBind.Invalidate( SID_LINKS );
+ }
+
+ bIsInUpdate = bWas;
+}
+
+void ScDdeLink::TryUpdate()
+{
+ if (bIsInUpdate)
+ bNeedUpdate = TRUE; // kann jetzt nicht ausgefuehrt werden
+ else
+ {
+ bIsInUpdate = TRUE;
+ //Application::Reschedule(); //! OS/2-Simulation
+ Update();
+ bIsInUpdate = FALSE;
+ bNeedUpdate = FALSE;
+ }
+}
+
+
diff --git a/sc/source/core/tool/detdata.cxx b/sc/source/core/tool/detdata.cxx
new file mode 100644
index 000000000000..8770f1b33881
--- /dev/null
+++ b/sc/source/core/tool/detdata.cxx
@@ -0,0 +1,175 @@
+/*************************************************************************
+ *
+ * $RCSfile: detdata.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <tools/debug.hxx>
+
+#include "detdata.hxx"
+#include "refupdat.hxx"
+#include "rechead.hxx"
+
+//------------------------------------------------------------------------
+
+SV_IMPL_PTRARR( ScDetOpArr_Impl, ScDetOpDataPtr );
+
+//------------------------------------------------------------------------
+
+ScDetOpList::ScDetOpList(const ScDetOpList& rList)
+{
+ USHORT nCount = rList.Count();
+
+ for (USHORT i=0; i<nCount; i++)
+ Append( new ScDetOpData(*rList[i]) );
+}
+
+void ScDetOpList::UpdateReference( ScDocument* pDoc, UpdateRefMode eUpdateRefMode,
+ const ScRange& rRange, short nDx, short nDy, short nDz )
+{
+ USHORT nCount = Count();
+ for (USHORT i=0; i<nCount; i++)
+ {
+ ScAddress aPos = (*this)[i]->GetPos();
+ USHORT nCol1 = aPos.Col();
+ USHORT nRow1 = aPos.Row();
+ USHORT nTab1 = aPos.Tab();
+ USHORT nCol2 = nCol1;
+ USHORT nRow2 = nRow1;
+ USHORT nTab2 = nTab1;
+
+ ScRefUpdateRes eRes =
+ ScRefUpdate::Update( pDoc, eUpdateRefMode,
+ rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
+ rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(), nDx, nDy, nDz,
+ nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ if ( eRes != UR_NOTHING )
+ (*this)[i]->SetPos( ScAddress( nCol1, nRow1, nTab1 ) );
+ }
+}
+
+BOOL ScDetOpList::operator==( const ScDetOpList& r ) const
+{
+ // fuer Ref-Undo
+
+ USHORT nCount = Count();
+ BOOL bEqual = ( nCount == r.Count() );
+ for (USHORT i=0; i<nCount && bEqual; i++) // Reihenfolge muss auch gleich sein
+ if ( !(*(*this)[i] == *r[i]) ) // Eintraege unterschiedlich ?
+ bEqual = FALSE;
+
+ return bEqual;
+}
+
+void ScDetOpList::Load( SvStream& rStream )
+{
+ ScMultipleReadHeader aHdr( rStream );
+
+ USHORT nNewCount;
+ rStream >> nNewCount;
+
+ ScAddress aPos;
+ USHORT nOper;
+
+ for (USHORT i=0; i<nNewCount; i++)
+ {
+ // 1) Position (ScAddress)
+ // 2) Operation (USHORT)
+
+ aHdr.StartEntry();
+
+ rStream >> aPos;
+ rStream >> nOper;
+ Append( new ScDetOpData( aPos, (ScDetOpType) nOper ) );
+
+ aHdr.EndEntry();
+ }
+}
+
+void ScDetOpList::Store( SvStream& rStream ) const
+{
+ ScMultipleWriteHeader aHdr( rStream );
+
+ USHORT nCount = Count();
+ rStream << nCount;
+
+ for (USHORT i=0; i<nCount; i++)
+ {
+ // 1) Position (ScAddress)
+ // 2) Operation (USHORT)
+
+ aHdr.StartEntry();
+
+ ScDetOpData* pData = (*this)[i];
+ rStream << pData->GetPos();
+ rStream << (USHORT) pData->GetOperation();
+
+ aHdr.EndEntry();
+ }
+}
+
+
+
diff --git a/sc/source/core/tool/detfunc.cxx b/sc/source/core/tool/detfunc.cxx
new file mode 100644
index 000000000000..a4a5d44422fa
--- /dev/null
+++ b/sc/source/core/tool/detfunc.cxx
@@ -0,0 +1,1553 @@
+/*************************************************************************
+ *
+ * $RCSfile: detfunc.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <svx/eeitem.hxx>
+#include <svx/sdshitm.hxx>
+#include <svx/sdsxyitm.hxx>
+#include <svx/sdtditm.hxx>
+#include <svx/svditer.hxx>
+#include <svx/svdocapt.hxx>
+#include <svx/svdocirc.hxx>
+#include <svx/svdopath.hxx>
+#include <svx/svdorect.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdundo.hxx>
+#include <svx/xfillit0.hxx>
+#include <svx/xflclit.hxx>
+#include <svx/xlnclit.hxx>
+#include <svx/xlnedcit.hxx>
+#include <svx/xlnedit.hxx>
+#include <svx/xlnedwit.hxx>
+#include <svx/xlnstcit.hxx>
+#include <svx/xlnstit.hxx>
+#include <svx/xlnstwit.hxx>
+#include <svx/xlnwtit.hxx>
+#include <svx/xtable.hxx>
+
+#include "detfunc.hxx"
+#include "document.hxx"
+#include "dociter.hxx"
+#include "drwlayer.hxx"
+#include "userdat.hxx"
+#include "validat.hxx"
+#include "cell.hxx"
+#include "docpool.hxx"
+#include "patattr.hxx"
+#include "attrib.hxx"
+
+//------------------------------------------------------------------------
+
+// #68927# created line ends must have a name
+#define SC_LINEEND_NAME '*'
+
+//------------------------------------------------------------------------
+
+enum DetInsertResult { // Return-Werte beim Einfuegen in einen Level
+ DET_INS_CONTINUE,
+ DET_INS_INSERTED,
+ DET_INS_EMPTY,
+ DET_INS_CIRCULAR };
+
+// maximale Textlaenge (Zeichen), die noch in "kleines" Objekt passt
+#define SC_NOTE_SMALLTEXT 100
+
+//------------------------------------------------------------------------
+
+class ScPublicAttrObj : public SdrAttrObj
+{
+private:
+ ScPublicAttrObj() {} // wird nicht angelegt
+public:
+ const XLineAttrSetItem* GetLineAttr() { return pLineAttr; }
+};
+
+//------------------------------------------------------------------------
+
+class ScDetectiveData
+{
+private:
+ SfxItemSet aBoxSet;
+ SfxItemSet aArrowSet;
+ SfxItemSet aToTabSet;
+ SfxItemSet aFromTabSet;
+ SfxItemSet aCircleSet; //! einzeln ?
+ USHORT nMaxLevel;
+
+public:
+ ScDetectiveData( SdrModel* pModel );
+
+ SfxItemSet& GetBoxSet() { return aBoxSet; }
+ SfxItemSet& GetArrowSet() { return aArrowSet; }
+ SfxItemSet& GetToTabSet() { return aToTabSet; }
+ SfxItemSet& GetFromTabSet() { return aFromTabSet; }
+ SfxItemSet& GetCircleSet() { return aCircleSet; }
+
+ void SetMaxLevel( USHORT nVal ) { nMaxLevel = nVal; }
+ USHORT GetMaxLevel() const { return nMaxLevel; }
+};
+
+class ScCommentData
+{
+private:
+ SfxItemSet aCaptionSet;
+
+public:
+ ScCommentData( ScDocument* pDoc, SdrModel* pModel );
+
+ SfxItemSet& GetCaptionSet() { return aCaptionSet; }
+};
+
+//------------------------------------------------------------------------
+
+ScDetectiveData::ScDetectiveData( SdrModel* pModel ) :
+ aBoxSet( pModel->GetItemPool(), SDRATTR_START, SDRATTR_END ),
+ aArrowSet( pModel->GetItemPool(), SDRATTR_START, SDRATTR_END ),
+ aToTabSet( pModel->GetItemPool(), SDRATTR_START, SDRATTR_END ),
+ aFromTabSet( pModel->GetItemPool(), SDRATTR_START, SDRATTR_END ),
+ aCircleSet( pModel->GetItemPool(), SDRATTR_START, SDRATTR_END )
+{
+ nMaxLevel = 0;
+
+ aBoxSet.Put( XLineColorItem( EMPTY_STRING, Color( COL_LIGHTBLUE ) ) );
+ aBoxSet.Put( XFillStyleItem( XFILL_NONE ) );
+
+ // #66479# Standard-Linienenden (wie aus XLineEndList::Create) selber zusammenbasteln,
+ // um von den konfigurierten Linienenden unabhaengig zu sein
+
+ XPolygon aTriangle(3);
+ aTriangle[0].X()=10; aTriangle[0].Y()= 0;
+ aTriangle[1].X()= 0; aTriangle[1].Y()=30;
+ aTriangle[2].X()=20; aTriangle[2].Y()=30;
+
+ XPolygon aSquare(4);
+ aSquare[0].X()= 0; aSquare[0].Y()= 0;
+ aSquare[1].X()=10; aSquare[1].Y()= 0;
+ aSquare[2].X()=10; aSquare[2].Y()=10;
+ aSquare[3].X()= 0; aSquare[3].Y()=10;
+
+ XPolygon aCircle(Point(0,0),100,100);
+
+ String aName = SC_LINEEND_NAME;
+
+ aArrowSet.Put( XLineStartItem( aName, aCircle ) );
+ aArrowSet.Put( XLineStartWidthItem( 200 ) );
+ aArrowSet.Put( XLineStartCenterItem( TRUE ) );
+ aArrowSet.Put( XLineEndItem( aName, aTriangle ) );
+ aArrowSet.Put( XLineEndWidthItem( 200 ) );
+ aArrowSet.Put( XLineEndCenterItem( FALSE ) );
+
+ aToTabSet.Put( XLineStartItem( aName, aCircle ) );
+ aToTabSet.Put( XLineStartWidthItem( 200 ) );
+ aToTabSet.Put( XLineStartCenterItem( TRUE ) );
+ aToTabSet.Put( XLineEndItem( aName, aSquare ) );
+ aToTabSet.Put( XLineEndWidthItem( 300 ) );
+ aToTabSet.Put( XLineEndCenterItem( FALSE ) );
+
+ aFromTabSet.Put( XLineStartItem( aName, aSquare ) );
+ aFromTabSet.Put( XLineStartWidthItem( 300 ) );
+ aFromTabSet.Put( XLineStartCenterItem( TRUE ) );
+ aFromTabSet.Put( XLineEndItem( aName, aTriangle ) );
+ aFromTabSet.Put( XLineEndWidthItem( 200 ) );
+ aFromTabSet.Put( XLineEndCenterItem( FALSE ) );
+
+ aCircleSet.Put( XLineColorItem( String(), Color( COL_LIGHTRED ) ) );
+ aCircleSet.Put( XFillStyleItem( XFILL_NONE ) );
+ USHORT nWidth = 55; // 54 = 1 Pixel
+ aCircleSet.Put( XLineWidthItem( nWidth ) );
+}
+
+ScCommentData::ScCommentData( ScDocument* pDoc, SdrModel* pModel ) :
+ aCaptionSet( pModel->GetItemPool(), SDRATTR_START, SDRATTR_END,
+ EE_CHAR_START, EE_CHAR_END, 0 )
+{
+ XPolygon aTriangle(3);
+ aTriangle[0].X()=10; aTriangle[0].Y()= 0;
+ aTriangle[1].X()= 0; aTriangle[1].Y()=30;
+ aTriangle[2].X()=20; aTriangle[2].Y()=30;
+
+ String aName = SC_LINEEND_NAME;
+
+ aCaptionSet.Put( XLineStartItem( aName, aTriangle ) );
+ aCaptionSet.Put( XLineStartWidthItem( 200 ) );
+ aCaptionSet.Put( XLineStartCenterItem( FALSE ) );
+ aCaptionSet.Put( XFillStyleItem( XFILL_SOLID ) );
+#ifdef VCL
+ Color aYellow( 255,255,192 ); // hellgelb
+#else
+ Color aYellow( 65535,65535,49152 ); // hellgelb
+#endif
+ aCaptionSet.Put( XFillColorItem( String(), aYellow ) );
+ // Schatten
+ aCaptionSet.Put( SdrShadowItem( TRUE ) );
+ aCaptionSet.Put( SdrShadowXDistItem( 100 ) );
+ aCaptionSet.Put( SdrShadowYDistItem( 100 ) );
+ // Text
+ aCaptionSet.Put( SdrTextLeftDistItem( 100 ) );
+ aCaptionSet.Put( SdrTextRightDistItem( 100 ) );
+ aCaptionSet.Put( SdrTextUpperDistItem( 100 ) );
+ aCaptionSet.Put( SdrTextLowerDistItem( 100 ) );
+ // Font etc. aus Pattern ohne Parent - nicht GetDefaultItem( ATTR_PATTERN )
+ // (nicht die Schrift aus der Standard-Vorlage nehmen, immer harte Defaults)
+ ScPatternAttr aEmptyPat( pDoc->GetPool() );
+ aEmptyPat.FillEditItemSet( &aCaptionSet );
+}
+
+//------------------------------------------------------------------------
+
+inline BOOL Intersect( USHORT nStartCol1, USHORT nStartRow1, USHORT nEndCol1, USHORT nEndRow1,
+ USHORT nStartCol2, USHORT nStartRow2, USHORT nEndCol2, USHORT nEndRow2 )
+{
+ return nEndCol1 >= nStartCol2 && nEndCol2 >= nStartCol1 &&
+ nEndRow1 >= nStartRow2 && nEndRow2 >= nStartRow1;
+}
+
+BOOL ScDetectiveFunc::HasError( const ScTripel& rStart, const ScTripel& rEnd, ScTripel& rErrPos )
+{
+ rErrPos = rStart;
+ USHORT nError = 0;
+
+ ScCellIterator aCellIter( pDoc, rStart.GetCol(), rStart.GetRow(), rStart.GetTab(),
+ rEnd.GetCol(), rEnd.GetRow(), rEnd.GetTab() );
+ ScBaseCell* pCell = aCellIter.GetFirst();
+ while (pCell)
+ {
+ if (pCell->GetCellType() == CELLTYPE_FORMULA)
+ {
+ nError = ((ScFormulaCell*)pCell)->GetErrCode();
+ if (nError)
+ rErrPos.Put( aCellIter.GetCol(), aCellIter.GetRow(), aCellIter.GetTab() );
+ }
+ pCell = aCellIter.GetNext();
+ }
+
+ return (nError != 0);
+}
+
+Point ScDetectiveFunc::GetDrawPos( USHORT nCol, USHORT nRow, BOOL bArrow )
+{
+ // MAXCOL/ROW+1 ist erlaubt fuer Ende von Rahmen
+ if (nCol > MAXCOL+1)
+ {
+ DBG_ERROR("falsche Col in ScDetectiveFunc::GetDrawPos");
+ nCol = MAXCOL+1;
+ }
+ if (nRow > MAXROW+1)
+ {
+ DBG_ERROR("falsche Row in ScDetectiveFunc::GetDrawPos");
+ nRow = MAXROW+1;
+ }
+
+ Point aPos;
+ USHORT i;
+ USHORT nLocalTab = nTab; // nicht ueber this
+
+ for (i=0; i<nCol; i++)
+ aPos.X() += pDoc->GetColWidth( i,nLocalTab );
+ for (i=0; i<nRow; i++)
+ aPos.Y() += pDoc->FastGetRowHeight( i,nLocalTab );
+
+ if (bArrow)
+ {
+ if (nCol<=MAXCOL)
+ aPos.X() += pDoc->GetColWidth( nCol, nLocalTab ) / 4;
+ if (nCol<=MAXROW)
+ aPos.Y() += pDoc->GetRowHeight( nRow, nLocalTab ) / 2;
+ }
+
+ aPos.X() = (long) ( aPos.X() * HMM_PER_TWIPS );
+ aPos.Y() = (long) ( aPos.Y() * HMM_PER_TWIPS );
+
+ return aPos;
+}
+
+BOOL ScDetectiveFunc::HasArrow( USHORT nStartCol, USHORT nStartRow, USHORT nStartTab,
+ USHORT nEndCol, USHORT nEndRow, USHORT nEndTab )
+{
+ BOOL bStartAlien = ( nStartTab != nTab );
+ BOOL bEndAlien = ( nEndTab != nTab );
+
+ if (bStartAlien && bEndAlien)
+ {
+ DBG_ERROR("bStartAlien && bEndAlien");
+ return TRUE;
+ }
+
+ Rectangle aStartRect;
+ Rectangle aEndRect;
+ if (!bStartAlien)
+ {
+ Point aStartPos = GetDrawPos( nStartCol, nStartRow, FALSE );
+ Size aStartSize = Size(
+ (long) ( pDoc->GetColWidth( nStartCol, nTab) * HMM_PER_TWIPS ),
+ (long) ( pDoc->GetRowHeight( nStartRow, nTab) * HMM_PER_TWIPS ) );
+ aStartRect = Rectangle( aStartPos, aStartSize );
+ }
+ if (!bEndAlien)
+ {
+ Point aEndPos = GetDrawPos( nEndCol, nEndRow, FALSE );
+ Size aEndSize = Size(
+ (long) ( pDoc->GetColWidth( nEndCol, nTab) * HMM_PER_TWIPS ),
+ (long) ( pDoc->GetRowHeight( nEndRow, nTab) * HMM_PER_TWIPS ) );
+ aEndRect = Rectangle( aEndPos, aEndSize );
+ }
+
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ SdrPage* pPage = pModel->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+
+ BOOL bFound = FALSE;
+ SdrObjListIter aIter( *pPage, IM_FLAT );
+ SdrObject* pObject = aIter.Next();
+ while (pObject && !bFound)
+ {
+ if ( pObject->GetLayer()==SC_LAYER_INTERN &&
+ pObject->IsPolyObj() && pObject->GetPointCount()==2 )
+ {
+ BOOL bObjStartAlien = FALSE;
+ BOOL bObjEndAlien = FALSE;
+ const XLineAttrSetItem* pLineAttrs =
+ ((ScPublicAttrObj*)(SdrAttrObj*)pObject)->GetLineAttr();
+ if (pLineAttrs)
+ {
+ const SfxItemSet& rSet = pLineAttrs->GetItemSet();
+ bObjStartAlien = (((const XLineStartItem&)rSet.Get(XATTR_LINESTART)).
+ GetValue().GetPointCount() == 4 );
+ bObjEndAlien = (((const XLineEndItem&)rSet.Get(XATTR_LINEEND)).
+ GetValue().GetPointCount() == 4 );
+ }
+
+ BOOL bStartHit = bStartAlien ? bObjStartAlien :
+ ( !bObjStartAlien && aStartRect.IsInside(pObject->GetPoint(0)) );
+ BOOL bEndHit = bEndAlien ? bObjEndAlien :
+ ( !bObjEndAlien && aEndRect.IsInside(pObject->GetPoint(1)) );
+
+ if ( bStartHit && bEndHit )
+ bFound = TRUE;
+ }
+ pObject = aIter.Next();
+ }
+
+ return bFound;
+}
+
+BOOL ScDetectiveFunc::IsNonAlienArrow( SdrObject* pObject ) // static
+{
+ if ( pObject->GetLayer()==SC_LAYER_INTERN &&
+ pObject->IsPolyObj() && pObject->GetPointCount()==2 )
+ {
+ BOOL bObjStartAlien = FALSE;
+ BOOL bObjEndAlien = FALSE;
+ const XLineAttrSetItem* pLineAttrs =
+ ((ScPublicAttrObj*)(SdrAttrObj*)pObject)->GetLineAttr();
+ if (pLineAttrs)
+ {
+ const SfxItemSet& rSet = pLineAttrs->GetItemSet();
+ bObjStartAlien = (((const XLineStartItem&)rSet.Get(XATTR_LINESTART)).
+ GetValue().GetPointCount() == 4 );
+ bObjEndAlien = (((const XLineEndItem&)rSet.Get(XATTR_LINEEND)).
+ GetValue().GetPointCount() == 4 );
+ }
+ return !bObjStartAlien && !bObjEndAlien;
+ }
+
+ return FALSE;
+}
+
+// DrawEntry: Formel auf dieser Tabelle,
+// Referenz auf dieser oder anderer
+// DrawAlienEntry: Formel auf anderer Tabelle,
+// Referenz auf dieser
+
+// return FALSE: da war schon ein Pfeil
+
+BOOL ScDetectiveFunc::DrawEntry( USHORT nCol, USHORT nRow,
+ const ScTripel& rRefStart, const ScTripel& rRefEnd,
+ ScDetectiveData& rData )
+{
+ if ( HasArrow( rRefStart.GetCol(), rRefStart.GetRow(), rRefStart.GetTab(),
+ nCol, nRow, nTab ) )
+ return FALSE;
+
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ SdrPage* pPage = pModel->GetPage(nTab);
+
+ BOOL bArea = (rRefStart != rRefEnd);
+ BOOL bAlien = ( rRefEnd.GetTab() < nTab || rRefStart.GetTab() > nTab );
+ if (bArea && !bAlien)
+ {
+ Point aStartCorner = GetDrawPos( rRefStart.GetCol(), rRefStart.GetRow(), FALSE );
+ Point aEndCorner = GetDrawPos( rRefEnd.GetCol()+1, rRefEnd.GetRow()+1, FALSE );
+
+ SdrRectObj* pBox = new SdrRectObj(Rectangle(aStartCorner,aEndCorner));
+ pBox->SetAttributes( rData.GetBoxSet(), FALSE );
+ ScDrawLayer::SetAnchor( pBox, SCA_CELL );
+ pBox->SetLayer( SC_LAYER_INTERN );
+ pPage->InsertObject( pBox );
+ pModel->AddCalcUndo( new SdrUndoInsertObj( *pBox ) );
+
+ ScDrawObjData* pData = ScDrawLayer::GetObjData( pBox, TRUE );
+ pData->aStt = rRefStart;
+ pData->aEnd = rRefEnd;
+ pData->bValidStart = TRUE;
+ pData->bValidEnd = TRUE;
+ }
+
+ Point aStartPos = GetDrawPos( rRefStart.GetCol(), rRefStart.GetRow(), TRUE );
+ Point aEndPos = GetDrawPos( nCol, nRow, TRUE );
+
+ if (bAlien)
+ {
+ aStartPos = Point( aEndPos.X() - 1000, aEndPos.Y() - 1000 );
+ if (aStartPos.X() < 0)
+ aStartPos.X() += 2000;
+ if (aStartPos.Y() < 0)
+ aStartPos.Y() += 2000;
+ }
+
+ SfxItemSet& rAttrSet = bAlien ? rData.GetFromTabSet() : rData.GetArrowSet();
+
+ if (bArea && !bAlien)
+ rAttrSet.Put( XLineWidthItem( 50 ) ); // Bereich
+ else
+ rAttrSet.Put( XLineWidthItem( 0 ) ); // einzelne Referenz
+
+ ColorData nColorData;
+ ScTripel aErrorPos;
+ if (HasError( rRefStart, rRefEnd, aErrorPos ))
+ nColorData = COL_LIGHTRED;
+ else
+ nColorData = COL_LIGHTBLUE;
+
+ rAttrSet.Put( XLineColorItem( String(), Color( nColorData ) ) );
+ Point aPointArr[2] = {aStartPos, aEndPos};
+ SdrPathObj* pArrow = new SdrPathObj(OBJ_LINE,
+ XPolyPolygon(XPolygon(Polygon(2, aPointArr))));
+
+ pArrow->NbcSetLogicRect(Rectangle(aStartPos,aEndPos)); //! noetig ???
+
+ pArrow->SetAttributes( rAttrSet, FALSE );
+ ScDrawLayer::SetAnchor( pArrow, SCA_CELL );
+ pArrow->SetLayer( SC_LAYER_INTERN );
+ pPage->InsertObject( pArrow );
+ pModel->AddCalcUndo( new SdrUndoInsertObj( *pArrow ) );
+
+ ScDrawObjData* pData = ScDrawLayer::GetObjData( pArrow, TRUE );
+ if (bAlien)
+ pData->bValidStart = FALSE;
+ else
+ {
+ pData->aStt.nCol = rRefStart.GetCol();
+ pData->aStt.nRow = rRefStart.GetRow();
+ pData->aStt.nTab = rRefStart.GetTab();
+ pData->bValidStart = TRUE;
+ }
+
+ pData->aEnd.nCol = nCol;
+ pData->aEnd.nRow = nRow;
+ pData->aEnd.nTab = nTab;
+ pData->bValidEnd = TRUE;
+
+ return TRUE;
+}
+
+BOOL ScDetectiveFunc::DrawAlienEntry( const ScTripel& rRefStart, const ScTripel& rRefEnd,
+ ScDetectiveData& rData )
+{
+ if ( HasArrow( rRefStart.GetCol(), rRefStart.GetRow(), rRefStart.GetTab(),
+ 0, 0, nTab+1 ) )
+ return FALSE;
+
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ SdrPage* pPage = pModel->GetPage(nTab);
+
+ BOOL bArea = (rRefStart != rRefEnd);
+ if (bArea)
+ {
+ Point aStartCorner = GetDrawPos( rRefStart.GetCol(), rRefStart.GetRow(), FALSE );
+ Point aEndCorner = GetDrawPos( rRefEnd.GetCol()+1, rRefEnd.GetRow()+1, FALSE );
+
+ SdrRectObj* pBox = new SdrRectObj(Rectangle(aStartCorner,aEndCorner));
+ pBox->SetAttributes( rData.GetBoxSet(), FALSE );
+ ScDrawLayer::SetAnchor( pBox, SCA_CELL );
+ pBox->SetLayer( SC_LAYER_INTERN );
+ pPage->InsertObject( pBox );
+ pModel->AddCalcUndo( new SdrUndoInsertObj( *pBox ) );
+
+ ScDrawObjData* pData = ScDrawLayer::GetObjData( pBox, TRUE );
+ pData->aStt = rRefStart;
+ pData->aEnd = rRefEnd;
+ pData->bValidStart = TRUE;
+ pData->bValidEnd = TRUE;
+ }
+
+ Point aStartPos = GetDrawPos( rRefStart.GetCol(), rRefStart.GetRow(), TRUE );
+ Point aEndPos = Point( aStartPos.X() + 1000, aStartPos.Y() - 1000 );
+ if (aEndPos.Y() < 0)
+ aEndPos.Y() += 2000;
+
+ SfxItemSet& rAttrSet = rData.GetToTabSet();
+ if (bArea)
+ rAttrSet.Put( XLineWidthItem( 50 ) ); // Bereich
+ else
+ rAttrSet.Put( XLineWidthItem( 0 ) ); // einzelne Referenz
+
+ ColorData nColorData;
+ ScTripel aErrorPos;
+ if (HasError( rRefStart, rRefEnd, aErrorPos ))
+ nColorData = COL_LIGHTRED;
+ else
+ nColorData = COL_LIGHTBLUE;
+ rAttrSet.Put( XLineColorItem( String(), Color( nColorData ) ) );
+ Point aPointArr[2] = {aStartPos, aEndPos};
+ SdrPathObj* pArrow = new SdrPathObj(OBJ_LINE,
+ XPolyPolygon(XPolygon(Polygon(2, aPointArr))));
+
+ pArrow->NbcSetLogicRect(Rectangle(aStartPos,aEndPos)); //! noetig ???
+
+ pArrow->SetAttributes( rAttrSet, FALSE );
+ ScDrawLayer::SetAnchor( pArrow, SCA_CELL );
+ pArrow->SetLayer( SC_LAYER_INTERN );
+ pPage->InsertObject( pArrow );
+ pModel->AddCalcUndo( new SdrUndoInsertObj( *pArrow ) );
+
+ ScDrawObjData* pData = ScDrawLayer::GetObjData( pArrow, TRUE );
+ pData->aStt.nCol = rRefStart.GetCol();
+ pData->aStt.nRow = rRefStart.GetRow();
+ pData->aStt.nTab = rRefStart.GetTab();
+ pData->bValidStart = TRUE;
+ pData->bValidEnd = FALSE;
+
+ return TRUE;
+}
+
+void ScDetectiveFunc::DrawCircle( USHORT nCol, USHORT nRow, ScDetectiveData& rData )
+{
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ SdrPage* pPage = pModel->GetPage(nTab);
+
+ Point aStartPos = GetDrawPos( nCol, nRow, FALSE );
+ Size aSize( (long) ( pDoc->GetColWidth(nCol, nTab) * HMM_PER_TWIPS ),
+ (long) ( pDoc->GetRowHeight(nRow, nTab) * HMM_PER_TWIPS ) );
+ Rectangle aRect( aStartPos, aSize );
+ aRect.Left() -= 250;
+ aRect.Right() += 250;
+ aRect.Top() -= 70;
+ aRect.Bottom() += 70;
+
+ SdrCircObj* pCircle = new SdrCircObj( OBJ_CIRC, aRect );
+ SfxItemSet& rAttrSet = rData.GetCircleSet();
+ pCircle->SetAttributes( rAttrSet, FALSE );
+ ScDrawLayer::SetAnchor( pCircle, SCA_CELL );
+ pCircle->SetLayer( SC_LAYER_INTERN );
+ pPage->InsertObject( pCircle );
+ pModel->AddCalcUndo( new SdrUndoInsertObj( *pCircle ) );
+
+ ScDrawObjData* pData = ScDrawLayer::GetObjData( pCircle, TRUE );
+ pData->aStt.nCol = nCol;
+ pData->aStt.nRow = nRow;
+ pData->aStt.nTab = nTab;
+ pData->bValidStart = TRUE;
+ pData->bValidEnd = FALSE;
+}
+
+SdrObject* ScDetectiveFunc::DrawCaption( USHORT nCol, USHORT nRow, const String& rText,
+ ScCommentData& rData, SdrPage* pDestPage,
+ BOOL bHasUserText, BOOL bLeft,
+ const Rectangle& rVisible )
+{
+ ScDrawLayer* pModel = NULL; // muss ScDrawLayer* sein wegen AddCalcUndo !!!
+ SdrPage* pPage = pDestPage;
+ if (!pPage) // keine angegeben?
+ {
+ pModel = pDoc->GetDrawLayer();
+ pPage = pModel->GetPage(nTab);
+ }
+
+ USHORT nNextCol = nCol+1;
+ const ScMergeAttr* pMerge = (const ScMergeAttr*) pDoc->GetAttr( nCol,nRow,nTab, ATTR_MERGE );
+ if ( pMerge->GetColMerge() > 1 )
+ nNextCol = nCol + pMerge->GetColMerge();
+
+ Point aTailPos = GetDrawPos( nNextCol, nRow, FALSE );
+ Point aRectPos = aTailPos;
+ if ( bLeft )
+ {
+ aTailPos = GetDrawPos( nCol, nRow, FALSE );
+ aTailPos.X() += 10; // links knapp innerhalb der Zelle
+ }
+ else
+ aTailPos.X() -= 10; // knapp vor die naechste Zelle zeigen
+
+ // arrow head should be visible (if visible rectangle is set)
+ if ( aTailPos.X() > rVisible.Right() && rVisible.Right() )
+ aTailPos.X() = rVisible.Right();
+
+ aRectPos.X() += 600;
+ aRectPos.Y() -= 1500;
+ if ( aRectPos.Y() < rVisible.Top() ) aRectPos.Y() = rVisible.Top();
+
+ // links wird spaeter getestet
+
+ // bei Textlaenge > SC_NOTE_SMALLTEXT wird die Breite verdoppelt...
+ long nDefWidth = ( rText.Len() > SC_NOTE_SMALLTEXT ) ? 5800 : 2900;
+ Size aRectSize( nDefWidth, 1800 ); // Hoehe wird hinterher angepasst
+
+ long nMaxWidth = 10000; //! oder wie?
+ if ( !bHasUserText )
+ nMaxWidth = aRectSize.Width(); // Notiz nicht zu gross
+
+ if ( rVisible.Right() )
+ {
+ nMaxWidth = rVisible.Right() - aRectPos.X() - 100;
+ if (nMaxWidth < nDefWidth)
+ {
+ aRectPos.X() -= nDefWidth - nMaxWidth;
+ nMaxWidth = nDefWidth;
+ }
+ }
+ if ( aRectPos.X() < rVisible.Left() )
+ aRectPos.X() = rVisible.Left();
+
+ SdrCaptionObj* pCaption = new SdrCaptionObj( Rectangle( aRectPos,aRectSize ), aTailPos );
+ SfxItemSet& rAttrSet = rData.GetCaptionSet();
+ if (bHasUserText)
+ {
+ rAttrSet.Put(SdrTextAutoGrowWidthItem(TRUE));
+ rAttrSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT));
+ rAttrSet.Put(SdrTextMaxFrameWidthItem(nMaxWidth));
+ }
+
+ pCaption->SetAttributes( rAttrSet, FALSE );
+ ScDrawLayer::SetAnchor( pCaption, SCA_CELL );
+ pCaption->SetLayer( SC_LAYER_INTERN );
+ pPage->InsertObject( pCaption );
+
+ // #78611# for SetText, the object must already be inserted
+ pCaption->SetText( rText );
+
+ Rectangle aLogic = pCaption->GetLogicRect();
+ Rectangle aOld = aLogic;
+ if (bHasUserText)
+ pCaption->AdjustTextFrameWidthAndHeight( aLogic, TRUE, TRUE );
+ else
+ pCaption->AdjustTextFrameWidthAndHeight( aLogic, TRUE, FALSE );
+ if (rVisible.Bottom())
+ {
+ // unterer Rand kann erst nach dem AdjustTextFrameWidthAndHeight getestet werden
+ if ( aLogic.Bottom() > rVisible.Bottom() )
+ {
+ long nDif = aLogic.Bottom() - rVisible.Bottom();
+ aLogic.Bottom() = rVisible.Bottom();
+ aLogic.Top() = Max( rVisible.Top(), (long)(aLogic.Top() - nDif) );
+ }
+ }
+ if (aLogic != aOld)
+ pCaption->SetLogicRect(aLogic);
+
+ // Undo und UserData nur, wenn's im Dokument ist, also keine Page angegeben war
+ if ( !pDestPage )
+ {
+ pModel->AddCalcUndo( new SdrUndoInsertObj( *pCaption ) );
+
+ ScDrawObjData* pData = ScDrawLayer::GetObjData( pCaption, TRUE );
+ pData->aStt.nCol = nCol;
+ pData->aStt.nRow = nRow;
+ pData->aStt.nTab = nTab;
+ pData->bValidStart = TRUE;
+ pData->bValidEnd = FALSE;
+ }
+
+ return pCaption;
+}
+
+void ScDetectiveFunc::DeleteArrowsAt( USHORT nCol, USHORT nRow, BOOL bDestPnt )
+{
+ Point aPos = GetDrawPos( nCol, nRow, FALSE );
+ Size aSize = Size( (long) ( pDoc->GetColWidth( nCol, nTab) * HMM_PER_TWIPS ),
+ (long) ( pDoc->GetRowHeight( nRow, nTab) * HMM_PER_TWIPS ) );
+ Rectangle aRect( aPos, aSize );
+
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ SdrPage* pPage = pModel->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+
+ pPage->RecalcObjOrdNums();
+
+ long nDelCount = 0;
+ ULONG nObjCount = pPage->GetObjCount();
+ if (nObjCount)
+ {
+ SdrObject** ppObj = new SdrObject*[nObjCount];
+
+ SdrObjListIter aIter( *pPage, IM_FLAT );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ if ( pObject->GetLayer()==SC_LAYER_INTERN &&
+ pObject->IsPolyObj() && pObject->GetPointCount()==2 )
+ {
+ if (aRect.IsInside(pObject->GetPoint(bDestPnt))) // Start/Zielpunkt
+ ppObj[nDelCount++] = pObject;
+ }
+
+ pObject = aIter.Next();
+ }
+
+ long i;
+ for (i=1; i<=nDelCount; i++)
+ pModel->AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) );
+
+ for (i=1; i<=nDelCount; i++)
+ pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
+
+ delete[] ppObj;
+ }
+}
+
+ // Box um Referenz loeschen
+
+#define SC_DET_TOLERANCE 50
+
+inline BOOL RectIsPoints( const Rectangle& rRect, const Point& rStart, const Point& rEnd )
+{
+ return rRect.Left() >= rStart.X() - SC_DET_TOLERANCE
+ && rRect.Left() <= rStart.X() + SC_DET_TOLERANCE
+ && rRect.Right() >= rEnd.X() - SC_DET_TOLERANCE
+ && rRect.Right() <= rEnd.X() + SC_DET_TOLERANCE
+ && rRect.Top() >= rStart.Y() - SC_DET_TOLERANCE
+ && rRect.Top() <= rStart.Y() + SC_DET_TOLERANCE
+ && rRect.Bottom() >= rEnd.Y() - SC_DET_TOLERANCE
+ && rRect.Bottom() <= rEnd.Y() + SC_DET_TOLERANCE;
+}
+
+#undef SC_DET_TOLERANCE
+
+void ScDetectiveFunc::DeleteBox( USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2 )
+{
+/* String aStr;
+ aStr += nCol1;
+ aStr += '/';
+ aStr += nRow1;
+ aStr += '/';
+ aStr += nCol2;
+ aStr += '/';
+ aStr += nRow2;
+ InfoBox(0,aStr).Execute();
+*/
+
+ Point aStartCorner = GetDrawPos( nCol1, nRow1, FALSE );
+ Point aEndCorner = GetDrawPos( nCol2+1, nRow2+1, FALSE );
+ Rectangle aObjRect;
+
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ SdrPage* pPage = pModel->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+
+ pPage->RecalcObjOrdNums();
+
+ long nDelCount = 0;
+ ULONG nObjCount = pPage->GetObjCount();
+ if (nObjCount)
+ {
+ SdrObject** ppObj = new SdrObject*[nObjCount];
+
+ SdrObjListIter aIter( *pPage, IM_FLAT );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ if ( pObject->GetLayer() == SC_LAYER_INTERN &&
+ pObject->Type() == TYPE(SdrRectObj) )
+ {
+ aObjRect = ((SdrRectObj*)pObject)->GetLogicRect();
+ if ( RectIsPoints( aObjRect, aStartCorner, aEndCorner ) )
+ ppObj[nDelCount++] = pObject;
+ }
+
+ pObject = aIter.Next();
+ }
+
+ long i;
+ for (i=1; i<=nDelCount; i++)
+ pModel->AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) );
+
+ for (i=1; i<=nDelCount; i++)
+ pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
+
+ delete[] ppObj;
+ }
+}
+
+//------------------------------------------------------------------------
+
+USHORT ScDetectiveFunc::InsertPredLevelArea( const ScTripel& rRefStart, const ScTripel& rRefEnd,
+ ScDetectiveData& rData, USHORT nLevel )
+{
+ USHORT nResult = DET_INS_EMPTY;
+
+ ScCellIterator aCellIter( pDoc, rRefStart.GetCol(), rRefStart.GetRow(), rRefStart.GetTab(),
+ rRefEnd.GetCol(), rRefEnd.GetRow(), rRefEnd.GetTab() );
+ ScBaseCell* pCell = aCellIter.GetFirst();
+ while (pCell)
+ {
+ if (pCell->GetCellType() == CELLTYPE_FORMULA)
+ switch( InsertPredLevel( aCellIter.GetCol(), aCellIter.GetRow(), rData, nLevel ) )
+ {
+ case DET_INS_INSERTED:
+ nResult = DET_INS_INSERTED;
+ break;
+ case DET_INS_CONTINUE:
+ if (nResult != DET_INS_INSERTED)
+ nResult = DET_INS_CONTINUE;
+ break;
+ case DET_INS_CIRCULAR:
+ if (nResult == DET_INS_EMPTY)
+ nResult = DET_INS_CIRCULAR;
+ break;
+ }
+
+ pCell = aCellIter.GetNext();
+ }
+
+ return nResult;
+}
+
+USHORT ScDetectiveFunc::InsertPredLevel( USHORT nCol, USHORT nRow, ScDetectiveData& rData,
+ USHORT nLevel )
+{
+ ScBaseCell* pCell;
+ pDoc->GetCell( nCol, nRow, nTab, pCell );
+ if (!pCell)
+ return DET_INS_EMPTY;
+ if (pCell->GetCellType() != CELLTYPE_FORMULA)
+ return DET_INS_EMPTY;
+
+ ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
+ if (pFCell->IsRunning())
+ return DET_INS_CIRCULAR;
+
+ if (pFCell->GetDirty())
+ pFCell->Interpret(); // nach SetRunning geht's nicht mehr!
+ pFCell->SetRunning(TRUE);
+
+ USHORT nResult = DET_INS_EMPTY;
+
+ ScDetectiveRefIter aIter( (ScFormulaCell*) pCell );
+ ScTripel aRefStart;
+ ScTripel aRefEnd;
+ while ( aIter.GetNextRef( aRefStart, aRefEnd ) )
+ {
+ if (DrawEntry( nCol, nRow, aRefStart, aRefEnd, rData ))
+ {
+ nResult = DET_INS_INSERTED; // neuer Pfeil eingetragen
+ }
+ else
+ {
+ // weiterverfolgen
+
+ if ( nLevel < rData.GetMaxLevel() )
+ {
+ USHORT nSubResult;
+ BOOL bArea = (aRefStart != aRefEnd);
+ if (bArea)
+ nSubResult = InsertPredLevelArea( aRefStart, aRefEnd, rData, nLevel+1 );
+ else
+ nSubResult = InsertPredLevel( aRefStart.GetCol(), aRefStart.GetRow(),
+ rData, nLevel+1 );
+
+ switch (nSubResult)
+ {
+ case DET_INS_INSERTED:
+ nResult = DET_INS_INSERTED;
+ break;
+ case DET_INS_CONTINUE:
+ if (nResult != DET_INS_INSERTED)
+ nResult = DET_INS_CONTINUE;
+ break;
+ case DET_INS_CIRCULAR:
+ if (nResult == DET_INS_EMPTY)
+ nResult = DET_INS_CIRCULAR;
+ break;
+ // DET_INS_EMPTY: unveraendert lassen
+ }
+ }
+ else // nMaxLevel erreicht
+ if (nResult != DET_INS_INSERTED)
+ nResult = DET_INS_CONTINUE;
+ }
+ }
+
+ pFCell->SetRunning(FALSE);
+
+ return nResult;
+}
+
+USHORT ScDetectiveFunc::FindPredLevelArea( const ScTripel& rRefStart, const ScTripel& rRefEnd,
+ USHORT nLevel, USHORT nDeleteLevel )
+{
+ USHORT nResult = nLevel;
+
+ ScCellIterator aCellIter( pDoc, rRefStart.GetCol(), rRefStart.GetRow(), rRefStart.GetTab(),
+ rRefEnd.GetCol(), rRefEnd.GetRow(), rRefEnd.GetTab() );
+ ScBaseCell* pCell = aCellIter.GetFirst();
+ while (pCell)
+ {
+ if (pCell->GetCellType() == CELLTYPE_FORMULA)
+ {
+ USHORT nTemp = FindPredLevel( aCellIter.GetCol(), aCellIter.GetRow(), nLevel, nDeleteLevel );
+ if (nTemp > nResult)
+ nResult = nTemp;
+ }
+ pCell = aCellIter.GetNext();
+ }
+
+ return nResult;
+}
+
+ // nDeleteLevel != 0 -> loeschen
+
+USHORT ScDetectiveFunc::FindPredLevel( USHORT nCol, USHORT nRow, USHORT nLevel, USHORT nDeleteLevel )
+{
+ DBG_ASSERT( nLevel<1000, "Level" );
+
+ ScBaseCell* pCell;
+ pDoc->GetCell( nCol, nRow, nTab, pCell );
+ if (!pCell)
+ return nLevel;
+ if (pCell->GetCellType() != CELLTYPE_FORMULA)
+ return nLevel;
+
+ ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
+ if (pFCell->IsRunning())
+ return nLevel;
+
+ if (pFCell->GetDirty())
+ pFCell->Interpret(); // nach SetRunning geht's nicht mehr!
+ pFCell->SetRunning(TRUE);
+
+ USHORT nResult = nLevel;
+ BOOL bDelete = ( nDeleteLevel && nLevel == nDeleteLevel-1 );
+
+ if ( bDelete )
+ {
+ DeleteArrowsAt( nCol, nRow, TRUE ); // Pfeile, die hierher zeigen
+ }
+
+ ScDetectiveRefIter aIter( (ScFormulaCell*) pCell );
+ ScTripel aRefStart;
+ ScTripel aRefEnd;
+ while ( aIter.GetNextRef( aRefStart, aRefEnd ) )
+ {
+ BOOL bArea = ( aRefStart != aRefEnd );
+
+ if ( bDelete ) // Rahmen loeschen ?
+ {
+ if (bArea)
+ {
+ DeleteBox( aRefStart.GetCol(), aRefStart.GetRow(), aRefEnd.GetCol(), aRefEnd.GetRow() );
+ }
+ }
+ else // weitersuchen
+ {
+ if ( HasArrow( aRefStart.GetCol(),aRefStart.GetRow(),aRefStart.GetTab(),
+ nCol,nRow,nTab ) )
+ {
+ USHORT nTemp;
+ if (bArea)
+ nTemp = FindPredLevelArea( aRefStart, aRefEnd, nLevel+1, nDeleteLevel );
+ else
+ nTemp = FindPredLevel( aRefStart.GetCol(),aRefStart.GetRow(),
+ nLevel+1, nDeleteLevel );
+ if (nTemp > nResult)
+ nResult = nTemp;
+ }
+ }
+ }
+
+ pFCell->SetRunning(FALSE);
+
+ return nResult;
+}
+
+//------------------------------------------------------------------------
+
+USHORT ScDetectiveFunc::InsertErrorLevel( USHORT nCol, USHORT nRow, ScDetectiveData& rData,
+ USHORT nLevel )
+{
+ ScBaseCell* pCell;
+ pDoc->GetCell( nCol, nRow, nTab, pCell );
+ if (!pCell)
+ return DET_INS_EMPTY;
+ if (pCell->GetCellType() != CELLTYPE_FORMULA)
+ return DET_INS_EMPTY;
+
+ ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
+ if (pFCell->IsRunning())
+ return DET_INS_CIRCULAR;
+
+ if (pFCell->GetDirty())
+ pFCell->Interpret(); // nach SetRunning geht's nicht mehr!
+ pFCell->SetRunning(TRUE);
+
+ USHORT nResult = DET_INS_EMPTY;
+
+ ScDetectiveRefIter aIter( (ScFormulaCell*) pCell );
+ ScTripel aRefStart;
+ ScTripel aRefEnd;
+ ScTripel aErrorPos;
+ BOOL bHasError = FALSE;
+ while ( aIter.GetNextRef( aRefStart, aRefEnd ) )
+ {
+ if (HasError( aRefStart, aRefEnd, aErrorPos ))
+ {
+ bHasError = TRUE;
+ if (DrawEntry( nCol, nRow, aErrorPos, aErrorPos, rData ))
+ nResult = DET_INS_INSERTED;
+
+ // und weiterverfolgen
+
+ if ( nLevel < rData.GetMaxLevel() ) // praktisch immer
+ {
+ if (InsertErrorLevel( aErrorPos.GetCol(), aErrorPos.GetRow(),
+ rData, nLevel+1 ) == DET_INS_INSERTED)
+ nResult = DET_INS_INSERTED;
+ }
+ }
+ }
+
+ pFCell->SetRunning(FALSE);
+
+ // Blaetter ?
+ if (!bHasError)
+ if (InsertPredLevel( nCol, nRow, rData, rData.GetMaxLevel() ) == DET_INS_INSERTED)
+ nResult = DET_INS_INSERTED;
+
+ return nResult;
+}
+
+//------------------------------------------------------------------------
+
+USHORT ScDetectiveFunc::InsertSuccLevel( USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2,
+ ScDetectiveData& rData, USHORT nLevel )
+{
+ // ueber ganzes Dokument
+
+ USHORT nResult = DET_INS_EMPTY;
+// ScCellIterator aCellIter( pDoc, 0,0, nTab, MAXCOL,MAXROW, nTab );
+ ScCellIterator aCellIter( pDoc, 0,0,0, MAXCOL,MAXROW,MAXTAB ); // alle Tabellen
+ ScBaseCell* pCell = aCellIter.GetFirst();
+ while (pCell)
+ {
+ if (pCell->GetCellType() == CELLTYPE_FORMULA)
+ {
+ ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
+ BOOL bRunning = pFCell->IsRunning();
+
+ if (pFCell->GetDirty())
+ pFCell->Interpret(); // nach SetRunning geht's nicht mehr!
+ pFCell->SetRunning(TRUE);
+
+ ScDetectiveRefIter aIter( (ScFormulaCell*) pCell );
+ ScTripel aRefStart;
+ ScTripel aRefEnd;
+ while ( aIter.GetNextRef( aRefStart, aRefEnd ) )
+ {
+ if (aRefStart.GetTab() <= nTab && aRefEnd.GetTab() >= nTab)
+ {
+ if (Intersect( nCol1,nRow1,nCol2,nRow2,
+ aRefStart.GetCol(),aRefStart.GetRow(),
+ aRefEnd.GetCol(),aRefEnd.GetRow() ))
+ {
+ BOOL bAlien = ( aCellIter.GetTab() != nTab );
+ BOOL bDrawRet;
+ if (bAlien)
+ bDrawRet = DrawAlienEntry( aRefStart, aRefEnd, rData );
+ else
+ bDrawRet = DrawEntry( aCellIter.GetCol(), aCellIter.GetRow(),
+ aRefStart, aRefEnd, rData );
+ if (bDrawRet)
+ {
+ nResult = DET_INS_INSERTED; // neuer Pfeil eingetragen
+ }
+ else
+ {
+ if (bRunning)
+ {
+ if (nResult == DET_INS_EMPTY)
+ nResult = DET_INS_CIRCULAR;
+ }
+ else
+ {
+ // weiterverfolgen
+
+ if ( nLevel < rData.GetMaxLevel() )
+ {
+ USHORT nSubResult = InsertSuccLevel(
+ aCellIter.GetCol(), aCellIter.GetRow(),
+ aCellIter.GetCol(), aCellIter.GetRow(),
+ rData, nLevel+1 );
+ switch (nSubResult)
+ {
+ case DET_INS_INSERTED:
+ nResult = DET_INS_INSERTED;
+ break;
+ case DET_INS_CONTINUE:
+ if (nResult != DET_INS_INSERTED)
+ nResult = DET_INS_CONTINUE;
+ break;
+ case DET_INS_CIRCULAR:
+ if (nResult == DET_INS_EMPTY)
+ nResult = DET_INS_CIRCULAR;
+ break;
+ // DET_INS_EMPTY: unveraendert lassen
+ }
+ }
+ else // nMaxLevel erreicht
+ if (nResult != DET_INS_INSERTED)
+ nResult = DET_INS_CONTINUE;
+ }
+ }
+ }
+ }
+ }
+ pFCell->SetRunning(bRunning);
+ }
+ pCell = aCellIter.GetNext();
+ }
+
+ return nResult;
+}
+
+USHORT ScDetectiveFunc::FindSuccLevel( USHORT nCol1, USHORT nRow1, USHORT nCol2, USHORT nRow2,
+ USHORT nLevel, USHORT nDeleteLevel )
+{
+ DBG_ASSERT( nLevel<1000, "Level" );
+
+ USHORT nResult = nLevel;
+ BOOL bDelete = ( nDeleteLevel && nLevel == nDeleteLevel-1 );
+
+ ScCellIterator aCellIter( pDoc, 0,0, nTab, MAXCOL,MAXROW, nTab );
+ ScBaseCell* pCell = aCellIter.GetFirst();
+ while (pCell)
+ {
+ if (pCell->GetCellType() == CELLTYPE_FORMULA)
+ {
+ ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
+ BOOL bRunning = pFCell->IsRunning();
+
+ if (pFCell->GetDirty())
+ pFCell->Interpret(); // nach SetRunning geht's nicht mehr!
+ pFCell->SetRunning(TRUE);
+
+ ScDetectiveRefIter aIter( (ScFormulaCell*) pCell );
+ ScTripel aRefStart;
+ ScTripel aRefEnd;
+ while ( aIter.GetNextRef( aRefStart, aRefEnd ) )
+ {
+ if (aRefStart.GetTab() <= nTab && aRefEnd.GetTab() >= nTab)
+ {
+ if (Intersect( nCol1,nRow1,nCol2,nRow2,
+ aRefStart.GetCol(),aRefStart.GetRow(),
+ aRefEnd.GetCol(),aRefEnd.GetRow() ))
+ {
+ if ( bDelete ) // Pfeile, die hier anfangen
+ {
+ if (aRefStart != aRefEnd)
+ {
+ DeleteBox( aRefStart.GetCol(), aRefStart.GetRow(),
+ aRefEnd.GetCol(), aRefEnd.GetRow() );
+ }
+ DeleteArrowsAt( aRefStart.GetCol(), aRefStart.GetRow(), FALSE );
+ }
+ else if ( !bRunning &&
+ HasArrow( aRefStart.GetCol(),aRefStart.GetRow(),aRefStart.GetTab(),
+ aCellIter.GetCol(),aCellIter.GetRow(),aCellIter.GetTab() ) )
+ {
+ USHORT nTemp = FindSuccLevel( aCellIter.GetCol(), aCellIter.GetRow(),
+ aCellIter.GetCol(), aCellIter.GetRow(),
+ nLevel+1, nDeleteLevel );
+ if (nTemp > nResult)
+ nResult = nTemp;
+ }
+ }
+ }
+ }
+
+ pFCell->SetRunning(bRunning);
+ }
+ pCell = aCellIter.GetNext();
+ }
+
+ return nResult;
+}
+
+
+//
+// --------------------------------------------------------------------------------
+//
+
+BOOL ScDetectiveFunc::ShowPred( USHORT nCol, USHORT nRow )
+{
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ if (!pModel)
+ return FALSE;
+
+ SdrPage* pPage = pModel->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+
+ ScDetectiveData aData( pModel );
+
+ USHORT nMaxLevel = 0;
+ USHORT nResult = DET_INS_CONTINUE;
+ while (nResult == DET_INS_CONTINUE && nMaxLevel < 1000)
+ {
+ aData.SetMaxLevel( nMaxLevel );
+ nResult = InsertPredLevel( nCol, nRow, aData, 0 );
+ ++nMaxLevel;
+ }
+
+ return ( nResult == DET_INS_INSERTED );
+}
+
+BOOL ScDetectiveFunc::ShowSucc( USHORT nCol, USHORT nRow )
+{
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ if (!pModel)
+ return FALSE;
+
+ SdrPage* pPage = pModel->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+
+ ScDetectiveData aData( pModel );
+
+ USHORT nMaxLevel = 0;
+ USHORT nResult = DET_INS_CONTINUE;
+ while (nResult == DET_INS_CONTINUE && nMaxLevel < 1000)
+ {
+ aData.SetMaxLevel( nMaxLevel );
+ nResult = InsertSuccLevel( nCol, nRow, nCol, nRow, aData, 0 );
+ ++nMaxLevel;
+ }
+
+ return ( nResult == DET_INS_INSERTED );
+}
+
+BOOL ScDetectiveFunc::ShowError( USHORT nCol, USHORT nRow )
+{
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ if (!pModel)
+ return FALSE;
+
+ SdrPage* pPage = pModel->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+
+ ScTripel aPos( nCol, nRow, nTab );
+ ScTripel aErrPos;
+ if ( !HasError( aPos,aPos,aErrPos ) )
+ return FALSE;
+
+ ScDetectiveData aData( pModel );
+
+ aData.SetMaxLevel( 1000 );
+ USHORT nResult = InsertErrorLevel( nCol, nRow, aData, 0 );
+
+ return ( nResult == DET_INS_INSERTED );
+}
+
+BOOL ScDetectiveFunc::DeleteSucc( USHORT nCol, USHORT nRow )
+{
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ if (!pModel)
+ return FALSE;
+
+ SdrPage* pPage = pModel->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+
+ USHORT nLevelCount = FindSuccLevel( nCol, nRow, nCol, nRow, 0, 0 );
+ if ( nLevelCount )
+ FindSuccLevel( nCol, nRow, nCol, nRow, 0, nLevelCount ); // loeschen
+
+ return ( nLevelCount != 0 );
+}
+
+BOOL ScDetectiveFunc::DeletePred( USHORT nCol, USHORT nRow )
+{
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ if (!pModel)
+ return FALSE;
+
+ SdrPage* pPage = pModel->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+
+ USHORT nLevelCount = FindPredLevel( nCol, nRow, 0, 0 );
+ if ( nLevelCount )
+ FindPredLevel( nCol, nRow, 0, nLevelCount ); // loeschen
+
+ return ( nLevelCount != 0 );
+}
+
+BOOL ScDetectiveFunc::DeleteAll( ScDetectiveDelete eWhat )
+{
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ if (!pModel)
+ return FALSE;
+
+ SdrPage* pPage = pModel->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+
+ pPage->RecalcObjOrdNums();
+
+ long nDelCount = 0;
+ ULONG nObjCount = pPage->GetObjCount();
+ if (nObjCount)
+ {
+ SdrObject** ppObj = new SdrObject*[nObjCount];
+
+ SdrObjListIter aIter( *pPage, IM_FLAT );
+ SdrObject* pObject = aIter.Next();
+ while (pObject)
+ {
+ if ( pObject->GetLayer() == SC_LAYER_INTERN )
+ {
+ BOOL bDoThis = TRUE;
+ if ( eWhat != SC_DET_ALL )
+ {
+ BOOL bCircle = ( pObject->ISA(SdrCircObj) );
+ BOOL bCaption = ( pObject->ISA(SdrCaptionObj) );
+ if ( eWhat == SC_DET_DETECTIVE ) // Detektiv, aus Menue
+ bDoThis = !bCaption; // auch Kreise
+ else if ( eWhat == SC_DET_CIRCLES ) // Kreise, wenn neue erzeugt werden
+ bDoThis = bCircle;
+ else if ( eWhat == SC_DET_COMMENTS )
+ bDoThis = bCaption;
+ else
+ DBG_ERROR("wat?");
+ }
+ if ( bDoThis )
+ ppObj[nDelCount++] = pObject;
+ }
+
+ pObject = aIter.Next();
+ }
+
+ long i;
+ for (i=1; i<=nDelCount; i++)
+ pModel->AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) );
+
+ for (i=1; i<=nDelCount; i++)
+ pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
+
+ delete[] ppObj;
+ }
+
+ return ( nDelCount != 0 );
+}
+
+BOOL ScDetectiveFunc::MarkInvalid(BOOL& rOverflow)
+{
+ rOverflow = FALSE;
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ if (!pModel)
+ return FALSE;
+
+ BOOL bDeleted = DeleteAll( SC_DET_CIRCLES ); // nur die Kreise
+
+ ScDetectiveData aData( pModel );
+ long nInsCount = 0;
+
+ // Stellen suchen, wo Gueltigkeit definiert ist
+
+ ScDocAttrIterator aAttrIter( pDoc, nTab, 0,0,MAXCOL,MAXROW );
+ USHORT nCol, nRow1, nRow2;
+ const ScPatternAttr* pPattern = aAttrIter.GetNext( nCol, nRow1, nRow2 );
+ while ( pPattern && nInsCount < SC_DET_MAXCIRCLE )
+ {
+ ULONG nIndex = ((const SfxUInt32Item&)pPattern->GetItem(ATTR_VALIDDATA)).GetValue();
+ if (nIndex)
+ {
+ const ScValidationData* pData = pDoc->GetValidationEntry( nIndex );
+ if ( pData )
+ {
+ // Zellen in dem Bereich durchgehen
+
+ BOOL bMarkEmpty = !pData->IsIgnoreBlank();
+ USHORT nNextRow = nRow1;
+ USHORT nRow;
+ ScCellIterator aCellIter( pDoc, nCol,nRow1,nTab, nCol,nRow2,nTab );
+ ScBaseCell* pCell = aCellIter.GetFirst();
+ while ( pCell && nInsCount < SC_DET_MAXCIRCLE )
+ {
+ USHORT nCellRow = aCellIter.GetRow();
+ if ( bMarkEmpty )
+ for ( nRow = nNextRow; nRow < nCellRow && nInsCount < SC_DET_MAXCIRCLE; nRow++ )
+ {
+ DrawCircle( nCol, nRow, aData );
+ ++nInsCount;
+ }
+ if ( !pData->IsDataValid( pCell, ScAddress( nCol, nCellRow, nTab ) ) )
+ {
+ DrawCircle( nCol, nCellRow, aData );
+ ++nInsCount;
+ }
+ nNextRow = nCellRow + 1;
+ pCell = aCellIter.GetNext();
+ }
+ if ( bMarkEmpty )
+ for ( nRow = nNextRow; nRow <= nRow2 && nInsCount < SC_DET_MAXCIRCLE; nRow++ )
+ {
+ DrawCircle( nCol, nRow, aData );
+ ++nInsCount;
+ }
+ }
+ }
+
+ pPattern = aAttrIter.GetNext( nCol, nRow1, nRow2 );
+ }
+
+ if ( nInsCount >= SC_DET_MAXCIRCLE )
+ rOverflow = TRUE;
+
+ return ( bDeleted || nInsCount != 0 );
+}
+
+SdrObject* ScDetectiveFunc::ShowCommentUser( USHORT nCol, USHORT nRow, const String& rUserText,
+ const Rectangle& rVisible, BOOL bLeft, BOOL bForce,
+ SdrPage* pDestPage )
+{
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ if (!pModel && !pDestPage)
+ return NULL;
+
+ SdrObject* pObject = NULL;
+ ScPostIt aNote;
+ BOOL bFound = pDoc->GetNote( nCol, nRow, nTab, aNote );
+ if ( bFound || bForce || rUserText.Len() )
+ {
+ SdrModel* pDestModel = pModel;
+ if ( pDestPage )
+ pDestModel = pDestPage->GetModel();
+ ScCommentData aData( pDoc, pDestModel ); // richtigen Pool benutzen
+
+ String aNoteText = aNote.GetText(); //! Autor etc. von der Notiz?
+
+ String aDisplay;
+ BOOL bHasUser = ( rUserText.Len() != 0 );
+ if ( bHasUser )
+ {
+ aDisplay += rUserText;
+ if ( aNoteText.Len() )
+ aDisplay.AppendAscii( RTL_CONSTASCII_STRINGPARAM("\n--------\n") );
+ }
+ aDisplay += aNoteText;
+
+ pObject = DrawCaption( nCol, nRow, aDisplay, aData, pDestPage, bHasUser, bLeft, rVisible );
+ }
+
+ return pObject;
+}
+
+SdrObject* ScDetectiveFunc::ShowComment( USHORT nCol, USHORT nRow, BOOL bForce, SdrPage* pDestPage )
+{
+ return ShowCommentUser( nCol, nRow, String(), Rectangle(0,0,0,0), FALSE, bForce, pDestPage );
+}
+
+BOOL ScDetectiveFunc::HideComment( USHORT nCol, USHORT nRow )
+{
+ ScDrawLayer* pModel = pDoc->GetDrawLayer();
+ if (!pModel)
+ return FALSE;
+ SdrPage* pPage = pModel->GetPage(nTab);
+ DBG_ASSERT(pPage,"Page ?");
+
+ pPage->RecalcObjOrdNums();
+ BOOL bDone = FALSE;
+
+ SdrObjListIter aIter( *pPage, IM_FLAT );
+ SdrObject* pObject = aIter.Next();
+ while (pObject && !bDone)
+ {
+ if ( pObject->GetLayer() == SC_LAYER_INTERN && pObject->ISA( SdrCaptionObj ) )
+ {
+ ScDrawObjData* pData = ScDrawLayer::GetObjData( pObject );
+ if ( pData && nCol == pData->aStt.nCol && nRow == pData->aStt.nRow )
+ {
+ pModel->AddCalcUndo( new SdrUndoRemoveObj( *pObject ) );
+ pPage->RemoveObject( pObject->GetOrdNum() );
+ bDone = TRUE;
+ }
+ }
+
+ pObject = aIter.Next();
+ }
+
+ return bDone;
+}
+
+
+
diff --git a/sc/source/core/tool/docoptio.cxx b/sc/source/core/tool/docoptio.cxx
new file mode 100644
index 000000000000..f0f5a9a59271
--- /dev/null
+++ b/sc/source/core/tool/docoptio.cxx
@@ -0,0 +1,337 @@
+/*************************************************************************
+ *
+ * $RCSfile: docoptio.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include <vcl/svapp.hxx>
+#include <svtools/zforlist.hxx>
+
+#include "cfgids.hxx"
+#include "docoptio.hxx"
+#include "rechead.hxx"
+#include "scresid.hxx"
+#include "sc.hrc"
+
+//------------------------------------------------------------------------
+
+#define SC_VERSION ((USHORT)251)
+
+TYPEINIT1(ScTpCalcItem, SfxPoolItem);
+
+//------------------------------------------------------------------------
+
+USHORT lcl_GetDefaultTabDist()
+{
+ MeasurementSystem eSys = Application::GetAppInternational().GetMeasurementSystem();
+ if ( eSys == MEASURE_METRIC )
+ return 709; // 1,25 cm
+ else
+ return 720; // 1/2"
+}
+
+//========================================================================
+// ScDocOptions - Dokument-Optionen
+//========================================================================
+
+ScDocOptions::ScDocOptions()
+{
+ ResetDocOptions();
+}
+
+//------------------------------------------------------------------------
+
+ScDocOptions::ScDocOptions( const ScDocOptions& rCpy )
+ : bIsIgnoreCase( rCpy.bIsIgnoreCase ),
+ bIsIter( rCpy.bIsIter ),
+ nIterCount( rCpy.nIterCount ),
+ fIterEps( rCpy.fIterEps ),
+ nPrecStandardFormat( rCpy.nPrecStandardFormat ),
+ nDay( rCpy.nDay ),
+ nMonth( rCpy.nMonth ),
+ nYear( rCpy.nYear ),
+ nYear2000( rCpy.nYear2000 ),
+ nTabDistance( rCpy.nTabDistance ),
+ bCalcAsShown( rCpy.bCalcAsShown ),
+ bMatchWholeCell( rCpy.bMatchWholeCell ),
+ bDoAutoSpell( rCpy.bDoAutoSpell ),
+ bLookUpColRowNames( rCpy.bLookUpColRowNames )
+{
+}
+
+//------------------------------------------------------------------------
+
+ScDocOptions::~ScDocOptions()
+{
+}
+
+//------------------------------------------------------------------------
+
+void ScDocOptions::Save(SvStream& rStream, BOOL bConfig) const
+{
+ ScWriteHeader aHdr( rStream, 28 );
+
+ rStream << bIsIgnoreCase;
+ rStream << bIsIter;
+ rStream << nIterCount;
+ rStream << fIterEps;
+ rStream << nPrecStandardFormat;
+ rStream << nDay;
+ rStream << nMonth;
+ rStream << nYear;
+ rStream << nTabDistance;
+ rStream << bCalcAsShown;
+ rStream << bMatchWholeCell;
+ rStream << bDoAutoSpell;
+ rStream << bLookUpColRowNames;
+
+ if ( bConfig || rStream.GetVersion() > SOFFICE_FILEFORMAT_40 ) // nicht bei 4.0 Export
+ {
+ if ( !bConfig && 1901 <= nYear2000 && nYear2000 <= 1999 )
+ { // fuer SO5 auf altes Format zweistellig abbilden
+ rStream << (USHORT) (nYear2000 - 1901);
+ }
+ else
+ { // neues Format vierstellig, beliebiges Jahrhundert
+ // erzeugt in SO5 vor src513e ein Warning beim Laden
+ rStream << (USHORT) 29; // Dummy, alter SO5 Default
+ rStream << nYear2000; // echter Wert
+ }
+ }
+}
+
+void ScDocOptions::Load(SvStream& rStream)
+{
+ ScReadHeader aHdr( rStream );
+
+ rStream >> bIsIgnoreCase;
+ rStream >> bIsIter;
+ rStream >> nIterCount;
+ rStream >> fIterEps;
+ rStream >> nPrecStandardFormat;
+ rStream >> nDay;
+ rStream >> nMonth;
+ rStream >> nYear;
+ if ( aHdr.BytesLeft() )
+ rStream >> nTabDistance;
+ else
+ nTabDistance = lcl_GetDefaultTabDist();
+ if ( aHdr.BytesLeft() )
+ rStream >> bCalcAsShown;
+ else
+ bCalcAsShown = FALSE;
+ if ( aHdr.BytesLeft() )
+ rStream >> bMatchWholeCell;
+ else
+ bMatchWholeCell = FALSE;
+ if ( aHdr.BytesLeft() )
+ rStream >> bDoAutoSpell;
+ else
+ bDoAutoSpell = FALSE;
+ if ( aHdr.BytesLeft() )
+ rStream >> bLookUpColRowNames;
+ else
+ bLookUpColRowNames = TRUE;
+ if ( aHdr.BytesLeft() )
+ {
+ rStream >> nYear2000; // SO5 ab 24.06.98
+ // SO51 ab src513e
+ if ( aHdr.BytesLeft() )
+ rStream >> nYear2000; // der echte Wert
+ else
+ nYear2000 += 1901; // altes zweistelliges auf neues vierstelliges
+ }
+ else
+ nYear2000 = 18 + 1901; // alter Wert vor SO5
+}
+
+void ScDocOptions::ResetDocOptions()
+{
+ bIsIgnoreCase = FALSE;
+ bIsIter = FALSE;
+ nIterCount = 100;
+ fIterEps = 1.0E-3;
+ nPrecStandardFormat = 2;
+ nDay = 30;
+ nMonth = 12;
+ nYear = 1899;
+ nYear2000 = SvNumberFormatter::GetYear2000Default();
+ nTabDistance = lcl_GetDefaultTabDist();
+ bCalcAsShown = FALSE;
+ bMatchWholeCell = TRUE;
+ bDoAutoSpell = FALSE;
+ bLookUpColRowNames = TRUE;
+}
+
+//========================================================================
+// ScTpCalcItem - Daten fuer die CalcOptions-TabPage
+//========================================================================
+
+ScTpCalcItem::ScTpCalcItem( USHORT nWhich ) : SfxPoolItem( nWhich )
+{
+}
+
+//------------------------------------------------------------------------
+
+ScTpCalcItem::ScTpCalcItem( USHORT nWhich, const ScDocOptions& rOpt )
+ : SfxPoolItem ( nWhich ),
+ theOptions ( rOpt )
+{
+}
+
+//------------------------------------------------------------------------
+
+ScTpCalcItem::ScTpCalcItem( const ScTpCalcItem& rItem )
+ : SfxPoolItem ( rItem ),
+ theOptions ( rItem.theOptions )
+{
+}
+
+//------------------------------------------------------------------------
+
+__EXPORT ScTpCalcItem::~ScTpCalcItem()
+{
+}
+
+//------------------------------------------------------------------------
+
+String __EXPORT ScTpCalcItem::GetValueText() const
+{
+ return String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("ScTpCalcItem") );
+}
+
+//------------------------------------------------------------------------
+
+int __EXPORT ScTpCalcItem::operator==( const SfxPoolItem& rItem ) const
+{
+ DBG_ASSERT( SfxPoolItem::operator==( rItem ), "unequal Which or Type" );
+
+ const ScTpCalcItem& rPItem = (const ScTpCalcItem&)rItem;
+
+ return ( theOptions == rPItem.theOptions );
+}
+
+//------------------------------------------------------------------------
+
+SfxPoolItem* __EXPORT ScTpCalcItem::Clone( SfxItemPool * ) const
+{
+ return new ScTpCalcItem( *this );
+}
+
+//==================================================================
+// CfgItem fuer Doc-Optionen
+//==================================================================
+
+ScDocCfg::ScDocCfg() : SfxConfigItem( SCCFG_DOC )
+{
+}
+
+//------------------------------------------------------------------------
+
+int __EXPORT ScDocCfg::Load( SvStream& rStream )
+{
+ USHORT nVersion;
+
+ rStream >> nVersion;
+ ScDocOptions::Load( rStream );
+
+ SetDefault( FALSE );
+
+ return ( nVersion == SC_VERSION )
+ ? SfxConfigItem::ERR_OK
+ : SfxConfigItem::WARNING_VERSION;
+}
+
+//------------------------------------------------------------------------
+
+BOOL __EXPORT ScDocCfg::Store( SvStream& rStream)
+{
+ // TRUE = alles speichern, unabhaengig von der Stream-Version
+ // (am Config-Stream ist noch SOFFICE_FILEFORMAT_40 eingestellt)
+
+ rStream << SC_VERSION;
+ ScDocOptions::Save( rStream, TRUE );
+
+ SetDefault( FALSE );
+
+ return SfxConfigItem::ERR_OK;
+}
+
+//------------------------------------------------------------------------
+
+void __EXPORT ScDocCfg::UseDefault()
+{
+ ResetDocOptions();
+ SetDefault( TRUE );
+}
+
+//------------------------------------------------------------------------
+
+String __EXPORT ScDocCfg::GetName() const
+{
+ return String( ScResId( SCSTR_CFG_DOC ) );
+}
+
+
+
diff --git a/sc/source/core/tool/editutil.cxx b/sc/source/core/tool/editutil.cxx
new file mode 100644
index 000000000000..7facad606f73
--- /dev/null
+++ b/sc/source/core/tool/editutil.cxx
@@ -0,0 +1,655 @@
+/*************************************************************************
+ *
+ * $RCSfile: editutil.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+// System - Includes -----------------------------------------------------
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <svx/eeitem.hxx>
+#define ITEMID_FIELD EE_FEATURE_FIELD
+
+#include <svx/algitem.hxx>
+#include <svx/editview.hxx>
+#include <svx/editstat.hxx>
+#include <svx/escpitem.hxx>
+#include <svx/flditem.hxx>
+#include <vcl/system.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/outdev.hxx>
+
+#include "editutil.hxx"
+#include "global.hxx"
+#include "attrib.hxx"
+#include "document.hxx"
+#include "docpool.hxx"
+#include "patattr.hxx"
+
+// STATIC DATA -----------------------------------------------------------
+
+// Delimiters zusaetzlich zu EditEngine-Default:
+
+const sal_Char __FAR_DATA ScEditUtil::pCalcDelimiters[] = "=();+-*/^&<>";
+
+
+//------------------------------------------------------------------------
+
+String ScEditUtil::ModifyDelimiters( const String& rOld )
+{
+ String aRet = rOld;
+ aRet.EraseAllChars( '_' ); // underscore is used in function argument names
+ aRet.AppendAscii( RTL_CONSTASCII_STRINGPARAM( pCalcDelimiters ) );
+ return aRet;
+}
+
+String ScEditUtil::GetSpaceDelimitedString( const EditEngine& rEngine )
+{
+ String aRet;
+ USHORT nParCount = rEngine.GetParagraphCount();
+ for (USHORT nPar=0; nPar<nParCount; nPar++)
+ {
+ if (nPar > 0)
+ aRet += ' ';
+ aRet += rEngine.GetText( nPar );
+ }
+ return aRet;
+}
+
+//------------------------------------------------------------------------
+
+Rectangle ScEditUtil::GetEditArea( const ScPatternAttr* pPattern )
+{
+ USHORT i;
+
+ if (!pPattern)
+ pPattern = pDoc->GetPattern( nCol, nRow, nTab );
+
+ Point aStartPos = aScrPos;
+
+ const ScMergeAttr* pMerge = (const ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE);
+ long nCellX = (long) ( pDoc->GetColWidth(nCol,nTab) * nPPTX );
+ if ( pMerge->GetColMerge() > 1 )
+ {
+ USHORT nCountX = pMerge->GetColMerge();
+ for (i=1; i<nCountX; i++)
+ nCellX += (long) ( pDoc->GetColWidth(nCol+i,nTab) * nPPTX );
+ }
+ long nCellY = (long) ( pDoc->GetRowHeight(nRow,nTab) * nPPTY );
+ if ( pMerge->GetRowMerge() > 1 )
+ {
+ USHORT nCountY = pMerge->GetRowMerge();
+ for (i=1; i<nCountY; i++)
+ nCellY += (long) ( pDoc->GetRowHeight(nRow+i,nTab) * nPPTY );
+ }
+
+ const SvxMarginItem* pMargin = (const SvxMarginItem*)&pPattern->GetItem(ATTR_MARGIN);
+ USHORT nIndent = 0;
+ if ( ((const SvxHorJustifyItem&)pPattern->GetItem(ATTR_HOR_JUSTIFY)).GetValue() ==
+ SVX_HOR_JUSTIFY_LEFT )
+ nIndent = ((const SfxUInt16Item&)pPattern->GetItem(ATTR_INDENT)).GetValue();
+ long nPixDifX = (long) ( ( pMargin->GetLeftMargin() + nIndent ) * nPPTX );
+ aStartPos.X() += nPixDifX;
+ nCellX -= nPixDifX + (long) ( pMargin->GetRightMargin() * nPPTX ); // wegen Umbruch etc.
+
+ // vertikale Position auf die in der Tabelle anpassen
+
+ long nPixDifY;
+ long nTopMargin = (long) ( pMargin->GetTopMargin() * nPPTY );
+ SvxCellVerJustify eJust = (SvxCellVerJustify) ((const SvxVerJustifyItem&)pPattern->
+ GetItem(ATTR_VER_JUSTIFY)).GetValue();
+ if ( eJust == SVX_VER_JUSTIFY_TOP )
+ nPixDifY = nTopMargin;
+ else
+ {
+// MapMode aMode = pDev->SetMapMode( MAP_PIXEL );
+ long nTextHeight = pDoc->GetNeededSize( nCol, nRow, nTab,
+ pDev, nPPTX, nPPTY, aZoomX, aZoomY, FALSE );
+ if (!nTextHeight)
+ { // leere Zelle
+ Font aFont;
+ pPattern->GetFont( aFont, pDev, &aZoomY );
+ pDev->SetFont(aFont);
+ nTextHeight = pDev->GetTextHeight() + nTopMargin +
+ (long) ( pMargin->GetBottomMargin() * nPPTY );
+ }
+// pDev->SetMapMode(aMode);
+
+ if ( nTextHeight > nCellY + nTopMargin )
+ nPixDifY = 0; // zu gross -> oben anfangen
+ else
+ {
+ if ( eJust == SVX_VER_JUSTIFY_CENTER )
+ nPixDifY = nTopMargin + ( nCellY - nTextHeight ) / 2;
+ else
+ nPixDifY = nCellY - nTextHeight + nTopMargin; // JUSTIFY_BOTTOM
+ }
+ }
+
+ aStartPos.Y() += nPixDifY;
+ nCellY -= nPixDifY;
+
+ // -1 -> Gitter nicht ueberschreiben
+ return Rectangle( aStartPos, Size(nCellX-1,nCellY-1) );
+}
+
+//------------------------------------------------------------------------
+
+ScEditAttrTester::ScEditAttrTester( EditEngine* pEng ) :
+ pEngine( pEng ),
+ pEditAttrs( NULL ),
+ bNeedsObject( FALSE ),
+ bNeedsCellAttr( FALSE )
+{
+ if ( pEngine->GetParagraphCount() > 1 )
+ {
+ bNeedsObject = TRUE; //! Zellatribute finden ?
+ }
+ else
+ {
+ const SfxPoolItem* pItem = NULL;
+ pEditAttrs = new SfxItemSet( pEngine->GetAttribs(
+ ESelection(0,0,0,pEngine->GetTextLen(0)) ) );
+ const SfxItemPool* pEditPool = pEditAttrs->GetPool();
+
+ for (USHORT nId = EE_CHAR_START; nId <= EE_CHAR_END && !bNeedsObject; nId++)
+ {
+ SfxItemState eState = pEditAttrs->GetItemState( nId, FALSE, &pItem );
+ if (eState == SFX_ITEM_DONTCARE)
+ bNeedsObject = TRUE;
+ else if (eState == SFX_ITEM_SET)
+ {
+ if ( nId == EE_CHAR_ESCAPEMENT ) // Hoch-/Tiefstellen immer ueber EE
+ {
+ if ( (SvxEscapement)((const SvxEscapementItem*)pItem)->GetEnumValue()
+ != SVX_ESCAPEMENT_OFF )
+ bNeedsObject = TRUE;
+ }
+ else
+ if (!bNeedsCellAttr)
+ if ( *pItem != pEditPool->GetDefaultItem(nId) )
+ bNeedsCellAttr = TRUE;
+ // SetDefaults an der EditEngine setzt Pool-Defaults
+ }
+ }
+
+ // Feldbefehle enthalten?
+
+ SfxItemState eFieldState = pEditAttrs->GetItemState( EE_FEATURE_FIELD, FALSE );
+ if ( eFieldState == SFX_ITEM_DONTCARE || eFieldState == SFX_ITEM_SET )
+ bNeedsObject = TRUE;
+
+ // not converted characters?
+
+ SfxItemState eConvState = pEditAttrs->GetItemState( EE_FEATURE_NOTCONV, FALSE );
+ if ( eConvState == SFX_ITEM_DONTCARE || eConvState == SFX_ITEM_SET )
+ bNeedsObject = TRUE;
+ }
+}
+
+ScEditAttrTester::~ScEditAttrTester()
+{
+ delete pEditAttrs;
+}
+
+
+//------------------------------------------------------------------------
+
+ScEnginePoolHelper::ScEnginePoolHelper( SfxItemPool* pEnginePoolP,
+ BOOL bDeleteEnginePoolP )
+ :
+ pEnginePool( pEnginePoolP ),
+ bDeleteEnginePool( bDeleteEnginePoolP ),
+ pDefaults( NULL ),
+ bDeleteDefaults( FALSE )
+{
+}
+
+
+ScEnginePoolHelper::ScEnginePoolHelper( const ScEnginePoolHelper& rOrg )
+ :
+ pEnginePool( rOrg.bDeleteEnginePool ? rOrg.pEnginePool->Clone() : rOrg.pEnginePool ),
+ bDeleteEnginePool( rOrg.bDeleteEnginePool ),
+ pDefaults( NULL ),
+ bDeleteDefaults( FALSE )
+{
+}
+
+
+ScEnginePoolHelper::~ScEnginePoolHelper()
+{
+ if ( bDeleteDefaults )
+ delete pDefaults;
+ if ( bDeleteEnginePool )
+ delete pEnginePool;
+}
+
+
+//------------------------------------------------------------------------
+
+ScEditEngineDefaulter::ScEditEngineDefaulter( SfxItemPool* pEnginePoolP,
+ BOOL bDeleteEnginePoolP )
+ :
+ ScEnginePoolHelper( pEnginePoolP, bDeleteEnginePoolP ),
+ EditEngine( pEnginePoolP )
+{
+}
+
+
+ScEditEngineDefaulter::ScEditEngineDefaulter( const ScEditEngineDefaulter& rOrg )
+ :
+ ScEnginePoolHelper( rOrg ),
+ EditEngine( pEnginePool )
+{
+}
+
+
+ScEditEngineDefaulter::~ScEditEngineDefaulter()
+{
+}
+
+
+void ScEditEngineDefaulter::SetDefaults( const SfxItemSet& rSet, BOOL bRememberCopy )
+{
+ if ( bRememberCopy )
+ {
+ if ( bDeleteDefaults )
+ delete pDefaults;
+ pDefaults = new SfxItemSet( rSet );
+ bDeleteDefaults = TRUE;
+ }
+ const SfxItemSet& rNewSet = bRememberCopy ? *pDefaults : rSet;
+ BOOL bUndo = IsUndoEnabled();
+ EnableUndo( FALSE );
+ USHORT nPara = GetParagraphCount();
+ for ( USHORT j=0; j<nPara; j++ )
+ {
+ SetParaAttribs( j, rNewSet );
+ }
+ if ( bUndo )
+ EnableUndo( TRUE );
+}
+
+
+void ScEditEngineDefaulter::SetDefaults( SfxItemSet* pSet, BOOL bTakeOwnership )
+{
+ if ( bDeleteDefaults )
+ delete pDefaults;
+ pDefaults = pSet;
+ bDeleteDefaults = bTakeOwnership;
+ if ( pDefaults )
+ SetDefaults( *pDefaults, FALSE );
+}
+
+
+void ScEditEngineDefaulter::SetDefaultItem( const SfxPoolItem& rItem )
+{
+ if ( !pDefaults )
+ {
+ pDefaults = new SfxItemSet( GetEmptyItemSet() );
+ bDeleteDefaults = TRUE;
+ }
+ pDefaults->Put( rItem );
+ SetDefaults( *pDefaults, FALSE );
+}
+
+
+void ScEditEngineDefaulter::SetText( const EditTextObject& rTextObject )
+{
+ EditEngine::SetText( rTextObject );
+ if ( pDefaults )
+ SetDefaults( *pDefaults, FALSE );
+}
+
+
+void ScEditEngineDefaulter::SetTextNewDefaults( const EditTextObject& rTextObject,
+ const SfxItemSet& rSet, BOOL bRememberCopy )
+{
+ EditEngine::SetText( rTextObject );
+ SetDefaults( rSet, bRememberCopy );
+}
+
+
+void ScEditEngineDefaulter::SetText( const String& rText )
+{
+ EditEngine::SetText( rText );
+ if ( pDefaults )
+ SetDefaults( *pDefaults, FALSE );
+}
+
+
+void ScEditEngineDefaulter::SetTextNewDefaults( const String& rText,
+ const SfxItemSet& rSet, BOOL bRememberCopy )
+{
+ EditEngine::SetText( rText );
+ SetDefaults( rSet, bRememberCopy );
+}
+
+
+//------------------------------------------------------------------------
+
+ScTabEditEngine::ScTabEditEngine( ScDocument* pDoc )
+ : ScEditEngineDefaulter( pDoc->GetEnginePool() )
+{
+ SetEditTextObjectPool( pDoc->GetEditPool() );
+ Init((const ScPatternAttr&)pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN));
+}
+
+ScTabEditEngine::ScTabEditEngine( const ScPatternAttr& rPattern,
+ SfxItemPool* pEnginePool, SfxItemPool* pTextObjectPool )
+ : ScEditEngineDefaulter( pEnginePool )
+{
+ if ( pTextObjectPool )
+ SetEditTextObjectPool( pTextObjectPool );
+ Init( rPattern );
+}
+
+void ScTabEditEngine::Init( const ScPatternAttr& rPattern )
+{
+ SetRefMapMode(MAP_100TH_MM);
+ SfxItemSet* pEditDefaults = new SfxItemSet( GetEmptyItemSet() );
+ rPattern.FillEditItemSet( pEditDefaults );
+ SetDefaults( pEditDefaults );
+ // wir haben keine StyleSheets fuer Text
+ SetControlWord( GetControlWord() & ~EE_CNTRL_RTFSTYLESHEETS );
+}
+
+//------------------------------------------------------------------------
+// Feldbefehle fuer Kopf- und Fusszeilen
+//------------------------------------------------------------------------
+
+//
+// Zahlen aus \sw\source\core\doc\numbers.cxx
+//
+
+String lcl_GetRomanStr( USHORT nNo )
+{
+ String aStr;
+ if( nNo < 4000 ) // mehr kann nicht dargestellt werden
+ {
+// i, ii, iii, iv, v, vi, vii, vii, viii, ix
+// (Dummy),1000,500,100,50,10,5,1
+ sal_Char *cRomanArr = "mdclxvi--"; // +2 Dummy-Eintraege !!
+ USHORT nMask = 1000;
+ while( nMask )
+ {
+ BYTE nZahl = BYTE(nNo / nMask);
+ BYTE nDiff = 1;
+ nNo %= nMask;
+
+ if( 5 < nZahl )
+ {
+ if( nZahl < 9 )
+ aStr += *(cRomanArr-1);
+ ++nDiff;
+ nZahl -= 5;
+ }
+ switch( nZahl )
+ {
+ case 3: { aStr += *cRomanArr; }
+ case 2: { aStr += *cRomanArr; }
+ case 1: { aStr += *cRomanArr; }
+ break;
+
+ case 4: {
+ aStr += *cRomanArr;
+ aStr += *(cRomanArr-nDiff);
+ }
+ break;
+ case 5: { aStr += *(cRomanArr-nDiff); }
+ break;
+ }
+
+ nMask /= 10; // zur naechsten Dekade
+ cRomanArr += 2;
+ }
+ }
+ return aStr;
+}
+
+String lcl_GetCharStr( USHORT nNo )
+{
+ DBG_ASSERT( nNo, "0 ist eine ungueltige Nummer !!" );
+ String aStr;
+
+ const USHORT coDiff = 'Z' - 'A' +1;
+ USHORT nCalc;
+
+ do {
+ nCalc = nNo % coDiff;
+ if( !nCalc )
+ nCalc = coDiff;
+ aStr.Insert( (sal_Unicode)('a' - 1 + nCalc ), 0 );
+ nNo -= nCalc;
+ if( nNo )
+ nNo /= coDiff;
+ } while( nNo );
+ return aStr;
+}
+
+String lcl_GetNumStr( USHORT nNo, SvxNumType eType )
+{
+ String aTmpStr( '0' );
+ if( nNo )
+ {
+ switch( eType )
+ {
+ case SVX_CHARS_UPPER_LETTER:
+ case SVX_CHARS_LOWER_LETTER:
+ aTmpStr = lcl_GetCharStr( nNo );
+ break;
+
+ case SVX_ROMAN_UPPER:
+ case SVX_ROMAN_LOWER:
+ aTmpStr = lcl_GetRomanStr( nNo );
+ break;
+
+ case SVX_NUMBER_NONE:
+ aTmpStr.Erase();
+ break;
+
+// CHAR_SPECIAL:
+// ????
+
+// case ARABIC: ist jetzt default
+ default:
+ aTmpStr = String::CreateFromInt32( nNo );
+ break;
+ }
+
+ if( SVX_CHARS_UPPER_LETTER == eType || SVX_ROMAN_UPPER == eType )
+ aTmpStr.ToUpperAscii();
+ }
+ return aTmpStr;
+}
+
+ScHeaderFieldData::ScHeaderFieldData()
+{
+ nPageNo = nTotalPages = 0;
+ eNumType = SVX_ARABIC;
+}
+
+ScHeaderEditEngine::ScHeaderEditEngine( SfxItemPool* pEnginePool, BOOL bDeleteEnginePool )
+ : ScEditEngineDefaulter( pEnginePool, bDeleteEnginePool )
+{
+}
+
+String __EXPORT ScHeaderEditEngine::CalcFieldValue( const SvxFieldItem& rField,
+ USHORT nPara, USHORT nPos,
+ Color*& rTxtColor, Color*& rFldColor )
+{
+ String aRet;
+ const SvxFieldData* pFieldData = rField.GetField();
+ if ( pFieldData )
+ {
+ TypeId aType = pFieldData->Type();
+ if (aType == TYPE(SvxPageField))
+ aRet = lcl_GetNumStr( (USHORT)aData.nPageNo,aData.eNumType );
+ else if (aType == TYPE(SvxPagesField))
+ aRet = lcl_GetNumStr( (USHORT)aData.nTotalPages,aData.eNumType );
+ else if (aType == TYPE(SvxTimeField))
+ aRet = Application::GetAppInternational().GetTime(aData.aTime);
+ else if (aType == TYPE(SvxFileField))
+ aRet = aData.aTitle;
+ else if (aType == TYPE(SvxExtFileField))
+ {
+ switch ( ((const SvxExtFileField*)pFieldData)->GetFormat() )
+ {
+ case SVXFILEFORMAT_FULLPATH :
+ aRet = aData.aLongDocName;
+ break;
+ default:
+ aRet = aData.aShortDocName;
+ }
+ }
+ else if (aType == TYPE(SvxTableField))
+ aRet = aData.aTabName;
+ else if (aType == TYPE(SvxDateField))
+ aRet = Application::GetAppInternational().GetDate(aData.aDate);
+ else
+ {
+ DBG_ERROR("unbekannter Feldbefehl");
+ aRet = '?';
+ }
+ }
+ else
+ {
+ DBG_ERROR("FieldData ist 0");
+ aRet = '?';
+ }
+
+ return aRet;
+}
+
+//------------------------------------------------------------------------
+//
+// Feld-Daten
+//
+//------------------------------------------------------------------------
+
+ScFieldEditEngine::ScFieldEditEngine( SfxItemPool* pEnginePool,
+ SfxItemPool* pTextObjectPool, BOOL bDeleteEnginePool )
+ :
+ ScEditEngineDefaulter( pEnginePool, bDeleteEnginePool ),
+ bExecuteURL( TRUE )
+{
+ if ( pTextObjectPool )
+ SetEditTextObjectPool( pTextObjectPool );
+ // EE_CNTRL_URLSFXEXECUTE nicht, weil die Edit-Engine den ViewFrame nicht kennt
+ // wir haben keine StyleSheets fuer Text
+ SetControlWord( (GetControlWord() | EE_CNTRL_MARKFIELDS) & ~EE_CNTRL_RTFSTYLESHEETS );
+}
+
+String __EXPORT ScFieldEditEngine::CalcFieldValue( const SvxFieldItem& rField,
+ USHORT nPara, USHORT nPos,
+ Color*& rTxtColor, Color*& rFldColor )
+{
+ String aRet;
+ const SvxFieldData* pFieldData = rField.GetField();
+
+ if ( pFieldData )
+ {
+ TypeId aType = pFieldData->Type();
+
+ if (aType == TYPE(SvxURLField))
+ {
+ switch ( ((const SvxURLField*)pFieldData)->GetFormat() )
+ {
+ case SVXURLFORMAT_APPDEFAULT: //!!! einstellbar an App???
+ case SVXURLFORMAT_REPR:
+ aRet = ((const SvxURLField*)pFieldData)->GetRepresentation();
+ break;
+
+ case SVXURLFORMAT_URL:
+ aRet = ((const SvxURLField*)pFieldData)->GetURL();
+ break;
+ }
+ rTxtColor = new Color( COL_LIGHTBLUE ); //!!! woher nehmen???
+ }
+ else
+ {
+ DBG_ERROR("unbekannter Feldbefehl");
+ aRet = '?';
+ }
+ }
+
+ if (!aRet.Len()) // leer ist baeh
+ aRet = ' '; // Space ist Default der Editengine
+
+ return aRet;
+}
+
+void __EXPORT ScFieldEditEngine::FieldClicked( const SvxFieldItem& rField, USHORT, USHORT )
+{
+ const SvxFieldData* pFld = rField.GetField();
+
+ if ( pFld && pFld->ISA( SvxURLField ) && bExecuteURL )
+ {
+ const SvxURLField* pURLField = (const SvxURLField*) pFld;
+ ScGlobal::OpenURL( pURLField->GetURL(), pURLField->GetTargetFrame() );
+ }
+}
+
diff --git a/sc/source/core/tool/hints.cxx b/sc/source/core/tool/hints.cxx
new file mode 100644
index 000000000000..8ee85190d309
--- /dev/null
+++ b/sc/source/core/tool/hints.cxx
@@ -0,0 +1,186 @@
+/*************************************************************************
+ *
+ * $RCSfile: hints.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include "hints.hxx"
+
+// -----------------------------------------------------------------------
+
+TYPEINIT1(ScPaintHint, SfxHint);
+TYPEINIT1(ScUpdateRefHint, SfxHint);
+TYPEINIT1(ScPointerChangedHint, SfxHint);
+TYPEINIT1(ScLinkRefreshedHint, SfxHint);
+TYPEINIT1(ScAutoStyleHint, SfxHint);
+
+// -----------------------------------------------------------------------
+// ScPaintHint - Angabe, was neu gezeichnet werden muss
+// -----------------------------------------------------------------------
+
+ScPaintHint::ScPaintHint() :
+ aRange( 0,0,0, MAXCOL,MAXROW,MAXTAB ),
+ nParts( PAINT_ALL ),
+ bPrint( TRUE )
+{
+}
+
+ScPaintHint::ScPaintHint( const ScRange& rRng, USHORT nPaint ) :
+ aRange( rRng ),
+ nParts( nPaint ),
+ bPrint( TRUE )
+{
+}
+
+ScPaintHint::~ScPaintHint()
+{
+}
+
+// -----------------------------------------------------------------------
+// ScUpdateRefHint - Referenz-Updaterei
+// -----------------------------------------------------------------------
+
+ScUpdateRefHint::ScUpdateRefHint( UpdateRefMode eMode, const ScRange& rR,
+ short nX, short nY, short nZ ) :
+ eUpdateRefMode( eMode ),
+ aRange( rR ),
+ nDx( nX ),
+ nDy( nY ),
+ nDz( nZ )
+{
+}
+
+ScUpdateRefHint::~ScUpdateRefHint()
+{
+}
+
+// -----------------------------------------------------------------------
+// ScPointerChangedHint - Pointer ist ungueltig geworden
+// -----------------------------------------------------------------------
+
+ScPointerChangedHint::ScPointerChangedHint( USHORT nF ) :
+ nFlags( nF )
+{
+}
+
+ScPointerChangedHint::~ScPointerChangedHint()
+{
+}
+
+// -----------------------------------------------------------------------
+// ScLinkRefreshedHint - a link has been refreshed
+// -----------------------------------------------------------------------
+
+ScLinkRefreshedHint::ScLinkRefreshedHint() :
+ nLinkType( SC_LINKREFTYPE_NONE ),
+ nDdeMode( 0 )
+{
+}
+
+ScLinkRefreshedHint::~ScLinkRefreshedHint()
+{
+}
+
+void ScLinkRefreshedHint::SetSheetLink( const String& rSourceUrl )
+{
+ nLinkType = SC_LINKREFTYPE_SHEET;
+ aUrl = rSourceUrl;
+}
+
+void ScLinkRefreshedHint::SetDdeLink(
+ const String& rA, const String& rT, const String& rI, BYTE nM )
+{
+ nLinkType = SC_LINKREFTYPE_DDE;
+ aDdeAppl = rA;
+ aDdeTopic = rT;
+ aDdeItem = rI;
+ nDdeMode = nM;
+}
+
+void ScLinkRefreshedHint::SetAreaLink( const ScAddress& rPos )
+{
+ nLinkType = SC_LINKREFTYPE_AREA;
+ aDestPos = rPos;
+}
+
+// -----------------------------------------------------------------------
+// ScAutoStyleHint - STYLE() function has been called
+// -----------------------------------------------------------------------
+
+ScAutoStyleHint::ScAutoStyleHint( const ScRange& rR, const String& rSt1,
+ ULONG nT, const String& rSt2 ) :
+ aRange( rR ),
+ aStyle1( rSt1 ),
+ aStyle2( rSt2 ),
+ nTimeout( nT )
+{
+}
+
+ScAutoStyleHint::~ScAutoStyleHint()
+{
+}
+
+
+
+
diff --git a/sc/source/core/tool/indexmap.cxx b/sc/source/core/tool/indexmap.cxx
new file mode 100644
index 000000000000..50c4531df363
--- /dev/null
+++ b/sc/source/core/tool/indexmap.cxx
@@ -0,0 +1,112 @@
+/*************************************************************************
+ *
+ * $RCSfile: indexmap.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+
+#include <memory.h>
+
+#include "indexmap.hxx"
+
+
+ScIndexMap::ScIndexMap( USHORT nEntries )
+{
+ nCount = nEntries;
+ ULONG nC = nEntries ? ((ULONG) nEntries * 2) : 2;
+ pMap = new USHORT [ nC ];
+ memset( pMap, 0, nC * sizeof(USHORT) );
+}
+
+
+ScIndexMap::~ScIndexMap()
+{
+ delete [] pMap;
+}
+
+
+void ScIndexMap::SetPair( USHORT nEntry, USHORT nIndex1, USHORT nIndex2 )
+{
+ if ( nEntry < nCount )
+ {
+ ULONG nOff = (ULONG) nEntry * 2;
+ pMap[nOff] = nIndex1;
+ pMap[nOff+1] = nIndex2;
+ }
+}
+
+
+USHORT ScIndexMap::Find( USHORT nIndex1 ) const
+{
+ USHORT* pStop = pMap + (ULONG) nCount * 2;
+ for ( USHORT* pOff = pMap; pOff < pStop; pOff += 2 )
+ {
+ if ( *pOff == nIndex1 )
+ return *(pOff+1);
+ }
+ return nIndex1;
+}
+
+
diff --git a/sc/source/core/tool/inputopt.cxx b/sc/source/core/tool/inputopt.cxx
new file mode 100644
index 000000000000..6d596b415f8f
--- /dev/null
+++ b/sc/source/core/tool/inputopt.cxx
@@ -0,0 +1,336 @@
+/*************************************************************************
+ *
+ * $RCSfile: inputopt.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+//------------------------------------------------------------------
+
+#include <tools/debug.hxx>
+
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include "cfgids.hxx"
+#include "inputopt.hxx"
+#include "rechead.hxx"
+#include "scresid.hxx"
+#include "global.hxx"
+#include "sc.hrc"
+#include "miscuno.hxx"
+
+using namespace utl;
+using namespace rtl;
+using namespace com::sun::star::uno;
+
+//------------------------------------------------------------------
+
+// Version, ab der das Item kompatibel ist
+#define SC_VERSION ((USHORT)351)
+
+
+//========================================================================
+// ScInputOptions - Eingabe-Optionen
+//========================================================================
+
+ScInputOptions::ScInputOptions()
+{
+ SetDefaults();
+}
+
+//------------------------------------------------------------------------
+
+ScInputOptions::ScInputOptions( const ScInputOptions& rCpy )
+{
+ *this = rCpy;
+}
+
+//------------------------------------------------------------------------
+
+ScInputOptions::~ScInputOptions()
+{
+}
+
+//------------------------------------------------------------------------
+
+void ScInputOptions::SetDefaults()
+{
+ nMoveDir = DIR_BOTTOM;
+ bMoveSelection = TRUE;
+ bEnterEdit = FALSE;
+ bExtendFormat = FALSE;
+ bRangeFinder = TRUE;
+ bExpandRefs = FALSE;
+ bMarkHeader = TRUE;
+ bUseTabCol = FALSE; //! ja wie denn nun?
+}
+
+//------------------------------------------------------------------------
+
+const ScInputOptions& ScInputOptions::operator=( const ScInputOptions& rCpy )
+{
+ nMoveDir = rCpy.nMoveDir;
+ bMoveSelection = rCpy.bMoveSelection;
+ bEnterEdit = rCpy.bEnterEdit;
+ bExtendFormat = rCpy.bExtendFormat;
+ bRangeFinder = rCpy.bRangeFinder;
+ bExpandRefs = rCpy.bExpandRefs;
+ bMarkHeader = rCpy.bMarkHeader;
+ bUseTabCol = rCpy.bUseTabCol;
+
+ return *this;
+}
+
+//------------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rStream, ScInputOptions& rOpt )
+{
+ rOpt.SetDefaults();
+
+ ScReadHeader aHdr( rStream );
+
+ rStream >> rOpt.nMoveDir;
+ rStream >> rOpt.bMoveSelection;
+ rStream >> rOpt.bEnterEdit;
+ rStream >> rOpt.bExtendFormat;
+
+ if (aHdr.BytesLeft())
+ rStream >> rOpt.bRangeFinder; // ab 363
+
+ if (aHdr.BytesLeft())
+ rStream >> rOpt.bExpandRefs; // ab 364v
+
+ if (aHdr.BytesLeft())
+ rStream >> rOpt.bMarkHeader; // ab 364irgendwas
+
+ if (aHdr.BytesLeft())
+ rStream >> rOpt.bUseTabCol; // ab 373d
+
+ return rStream;
+}
+
+//------------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rStream, const ScInputOptions& rOpt )
+{
+ ScWriteHeader aHdr( rStream, 6 );
+
+ rStream << rOpt.nMoveDir;
+ rStream << rOpt.bMoveSelection;
+ rStream << rOpt.bEnterEdit;
+ rStream << rOpt.bExtendFormat;
+ rStream << rOpt.bRangeFinder;
+ rStream << rOpt.bExpandRefs;
+ rStream << rOpt.bMarkHeader;
+ rStream << rOpt.bUseTabCol;
+
+ return rStream;
+}
+
+//==================================================================
+// Config Item containing input options
+//==================================================================
+
+#define CFGPATH_INPUT "Office.Calc/Input"
+
+#define SCINPUTOPT_MOVEDIR 0
+#define SCINPUTOPT_MOVESEL 1
+#define SCINPUTOPT_EDTEREDIT 2
+#define SCINPUTOPT_EXTENDFMT 3
+#define SCINPUTOPT_RANGEFIND 4
+#define SCINPUTOPT_EXPANDREFS 5
+#define SCINPUTOPT_MARKHEADER 6
+#define SCINPUTOPT_USETABCOL 7
+#define SCINPUTOPT_COUNT 8
+
+Sequence<OUString> ScInputCfg::GetPropertyNames()
+{
+ static const char* aPropNames[] =
+ {
+ "MoveSelectionDirection", // SCINPUTOPT_MOVEDIR
+ "MoveSelection", // SCINPUTOPT_MOVESEL
+ "SwitchToEditMode", // SCINPUTOPT_EDTEREDIT
+ "ExpandFormatting", // SCINPUTOPT_EXTENDFMT
+ "ShowReference", // SCINPUTOPT_RANGEFIND
+ "ExpandReference", // SCINPUTOPT_EXPANDREFS
+ "HighlightSelection", // SCINPUTOPT_MARKHEADER
+ "UseTabCol" // SCINPUTOPT_USETABCOL
+ };
+ Sequence<OUString> aNames(SCINPUTOPT_COUNT);
+ OUString* pNames = aNames.getArray();
+ for(int i = 0; i < SCINPUTOPT_COUNT; i++)
+ pNames[i] = OUString::createFromAscii(aPropNames[i]);
+
+ return aNames;
+}
+
+ScInputCfg::ScInputCfg() :
+ ConfigItem( OUString::createFromAscii( CFGPATH_INPUT ) )
+{
+ sal_Int32 nIntVal;
+
+ Sequence<OUString> aNames = GetPropertyNames();
+ Sequence<Any> aValues = GetProperties(aNames);
+ EnableNotification(aNames);
+ const Any* pValues = aValues.getConstArray();
+ DBG_ASSERT(aValues.getLength() == aNames.getLength(), "GetProperties failed")
+ if(aValues.getLength() == aNames.getLength())
+ {
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ DBG_ASSERT(pValues[nProp].hasValue(), "property value missing")
+ if(pValues[nProp].hasValue())
+ {
+ switch(nProp)
+ {
+ case SCINPUTOPT_MOVEDIR:
+ if ( pValues[nProp] >>= nIntVal )
+ SetMoveDir( nIntVal );
+ break;
+ case SCINPUTOPT_MOVESEL:
+ SetMoveSelection( ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCINPUTOPT_EDTEREDIT:
+ SetEnterEdit( ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCINPUTOPT_EXTENDFMT:
+ SetExtendFormat( ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCINPUTOPT_RANGEFIND:
+ SetRangeFinder( ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCINPUTOPT_EXPANDREFS:
+ SetExpandRefs( ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCINPUTOPT_MARKHEADER:
+ SetMarkHeader( ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCINPUTOPT_USETABCOL:
+ SetUseTabCol( ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ }
+ }
+ }
+ }
+}
+
+
+void ScInputCfg::Commit()
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+ OUString* pNames = aNames.getArray();
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ const Type& rType = ::getBooleanCppuType();
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ switch(nProp)
+ {
+ case SCINPUTOPT_MOVEDIR:
+ pValues[nProp] <<= (sal_Int32) GetMoveDir();
+ break;
+ case SCINPUTOPT_MOVESEL:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetMoveSelection() );
+ break;
+ case SCINPUTOPT_EDTEREDIT:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetEnterEdit() );
+ break;
+ case SCINPUTOPT_EXTENDFMT:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetExtendFormat() );
+ break;
+ case SCINPUTOPT_RANGEFIND:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetRangeFinder() );
+ break;
+ case SCINPUTOPT_EXPANDREFS:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetExpandRefs() );
+ break;
+ case SCINPUTOPT_MARKHEADER:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetMarkHeader() );
+ break;
+ case SCINPUTOPT_USETABCOL:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetUseTabCol() );
+ break;
+ }
+ }
+ PutProperties(aNames, aValues);
+}
+
+void ScInputCfg::Notify( const Sequence<rtl::OUString>& aPropertyNames )
+{
+ DBG_ERROR("properties have been changed")
+}
+
+void ScInputCfg::SetOptions( const ScInputOptions& rNew )
+{
+ *(ScInputOptions*)this = rNew;
+ SetModified();
+}
+
+void ScInputCfg::OptionsChanged()
+{
+ SetModified();
+}
+
+
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
new file mode 100644
index 000000000000..738a6f0911ae
--- /dev/null
+++ b/sc/source/core/tool/interpr1.cxx
@@ -0,0 +1,5204 @@
+/*************************************************************************
+ *
+ * $RCSfile: interpr1.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#ifdef RS6000
+#pragma options FLTTRAP
+#include <fptrap.h>
+#include <fpxcp.h>
+#endif
+
+#include "scitems.hxx"
+#include <svx/langitem.hxx>
+#include <svtools/txtcmp.hxx>
+#include <svtools/zforlist.hxx>
+#include <tools/intn.hxx>
+#include <tools/solar.h>
+#include <unotools/charclass.hxx>
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "interpre.hxx"
+#include "patattr.hxx"
+#include "global.hxx"
+#include "document.hxx"
+#include "dociter.hxx"
+#include "cell.hxx"
+#include "scmatrix.hxx"
+#include "docoptio.hxx"
+#include "globstr.hrc"
+
+
+// PI jetzt als F_PI aus solar.h
+//#define PI 3.1415926535897932
+//#define MINVALUE 1.7e-307
+//#define SQRT_2_PI 2.506628274631000
+
+// globale Variablen
+
+#pragma code_seg("SCSTATICS")
+
+IMPL_FIXEDMEMPOOL_NEWDEL( ScTokenStack, 8, 4 )
+IMPL_FIXEDMEMPOOL_NEWDEL( ScErrorStack, 8, 4 )
+IMPL_FIXEDMEMPOOL_NEWDEL( ScInterpreter, 32, 16 )
+
+#pragma code_seg()
+
+ScTokenStack* ScInterpreter::pGlobalStack = NULL;
+ScErrorStack* ScInterpreter::pGlobalErrorStack = NULL;
+BOOL ScInterpreter::bGlobalStackInUse = FALSE;
+
+
+//-----------------------------------------------------------------------------
+// Funktionen
+//-----------------------------------------------------------------------------
+
+
+void ScInterpreter::ScIfJump()
+{
+ short nJumpCount = pCur->nJump[ 0 ];
+ if ( GetBool() )
+ { // TRUE
+ if( nJumpCount >= 2 )
+ { // then Zweig
+ nFuncFmtType = NUMBERFORMAT_UNDEFINED;
+ aCode.Jump( pCur->nJump[ 1 ], pCur->nJump[ nJumpCount ] );
+ }
+ else
+ { // kein Parameter fuer then
+ nFuncFmtType = NUMBERFORMAT_LOGICAL;
+ PushInt(1);
+ aCode.Jump( pCur->nJump[ nJumpCount ], pCur->nJump[ nJumpCount ] );
+ }
+ }
+ else
+ { // FALSE
+ if( nJumpCount == 3 )
+ { // else Zweig
+ nFuncFmtType = NUMBERFORMAT_UNDEFINED;
+ aCode.Jump( pCur->nJump[ 2 ], pCur->nJump[ nJumpCount ] );
+ }
+ else
+ { // kein Parameter fuer else
+ nFuncFmtType = NUMBERFORMAT_LOGICAL;
+ PushInt(0);
+ aCode.Jump( pCur->nJump[ nJumpCount ], pCur->nJump[ nJumpCount ] );
+ }
+ }
+}
+
+
+void ScInterpreter::ScChoseJump()
+{
+ short nJumpCount = pCur->nJump[ 0 ];
+ double nJumpIndex = SolarMath::ApproxFloor( GetDouble() );
+ if ((nJumpIndex >= 1) && (nJumpIndex < nJumpCount))
+ aCode.Jump( pCur->nJump[ (short) nJumpIndex ], pCur->nJump[ nJumpCount ] );
+ else
+ SetError(errIllegalArgument);
+}
+
+
+short ScInterpreter::CompareFunc( const ScCompare& rComp )
+{
+ short nRes = 0;
+ if ( rComp.bEmpty[ 0 ] )
+ {
+ if ( rComp.bEmpty[ 1 ] )
+ ; // leere Zelle == leere Zelle, nRes 0
+ else if( rComp.bVal[ 1 ] )
+ {
+ if ( !SolarMath::ApproxEqual( rComp.nVal[ 1 ], 0.0 ) )
+ {
+ if ( rComp.nVal[ 1 ] < 0.0 )
+ nRes = 1; // leere Zelle > -x
+ else
+ nRes = -1; // leere Zelle < x
+ }
+ // else: leere Zelle == 0.0
+ }
+ else
+ {
+ if ( rComp.pVal[ 1 ]->Len() )
+ nRes = -1; // leere Zelle < "..."
+ // else: leere Zelle == ""
+ }
+ }
+ else if ( rComp.bEmpty[ 1 ] )
+ {
+ if( rComp.bVal[ 0 ] )
+ {
+ if ( !SolarMath::ApproxEqual( rComp.nVal[ 0 ], 0.0 ) )
+ {
+ if ( rComp.nVal[ 0 ] < 0.0 )
+ nRes = -1; // -x < leere Zelle
+ else
+ nRes = 1; // x > leere Zelle
+ }
+ // else: leere Zelle == 0.0
+ }
+ else
+ {
+ if ( rComp.pVal[ 0 ]->Len() )
+ nRes = 1; // "..." > leere Zelle
+ // else: "" == leere Zelle
+ }
+ }
+ else if( rComp.bVal[ 0 ] )
+ {
+ if( rComp.bVal[ 1 ] )
+ {
+ if ( !SolarMath::ApproxEqual( rComp.nVal[ 0 ], rComp.nVal[ 1 ] ) )
+ {
+ if( rComp.nVal[ 0 ] - rComp.nVal[ 1 ] < 0 )
+ nRes = -1;
+ else
+ nRes = 1;
+ }
+ }
+ else
+ nRes = -1; // Zahl ist kleiner als String
+ }
+ else if( rComp.bVal[ 1 ] )
+ nRes = 1; // Zahl ist kleiner als String
+ else
+ {
+ StringCompare eComp;
+ if (pDok->GetDocOptions().IsIgnoreCase())
+ eComp = ScGlobal::pScInternational->Compare( *rComp.pVal[ 0 ],
+ *rComp.pVal[ 1 ], INTN_COMPARE_IGNORECASE );
+ else
+ eComp = (*rComp.pVal[ 0 ]).CompareTo( *rComp.pVal[ 1 ] );
+ switch( eComp )
+ {
+ case COMPARE_LESS: nRes = 1; break;
+ case COMPARE_GREATER: nRes = -1; break;
+ }
+ }
+ return nRes;
+}
+
+
+short ScInterpreter::Compare()
+{
+ nCurFmtType = nFuncFmtType = NUMBERFORMAT_LOGICAL;
+ String aVal1, aVal2;
+ ScCompare aComp( &aVal1, &aVal2 );
+ for( short i = 1; i >= 0; i-- )
+ {
+ switch ( GetStackType() )
+ {
+ case svDouble:
+ aComp.nVal[ i ] = GetDouble();
+ aComp.bVal[ i ] = TRUE;
+ break;
+ case svString:
+ *aComp.pVal[ i ] = GetString();
+ aComp.bVal[ i ] = FALSE;
+ break;
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ break;
+ ScBaseCell* pCell = GetCell( aAdr );
+ if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE )
+ {
+ if (HasCellStringData(pCell))
+ {
+ GetCellString(*aComp.pVal[ i ], pCell);
+ aComp.bVal[ i ] = FALSE;
+ }
+ else
+ {
+ aComp.nVal[ i ] = GetCellValue( aAdr, pCell );
+ aComp.bVal[ i ] = TRUE;
+ }
+ }
+ else
+ aComp.bEmpty[ i ] = TRUE;
+ }
+ break;
+ default:
+ SetError(errIllegalParameter);
+ break;
+ }
+ }
+ if( nGlobalError )
+ return 0;
+ return CompareFunc( aComp );
+}
+
+
+ScMatrix* ScInterpreter::CompareMat()
+{
+ nCurFmtType = nFuncFmtType = NUMBERFORMAT_LOGICAL;
+ String aVal1, aVal2;
+ ScCompare aComp( &aVal1, &aVal2 );
+ ScMatrix* pMat[2];
+ pMat[0] = pMat[1] = NULL;
+ USHORT nMatInd[2];
+ BOOL bTmpMat[2];
+ bTmpMat[0] = bTmpMat[1] = FALSE;
+ ScAddress aAdr;
+ for( short i = 1; i >= 0; i-- )
+ {
+ switch (GetStackType())
+ {
+ case svDouble:
+ aComp.nVal[ i ] = GetDouble();
+ aComp.bVal[ i ] = TRUE;
+ break;
+ case svString:
+ *aComp.pVal[ i ] = GetString();
+ aComp.bVal[ i ] = FALSE;
+ break;
+ case svSingleRef:
+ {
+ PopSingleRef( aAdr );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE )
+ {
+ if (HasCellStringData(pCell))
+ {
+ GetCellString(*aComp.pVal[ i ], pCell);
+ aComp.bVal[ i ] = FALSE;
+ }
+ else
+ {
+ aComp.nVal[ i ] = GetCellValue( aAdr, pCell );
+ aComp.bVal[ i ] = TRUE;
+ }
+ }
+ else
+ aComp.bEmpty[ i ] = TRUE;
+ }
+ break;
+ case svDoubleRef:
+ bTmpMat[ i ] = TRUE;
+ case svMatrix:
+ pMat[ i ] = GetMatrix( nMatInd[ i ] );
+ if ( !pMat[ i ] )
+ SetError(errIllegalParameter);
+ break;
+ default:
+ SetError(errIllegalParameter);
+ break;
+ }
+ }
+ ScMatrix* pResMat = NULL;
+ if( !nGlobalError )
+ {
+ USHORT nResMatInd;
+ if ( pMat[0] && pMat[1] )
+ {
+ USHORT nC0, nR0, nC1, nR1;
+ pMat[0]->GetDimensions( nC0, nR0 );
+ pMat[1]->GetDimensions( nC1, nR1 );
+ USHORT nC = Max( nC0, nC1 );
+ USHORT nR = Max( nR0, nR1 );
+ pResMat = GetNewMat( nC, nR, nResMatInd );
+ if ( !pResMat )
+ return NULL;
+ for ( USHORT j=0; j<nC; j++ )
+ {
+ for ( USHORT k=0; k<nR; k++ )
+ {
+ if ( j < nC0 && j < nC1 && k < nR0 && k < nR1 )
+ {
+ for ( short i=1; i>=0; i-- )
+ {
+ if ( pMat[i]->IsString(j,k) )
+ {
+ aComp.bVal[i] = FALSE;
+ *aComp.pVal[i] = pMat[i]->GetString(j,k);
+ aComp.bEmpty[i] = pMat[i]->IsEmpty(j,k);
+ }
+ else
+ {
+ aComp.bVal[i] = TRUE;
+ aComp.nVal[i] = pMat[i]->GetDouble(j,k);
+ aComp.bEmpty[i] = FALSE;
+ }
+ }
+ pResMat->PutDouble( CompareFunc( aComp ), j,k );
+ }
+ else
+ pResMat->PutString( ScGlobal::GetRscString(STR_NO_VALUE), j,k );
+ }
+ }
+ nRetMat = nResMatInd;
+ }
+ else if ( pMat[0] || pMat[1] )
+ {
+ short i = ( pMat[0] ? 0 : 1);
+ USHORT nC, nR;
+ pMat[i]->GetDimensions( nC, nR );
+ pResMat = GetNewMat( nC, nR, nResMatInd );
+ if ( !pResMat )
+ return NULL;
+ USHORT n = nC * nR;
+ for ( USHORT j=0; j<n; j++ )
+ {
+ if ( pMat[i]->IsValue(j) )
+ {
+ aComp.bVal[i] = TRUE;
+ aComp.nVal[i] = pMat[i]->GetDouble(j);
+ aComp.bEmpty[i] = FALSE;
+ }
+ else
+ {
+ aComp.bVal[i] = FALSE;
+ *aComp.pVal[i] = pMat[i]->GetString(j);
+ aComp.bEmpty[i] = pMat[i]->IsEmpty(j);
+ }
+ pResMat->PutDouble( CompareFunc( aComp ), j );
+ }
+ nRetMat = nResMatInd;
+ }
+ }
+ for( short x=1; x >= 0; x-- )
+ {
+ if ( bTmpMat[x] && pMat[x] )
+ {
+ delete pMat[x];
+ ResetNewMat( nMatInd[x] );
+ }
+ }
+ return pResMat;
+}
+
+
+void ScInterpreter::ScEqual()
+{
+ StackVar eType;
+ if ( ((eType = GetStackType(2)) == svMatrix) ||
+ (bMatrixFormula && eType == svDoubleRef) ||
+ ((eType = GetStackType(1)) == svMatrix) ||
+ (bMatrixFormula && eType == svDoubleRef)
+ )
+ {
+ ScMatrix* pMat = CompareMat();
+ if ( !pMat )
+ SetIllegalParameter();
+ else
+ {
+ pMat->CompareEqual();
+ PushMatrix( pMat );
+ }
+ }
+ else
+ PushInt( Compare() == 0 );
+}
+
+
+void ScInterpreter::ScNotEqual()
+{
+ StackVar eType;
+ if ( ((eType = GetStackType(2)) == svMatrix) ||
+ (bMatrixFormula && eType == svDoubleRef) ||
+ ((eType = GetStackType(1)) == svMatrix) ||
+ (bMatrixFormula && eType == svDoubleRef)
+ )
+ {
+ ScMatrix* pMat = CompareMat();
+ if ( !pMat )
+ SetIllegalParameter();
+ else
+ {
+ pMat->CompareNotEqual();
+ PushMatrix( pMat );
+ }
+ }
+ else
+ PushInt( Compare() != 0 );
+}
+
+
+void ScInterpreter::ScLess()
+{
+ StackVar eType;
+ if ( ((eType = GetStackType(2)) == svMatrix) ||
+ (bMatrixFormula && eType == svDoubleRef) ||
+ ((eType = GetStackType(1)) == svMatrix) ||
+ (bMatrixFormula && eType == svDoubleRef)
+ )
+ {
+ ScMatrix* pMat = CompareMat();
+ if ( !pMat )
+ SetIllegalParameter();
+ else
+ {
+ pMat->CompareLess();
+ PushMatrix( pMat );
+ }
+ }
+ else
+ PushInt( Compare() < 0 );
+}
+
+
+void ScInterpreter::ScGreater()
+{
+ StackVar eType;
+ if ( ((eType = GetStackType(2)) == svMatrix) ||
+ (bMatrixFormula && eType == svDoubleRef) ||
+ ((eType = GetStackType(1)) == svMatrix) ||
+ (bMatrixFormula && eType == svDoubleRef)
+ )
+ {
+ ScMatrix* pMat = CompareMat();
+ if ( !pMat )
+ SetIllegalParameter();
+ else
+ {
+ pMat->CompareGreater();
+ PushMatrix( pMat );
+ }
+ }
+ else
+ PushInt( Compare() > 0 );
+}
+
+
+void ScInterpreter::ScLessEqual()
+{
+ StackVar eType;
+ if ( ((eType = GetStackType(2)) == svMatrix) ||
+ (bMatrixFormula && eType == svDoubleRef) ||
+ ((eType = GetStackType(1)) == svMatrix) ||
+ (bMatrixFormula && eType == svDoubleRef)
+ )
+ {
+ ScMatrix* pMat = CompareMat();
+ if ( !pMat )
+ SetIllegalParameter();
+ else
+ {
+ pMat->CompareLessEqual();
+ PushMatrix( pMat );
+ }
+ }
+ else
+ PushInt( Compare() <= 0 );
+}
+
+
+void ScInterpreter::ScGreaterEqual()
+{
+ StackVar eType;
+ if ( ((eType = GetStackType(2)) == svMatrix) ||
+ (bMatrixFormula && eType == svDoubleRef) ||
+ ((eType = GetStackType(1)) == svMatrix) ||
+ (bMatrixFormula && eType == svDoubleRef)
+ )
+ {
+ ScMatrix* pMat = CompareMat();
+ if ( !pMat )
+ SetIllegalParameter();
+ else
+ {
+ pMat->CompareGreaterEqual();
+ PushMatrix( pMat );
+ }
+ }
+ else
+ PushInt( Compare() >= 0 );
+}
+
+
+void ScInterpreter::ScAnd()
+{
+ nFuncFmtType = NUMBERFORMAT_LOGICAL;
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCountMin( nParamCount, 1 ) )
+ {
+ BOOL bHaveValue = FALSE;
+ short nRes = TRUE;
+ while( nParamCount-- )
+ {
+ if ( !nGlobalError )
+ {
+ switch ( GetStackType() )
+ {
+ case svDouble :
+ bHaveValue = TRUE;
+ nRes &= ( PopDouble() != 0.0 );
+ break;
+ case svString :
+ Pop();
+ SetError( errNoValue );
+ break;
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ PopSingleRef( aAdr );
+ if ( !nGlobalError )
+ {
+ ScBaseCell* pCell = GetCell( aAdr );
+ if ( HasCellValueData( pCell ) )
+ {
+ bHaveValue = TRUE;
+ nRes &= ( GetCellValue( aAdr, pCell ) != 0.0 );
+ }
+ // else: Xcl setzt hier keinen Fehler
+ }
+ }
+ break;
+ case svDoubleRef:
+ {
+ ScRange aRange;
+ PopDoubleRef( aRange );
+ if ( !nGlobalError )
+ {
+ double fVal;
+ USHORT nErr = 0;
+ ScValueIterator aValIter( pDok, aRange );
+ if ( aValIter.GetFirst( fVal, nErr ) )
+ {
+ bHaveValue = TRUE;
+ do
+ {
+ nRes &= ( fVal != 0.0 );
+ } while ( (nErr == 0) &&
+ aValIter.GetNext( fVal, nErr ) );
+ }
+ SetError( nErr );
+ }
+ }
+ break;
+ case svMatrix:
+ {
+ USHORT nMatInd;
+ ScMatrix* pMat = GetMatrix( nMatInd );
+ if ( pMat )
+ {
+ bHaveValue = TRUE;
+ nRes &= pMat->And();
+ }
+ // else: GetMatrix hat errIllegalParameter gesetzt
+ }
+ break;
+ default:
+ Pop();
+ SetError( errIllegalParameter );
+ }
+ }
+ else
+ Pop();
+ }
+ if ( bHaveValue )
+ PushInt( nRes );
+ else
+ SetNoValue();
+ }
+}
+
+
+void ScInterpreter::ScOr()
+{
+ nFuncFmtType = NUMBERFORMAT_LOGICAL;
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCountMin( nParamCount, 1 ) )
+ {
+ BOOL bHaveValue = FALSE;
+ short nRes = FALSE;
+ while( nParamCount-- )
+ {
+ if ( !nGlobalError )
+ {
+ switch ( GetStackType() )
+ {
+ case svDouble :
+ bHaveValue = TRUE;
+ nRes |= ( PopDouble() != 0.0 );
+ break;
+ case svString :
+ Pop();
+ SetError( errNoValue );
+ break;
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ PopSingleRef( aAdr );
+ if ( !nGlobalError )
+ {
+ ScBaseCell* pCell = GetCell( aAdr );
+ if ( HasCellValueData( pCell ) )
+ {
+ bHaveValue = TRUE;
+ nRes |= ( GetCellValue( aAdr, pCell ) != 0.0 );
+ }
+ // else: Xcl setzt hier keinen Fehler
+ }
+ }
+ break;
+ case svDoubleRef:
+ {
+ ScRange aRange;
+ PopDoubleRef( aRange );
+ if ( !nGlobalError )
+ {
+ double fVal;
+ USHORT nErr = 0;
+ ScValueIterator aValIter( pDok, aRange );
+ if ( aValIter.GetFirst( fVal, nErr ) )
+ {
+ bHaveValue = TRUE;
+ do
+ {
+ nRes |= ( fVal != 0.0 );
+ } while ( (nErr == 0) &&
+ aValIter.GetNext( fVal, nErr ) );
+ }
+ SetError( nErr );
+ }
+ }
+ break;
+ case svMatrix:
+ {
+ bHaveValue = TRUE;
+ USHORT nMatInd;
+ ScMatrix* pMat = GetMatrix( nMatInd );
+ if ( pMat )
+ {
+ bHaveValue = TRUE;
+ nRes |= pMat->Or();
+ }
+ // else: GetMatrix hat errIllegalParameter gesetzt
+ }
+ break;
+ default:
+ Pop();
+ SetError( errIllegalParameter );
+ }
+ }
+ else
+ Pop();
+ }
+ if ( bHaveValue )
+ PushInt( nRes );
+ else
+ SetNoValue();
+ }
+}
+
+
+void ScInterpreter::ScNot()
+{
+ nFuncFmtType = NUMBERFORMAT_LOGICAL;
+ PushInt( GetDouble() == 0.0 );
+}
+
+
+void ScInterpreter::ScNeg()
+{
+ PushDouble(-GetDouble());
+}
+
+
+void ScInterpreter::ScPi()
+{
+ PushDouble(F_PI);
+}
+
+
+void ScInterpreter::ScRandom()
+{
+ PushDouble((double)rand() / RAND_MAX);
+}
+
+
+void ScInterpreter::ScTrue()
+{
+ nFuncFmtType = NUMBERFORMAT_LOGICAL;
+ PushInt(1);
+}
+
+
+void ScInterpreter::ScFalse()
+{
+ nFuncFmtType = NUMBERFORMAT_LOGICAL;
+ PushInt(0);
+}
+
+
+void ScInterpreter::ScDeg()
+{
+ PushDouble((GetDouble() / F_PI) * 180.0);
+}
+
+
+void ScInterpreter::ScRad()
+{
+ PushDouble(GetDouble() * (F_PI / 180));
+}
+
+
+void ScInterpreter::ScSin()
+{
+ PushDouble(sin(GetDouble()));
+}
+
+
+void ScInterpreter::ScCos()
+{
+ PushDouble(cos(GetDouble()));
+}
+
+
+void ScInterpreter::ScTan()
+{
+ PushDouble(tan(GetDouble()));
+}
+
+
+void ScInterpreter::ScCot()
+{
+ PushDouble(1.0 / tan(GetDouble()));
+}
+
+
+void ScInterpreter::ScArcSin()
+{
+ PushDouble(asin(GetDouble()));
+}
+
+
+void ScInterpreter::ScArcCos()
+{
+ PushDouble(acos(GetDouble()));
+}
+
+
+void ScInterpreter::ScArcTan()
+{
+ PushDouble(atan(GetDouble()));
+}
+
+
+void ScInterpreter::ScArcCot()
+{
+ PushDouble((F_PI2) - atan(GetDouble()));
+}
+
+
+void ScInterpreter::ScSinHyp()
+{
+ PushDouble(sinh(GetDouble()));
+}
+
+
+void ScInterpreter::ScCosHyp()
+{
+ PushDouble(cosh(GetDouble()));
+}
+
+
+void ScInterpreter::ScTanHyp()
+{
+ PushDouble(tanh(GetDouble()));
+}
+
+
+void ScInterpreter::ScCotHyp()
+{
+ PushDouble(1.0 / tanh(GetDouble()));
+}
+
+
+void ScInterpreter::ScArcSinHyp()
+{
+ double nVal = GetDouble();
+ PushDouble(log(nVal + sqrt((nVal * nVal) + 1.0)));
+}
+
+
+void ScInterpreter::ScArcCosHyp()
+{
+ double nVal = GetDouble();
+ if (nVal < 1.0)
+ SetIllegalArgument();
+ else
+ PushDouble(log(nVal + sqrt((nVal * nVal) - 1.0)));
+}
+
+
+void ScInterpreter::ScArcTanHyp()
+{
+ double nVal = GetDouble();
+ if (fabs(nVal) >= 1.0)
+ SetIllegalArgument();
+ else
+ PushDouble(0.5 * log((1.0 + nVal) / (1.0 - nVal)));
+}
+
+
+void ScInterpreter::ScArcCotHyp()
+{
+ double nVal = GetDouble();
+ if (fabs(nVal) <= 1.0)
+ SetIllegalArgument();
+ else
+ PushDouble(0.5 * log((nVal + 1.0) / (nVal - 1.0)));
+}
+
+
+void ScInterpreter::ScExp()
+{
+ PushDouble(exp(GetDouble()));
+}
+
+
+void ScInterpreter::ScSqrt()
+{
+ double fVal = GetDouble();
+ if (fVal >= 0.0)
+ PushDouble(sqrt(fVal));
+ else
+ SetIllegalArgument();
+}
+
+
+void ScInterpreter::ScIsEmpty()
+{
+ short nRes = 0;
+ nFuncFmtType = NUMBERFORMAT_LOGICAL;
+ switch ( GetStackType() )
+ {
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ break;
+ CellType eCellType = GetCellType( GetCell( aAdr ) );
+ if((eCellType == CELLTYPE_NONE) || (eCellType == CELLTYPE_NOTE))
+ nRes = 1;
+ }
+ break;
+ default:
+ Pop();
+ }
+ nGlobalError = 0;
+ PushInt( nRes );
+}
+
+
+short ScInterpreter::IsString()
+{
+ nFuncFmtType = NUMBERFORMAT_LOGICAL;
+ short nRes = 0;
+ switch ( GetStackType() )
+ {
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ break;
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (GetCellErrCode( pCell ) == 0)
+ {
+ switch ( GetCellType( pCell ) )
+ {
+ case CELLTYPE_STRING :
+ case CELLTYPE_EDIT :
+ nRes = 1;
+ break;
+ case CELLTYPE_FORMULA :
+ nRes = !((ScFormulaCell*)pCell)->IsValue();
+ break;
+ }
+ }
+ }
+ break;
+ case svString:
+ PopError();
+ if ( !nGlobalError )
+ nRes = 1;
+ break;
+ default:
+ Pop();
+ }
+ nGlobalError = 0;
+ return nRes;
+}
+
+
+void ScInterpreter::ScIsString()
+{
+ PushInt( IsString() );
+}
+
+
+void ScInterpreter::ScIsNonString()
+{
+ PushInt( !IsString() );
+}
+
+
+void ScInterpreter::ScIsLogical(UINT16 aOldNumType)
+{
+ short nRes = 0;
+ switch ( GetStackType() )
+ {
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ break;
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (GetCellErrCode( pCell ) == 0)
+ {
+ if (HasCellValueData(pCell))
+ {
+ ULONG nFormat = GetCellNumberFormat( aAdr, pCell );
+ nRes = ( pFormatter->GetType(nFormat)
+ == NUMBERFORMAT_LOGICAL);
+ }
+ }
+ }
+ break;
+ default:
+ PopError();
+ if ( !nGlobalError )
+ nRes = ( nCurFmtType == NUMBERFORMAT_LOGICAL );
+ }
+ nCurFmtType = nFuncFmtType = NUMBERFORMAT_LOGICAL;
+ nGlobalError = 0;
+ PushInt( nRes );
+}
+
+
+void ScInterpreter::ScType()
+{
+ short nType = 0;
+ switch ( GetStackType() )
+ {
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ break;
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (GetCellErrCode( pCell ) == 0)
+ {
+ switch ( GetCellType( pCell ) )
+ {
+ case CELLTYPE_STRING :
+ case CELLTYPE_EDIT :
+ nType = 2;
+ break;
+ case CELLTYPE_VALUE :
+ {
+ ULONG nFormat = GetCellNumberFormat( aAdr, pCell );
+ if (pFormatter->GetType(nFormat)
+ == NUMBERFORMAT_LOGICAL)
+ nType = 4;
+ else
+ nType = 1;
+ }
+ break;
+ case CELLTYPE_FORMULA :
+ nType = 8;
+ break;
+ default:
+ SetIllegalParameter();
+ }
+ }
+ else
+ nType = 16;
+ }
+ break;
+ case svString:
+ PopError();
+ if ( nGlobalError )
+ {
+ nType = 16;
+ nGlobalError = 0;
+ }
+ else
+ nType = 2;
+ break;
+ default:
+ PopError();
+ if ( nGlobalError )
+ {
+ nType = 16;
+ nGlobalError = 0;
+ }
+ else
+ nType = 1;
+ }
+ PushInt( nType );
+}
+
+
+void ScInterpreter::ScIsRef()
+{
+ nFuncFmtType = NUMBERFORMAT_LOGICAL;
+ short nRes = 0;
+ switch ( GetStackType() )
+ {
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ PopSingleRef( aAdr );
+ if ( !nGlobalError )
+ nRes = 1;
+ }
+ break;
+ case svDoubleRef :
+ {
+ ScRange aRange;
+ PopDoubleRef( aRange );
+ if ( !nGlobalError )
+ nRes = 1;
+ }
+ break;
+ default:
+ Pop();
+ }
+ nGlobalError = 0;
+ PushInt( nRes );
+}
+
+
+void ScInterpreter::ScIsValue()
+{
+ nFuncFmtType = NUMBERFORMAT_LOGICAL;
+ short nRes = 0;
+ switch ( GetStackType() )
+ {
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ break;
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (GetCellErrCode( pCell ) == 0)
+ {
+ switch ( GetCellType( pCell ) )
+ {
+ case CELLTYPE_VALUE :
+ nRes = 1;
+ break;
+ case CELLTYPE_FORMULA :
+ nRes = ((ScFormulaCell*)pCell)->IsValue();
+ break;
+ }
+ }
+ }
+ break;
+ case svString:
+ Pop();
+ break;
+ default:
+ PopError();
+ if ( !nGlobalError )
+ nRes = 1;
+ }
+ nGlobalError = 0;
+ PushInt( nRes );
+}
+
+
+void ScInterpreter::ScIsFormula()
+{
+ nFuncFmtType = NUMBERFORMAT_LOGICAL;
+ short nRes = 0;
+ switch ( GetStackType() )
+ {
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ break;
+ nRes = (GetCellType( GetCell( aAdr ) ) == CELLTYPE_FORMULA);
+ }
+ break;
+ default:
+ Pop();
+ }
+ nGlobalError = 0;
+ PushInt( nRes );
+}
+
+
+void ScInterpreter::ScFormula()
+{
+ String aFormula;
+ switch ( GetStackType() )
+ {
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ break;
+ ScBaseCell* pCell = GetCell( aAdr );
+ switch ( GetCellType( pCell ) )
+ {
+ case CELLTYPE_FORMULA :
+ ((ScFormulaCell*)pCell)->GetFormula( aFormula );
+ break;
+ default:
+ SetError( NOVALUE );
+ }
+ }
+ break;
+ default:
+ Pop();
+ SetError( NOVALUE );
+ }
+ PushStringObject( aFormula );
+}
+
+
+
+void ScInterpreter::ScIsNV()
+{
+ nFuncFmtType = NUMBERFORMAT_LOGICAL;
+ short nRes = 0;
+ switch ( GetStackType() )
+ {
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ PopDoubleRefOrSingleRef( aAdr );
+ if ( nGlobalError == NOVALUE )
+ nRes = 1;
+ else
+ {
+ ScBaseCell* pCell = GetCell( aAdr );
+ USHORT nErr = GetCellErrCode( pCell );
+ nRes = (nErr == NOVALUE);
+ }
+ }
+ break;
+ default:
+ PopError();
+ if ( nGlobalError == NOVALUE )
+ nRes = 1;
+ }
+ nGlobalError = 0;
+ PushInt( nRes );
+}
+
+
+void ScInterpreter::ScIsErr()
+{
+ nFuncFmtType = NUMBERFORMAT_LOGICAL;
+ short nRes = 0;
+ switch ( GetStackType() )
+ {
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ PopDoubleRefOrSingleRef( aAdr );
+ if ( nGlobalError && nGlobalError != NOVALUE )
+ nRes = 1;
+ else
+ {
+ ScBaseCell* pCell = GetCell( aAdr );
+ USHORT nErr = GetCellErrCode( pCell );
+ nRes = (nErr && nErr != NOVALUE);
+ }
+ }
+ break;
+ default:
+ PopError();
+ if ( nGlobalError && nGlobalError != NOVALUE )
+ nRes = 1;
+ }
+ nGlobalError = 0;
+ PushInt( nRes );
+}
+
+
+void ScInterpreter::ScIsError()
+{
+ nFuncFmtType = NUMBERFORMAT_LOGICAL;
+ short nRes = 0;
+ switch ( GetStackType() )
+ {
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ {
+ nRes = 1;
+ break;
+ }
+ if ( nGlobalError )
+ nRes = 1;
+ else
+ {
+ ScBaseCell* pCell = GetCell( aAdr );
+ nRes = (GetCellErrCode( pCell ) != 0);
+ }
+ }
+ break;
+ default:
+ PopError();
+ if ( nGlobalError )
+ nRes = 1;
+ }
+ nGlobalError = 0;
+ PushInt( nRes );
+}
+
+
+short ScInterpreter::IsEven()
+{
+ nFuncFmtType = NUMBERFORMAT_LOGICAL;
+ short nRes = 0;
+ double fVal;
+ switch ( GetStackType() )
+ {
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ break;
+ ScBaseCell* pCell = GetCell( aAdr );
+ USHORT nErr = GetCellErrCode( pCell );
+ if (nErr != 0)
+ SetError(nErr);
+ else
+ {
+ switch ( GetCellType( pCell ) )
+ {
+ case CELLTYPE_VALUE :
+ fVal = GetCellValue( aAdr, pCell );
+ nRes = 1;
+ break;
+ case CELLTYPE_FORMULA :
+ if( ((ScFormulaCell*)pCell)->IsValue() )
+ {
+ fVal = GetCellValue( aAdr, pCell );
+ nRes = 1;
+ }
+ else
+ SetIllegalParameter();
+ break;
+ default:
+ SetIllegalParameter();
+ }
+ }
+ }
+ break;
+ case svDouble:
+ {
+ fVal = PopDouble();
+ nRes = 1;
+ }
+ break;
+ default:
+ SetIllegalParameter();
+ }
+ if (nRes)
+ nRes = ( fmod( SolarMath::ApproxFloor( fabs( fVal ) ), 2.0 ) < 0.5 );
+ return nRes;
+}
+
+
+void ScInterpreter::ScIsEven()
+{
+ PushInt( IsEven() );
+}
+
+
+void ScInterpreter::ScIsOdd()
+{
+ PushInt( !IsEven() );
+}
+
+
+void ScInterpreter::ScN()
+{
+ USHORT nErr = nGlobalError;
+ nGlobalError = 0;
+ double fVal = GetDouble();
+ if ( nGlobalError == NOVALUE || nGlobalError == errIllegalArgument )
+ nGlobalError = 0; // N(#NV) und N("text") sind ok
+ if ( !nGlobalError && nErr != NOVALUE )
+ nGlobalError = nErr;
+ PushDouble( fVal );
+}
+
+
+void ScInterpreter::ScTrim()
+{ // trimmt nicht nur sondern schnibbelt auch doppelte raus!
+ String aVal( GetString() );
+ aVal.EraseLeadingChars();
+ aVal.EraseTrailingChars();
+ String aStr;
+ register const sal_Unicode* p = aVal.GetBuffer();
+ register const sal_Unicode* const pEnd = p + aVal.Len();
+ while ( p < pEnd )
+ {
+ if ( *p != ' ' || p[-1] != ' ' ) // erster kann kein ' ' sein, -1 ist also ok
+ aStr += *p;
+ p++;
+ }
+ PushStringObject( aStr );
+}
+
+
+void ScInterpreter::ScUpper()
+{
+ String aString = GetString();
+ ScGlobal::pCharClass->toUpper(aString);
+ PushStringObject(aString);
+}
+
+
+void ScInterpreter::ScPropper()
+{
+//2do: what to do with I18N-CJK ?!?
+ String aStr( GetString() );
+ String aUpr( ScGlobal::pCharClass->upper( aStr ) );
+ String aLwr( ScGlobal::pCharClass->lower( aStr ) );
+ register sal_Unicode* pStr = aStr.GetBufferAccess();
+ const sal_Unicode* pUpr = aUpr.GetBuffer();
+ const sal_Unicode* pLwr = aLwr.GetBuffer();
+ *pStr = *pUpr;
+ String aTmpStr( 'x' );
+ xub_StrLen nPos = 1;
+ const xub_StrLen nLen = aStr.Len();
+ while( nPos < nLen )
+ {
+ aTmpStr.SetChar( 0, pStr[nPos-1] );
+ if ( !ScGlobal::pCharClass->isLetter( aTmpStr, 0 ) )
+ pStr[nPos] = pUpr[nPos];
+ else
+ pStr[nPos] = pLwr[nPos];
+ nPos++;
+ }
+ aStr.ReleaseBufferAccess( nLen );
+ PushStringObject( aStr );
+}
+
+
+void ScInterpreter::ScLower()
+{
+ String aString = GetString();
+ ScGlobal::pCharClass->toLower(aString);
+ PushStringObject(aString);
+}
+
+
+void ScInterpreter::ScLen()
+{
+ String aStr( GetString() );
+ PushDouble( aStr.Len() );
+}
+
+
+void ScInterpreter::ScT()
+{
+ switch ( GetStackType() )
+ {
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ {
+ PushInt(0);
+ return ;
+ }
+ BOOL bValue = FALSE;
+ ScBaseCell* pCell = GetCell( aAdr );
+ if ( GetCellErrCode( pCell ) == 0 )
+ {
+ switch ( GetCellType( pCell ) )
+ {
+ case CELLTYPE_VALUE :
+ bValue = TRUE;
+ break;
+ case CELLTYPE_FORMULA :
+ bValue = ((ScFormulaCell*)pCell)->IsValue();
+ break;
+ }
+ }
+ if ( bValue )
+ PushString( NULL );
+ else
+ {
+ // wie GetString()
+ GetCellString( aTempStr, pCell );
+ PushString( aTempStr.GetBuffer() );
+ }
+ }
+ break;
+ case svDouble :
+ {
+ PopError();
+ PushString( NULL );
+ }
+ break;
+ case svString :
+ break;
+ default :
+ SetError(errUnknownOpCode);
+ PushInt(0);
+
+ }
+}
+
+
+void ScInterpreter::ScValue()
+{
+ String aInputString = GetString();
+ ULONG nFIndex = 0; // damit default Land/Spr.
+ double fVal;
+ if (pFormatter->IsNumberFormat(aInputString, nFIndex, fVal))
+ PushDouble(fVal);
+ else
+ SetIllegalArgument();
+}
+
+
+//2do: this should be a proper unicode string method
+inline BOOL lcl_ScInterpreter_IsPrintable( sal_Unicode c )
+{
+ return 0x20 <= c && c != 0x7f;
+}
+
+void ScInterpreter::ScClean()
+{
+ String aStr( GetString() );
+ for ( xub_StrLen i = 0; i < aStr.Len(); i++ )
+ {
+ if ( !lcl_ScInterpreter_IsPrintable( aStr.GetChar( i ) ) )
+ aStr.Erase(i,1);
+ }
+ PushStringObject(aStr);
+}
+
+
+void ScInterpreter::ScCode()
+{
+//2do: make it full range unicode?
+ const sal_Unicode* pStr = GetString();
+ PushInt( (sal_uChar) ByteString::ConvertFromUnicode( pStr[0], gsl_getSystemTextEncoding() ) );
+}
+
+
+void ScInterpreter::ScChar()
+{
+//2do: make it full range unicode?
+ double fVal = GetDouble();
+ if (fVal < 0.0 || fVal >= 256.0)
+ SetIllegalArgument();
+ else
+ {
+ sal_Unicode cs[2];
+ cs[0] = ByteString::ConvertToUnicode( (sal_Char) fVal, gsl_getSystemTextEncoding() );
+ cs[1] = 0;
+ PushString(cs);
+ }
+}
+
+
+void ScInterpreter::ScMin( BOOL bTextAsZero )
+{
+ BYTE nParamCount = GetByte();
+ double nMin = SC_DOUBLE_MAXVALUE;
+ double nVal = 0.0;
+ ScAddress aAdr;
+ ScRange aRange;
+ for (short i = 0; i < nParamCount; i++)
+ {
+ switch (GetStackType())
+ {
+ case svDouble :
+ {
+ nVal = GetDouble();
+ if (nMin > nVal) nMin = nVal;
+ nFuncFmtType = NUMBERFORMAT_NUMBER;
+ }
+ break;
+ case svSingleRef :
+ {
+ PopSingleRef( aAdr );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ {
+ nVal = GetCellValue( aAdr, pCell );
+ CurFmtToFuncFmt();
+ if (nMin > nVal) nMin = nVal;
+ }
+ else if ( bTextAsZero && HasCellStringData( pCell ) )
+ {
+ if ( nMin > 0.0 )
+ nMin = 0.0;
+ }
+ }
+ break;
+ case svDoubleRef :
+ {
+ USHORT nErr = 0;
+ PopDoubleRef( aRange );
+ ScValueIterator aValIter( pDok, aRange, glSubTotal, bTextAsZero );
+ if (aValIter.GetFirst(nVal, nErr))
+ {
+ if (nMin > nVal)
+ nMin = nVal;
+ aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex );
+ while ((nErr == 0) && aValIter.GetNext(nVal, nErr))
+ {
+ if (nMin > nVal)
+ nMin = nVal;
+ }
+ SetError(nErr);
+ }
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ USHORT nC, nR;
+ nFuncFmtType = NUMBERFORMAT_NUMBER;
+ pMat->GetDimensions(nC, nR);
+ if (pMat->IsNumeric())
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ {
+ nVal = pMat->GetDouble(i,j);
+ if (nMin > nVal) nMin = nVal;
+ }
+ }
+ else
+ {
+ for (USHORT i = 0; i < nC; i++)
+ {
+ for (USHORT j = 0; j < nR; j++)
+ {
+ if (!pMat->IsString(i,j))
+ {
+ nVal = pMat->GetDouble(i,j);
+ if (nMin > nVal) nMin = nVal;
+ }
+ else if ( bTextAsZero )
+ {
+ if ( nMin > 0.0 )
+ nMin = 0.0;
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ case svString :
+ {
+ Pop();
+ if ( bTextAsZero )
+ {
+ if ( nMin > 0.0 )
+ nMin = 0.0;
+ }
+ else
+ SetError(errIllegalParameter);
+ }
+ break;
+ default :
+ Pop();
+ SetError(errIllegalParameter);
+ }
+ }
+ if (nMin == SC_DOUBLE_MAXVALUE)
+ SetIllegalArgument();
+ else
+ PushDouble(nMin);
+}
+
+#if defined(WIN) && defined(MSC)
+#pragma optimize("",off)
+#endif
+
+void ScInterpreter::ScMax( BOOL bTextAsZero )
+{
+ BYTE nParamCount = GetByte();
+ double nMax = -SC_DOUBLE_MAXVALUE;
+ double nVal = 0.0;
+ ScAddress aAdr;
+ ScRange aRange;
+ for (short i = 0; i < nParamCount; i++)
+ {
+ switch (GetStackType())
+ {
+ case svDouble :
+ {
+ nVal = GetDouble();
+ if (nMax < nVal) nMax = nVal;
+ nFuncFmtType = NUMBERFORMAT_NUMBER;
+ }
+ break;
+ case svSingleRef :
+ {
+ PopSingleRef( aAdr );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ {
+ nVal = GetCellValue( aAdr, pCell );
+ CurFmtToFuncFmt();
+ if (nMax < nVal) nMax = nVal;
+ }
+ else if ( bTextAsZero && HasCellStringData( pCell ) )
+ {
+ if ( nMax < 0.0 )
+ nMax = 0.0;
+ }
+ }
+ break;
+ case svDoubleRef :
+ {
+ USHORT nErr = 0;
+ PopDoubleRef( aRange );
+ ScValueIterator aValIter( pDok, aRange, glSubTotal, bTextAsZero );
+ if (aValIter.GetFirst(nVal, nErr))
+ {
+ if (nMax < nVal)
+ nMax = nVal;
+ aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex );
+ while ((nErr == 0) && aValIter.GetNext(nVal, nErr))
+ {
+ if (nMax < nVal)
+ nMax = nVal;
+ }
+ SetError(nErr);
+ }
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ nFuncFmtType = NUMBERFORMAT_NUMBER;
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ if (pMat->IsNumeric())
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ {
+ nVal = pMat->GetDouble(i,j);
+ if (nMax < nVal) nMax = nVal;
+ }
+ }
+ else
+ {
+ for (USHORT i = 0; i < nC; i++)
+ {
+ for (USHORT j = 0; j < nR; j++)
+ {
+ if (!pMat->IsString(i,j))
+ {
+ nVal = pMat->GetDouble(i,j);
+ if (nMax < nVal) nMax = nVal;
+ }
+ else if ( bTextAsZero )
+ {
+ if ( nMax < 0.0 )
+ nMax = 0.0;
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ case svString :
+ {
+ Pop();
+ if ( bTextAsZero )
+ {
+ if ( nMax < 0.0 )
+ nMax = 0.0;
+ }
+ else
+ SetError(errIllegalParameter);
+ }
+ break;
+ default :
+ Pop();
+ SetError(errIllegalParameter);
+ }
+ }
+ if (nMax == -SC_DOUBLE_MAXVALUE)
+ SetIllegalArgument();
+ else
+ PushDouble(nMax);
+}
+#if defined(WIN) && defined(MSC)
+#pragma optimize("",on)
+#endif
+
+
+double ScInterpreter::IterateParameters( ScIterFunc eFunc, BOOL bTextAsZero )
+{
+ BYTE nParamCount = GetByte();
+ double fRes = ( eFunc == ifPRODUCT ) ? 1.0 : 0.0;
+ double fVal = 0.0;
+ double fMem = 0.0;
+ BOOL bNull = TRUE;
+ long nCount = 0;
+ ScAddress aAdr;
+ ScRange aRange;
+ for (short i = 0; i < nParamCount; i++)
+ {
+ switch (GetStackType())
+ {
+
+ case svString:
+ {
+ if( eFunc == ifCOUNT )
+ {
+ String aStr( PopString() );
+ ULONG nFIndex = 0; // damit default Land/Spr.
+ if ( bTextAsZero || pFormatter->IsNumberFormat(aStr, nFIndex, fVal))
+ nCount++;
+ }
+ else
+ {
+ switch ( eFunc )
+ {
+ case ifAVERAGE:
+ case ifSUM:
+ case ifSUMSQ:
+ case ifPRODUCT:
+ {
+ if ( bTextAsZero )
+ {
+ Pop();
+ nCount++;
+ if ( eFunc == ifPRODUCT )
+ fRes = 0.0;
+ }
+ else
+ {
+ for ( ; i < nParamCount; i++ )
+ Pop();
+ SetError( errNoValue );
+ }
+ }
+ break;
+ default:
+ Pop();
+ nCount++;
+ }
+ }
+ }
+ break;
+ case svDouble :
+ fVal = GetDouble();
+ nCount++;
+ switch( eFunc )
+ {
+ case ifAVERAGE:
+ case ifSUM:
+ if ( bNull && fVal != 0.0 )
+ {
+ bNull = FALSE;
+ fMem = fVal;
+ }
+ else
+ fRes += fVal;
+ break;
+ case ifSUMSQ: fRes += fVal * fVal; break;
+ case ifPRODUCT: fRes *= fVal; break;
+ }
+ nFuncFmtType = NUMBERFORMAT_NUMBER;
+ break;
+ case svSingleRef :
+ {
+ PopSingleRef( aAdr );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if ( pCell )
+ {
+ if( eFunc == ifCOUNT2 )
+ {
+ CellType eCellType = pCell->GetCellType();
+ if (eCellType != CELLTYPE_NONE && eCellType != CELLTYPE_NOTE)
+ nCount++;
+ }
+ else if ( pCell->HasValueData() )
+ {
+ nCount++;
+ fVal = GetCellValue( aAdr, pCell );
+ CurFmtToFuncFmt();
+ switch( eFunc )
+ {
+ case ifAVERAGE:
+ case ifSUM:
+ if ( bNull && fVal != 0.0 )
+ {
+ bNull = FALSE;
+ fMem = fVal;
+ }
+ else
+ fRes += fVal;
+ break;
+ case ifSUMSQ: fRes += fVal * fVal; break;
+ case ifPRODUCT: fRes *= fVal; break;
+ }
+ }
+ else if ( bTextAsZero && pCell->HasStringData() )
+ {
+ nCount++;
+ if ( eFunc == ifPRODUCT )
+ fRes = 0.0;
+ }
+ }
+ }
+ break;
+ case svDoubleRef :
+ {
+ USHORT nErr = 0;
+ PopDoubleRef( aRange );
+ if( eFunc == ifCOUNT2 )
+ {
+ ScBaseCell* pCell;
+ ScCellIterator aIter( pDok, aRange, glSubTotal );
+ if (pCell = aIter.GetFirst())
+ {
+ do
+ {
+ CellType eType = pCell->GetCellType();
+ if( eType != CELLTYPE_NONE && eType != CELLTYPE_NOTE )
+ nCount++;
+ }
+ while ( pCell = aIter.GetNext());
+ }
+ }
+ else
+ {
+ ScValueIterator aValIter( pDok, aRange, glSubTotal, bTextAsZero );
+ if (aValIter.GetFirst(fVal, nErr))
+ {
+ // Schleife aus Performance-Gruenden nach innen verlegt:
+ aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex );
+ switch( eFunc )
+ {
+ case ifAVERAGE:
+ case ifSUM:
+ do
+ {
+ SetError(nErr);
+ if ( bNull && fVal != 0.0 )
+ {
+ bNull = FALSE;
+ fMem = fVal;
+ }
+ else
+ fRes += fVal;
+ nCount++;
+ }
+ while (aValIter.GetNext(fVal, nErr));
+ break;
+ case ifSUMSQ:
+ do
+ {
+ SetError(nErr);
+ fRes += fVal * fVal;
+ nCount++;
+ }
+ while (aValIter.GetNext(fVal, nErr));
+ break;
+ case ifPRODUCT:
+ do
+ {
+ SetError(nErr);
+ fRes *= fVal;
+ nCount++;
+ }
+ while (aValIter.GetNext(fVal, nErr));
+ break;
+ default: // count
+ do
+ {
+ SetError(nErr);
+ nCount++;
+ }
+ while (aValIter.GetNext(fVal, nErr));
+ break;
+ }
+ SetError( nErr );
+ }
+ }
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ USHORT nC, nR;
+ nFuncFmtType = NUMBERFORMAT_NUMBER;
+ pMat->GetDimensions(nC, nR);
+ if( eFunc == ifCOUNT2 )
+ nCount += nC * nR;
+ else
+ {
+ for (USHORT i = 0; i < nC; i++)
+ {
+ for (USHORT j = 0; j < nR; j++)
+ {
+ if (!pMat->IsString(i,j))
+ {
+ nCount++;
+ fVal = pMat->GetDouble(i,j);
+ switch( eFunc )
+ {
+ case ifAVERAGE:
+ case ifSUM:
+ if ( bNull && fVal != 0.0 )
+ {
+ bNull = FALSE;
+ fMem = fVal;
+ }
+ else
+ fRes += fVal;
+ break;
+ case ifSUMSQ: fRes += fVal * fVal; break;
+ case ifPRODUCT: fRes *= fVal; break;
+ }
+ }
+ else if ( bTextAsZero )
+ {
+ nCount++;
+ if ( eFunc == ifPRODUCT )
+ fRes = 0.0;
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ default :
+ for ( ; i < nParamCount; i++ )
+ Pop();
+ SetError(errIllegalParameter);
+ }
+ }
+ switch( eFunc )
+ {
+ case ifSUM: fRes = SolarMath::ApproxAdd( fRes, fMem ); break;
+ case ifAVERAGE: fRes = SolarMath::ApproxAdd( fRes, fMem ) / nCount; break;
+ case ifCOUNT2:
+ case ifCOUNT: fRes = nCount; break;
+ case ifPRODUCT: if ( !nCount ) fRes = 0.0; break;
+ }
+ // Bei Summen etc. macht ein BOOL-Ergebnis keinen Sinn
+ // und Anzahl ist immer Number (#38345#)
+ if( eFunc == ifCOUNT || nFuncFmtType == NUMBERFORMAT_LOGICAL )
+ nFuncFmtType = NUMBERFORMAT_NUMBER;
+ return fRes;
+}
+
+
+void ScInterpreter::ScSumSQ()
+{
+ PushDouble( IterateParameters( ifSUMSQ ) );
+}
+
+
+void ScInterpreter::ScSum()
+{
+ PushDouble( IterateParameters( ifSUM ) );
+}
+
+
+void ScInterpreter::ScProduct()
+{
+ PushDouble( IterateParameters( ifPRODUCT ) );
+}
+
+
+void ScInterpreter::ScAverage( BOOL bTextAsZero )
+{
+ PushDouble( IterateParameters( ifAVERAGE, bTextAsZero ) );
+}
+
+
+void ScInterpreter::ScCount()
+{
+ PushDouble( IterateParameters( ifCOUNT ) );
+}
+
+
+void ScInterpreter::ScCount2()
+{
+ PushDouble( IterateParameters( ifCOUNT2 ) );
+}
+
+
+void ScInterpreter::GetStVarParams( double& rVal, double& rValCount,
+ BOOL bTextAsZero )
+{
+ BYTE nParamCount = GetByte();
+ USHORT i;
+ double fSum = 0.0;
+ double fSumSqr = 0.0;
+ double fVal;
+ rValCount = 0.0;
+ ScAddress aAdr;
+ ScRange aRange;
+ for (i = 0; i < nParamCount; i++)
+ {
+ switch (GetStackType())
+ {
+ case svDouble :
+ {
+ fVal = GetDouble();
+ fSum += fVal;
+ fSumSqr += fVal*fVal;
+ rValCount++;
+ }
+ break;
+ case svSingleRef :
+ {
+ PopSingleRef( aAdr );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ {
+ fVal = GetCellValue( aAdr, pCell );
+ fSum += fVal;
+ fSumSqr += fVal*fVal;
+ rValCount++;
+ }
+ else if ( bTextAsZero && HasCellStringData( pCell ) )
+ rValCount++;
+ }
+ break;
+ case svDoubleRef :
+ {
+ USHORT nErr = 0;
+ PopDoubleRef( aRange );
+ ScValueIterator aValIter( pDok, aRange, glSubTotal, bTextAsZero );
+ if (aValIter.GetFirst(fVal, nErr))
+ {
+ do
+ {
+ fSum += fVal;
+ fSumSqr += fVal*fVal;
+ rValCount++;
+ }
+ while ((nErr == 0) && aValIter.GetNext(fVal, nErr));
+ }
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ for (USHORT i = 0; i < nC; i++)
+ {
+ for (USHORT j = 0; j < nR; j++)
+ {
+ if (!pMat->IsString(i,j))
+ {
+ fVal= pMat->GetDouble(i,j);
+ fSum += fVal;
+ fSumSqr += fVal * fVal;
+ rValCount++;
+ }
+ else if ( bTextAsZero )
+ rValCount++;
+ }
+ }
+ }
+ }
+ break;
+ case svString :
+ {
+ if ( bTextAsZero )
+ rValCount++;
+ else
+ {
+ Pop();
+ SetError(errIllegalParameter);
+ }
+ }
+ default :
+ Pop();
+ SetError(errIllegalParameter);
+ }
+ }
+ rVal = fSumSqr - fSum*fSum/rValCount;
+}
+
+
+void ScInterpreter::ScVar( BOOL bTextAsZero )
+{
+ double nVal;
+ double nValCount;
+ GetStVarParams( nVal, nValCount, bTextAsZero );
+ PushDouble(nVal / (nValCount - 1.0));
+}
+
+
+void ScInterpreter::ScVarP( BOOL bTextAsZero )
+{
+ double nVal;
+ double nValCount;
+ GetStVarParams( nVal, nValCount, bTextAsZero );
+ PushDouble(nVal / nValCount);
+}
+
+
+void ScInterpreter::ScStDev( BOOL bTextAsZero )
+{
+ double nVal;
+ double nValCount;
+ GetStVarParams( nVal, nValCount, bTextAsZero );
+ PushDouble(sqrt(nVal / (nValCount - 1.0)));
+}
+
+
+void ScInterpreter::ScStDevP( BOOL bTextAsZero )
+{
+ double nVal;
+ double nValCount;
+ GetStVarParams( nVal, nValCount, bTextAsZero );
+ PushDouble(sqrt(nVal / nValCount));
+}
+
+
+void ScInterpreter::ScColumns()
+{
+ BYTE nParamCount = GetByte();
+ ULONG nVal = 0;
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ for (USHORT i = 1; i <= nParamCount; i++)
+ {
+ switch ( GetStackType() )
+ {
+ case svSingleRef:
+ PopError();
+ nVal++;
+ break;
+ case svDoubleRef:
+ PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+ nVal += (nTab2 - nTab1 + 1) * (nCol2 - nCol1 + 1);
+ break;
+ case svMatrix:
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ nVal += nC;
+ }
+ }
+ break;
+ default:
+ PopError();
+ SetError(errIllegalParameter);
+ }
+ }
+ PushDouble((double)nVal);
+}
+
+
+void ScInterpreter::ScRows()
+{
+ BYTE nParamCount = GetByte();
+ ULONG nVal = 0;
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ for (USHORT i = 1; i <= nParamCount; i++)
+ {
+ switch ( GetStackType() )
+ {
+ case svSingleRef:
+ PopError();
+ nVal++;
+ break;
+ case svDoubleRef:
+ PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+ nVal += (nTab2 - nTab1 + 1) * (nRow2 - nRow1 + 1);
+ break;
+ case svMatrix:
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ nVal += nR;
+ }
+ }
+ break;
+ default:
+ PopError();
+ SetError(errIllegalParameter);
+ }
+ }
+ PushDouble((double)nVal);
+}
+
+void ScInterpreter::ScTables()
+{
+ BYTE nParamCount = GetByte();
+ ULONG nVal;
+ if ( nParamCount == 0 )
+ nVal = pDok->GetTableCount();
+ else
+ {
+ nVal = 0;
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ for (USHORT i = 1; i <= nParamCount; i++)
+ {
+ switch ( GetStackType() )
+ {
+ case svSingleRef:
+ PopError();
+ nVal++;
+ break;
+ case svDoubleRef:
+ PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+ nVal += (nTab2 - nTab1 + 1);
+ break;
+ case svMatrix:
+ PopError();
+ nVal++;
+ break;
+ default:
+ PopError();
+ SetError( errIllegalParameter );
+ }
+ }
+ }
+ PushDouble( (double) nVal );
+}
+
+
+void ScInterpreter::ScColumn()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 0, 1 ) )
+ {
+ double nVal;
+ if (nParamCount == 0)
+ nVal = aPos.Col() + 1;
+ else
+ {
+ switch ( GetStackType() )
+ {
+ case svSingleRef :
+ {
+ USHORT nCol1, nRow1, nTab1;
+ PopSingleRef( nCol1, nRow1, nTab1 );
+ nVal = (double) (nCol1 + 1);
+ }
+ break;
+ case svDoubleRef :
+ {
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ if (nCol2 > nCol1)
+ {
+ USHORT nMatInd;
+ ScMatrix* pResMat = GetNewMat(nCol2-nCol1+1, 1, nMatInd);
+ if (pResMat)
+ {
+ for (USHORT i = nCol1; i <= nCol2; i++)
+ pResMat->PutDouble((double)(i+1), i-nCol1, 0);
+ PushMatrix(pResMat);
+ nRetMat = nMatInd;
+ return;
+ }
+ else
+ {
+ SetError( errIllegalParameter );
+ nVal = 0.0;
+ }
+ }
+ else
+ nVal = (double) (nCol1 + 1);
+ }
+ break;
+ default:
+ SetError( errIllegalParameter );
+ nVal = 0.0;
+ }
+ }
+ PushDouble( nVal );
+ }
+}
+
+
+void ScInterpreter::ScRow()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 0, 1 ) )
+ {
+ double nVal;
+ if (nParamCount == 0)
+ nVal = aPos.Row() + 1;
+ else
+ {
+ switch ( GetStackType() )
+ {
+ case svSingleRef :
+ {
+ USHORT nCol1, nRow1, nTab1;
+ PopSingleRef( nCol1, nRow1, nTab1 );
+ nVal = (double) (nRow1 + 1);
+ }
+ break;
+ case svDoubleRef :
+ {
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ if (nRow2 > nRow1)
+ {
+ USHORT nMatInd;
+ ScMatrix* pResMat = GetNewMat(1, nRow2-nRow1+1, nMatInd);
+ if (pResMat)
+ {
+ for (USHORT i = nRow1; i <= nRow2; i++)
+ pResMat->PutDouble((double)(i+1), 0, i-nRow1);
+ PushMatrix(pResMat);
+ nRetMat = nMatInd;
+ return;
+ }
+ else
+ {
+ SetError( errIllegalParameter );
+ nVal = 0.0;
+ }
+ }
+ else
+ nVal = (double) (nRow1 + 1);
+ }
+ break;
+ default:
+ SetError( errIllegalParameter );
+ nVal = 0.0;
+ }
+ }
+ PushDouble( nVal );
+ }
+}
+
+void ScInterpreter::ScTable()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 0, 1 ) )
+ {
+ USHORT nVal;
+ if ( nParamCount == 0 )
+ nVal = aPos.Tab() + 1;
+ else
+ {
+ switch ( GetStackType() )
+ {
+ case svString :
+ {
+ String aStr( PopString() );
+ if ( pDok->GetTable( aStr, nVal ) )
+ ++nVal;
+ else
+ SetError( errIllegalArgument );
+ }
+ break;
+ case svSingleRef :
+ {
+ USHORT nCol1, nRow1, nTab1;
+ PopSingleRef( nCol1, nRow1, nTab1 );
+ nVal = nTab1 + 1;
+ }
+ break;
+ case svDoubleRef :
+ {
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ nVal = nTab1 + 1;
+ }
+ break;
+ default:
+ SetError( errIllegalParameter );
+ }
+ if ( nGlobalError )
+ nVal = 0;
+ }
+ PushDouble( (double) nVal );
+ }
+}
+
+
+void ScInterpreter::ScMatch()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 2, 3 ) )
+ {
+ double fTyp;
+ if (nParamCount == 3)
+ fTyp = GetDouble();
+ else
+ fTyp = 1.0;
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ if (GetStackType() == svDoubleRef)
+ {
+ PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+ if (nTab1 != nTab2 || (nCol1 != nCol2 && nRow1 != nRow2))
+ {
+ SetIllegalParameter();
+ return;
+ }
+ }
+ else
+ {
+ SetIllegalParameter();
+ return;
+ }
+ if (nGlobalError == 0)
+ {
+ double fVal;
+ String sStr;
+ ScQueryParam rParam;
+ rParam.nCol1 = nCol1;
+ rParam.nRow1 = nRow1;
+ rParam.nCol2 = nCol2;
+ rParam.bHasHeader = FALSE;
+ rParam.bInplace = TRUE;
+ rParam.bCaseSens = FALSE;
+ rParam.bRegExp = TRUE;
+ rParam.bDuplicate = FALSE;
+
+ ScQueryEntry& rEntry = rParam.GetEntry(0);
+ rEntry.bDoQuery = TRUE;
+ if (fTyp < 0.0)
+ rEntry.eOp = SC_GREATER_EQUAL;
+ else if (fTyp > 0.0)
+ rEntry.eOp = SC_LESS_EQUAL;
+ switch ( GetStackType() )
+ {
+ case svDouble:
+ {
+ fVal = GetDouble();
+ rEntry.bQueryByString = FALSE;
+ rEntry.nVal = fVal;
+ }
+ break;
+ case svString:
+ {
+ sStr = GetString();
+ rEntry.bQueryByString = TRUE;
+ *rEntry.pStr = sStr;
+ }
+ break;
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ {
+ PushInt(0);
+ return ;
+ }
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ {
+ fVal = GetCellValue( aAdr, pCell );
+ rEntry.bQueryByString = FALSE;
+ rEntry.nVal = fVal;
+ }
+ else
+ {
+ GetCellString(sStr, pCell);
+ rEntry.bQueryByString = TRUE;
+ *rEntry.pStr = sStr;
+ }
+ }
+ break;
+ default:
+ {
+ SetIllegalParameter();
+ return;
+ }
+ }
+ if ( rEntry.bQueryByString )
+ rParam.bRegExp = MayBeRegExp( *rEntry.pStr );
+ USHORT nDelta, nR, nC;
+ if (nCol1 == nCol2) // spaltenweise
+ {
+ rParam.nRow2 = nRow2;
+ rEntry.nField = nCol1;
+ ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE);
+ if (fTyp == 0.0) // exakte Suche
+ {
+ if (aCellIter.GetFirst())
+ {
+ nR = aCellIter.GetRow();
+ if (aCellIter.GetNext())
+ {
+ SetNV();
+ return;
+ }
+ }
+ else
+ {
+ SetNV();
+ return;
+ }
+ }
+ else if (aCellIter.GetFirst()) // <= bzw. >= Suche
+ {
+ do
+ {
+ nR = aCellIter.GetRow();
+ } while ( aCellIter.GetNext() );
+ }
+ else
+ {
+ SetNV();
+ return;
+ }
+ nDelta = nR - nRow1;
+ }
+ else // zeilenweise
+ {
+ rParam.nRow2 = nRow1;
+ rEntry.nField = nCol1;
+ ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE);
+ // Entry.nField im Iterator bei Spaltenwechsel weiterschalten
+ aCellIter.SetAdvanceQueryParamEntryField( TRUE );
+ if (fTyp == 0.0) // exakte Suche
+ {
+ if ( aCellIter.GetFirst() )
+ {
+ nC = aCellIter.GetCol();
+ if ( aCellIter.GetNext() )
+ { // doppelt gefunden
+ SetNV();
+ return;
+ }
+ }
+ else
+ { // gar nicht gefunden
+ SetNV();
+ return;
+ }
+ }
+ else if ( aCellIter.GetFirst() ) // <= bzw. >= Suche
+ {
+ do
+ {
+ nC = aCellIter.GetCol();
+ } while ( aCellIter.GetNext() );
+ }
+ else
+ {
+ SetNV();
+ return;
+ }
+ nDelta = nC - nCol1;
+ }
+ PushDouble((double) (nDelta + 1));
+ }
+ else
+ SetIllegalParameter();
+ }
+}
+
+
+void ScInterpreter::ScCountEmptyCells()
+{
+ if ( MustHaveParamCount( GetByte(), 1 ) )
+ {
+ long nMaxCount = 0, nCount = 0;
+ CellType eCellType;
+ switch (GetStackType())
+ {
+ case svSingleRef :
+ {
+ nMaxCount = 1;
+ ScAddress aAdr;
+ PopSingleRef( aAdr );
+ eCellType = GetCellType( GetCell( aAdr ) );
+ if (eCellType != CELLTYPE_NONE && eCellType != CELLTYPE_NOTE)
+ nCount = 1;
+ }
+ break;
+ case svDoubleRef :
+ {
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+ nMaxCount = (nRow2 - nRow1 + 1) * (nCol2 - nCol1 + 1)
+ * (nTab2 - nTab1 + 1);
+ ScBaseCell* pCell;
+ ScCellIterator aDocIter(pDok, nCol1, nRow1, nTab1,
+ nCol2, nRow2, nTab2, glSubTotal);
+ if (pCell = aDocIter.GetFirst())
+ {
+ do
+ {
+ if ((eCellType = pCell->GetCellType()) != CELLTYPE_NONE
+ && eCellType != CELLTYPE_NOTE)
+ nCount++;
+ } while ( pCell = aDocIter.GetNext() );
+ }
+ }
+ break;
+ default : SetError(errIllegalParameter); break;
+ }
+ PushDouble(nMaxCount - nCount);
+ }
+}
+
+
+void ScInterpreter::ScCountIf()
+{
+ if ( MustHaveParamCount( GetByte(), 2 ) )
+ {
+ String rString;
+ double fVal;
+ BOOL bIsString = TRUE;
+ switch ( GetStackType() )
+ {
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ {
+ PushInt(0);
+ return ;
+ }
+ ScBaseCell* pCell = GetCell( aAdr );
+ switch ( GetCellType( pCell ) )
+ {
+ case CELLTYPE_VALUE :
+ fVal = GetCellValue( aAdr, pCell );
+ bIsString = FALSE;
+ break;
+ case CELLTYPE_FORMULA :
+ if( ((ScFormulaCell*)pCell)->IsValue() )
+ {
+ fVal = GetCellValue( aAdr, pCell );
+ bIsString = FALSE;
+ }
+ else
+ GetCellString(rString, pCell);
+ break;
+ case CELLTYPE_STRING :
+ case CELLTYPE_EDIT :
+ GetCellString(rString, pCell);
+ break;
+ default:
+ fVal = 0.0;
+ bIsString = FALSE;
+ }
+ }
+ break;
+ case svString:
+ rString = GetString();
+ break;
+ default:
+ {
+ fVal = GetDouble();
+ bIsString = FALSE;
+ }
+ }
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ switch ( GetStackType() )
+ {
+ case svDoubleRef :
+ PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ break;
+ case svSingleRef :
+ PopSingleRef( nCol1, nRow1, nTab1 );
+ nCol2 = nCol1;
+ nRow2 = nRow1;
+ nTab2 = nTab1;
+ break;
+ default:
+ SetIllegalParameter();
+ return ;
+ }
+ if ( nTab1 != nTab2 )
+ {
+ SetIllegalParameter();
+ return;
+ }
+ if (nCol1 > nCol2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ if (nGlobalError == 0)
+ {
+ ScQueryParam rParam;
+ rParam.nRow1 = nRow1;
+ rParam.nRow2 = nRow2;
+ rParam.bHasHeader = FALSE;
+ rParam.bInplace = TRUE;
+ rParam.bCaseSens = FALSE;
+ rParam.bRegExp = TRUE;
+ rParam.bDuplicate = FALSE;
+
+ ScQueryEntry& rEntry = rParam.GetEntry(0);
+ rEntry.bDoQuery = TRUE;
+ if (!bIsString)
+ {
+ rEntry.bQueryByString = FALSE;
+ rEntry.nVal = fVal;
+ rEntry.eOp = SC_EQUAL;
+ }
+ else if( rString.Len() )
+ {
+ rParam.FillInExcelSyntax(rString,(USHORT) 0);
+ ULONG nIndex = 0;
+ rEntry.bQueryByString =
+ !(pFormatter->IsNumberFormat(
+ *rEntry.pStr, nIndex, rEntry.nVal));
+ if ( rEntry.bQueryByString )
+ rParam.bRegExp = MayBeRegExp( *rEntry.pStr );
+ }
+ else
+ {
+ PushInt( 0 );
+ return;
+ }
+ double fSum = 0.0;
+ rParam.nCol1 = nCol1;
+ rParam.nCol2 = nCol2;
+ rEntry.nField = nCol1;
+ ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE);
+ // Entry.nField im Iterator bei Spaltenwechsel weiterschalten
+ aCellIter.SetAdvanceQueryParamEntryField( TRUE );
+ if ( aCellIter.GetFirst() )
+ {
+ do
+ {
+ fSum++;
+ } while ( aCellIter.GetNext() );
+ }
+ PushDouble(fSum);
+ }
+ else
+ SetIllegalParameter();
+ }
+}
+
+
+void ScInterpreter::ScSumIf()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 2, 3 ) )
+ {
+ USHORT nCol3, nRow3, nTab3, nCol4, nRow4, nTab4;
+ if (nParamCount == 3)
+ {
+ switch ( GetStackType() )
+ {
+ case svDoubleRef :
+ PopDoubleRef( nCol3, nRow3, nTab3, nCol4, nRow4, nTab4 );
+ break;
+ case svSingleRef :
+ PopSingleRef( nCol3, nRow3, nTab3 );
+ nCol4 = nCol3;
+ nRow4 = nRow3;
+ nTab4 = nTab3;
+ break;
+ default:
+ SetIllegalParameter();
+ return ;
+ }
+ if ( nTab3 != nTab4 )
+ {
+ SetIllegalParameter();
+ return;
+ }
+ }
+ String rString;
+ double fVal;
+ BOOL bIsString = TRUE;
+ switch ( GetStackType() )
+ {
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ {
+ PushInt(0);
+ return ;
+ }
+ ScBaseCell* pCell = GetCell( aAdr );
+ switch ( GetCellType( pCell ) )
+ {
+ case CELLTYPE_VALUE :
+ fVal = GetCellValue( aAdr, pCell );
+ bIsString = FALSE;
+ break;
+ case CELLTYPE_FORMULA :
+ if( ((ScFormulaCell*)pCell)->IsValue() )
+ {
+ fVal = GetCellValue( aAdr, pCell );
+ bIsString = FALSE;
+ }
+ else
+ GetCellString(rString, pCell);
+ break;
+ case CELLTYPE_STRING :
+ case CELLTYPE_EDIT :
+ GetCellString(rString, pCell);
+ break;
+ default:
+ fVal = 0.0;
+ bIsString = FALSE;
+ }
+ }
+ break;
+ case svString:
+ rString = GetString();
+ break;
+ default:
+ {
+ fVal = GetDouble();
+ bIsString = FALSE;
+ }
+ }
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ switch ( GetStackType() )
+ {
+ case svDoubleRef :
+ PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ break;
+ case svSingleRef :
+ PopSingleRef( nCol1, nRow1, nTab1 );
+ nCol2 = nCol1;
+ nRow2 = nRow1;
+ nTab2 = nTab1;
+ break;
+ default:
+ SetIllegalParameter();
+ return ;
+ }
+ if ( nTab1 != nTab2 )
+ {
+ SetIllegalParameter();
+ return;
+ }
+ if (nParamCount != 3)
+ {
+ nCol3 = nCol1;
+ nRow3 = nRow1;
+ nTab3 = nTab1;
+ nCol4 = nCol2;
+ nRow4 = nRow2;
+ nTab4 = nTab2;
+ }
+ else if (nCol4 - nCol3 != nCol2 - nCol1 ||
+ nRow4 - nRow3 != nRow2 - nRow1 || nCol1 > nCol2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ if (nGlobalError == 0)
+ {
+ ScQueryParam rParam;
+ rParam.nRow1 = nRow1;
+ rParam.nRow2 = nRow2;
+ rParam.bHasHeader = FALSE;
+ rParam.bInplace = TRUE;
+ rParam.bCaseSens = FALSE;
+ rParam.bRegExp = TRUE;
+ rParam.bDuplicate = FALSE;
+
+ ScQueryEntry& rEntry = rParam.GetEntry(0);
+ rEntry.bDoQuery = TRUE;
+ if (!bIsString)
+ {
+ rEntry.bQueryByString = FALSE;
+ rEntry.nVal = fVal;
+ rEntry.eOp = SC_EQUAL;
+ }
+ else
+ {
+ rParam.FillInExcelSyntax(rString,(USHORT) 0);
+ ULONG nIndex = 0;
+ rEntry.bQueryByString =
+ !(pFormatter->IsNumberFormat(
+ *rEntry.pStr, nIndex, rEntry.nVal));
+ if ( rEntry.bQueryByString )
+ rParam.bRegExp = MayBeRegExp( *rEntry.pStr );
+ }
+ double fSum = 0.0;
+ double fMem = 0.0;
+ BOOL bNull = TRUE;
+ ScAddress aAdr;
+ aAdr.SetTab( nTab3 );
+ rParam.nCol1 = nCol1;
+ rParam.nCol2 = nCol2;
+ rEntry.nField = nCol1;
+ short nColDiff = nCol3 - nCol1;
+ short nRowDiff = nRow3 - nRow1;
+ ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE);
+ // Entry.nField im Iterator bei Spaltenwechsel weiterschalten
+ aCellIter.SetAdvanceQueryParamEntryField( TRUE );
+ if ( aCellIter.GetFirst() )
+ {
+ do
+ {
+ aAdr.SetCol( aCellIter.GetCol() + nColDiff );
+ aAdr.SetRow( aCellIter.GetRow() + nRowDiff );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if ( HasCellValueData(pCell) )
+ {
+ fVal = GetCellValue( aAdr, pCell );
+ if ( bNull && fVal != 0.0 )
+ {
+ bNull = FALSE;
+ fMem = fVal;
+ }
+ else
+ fSum += fVal;
+ }
+ } while ( aCellIter.GetNext() );
+ }
+ PushDouble( SolarMath::ApproxAdd( fSum, fMem ) );
+ }
+ else
+ SetIllegalParameter();
+ }
+}
+
+
+void ScInterpreter::ScLookup()
+{
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
+ return ;
+ USHORT nC3, nR3, nC1, nR1;
+ ScMatrix* pMat3 = NULL;
+ ScMatrix* pMat1 = NULL;
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ USHORT nCol3, nRow3, nTab3, nCol4, nRow4, nTab4;
+ USHORT nDelta;
+ if (nParamCount == 3)
+ {
+ if (GetStackType() == svDoubleRef)
+ {
+ PopDoubleRef(nCol3, nRow3, nTab3, nCol4, nRow4, nTab4);
+ if (nTab3 != nTab4 || (nCol3 != nCol4 && nRow3 != nRow4))
+ {
+ SetIllegalParameter();
+ return;
+ }
+ }
+ else if (GetStackType() == svMatrix)
+ {
+ pMat3 = PopMatrix();
+ if (pMat3)
+ {
+ pMat3->GetDimensions(nC3, nR3);
+ if (nC3 != 1 && nR3 != 1)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ }
+ else
+ {
+ SetIllegalParameter();
+ return;
+ }
+ }
+ else
+ {
+ SetIllegalParameter();
+ return;
+ }
+ if (GetStackType() == svDoubleRef)
+ {
+ PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+ if (nTab1 != nTab2 || (nCol1 != nCol2 && nRow1 != nRow2))
+ {
+ SetIllegalParameter();
+ return;
+ }
+ }
+ else if (GetStackType() == svMatrix)
+ {
+ pMat1 = PopMatrix();
+ if (pMat1)
+ {
+ pMat1->GetDimensions(nC1, nR1);
+ if (nC1 != 1 && nR1 != 1)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ }
+ else
+ {
+ SetIllegalParameter();
+ return;
+ }
+ }
+ else
+ {
+ SetIllegalParameter();
+ return;
+ }
+ BOOL bSpMatrix, bSpVector;
+ USHORT nMatCount, nVecCount;
+ if (pMat1 == NULL)
+ {
+ if (nCol1 == nCol2)
+ {
+ nMatCount = nRow2 - nRow1 + 1;
+ bSpMatrix = TRUE;
+ }
+ else
+ {
+ nMatCount = nCol2 - nCol1 + 1;
+ bSpMatrix = FALSE;
+ }
+ }
+ else
+ {
+ if (nR1 == 1)
+ {
+ nMatCount = nC1;
+ bSpMatrix = TRUE;
+ }
+ else
+ {
+ nMatCount = nR1;
+ bSpMatrix = FALSE;
+ }
+ }
+ if (pMat3 == NULL)
+ {
+ if (nCol3 == nCol4)
+ {
+ nVecCount = nRow4 - nRow3 + 1;
+ bSpVector = TRUE;
+ }
+ else
+ {
+ nVecCount = nCol4 - nCol3 + 1;
+ bSpVector = FALSE;
+ }
+ }
+ else
+ {
+ if (nR3 == 1)
+ {
+ nVecCount = nC3;
+ bSpVector = TRUE;
+ }
+ else
+ {
+ nVecCount = nR3;
+ bSpVector = FALSE;
+ }
+ }
+ if (nGlobalError == 0 && nVecCount == nMatCount)
+ {
+ String sStr;
+ ScQueryParam rParam;
+ rParam.nCol1 = nCol1;
+ rParam.nRow1 = nRow1;
+ rParam.nCol2 = nCol2;
+ rParam.bHasHeader = FALSE;
+ rParam.bInplace = TRUE;
+ rParam.bCaseSens = FALSE;
+ rParam.bRegExp = TRUE;
+ rParam.bDuplicate = FALSE;
+
+ ScQueryEntry& rEntry = rParam.GetEntry(0);
+ rEntry.bDoQuery = TRUE;
+ rEntry.eOp = SC_LESS_EQUAL;
+ switch ( GetStackType() )
+ {
+ case svDouble:
+ {
+ rEntry.bQueryByString = FALSE;
+ rEntry.nVal = GetDouble();
+ }
+ break;
+ case svString:
+ {
+ sStr = GetString();
+ rEntry.bQueryByString = TRUE;
+ *rEntry.pStr = sStr;
+ }
+ break;
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ {
+ PushInt(0);
+ return ;
+ }
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ {
+ rEntry.bQueryByString = FALSE;
+ rEntry.nVal = GetCellValue( aAdr, pCell );
+ }
+ else
+ {
+ if ( GetCellType( pCell ) == CELLTYPE_NOTE )
+ {
+ rEntry.bQueryByString = FALSE;
+ rEntry.nVal = 0.0;
+ }
+ else
+ {
+ GetCellString(sStr, pCell);
+ rEntry.bQueryByString = TRUE;
+ *rEntry.pStr = sStr;
+ }
+ }
+ }
+ break;
+ default:
+ {
+ SetIllegalParameter();
+ return;
+ }
+ }
+ if ( rEntry.bQueryByString )
+ rParam.bRegExp = MayBeRegExp( *rEntry.pStr );
+ if (pMat1)
+ {
+ if (rEntry.bQueryByString)
+ {
+ BOOL bFound = FALSE;
+ StringCompare eRes;
+ String aParamStr = *rEntry.pStr;
+ for (USHORT i = 0; i < nMatCount; i++)
+ {
+ if (!pMat1->IsValue(i))
+ eRes = ScGlobal::pScInternational->Compare(
+ pMat1->GetString(i), aParamStr,
+ INTN_COMPARE_IGNORECASE );
+ else
+ eRes = COMPARE_GREATER;
+ if (eRes == COMPARE_EQUAL)
+ {
+ bFound = TRUE;
+ nDelta = i;
+ }
+ else if (eRes == COMPARE_LESS)
+ i = nMatCount+1;
+ }
+ if (i == nMatCount+2 && !bFound)
+ {
+ SetNV();
+ return;
+ }
+ else if (!bFound)
+ nDelta = i-1;
+ }
+ else
+ {
+ BOOL bFound = FALSE;
+ double fVal1;
+ for (USHORT i = 0; i < nMatCount; i++)
+ {
+ if (pMat1->IsValue(i))
+ fVal1 = pMat1->GetDouble(i);
+ else
+ fVal1 = MAXDOUBLE;
+ if (fVal1 == rEntry.nVal)
+ {
+ bFound = TRUE;
+ nDelta = i;
+ }
+ else if (fVal1 > rEntry.nVal)
+ i = nMatCount+1;
+ }
+ if (i == nMatCount+2 && !bFound)
+ {
+ SetNV();
+ return;
+ }
+ else if (!bFound)
+ nDelta = i-1;
+ }
+ }
+ else if (bSpMatrix) // spaltenweise
+ {
+ rParam.nRow2 = nRow2;
+ rEntry.nField = nCol1;
+ ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE);
+ if ( aCellIter.GetFirst() )
+ {
+ USHORT nR;
+ do
+ {
+ nR = aCellIter.GetRow();
+ } while ( aCellIter.GetNext() );
+ nDelta = nR - nRow1;
+ }
+ else
+ {
+ SetNV();
+ return;
+ }
+ }
+ else // zeilenweise
+ {
+ rParam.nRow2 = nRow1;
+ rEntry.nField = nCol1;
+ ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE);
+ // Entry.nField im Iterator bei Spaltenwechsel weiterschalten
+ aCellIter.SetAdvanceQueryParamEntryField( TRUE );
+ if ( aCellIter.GetFirst() )
+ {
+ USHORT nC;
+ do
+ {
+ nC = aCellIter.GetCol();
+ } while ( aCellIter.GetNext() );
+ nDelta = nC - nCol1;
+ }
+ else
+ {
+ SetNV();
+ return;
+ }
+ }
+ }
+ else
+ {
+ SetIllegalParameter();
+ return;
+ }
+ if (pMat3)
+ {
+ if (pMat3->IsValue(nDelta))
+ PushDouble(pMat3->GetDouble(nDelta));
+ else
+ PushStringObject(pMat3->GetString(nDelta));
+ }
+ else
+ {
+ ScAddress aAdr;
+ if (bSpVector)
+ {
+ aAdr.SetCol( nCol3 );
+ aAdr.SetRow( nRow3 + nDelta );
+ }
+ else
+ {
+ aAdr.SetCol( nCol3 + nDelta );
+ aAdr.SetRow( nRow3 );
+ }
+ aAdr.SetTab( nTab3 );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ PushDouble(GetCellValue( aAdr, pCell ));
+ else
+ {
+ String aStr;
+ GetCellString(aStr, pCell);
+ PushStringObject(aStr);
+ }
+ }
+ }
+ else if (nParamCount == 2)
+ {
+ USHORT nMatInd;
+ BOOL bSpMatrix;
+ USHORT nMatCount;
+ pMat1 = GetMatrix(nMatInd);
+ if (!pMat1)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ pMat1->GetDimensions(nC1, nR1);
+ if (nR1 >= nC1)
+ {
+ bSpMatrix = FALSE;
+ nMatCount = nR1;
+ }
+ else
+ {
+ bSpMatrix = TRUE;
+ nMatCount = nC1;
+ }
+ BOOL bIsStr;
+ double fVal;
+ String sStr;
+ switch ( GetStackType() )
+ {
+ case svDouble:
+ {
+ fVal = GetDouble();
+ bIsStr = FALSE;
+ }
+ break;
+ case svString:
+ {
+ sStr = GetString();
+ bIsStr = TRUE;
+ }
+ break;
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ {
+ PushInt(0);
+ return ;
+ }
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ {
+ fVal = GetCellValue( aAdr, pCell );
+ bIsStr = FALSE;
+ }
+ else
+ {
+ if ( GetCellType( pCell ) == CELLTYPE_NOTE )
+ {
+ fVal = 0.0;
+ bIsStr = FALSE;
+ }
+ else
+ {
+ GetCellString(sStr, pCell);
+ bIsStr = TRUE;
+ }
+ }
+ }
+ break;
+ default:
+ {
+ SetIllegalParameter();
+ return;
+ }
+ }
+ if (bIsStr)
+ {
+ BOOL bFound = FALSE;
+ StringCompare eRes;
+ for (USHORT i = 0; i < nMatCount; i++)
+ {
+ if (bSpMatrix)
+ {
+ if (pMat1->IsString(i, 0))
+ eRes = ScGlobal::pScInternational->Compare(
+ pMat1->GetString(i,0), sStr,
+ INTN_COMPARE_IGNORECASE );
+ else
+ eRes = COMPARE_GREATER;
+ }
+ else
+ {
+ if (pMat1->IsString(0, i))
+ eRes = ScGlobal::pScInternational->Compare(
+ pMat1->GetString(0,i), sStr,
+ INTN_COMPARE_IGNORECASE );
+ else
+ eRes = COMPARE_GREATER;
+ }
+ if (eRes == COMPARE_EQUAL)
+ {
+ bFound = TRUE;
+ nDelta = i;
+ }
+ else if (eRes == COMPARE_LESS)
+ i = nMatCount+1;
+ }
+ if (i == nMatCount+2 && !bFound)
+ {
+ SetNV();
+ return;
+ }
+ else if (!bFound)
+ nDelta = i-1;
+ }
+ else
+ {
+ BOOL bFound = FALSE;
+ double fVal1;
+ for (USHORT i = 0; i < nMatCount; i++)
+ {
+ if (bSpMatrix)
+ {
+ if (!pMat1->IsString(i, 0))
+ fVal1 = pMat1->GetDouble(i, 0);
+ else
+ fVal1 = MAXDOUBLE;
+ }
+ else
+ {
+ if (!pMat1->IsString(0, i))
+ fVal1 = pMat1->GetDouble(0, i);
+ else
+ fVal1 = MAXDOUBLE;
+ }
+ if (fVal1 == fVal)
+ {
+ bFound = TRUE;
+ nDelta = i;
+ }
+ else if (fVal1 > fVal)
+ i = nMatCount+1;
+ }
+ if (i == nMatCount+2 && !bFound)
+ {
+ SetNV();
+ return;
+ }
+ else if (!bFound)
+ nDelta = i-1;
+ }
+ if (bSpMatrix)
+ {
+ if (pMat1->IsString(nDelta, nR1-1))
+ PushStringObject(pMat1->GetString(nDelta, nR1-1));
+ else
+ PushDouble(pMat1->GetDouble(nDelta, nR1-1));
+ }
+ else
+ {
+ if (pMat1->IsString(nC1-1, nDelta))
+ PushStringObject(pMat1->GetString(nC1-1, nDelta));
+ else
+ PushDouble(pMat1->GetDouble(nC1-1, nDelta));
+ }
+ }
+}
+
+
+void ScInterpreter::ScHLookup()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 3, 4 ) )
+ {
+ BOOL bSorted;
+ if (nParamCount == 4)
+ bSorted = GetBool();
+ else
+ bSorted = TRUE;
+ double fIndex = SolarMath::ApproxFloor( GetDouble() ) - 1.0;
+ ScMatrix* pMat = NULL;
+ USHORT nC, nR;
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ if (GetStackType() == svDoubleRef)
+ {
+ PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+ if (nTab1 != nTab2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ }
+ else if (GetStackType() == svMatrix)
+ {
+ pMat = PopMatrix();
+ if (pMat)
+ pMat->GetDimensions(nC, nR);
+ else
+ {
+ SetIllegalParameter();
+ return;
+ }
+ }
+ else
+ {
+ SetIllegalParameter();
+ return;
+ }
+ if ( fIndex < 0.0 || (pMat ? (fIndex >= nR) : (fIndex+nRow1 > nRow2)) )
+ {
+ SetIllegalArgument();
+ return;
+ }
+ USHORT nZIndex = (USHORT) fIndex;
+ if (!pMat)
+ nZIndex += nRow1; // Wertzeile
+ if (nGlobalError == 0)
+ {
+ String sStr;
+ ScQueryParam rParam;
+ rParam.nCol1 = nCol1;
+ rParam.nRow1 = nRow1;
+ rParam.nCol2 = nCol2;
+ rParam.nRow2 = nRow1; // nur in der ersten Zeile suchen
+ rParam.bHasHeader = FALSE;
+ rParam.bInplace = TRUE;
+ rParam.bCaseSens = FALSE;
+ rParam.bRegExp = TRUE;
+ rParam.bDuplicate = FALSE;
+
+ ScQueryEntry& rEntry = rParam.GetEntry(0);
+ rEntry.bDoQuery = TRUE;
+ if ( bSorted )
+ rEntry.eOp = SC_LESS_EQUAL;
+ switch ( GetStackType() )
+ {
+ case svDouble:
+ {
+ rEntry.bQueryByString = FALSE;
+ rEntry.nVal = GetDouble();
+ }
+ break;
+ case svString:
+ {
+ sStr = GetString();
+ rEntry.bQueryByString = TRUE;
+ *rEntry.pStr = sStr;
+ }
+ break;
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ {
+ PushInt(0);
+ return ;
+ }
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ {
+ rEntry.bQueryByString = FALSE;
+ rEntry.nVal = GetCellValue( aAdr, pCell );
+ }
+ else
+ {
+ if ( GetCellType( pCell ) == CELLTYPE_NOTE )
+ {
+ rEntry.bQueryByString = FALSE;
+ rEntry.nVal = 0.0;
+ }
+ else
+ {
+ GetCellString(sStr, pCell);
+ rEntry.bQueryByString = TRUE;
+ *rEntry.pStr = sStr;
+ }
+ }
+ }
+ break;
+ default:
+ {
+ SetIllegalParameter();
+ return;
+ }
+ }
+ if ( rEntry.bQueryByString )
+ rParam.bRegExp = MayBeRegExp( *rEntry.pStr );
+ if (pMat)
+ {
+ USHORT nMatCount = nC;
+ short nDelta = -1;
+ if (rEntry.bQueryByString)
+ {
+ StringCompare eRes;
+ String aParamStr = *rEntry.pStr;
+ USHORT i;
+ if ( bSorted )
+ {
+ for (i = 0; i < nMatCount; i++)
+ {
+ if (pMat->IsString(i, 0))
+ eRes = ScGlobal::pScInternational->Compare(
+ pMat->GetString(i,0), aParamStr,
+ INTN_COMPARE_IGNORECASE );
+ else
+ eRes = COMPARE_GREATER;
+ if (eRes == COMPARE_GREATER || eRes == COMPARE_EQUAL)
+ nDelta = i;
+ else if (eRes == COMPARE_LESS)
+ i = nMatCount+1;
+ }
+ }
+ else
+ {
+ for (i = 0; i < nMatCount; i++)
+ {
+ if (pMat->IsString(i, 0))
+ eRes = ScGlobal::pScInternational->Compare(
+ pMat->GetString(i,0), aParamStr,
+ INTN_COMPARE_IGNORECASE );
+ else
+ eRes = COMPARE_GREATER;
+ if (eRes == COMPARE_EQUAL)
+ {
+ nDelta = i;
+ i = nMatCount + 1;
+ }
+ }
+ }
+ }
+ else
+ {
+ double fVal1;
+ USHORT i;
+ if ( bSorted )
+ {
+ for (i = 0; i < nMatCount; i++)
+ {
+ if (!pMat->IsString(i, 0))
+ fVal1 = pMat->GetDouble(i,0);
+ else
+ fVal1 = MAXDOUBLE;
+ if (fVal1 <= rEntry.nVal)
+ nDelta = i;
+ else
+ i = nMatCount+1;
+ }
+ }
+ else
+ {
+ for (i = 0; i < nMatCount; i++)
+ {
+ if (!pMat->IsString(i, 0))
+ fVal1 = pMat->GetDouble(i,0);
+ else
+ fVal1 = MAXDOUBLE;
+ if (fVal1 == rEntry.nVal)
+ {
+ nDelta = i;
+ i = nMatCount + 1;
+ }
+ }
+ }
+ }
+ if ( nDelta >= 0 )
+ {
+ if (!pMat->IsString(nDelta, nZIndex))
+ PushDouble(pMat->GetDouble(nDelta, nZIndex));
+ else
+ PushStringObject(pMat->GetString(nDelta, nZIndex));
+ }
+ else
+ SetNV();
+ }
+ else
+ {
+ rEntry.nField = nCol1;
+ ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE);
+ // Entry.nField im Iterator bei Spaltenwechsel weiterschalten
+ aCellIter.SetAdvanceQueryParamEntryField( TRUE );
+ if ( aCellIter.GetFirst() )
+ {
+ USHORT nC = aCellIter.GetCol();
+ if ( bSorted )
+ { // <= Suche, #37661#: nicht abbrechen wenn nC > nCol1
+ // weil leere Zelle
+ while ( aCellIter.GetNext() )
+ nC = aCellIter.GetCol();
+ }
+ ScBaseCell* pCell;
+ ScAddress aAdr( nC, nZIndex, nTab1 );
+ if ( HasCellValueData( pCell = GetCell( aAdr ) ) )
+ PushDouble(GetCellValue( aAdr, pCell ));
+ else
+ {
+ String aStr;
+ GetCellString(aStr, pCell);
+ PushStringObject(aStr);
+ }
+ }
+ else
+ SetNV();
+ }
+ }
+ else
+ SetIllegalParameter();
+ }
+}
+
+
+void ScInterpreter::ScVLookup()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 3, 4 ) )
+ {
+ BOOL bSorted;
+ if (nParamCount == 4)
+ bSorted = GetBool();
+ else
+ bSorted = TRUE;
+ double fIndex = SolarMath::ApproxFloor( GetDouble() ) - 1.0;
+ ScMatrix* pMat = NULL;
+ USHORT nC, nR;
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ if (GetStackType() == svDoubleRef)
+ {
+ PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+ if (nTab1 != nTab2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ }
+ else if (GetStackType() == svMatrix)
+ {
+ pMat = PopMatrix();
+ if (pMat)
+ pMat->GetDimensions(nC, nR);
+ else
+ {
+ SetIllegalParameter();
+ return;
+ }
+ }
+ else
+ {
+ SetIllegalParameter();
+ return;
+ }
+ if ( fIndex < 0.0 || (pMat ? (fIndex >= nC) : (fIndex+nCol1 > nCol2)) )
+ {
+ SetIllegalArgument();
+ return;
+ }
+ USHORT nSpIndex = (USHORT) fIndex;
+ if (!pMat)
+ nSpIndex += nCol1; // Wertspalte
+ if (nGlobalError == 0)
+ {
+ String sStr;
+ ScQueryParam rParam;
+ rParam.nCol1 = nCol1;
+ rParam.nRow1 = nRow1;
+ rParam.nCol2 = nCol1; // nur in der ersten Spalte suchen
+ rParam.nRow2 = nRow2;
+ rParam.bHasHeader = FALSE;
+ rParam.bInplace = TRUE;
+ rParam.bCaseSens = FALSE;
+ rParam.bRegExp = TRUE;
+ rParam.bDuplicate = FALSE;
+
+ ScQueryEntry& rEntry = rParam.GetEntry(0);
+ rEntry.bDoQuery = TRUE;
+ if ( bSorted )
+ rEntry.eOp = SC_LESS_EQUAL;
+ switch ( GetStackType() )
+ {
+ case svDouble:
+ {
+ rEntry.bQueryByString = FALSE;
+ rEntry.nVal = GetDouble();
+ }
+ break;
+ case svString:
+ {
+ sStr = GetString();
+ rEntry.bQueryByString = TRUE;
+ *rEntry.pStr = sStr;
+ }
+ break;
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ {
+ PushInt(0);
+ return ;
+ }
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ {
+ rEntry.bQueryByString = FALSE;
+ rEntry.nVal = GetCellValue( aAdr, pCell );
+ }
+ else
+ {
+ if ( GetCellType( pCell ) == CELLTYPE_NOTE )
+ {
+ rEntry.bQueryByString = FALSE;
+ rEntry.nVal = 0.0;
+ }
+ else
+ {
+ GetCellString(sStr, pCell);
+ rEntry.bQueryByString = TRUE;
+ *rEntry.pStr = sStr;
+ }
+ }
+ }
+ break;
+ default:
+ {
+ SetIllegalParameter();
+ return;
+ }
+ }
+ if ( rEntry.bQueryByString )
+ rParam.bRegExp = MayBeRegExp( *rEntry.pStr );
+ if (pMat)
+ {
+ USHORT nMatCount = nR;
+ short nDelta = -1;
+ if (rEntry.bQueryByString)
+ {
+ StringCompare eRes;
+ String aParamStr = *rEntry.pStr;
+ USHORT i;
+ if ( bSorted )
+ {
+ for (i = 0; i < nMatCount; i++)
+ {
+ if (pMat->IsString(0, i))
+ eRes = ScGlobal::pScInternational->Compare(
+ pMat->GetString(0,i), aParamStr,
+ INTN_COMPARE_IGNORECASE );
+ else
+ eRes = COMPARE_GREATER;
+ if (eRes == COMPARE_GREATER || eRes == COMPARE_EQUAL)
+ nDelta = i;
+ else if (eRes == COMPARE_LESS)
+ i = nMatCount+1;
+ }
+ }
+ else
+ {
+ for (i = 0; i < nMatCount; i++)
+ {
+ if (pMat->IsString(0, i))
+ eRes = ScGlobal::pScInternational->Compare(
+ pMat->GetString(0,i), aParamStr,
+ INTN_COMPARE_IGNORECASE );
+ else
+ eRes = COMPARE_GREATER;
+ if (eRes == COMPARE_EQUAL)
+ {
+ nDelta = i;
+ i = nMatCount + 1;
+ }
+ }
+ }
+ }
+ else
+ {
+ double fVal1;
+ USHORT i;
+ if ( bSorted )
+ {
+ for (i = 0; i < nMatCount; i++)
+ {
+ if (!pMat->IsString(0, i))
+ fVal1 = pMat->GetDouble(0, i);
+ else
+ fVal1 = MAXDOUBLE;
+ if (fVal1 <= rEntry.nVal)
+ nDelta = i;
+ else
+ i = nMatCount+1;
+ }
+ }
+ else
+ {
+ for (i = 0; i < nMatCount; i++)
+ {
+ if (!pMat->IsString(0, i))
+ fVal1 = pMat->GetDouble(0, i);
+ else
+ fVal1 = MAXDOUBLE;
+ if (fVal1 == rEntry.nVal)
+ {
+ nDelta = i;
+ i = nMatCount + 1;
+ }
+ }
+ }
+ }
+ if ( nDelta >= 0 )
+ {
+ if (!pMat->IsString(nSpIndex, nDelta))
+ PushDouble(pMat->GetDouble(nSpIndex, nDelta));
+ else
+ PushStringObject(pMat->GetString(nSpIndex, nDelta));
+ }
+ else
+ SetNV();
+ }
+ else
+ {
+ rEntry.nField = nCol1;
+ ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE);
+ if (aCellIter.GetFirst())
+ {
+ USHORT nR = aCellIter.GetRow();
+ if ( bSorted )
+ { // <= Suche, #37661#: nicht abbrechen wenn nR > nRow1
+ // weil leere Zelle
+ while (aCellIter.GetNext())
+ nR = aCellIter.GetRow();
+ }
+ ScBaseCell* pCell;
+ ScAddress aAdr( nSpIndex, nR, nTab1 );
+ if ( HasCellValueData( pCell = GetCell( aAdr ) ) )
+ PushDouble(GetCellValue( aAdr, pCell ));
+ else
+ {
+ String aStr;
+ GetCellString(aStr, pCell);
+ PushStringObject(aStr);
+ }
+ }
+ else
+ SetNV();
+ }
+ }
+ else
+ SetIllegalParameter();
+ }
+}
+
+#if defined(WIN) && defined(MSC)
+#pragma optimize("",off)
+#endif
+
+void ScInterpreter::ScSubTotal()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCountMin( nParamCount, 2 ) )
+ {
+ // Wir muessen den 1. Parameter tief aus dem Stack herausfischen!
+ const ScToken* p = pStack[ sp - nParamCount ];
+ PushTempToken( *p );
+ int nFunc = (int) SolarMath::ApproxFloor( GetDouble() );
+ if( nFunc < 1 || nFunc > 11 )
+ SetIllegalParameter();
+ else
+ {
+ cPar = nParamCount - 1;
+ glSubTotal = TRUE;
+ switch( nFunc )
+ {
+ case SUBTOTAL_FUNC_AVE : ScAverage(); break;
+ case SUBTOTAL_FUNC_CNT : ScCount(); break;
+ case SUBTOTAL_FUNC_CNT2 : ScCount2(); break;
+ case SUBTOTAL_FUNC_MAX : ScMax(); break;
+ case SUBTOTAL_FUNC_MIN : ScMin(); break;
+ case SUBTOTAL_FUNC_PROD : ScProduct(); break;
+ case SUBTOTAL_FUNC_STD : ScStDev(); break;
+ case SUBTOTAL_FUNC_STDP : ScStDevP(); break;
+ case SUBTOTAL_FUNC_SUM : ScSum(); break;
+ case SUBTOTAL_FUNC_VAR : ScVar(); break;
+ case SUBTOTAL_FUNC_VARP : ScVarP(); break;
+ default : SetIllegalParameter(); break;
+ }
+ glSubTotal = FALSE;
+ }
+ // den abgefischten 1. Parameter entfernen
+ double nVal = GetDouble();
+ Pop();
+ PushDouble( nVal );
+ }
+}
+#if defined(WIN) && defined(MSC)
+#pragma optimize("",on)
+#endif
+
+
+BOOL ScInterpreter::GetDBParams(USHORT& rTab, ScQueryParam& rParam)
+{
+ BOOL bRet = FALSE;
+ if ( GetByte() == 3 )
+ {
+
+ USHORT nQCol1, nQRow1, nQTab1, nQCol2, nQRow2, nQTab2;
+ PopDoubleRef(nQCol1, nQRow1, nQTab1, nQCol2, nQRow2, nQTab2);
+
+ BOOL bByVal = TRUE;
+ double nVal;
+ String aStr;
+ switch (GetStackType())
+ {
+ case svDouble :
+ nVal = GetDouble();
+ break;
+ case svString :
+ bByVal = FALSE;
+ aStr = GetString();
+ break;
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ PopSingleRef( aAdr );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ nVal = GetCellValue( aAdr, pCell );
+ else
+ {
+ bByVal = FALSE;
+ GetCellString(aStr, pCell);
+ }
+ }
+ break;
+ }
+
+ USHORT nDBCol1, nDBRow1, nDBTab1, nDBCol2, nDBRow2, nDBTab2;
+ PopDoubleRef(nDBCol1, nDBRow1, nDBTab1, nDBCol2, nDBRow2, nDBTab2);
+
+ if (nGlobalError == 0)
+ {
+ USHORT nField = nDBCol1;
+ BOOL bFound = TRUE;
+ if (bByVal)
+ nField = Min(nDBCol2, (USHORT)(nDBCol1 + (USHORT)SolarMath::ApproxFloor(nVal) - 1));
+ else
+ {
+ bFound = FALSE;
+ String aCellStr;
+ nField = nDBCol1;
+ while (!bFound && (nField <= nDBCol2))
+ {
+ pDok->GetString(nField, nDBRow1, nDBTab1, aCellStr);
+ bFound = ScGlobal::pScInternational->CompareEqual(
+ aCellStr, aStr, INTN_COMPARE_IGNORECASE );
+ if (!bFound)
+ nField++;
+ }
+ }
+ if (bFound)
+ {
+ rParam.nCol1 = nDBCol1;
+ rParam.nRow1 = nDBRow1;
+ rParam.nCol2 = nDBCol2;
+ rParam.nRow2 = nDBRow2;
+ rParam.nTab = nDBTab1;
+ rParam.bHasHeader = TRUE;
+ rParam.bByRow = TRUE;
+ rParam.bInplace = TRUE;
+ rParam.bCaseSens = FALSE;
+ rParam.bRegExp = FALSE;
+ rParam.bDuplicate = TRUE;
+ if (pDok->CreateQueryParam(nQCol1, nQRow1, nQCol2, nQRow2, nQTab1, rParam))
+ {
+ rParam.nCol1 = nField;
+ rParam.nCol2 = nField;
+ rTab = nDBTab1;
+ bRet = TRUE;
+ USHORT nCount = rParam.GetEntryCount();
+ for ( USHORT i=0; i < nCount; i++ )
+ {
+ ScQueryEntry& rEntry = rParam.GetEntry(i);
+ if ( rEntry.bDoQuery )
+ {
+ ULONG nIndex = 0;
+ rEntry.bQueryByString = !pFormatter->IsNumberFormat(
+ *rEntry.pStr, nIndex, rEntry.nVal );
+ if ( rEntry.bQueryByString && !rParam.bRegExp )
+ rParam.bRegExp = MayBeRegExp( *rEntry.pStr );
+ }
+ else
+ break; // for
+ }
+ }
+ }
+ }
+ }
+ return bRet;
+}
+
+
+void ScInterpreter::DBIterator( ScIterFunc eFunc )
+{
+ USHORT nTab1;
+ double nErg = 0.0;
+ double fMem = 0.0;
+ BOOL bNull = TRUE;
+ long nCount = 0;
+ ScQueryParam aQueryParam;
+ if (GetDBParams(nTab1, aQueryParam))
+ {
+ double nVal;
+ USHORT nErr;
+ ScQueryValueIterator aValIter(pDok, nTab1, aQueryParam);
+ if ( aValIter.GetFirst(nVal, nErr) && !nErr )
+ {
+ switch( eFunc )
+ {
+ case ifPRODUCT: nErg = 1; break;
+ case ifMAX: nErg = MINDOUBLE; break;
+ case ifMIN: nErg = MAXDOUBLE; break;
+ }
+ do
+ {
+ nCount++;
+ switch( eFunc )
+ {
+ case ifAVERAGE:
+ case ifSUM:
+ if ( bNull && nVal != 0.0 )
+ {
+ bNull = FALSE;
+ fMem = nVal;
+ }
+ else
+ nErg += nVal;
+ break;
+ case ifSUMSQ: nErg += nVal * nVal; break;
+ case ifPRODUCT: nErg *= nVal; break;
+ case ifMAX: if( nVal > nErg ) nErg = nVal; break;
+ case ifMIN: if( nVal < nErg ) nErg = nVal; break;
+ }
+ }
+ while ( aValIter.GetNext(nVal, nErr) && !nErr );
+ }
+ SetError(nErr);
+ }
+ else
+ SetIllegalParameter();
+ switch( eFunc )
+ {
+ case ifCOUNT: nErg = nCount; break;
+ case ifSUM: nErg = SolarMath::ApproxAdd( nErg, fMem ); break;
+ case ifAVERAGE: nErg = (nCount ? SolarMath::ApproxAdd( nErg, fMem ) / nCount : 0); break;
+ }
+ PushDouble( nErg );
+}
+
+
+void ScInterpreter::ScDBSum()
+{
+ DBIterator( ifSUM );
+}
+
+
+void ScInterpreter::ScDBCount()
+{
+ DBIterator( ifCOUNT );
+}
+
+
+void ScInterpreter::ScDBCount2()
+{
+ USHORT nTab;
+ ScQueryParam aQueryParam;
+ if (GetDBParams(nTab, aQueryParam))
+ {
+ ULONG nCount = 0;
+ ScQueryCellIterator aCellIter(pDok, nTab, aQueryParam);
+ if ( aCellIter.GetFirst() )
+ {
+ do
+ {
+ nCount++;
+ } while ( aCellIter.GetNext() );
+ }
+ PushDouble(nCount);
+ }
+ else
+ SetIllegalParameter();
+}
+
+
+void ScInterpreter::ScDBAverage()
+{
+ DBIterator( ifAVERAGE );
+}
+
+
+void ScInterpreter::ScDBMax()
+{
+ DBIterator( ifMAX );
+}
+
+
+void ScInterpreter::ScDBMin()
+{
+ DBIterator( ifMIN );
+}
+
+
+void ScInterpreter::ScDBProduct()
+{
+ DBIterator( ifPRODUCT );
+}
+
+
+ULONG ScInterpreter::StdDev( double& rSum, double& rSum2 )
+{
+ USHORT nTab;
+ ULONG nCount = 0;
+ ScQueryParam aQueryParam;
+ if (GetDBParams(nTab, aQueryParam))
+ {
+ double fVal, fSum = 0.0, fSumSqr = 0.0;
+ USHORT nErr;
+ ScQueryValueIterator aValIter(pDok, nTab, aQueryParam);
+ if (aValIter.GetFirst(fVal, nErr) && !nErr)
+ {
+ do
+ {
+ nCount++;
+ fSum += fVal;
+ fSumSqr += fVal*fVal;
+ }
+ while ((nErr == 0) && aValIter.GetNext(fVal, nErr));
+ }
+ SetError(nErr);
+ rSum = fSum;
+ rSum2 = fSumSqr;
+ }
+ else
+ SetIllegalParameter();
+ return nCount;
+}
+
+
+void ScInterpreter::ScDBStdDev()
+{
+ ULONG nCount;
+ double fSum, fSumSqr;
+ nCount = StdDev( fSum, fSumSqr );
+ PushDouble( sqrt((fSumSqr - fSum*fSum/nCount)/(nCount-1)));
+}
+
+
+void ScInterpreter::ScDBStdDevP()
+{
+ ULONG nCount;
+ double fSum, fSumSqr;
+ nCount = StdDev( fSum, fSumSqr );
+ PushDouble( sqrt((fSumSqr - fSum*fSum/nCount)/nCount));
+}
+
+
+void ScInterpreter::ScDBVar()
+{
+ ULONG nCount;
+ double fSum, fSumSqr;
+ nCount = StdDev( fSum, fSumSqr );
+ PushDouble((fSumSqr - fSum*fSum/nCount)/(nCount-1));
+}
+
+
+void ScInterpreter::ScDBVarP()
+{
+ ULONG nCount;
+ double fSum, fSumSqr;
+ nCount = StdDev( fSum, fSumSqr );
+ PushDouble((fSumSqr - fSum*fSum/nCount)/nCount);
+}
+
+
+void ScInterpreter::ScIndirect()
+{
+ BYTE nParamCount = GetByte();
+/*
+ if (nParamCount == 2)
+ {
+ double fBool = GetDouble();
+ if (fBool == 0.0) // nur TRUE erlaubt!!
+ {
+ SetIllegalParameter();
+ return;
+ }
+ else
+ nParamCount = 1;
+ }
+*/
+ if ( MustHaveParamCount( nParamCount, 1 ) )
+ {
+ USHORT nTab = aPos.Tab();
+ String sRefStr( GetString() );
+ ScRefTripel aRefTr, aRefTr2;
+ if ( ConvertDoubleRef( pDok, sRefStr, nTab, aRefTr, aRefTr2 ) )
+ PushDoubleRef( aRefTr.GetCol(), aRefTr.GetRow(), aRefTr.GetTab(),
+ aRefTr2.GetCol(), aRefTr2.GetRow(), aRefTr2.GetTab() );
+ else if ( ConvertSingleRef( pDok, sRefStr, nTab, aRefTr ) )
+ PushSingleRef( aRefTr.GetCol(), aRefTr.GetRow(), aRefTr.GetTab() );
+ else
+ SetIllegalArgument();
+ }
+}
+
+
+void ScInterpreter::ScAdress()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 2, 4 ) )
+ {
+ const sal_Unicode* sTabStr;
+ USHORT nAbs = 1;
+ if (nParamCount == 4)
+ sTabStr = GetString();
+ else
+ sTabStr = NULL;
+ if (nParamCount >= 3)
+ nAbs = (USHORT) SolarMath::ApproxFloor(GetDouble());
+ USHORT nCol = (USHORT) SolarMath::ApproxFloor(GetDouble());
+ USHORT nRow = (USHORT) SolarMath::ApproxFloor(GetDouble());
+ if (nCol < 1 || nCol > MAXCOL + 1 || nRow < 1 || nRow > MAXROW + 1)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ else
+ {
+ nRow--;
+ nCol--;
+ }
+ String aRefStr;
+ ScTripel aScTr;
+ aScTr.SetCol(nCol);
+ aScTr.SetRow(nRow);
+ if (nAbs == 4)
+ aRefStr = aScTr.GetColRowString();
+ else
+ {
+ aRefStr = aScTr.GetColRowString(TRUE);
+ if (nAbs == 2)
+ aRefStr.EraseLeadingChars('$');
+ else if (nAbs == 3)
+ aRefStr.Erase(aRefStr.Search('$',1),1);
+ }
+ if (sTabStr != NULL)
+ {
+ aRefStr.Insert('.',0);
+ aRefStr.Insert(sTabStr,0);
+ }
+ PushStringObject(aRefStr);
+ }
+}
+
+
+void ScInterpreter::ScOffset()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 3, 5 ) )
+ {
+ short nColNew, nRowNew, nColPlus, nRowPlus;
+ if (nParamCount == 5)
+ nColNew = (short) SolarMath::ApproxFloor(GetDouble());
+ if (nParamCount >= 4)
+ nRowNew = (short) SolarMath::ApproxFloor(GetDouble());
+ nColPlus = (short) SolarMath::ApproxFloor(GetDouble());
+ nRowPlus = (short) SolarMath::ApproxFloor(GetDouble());
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ if ( (nParamCount == 5 && nColNew == 0)
+ || (nParamCount >= 4 && nRowNew == 0) )
+ {
+ SetIllegalParameter();
+ return;
+ }
+ if (GetStackType() == svSingleRef)
+ {
+ PopSingleRef(nCol1, nRow1, nTab1);
+ if (nParamCount == 3)
+ {
+ nCol1 = (USHORT)((short) nCol1 + nColPlus);
+ nRow1 = (USHORT)((short) nRow1 + nRowPlus);
+ if (nCol1 > MAXCOL || nRow1 > MAXROW)
+ SetIllegalParameter();
+ else
+ PushSingleRef(nCol1, nRow1, nTab1);
+ }
+ else
+ {
+ if (nParamCount == 4)
+ nColNew = 1;
+ nCol1 = (USHORT)((short)nCol1+nColPlus); // ! nCol1 wird veraendert!
+ nRow1 = (USHORT)((short)nRow1+nRowPlus);
+ nCol2 = (USHORT)((short)nCol1+nColNew-1);
+ nRow2 = (USHORT)((short)nRow1+nRowNew-1);
+ if (nCol1 > MAXCOL || nRow1 > MAXROW ||
+ nCol2 > MAXCOL || nRow2 > MAXROW)
+ SetIllegalParameter();
+ else
+ PushDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab1);
+ }
+ }
+ else if (GetStackType() == svDoubleRef)
+ {
+ PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+ if (nParamCount < 5)
+ nColNew = nCol2 - nCol1 + 1;
+ if (nParamCount < 4)
+ nRowNew = nRow2 - nRow1 + 1;
+ nCol1 = (USHORT)((short)nCol1+nColPlus);
+ nRow1 = (USHORT)((short)nRow1+nRowPlus);
+ nCol2 = (USHORT)((short)nCol1+nColNew-1);
+ nRow2 = (USHORT)((short)nRow1+nRowNew-1);
+ if (nCol1 > MAXCOL || nRow1 > MAXROW ||
+ nCol2 > MAXCOL || nRow2 > MAXROW || nTab1 != nTab2)
+ SetIllegalParameter();
+ else
+ PushDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab1);
+ }
+ else
+ SetIllegalParameter();
+ }
+}
+
+
+void ScInterpreter::ScIndex()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 1, 4 ) )
+ {
+ short nBereich, nMaxAnz, nCount;
+ USHORT nCol, nRow;
+ if (nParamCount == 4)
+ nBereich = (short) SolarMath::ApproxFloor(GetDouble());
+ else
+ nBereich = 1;
+ if (nParamCount >= 3)
+ nCol = (USHORT) SolarMath::ApproxFloor(GetDouble());
+ else
+ nCol = 0;
+ if (nParamCount >= 2)
+ nRow = (USHORT) SolarMath::ApproxFloor(GetDouble());
+ else
+ nRow = 0;
+ if (GetStackType() == svByte) // vorher MultiSelektion?
+ nMaxAnz = (short) PopByte();
+ else // sonst Einzelselektion
+ nMaxAnz = 1;
+ if (nBereich > nMaxAnz || nBereich < 1)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ if (GetStackType() == svMatrix)
+ {
+ if (nBereich != 1)
+ SetError(errIllegalParameter);
+ USHORT nMatInd1;
+ USHORT nOldSp = sp;
+ ScMatrix* pMat = GetMatrix(nMatInd1);
+ if (pMat)
+ {
+ USHORT nC, nR, nMatInd;
+ pMat->GetDimensions(nC, nR);
+ if (nC == 0 || nR == 0 || nCol > nC || nRow > nR)
+ SetIllegalArgument();
+ else if (nCol == 0 && nRow == 0)
+ sp = nOldSp;
+ else if (nRow == 0)
+ {
+ ScMatrix* pResMat = GetNewMat(nC, 1, nMatInd);
+ if (pResMat)
+ {
+ USHORT nColMinus1 = nCol - 1;
+ for (USHORT i = 0; i < nC; i++)
+ if (!pMat->IsString(i, nColMinus1))
+ pResMat->PutDouble(pMat->GetDouble(i,
+ nColMinus1), i, 0);
+ else
+ pResMat->PutString(pMat->GetString(i,
+ nColMinus1), i, 0);
+ PushMatrix(pResMat);
+ nRetMat = nMatInd;
+ }
+ else
+ SetNoValue();
+ }
+ else if (nCol == 0)
+ {
+ ScMatrix* pResMat = GetNewMat(1, nR, nMatInd);
+ if (pResMat)
+ {
+ USHORT nRowMinus1 = nRow - 1;
+ for (USHORT i = 0; i < nR; i++)
+ if (!pMat->IsString(nRowMinus1, i))
+ pResMat->PutDouble(pMat->GetDouble(nRowMinus1,
+ i), 0, i);
+ else
+ pResMat->PutString(pMat->GetString(nRowMinus1,
+ i), 0, i);
+ PushMatrix(pResMat);
+ nRetMat = nMatInd;
+ }
+ else
+ SetNoValue();
+ }
+ else
+ {
+ if (!pMat->IsString(nCol-1, nRow-1))
+ PushDouble(pMat->GetDouble(nCol-1, nRow-1));
+ else
+ PushStringObject(pMat->GetString(nCol-1, nRow-1));
+ }
+ ResetNewMat(nMatInd1);
+ }
+ }
+ else if (GetStackType() == svSingleRef || GetStackType() == svDoubleRef)
+ {
+ ScAddress aDummyAdr;
+ ScRange aDummyRange;
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 = MAXTAB+1;
+ nCount = nMaxAnz; // Refs liegen umgekehrt auf dem Stack!
+ while (nCount > nBereich && !nGlobalError) // erste Refs weg
+ {
+ nCount--;
+ if ( GetStackType() == svSingleRef )
+ PopSingleRef( aDummyAdr );
+ else if ( GetStackType() == svDoubleRef )
+ PopDoubleRef( aDummyRange );
+ }
+ while (nCount > nBereich-1 && !nGlobalError) // richtigen Teilbezug
+ {
+ nCount--;
+ if (GetStackType() == svSingleRef)
+ PopSingleRef(nCol1, nRow1, nTab1);
+ else if (GetStackType() == svDoubleRef)
+ PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+ }
+ while (nCount > 0 && !nGlobalError) // restliche Refs weg
+ {
+ nCount--;
+ if ( GetStackType() == svSingleRef )
+ PopSingleRef( aDummyAdr );
+ else if ( GetStackType() == svDoubleRef )
+ PopDoubleRef( aDummyRange );
+ }
+ if (nTab2 == MAXTAB+1) // SingleRef
+ {
+ if (nCol > 1 || nRow > 1)
+ SetIllegalParameter();
+ else
+ PushSingleRef(nCol1, nRow1, nTab1);
+ }
+ else // DoubleRef
+ {
+ if ( nTab1 != nTab2 ||
+ (nCol > 0 && nCol1+nCol-1 > nCol2) ||
+ (nRow > 0 && nRow1+nRow-1 > nRow2) )
+ SetIllegalParameter();
+ else if (nCol == 0 && nRow == 0)
+ {
+ if ( nCol1 == nCol2 && nRow1 == nRow2 )
+ PushSingleRef( nCol1, nRow1, nTab1 );
+ else
+ PushDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab1 );
+ }
+ else if (nRow == 0)
+ {
+ if ( nRow1 == nRow2 )
+ PushSingleRef( nCol1+nCol-1, nRow1, nTab1 );
+ else
+ PushDoubleRef( nCol1+nCol-1, nRow1, nTab1,
+ nCol1+nCol-1, nRow2, nTab1 );
+ }
+ else if (nCol == 0)
+ {
+ if ( nCol1 == nCol2 )
+ PushSingleRef( nCol1, nRow1+nRow-1, nTab1 );
+ else
+ PushDoubleRef(nCol1, nRow1+nRow-1, nTab1,
+ nCol2, nRow1+nRow-1, nTab1);
+ }
+ else
+ PushSingleRef(nCol1+nCol-1, nRow1+nRow-1, nTab1);
+ }
+ }
+ else
+ SetIllegalParameter();
+ }
+}
+
+
+void ScInterpreter::ScMultiArea()
+{
+ // Hier ist nichts zu tun, der paramCount von ScMultiSelektion
+ // bleibt auf dem Stack !!
+ // Den muessen die nachfolgenden Funktionen (Index ...) wegraeumen !!
+}
+
+
+void ScInterpreter::ScAreas()
+{
+ BYTE nParamCount = GetByte();
+ double fMaxAnz = 1.0;
+ ScAddress aDummyAdr;
+ ScRange aDummyRange;
+ for (USHORT i = 0; i < nParamCount && nGlobalError == 0; i++)
+ {
+ if (GetStackType() == svByte) // vorher MultiSelektion?
+ {
+ double fCount = 0.0;
+ fMaxAnz = (double) GetByte();
+ while (fCount < fMaxAnz && !nGlobalError) // mehrere Refs
+ {
+ fCount++;
+ if (GetStackType() == svSingleRef)
+ PopSingleRef( aDummyAdr );
+ else if (GetStackType() == svDoubleRef)
+ PopDoubleRef( aDummyRange );
+ else
+ SetIllegalParameter();
+ }
+ }
+ else if (GetStackType() == svSingleRef)
+ PopSingleRef( aDummyAdr );
+ else if (GetStackType() == svDoubleRef)
+ PopDoubleRef( aDummyRange );
+ else
+ SetIllegalParameter();
+ }
+ if (nGlobalError == 0)
+ PushDouble((double)nParamCount + fMaxAnz - 1.0);
+}
+
+
+void ScInterpreter::ScCurrency()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 1, 2 ) )
+ {
+ String cStr;
+ double fDec;
+ if (nParamCount == 2)
+ {
+ fDec = SolarMath::ApproxFloor(GetDouble());
+ if (fDec < -15.0 || fDec > 15.0)
+ {
+ SetIllegalArgument();
+ return;
+ }
+ }
+ else
+ fDec = 2.0;
+ double fVal = GetDouble();
+ double fFac;
+ if ( fDec != 0.0 )
+ fFac = pow( (double)10, fDec );
+ else
+ fFac = 1.0;
+ if (fVal < 0.0)
+ fVal = ceil(fVal*fFac-0.5)/fFac;
+ else
+ fVal = floor(fVal*fFac+0.5)/fFac;
+ Color* pColor = NULL;
+ if ( fDec < 0.0 )
+ fDec = 0.0;
+ ULONG nIndex = pFormatter->GetStandardFormat(
+ NUMBERFORMAT_CURRENCY,
+ ScGlobal::eLnge);
+ if ( (USHORT) fDec != pFormatter->GetFormatPrecision( nIndex ) )
+ {
+ String sFormatString;
+ pFormatter->GenerateFormat(sFormatString,
+ nIndex,
+ ScGlobal::eLnge,
+ TRUE, // mit Tausenderpunkt
+ FALSE, // nicht rot
+ (USHORT) fDec,// Nachkommastellen
+ 1); // 1 Vorkommanull
+ if (!pFormatter->GetPreviewString(sFormatString,
+ fVal,
+ cStr,
+ &pColor,
+ ScGlobal::eLnge))
+ SetError(errIllegalParameter);
+ }
+ else
+ {
+ pFormatter->GetOutputString(fVal, nIndex, cStr, &pColor);
+ }
+ PushStringObject(cStr);
+ }
+}
+
+
+void ScInterpreter::ScReplace()
+{
+ if ( MustHaveParamCount( GetByte(), 4 ) )
+ {
+ String aNewStr( GetString() );
+ short nCount = (short) GetDouble();
+ short nPos = (short) GetDouble();
+ String aOldStr( GetString() );
+ if( nPos < 1 || nCount < 1 )
+ SetIllegalArgument();
+ else
+ {
+ aOldStr.Erase( nPos-1, nCount );
+ aOldStr.Insert( aNewStr, nPos-1 );
+ if( aOldStr.Len() >= MAXSTRLEN )
+ {
+ SetError(errStringOverflow);
+ aOldStr.Erase();
+ }
+ PushStringObject( aOldStr );
+ }
+ }
+}
+
+
+void ScInterpreter::ScFixed()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 1, 3 ) )
+ {
+ String cStr;
+ double fDec;
+ BOOL bThousand;
+ if (nParamCount == 3)
+ bThousand = !GetBool(); // Param TRUE: keine Tausenderpunkte
+ else
+ bThousand = TRUE;
+ if (nParamCount >= 2)
+ {
+ fDec = SolarMath::ApproxFloor(GetDouble());
+ if (fDec < -15.0 || fDec > 15.0)
+ {
+ SetIllegalArgument();
+ return;
+ }
+ }
+ else
+ fDec = 2.0;
+ double fVal = GetDouble();
+ double fFac;
+ if ( fDec != 0.0 )
+ fFac = pow( (double)10, fDec );
+ else
+ fFac = 1.0;
+ if (fVal < 0.0)
+ fVal = ceil(fVal*fFac-0.5)/fFac;
+ else
+ fVal = floor(fVal*fFac+0.5)/fFac;
+ Color* pColor = NULL;
+ String sFormatString;
+ if (fDec < 0.0)
+ fDec = 0.0;
+ ULONG nIndex = pFormatter->GetStandardFormat(
+ NUMBERFORMAT_NUMBER,
+ ScGlobal::eLnge);
+ pFormatter->GenerateFormat(sFormatString,
+ nIndex,
+ ScGlobal::eLnge,
+ bThousand, // mit Tausenderpunkt
+ FALSE, // nicht rot
+ (USHORT) fDec,// Nachkommastellen
+ 1); // 1 Vorkommanull
+ if (!pFormatter->GetPreviewString(sFormatString,
+ fVal,
+ cStr,
+ &pColor,
+ ScGlobal::eLnge))
+ SetIllegalParameter();
+ else
+ PushStringObject(cStr);
+ }
+}
+
+
+void ScInterpreter::ScFind()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 2, 3 ) )
+ {
+ double fAnz;
+ if (nParamCount == 3)
+ fAnz = GetDouble();
+ else
+ fAnz = 1.0;
+ String sStr = GetString();
+ if( fAnz < 1.0 || fAnz > (double) sStr.Len() )
+ SetNoValue();
+ else
+ {
+ xub_StrLen nPos = sStr.Search( GetString(), (xub_StrLen) fAnz - 1 );
+ if (nPos == STRING_NOTFOUND)
+ SetNoValue();
+ else
+ PushDouble((double)(nPos + 1));
+ }
+ }
+}
+
+
+void ScInterpreter::ScExact()
+{
+ nFuncFmtType = NUMBERFORMAT_LOGICAL;
+ if ( MustHaveParamCount( GetByte(), 2 ) )
+ {
+ String s1( GetString() );
+ String s2( GetString() );
+ PushInt( s1 == s2 );
+ }
+}
+
+
+void ScInterpreter::ScLeft()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 1, 2 ) )
+ {
+ xub_StrLen n;
+ if (nParamCount == 2)
+ {
+ double nVal = SolarMath::ApproxFloor(GetDouble());
+ if (nVal < 0.0 || nVal > MAXSTRLEN)
+ {
+ SetIllegalParameter();
+ return ;
+ }
+ else
+ n = (xub_StrLen) nVal;
+ }
+ else
+ n = 1;
+ String aStr( GetString() );
+ aStr.Erase( n );
+ PushStringObject( aStr );
+ }
+}
+
+
+void ScInterpreter::ScRight()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 1, 2 ) )
+ {
+ xub_StrLen n;
+ if (nParamCount == 2)
+ {
+ double nVal = SolarMath::ApproxFloor(GetDouble());
+ if (nVal < 0.0 || nVal > MAXSTRLEN)
+ {
+ SetIllegalParameter();
+ return ;
+ }
+ else
+ n = (xub_StrLen) nVal;
+ }
+ else
+ n = 1;
+ String aStr( GetString() );
+ if( n < aStr.Len() )
+ aStr.Erase( 0, aStr.Len() - n );
+ PushStringObject( aStr );
+ }
+}
+
+
+void ScInterpreter::ScSearch()
+{
+ double fAnz;
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 2, 3 ) )
+ {
+ if (nParamCount == 3)
+ {
+ fAnz = SolarMath::ApproxFloor(GetDouble());
+ if (fAnz > double(STRING_MAXLEN))
+ {
+ SetIllegalParameter();
+ return;
+ }
+ }
+ else
+ fAnz = 1.0;
+ String sStr = GetString();
+ String SearchStr = GetString();
+ xub_StrLen nPos = (xub_StrLen) fAnz - 1;
+ xub_StrLen nEndPos = sStr.Len();
+ if( nPos >= nEndPos )
+ SetNoValue();
+ else
+ {
+ SearchParam sPar(SearchStr, SearchParam::SRCH_REGEXP, FALSE, FALSE, FALSE);
+ SearchText sT( sPar, *ScGlobal::pScInternational );
+ int nBool = sT.SearchFrwrd(sStr, &nPos, &nEndPos);
+ if (!nBool)
+ SetNoValue();
+ else
+ PushDouble((double)(nPos) + 1);
+ }
+ }
+}
+
+
+void ScInterpreter::ScMid()
+{
+ if ( MustHaveParamCount( GetByte(), 3 ) )
+ {
+ double fAnz = SolarMath::ApproxFloor(GetDouble());
+ double fAnfang = SolarMath::ApproxFloor(GetDouble());
+ String sStr = GetString();
+ if (fAnfang < 1.0 || fAnz < 0.0 || fAnfang > double(STRING_MAXLEN) || fAnz > double(STRING_MAXLEN))
+ SetIllegalParameter();
+ else
+ PushStringObject(sStr.Copy( (xub_StrLen) fAnfang - 1, (xub_StrLen) fAnz ));
+ }
+}
+
+
+void ScInterpreter::ScText()
+{
+ if ( MustHaveParamCount( GetByte(), 2 ) )
+ {
+ String sFormatString = GetString();
+ double fVal = GetDouble();
+ String cStr;
+ Color* pColor = NULL;
+ LanguageType eCellLang;
+ const ScPatternAttr* pPattern = pDok->GetPattern(
+ aPos.Col(), aPos.Row(), aPos.Tab() );
+ if ( pPattern )
+ eCellLang = ((const SvxLanguageItem&)
+ pPattern->GetItem( ATTR_LANGUAGE_FORMAT )).GetValue();
+ else
+ eCellLang = ScGlobal::eLnge;
+ if ( !pFormatter->GetPreviewStringGuess( sFormatString, fVal, cStr,
+ &pColor, eCellLang ) )
+ SetIllegalParameter();
+ else
+ PushStringObject(cStr);
+ }
+}
+
+
+void ScInterpreter::ScSubstitute()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 3, 4 ) )
+ {
+ xub_StrLen nAnz;
+ if (nParamCount == 4)
+ {
+ double fAnz = SolarMath::ApproxFloor(GetDouble());
+ if( fAnz < 1 || fAnz > MAXSTRLEN )
+ {
+ SetIllegalParameter();
+ return;
+ }
+ else
+ nAnz = (xub_StrLen) fAnz;
+ }
+ else
+ nAnz = 0;
+ String sNewStr = GetString();
+ String sOldStr = GetString();
+ String sStr = GetString();
+ xub_StrLen nPos = 0;
+ xub_StrLen nCount = 0;
+ xub_StrLen nNewLen = sNewStr.Len();
+ xub_StrLen nOldLen = sOldStr.Len();
+ while( TRUE )
+ {
+ nPos = sStr.Search( sOldStr, nPos );
+ if (nPos != STRING_NOTFOUND)
+ {
+ nCount++;
+ if( !nAnz || nCount == nAnz )
+ {
+ sStr.Erase(nPos,nOldLen);
+ sStr.Insert(sNewStr,nPos);
+ nPos += nNewLen;
+ if( sStr.Len() >= MAXSTRLEN )
+ break;
+ }
+ else
+ nPos++;
+ }
+ else
+ break;
+ }
+ PushStringObject( sStr );
+ }
+}
+
+
+void ScInterpreter::ScRept()
+{
+ if ( MustHaveParamCount( GetByte(), 2 ) )
+ {
+ double fAnz = GetDouble();
+ if( fAnz < 1.0 || fAnz > MAXSTRLEN )
+ SetIllegalParameter();
+ else
+ {
+ short n = (short) fAnz;
+ String aRes;
+ String aStr( GetString() );
+ while( n-- )
+ aRes += aStr;
+ PushStringObject( aRes );
+ }
+ }
+}
+
+
+void ScInterpreter::ScConcat()
+{
+ BYTE nParamCount = GetByte();
+ String aRes;
+ while( nParamCount-- )
+ {
+ const sal_Unicode* p = GetString();
+ aRes.Insert( p, 0 );
+ }
+ PushStringObject( aRes );
+}
+
+
+void ScInterpreter::ScErrorType()
+{
+ USHORT nErr;
+ USHORT nOldError = nGlobalError;
+ nGlobalError = 0;
+ switch ( GetStackType() )
+ {
+ case svDoubleRef :
+ {
+ ScRange aRange;
+ PopDoubleRef( aRange );
+ if ( nGlobalError )
+ nErr = nGlobalError;
+ else
+ {
+ ScAddress aAdr;
+ if ( DoubleRefToPosSingleRef( aRange, aAdr ) )
+ nErr = pDok->GetErrCode( aAdr );
+ else
+ nErr = nGlobalError;
+ }
+ }
+ break;
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ PopSingleRef( aAdr );
+ if ( nGlobalError )
+ nErr = nGlobalError;
+ else
+ nErr = pDok->GetErrCode( aAdr );
+ }
+ break;
+ default:
+ PopError();
+ nErr = nGlobalError;
+ }
+ if ( nErr )
+ {
+ nGlobalError = 0;
+ PushDouble( nErr );
+ }
+ else
+ {
+ nGlobalError = nOldError;
+ SetNV();
+ }
+}
+
+
+BOOL ScInterpreter::MayBeRegExp( const String& rStr )
+{
+ if ( !rStr.Len() || (rStr.Len() == 1 && rStr.GetChar(0) != '.') )
+ return FALSE; // einzelnes Metazeichen kann keine RegExp sein
+ static const sal_Unicode cre[] = { '.','*','+','?','[',']','^','$','\\','(',')','|', 0 };
+ const sal_Unicode* p1 = rStr.GetBuffer();
+ sal_Unicode c1;
+ while ( c1 = *p1++ )
+ {
+ const sal_Unicode* p2 = cre;
+ while ( *p2 )
+ {
+ if ( c1 == *p2++ )
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx
new file mode 100644
index 000000000000..df08614d5df6
--- /dev/null
+++ b/sc/source/core/tool/interpr2.cxx
@@ -0,0 +1,1957 @@
+/*************************************************************************
+ *
+ * $RCSfile: interpr2.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <svx/linkmgr.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/objsh.hxx>
+#include <svtools/stritem.hxx>
+#include <svtools/zforlist.hxx>
+#include <string.h>
+#include <math.h>
+
+#include "interpre.hxx"
+#include "attrib.hxx"
+#include "sc.hrc"
+#include "ddelink.hxx"
+#include "scmatrix.hxx"
+#include "compiler.hxx"
+#include "cell.hxx"
+#include "document.hxx"
+#include "dociter.hxx"
+#include "docoptio.hxx"
+#include "unitconv.hxx"
+#include "globstr.hrc"
+#include "hints.hxx"
+
+// STATIC DATA -----------------------------------------------------------
+
+#define D_TIMEFACTOR 86400.0
+#define SCdEpsilon 1.0E-7
+
+//-----------------------------------------------------------------------------
+// Datum und Zeit
+//-----------------------------------------------------------------------------
+
+double ScInterpreter::GetDate(INT16 nYear, INT16 nMonth, INT16 nDay)
+{
+ if ( nYear < 100 )
+ nYear = pFormatter->ExpandTwoDigitYear( nYear );
+ INT16 nY, nM;
+ if (nMonth > 0)
+ {
+ nY = nYear + (nMonth-1) / 12;
+ nM = ((nMonth-1) % 12) + 1;
+ }
+ else
+ {
+ nY = nYear + (nMonth-12) / 12;
+ nM = 12 - (-nMonth) % 12;
+ }
+ Date aDate(1, nM, nY);
+ aDate += nDay - 1;
+ if (aDate.IsValid())
+ return (double) (aDate - *(pFormatter->GetNullDate()));
+ else
+ {
+ SetError(errNoValue);
+ return 0;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Funktionen
+//-----------------------------------------------------------------------------
+
+void ScInterpreter::ScGetActDate()
+{
+ nFuncFmtType = NUMBERFORMAT_DATE;
+ Date aActDate;
+ long nDiff = aActDate - *(pFormatter->GetNullDate());
+ PushDouble((double) nDiff);
+}
+
+void ScInterpreter::ScGetActTime()
+{
+ nFuncFmtType = NUMBERFORMAT_DATETIME;
+ Date aActDate;
+ long nDiff = aActDate - *(pFormatter->GetNullDate());
+ Time aActTime;
+ double nTime = ((double)aActTime.Get100Sec() / 100 +
+ (double)(aActTime.GetSec() +
+ (aActTime.GetMin() * 60) +
+ (aActTime.GetHour() * 3600))) / D_TIMEFACTOR;
+ PushDouble( (double) nDiff + nTime );
+}
+
+void ScInterpreter::ScGetYear()
+{
+ Date aDate = *(pFormatter->GetNullDate());
+ aDate += (long) SolarMath::ApproxFloor(GetDouble());
+ PushDouble( (double) aDate.GetYear() );
+}
+
+void ScInterpreter::ScGetMonth()
+{
+ Date aDate = *(pFormatter->GetNullDate());
+ aDate += (long) SolarMath::ApproxFloor(GetDouble());
+ PushDouble( (double) aDate.GetMonth() );
+}
+
+void ScInterpreter::ScGetDay()
+{
+ Date aDate = *(pFormatter->GetNullDate());
+ aDate += (long)SolarMath::ApproxFloor(GetDouble());
+ PushDouble((double) aDate.GetDay());
+}
+
+void ScInterpreter::ScGetMin()
+{
+ double fTime = GetDouble();
+ fTime -= SolarMath::ApproxFloor(fTime); // Datumsanteil weg
+ long nVal = (long)SolarMath::ApproxFloor(fTime*D_TIMEFACTOR+0.5) % 3600;
+ PushDouble( (double) (nVal/60) );
+}
+
+void ScInterpreter::ScGetSec()
+{
+ double fTime = GetDouble();
+ fTime -= SolarMath::ApproxFloor(fTime); // Datumsanteil weg
+ long nVal = (long)SolarMath::ApproxFloor(fTime*D_TIMEFACTOR+0.5) % 60;
+ PushDouble( (double) nVal );
+}
+
+void ScInterpreter::ScGetHour()
+{
+ double fTime = GetDouble();
+ fTime -= SolarMath::ApproxFloor(fTime); // Datumsanteil weg
+ long nVal = (long)SolarMath::ApproxFloor(fTime*D_TIMEFACTOR+0.5) / 3600;
+ PushDouble((double) nVal);
+}
+
+void ScInterpreter::ScGetDateValue()
+{
+ String aInputString = GetString();
+ ULONG nFIndex = 0; // damit default Land/Spr.
+ double fVal;
+ if (pFormatter->IsNumberFormat(aInputString, nFIndex, fVal))
+ {
+ short eType = pFormatter->GetType(nFIndex);
+ if (eType == NUMBERFORMAT_DATE || eType == NUMBERFORMAT_DATETIME)
+ PushDouble(fVal);
+ else
+ SetIllegalArgument();
+ }
+ else
+ SetIllegalArgument();
+}
+
+void ScInterpreter::ScGetDayOfWeek()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 1, 2 ) )
+ {
+ short nFlag;
+ if (nParamCount == 2)
+ nFlag = (short) SolarMath::ApproxFloor(GetDouble());
+ else
+ nFlag = 1;
+
+ Date aDate = *(pFormatter->GetNullDate());
+ aDate += (long)SolarMath::ApproxFloor(GetDouble());
+ int nVal = (int) aDate.GetDayOfWeek();
+ if (nFlag == 1)
+ {
+ if (nVal == 6)
+ nVal = 1;
+ else
+ nVal += 2;
+ }
+ else if (nFlag == 2)
+ nVal += 1;
+ PushInt( nVal );
+ }
+}
+
+void ScInterpreter::ScGetWeekOfYear()
+{
+ if ( MustHaveParamCount( GetByte(), 2 ) )
+ {
+ short nFlag = (short) SolarMath::ApproxFloor(GetDouble());
+
+ Date aDate = *(pFormatter->GetNullDate());
+ aDate += (long)SolarMath::ApproxFloor(GetDouble());
+ PushInt( (int) aDate.GetWeekOfYear( nFlag == 1 ? SUNDAY : MONDAY ));
+ }
+}
+
+void ScInterpreter::ScEasterSunday()
+{
+ nFuncFmtType = NUMBERFORMAT_DATE;
+ if ( MustHaveParamCount( GetByte(), 1 ) )
+ {
+ INT16 nDay, nMonth, nYear;
+ nYear = (INT16) SolarMath::ApproxFloor( GetDouble() );
+ if ( nYear < 100 )
+ nYear = pFormatter->ExpandTwoDigitYear( nYear );
+ // don't worry, be happy :)
+ int B,C,D,E,F,G,H,I,K,L,M,N,O;
+ N = nYear % 19;
+ B = int(nYear / 100);
+ C = nYear % 100;
+ D = int(B / 4);
+ E = B % 4;
+ F = int((B + 8) / 25);
+ G = int((B - F + 1) / 3);
+ H = (19 * N + B - D - G + 15) % 30;
+ I = int(C / 4);
+ K = C % 4;
+ L = (32 + 2 * E + 2 * I - H - K) % 7;
+ M = int((N + 11 * H + 22 * L) / 451);
+ O = H + L - 7 * M + 114;
+ nDay = O % 31 + 1;
+ nMonth = int(O / 31);
+ PushDouble( GetDate( nYear, nMonth, nDay ) );
+ }
+}
+
+void ScInterpreter::ScGetDate()
+{
+ nFuncFmtType = NUMBERFORMAT_DATE;
+ if ( MustHaveParamCount( GetByte(), 3 ) )
+ {
+ INT16 nDay = (INT16) SolarMath::ApproxFloor(GetDouble());
+ INT16 nMonth = (INT16) SolarMath::ApproxFloor(GetDouble());
+ INT16 nYear = (INT16) SolarMath::ApproxFloor(GetDouble());
+ if (nYear < 0)
+ SetIllegalParameter();
+ else
+ {
+ PushDouble(GetDate(nYear, nMonth, nDay));
+ }
+ }
+}
+
+void ScInterpreter::ScGetTime()
+{
+ nFuncFmtType = NUMBERFORMAT_TIME;
+ if ( MustHaveParamCount( GetByte(), 3 ) )
+ {
+ double nSec = GetDouble();
+ double nMin = GetDouble();
+ double nHour = GetDouble();
+ PushDouble( ( (nHour * 3600) + (nMin * 60) + nSec ) / D_TIMEFACTOR );
+ }
+}
+
+void ScInterpreter::ScGetDiffDate()
+{
+ if ( MustHaveParamCount( GetByte(), 2 ) )
+ {
+ double nDate2 = GetDouble();
+ double nDate1 = GetDouble();
+ PushDouble(nDate1 - nDate2);
+ }
+}
+
+void ScInterpreter::ScGetDiffDate360()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 2, 3 ) )
+ {
+ BOOL bFlag;
+ if (nParamCount == 3)
+ bFlag = GetBool();
+ else
+ bFlag = FALSE;
+ double nDate2 = GetDouble();
+ double nDate1 = GetDouble();
+ double fSign;
+ if (nGlobalError == 0)
+ {
+ if (nDate2 < nDate1)
+ {
+ fSign = nDate1;
+ nDate1 = nDate2;
+ nDate2 = fSign;
+ fSign = -1.0;
+ }
+ else
+ fSign = 1.0;
+ Date aDate1 = *(pFormatter->GetNullDate());
+ aDate1 += (long) SolarMath::ApproxFloor(nDate1);
+ Date aDate2 = *(pFormatter->GetNullDate());
+ aDate2 += (long) SolarMath::ApproxFloor(nDate2);
+ if (aDate1.GetDay() == 31)
+ aDate1 -= (ULONG) 1;
+ else if (!bFlag)
+ {
+ if (aDate1.GetMonth() == 2)
+ {
+ switch ( aDate1.GetDay() )
+ {
+ case 28 :
+ if ( !aDate1.IsLeapYear() )
+ aDate1.SetDay(30);
+ break;
+ case 29 :
+ aDate1.SetDay(30);
+ break;
+ }
+ }
+ }
+ if (aDate2.GetDay() == 31)
+ {
+ if (!bFlag && aDate1.GetDay() != 30)
+ aDate2 += (ULONG) 1; // -> 1.
+ else
+ aDate2.SetDay(30);
+ }
+ PushDouble( fSign * (double)
+ ( (double) aDate2.GetDay() + (double) aDate2.GetMonth() * 30.0 +
+ (double) aDate2.GetYear() * 360.0
+ - (double) aDate1.GetDay() - (double) aDate1.GetMonth() * 30.0
+ - (double)aDate1.GetYear() * 360.0) );
+ }
+ else
+ SetIllegalParameter();
+ }
+}
+
+void ScInterpreter::ScGetTimeValue()
+{
+ String aInputString = GetString();
+ ULONG nFIndex = 0; // damit default Land/Spr.
+ double fVal;
+ if (pFormatter->IsNumberFormat(aInputString, nFIndex, fVal))
+ {
+ short eType = pFormatter->GetType(nFIndex);
+ if (eType == NUMBERFORMAT_TIME || eType == NUMBERFORMAT_DATETIME)
+ PushDouble(fVal);
+ else
+ SetIllegalArgument();
+ }
+ else
+ SetIllegalArgument();
+}
+
+void ScInterpreter::ScPlusMinus()
+{
+ double nVal = GetDouble();
+ short n = 0;
+ if (nVal < 0.0)
+ n = -1;
+ else if (nVal > 0.0)
+ n = 1;
+ PushInt( n );
+}
+
+void ScInterpreter::ScAbs()
+{
+ PushDouble(fabs(GetDouble()));
+}
+
+void ScInterpreter::ScInt()
+{
+ PushDouble(SolarMath::ApproxFloor(GetDouble()));
+}
+
+
+void ScInterpreter::RoundNumber( SolarMathRoundingMode eMode )
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 1, 2 ) )
+ {
+ double fVal = 0.0;
+ if (nParamCount == 1)
+ fVal = SolarMath::Round( GetDouble(), 0, eMode );
+ else
+ {
+ INT32 nDec = (INT32) SolarMath::ApproxFloor(GetDouble());
+ if( nDec < -20 || nDec > 20 )
+ SetIllegalArgument();
+ else
+ fVal = SolarMath::Round( GetDouble(), (short)nDec, eMode );
+ }
+ PushDouble(fVal);
+ }
+}
+
+void ScInterpreter::ScRound()
+{
+ RoundNumber( SolarMathRoundCorrected );
+}
+
+void ScInterpreter::ScRoundDown()
+{
+ RoundNumber( SolarMathRoundDown );
+}
+
+void ScInterpreter::ScRoundUp()
+{
+ RoundNumber( SolarMathRoundUp );
+}
+
+void ScInterpreter::ScCeil()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 2, 3 ) )
+ {
+ BOOL bAbs = ( nParamCount == 3 ? GetBool() : FALSE );
+ double fDec = GetDouble();
+ double fVal = GetDouble();
+ if ( fDec == 0.0 )
+ PushInt(0);
+ else if (fVal*fDec < 0.0)
+ SetIllegalArgument();
+ else
+ {
+ if ( !bAbs && fVal < 0.0 )
+ PushDouble(SolarMath::ApproxFloor(fVal/fDec) * fDec);
+ else
+ PushDouble(SolarMath::ApproxCeil(fVal/fDec) * fDec);
+ }
+ }
+}
+
+void ScInterpreter::ScFloor()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 2, 3 ) )
+ {
+ BOOL bAbs = ( nParamCount == 3 ? GetBool() : FALSE );
+ double fDec = GetDouble();
+ double fVal = GetDouble();
+ if ( fDec == 0.0 )
+ PushInt(0);
+ else if (fVal*fDec < 0.0)
+ SetIllegalArgument();
+ else
+ {
+ if ( !bAbs && fVal < 0.0 )
+ PushDouble(SolarMath::ApproxCeil(fVal/fDec) * fDec);
+ else
+ PushDouble(SolarMath::ApproxFloor(fVal/fDec) * fDec);
+ }
+ }
+}
+
+void ScInterpreter::ScEven()
+{
+ double fVal = GetDouble();
+ if (fVal < 0.0)
+ PushDouble(SolarMath::ApproxFloor(fVal/2.0) * 2.0);
+ else
+ PushDouble(SolarMath::ApproxCeil(fVal/2.0) * 2.0);
+}
+
+void ScInterpreter::ScOdd()
+{
+ double fVal = GetDouble();
+ if (fVal >= 0.0)
+ {
+ fVal = SolarMath::ApproxCeil(fVal);
+ if (fmod(fVal, 2.0) == 0.0)
+ fVal += 1.0;
+ }
+ else
+ {
+ fVal = SolarMath::ApproxFloor(fVal);
+ if (fmod(fVal, 2.0) == 0.0)
+ fVal -= 1.0;
+ }
+ PushDouble(fVal);
+}
+
+void ScInterpreter::ScArcTan2()
+{
+ if ( MustHaveParamCount( GetByte(), 2 ) )
+ {
+ double nVal2 = GetDouble();
+ double nVal1 = GetDouble();
+ PushDouble(atan2(nVal2, nVal1));
+ }
+}
+
+void ScInterpreter::ScLog()
+{
+ if ( MustHaveParamCount( GetByte(), 2 ) )
+ {
+ double nBase = GetDouble();
+ double nVal = GetDouble();
+ if (nVal > 0.0 && nBase > 0.0 && nBase != 1.0)
+ PushDouble(log(nVal) / log(nBase));
+ else
+ SetIllegalArgument();
+ }
+}
+
+void ScInterpreter::ScLn()
+{
+ double fVal = GetDouble();
+ if (fVal > 0.0)
+ PushDouble(log(fVal));
+ else
+ SetIllegalArgument();
+}
+
+void ScInterpreter::ScLog10()
+{
+ double fVal = GetDouble();
+ if (fVal > 0.0)
+ PushDouble(log10(fVal));
+ else
+ SetIllegalArgument();
+}
+
+void ScInterpreter::ScNBW()
+{
+ nFuncFmtType = NUMBERFORMAT_CURRENCY;
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 2, 31 ) )
+ {
+ double nVal = 0.0;
+ // Wir drehen den Stack um!!
+ ScToken* pTemp[ 31 ];
+ for( short i = 0; i < nParamCount; i++ )
+ pTemp[ i ] = pStack[ sp - i - 1 ];
+ memcpy( &pStack[ sp - nParamCount ], pTemp, nParamCount * sizeof( ScToken* ) );
+ if (nGlobalError == 0)
+ {
+ double nCount = 1.0;
+ double nZins = GetDouble();
+ ScRange aRange;
+ for (short i = 2; i <= (short) nParamCount; i++)
+ {
+ switch (GetStackType())
+ {
+ case svDouble :
+ {
+ nVal += (GetDouble() / pow(1.0 + nZins, nCount));
+ nCount++;
+ }
+ break;
+ case svSingleRef :
+ {
+ nVal += (GetDouble() / pow(1.0 + nZins, nCount));
+ nCount++;
+ }
+ break;
+ case svDoubleRef :
+ {
+ USHORT nErr = 0;
+ double nCellVal;
+ PopDoubleRef( aRange );
+ ScValueIterator aValIter(pDok, aRange, glSubTotal);
+ if (aValIter.GetFirst(nCellVal, nErr))
+ {
+ nVal += (nCellVal / pow(1.0 + nZins, nCount));
+ nCount++;
+ while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
+ {
+ nVal += (nCellVal / pow(1.0 + nZins, nCount));
+ nCount++;
+ }
+ SetError(nErr);
+ }
+ }
+ break;
+ default : SetError(errIllegalParameter); break;
+ }
+ }
+ }
+ PushDouble(nVal);
+ }
+}
+
+#if defined(WIN) && defined(MSC)
+#pragma optimize("",off)
+#endif
+
+void ScInterpreter::ScIKV()
+{
+ double fSchaetzwert;
+ nFuncFmtType = NUMBERFORMAT_PERCENT;
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 1, 2 ) )
+ return;
+ if (nParamCount == 2)
+ fSchaetzwert = GetDouble();
+ else
+ fSchaetzwert = 0.1;
+ USHORT sPos = sp; // Stack-Position merken
+ double fEps = 1.0;
+ double x, xNeu, fWert, fZaehler, fNenner, nCount;
+ if (fSchaetzwert == -1.0)
+ x = 0.1; // default gegen Nulldivisionen
+ else
+ x = fSchaetzwert; // Startwert
+ switch (GetStackType())
+ {
+ case svDoubleRef :
+ break;
+ case svDouble :
+ case svSingleRef :
+ default:
+ {
+ SetError(errIllegalParameter);
+ return;
+ }
+ }
+ const USHORT nIterationsMax = 20;
+ USHORT nItCount = 0;
+ ScRange aRange;
+ while (fEps > SCdEpsilon && nItCount < nIterationsMax)
+ { // Newton-Verfahren:
+ sp = sPos; // Stack zuruecksetzen
+ nCount = 0.0;
+ fZaehler = 0.0;
+ fNenner = 0.0;
+ USHORT nErr = 0;
+ PopDoubleRef( aRange );
+ ScValueIterator aValIter(pDok, aRange, glSubTotal);
+ if (aValIter.GetFirst(fWert, nErr))
+ {
+ fZaehler += fWert / pow(1.0+x,nCount);
+ fNenner += -nCount * fWert / pow(1.0+x,nCount+1.0);
+ nCount++;
+ while ((nErr == 0) && aValIter.GetNext(fWert, nErr))
+ {
+ fZaehler += fWert / pow(1.0+x,nCount);
+ fNenner += -nCount * fWert / pow(1.0+x,nCount+1.0);
+ nCount++;
+ }
+ SetError(nErr);
+ }
+ xNeu = x - fZaehler / fNenner; // x(i+1) = x(i)-f(x(i))/f'(x(i))
+ nItCount++;
+ fEps = fabs(xNeu - x);
+ x = xNeu;
+ }
+ if (fSchaetzwert == 0.0 && fabs(x) < SCdEpsilon)
+ x = 0.0; // auf Null normieren
+ if (fEps < SCdEpsilon)
+ PushDouble(x);
+ else
+ {
+ SetError(errNoConvergence);
+ PushInt(0);
+ }
+}
+#if defined(WIN) && defined(MSC)
+#pragma optimize("",on)
+#endif
+
+//----------------------- Finanzfunktionen ------------------------------------
+
+double ScInterpreter::ScGetBw(double fZins, double fZzr, double fRmz,
+ double fZw, double fF)
+{
+ double fBw;
+ if (fZins == 0.0)
+ fBw = fZw + fRmz * fZzr;
+ else if (fF > 0.0)
+ fBw = (fZw * pow(1.0 + fZins, -fZzr))
+ + (fRmz * (1.0 - pow(1.0 + fZins, -fZzr + 1.0)) / fZins)
+ + fRmz;
+ else
+ fBw = (fZw * pow(1.0 + fZins, -fZzr))
+ + (fRmz * (1.0 - pow(1.0 + fZins, -fZzr)) / fZins);
+ return -fBw;
+}
+
+void ScInterpreter::ScBW()
+{
+ nFuncFmtType = NUMBERFORMAT_CURRENCY;
+ double nRmz, nZzr, nZins, nZw = 0, nFlag = 0;
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 3, 5 ) )
+ return;
+ if (nParamCount == 5)
+ nFlag = GetDouble();
+ if (nParamCount >= 4)
+ nZw = GetDouble();
+ nRmz = GetDouble();
+ nZzr = GetDouble();
+ nZins = GetDouble();
+ PushDouble(ScGetBw(nZins, nZzr, nRmz, nZw, nFlag));
+}
+
+void ScInterpreter::ScDIA()
+{
+ nFuncFmtType = NUMBERFORMAT_CURRENCY;
+ if ( MustHaveParamCount( GetByte(), 4 ) )
+ {
+ double nZr = GetDouble();
+ double nDauer = GetDouble();
+ double nRest = GetDouble();
+ double nWert = GetDouble();
+ double nDia = ((nWert - nRest) * (nDauer - nZr + 1.0)) /
+ ((nDauer * (nDauer + 1.0)) / 2.0);
+ PushDouble(nDia);
+ }
+}
+
+double ScInterpreter::ScGetGDA(double fWert, double fRest, double fDauer,
+ double fPeriode, double fFaktor)
+{
+ double fGda, fZins, fAlterWert, fNeuerWert;
+ fZins = fFaktor / fDauer;
+ if (fZins >= 1.0)
+ {
+ fZins = 1.0;
+ if (fPeriode == 1.0)
+ fAlterWert = fWert;
+ else
+ fAlterWert = 0.0;
+ }
+ else
+ fAlterWert = fWert * pow(1.0 - fZins, fPeriode - 1.0);
+ fNeuerWert = fWert * pow(1.0 - fZins, fPeriode);
+
+ if (fNeuerWert < fRest)
+ fGda = fAlterWert - fRest;
+ else
+ fGda = fAlterWert - fNeuerWert;
+ if (fGda < 0.0)
+ fGda = 0.0;
+ return fGda;
+}
+
+void ScInterpreter::ScGDA()
+{
+ nFuncFmtType = NUMBERFORMAT_CURRENCY;
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 4, 5 ) )
+ {
+ double nFaktor;
+ if (nParamCount == 5)
+ nFaktor = GetDouble();
+ else
+ nFaktor = 2.0;
+ double nPeriode = GetDouble();
+ double nDauer = GetDouble();
+ double nRest = GetDouble();
+ double nWert = GetDouble();
+ if (nWert < 0.0 || nRest < 0.0 || nFaktor <= 0.0 || nRest > nWert
+ || nPeriode < 1.0 || nPeriode > nDauer)
+ SetIllegalParameter();
+ else
+ PushDouble(ScGetGDA(nWert, nRest, nDauer, nPeriode, nFaktor));
+ }
+}
+
+void ScInterpreter::ScGDA2()
+{
+ nFuncFmtType = NUMBERFORMAT_CURRENCY;
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 4, 5 ) )
+ return ;
+ double nMonate;
+ if (nParamCount == 4)
+ nMonate = 12.0;
+ else
+ nMonate = SolarMath::ApproxFloor(GetDouble());
+ double nPeriode = GetDouble();
+ double nDauer = GetDouble();
+ double nRest = GetDouble();
+ double nWert = GetDouble();
+ if (nMonate < 1.0 || nMonate > 12.0 || nDauer > 1200.0 || nRest < 0.0 ||
+ nPeriode > (nDauer + 1.0) || nRest > nWert || nWert < 0.0)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ double nAbRate = 1.0 - pow(nRest / nWert, 1.0 / nDauer);
+ nAbRate = SolarMath::ApproxFloor((nAbRate * 1000.0) + 0.5) / 1000.0;
+ double nErsteAbRate = nWert * nAbRate * nMonate / 12.0;
+ double nGda2;
+ if (SolarMath::ApproxFloor(nPeriode) == 1)
+ nGda2 = nErsteAbRate;
+ else
+ {
+ double nSummAbRate = nErsteAbRate;
+ double nMin = nDauer;
+ if (nMin > nPeriode) nMin = nPeriode;
+ USHORT iMax = (USHORT)SolarMath::ApproxFloor(nMin);
+ for (USHORT i = 2; i <= iMax; i++)
+ {
+ nGda2 = (nWert - nSummAbRate) * nAbRate;
+ nSummAbRate += nGda2;
+ }
+ if (nPeriode > nDauer)
+ nGda2 = ((nWert - nSummAbRate) * nAbRate * (12.0 - nMonate)) / 12.0;
+ }
+ PushDouble(nGda2);
+}
+
+
+double ScInterpreter::ScInterVDB(double fWert,double fRest,double fDauer,
+ double fDauer1,double fPeriode,double fFaktor)
+{
+ double fVdb=0;
+ double fIntEnd = SolarMath::ApproxCeil(fPeriode);
+ ULONG nLoopEnd = (ULONG) fIntEnd;
+
+ double fTerm, fLia;
+ double fRestwert = fWert - fRest;
+ double fRestwert1 = fRestwert;
+ BOOL bNowLia = FALSE;
+ BOOL bFirstFlag=TRUE;
+ BOOL b2Flag=TRUE;
+ double fAbschlag=0;
+
+ double fGda;
+ ULONG i;
+ fLia=0;
+ for ( i = 1; i <= nLoopEnd; i++)
+ {
+ if(!bNowLia)
+ {
+ fGda = ScGetGDA(fWert, fRest, fDauer, (double) i, fFaktor);
+ fLia = fRestwert/ (fDauer1 - (double) (i-1));
+
+ if (fLia > fGda)
+ {
+ fTerm = fLia;
+ bNowLia = TRUE;
+ }
+ else
+ {
+ fTerm = fGda;
+ fRestwert -= fGda;
+ }
+ }
+ else
+ {
+ fTerm = fLia;
+ }
+
+ if ( i == nLoopEnd)
+ fTerm *= ( fPeriode + 1.0 - fIntEnd );
+
+ fVdb += fTerm;
+ }
+ return fVdb;
+}
+
+
+inline double DblMin( double a, double b )
+{
+ return (a < b) ? a : b;
+}
+
+void ScInterpreter::ScVDB()
+{
+ nFuncFmtType = NUMBERFORMAT_CURRENCY;
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 5, 7 ) )
+ {
+ double fWert, fRest, fDauer, fAnfang, fEnde, fFaktor, fVdb;
+ BOOL bFlag;
+ if (nParamCount == 7)
+ bFlag = GetBool();
+ else
+ bFlag = FALSE;
+ if (nParamCount >= 6)
+ fFaktor = GetDouble();
+ else
+ fFaktor = 2.0;
+ fEnde = GetDouble();
+ fAnfang = GetDouble();
+ fDauer = GetDouble();
+ fRest = GetDouble();
+ fWert = GetDouble();
+ if (fAnfang < 0.0 || fEnde < fAnfang || fEnde > fDauer || fWert < 0.0
+ || fRest > fWert || fFaktor <= 0.0)
+ SetIllegalParameter();
+ else
+ {
+ double fIntStart = SolarMath::ApproxFloor(fAnfang);
+ double fIntEnd = SolarMath::ApproxCeil(fEnde);
+ ULONG nLoopStart = (ULONG) fIntStart;
+ ULONG nLoopEnd = (ULONG) fIntEnd;
+
+ fVdb = 0.0;
+ if (bFlag)
+ {
+ for (ULONG i = nLoopStart + 1; i <= nLoopEnd; i++)
+ {
+ double fTerm = ScGetGDA(fWert, fRest, fDauer, (double) i, fFaktor);
+
+ // Teilperioden am Anfang / Ende beruecksichtigen:
+ if ( i == nLoopStart+1 )
+ fTerm *= ( DblMin( fEnde, fIntStart + 1.0 ) - fAnfang );
+ else if ( i == nLoopEnd )
+ fTerm *= ( fEnde + 1.0 - fIntEnd );
+
+ fVdb += fTerm;
+ }
+ }
+ else
+ {
+
+ double fDauer1=fDauer;
+ double fPart;
+
+ //@Die Frage aller Fragen: "Ist das hier richtig"
+ if(!SolarMath::ApproxEqual(fAnfang,SolarMath::ApproxFloor(fAnfang)))
+ {
+ if(fFaktor>1)
+ {
+ if(fAnfang>fDauer/2 || SolarMath::ApproxEqual(fAnfang,fDauer/2))
+ {
+ fPart=fAnfang-fDauer/2;
+ fAnfang=fDauer/2;
+ fEnde-=fPart;
+ fDauer1+=1;
+ }
+ }
+ }
+
+ fWert-=ScInterVDB(fWert,fRest,fDauer,fDauer1,fAnfang,fFaktor);
+ fVdb=ScInterVDB(fWert,fRest,fDauer,fDauer-fAnfang,fEnde-fAnfang,fFaktor);
+ }
+ }
+ PushDouble(fVdb);
+ }
+}
+
+void ScInterpreter::ScLaufz()
+{
+ if ( MustHaveParamCount( GetByte(), 3 ) )
+ {
+ double nZukunft = GetDouble();
+ double nGegenwart = GetDouble();
+ double nZins = GetDouble();
+ PushDouble(log(nZukunft / nGegenwart) / log(1.0 + nZins));
+ }
+}
+
+void ScInterpreter::ScLIA()
+{
+ nFuncFmtType = NUMBERFORMAT_CURRENCY;
+ if ( MustHaveParamCount( GetByte(), 3 ) )
+ {
+ double nDauer = GetDouble();
+ double nRest = GetDouble();
+ double nWert = GetDouble();
+ PushDouble((nWert - nRest) / nDauer);
+ }
+}
+
+double ScInterpreter::ScGetRmz(double fZins, double fZzr, double fBw,
+ double fZw, double fF)
+{
+ double fRmz;
+ if (fZins == 0.0)
+ fRmz = (fBw + fZw) / fZzr;
+ else
+ {
+ double fTerm = pow(1.0 + fZins, fZzr);
+ if (fF > 0.0)
+ fRmz = (fZw * fZins / (fTerm - 1.0)
+ + fBw * fZins / (1.0 - 1.0 / fTerm)) / (1.0+fZins);
+ else
+ fRmz = fZw * fZins / (fTerm - 1.0)
+ + fBw * fZins / (1.0 - 1.0 / fTerm);
+ }
+ return -fRmz;
+}
+
+void ScInterpreter::ScRMZ()
+{
+ double nZins, nZzr, nBw, nZw = 0, nFlag = 0;
+ nFuncFmtType = NUMBERFORMAT_CURRENCY;
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 3, 5 ) )
+ return;
+ if (nParamCount == 5)
+ nFlag = GetDouble();
+ if (nParamCount >= 4)
+ nZw = GetDouble();
+ nBw = GetDouble();
+ nZzr = GetDouble();
+ nZins = GetDouble();
+ PushDouble(ScGetRmz(nZins, nZzr, nBw, nZw, nFlag));
+}
+
+void ScInterpreter::ScZGZ()
+{
+ nFuncFmtType = NUMBERFORMAT_PERCENT;
+ if ( MustHaveParamCount( GetByte(), 3 ) )
+ {
+ double nZukunftswert = GetDouble();
+ double nGegenwartswert = GetDouble();
+ double nZeitraum = GetDouble();
+ PushDouble(pow(nZukunftswert / nGegenwartswert, 1.0 / nZeitraum) - 1.0);
+ }
+}
+
+double ScInterpreter::ScGetZw(double fZins, double fZzr, double fRmz,
+ double fBw, double fF)
+{
+ double fZw;
+ if (fZins == 0.0)
+ fZw = fBw + fRmz * fZzr;
+ else
+ {
+ double fTerm = pow(1.0 + fZins, fZzr);
+ if (fF > 0.0)
+ fZw = fBw * fTerm + fRmz*(1.0 + fZins)*(fTerm - 1.0)/fZins;
+ else
+ fZw = fBw * fTerm + fRmz*(fTerm - 1.0)/fZins;
+ }
+ return -fZw;
+}
+
+void ScInterpreter::ScZW()
+{
+ double nZins, nZzr, nRmz, nBw = 0, nFlag = 0;
+ nFuncFmtType = NUMBERFORMAT_CURRENCY;
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 3, 5 ) )
+ return;
+ if (nParamCount == 5)
+ nFlag = GetDouble();
+ if (nParamCount >= 4)
+ nBw = GetDouble();
+ nRmz = GetDouble();
+ nZzr = GetDouble();
+ nZins = GetDouble();
+ PushDouble(ScGetZw(nZins, nZzr, nRmz, nBw, nFlag));
+}
+
+void ScInterpreter::ScZZR()
+{
+ double nZins, nRmz, nBw, nZw = 0, nFlag = 0;
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 3, 5 ) )
+ return;
+ if (nParamCount == 5)
+ nFlag = GetDouble();
+ if (nParamCount >= 4)
+ nZw = GetDouble();
+ nBw = GetDouble();
+ nRmz = GetDouble();
+ nZins = GetDouble();
+ if (nZins == 0.0)
+ PushDouble(-(nBw + nZw)/nRmz);
+ else if (nFlag > 0.0)
+ PushDouble(log(-(nZins*nZw-nRmz*(1.0+nZins))/(nZins*nBw+nRmz*(1.0+nZins)))
+ /log(1.0+nZins));
+ else
+ PushDouble(log(-(nZins*nZw-nRmz)/(nZins*nBw+nRmz))/log(1.0+nZins));
+}
+
+double ScInterpreter::GetZinsIterationEps(double fZzr, double fRmz, double fBw,
+ double fZw, double fF, double& fSchaetzwert)
+{
+ double fEps = 1.0;
+ double x, xNeu, fTerm1, fTerm2;
+ if (fSchaetzwert == 0.0)
+ x = 0.1; // default gegen Nulldivisionen
+ else
+ x = fSchaetzwert; // Startwert
+ const USHORT nIterationsMax = 150;
+ USHORT nCount = 0;
+ while (fEps > SCdEpsilon && nCount < nIterationsMax)
+ { // Newton-Verfahren:
+ if (x == 0.0)
+ xNeu = x -
+ (fBw + fRmz*fZzr + fZw) /
+ (fBw*fZzr + fRmz*(fZzr*(fZzr-1.0) + 2*fF*fZzr)/2.0);
+ else
+ {
+ fTerm1 = pow(1.0+x, fZzr-1);
+ fTerm2 = fTerm1*(1.0+x);
+ xNeu = x*(1.0 - // x(i+1) = x(i) - f(x(i)) / f'(x(i))
+ (x*fBw*fTerm2 + fRmz*(1.0+x*fF)*(fTerm2-1.0) + x*fZw) /
+ (x*x*fZzr*fBw*fTerm1 - fRmz*(fTerm2-1.0)
+ + x*fRmz*(1.0+x*fF)*fZzr*fTerm1) );
+ }
+ nCount++;
+ fEps = fabs(xNeu - x);
+ x = xNeu;
+ }
+ if (fSchaetzwert == 0.0 && fabs(x) < SCdEpsilon)
+ x = 0.0; // auf Null normieren
+ fSchaetzwert = x; //n Rueckgabe
+ return fEps;
+}
+
+void ScInterpreter::ScZins()
+{
+ double nZw = 0, nRmz, nZzr, nBw, nFlag = 0, nSchaetzwert = 0.1, fEps;
+ nFuncFmtType = NUMBERFORMAT_PERCENT;
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 3, 6 ) )
+ return;
+ if (nParamCount == 6)
+ nSchaetzwert = GetDouble();
+ if (nParamCount >= 5)
+ nFlag = GetDouble();
+ if (nParamCount >= 4)
+ nZw = GetDouble();
+ nBw = GetDouble();
+ nRmz = GetDouble();
+ nZzr = GetDouble();
+ if (nFlag == 0.0)
+ fEps = GetZinsIterationEps(nZzr, nRmz, nBw, nZw, 0.0, nSchaetzwert);
+ else
+ fEps = GetZinsIterationEps(nZzr, nRmz, nBw, nZw, 1.0, nSchaetzwert);
+ if (fEps >= SCdEpsilon)
+ {
+ SetError(errNoConvergence);
+ nSchaetzwert = 0;
+ }
+ PushDouble(nSchaetzwert);
+}
+
+double ScInterpreter::ScGetZinsZ(double fZins, double fZr, double fZzr, double fBw,
+ double fZw, double fF, double& fRmz)
+{
+ fRmz = ScGetRmz(fZins, fZzr, fBw, fZw, fF); // fuer kapz auch bei fZr == 1
+ double fZinsZ;
+ nFuncFmtType = NUMBERFORMAT_CURRENCY;
+ if (fZr == 1.0)
+ {
+ if (fF > 0.0)
+ fZinsZ = 0.0;
+ else
+ fZinsZ = -fBw;
+ }
+ else
+ {
+ if (fF > 0.0)
+ fZinsZ = ScGetZw(fZins, fZr-2.0, fRmz, fBw, 1.0) - fRmz;
+ else
+ fZinsZ = ScGetZw(fZins, fZr-1.0, fRmz, fBw, 0.0);
+ }
+ return fZinsZ * fZins;
+}
+
+void ScInterpreter::ScZinsZ()
+{
+ double nZins, nZr, nRmz, nZzr, nBw, nZw = 0, nFlag = 0;
+ nFuncFmtType = NUMBERFORMAT_CURRENCY;
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 4, 6 ) )
+ return;
+ if (nParamCount == 6)
+ nFlag = GetDouble();
+ if (nParamCount >= 5)
+ nZw = GetDouble();
+ nBw = GetDouble();
+ nZzr = GetDouble();
+ nZr = GetDouble();
+ nZins = GetDouble();
+ if (nZr < 1.0 || nZr > nZzr)
+ SetIllegalParameter();
+ else
+ PushDouble(ScGetZinsZ(nZins, nZr, nZzr, nBw, nZw, nFlag, nRmz));
+}
+
+void ScInterpreter::ScKapz()
+{
+ double nZins, nZr, nZzr, nBw, nZw = 0, nFlag = 0, nRmz, nZinsz;
+ nFuncFmtType = NUMBERFORMAT_CURRENCY;
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 4, 6 ) )
+ return;
+ if (nParamCount == 6)
+ nFlag = GetDouble();
+ if (nParamCount >= 5)
+ nZw = GetDouble();
+ nBw = GetDouble();
+ nZzr = GetDouble();
+ nZr = GetDouble();
+ nZins = GetDouble();
+ if (nZr < 1.0 || nZr > nZzr)
+ SetIllegalParameter();
+ else
+ {
+ nZinsz = ScGetZinsZ(nZins, nZr, nZzr, nBw, nZw, nFlag, nRmz);
+ PushDouble(nRmz - nZinsz);
+ }
+}
+
+void ScInterpreter::ScKumZinsZ()
+{
+ nFuncFmtType = NUMBERFORMAT_CURRENCY;
+ if ( MustHaveParamCount( GetByte(), 6 ) )
+ {
+ double fZins, fZzr, fBw, fAnfang, fEnde, fF, fRmz, fZinsZ;
+ fF = GetDouble();
+ fEnde = SolarMath::ApproxFloor(GetDouble());
+ fAnfang = SolarMath::ApproxFloor(GetDouble());
+ fBw = GetDouble();
+ fZzr = GetDouble();
+ fZins = GetDouble();
+ if (fAnfang < 1.0 || fEnde < fAnfang || fZins <= 0.0 ||
+ fEnde > fZzr || fZzr <= 0.0 || fBw <= 0.0)
+ SetIllegalParameter();
+ else
+ {
+ ULONG nAnfang = (ULONG) fAnfang;
+ ULONG nEnde = (ULONG) fEnde ;
+ fRmz = ScGetRmz(fZins, fZzr, fBw, 0.0, fF);
+ fZinsZ = 0.0;
+ if (nAnfang == 1)
+ {
+ if (fF <= 0.0)
+ fZinsZ = -fBw;
+ nAnfang++;
+ }
+ for (ULONG i = nAnfang; i <= nEnde; i++)
+ {
+ if (fF > 0.0)
+ fZinsZ += ScGetZw(fZins, (double)(i-2), fRmz, fBw, 1.0) - fRmz;
+ else
+ fZinsZ += ScGetZw(fZins, (double)(i-1), fRmz, fBw, 0.0);
+ }
+ fZinsZ *= fZins;
+ PushDouble(fZinsZ);
+ }
+ }
+}
+
+void ScInterpreter::ScKumKapZ()
+{
+ nFuncFmtType = NUMBERFORMAT_CURRENCY;
+ if ( MustHaveParamCount( GetByte(), 6 ) )
+ {
+ double fZins, fZzr, fBw, fAnfang, fEnde, fF, fRmz, fKapZ;
+ fF = GetDouble();
+ fEnde = SolarMath::ApproxFloor(GetDouble());
+ fAnfang = SolarMath::ApproxFloor(GetDouble());
+ fBw = GetDouble();
+ fZzr = GetDouble();
+ fZins = GetDouble();
+ if (fAnfang < 1.0 || fEnde < fAnfang || fZins <= 0.0 ||
+ fEnde > fZzr || fZzr <= 0.0 || fBw <= 0.0)
+ SetIllegalParameter();
+ else
+ {
+ fRmz = ScGetRmz(fZins, fZzr, fBw, 0.0, fF);
+ fKapZ = 0.0;
+ ULONG nAnfang = (ULONG) fAnfang;
+ ULONG nEnde = (ULONG) fEnde;
+ if (nAnfang == 1)
+ {
+ if (fF <= 0.0)
+ fKapZ = fRmz + fBw * fZins;
+ else
+ fKapZ = fRmz;
+ nAnfang++;
+ }
+ for (ULONG i = nAnfang; i <= nEnde; i++)
+ {
+ if (fF > 0.0)
+ fKapZ += fRmz - (ScGetZw(fZins, (double)(i-2), fRmz, fBw, 1.0) - fRmz) * fZins;
+ else
+ fKapZ += fRmz - ScGetZw(fZins, (double)(i-1), fRmz, fBw, 0.0) * fZins;
+ }
+ PushDouble(fKapZ);
+ }
+ }
+}
+
+void ScInterpreter::ScEffektiv()
+{
+ nFuncFmtType = NUMBERFORMAT_PERCENT;
+ if ( MustHaveParamCount( GetByte(), 2 ) )
+ {
+ double fPerioden = GetDouble();
+ double fNominal = GetDouble();
+ if (fPerioden < 1.0 || fNominal <= 0.0)
+ SetIllegalParameter();
+ else
+ {
+ fPerioden = SolarMath::ApproxFloor(fPerioden);
+ PushDouble(pow(1.0 + fNominal/fPerioden, fPerioden) - 1.0);
+ }
+ }
+}
+
+void ScInterpreter::ScNominal()
+{
+ nFuncFmtType = NUMBERFORMAT_PERCENT;
+ if ( MustHaveParamCount( GetByte(), 2 ) )
+ {
+ double fPerioden = GetDouble();
+ double fEffektiv = GetDouble();
+ if (fPerioden < 1.0 || fEffektiv <= 0.0)
+ SetIllegalParameter();
+ else
+ {
+ fPerioden = SolarMath::ApproxFloor(fPerioden);
+ PushDouble( (pow(fEffektiv + 1.0, 1.0 / fPerioden) - 1.0) * fPerioden );
+ }
+ }
+}
+
+void ScInterpreter::ScMod()
+{
+ if ( MustHaveParamCount( GetByte(), 2 ) )
+ {
+ double nVal2 = GetDouble();
+ double nVal1 = GetDouble();
+ PushDouble(nVal1 - (SolarMath::ApproxFloor(nVal1 / nVal2) * nVal2));
+ }
+}
+
+void ScInterpreter::ScBackSolver()
+{
+ if ( MustHaveParamCount( GetByte(), 3 ) )
+ {
+ BOOL bRet = FALSE;
+ ScAddress aVAdr, aFAdr;
+ double nVal = GetDouble();
+ PopSingleRef( aFAdr );
+ PopSingleRef( aVAdr );
+ if (nGlobalError == 0)
+ {
+ ScBaseCell* pVCell = GetCell( aVAdr );
+ // CELLTYPE_NOTE: kein Value aber von Formel referiert
+ BOOL bTempCell = (!pVCell || pVCell->GetCellType() == CELLTYPE_NOTE);
+ ScBaseCell* pFCell = GetCell( aFAdr );
+ if ( ((pVCell && pVCell->GetCellType() == CELLTYPE_VALUE) || bTempCell)
+ && pFCell && pFCell->GetCellType() == CELLTYPE_FORMULA )
+ {
+ ScRange aVRange( aVAdr, aVAdr ); // fuer SetDirty
+ double nSaveVal;
+ ScPostIt aNote;
+ BOOL bHasNote;
+ if ( bTempCell )
+ {
+ if ( bHasNote = (pVCell != NULL) )
+ bHasNote = pVCell->GetNote( aNote );
+ nSaveVal = 0.0;
+ pVCell = new ScValueCell( nSaveVal );
+ pDok->PutCell( aVAdr, pVCell );
+ }
+ else
+ nSaveVal = GetCellValue( aVAdr, pVCell );
+ const USHORT nMaxIter = 100;
+ const double nEps = 1E-10;
+ const double nDelta = 1E-3;
+ double nBestX = nSaveVal;
+ double nBestF, xn1, fn1;
+ ScFormulaCell* pFormula = (ScFormulaCell*) pFCell;
+ ScValueCell* pValue = (ScValueCell*) pVCell;
+ pFormula->Interpret();
+ fn1 = pFormula->GetValue();
+ fn1 -= nVal;
+ xn1 = nBestX;
+ nBestF = fabs(fn1);
+ if (nBestF < nDelta)
+ bRet = TRUE;
+ double xn = xn1 + nEps;
+ double fn = fn1;
+ double fs;
+ USHORT i = 0;
+ // Nach der Regula Falsi Methode
+ while (!bRet && (i < nMaxIter))
+ {
+ i++;
+ pValue->SetValue(xn);
+ pDok->SetDirty( aVRange );
+ pFormula->Interpret();
+ fn = pFormula->GetValue();
+ fn -= nVal;
+ if (fabs(fn) < nDelta)
+ {
+ nBestX = xn;
+ bRet = TRUE;
+ }
+ else
+ {
+ if (fabs(fn) + nDelta < nBestF)
+ {
+ nBestX = xn;
+ nBestF = fabs(fn);
+ }
+ if ((xn1 - xn) != 0)
+ {
+ fs = (fn1 - fn) / (xn1 - xn);
+ if (fabs(fs) < nEps)
+ if (fs < 0.0)
+ fs = -nEps;
+ else
+ fs = nEps;
+ }
+ else
+ fs = nEps;
+ xn1 = xn;
+ fn1 = fn;
+ xn = xn - (fn / fs);
+ }
+ }
+ double nX = SolarMath::ApproxFloor((nBestX / nDelta) + 0.5) * nDelta;
+ if ( bRet )
+ {
+ pValue->SetValue( nX );
+ pDok->SetDirty( aVRange );
+ pFormula->Interpret();
+ if ( fabs( pFormula->GetValue() - nVal ) > fabs( fn ) )
+ nX = nBestX;
+ }
+ if ( bTempCell )
+ {
+ if ( bHasNote )
+ pVCell = new ScNoteCell( aNote );
+ else
+ pVCell = NULL;
+ pDok->PutCell( aVAdr, pVCell );
+ }
+ else
+ pValue->SetValue(nSaveVal);
+ pDok->SetDirty( aVRange );
+ pFormula->Interpret();
+ if (!bRet)
+ SetError(NOVALUE);
+ PushDouble(nX);
+ }
+ else
+ {
+ if (!bRet)
+ SetError(NOVALUE);
+ PushInt(0); // falsche Zelltypen
+ }
+ }
+ else
+ {
+ if (!bRet)
+ SetError(NOVALUE);
+ PushInt(0); // nGlobalError
+ }
+ }
+}
+
+void ScInterpreter::ScIntersect()
+{
+ USHORT nCol11, nRow11, nTab11, nCol21, nRow21, nTab21,
+ nCol12, nRow12, nTab12, nCol22, nRow22, nTab22,
+ nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ BYTE eStackVar = GetStackType();
+ if (eStackVar == svDoubleRef)
+ PopDoubleRef(nCol11, nRow11, nTab11, nCol21, nRow21, nTab21);
+ else if (eStackVar == svSingleRef)
+ {
+ PopSingleRef(nCol11, nRow11, nTab11);
+ nCol21 = nCol11;
+ nRow21 = nRow11;
+ nTab21 = nTab11;
+ }
+ else
+ {
+ SetError(errNoRef);
+ PushInt(0);
+ return;
+ }
+ eStackVar = GetStackType();
+ if (eStackVar == svDoubleRef)
+ PopDoubleRef(nCol12, nRow12, nTab12, nCol22, nRow22, nTab22);
+ else if (eStackVar == svSingleRef)
+ {
+ PopSingleRef(nCol12, nRow12, nTab12);
+ nCol22 = nCol12;
+ nRow22 = nRow12;
+ nTab22 = nTab12;
+ }
+ else
+ {
+ SetError(errNoRef);
+ PushInt(0);
+ return;
+ }
+ nCol1 = Max(nCol11, nCol12);
+ nRow1 = Max(nRow11, nRow12);
+ nTab1 = Max(nTab11, nTab12);
+ nCol2 = Min(nCol21, nCol22);
+ nRow2 = Min(nRow21, nRow22);
+ nTab2 = Min(nTab21, nTab22);
+ if (nCol2 < nCol1 || nRow2 < nRow1 || nTab2 < nTab1)
+ {
+ SetError(errNoRef);
+ PushInt(0);
+ }
+ else if (nCol2 == nCol1 && nRow2 == nRow1 && nTab2 == nTab1)
+ PushSingleRef(nCol1, nRow1, nTab1);
+ else
+ PushDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+}
+
+
+void ScInterpreter::ScCurrent()
+{
+ switch ( GetStackType() )
+ {
+ case svDouble :
+ {
+ double nVal = PopDouble();
+ PushDouble( nVal );
+ PushDouble( nVal );
+ }
+ break;
+ case svString :
+ {
+ const sal_Unicode* pStr = PopString();
+ PushString( pStr );
+ PushString( pStr );
+ }
+ break;
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ {
+ PushInt(0);
+ break;
+ }
+ ScBaseCell* pCell = GetCell( aAdr );
+ // NoteCell entsteht auch durch Referenz auf leere Zelle
+ if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE )
+ {
+ if ( HasCellValueData( pCell ) )
+ {
+ double nVal = GetCellValue( aAdr, pCell );
+ PushDouble( nVal );
+ PushDouble( nVal );
+ }
+ else
+ {
+ String aStr;
+ GetCellString( aStr, pCell );
+ PushStringObject( aStr );
+ PushStringObject( aStr );
+ }
+ }
+ else
+ {
+ PushSingleRef( aAdr.Col(), aAdr.Row(), aAdr.Tab() );
+ PushSingleRef( aAdr.Col(), aAdr.Row(), aAdr.Tab() );
+ }
+ }
+ break;
+ default:
+ SetIllegalParameter();
+ }
+}
+
+void ScInterpreter::ScStyle()
+{
+ BYTE nParamCount = GetByte();
+ if (nParamCount >= 1 && nParamCount <= 3)
+ {
+ String aStyle2; // Vorlage nach Timer
+ if (nParamCount >= 3)
+ aStyle2 = GetString();
+ long nTimeOut = 0; // Timeout
+ if (nParamCount >= 2)
+ nTimeOut = (long)(GetDouble()*1000.0);
+ String aStyle1 = GetString(); // Vorlage fuer sofort
+
+ if (nTimeOut < 0)
+ nTimeOut = 0;
+
+ //
+ // Request ausfuehren, um Vorlage anzuwenden
+ //
+
+ if ( !pDok->IsClipOrUndo() )
+ {
+ SfxObjectShell* pShell = pDok->GetDocumentShell();
+ if (pShell)
+ {
+ //! notify object shell directly
+
+ ScRange aRange(aPos);
+ ScAutoStyleHint aHint( aRange, aStyle1, nTimeOut, aStyle2 );
+ pShell->Broadcast( aHint );
+ }
+ }
+
+ PushDouble(0.0);
+ }
+ else
+ SetIllegalParameter();
+}
+
+ScDdeLink* lcl_GetDdeLink( SvLinkManager* pLinkMgr,
+ const String& rA, const String& rT, const String& rI, BYTE nM )
+{
+ USHORT nCount = pLinkMgr->GetLinks().Count();
+ for (USHORT i=0; i<nCount; i++ )
+ {
+ SvBaseLink* pBase = *pLinkMgr->GetLinks()[i];
+ if (pBase->ISA(ScDdeLink))
+ {
+ ScDdeLink* pLink = (ScDdeLink*)pBase;
+ if ( pLink->GetAppl() == rA &&
+ pLink->GetTopic() == rT &&
+ pLink->GetItem() == rI &&
+ pLink->GetMode() == nM )
+ return pLink;
+ }
+ }
+
+ return NULL;
+}
+
+void ScInterpreter::ScDde()
+{
+ // Applikation, Datei, Bereich
+ // Application, Topic, Item
+
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 3, 4 ) )
+ {
+ BYTE nMode = SC_DDE_DEFAULT;
+ if (nParamCount == 4)
+ nMode = (BYTE) SolarMath::ApproxFloor(GetDouble());
+ String aItem = GetString();
+ String aTopic = GetString();
+ String aAppl = GetString();
+
+ if (nMode < SC_DDE_DEFAULT || nMode > SC_DDE_TEXT)
+ nMode = SC_DDE_DEFAULT;
+
+ // Nach dem Laden muss neu interpretiert werden (Verknuepfungen aufbauen)
+
+ if ( pMyFormulaCell->GetCode()->IsRecalcModeNormal() )
+ pMyFormulaCell->GetCode()->SetRecalcModeOnLoad();
+
+ // solange der Link nicht ausgewertet ist, Idle abklemmen
+ // (um zirkulaere Referenzen zu vermeiden)
+
+ BOOL bOldDis = pDok->IsIdleDisabled();
+ pDok->DisableIdle( TRUE );
+
+ // Link-Objekt holen / anlegen
+
+ SvLinkManager* pLinkMgr = pDok->GetLinkManager();
+ ScDdeLink* pLink = lcl_GetDdeLink( pLinkMgr, aAppl, aTopic, aItem, nMode );
+
+ //! Dde-Links (zusaetzlich) effizienter am Dokument speichern !!!!!
+ // ScDdeLink* pLink = pDok->GetDdeLink( aAppl, aTopic, aItem );
+
+ BOOL bWasError = ( pMyFormulaCell->GetCode()->GetError() != 0 );
+
+ if (!pLink)
+ {
+ pLink = new ScDdeLink( pDok, aAppl, aTopic, aItem, nMode );
+ pLinkMgr->InsertDDELink( *pLink, aAppl, aTopic, aItem );
+ if ( pLinkMgr->GetLinks().Count() == 1 ) // erster ?
+ {
+ SfxBindings& rBind = SFX_BINDINGS();
+ rBind.Invalidate( SID_LINKS ); // Link-Manager enablen
+ }
+
+ //! asynchron auswerten ???
+ pLink->TryUpdate(); // TryUpdate ruft Update nicht mehrfach auf
+
+ // StartListening erst nach dem Update, sonst circular reference
+ pMyFormulaCell->StartListening( *pLink, TRUE );
+ }
+ else
+ {
+ if ( !pMyFormulaCell->IsListening( *pLink ) )
+ pMyFormulaCell->StartListening( *pLink, TRUE );
+ }
+
+ // Wenn aus dem Reschedule beim Ausfuehren des Links ein Fehler
+ // (z.B. zirkulaere Referenz) entstanden ist, der vorher nicht da war,
+ // das Fehler-Flag zuruecksetzen:
+
+ if ( pMyFormulaCell->GetCode()->GetError() && !bWasError )
+ pMyFormulaCell->GetCode()->SetError(0);
+
+ // Wert abfragen
+
+ const ScMatrix* pLinkMat = pLink->GetResult();
+ if (pLinkMat)
+ {
+ USHORT nC, nR, nMatInd;
+ pLinkMat->GetDimensions(nC, nR);
+ ScMatrix* pNewMat = GetNewMat( nC, nR, nMatInd );
+ if (pNewMat)
+ {
+ pLinkMat->MatCopy(*pNewMat); // kopieren
+ PushMatrix( pNewMat );
+ nRetMat = nMatInd;
+ }
+ // sonst Fehler schon in GetNewMat gesetzt
+ }
+ else
+ SetNV();
+
+ pDok->DisableIdle( bOldDis );
+ }
+}
+
+void ScInterpreter::ScBase()
+{ // Value, Base [, MinLen]
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 2, 3 ) )
+ {
+ static const sal_Unicode __FAR_DATA pDigits[] = {
+ '0','1','2','3','4','5','6','7','8','9',
+ 'A','B','C','D','E','F','G','H','I','J','K','L','M',
+ 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
+ 0
+ };
+ static const int nDigits = (sizeof(pDigits)/sizeof(sal_Unicode))-1;
+ USHORT nMinLen;
+ if ( nParamCount == 3 )
+ {
+ double fLen = SolarMath::ApproxFloor( GetDouble() );
+ if ( 1 <= fLen && fLen < MAXSTRLEN )
+ nMinLen = (USHORT) fLen;
+ else
+ nMinLen = 0; // Error
+ }
+ else
+ nMinLen = 1;
+ double fBase = SolarMath::ApproxFloor( GetDouble() );
+ double fVal = SolarMath::ApproxFloor( GetDouble() );
+
+ if ( !nGlobalError && nMinLen && 2 <= fBase && fBase <= nDigits && 0 <= fVal )
+ {
+ const size_t nBuf = MAXSTRLEN+1;
+ sal_Unicode pBuf[nBuf];
+ for ( size_t j=0; j<nBuf; j++ )
+ {
+ pBuf[j] = '0';
+ }
+ sal_Unicode* p = pBuf + nBuf - 1;
+ *p = 0;
+ if ( fVal <= (ULONG)(~0) )
+ {
+ ULONG nVal = (ULONG) fVal;
+ ULONG nBase = (ULONG) fBase;
+ while ( nVal && p > pBuf )
+ {
+ *--p = pDigits[ nVal % nBase ];
+ nVal /= nBase;
+ }
+ fVal = (double) nVal;
+ }
+ else
+ {
+ BOOL bDirt = FALSE;
+ while ( fVal && p > pBuf )
+ {
+//! mit fmod Rundungsfehler ab 2**48
+// double fDig = SolarMath::ApproxFloor( fmod( fVal, fBase ) );
+// so ist es etwas besser
+ double fInt = SolarMath::ApproxFloor( fVal / fBase );
+ double fMult = fInt * fBase;
+#ifdef DEBUG
+ // #53943# =BASIS(1e308;36) => GPF mit
+ // nDig = (size_t) SolarMath::ApproxFloor( fVal - fMult );
+ // trotz vorheriger Pruefung ob fVal >= fMult
+ double fDebug1 = fVal - fMult;
+ // fVal := 7,5975311883090e+290
+ // fMult := 7,5975311883090e+290
+ // fDebug1 := 1,3848924157003e+275 <- RoundOff-Error
+ // fVal != fMult, aber: SolarMath::ApproxEqual( fVal, fMult ) == TRUE
+ double fDebug2 = SolarMath::ApproxSub( fVal, fMult );
+ // und SolarMath::ApproxSub( fVal, fMult ) == 0
+ double fDebug3 = ( fInt ? fVal / fInt : 0.0 );
+ // Nach dem strange fDebug1 und fVal < fMult ist eigentlich
+ // fDebug2 == fBase, trotzdem wird das mit einem Vergleich
+ // nicht erkannt, dann schlaegt bDirt zu und alles wird wieder gut..
+#endif
+ size_t nDig;
+ if ( fVal < fMult )
+ { // da ist was gekippt
+ bDirt = TRUE;
+ nDig = 0;
+ }
+ else
+ {
+ double fDig = SolarMath::ApproxFloor( SolarMath::ApproxSub( fVal, fMult ) );
+ if ( bDirt )
+ {
+ bDirt = FALSE;
+ --fDig;
+ }
+ if ( fDig <= 0.0 )
+ nDig = 0;
+ else if ( fDig >= fBase )
+ nDig = ((size_t) fBase) - 1;
+ else
+ nDig = (size_t) fDig;
+ }
+ *--p = pDigits[ nDig ];
+ fVal = fInt;
+ }
+ }
+ if ( fVal )
+ {
+ SetError( errStringOverflow );
+ PushInt(0);
+ }
+ else
+ {
+ if ( nBuf - (p - pBuf) <= nMinLen )
+ p = pBuf + nBuf - 1 - nMinLen;
+ PushString( p );
+ }
+ }
+ else
+ SetIllegalArgument();
+ }
+}
+
+
+void ScInterpreter::ScDecimal()
+{ // Text, Base
+ if ( MustHaveParamCount( GetByte(), 2 ) )
+ {
+ double fBase = SolarMath::ApproxFloor( GetDouble() );
+ String aStr( GetString() );
+ if ( !nGlobalError && 2 <= fBase && fBase <= 36 )
+ {
+ double fVal = 0.0;
+ int nBase = (int) fBase;
+ register const sal_Unicode* p = aStr.GetBuffer();
+ while ( *p == ' ' || *p == '\t' )
+ p++; // strip leading white space
+ if ( nBase == 16 )
+ { // evtl. hex-prefix strippen
+ if ( *p == 'x' || *p == 'X' )
+ p++;
+ else if ( *p == '0' && (*(p+1) == 'x' || *(p+1) == 'X') )
+ p += 2;
+ }
+ while ( *p )
+ {
+ int n;
+ if ( '0' <= *p && *p <= '9' )
+ n = *p - '0';
+ else if ( 'A' <= *p && *p <= 'Z' )
+ n = 10 + (*p - 'A');
+ else if ( 'a' <= *p && *p <= 'z' )
+ n = 10 + (*p - 'a');
+ else
+ n = nBase;
+ if ( nBase <= n )
+ {
+ if ( *(p+1) == 0 &&
+ ( (nBase == 2 && (*p == 'b' || *p == 'B'))
+ ||(nBase == 16 && (*p == 'h' || *p == 'H')) )
+ )
+ ; // 101b und F00Dh sind ok
+ else
+ {
+ SetIllegalArgument();
+ return ;
+ }
+ }
+ else
+ fVal = fVal * fBase + n;
+ p++;
+
+ }
+ PushDouble( fVal );
+ }
+ else
+ SetIllegalArgument();
+ }
+}
+
+
+void ScInterpreter::ScConvert()
+{ // Value, FromUnit, ToUnit
+ if ( MustHaveParamCount( GetByte(), 3 ) )
+ {
+ String aToUnit( GetString() );
+ String aFromUnit( GetString() );
+ double fVal = GetDouble();
+ if ( nGlobalError )
+ SetIllegalArgument();
+ else
+ { // erst die angegebene Reihenfolge suchen, wenn nicht gefunden den Kehrwert
+ double fConv;
+ if ( ScGlobal::GetUnitConverter()->GetValue( fConv, aFromUnit, aToUnit ) )
+ PushDouble( fVal * fConv );
+ else if ( ScGlobal::GetUnitConverter()->GetValue( fConv, aToUnit, aFromUnit ) )
+ PushDouble( fVal / fConv );
+ else
+ SetNV();
+ }
+ }
+}
+
+
+
+
diff --git a/sc/source/core/tool/interpr3.cxx b/sc/source/core/tool/interpr3.cxx
new file mode 100644
index 000000000000..7e1ab2459988
--- /dev/null
+++ b/sc/source/core/tool/interpr3.cxx
@@ -0,0 +1,3970 @@
+/*************************************************************************
+ *
+ * $RCSfile: interpr3.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:17 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <tools/solar.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "interpre.hxx"
+#include "global.hxx"
+#include "compiler.hxx"
+#include "cell.hxx"
+#include "document.hxx"
+#include "dociter.hxx"
+#include "scmatrix.hxx"
+#include "globstr.hrc"
+
+// STATIC DATA -----------------------------------------------------------
+
+#define SCdEpsilon 1.0E-7
+#define SC_MAX_ITERATION_COUNT 20
+#define MAX_ANZ_DOUBLE_FOR_SORT 100000
+// PI jetzt als F_PI aus solar.h
+//#define PI 3.1415926535897932
+
+
+//-----------------------------------------------------------------------------
+// Allgemeine Funktionen
+//-----------------------------------------------------------------------------
+
+void ScInterpreter::ScNoName()
+{
+ SetError(errNoName);
+}
+
+double ScInterpreter::phi(double x)
+{
+ return 0.39894228040143268 * exp(-(x * x) / 2.0);
+}
+
+double ScInterpreter::taylor(double* pPolynom, USHORT nMax, double x)
+{
+ double nVal = pPolynom[nMax];
+ for (short i = nMax-1; i >= 0; i--)
+ {
+ nVal = pPolynom[i] + (nVal * x);
+ }
+ return nVal;
+}
+
+double ScInterpreter::gauss(double x)
+{
+ double t0[] =
+ { 0.39894228040143268, -0.06649038006690545, 0.00997355701003582,
+ -0.00118732821548045, 0.00011543468761616, -0.00000944465625950,
+ 0.00000066596935163, -0.00000004122667415, 0.00000000227352982,
+ 0.00000000011301172, 0.00000000000511243, -0.00000000000021218 };
+ double t2[] =
+ { 0.47724986805182079, 0.05399096651318805, -0.05399096651318805,
+ 0.02699548325659403, -0.00449924720943234, -0.00224962360471617,
+ 0.00134977416282970, -0.00011783742691370, -0.00011515930357476,
+ 0.00003704737285544, 0.00000282690796889, -0.00000354513195524,
+ 0.00000037669563126, 0.00000019202407921, -0.00000005226908590,
+ -0.00000000491799345, 0.00000000366377919, -0.00000000015981997,
+ -0.00000000017381238, 0.00000000002624031, 0.00000000000560919,
+ -0.00000000000172127, -0.00000000000008634, 0.00000000000007894 };
+ double t4[] =
+ { 0.49996832875816688, 0.00013383022576489, -0.00026766045152977,
+ 0.00033457556441221, -0.00028996548915725, 0.00018178605666397,
+ -0.00008252863922168, 0.00002551802519049, -0.00000391665839292,
+ -0.00000074018205222, 0.00000064422023359, -0.00000017370155340,
+ 0.00000000909595465, 0.00000000944943118, -0.00000000329957075,
+ 0.00000000029492075, 0.00000000011874477, -0.00000000004420396,
+ 0.00000000000361422, 0.00000000000143638, -0.00000000000045848 };
+ double asympt[] = { -1.0, 1.0, -3.0, 15.0, -105.0 };
+
+ double xAbs = fabs(x);
+ USHORT xShort = (USHORT)SolarMath::ApproxFloor(xAbs);
+ double nVal = 0.0;
+ if (xShort == 0)
+ nVal = taylor(t0, 11, (xAbs * xAbs)) * xAbs;
+ else if ((xShort >= 1) && (xShort <= 2))
+ nVal = taylor(t2, 23, (xAbs - 2.0));
+ else if ((xShort >= 3) && (xShort <= 4))
+ nVal = taylor(t4, 20, (xAbs - 4.0));
+ else
+ nVal = 0.5 + phi(xAbs) * taylor(asympt, 4, 1.0 / (xAbs * xAbs)) / xAbs;
+ if (x < 0.0)
+ return -nVal;
+ else
+ return nVal;
+}
+
+#if defined(WIN) && defined(MSC)
+#pragma optimize("",off)
+#endif
+
+double ScInterpreter::gaussinv(double x)
+{
+ double c0, c1, c2, d1, d2, d3, q, t, z;
+ c0 = 2.515517;
+ c1 = 0.802853;
+ c2 = 0.010328;
+ d1 = 1.432788;
+ d2 = 0.189269;
+ d3 = 0.001308;
+ if (x < 0.5)
+ q = x;
+ else
+ q = 1.0-x;
+ t = sqrt(-log(q*q));
+ z = t - (c0 + t*(c1 + t*c2)) / (1.0 + t*(d1 + t*(d2 + t*d3)));
+ if (x < 0.5)
+ z *= -1.0;
+ return z;
+}
+#if defined(WIN) && defined(MSC)
+#pragma optimize("",on)
+#endif
+
+double ScInterpreter::Fakultaet(double x)
+{
+ x = SolarMath::ApproxFloor(x);
+ if (x < 0.0)
+ return 0.0;
+ else if (x == 0.0)
+ return 1.0;
+ else if (x <= 170.0)
+ {
+ double fTemp = x;
+ while (fTemp > 2.0)
+ {
+ fTemp--;
+ x *= fTemp;
+ }
+ }
+ else
+ SetError(errNoValue);
+/* // Stirlingsche Naeherung zu ungenau
+ else
+ x = pow(x/exp(1), x) * sqrt(x) * SQRT_2_PI * (1.0 + 1.0 / (12.0 * x));
+*/
+ return x;
+}
+
+double ScInterpreter::BinomKoeff(double n, double k)
+{
+ double nVal = 0.0;
+ k = SolarMath::ApproxFloor(k);
+ if (n < k)
+ nVal = 0.0;
+ else if (k == 0.0)
+ nVal = 1.0;
+ else
+ {
+ nVal = n/k;
+ n--;
+ k--;
+ while (k > 0.0)
+ {
+ nVal *= n/k;
+ k--;
+ n--;
+ }
+/*
+ double f1 = n; // Zaehler
+ double f2 = k; // Nenner
+ n--;
+ k--;
+ while (k > 0.0)
+ {
+ f2 *= k;
+ f1 *= n;
+ k--;
+ n--;
+ }
+ nVal = f1 / f2;
+*/
+ }
+ return nVal;
+}
+
+double ScInterpreter::GammaHelp(double& x, BOOL& bReflect)
+{
+ double c[6] = {76.18009173, -86.50532033, 24.01409822,
+ -1.231739516, 0.120858003E-2, -0.536382E-5};
+ if (x >= 1.0)
+ {
+ bReflect = FALSE;
+ x -= 1.0;
+ }
+ else
+ {
+ bReflect = TRUE;
+ x = 1.0 - x;
+ }
+ double s, anum;
+ s = 1.0;
+ anum = x;
+ for (USHORT i = 0; i < 6; i++)
+ {
+ anum += 1.0;
+ s += c[i]/anum;
+ }
+ s *= 2.506628275; // sqrt(2*PI)
+ return s;
+}
+
+double ScInterpreter::GetGamma(double x)
+{
+ BOOL bReflect;
+ double G = GammaHelp(x, bReflect);
+ G = pow(x+5.5,x+0.5)*G/exp(x+5.5);
+ if (bReflect)
+ G = F_PI*x/(G*sin(F_PI*x));
+ return G;
+}
+
+double ScInterpreter::GetLogGamma(double x)
+{
+ BOOL bReflect;
+ double G = GammaHelp(x, bReflect);
+ G = (x+0.5)*log(x+5.5)+log(G)-(x+5.5);
+ if (bReflect)
+ G = log(F_PI*x)-G-log(sin(F_PI*x));
+ return G;
+}
+
+double ScInterpreter::GetBetaDist(double x, double alpha, double beta)
+{
+ if (beta == 1.0)
+ return pow(x, alpha);
+ else if (alpha == 1.0)
+ return 1.0 - pow(1.0-x,beta);
+ double fEps = 1.0E-8;
+ BOOL bReflect;
+ double cf, fA, fB;
+ if (x < (alpha+1.0)/(alpha+beta+1.0))
+ {
+ bReflect = FALSE;
+ fA = alpha;
+ fB = beta;
+ }
+ else
+ {
+ bReflect = TRUE;
+ fA = beta;
+ fB = alpha;
+ x = 1.0 - x;
+ }
+ if (x < fEps)
+ cf = 0.0;
+ else
+ {
+ double a1, b1, a2, b2, fnorm, rm, apl2m, d2m, d2m1, cfnew;
+ a1 = 1.0; b1 = 1.0;
+ b2 = 1.0 - (fA+fB)*x/(fA+1.0);
+ if (b2 == 0.0)
+ {
+ a2 = b2;
+ fnorm = 1.0;
+ cf = 1.0;
+ }
+ else
+ {
+ a2 = 1.0;
+ fnorm = 1.0/b2;
+ cf = a2*fnorm;
+ }
+ cfnew = 1.0;
+ for (USHORT j = 1; j <= 100; j++)
+ {
+ rm = (double) j;
+ apl2m = fA + 2.0*rm;
+ d2m = rm*(fB-rm)*x/((apl2m-1.0)*apl2m);
+ d2m1 = -(fA+rm)*(fA+fB+rm)*x/(apl2m*(apl2m+1.0));
+ a1 = (a2+d2m*a1)*fnorm;
+ b1 = (b2+d2m*b1)*fnorm;
+ a2 = a1 + d2m1*a2*fnorm;
+ b2 = b1 + d2m1*b2*fnorm;
+ if (b2 != 0.0)
+ {
+ fnorm = 1.0/b2;
+ cfnew = a2*fnorm;
+ if (fabs(cf-cfnew)/cf < fEps)
+ j = 101;
+ else
+ cf = cfnew;
+ }
+ }
+ if (fB < fEps)
+ b1 = 1.0E30;
+ else
+ b1 = exp(GetLogGamma(fA)+GetLogGamma(fB)-GetLogGamma(fA+fB));
+
+ cf *= pow(x, fA)*pow(1.0-x,fB)/(fA*b1);
+ }
+ if (bReflect)
+ return 1.0-cf;
+ else
+ return cf;
+}
+
+double ScInterpreter::GetFDist(double x, double fF1, double fF2)
+{
+ double arg = fF2/(fF2+fF1*x);
+ double alpha = fF2/2.0;
+ double beta = fF1/2.0;
+ return (GetBetaDist(arg, alpha, beta));
+/*
+ double Z = (pow(fF,1.0/3.0)*(1.0-2.0/(9.0*fF2)) - (1.0-2.0/(9.0*fF1))) /
+ sqrt(2.0/(9.0*fF1) + pow(fF,2.0/3.0)*2.0/(9.0*fF2));
+ return (0.5-gauss(Z));
+*/
+}
+
+double ScInterpreter::GetTDist(double T, double fDF)
+{
+ return 0.5 * GetBetaDist(fDF/(fDF+T*T), fDF/2.0, 0.5);
+/*
+ USHORT DF = (USHORT) fDF;
+ double A = T / sqrt(DF);
+ double B = 1.0 + A*A;
+ double R;
+ if (DF == 1)
+ R = 0.5 + atan(A)/F_PI;
+ else if (DF % 2 == 0)
+ {
+ double S0 = A/(2.0 * sqrt(B));
+ double C0 = S0;
+ for (USHORT i = 2; i <= DF-2; i+=2)
+ {
+ C0 *= (1.0 - 1.0/(double)i)/B;
+ S0 += C0;
+ }
+ R = 0.5 + S0;
+ }
+ else
+ {
+ double S1 = A / (B * F_PI);
+ double C1 = S1;
+ for (USHORT i = 3; i <= DF-2; i+=2)
+ {
+ C1 *= (1.0 - 1.0/(double)i)/B;
+ S1 += C1;
+ }
+ R = 0.5 + atan(A)/F_PI + S1;
+ }
+ return 1.0 - R;
+*/
+}
+
+double ScInterpreter::GetChiDist(double fChi, double fDF)
+{
+ return 1.0 - GetGammaDist(fChi/2.0, fDF/2.0, 1.0);
+/*
+ double x = 1.0;
+ for (double i = fDF; i >= 2.0; i -= 2.0)
+ x *= fChi/i;
+ x *= exp(-fChi/2.0);
+ if (fmod(fDF, 2.0) != 0.0)
+ x *= sqrt(2.0*fChi/F_PI);
+ double S = 1.0;
+ double T = 1.0;
+ double G = fDF;
+ BOOL bStop = FALSE;
+ while (!bStop)
+ {
+ G += 2.0;
+ T *= fChi/G;
+ if (T < 1.0E-7)
+ bStop = TRUE;
+ else
+ S += T;
+ }
+ return 1.0 - x*S;
+*/
+}
+
+void ScInterpreter::ScLogGamma()
+{
+ double x = GetDouble();
+ if (x > 0.0)
+ PushDouble(GetLogGamma(x));
+ else
+ SetIllegalArgument();
+}
+
+void ScInterpreter::ScBetaDist()
+{
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 3, 5 ) )
+ return;
+ double fA, fB, alpha, beta, x;
+ if (nParamCount == 5)
+ fB = GetDouble();
+ else
+ fB = 1.0;
+ if (nParamCount >= 4)
+ fA = GetDouble();
+ else
+ fA = 0.0;
+ beta = GetDouble();
+ alpha = GetDouble();
+ x = GetDouble();
+ if (x < fA || x > fB || fA == fB || alpha <= 0.0 || beta <= 0.0)
+ {
+ SetIllegalArgument();
+ return;
+ }
+ x = (x-fA)/(fB-fA); // Skalierung auf (0,1)
+ PushDouble(GetBetaDist(x, alpha, beta));
+}
+
+void ScInterpreter::ScPhi()
+{
+ PushDouble(phi(GetDouble()));
+}
+
+void ScInterpreter::ScGauss()
+{
+ PushDouble(gauss(GetDouble()));
+}
+
+void ScInterpreter::ScFisher()
+{
+ double fVal = GetDouble();
+ if (fabs(fVal) >= 1.0)
+ SetIllegalArgument();
+ else
+ PushDouble(0.5*log((1.0+fVal)/(1.0-fVal)));
+}
+
+void ScInterpreter::ScFisherInv()
+{
+ double fVal = GetDouble();
+ PushDouble((exp(2.0*fVal)-1.0)/(exp(2.0*fVal)+1.0));
+}
+
+void ScInterpreter::ScFact()
+{
+ double nVal = GetDouble();
+ if (nVal < 0.0)
+ SetIllegalArgument();
+ else
+ PushDouble(Fakultaet(nVal));
+}
+
+void ScInterpreter::ScKombin()
+{
+ if ( MustHaveParamCount( GetByte(), 2 ) )
+ {
+ double k = SolarMath::ApproxFloor(GetDouble());
+ double n = SolarMath::ApproxFloor(GetDouble());
+ if (k < 0.0 || n < 0.0 || k > n)
+ SetIllegalArgument();
+ else
+ PushDouble(BinomKoeff(n, k));
+ }
+}
+
+void ScInterpreter::ScKombin2()
+{
+ if ( MustHaveParamCount( GetByte(), 2 ) )
+ {
+ double k = SolarMath::ApproxFloor(GetDouble());
+ double n = SolarMath::ApproxFloor(GetDouble());
+ if (k < 0.0 || n < 0.0 || k > n)
+ SetIllegalArgument();
+ else
+ PushDouble(BinomKoeff(n + k - 1, k));
+ }
+}
+
+void ScInterpreter::ScVariationen()
+{
+ if ( MustHaveParamCount( GetByte(), 2 ) )
+ {
+ double k = SolarMath::ApproxFloor(GetDouble());
+ double n = SolarMath::ApproxFloor(GetDouble());
+ if (n < 0.0 || k < 0.0 || k > n)
+ SetIllegalArgument();
+ else if (k == 0.0)
+ PushInt(1); // (n! / (n - 0)!) == 1
+ else
+ {
+ double nVal = n;
+ for (ULONG i = (ULONG)k-1; i >= 1; i--)
+ nVal *= n-(double)i;
+ PushDouble(nVal);
+ }
+ }
+}
+
+void ScInterpreter::ScVariationen2()
+{
+ if ( MustHaveParamCount( GetByte(), 2 ) )
+ {
+ double k = SolarMath::ApproxFloor(GetDouble());
+ double n = SolarMath::ApproxFloor(GetDouble());
+ if (n < 0.0 || k < 0.0 || k > n)
+ SetIllegalArgument();
+ else
+ PushDouble(pow(n,k));
+ }
+}
+
+void ScInterpreter::ScB()
+{
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 3, 4 ) )
+ return ;
+ if (nParamCount == 3)
+ {
+ double x = SolarMath::ApproxFloor(GetDouble());
+ double p = GetDouble();
+ double n = SolarMath::ApproxFloor(GetDouble());
+ if (n < 0.0 || x < 0.0 || x > n || p < 0.0 || p > 1.0)
+ SetIllegalArgument();
+ else
+ {
+ double q = 1.0 - p;
+ double fFactor = pow(q, n);
+ if (fFactor == 0.0)
+ {
+ fFactor = pow(p, n);
+ if (fFactor == 0.0)
+ SetNoValue();
+ else
+ {
+ ULONG max = (ULONG) (n - x);
+ for (ULONG i = 0; i < max && fFactor > 0.0; i++)
+ fFactor *= (n-i)/(i+1)*q/p;
+ PushDouble(fFactor);
+ }
+ }
+ else
+ {
+ ULONG max = (ULONG) x;
+ for (ULONG i = 0; i < max && fFactor > 0.0; i++)
+ fFactor *= (n-i)/(i+1)*p/q;
+ PushDouble(fFactor);
+ }
+ }
+ }
+ else if (nParamCount == 4)
+ {
+ double xe = GetDouble();
+ double xs = GetDouble();
+ double p = GetDouble();
+ double n = GetDouble();
+// alter Stand 300-SC
+// if ((xs < n) && (xe < n) && (p < 1.0))
+// {
+// double Varianz = sqrt(n * p * (1.0 - p));
+// xs = fabs(xs - (n * p /* / 2.0 STE */ ));
+// xe = fabs(xe - (n * p /* / 2.0 STE */ ));
+//// STE double nVal = gauss((xs + 0.5) / Varianz) + gauss((xe + 0.5) / Varianz);
+// double nVal = fabs(gauss(xs / Varianz) - gauss(xe / Varianz));
+// PushDouble(nVal);
+// }
+ if (xe <= n && xs <= xe &&
+ p < 1.0 && p > 0.0 && n >= 0.0 && xs >= 0.0 )
+ {
+ double q = 1.0 - p;
+ double fFactor = pow(q, n);
+ if (fFactor == 0.0)
+ {
+ fFactor = pow(p, n);
+ if (fFactor == 0.0)
+ SetNoValue();
+ else
+ {
+ double fSum = 0.0;
+ ULONG max;
+ if (xe < (ULONG) n)
+ max = (ULONG) (n-xe)-1;
+ else
+ max = 0;
+ ULONG i;
+ for (i = 0; i < max && fFactor > 0.0; i++)
+ fFactor *= (n-i)/(i+1)*q/p;
+ if (xs < (ULONG) n)
+ max = (ULONG) (n-xs);
+ else
+ fSum = fFactor;
+ for (; i < max && fFactor > 0.0; i++)
+ {
+ fFactor *= (n-i)/(i+1)*q/p;
+ fSum += fFactor;
+ }
+ PushDouble(fSum);
+ }
+ }
+ else
+ {
+ ULONG max;
+ double fSum;
+ if ( (ULONG) xs == 0)
+ {
+ fSum = fFactor;
+ max = 0;
+ }
+ else
+ {
+ max = (ULONG) xs-1;
+ fSum = 0.0;
+ }
+ ULONG i;
+ for (i = 0; i < max && fFactor > 0.0; i++)
+ fFactor *= (n-i)/(i+1)*p/q;
+ if ((ULONG)xe == 0) // beide 0
+ fSum = fFactor;
+ else
+ max = (ULONG) xe;
+ for (; i < max && fFactor > 0.0; i++)
+ {
+ fFactor *= (n-i)/(i+1)*p/q;
+ fSum += fFactor;
+ }
+ PushDouble(fSum);
+ }
+ }
+ else
+ SetIllegalArgument();
+ }
+}
+
+void ScInterpreter::ScBinomDist()
+{
+ if ( MustHaveParamCount( GetByte(), 4 ) )
+ {
+ double kum = GetDouble(); // 0 oder 1
+ double p = GetDouble(); // p
+ double n = SolarMath::ApproxFloor(GetDouble()); // n
+ double x = SolarMath::ApproxFloor(GetDouble()); // x
+ double fFactor, q, fSum;
+ if (n < 0.0 || x < 0.0 || x > n || p < 0.0 || p > 1.0)
+ SetIllegalArgument();
+ else if (kum == 0.0) // Dichte
+ {
+ q = 1.0 - p;
+ fFactor = pow(q, n);
+ if (fFactor == 0.0)
+ {
+ fFactor = pow(p, n);
+ if (fFactor == 0.0)
+ SetNoValue();
+ else
+ {
+ ULONG max = (ULONG) (n - x);
+ for (ULONG i = 0; i < max && fFactor > 0.0; i++)
+ fFactor *= (n-i)/(i+1)*q/p;
+ PushDouble(fFactor);
+ }
+ }
+ else
+ {
+ ULONG max = (ULONG) x;
+ for (ULONG i = 0; i < max && fFactor > 0.0; i++)
+ fFactor *= (n-i)/(i+1)*p/q;
+ PushDouble(fFactor);
+ }
+ }
+ else // Verteilung
+ {
+ if (n == x)
+ PushDouble(1.0);
+ else
+ {
+ q = 1.0 - p;
+ fFactor = pow(q, n);
+ if (fFactor == 0.0)
+ {
+ fFactor = pow(p, n);
+ if (fFactor == 0.0)
+ SetNoValue();
+ else
+ {
+ fSum = 1.0 - fFactor;
+ ULONG max = (ULONG) (n - x) - 1;
+ for (ULONG i = 0; i < max && fFactor > 0.0; i++)
+ {
+ fFactor *= (n-i)/(i+1)*q/p;
+ fSum -= fFactor;
+ }
+ if (fSum < 0.0)
+ PushDouble(0.0);
+ else
+ PushDouble(fSum);
+ }
+ }
+ else
+ {
+ double fSum = fFactor;
+ ULONG max = (ULONG) x;
+ for (ULONG i = 0; i < max && fFactor > 0.0; i++)
+ {
+ fFactor *= (n-i)/(i+1)*p/q;
+ fSum += fFactor;
+ }
+ PushDouble(fSum);
+ }
+ }
+ }
+ }
+}
+
+void ScInterpreter::ScCritBinom()
+{
+ if ( MustHaveParamCount( GetByte(), 3 ) )
+ {
+ double alpha = GetDouble(); // alpha
+ double p = GetDouble(); // p
+ double n = SolarMath::ApproxFloor(GetDouble());
+ if (n < 0.0 || alpha <= 0.0 || alpha >= 1.0 || p < 0.0 || p > 1.0)
+ SetIllegalArgument();
+ else
+ {
+ double q = 1.0 - p;
+ double fFactor = pow(q,n);
+ if (fFactor == 0.0)
+ {
+ fFactor = pow(p, n);
+ if (fFactor == 0.0)
+ SetNoValue();
+ else
+ {
+ double fSum = 1.0 - fFactor; ULONG max = (ULONG) n;
+ for (ULONG i = 0; i < max && fSum >= alpha; i++)
+ {
+ fFactor *= (n-i)/(i+1)*q/p;
+ fSum -= fFactor;
+ }
+ PushDouble(n-i);
+ }
+ }
+ else
+ {
+ double fSum = fFactor; ULONG max = (ULONG) n;
+ for (ULONG i = 0; i < max && fSum < alpha; i++)
+ {
+ fFactor *= (n-i)/(i+1)*p/q;
+ fSum += fFactor;
+ }
+ PushDouble(i);
+ }
+ }
+ }
+}
+
+void ScInterpreter::ScNegBinomDist()
+{
+ if ( MustHaveParamCount( GetByte(), 3 ) )
+ {
+ double p = GetDouble(); // p
+ double r = GetDouble(); // r
+ double x = GetDouble(); // x
+ if (r < 0.0 || x < 0.0 || p < 0.0 || p > 1.0)
+ SetIllegalArgument();
+ else
+ {
+ double q = 1.0 - p;
+ double fFactor = pow(p,r);
+ for (double i = 0.0; i < x; i++)
+ fFactor *= (i+r)/(i+1.0)*q;
+ PushDouble(fFactor);
+ }
+ }
+}
+
+void ScInterpreter::ScNormDist()
+{
+ if ( MustHaveParamCount( GetByte(), 4 ) )
+ {
+ double kum = GetDouble(); // 0 oder 1
+ double sigma = GetDouble(); // Stdabw
+ double mue = GetDouble(); // Mittelwert
+ double x = GetDouble(); // x
+ if (sigma <= 0.0)
+ SetIllegalArgument();
+ else if (kum == 0.0) // Dichte
+ PushDouble(phi((x-mue)/sigma)/sigma);
+ else // Verteilung
+ PushDouble(0.5 + gauss((x-mue)/sigma));
+ }
+}
+
+void ScInterpreter::ScLogNormDist()
+{
+ if ( MustHaveParamCount( GetByte(), 3 ) )
+ {
+ double sigma = GetDouble(); // Stdabw
+ double mue = GetDouble(); // Mittelwert
+ double x = GetDouble(); // x
+ if (sigma <= 0.0 || x <= 0.0)
+ SetIllegalArgument();
+ else
+ PushDouble(0.5 + gauss((log(x)-mue)/sigma));
+ }
+}
+
+void ScInterpreter::ScStdNormDist()
+{
+ PushDouble(0.5 + gauss(GetDouble()));
+}
+
+void ScInterpreter::ScExpDist()
+{
+ if ( MustHaveParamCount( GetByte(), 3 ) )
+ {
+ double kum = GetDouble(); // 0 oder 1
+ double lambda = GetDouble(); // lambda
+ double x = GetDouble(); // x
+ if (lambda <= 0.0)
+ SetIllegalArgument();
+ else if (kum == 0.0) // Dichte
+ {
+ if (x >= 0.0)
+ PushDouble(lambda * exp(-lambda*x));
+ else
+ PushInt(0);
+ }
+ else // Verteilung
+ {
+ if (x > 0.0)
+ PushDouble(1.0 - exp(-lambda*x));
+ else
+ PushInt(0);
+ }
+ }
+}
+
+void ScInterpreter::ScTDist()
+{
+ if ( !MustHaveParamCount( GetByte(), 3 ) )
+ return;
+ double fFlag = SolarMath::ApproxFloor(GetDouble());
+ double fDF = SolarMath::ApproxFloor(GetDouble());
+ double T = GetDouble();
+ if (fDF < 1.0 || T < 0.0 || (fFlag != 1.0 && fFlag != 2.0) )
+ {
+ SetIllegalArgument();
+ return;
+ }
+ double R = GetTDist(T, fDF);
+ if (fFlag == 1.0)
+ PushDouble(R);
+ else
+ PushDouble(2.0*R);
+}
+
+void ScInterpreter::ScFDist()
+{
+ if ( !MustHaveParamCount( GetByte(), 3 ) )
+ return;
+ double fF2 = SolarMath::ApproxFloor(GetDouble());
+ double fF1 = SolarMath::ApproxFloor(GetDouble());
+ double fF = GetDouble();
+ if (fF < 0.0 || fF1 < 1.0 || fF2 < 1.0 || fF1 >= 1.0E10 || fF2 >= 1.0E10)
+ {
+ SetIllegalArgument();
+ return;
+ }
+ PushDouble(GetFDist(fF, fF1, fF2));
+}
+
+void ScInterpreter::ScChiDist()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+ double fDF = SolarMath::ApproxFloor(GetDouble());
+ double fChi = GetDouble();
+ if (fDF < 1.0 || fDF >= 1.0E5 || fChi < 0.0 )
+ {
+ SetIllegalArgument();
+ return;
+ }
+ PushDouble(GetChiDist(fChi, fDF));
+}
+
+void ScInterpreter::ScWeibull()
+{
+ if ( MustHaveParamCount( GetByte(), 4 ) )
+ {
+ double kum = GetDouble(); // 0 oder 1
+ double beta = GetDouble(); // beta
+ double alpha = GetDouble(); // alpha
+ double x = GetDouble(); // x
+ if (alpha <= 0.0 || beta <= 0.0 || x < 0.0)
+ SetIllegalArgument();
+ else if (kum == 0.0) // Dichte
+ PushDouble(alpha/pow(beta,alpha)*pow(x,alpha-1.0)*
+ exp(-pow(x/beta,alpha)));
+ else // Verteilung
+ PushDouble(1.0 - exp(-pow(x/beta,alpha)));
+ }
+}
+
+void ScInterpreter::ScPoissonDist()
+{
+ if ( MustHaveParamCount( GetByte(), 3 ) )
+ {
+ double kum = GetDouble(); // 0 oder 1
+ double lambda = GetDouble(); // Mittelwert
+ double x = SolarMath::ApproxFloor(GetDouble()); // x
+ if (lambda < 0.0 || x < 0.0)
+ SetIllegalArgument();
+ else if (kum == 0.0) // Dichte
+ {
+ if (lambda == 0.0)
+ PushInt(0);
+ else
+ PushDouble(exp(-lambda)*pow(lambda,x)/Fakultaet(x));
+ }
+ else // Verteilung
+ {
+ if (lambda == 0.0)
+ PushInt(1);
+ else
+ {
+ double sum = 1.0;
+ double fFak = 1.0;
+ ULONG nEnd = (ULONG) x;
+ for (ULONG i = 1; i <= nEnd; i++)
+ {
+ fFak *= (double)i;
+ sum += pow( lambda, (double)i ) / fFak;
+ }
+ sum *= exp(-lambda);
+ PushDouble(sum);
+ }
+ }
+ }
+}
+
+void ScInterpreter::ScHypGeomDist()
+{
+ if ( MustHaveParamCount( GetByte(), 4 ) )
+ {
+ double N = SolarMath::ApproxFloor(GetDouble());
+ double M = SolarMath::ApproxFloor(GetDouble());
+ double n = SolarMath::ApproxFloor(GetDouble());
+ double x = SolarMath::ApproxFloor(GetDouble());
+
+ if( (x < 0.0) || (n < x) || (M < x) || (N < n) || (N < M) || (x < n - N + M) )
+ {
+ SetIllegalArgument();
+ return;
+ }
+ double fFactor =
+ BinomKoeff( n, x ) / BinomKoeff( N, M ) * BinomKoeff( N - n, M - x );
+
+/*
+ double fFactor;
+ if (x == n - N + M)
+ fFactor = BinomKoeff(M,x)/BinomKoeff(N,n);
+ else
+ {
+ double fIndex = N - M - n;
+ if (fIndex >= 0.0)
+ {
+ fFactor = BinomKoeff(N-M,n)/BinomKoeff(N,n);
+ for (double i = 0; i < x; i++)
+ fFactor *= (M-i)*(n-i)/((i+1.0)*(N-M-n+i+1.0));
+ }
+ else
+ {
+ fFactor = BinomKoeff(M,-fIndex)/BinomKoeff(N,n);
+ for (double i = -fIndex + 1.0; i < x; i++)
+ fFactor *= (M-i)*(n-i)/((i+1)*(N-M-n+i+1.0));
+ }
+ }
+*/
+ PushDouble(fFactor);
+ }
+}
+
+void ScInterpreter::ScGammaDist()
+{
+ if ( !MustHaveParamCount( GetByte(), 4 ) )
+ return;
+ double kum = GetDouble(); // 0 oder 1
+ double beta = GetDouble();
+ double alpha = GetDouble();
+ double x = GetDouble(); // x
+ if (x < 0.0 || alpha <= 0.0 || beta <= 0.0)
+ SetIllegalArgument();
+ else if (kum == 0.0) // Dichte
+ {
+ double G = GetGamma(alpha);
+ PushDouble(pow(x,alpha-1.0)/exp(x/beta)/pow(beta,alpha)/G);
+ }
+ else // Verteilung
+ PushDouble(GetGammaDist(x, alpha, beta));
+}
+
+void ScInterpreter::ScNormInv()
+{
+ if ( MustHaveParamCount( GetByte(), 3 ) )
+ {
+ double sigma = GetDouble();
+ double mue = GetDouble();
+ double x = GetDouble();
+ if (sigma <= 0.0 || x < 0.0 || x > 1.0)
+ SetIllegalArgument();
+ else if (x == 0.0 || x == 1.0)
+ SetNoValue();
+ else
+ PushDouble(gaussinv(x)*sigma + mue);
+ }
+}
+
+void ScInterpreter::ScSNormInv()
+{
+ double x = GetDouble();
+ if (x < 0.0 || x > 1.0)
+ SetIllegalArgument();
+ else if (x == 0.0 || x == 1.0)
+ SetNoValue();
+ else
+ PushDouble(gaussinv(x));
+}
+
+void ScInterpreter::ScLogNormInv()
+{
+ if ( MustHaveParamCount( GetByte(), 3 ) )
+ {
+ double sigma = GetDouble(); // Stdabw
+ double mue = GetDouble(); // Mittelwert
+ double y = GetDouble(); // y
+ if (sigma <= 0.0 || y <= 0.0 || y >= 1.0)
+ SetIllegalArgument();
+ else
+ PushDouble(exp(mue+sigma*gaussinv(y)));
+ }
+}
+
+void ScInterpreter::ScGammaInv()
+{
+ if ( !MustHaveParamCount( GetByte(), 3 ) )
+ return;
+ double fBeta = GetDouble();
+ double fAlpha = GetDouble();
+ double fP = GetDouble();
+ if (fAlpha <= 0.0 || fBeta <= 0.0 || fP < 0.0 || fP >= 1.0 )
+ {
+ SetIllegalArgument();
+ return;
+ }
+ if (fP == 0.0)
+ PushInt(0);
+ else
+ {
+ double x0, x1, f0, f1, xs;
+ double fEps = 1.0E-7;
+ USHORT i;
+ x1 = fAlpha; // Einschachteln:
+ x0 = x1*0.5;
+ f0 = fP - GetGammaDist(x0, fAlpha, fBeta);
+ f1 = fP - GetGammaDist(x1, fAlpha, fBeta);
+ for (i = 0; i < 1000 && f0*f1 > 0.0; i++)
+ {
+ if (fabs(f0) < fabs(f1))
+ {
+ xs = x0;
+ x0 += 2.0 * (x0 - x1);
+ if (x0 < 0.0)
+ x0 = 0.0;
+ x1 = xs;
+ f1 = f0;
+ f0 = fP - GetGammaDist(x0, fAlpha, fBeta);
+ }
+ else
+ {
+ xs = x1;
+ x1 += 2.0 * (x1 - x0);
+ x0 = xs;
+ f0 = f1;
+ f1 = fP - GetGammaDist(x1, fAlpha, fBeta);
+ }
+ }
+ // Regula Falsi:
+ double x00 = x0;
+ double x11 = x1;
+ for (i = 0; i < 100 && fabs(x1-x0) > fEps; i++)
+ {
+ xs = (f1-f0)/(x1-x0);
+ x0 = x1;
+ f0 = f1;
+ x1 -= f1/xs;
+ if (x1 < x00)
+ x1 = x00;
+ else if (x1 > x11)
+ x1 = x11;
+ f1 = fP - GetGammaDist(x1, fAlpha, fBeta);
+ }
+ if (i >= 100)
+ {
+ SetError(errNoConvergence);
+ PushInt(0);
+ }
+ else
+ PushDouble(x1);
+ }
+}
+
+void ScInterpreter::ScBetaInv()
+{
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 3, 5 ) )
+ return;
+ double fP, fA, fB, fAlpha, fBeta;
+ if (nParamCount == 5)
+ fB = GetDouble();
+ else
+ fB = 1.0;
+ if (nParamCount >= 4)
+ fA = GetDouble();
+ else
+ fA = 0.0;
+ fBeta = GetDouble();
+ fAlpha = GetDouble();
+ fP = GetDouble();
+ if (fP < 0.0 || fP >= 1.0 || fA == fB || fAlpha <= 0.0 || fBeta <= 0.0)
+ {
+ SetIllegalArgument();
+ return;
+ }
+ if (fP == 0.0)
+ PushInt(0);
+ else
+ {
+ double x0, x1, f0, f1, xs;
+ double fEps = 1.0E-7;
+ USHORT i;
+ x1 = 0.75; // Einschachteln:
+ x0 = 0.25;
+ f0 = fP - GetBetaDist(x0, fAlpha, fBeta);
+ f1 = fP - GetBetaDist(x1, fAlpha, fBeta);
+ for (i = 0; i < 1000 && f0*f1 > 0.0; i++)
+ {
+ if (fabs(f0) < fabs(f1))
+ {
+ xs = x0;
+ x0 += 2.0 * (x0 - x1);
+ if (x0 < 0.0)
+ x0 = 0.0;
+ x1 = xs;
+ f1 = f0;
+ f0 = fP - GetBetaDist(x0, fAlpha, fBeta);
+ }
+ else
+ {
+ xs = x1;
+ x1 += 2.0 * (x1 - x0);
+ x0 = xs;
+ f0 = f1;
+ f1 = fP - GetBetaDist(x1, fAlpha, fBeta);
+ }
+ }
+ // Regula Falsi:
+ double x00 = x0;
+ double x11 = x1;
+ for (i = 0; i < 100 && fabs(x1-x0) > fEps; i++)
+ {
+ xs = (f1-f0)/(x1-x0);
+ x0 = x1;
+ f0 = f1;
+ x1 -= f1/xs;
+ if (x1 < x00)
+ x1 = x00;
+ else if (x1 > x11)
+ x1 = x11;
+ f1 = fP - GetBetaDist(x1, fAlpha, fBeta);
+ }
+ if (i >= 100)
+ {
+ SetError(errNoConvergence);
+ PushInt(0);
+ }
+ else
+ PushDouble(fA + x1*(fB-fA)); // Skalierung auf (A,B)
+ }
+}
+ // Achtung: T, F und Chi
+ // sind monoton fallend,
+ // deshalb 1-Dist als Funktion
+
+#if defined(WIN) && defined(MSC)
+#pragma optimize("",off)
+#endif
+
+void ScInterpreter::ScTInv()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+ double fDF = SolarMath::ApproxFloor(GetDouble());
+ double fP = GetDouble();
+ if (fDF < 1.0 || fDF >= 1.0E5 || fP <= 0.0 || fP > 1.0 )
+ {
+ SetIllegalArgument();
+ return;
+ }
+ double x0, x1, f0, f1, xs;
+ double fEps = 1.0E-7;
+ USHORT i;
+ x1 = fDF; // Einschachteln:
+ x0 = x1*0.5;
+ f0 = fP - 2*GetTDist(x0, fDF);
+ f1 = fP - 2*GetTDist(x1, fDF);
+ for (i = 0; i < 1000 && f0*f1 > 0.0; i++)
+ {
+ if (fabs(f0) <= fabs(f1))
+ {
+ xs = x0;
+ x0 += 2.0 * (x0 - x1);
+ if (x0 < 0.0)
+ x0 = 0.0;
+ x1 = xs;
+ f1 = f0;
+ f0 = fP - 2*GetTDist(x0, fDF);
+ }
+ else
+ {
+ xs = x1;
+ x1 += 2.0 * (x1 - x0);
+ x0 = xs;
+ f0 = f1;
+ f1 = fP - 2*GetTDist(x1, fDF);
+ }
+ }
+ // Regula Falsi:
+ double x00 = x0;
+ double x11 = x1;
+ double f00 = f0;
+ for (i = 0; i < 100 && fabs(x1-x0) > fEps; i++)
+ {
+ xs = (f1-f0)/(x1-x0);
+ if (xs == 0.0)
+ {
+ x0 = x00;
+ f0 = f00;
+ }
+ else
+ {
+ x0 = x1;
+ f0 = f1;
+ x1 -= f1/xs;
+ if (x1 < x00)
+ x1 = x00;
+ else if (x1 > x11)
+ x1 = x11;
+ f1 = fP - 2*GetTDist(x1, fDF);
+ }
+ }
+ if (i >= 100)
+ {
+ SetError(errNoConvergence);
+ PushInt(0);
+ }
+ else
+ PushDouble(x1);
+}
+#if defined(WIN) && defined(MSC)
+#pragma optimize("",on)
+#endif
+
+void ScInterpreter::ScFInv()
+{
+ if ( !MustHaveParamCount( GetByte(), 3 ) )
+ return;
+ double fF2 = SolarMath::ApproxFloor(GetDouble());
+ double fF1 = SolarMath::ApproxFloor(GetDouble());
+ double fP = GetDouble();
+ if (fP <= 0.0 || fF1 < 1.0 || fF2 < 1.0 || fF1 >= 1.0E10 || fF2 >= 1.0E10 || fP > 1.0)
+ {
+ SetIllegalArgument();
+ return;
+ }
+ double x0, x1, f0, f1, xs;
+ double fEps = 1.0E-7;
+ USHORT i;
+ x1 = fF1; // Einschachteln:
+ x0 = x1*0.5;
+ f0 = fP - GetFDist(x0, fF1, fF2);
+ f1 = fP - GetFDist(x1, fF1, fF2);
+ for (i = 0; i < 1000 && f0*f1 > 0.0; i++)
+ {
+ if (fabs(f0) <= fabs(f1))
+ {
+ xs = x0;
+ x0 += 2.0 * (x0 - x1);
+ if (x0 < 0.0)
+ x0 = 0.0;
+ x1 = xs;
+ f1 = f0;
+ f0 = fP - GetFDist(x0, fF1, fF2);
+ }
+ else
+ {
+ xs = x1;
+ x1 += 2.0 * (x1 - x0);
+ x0 = xs;
+ f0 = f1;
+ f1 = fP - GetFDist(x1, fF1, fF2);
+ }
+ }
+ // Regula Falsi:
+ double x00 = x0;
+ double x11 = x1;
+ double f00 = f0;
+ for (i = 0; i < 100 && fabs(x1-x0) > fEps; i++)
+ {
+ xs = (f1-f0)/(x1-x0);
+ if (xs == 0.0)
+ {
+ x0 = x00;
+ f0 = f00;
+ }
+ else
+ {
+ x0 = x1;
+ f0 = f1;
+ x1 -= f1/xs;
+ if (x1 < x00)
+ x1 = x00;
+ else if (x1 > x11)
+ x1 = x11;
+ f1 = fP - GetFDist(x1, fF1, fF2);
+ }
+/*
+ x0 = x1;
+ f0 = f1;
+ x1 -= f1/xs;
+ if (x1 < x00)
+ x1 = x00;
+ else if (x1 > x11)
+ x1 = x11;
+ f1 = fP - GetFDist(x1, fF1, fF2);
+*/
+ }
+ if (i >= 100)
+ {
+ SetError(errNoConvergence);
+ PushInt(0);
+ }
+ else
+ PushDouble(x1);
+}
+
+void ScInterpreter::ScChiInv()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+ double fDF = SolarMath::ApproxFloor(GetDouble());
+ double fP = GetDouble();
+ if (fDF < 1.0 || fDF >= 1.0E5 || fP <= 0.0 || fP > 1.0 )
+ {
+ SetIllegalArgument();
+ return;
+ }
+ double x0, x1, f0, f1, xs;
+ double fEps = 1.0E-7;
+ USHORT i;
+ x1 = fDF; // Einschachteln:
+ x0 = x1*0.5;
+ f0 = fP - GetChiDist(x0, fDF);
+ f1 = fP - GetChiDist(x1, fDF);
+ for (i = 0; i < 1000 && f0*f1 > 0.0; i++)
+ {
+ if (fabs(f0) <= fabs(f1))
+ {
+ xs = x0;
+ x0 += 2.0 * (x0 - x1);
+ if (x0 < 0.0)
+ x0 = 0.0;
+ x1 = xs;
+ f1 = f0;
+ f0 = fP - GetChiDist(x0, fDF);
+ }
+ else
+ {
+ xs = x1;
+ x1 += 2.0 * (x1 - x0);
+ x0 = xs;
+ f0 = f1;
+ f1 = fP - GetChiDist(x1, fDF);
+ }
+ }
+ // Regula Falsi:
+ double x00 = x0;
+ double x11 = x1;
+ double f00 = f0;
+ for (i = 0; i < 100 && fabs(x1-x0) > fEps; i++)
+ {
+ xs = (f1-f0)/(x1-x0);
+ if (xs == 0.0)
+ {
+ x0 = x00;
+ f0 = f00;
+ }
+ else
+ {
+ x0 = x1;
+ f0 = f1;
+ x1 -= f1/xs;
+ if (x1 < x00)
+ x1 = x00;
+ else if (x1 > x11)
+ x1 = x11;
+ f1 = fP - GetChiDist(x1, fDF);
+ }
+/*
+ x0 = x1;
+ f0 = f1;
+ x1 -= f1/xs;
+ if (x1 < x00)
+ x1 = x00;
+ else if (x1 > x11)
+ x1 = x11;
+ f1 = fP - GetChiDist(x1, fDF);
+*/
+ }
+ if (i >= 100)
+ {
+ SetError(errNoConvergence);
+ PushInt(0);
+ }
+ else
+ PushDouble(x1);
+}
+
+/********************************************************/
+/* // Halbierung statt Regula Falsi
+ if (f0 == 0.0)
+ {
+ PushDouble(x0);
+ return;
+ }
+ if (f1 == 0.0)
+ {
+ PushDouble(x1);
+ return;
+ }
+ double fs;
+ for (i = 0; i < 100; i++)
+ {
+ xs = 0.5*(x0+x1);
+ if (fabs(f1-f0) >= fEps)
+ {
+ fs = fP - GetChiDist(xs, fDF);
+ if (f0*fs < 0.0)
+ {
+ x1 = xs;
+ f1 = fs;
+ }
+ else
+ {
+ x0 = xs;
+ f0 = fs;
+ }
+ }
+ else
+ {
+ PushDouble(xs);
+ return;
+ }
+ }
+*/
+/***********************************************/
+
+void ScInterpreter::ScConfidence()
+{
+ if ( MustHaveParamCount( GetByte(), 3 ) )
+ {
+ double n = SolarMath::ApproxFloor(GetDouble());
+ double sigma = GetDouble();
+ double alpha = GetDouble();
+ if (sigma <= 0.0 || alpha <= 0.0 || alpha >= 1.0 || n < 1.0)
+ SetIllegalArgument();
+ else
+ PushDouble( gaussinv(1.0-alpha/2.0) * sigma/sqrt(n) );
+ }
+}
+
+void ScInterpreter::ScZTest()
+{
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
+ return;
+ double sigma, mue, x;
+ if (nParamCount == 3)
+ {
+ sigma = GetDouble();
+ if (sigma <= 0.0)
+ {
+ SetIllegalArgument();
+ return;
+ }
+ }
+ x = GetDouble();
+
+ double fSum = 0.0;
+ double fSumSqr = 0.0;
+ double fVal;
+ double rValCount = 0.0;
+ switch (GetStackType())
+ {
+ case svDouble :
+ {
+ fVal = GetDouble();
+ fSum += fVal;
+ fSumSqr += fVal*fVal;
+ rValCount++;
+ }
+ break;
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ PopSingleRef( aAdr );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ {
+ fVal = GetCellValue( aAdr, pCell );
+ fSum += fVal;
+ fSumSqr += fVal*fVal;
+ rValCount++;
+ }
+ }
+ break;
+ case svDoubleRef :
+ {
+ ScRange aRange;
+ USHORT nErr = 0;
+ PopDoubleRef( aRange );
+ ScValueIterator aValIter(pDok, aRange, glSubTotal);
+ if (aValIter.GetFirst(fVal, nErr))
+ {
+ fSum += fVal;
+ fSumSqr += fVal*fVal;
+ rValCount++;
+ while ((nErr == 0) && aValIter.GetNext(fVal, nErr))
+ {
+ fSum += fVal;
+ fSumSqr += fVal*fVal;
+ rValCount++;
+ }
+ SetError(nErr);
+ }
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ if (pMat->IsNumeric())
+ {
+ for (USHORT i = 0; i < nC*nR; i++)
+ {
+ fVal= pMat->GetDouble(i);
+ fSum += fVal;
+ fSumSqr += fVal * fVal;
+ rValCount++;
+ }
+ }
+ else
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ if (!pMat->IsString(i,j))
+ {
+ fVal= pMat->GetDouble(i,j);
+ fSum += fVal;
+ fSumSqr += fVal * fVal;
+ rValCount++;
+ }
+ }
+ }
+ }
+ break;
+ default : SetError(errIllegalParameter); break;
+ }
+ if (rValCount <= 1.0)
+ SetNoValue();
+ else
+ {
+ mue = fSum/rValCount;
+ if (nParamCount != 3)
+ sigma = (fSumSqr - fSum*fSum/rValCount)/(rValCount-1.0);
+
+ PushDouble(0.5 - gauss((mue-x)/sqrt(sigma/rValCount)));
+ }
+}
+
+void ScInterpreter::ScTTest()
+{
+ if ( !MustHaveParamCount( GetByte(), 4 ) )
+ return;
+ double fTyp = SolarMath::ApproxFloor(GetDouble());
+ double fAnz = SolarMath::ApproxFloor(GetDouble());
+ if (fAnz != 1.0 && fAnz != 2.0)
+ {
+ SetIllegalArgument();
+ return;
+ }
+
+ USHORT nMatInd1, nMatInd2;
+ ScMatrix* pMat2 = GetMatrix(nMatInd2);
+ ScMatrix* pMat1 = GetMatrix(nMatInd1);
+ if (!pMat1 || !pMat2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ double fT, fF;
+ USHORT nC1, nR1, nC2, nR2, i, j;
+ pMat1->GetDimensions(nC1, nR1);
+ pMat2->GetDimensions(nC2, nR2);
+ if (fTyp == 1.0)
+ {
+ if (nC1 != nC2 || nR1 != nR2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ double fCount = 0.0;
+ double fSum1 = 0.0;
+ double fSum2 = 0.0;
+ double fSumSqrD = 0.0;
+ double fVal1, fVal2;
+ for (i = 0; i < nC1; i++)
+ for (j = 0; j < nR1; j++)
+ {
+ if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
+ {
+ fVal1 = pMat1->GetDouble(i,j);
+ fVal2 = pMat2->GetDouble(i,j);
+ fSum1 += fVal1;
+ fSum2 += fVal2;
+ fSumSqrD += (fVal1 - fVal2)*(fVal1 - fVal2);
+ fCount++;
+ }
+ }
+ if (fCount < 1.0)
+ {
+ SetNoValue();
+ return;
+ }
+ fT = sqrt(fCount-1.0) * fabs(fSum1 - fSum2) /
+ sqrt(fCount * fSumSqrD - (fSum1-fSum2)*(fSum1-fSum2));
+ fF = fCount - 1.0;
+ }
+ else if (fTyp == 2.0)
+ {
+ double fCount1 = 0.0;
+ double fCount2 = 0.0;
+ double fSum1 = 0.0;
+ double fSumSqr1 = 0.0;
+ double fSum2 = 0.0;
+ double fSumSqr2 = 0.0;
+ double fVal;
+ for (i = 0; i < nC1; i++)
+ for (j = 0; j < nR1; j++)
+ {
+ if (!pMat1->IsString(i,j))
+ {
+ fVal = pMat1->GetDouble(i,j);
+ fSum1 += fVal;
+ fSumSqr1 += fVal * fVal;
+ fCount1++;
+ }
+ }
+ for (i = 0; i < nC2; i++)
+ for (j = 0; j < nR2; j++)
+ {
+ if (!pMat2->IsString(i,j))
+ {
+ fVal = pMat2->GetDouble(i,j);
+ fSum2 += fVal;
+ fSumSqr2 += fVal * fVal;
+ fCount2++;
+ }
+ }
+ if (fCount1 < 2.0 || fCount2 < 2.0)
+ {
+ SetNoValue();
+ return;
+ }
+#if 0
+ // alter Templin-Code
+ double fS1 = (fSumSqr1-fSum1*fSum1/fCount1)/(fCount1-1.0)/fCount1;
+ double fS2 = (fSumSqr2-fSum2*fSum2/fCount2)/(fCount2-1.0)/fCount2;
+ if (fS1 + fS2 == 0.0)
+ {
+ SetNoValue();
+ return;
+ }
+ fT = fabs(fSum1/fCount1 - fSum2/fCount2)/sqrt(fS1+fS2);
+ fF = fCount1 + fCount2 - 2;
+#else
+ // laut Bronstein-Semendjajew
+ double fS1 = (fSumSqr1 - fSum1*fSum1/fCount1) / (fCount1 - 1.0); // Varianz
+ double fS2 = (fSumSqr2 - fSum2*fSum2/fCount2) / (fCount2 - 1.0);
+ fT = fabs( fSum1/fCount1 - fSum2/fCount2 ) /
+ sqrt( (fCount1-1.0)*fS1 + (fCount2-1.0)*fS2 ) *
+ sqrt( fCount1*fCount2*(fCount1+fCount2-2)/(fCount1+fCount2) );
+ fF = fCount1 + fCount2 - 2;
+#endif
+ }
+ else if (fTyp == 3.0)
+ {
+ double fCount1 = 0.0;
+ double fCount2 = 0.0;
+ double fSum1 = 0.0;
+ double fSumSqr1 = 0.0;
+ double fSum2 = 0.0;
+ double fSumSqr2 = 0.0;
+ double fVal;
+ for (i = 0; i < nC1; i++)
+ for (j = 0; j < nR1; j++)
+ {
+ if (!pMat1->IsString(i,j))
+ {
+ fVal = pMat1->GetDouble(i,j);
+ fSum1 += fVal;
+ fSumSqr1 += fVal * fVal;
+ fCount1++;
+ }
+ }
+ for (i = 0; i < nC2; i++)
+ for (j = 0; j < nR2; j++)
+ {
+ if (!pMat2->IsString(i,j))
+ {
+ fVal = pMat2->GetDouble(i,j);
+ fSum2 += fVal;
+ fSumSqr2 += fVal * fVal;
+ fCount2++;
+ }
+ }
+ if (fCount1 < 2.0 || fCount2 < 2.0)
+ {
+ SetNoValue();
+ return;
+ }
+ double fS1 = (fSumSqr1-fSum1*fSum1/fCount1)/(fCount1-1.0)/fCount1;
+ double fS2 = (fSumSqr2-fSum2*fSum2/fCount2)/(fCount2-1.0)/fCount2;
+ if (fS1 + fS2 == 0.0)
+ {
+ SetNoValue();
+ return;
+ }
+ fT = fabs(fSum1/fCount1 - fSum2/fCount2)/sqrt(fS1+fS2);
+ double c = fS1/(fS1+fS2);
+// s.u. fF = SolarMath::ApproxFloor(1.0/(c*c/(fCount1-1.0)+(1.0-c)*(1.0-c)/(fCount2-1.0)));
+// fF = SolarMath::ApproxFloor((fS1+fS2)*(fS1+fS2)/(fS1*fS1/(fCount1-1.0) + fS2*fS2/(fCount2-1.0)));
+
+ // GetTDist wird mit GetBetaDist berechnet und kommt auch mit nicht ganzzahligen
+ // Freiheitsgraden klar. Dann stimmt das Ergebnis auch mit Excel ueberein (#52406#):
+ fF = 1.0/(c*c/(fCount1-1.0)+(1.0-c)*(1.0-c)/(fCount2-1.0));
+ }
+
+ else
+ {
+ SetIllegalArgument();
+ return;
+ }
+ if (fAnz == 1.0)
+ PushDouble(GetTDist(fT, fF));
+ else
+ PushDouble(2.0*GetTDist(fT, fF));
+}
+
+void ScInterpreter::ScFTest()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+ USHORT nMatInd1, nMatInd2;
+ ScMatrix* pMat2 = GetMatrix(nMatInd2);
+ ScMatrix* pMat1 = GetMatrix(nMatInd1);
+ if (!pMat1 || !pMat2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ USHORT nC1, nR1, nC2, nR2, i, j;
+ pMat1->GetDimensions(nC1, nR1);
+ pMat2->GetDimensions(nC2, nR2);
+ double fCount1 = 0.0;
+ double fCount2 = 0.0;
+ double fSum1 = 0.0;
+ double fSumSqr1 = 0.0;
+ double fSum2 = 0.0;
+ double fSumSqr2 = 0.0;
+ double fVal;
+ for (i = 0; i < nC1; i++)
+ for (j = 0; j < nR1; j++)
+ {
+ if (!pMat1->IsString(i,j))
+ {
+ fVal = pMat1->GetDouble(i,j);
+ fSum1 += fVal;
+ fSumSqr1 += fVal * fVal;
+ fCount1++;
+ }
+ }
+ for (i = 0; i < nC2; i++)
+ for (j = 0; j < nR2; j++)
+ {
+ if (!pMat2->IsString(i,j))
+ {
+ fVal = pMat2->GetDouble(i,j);
+ fSum2 += fVal;
+ fSumSqr2 += fVal * fVal;
+ fCount2++;
+ }
+ }
+ if (fCount1 < 2.0 || fCount2 < 2.0)
+ {
+ SetNoValue();
+ return;
+ }
+ double fS1 = (fSumSqr1-fSum1*fSum1/fCount1)/(fCount1-1.0);
+ double fS2 = (fSumSqr2-fSum2*fSum2/fCount2)/(fCount2-1.0);
+ if (fS1 == 0.0 || fS2 == 0.0)
+ {
+ SetNoValue();
+ return;
+ }
+ double fF, fF1, fF2;
+ if (fS1 > fS2)
+ {
+ fF = fS1/fS2;
+ fF1 = fCount1-1.0;
+ fF2 = fCount2-1.0;
+ }
+ else
+ {
+ fF = fS2/fS1;
+ fF1 = fCount2-1.0;
+ fF2 = fCount1-1.0;
+ }
+ PushDouble(2.0*GetFDist(fF, fF1, fF2));
+/*
+ double Z = (pow(fF,1.0/3.0)*(1.0-2.0/(9.0*fF2)) - (1.0-2.0/(9.0*fF1))) /
+ sqrt(2.0/(9.0*fF1) + pow(fF,2.0/3.0)*2.0/(9.0*fF2));
+ PushDouble(1.0-2.0*gauss(Z));
+*/
+}
+
+void ScInterpreter::ScChiTest()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+ USHORT nMatInd1, nMatInd2;
+ ScMatrix* pMat2 = GetMatrix(nMatInd2);
+ ScMatrix* pMat1 = GetMatrix(nMatInd1);
+ if (!pMat1 || !pMat2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ USHORT nC1, nR1, nC2, nR2;
+ pMat1->GetDimensions(nC1, nR1);
+ pMat2->GetDimensions(nC2, nR2);
+ if (nR1 != nR2 || nC1 != nC2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ double fChi = 0.0;
+ USHORT i, j;
+ double fValX, fValE;
+ for (i = 0; i < nC1; i++)
+ for (j = 0; j < nR1; j++)
+ {
+ if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
+ {
+ fValX = pMat1->GetDouble(i,j);
+ fValE = pMat2->GetDouble(i,j);
+ fChi += (fValX-fValE)*(fValX-fValE)/fValE;
+ }
+ else
+ {
+ SetIllegalArgument();
+ return;
+ }
+ }
+ double fDF;
+ if (nC1 == 1 || nR1 == 1)
+ {
+ fDF = (double)(nC1*nR1 - 1);
+ if (fDF == 0.0)
+ {
+ SetNoValue();
+ return;
+ }
+ }
+ else
+ fDF = (double)(nC1-1)*(double)(nR1-1);
+ PushDouble(GetChiDist(fChi, fDF));
+/*
+ double fX, fS, fT, fG;
+ fX = 1.0;
+ for (double fi = fDF; fi >= 2.0; fi -= 2.0)
+ fX *= fChi/fi;
+ fX *= exp(-fChi/2.0);
+ if (fmod(fDF, 2.0) != 0.0)
+ fX *= sqrt(2.0*fChi/F_PI);
+ fS = 1.0;
+ fT = 1.0;
+ fG = fDF;
+ while (fT >= 1.0E-7)
+ {
+ fG += 2.0;
+ fT *= fChi/fG;
+ fS += fT;
+ }
+ PushDouble(1.0 - fX*fS);
+*/
+}
+
+void ScInterpreter::ScKurt()
+{
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCountMin( nParamCount, 1 ) )
+ return;
+ USHORT SaveSP = sp;
+ USHORT i;
+ double fSum = 0.0;
+ double fSumSqr = 0.0;
+ double fCount = 0.0;
+ double fVal;
+ ScAddress aAdr;
+ ScRange aRange;
+ for (i = 0; i < nParamCount; i++)
+ {
+ switch (GetStackType())
+ {
+ case svDouble :
+ {
+ fVal = GetDouble();
+ fSum += fVal;
+ fSumSqr += fVal*fVal;
+ fCount++;
+ }
+ break;
+ case svSingleRef :
+ {
+ PopSingleRef( aAdr );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ {
+ fVal = GetCellValue( aAdr, pCell );
+ fSum += fVal;
+ fSumSqr += fVal*fVal;
+ fCount++;
+ }
+ }
+ break;
+ case svDoubleRef :
+ {
+ PopDoubleRef( aRange );
+ USHORT nErr = 0;
+ ScValueIterator aValIter(pDok, aRange);
+ if (aValIter.GetFirst(fVal, nErr))
+ {
+ fSum += fVal;
+ fSumSqr += fVal*fVal;
+ fCount++;
+ SetError(nErr);
+ while ((nErr == 0) && aValIter.GetNext(fVal, nErr))
+ {
+ fSum += fVal;
+ fSumSqr += fVal*fVal;
+ fCount++;
+ }
+ SetError(nErr);
+ }
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ if (pMat->IsNumeric())
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ {
+ fVal = pMat->GetDouble(i,j);
+ fSum += fVal;
+ fSumSqr += fVal*fVal;
+ fCount++;
+ }
+ }
+ else
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ if (!pMat->IsString(i,j))
+ {
+ fVal = pMat->GetDouble(i,j);
+ fSum += fVal;
+ fSumSqr += fVal*fVal;
+ fCount++;
+ }
+ }
+ }
+ }
+ break;
+ default :
+ SetError(errIllegalParameter);
+ break;
+ }
+ }
+ if (nGlobalError)
+ {
+ PushInt(0);
+ return;
+ }
+ double fMean = fSum / fCount;
+ double fSSqr = (fSumSqr - fSum*fSum/fCount)/(fCount-1.0);
+ sp = SaveSP;
+ fSum = 0.0;
+ // #55733# GCC Optimierungsfehler, GPF wenn die 4.0 als Konstante an pow()
+ // uebergeben wird, auch ein "const double fPow = 4.0;" GPF't,
+ double fPow = 4.0;
+ for (i = 0; i < nParamCount; i++)
+ {
+ switch (GetStackType())
+ {
+ case svDouble :
+ fSum += pow(GetDouble()-fMean,fPow);
+ break;
+ case svSingleRef :
+ {
+ PopSingleRef( aAdr );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ fSum += pow(GetCellValue( aAdr, pCell ) - fMean, fPow);
+ }
+ break;
+ case svDoubleRef :
+ {
+ PopDoubleRef( aRange );
+ USHORT nErr = 0;
+ ScValueIterator aValIter(pDok, aRange);
+ if (aValIter.GetFirst(fVal, nErr))
+ {
+ fSum += pow(fVal - fMean, fPow);
+ while (aValIter.GetNext(fVal, nErr))
+ fSum += pow(fVal - fMean, fPow);
+ }
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ if (pMat->IsNumeric())
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ fSum += pow(pMat->GetDouble(i,j) - fMean, fPow);
+ }
+ else
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ if (!pMat->IsString(i,j))
+ fSum += pow(pMat->GetDouble(i,j) - fMean, fPow);
+ }
+ }
+ }
+ break;
+ default : SetError(errIllegalParameter); break;
+ }
+ }
+ PushDouble(fCount*(fCount+1.0)/((fCount-1.0)*(fCount-2.0)*(fCount-3.0))
+ *fSum/(fSSqr*fSSqr)
+ - 3.0*(fCount-1.0)*(fCount-1.0)/((fCount-2.0)*(fCount-3.0)));
+}
+
+void ScInterpreter::ScHarMean()
+{
+ BYTE nParamCount = GetByte();
+ double nVal = 0.0;
+ ULONG nCount = 0;
+ ScAddress aAdr;
+ ScRange aRange;
+ for (short i = 0; i < nParamCount && (nGlobalError == 0); i++)
+ {
+ switch (GetStackType())
+ {
+ case svDouble :
+ {
+ double x = GetDouble();
+ if (x > 0.0)
+ {
+ nVal += 1.0/x;
+ nCount++;
+ }
+ else
+ SetIllegalArgument();
+ break;
+ }
+ case svSingleRef :
+ {
+ PopSingleRef( aAdr );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ {
+ double x = GetCellValue( aAdr, pCell );
+ if (x > 0.0)
+ {
+ nVal += 1.0/x;
+ nCount++;
+ }
+ else
+ SetIllegalArgument();
+ }
+ break;
+ }
+ case svDoubleRef :
+ {
+ USHORT nErr = 0;
+ PopDoubleRef( aRange );
+ double nCellVal;
+ ScValueIterator aValIter(pDok, aRange, glSubTotal);
+ if (aValIter.GetFirst(nCellVal, nErr))
+ {
+ if (nCellVal > 0.0)
+ {
+ nVal += 1.0/nCellVal;
+ nCount++;
+ }
+ else
+ SetIllegalArgument();
+ SetError(nErr);
+ while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
+ {
+ if (nCellVal > 0.0)
+ {
+ nVal += 1.0/nCellVal;
+ nCount++;
+ }
+ else
+ SetIllegalArgument();
+ }
+ SetError(nErr);
+ }
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ if (pMat->IsNumeric())
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ {
+ double x = pMat->GetDouble(i,j);
+ if (x > 0.0)
+ {
+ nVal += 1.0/x;
+ nCount++;
+ }
+ else
+ SetIllegalArgument();
+ }
+ }
+ else
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ if (!pMat->IsString(i,j))
+ {
+ double x = pMat->GetDouble(i,j);
+ if (x > 0.0)
+ {
+ nVal += 1.0/x;
+ nCount++;
+ }
+ else
+ SetIllegalArgument();
+ }
+ }
+ }
+ }
+ break;
+ default : SetError(errIllegalParameter); break;
+ }
+ }
+ if (nGlobalError == 0)
+ PushDouble((double)nCount/nVal);
+}
+
+void ScInterpreter::ScGeoMean()
+{
+ BYTE nParamCount = GetByte();
+ double nVal = 0.0;
+ ULONG nCount = 0;
+ ScAddress aAdr;
+ ScRange aRange;
+ for (short i = 0; i < nParamCount && (nGlobalError == 0); i++)
+ {
+ switch (GetStackType())
+ {
+ case svDouble :
+ {
+ double x = GetDouble();
+ if (x > 0.0)
+ {
+ nVal += log(x);
+ nCount++;
+ }
+ else
+ SetIllegalArgument();
+ break;
+ }
+ case svSingleRef :
+ {
+ PopSingleRef( aAdr );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ {
+ double x = GetCellValue( aAdr, pCell );
+ if (x > 0.0)
+ {
+ nVal += log(x);
+ nCount++;
+ }
+ else
+ SetIllegalArgument();
+ }
+ break;
+ }
+ case svDoubleRef :
+ {
+ USHORT nErr = 0;
+ PopDoubleRef( aRange );
+ double nCellVal;
+ ScValueIterator aValIter(pDok, aRange, glSubTotal);
+ if (aValIter.GetFirst(nCellVal, nErr))
+ {
+ if (nCellVal > 0.0)
+ {
+ nVal += log(nCellVal);
+ nCount++;
+ }
+ else
+ SetIllegalArgument();
+ SetError(nErr);
+ while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
+ {
+ if (nCellVal > 0.0)
+ {
+ nVal += log(nCellVal);
+ nCount++;
+ }
+ else
+ SetIllegalArgument();
+ }
+ SetError(nErr);
+ }
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ if (pMat->IsNumeric())
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ {
+ double x = pMat->GetDouble(i,j);
+ if (x > 0.0)
+ {
+ nVal += log(x);
+ nCount++;
+ }
+ else
+ SetIllegalArgument();
+ }
+ }
+ else
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ if (!pMat->IsString(i,j))
+ {
+ double x = pMat->GetDouble(i,j);
+ if (x > 0.0)
+ {
+ nVal += log(x);
+ nCount++;
+ }
+ else
+ SetIllegalArgument();
+ }
+ }
+ }
+ }
+ break;
+ default : SetError(errIllegalParameter); break;
+ }
+ }
+ if (nGlobalError == 0)
+ PushDouble(exp(nVal/(double)nCount));
+}
+
+void ScInterpreter::ScStandard()
+{
+ if ( MustHaveParamCount( GetByte(), 3 ) )
+ {
+ double sigma = GetDouble();
+ double mue = GetDouble();
+ double x = GetDouble();
+ if (sigma <= 0.0)
+ SetIllegalArgument();
+ else
+ PushDouble((x-mue)/sigma);
+ }
+}
+
+void ScInterpreter::ScSkew()
+{
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCountMin( nParamCount, 1 ) )
+ return;
+ USHORT SaveSP = sp;
+ USHORT i;
+ double fSum = 0.0;
+ double fSumSqr = 0.0;
+ double fCount = 0.0;
+ double fVal;
+ ScAddress aAdr;
+ ScRange aRange;
+ for (i = 0; i < nParamCount; i++)
+ {
+ switch (GetStackType())
+ {
+ case svDouble :
+ {
+ fVal = GetDouble();
+ fSum += fVal;
+ fSumSqr += fVal*fVal;
+ fCount++;
+ }
+ break;
+ case svSingleRef :
+ {
+ PopSingleRef( aAdr );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ {
+ fVal = GetCellValue( aAdr, pCell );
+ fSum += fVal;
+ fSumSqr += fVal*fVal;
+ fCount++;
+ }
+ }
+ break;
+ case svDoubleRef :
+ {
+ PopDoubleRef( aRange );
+ USHORT nErr = 0;
+ ScValueIterator aValIter(pDok, aRange);
+ if (aValIter.GetFirst(fVal, nErr))
+ {
+ fSum += fVal;
+ fSumSqr += fVal*fVal;
+ fCount++;
+ SetError(nErr);
+ while ((nErr == 0) && aValIter.GetNext(fVal, nErr))
+ {
+ fSum += fVal;
+ fSumSqr += fVal*fVal;
+ fCount++;
+ }
+ SetError(nErr);
+ }
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ if (pMat->IsNumeric())
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ {
+ fVal = pMat->GetDouble(i,j);
+ fSum += fVal;
+ fSumSqr += fVal*fVal;
+ fCount++;
+ }
+ }
+ else
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ if (!pMat->IsString(i,j))
+ {
+ fVal = pMat->GetDouble(i,j);
+ fSum += fVal;
+ fSumSqr += fVal*fVal;
+ fCount++;
+ }
+ }
+ }
+ }
+ break;
+ default :
+ SetError(errIllegalParameter);
+ break;
+ }
+ }
+ if (nGlobalError)
+ {
+ PushInt(0);
+ return;
+ }
+ double fMean = fSum / fCount;
+ double fSSqr = (fSumSqr - fSum*fSum/fCount)/(fCount-1.0);
+ sp = SaveSP;
+ fSum = 0.0;
+ double fPow = 3.0; // vorsichtshalber wg. #55733#, siehe ScKurt()
+ for (i = 0; i < nParamCount; i++)
+ {
+ switch (GetStackType())
+ {
+ case svDouble :
+ fSum += pow(GetDouble()-fMean,fPow);
+ break;
+ case svSingleRef :
+ {
+ PopSingleRef( aAdr );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ fSum += pow(GetCellValue( aAdr, pCell ) - fMean, fPow);
+ }
+ break;
+ case svDoubleRef :
+ {
+ PopDoubleRef( aRange );
+ USHORT nErr = 0;
+ ScValueIterator aValIter(pDok, aRange);
+ if (aValIter.GetFirst(fVal, nErr))
+ {
+ fSum += pow(fVal - fMean, fPow);
+ while (aValIter.GetNext(fVal, nErr))
+ fSum += pow(fVal - fMean, fPow);
+ }
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ if (pMat->IsNumeric())
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ fSum += pow(pMat->GetDouble(i,j) - fMean, fPow);
+ }
+ else
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ if (!pMat->IsString(i,j))
+ fSum += pow(pMat->GetDouble(i,j) - fMean, fPow);
+ }
+ }
+ }
+ break;
+ default : SetError(errIllegalParameter); break;
+ }
+ }
+ PushDouble(fCount/((fCount-1.0)*(fCount-2.0))*fSum/(fSSqr*sqrt(fSSqr)));
+}
+
+void ScInterpreter::ScMedian()
+{
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCountMin( nParamCount, 1 ) )
+ return;
+ double* pSortArray = NULL;
+ ULONG nSize = 0;
+ GetSortArray(nParamCount, &pSortArray, nSize);
+ if (!pSortArray || nSize == 0 || nGlobalError)
+ SetNoValue();
+ else
+ {
+#ifdef WIN
+ double huge* pSArray = (double huge*) pSortArray;
+#else
+ double* pSArray = pSortArray;
+#endif
+ if (nSize % 2 == 0)
+ PushDouble((pSArray[nSize/2-1]+pSArray[nSize/2])/2.0);
+ else
+ PushDouble(pSArray[(nSize-1)/2]);
+ }
+ if (pSortArray)
+ {
+#ifdef WIN
+ SvMemFree(pSortArray);
+#else
+ delete [] pSortArray;
+#endif
+ }
+
+}
+
+void ScInterpreter::ScPercentile()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+ double alpha = GetDouble();
+ if (alpha < 0.0 || alpha > 1.0)
+ {
+ SetIllegalArgument();
+ return;
+ }
+ double* pSortArray = NULL;
+ ULONG nSize = 0;
+ GetSortArray(1, &pSortArray, nSize);
+ if (!pSortArray || nSize == 0 || nGlobalError)
+ SetNoValue();
+ else
+ {
+#ifdef WIN
+ double huge* pSArray = (double huge*) pSortArray;
+#else
+ double* pSArray = pSortArray;
+#endif
+ if (nSize == 1)
+ PushDouble(pSArray[0]);
+ else
+ {
+ ULONG nIndex = (ULONG)SolarMath::ApproxFloor(alpha*(nSize-1));
+ double fDiff = alpha*(nSize-1) - SolarMath::ApproxFloor(alpha*(nSize-1));
+ DBG_ASSERT(nIndex >= 0 && nIndex < nSize, "ScPercentile: falscher Index (1)");
+ if (fDiff == 0.0)
+ PushDouble(pSArray[nIndex]);
+ else
+ {
+ DBG_ASSERT(nIndex < nSize-1, "ScPercentile: falscher Index(2)");
+ PushDouble(pSArray[nIndex] +
+ fDiff*(pSArray[nIndex+1]-pSArray[nIndex]));
+ }
+ }
+ }
+ if (pSortArray)
+ {
+#ifdef WIN
+ SvMemFree(pSortArray);
+#else
+ delete [] pSortArray;
+#endif
+ }
+}
+
+void ScInterpreter::ScQuartile()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+ double fFlag = SolarMath::ApproxFloor(GetDouble());
+ if (fFlag < 0.0 || fFlag > 4.0)
+ {
+ SetIllegalArgument();
+ return;
+ }
+ double* pSortArray = NULL;
+ ULONG nSize = 0;
+ GetSortArray(1, &pSortArray, nSize);
+ if (!pSortArray || nSize == 0 || nGlobalError)
+ SetNoValue();
+ else
+ {
+#ifdef WIN
+ double huge* pSArray = (double huge*) pSortArray;
+#else
+ double* pSArray = pSortArray;
+#endif
+ if (nSize == 1)
+ PushDouble(pSArray[0]);
+ else
+ {
+ if (fFlag == 0.0)
+ PushDouble(pSArray[0]);
+ else if (fFlag == 1.0)
+ {
+ ULONG nIndex = (ULONG)SolarMath::ApproxFloor(0.25*(nSize-1));
+ double fDiff = 0.25*(nSize-1) - SolarMath::ApproxFloor(0.25*(nSize-1));
+ DBG_ASSERT(nIndex >= 0 && nIndex < nSize, "ScQuartile: falscher Index (1)");
+ if (fDiff == 0.0)
+ PushDouble(pSArray[nIndex]);
+ else
+ {
+ DBG_ASSERT(nIndex < nSize-1, "ScQuartile: falscher Index(2)");
+ PushDouble(pSArray[nIndex] +
+ fDiff*(pSArray[nIndex+1]-pSArray[nIndex]));
+ }
+ }
+ else if (fFlag == 2.0)
+ {
+ if (nSize % 2 == 0)
+ PushDouble((pSArray[nSize/2-1]+pSArray[nSize/2])/2.0);
+ else
+ PushDouble(pSArray[(nSize-1)/2]);
+ }
+ else if (fFlag == 3.0)
+ {
+ ULONG nIndex = (ULONG)SolarMath::ApproxFloor(0.75*(nSize-1));
+ double fDiff = 0.75*(nSize-1) - SolarMath::ApproxFloor(0.75*(nSize-1));
+ DBG_ASSERT(nIndex >= 0 && nIndex < nSize, "ScQuartile: falscher Index (3)");
+ if (fDiff == 0.0)
+ PushDouble(pSArray[nIndex]);
+ else
+ {
+ DBG_ASSERT(nIndex < nSize-1, "ScQuartile: falscher Index(4)");
+ PushDouble(pSArray[nIndex] +
+ fDiff*(pSArray[nIndex+1]-pSArray[nIndex]));
+ }
+ }
+ else
+ PushDouble(pSArray[nSize-1]);
+ }
+ }
+ if (pSortArray)
+ {
+#ifdef WIN
+ SvMemFree(pSortArray);
+#else
+ delete [] pSortArray;
+#endif
+ }
+}
+
+void ScInterpreter::ScModalValue()
+{
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCountMin( nParamCount, 1 ) )
+ return;
+ double* pSortArray = NULL;
+ ULONG nSize = 0;
+ GetSortArray(nParamCount, &pSortArray, nSize);
+ if (!pSortArray || nSize == 0 || nGlobalError)
+ SetNoValue();
+ else
+ {
+#ifdef WIN
+ double huge* pSArray = (double huge*) pSortArray;
+#else
+ double* pSArray = pSortArray;
+#endif
+ ULONG nMaxIndex, nMax = 1, nCount = 1;
+ double nOldVal = pSArray[0];
+ for (ULONG i = 1; i < nSize; i++)
+ {
+ if (pSArray[i] == nOldVal)
+ nCount++;
+ else
+ {
+ nOldVal = pSArray[i];
+ if (nCount > nMax)
+ {
+ nMax = nCount;
+ nMaxIndex = i-1;
+ }
+ nCount = 1;
+ }
+ }
+ if (nCount > nMax)
+ {
+ nMax = nCount;
+ nMaxIndex = i-1;
+ }
+ if (nMax == 1 && nCount == 1)
+ SetNoValue();
+ else if (nMax == 1)
+ PushDouble(nOldVal);
+ else
+ PushDouble(pSArray[nMaxIndex]);
+ }
+ if (pSortArray)
+ {
+#ifdef WIN
+ SvMemFree(pSortArray);
+#else
+ delete [] pSortArray;
+#endif
+ }
+}
+
+void ScInterpreter::ScLarge()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+ double* pSortArray = NULL;
+ ULONG nSize = 0;
+ ULONG k = (ULONG) SolarMath::ApproxFloor(GetDouble());
+ if (k <= 0)
+ {
+ SetIllegalArgument();
+ return;
+ }
+ GetSortArray(1, &pSortArray, nSize);
+ if (!pSortArray || nSize == 0 || nGlobalError || nSize < k)
+ SetNoValue();
+ else
+ {
+#ifdef WIN
+ double huge* pSArray = (double huge*) pSortArray;
+#else
+ double* pSArray = pSortArray;
+#endif
+/*
+ ULONG nCount = 1;
+ double nOldVal = pSArray[nSize-1];
+ for (long i = nSize-2; i >= 0 && nCount < k; i--)
+ {
+ if (pSArray[i] != nOldVal)
+ {
+ nCount++;
+ nOldVal = pSArray[i];
+ }
+ }
+ if (nCount < k)
+ SetNoValue();
+ else
+ PushDouble(nOldVal);
+*/
+ PushDouble( pSArray[ nSize-k ] );
+ }
+ if (pSortArray)
+ {
+#ifdef WIN
+ SvMemFree(pSortArray);
+#else
+ delete [] pSortArray;
+#endif
+ }
+}
+
+void ScInterpreter::ScSmall()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+ double* pSortArray = NULL;
+ ULONG nSize = 0;
+ ULONG k = (ULONG) SolarMath::ApproxFloor(GetDouble());
+ if (k <= 0)
+ {
+ SetIllegalArgument();
+ return;
+ }
+ GetSortArray(1, &pSortArray, nSize);
+ if (!pSortArray || nSize == 0 || nGlobalError || nSize < k)
+ SetNoValue();
+ else
+ {
+#ifdef WIN
+ double huge* pSArray = (double huge*) pSortArray;
+#else
+ double* pSArray = pSortArray;
+#endif
+/*
+ ULONG nCount = 1;
+ double nOldVal = pSArray[0];
+ for (ULONG i = 1; i < nSize && nCount < k; i++)
+ {
+ if (pSArray[i] != nOldVal)
+ {
+ nCount++;
+ nOldVal = pSArray[i];
+ }
+ }
+ if (nCount < k)
+ SetNoValue();
+ else
+ PushDouble(nOldVal);
+*/
+ PushDouble( pSArray[ k-1 ] );
+ }
+ if (pSortArray)
+ {
+#ifdef WIN
+ SvMemFree(pSortArray);
+#else
+ delete [] pSortArray;
+#endif
+ }
+}
+
+void ScInterpreter::ScPercentrank()
+{
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 2 ) )
+ return;
+/* wird nicht unterstuetzt
+ double fPrec;
+ if (nParamCount == 3)
+ {
+ fPrec = SolarMath::ApproxFloor(GetDouble());
+ if (fPrec < 1.0)
+ {
+ SetIllegalArgument();
+ return;
+ }
+ }
+ else
+ fPrec = 3.0;
+*/
+ double fNum = GetDouble();
+ double* pSortArray = NULL;
+ ULONG nSize = 0;
+ GetSortArray(1, &pSortArray, nSize);
+ if (!pSortArray || nSize == 0 || nGlobalError)
+ SetNoValue();
+ else
+ {
+#ifdef WIN
+ double huge* pSArray = (double huge*) pSortArray;
+#else
+ double* pSArray = pSortArray;
+#endif
+ if (fNum < pSArray[0] || fNum > pSArray[nSize-1])
+ SetNoValue();
+ else if ( nSize == 1 )
+ PushDouble(1.0); // fNum == pSArray[0], see test above
+ else
+ {
+ double fRes;
+ ULONG nOldCount = 0;
+ double fOldVal = pSArray[0];
+ ULONG i;
+ for (i = 1; i < nSize && pSArray[i] < fNum; i++)
+ {
+ if (pSArray[i] != fOldVal)
+ {
+ nOldCount = i;
+ fOldVal = pSArray[i];
+ }
+ }
+ if (pSArray[i] != fOldVal)
+ nOldCount = i;
+ if (fNum == pSArray[i])
+ fRes = (double)nOldCount/(double)(nSize-1);
+ else
+ {
+ // #75312# nOldCount is the count of smaller entries
+ // fNum is between pSArray[nOldCount-1] and pSArray[nOldCount]
+ // use linear interpolation to find a position between the entries
+
+ if ( nOldCount == 0 )
+ {
+ DBG_ERROR("should not happen");
+ fRes = 0.0;
+ }
+ else
+ {
+ double fFract = ( fNum - pSArray[nOldCount-1] ) /
+ ( pSArray[nOldCount] - pSArray[nOldCount-1] );
+ fRes = ( (double)(nOldCount-1)+fFract )/(double)(nSize-1);
+ }
+ }
+ PushDouble(fRes);
+ }
+ }
+ if (pSortArray)
+ {
+#ifdef WIN
+ SvMemFree(pSortArray);
+#else
+ delete [] pSortArray;
+#endif
+ }
+}
+
+void ScInterpreter::ScTrimMean()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+ double alpha = GetDouble();
+ if (alpha < 0.0 || alpha >= 1.0)
+ {
+ SetIllegalArgument();
+ return;
+ }
+ double* pSortArray = NULL;
+ ULONG nSize = 0;
+ GetSortArray(1, &pSortArray, nSize);
+ if (!pSortArray || nSize == 0 || nGlobalError)
+ SetNoValue();
+ else
+ {
+ ppGlobSortArray = &pSortArray;
+#ifdef WIN
+ double huge* pSArray = (double huge*) pSortArray;
+#else
+ double* pSArray = pSortArray;
+#endif
+ ULONG nIndex = (ULONG) SolarMath::ApproxFloor(alpha*(double)nSize);
+ if (nIndex % 2 != 0)
+ nIndex--;
+ nIndex /= 2;
+ DBG_ASSERT(nIndex >= 0 && nIndex < nSize, "ScTrimMean: falscher Index");
+ double fSum = 0.0;
+ for (ULONG i = nIndex; i < nSize-nIndex; i++)
+ fSum += pSArray[i];
+ PushDouble(fSum/(double)(nSize-2*nIndex));
+ }
+ if (pSortArray)
+ {
+#ifdef WIN
+ SvMemFree(pSortArray);
+#else
+ delete [] pSortArray;
+#endif
+ ppGlobSortArray = NULL;
+ }
+}
+
+void ScInterpreter::GetSortArray(BYTE nParamCount, double** ppSortArray, ULONG& nSize)
+{
+ *ppSortArray = NULL;
+ nSize = 0;
+
+ USHORT SaveSP = sp;
+ USHORT i;
+ ULONG rValCount = 0;
+ ScAddress aAdr;
+ ScRange aRange;
+ for (i = 0; i < nParamCount; i++)
+ {
+ switch (GetStackType())
+ {
+ case svDouble :
+ rValCount++;
+ break;
+ case svSingleRef :
+ {
+ PopSingleRef( aAdr );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ rValCount++;
+ }
+ break;
+ case svDoubleRef :
+ {
+ PopDoubleRef( aRange );
+ USHORT nErr = 0;
+ double nCellVal;
+ ScValueIterator aValIter(pDok, aRange);
+ if (aValIter.GetFirst(nCellVal, nErr))
+ {
+ rValCount++;
+ SetError(nErr);
+ while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
+ rValCount++;
+ SetError(nErr);
+ }
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ if (pMat->IsNumeric())
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ rValCount++;
+ }
+ else
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ if (!pMat->IsString(i,j))
+ rValCount++;
+ }
+ }
+ }
+ break;
+ default :
+ SetError(errIllegalParameter);
+ break;
+ }
+ }
+ if (rValCount > MAX_ANZ_DOUBLE_FOR_SORT || nGlobalError)
+ {
+ SetError(errStackOverflow);
+ return;
+ }
+ else if (rValCount == 0)
+ {
+ SetNoValue();
+ return;
+ }
+#ifdef WIN
+ *ppSortArray = (double*) SvMemAlloc( rValCount * sizeof(double));
+ double huge* pSArray = (double huge*) (*ppSortArray);
+#else
+ *ppSortArray = new double[rValCount];
+ double* pSArray = *ppSortArray;
+#endif
+ if (!*ppSortArray)
+ {
+ rValCount = 0;
+ SetError(errStackOverflow);
+ return;
+ }
+ sp = SaveSP;
+ ULONG nIndex = 0;
+ for (i = 0; i < nParamCount; i++)
+ {
+ switch (GetStackType())
+ {
+ case svDouble :
+ pSArray[nIndex] = GetDouble();
+ nIndex++;
+ break;
+ case svSingleRef :
+ {
+ PopSingleRef( aAdr );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ {
+ pSArray[nIndex] = GetCellValue( aAdr, pCell );
+ nIndex++;
+ }
+ }
+ break;
+ case svDoubleRef :
+ {
+ PopDoubleRef( aRange );
+ USHORT nErr;
+ double nCellVal;
+ ScValueIterator aValIter(pDok, aRange);
+ if (aValIter.GetFirst(nCellVal, nErr))
+ {
+ pSArray[nIndex] = nCellVal;
+ nIndex++;
+ while (aValIter.GetNext(nCellVal, nErr))
+ {
+ pSArray[nIndex] = nCellVal;
+ nIndex++;
+ }
+ }
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ if (pMat->IsNumeric())
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ {
+ pSArray[nIndex] = pMat->GetDouble(i,j);
+ nIndex++;
+ }
+ }
+ else
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ if (!pMat->IsString(i,j))
+ {
+ pSArray[nIndex] = pMat->GetDouble(i,j);
+ nIndex++;
+ }
+ }
+ }
+ }
+ break;
+ default : SetError(errIllegalParameter); break;
+ }
+ }
+ DBG_ASSERT(nIndex == rValCount,"nIndex != rValCount");
+ if (nGlobalError == 0)
+ {
+ double fVal;
+ USHORT nInd;
+ for (ULONG i = 0; (i + 4) <= rValCount-1; i += 4)
+ {
+ nInd = rand() % (int) (rValCount-1);
+ fVal = pSArray[i];
+ pSArray[i] = pSArray[nInd];
+ pSArray[nInd] = fVal;
+ }
+ QuickSort(0, rValCount-1, pSArray);
+ }
+ nSize = rValCount;
+}
+
+void ScInterpreter::QuickSort(long nLo, long nHi, double* pSortArray)
+{
+#ifdef WIN
+ double huge* pSArray = (double huge*) pSortArray;
+#else
+ double* pSArray = pSortArray;
+#endif
+ if (nHi - nLo == 1)
+ {
+ if (pSArray[nLo] > pSArray[nHi])
+ {
+ double fVal;
+ fVal = pSArray[nLo];
+ pSArray[nLo] = pSArray[nHi];
+ pSArray[nHi] = fVal;
+ }
+ }
+ else
+ {
+ long ni = nLo;
+ long nj = nHi;
+ do
+ {
+ while (ni <= nHi && pSArray[ni] < pSArray[nLo]) ni++;
+ while (nj >= nLo && pSArray[nLo] < pSArray[nj]) nj--;
+ if (ni <= nj)
+ {
+ if (ni != nj)
+ {
+ double fVal;
+ fVal = pSArray[ni];
+ pSArray[ni] = pSArray[nj];
+ pSArray[nj] = fVal;
+ }
+ ni++;
+ nj--;
+ }
+ }
+ while (ni < nj);
+ if ((nj - nLo) < (nHi - ni))
+ {
+ if (nLo < nj) QuickSort(nLo, nj, pSortArray);
+ if (ni < nHi) QuickSort(ni, nHi, pSortArray);
+ }
+ else
+ {
+ if (ni < nHi) QuickSort(ni, nHi, pSortArray);
+ if (nLo < nj) QuickSort(nLo, nj, pSortArray);
+ }
+ }
+}
+
+void ScInterpreter::ScRank()
+{
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
+ return;
+ BOOL bDescending;
+ if (nParamCount == 3)
+ bDescending = GetBool();
+ else
+ bDescending = FALSE;
+ double fCount = 1.0;
+ BOOL bValid = FALSE;
+ switch (GetStackType())
+ {
+ case svDouble :
+ {
+ double x = GetDouble();
+ double fVal = GetDouble();
+ if (x == fVal)
+ bValid = TRUE;
+ break;
+ }
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ PopSingleRef( aAdr );
+ double fVal = GetDouble();
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ {
+ double x = GetCellValue( aAdr, pCell );
+ if (x == fVal)
+ bValid = TRUE;
+ }
+ break;
+ }
+ case svDoubleRef :
+ {
+ ScRange aRange;
+ USHORT nErr = 0;
+ PopDoubleRef( aRange );
+ double fVal = GetDouble();
+ double nCellVal;
+ ScValueIterator aValIter(pDok, aRange, glSubTotal);
+ if (aValIter.GetFirst(nCellVal, nErr))
+ {
+ if (nCellVal == fVal)
+ bValid = TRUE;
+ else if ((!bDescending && nCellVal > fVal) ||
+ (bDescending && nCellVal < fVal) )
+ fCount++;
+ SetError(nErr);
+ while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
+ {
+ if (nCellVal == fVal)
+ bValid = TRUE;
+ else if ((!bDescending && nCellVal > fVal) ||
+ (bDescending && nCellVal < fVal) )
+ fCount++;
+ }
+ }
+ SetError(nErr);
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrix* pMat = PopMatrix();
+ double fVal = GetDouble();
+ if (pMat)
+ {
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ if (pMat->IsNumeric())
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ {
+ double x = pMat->GetDouble(i,j);
+ if (x == fVal)
+ bValid = TRUE;
+ else if ((!bDescending && x > fVal) ||
+ (bDescending && x < fVal) )
+ fCount++;
+ }
+ }
+ else
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ if (!pMat->IsString(i,j))
+ {
+ double x = pMat->GetDouble(i,j);
+ if (x == fVal)
+ bValid = TRUE;
+ else if ((!bDescending && x > fVal) ||
+ (bDescending && x < fVal) )
+ fCount++;
+ }
+ }
+ }
+ }
+ break;
+ default : SetError(errIllegalParameter); break;
+ }
+ if (bValid)
+ PushDouble(fCount);
+ else
+ SetNoValue();
+}
+
+void ScInterpreter::ScAveDev()
+{
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCountMin( nParamCount, 1 ) )
+ return;
+ USHORT SaveSP = sp;
+ USHORT i;
+ double nMiddle = 0.0;
+ double rVal = 0.0;
+ double rValCount = 0.0;
+ ScAddress aAdr;
+ ScRange aRange;
+ for (i = 0; i < nParamCount; i++)
+ {
+ switch (GetStackType())
+ {
+ case svDouble :
+ rVal += GetDouble();
+ rValCount++;
+ break;
+ case svSingleRef :
+ {
+ PopSingleRef( aAdr );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ {
+ rVal += GetCellValue( aAdr, pCell );
+ rValCount++;
+ }
+ }
+ break;
+ case svDoubleRef :
+ {
+ USHORT nErr = 0;
+ double nCellVal;
+ PopDoubleRef( aRange );
+ ScValueIterator aValIter(pDok, aRange);
+ if (aValIter.GetFirst(nCellVal, nErr))
+ {
+ rVal += nCellVal;
+ rValCount++;
+ SetError(nErr);
+ while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
+ {
+ rVal += nCellVal;
+ rValCount++;
+ }
+ SetError(nErr);
+ }
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ if (pMat->IsNumeric())
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ {
+ rVal += pMat->GetDouble(i,j);
+ rValCount++;
+ }
+ }
+ else
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ if (!pMat->IsString(i,j))
+ {
+ rVal += pMat->GetDouble(i,j);
+ rValCount++;
+ }
+ }
+ }
+ }
+ break;
+ default :
+ SetError(errIllegalParameter);
+ break;
+ }
+ }
+ if (nGlobalError)
+ {
+ PushInt(0);
+ return;
+ }
+ nMiddle = rVal / rValCount;
+ sp = SaveSP;
+ rVal = 0.0;
+ for (i = 0; i < nParamCount; i++)
+ {
+ switch (GetStackType())
+ {
+ case svDouble :
+ rVal += fabs(GetDouble() - nMiddle);
+ break;
+ case svSingleRef :
+ {
+ PopSingleRef( aAdr );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ rVal += fabs(GetCellValue( aAdr, pCell ) - nMiddle);
+ }
+ break;
+ case svDoubleRef :
+ {
+ USHORT nErr = 0;
+ double nCellVal;
+ PopDoubleRef( aRange );
+ ScValueIterator aValIter(pDok, aRange);
+ if (aValIter.GetFirst(nCellVal, nErr))
+ {
+ rVal += (fabs(nCellVal - nMiddle));
+ while (aValIter.GetNext(nCellVal, nErr))
+ rVal += fabs(nCellVal - nMiddle);
+ }
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ if (pMat->IsNumeric())
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ rVal += fabs(pMat->GetDouble(i,j) - nMiddle);
+ }
+ else
+ {
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nR; j++)
+ if (!pMat->IsString(i,j))
+ rVal += fabs(pMat->GetDouble(i,j) - nMiddle);
+ }
+ }
+ }
+ break;
+ default : SetError(errIllegalParameter); break;
+ }
+ }
+ PushDouble(rVal / rValCount);
+}
+
+void ScInterpreter::ScDevSq()
+{
+ double nVal;
+ double nValCount;
+ GetStVarParams(nVal, nValCount);
+ PushDouble(nVal);
+}
+
+void ScInterpreter::ScProbability()
+{
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 3, 4 ) )
+ return;
+ double fUp, fLo;
+ fUp = GetDouble();
+ if (nParamCount == 4)
+ fLo = GetDouble();
+ else
+ fLo = fUp;
+ if (fLo > fUp)
+ {
+ double fTemp = fLo;
+ fLo = fUp;
+ fUp = fTemp;
+ }
+ USHORT nMatInd1, nMatInd2;
+ ScMatrix* pMatP = GetMatrix(nMatInd1);
+ ScMatrix* pMatW = GetMatrix(nMatInd2);
+ if (!pMatP || !pMatW)
+ SetIllegalParameter();
+ else
+ {
+ USHORT nC1, nR1, nC2, nR2;
+ pMatP->GetDimensions(nC1, nR1);
+ pMatW->GetDimensions(nC2, nR2);
+ if (nC1 != nC2 || nR1 != nR2 || nC1 == 0 || nR1 == 0 ||
+ nC2 == 0 || nR2 == 0)
+ SetNV();
+ else
+ {
+ double fSum = 0.0;
+ double fRes = 0.0;
+ BOOL bStop = FALSE;
+ double fP, fW;
+ for (USHORT i = 0; i < nC1*nR1 && !bStop; i++)
+ {
+ if (pMatP->IsValue(i) && pMatW->IsValue(i))
+ {
+ fP = pMatP->GetDouble(i);
+ fW = pMatW->GetDouble(i);
+ if (fP < 0.0 || fP > 1.0)
+ bStop = TRUE;
+ else
+ {
+ fSum += fP;
+ if (fW >= fLo && fW <= fUp)
+ fRes += fP;
+ }
+ }
+ else
+ SetIllegalArgument();
+ }
+ if (bStop || fabs(fSum -1.0) > 1.0E-7)
+ SetNoValue();
+ else
+ PushDouble(fRes);
+ }
+ }
+}
+
+void ScInterpreter::ScCorrel()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+ USHORT nMatInd1, nMatInd2;
+ ScMatrix* pMat1 = GetMatrix(nMatInd2);
+ ScMatrix* pMat2 = GetMatrix(nMatInd1);
+ if (!pMat1 || !pMat2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ USHORT nC1, nR1, nC2, nR2;
+ pMat1->GetDimensions(nC1, nR1);
+ pMat2->GetDimensions(nC2, nR2);
+ if (nR1 != nR2 || nC1 != nC2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ double fCount = 0.0;
+ double fSumX = 0.0;
+ double fSumSqrX = 0.0;
+ double fSumY = 0.0;
+ double fSumSqrY = 0.0;
+ double fSumXY = 0.0;
+ double fValX, fValY;
+ for (USHORT i = 0; i < nC1; i++)
+ for (USHORT j = 0; j < nR1; j++)
+ {
+ if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
+ {
+ fValX = pMat1->GetDouble(i,j);
+ fValY = pMat2->GetDouble(i,j);
+ fSumX += fValX;
+ fSumSqrX += fValX * fValX;
+ fSumY += fValY;
+ fSumSqrY += fValY * fValY;
+ fSumXY += fValX*fValY;
+ fCount++;
+ }
+ }
+ if (fCount < 2.0)
+ SetNoValue();
+ else
+ PushDouble( (fSumXY-fSumX*fSumY/fCount)/
+ sqrt((fSumSqrX-fSumX*fSumX/fCount)*
+ (fSumSqrY-fSumY*fSumY/fCount)));
+}
+
+void ScInterpreter::ScCovar()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+ USHORT nMatInd1, nMatInd2;
+ ScMatrix* pMat1 = GetMatrix(nMatInd2);
+ ScMatrix* pMat2 = GetMatrix(nMatInd1);
+ if (!pMat1 || !pMat2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ USHORT nC1, nR1, nC2, nR2;
+ pMat1->GetDimensions(nC1, nR1);
+ pMat2->GetDimensions(nC2, nR2);
+ if (nR1 != nR2 || nC1 != nC2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ double fCount = 0.0;
+ double fSumX = 0.0;
+ double fSumY = 0.0;
+ double fSumXY = 0.0;
+ double fValX, fValY;
+ for (USHORT i = 0; i < nC1; i++)
+ for (USHORT j = 0; j < nR1; j++)
+ {
+ if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
+ {
+ fValX = pMat1->GetDouble(i,j);
+ fValY = pMat2->GetDouble(i,j);
+ fSumX += fValX;
+ fSumY += fValY;
+ fSumXY += fValX*fValY;
+ fCount++;
+ }
+ }
+ if (fCount < 1.0)
+ SetNoValue();
+ else
+ PushDouble( (fSumXY-fSumX*fSumY/fCount)/fCount);
+}
+
+void ScInterpreter::ScPearson()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+ USHORT nMatInd1, nMatInd2;
+ ScMatrix* pMat1 = GetMatrix(nMatInd2);
+ ScMatrix* pMat2 = GetMatrix(nMatInd1);
+ if (!pMat1 || !pMat2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ USHORT nC1, nR1, nC2, nR2;
+ pMat1->GetDimensions(nC1, nR1);
+ pMat2->GetDimensions(nC2, nR2);
+ if (nR1 != nR2 || nC1 != nC2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ double fCount = 0.0;
+ double fSumX = 0.0;
+ double fSumSqrX = 0.0;
+ double fSumY = 0.0;
+ double fSumSqrY = 0.0;
+ double fSumXY = 0.0;
+ double fValX, fValY;
+ for (USHORT i = 0; i < nC1; i++)
+ for (USHORT j = 0; j < nR1; j++)
+ {
+ if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
+ {
+ fValX = pMat1->GetDouble(i,j);
+ fValY = pMat2->GetDouble(i,j);
+ fSumX += fValX;
+ fSumSqrX += fValX * fValX;
+ fSumY += fValY;
+ fSumSqrY += fValY * fValY;
+ fSumXY += fValX*fValY;
+ fCount++;
+ }
+ }
+ if (fCount < 2.0)
+ SetNoValue();
+ else
+ PushDouble( (fCount*fSumXY-fSumX*fSumY)/
+ sqrt((fCount*fSumSqrX-fSumX*fSumX)*
+ (fCount*fSumSqrY-fSumY*fSumY)));
+}
+
+void ScInterpreter::ScRSQ()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+ USHORT nMatInd1, nMatInd2;
+ ScMatrix* pMat1 = GetMatrix(nMatInd2);
+ ScMatrix* pMat2 = GetMatrix(nMatInd1);
+ if (!pMat1 || !pMat2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ USHORT nC1, nR1, nC2, nR2;
+ pMat1->GetDimensions(nC1, nR1);
+ pMat2->GetDimensions(nC2, nR2);
+ if (nR1 != nR2 || nC1 != nC2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ double fCount = 0.0;
+ double fSumX = 0.0;
+ double fSumSqrX = 0.0;
+ double fSumY = 0.0;
+ double fSumSqrY = 0.0;
+ double fSumXY = 0.0;
+ double fValX, fValY;
+ for (USHORT i = 0; i < nC1; i++)
+ for (USHORT j = 0; j < nR1; j++)
+ {
+ if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
+ {
+ fValX = pMat1->GetDouble(i,j);
+ fValY = pMat2->GetDouble(i,j);
+ fSumX += fValX;
+ fSumSqrX += fValX * fValX;
+ fSumY += fValY;
+ fSumSqrY += fValY * fValY;
+ fSumXY += fValX*fValY;
+ fCount++;
+ }
+ }
+ if (fCount < 2.0)
+ SetNoValue();
+ else
+ PushDouble( (fCount*fSumXY-fSumX*fSumY)*(fCount*fSumXY-fSumX*fSumY)/
+ (fCount*fSumSqrX-fSumX*fSumX)/(fCount*fSumSqrY-fSumY*fSumY));
+}
+
+void ScInterpreter::ScSTEXY()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+ USHORT nMatInd1, nMatInd2;
+ ScMatrix* pMat1 = GetMatrix(nMatInd2);
+ ScMatrix* pMat2 = GetMatrix(nMatInd1);
+ if (!pMat1 || !pMat2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ USHORT nC1, nR1, nC2, nR2;
+ pMat1->GetDimensions(nC1, nR1);
+ pMat2->GetDimensions(nC2, nR2);
+ if (nR1 != nR2 || nC1 != nC2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ double fCount = 0.0;
+ double fSumX = 0.0;
+ double fSumSqrX = 0.0;
+ double fSumY = 0.0;
+ double fSumSqrY = 0.0;
+ double fSumXY = 0.0;
+ double fValX, fValY;
+ for (USHORT i = 0; i < nC1; i++)
+ for (USHORT j = 0; j < nR1; j++)
+ {
+ if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
+ {
+ fValX = pMat1->GetDouble(i,j);
+ fValY = pMat2->GetDouble(i,j);
+ fSumX += fValX;
+ fSumSqrX += fValX * fValX;
+ fSumY += fValY;
+ fSumSqrY += fValY * fValY;
+ fSumXY += fValX*fValY;
+ fCount++;
+ }
+ }
+ if (fCount < 3.0)
+ SetNoValue();
+ else
+ PushDouble(sqrt((fCount*fSumSqrY - fSumY*fSumY -
+ (fCount*fSumXY -fSumX*fSumY)*(fCount*fSumXY -fSumX*fSumY)/
+ (fCount*fSumSqrX-fSumX*fSumX) )/(fCount*(fCount-2.0))));
+}
+
+void ScInterpreter::ScSlope()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+ USHORT nMatInd1, nMatInd2;
+ ScMatrix* pMat1 = GetMatrix(nMatInd2);
+ ScMatrix* pMat2 = GetMatrix(nMatInd1);
+ if (!pMat1 || !pMat2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ USHORT nC1, nR1, nC2, nR2;
+ pMat1->GetDimensions(nC1, nR1);
+ pMat2->GetDimensions(nC2, nR2);
+ if (nR1 != nR2 || nC1 != nC2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ double fCount = 0.0;
+ double fSumX = 0.0;
+ double fSumSqrX = 0.0;
+ double fSumY = 0.0;
+ double fSumXY = 0.0;
+ double fValX, fValY;
+ for (USHORT i = 0; i < nC1; i++)
+ for (USHORT j = 0; j < nR1; j++)
+ {
+ if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
+ {
+ fValX = pMat1->GetDouble(i,j);
+ fValY = pMat2->GetDouble(i,j);
+ fSumX += fValX;
+ fSumSqrX += fValX * fValX;
+ fSumY += fValY;
+ fSumXY += fValX*fValY;
+ fCount++;
+ }
+ }
+ if (fCount < 1.0)
+ SetNoValue();
+ else
+ PushDouble( (fCount*fSumXY-fSumX*fSumY)/
+ (fCount*fSumSqrX-fSumX*fSumX) );
+}
+
+void ScInterpreter::ScIntercept()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+ USHORT nMatInd1, nMatInd2;
+ ScMatrix* pMat1 = GetMatrix(nMatInd2);
+ ScMatrix* pMat2 = GetMatrix(nMatInd1);
+ if (!pMat1 || !pMat2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ USHORT nC1, nR1, nC2, nR2;
+ pMat1->GetDimensions(nC1, nR1);
+ pMat2->GetDimensions(nC2, nR2);
+ if (nR1 != nR2 || nC1 != nC2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ double fCount = 0.0;
+ double fSumX = 0.0;
+ double fSumSqrX = 0.0;
+ double fSumY = 0.0;
+ double fSumXY = 0.0;
+ double fValX, fValY;
+ for (USHORT i = 0; i < nC1; i++)
+ for (USHORT j = 0; j < nR1; j++)
+ {
+ if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
+ {
+ fValX = pMat1->GetDouble(i,j);
+ fValY = pMat2->GetDouble(i,j);
+ fSumX += fValX;
+ fSumSqrX += fValX * fValX;
+ fSumY += fValY;
+ fSumXY += fValX*fValY;
+ fCount++;
+ }
+ }
+ if (fCount < 1.0)
+ SetNoValue();
+ else
+ PushDouble( fSumY/fCount - (fCount*fSumXY-fSumX*fSumY)/
+ (fCount*fSumSqrX-fSumX*fSumX)*fSumX/fCount );
+
+}
+
+void ScInterpreter::ScForecast()
+{
+ if ( !MustHaveParamCount( GetByte(), 3 ) )
+ return;
+ USHORT nMatInd1, nMatInd2;
+ ScMatrix* pMat1 = GetMatrix(nMatInd2);
+ ScMatrix* pMat2 = GetMatrix(nMatInd1);
+ if (!pMat1 || !pMat2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ USHORT nC1, nR1, nC2, nR2;
+ pMat1->GetDimensions(nC1, nR1);
+ pMat2->GetDimensions(nC2, nR2);
+ if (nR1 != nR2 || nC1 != nC2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ double fVal = GetDouble();
+ double fCount = 0.0;
+ double fSumX = 0.0;
+ double fSumSqrX = 0.0;
+ double fSumY = 0.0;
+ double fSumXY = 0.0;
+ double fValX, fValY;
+ for (USHORT i = 0; i < nC1; i++)
+ for (USHORT j = 0; j < nR1; j++)
+ {
+ if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
+ {
+ fValX = pMat1->GetDouble(i,j);
+ fValY = pMat2->GetDouble(i,j);
+ fSumX += fValX;
+ fSumSqrX += fValX * fValX;
+ fSumY += fValY;
+ fSumXY += fValX*fValY;
+ fCount++;
+ }
+ }
+ if (fCount < 1.0)
+ SetNoValue();
+ else
+ PushDouble( fSumY/fCount + (fCount*fSumXY-fSumX*fSumY)/
+ (fCount*fSumSqrX-fSumX*fSumX) * (fVal - fSumX/fCount) );
+}
+
+
+
+
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
new file mode 100644
index 000000000000..2d513350435b
--- /dev/null
+++ b/sc/source/core/tool/interpr4.cxx
@@ -0,0 +1,3588 @@
+/*************************************************************************
+ *
+ * $RCSfile: interpr4.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:18 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#ifdef RS6000
+
+#pragma options FLTTRAP
+#include <fptrap.h>
+#include <fpxcp.h>
+
+#elif defined ( MAC )
+
+#include <MAC_START.h>
+#include <fp.h>
+#include <MAC_END.h>
+#include <ctype.h>
+
+#elif defined ( SOLARIS)
+
+#include <ieeefp.h>
+#include <ctype.h>
+
+#elif defined ( ICC )
+
+#include <ctype.h>
+
+#endif
+
+
+#include <rangelst.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/objsh.hxx>
+#include <basic/sbmeth.hxx>
+#include <basic/sbmod.hxx>
+#include <basic/sbstar.hxx>
+#include <svtools/sbx.hxx>
+#include <svtools/zforlist.hxx>
+#include <tools/urlobj.hxx>
+#include <segmentc.hxx>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <math.h>
+#include <float.h>
+
+#include <com/sun/star/table/XCellRange.hpp>
+
+using namespace com::sun::star;
+
+#include "interpre.hxx"
+#include "global.hxx"
+#include "dbcolect.hxx"
+#include "cell.hxx"
+#include "callform.hxx"
+#include "addincol.hxx"
+#include "document.hxx"
+#include "dociter.hxx"
+#include "docoptio.hxx"
+#include "scmatrix.hxx"
+#include "adiasync.hxx"
+#include "sc.hrc"
+#include "scdll.hxx" // ScLibSignalFunc
+#include "cellsuno.hxx"
+#include "rangeseq.hxx"
+#include "addinlis.hxx"
+
+// Implementiert in ui\miscdlgs\teamdlg.cxx
+
+extern void ShowTheTeam();
+
+extern BOOL bOderSo; // in GLOBAL.CXX
+
+//-----------------------------statische Daten-----------------
+
+const sal_Unicode ScInterpreter::cEmptyString = 0;
+
+USHORT ScInterpreter::nGlobalError = 0; // fuer matherr
+
+#if SOMA_FPSIGNAL_JUMP
+jmp_buf* ScInterpreter::pJumpBuf = NULL; // fuer die mySignal-Funktion
+ScLibSignalFunc ScInterpreter::pSignalFunc = NULL; // signal() Wrapper der App
+#endif
+
+#pragma code_seg("SCSTATICS")
+
+TabOpList ScInterpreter::aTableOpList;
+#if SC_SPEW_ENABLED
+ScSpew ScInterpreter::theSpew;
+#endif
+
+#pragma code_seg()
+
+//-------------------------------------------------------
+
+#if SOMA_FPSIGNAL_JUMP
+
+#if ( defined (MSC) && defined (WIN) && ! ( defined (WNT) ) )
+extern "C" int _matherr(struct _exception *except);
+#elif defined (OS2) && !defined( WTC )
+extern "C" int _matherr(struct exception *except);
+#elif defined (OS2) && defined( WTC )
+extern "C" double _matherr(struct exception *except);
+#elif defined (LINUX)
+extern "C" int matherr(struct __exception *except);
+#elif defined (UNX) && !defined (LINUX)
+extern "C" int matherr(struct exception *except);
+#endif
+
+#ifndef _UNDERFLOW
+#define _UNDERFLOW UNDERFLOW
+#endif
+
+#if ( defined (MSC) && defined (WIN) && ! ( defined (WNT) ) )
+
+
+int _matherr(struct _exception *except)
+{
+ if( except->type == _UNDERFLOW )
+ except->retval = 0.0;
+ else
+ {
+ ScInterpreter::SetError(errIllegalFPOperation);
+ except->retval = 1.0;
+ }
+ return 1;
+};
+
+#elif defined (OS2)
+
+
+#ifndef WTC
+int _matherr(struct exception *except)
+#else
+double _matherr(struct exception *except)
+#endif
+{
+ if( except->type == UNDERFLOW )
+ except->retval = 0.0;
+ else
+ {
+ ScInterpreter::SetError(errIllegalFPOperation);
+ except->retval = 1.0;
+ }
+ return 1;
+};
+#elif ( defined UNX && !defined LINUX )
+
+
+int matherr(struct exception *except)
+{
+ if( except->type == UNDERFLOW )
+ except->retval = 0.0;
+ else
+ {
+ ScInterpreter::SetError(errIllegalFPOperation);
+ except->retval = 1.0;
+ }
+ return 1;
+};
+#endif
+
+#endif
+
+
+void ScInterpreter::MySigFunc(int sig)
+{
+#if SOMA_FPSIGNAL_JUMP
+ SOMA_FPRESET(); // reinitialize math package
+ longjmp(*ScInterpreter::pJumpBuf,1);
+#endif
+}
+
+/* inline:
+
+void ScInterpreter::SetError(USHORT nError)
+{
+ if( nError && !nGlobalError )
+ nGlobalError = nError;
+}
+*/
+
+//-------------------------------------------------------------------------
+// Funktionen für den Zugriff auf das Document
+//-------------------------------------------------------------------------
+
+
+void ScInterpreter::ReplaceCell( ScAddress& rPos )
+{
+ USHORT nCol, nRow, nTab;
+ nCol = rPos.Col();
+ nRow = rPos.Row();
+ nTab = rPos.Tab();
+ USHORT* pTOp = aTableOpList.First();
+ while (pTOp)
+ {
+ if (nCol == pTOp[0] && nRow == pTOp[1] && nTab == pTOp[2])
+ {
+ rPos.Set( pTOp[3], pTOp[4], pTOp[5] );
+ return ;
+ }
+ else if (nCol == pTOp[6] && nRow == pTOp[7] && nTab == pTOp[8])
+ {
+ rPos.Set( pTOp[9], pTOp[10], pTOp[11] );
+ return ;
+ }
+ else
+ pTOp = aTableOpList.Next();
+ }
+}
+
+
+ULONG ScInterpreter::GetCellNumberFormat( const ScAddress& rPos, const ScBaseCell* pCell)
+{
+ ULONG nFormat;
+ USHORT nErr;
+ if ( pCell )
+ {
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA )
+ nErr = ((ScFormulaCell*)pCell)->GetErrCode();
+ else
+ nErr = 0;
+ if ( aTableOpList.Count() > 0 )
+ {
+ ScAddress aAdr( rPos );
+ ReplaceCell( aAdr );
+ nFormat = pDok->GetNumberFormat( aAdr );
+ }
+ else
+ nFormat = pDok->GetNumberFormat( rPos );
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA
+ && ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0) )
+ nFormat = ((ScFormulaCell*)pCell)->GetStandardFormat( *pFormatter,
+ nFormat );
+ }
+ else
+ {
+ nFormat = pDok->GetNumberFormat( rPos );
+ nErr = 0;
+ }
+ SetError(nErr);
+ return nFormat;
+}
+
+
+// nur ValueCell, Formelzellen speichern das Ergebnis bereits gerundet
+double ScInterpreter::GetValueCellValue( const ScAddress& rPos, const ScValueCell* pCell )
+{
+ double fVal = pCell->GetValue();
+ if ( bCalcAsShown && fVal != 0.0 )
+ {
+ ULONG nFormat = pDok->GetNumberFormat( rPos );
+ fVal = pDok->RoundValueAsShown( fVal, nFormat );
+ }
+ return fVal;
+}
+
+
+double ScInterpreter::GetCellValue( const ScAddress& rPos, const ScBaseCell* pCell )
+{
+ USHORT nErr = nGlobalError;
+ nGlobalError = 0;
+ double nVal = GetCellValueOrZero( rPos, pCell );
+ if ( !nGlobalError || nGlobalError == errNoValue )
+ nGlobalError = nErr;
+ return nVal;
+}
+
+
+double ScInterpreter::GetCellValueOrZero( const ScAddress& rPos, const ScBaseCell* pCell )
+{
+ double fValue;
+ if (pCell)
+ {
+ CellType eType = pCell->GetCellType();
+ switch ( eType )
+ {
+ case CELLTYPE_FORMULA:
+ {
+ ScFormulaCell* pFCell = (ScFormulaCell*) pCell;
+ USHORT nErr = pFCell->GetErrCode();
+ if( !nErr )
+ {
+ if (pFCell->IsValue())
+ {
+ fValue = pFCell->GetValue();
+ if ( aTableOpList.Count() > 0 )
+ {
+ ScAddress aAdr( rPos );
+ ReplaceCell( aAdr );
+ pDok->GetNumberFormatInfo( nCurFmtType, nCurFmtIndex,
+ aAdr, *pFCell );
+ }
+ else
+ pDok->GetNumberFormatInfo( nCurFmtType, nCurFmtIndex,
+ rPos, *pFCell );
+ }
+ else
+ {
+ SetError(errNoValue);
+ fValue = 0.0;
+ }
+ }
+ else
+ {
+ fValue = 0.0;
+ SetError(nErr);
+ }
+ }
+ break;
+ case CELLTYPE_VALUE:
+ {
+ fValue = ((ScValueCell*)pCell)->GetValue();
+ if ( aTableOpList.Count() > 0 )
+ {
+ ScAddress aAdr( rPos );
+ ReplaceCell( aAdr );
+ nCurFmtIndex = pDok->GetNumberFormat( aAdr );
+ }
+ else
+ nCurFmtIndex = pDok->GetNumberFormat( rPos );
+ nCurFmtType = pFormatter->GetType( nCurFmtIndex );
+ if ( bCalcAsShown && fValue != 0.0 )
+ fValue = pDok->RoundValueAsShown( fValue, nCurFmtIndex );
+ }
+ break;
+ case CELLTYPE_STRING:
+ case CELLTYPE_EDIT:
+#if 0
+// Xcl macht es so, aber dann gibt z.B. SUMME(A1:A2) was anderes als A1+A2.
+// In dem Fall muesste GetCellValue den errNoValue auch durchreichen.
+ {
+ String aStr;
+ if ( eType == CELLTYPE_STRING )
+ ((ScStringCell*)pCell)->GetString( aStr );
+ else
+ ((ScEditCell*)pCell)->GetString( aStr );
+ ULONG nFIndex = 0; // damit default Land/Spr.
+ if ( !pFormatter->IsNumberFormat( aStr, nFIndex, fValue ) )
+ {
+ SetError(errNoValue);
+ fValue = 0.0;
+ }
+ }
+ break;
+#endif
+ default:
+ SetError(errNoValue);
+ fValue = 0.0;
+ }
+ }
+ else
+ fValue = 0.0;
+ return fValue;
+}
+
+
+ScBaseCell* ScInterpreter::GetCell( const ScAddress& rPos )
+{
+ if (aTableOpList.Count() > 0)
+ {
+ ScAddress aTmp( rPos );
+ ReplaceCell( aTmp );
+ return pDok->GetCell( aTmp );
+ }
+ return pDok->GetCell( rPos );
+}
+
+
+void ScInterpreter::GetCellString( String& rStr, const ScBaseCell* pCell )
+{
+ USHORT nErr = 0;
+ if (pCell)
+ {
+ switch (pCell->GetCellType())
+ {
+ case CELLTYPE_STRING:
+ {
+ ((ScStringCell*) pCell)->GetString(rStr);
+ if (rStr.Len() >= MAXSTRLEN)
+ {
+ rStr.Erase();
+ nErr = errStringOverflow;
+ }
+ }
+ break;
+ case CELLTYPE_EDIT:
+ {
+ ((ScEditCell*) pCell)->GetString(rStr);
+ if (rStr.Len() >= MAXSTRLEN)
+ {
+ rStr.Erase();
+ nErr = errStringOverflow;
+ }
+ }
+ break;
+ case CELLTYPE_FORMULA:
+ {
+ ScFormulaCell* pFCell = (ScFormulaCell*) pCell;
+ nErr = pFCell->GetErrCode();
+ if (pFCell->IsValue())
+ {
+ double fVal = pFCell->GetValue();
+ ULONG nIndex = pFormatter->GetStandardFormat(
+ NUMBERFORMAT_NUMBER,
+ ScGlobal::eLnge);
+ pFormatter->GetInputLineString(fVal, nIndex, rStr);
+ }
+ else
+ pFCell->GetString(rStr);
+ }
+ break;
+ case CELLTYPE_VALUE:
+ {
+ double fVal = ((ScValueCell*) pCell)->GetValue();
+ ULONG nIndex = pFormatter->GetStandardFormat(
+ NUMBERFORMAT_NUMBER,
+ ScGlobal::eLnge);
+ pFormatter->GetInputLineString(fVal, nIndex, rStr);
+ }
+ break;
+ default:
+ rStr = ScGlobal::GetEmptyString();
+ break;
+ }
+ }
+ else
+ rStr = ScGlobal::GetEmptyString();
+ SetError(nErr);
+}
+
+
+USHORT ScInterpreter::GetCellErrCode( const ScBaseCell* pCell )
+{
+ if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
+ return ((ScFormulaCell*)pCell)->GetErrCode();
+ return 0;
+}
+
+
+BOOL ScInterpreter::CreateDoubleArr(USHORT nCol1, USHORT nRow1, USHORT nTab1,
+ USHORT nCol2, USHORT nRow2, USHORT nTab2, BYTE* pCellArr)
+{
+ USHORT nCount = 0;
+ USHORT* p = (USHORT*) pCellArr;
+ *p++ = nCol1;
+ *p++ = nRow1;
+ *p++ = nTab1;
+ *p++ = nCol2;
+ *p++ = nRow2;
+ *p++ = nTab2;
+ USHORT* pCount = p;
+ *p++ = 0;
+ USHORT nPos = 14;
+ USHORT nTab = nTab1;
+ ScAddress aAdr;
+ while (nTab <= nTab2)
+ {
+ aAdr.SetTab( nTab );
+ USHORT nRow = nRow1;
+ while (nRow <= nRow2)
+ {
+ aAdr.SetRow( nRow );
+ USHORT nCol = nCol1;
+ while (nCol <= nCol2)
+ {
+ aAdr.SetCol( nCol );
+ ScBaseCell* pCell = pDok->GetCell( aAdr );
+ if (pCell)
+ {
+ USHORT nErr = 0;
+ double nVal = 0.0;
+ BOOL bOk = TRUE;
+ switch ( pCell->GetCellType() )
+ {
+ case CELLTYPE_VALUE :
+ nVal = GetValueCellValue( aAdr, (ScValueCell*)pCell );
+ break;
+ case CELLTYPE_FORMULA :
+ if (((ScFormulaCell*)pCell)->IsValue())
+ {
+ nErr = ((ScFormulaCell*)pCell)->GetErrCode();
+ nVal = ((ScFormulaCell*)pCell)->GetValue();
+ }
+ else
+ bOk = FALSE;
+ break;
+ default :
+ bOk = FALSE;
+ break;
+ }
+ if (bOk)
+ {
+ if ((nPos + (4 * sizeof(USHORT)) + sizeof(double)) > MAXARRSIZE)
+ return FALSE;
+ *p++ = nCol;
+ *p++ = nRow;
+ *p++ = nTab;
+ *p++ = nErr;
+ memcpy( p, &nVal, sizeof(double));
+ nPos += 8 + sizeof(double);
+ p = (USHORT*) ( pCellArr + nPos );
+ nCount++;
+ }
+ }
+ nCol++;
+ }
+ nRow++;
+ }
+ nTab++;
+ }
+ *pCount = nCount;
+ return TRUE;
+}
+
+
+BOOL ScInterpreter::CreateStringArr(USHORT nCol1, USHORT nRow1, USHORT nTab1,
+ USHORT nCol2, USHORT nRow2, USHORT nTab2,
+ BYTE* pCellArr)
+{
+ USHORT nCount = 0;
+ USHORT* p = (USHORT*) pCellArr;
+ *p++ = nCol1;
+ *p++ = nRow1;
+ *p++ = nTab1;
+ *p++ = nCol2;
+ *p++ = nRow2;
+ *p++ = nTab2;
+ USHORT* pCount = p;
+ *p++ = 0;
+ USHORT nPos = 14;
+ USHORT nTab = nTab1;
+ while (nTab <= nTab2)
+ {
+ USHORT nRow = nRow1;
+ while (nRow <= nRow2)
+ {
+ USHORT nCol = nCol1;
+ while (nCol <= nCol2)
+ {
+ ScBaseCell* pCell;
+ pDok->GetCell(nCol, nRow, nTab, pCell);
+ if (pCell)
+ {
+ String aStr;
+ USHORT nErr = 0;
+ BOOL bOk = TRUE;
+ switch ( pCell->GetCellType() )
+ {
+ case CELLTYPE_STRING :
+ ((ScStringCell*)pCell)->GetString(aStr);
+ break;
+ case CELLTYPE_EDIT :
+ ((ScEditCell*)pCell)->GetString(aStr);
+ break;
+ case CELLTYPE_FORMULA :
+ if (!((ScFormulaCell*)pCell)->IsValue())
+ {
+ nErr = ((ScFormulaCell*)pCell)->GetErrCode();
+ ((ScFormulaCell*)pCell)->GetString(aStr);
+ }
+ else
+ bOk = FALSE;
+ break;
+ default :
+ bOk = FALSE;
+ break;
+ }
+ if (bOk)
+ {
+ ByteString aTmp( aStr, osl_getThreadTextEncoding() );
+ // Wir schummeln hier und haengen ein 0-Byte dran,
+ // falls die Stringlaenge ungerade werden sollte!
+ //! MUST be USHORT and not xub_StrLen
+ USHORT nStrLen = (USHORT) aTmp.Len();
+ USHORT nLen = ( nStrLen + 2 ) & ~1;
+
+ if ((nPos + (5 * sizeof(USHORT)) + nLen) > MAXARRSIZE)
+ return FALSE;
+ *p++ = nCol;
+ *p++ = nRow;
+ *p++ = nTab;
+ *p++ = nErr;
+ *p++ = nLen;
+ memcpy( p, aTmp.GetBuffer(), nStrLen + 1);
+ nPos += 10 + nStrLen + 1;
+ BYTE* q = ( pCellArr + nPos );
+ if( !nStrLen & 1 )
+ *q++ = 0, nPos++;
+ p = (USHORT*) ( pCellArr + nPos );
+ nCount++;
+ }
+ }
+ nCol++;
+ }
+ nRow++;
+ }
+ nTab++;
+ }
+ *pCount = nCount;
+ return TRUE;
+}
+
+
+BOOL ScInterpreter::CreateCellArr(USHORT nCol1, USHORT nRow1, USHORT nTab1,
+ USHORT nCol2, USHORT nRow2, USHORT nTab2,
+ BYTE* pCellArr)
+{
+ USHORT nCount = 0;
+ USHORT* p = (USHORT*) pCellArr;
+ *p++ = nCol1;
+ *p++ = nRow1;
+ *p++ = nTab1;
+ *p++ = nCol2;
+ *p++ = nRow2;
+ *p++ = nTab2;
+ USHORT* pCount = p;
+ *p++ = 0;
+ USHORT nPos = 14;
+ USHORT nTab = nTab1;
+ ScAddress aAdr;
+ while (nTab <= nTab2)
+ {
+ aAdr.SetTab( nTab );
+ USHORT nRow = nRow1;
+ while (nRow <= nRow2)
+ {
+ aAdr.SetRow( nRow );
+ USHORT nCol = nCol1;
+ while (nCol <= nCol2)
+ {
+ aAdr.SetCol( nCol );
+ ScBaseCell* pCell = pDok->GetCell( aAdr );
+ if (pCell)
+ {
+ USHORT nErr = 0;
+ USHORT nType = 0; // 0 = Zahl; 1 = String
+ double nVal = 0.0;
+ String aStr;
+ BOOL bOk = TRUE;
+ switch ( pCell->GetCellType() )
+ {
+ case CELLTYPE_STRING :
+ ((ScStringCell*)pCell)->GetString(aStr);
+ nType = 1;
+ break;
+ case CELLTYPE_EDIT :
+ ((ScEditCell*)pCell)->GetString(aStr);
+ nType = 1;
+ break;
+ case CELLTYPE_VALUE :
+ nVal = GetValueCellValue( aAdr, (ScValueCell*)pCell );
+ break;
+ case CELLTYPE_FORMULA :
+ nErr = ((ScFormulaCell*)pCell)->GetErrCode();
+ if (((ScFormulaCell*)pCell)->IsValue())
+ nVal = ((ScFormulaCell*)pCell)->GetValue();
+ else
+ ((ScFormulaCell*)pCell)->GetString(aStr);
+ break;
+ default :
+ bOk = FALSE;
+ break;
+ }
+ if (bOk)
+ {
+ if ((nPos + (5 * sizeof(USHORT))) > MAXARRSIZE)
+ return FALSE;
+ *p++ = nCol;
+ *p++ = nRow;
+ *p++ = nTab;
+ *p++ = nErr;
+ *p++ = nType;
+ nPos += 10;
+ if (nType == 0)
+ {
+ if ((nPos + sizeof(double)) > MAXARRSIZE)
+ return FALSE;
+ memcpy( p, &nVal, sizeof(double));
+ nPos += sizeof(double);
+ }
+ else
+ {
+ ByteString aTmp( aStr, osl_getThreadTextEncoding() );
+ // Wir schummeln hier und haengen ein 0-Byte dran,
+ // falls die Stringlaenge ungerade werden sollte!
+ //! MUST be USHORT and not xub_StrLen
+ USHORT nStrLen = (USHORT) aTmp.Len();
+ USHORT nLen = ( nStrLen + 2 ) & ~1;
+ if ((nPos + 2 + nLen) > MAXARRSIZE)
+ return FALSE;
+ *p++ = nLen;
+ memcpy( p, aTmp.GetBuffer(), nStrLen + 1);
+ nPos += 2 + nStrLen + 1;
+ BYTE* q = ( pCellArr + nPos );
+ if( !nStrLen & 1 )
+ *q++ = 0, nPos++;
+ }
+ nCount++;
+ p = (USHORT*) ( pCellArr + nPos );
+ }
+ }
+ nCol++;
+ }
+ nRow++;
+ }
+ nTab++;
+ }
+ *pCount = nCount;
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// Stackoperationen
+//-----------------------------------------------------------------------------
+
+// vorher wird ggf. ein Temp-Token geloescht.
+
+
+void ScInterpreter::Push( ScToken& r )
+{
+ if ( sp >= MAXSTACK )
+ SetError( errStackOverflow );
+ else
+ {
+ nCurFmtType = NUMBERFORMAT_UNDEFINED;
+ r.IncRef();
+ if( sp >= maxsp )
+ maxsp = sp + 1;
+ else
+ pStack[ sp ]->DecRef();
+ pStack[ sp ] = (ScToken*) &r;
+ pErrorStack[ sp ] = nGlobalError;
+ ++sp;
+ }
+}
+
+// Schlichtes Wegwerfen von TOS
+
+
+void ScInterpreter::Pop()
+{
+ if( sp )
+ sp--;
+ else
+ SetError(errUnknownStackVariable);
+}
+
+// Schlichtes Wegwerfen von TOS mit Fehlercode setzen, fuer ocIsError etc.
+
+
+void ScInterpreter::PopError()
+{
+ if( sp )
+ {
+ sp--;
+ if ( !nGlobalError )
+ nGlobalError = pErrorStack[ sp ];
+ }
+ else
+ SetError(errUnknownStackVariable);
+}
+
+
+void ScInterpreter::PushTempToken( const ScToken& r )
+{
+ if ( sp >= MAXSTACK )
+ SetError( errStackOverflow );
+ else
+ {
+ ScToken* p = r.Clone();
+ p->IncRef();
+ if( sp >= maxsp )
+ maxsp = sp + 1;
+ else
+ pStack[ sp ]->DecRef();
+ pStack[ sp ] = p;
+ pErrorStack[ sp ] = nGlobalError;
+ ++sp;
+ }
+}
+
+
+//! Nur fuer PushDouble/PushInt!
+//! Das Token wurde per new angelegt und darf nach diesem Aufruf wg.
+//! eventuellem delete bei errStackOverflow nicht mehr benutzt werden, falls
+//! nicht ein RefCount gesetzt wurde!
+void ScInterpreter::PushTempToken( ScDoubleToken* p )
+{
+ ((ScToken*)p)->IncRef();
+ if ( sp >= MAXSTACK )
+ {
+ SetError( errStackOverflow );
+ ((ScToken*)p)->DecRef();
+ }
+ else
+ {
+ if( sp >= maxsp )
+ maxsp = sp + 1;
+ else
+ pStack[ sp ]->DecRef();
+ pStack[ sp ] = (ScToken*) p;
+ pErrorStack[ sp ] = nGlobalError;
+ ++sp;
+ }
+}
+
+
+double ScInterpreter::PopDouble()
+{
+ nCurFmtType = NUMBERFORMAT_NUMBER;
+ nCurFmtIndex = 0;
+ if( sp )
+ {
+ --sp;
+ ScToken* p = pStack[ sp ];
+ if ( !nGlobalError )
+ nGlobalError = pErrorStack[ sp ];
+ if( p->GetType() == svDouble )
+ return p->nValue;
+ else if( p->GetType() == svMissing )
+ return 0;
+ }
+ SetError(errUnknownStackVariable);
+ return 0;
+}
+
+
+BYTE ScInterpreter::PopByte()
+{
+ if( sp )
+ {
+ --sp;
+ ScToken* p = pStack[ sp ];
+ if ( !nGlobalError )
+ nGlobalError = pErrorStack[ sp ];
+ if( p->GetType() == svByte )
+ return p->cByte;
+ else if( p->GetType() == svMissing )
+ SetError( errIllegalParameter );
+ }
+ SetError(errUnknownStackVariable);
+ return 0;
+}
+
+
+const sal_Unicode* ScInterpreter::PopString()
+{
+ nCurFmtType = NUMBERFORMAT_TEXT;
+ nCurFmtIndex = 0;
+ if( sp )
+ {
+ --sp;
+ ScToken* p = pStack[ sp ];
+ if ( !nGlobalError )
+ nGlobalError = pErrorStack[ sp ];
+ if( p->GetType() == svString )
+ return p->cStr;
+ else if( p->GetType() == svMissing )
+ return &cEmptyString;
+ }
+ SetError(errUnknownStackVariable);
+ return &cEmptyString;
+}
+
+
+void ScInterpreter::PopSingleRef(USHORT& rCol, USHORT &rRow, USHORT& rTab)
+{
+ if( sp )
+ {
+ --sp;
+ ScToken* p = pStack[ sp ];
+ if ( !nGlobalError )
+ nGlobalError = pErrorStack[ sp ];
+ if( p->GetType() == svSingleRef )
+ {
+ const SingleRefData& aRef = p->aRef.Ref1;
+ if ( aRef.IsColRel() )
+ rCol = aPos.Col() + aRef.nRelCol;
+ else
+ rCol = aRef.nCol;
+ if ( aRef.IsRowRel() )
+ rRow = aPos.Row() + aRef.nRelRow;
+ else
+ rRow = aRef.nRow;
+ if ( aRef.IsTabRel() )
+ rTab = aPos.Tab() + aRef.nRelTab;
+ else
+ rTab = aRef.nTab;
+ if( rCol < 0 || rCol > MAXCOL || aRef.IsColDeleted() )
+ SetError( errNoRef ), rCol = 0;
+ if( rRow < 0 || rRow > MAXROW || aRef.IsRowDeleted() )
+ SetError( errNoRef ), rRow = 0;
+ if( rTab < 0 || rTab >= pDok->GetTableCount() || aRef.IsTabDeleted() )
+ SetError( errNoRef ), rTab = 0;
+ return;
+ }
+ else if( p->GetType() == svMissing )
+ SetError( errIllegalParameter );
+ }
+ SetError(errUnknownStackVariable);
+}
+
+
+void ScInterpreter::PopSingleRef( ScAddress& rAdr )
+{
+ if( sp )
+ {
+ --sp;
+ ScToken* p = pStack[ sp ];
+ if ( !nGlobalError )
+ nGlobalError = pErrorStack[ sp ];
+ if( p->GetType() == svSingleRef )
+ {
+ short nCol, nRow, nTab;
+ const SingleRefData& aRef = p->aRef.Ref1;
+ if ( aRef.IsColRel() )
+ nCol = aPos.Col() + aRef.nRelCol;
+ else
+ nCol = aRef.nCol;
+ if ( aRef.IsRowRel() )
+ nRow = aPos.Row() + aRef.nRelRow;
+ else
+ nRow = aRef.nRow;
+ if ( aRef.IsTabRel() )
+ nTab = aPos.Tab() + aRef.nRelTab;
+ else
+ nTab = aRef.nTab;
+ if( nCol < 0 || nCol > MAXCOL || aRef.IsColDeleted() )
+ SetError( errNoRef ), nCol = 0;
+ if( nRow < 0 || nRow > MAXROW || aRef.IsRowDeleted() )
+ SetError( errNoRef ), nRow = 0;
+ if( nTab < 0 || nTab >= pDok->GetTableCount() || aRef.IsTabDeleted() )
+ SetError( errNoRef ), nTab = 0;
+ rAdr.Set( (USHORT)nCol, (USHORT)nRow, (USHORT)nTab );
+ return;
+ }
+ else if( p->GetType() == svMissing )
+ SetError( errIllegalParameter );
+ }
+ SetError(errUnknownStackVariable);
+}
+
+
+void ScInterpreter::PopDoubleRef(USHORT& rCol1, USHORT &rRow1, USHORT& rTab1,
+ USHORT& rCol2, USHORT &rRow2, USHORT& rTab2)
+{
+ if( sp )
+ {
+ --sp;
+ ScToken* p = pStack[ sp ];
+ if ( !nGlobalError )
+ nGlobalError = pErrorStack[ sp ];
+ if( p->GetType() == svDoubleRef )
+ {
+ USHORT nMaxTab = pDok->GetTableCount();
+ {
+ const SingleRefData& aRef = p->aRef.Ref1;
+ if ( aRef.IsColRel() )
+ rCol1 = aPos.Col() + aRef.nRelCol;
+ else
+ rCol1 = aRef.nCol;
+ if ( aRef.IsRowRel() )
+ rRow1 = aPos.Row() + aRef.nRelRow;
+ else
+ rRow1 = aRef.nRow;
+ if ( aRef.IsTabRel() )
+ rTab1 = aPos.Tab() + aRef.nRelTab;
+ else
+ rTab1 = aRef.nTab;
+ if( rCol1 < 0 || rCol1 > MAXCOL || aRef.IsColDeleted() )
+ SetError( errNoRef ), rCol1 = 0;
+ if( rRow1 < 0 || rRow1 > MAXROW || aRef.IsRowDeleted() )
+ SetError( errNoRef ), rRow1 = 0;
+ if( rTab1 < 0 || rTab1 >= nMaxTab || aRef.IsTabDeleted() )
+ SetError( errNoRef ), rTab1 = 0;
+ }
+ {
+ const SingleRefData& aRef = p->aRef.Ref2;
+ if ( aRef.IsColRel() )
+ rCol2 = aPos.Col() + aRef.nRelCol;
+ else
+ rCol2 = aRef.nCol;
+ if ( aRef.IsRowRel() )
+ rRow2 = aPos.Row() + aRef.nRelRow;
+ else
+ rRow2 = aRef.nRow;
+ if ( aRef.IsTabRel() )
+ rTab2 = aPos.Tab() + aRef.nRelTab;
+ else
+ rTab2 = aRef.nTab;
+ if( rCol2 < 0 || rCol2 > MAXCOL || aRef.IsColDeleted() )
+ SetError( errNoRef ), rCol2 = 0;
+ if( rRow2 < 0 || rRow2 > MAXROW || aRef.IsRowDeleted() )
+ SetError( errNoRef ), rRow2 = 0;
+ if( rTab2 < 0 || rTab2 >= nMaxTab || aRef.IsTabDeleted() )
+ SetError( errNoRef ), rTab2 = 0;
+ }
+ return;
+ }
+ else if( p->GetType() == svMissing )
+ SetError( errIllegalParameter );
+ }
+ SetError(errUnknownStackVariable);
+}
+
+
+void ScInterpreter::PopDoubleRef( ScRange& rRange )
+{
+ if( sp )
+ {
+ --sp;
+ ScToken* p = pStack[ sp ];
+ if ( !nGlobalError )
+ nGlobalError = pErrorStack[ sp ];
+ if( p->GetType() == svDoubleRef )
+ {
+ short nCol, nRow, nTab;
+ USHORT nMaxTab = pDok->GetTableCount();
+ {
+ const SingleRefData& aRef = p->aRef.Ref1;
+ if ( aRef.IsColRel() )
+ nCol = aPos.Col() + aRef.nRelCol;
+ else
+ nCol = aRef.nCol;
+ if ( aRef.IsRowRel() )
+ nRow = aPos.Row() + aRef.nRelRow;
+ else
+ nRow = aRef.nRow;
+ if ( aRef.IsTabRel() )
+ nTab = aPos.Tab() + aRef.nRelTab;
+ else
+ nTab = aRef.nTab;
+ if( nCol < 0 || nCol > MAXCOL || aRef.IsColDeleted() )
+ SetError( errNoRef ), nCol = 0;
+ if( nRow < 0 || nRow > MAXROW || aRef.IsRowDeleted() )
+ SetError( errNoRef ), nRow = 0;
+ if( nTab < 0 || nTab >= nMaxTab || aRef.IsTabDeleted() )
+ SetError( errNoRef ), nTab = 0;
+ rRange.aStart.Set( (USHORT)nCol, (USHORT)nRow, (USHORT)nTab );
+ }
+ {
+ const SingleRefData& aRef = p->aRef.Ref2;
+ if ( aRef.IsColRel() )
+ nCol = aPos.Col() + aRef.nRelCol;
+ else
+ nCol = aRef.nCol;
+ if ( aRef.IsRowRel() )
+ nRow = aPos.Row() + aRef.nRelRow;
+ else
+ nRow = aRef.nRow;
+ if ( aRef.IsTabRel() )
+ nTab = aPos.Tab() + aRef.nRelTab;
+ else
+ nTab = aRef.nTab;
+ if( nCol < 0 || nCol > MAXCOL || aRef.IsColDeleted() )
+ SetError( errNoRef ), nCol = 0;
+ if( nRow < 0 || nRow > MAXROW || aRef.IsRowDeleted() )
+ SetError( errNoRef ), nRow = 0;
+ if( nTab < 0 || nTab >= nMaxTab || aRef.IsTabDeleted() )
+ SetError( errNoRef ), nTab = 0;
+ rRange.aEnd.Set( (USHORT)nCol, (USHORT)nRow, (USHORT)nTab );
+ }
+ return;
+ }
+ else if( p->GetType() == svMissing )
+ SetError( errIllegalParameter );
+ }
+ SetError(errUnknownStackVariable);
+}
+
+
+BOOL ScInterpreter::PopDoubleRefOrSingleRef( ScAddress& rAdr )
+{
+ switch ( GetStackType() )
+ {
+ case svDoubleRef :
+ {
+ ScRange aRange;
+ PopDoubleRef( aRange );
+ return DoubleRefToPosSingleRef( aRange, rAdr );
+ }
+ break;
+ case svSingleRef :
+ {
+ PopSingleRef( rAdr );
+ return TRUE;
+ }
+ break;
+ default:
+ Pop();
+ SetError( errNoRef );
+ }
+ return FALSE;
+}
+
+
+void ScInterpreter::PopDoubleRefPushMatrix()
+{
+ if ( GetStackType() == svDoubleRef )
+ {
+ USHORT nMatInd;
+ ScMatrix* pMat = GetMatrix( nMatInd );
+ if ( pMat )
+ {
+ PushMatrix( pMat );
+ nRetMat = nMatInd;
+ }
+ else
+ SetIllegalParameter();
+ }
+ else
+ SetError( errNoRef );
+}
+
+
+ScMatrix* ScInterpreter::PopMatrix()
+{
+ if( sp )
+ {
+ --sp;
+ ScToken* p = pStack[ sp ];
+ if ( !nGlobalError )
+ nGlobalError = pErrorStack[ sp ];
+ if( p->GetType() == svMatrix )
+ return p->pMat;
+ else if( p->GetType() == svMissing )
+ SetError( errIllegalParameter );
+ }
+ SetError(errUnknownVariable);
+ return NULL;
+}
+
+
+
+void ScInterpreter::PushDouble(double nVal)
+{
+#if !SOMA_FPSIGNAL_JUMP
+ if (!SOMA_FINITE(nVal))
+ {
+ nVal = 0.0;
+ SetError(errIllegalFPOperation);
+ }
+#endif
+ ScDoubleToken* pToken = new ScDoubleToken;
+ ((ScToken*)pToken)->SetDouble( nVal );
+ ((ScToken*)pToken)->bRaw = FALSE;
+ PushTempToken( pToken );
+}
+
+
+void ScInterpreter::PushInt(int nVal)
+{
+ ScDoubleToken* pToken = new ScDoubleToken;
+ ((ScToken*)pToken)->SetInt( nVal );
+ ((ScToken*)pToken)->bRaw = FALSE;
+ PushTempToken( pToken );
+}
+
+
+void ScInterpreter::PushString( const sal_Unicode* cString )
+{
+ ScToken aToken;
+ aToken.SetString( cString );
+ PushTempToken( aToken );
+}
+
+
+void ScInterpreter::PushStringObject(const String& aString)
+{
+ if( aString.Len() >= MAXSTRLEN )
+ {
+ SetError( errStringOverflow );
+ PushString( NULL );
+ }
+ else
+ PushString( aString.GetBuffer() );
+}
+
+
+void ScInterpreter::PushSingleRef(USHORT nCol, USHORT nRow, USHORT nTab)
+{
+ ScToken aToken;
+ SingleRefData aRef;
+ aRef.InitFlags();
+ aRef.nCol = nCol;
+ aRef.nRow = nRow;
+ aRef.nTab = nTab;
+ aToken.SetSingleReference( aRef );
+ PushTempToken( aToken );
+}
+
+
+void ScInterpreter::PushDoubleRef(USHORT nCol1, USHORT nRow1, USHORT nTab1,
+ USHORT nCol2, USHORT nRow2, USHORT nTab2)
+{
+ ScToken aToken;
+ ComplRefData aRef;
+ aRef.InitFlags();
+ aRef.Ref1.nCol = nCol1;
+ aRef.Ref1.nRow = nRow1;
+ aRef.Ref1.nTab = nTab1;
+ aRef.Ref2.nCol = nCol2;
+ aRef.Ref2.nRow = nRow2;
+ aRef.Ref2.nTab = nTab2;
+ aToken.SetDoubleReference( aRef );
+ PushTempToken( aToken );
+}
+
+
+void ScInterpreter::PushMatrix(ScMatrix* pMat)
+{
+ ScToken aToken;
+ aToken.SetMatrix( pMat );
+ PushTempToken( aToken );
+}
+
+
+void ScInterpreter::SetParameterExpected()
+{
+ SetError(errParameterExpected);
+ PushInt(0);
+}
+
+
+void ScInterpreter::SetIllegalParameter()
+{
+ SetError(errIllegalParameter);
+ PushInt(0);
+}
+
+
+void ScInterpreter::SetIllegalArgument()
+{
+ SetError(errIllegalArgument);
+ PushInt(0);
+}
+
+
+void ScInterpreter::SetNV()
+{
+ SetError(NOVALUE);
+ PushInt(0);
+}
+
+
+void ScInterpreter::SetNoValue()
+{
+ SetError(errNoValue);
+ PushInt(0);
+}
+
+
+BYTE ScInterpreter::GetStackType()
+{
+ StackVar eRes;
+ if( sp )
+ {
+ eRes = pStack[sp - 1]->GetType();
+ if( eRes == svMissing )
+ eRes = svDouble; // default!
+ }
+ else
+ {
+ SetError(errUnknownStackVariable);
+ eRes = svErr;
+ }
+ return eRes;
+}
+
+
+StackVar ScInterpreter::GetStackType( BYTE nParam )
+{
+ StackVar eRes;
+ if( sp > nParam-1 )
+ {
+ eRes = pStack[sp - nParam]->GetType();
+ if( eRes == svMissing )
+ eRes = svDouble; // default!
+ }
+ else
+ eRes = svErr;
+ return eRes;
+}
+
+
+BOOL ScInterpreter::DoubleRefToPosSingleRef( const ScRange& rRange, ScAddress& rAdr )
+{
+ USHORT nMyCol = aPos.Col();
+ USHORT nMyRow = aPos.Row();
+ USHORT nMyTab = aPos.Tab();
+ USHORT nCol, nRow, nTab;
+ nTab = rRange.aStart.Tab();
+ BOOL bOk = FALSE;
+ if ( rRange.aStart.Col() <= nMyCol && nMyCol <= rRange.aEnd.Col() )
+ {
+ nRow = rRange.aStart.Row();
+ if ( nRow == rRange.aEnd.Row() )
+ {
+ bOk = TRUE;
+ nCol = nMyCol;
+ }
+ else if ( nTab != nMyTab && nTab == rRange.aEnd.Tab()
+ && rRange.aStart.Row() <= nMyRow && nMyRow <= rRange.aEnd.Row() )
+ {
+ bOk = TRUE;
+ nCol = nMyCol;
+ nRow = nMyRow;
+ }
+ }
+ else if ( rRange.aStart.Row() <= nMyRow && nMyRow <= rRange.aEnd.Row() )
+ {
+ nCol = rRange.aStart.Col();
+ if ( nCol == rRange.aEnd.Col() )
+ {
+ bOk = TRUE;
+ nRow = nMyRow;
+ }
+ else if ( nTab != nMyTab && nTab == rRange.aEnd.Tab()
+ && rRange.aStart.Col() <= nMyCol && nMyCol <= rRange.aEnd.Col() )
+ {
+ bOk = TRUE;
+ nCol = nMyCol;
+ nRow = nMyRow;
+ }
+ }
+ if ( bOk )
+ {
+ if ( nTab == rRange.aEnd.Tab() )
+ ; // all done
+ else if ( nTab <= nMyTab && nMyTab <= rRange.aEnd.Tab() )
+ nTab = nMyTab;
+ else
+ bOk = FALSE;
+ if ( bOk )
+ rAdr.Set( nCol, nRow, nTab );
+ }
+ if ( !bOk )
+ SetError( errNoValue );
+ return bOk;
+}
+
+
+double ScInterpreter::GetDouble()
+{
+ double nVal;
+ switch( GetStackType() )
+ {
+ case svDouble:
+ nVal = PopDouble(); break;
+ case svString:
+ {
+ String aStr(PopString());
+ ULONG nFIndex = 0; // damit default Land/Spr.
+ if(!pFormatter->IsNumberFormat( aStr, nFIndex, nVal ) )
+ {
+ SetError(errIllegalArgument);
+ nVal = 0.0;
+ }
+ break;
+ }
+ case svSingleRef:
+ {
+ ScAddress aAdr;
+ PopSingleRef( aAdr );
+ ScBaseCell* pCell = GetCell( aAdr );
+ nVal = GetCellValue( aAdr, pCell );
+ break;
+ }
+ case svDoubleRef:
+ { // positionsabhaengige SingleRef generieren
+ ScRange aRange;
+ PopDoubleRef( aRange );
+ ScAddress aAdr;
+ if ( !nGlobalError && DoubleRefToPosSingleRef( aRange, aAdr ) )
+ {
+ ScBaseCell* pCell = GetCell( aAdr );
+ nVal = GetCellValue( aAdr, pCell );
+ }
+ else
+ nVal = 0.0;
+ }
+ break;
+ default:
+ Pop();
+ SetError(errIllegalParameter);
+ nVal = 0.0;
+ }
+ if ( nFuncFmtType == nCurFmtType )
+ nFuncFmtIndex = nCurFmtIndex;
+ return nVal;
+}
+
+
+const sal_Unicode* ScInterpreter::GetString()
+{
+ const sal_Unicode* p;
+ StackVar eRes = (StackVar) GetStackType();
+ if( eRes == svDouble && pStack[ sp-1 ]->GetType() == svMissing )
+ eRes = svString;
+ switch( eRes )
+ {
+ case svDouble:
+ {
+ double fVal = PopDouble();
+ ULONG nIndex = pFormatter->GetStandardFormat(
+ NUMBERFORMAT_NUMBER,
+ ScGlobal::eLnge);
+ pFormatter->GetInputLineString(fVal, nIndex, aTempStr);
+ p = aTempStr.GetBuffer();
+ break;
+ }
+ case svString:
+ p = PopString(); break;
+ case svSingleRef:
+ {
+ ScAddress aAdr;
+ PopSingleRef( aAdr );
+ if (nGlobalError == 0)
+ {
+ ScBaseCell* pCell = GetCell( aAdr );
+ GetCellString( aTempStr, pCell );
+ p = aTempStr.GetBuffer();
+ }
+ else
+ p = &cEmptyString;
+ break;
+ }
+ case svDoubleRef:
+ { // positionsabhaengige SingleRef generieren
+ ScRange aRange;
+ PopDoubleRef( aRange );
+ ScAddress aAdr;
+ if ( !nGlobalError && DoubleRefToPosSingleRef( aRange, aAdr ) )
+ {
+ ScBaseCell* pCell = GetCell( aAdr );
+ GetCellString( aTempStr, pCell );
+ p = aTempStr.GetBuffer();
+ }
+ else
+ p = &cEmptyString;
+ }
+ break;
+ default:
+ Pop();
+ SetError(errIllegalParameter);
+ p = &cEmptyString;
+ }
+ return p;
+}
+
+
+void ScInterpreter::ScDBGet()
+{
+ USHORT nTab;
+ ScQueryParam aQueryParam;
+ if (GetDBParams(nTab, aQueryParam))
+ {
+ ScBaseCell* pCell;
+ ScQueryCellIterator aCellIter(pDok, nTab, aQueryParam);
+ if (pCell = aCellIter.GetFirst())
+ {
+ if (aCellIter.GetNext())
+ SetIllegalArgument();
+ else
+ {
+ switch (pCell->GetCellType())
+ {
+ case CELLTYPE_VALUE:
+ {
+ double rValue = ((ScValueCell*)pCell)->GetValue();
+ if ( bCalcAsShown )
+ {
+ ULONG nFormat;
+ nFormat = aCellIter.GetNumberFormat();
+ rValue = pDok->RoundValueAsShown( rValue, nFormat );
+ }
+ PushDouble(rValue);
+ }
+ break;
+ case CELLTYPE_STRING:
+ {
+ String rString;
+ ((ScStringCell*)pCell)->GetString(rString);
+ PushStringObject(rString);
+ }
+ break;
+ case CELLTYPE_EDIT:
+ {
+ String rString;
+ ((ScEditCell*)pCell)->GetString(rString);
+ PushStringObject(rString);
+ }
+ break;
+ case CELLTYPE_FORMULA:
+ {
+ USHORT rErr = ((ScFormulaCell*)pCell)->GetErrCode();
+ if (rErr)
+ {
+ SetError(rErr);
+ PushInt(0);
+ }
+ else if (((ScFormulaCell*)pCell)->IsValue())
+ {
+ double rValue = ((ScFormulaCell*)pCell)->GetValue();
+ PushDouble(rValue);
+ }
+ else
+ {
+ String rString;
+ ((ScFormulaCell*)pCell)->GetString(rString);
+ PushStringObject(rString);
+ }
+ }
+ break;
+ case CELLTYPE_NONE:
+ case CELLTYPE_NOTE:
+ default:
+ SetIllegalArgument();
+ break;
+ }
+ }
+ }
+ else
+ SetNoValue();
+ }
+ else
+ SetIllegalParameter();
+}
+
+
+void ScInterpreter::ScExternal()
+{
+ USHORT nIndex;
+ BYTE nParamCount = GetByte();
+ String aUnoName;
+ // Achtung: Der String faengt im 2. Byte an!!
+ const sal_Unicode* pFuncName = pCur->cStr + 1;
+ if (ScGlobal::GetFuncCollection()->SearchFunc(pFuncName, nIndex))
+ {
+ FuncData* pFuncData = (FuncData*)ScGlobal::GetFuncCollection()->At(nIndex);
+ if (nParamCount == pFuncData->GetParamCount() - 1)
+ {
+ ParamType eParamType[MAXFUNCPARAM];
+ void* ppParam[MAXFUNCPARAM];
+ double nVal[MAXFUNCPARAM];
+ sal_Char* pStr[MAXFUNCPARAM];
+ BYTE* pCellArr[MAXFUNCPARAM];
+ short i;
+
+ for (i = 0; i < MAXFUNCPARAM; i++)
+ {
+ eParamType[i] = pFuncData->GetParamType(i);
+ ppParam[i] = NULL;
+ nVal[i] = 0.0;
+ pStr[i] = NULL;
+ pCellArr[i] = NULL;
+ }
+
+ for (i = nParamCount; (i > 0) && (nGlobalError == 0); i--)
+ {
+ BYTE nStackType = GetStackType();
+ switch (eParamType[i])
+ {
+ case PTR_DOUBLE :
+ {
+ nVal[i-1] = GetDouble();
+ ppParam[i] = &nVal[i-1];
+ }
+ break;
+ case PTR_STRING :
+ {
+ pStr[i-1] = new sal_Char[MAXSTRLEN];
+ strcpy( pStr[i-1], ByteString( GetString(), osl_getThreadTextEncoding() ).GetBuffer() );
+ ppParam[i] = pStr[i-1];
+ }
+ break;
+ case PTR_DOUBLE_ARR :
+ {
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+ pCellArr[i-1] = new BYTE[MAXARRSIZE];
+ if (!CreateDoubleArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
+ SetError(errCodeOverflow);
+ else
+ ppParam[i] = pCellArr[i-1];
+ }
+ break;
+ case PTR_STRING_ARR :
+ {
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+ pCellArr[i-1] = new BYTE[MAXARRSIZE];
+ if (!CreateStringArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
+ SetError(errCodeOverflow);
+ else
+ ppParam[i] = pCellArr[i-1];
+ }
+ break;
+ case PTR_CELL_ARR :
+ {
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+ pCellArr[i-1] = new BYTE[MAXARRSIZE];
+ if (!CreateCellArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
+ SetError(errCodeOverflow);
+ else
+ ppParam[i] = pCellArr[i-1];
+ }
+ break;
+ default :
+ SetError(errIllegalParameter);
+ break;
+ }
+ }
+ while ( i-- )
+ Pop(); // im Fehlerfall (sonst ist i==0) Parameter wegpoppen
+
+ if (nGlobalError == 0)
+ {
+ if ( pFuncData->GetAsyncType() == NONE )
+ {
+ switch ( eParamType[0] )
+ {
+ case PTR_DOUBLE :
+ {
+ double nErg = 0.0;
+ ppParam[0] = &nErg;
+ pFuncData->Call(ppParam);
+ PushDouble(nErg);
+ }
+ break;
+ case PTR_STRING :
+ {
+ sal_Char* pcErg = new sal_Char[MAXSTRLEN];
+ ppParam[0] = pcErg;
+ pFuncData->Call(ppParam);
+ String aUni( pcErg, osl_getThreadTextEncoding() );
+ PushString( aUni.GetBuffer() );
+ delete[] pcErg;
+ }
+ break;
+ default:
+ SetError( errUnknownState );
+ PushInt(0);
+ }
+ }
+ else
+ {
+ // nach dem Laden Asyncs wieder anwerfen
+ if ( pMyFormulaCell->GetCode()->IsRecalcModeNormal() )
+ pMyFormulaCell->GetCode()->SetRecalcModeOnLoad();
+ // garantiert identischer Handle bei identischem Aufruf?!?
+ // sonst schei*e ...
+ double nErg = 0.0;
+ ppParam[0] = &nErg;
+ pFuncData->Call(ppParam);
+ ULONG nHandle = ULONG( nErg );
+ if ( nHandle >= 65536 )
+ {
+ ScAddInAsync* pAs = ScAddInAsync::Get( nHandle );
+ if ( !pAs )
+ {
+ pAs = new ScAddInAsync( nHandle, nIndex, pDok );
+ pMyFormulaCell->StartListening( *pAs, TRUE );
+ }
+ else
+ {
+ // falls per cut/copy/paste
+ if ( !pMyFormulaCell->IsListening( *pAs ) )
+ pMyFormulaCell->StartListening( *pAs, TRUE );
+ // in anderes Dokument?
+ if ( !pAs->HasDocument( pDok ) )
+ pAs->AddDocument( pDok );
+ }
+ if ( pAs->IsValid() )
+ {
+ switch ( pAs->GetType() )
+ {
+ case PTR_DOUBLE :
+ PushDouble( pAs->GetValue() );
+ break;
+ case PTR_STRING :
+ PushStringObject( pAs->GetString() );
+ break;
+ default:
+ SetError( errUnknownState );
+ PushInt(0);
+ }
+ }
+ else
+ SetNV();
+ }
+ else
+ SetNoValue();
+ }
+ }
+
+ for (i = 0; i < MAXFUNCPARAM; i++)
+ {
+ delete[] pStr[i];
+ delete[] pCellArr[i];
+ }
+ }
+ else
+ {
+ while( nParamCount-- )
+ Pop();
+ SetError(errIllegalParameter);
+ PushInt(0);
+ }
+ }
+ else if ( ( aUnoName = ScGlobal::GetAddInCollection()->FindFunction(pFuncName, FALSE) ).Len() )
+ {
+ // bLocalFirst=FALSE in FindFunction, cFunc should be the stored internal name
+
+ ScUnoAddInCall aCall( *ScGlobal::GetAddInCollection(), aUnoName, nParamCount );
+
+ if ( !aCall.ValidParamCount() )
+ SetError( errIllegalParameter );
+
+ if ( aCall.NeedsCaller() && !GetError() )
+ aCall.SetCallerFromObjectShell( pDok->GetDocumentShell() );
+
+ short nPar = nParamCount;
+ while ( nPar && !GetError() )
+ {
+ --nPar; // 0 .. (nParamCount-1)
+
+ ScAddInArgumentType eType = aCall.GetArgType( nPar );
+ BYTE nStackType = GetStackType();
+
+ uno::Any aParam;
+ switch (eType)
+ {
+ case SC_ADDINARG_INTEGER:
+ {
+ double fVal = GetDouble();
+ double fInt = (fVal >= 0.0) ? SolarMath::ApproxFloor( fVal ) :
+ SolarMath::ApproxCeil( fVal );
+ if ( fInt >= LONG_MIN && fInt <= LONG_MAX )
+ aParam <<= (INT32)fInt;
+ else
+ SetError(errIllegalArgument);
+ }
+ break;
+
+ case SC_ADDINARG_DOUBLE:
+ aParam <<= (double) GetDouble();
+ break;
+
+ case SC_ADDINARG_STRING:
+ aParam <<= rtl::OUString( GetString() );
+ break;
+
+ case SC_ADDINARG_INTEGER_ARRAY:
+ switch( nStackType )
+ {
+ case svDouble:
+ case svString:
+ case svSingleRef:
+ {
+ double fVal = GetDouble();
+ double fInt = (fVal >= 0.0) ? SolarMath::ApproxFloor( fVal ) :
+ SolarMath::ApproxCeil( fVal );
+ if ( fInt >= LONG_MIN && fInt <= LONG_MAX )
+ {
+ INT32 nIntVal = (long)fInt;
+ uno::Sequence<INT32> aInner( &nIntVal, 1 );
+ uno::Sequence< uno::Sequence<INT32> > aOuter( &aInner, 1 );
+ aParam <<= aOuter;
+ }
+ else
+ SetError(errIllegalArgument);
+ }
+ break;
+ case svDoubleRef:
+ {
+ ScRange aRange;
+ PopDoubleRef( aRange );
+ if (!ScRangeToSequence::FillLongArray( aParam, pDok, aRange ))
+ SetError(errIllegalParameter);
+ }
+ break;
+ case svMatrix:
+ if (!ScRangeToSequence::FillLongArray( aParam, PopMatrix() ))
+ SetError(errIllegalParameter);
+ break;
+ default:
+ Pop();
+ SetError(errIllegalParameter);
+ }
+ break;
+
+ case SC_ADDINARG_DOUBLE_ARRAY:
+ switch( nStackType )
+ {
+ case svDouble:
+ case svString:
+ case svSingleRef:
+ {
+ double fVal = GetDouble();
+ uno::Sequence<double> aInner( &fVal, 1 );
+ uno::Sequence< uno::Sequence<double> > aOuter( &aInner, 1 );
+ aParam <<= aOuter;
+ }
+ break;
+ case svDoubleRef:
+ {
+ ScRange aRange;
+ PopDoubleRef( aRange );
+ if (!ScRangeToSequence::FillDoubleArray( aParam, pDok, aRange ))
+ SetError(errIllegalParameter);
+ }
+ break;
+ case svMatrix:
+ if (!ScRangeToSequence::FillDoubleArray( aParam, PopMatrix() ))
+ SetError(errIllegalParameter);
+ break;
+ default:
+ Pop();
+ SetError(errIllegalParameter);
+ }
+ break;
+
+ case SC_ADDINARG_STRING_ARRAY:
+ switch( nStackType )
+ {
+ case svDouble:
+ case svString:
+ case svSingleRef:
+ {
+ rtl::OUString aString = rtl::OUString( GetString() );
+ uno::Sequence<rtl::OUString> aInner( &aString, 1 );
+ uno::Sequence< uno::Sequence<rtl::OUString> > aOuter( &aInner, 1 );
+ aParam <<= aOuter;
+ }
+ break;
+ case svDoubleRef:
+ {
+ ScRange aRange;
+ PopDoubleRef( aRange );
+ if (!ScRangeToSequence::FillStringArray( aParam, pDok, aRange ))
+ SetError(errIllegalParameter);
+ }
+ break;
+ case svMatrix:
+ if (!ScRangeToSequence::FillStringArray( aParam, PopMatrix(), pFormatter ))
+ SetError(errIllegalParameter);
+ break;
+ default:
+ Pop();
+ SetError(errIllegalParameter);
+ }
+ break;
+
+ case SC_ADDINARG_MIXED_ARRAY:
+ switch( nStackType )
+ {
+ case svDouble:
+ case svString:
+ case svSingleRef:
+ {
+ uno::Any aElem;
+ if ( nStackType == svDouble )
+ aElem <<= (double) GetDouble();
+ else if ( nStackType == svString )
+ aElem <<= rtl::OUString( GetString() );
+ else
+ {
+ ScAddress aAdr;
+ if ( PopDoubleRefOrSingleRef( aAdr ) )
+ {
+ ScBaseCell* pCell = GetCell( aAdr );
+ if ( pCell && pCell->HasStringData() )
+ {
+ String aStr;
+ GetCellString( aStr, pCell );
+ aElem <<= rtl::OUString( aStr );
+ }
+ else
+ aElem <<= (double) GetCellValue( aAdr, pCell );
+ }
+ }
+ uno::Sequence<uno::Any> aInner( &aElem, 1 );
+ uno::Sequence< uno::Sequence<uno::Any> > aOuter( &aInner, 1 );
+ aParam <<= aOuter;
+ }
+ break;
+ case svDoubleRef:
+ {
+ ScRange aRange;
+ PopDoubleRef( aRange );
+ if (!ScRangeToSequence::FillMixedArray( aParam, pDok, aRange ))
+ SetError(errIllegalParameter);
+ }
+ break;
+ case svMatrix:
+ if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix() ))
+ SetError(errIllegalParameter);
+ break;
+ default:
+ Pop();
+ SetError(errIllegalParameter);
+ }
+ break;
+
+ case SC_ADDINARG_VALUE_OR_ARRAY:
+ switch( nStackType )
+ {
+ case svDouble:
+ aParam <<= (double) GetDouble();
+ break;
+ case svString:
+ aParam <<= rtl::OUString( GetString() );
+ break;
+ case svSingleRef:
+ {
+ ScAddress aAdr;
+ if ( PopDoubleRefOrSingleRef( aAdr ) )
+ {
+ ScBaseCell* pCell = GetCell( aAdr );
+ if ( pCell && pCell->HasStringData() )
+ {
+ String aStr;
+ GetCellString( aStr, pCell );
+ aParam <<= rtl::OUString( aStr );
+ }
+ else
+ aParam <<= (double) GetCellValue( aAdr, pCell );
+ }
+ }
+ break;
+ case svDoubleRef:
+ {
+ ScRange aRange;
+ PopDoubleRef( aRange );
+ if (!ScRangeToSequence::FillMixedArray( aParam, pDok, aRange ))
+ SetError(errIllegalParameter);
+ }
+ break;
+ case svMatrix:
+ if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix() ))
+ SetError(errIllegalParameter);
+ break;
+ default:
+ Pop();
+ SetError(errIllegalParameter);
+ }
+ break;
+
+ case SC_ADDINARG_CELLRANGE:
+ switch( nStackType )
+ {
+ case svSingleRef:
+ {
+ ScAddress aAdr;
+ PopSingleRef( aAdr );
+ if (aTableOpList.Count() > 0)
+ ReplaceCell( aAdr );
+ ScRange aRange( aAdr );
+ uno::Reference<table::XCellRange> xObj =
+ ScCellRangeObj::CreateRangeFromDoc( pDok, aRange );
+ if (xObj.is())
+ aParam <<= xObj;
+ else
+ SetError(errIllegalParameter);
+ }
+ break;
+ case svDoubleRef:
+ {
+ ScRange aRange;
+ PopDoubleRef( aRange );
+ uno::Reference<table::XCellRange> xObj =
+ ScCellRangeObj::CreateRangeFromDoc( pDok, aRange );
+ if (xObj.is())
+ aParam <<= xObj;
+ else
+ SetError(errIllegalParameter);
+ }
+ break;
+ default:
+ Pop();
+ SetError(errIllegalParameter);
+ }
+ break;
+
+ default:
+ Pop();
+ SetError(errIllegalParameter);
+ }
+ aCall.SetParam( nPar, aParam );
+ }
+
+ while (nPar--)
+ Pop(); // in case of error, remove remaining args
+
+ if ( !GetError() )
+ {
+ aCall.ExecuteCall();
+
+ if ( aCall.HasVarRes() ) // handle async functions
+ {
+ if ( pMyFormulaCell->GetCode()->IsRecalcModeNormal() )
+ pMyFormulaCell->GetCode()->SetRecalcModeOnLoad();
+
+ uno::Reference<sheet::XVolatileResult> xResult = aCall.GetVarRes();
+ ScAddInListener* pLis = ScAddInListener::Get( xResult );
+ if ( !pLis )
+ {
+ pLis = ScAddInListener::CreateListener( xResult, pDok );
+ pMyFormulaCell->StartListening( *pLis, TRUE );
+ }
+ else
+ {
+ if ( !pMyFormulaCell->IsListening( *pLis ) )
+ pMyFormulaCell->StartListening( *pLis, TRUE );
+ if ( !pLis->HasDocument( pDok ) )
+ pLis->AddDocument( pDok );
+ }
+
+ aCall.SetResult( pLis->GetResult() ); // use result from async
+ }
+
+ if ( aCall.GetErrCode() )
+ {
+ SetError( aCall.GetErrCode() );
+ PushInt(0);
+ }
+ else if ( aCall.HasMatrix() )
+ {
+ const ScMatrix* pLinkMat = aCall.GetMatrix(); // not NULL
+
+ USHORT nC, nR, nMatInd; // copy matrix result
+ pLinkMat->GetDimensions(nC, nR);
+ ScMatrix* pNewMat = GetNewMat( nC, nR, nMatInd );
+ if (pNewMat)
+ {
+ pLinkMat->MatCopy(*pNewMat);
+ PushMatrix( pNewMat );
+ nRetMat = nMatInd;
+ } // otherwise error code has been set in GetNewMat
+ }
+ else if ( aCall.HasString() )
+ PushStringObject( aCall.GetString() );
+ else
+ PushDouble( aCall.GetValue() );
+ }
+ else // error...
+ PushInt(0);
+ }
+ else
+ {
+ while( nParamCount-- )
+ Pop();
+ SetError(errNoName);
+ PushInt(0);
+ }
+}
+
+
+void ScInterpreter::ScMissing()
+{
+ ScToken aToken;
+ aToken.SetOpCode( ocMissing );
+ PushTempToken( aToken );
+}
+
+
+void ScInterpreter::ScMacro()
+{
+ SbxBase::ResetError();
+
+ BYTE nParamCount = GetByte();
+ const sal_Unicode* pMacro = pCur->cStr + 1; // Achtung: Der String faengt im 2. Byte an!!
+
+ SfxObjectShell* pDocSh = pDok->GetDocumentShell();
+ if ( !pDocSh || !pDok->CheckMacroWarn() )
+ {
+ SetError( errNoValue ); // ohne DocShell kein CallBasic
+ return;
+ }
+
+ // keine Sicherheitsabfrage mehr vorneweg (nur CheckMacroWarn), das passiert im CallBasic
+
+ SfxApplication* pSfxApp = SFX_APP();
+ pSfxApp->EnterBasicCall(); // Dok-Basic anlegen etc.
+
+ // Wenn das Dok waehrend eines Basic-Calls geladen wurde,
+ // ist das Sbx-Objekt evtl. nicht angelegt (?)
+// pDocSh->GetSbxObject();
+
+ // Funktion ueber den einfachen Namen suchen,
+ // dann aBasicStr, aMacroStr fuer SfxObjectShell::CallBasic zusammenbauen
+
+ StarBASIC* pRoot = pDocSh->GetBasic();
+ SbxVariable* pVar = pRoot->Find( String( pMacro ), SbxCLASS_METHOD );
+ if( !pVar || pVar->GetType() == SbxVOID || !pVar->ISA(SbMethod) )
+ {
+ SetError( errNoName );
+ pSfxApp->LeaveBasicCall();
+ return;
+ }
+
+ SbMethod* pMethod = (SbMethod*)pVar;
+ SbModule* pModule = pMethod->GetModule();
+ SbxObject* pObject = pModule->GetParent();
+ DBG_ASSERT(pObject->IsA(TYPE(StarBASIC)), "Kein Basic gefunden!");
+ String aMacroStr = pObject->GetName();
+ aMacroStr += '.';
+ aMacroStr += pModule->GetName();
+ aMacroStr += '.';
+ aMacroStr += pMethod->GetName();
+ String aBasicStr;
+ if (pObject->GetParent())
+ aBasicStr = pObject->GetParent()->GetName(); // Dokumentenbasic
+ else
+ aBasicStr = SFX_APP()->GetName(); // Applikationsbasic
+
+ // Parameter-Array zusammenbauen
+
+ SbxArrayRef refPar = new SbxArray;
+ BOOL bOk = TRUE;
+ for( short i = nParamCount; i && bOk ; i-- )
+ {
+ SbxVariable* pPar = refPar->Get( (USHORT) i );
+ BYTE nStackType = GetStackType();
+ switch( nStackType )
+ {
+ case svDouble:
+ pPar->PutDouble( GetDouble() );
+ break;
+ case svString:
+ pPar->PutString( String( GetString() ) );
+ break;
+ case svSingleRef:
+ {
+ ScAddress aAdr;
+ PopSingleRef( aAdr );
+ if (aTableOpList.Count() > 0)
+ ReplaceCell( aAdr );
+ bOk = SetSbxVariable( pPar, aAdr );
+ }
+ break;
+ case svDoubleRef:
+ {
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ if( nTab1 != nTab2 )
+ {
+ SetError( errIllegalParameter );
+ bOk = FALSE;
+ }
+ else
+ {
+ SbxDimArrayRef refArray = new SbxDimArray;
+ refArray->AddDim( 1, nRow2 - nRow1 + 1 );
+ refArray->AddDim( 1, nCol2 - nCol1 + 1 );
+ ScAddress aAdr( nCol1, nRow1, nTab1 );
+ for( USHORT nRow = nRow1; bOk && nRow <= nRow2; nRow++ )
+ {
+ aAdr.SetRow( nRow );
+ short nIdx[ 2 ];
+ nIdx[ 0 ] = nRow-nRow1+1;
+ for( USHORT nCol = nCol1; bOk && nCol <= nCol2; nCol++ )
+ {
+ aAdr.SetCol( nCol );
+ nIdx[ 1 ] = nCol-nCol1+1;
+ SbxVariable* p = refArray->Get( nIdx );
+ bOk = SetSbxVariable( p, aAdr );
+ }
+ }
+ pPar->PutObject( refArray );
+ }
+ }
+ break;
+ case svMatrix:
+ {
+ ScMatrix* pMat = PopMatrix();
+ USHORT nC, nR;
+ if (pMat)
+ {
+ pMat->GetDimensions(nC, nR);
+ SbxDimArrayRef refArray = new SbxDimArray;
+ refArray->AddDim( 1, nR );
+ refArray->AddDim( 1, nC );
+ for( USHORT j = 0; j < nR; j++ )
+ {
+ short nIdx[ 2 ];
+ nIdx[ 0 ] = j+1;
+ for( USHORT i = 0; i < nC; i++ )
+ {
+ nIdx[ 1 ] = i+1;
+ SbxVariable* p = refArray->Get( nIdx );
+ if (pMat->IsString(i, j))
+ p->PutString( pMat->GetString(i, j) );
+ else
+ p->PutDouble( pMat->GetDouble(i, j) );
+ }
+ }
+ pPar->PutObject( refArray );
+ }
+ else
+ SetError( errIllegalParameter );
+ }
+ break;
+ default:
+ SetError( errIllegalParameter );
+ bOk = FALSE;
+ }
+ }
+ if( bOk )
+ {
+ pDok->LockTable( aPos.Tab() );
+ SbxVariableRef refRes = new SbxVariable;
+ pDok->IncMacroInterpretLevel();
+ ErrCode eRet = pDocSh->CallBasic( aMacroStr, aBasicStr, NULL, refPar, refRes );
+ pDok->DecMacroInterpretLevel();
+ pDok->UnlockTable( aPos.Tab() );
+
+ SbxDataType eResType = refRes->GetType();
+ if ( eRet != ERRCODE_NONE )
+ SetNoValue();
+ else if( eResType >= SbxINTEGER && eResType <= SbxDOUBLE )
+ PushDouble( refRes->GetDouble() );
+ else if ( eResType & SbxARRAY )
+ {
+ SbxBase* pElemObj = refRes->GetObject();
+ SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj);
+ short nDim = pDimArray->GetDims();
+ if ( 1 <= nDim && nDim <= 2 )
+ {
+ short nCs, nCe, nRs, nRe;
+ USHORT nC, nR, nMatInd;
+ USHORT nColIdx, nRowIdx;
+ if ( nDim == 1 )
+ { // array( cols ) eine Zeile, mehrere Spalten
+ pDimArray->GetDim( 1, nCs, nCe );
+ nC = USHORT(nCe - nCs + 1);
+ nRs = nRe = 0;
+ nR = 1;
+ nColIdx = 0;
+ nRowIdx = 1;
+ }
+ else
+ { // array( rows, cols )
+ pDimArray->GetDim( 1, nRs, nRe );
+ nR = USHORT(nRe - nRs + 1);
+ pDimArray->GetDim( 2, nCs, nCe );
+ nC = USHORT(nCe - nCs + 1);
+ nColIdx = 1;
+ nRowIdx = 0;
+ }
+ ScMatrix* pMat = GetNewMat( nC, nR, nMatInd );
+ if ( pMat )
+ {
+ SbxVariable* pV;
+ SbxDataType eType;
+ for ( USHORT j=0; j < nR; j++ )
+ {
+ short nIdx[ 2 ];
+ // bei eindimensionalem array( cols ) wird nIdx[1]
+ // von SbxDimArray::Get ignoriert
+ nIdx[ nRowIdx ] = nRs + j;
+ for ( USHORT i=0; i < nC; i++ )
+ {
+ nIdx[ nColIdx ] = nCs + i;
+ pV = pDimArray->Get( nIdx );
+ eType = pV->GetType();
+ if ( eType >= SbxINTEGER && eType <= SbxDOUBLE )
+ pMat->PutDouble( pV->GetDouble(), i, j );
+ else
+ pMat->PutString( pV->GetString(), i, j );
+ }
+ }
+ PushMatrix( pMat );
+ nRetMat = nMatInd;
+ }
+ }
+ else
+ SetNoValue();
+ }
+ else
+ PushStringObject( refRes->GetString() );
+ if( pVar->GetError() )
+ SetNoValue();
+ }
+
+ pSfxApp->LeaveBasicCall();
+}
+
+
+BOOL ScInterpreter::SetSbxVariable( SbxVariable* pVar, const ScAddress& rPos )
+{
+ BOOL bOk = TRUE;
+ ScBaseCell* pCell = pDok->GetCell( rPos );
+ if (pCell)
+ {
+ USHORT nErr;
+ double nVal;
+ switch( pCell->GetCellType() )
+ {
+ case CELLTYPE_VALUE :
+ nVal = GetValueCellValue( rPos, (ScValueCell*)pCell );
+ pVar->PutDouble( nVal );
+ break;
+ case CELLTYPE_STRING :
+ {
+ String aVal;
+ ((ScStringCell*)pCell)->GetString( aVal );
+ pVar->PutString( aVal );
+ break;
+ }
+ case CELLTYPE_EDIT :
+ {
+ String aVal;
+ ((ScEditCell*) pCell)->GetString( aVal );
+ pVar->PutString( aVal );
+ break;
+ }
+ case CELLTYPE_FORMULA :
+ nErr = ((ScFormulaCell*)pCell)->GetErrCode();
+ if( !nErr )
+ {
+ if( ((ScFormulaCell*)pCell)->IsValue() )
+ {
+ nVal = ((ScFormulaCell*)pCell)->GetValue();
+ pVar->PutDouble( nVal );
+ }
+ else
+ {
+ String aVal;
+ ((ScFormulaCell*)pCell)->GetString( aVal );
+ pVar->PutString( aVal );
+ }
+ }
+ else
+ SetError( nErr ), bOk = FALSE;
+ break;
+ default :
+ pVar->PutDouble( 0.0 );
+ }
+ }
+ else
+ pVar->PutDouble( 0.0 );
+ return bOk;
+}
+
+
+void ScInterpreter::ScTableOp()
+{
+ BYTE nParamCount = GetByte();
+ if (nParamCount != 3 && nParamCount != 5)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ ScAddress aFAdr;
+ USHORT nOCol1, nORow1, nOTab1, nNCol1, nNRow1, nNTab1;
+ USHORT nOCol2, nORow2, nOTab2, nNCol2, nNRow2, nNTab2;
+ if (nParamCount == 5)
+ {
+ PopSingleRef(nNCol2, nNRow2, nNTab2);
+ PopSingleRef(nOCol2, nORow2, nOTab2);
+ }
+ else
+ nOCol2 = MAXCOL+1;
+ PopSingleRef(nNCol1, nNRow1, nNTab1);
+ PopSingleRef(nOCol1, nORow1, nOTab1);
+ PopSingleRef( aFAdr );
+ pTableOp = new USHORT[12];
+ pTableOp[0] = nOCol1;
+ pTableOp[1] = nORow1;
+ pTableOp[2] = nOTab1;
+ pTableOp[3] = nNCol1;
+ pTableOp[4] = nNRow1;
+ pTableOp[5] = nNTab1;
+ pTableOp[6] = nOCol2;
+ pTableOp[7] = nORow2;
+ pTableOp[8] = nOTab2;
+ pTableOp[9] = nNCol2;
+ pTableOp[10] = nNRow2;
+ pTableOp[11] = nNTab2;
+ aTableOpList.Insert(pTableOp);
+
+ ScBaseCell* pFCell = pDok->GetCell( aFAdr );
+ if (pFCell && pFCell->GetCellType() == CELLTYPE_FORMULA)
+ ((ScFormulaCell*)pFCell)->SetDirtyVar();
+ if (HasCellValueData(pFCell))
+ PushDouble(GetCellValue( aFAdr, pFCell ));
+ else
+ {
+ String aCellString;
+ GetCellString(aCellString, pFCell);
+ PushStringObject(aCellString);
+ }
+ if (pTableOp)
+ {
+ aTableOpList.Remove(pTableOp);
+ delete [] pTableOp;
+ pTableOp = NULL;
+ }
+ if (pFCell && pFCell->GetCellType() == CELLTYPE_FORMULA)
+ ((ScFormulaCell*)pFCell)->SetDirtyVar();
+}
+
+/*
+
+void ScInterpreter::ScErrCell()
+{
+ double fErrNum = GetDouble();
+ SetError((USHORT) fErrNum);
+ PushInt(0);
+}
+*/
+
+
+void ScInterpreter::ScDefPar()
+{
+ PushInt(0);
+}
+
+
+void ScInterpreter::ScDBArea()
+{
+ ScDBData* pDBData = pDok->GetDBCollection()->FindIndex( pCur->nIndex);
+ if (pDBData)
+ {
+ ComplRefData aRefData;
+ aRefData.InitFlags();
+ pDBData->GetArea( (USHORT&) aRefData.Ref1.nTab,
+ (USHORT&) aRefData.Ref1.nCol,
+ (USHORT&) aRefData.Ref1.nRow,
+ (USHORT&) aRefData.Ref2.nCol,
+ (USHORT&) aRefData.Ref2.nRow);
+ aRefData.Ref2.nTab = aRefData.Ref1.nTab;
+ aRefData.CalcRelFromAbs( aPos );
+ ScToken aTok;
+ aTok.SetDoubleReference( aRefData );
+ PushTempToken( aTok );
+ }
+ else
+ SetError(errNoName);
+}
+
+
+void ScInterpreter::ScColRowNameAuto()
+{
+ ComplRefData aRefData( pCur->aRef );
+ aRefData.CalcAbsIfRel( aPos );
+ if ( aRefData.Valid() )
+ {
+ INT16 nStartCol, nStartRow, nCol2, nRow2;
+ // evtl. Begrenzung durch definierte ColRowNameRanges merken
+ nCol2 = aRefData.Ref2.nCol;
+ nRow2 = aRefData.Ref2.nRow;
+ // DataArea der ersten Zelle
+ nStartCol = aRefData.Ref2.nCol = aRefData.Ref1.nCol;
+ nStartRow = aRefData.Ref2.nRow = aRefData.Ref1.nRow;
+ aRefData.Ref2.nTab = aRefData.Ref1.nTab;
+ pDok->GetDataArea( (USHORT) aRefData.Ref1.nTab,
+ (USHORT&) aRefData.Ref1.nCol,
+ (USHORT&) aRefData.Ref1.nRow,
+ (USHORT&) aRefData.Ref2.nCol,
+ (USHORT&) aRefData.Ref2.nRow,
+ TRUE );
+ // DataArea im Ursprung begrenzen
+ aRefData.Ref1.nCol = nStartCol;
+ aRefData.Ref1.nRow = nStartRow;
+
+ //! korrespondiert mit ScCompiler::GetToken
+ if ( aRefData.Ref1.IsColRel() )
+ { // ColName
+ aRefData.Ref2.nCol = nStartCol;
+ // evtl. vorherige Begrenzung durch definierte ColRowNameRanges erhalten
+ if ( aRefData.Ref2.nRow > nRow2 )
+ aRefData.Ref2.nRow = nRow2;
+ USHORT nMyRow;
+ if ( aPos.Col() == nStartCol
+ && nStartRow <= (nMyRow = aPos.Row()) && nMyRow <= aRefData.Ref2.nRow )
+ { // Formel in gleicher Spalte und innerhalb des Range
+ if ( nMyRow == nStartRow )
+ { // direkt unter dem Namen den Rest nehmen
+ nStartRow++;
+ if ( nStartRow > MAXROW )
+ nStartRow = MAXROW;
+ aRefData.Ref1.nRow = nStartRow;
+ }
+ else
+ { // weiter unten vom Namen bis zur Formelzelle
+ aRefData.Ref2.nRow = nMyRow - 1;
+ }
+ }
+ }
+ else
+ { // RowName
+ aRefData.Ref2.nRow = nStartRow;
+ // evtl. vorherige Begrenzung durch definierte ColRowNameRanges erhalten
+ if ( aRefData.Ref2.nCol > nCol2 )
+ aRefData.Ref2.nCol = nCol2;
+ USHORT nMyCol;
+ if ( aPos.Row() == nStartRow
+ && nStartCol <= (nMyCol = aPos.Col()) && nMyCol <= aRefData.Ref2.nCol )
+ { // Formel in gleicher Zeile und innerhalb des Range
+ if ( nMyCol == nStartCol )
+ { // direkt neben dem Namen den Rest nehmen
+ nStartCol++;
+ if ( nStartCol > MAXCOL )
+ nStartCol = MAXCOL;
+ aRefData.Ref1.nCol = nStartCol;
+ }
+ else
+ { // weiter rechts vom Namen bis zur Formelzelle
+ aRefData.Ref2.nCol = nMyCol - 1;
+ }
+ }
+ }
+ aRefData.CalcRelFromAbs( aPos );
+ }
+ else
+ SetError( errNoRef );
+ ScToken aTok;
+ aTok.SetDoubleReference( aRefData );
+ PushTempToken( aTok );
+}
+
+// --- internals ------------------------------------------------------------
+
+
+void ScInterpreter::ScAnswer()
+{
+ String aStr( GetString() );
+ if( aStr.EqualsIgnoreCaseAscii( "Das Leben, das Universum und der ganze Rest" ) )
+ {
+ PushInt( 42 );
+ bOderSo = TRUE;
+ }
+ else
+ SetNoValue();
+}
+
+
+void ScInterpreter::ScCalcTeam()
+{
+ static BOOL bShown = FALSE;
+ if( !bShown )
+ {
+ ShowTheTeam();
+ String aTeam( RTL_CONSTASCII_USTRINGPARAM( "Nebel, Krebs, Timm, Rathke" ) );
+ if ( (GetByte() == 1) && SolarMath::ApproxEqual( GetDouble(), 1996) )
+ aTeam.AppendAscii( " (a word with 'B': -Olk, -Nietsch, -Daeumling)" );
+ PushStringObject( aTeam );
+ bShown = TRUE;
+ }
+ else
+ PushInt( 42 );
+}
+
+
+void ScInterpreter::ScSpewFunc()
+{
+ BOOL bRefresh = FALSE;
+ BOOL bClear = FALSE;
+ // Stack aufraeumen
+ BYTE nParamCount = GetByte();
+ while ( nParamCount-- )
+ {
+ switch ( GetStackType() )
+ {
+ case svString:
+ case svSingleRef:
+ case svDoubleRef:
+ {
+ const sal_Unicode* p = GetString();
+ if ( !bRefresh && *p < 256 )
+ bRefresh = (tolower( (sal_uChar) *p ) == 'r');
+ if ( !bClear && *p < 256 )
+ bClear = (tolower( (sal_uChar) *p ) == 'c');
+ }
+ break;
+ default:
+ Pop();
+ }
+ }
+ String aStr;
+#if SC_SPEW_ENABLED
+ if ( bRefresh )
+ theSpew.Clear(); // GetSpew liest SpewRulesFile neu
+ theSpew.GetSpew( aStr );
+ if ( bClear )
+ theSpew.Clear(); // release Memory
+ xub_StrLen nPos = 0;
+ while ( (nPos = aStr.SearchAndReplace( '\n', ' ', nPos )) != STRING_NOTFOUND )
+ nPos++;
+#else
+ aStr.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "spitted out all spew :-(" ) );
+#endif
+ PushStringObject( aStr );
+}
+
+
+#include "sctictac.hxx"
+
+//#define SC_INVADER_GPF // GPF wollen wir nicht :-(
+// zum testen Environment-Variable SC_INVADER_GPF=xxx setzen
+// 08.10.98: wenn PB optpath.cxx gefixt hat geht's wieder
+
+extern void StartInvader( Window* pParent ); // StarWars, Wrapper in SVX options/optpath.cxx
+extern void Game(); // Froggie
+void ScInterpreter::ScGame()
+{
+ enum GameType {
+ SC_GAME_NONE,
+ SC_GAME_ONCE,
+ SC_GAME_START,
+ SC_GAME_TICTACTOE = SC_GAME_START,
+ SC_GAME_STARWARS,
+ SC_GAME_FROGGER,
+ SC_GAME_COUNT
+ };
+ // ein grep im binary laeuft ins leere
+ static sal_Char sGameNone[] = "\14\36\6\137\10\27\36\13\100";
+ static sal_Char sGameOnce[] = "\20\27\137\21\20\123\137\21\20\13\137\36\30\36\26\21\136";
+ static sal_Char sGameTicTacToe[] = "\53\26\34\53\36\34\53\20\32";
+ static sal_Char sGameStarWars[] = "\54\13\36\15\50\36\15\14";
+ static sal_Char sGameFrogger[] = "\71\15\20\30\30\26\32";
+ sal_Char* const pGames[SC_GAME_COUNT] = {
+ sGameNone,
+ sGameOnce,
+ sGameTicTacToe,
+ sGameStarWars,
+ sGameFrogger
+ };
+#if 0
+say what?
+oh no, not again!
+TicTacToe
+StarWars
+Froggie
+// Routine um Datenblock zu erzeugen:
+#include <stdio.h>
+int main()
+{
+ int b = 1;
+ int c;
+ while ( (c = getchar()) != EOF )
+ {
+ if ( b == 1 )
+ {
+ printf( "\"" );
+ b = 0;
+ }
+ if ( c != 10 )
+ {
+ c ^= 0x7F;
+ printf( "\\%o", c );
+
+ }
+ else
+ {
+ printf( "\";\n" );
+ b = 1;
+ }
+ }
+ return 0;
+}
+#endif
+ static BOOL bRun[SC_GAME_COUNT] = { FALSE };
+ static BOOL bFirst = TRUE;
+ if ( bFirst )
+ {
+ bFirst = FALSE;
+ for ( int j = SC_GAME_NONE; j < SC_GAME_COUNT; j++ )
+ {
+ sal_Char* p = pGames[j];
+ while ( *p )
+ *p++ ^= 0x7F;
+ }
+ }
+ String aResult;
+ GameType eGame = SC_GAME_NONE;
+ BYTE nParamCount = GetByte();
+ if ( nParamCount >= 1 )
+ {
+ String aStr( GetString() );
+ nParamCount--;
+ for ( int j = SC_GAME_START; j < SC_GAME_COUNT; j++ )
+ {
+ if ( aStr.EqualsAscii( pGames[j] ) )
+ {
+ eGame = (GameType) j;
+ break; // for
+ }
+ }
+ if ( eGame != SC_GAME_NONE )
+ {
+ // jedes Game nur ein einziges Mal starten, um nicht durch Recalc
+ // o.ae. mehrere Instanzen zu haben, ideal waere eine Abfrage an den
+ // Games, ob sie bereits laufen ...
+ if ( bRun[ eGame ] && eGame != SC_GAME_TICTACTOE )
+ eGame = SC_GAME_ONCE;
+ else
+ {
+ bRun[ eGame ] = TRUE;
+ switch ( eGame )
+ {
+ case SC_GAME_TICTACTOE :
+ {
+ static ScTicTacToe* pTicTacToe = NULL;
+ static ScRange aTTTrange;
+ static BOOL bHumanFirst = FALSE;
+ if ( nParamCount >= 1 )
+ {
+ if ( GetStackType() == svDoubleRef )
+ {
+ ScRange aRange;
+ PopDoubleRef( aRange );
+ nParamCount--;
+ if ( aRange.aEnd.Col() - aRange.aStart.Col() == 2
+ && aRange.aEnd.Row() - aRange.aStart.Row() == 2 )
+ {
+ BOOL bOk;
+ if ( pTicTacToe )
+ bOk = (aRange == aTTTrange);
+ else
+ {
+ bOk =TRUE;
+ aTTTrange = aRange;
+ pTicTacToe = new ScTicTacToe( pDok,
+ aRange.aStart );
+ pTicTacToe->Initialize( bHumanFirst );
+ }
+ // nur einmal und das auf dem gleichen Range
+ if ( !bOk )
+ eGame = SC_GAME_ONCE;
+ else
+ {
+ Square_Type aWinner = pTicTacToe->CalcMove();
+ pTicTacToe->GetOutput( aResult );
+ if ( aWinner != pTicTacToe->GetEmpty() )
+ {
+ delete pTicTacToe;
+ pTicTacToe = NULL;
+ bRun[ eGame ] = FALSE;
+ bHumanFirst = !bHumanFirst;
+ }
+ pDok->GetDocumentShell()->Broadcast(
+ SfxSimpleHint( FID_DATACHANGED ) );
+ pDok->ResetChanged( aRange );
+ }
+ }
+ else
+ SetError( errIllegalArgument );
+ }
+ else
+ SetError( errIllegalParameter );
+ }
+ else
+ SetError( errIllegalParameter );
+ }
+ break;
+ case SC_GAME_STARWARS :
+#ifdef SC_INVADER_GPF
+ if ( getenv( "SC_INVADER_GPF" ) )
+#endif
+ StartInvader( Application::GetDefDialogParent() );
+ break;
+ case SC_GAME_FROGGER :
+ //Game();
+ break;
+ }
+ }
+ }
+ }
+ // Stack aufraeumen
+ while ( nParamCount-- )
+ Pop();
+ if ( !aResult.Len() )
+ PushStringObject( String( pGames[ eGame ], RTL_TEXTENCODING_ASCII_US ) );
+ else
+ PushStringObject( aResult );
+}
+
+
+
+void ScInterpreter::ScTTT()
+{ // Temporaerer Test-Tanz, zum auspropieren von Funktionen etc.
+ BOOL bOk = TRUE;
+ BYTE nParamCount = GetByte();
+ // do something, nParamCount bei Pops runterzaehlen!
+
+ if ( bOk && nParamCount )
+ {
+ bOk = GetBool();
+ --nParamCount;
+ }
+ // Stack aufraeumen
+ while ( nParamCount-- )
+ Pop();
+ static const sal_Unicode __FAR_DATA sEyes[] = { ',',';',':','|','8','B', 0 };
+ static const sal_Unicode __FAR_DATA sGoods[] = { ')',']','}', 0 };
+ static const sal_Unicode __FAR_DATA sBads[] = { '(','[','{','/', 0 };
+ sal_Unicode aFace[4];
+ if ( bOk )
+ {
+ aFace[0] = sEyes[ rand() % ((sizeof( sEyes )/sizeof(sal_Unicode)) - 1) ];
+ aFace[1] = '-';
+ aFace[2] = sGoods[ rand() % ((sizeof( sGoods )/sizeof(sal_Unicode)) - 1) ];
+ }
+ else
+ {
+ aFace[0] = ':';
+ aFace[1] = '-';
+ aFace[2] = sBads[ rand() % ((sizeof( sBads )/sizeof(sal_Unicode)) - 1) ];
+ }
+ aFace[3] = 0;
+ PushString( aFace );
+}
+
+// -------------------------------------------------------------------------
+
+
+ScInterpreter::ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc,
+ const ScAddress& rPos, ScTokenArray& r ) :
+ pMyFormulaCell( pCell ),
+ pDok( pDoc ),
+ aCode( r ),
+ aPos( rPos ),
+ rArr( r ),
+ bCalcAsShown( pDoc->GetDocOptions().IsCalcAsShown() ),
+ pFormatter( pDoc->GetFormatTable() )
+{
+// pStack = new ScToken*[ MAXSTACK ];
+
+ BYTE cMatFlag = pMyFormulaCell->GetMatrixFlag();
+ bMatrixFormula = ( cMatFlag == MM_FORMULA || cMatFlag == MM_FAKE );
+ if (!bGlobalStackInUse)
+ {
+ bGlobalStackInUse = TRUE;
+ if (!pGlobalStack)
+ pGlobalStack = new ScTokenStack;
+ if (!pGlobalErrorStack)
+ pGlobalErrorStack = new ScErrorStack;
+ pStackObj = pGlobalStack;
+ pErrorStackObj = pGlobalErrorStack;
+ }
+ else
+ {
+ pStackObj = new ScTokenStack;
+ pErrorStackObj = new ScErrorStack;
+ }
+ pStack = pStackObj->pPointer;
+ pErrorStack = pErrorStackObj->pPointer;
+}
+
+
+ScInterpreter::~ScInterpreter()
+{
+// delete pStack;
+
+ if ( pStackObj == pGlobalStack )
+ bGlobalStackInUse = FALSE;
+ else
+ {
+ delete pStackObj;
+ delete pErrorStackObj;
+ }
+}
+
+
+void ScInterpreter::GlobalExit() // static
+{
+ DBG_ASSERT(!bGlobalStackInUse, "wer benutzt noch den TokenStack?");
+ DELETEZ(pGlobalStack);
+ DELETEZ(pGlobalErrorStack);
+}
+
+
+StackVar ScInterpreter::Interpret()
+{
+ short nRetTypeExpr = NUMBERFORMAT_UNDEFINED;
+ ULONG nRetIndexExpr = 0;
+ USHORT nErrorFunction = 0;
+ USHORT nErrorFunctionCount = 0;
+ USHORT nStackBase;
+
+#if SOMA_FPSIGNAL_JUMP
+ BOOL bIllegalFPOperationSignal = FALSE;
+ pLocalJumpBuf = pJumpBuf;
+ pJumpBuf = (jmp_buf*) new BYTE[sizeof(jmp_buf)];
+#endif
+ nGlobError = nGlobalError;
+ nGlobalError = 0;
+ nMatCount = 0;
+ bMatDel = FALSE;
+ ppGlobSortArray = NULL;
+ pTableOp = NULL;
+ nStackBase = sp = maxsp = 0;
+ nRetFmtType = NUMBERFORMAT_UNDEFINED;
+ nFuncFmtType = NUMBERFORMAT_UNDEFINED;
+ nFuncFmtIndex = nCurFmtIndex = nRetFmtIndex = 0;
+ nResult = 0;
+ pResult = NULL;
+ eResult = svDouble;
+ glSubTotal = FALSE;
+ UINT16 nOldOpCode = ocStop;
+
+ SOMA_FPCONTROL(); // FP-Exceptions ein-/ausschalten
+#if SOMA_FPSIGNAL_JUMP
+ ScSigCatchFunc pOldSigFunc = (pSignalFunc)( SC_SIGFPE, MySigFunc );
+#endif // SOMA_FPSIGNAL_JUMP
+ aCode.Reset();
+ while( ( pCur = aCode.Next() ) != NULL
+ && (!nGlobalError || nErrorFunction <= nErrorFunctionCount) )
+ {
+ OpCode eOp = pCur->GetOpCode();
+ cPar = pCur->cByte;
+ if ( eOp == ocPush )
+ {
+ Push( (ScToken&) *pCur );
+ if ( sp <= MAXSTACK )
+ pErrorStack[ sp - 1 ] = 0; // RPN-Code Push ohne Fehler
+ }
+ else
+ {
+ // bisheriger Ausdruck bestimmt das aktuelle Format
+ nCurFmtType = nRetTypeExpr;
+ nCurFmtIndex = nRetIndexExpr;
+ // default Funtionsformat, andere werden bei Bedarf gesetzt
+ nFuncFmtType = NUMBERFORMAT_NUMBER;
+ nFuncFmtIndex = 0;
+
+ if ( eOp == ocIf || eOp == ocChose )
+ nStackBase = sp; // nicht die Jumps vertueddeln
+ else
+ nStackBase = sp - pCur->GetParamCount();
+ if ( nStackBase > sp )
+ nStackBase = sp; // underflow?!?
+
+#if SOMA_FPSIGNAL_JUMP
+ if (setjmp(*pJumpBuf))
+ {
+ bIllegalFPOperationSignal = TRUE;
+ SetError( errIllegalFPOperation );
+ }
+ else
+#endif
+ {
+ switch( eOp )
+ {
+ case ocSep:
+ case ocClose: // vom Compiler gepusht
+ case ocMissing : ScMissing(); break;
+ case ocMacro : ScMacro(); break;
+ case ocDBArea : ScDBArea(); break;
+ case ocColRowNameAuto : ScColRowNameAuto(); break;
+// gesondert case ocPush : Push( (ScToken&) *pCur ); break;
+ case ocIf : ScIfJump(); break;
+ case ocChose : ScChoseJump(); break;
+ case ocAdd : ScAdd(); break;
+ case ocSub : ScSub(); break;
+ case ocMul : ScMul(); break;
+ case ocDiv : ScDiv(); break;
+ case ocAmpersand : ScAmpersand(); break;
+ case ocPow : ScPow(); break;
+ case ocEqual : ScEqual(); break;
+ case ocNotEqual : ScNotEqual(); break;
+ case ocLess : ScLess(); break;
+ case ocGreater : ScGreater(); break;
+ case ocLessEqual : ScLessEqual(); break;
+ case ocGreaterEqual : ScGreaterEqual(); break;
+ case ocAnd : ScAnd(); break;
+ case ocOr : ScOr(); break;
+ case ocIntersect : ScIntersect(); break;
+ case ocNot : ScNot(); break;
+ case ocNegSub :
+ case ocNeg : ScNeg(); break;
+ case ocPi : ScPi(); break;
+// case ocDefPar : ScDefPar(); break;
+ case ocRandom : ScRandom(); break;
+ case ocTrue : ScTrue(); break;
+ case ocFalse : ScFalse(); break;
+ case ocGetActDate : ScGetActDate(); break;
+ case ocGetActTime : ScGetActTime(); break;
+ case ocNoValue : nGlobalError = NOVALUE;
+ PushInt(0); break;
+ case ocDeg : ScDeg(); break;
+ case ocRad : ScRad(); break;
+ case ocSin : ScSin(); break;
+ case ocCos : ScCos(); break;
+ case ocTan : ScTan(); break;
+ case ocCot : ScCot(); break;
+ case ocArcSin : ScArcSin(); break;
+ case ocArcCos : ScArcCos(); break;
+ case ocArcTan : ScArcTan(); break;
+ case ocArcCot : ScArcCot(); break;
+ case ocSinHyp : ScSinHyp(); break;
+ case ocCosHyp : ScCosHyp(); break;
+ case ocTanHyp : ScTanHyp(); break;
+ case ocCotHyp : ScCotHyp(); break;
+ case ocArcSinHyp : ScArcSinHyp(); break;
+ case ocArcCosHyp : ScArcCosHyp(); break;
+ case ocArcTanHyp : ScArcTanHyp(); break;
+ case ocArcCotHyp : ScArcCotHyp(); break;
+ case ocExp : ScExp(); break;
+ case ocLn : ScLn(); break;
+ case ocLog10 : ScLog10(); break;
+ case ocSqrt : ScSqrt(); break;
+ case ocFact : ScFact(); break;
+ case ocGetYear : ScGetYear(); break;
+ case ocGetMonth : ScGetMonth(); break;
+ case ocGetDay : ScGetDay(); break;
+ case ocGetDayOfWeek : ScGetDayOfWeek(); break;
+ case ocWeek : ScGetWeekOfYear(); break;
+ case ocEasterSunday : ScEasterSunday(); break;
+ case ocGetHour : ScGetHour(); break;
+ case ocGetMin : ScGetMin(); break;
+ case ocGetSec : ScGetSec(); break;
+ case ocPlusMinus : ScPlusMinus(); break;
+ case ocAbs : ScAbs(); break;
+ case ocInt : ScInt(); break;
+ case ocEven : ScEven(); break;
+ case ocOdd : ScOdd(); break;
+ case ocPhi : ScPhi(); break;
+ case ocGauss : ScGauss(); break;
+ case ocStdNormDist : ScStdNormDist(); break;
+ case ocFisher : ScFisher(); break;
+ case ocFisherInv : ScFisherInv(); break;
+ case ocIsEmpty : ScIsEmpty(); break;
+ case ocIsString : ScIsString(); break;
+ case ocIsNonString : ScIsNonString(); break;
+ case ocIsLogical : ScIsLogical(nOldOpCode); break;
+ case ocType : ScType(); break;
+ case ocIsRef : ScIsRef(); break;
+ case ocIsValue : ScIsValue(); break;
+ case ocIsFormula : ScIsFormula(); break;
+ case ocFormula : ScFormula(); break;
+ case ocIsNV : ScIsNV(); break;
+ case ocIsErr : ScIsErr(); break;
+ case ocIsError : ScIsError(); break;
+ case ocIsEven : ScIsEven(); break;
+ case ocIsOdd : ScIsOdd(); break;
+ case ocN : ScN(); break;
+ case ocGetDateValue : ScGetDateValue(); break;
+ case ocGetTimeValue : ScGetTimeValue(); break;
+ case ocCode : ScCode(); break;
+ case ocTrim : ScTrim(); break;
+ case ocUpper : ScUpper(); break;
+ case ocPropper : ScPropper(); break;
+ case ocLower : ScLower(); break;
+ case ocLen : ScLen(); break;
+ case ocT : ScT(); break;
+ case ocClean : ScClean(); break;
+ case ocValue : ScValue(); break;
+ case ocChar : ScChar(); break;
+ case ocArcTan2 : ScArcTan2(); break;
+ case ocMod : ScMod(); break;
+ case ocPower : ScPower(); break;
+ case ocRound : ScRound(); break;
+ case ocRoundUp : ScRoundUp(); break;
+ case ocTrunc :
+ case ocRoundDown : ScRoundDown(); break;
+ case ocCeil : ScCeil(); break;
+ case ocFloor : ScFloor(); break;
+ case ocSumProduct : ScSumProduct(); break;
+ case ocSumSQ : ScSumSQ(); break;
+ case ocSumX2MY2 : ScSumX2MY2(); break;
+ case ocSumX2DY2 : ScSumX2DY2(); break;
+ case ocSumXMY2 : ScSumXMY2(); break;
+ case ocLog : ScLog(); break;
+ case ocGGT : ScGGT(); break;
+ case ocKGV : ScKGV(); break;
+ case ocGetDate : ScGetDate(); break;
+ case ocGetTime : ScGetTime(); break;
+ case ocGetDiffDate : ScGetDiffDate(); break;
+ case ocGetDiffDate360 : ScGetDiffDate360(); break;
+ case ocMin : ScMin( FALSE ); break;
+ case ocMinA : ScMin( TRUE ); break;
+ case ocMax : ScMax( FALSE ); break;
+ case ocMaxA : ScMax( TRUE ); break;
+ case ocSum : ScSum(); break;
+ case ocProduct : ScProduct(); break;
+ case ocNBW : ScNBW(); break;
+ case ocIKV : ScIKV(); break;
+ case ocAverage : ScAverage( FALSE ); break;
+ case ocAverageA : ScAverage( TRUE ); break;
+ case ocCount : ScCount(); break;
+ case ocCount2 : ScCount2(); break;
+ case ocVar : ScVar( FALSE ); break;
+ case ocVarA : ScVar( TRUE ); break;
+ case ocVarP : ScVarP( FALSE ); break;
+ case ocVarPA : ScVarP( TRUE ); break;
+ case ocStDev : ScStDev( FALSE ); break;
+ case ocStDevA : ScStDev( TRUE ); break;
+ case ocStDevP : ScStDevP( FALSE ); break;
+ case ocStDevPA : ScStDevP( TRUE ); break;
+ case ocBW : ScBW(); break;
+ case ocDIA : ScDIA(); break;
+ case ocGDA : ScGDA(); break;
+ case ocGDA2 : ScGDA2(); break;
+ case ocVBD : ScVDB(); break;
+ case ocLaufz : ScLaufz(); break;
+ case ocLIA : ScLIA(); break;
+ case ocRMZ : ScRMZ(); break;
+ case ocColumns : ScColumns(); break;
+ case ocRows : ScRows(); break;
+ case ocTables : ScTables(); break;
+ case ocColumn : ScColumn(); break;
+ case ocRow : ScRow(); break;
+ case ocTable : ScTable(); break;
+ case ocZGZ : ScZGZ(); break;
+ case ocZW : ScZW(); break;
+ case ocZZR : ScZZR(); break;
+ case ocZins : ScZins(); break;
+ case ocZinsZ : ScZinsZ(); break;
+ case ocKapz : ScKapz(); break;
+ case ocKumZinsZ : ScKumZinsZ(); break;
+ case ocKumKapZ : ScKumKapZ(); break;
+ case ocEffektiv : ScEffektiv(); break;
+ case ocNominal : ScNominal(); break;
+ case ocSubTotal : ScSubTotal(); break;
+ case ocDBSum : ScDBSum(); break;
+ case ocDBCount : ScDBCount(); break;
+ case ocDBCount2 : ScDBCount2(); break;
+ case ocDBAverage : ScDBAverage(); break;
+ case ocDBGet : ScDBGet(); break;
+ case ocDBMax : ScDBMax(); break;
+ case ocDBMin : ScDBMin(); break;
+ case ocDBProduct : ScDBProduct(); break;
+ case ocDBStdDev : ScDBStdDev(); break;
+ case ocDBStdDevP : ScDBStdDevP(); break;
+ case ocDBVar : ScDBVar(); break;
+ case ocDBVarP : ScDBVarP(); break;
+ case ocIndirect : ScIndirect(); break;
+ case ocAdress : ScAdress(); break;
+ case ocMatch : ScMatch(); break;
+ case ocCountEmptyCells : ScCountEmptyCells(); break;
+ case ocCountIf : ScCountIf(); break;
+ case ocSumIf : ScSumIf(); break;
+ case ocLookup : ScLookup(); break;
+ case ocVLookup : ScVLookup(); break;
+ case ocHLookup : ScHLookup(); break;
+ case ocIndex : ScIndex(); break;
+ case ocMultiArea : ScMultiArea(); break;
+ case ocOffset : ScOffset(); break;
+ case ocAreas : ScAreas(); break;
+ case ocCurrency : ScCurrency(); break;
+ case ocReplace : ScReplace(); break;
+ case ocFixed : ScFixed(); break;
+ case ocFind : ScFind(); break;
+ case ocExact : ScExact(); break;
+ case ocLeft : ScLeft(); break;
+ case ocRight : ScRight(); break;
+ case ocSearch : ScSearch(); break;
+ case ocMid : ScMid(); break;
+ case ocText : ScText(); break;
+ case ocSubstitute : ScSubstitute(); break;
+ case ocRept : ScRept(); break;
+ case ocConcat : ScConcat(); break;
+ case ocMatValue : ScMatValue(); break;
+ case ocMatrixUnit : ScEMat(); break;
+ case ocMatDet : ScMatDet(); break;
+ case ocMatInv : ScMatInv(); break;
+ case ocMatMult : ScMatMult(); break;
+ case ocMatTrans : ScMatTrans(); break;
+ case ocMatRef : ScMatRef(); break;
+ case ocBackSolver : ScBackSolver(); break;
+ case ocB : ScB(); break;
+ case ocNormDist : ScNormDist(); break;
+ case ocExpDist : ScExpDist(); break;
+ case ocBinomDist : ScBinomDist(); break;
+ case ocPoissonDist : ScPoissonDist(); break;
+ case ocKombin : ScKombin(); break;
+ case ocKombin2 : ScKombin2(); break;
+ case ocVariationen : ScVariationen(); break;
+ case ocVariationen2 : ScVariationen2(); break;
+ case ocHypGeomDist : ScHypGeomDist(); break;
+ case ocLogNormDist : ScLogNormDist(); break;
+ case ocTDist : ScTDist(); break;
+ case ocFDist : ScFDist(); break;
+ case ocChiDist : ScChiDist(); break;
+ case ocStandard : ScStandard(); break;
+ case ocAveDev : ScAveDev(); break;
+ case ocDevSq : ScDevSq(); break;
+ case ocKurt : ScKurt(); break;
+ case ocSchiefe : ScSkew(); break;
+ case ocModalValue : ScModalValue(); break;
+ case ocMedian : ScMedian(); break;
+ case ocGeoMean : ScGeoMean(); break;
+ case ocHarMean : ScHarMean(); break;
+ case ocWeibull : ScWeibull(); break;
+ case ocKritBinom : ScCritBinom(); break;
+ case ocNegBinomVert : ScNegBinomDist(); break;
+ case ocNoName : ScNoName(); break;
+ case ocZTest : ScZTest(); break;
+ case ocTTest : ScTTest(); break;
+ case ocFTest : ScFTest(); break;
+ case ocRank : ScRank(); break;
+ case ocPercentile : ScPercentile(); break;
+ case ocPercentrank : ScPercentrank(); break;
+ case ocLarge : ScLarge(); break;
+ case ocSmall : ScSmall(); break;
+ case ocFrequency : ScFrequency(); break;
+ case ocQuartile : ScQuartile(); break;
+ case ocNormInv : ScNormInv(); break;
+ case ocSNormInv : ScSNormInv(); break;
+ case ocConfidence : ScConfidence(); break;
+ case ocTrimMean : ScTrimMean(); break;
+ case ocProb : ScProbability(); break;
+ case ocCorrel : ScCorrel(); break;
+ case ocCovar : ScCovar(); break;
+ case ocPearson : ScPearson(); break;
+ case ocRSQ : ScRSQ(); break;
+ case ocSTEYX : ScSTEXY(); break;
+ case ocSlope : ScSlope(); break;
+ case ocIntercept : ScIntercept(); break;
+ case ocTrend : ScTrend(); break;
+ case ocGrowth : ScGrowth(); break;
+ case ocRGP : ScRGP(); break;
+ case ocRKP : ScRKP(); break;
+ case ocForecast : ScForecast(); break;
+ case ocGammaLn : ScLogGamma(); break;
+ case ocGammaDist : ScGammaDist(); break;
+ case ocGammaInv : ScGammaInv(); break;
+ case ocChiTest : ScChiTest(); break;
+ case ocChiInv : ScChiInv(); break;
+ case ocTInv : ScTInv(); break;
+ case ocFInv : ScFInv(); break;
+ case ocLogInv : ScLogNormInv(); break;
+ case ocBetaDist : ScBetaDist(); break;
+ case ocBetaInv : ScBetaInv(); break;
+ case ocExternal : ScExternal(); break;
+ case ocTableOp : ScTableOp(); break;
+// case ocErrCell : ScErrCell(); break;
+ case ocStop : break;
+ case ocErrorType : ScErrorType(); break;
+ case ocCurrent : ScCurrent(); break;
+ case ocStyle : ScStyle(); break;
+ case ocDde : ScDde(); break;
+ case ocBase : ScBase(); break;
+ case ocDecimal : ScDecimal(); break;
+ case ocConvert : ScConvert(); break;
+ case ocAnswer : ScAnswer(); break;
+ case ocTeam : ScCalcTeam(); break;
+ case ocTTT : ScTTT(); break;
+ case ocSpew : ScSpewFunc(); break;
+ case ocGame : ScGame(); break;
+ default : SetError(errUnknownOpCode); PushInt(0); break;
+ }
+ } // of else ( !setjmp )
+
+ // aeussere Funktion bestimmt das Format eines Ausdrucks
+ if ( nFuncFmtType != NUMBERFORMAT_UNDEFINED )
+ {
+ nRetTypeExpr = nFuncFmtType;
+ // nur fuer Waehrungsformate den FormatIndex uebernehmen
+ nRetIndexExpr = ( nFuncFmtType == NUMBERFORMAT_CURRENCY ?
+ nFuncFmtIndex : 0 );
+ }
+ }
+
+// Funktionen, die einen Fehlercode auswerten und nGlobalError direkt auf 0 setzen
+// usage: switch( OpCode ) { OCERRFUNCCASE( ++n ) }
+#define CASEOCERRFUNC( statement ) \
+ case ocErrorType : \
+ case ocIsEmpty : \
+ case ocIsErr : \
+ case ocIsError : \
+ case ocIsFormula : \
+ case ocIsLogical : \
+ case ocIsNV : \
+ case ocIsNonString : \
+ case ocIsRef : \
+ case ocIsString : \
+ case ocIsValue : \
+ case ocN : \
+ case ocType : \
+ statement;
+
+ switch ( eOp )
+ {
+ CASEOCERRFUNC( ++nErrorFunction )
+ }
+ if ( nGlobalError )
+ {
+ if ( !nErrorFunctionCount )
+ { // Anzahl der Fehlercode-Funktionen in Formel
+ for ( ScToken* t = rArr.FirstRPN(); t; t = rArr.NextRPN() )
+ {
+ switch ( t->GetOpCode() )
+ {
+ CASEOCERRFUNC( ++nErrorFunctionCount )
+ }
+ }
+ }
+#if SOMA_FPSIGNAL_JUMP
+ if ( bIllegalFPOperationSignal )
+ {
+ if ( sp )
+ { // eigentlich kann kein Ergebnis gepusht worden sein
+ ScToken* pRes = pStack[ sp - 1 ];
+ if ( pRes->GetOpCode() == ocPush
+ && pRes->GetType() == svDouble
+ && !SOMA_FINITE( pRes->nValue ) )
+ {
+ pRes->nValue = 0.0;
+ }
+ else
+ PushInt(0);
+ }
+ else
+ PushInt(0);
+ }
+#endif
+ if ( nErrorFunction >= nErrorFunctionCount )
+ ++nErrorFunction; // das war's, Fehler => Abbruch
+ else
+ {
+ if ( eOp != ocPush && sp > nStackBase + 1 )
+ { // Stack abraeumen, geht davon aus, dass jede Funktion
+ // prinzipiell ein Ergebnis pusht, im Fehlerfall kann dies
+ // ein zufaelliger Wert sein
+ const ScToken* pResult = pStack[ sp - 1 ];
+ while ( sp > nStackBase )
+ Pop();
+ PushTempToken( *pResult );
+ }
+#if SOMA_FPSIGNAL_JUMP
+ if ( bIllegalFPOperationSignal )
+ {
+ bIllegalFPOperationSignal = FALSE;
+ SOMA_FPCONTROL(); // FP-Exceptions ein-/ausschalten
+ (pSignalFunc)( SC_SIGFPE, MySigFunc ); // reestablish handler
+ }
+#endif
+ }
+ }
+
+ nOldOpCode = eOp;
+ }
+
+ // Ende: Returnwert holen
+
+ if( sp )
+ {
+ pCur = pStack[ sp-1 ];
+ if( pCur->GetOpCode() == ocPush )
+ {
+ if ( !nGlobalError )
+ nGlobalError = pErrorStack[ sp-1 ];
+ switch( eResult = pCur->GetType() )
+ {
+ case svDouble :
+ nResult = pCur->nValue;
+ if ( nFuncFmtType == NUMBERFORMAT_UNDEFINED )
+ {
+ nRetTypeExpr = NUMBERFORMAT_NUMBER;
+ nRetIndexExpr = 0;
+ }
+ break;
+ case svString :
+ nRetTypeExpr = NUMBERFORMAT_TEXT;
+ nRetIndexExpr = 0;
+ aResult = PopString();
+ break;
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ PopSingleRef( aAdr );
+ if( !nGlobalError )
+ {
+ ScBaseCell* pCell = pDok->GetCell( aAdr );
+ if( pCell && pCell->HasStringData() )
+ {
+ GetCellString( aResult, pCell );
+ nRetTypeExpr = NUMBERFORMAT_TEXT;
+ nRetIndexExpr = 0;
+ eResult = svString;
+ }
+ else
+ {
+ nResult = GetCellValue( aAdr, pCell );
+ nRetTypeExpr = nCurFmtType;
+ nRetIndexExpr = nCurFmtIndex;
+ eResult = svDouble;
+ }
+ }
+ }
+ break;
+ case svDoubleRef :
+ {
+ if ( bMatrixFormula )
+ { // Matrix erzeugen fuer {=A1:A5}
+ PopDoubleRefPushMatrix();
+ // kein break, weiter mit svMatrix
+ }
+ else
+ {
+ ScRange aRange;
+ PopDoubleRef( aRange );
+ ScAddress aAdr;
+ if ( !nGlobalError && DoubleRefToPosSingleRef( aRange, aAdr ) )
+ {
+ ScBaseCell* pCell = pDok->GetCell( aAdr );
+ if( pCell && pCell->HasStringData() )
+ {
+ GetCellString( aResult, pCell );
+ nRetTypeExpr = NUMBERFORMAT_TEXT;
+ nRetIndexExpr = 0;
+ eResult = svString;
+ }
+ else
+ {
+ nResult = GetCellValue( aAdr, pCell );
+ nRetTypeExpr = nCurFmtType;
+ nRetIndexExpr = nCurFmtIndex;
+ eResult = svDouble;
+ }
+ }
+ break;
+ }
+ }
+ // kein break
+ case svMatrix :
+ pResult = PopMatrix();
+ if (pResult)
+ {
+ BOOL bIsString;
+ const MatValue* pMatVal = pResult->Get(0, 0, bIsString);
+ if ( pMatVal )
+ {
+ if (bIsString)
+ {
+ aResult = *pMatVal->pS;
+ eResult = svString;
+ nRetTypeExpr = NUMBERFORMAT_TEXT;
+ nRetIndexExpr = 0;
+ }
+ else
+ {
+ nResult = pMatVal->fVal;
+ eResult = svDouble;
+ if ( nRetTypeExpr != NUMBERFORMAT_LOGICAL )
+ nRetTypeExpr = NUMBERFORMAT_NUMBER;
+ nRetIndexExpr = 0;
+ }
+ }
+ else
+ SetError(errUnknownStackVariable);
+ DBG_ASSERT(nRetMat <= MAX_ANZ_MAT,
+ "ScInterpreter::nRetMat falsch");
+ ResetNewMat(nRetMat); // Matrix nicht loeschen
+ }
+ else
+ eResult = svDouble;
+ break;
+ default :
+ SetError(errUnknownStackVariable);
+ }
+ }
+ else
+ SetError(errUnknownStackVariable);
+ }
+ else
+ SetError(errNoCode);
+#if !SOMA_FPSIGNAL_JUMP
+ if (!SOMA_FINITE(nResult))
+ {
+ nResult = 0.0;
+ SetError(errIllegalFPOperation);
+ }
+#else
+ delete [] pJumpBuf;
+ pJumpBuf = (jmp_buf*) pLocalJumpBuf;
+ (pSignalFunc)(SC_SIGFPE, pOldSigFunc);
+#endif
+
+ if( nRetTypeExpr != NUMBERFORMAT_UNDEFINED )
+ {
+ nRetFmtType = nRetTypeExpr;
+ nRetFmtIndex = nRetIndexExpr;
+ }
+ else if( nFuncFmtType != NUMBERFORMAT_UNDEFINED )
+ {
+ nRetFmtType = nFuncFmtType;
+ nRetFmtIndex = nFuncFmtIndex;
+ }
+ else
+ nRetFmtType = NUMBERFORMAT_NUMBER;
+ // nur fuer Waehrungsformate den FormatIndex uebernehmen
+ if ( nRetFmtType != NUMBERFORMAT_CURRENCY )
+ nRetFmtIndex = 0;
+
+ // grrr.. EiterZirkel!
+ // Fehler nur zuruecksetzen wenn nicht errCircularReference ohne Iterationen
+ if ( nGlobalError || !(rArr.GetError() == errCircularReference && !pDok->GetDocOptions().IsIter()) )
+ rArr.SetError( nGlobalError );
+
+ if (ppGlobSortArray)
+#ifdef WIN
+ SvMemFree(*ppGlobSortArray);
+#else
+ delete [] (*ppGlobSortArray);
+#endif
+ if (bMatDel)
+ {
+ for (USHORT i = 0; i < MAX_ANZ_MAT; i++)
+ delete ppTempMatArray[i];
+ delete [] ppTempMatArray;
+ }
+ // Tokens im ExprStack freigeben
+ ScToken** p = pStack;
+ while( maxsp-- )
+ (*p++)->DecRef();
+ nGlobalError = nGlobError;
+ if (pTableOp)
+ {
+ aTableOpList.Remove(pTableOp);
+ delete [] pTableOp;
+ }
+ return eResult;
+}
+
diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx
new file mode 100644
index 000000000000..73b210e65741
--- /dev/null
+++ b/sc/source/core/tool/interpr5.cxx
@@ -0,0 +1,4062 @@
+/*************************************************************************
+ *
+ * $RCSfile: interpr5.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:18 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <string.h>
+#include <math.h>
+
+#ifndef _ZFORLIST_HXX //autogen
+#include <svtools/zforlist.hxx>
+#endif
+
+#include "interpre.hxx"
+#include "global.hxx"
+#include "compiler.hxx"
+#include "cell.hxx"
+#include "document.hxx"
+#include "dociter.hxx"
+#include "scmatrix.hxx"
+#include "globstr.hrc"
+
+// STATIC DATA -----------------------------------------------------------
+
+#define SCdEpsilon 1.0E-7
+#ifdef WIN
+#define SC_MAX_MAT_DIM 64
+#else
+#define SC_MAX_MAT_DIM 128
+#endif
+
+
+// -----------------------------------------------------------------------
+
+double ScInterpreter::ScGetGGT(double fx, double fy)
+{
+ if (fy == 0.0 || fx == 0.0)
+ {
+ SetError(errIllegalArgument);
+ return 1.0;
+ }
+ else
+ {
+ double fz = fmod(fx, fy);
+ while (fz > 0.0)
+ {
+ fx = fy;
+ fy = fz;
+ fz = fmod(fx, fy);
+ }
+ return fy;
+ }
+}
+
+void ScInterpreter::ScGGT()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCountMin( nParamCount, 1 ) )
+ {
+ double fSign = 1.0;
+ double fx, fy;
+ switch (GetStackType())
+ {
+ case svDouble :
+ case svString:
+ case svSingleRef:
+ {
+ fy = GetDouble();
+ if (fy < 0.0)
+ {
+ fy *= -1.0;
+ fSign *= -1.0;
+ }
+ }
+ break;
+ case svDoubleRef :
+ {
+ ScRange aRange;
+ USHORT nErr = 0;
+ PopDoubleRef( aRange );
+ double nCellVal;
+ ScValueIterator aValIter(pDok, aRange, glSubTotal);
+ if (aValIter.GetFirst(nCellVal, nErr))
+ {
+ fy = nCellVal;
+ if (fy < 0.0)
+ {
+ fy *= -1.0;
+ fSign *= -1.0;
+ }
+ while (nErr == 0 && aValIter.GetNext(nCellVal, nErr))
+ {
+ fx = nCellVal;
+ if (fx < 0.0)
+ {
+ fx *= -1.0;
+ fSign *= -1.0;
+ }
+ fy = ScGetGGT(fx, fy);
+ }
+ SetError(nErr);
+ }
+ else
+ SetError(errIllegalArgument);
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ if (nC == 0 || nR == 0)
+ SetError(errIllegalArgument);
+ else
+ {
+ if (!pMat->IsValue(0))
+ {
+ SetIllegalArgument();
+ return;
+ }
+ fy = pMat->GetDouble(0);
+ if (fy < 0.0)
+ {
+ fy *= -1.0;
+ fSign *= -1.0;
+ }
+ for (USHORT j = 1; j < nC*nR; j++)
+ {
+ if (!pMat->IsValue(j))
+ {
+ SetIllegalArgument();
+ return;
+ }
+ fx = pMat->GetDouble(j);
+ if (fx < 0.0)
+ {
+ fx *= -1.0;
+ fSign *= -1.0;
+ }
+ fy = ScGetGGT(fx, fy);
+ }
+ }
+ }
+ }
+ break;
+ default : SetError(errIllegalParameter); break;
+ }
+ ScRange aRange;
+ for (short i = 0; i < (short) nParamCount - 1; i++)
+ {
+ switch (GetStackType())
+ {
+ case svDouble :
+ case svString:
+ case svSingleRef:
+ {
+ fx = GetDouble();
+ if (fx < 0.0)
+ {
+ fx *= -1.0;
+ fSign *= -1.0;
+ }
+ fy = ScGetGGT(fx, fy);
+ }
+ break;
+ case svDoubleRef :
+ {
+ USHORT nErr = 0;
+ PopDoubleRef( aRange );
+ double nCellVal;
+ ScValueIterator aValIter(pDok, aRange, glSubTotal);
+ if (aValIter.GetFirst(nCellVal, nErr))
+ {
+ fx = nCellVal;
+ if (fx < 0.0)
+ {
+ fx *= -1.0;
+ fSign *= -1.0;
+ }
+ fy = ScGetGGT(fx, fy);
+ while (nErr == 0 && aValIter.GetNext(nCellVal, nErr))
+ {
+ fx = nCellVal;
+ if (fx < 0.0)
+ {
+ fx *= -1.0;
+ fSign *= -1.0;
+ }
+ fy = ScGetGGT(fx, fy);
+ }
+ SetError(nErr);
+ }
+ else
+ SetError(errIllegalArgument);
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ if (nC == 0 || nR == 0)
+ SetError(errIllegalArgument);
+ else
+ {
+ if (!pMat->IsValue(0))
+ {
+ SetIllegalArgument();
+ return;
+ }
+ fx = pMat->GetDouble(0);
+ if (fx < 0.0)
+ {
+ fx *= -1.0;
+ fSign *= -1.0;
+ }
+ fy = ScGetGGT(fx, fy);
+ for (USHORT j = 1; j < nC*nR; j++)
+ {
+ if (!pMat->IsValue(j))
+ {
+ SetIllegalArgument();
+ return;
+ }
+ fx = pMat->GetDouble(j);
+ if (fx < 0.0)
+ {
+ fx *= -1.0;
+ fSign *= -1.0;
+ }
+ fy = ScGetGGT(fx, fy);
+ }
+ }
+ }
+ }
+ break;
+ default : SetError(errIllegalParameter); break;
+ }
+ }
+ if (fSign == -1.0)
+ PushDouble(-fy);
+ else
+ PushDouble(fy);
+ }
+}
+
+void ScInterpreter:: ScKGV()
+{
+ BYTE nParamCount = GetByte();
+ if ( MustHaveParamCountMin( nParamCount, 1 ) )
+ {
+ double fSign = 1.0;
+ double fx, fy;
+ switch (GetStackType())
+ {
+ case svDouble :
+ case svString:
+ case svSingleRef:
+ {
+ fy = GetDouble();
+ if (fy < 0.0)
+ {
+ fy *= -1.0;
+ fSign *= -1.0;
+ }
+ }
+ break;
+ case svDoubleRef :
+ {
+ ScRange aRange;
+ USHORT nErr = 0;
+ PopDoubleRef( aRange );
+ double nCellVal;
+ ScValueIterator aValIter(pDok, aRange, glSubTotal);
+ if (aValIter.GetFirst(nCellVal, nErr))
+ {
+ fy = nCellVal;
+ if (fy < 0.0)
+ {
+ fy *= -1.0;
+ fSign *= -1.0;
+ }
+ while (nErr == 0 && aValIter.GetNext(nCellVal, nErr))
+ {
+ fx = nCellVal;
+ if (fx < 0.0)
+ {
+ fx *= -1.0;
+ fSign *= -1.0;
+ }
+ fy = fx * fy / ScGetGGT(fx, fy);
+ }
+ SetError(nErr);
+ }
+ else
+ SetError(errIllegalArgument);
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ if (nC == 0 || nR == 0)
+ SetError(errIllegalArgument);
+ else
+ {
+ if (!pMat->IsValue(0))
+ {
+ SetIllegalArgument();
+ return;
+ }
+ fy = pMat->GetDouble(0);
+ if (fy < 0.0)
+ {
+ fy *= -1.0;
+ fSign *= -1.0;
+ }
+ for (USHORT j = 1; j < nC*nR; j++)
+ {
+ if (!pMat->IsValue(j))
+ {
+ SetIllegalArgument();
+ return;
+ }
+ fx = pMat->GetDouble(j);
+ if (fx < 0.0)
+ {
+ fx *= -1.0;
+ fSign *= -1.0;
+ }
+ fy = fx * fy / ScGetGGT(fx, fy);
+ }
+ }
+ }
+ }
+ break;
+ default : SetError(errIllegalParameter); break;
+ }
+ ScRange aRange;
+ for (short i = 0; i < (short) nParamCount - 1; i++)
+ {
+ switch (GetStackType())
+ {
+ case svDouble :
+ case svString:
+ case svSingleRef:
+ {
+ fx = GetDouble();
+ if (fx < 0.0)
+ {
+ fx *= -1.0;
+ fSign *= -1.0;
+ }
+ fy = fx * fy / ScGetGGT(fx, fy);
+ }
+ break;
+ case svDoubleRef :
+ {
+ USHORT nErr = 0;
+ PopDoubleRef( aRange );
+ double nCellVal;
+ ScValueIterator aValIter(pDok, aRange, glSubTotal);
+ if (aValIter.GetFirst(nCellVal, nErr))
+ {
+ fx = nCellVal;
+ if (fx < 0.0)
+ {
+ fx *= -1.0;
+ fSign *= -1.0;
+ }
+ fy = fx * fy / ScGetGGT(fx, fy);
+ while (nErr == 0 && aValIter.GetNext(nCellVal, nErr))
+ {
+ fx = nCellVal;
+ if (fx < 0.0)
+ {
+ fx *= -1.0;
+ fSign *= -1.0;
+ }
+ fy = fx * fy / ScGetGGT(fx, fy);
+ }
+ SetError(nErr);
+ }
+ else
+ SetError(errIllegalArgument);
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ if (nC == 0 || nR == 0)
+ SetError(errIllegalArgument);
+ else
+ {
+ if (!pMat->IsValue(0))
+ {
+ SetIllegalArgument();
+ return;
+ }
+ fx = pMat->GetDouble(0);
+ if (fx < 0.0)
+ {
+ fx *= -1.0;
+ fSign *= -1.0;
+ }
+ fy = fx * fy / ScGetGGT(fx, fy);
+ for (USHORT j = 1; j < nC*nR; j++)
+ {
+ if (!pMat->IsValue(j))
+ {
+ SetIllegalArgument();
+ return;
+ }
+ fx = pMat->GetDouble(j);
+ if (fx < 0.0)
+ {
+ fx *= -1.0;
+ fSign *= -1.0;
+ }
+ fy = fx * fy / ScGetGGT(fx, fy);
+ }
+ }
+ }
+ }
+ break;
+ default : SetError(errIllegalParameter); break;
+ }
+ }
+ if (fSign == -1.0)
+ PushDouble(-fy);
+ else
+ PushDouble(fy);
+ }
+}
+
+ScMatrix* ScInterpreter::GetNewMat(USHORT nC, USHORT nR, USHORT& nMatInd)
+{
+ if (nMatCount == MAX_ANZ_MAT)
+ {
+ DBG_ERROR("ScInterpreter::GetNewMat: Matrixueberlauf");
+ SetError(errCodeOverflow);
+ nMatInd = MAX_ANZ_MAT;
+ return NULL;
+ }
+ else
+ {
+ if (!bMatDel) // beim ersten Mal
+ {
+ ppTempMatArray = new ScMatrix* [MAX_ANZ_MAT];
+ for (USHORT i = 0; i < MAX_ANZ_MAT; i++)
+ ppTempMatArray[i] = NULL;
+ bMatDel = TRUE;
+ }
+ ppTempMatArray[nMatCount] = new ScMatrix(nC, nR);
+ nMatInd = nMatCount++;
+ return ppTempMatArray[nMatCount-1];
+ }
+}
+
+void ScInterpreter::ResetNewMat(USHORT nIndex)
+{
+ if (nIndex < MAX_ANZ_MAT)
+ {
+ ppTempMatArray[nIndex] = NULL;
+ if (nIndex == nMatCount - 1)
+ nMatCount--;
+ }
+}
+
+ScMatrix* ScInterpreter::GetMatrix(USHORT& nMatInd)
+{
+ ScMatrix* pMat = NULL;
+ switch (GetStackType())
+ {
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ PopSingleRef( aAdr );
+ pMat = GetNewMat(1, 1, nMatInd);
+ if (pMat)
+ {
+ ScBaseCell* pCell = GetCell( aAdr );
+ if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE )
+ {
+ if (HasCellValueData(pCell))
+ pMat->PutDouble(GetCellValue(aAdr, pCell), 0, 0);
+ else
+ {
+ String aStr;
+ GetCellString(aStr, pCell);
+ pMat->PutString(aStr, 0, 0);
+ }
+ }
+ else
+ pMat->PutEmpty( 0, 0 );
+ }
+ else
+ SetError(errCodeOverflow);
+ }
+ break;
+ case svDoubleRef:
+ {
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+ if (nTab1 == nTab2)
+ {
+ USHORT i, j;
+ if ((nRow2 - nRow1 + 1) * (nCol2 - nCol1 + 1) >
+ SC_MAX_MAT_DIM * SC_MAX_MAT_DIM)
+ SetError(errStackOverflow);
+ else
+ {
+ pMat = GetNewMat(nCol2 - nCol1 + 1, nRow2 - nRow1 + 1, nMatInd);
+ if (pMat)
+ {
+ ScAddress aAdr( nCol1, nRow1, nTab1 );
+ for (i = nRow1; i <= nRow2; i++)
+ {
+ aAdr.SetRow( i );
+ for (j = nCol1; j <= nCol2; j++)
+ {
+ aAdr.SetCol( j );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE )
+ {
+ if (HasCellValueData(pCell))
+ pMat->PutDouble(
+ GetCellValue( aAdr, pCell ),
+ j-nCol1, i-nRow1);
+ else
+ {
+ String aStr;
+ GetCellString(aStr, pCell);
+ pMat->PutString(aStr, j-nCol1, i-nRow1);
+ }
+ }
+ else
+ pMat->PutEmpty( j-nCol1, i-nRow1 );
+ }
+ }
+ }
+ else
+ SetError(errCodeOverflow);
+ }
+ }
+ else // keine 2D-Matrix
+ {
+ nMatInd = MAX_ANZ_MAT;
+ SetError(errIllegalParameter);
+ }
+ }
+ break;
+ case svMatrix:
+ pMat = PopMatrix();
+ nMatInd = MAX_ANZ_MAT;
+ break;
+ default:
+ Pop();
+ nMatInd = MAX_ANZ_MAT;
+ SetError(errIllegalParameter);
+ break;
+ }
+ return pMat;
+}
+
+void ScInterpreter::ScMatValue()
+{
+ if ( MustHaveParamCount( GetByte(), 3 ) )
+ {
+ USHORT nR = (USHORT) SolarMath::ApproxFloor(GetDouble()); // 0 bis nAnz - 1
+ USHORT nC = (USHORT) SolarMath::ApproxFloor(GetDouble()); // 0 bis nAnz - 1
+ switch (GetStackType())
+ {
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ PopSingleRef( aAdr );
+ ScBaseCell* pCell = pDok->GetCell( aAdr );
+ if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA)
+ {
+ USHORT nErrCode = ((ScFormulaCell*)pCell)->GetErrCode();
+ if (nErrCode != 0)
+ {
+ SetError(nErrCode);
+ PushInt(0);
+ }
+ else
+ {
+ ScMatrix* pMat;
+ ((ScFormulaCell*)pCell)->GetMatrix(&pMat);
+ if (pMat)
+ {
+ USHORT nCl, nRw;
+ pMat->GetDimensions(nCl, nRw);
+ if (nC < nCl && nR < nRw)
+ {
+ BOOL bIsString;
+ const MatValue* pMatVal = pMat->Get(nC, nR, bIsString);
+ if (bIsString)
+ PushStringObject(*(pMatVal->pS));
+ else
+ PushDouble(pMatVal->fVal);
+ }
+ else
+ SetNoValue();
+ }
+ else
+ SetNoValue();
+ }
+ }
+ else
+ SetIllegalParameter();
+ }
+ break;
+ case svDoubleRef :
+ {
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+ if (nCol2 - nCol1 >= nR && nRow2 - nRow1 >= nC && nTab1 == nTab2)
+ {
+ ScAddress aAdr( nCol1 + nR, nRow1 + nC, nTab1 );
+ ScBaseCell* pCell = GetCell( aAdr );
+ if (HasCellValueData(pCell))
+ PushDouble(GetCellValue( aAdr, pCell ));
+ else
+ {
+ String aStr;
+ GetCellString(aStr, pCell);
+ PushStringObject(aStr);
+ }
+ }
+ else
+ SetNoValue();
+ }
+ break;
+ case svMatrix:
+ {
+ ScMatrix* pMat = PopMatrix();
+ if (pMat)
+ {
+ USHORT nCl, nRw;
+ pMat->GetDimensions(nCl, nRw);
+ if (nC < nCl && nR < nRw)
+ {
+ BOOL bIsString;
+ const MatValue* pMatVal = pMat->Get(nC, nR, bIsString);
+ if (bIsString)
+ PushStringObject(*(pMatVal->pS));
+ else
+ PushDouble(pMatVal->fVal);
+ }
+ else
+ SetNoValue();
+ }
+ else
+ SetNoValue();
+ }
+ break;
+ default:
+ Pop();
+ SetIllegalParameter();
+ break;
+ }
+ }
+}
+
+void ScInterpreter::ScEMat()
+{
+ if ( MustHaveParamCount( GetByte(), 1 ) )
+ {
+ ULONG nDim = (ULONG) SolarMath::ApproxFloor(GetDouble());
+ if (nDim > SC_MAX_MAT_DIM || nDim == 0)
+ SetIllegalArgument();
+ else
+ {
+ USHORT nMatInd;
+ ScMatrix* pRMat = GetNewMat((USHORT)nDim, (USHORT)nDim, nMatInd);
+ if (pRMat)
+ {
+ MEMat(pRMat, (USHORT) nDim);
+ nRetMat = nMatInd;
+ PushMatrix(pRMat);
+ }
+ else
+ SetError(errStackOverflow);
+ }
+ }
+}
+
+void ScInterpreter::MEMat(ScMatrix* mM, USHORT n)
+{
+ mM->FillDouble(0.0, 0, 0, n-1, n-1);
+ for (USHORT i = 0; i < n; i++)
+ mM->PutDouble(1.0, i, i);
+}
+
+void ScInterpreter::MFastMult(ScMatrix* pA, ScMatrix* pB, ScMatrix* pR,
+ USHORT n, USHORT m, USHORT l)
+ // Multipliziert n x m Mat a mit m x l Mat b nach Mat r
+{
+ double sum;
+ for (USHORT i = 0; i < n; i++)
+ {
+ for (USHORT j = 0; j < l; j++)
+ {
+ sum = 0.0;
+ for (USHORT k = 0; k < m; k++)
+ sum += pA->GetDouble(i,k)*pB->GetDouble(k,j);
+ pR->PutDouble(sum, i, j);
+ }
+ }
+}
+
+void ScInterpreter::MFastSub(ScMatrix* pA, ScMatrix* pB, ScMatrix* pR,
+ USHORT n, USHORT m)
+ // Subtrahiert n x m Mat a - m x l Mat b nach Mat r
+{
+ for (USHORT i = 0; i < n; i++)
+ {
+ for (USHORT j = 0; j < m; j++)
+ pR->PutDouble(pA->GetDouble(i,j) - pB->GetDouble(i,j), i, j);
+ }
+}
+
+void ScInterpreter::MFastTrans(ScMatrix* pA, ScMatrix* pR,
+ USHORT n, USHORT m)
+ // Transponiert n x m Mat a nach Mat r
+{
+ for (USHORT i = 0; i < n; i++)
+ for (USHORT j = 0; j < m; j++)
+ pR->PutDouble(pA->GetDouble(i, j), j, i);
+}
+
+BOOL ScInterpreter::MFastBackSubst(ScMatrix* pA, ScMatrix* pR, USHORT n, BOOL bIsUpper)
+ // Führt Rückwaertsersetzung der Dreickesmatrix Mat a nach Mat r durch
+ // 2 Versionen fuer obere (U) oder untere (L- Unit) Dreiecksmatrizen
+{
+ short i, j, k;
+ double fSum;
+ if (!bIsUpper) // L-Matrix, immer invertierbar
+ {
+ MEMat(pR, n);
+ for (i = 1; i < (short) n; i++)
+ {
+ for (j = 0; j < i; j++)
+ {
+ fSum = 0.0;
+ for (k = 0; k < i; k++)
+ fSum += pA->GetDouble(i,k) * pR->GetDouble(k,j);
+ pR->PutDouble(-fSum, i, j);
+ }
+ }
+ }
+ else // U-Matrix
+ {
+ for (i = 0; i < (short) n; i++) // Ist invertierbar?
+ if (fabs(pA->GetDouble(i,i)) < SCdEpsilon)
+ return FALSE;
+ pR->FillDoubleLowerLeft(0.0, n-1); // untere Haelfte
+ pR->PutDouble(1.0/pA->GetDouble(n-1, n-1), n-1, n-1); // n-1, n-1
+ for (i = (short) n-2; i >= 0; i--)
+ {
+ for (j = (short) n-1; j > i; j--)
+ {
+ fSum = 0.0;
+ for (k = (short) n-1; k > i; k--)
+ fSum += pA->GetDouble(i, k) * pR->GetDouble(k, j);
+ pR->PutDouble(-fSum/pA->GetDouble(i, i), i, j);
+ }
+ fSum = 0.0; // Hauptdiagonale:
+ for (k = (short) n-1; k > i; k--)
+ fSum += pA->GetDouble(i, k) * pR->GetDouble(k, j);
+ pR->PutDouble((1.0-fSum)/pA->GetDouble(i, i), i, i);
+ }
+ }
+ return TRUE;
+}
+
+BOOL ScInterpreter::ScMatLUP(ScMatrix* mA, USHORT m, USHORT p,
+ ScMatrix* mL, ScMatrix* mU, ScMatrix* mP,
+ USHORT& rPermutCounter, BOOL& bIsInvertable)
+ // Returnwert = False <=> Matrixarray voll
+ // BIsInvertable = False: <= mA hat nicht Rang m
+{
+ USHORT nMatInd1, nMatInd2, nMatInd3, nMatInd4, nMatInd5;
+ USHORT i, j;
+ if (m == 1)
+ {
+ mL->PutDouble(1.0,0,0);
+ for (j = 0; j < p; j++)
+ if (fabs(mA->GetDouble(0, j)) >= SCdEpsilon)
+ break;
+ if (j == p)
+ {
+ bIsInvertable = FALSE;
+ return TRUE;
+ }
+ MEMat(mP, p);
+ if (j > 0 && j < p)
+ {
+ mP->PutDouble(0.0, 0, 0);
+ mP->PutDouble(1.0, j, 0);
+ mP->PutDouble(0.0, j, j);
+ mP->PutDouble(1.0, 0, j);
+ rPermutCounter++;
+ }
+ MFastMult(mA, mP, mU, m, p, p);
+ }
+ else
+ {
+ USHORT md2 = m/2;
+ ScMatrix* mB = GetNewMat(md2, p, nMatInd1);
+ ScMatrix* mC = GetNewMat(md2, p, nMatInd2);
+ ScMatrix* mL1 = GetNewMat(md2, md2, nMatInd3);
+ ScMatrix* mU1 = GetNewMat(md2, p, nMatInd4);
+ ScMatrix* mP1 = GetNewMat(p, p, nMatInd5);
+ if (!mB || !mC || !mL1 || !mU1 || !mP1 )
+ return FALSE;
+ for (i = 0; i < md2; i++)
+ {
+ for (j = 0; j < p; j++)
+ {
+ mB->PutDouble(mA->GetDouble(i, j), i, j);
+ mC->PutDouble(mA->GetDouble(md2+i,j), i, j);
+ }
+ }
+ if (!ScMatLUP(mB, md2, p, mL1, mU1, mP1, rPermutCounter, bIsInvertable))
+ return FALSE;
+ if (!bIsInvertable)
+ {
+ ResetNewMat(nMatInd5);
+ ResetNewMat(nMatInd4);
+ ResetNewMat(nMatInd3);
+ ResetNewMat(nMatInd2);
+ ResetNewMat(nMatInd1);
+ delete mP1;
+ delete mU1;
+ delete mL1;
+ delete mC;
+ delete mB;
+ return TRUE;
+ }
+ USHORT nMatInd6, nMatInd7, nMatInd8, nMatInd9, nMatInd10;
+ USHORT nMatInd11, nMatInd12, nMatInd13;
+ ScMatrix* mE = GetNewMat(md2, md2, nMatInd6);
+ ScMatrix* mF = GetNewMat(md2, md2, nMatInd7);
+ ScMatrix* mEInv = GetNewMat(md2, md2, nMatInd8);
+ ScMatrix* mG = GetNewMat(md2, p, nMatInd9);
+ ScMatrix* mGs = GetNewMat(md2, p - md2, nMatInd10);
+ ScMatrix* mU2 = GetNewMat(md2, p - md2, nMatInd11);
+ ScMatrix* mP2 = GetNewMat(p - md2, p - md2, nMatInd12);
+ if (!mP2 || !mU2 || !mGs|| !mG || !mEInv || !mF || !mE)
+ return FALSE;
+ MFastTrans(mP1, mP, p, p); // mP = mP1 hoch -1
+ ScMatrix* mD = mB; // mB wird nicht mehr gebraucht
+ MFastMult(mC, mP, mD, md2, p, p);
+ for (i = 0; i < md2; i++)
+ {
+ for (j = 0; j < md2; j++)
+ {
+ mE->PutDouble(mU1->GetDouble(i, j), i, j);
+ mF->PutDouble(mD->GetDouble(i, j), i, j);
+ }
+ }
+ BOOL bEInvok = MFastBackSubst(mE, mEInv, md2, TRUE); // MeInv = E hoch -1
+ if (!bEInvok)
+ {
+ bIsInvertable = FALSE;
+ ResetNewMat(nMatInd12);
+ ResetNewMat(nMatInd11);
+ ResetNewMat(nMatInd10);
+ ResetNewMat(nMatInd9);
+ ResetNewMat(nMatInd8);
+ ResetNewMat(nMatInd7);
+ ResetNewMat(nMatInd6);
+ ResetNewMat(nMatInd5);
+ ResetNewMat(nMatInd4);
+ ResetNewMat(nMatInd3);
+ ResetNewMat(nMatInd2);
+ ResetNewMat(nMatInd1);
+ delete mP2;
+ delete mU2;
+ delete mGs;
+ delete mG;
+ delete mEInv;
+ delete mF;
+ delete mE;
+ delete mP1;
+ delete mU1;
+ delete mL1;
+ delete mC;
+ delete mB;
+ return TRUE;
+ }
+ ScMatrix* mFEInv = mE; // mE wird nicht mehr gebraucht.
+ MFastMult(mF, mEInv, mFEInv, md2, md2, md2);
+ ScMatrix* mFEInvU1 = mC; // mC wird nicht mehr gebraucht
+ MFastMult(mFEInv, mU1, mFEInvU1, md2, md2, p);
+ MFastSub(mD, mFEInvU1, mG, md2, p);
+ for (i = 0; i < md2; i++)
+ {
+ for (j = 0; j < p-md2; j++)
+ mGs->PutDouble(mG->GetDouble(i, md2+j), i, j);
+ }
+ ScMatrix* mL2 = mF; // mF wird nicht mehr gebraucht
+ if (!ScMatLUP(mGs, md2, p - md2, mL2, mU2, mP2, rPermutCounter, bIsInvertable))
+ return FALSE;
+ if (!bIsInvertable)
+ {
+ ResetNewMat(nMatInd12);
+ ResetNewMat(nMatInd11);
+ ResetNewMat(nMatInd10);
+ ResetNewMat(nMatInd9);
+ ResetNewMat(nMatInd8);
+ ResetNewMat(nMatInd7);
+ ResetNewMat(nMatInd6);
+ ResetNewMat(nMatInd5);
+ ResetNewMat(nMatInd4);
+ ResetNewMat(nMatInd3);
+ ResetNewMat(nMatInd2);
+ ResetNewMat(nMatInd1);
+ delete mP2;
+ delete mU2;
+ delete mGs;
+ delete mG;
+ delete mEInv;
+ delete mF;
+ delete mE;
+ delete mP1;
+ delete mU1;
+ delete mL1;
+ delete mC;
+ delete mB;
+ return TRUE;
+ }
+ ScMatrix* mP3 = GetNewMat(p, p, nMatInd13);
+ if (!mP3)
+ return FALSE;
+ MEMat(mP3, p);
+ for (i = md2; i < p; i++)
+ {
+ for (j = md2; j < p; j++)
+ mP3->PutDouble(mP2->GetDouble(i-md2, j-md2), i, j);
+ }
+ MFastMult(mP3, mP1, mP, p, p, p); // Ergebnis P !!
+ ScMatrix* mP3Inv = mP1; // mP1 wird nicht mehr gebraucht;
+ MFastTrans(mP3, mP3Inv, p, p);
+ ScMatrix* mH = mD; // mD wird nicht mehr gebraucht
+ MFastMult(mU1, mP3Inv, mH, md2, p, p);
+ MEMat(mL, m); // Ergebnis L :
+ for (i = 0; i < md2; i++)
+ {
+ for (j = 0; j < i; j++)
+ mL->PutDouble(mL1->GetDouble(i, j), i, j);
+ }
+ for (i = md2; i < m; i++)
+ for (j = md2; j < i; j++)
+ mL->PutDouble(mL2->GetDouble(i-md2, j-md2), i, j);
+ for (i = md2; i < m; i++)
+ for (j = 0; j < md2; j++)
+ mL->PutDouble(mFEInv->GetDouble(i-md2, j), i, j);
+ // Ergebnis U:
+ mU->FillDoubleLowerLeft(0.0, m-1);
+ for (i = 0; i < md2; i++)
+ for (j = i; j < p; j++)
+ mU->PutDouble(mH->GetDouble(i, j), i, j);
+ for (i = md2; i < m; i++)
+ for (j = i; j < p; j++)
+ mU->PutDouble(mU2->GetDouble(i - md2, j - md2), i, j);
+ ResetNewMat(nMatInd13); // alle wieder freigeben;
+ ResetNewMat(nMatInd12);
+ ResetNewMat(nMatInd11);
+ ResetNewMat(nMatInd10);
+ ResetNewMat(nMatInd9);
+ ResetNewMat(nMatInd8);
+ ResetNewMat(nMatInd7);
+ ResetNewMat(nMatInd6);
+ ResetNewMat(nMatInd5);
+ ResetNewMat(nMatInd4);
+ ResetNewMat(nMatInd3);
+ ResetNewMat(nMatInd2);
+ ResetNewMat(nMatInd1);
+ delete mP3;
+ delete mP2;
+ delete mU2;
+ delete mGs;
+ delete mG;
+ delete mEInv;
+ delete mF;
+ delete mE;
+ delete mP1;
+ delete mU1;
+ delete mL1;
+ delete mC;
+ delete mB;
+ }
+ return TRUE;
+}
+
+void ScInterpreter::ScMatDet()
+{
+ if ( MustHaveParamCount( GetByte(), 1 ) )
+ {
+ USHORT nMatInd;
+ ScMatrix* pMat = GetMatrix(nMatInd);
+ if (!pMat)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ if ( !pMat->IsNumeric() )
+ {
+ SetNoValue();
+ return;
+ }
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ if (nC != nR || nC == 0 || nC > SC_MAX_MAT_DIM)
+ SetIllegalParameter();
+ else
+ {
+ double fVal = log((double)nC) / log(2.0);
+ if (fVal - floor(fVal) != 0.0)
+ fVal = floor(fVal) + 1.0;
+ USHORT nDim = (USHORT) pow(2.0, fVal);
+ USHORT nMatInd1, nMatInd2, nMatInd3;
+ USHORT nMatInd4 = MAX_ANZ_MAT;
+ ScMatrix* pU = GetNewMat(nDim, nDim, nMatInd1);
+ ScMatrix* pL = GetNewMat(nDim, nDim, nMatInd2);
+ ScMatrix* pP = GetNewMat(nDim, nDim, nMatInd3);
+ ScMatrix* pA;
+ if (nC == nDim)
+ pA = pMat;
+ else
+ {
+ pA = GetNewMat(nDim, nDim, nMatInd4);
+ MEMat(pA, nDim);
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nC; j++)
+ {
+ pA->PutDouble(pMat->GetDouble(i, j), i, j);
+ }
+ }
+ USHORT nPermutCounter = 0;
+ BOOL bIsInvertable = TRUE;
+ BOOL bOk = ScMatLUP(pA, nDim, nDim, pL, pU, pP,
+ nPermutCounter, bIsInvertable);
+ ResetNewMat(nMatInd4);
+ ResetNewMat(nMatInd3);
+ ResetNewMat(nMatInd2);
+ if (nC != nDim)
+ delete pA;
+ delete pP;
+ delete pL;
+ if (bOk)
+ {
+ if (!bIsInvertable)
+ PushInt(0);
+ else
+ {
+ double fDet = 1.0;
+ for (USHORT i = 0; i < nC; i++)
+ fDet *= pU->GetDouble(i, i);
+ if (nPermutCounter % 2 != 0)
+ fDet *= -1.0;
+ PushDouble(fDet);
+ }
+ }
+ else
+ {
+ SetError(errCodeOverflow);
+ PushInt(0);
+ }
+ ResetNewMat(nMatInd1);
+ delete pU;
+ }
+ }
+}
+
+void ScInterpreter::ScMatInv()
+{
+ if ( MustHaveParamCount( GetByte(), 1 ) )
+ {
+ USHORT nMatInd;
+ ScMatrix* pMat = GetMatrix(nMatInd);
+ if (!pMat)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ if ( !pMat->IsNumeric() )
+ {
+ SetNoValue();
+ return;
+ }
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ if (nC != nR || nC == 0 || nC > SC_MAX_MAT_DIM)
+ SetIllegalParameter();
+ else
+ {
+ double fVal = log((double)nC) / log(2.0);
+ if (fVal - floor(fVal) != 0.0)
+ fVal = floor(fVal) + 1.0;
+ USHORT nDim = (USHORT) pow(2.0, fVal);
+ USHORT nMatInd1, nMatInd2, nMatInd3;
+ USHORT nMatInd4 = MAX_ANZ_MAT;
+ ScMatrix* pU = GetNewMat(nDim, nDim, nMatInd1);
+ ScMatrix* pL = GetNewMat(nDim, nDim, nMatInd2);
+ ScMatrix* pP = GetNewMat(nDim, nDim, nMatInd3);
+ ScMatrix* pA;
+ if (nC == nDim)
+ pA = pMat;
+ else
+ {
+ pA = GetNewMat(nDim, nDim, nMatInd4);
+ MEMat(pA, nDim);
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nC; j++)
+ {
+ pA->PutDouble(pMat->GetDouble(i, j), i, j);
+ }
+ }
+ USHORT nPermutCounter = 0;
+ BOOL bIsInvertable = TRUE;
+ BOOL bOk = ScMatLUP(pA, nDim, nDim, pL, pU, pP,
+ nPermutCounter, bIsInvertable);
+ if (bOk)
+ {
+ if (!bIsInvertable)
+ SetNoValue();
+ else
+ {
+ USHORT nMatInd5;
+ ScMatrix* pUInv = GetNewMat(nDim, nDim, nMatInd5);
+ if (!pUInv)
+ PushInt(0);
+ else
+ {
+ bOk = MFastBackSubst(pU, pUInv, nDim, TRUE);
+ if (!bOk)
+ SetNoValue();
+ else
+ {
+ ScMatrix* pPInv = pU;
+ MFastTrans(pP, pPInv, nDim, nDim);
+ ScMatrix* pPInvUInv = pP;
+ MFastMult(pPInv, pUInv, pPInvUInv, nDim, nDim, nDim);
+ ScMatrix* pLInv = pPInv;
+ MFastBackSubst(pL, pLInv, nDim, FALSE);
+ if (nDim == nC)
+ MFastMult(pPInvUInv, pLInv, pMat, nDim, nDim, nDim);
+ else
+ {
+ MFastMult(pPInvUInv, pLInv, pL, nDim, nDim, nDim);
+ for (USHORT i = 0; i < nC; i++)
+ for (USHORT j = 0; j < nC; j++)
+ pMat->PutDouble(pL->GetDouble(i, j), i, j);
+ }
+ PushMatrix(pMat);
+ if (nMatInd != MAX_ANZ_MAT) // vorher neue Matrix
+ nRetMat = nMatInd; // sonst nRetMat wie vorher
+ ResetNewMat(nMatInd5);
+ delete pUInv;
+ }
+ }
+ }
+ }
+ else
+ {
+ SetError(errCodeOverflow);
+ PushInt(0);
+ }
+ ResetNewMat(nMatInd4);
+ ResetNewMat(nMatInd3);
+ ResetNewMat(nMatInd2);
+ ResetNewMat(nMatInd1);
+ if (nC != nDim)
+ delete pA;
+ delete pP;
+ delete pL;
+ delete pU;
+ }
+ }
+}
+
+void ScInterpreter::ScMatMult()
+{
+ if ( MustHaveParamCount( GetByte(), 2 ) )
+ {
+ USHORT nMatInd1, nMatInd2;
+ ScMatrix* pMat2 = GetMatrix(nMatInd2);
+ ScMatrix* pMat1 = GetMatrix(nMatInd1);
+ ScMatrix* pRMat;
+ if (pMat1 && pMat2)
+ {
+ if ( pMat1->IsNumeric() && pMat2->IsNumeric() )
+ {
+ USHORT nC1, nR1, nC2, nR2;
+ pMat1->GetDimensions(nC1, nR1);
+ pMat2->GetDimensions(nC2, nR2);
+ if (nC1 != nR2)
+ SetIllegalParameter();
+ else
+ {
+ USHORT nMatInd;
+ pRMat = GetNewMat(nC2, nR1, nMatInd); // Matrixabsicherung
+ if (pRMat)
+ {
+ double sum;
+ for (USHORT i = 0; i < nR1; i++)
+ {
+ for (USHORT j = 0; j < nC2; j++)
+ {
+ sum = 0.0;
+ for (USHORT k = 0; k < nC1; k++)
+ {
+ sum += pMat1->GetDouble(k,i)*pMat2->GetDouble(j,k);
+ }
+ pRMat->PutDouble(sum, j, i);
+ }
+ }
+ PushMatrix(pRMat);
+ nRetMat = nMatInd;
+ }
+ else
+ SetNoValue();
+ }
+ }
+ else
+ SetNoValue();
+ }
+ else
+ SetIllegalParameter();
+ }
+}
+
+void ScInterpreter::ScMatTrans()
+{
+ if ( MustHaveParamCount( GetByte(), 1 ) )
+ {
+ USHORT nMatInd, nMatInd1;
+ ScMatrix* pMat = GetMatrix(nMatInd);
+ ScMatrix* pRMat;
+ if (pMat)
+ {
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ pRMat = GetNewMat(nR, nC, nMatInd1);
+ pMat->MatTrans(*pRMat);
+ PushMatrix(pRMat);
+ nRetMat = nMatInd1;
+ }
+ else
+ SetIllegalParameter();
+ }
+}
+
+ScMatrix* ScInterpreter::MatAdd(ScMatrix* pMat1, ScMatrix* pMat2)
+{
+ USHORT nC1, nR1, nC2, nR2, nMinC, nMinR, i, j;
+ pMat1->GetDimensions(nC1, nR1);
+ pMat2->GetDimensions(nC2, nR2);
+ if (nC1 < nC2)
+ nMinC = nC1;
+ else
+ nMinC = nC2;
+ if (nR1 < nR2)
+ nMinR = nR1;
+ else
+ nMinR = nR2;
+ USHORT nMatInd;
+ ScMatrix* pResMat = GetNewMat(nMinC, nMinR, nMatInd);
+ if (pResMat)
+ {
+ for (i = 0; i < nMinC; i++)
+ {
+ for (j = 0; j < nMinR; j++)
+ {
+ if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
+ pResMat->PutDouble( SolarMath::ApproxAdd( pMat1->GetDouble(i,j),
+ pMat2->GetDouble(i,j)), i, j);
+ else
+ pResMat->PutString(ScGlobal::GetRscString(
+ STR_NO_VALUE), i, j);
+ }
+ }
+ nRetMat = nMatInd;
+ }
+ return pResMat;
+}
+
+ScMatrix* ScInterpreter::MatSub(ScMatrix* pMat1, ScMatrix* pMat2)
+{
+ USHORT nC1, nR1, nC2, nR2, nMinC, nMinR, i, j;
+ pMat1->GetDimensions(nC1, nR1);
+ pMat2->GetDimensions(nC2, nR2);
+ if (nC1 < nC2)
+ nMinC = nC1;
+ else
+ nMinC = nC2;
+ if (nR1 < nR2)
+ nMinR = nR1;
+ else
+ nMinR = nR2;
+ USHORT nMatInd;
+ ScMatrix* pResMat = GetNewMat(nMinC, nMinR, nMatInd);
+ if (pResMat)
+ {
+ for (i = 0; i < nMinC; i++)
+ {
+ for (j = 0; j < nMinR; j++)
+ {
+ if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
+ pResMat->PutDouble( SolarMath::ApproxSub( pMat1->GetDouble(i,j),
+ pMat2->GetDouble(i,j)), i, j);
+ else
+ pResMat->PutString(ScGlobal::GetRscString(
+ STR_NO_VALUE), i, j);
+ }
+ }
+ nRetMat = nMatInd;
+ }
+ return pResMat;
+}
+
+ScMatrix* ScInterpreter::MatMul(ScMatrix* pMat1, ScMatrix* pMat2)
+{
+ USHORT nC1, nR1, nC2, nR2, nMinC, nMinR, i, j;
+ pMat1->GetDimensions(nC1, nR1);
+ pMat2->GetDimensions(nC2, nR2);
+ if (nC1 < nC2)
+ nMinC = nC1;
+ else
+ nMinC = nC2;
+ if (nR1 < nR2)
+ nMinR = nR1;
+ else
+ nMinR = nR2;
+ USHORT nMatInd;
+ ScMatrix* pResMat = GetNewMat(nMinC, nMinR, nMatInd);
+ if (pResMat)
+ {
+ for (i = 0; i < nMinC; i++)
+ {
+ for (j = 0; j < nMinR; j++)
+ {
+ if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
+ pResMat->PutDouble(pMat1->GetDouble(i,j) *
+ pMat2->GetDouble(i,j), i, j);
+ else
+ pResMat->PutString(ScGlobal::GetRscString(
+ STR_NO_VALUE), i, j);
+ }
+ }
+ nRetMat = nMatInd;
+ }
+ return pResMat;
+}
+
+ScMatrix* ScInterpreter::MatDiv(ScMatrix* pMat1, ScMatrix* pMat2)
+{
+ USHORT nC1, nR1, nC2, nR2, nMinC, nMinR, i, j;
+ pMat1->GetDimensions(nC1, nR1);
+ pMat2->GetDimensions(nC2, nR2);
+ if (nC1 < nC2)
+ nMinC = nC1;
+ else
+ nMinC = nC2;
+ if (nR1 < nR2)
+ nMinR = nR1;
+ else
+ nMinR = nR2;
+ USHORT nMatInd;
+ ScMatrix* pResMat = GetNewMat(nMinC, nMinR, nMatInd);
+ if (pResMat)
+ {
+ for (i = 0; i < nMinC; i++)
+ {
+ for (j = 0; j < nMinR; j++)
+ {
+ if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
+ pResMat->PutDouble(pMat1->GetDouble(i,j) /
+ pMat2->GetDouble(i,j), i, j);
+ else
+ pResMat->PutString(ScGlobal::GetRscString(
+ STR_NO_VALUE), i, j);
+ }
+ }
+ nRetMat = nMatInd;
+ }
+ return pResMat;
+}
+
+ScMatrix* ScInterpreter::MatPow(ScMatrix* pMat1, ScMatrix* pMat2)
+{
+ USHORT nC1, nR1, nC2, nR2, nMinC, nMinR, i, j;
+ pMat1->GetDimensions(nC1, nR1);
+ pMat2->GetDimensions(nC2, nR2);
+ if (nC1 < nC2)
+ nMinC = nC1;
+ else
+ nMinC = nC2;
+ if (nR1 < nR2)
+ nMinR = nR1;
+ else
+ nMinR = nR2;
+ USHORT nMatInd;
+ ScMatrix* pResMat = GetNewMat(nMinC, nMinR, nMatInd);
+ if (pResMat)
+ {
+ for (i = 0; i < nMinC; i++)
+ {
+ for (j = 0; j < nMinR; j++)
+ {
+ if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
+ pResMat->PutDouble(pow(pMat1->GetDouble(i,j),
+ pMat2->GetDouble(i,j)), i, j);
+ else
+ pResMat->PutString(ScGlobal::GetRscString(
+ STR_NO_VALUE), i, j);
+ }
+ }
+ nRetMat = nMatInd;
+ }
+ return pResMat;
+}
+
+ScMatrix* ScInterpreter::MatConcat(ScMatrix* pMat1, ScMatrix* pMat2)
+{
+ USHORT nC1, nR1, nC2, nR2, nMinC, nMinR, i, j;
+ pMat1->GetDimensions(nC1, nR1);
+ pMat2->GetDimensions(nC2, nR2);
+ if (nC1 < nC2)
+ nMinC = nC1;
+ else
+ nMinC = nC2;
+ if (nR1 < nR2)
+ nMinR = nR1;
+ else
+ nMinR = nR2;
+ USHORT nMatInd;
+ ScMatrix* pResMat = GetNewMat(nMinC, nMinR, nMatInd);
+ if (pResMat)
+ {
+ for (i = 0; i < nMinC; i++)
+ {
+ for (j = 0; j < nMinR; j++)
+ {
+ if (pMat1->IsString(i,j) && pMat2->IsString(i,j))
+ {
+ String aTmp( pMat1->GetString(i,j) );
+ aTmp += pMat2->GetString(i,j);
+ pResMat->PutString( aTmp , i, j);
+ }
+ else
+ pResMat->PutString(ScGlobal::GetRscString(
+ STR_NO_VALUE), i, j);
+ }
+ }
+ nRetMat = nMatInd;
+ }
+ return pResMat;
+}
+
+
+// fuer DATE, TIME, DATETIME
+void lcl_GetDiffDateTimeFmtType( short& nFuncFmt, short nFmt1, short nFmt2 )
+{
+ if ( nFmt1 != NUMBERFORMAT_UNDEFINED || nFmt2 != NUMBERFORMAT_UNDEFINED )
+ {
+ if ( nFmt1 == nFmt2 )
+ {
+ if ( nFmt1 == NUMBERFORMAT_TIME || nFmt1 == NUMBERFORMAT_DATETIME )
+ nFuncFmt = NUMBERFORMAT_TIME; // Zeiten ergeben Zeit
+ // else: nichts besonderes, Zahl (Datum - Datum := Tage)
+ }
+ else if ( nFmt1 == NUMBERFORMAT_UNDEFINED )
+ nFuncFmt = nFmt2; // z.B. Datum + Tage := Datum
+ else if ( nFmt2 == NUMBERFORMAT_UNDEFINED )
+ nFuncFmt = nFmt1;
+ else
+ {
+ if ( nFmt1 == NUMBERFORMAT_DATE || nFmt2 == NUMBERFORMAT_DATE ||
+ nFmt1 == NUMBERFORMAT_DATETIME || nFmt2 == NUMBERFORMAT_DATETIME )
+ {
+ if ( nFmt1 == NUMBERFORMAT_TIME || nFmt2 == NUMBERFORMAT_TIME )
+ nFuncFmt = NUMBERFORMAT_DATETIME; // Datum + Zeit
+ }
+ }
+ }
+}
+
+
+void ScInterpreter::ScAdd()
+{
+ ScMatrix* pMat1 = NULL;
+ ScMatrix* pMat2 = NULL;
+ double fVal1, fVal2;
+ USHORT nMatInd1, nMatInd2;
+ short nFmt1, nFmt2;
+ nFmt1 = nFmt2 = NUMBERFORMAT_UNDEFINED;
+ short nFmtCurrencyType = nCurFmtType;
+ ULONG nFmtCurrencyIndex = nCurFmtIndex;
+ MatrixDoubleRefToMatrix();
+ if ( GetStackType() == svMatrix )
+ pMat2 = GetMatrix(nMatInd2);
+ else
+ {
+ fVal2 = GetDouble();
+ switch ( nCurFmtType )
+ {
+ case NUMBERFORMAT_DATE :
+ case NUMBERFORMAT_TIME :
+ case NUMBERFORMAT_DATETIME :
+ nFmt2 = nCurFmtType;
+ break;
+ case NUMBERFORMAT_CURRENCY :
+ nFmtCurrencyType = nCurFmtType;
+ nFmtCurrencyIndex = nCurFmtIndex;
+ break;
+ }
+ }
+ MatrixDoubleRefToMatrix();
+ if ( GetStackType() == svMatrix )
+ pMat1 = GetMatrix(nMatInd1);
+ else
+ {
+ fVal1 = GetDouble();
+ switch ( nCurFmtType )
+ {
+ case NUMBERFORMAT_DATE :
+ case NUMBERFORMAT_TIME :
+ case NUMBERFORMAT_DATETIME :
+ nFmt1 = nCurFmtType;
+ break;
+ case NUMBERFORMAT_CURRENCY :
+ nFmtCurrencyType = nCurFmtType;
+ nFmtCurrencyIndex = nCurFmtIndex;
+ break;
+ }
+ }
+ if (pMat1 && pMat2)
+ {
+ ScMatrix* pResMat = MatAdd(pMat1, pMat2);
+ if (!pResMat)
+ SetNoValue();
+ else
+ PushMatrix(pResMat);
+ }
+ else if (pMat1 || pMat2)
+ {
+ double fVal;
+ ScMatrix* pMat = pMat1;
+ if (!pMat)
+ {
+ fVal = fVal1;
+ pMat = pMat2;
+ }
+ else
+ fVal = fVal2;
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ USHORT nMatInd;
+ ScMatrix* pResMat = GetNewMat(nC, nR, nMatInd);
+ if (pResMat)
+ {
+ for (USHORT i = 0; i < nC*nR; i++)
+ {
+ if (pMat->IsValue(i))
+ pResMat->PutDouble( SolarMath::ApproxAdd( pMat->GetDouble(i), fVal), i);
+ else
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i);
+ }
+ PushMatrix(pResMat);
+ nRetMat = nMatInd;
+ }
+ else
+ SetNoValue();
+ }
+ else
+ PushDouble( SolarMath::ApproxAdd( fVal1, fVal2 ) );
+ if ( nFmtCurrencyType == NUMBERFORMAT_CURRENCY )
+ {
+ nFuncFmtType = nFmtCurrencyType;
+ nFuncFmtIndex = nFmtCurrencyIndex;
+ }
+ else
+ lcl_GetDiffDateTimeFmtType( nFuncFmtType, nFmt1, nFmt2 );
+}
+
+void ScInterpreter::ScAmpersand()
+{
+ ScMatrix* pMat1 = NULL;
+ ScMatrix* pMat2 = NULL;
+ String sStr1, sStr2;
+ USHORT nMatInd1, nMatInd2;
+ MatrixDoubleRefToMatrix();
+ if ( GetStackType() == svMatrix )
+ pMat2 = GetMatrix(nMatInd2);
+ else
+ sStr2 = GetString();
+ MatrixDoubleRefToMatrix();
+ if ( GetStackType() == svMatrix )
+ pMat1 = GetMatrix(nMatInd1);
+ else
+ sStr1 = GetString();
+ if (pMat1 && pMat2)
+ {
+ ScMatrix* pResMat = MatConcat(pMat1, pMat2);
+ if (!pResMat)
+ SetNoValue();
+ else
+ PushMatrix(pResMat);
+ }
+ else if (pMat1 || pMat2)
+ {
+ String sStr;
+ BOOL bFlag;
+ ScMatrix* pMat = pMat1;
+ if (!pMat)
+ {
+ sStr = sStr1;
+ pMat = pMat2;
+ bFlag = TRUE; // double - Matrix
+ }
+ else
+ {
+ sStr = sStr2;
+ bFlag = FALSE; // Matrix - double
+ }
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ USHORT nMatInd;
+ ScMatrix* pResMat = GetNewMat(nC, nR, nMatInd);
+ if (pResMat)
+ {
+ if (bFlag)
+ {
+ for (USHORT i = 0; i < nC*nR; i++)
+ if (!pMat->IsValue(i))
+ {
+ String sS = sStr;
+ sS += pMat->GetString(i);
+ pResMat->PutString(sS, i);
+ }
+ else
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i);
+ }
+ else
+ {
+ for (USHORT i = 0; i < nC*nR; i++)
+ if (!pMat->IsValue(i))
+ {
+ String sS = pMat->GetString(i);
+ sS += sStr;
+ pResMat->PutString(sS, i);
+ }
+ else
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i);
+ }
+ PushMatrix(pResMat);
+ nRetMat = nMatInd;
+ }
+ else
+ SetNoValue();
+ }
+ else
+ {
+ sStr1 += sStr2;
+ if (sStr1.Len() < MAXSTRLEN)
+ PushStringObject(sStr1);
+ else
+ SetError(errStringOverflow);
+ }
+}
+
+void ScInterpreter::ScSub()
+{
+ ScMatrix* pMat1 = NULL;
+ ScMatrix* pMat2 = NULL;
+ double fVal1, fVal2;
+ USHORT nMatInd1, nMatInd2;
+ short nFmt1, nFmt2;
+ nFmt1 = nFmt2 = NUMBERFORMAT_UNDEFINED;
+ short nFmtCurrencyType = nCurFmtType;
+ ULONG nFmtCurrencyIndex = nCurFmtIndex;
+ MatrixDoubleRefToMatrix();
+ if ( GetStackType() == svMatrix )
+ pMat2 = GetMatrix(nMatInd2);
+ else
+ {
+ fVal2 = GetDouble();
+ switch ( nCurFmtType )
+ {
+ case NUMBERFORMAT_DATE :
+ case NUMBERFORMAT_TIME :
+ case NUMBERFORMAT_DATETIME :
+ nFmt2 = nCurFmtType;
+ break;
+ case NUMBERFORMAT_CURRENCY :
+ nFmtCurrencyType = nCurFmtType;
+ nFmtCurrencyIndex = nCurFmtIndex;
+ break;
+ }
+ }
+ MatrixDoubleRefToMatrix();
+ if ( GetStackType() == svMatrix )
+ pMat1 = GetMatrix(nMatInd1);
+ else
+ {
+ fVal1 = GetDouble();
+ switch ( nCurFmtType )
+ {
+ case NUMBERFORMAT_DATE :
+ case NUMBERFORMAT_TIME :
+ case NUMBERFORMAT_DATETIME :
+ nFmt1 = nCurFmtType;
+ break;
+ case NUMBERFORMAT_CURRENCY :
+ nFmtCurrencyType = nCurFmtType;
+ nFmtCurrencyIndex = nCurFmtIndex;
+ break;
+ }
+ }
+ if (pMat1 && pMat2)
+ {
+ ScMatrix* pResMat = MatSub(pMat1, pMat2);
+ if (!pResMat)
+ SetNoValue();
+ else
+ PushMatrix(pResMat);
+ }
+ else if (pMat1 || pMat2)
+ {
+ double fVal;
+ BOOL bFlag;
+ ScMatrix* pMat = pMat1;
+ if (!pMat)
+ {
+ fVal = fVal1;
+ pMat = pMat2;
+ bFlag = TRUE; // double - Matrix
+ }
+ else
+ {
+ fVal = fVal2;
+ bFlag = FALSE; // Matrix - double
+ }
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ USHORT nMatInd;
+ ScMatrix* pResMat = GetNewMat(nC, nR, nMatInd);
+ if (pResMat)
+ { // mehr klammern wg. compiler macke
+ if (bFlag)
+ { for (USHORT i = 0; i < nC*nR; i++)
+ { if (pMat->IsValue(i))
+ pResMat->PutDouble( SolarMath::ApproxSub( fVal, pMat->GetDouble(i)), i);
+ else
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i);
+ }
+ }
+ else
+ { for (USHORT i = 0; i < nC*nR; i++)
+ { if (pMat->IsValue(i))
+ pResMat->PutDouble( SolarMath::ApproxSub( pMat->GetDouble(i), fVal), i);
+ else
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i);
+ }
+ }
+ PushMatrix(pResMat);
+ nRetMat = nMatInd;
+ }
+ else
+ SetNoValue();
+ }
+ else
+ PushDouble( SolarMath::ApproxSub( fVal1, fVal2 ) );
+ if ( nFmtCurrencyType == NUMBERFORMAT_CURRENCY )
+ {
+ nFuncFmtType = nFmtCurrencyType;
+ nFuncFmtIndex = nFmtCurrencyIndex;
+ }
+ else
+ lcl_GetDiffDateTimeFmtType( nFuncFmtType, nFmt1, nFmt2 );
+}
+
+void ScInterpreter::ScMul()
+{
+ ScMatrix* pMat1 = NULL;
+ ScMatrix* pMat2 = NULL;
+ double fVal1, fVal2;
+ USHORT nMatInd1, nMatInd2;
+ short nFmtCurrencyType = nCurFmtType;
+ ULONG nFmtCurrencyIndex = nCurFmtIndex;
+ MatrixDoubleRefToMatrix();
+ if ( GetStackType() == svMatrix )
+ pMat2 = GetMatrix(nMatInd2);
+ else
+ {
+ fVal2 = GetDouble();
+ switch ( nCurFmtType )
+ {
+ case NUMBERFORMAT_CURRENCY :
+ nFmtCurrencyType = nCurFmtType;
+ nFmtCurrencyIndex = nCurFmtIndex;
+ break;
+ }
+ }
+ MatrixDoubleRefToMatrix();
+ if ( GetStackType() == svMatrix )
+ pMat1 = GetMatrix(nMatInd1);
+ else
+ {
+ fVal1 = GetDouble();
+ switch ( nCurFmtType )
+ {
+ case NUMBERFORMAT_CURRENCY :
+ nFmtCurrencyType = nCurFmtType;
+ nFmtCurrencyIndex = nCurFmtIndex;
+ break;
+ }
+ }
+ if (pMat1 && pMat2)
+ {
+ ScMatrix* pResMat = MatMul(pMat1, pMat2);
+ if (!pResMat)
+ SetNoValue();
+ else
+ PushMatrix(pResMat);
+ }
+ else if (pMat1 || pMat2)
+ {
+ double fVal;
+ ScMatrix* pMat = pMat1;
+ if (!pMat)
+ {
+ fVal = fVal1;
+ pMat = pMat2;
+ }
+ else
+ fVal = fVal2;
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ USHORT nMatInd;
+ ScMatrix* pResMat = GetNewMat(nC, nR, nMatInd);
+ if (pResMat)
+ {
+ for (USHORT i = 0; i < nC*nR; i++)
+ if (pMat->IsValue(i))
+ pResMat->PutDouble(pMat->GetDouble(i)*fVal, i);
+ else
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i);
+ PushMatrix(pResMat);
+ nRetMat = nMatInd;
+ }
+ else
+ SetNoValue();
+ }
+ else
+ PushDouble(fVal1 * fVal2);
+ if ( nFmtCurrencyType == NUMBERFORMAT_CURRENCY )
+ {
+ nFuncFmtType = nFmtCurrencyType;
+ nFuncFmtIndex = nFmtCurrencyIndex;
+ }
+}
+
+void ScInterpreter::ScDiv()
+{
+ ScMatrix* pMat1 = NULL;
+ ScMatrix* pMat2 = NULL;
+ double fVal1, fVal2;
+ USHORT nMatInd1, nMatInd2;
+ short nFmtCurrencyType = nCurFmtType;
+ ULONG nFmtCurrencyIndex = nCurFmtIndex;
+ short nFmtCurrencyType2 = NUMBERFORMAT_UNDEFINED;
+ MatrixDoubleRefToMatrix();
+ if ( GetStackType() == svMatrix )
+ pMat2 = GetMatrix(nMatInd2);
+ else
+ {
+ fVal2 = GetDouble();
+ // hier kein Currency uebernehmen, 123kg/456DM sind nicht DM
+ nFmtCurrencyType2 = nCurFmtType;
+ }
+ MatrixDoubleRefToMatrix();
+ if ( GetStackType() == svMatrix )
+ pMat1 = GetMatrix(nMatInd1);
+ else
+ {
+ fVal1 = GetDouble();
+ switch ( nCurFmtType )
+ {
+ case NUMBERFORMAT_CURRENCY :
+ nFmtCurrencyType = nCurFmtType;
+ nFmtCurrencyIndex = nCurFmtIndex;
+ break;
+ }
+ }
+ if (pMat1 && pMat2)
+ {
+ ScMatrix* pResMat = MatDiv(pMat1, pMat2);
+ if (!pResMat)
+ SetNoValue();
+ else
+ PushMatrix(pResMat);
+ }
+ else if (pMat1 || pMat2)
+ {
+ double fVal;
+ BOOL bFlag;
+ ScMatrix* pMat = pMat1;
+ if (!pMat)
+ {
+ fVal = fVal1;
+ pMat = pMat2;
+ bFlag = TRUE; // double - Matrix
+ }
+ else
+ {
+ fVal = fVal2;
+ bFlag = FALSE; // Matrix - double
+ }
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ USHORT nMatInd;
+ ScMatrix* pResMat = GetNewMat(nC, nR, nMatInd);
+ if (pResMat)
+ {
+ if (bFlag)
+ { for (USHORT i = 0; i < nC*nR; i++)
+ if (pMat->IsValue(i))
+ pResMat->PutDouble(fVal / pMat->GetDouble(i), i);
+ else
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i);
+ }
+ else
+ { for (USHORT i = 0; i < nC*nR; i++)
+ if (pMat->IsValue(i))
+ pResMat->PutDouble(pMat->GetDouble(i) / fVal, i);
+ else
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i);
+ }
+ PushMatrix(pResMat);
+ nRetMat = nMatInd;
+ }
+ else
+ SetNoValue();
+ }
+ else
+ PushDouble(fVal1 / fVal2);
+ if ( nFmtCurrencyType == NUMBERFORMAT_CURRENCY && nFmtCurrencyType2 != NUMBERFORMAT_CURRENCY )
+ { // auch DM/DM ist nicht DM bzw. DEM/EUR nicht DEM
+ nFuncFmtType = nFmtCurrencyType;
+ nFuncFmtIndex = nFmtCurrencyIndex;
+ }
+}
+
+void ScInterpreter::ScPower()
+{
+ if ( MustHaveParamCount( GetByte(), 2 ) )
+ ScPow();
+}
+
+void ScInterpreter::ScPow()
+{
+ ScMatrix* pMat1 = NULL;
+ ScMatrix* pMat2 = NULL;
+ double fVal1, fVal2;
+ USHORT nMatInd1, nMatInd2;
+ MatrixDoubleRefToMatrix();
+ if ( GetStackType() == svMatrix )
+ pMat2 = GetMatrix(nMatInd2);
+ else
+ fVal2 = GetDouble();
+ MatrixDoubleRefToMatrix();
+ if ( GetStackType() == svMatrix )
+ pMat1 = GetMatrix(nMatInd1);
+ else
+ fVal1 = GetDouble();
+ if (pMat1 && pMat2)
+ {
+ ScMatrix* pResMat = MatPow(pMat1, pMat2);
+ if (!pResMat)
+ SetNoValue();
+ else
+ PushMatrix(pResMat);
+ }
+ else if (pMat1 || pMat2)
+ {
+ double fVal;
+ BOOL bFlag;
+ ScMatrix* pMat = pMat1;
+ if (!pMat)
+ {
+ fVal = fVal1;
+ pMat = pMat2;
+ bFlag = TRUE; // double - Matrix
+ }
+ else
+ {
+ fVal = fVal2;
+ bFlag = FALSE; // Matrix - double
+ }
+ USHORT nC, nR;
+ pMat->GetDimensions(nC, nR);
+ USHORT nMatInd;
+ ScMatrix* pResMat = GetNewMat(nC, nR, nMatInd);
+ if (pResMat)
+ {
+ if (bFlag)
+ { for (USHORT i = 0; i < nC*nR; i++)
+ if (pMat->IsValue(i))
+ pResMat->PutDouble(pow(fVal,pMat->GetDouble(i)), i);
+ else
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i);
+ }
+ else
+ { for (USHORT i = 0; i < nC*nR; i++)
+ if (pMat->IsValue(i))
+ pResMat->PutDouble(pow(pMat->GetDouble(i),fVal), i);
+ else
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i);
+ }
+ PushMatrix(pResMat);
+ nRetMat = nMatInd;
+ }
+ else
+ SetNoValue();
+ }
+ else
+ PushDouble(pow(fVal1,fVal2));
+}
+
+void ScInterpreter::ScSumProduct()
+{
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 1, 30 ) )
+ return;
+
+ ScMatrix* pMat1 = NULL;
+ ScMatrix* pMat2 = NULL;
+ ScMatrix* pMat = NULL;
+ USHORT nMatInd1, nMatInd2, i, j;
+ pMat2 = GetMatrix(nMatInd2);
+ if (!pMat2)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ USHORT nC, nR, nC1, nR1;
+ pMat2->GetDimensions(nC, nR);
+ pMat = pMat2;
+ for (i = 1; i < nParamCount; i++)
+ {
+ pMat1 = GetMatrix(nMatInd1);
+ if (!pMat1)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ pMat1->GetDimensions(nC1, nR1);
+ if (nC1 != nC || nR1 != nR)
+ {
+ SetNoValue();
+ return;
+ }
+ ScMatrix* pResMat = MatMul(pMat1, pMat);
+ if (!pResMat)
+ {
+ SetNoValue();
+ return;
+ }
+ else
+ pMat = pResMat;
+ }
+ double fSum = 0.0;
+ for (i = 0; i < nC; i++)
+ for (j = 0; j < nR; j++)
+ if (!pMat->IsString(i,j))
+ fSum += pMat->GetDouble(i,j);
+ PushDouble(fSum);
+}
+
+void ScInterpreter::ScSumX2MY2()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+
+ ScMatrix* pMat1 = NULL;
+ ScMatrix* pMat2 = NULL;
+ USHORT nMatInd1, nMatInd2, i, j;
+ pMat2 = GetMatrix(nMatInd2);
+ pMat1 = GetMatrix(nMatInd1);
+ if (!pMat2 || !pMat1)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ USHORT nC2, nR2, nC1, nR1;
+ pMat2->GetDimensions(nC2, nR2);
+ pMat1->GetDimensions(nC1, nR1);
+ if (nC1 != nC2 || nR1 != nR2)
+ {
+ SetNoValue();
+ return;
+ }
+ double fVal, fSum = 0.0;
+ for (i = 0; i < nC1; i++)
+ for (j = 0; j < nR1; j++)
+ if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
+ {
+ fVal = pMat1->GetDouble(i,j);
+ fSum += fVal * fVal;
+ fVal = pMat2->GetDouble(i,j);
+ fSum -= fVal * fVal;
+ }
+ PushDouble(fSum);
+}
+
+void ScInterpreter::ScSumX2DY2()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+
+ ScMatrix* pMat1 = NULL;
+ ScMatrix* pMat2 = NULL;
+ USHORT nMatInd1, nMatInd2, i, j;
+ pMat2 = GetMatrix(nMatInd2);
+ pMat1 = GetMatrix(nMatInd1);
+ if (!pMat2 || !pMat1)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ USHORT nC2, nR2, nC1, nR1;
+ pMat2->GetDimensions(nC2, nR2);
+ pMat1->GetDimensions(nC1, nR1);
+ if (nC1 != nC2 || nR1 != nR2)
+ {
+ SetNoValue();
+ return;
+ }
+ double fVal, fSum = 0.0;
+ for (i = 0; i < nC1; i++)
+ for (j = 0; j < nR1; j++)
+ if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
+ {
+ fVal = pMat1->GetDouble(i,j);
+ fSum += fVal * fVal;
+ fVal = pMat2->GetDouble(i,j);
+ fSum += fVal * fVal;
+ }
+ PushDouble(fSum);
+}
+
+void ScInterpreter::ScSumXMY2()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+
+ ScMatrix* pMat1 = NULL;
+ ScMatrix* pMat2 = NULL;
+ USHORT nMatInd1, nMatInd2, i, j;
+ pMat2 = GetMatrix(nMatInd2);
+ pMat1 = GetMatrix(nMatInd1);
+ if (!pMat2 || !pMat1)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ USHORT nC2, nR2, nC1, nR1;
+ pMat2->GetDimensions(nC2, nR2);
+ pMat1->GetDimensions(nC1, nR1);
+ if (nC1 != nC2 || nR1 != nR2)
+ {
+ SetNoValue();
+ return;
+ }
+ ScMatrix* pResMat = MatSub(pMat1, pMat2);
+ if (!pResMat)
+ {
+ SetNoValue();
+ return;
+ }
+ else
+ {
+ double fVal, fSum = 0.0;
+ for (i = 0; i < nC1; i++)
+ for (j = 0; j < nR1; j++)
+ if (!pResMat->IsString(i,j))
+ {
+ fVal = pResMat->GetDouble(i,j);
+ fSum += fVal * fVal;
+ }
+ PushDouble(fSum);
+ }
+}
+
+void ScInterpreter::ScFrequency()
+{
+ if ( !MustHaveParamCount( GetByte(), 2 ) )
+ return;
+
+ USHORT nMatInd;
+ double* pSortArray1 = NULL;
+ ULONG nSize1 = 0;
+ GetSortArray(1, &pSortArray1, nSize1);
+ if (nGlobalError)
+ SetNoValue();
+ double* pSortArray2 = NULL;
+ ULONG nSize2 = 0;
+ GetSortArray(1, &pSortArray2, nSize2);
+ if (!pSortArray2 || nSize2 == 0 || nGlobalError)
+ {
+ if (pSortArray1)
+ delete pSortArray1;
+ if (pSortArray2)
+ delete pSortArray2;
+ SetNoValue();
+ return;
+ }
+ ScMatrix* pResMat = GetNewMat(1,(USHORT)nSize1+1,nMatInd);
+ if (!pResMat)
+ {
+ if (pSortArray1)
+ delete pSortArray1;
+ if (pSortArray2)
+ delete pSortArray2;
+ SetNoValue();
+ return;
+ }
+
+ USHORT j;
+ ULONG i = 0;
+ ULONG nCount;
+ for (j = 0; j < nSize1; j++)
+ {
+ nCount = 0;
+ while (i < nSize2 && pSortArray2[i] <= pSortArray1[j])
+ {
+ nCount++;
+ i++;
+ }
+ pResMat->PutDouble((double) nCount, 0, j);
+ }
+ pResMat->PutDouble((double) (nSize2-i), 0, j);
+ if (pSortArray1)
+ delete pSortArray1;
+ if (pSortArray2)
+ delete pSortArray2;
+ PushMatrix(pResMat);
+ nRetMat = nMatInd;
+}
+
+BOOL ScInterpreter::RGetVariances( ScMatrix* pV, ScMatrix* pX,
+ USHORT nC, USHORT nR, BOOL bSwapColRow, BOOL bZeroConstant )
+{ // multiple Regression: Varianzen der Koeffizienten
+ // bSwapColRow==TRUE : Koeffizienten in Zeilen statt Spalten angeordnet
+ USHORT i, j, k, nMatInd;
+ double sum;
+ ScMatrix* pC = GetNewMat(nC, nC, nMatInd);
+ if ( !pC )
+ return FALSE;
+ // X transformiert mit X multipziert, X'X Matrix
+ if ( !bZeroConstant )
+ { // in der X-Designmatrix existiert ein gedachtes X0j==1
+ if ( bSwapColRow )
+ {
+ for ( i=0; i<nC; i++ )
+ {
+ for ( j=0; j<nC; j++ )
+ {
+ sum = 0.0;
+ for ( k=0; k<nR; k++ )
+ {
+ sum += (j==0 ? 1 : pX->GetDouble(k,j-1))
+ * (i==0 ? 1 : pX->GetDouble(k,i-1));
+ }
+ pC->PutDouble(sum, i, j);
+ }
+ }
+ }
+ else
+ {
+ for ( i=0; i<nC; i++ )
+ {
+ for ( j=0; j<nC; j++ )
+ {
+ sum = 0.0;
+ for ( k=0; k<nR; k++ )
+ {
+ sum += (j==0 ? 1 : pX->GetDouble(j-1,k))
+ * (i==0 ? 1 : pX->GetDouble(i-1,k));
+ }
+ pC->PutDouble(sum, i, j);
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( bSwapColRow )
+ {
+ for ( i=0; i<nC; i++ )
+ {
+ for ( j=0; j<nC; j++ )
+ {
+ sum = 0.0;
+ for ( k=0; k<nR; k++ )
+ {
+ sum += pX->GetDouble(k,j) * pX->GetDouble(k,i);
+ }
+ pC->PutDouble(sum, i, j);
+ }
+ }
+ }
+ else
+ {
+ for ( i=0; i<nC; i++ )
+ {
+ for ( j=0; j<nC; j++ )
+ {
+ sum = 0.0;
+ for ( k=0; k<nR; k++ )
+ {
+ sum += pX->GetDouble(j,k) * pX->GetDouble(i,k);
+ }
+ pC->PutDouble(sum, i, j);
+ }
+ }
+ }
+ }
+ // X'X Inverse
+ BOOL bOk = TRUE;
+ USHORT nErr = nGlobalError;
+ PushMatrix(pC);
+ BYTE nTmp = cPar;
+ cPar = 1;
+ ScMatInv();
+ cPar = nTmp;
+ if ( nGlobalError )
+ {
+ nGlobalError = nErr;
+ bOk = FALSE;
+ }
+ else
+ {
+ Pop(); // pC bleibt erhalten
+ // Varianzen auf der Diagonalen, andere sind Kovarianzen
+ for (i = 0; i < nC; i++)
+ pV->PutDouble(pC->GetDouble(i, i), i);
+ }
+ delete pC;
+ ResetNewMat(nMatInd);
+ return bOk;
+}
+
+void ScInterpreter::ScRGP()
+{
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 1, 4 ) )
+ return;
+ BOOL bConstant, bStats;
+ if (nParamCount == 4)
+ bStats = GetBool();
+ else
+ bStats = FALSE;
+ if (nParamCount >= 3)
+ bConstant = GetBool();
+ else
+ bConstant = TRUE;
+ USHORT nMatInd1, nMatInd2;
+ ScMatrix* pMatX;
+ ScMatrix* pMatY;
+ if (nParamCount >= 2)
+ pMatX = GetMatrix(nMatInd2);
+ else
+ pMatX = NULL;
+ pMatY = GetMatrix(nMatInd1);
+ if (!pMatY)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ BYTE nCase; // 1 = normal, 2,3 = mehrfach
+ USHORT nCX, nRX, nCY, nRY, M, N;
+ pMatY->GetDimensions(nCY, nRY);
+ for (USHORT i = 0; i < nCY*nRY; i++)
+ if (!pMatY->IsValue(i))
+ {
+ SetIllegalArgument();
+ return;
+ }
+ if (pMatX)
+ {
+ pMatX->GetDimensions(nCX, nRX);
+ for (USHORT i = 0; i < nCX*nRX; i++)
+ if (!pMatX->IsValue(i))
+ {
+ SetIllegalArgument();
+ return;
+ }
+ if (nCX == nCY && nRX == nRY)
+ nCase = 1; // einfache Regression
+ else if (nCY != 1 && nRY != 1)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ else if (nCY == 1)
+ {
+ if (nRX != nRY)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ else
+ {
+ nCase = 2; // zeilenweise
+ N = nRY;
+ M = nCX;
+ }
+ }
+ else if (nCX != nCY)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ else
+ {
+ nCase = 3; // spaltenweise
+ N = nCY;
+ M = nRX;
+ }
+ }
+ else
+ {
+ pMatX = GetNewMat(nCY, nRY, nMatInd2);
+ if (!pMatX)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ for (USHORT i = 1; i <= nCY*nRY; i++)
+ pMatX->PutDouble((double)i, i-1);
+ nCase = 1;
+ }
+ USHORT nMatInd;
+ ScMatrix* pResMat;
+ if (nCase == 1)
+ {
+ if (!bStats)
+ pResMat = GetNewMat(2,1,nMatInd);
+ else
+ pResMat = GetNewMat(2,5,nMatInd);
+ if (!pResMat)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ double fCount = 0.0;
+ double fSumX = 0.0;
+ double fSumSqrX = 0.0;
+ double fSumY = 0.0;
+ double fSumSqrY = 0.0;
+ double fSumXY = 0.0;
+ double fValX, fValY;
+ for (USHORT i = 0; i < nCY; i++)
+ for (USHORT j = 0; j < nRY; j++)
+ {
+ fValX = pMatX->GetDouble(i,j);
+ fValY = pMatY->GetDouble(i,j);
+ fSumX += fValX;
+ fSumSqrX += fValX * fValX;
+ fSumY += fValY;
+ fSumSqrY += fValY * fValY;
+ fSumXY += fValX*fValY;
+ fCount++;
+ }
+ if (fCount < 1.0)
+ SetNoValue();
+ else
+ {
+ double f1 = fCount*fSumXY-fSumX*fSumY;
+ double fX = fCount*fSumSqrX-fSumX*fSumX;
+ double b, m;
+ if (bConstant)
+ {
+ b = fSumY/fCount - f1/fX*fSumX/fCount;
+ m = f1/fX;
+ }
+ else
+ {
+ b = 0.0;
+ m = fSumXY/fSumSqrX;
+ }
+ pResMat->PutDouble(m, 0, 0);
+ pResMat->PutDouble(b, 1, 0);
+ if (bStats)
+ {
+ double fY = fCount*fSumSqrY-fSumY*fSumY;
+ double fSyx = fSumSqrY-b*fSumY-m*fSumXY;
+ double fR2 = f1*f1/(fX*fY);
+ pResMat->PutDouble (fR2, 0, 2);
+ if (fCount < 3.0)
+ {
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), 0, 1 );
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), 1, 1 );
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), 1, 2 );
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), 0, 3 );
+ }
+ else
+ {
+ pResMat->PutDouble(sqrt(fSyx*fCount/(fX*(fCount-2.0))), 0, 1);
+ pResMat->PutDouble(sqrt(fSyx*fSumSqrX/fX/(fCount-2.0)), 1, 1);
+ pResMat->PutDouble(
+ sqrt((fCount*fSumSqrY - fSumY*fSumY - f1*f1/fX)/
+ (fCount*(fCount-2.0))), 1, 2);
+ if (fR2 == 1.0)
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), 0, 3 );
+ else
+ pResMat->PutDouble(fR2*(fCount-2.0)/(1.0-fR2), 0, 3);
+ }
+ pResMat->PutDouble(((double)(nCY*nRY))-2.0, 1, 3);
+ pResMat->PutDouble(fY/fCount-fSyx, 0, 4);
+ pResMat->PutDouble(fSyx, 1, 4);
+ }
+ }
+ }
+ else
+ {
+ USHORT nMatInd10, nMatInd12, nMatInd13, i, j, k;
+ if (!bStats)
+ pResMat = GetNewMat(M+1,1,nMatInd);
+ else
+ pResMat = GetNewMat(M+1,5,nMatInd);
+ if (!pResMat)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ BOOL bVariancesOk = TRUE;
+ ScMatrix* pQ = GetNewMat(M+1, M+2, nMatInd10);
+ ScMatrix* pE = GetNewMat(M+2, 1, nMatInd12);
+ ScMatrix* pV = GetNewMat(M+1, 1, nMatInd13);
+ pE->PutDouble(0.0, M+1);
+ pQ->FillDouble(0.0, 0, 0, M, M+1);
+ if (nCase == 2)
+ {
+ for (k = 0; k < N; k++)
+ {
+ double Yk = pMatY->GetDouble(k);
+ pE->PutDouble( pE->GetDouble(M+1)+Yk*Yk, M+1 );
+ double sumYk = pQ->GetDouble(0, M+1) + Yk;
+ pQ->PutDouble( sumYk, 0, M+1 );
+ pE->PutDouble( sumYk, 0 );
+ for (i = 0; i < M; i++)
+ {
+ double Xik = pMatX->GetDouble(i,k);
+ double sumXik = pQ->GetDouble(0, i+1) + Xik;
+ pQ->PutDouble( sumXik, 0, i+1);
+ pQ->PutDouble( sumXik, i+1, 0);
+ double sumXikYk = pQ->GetDouble(i+1, M+1) + Xik * Yk;
+ pQ->PutDouble( sumXikYk, i+1, M+1);
+ pE->PutDouble( sumXikYk, i+1);
+ for (j = i; j < M; j++)
+ {
+ double sumXikXjk = pQ->GetDouble(j+1, i+1) +
+ Xik * pMatX->GetDouble(j,k);
+ pQ->PutDouble( sumXikXjk, j+1, i+1);
+ pQ->PutDouble( sumXikXjk, i+1, j+1);
+ }
+ }
+ }
+ }
+ else
+ {
+ for (k = 0; k < N; k++)
+ {
+ double Yk = pMatY->GetDouble(k);
+ pE->PutDouble( pE->GetDouble(M+1)+Yk*Yk, M+1 );
+ double sumYk = pQ->GetDouble(0, M+1) + Yk;
+ pQ->PutDouble( sumYk, 0, M+1 );
+ pE->PutDouble( sumYk, 0 );
+ for (i = 0; i < M; i++)
+ {
+ double Xki = pMatX->GetDouble(k,i);
+ double sumXki = pQ->GetDouble(0, i+1) + Xki;
+ pQ->PutDouble( sumXki, 0, i+1);
+ pQ->PutDouble( sumXki, i+1, 0);
+ double sumXkiYk = pQ->GetDouble(i+1, M+1) + Xki * Yk;
+ pQ->PutDouble( sumXkiYk, i+1, M+1);
+ pE->PutDouble( sumXkiYk, i+1);
+ for (j = i; j < M; j++)
+ {
+ double sumXkiXkj = pQ->GetDouble(j+1, i+1) +
+ Xki * pMatX->GetDouble(k,j);
+ pQ->PutDouble( sumXkiXkj, j+1, i+1);
+ pQ->PutDouble( sumXkiXkj, i+1, j+1);
+ }
+ }
+ }
+ }
+ pQ->PutDouble((double)N, 0, 0);
+ if (bConstant)
+ {
+ USHORT S, L;
+ for (S = 0; S < M+1; S++)
+ {
+ i = S;
+ while (i < M+1 && pQ->GetDouble(i, S) == 0.0)
+ i++;
+ if (i >= M+1)
+ {
+ SetNoValue();
+ delete pQ;
+ delete pE;
+ delete pV;
+ ResetNewMat(nMatInd13);
+ ResetNewMat(nMatInd12);
+ ResetNewMat(nMatInd10);
+ return;
+ }
+ double fVal;
+ for (L = 0; L < M+2; L++)
+ {
+ fVal = pQ->GetDouble(S, L);
+ pQ->PutDouble(pQ->GetDouble(i, L), S, L);
+ pQ->PutDouble(fVal, i, L);
+ }
+ fVal = 1.0/pQ->GetDouble(S, S);
+ for (L = 0; L < M+2; L++)
+ pQ->PutDouble(pQ->GetDouble(S, L)*fVal, S, L);
+ for (i = 0; i < M+1; i++)
+ {
+ if (i != S)
+ {
+ fVal = -pQ->GetDouble(i, S);
+ for (L = 0; L < M+2; L++)
+ pQ->PutDouble(
+ pQ->GetDouble(i,L)+fVal*pQ->GetDouble(S,L),i,L);
+ }
+ }
+ }
+ }
+ else
+ {
+ USHORT S, L;
+ for (S = 1; S < M+1; S++)
+ {
+ i = S;
+ while (i < M+1 && pQ->GetDouble(i, S) == 0.0)
+ i++;
+ if (i >= M+1)
+ {
+ SetNoValue();
+ delete pQ;
+ delete pE;
+ delete pV;
+ ResetNewMat(nMatInd13);
+ ResetNewMat(nMatInd12);
+ ResetNewMat(nMatInd10);
+ return;
+ }
+ double fVal;
+ for (L = 1; L < M+2; L++)
+ {
+ fVal = pQ->GetDouble(S, L);
+ pQ->PutDouble(pQ->GetDouble(i, L), S, L);
+ pQ->PutDouble(fVal, i, L);
+ }
+ fVal = 1.0/pQ->GetDouble(S, S);
+ for (L = 1; L < M+2; L++)
+ pQ->PutDouble(pQ->GetDouble(S, L)*fVal, S, L);
+ for (i = 1; i < M+1; i++)
+ {
+ if (i != S)
+ {
+ fVal = -pQ->GetDouble(i, S);
+ for (L = 1; L < M+2; L++)
+ pQ->PutDouble(
+ pQ->GetDouble(i,L)+fVal*pQ->GetDouble(S,L),i,L);
+ }
+ }
+ pQ->PutDouble(0.0, 0, M+1); // Konstante b
+ }
+ }
+ // mn ... m1, b
+ for (i = 0; i < M+1; i++)
+ pResMat->PutDouble(pQ->GetDouble(M-i,M+1), i, 0);
+ if (bStats)
+ {
+ // pE[0] := Sigma i=1...n (Yi)
+ // pE[k] := Sigma i=1...n (Xki*Yi)
+ // pE[M+1] := Sigma i=1...n (Yi**2)
+ // pQ[0,M+1]:= B
+ // pQ[k,M+1]:= Mk
+ double fSQR, fSQT, fSQE;
+ fSQT = pE->GetDouble(M+1)
+ - pE->GetDouble(0) * pE->GetDouble(0) / (double)N;
+ fSQR = pE->GetDouble(M+1);
+ for (i = 0; i < M+1; i++)
+ fSQR -= pQ->GetDouble(i, M+1) * pE->GetDouble(i);
+ fSQE = fSQT-fSQR;
+ // r2 (Bestimmtheitsmass, 0...1)
+ if (fSQT == 0.0)
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), 0, 2);
+ else
+ pResMat->PutDouble (fSQE/fSQT, 0, 2);
+ // ssReg (Regressions-Quadratsumme)
+ pResMat->PutDouble(fSQE, 0, 4);
+ // ssResid (Residual-Quadratsumme, Summe der Abweichungsquadrate)
+ pResMat->PutDouble(fSQR, 1, 4);
+ for (i = 2; i < 5; i++)
+ for (j = 2; j < M+1; j++)
+ pResMat->PutString(ScGlobal::GetRscString(STR_NV_STR), j, i);
+ if (bConstant)
+ {
+ if (N-M-1 == 0)
+ {
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), 1, 2);
+ for (i = 0; i < M+1; i++)
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i, 1);
+ }
+ else
+ {
+ double fSE2 = fSQR/(N-M-1);
+ // sey (Standardfehler des Schaetzwertes y)
+ pResMat->PutDouble(sqrt(fSE2), 1, 2);
+ // sen...se1 (Standardfehler der Koeffizienten mn...m1)
+ // seb (Standardfehler der Konstanten b)
+ if ( RGetVariances( pV, pMatX, M+1, N, nCase != 2, FALSE ) )
+ {
+ for (i = 0; i < M+1; i++)
+ pResMat->PutDouble( sqrt(fSE2 * pV->GetDouble(i)), M-i, 1 );
+ }
+ else
+ {
+ for (i = 0; i < M+1; i++)
+ pResMat->PutString(ScGlobal::GetRscString(STR_NV_STR), i, 1);
+ }
+ }
+ // F (F-Statistik)
+ if (fSQR == 0.0)
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), 0, 3);
+ else
+ pResMat->PutDouble(((double)(N-M-1))*fSQE/fSQR/((double)M),0, 3);
+ // df (Freiheitsgrad)
+ pResMat->PutDouble(((double)(N-M-1)), 1, 3);
+ }
+ else
+ {
+ if (N-M == 0)
+ {
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), 1, 2);
+ for (i = 0; i < M+1; i++)
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i, 1);
+ }
+ else
+ {
+ double fSE2 = fSQR/(N-M);
+ pResMat->PutDouble(sqrt(fSE2), 1, 2);
+ if ( RGetVariances( pV, pMatX, M, N, nCase != 2, TRUE ) )
+ {
+ for (i = 0; i < M; i++)
+ pResMat->PutDouble( sqrt(fSE2 * pV->GetDouble(i)), M-i-1, 1 );
+ pResMat->PutString(ScGlobal::GetRscString(STR_NV_STR), M, 1);
+ }
+ else
+ {
+ for (i = 0; i < M+1; i++)
+ pResMat->PutString(ScGlobal::GetRscString(STR_NV_STR), i, 1);
+ }
+ }
+ if (fSQR == 0.0)
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), 0, 3);
+ else
+ pResMat->PutDouble(((double)(N-M))*fSQE/fSQR/((double)M),0, 3);
+ pResMat->PutDouble(((double)(N-M)), 1, 3);
+ }
+ }
+ delete pQ;
+ delete pE;
+ delete pV;
+ ResetNewMat(nMatInd13);
+ ResetNewMat(nMatInd12);
+ ResetNewMat(nMatInd10);
+ }
+ PushMatrix(pResMat);
+ nRetMat = nMatInd;
+}
+
+void ScInterpreter::ScRKP()
+{
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 1, 4 ) )
+ return;
+ BOOL bConstant, bStats;
+ if (nParamCount == 4)
+ bStats = GetBool();
+ else
+ bStats = FALSE;
+ if (nParamCount >= 3)
+ bConstant = GetBool();
+ else
+ bConstant = TRUE;
+ USHORT nMatInd1, nMatInd2;
+ ScMatrix* pMatX;
+ ScMatrix* pMatY;
+ if (nParamCount >= 2)
+ pMatX = GetMatrix(nMatInd2);
+ else
+ pMatX = NULL;
+ pMatY = GetMatrix(nMatInd1);
+ if (!pMatY)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ BYTE nCase; // 1 = normal, 2,3 = mehrfach
+ USHORT nCX, nRX, nCY, nRY, M, N;
+ pMatY->GetDimensions(nCY, nRY);
+ USHORT i;
+ for (i = 0; i < nCY*nRY; i++)
+ if (!pMatY->IsValue(i))
+ {
+ SetIllegalArgument();
+ return;
+ }
+ for (i = 0; i < nCY*nRY; i++)
+ {
+ if (pMatY->GetDouble(i) <= 0.0)
+ {
+ SetIllegalArgument();
+ return;
+ }
+ else
+ pMatY->PutDouble(log(pMatY->GetDouble(i)), i);
+ }
+ if (pMatX)
+ {
+ pMatX->GetDimensions(nCX, nRX);
+ for (i = 0; i < nCX*nRX; i++)
+ if (!pMatX->IsValue(i))
+ {
+ SetIllegalArgument();
+ return;
+ }
+ if (nCX == nCY && nRX == nRY)
+ nCase = 1; // einfache Regression
+ else if (nCY != 1 && nRY != 1)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ else if (nCY == 1)
+ {
+ if (nRX != nRY)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ else
+ {
+ nCase = 2; // zeilenweise
+ N = nRY;
+ M = nCX;
+ }
+ }
+ else if (nCX != nCY)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ else
+ {
+ nCase = 3; // spaltenweise
+ N = nCY;
+ M = nRX;
+ }
+ }
+ else
+ {
+ pMatX = GetNewMat(nCY, nRY, nMatInd2);
+ if (!pMatX)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ for (USHORT i = 1; i <= nCY*nRY; i++)
+ pMatX->PutDouble((double)i, i-1);
+ nCase = 1;
+ }
+ USHORT nMatInd;
+ ScMatrix* pResMat;
+ if (nCase == 1)
+ {
+ if (!bStats)
+ pResMat = GetNewMat(2,1,nMatInd);
+ else
+ pResMat = GetNewMat(2,5,nMatInd);
+ if (!pResMat)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ double fCount = 0.0;
+ double fSumX = 0.0;
+ double fSumSqrX = 0.0;
+ double fSumY = 0.0;
+ double fSumSqrY = 0.0;
+ double fSumXY = 0.0;
+ double fValX, fValY;
+ for (USHORT i = 0; i < nCY; i++)
+ for (USHORT j = 0; j < nRY; j++)
+ {
+ fValX = pMatX->GetDouble(i,j);
+ fValY = pMatY->GetDouble(i,j);
+ fSumX += fValX;
+ fSumSqrX += fValX * fValX;
+ fSumY += fValY;
+ fSumSqrY += fValY * fValY;
+ fSumXY += fValX*fValY;
+ fCount++;
+ }
+ if (fCount < 1.0)
+ SetNoValue();
+ else
+ {
+ double f1 = fCount*fSumXY-fSumX*fSumY;
+ double fX = fCount*fSumSqrX-fSumX*fSumX;
+ double b, m;
+ if (bConstant)
+ {
+ b = fSumY/fCount - f1/fX*fSumX/fCount;
+ m = f1/fX;
+ }
+ else
+ {
+ b = 0.0;
+ m = fSumXY/fSumSqrX;
+ }
+ pResMat->PutDouble(exp(m), 0, 0);
+ pResMat->PutDouble(exp(b), 1, 0);
+ if (bStats)
+ {
+ double fY = fCount*fSumSqrY-fSumY*fSumY;
+ double fSyx = fSumSqrY-b*fSumY-m*fSumXY;
+ double fR2 = f1*f1/(fX*fY);
+ pResMat->PutDouble (fR2, 0, 2);
+ if (fCount < 3.0)
+ {
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), 0, 1 );
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), 1, 1 );
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), 1, 2 );
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), 0, 3 );
+ }
+ else
+ {
+ pResMat->PutDouble(sqrt(fSyx*fCount/(fX*(fCount-2.0))), 0, 1);
+ pResMat->PutDouble(sqrt(fSyx*fSumSqrX/fX/(fCount-2.0)), 1, 1);
+ pResMat->PutDouble(
+ sqrt((fCount*fSumSqrY - fSumY*fSumY - f1*f1/fX)/
+ (fCount*(fCount-2.0))), 1, 2);
+ if (fR2 == 1.0)
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), 0, 3 );
+ else
+ pResMat->PutDouble(fR2*(fCount-2.0)/(1.0-fR2), 0, 3);
+ }
+ pResMat->PutDouble(((double)(nCY*nRY))-2.0, 1, 3);
+ pResMat->PutDouble(fY/fCount-fSyx, 0, 4);
+ pResMat->PutDouble(fSyx, 1, 4);
+ }
+ }
+ }
+ else
+ {
+ USHORT nMatInd10, nMatInd12, nMatInd13, i, j, k;
+ if (!bStats)
+ pResMat = GetNewMat(M+1,1,nMatInd);
+ else
+ pResMat = GetNewMat(M+1,5,nMatInd);
+ if (!pResMat)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ ScMatrix* pQ = GetNewMat(M+1, M+2, nMatInd10);
+ ScMatrix* pE = GetNewMat(M+2, 1, nMatInd12);
+ ScMatrix* pV = GetNewMat(M+1, 1, nMatInd13);
+ pE->PutDouble(0.0, M+1);
+ pQ->FillDouble(0.0, 0, 0, M, M+1);
+ if (nCase == 2)
+ {
+ for (k = 0; k < N; k++)
+ {
+ double Yk = pMatY->GetDouble(k);
+ pE->PutDouble( pE->GetDouble(M+1)+Yk*Yk, M+1 );
+ double sumYk = pQ->GetDouble(0, M+1) + Yk;
+ pQ->PutDouble( sumYk, 0, M+1 );
+ pE->PutDouble( sumYk, 0 );
+ for (i = 0; i < M; i++)
+ {
+ double Xik = pMatX->GetDouble(i,k);
+ double sumXik = pQ->GetDouble(0, i+1) + Xik;
+ pQ->PutDouble( sumXik, 0, i+1);
+ pQ->PutDouble( sumXik, i+1, 0);
+ double sumXikYk = pQ->GetDouble(i+1, M+1) + Xik * Yk;
+ pQ->PutDouble( sumXikYk, i+1, M+1);
+ pE->PutDouble( sumXikYk, i+1);
+ for (j = i; j < M; j++)
+ {
+ double sumXikXjk = pQ->GetDouble(j+1, i+1) +
+ Xik * pMatX->GetDouble(j,k);
+ pQ->PutDouble( sumXikXjk, j+1, i+1);
+ pQ->PutDouble( sumXikXjk, i+1, j+1);
+ }
+ }
+ }
+ }
+ else
+ {
+ for (k = 0; k < N; k++)
+ {
+ double Yk = pMatY->GetDouble(k);
+ pE->PutDouble( pE->GetDouble(M+1)+Yk*Yk, M+1 );
+ double sumYk = pQ->GetDouble(0, M+1) + Yk;
+ pQ->PutDouble( sumYk, 0, M+1 );
+ pE->PutDouble( sumYk, 0 );
+ for (i = 0; i < M; i++)
+ {
+ double Xki = pMatX->GetDouble(k,i);
+ double sumXki = pQ->GetDouble(0, i+1) + Xki;
+ pQ->PutDouble( sumXki, 0, i+1);
+ pQ->PutDouble( sumXki, i+1, 0);
+ double sumXkiYk = pQ->GetDouble(i+1, M+1) + Xki * Yk;
+ pQ->PutDouble( sumXkiYk, i+1, M+1);
+ pE->PutDouble( sumXkiYk, i+1);
+ for (j = i; j < M; j++)
+ {
+ double sumXkiXkj = pQ->GetDouble(j+1, i+1) +
+ Xki * pMatX->GetDouble(k,j);
+ pQ->PutDouble( sumXkiXkj, j+1, i+1);
+ pQ->PutDouble( sumXkiXkj, i+1, j+1);
+ }
+ }
+ }
+ }
+ pQ->PutDouble((double)N, 0, 0);
+ if (bConstant)
+ {
+ USHORT S, L;
+ for (S = 0; S < M+1; S++)
+ {
+ i = S;
+ while (i < M+1 && pQ->GetDouble(i, S) == 0.0)
+ i++;
+ if (i >= M+1)
+ {
+ SetNoValue();
+ delete pQ;
+ delete pE;
+ delete pV;
+ ResetNewMat(nMatInd13);
+ ResetNewMat(nMatInd12);
+ ResetNewMat(nMatInd10);
+ return;
+ }
+ double fVal;
+ for (L = 0; L < M+2; L++)
+ {
+ fVal = pQ->GetDouble(S, L);
+ pQ->PutDouble(pQ->GetDouble(i, L), S, L);
+ pQ->PutDouble(fVal, i, L);
+ }
+ fVal = 1.0/pQ->GetDouble(S, S);
+ for (L = 0; L < M+2; L++)
+ pQ->PutDouble(pQ->GetDouble(S, L)*fVal, S, L);
+ for (i = 0; i < M+1; i++)
+ {
+ if (i != S)
+ {
+ fVal = -pQ->GetDouble(i, S);
+ for (L = 0; L < M+2; L++)
+ pQ->PutDouble(
+ pQ->GetDouble(i,L)+fVal*pQ->GetDouble(S,L),i,L);
+ }
+ }
+ }
+ }
+ else
+ {
+ USHORT S, L;
+ for (S = 1; S < M+1; S++)
+ {
+ i = S;
+ while (i < M+1 && pQ->GetDouble(i, S) == 0.0)
+ i++;
+ if (i >= M+1)
+ {
+ SetNoValue();
+ delete pQ;
+ delete pE;
+ delete pV;
+ ResetNewMat(nMatInd13);
+ ResetNewMat(nMatInd12);
+ ResetNewMat(nMatInd10);
+ return;
+ }
+ double fVal;
+ for (L = 1; L < M+2; L++)
+ {
+ fVal = pQ->GetDouble(S, L);
+ pQ->PutDouble(pQ->GetDouble(i, L), S, L);
+ pQ->PutDouble(fVal, i, L);
+ }
+ fVal = 1.0/pQ->GetDouble(S, S);
+ for (L = 1; L < M+2; L++)
+ pQ->PutDouble(pQ->GetDouble(S, L)*fVal, S, L);
+ for (i = 1; i < M+1; i++)
+ {
+ if (i != S)
+ {
+ fVal = -pQ->GetDouble(i, S);
+ for (L = 1; L < M+2; L++)
+ pQ->PutDouble(
+ pQ->GetDouble(i,L)+fVal*pQ->GetDouble(S,L),i,L);
+ }
+ }
+ pQ->PutDouble(0.0, 0, M+1);
+ }
+ }
+ for (i = 0; i < M+1; i++)
+ pResMat->PutDouble(exp(pQ->GetDouble(M-i,M+1)), i, 0);
+ if (bStats)
+ {
+ double fSQR, fSQT, fSQE;
+ fSQT = pE->GetDouble(M+1)-pE->GetDouble(0)*pE->GetDouble(0)/((double)N);
+ fSQR = pE->GetDouble(M+1);
+ for (i = 0; i < M+1; i++)
+ fSQR += -pQ->GetDouble(i, M+1)*pE->GetDouble(i);
+ fSQE = fSQT-fSQR;
+ if (fSQT == 0.0)
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), 0, 2);
+ else
+ pResMat->PutDouble (fSQE/fSQT, 0, 2);
+ pResMat->PutDouble(fSQE, 0, 4);
+ pResMat->PutDouble(fSQR, 1, 4);
+ for (i = 2; i < 5; i++)
+ for (j = 2; j < M+1; j++)
+ pResMat->PutString(ScGlobal::GetRscString(STR_NV_STR), j, i);
+ if (bConstant)
+ {
+ if (N-M-1 == 0)
+ {
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), 1, 2);
+ for (i = 0; i < M+1; i++)
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i, 1);
+ }
+ else
+ {
+ double fSE2 = fSQR/(N-M-1);
+ pResMat->PutDouble(sqrt(fSE2), 1, 2);
+ if ( RGetVariances( pV, pMatX, M+1, N, nCase != 2, FALSE ) )
+ {
+ for (i = 0; i < M+1; i++)
+ pResMat->PutDouble( sqrt(fSE2 * pV->GetDouble(i)), M-i, 1 );
+ }
+ else
+ {
+ for (i = 0; i < M+1; i++)
+ pResMat->PutString(ScGlobal::GetRscString(STR_NV_STR), i, 1);
+ }
+ }
+ if (fSQR == 0.0)
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), 0, 3);
+ else
+ pResMat->PutDouble(((double)(N-M-1))*fSQE/fSQR/((double)M),0, 3);
+ pResMat->PutDouble(((double)(N-M-1)), 1, 3);
+ }
+ else
+ {
+ if (N-M == 0)
+ {
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), 1, 2);
+ for (i = 0; i < M+1; i++)
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), i, 1);
+ }
+ else
+ {
+ double fSE2 = fSQR/(N-M);
+ pResMat->PutDouble(sqrt(fSE2), 1, 2);
+ if ( RGetVariances( pV, pMatX, M, N, nCase != 2, TRUE ) )
+ {
+ for (i = 0; i < M; i++)
+ pResMat->PutDouble( sqrt(fSE2 * pV->GetDouble(i)), M-i-1, 1 );
+ pResMat->PutString(ScGlobal::GetRscString(STR_NV_STR), M, 1);
+ }
+ else
+ {
+ for (i = 0; i < M+1; i++)
+ pResMat->PutString(ScGlobal::GetRscString(STR_NV_STR), i, 1);
+ }
+ }
+ if (fSQR == 0.0)
+ pResMat->PutString(ScGlobal::GetRscString(STR_NO_VALUE), 0, 3);
+ else
+ pResMat->PutDouble(((double)(N-M))*fSQE/fSQR/((double)M),0, 3);
+ pResMat->PutDouble(((double)(N-M)), 1, 3);
+ }
+ }
+ delete pQ;
+ delete pE;
+ delete pV;
+ ResetNewMat(nMatInd13);
+ ResetNewMat(nMatInd12);
+ ResetNewMat(nMatInd10);
+ }
+ PushMatrix(pResMat);
+ nRetMat = nMatInd;
+}
+
+
+void ScInterpreter::ScTrend()
+{
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 1, 4 ) )
+ return;
+ BOOL bConstant;
+ if (nParamCount == 4)
+ bConstant = GetBool();
+ else
+ bConstant = TRUE;
+ USHORT nMatInd1, nMatInd2, nMatInd3;
+ ScMatrix* pMatX;
+ ScMatrix* pMatY;
+ ScMatrix* pMatNewX;
+ if (nParamCount >= 3)
+ pMatNewX = GetMatrix(nMatInd3);
+ else
+ pMatNewX = NULL;
+ if (nParamCount >= 2)
+ pMatX = GetMatrix(nMatInd2);
+ else
+ pMatX = NULL;
+ pMatY = GetMatrix(nMatInd1);
+ if (!pMatY)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ BYTE nCase; // 1 = normal, 2,3 = mehrfach
+ USHORT nCX, nRX, nCY, nRY, M, N;
+ pMatY->GetDimensions(nCY, nRY);
+ USHORT i;
+ for (i = 0; i < nCY*nRY; i++)
+ if (!pMatY->IsValue(i))
+ {
+ SetIllegalArgument();
+ return;
+ }
+ if (pMatX)
+ {
+ pMatX->GetDimensions(nCX, nRX);
+ for (i = 0; i < nCX*nRX; i++)
+ if (!pMatX->IsValue(i))
+ {
+ SetIllegalArgument();
+ return;
+ }
+ if (nCX == nCY && nRX == nRY)
+ nCase = 1; // einfache Regression
+ else if (nCY != 1 && nRY != 1)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ else if (nCY == 1)
+ {
+ if (nRX != nRY)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ else
+ {
+ nCase = 2; // zeilenweise
+ N = nRY;
+ M = nCX;
+ }
+ }
+ else if (nCX != nCY)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ else
+ {
+ nCase = 3; // spaltenweise
+ N = nCY;
+ M = nRX;
+ }
+ }
+ else
+ {
+ pMatX = GetNewMat(nCY, nRY, nMatInd2);
+ nCX = nCY;
+ nRX = nRY;
+ if (!pMatX)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ for (i = 1; i <= nCY*nRY; i++)
+ pMatX->PutDouble((double)i, i-1);
+ nCase = 1;
+ }
+ USHORT nCXN, nRXN;
+ if (!pMatNewX)
+ {
+ nCXN = nCX;
+ nRXN = nRX;
+ pMatNewX = pMatX;
+ }
+ else
+ {
+ pMatNewX->GetDimensions(nCXN, nRXN);
+ if ((nCase == 2 && nCX != nCXN) || (nCase == 3 && nRX != nRXN))
+ {
+ SetIllegalArgument();
+ return;
+ }
+ for (USHORT i = 0; i < nCXN*nRXN; i++)
+ if (!pMatNewX->IsValue(i))
+ {
+ SetIllegalArgument();
+ return;
+ }
+ }
+ USHORT nMatInd;
+ ScMatrix* pResMat;
+ if (nCase == 1)
+ {
+ double fCount = 0.0;
+ double fSumX = 0.0;
+ double fSumSqrX = 0.0;
+ double fSumY = 0.0;
+ double fSumSqrY = 0.0;
+ double fSumXY = 0.0;
+ double fValX, fValY;
+ for (USHORT i = 0; i < nCY; i++)
+ for (USHORT j = 0; j < nRY; j++)
+ {
+ fValX = pMatX->GetDouble(i,j);
+ fValY = pMatY->GetDouble(i,j);
+ fSumX += fValX;
+ fSumSqrX += fValX * fValX;
+ fSumY += fValY;
+ fSumSqrY += fValY * fValY;
+ fSumXY += fValX*fValY;
+ fCount++;
+ }
+ if (fCount < 1.0)
+ {
+ SetNoValue();
+ return;
+ }
+ else
+ {
+ double f1 = fCount*fSumXY-fSumX*fSumY;
+ double fX = fCount*fSumSqrX-fSumX*fSumX;
+ double b, m;
+ if (bConstant)
+ {
+ b = fSumY/fCount - f1/fX*fSumX/fCount;
+ m = f1/fX;
+ }
+ else
+ {
+ b = 0.0;
+ m = fSumXY/fSumSqrX;
+ }
+ pResMat = GetNewMat(nCXN, nRXN, nMatInd);
+ if (!pResMat)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ for (i = 0; i < nCXN*nRXN; i++)
+ pResMat->PutDouble(pMatNewX->GetDouble(i)*m+b, i);
+ }
+ }
+ else
+ {
+ USHORT nMatInd10, nMatInd12, i, j, k;
+ ScMatrix* pQ = GetNewMat(M+1, M+2, nMatInd10);
+ ScMatrix* pE = GetNewMat(M+2, 1, nMatInd12);
+ pE->PutDouble(0.0, M+1);
+ pQ->FillDouble(0.0, 0, 0, M, M+1);
+ if (nCase == 2)
+ {
+ for (k = 0; k < N; k++)
+ {
+ pE->PutDouble(
+ pE->GetDouble(M+1)+pMatY->GetDouble(k)*pMatY->GetDouble(k), M+1);
+ pQ->PutDouble(pQ->GetDouble(0, M+1) + pMatY->GetDouble(k), 0, M+1);
+ pE->PutDouble(pQ->GetDouble(0, M+1), 0);
+ for (i = 0; i < M; i++)
+ {
+ pQ->PutDouble(pQ->GetDouble(0, i+1)+pMatX->GetDouble(i,k), 0, i+1);
+ pQ->PutDouble(pQ->GetDouble(0, i+1), i+1, 0);
+ pQ->PutDouble(pQ->GetDouble(i+1, M+1) +
+ pMatX->GetDouble(i,k)*pMatY->GetDouble(k), i+1, M+1);
+ pE->PutDouble(pQ->GetDouble(i+1, M+1), i+1);
+ for (j = i; j < M; j++)
+ {
+ pQ->PutDouble(pQ->GetDouble(j+1, i+1) +
+ pMatX->GetDouble(i,k)*pMatX->GetDouble(j,k), j+1, i+1);
+ pQ->PutDouble(pQ->GetDouble(j+1, i+1), i+1, j+1);
+ }
+ }
+ }
+ }
+ else
+ {
+ for (k = 0; k < N; k++)
+ {
+ pE->PutDouble(
+ pE->GetDouble(M+1)+pMatY->GetDouble(k)*pMatY->GetDouble(k), M+1);
+ pQ->PutDouble(pQ->GetDouble(0, M+1) + pMatY->GetDouble(k), 0, M+1);
+ pE->PutDouble(pQ->GetDouble(0, M+1), 0);
+ for (i = 0; i < M; i++)
+ {
+ pQ->PutDouble(pQ->GetDouble(0, i+1)+pMatX->GetDouble(k,i), 0, i+1);
+ pQ->PutDouble(pQ->GetDouble(0, i+1), i+1, 0);
+ pQ->PutDouble(pQ->GetDouble(i+1, M+1) +
+ pMatX->GetDouble(k,i)*pMatY->GetDouble(k), i+1, M+1);
+ pE->PutDouble(pQ->GetDouble(i+1, M+1), i+1);
+ for (j = i; j < M; j++)
+ {
+ pQ->PutDouble(pQ->GetDouble(j+1, i+1) +
+ pMatX->GetDouble(k, i)*pMatX->GetDouble(k, j), j+1, i+1);
+ pQ->PutDouble(pQ->GetDouble(j+1, i+1), i+1, j+1);
+ }
+ }
+ }
+ }
+ pQ->PutDouble((double)N, 0, 0);
+ if (bConstant)
+ {
+ USHORT S, L;
+ for (S = 0; S < M+1; S++)
+ {
+ i = S;
+ while (i < M+1 && pQ->GetDouble(i, S) == 0.0)
+ i++;
+ if (i >= M+1)
+ {
+ SetNoValue();
+ delete pQ;
+ delete pE;
+ ResetNewMat(nMatInd12);
+ ResetNewMat(nMatInd10);
+ return;
+ }
+ double fVal;
+ for (L = 0; L < M+2; L++)
+ {
+ fVal = pQ->GetDouble(S, L);
+ pQ->PutDouble(pQ->GetDouble(i, L), S, L);
+ pQ->PutDouble(fVal, i, L);
+ }
+ fVal = 1.0/pQ->GetDouble(S, S);
+ for (L = 0; L < M+2; L++)
+ pQ->PutDouble(pQ->GetDouble(S, L)*fVal, S, L);
+ for (i = 0; i < M+1; i++)
+ {
+ if (i != S)
+ {
+ fVal = -pQ->GetDouble(i, S);
+ for (L = 0; L < M+2; L++)
+ pQ->PutDouble(
+ pQ->GetDouble(i,L)+fVal*pQ->GetDouble(S,L),i,L);
+ }
+ }
+ }
+ }
+ else
+ {
+ USHORT S, L;
+ for (S = 1; S < M+1; S++)
+ {
+ i = S;
+ while (i < M+1 && pQ->GetDouble(i, S) == 0.0)
+ i++;
+ if (i >= M+1)
+ {
+ SetNoValue();
+ delete pQ;
+ delete pE;
+ ResetNewMat(nMatInd12);
+ ResetNewMat(nMatInd10);
+ return;
+ }
+ double fVal;
+ for (L = 1; L < M+2; L++)
+ {
+ fVal = pQ->GetDouble(S, L);
+ pQ->PutDouble(pQ->GetDouble(i, L), S, L);
+ pQ->PutDouble(fVal, i, L);
+ }
+ fVal = 1.0/pQ->GetDouble(S, S);
+ for (L = 1; L < M+2; L++)
+ pQ->PutDouble(pQ->GetDouble(S, L)*fVal, S, L);
+ for (i = 1; i < M+1; i++)
+ {
+ if (i != S)
+ {
+ fVal = -pQ->GetDouble(i, S);
+ for (L = 1; L < M+2; L++)
+ pQ->PutDouble(
+ pQ->GetDouble(i,L)+fVal*pQ->GetDouble(S,L),i,L);
+ }
+ }
+ pQ->PutDouble(0.0, 0, M+1);
+ }
+ }
+ if (nCase == 2)
+ {
+ pResMat = GetNewMat(1, nRXN, nMatInd);
+ if (!pResMat)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ double fVal;
+ for (i = 0; i < nRXN; i++)
+ {
+ fVal = pQ->GetDouble(0, M+1);
+ for (j = 0; j < M; j++)
+ fVal += pQ->GetDouble(j+1, M+1)*pMatNewX->GetDouble(j, i);
+ pResMat->PutDouble(fVal, i);
+ }
+ }
+ else
+ {
+ pResMat = GetNewMat(nCXN, 1, nMatInd);
+ if (!pResMat)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ double fVal;
+ for (i = 0; i < nCXN; i++)
+ {
+ fVal = pQ->GetDouble(0, M+1);
+ for (j = 0; j < M; j++)
+ fVal += pQ->GetDouble(j+1, M+1)*pMatNewX->GetDouble(i, j);
+ pResMat->PutDouble(fVal, i);
+ }
+ }
+ delete pQ;
+ delete pE;
+ ResetNewMat(nMatInd12);
+ ResetNewMat(nMatInd10);
+ }
+ PushMatrix(pResMat);
+ nRetMat = nMatInd;
+}
+
+void ScInterpreter::ScGrowth()
+{
+ BYTE nParamCount = GetByte();
+ if ( !MustHaveParamCount( nParamCount, 1, 4 ) )
+ return;
+ BOOL bConstant;
+ if (nParamCount == 4)
+ bConstant = GetBool();
+ else
+ bConstant = TRUE;
+ USHORT nMatInd1, nMatInd2, nMatInd3;
+ ScMatrix* pMatX;
+ ScMatrix* pMatY;
+ ScMatrix* pMatNewX;
+ if (nParamCount >= 3)
+ pMatNewX = GetMatrix(nMatInd3);
+ else
+ pMatNewX = NULL;
+ if (nParamCount >= 2)
+ pMatX = GetMatrix(nMatInd2);
+ else
+ pMatX = NULL;
+ pMatY = GetMatrix(nMatInd1);
+ if (!pMatY)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ BYTE nCase; // 1 = normal, 2,3 = mehrfach
+ USHORT nCX, nRX, nCY, nRY, M, N;
+ pMatY->GetDimensions(nCY, nRY);
+ USHORT i;
+ for (i = 0; i < nCY*nRY; i++)
+ if (!pMatY->IsValue(i))
+ {
+ SetIllegalArgument();
+ return;
+ }
+ for (i = 0; i < nCY*nRY; i++)
+ {
+ if (pMatY->GetDouble(i) <= 0.0)
+ {
+ SetIllegalArgument();
+ return;
+ }
+ else
+ pMatY->PutDouble(log(pMatY->GetDouble(i)), i);
+ }
+ if (pMatX)
+ {
+ pMatX->GetDimensions(nCX, nRX);
+ for (USHORT i = 0; i < nCX*nRX; i++)
+ if (!pMatX->IsValue(i))
+ {
+ SetIllegalArgument();
+ return;
+ }
+ if (nCX == nCY && nRX == nRY)
+ nCase = 1; // einfache Regression
+ else if (nCY != 1 && nRY != 1)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ else if (nCY == 1)
+ {
+ if (nRX != nRY)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ else
+ {
+ nCase = 2; // zeilenweise
+ N = nRY;
+ M = nCX;
+ }
+ }
+ else if (nCX != nCY)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ else
+ {
+ nCase = 3; // spaltenweise
+ N = nCY;
+ M = nRX;
+ }
+ }
+ else
+ {
+ pMatX = GetNewMat(nCY, nRY, nMatInd2);
+ nCX = nCY;
+ nRX = nRY;
+ if (!pMatX)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ for (i = 1; i <= nCY*nRY; i++)
+ pMatX->PutDouble((double)i, i-1);
+ nCase = 1;
+ }
+ USHORT nCXN, nRXN;
+ if (!pMatNewX)
+ {
+ nCXN = nCX;
+ nRXN = nRX;
+ pMatNewX = pMatX;
+ }
+ else
+ {
+ pMatNewX->GetDimensions(nCXN, nRXN);
+ if ((nCase == 2 && nCX != nCXN) || (nCase == 3 && nRX != nRXN))
+ {
+ SetIllegalArgument();
+ return;
+ }
+ for (USHORT i = 0; i < nCXN*nRXN; i++)
+ if (!pMatNewX->IsValue(i))
+ {
+ SetIllegalArgument();
+ return;
+ }
+ }
+ USHORT nMatInd;
+ ScMatrix* pResMat;
+ if (nCase == 1)
+ {
+ double fCount = 0.0;
+ double fSumX = 0.0;
+ double fSumSqrX = 0.0;
+ double fSumY = 0.0;
+ double fSumSqrY = 0.0;
+ double fSumXY = 0.0;
+ double fValX, fValY;
+ for (USHORT i = 0; i < nCY; i++)
+ for (USHORT j = 0; j < nRY; j++)
+ {
+ fValX = pMatX->GetDouble(i,j);
+ fValY = pMatY->GetDouble(i,j);
+ fSumX += fValX;
+ fSumSqrX += fValX * fValX;
+ fSumY += fValY;
+ fSumSqrY += fValY * fValY;
+ fSumXY += fValX*fValY;
+ fCount++;
+ }
+ if (fCount < 1.0)
+ {
+ SetNoValue();
+ return;
+ }
+ else
+ {
+ double f1 = fCount*fSumXY-fSumX*fSumY;
+ double fX = fCount*fSumSqrX-fSumX*fSumX;
+ double b, m;
+ if (bConstant)
+ {
+ b = fSumY/fCount - f1/fX*fSumX/fCount;
+ m = f1/fX;
+ }
+ else
+ {
+ b = 0.0;
+ m = fSumXY/fSumSqrX;
+ }
+ pResMat = GetNewMat(nCXN, nRXN, nMatInd);
+ if (!pResMat)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ for (i = 0; i < nCXN*nRXN; i++)
+ pResMat->PutDouble(exp(pMatNewX->GetDouble(i)*m+b), i);
+ }
+ }
+ else
+ {
+ USHORT nMatInd10, nMatInd12, i, j, k;
+ ScMatrix* pQ = GetNewMat(M+1, M+2, nMatInd10);
+ ScMatrix* pE = GetNewMat(M+2, 1, nMatInd12);
+ pE->PutDouble(0.0, M+1);
+ pQ->FillDouble(0.0, 0, 0, M, M+1);
+ if (nCase == 2)
+ {
+ for (k = 0; k < N; k++)
+ {
+ pE->PutDouble(
+ pE->GetDouble(M+1)+pMatY->GetDouble(k)*pMatY->GetDouble(k), M+1);
+ pQ->PutDouble(pQ->GetDouble(0, M+1) + pMatY->GetDouble(k), 0, M+1);
+ pE->PutDouble(pQ->GetDouble(0, M+1), 0);
+ for (i = 0; i < M; i++)
+ {
+ pQ->PutDouble(pQ->GetDouble(0, i+1)+pMatX->GetDouble(i,k), 0, i+1);
+ pQ->PutDouble(pQ->GetDouble(0, i+1), i+1, 0);
+ pQ->PutDouble(pQ->GetDouble(i+1, M+1) +
+ pMatX->GetDouble(i,k)*pMatY->GetDouble(k), i+1, M+1);
+ pE->PutDouble(pQ->GetDouble(i+1, M+1), i+1);
+ for (j = i; j < M; j++)
+ {
+ pQ->PutDouble(pQ->GetDouble(j+1, i+1) +
+ pMatX->GetDouble(i,k)*pMatX->GetDouble(j,k), j+1, i+1);
+ pQ->PutDouble(pQ->GetDouble(j+1, i+1), i+1, j+1);
+ }
+ }
+ }
+ }
+ else
+ {
+ for (k = 0; k < N; k++)
+ {
+ pE->PutDouble(
+ pE->GetDouble(M+1)+pMatY->GetDouble(k)*pMatY->GetDouble(k), M+1);
+ pQ->PutDouble(pQ->GetDouble(0, M+1) + pMatY->GetDouble(k), 0, M+1);
+ pE->PutDouble(pQ->GetDouble(0, M+1), 0);
+ for (i = 0; i < M; i++)
+ {
+ pQ->PutDouble(pQ->GetDouble(0, i+1)+pMatX->GetDouble(k,i), 0, i+1);
+ pQ->PutDouble(pQ->GetDouble(0, i+1), i+1, 0);
+ pQ->PutDouble(pQ->GetDouble(i+1, M+1) +
+ pMatX->GetDouble(k,i)*pMatY->GetDouble(k), i+1, M+1);
+ pE->PutDouble(pQ->GetDouble(i+1, M+1), i+1);
+ for (j = i; j < M; j++)
+ {
+ pQ->PutDouble(pQ->GetDouble(j+1, i+1) +
+ pMatX->GetDouble(k, i)*pMatX->GetDouble(k, j), j+1, i+1);
+ pQ->PutDouble(pQ->GetDouble(j+1, i+1), i+1, j+1);
+ }
+ }
+ }
+ }
+ pQ->PutDouble((double)N, 0, 0);
+ if (bConstant)
+ {
+ USHORT S, L;
+ for (S = 0; S < M+1; S++)
+ {
+ i = S;
+ while (i < M+1 && pQ->GetDouble(i, S) == 0.0)
+ i++;
+ if (i >= M+1)
+ {
+ SetNoValue();
+ delete pQ;
+ delete pE;
+ ResetNewMat(nMatInd12);
+ ResetNewMat(nMatInd10);
+ return;
+ }
+ double fVal;
+ for (L = 0; L < M+2; L++)
+ {
+ fVal = pQ->GetDouble(S, L);
+ pQ->PutDouble(pQ->GetDouble(i, L), S, L);
+ pQ->PutDouble(fVal, i, L);
+ }
+ fVal = 1.0/pQ->GetDouble(S, S);
+ for (L = 0; L < M+2; L++)
+ pQ->PutDouble(pQ->GetDouble(S, L)*fVal, S, L);
+ for (i = 0; i < M+1; i++)
+ {
+ if (i != S)
+ {
+ fVal = -pQ->GetDouble(i, S);
+ for (L = 0; L < M+2; L++)
+ pQ->PutDouble(
+ pQ->GetDouble(i,L)+fVal*pQ->GetDouble(S,L),i,L);
+ }
+ }
+ }
+ }
+ else
+ {
+ USHORT S, L;
+ for (S = 1; S < M+1; S++)
+ {
+ i = S;
+ while (i < M+1 && pQ->GetDouble(i, S) == 0.0)
+ i++;
+ if (i >= M+1)
+ {
+ SetNoValue();
+ delete pQ;
+ delete pE;
+ ResetNewMat(nMatInd12);
+ ResetNewMat(nMatInd10);
+ return;
+ }
+ double fVal;
+ for (L = 1; L < M+2; L++)
+ {
+ fVal = pQ->GetDouble(S, L);
+ pQ->PutDouble(pQ->GetDouble(i, L), S, L);
+ pQ->PutDouble(fVal, i, L);
+ }
+ fVal = 1.0/pQ->GetDouble(S, S);
+ for (L = 1; L < M+2; L++)
+ pQ->PutDouble(pQ->GetDouble(S, L)*fVal, S, L);
+ for (i = 1; i < M+1; i++)
+ {
+ if (i != S)
+ {
+ fVal = -pQ->GetDouble(i, S);
+ for (L = 1; L < M+2; L++)
+ pQ->PutDouble(
+ pQ->GetDouble(i,L)+fVal*pQ->GetDouble(S,L),i,L);
+ }
+ }
+ pQ->PutDouble(0.0, 0, M+1);
+ }
+ }
+ if (nCase == 2)
+ {
+ pResMat = GetNewMat(1, nRXN, nMatInd);
+ if (!pResMat)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ double fVal;
+ for (i = 0; i < nRXN; i++)
+ {
+ fVal = pQ->GetDouble(0, M+1);
+ for (j = 0; j < M; j++)
+ fVal += pQ->GetDouble(j+1, M+1)*pMatNewX->GetDouble(j, i);
+ pResMat->PutDouble(exp(fVal), i);
+ }
+ }
+ else
+ {
+ pResMat = GetNewMat(nCXN, 1, nMatInd);
+ if (!pResMat)
+ {
+ SetIllegalParameter();
+ return;
+ }
+ double fVal;
+ for (i = 0; i < nCXN; i++)
+ {
+ fVal = pQ->GetDouble(0, M+1);
+ for (j = 0; j < M; j++)
+ fVal += pQ->GetDouble(j+1, M+1)*pMatNewX->GetDouble(i, j);
+ pResMat->PutDouble(exp(fVal), i);
+ }
+ }
+ delete pQ;
+ delete pE;
+ ResetNewMat(nMatInd12);
+ ResetNewMat(nMatInd10);
+ }
+ PushMatrix(pResMat);
+ nRetMat = nMatInd;
+}
+
+void ScInterpreter::ScMatRef()
+{
+ // Falls Deltarefs drin sind...
+ Push( (ScToken&) *pCur );
+ ScAddress aAdr;
+ PopSingleRef( aAdr );
+ ScFormulaCell* pCell = (ScFormulaCell*) GetCell( aAdr );
+ if( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
+ {
+ ScMatrix* pMat;
+ pCell->GetMatrix( &pMat );
+ if( pMat )
+ {
+ USHORT nCl, nRw;
+ pMat->GetDimensions( nCl, nRw );
+ USHORT nC = aPos.Col() - aAdr.Col();
+ USHORT nR = aPos.Row() - aAdr.Row();
+ if (nC < nCl && nR < nRw)
+ {
+ BOOL bIsString;
+ const MatValue* pMatVal = pMat->Get(nC, nR, bIsString);
+ if (bIsString)
+ PushStringObject(*(pMatVal->pS));
+ else
+ {
+ PushDouble(pMatVal->fVal);
+ pDok->GetNumberFormatInfo( nCurFmtType, nCurFmtIndex, aAdr, *pCell );
+ nFuncFmtType = nCurFmtType;
+ nFuncFmtIndex = nCurFmtIndex;
+ }
+ }
+ else
+ SetNV();
+ }
+ else
+ {
+ // Ist gar keine Ergebnis-Matrix, dann bitte den Wert holen!
+ USHORT nErr = pCell->GetErrCode();
+ SetError( nErr );
+ if( pCell->IsValue() )
+ PushDouble( pCell->GetValue() );
+ else
+ {
+ String aVal;
+ pCell->GetString( aVal );
+ PushStringObject( aVal );
+ }
+ pDok->GetNumberFormatInfo( nCurFmtType, nCurFmtIndex, aAdr, *pCell );
+ nFuncFmtType = nCurFmtType;
+ nFuncFmtIndex = nCurFmtIndex;
+ }
+ }
+ else
+ SetError( errNoRef );
+}
+
+
+
diff --git a/sc/source/core/tool/interpr6.cxx b/sc/source/core/tool/interpr6.cxx
new file mode 100644
index 000000000000..ee913f73d722
--- /dev/null
+++ b/sc/source/core/tool/interpr6.cxx
@@ -0,0 +1,216 @@
+/*************************************************************************
+ *
+ * $RCSfile: interpr6.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:18 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+
+#include <math.h>
+
+#ifndef _TOOLS_DEBUG_HXX //autogen
+#include <tools/debug.hxx>
+#endif
+
+#include "interpre.hxx"
+
+
+//! #66556# for os2icci3 this function MUST be compiled without optimizations,
+//! otherwise it won't work at all or even worse will produce false results!
+double ScInterpreter::GetGammaDist(double x, double alpha, double beta)
+{
+ if (x == 0.0)
+ return 0.0;
+
+ x /= beta;
+ double gamma = alpha;
+
+ double c = 0.918938533204672741;
+ double d[10] = {
+ 0.833333333333333333E-1,
+ -0.277777777777777778E-2,
+ 0.793650793650793651E-3,
+ -0.595238095238095238E-3,
+ 0.841750841750841751E-3,
+ -0.191752691752691753E-2,
+ 0.641025641025641025E-2,
+ -0.295506535947712418E-1,
+ 0.179644372368830573,
+ -0.139243221690590111E1
+ };
+
+ int ipr = 6;
+
+ double dx = x;
+ double dgamma = gamma;
+ int maxit = 10000;
+
+ double z = dgamma;
+ double den = 1.0;
+ while ( z < 10.0 ) //! approx?
+ {
+ den *= z;
+ z += 1.0;
+ }
+
+ double z2 = z*z;
+ double z3 = z*z2;
+ double z4 = z2*z2;
+ double z5 = z2*z3;
+ double a = ( z - 0.5 ) * log(z) - z + c;
+ double b = d[0]/z + d[1]/z3 + d[2]/z5 + d[3]/(z2*z5) + d[4]/(z4*z5) +
+ d[5]/(z*z5*z5) + d[6]/(z3*z5*z5) + d[7]/(z5*z5*z5) + d[8]/(z2*z5*z5*z5);
+ double g = exp(a+b) / den;
+
+ double sum = 1.0 / dgamma;
+ double term = 1.0 / dgamma;
+ double cut1 = dx - dgamma;
+ double cut2 = dx * 10000000000.0;
+
+ for ( int i=1; i<=maxit; i++ )
+ {
+ double ai = i;
+ term = dx * term / ( dgamma + ai );
+ sum += term;
+ double cutoff = cut1 + ( cut2 * term / sum );
+ if ( ai > cutoff )
+ {
+ double t = sum;
+ return pow( dx, dgamma ) * exp( -dx ) * t / g;
+ }
+ }
+
+ DBG_ERROR("GetGammaDist bricht nicht ab");
+
+ return 1.0; // should not happen ...
+}
+
+#if 0
+//! this algorithm doesn't work right in every cases!
+double ScInterpreter::GetGammaDist(double x, double alpha, double beta)
+{
+ if (x == 0.0)
+ return 0.0;
+ double fEps = 1.0E-6;
+ double fGamma;
+ double G = GetLogGamma(alpha);
+ x /= beta;
+ G = alpha*log(x)-x-G;
+ if (x <= alpha+1.0)
+ {
+ if (x < fEps || fabs(G) >= 500.0)
+ fGamma = 0.0;
+ else
+ {
+ double fF = 1.0/alpha;
+ double fS = fF;
+ double anum = alpha;
+ for (USHORT i = 0; i < 100; i++)
+ {
+ anum += 1.0;
+ fF *= x/anum;
+ fS += fF;
+ if (fF < fEps)
+ i = 100;
+ }
+ fGamma = fS*exp(G);
+ }
+ }
+ else
+ {
+ if (fabs(G) >= 500.0)
+ fGamma = 1.0;
+ else
+ {
+ double a0, b0, a1, b1, cf, fnorm, a2j, a2j1, cfnew;
+ a0 = 0.0; b0 = 1.0; a1 = 1.0;
+ b1 = x;
+ cf = fEps;
+ fnorm = 1.0;
+ cfnew = 0.0;
+ for (USHORT j = 1; j <= 100; j++)
+ {
+ a2j = ((double) j) - alpha;
+ a2j1 = (double) j;
+ a0 = (a1+a2j*a0); // *fnorm;
+ b0 = (b1+a2j*b0); // *fnorm;
+ a1 = (x*a0+a2j1*a1)*fnorm;
+ b1 = (x*b0+a2j1*b1)*fnorm;
+ if (b1 != 0.0)
+ {
+ fnorm = 1.0/b1;
+ cfnew = a1*fnorm;
+ if (fabs(cf-cfnew)/cf < fEps)
+ j = 101;
+ else
+ cf = cfnew;
+ }
+ }
+ fGamma = 1.0 - exp(G)*cfnew;
+ }
+ }
+ return fGamma;
+}
+#endif
+
+
diff --git a/sc/source/core/tool/makefile.mk b/sc/source/core/tool/makefile.mk
new file mode 100644
index 000000000000..f70900d04061
--- /dev/null
+++ b/sc/source/core/tool/makefile.mk
@@ -0,0 +1,199 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-19 00:16:18 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=sc
+TARGET=tool
+
+PROJECTPCH4DLL=TRUE
+PROJECTPCH=core_pch
+PROJECTPCHSOURCE=..\pch\core_pch
+
+AUTOSEG=true
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : scpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sc.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Files --------------------------------------------------------
+
+CXXFILES = \
+ adiasync.cxx \
+ appoptio.cxx \
+ autoform.cxx \
+ callform.cxx \
+ cellform.cxx \
+ chartarr.cxx \
+ chartlis.cxx \
+ chgtrack.cxx \
+ chgviset.cxx \
+ collect.cxx \
+ compiler.cxx \
+ consoli.cxx \
+ dbcolect.cxx \
+ ddelink.cxx \
+ detfunc.cxx \
+ detdata.cxx \
+ docoptio.cxx \
+ editutil.cxx \
+ indexmap.cxx \
+ interpr1.cxx \
+ interpr2.cxx \
+ interpr3.cxx \
+ interpr4.cxx \
+ interpr5.cxx \
+ interpr6.cxx \
+ linelink.cxx \
+ progress.cxx \
+ rangenam.cxx \
+ rangelst.cxx \
+ rangeutl.cxx \
+ rechead.cxx \
+ refupdat.cxx \
+ refdata.cxx \
+ reffind.cxx \
+ scdebug.cxx \
+ scmatrix.cxx \
+ sctictac.cxx \
+ subtotal.cxx \
+ token.cxx \
+ unitconv.cxx \
+ userlist.cxx \
+ viewopti.cxx \
+ inputopt.cxx \
+ zforauto.cxx \
+ hints.cxx \
+ prnsave.cxx \
+ navicfg.cxx \
+ addincol.cxx \
+ addinlis.cxx \
+ rangeseq.cxx
+
+
+SLOFILES = \
+ $(SLO)$/adiasync.obj \
+ $(SLO)$/appoptio.obj \
+ $(SLO)$/autoform.obj \
+ $(SLO)$/callform.obj \
+ $(SLO)$/cellform.obj \
+ $(SLO)$/chartarr.obj \
+ $(SLO)$/chartlis.obj \
+ $(SLO)$/chgtrack.obj \
+ $(SLO)$/chgviset.obj \
+ $(SLO)$/collect.obj \
+ $(SLO)$/compiler.obj \
+ $(SLO)$/consoli.obj \
+ $(SLO)$/dbcolect.obj \
+ $(SLO)$/ddelink.obj \
+ $(SLO)$/detfunc.obj \
+ $(SLO)$/detdata.obj \
+ $(SLO)$/docoptio.obj \
+ $(SLO)$/editutil.obj \
+ $(SLO)$/indexmap.obj \
+ $(SLO)$/interpr1.obj \
+ $(SLO)$/interpr2.obj \
+ $(SLO)$/interpr3.obj \
+ $(SLO)$/interpr4.obj \
+ $(SLO)$/interpr5.obj \
+ $(SLO)$/interpr6.obj \
+ $(SLO)$/linelink.obj \
+ $(SLO)$/progress.obj \
+ $(SLO)$/rangenam.obj \
+ $(SLO)$/rangelst.obj \
+ $(SLO)$/rangeutl.obj \
+ $(SLO)$/rechead.obj \
+ $(SLO)$/refupdat.obj \
+ $(SLO)$/refdata.obj \
+ $(SLO)$/reffind.obj \
+ $(SLO)$/scdebug.obj \
+ $(SLO)$/scmatrix.obj \
+ $(SLO)$/sctictac.obj \
+ $(SLO)$/subtotal.obj \
+ $(SLO)$/token.obj \
+ $(SLO)$/unitconv.obj \
+ $(SLO)$/userlist.obj \
+ $(SLO)$/viewopti.obj \
+ $(SLO)$/inputopt.obj \
+ $(SLO)$/zforauto.obj \
+ $(SLO)$/hints.obj \
+ $(SLO)$/prnsave.obj \
+ $(SLO)$/navicfg.obj \
+ $(SLO)$/addincol.obj \
+ $(SLO)$/addinlis.obj \
+ $(SLO)$/rangeseq.obj
+
+EXCEPTIONSFILES= \
+ $(SLO)$/addincol.obj
+
+.IF "$(GUI)"=="OS2"
+NOOPTFILES= \
+ $(SLO)$/interpr6.obj
+.ENDIF
+
+# --- Tagets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/sc/source/core/tool/navicfg.cxx b/sc/source/core/tool/navicfg.cxx
new file mode 100644
index 000000000000..a37b86671dcb
--- /dev/null
+++ b/sc/source/core/tool/navicfg.cxx
@@ -0,0 +1,169 @@
+/*************************************************************************
+ *
+ * $RCSfile: navicfg.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:18 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+//------------------------------------------------------------------
+
+#include <tools/stream.hxx>
+
+#include "navicfg.hxx"
+#include "cfgids.hxx"
+#include "scresid.hxx"
+#include "sc.hrc"
+
+#define SC_NAVICFG_VERSION 0
+
+//------------------------------------------------------------------
+
+ScNavipiCfg::ScNavipiCfg() :
+ SfxConfigItem( SCCFG_NAVIPI ),
+ nListMode(0),
+ nDragMode(0),
+ nRootType(0)
+{
+}
+
+//------------------------------------------------------------------------
+
+int __EXPORT ScNavipiCfg::Load( SvStream& rStream )
+{
+ SetDefault(FALSE);
+
+ USHORT nVer;
+ rStream >> nVer;
+ if ( nVer != SC_NAVICFG_VERSION )
+ return SfxConfigItem::WARNING_VERSION;
+
+ rStream >> nListMode;
+ rStream >> nDragMode;
+ rStream >> nRootType;
+
+ return SfxConfigItem::ERR_OK;
+}
+
+//------------------------------------------------------------------------
+
+BOOL __EXPORT ScNavipiCfg::Store( SvStream& rStream)
+{
+ rStream << (USHORT) SC_NAVICFG_VERSION;
+
+ rStream << nListMode;
+ rStream << nDragMode;
+ rStream << nRootType;
+
+//? SetDefault( FALSE );
+ return SfxConfigItem::ERR_OK;
+}
+
+//------------------------------------------------------------------------
+
+void __EXPORT ScNavipiCfg::UseDefault()
+{
+ nListMode = nDragMode = nRootType = 0;
+
+ SetDefault( TRUE );
+}
+
+
+//------------------------------------------------------------------------
+
+void ScNavipiCfg::SetListMode(USHORT nNew)
+{
+ if ( nListMode != nNew )
+ {
+ nListMode = nNew;
+ SetDefault(FALSE);
+ }
+}
+
+void ScNavipiCfg::SetDragMode(USHORT nNew)
+{
+ if ( nDragMode != nNew )
+ {
+ nDragMode = nNew;
+ SetDefault(FALSE);
+ }
+}
+
+void ScNavipiCfg::SetRootType(USHORT nNew)
+{
+ if ( nRootType != nNew )
+ {
+ nRootType = nNew;
+ SetDefault(FALSE);
+ }
+}
+
+//------------------------------------------------------------------------
+
+String __EXPORT ScNavipiCfg::GetName() const
+{
+ return String( ScResId( SCSTR_CFG_NAVIPI ) );
+}
+
+
+
+
diff --git a/sc/source/core/tool/printopt.cxx b/sc/source/core/tool/printopt.cxx
new file mode 100644
index 000000000000..8b283b8d5f81
--- /dev/null
+++ b/sc/source/core/tool/printopt.cxx
@@ -0,0 +1,297 @@
+/*************************************************************************
+ *
+ * $RCSfile: printopt.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:18 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include <segmentc.hxx>
+
+#include <tlstream.hxx>
+#include "cfgids.hxx"
+#include "printopt.hxx"
+#include "scresid.hxx"
+#include "sc.hrc"
+
+// STATIC DATA -----------------------------------------------------------
+
+#define SC_VERSION ((USHORT)251)
+
+TYPEINIT1(ScTpPrintItem, SfxPoolItem);
+
+SEG_EOFGLOBALS()
+
+//========================================================================
+// ScPrintOptions - Dokument-Optionen
+//========================================================================
+#pragma SEG_FUNCDEF(printopt_01)
+
+ScPrintOptions::ScPrintOptions()
+{
+ SetDefaults();
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(printopt_02)
+
+ScPrintOptions::ScPrintOptions( const ScPrintOptions& rCpy )
+ : bWarnPrinterNotFound( rCpy.bWarnPrinterNotFound ),
+ bWarnPageSize( rCpy.bWarnPageSize ),
+ bWarnOrientation( rCpy.bWarnOrientation )
+{
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(printopt_03)
+
+__EXPORT ScPrintOptions::~ScPrintOptions()
+{
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(printopt_04)
+
+SvStream& operator>>( SvStream& rStream, ScPrintOptions& rOpt )
+{
+ rStream >> rOpt.bWarnPrinterNotFound;
+ rStream >> rOpt.bWarnPageSize;
+ rStream >> rOpt.bWarnOrientation;
+
+ return rStream;
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(printopt_05)
+
+SvStream& operator<<( SvStream& rStream, const ScPrintOptions& rOpt )
+{
+ rStream << rOpt.bWarnPrinterNotFound;
+ rStream << rOpt.bWarnPageSize;
+ rStream << rOpt.bWarnOrientation;
+
+ return rStream;
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(printopt_06)
+
+void ScPrintOptions::SetDefaults()
+{
+ bWarnPrinterNotFound = TRUE;
+ bWarnPageSize = FALSE;
+ bWarnOrientation = FALSE;
+}
+
+//========================================================================
+// ScTpPrintItem - Daten fuer die PrintOptions-TabPage
+//========================================================================
+#pragma SEG_FUNCDEF(printopt_07)
+
+ScTpPrintItem::ScTpPrintItem( USHORT nWhich ) : SfxPoolItem( nWhich )
+{
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(printopt_08)
+
+ScTpPrintItem::ScTpPrintItem( USHORT nWhich, const ScPrintOptions& rOpt )
+ : SfxPoolItem ( nWhich ),
+ theOptions ( rOpt )
+{
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(printopt_09)
+
+ScTpPrintItem::ScTpPrintItem( const ScTpPrintItem& rItem )
+ : SfxPoolItem ( rItem ),
+ theOptions ( rItem.theOptions )
+{
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(printopt_0a)
+
+__EXPORT ScTpPrintItem::~ScTpPrintItem()
+{
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(printopt_0b)
+
+String __EXPORT ScTpPrintItem::GetValueText() const
+{
+ return "ScTpPrintItem";
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(printopt_0c)
+
+int __EXPORT ScTpPrintItem::operator==( const SfxPoolItem& rItem ) const
+{
+ DBG_ASSERT( SfxPoolItem::operator==( rItem ), "unequal Which or Type" );
+
+ const ScTpPrintItem& rPItem = (const ScTpPrintItem&)rItem;
+
+ return ( theOptions == rPItem.theOptions );
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(printopt_0d)
+
+SfxPoolItem* __EXPORT ScTpPrintItem::Clone( SfxItemPool * ) const
+{
+ return new ScTpPrintItem( *this );
+}
+
+//==================================================================
+// CfgItem fuer Print-Optionen
+//==================================================================
+#pragma SEG_FUNCDEF(printopt_12)
+
+ScPrintCfg::ScPrintCfg() : SfxConfigItem( SCCFG_PRINT )
+{
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(printopt_0e)
+
+int __EXPORT ScPrintCfg::Load( SvStream& rStream )
+{
+ USHORT nVersion;
+
+ rStream >> nVersion;
+ rStream >> (ScPrintOptions&)*this;
+
+ SetDefault( FALSE );
+
+ return ( nVersion == SC_VERSION )
+ ? SfxConfigItem::ERR_OK
+ : SfxConfigItem::WARNING_VERSION;
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(printopt_11)
+
+BOOL SEXPORT ScPrintCfg::Store( SvStream& rStream)
+{
+ rStream << SC_VERSION;
+ rStream << *this;
+
+ SetDefault( FALSE );
+
+ return SfxConfigItem::ERR_OK;
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(printopt_0f)
+
+void __EXPORT ScPrintCfg::UseDefault()
+{
+ SetDefaults();
+ SetDefault( TRUE );
+}
+
+//------------------------------------------------------------------------
+#pragma SEG_FUNCDEF(printopt_10)
+
+String __EXPORT ScPrintCfg::GetName() const
+{
+ return String( ScResId( SCSTR_CFG_PRINT ) );
+}
+
+/*------------------------------------------------------------------------
+
+ $Log: not supported by cvs2svn $
+ Revision 1.8 2000/09/17 14:08:42 willem.vandorp
+ OpenOffice header added.
+
+ Revision 1.7 2000/08/31 16:38:03 willem.vandorp
+ Header and footer replaced
+
+ Revision 1.6 1997/11/13 20:05:36 NN
+ ifndef PCH raus
+
+
+ Rev 1.5 13 Nov 1997 21:05:36 NN
+ ifndef PCH raus
+
+ Rev 1.4 06 Nov 1996 09:48:56 TRI
+ includes
+
+ Rev 1.3 17 Nov 1995 14:49:44 MO
+ SetModified entfernt
+
+ Rev 1.2 16 Nov 1995 20:41:44 MO
+ SetDefault()/SetModified im Load/Save
+
+ Rev 1.1 09 Oct 1995 11:49:02 MO
+ ResId -> ScResId
+
+ Rev 1.0 18 Sep 1995 17:04:30 MO
+ Initial revision.
+
+------------------------------------------------------------------------*/
+
+#pragma SEG_EOFMODULE
+
diff --git a/sc/source/core/tool/prnsave.cxx b/sc/source/core/tool/prnsave.cxx
new file mode 100644
index 000000000000..d396419a4fb7
--- /dev/null
+++ b/sc/source/core/tool/prnsave.cxx
@@ -0,0 +1,189 @@
+/*************************************************************************
+ *
+ * $RCSfile: prnsave.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:18 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <tools/debug.hxx>
+
+#include "prnsave.hxx"
+#include "global.hxx"
+
+// STATIC DATA -----------------------------------------------------------
+
+//------------------------------------------------------------------
+
+//
+// Daten pro Tabelle
+//
+
+ScPrintSaverTab::ScPrintSaverTab() :
+ nPrintCount(0),
+ pPrintRanges(NULL),
+ pRepeatCol(NULL),
+ pRepeatRow(NULL)
+{
+}
+
+ScPrintSaverTab::~ScPrintSaverTab()
+{
+ delete[] pPrintRanges;
+ delete pRepeatCol;
+ delete pRepeatRow;
+}
+
+void ScPrintSaverTab::SetAreas( USHORT nCount, const ScRange* pRanges )
+{
+ delete[] pPrintRanges;
+ if (nCount && pRanges)
+ {
+ nPrintCount = nCount;
+ pPrintRanges = new ScRange[nCount];
+ for (USHORT i=0; i<nCount; i++)
+ pPrintRanges[i] = pRanges[i];
+ }
+ else
+ {
+ nPrintCount = 0;
+ pPrintRanges = NULL;
+ }
+}
+
+void ScPrintSaverTab::SetRepeat( const ScRange* pCol, const ScRange* pRow )
+{
+ delete pRepeatCol;
+ pRepeatCol = pCol ? new ScRange(*pCol) : NULL;
+ delete pRepeatRow;
+ pRepeatRow = pRow ? new ScRange(*pRow) : NULL;
+}
+
+inline BOOL PtrEqual( const ScRange* p1, const ScRange* p2 )
+{
+ return ( !p1 && !p2 ) || ( p1 && p2 && *p1 == *p2 );
+}
+
+BOOL ScPrintSaverTab::operator==( const ScPrintSaverTab& rCmp ) const
+{
+ BOOL bEqual = ( nPrintCount == rCmp.nPrintCount &&
+ PtrEqual( pRepeatCol, rCmp.pRepeatCol ) &&
+ PtrEqual( pRepeatRow, rCmp.pRepeatRow ) );
+ if (bEqual)
+ for (USHORT i=0; i<nPrintCount; i++)
+ if ( pPrintRanges[i] != rCmp.pPrintRanges[i] )
+ {
+ bEqual = FALSE;
+ break;
+ }
+
+ return bEqual;
+}
+
+//
+// Daten fuer das ganze Dokument
+//
+
+ScPrintRangeSaver::ScPrintRangeSaver( USHORT nCount ) :
+ nTabCount( nCount )
+{
+ if (nCount)
+ pData = new ScPrintSaverTab[nCount];
+ else
+ pData = NULL;
+}
+
+ScPrintRangeSaver::~ScPrintRangeSaver()
+{
+ delete[] pData;
+}
+
+ScPrintSaverTab& ScPrintRangeSaver::GetTabData(USHORT nTab)
+{
+ DBG_ASSERT(nTab<nTabCount,"ScPrintRangeSaver Tab zu gross");
+ return pData[nTab];
+}
+
+const ScPrintSaverTab& ScPrintRangeSaver::GetTabData(USHORT nTab) const
+{
+ DBG_ASSERT(nTab<nTabCount,"ScPrintRangeSaver Tab zu gross");
+ return pData[nTab];
+}
+
+BOOL ScPrintRangeSaver::operator==( const ScPrintRangeSaver& rCmp ) const
+{
+ BOOL bEqual = ( nTabCount == rCmp.nTabCount );
+ if (bEqual)
+ for (USHORT i=0; i<nTabCount; i++)
+ if (!(pData[i]==rCmp.pData[i]))
+ {
+ bEqual = FALSE;
+ break;
+ }
+ return bEqual;
+}
+
+
+
+
diff --git a/sc/source/core/tool/progress.cxx b/sc/source/core/tool/progress.cxx
new file mode 100644
index 000000000000..8dd69f319108
--- /dev/null
+++ b/sc/source/core/tool/progress.cxx
@@ -0,0 +1,216 @@
+/*************************************************************************
+ *
+ * $RCSfile: progress.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:18 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+//------------------------------------------------------------------------
+
+#include <sfx2/app.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/progress.hxx>
+
+#define SC_PROGRESS_CXX
+#include "progress.hxx"
+#include "document.hxx"
+#include "global.hxx"
+#include "globstr.hrc"
+
+
+
+ScProgress theDummyInterpretProgress;
+SfxProgress* ScProgress::pGlobalProgress = NULL;
+ULONG ScProgress::nGlobalRange = 0;
+ULONG ScProgress::nGlobalPercent = 0;
+BOOL ScProgress::bGlobalNoUserBreak = TRUE;
+ScProgress* ScProgress::pInterpretProgress = &theDummyInterpretProgress;
+ScProgress* ScProgress::pOldInterpretProgress = NULL;
+ULONG ScProgress::nInterpretProgress = 0;
+BOOL ScProgress::bAllowInterpretProgress = TRUE;
+ScDocument* ScProgress::pInterpretDoc;
+BOOL ScProgress::bIdleWasDisabled = FALSE;
+
+
+
+ScProgress::ScProgress( SfxObjectShell* pObjSh, const String& rText,
+ ULONG nRange, BOOL bAllDocs, BOOL bWait )
+{
+
+ if ( pGlobalProgress || SfxProgress::GetActiveProgress( NULL ) )
+ {
+ DBG_ERROR( "ScProgress: es kann nur einen geben!" );
+ pProgress = NULL;
+ }
+ else if ( SFX_APP()->IsDowning() )
+ {
+ // kommt vor z.B. beim Speichern des Clipboard-Inhalts als OLE beim Beenden
+ // Dann wuerde ein SfxProgress wild im Speicher rummuellen
+ //! Soll das so sein ???
+
+ pProgress = NULL;
+ }
+ else if ( pObjSh && ( pObjSh->GetCreateMode() == SFX_CREATE_MODE_EMBEDDED ||
+ pObjSh->GetProgress() ) )
+ {
+ // #62808# no own progress for embedded objects,
+ // #73633# no second progress if the document already has one
+
+ pProgress = NULL;
+ }
+ else
+ {
+ pProgress = new SfxProgress( pObjSh, rText, nRange, bAllDocs, bWait );
+ pGlobalProgress = pProgress;
+ nGlobalRange = nRange;
+ nGlobalPercent = 0;
+ bGlobalNoUserBreak = TRUE;
+ }
+}
+
+
+ScProgress::ScProgress() :
+ pProgress( NULL )
+{ // DummyInterpret
+}
+
+
+ScProgress::~ScProgress()
+{
+ if ( pProgress )
+ {
+ delete pProgress;
+ pGlobalProgress = NULL;
+ nGlobalRange = 0;
+ nGlobalPercent = 0;
+ bGlobalNoUserBreak = TRUE;
+ }
+}
+
+
+// static
+
+void ScProgress::SetAllowInterpret( BOOL bAllow )
+{ // Grundzustand: Allow, Dummy gesetzt, pOld==NULL
+ if ( !bAllow && bAllowInterpretProgress )
+ { // vorherigen/Dummy merken und Dummy setzen
+ pOldInterpretProgress = pInterpretProgress;
+ pInterpretProgress = &theDummyInterpretProgress;
+ bAllowInterpretProgress = FALSE;
+ }
+ else if ( bAllow && !bAllowInterpretProgress )
+ { // Dummy weg und vorherigen/Dummy setzen
+ pInterpretProgress = pOldInterpretProgress;
+ pOldInterpretProgress = NULL;
+ bAllowInterpretProgress = TRUE;
+ }
+}
+
+
+// static
+
+void ScProgress::CreateInterpretProgress( ScDocument* pDoc, BOOL bWait )
+{
+ if ( bAllowInterpretProgress )
+ {
+ if ( nInterpretProgress )
+ nInterpretProgress++;
+ else if ( pDoc->GetAutoCalc() )
+ {
+ bIdleWasDisabled = pDoc->IsIdleDisabled();
+ pDoc->DisableIdle( TRUE );
+ pInterpretProgress = new ScProgress( pDoc->GetDocumentShell(),
+ ScGlobal::GetRscString( STR_PROGRESS_CALCULATING ),
+ pDoc->GetFormulaCodeInTree(), FALSE, bWait );
+ pInterpretDoc = pDoc;
+ nInterpretProgress = 1;
+ }
+ }
+}
+
+
+// static
+
+void ScProgress::DeleteInterpretProgress()
+{
+ if ( bAllowInterpretProgress && nInterpretProgress )
+ {
+ if ( --nInterpretProgress == 0 )
+ {
+ if ( pInterpretProgress != &theDummyInterpretProgress )
+ {
+ delete pInterpretProgress;
+ pInterpretProgress = &theDummyInterpretProgress;
+ pInterpretDoc->DisableIdle( bIdleWasDisabled );
+ }
+ else
+ {
+ DBG_ASSERT( pInterpretProgress != &theDummyInterpretProgress,
+ "DeleteInterpretProgress: Dummy loeschen?!?" )
+ }
+ }
+ }
+}
+
+
+
diff --git a/sc/source/core/tool/rangelst.cxx b/sc/source/core/tool/rangelst.cxx
new file mode 100644
index 000000000000..0468900ebe22
--- /dev/null
+++ b/sc/source/core/tool/rangelst.cxx
@@ -0,0 +1,781 @@
+/*************************************************************************
+ *
+ * $RCSfile: rangelst.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:18 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+//------------------------------------------------------------------------
+
+#define SC_RANGELST_CXX //fuer ICC
+
+#include <tools/debug.hxx>
+#include <tools/intn.hxx>
+#include <stdlib.h> // qsort
+
+#include "rangelst.hxx"
+#include "document.hxx"
+#include "refupdat.hxx"
+#include "rechead.hxx"
+
+
+// === ScRangeList ====================================================
+
+ScRangeList::~ScRangeList()
+{
+ for ( ScRangePtr pR = First(); pR; pR = Next() )
+ delete pR;
+}
+
+void ScRangeList::RemoveAll()
+{
+ for ( ScRangePtr pR = First(); pR; pR = Next() )
+ delete pR;
+ Clear();
+}
+
+USHORT ScRangeList::Parse( const String& rStr, ScDocument* pDoc, USHORT nMask )
+{
+ if ( rStr.Len() )
+ {
+ nMask |= SCA_VALID; // falls das jemand vergessen sollte
+ USHORT nResult = (USHORT)~0; // alle Bits setzen
+ ScRange aRange;
+ String aOne;
+ USHORT nTab = 0;
+ if ( pDoc )
+ {
+ //! erste markierte Tabelle gibts nicht mehr am Dokument
+ //! -> uebergeben? oder spaeter an den Ranges setzen
+ }
+ else
+ nTab = 0;
+ USHORT nTCount = rStr.GetTokenCount();
+ for ( USHORT i=0; i<nTCount; i++ )
+ {
+ aOne = rStr.GetToken(i);
+ if ( aOne.Search( ':' ) == STRING_NOTFOUND )
+ { // Range muss es sein
+ String aStrTmp( aOne );
+ aOne += ':';
+ aOne += aStrTmp;
+ }
+ aRange.aStart.SetTab( nTab ); // Default Tab wenn nicht angegeben
+ USHORT nRes = aRange.Parse( aOne, pDoc );
+ if ( (nRes & nMask) == nMask )
+ Append( aRange );
+ nResult &= nRes; // alle gemeinsamen Bits bleiben erhalten
+ }
+ return nResult; // SCA_VALID gesetzt wenn alle ok
+ }
+ else
+ return 0;
+}
+
+
+void ScRangeList::Format( String& rStr, USHORT nFlags, ScDocument* pDoc ) const
+{
+ rStr.Erase();
+ ULONG nCnt = Count();
+ for ( ULONG nIdx = 0; nIdx < nCnt; nIdx++ )
+ {
+ String aStr;
+ GetObject( nIdx )->Format( aStr, nFlags, pDoc );
+ if ( nIdx )
+ rStr += ';';
+ rStr += aStr;
+ }
+}
+
+
+void ScRangeList::Join( const ScRange& r, BOOL bIsInList )
+{
+ if ( !Count() )
+ {
+ Append( r );
+ return ;
+ }
+ USHORT nCol1 = r.aStart.Col();
+ USHORT nRow1 = r.aStart.Row();
+ USHORT nTab1 = r.aStart.Tab();
+ USHORT nCol2 = r.aEnd.Col();
+ USHORT nRow2 = r.aEnd.Row();
+ USHORT nTab2 = r.aEnd.Tab();
+ ScRangePtr pOver = (ScRangePtr) &r; // fies aber wahr wenn bInList
+ ULONG nOldPos;
+ if ( bIsInList )
+ { // merken um ggbf. zu loeschen bzw. wiederherzustellen
+ nOldPos = GetPos( pOver );
+ }
+ BOOL bJoinedInput = FALSE;
+ for ( ScRangePtr p = First(); p && pOver; p = Next() )
+ {
+ if ( p == pOver )
+ continue; // derselbe, weiter mit dem naechsten
+ BOOL bJoined = FALSE;
+ if ( p->In( r ) )
+ { // Range r in Range p enthalten oder identisch
+ if ( bIsInList )
+ bJoined = TRUE; // weg mit Range r
+ else
+ { // das war's dann
+ bJoinedInput = TRUE; // nicht anhaengen
+ break; // for
+ }
+ }
+ else if ( r.In( *p ) )
+ { // Range p in Range r enthalten, r zum neuen Range machen
+ *p = r;
+ bJoined = TRUE;
+ }
+ if ( !bJoined && p->aStart.Tab() == nTab1 && p->aEnd.Tab() == nTab2 )
+ { // 2D
+ if ( p->aStart.Col() == nCol1 && p->aEnd.Col() == nCol2 )
+ {
+ if ( p->aStart.Row() == nRow2+1 )
+ { // oben
+ p->aStart.SetRow( nRow1 );
+ bJoined = TRUE;
+ }
+ else if ( p->aEnd.Row() == nRow1-1 )
+ { // unten
+ p->aEnd.SetRow( nRow2 );
+ bJoined = TRUE;
+ }
+ }
+ else if ( p->aStart.Row() == nRow1 && p->aEnd.Row() == nRow2 )
+ {
+ if ( p->aStart.Col() == nCol2+1 )
+ { // links
+ p->aStart.SetCol( nCol1 );
+ bJoined = TRUE;
+ }
+ else if ( p->aEnd.Col() == nCol1-1 )
+ { // rechts
+ p->aEnd.SetCol( nCol2 );
+ bJoined = TRUE;
+ }
+ }
+ }
+ if ( bJoined )
+ {
+ if ( bIsInList )
+ { // innerhalb der Liste Range loeschen
+ Remove( nOldPos );
+ delete pOver;
+ pOver = NULL;
+ if ( nOldPos )
+ nOldPos--; // Seek richtig aufsetzen
+ }
+ bJoinedInput = TRUE;
+ Join( *p, TRUE ); // rekursiv!
+ }
+ }
+ if ( bIsInList )
+ Seek( nOldPos );
+ else if ( !bJoinedInput )
+ Append( r );
+}
+
+
+BOOL ScRangeList::operator==( const ScRangeList& r ) const
+{
+ if ( this == &r )
+ return TRUE; // identische Referenz
+ if ( Count() != r.Count() )
+ return FALSE;
+ ULONG nCnt = Count();
+ for ( ULONG nIdx = 0; nIdx < nCnt; nIdx++ )
+ {
+ if ( *GetObject( nIdx ) != *r.GetObject( nIdx ) )
+ return FALSE; // auch andere Reihenfolge ist ungleich
+ }
+ return TRUE;
+}
+
+
+BOOL ScRangeList::Store( SvStream& rStream ) const
+{
+ BOOL bOk = TRUE;
+ ULONG nCount = Count();
+ ULONG nBytes = sizeof(UINT32) + nCount * sizeof(ScRange);
+ ScWriteHeader aHdr( rStream, nBytes );
+ rStream << (UINT32) nCount;
+ for ( ULONG j = 0; j < nCount && bOk; j++ )
+ {
+ rStream << *GetObject( j );
+ if( rStream.GetError() != SVSTREAM_OK )
+ bOk = FALSE;
+ }
+ return bOk;
+}
+
+
+BOOL ScRangeList::Load( SvStream& rStream, USHORT nVer )
+{
+ BOOL bOk = TRUE;
+ ScReadHeader aHdr( rStream );
+ ScRange aRange;
+ UINT32 n;
+ rStream >> n;
+ ULONG nCount = n;
+ for ( ULONG j = 0; j < nCount && bOk; j++ )
+ {
+ rStream >> aRange;
+ Append( aRange );
+ if( rStream.GetError() != SVSTREAM_OK )
+ bOk = FALSE;
+ }
+ return bOk;
+}
+
+
+BOOL ScRangeList::UpdateReference( UpdateRefMode eUpdateRefMode,
+ ScDocument* pDoc, const ScRange& rWhere,
+ short nDx, short nDy, short nDz )
+{
+ BOOL bChanged = FALSE;
+ if ( Count() )
+ {
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ rWhere.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ for ( ScRange* pR = First(); pR; pR = Next() )
+ {
+ USHORT theCol1, theRow1, theTab1, theCol2, theRow2, theTab2;
+ pR->GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 );
+ if ( ScRefUpdate::Update( pDoc, eUpdateRefMode,
+ nCol1, nRow1, nTab1, nCol2, nRow2, nTab2,
+ nDx, nDy, nDz,
+ theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 )
+ != UR_NOTHING )
+ {
+ bChanged = TRUE;
+ pR->aStart.Set( theCol1, theRow1, theTab1 );
+ pR->aEnd.Set( theCol2, theRow2, theTab2 );
+ }
+ }
+ }
+ return bChanged;
+}
+
+
+ScRange* ScRangeList::Find( const ScAddress& rAdr ) const
+{
+ ULONG nCount = Count();
+ for ( ULONG j = 0; j < nCount; j++ )
+ {
+ ScRange* pR = GetObject( j );
+ if ( pR->In( rAdr ) )
+ return pR;
+ }
+ return NULL;
+}
+
+
+ScRange* ScRangeList::Find( const ScRange& rRange ) const
+{
+ ULONG nCount = Count();
+ for ( ULONG j = 0; j < nCount; j++ )
+ {
+ ScRange* pR = GetObject( j );
+ if ( *pR == rRange )
+ return pR;
+ }
+ return NULL;
+}
+
+
+ScRangeList::ScRangeList( const ScRangeList& rList )
+{
+ ULONG nCount = rList.Count();
+ for ( ULONG j = 0; j < nCount; j++ )
+ Append( *rList.GetObject( j ) );
+}
+
+
+ScRangeList* ScRangeList::Clone() const
+{
+ return new ScRangeList( *this );
+}
+
+
+ScRangeList& ScRangeList::operator=(const ScRangeList& rList)
+{
+ RemoveAll();
+
+ ULONG nCount = rList.Count();
+ for ( ULONG j = 0; j < nCount; j++ )
+ Append( *rList.GetObject( j ) );
+
+ return *this;
+}
+
+
+BOOL ScRangeList::Intersects( const ScRange& rRange ) const
+{
+ ULONG nCount = Count();
+ for ( ULONG j = 0; j < nCount; j++ )
+ if ( GetObject(j)->Intersects( rRange ) )
+ return TRUE;
+
+ return FALSE;
+}
+
+
+ULONG ScRangeList::GetCellCount() const
+{
+ ULONG nCellCount = 0;
+ ULONG nCount = Count();
+ for ( ULONG j = 0; j < nCount; j++ )
+ {
+ ScRange* pR = GetObject( j );
+ nCellCount += ULONG(pR->aEnd.Col() - pR->aStart.Col() + 1)
+ * ULONG(pR->aEnd.Row() - pR->aStart.Row() + 1)
+ * ULONG(pR->aEnd.Tab() - pR->aStart.Tab() + 1);
+ }
+ return nCellCount;
+}
+
+
+// === ScRangePairList ====================================================
+
+ScRangePairList::~ScRangePairList()
+{
+ for ( ScRangePair* pR = First(); pR; pR = Next() )
+ delete pR;
+}
+
+
+void ScRangePairList::Join( const ScRangePair& r, BOOL bIsInList )
+{
+ if ( !Count() )
+ {
+ Append( r );
+ return ;
+ }
+ const ScRange& r1 = r.GetRange(0);
+ const ScRange& r2 = r.GetRange(1);
+ USHORT nCol1 = r1.aStart.Col();
+ USHORT nRow1 = r1.aStart.Row();
+ USHORT nTab1 = r1.aStart.Tab();
+ USHORT nCol2 = r1.aEnd.Col();
+ USHORT nRow2 = r1.aEnd.Row();
+ USHORT nTab2 = r1.aEnd.Tab();
+ ScRangePair* pOver = (ScRangePair*) &r; // fies aber wahr wenn bInList
+ ULONG nOldPos;
+ if ( bIsInList )
+ { // merken um ggbf. zu loeschen bzw. wiederherzustellen
+ nOldPos = GetPos( pOver );
+ }
+ BOOL bJoinedInput = FALSE;
+ for ( ScRangePair* p = First(); p && pOver; p = Next() )
+ {
+ if ( p == pOver )
+ continue; // derselbe, weiter mit dem naechsten
+ BOOL bJoined = FALSE;
+ ScRange& rp1 = p->GetRange(0);
+ ScRange& rp2 = p->GetRange(1);
+ if ( rp2 == r2 )
+ { // nur wenn Range2 gleich ist
+ if ( rp1.In( r1 ) )
+ { // RangePair r in RangePair p enthalten oder identisch
+ if ( bIsInList )
+ bJoined = TRUE; // weg mit RangePair r
+ else
+ { // das war's dann
+ bJoinedInput = TRUE; // nicht anhaengen
+ break; // for
+ }
+ }
+ else if ( r1.In( rp1 ) )
+ { // RangePair p in RangePair r enthalten, r zum neuen RangePair machen
+ *p = r;
+ bJoined = TRUE;
+ }
+ }
+ if ( !bJoined && rp1.aStart.Tab() == nTab1 && rp1.aEnd.Tab() == nTab2
+ && rp2.aStart.Tab() == r2.aStart.Tab()
+ && rp2.aEnd.Tab() == r2.aEnd.Tab() )
+ { // 2D, Range2 muss genauso nebeneinander liegen wie Range1
+ if ( rp1.aStart.Col() == nCol1 && rp1.aEnd.Col() == nCol2
+ && rp2.aStart.Col() == r2.aStart.Col()
+ && rp2.aEnd.Col() == r2.aEnd.Col() )
+ {
+ if ( rp1.aStart.Row() == nRow2+1
+ && rp2.aStart.Row() == r2.aEnd.Row()+1 )
+ { // oben
+ rp1.aStart.SetRow( nRow1 );
+ rp2.aStart.SetRow( r2.aStart.Row() );
+ bJoined = TRUE;
+ }
+ else if ( rp1.aEnd.Row() == nRow1-1
+ && rp2.aEnd.Row() == r2.aStart.Row()-1 )
+ { // unten
+ rp1.aEnd.SetRow( nRow2 );
+ rp2.aEnd.SetRow( r2.aEnd.Row() );
+ bJoined = TRUE;
+ }
+ }
+ else if ( rp1.aStart.Row() == nRow1 && rp1.aEnd.Row() == nRow2
+ && rp2.aStart.Row() == r2.aStart.Row()
+ && rp2.aEnd.Row() == r2.aEnd.Row() )
+ {
+ if ( rp1.aStart.Col() == nCol2+1
+ && rp2.aStart.Col() == r2.aEnd.Col()+1 )
+ { // links
+ rp1.aStart.SetCol( nCol1 );
+ rp2.aStart.SetCol( r2.aStart.Col() );
+ bJoined = TRUE;
+ }
+ else if ( rp1.aEnd.Col() == nCol1-1
+ && rp2.aEnd.Col() == r2.aEnd.Col()-1 )
+ { // rechts
+ rp1.aEnd.SetCol( nCol2 );
+ rp2.aEnd.SetCol( r2.aEnd.Col() );
+ bJoined = TRUE;
+ }
+ }
+ }
+ if ( bJoined )
+ {
+ if ( bIsInList )
+ { // innerhalb der Liste RangePair loeschen
+ Remove( nOldPos );
+ delete pOver;
+ pOver = NULL;
+ if ( nOldPos )
+ nOldPos--; // Seek richtig aufsetzen
+ }
+ bJoinedInput = TRUE;
+ Join( *p, TRUE ); // rekursiv!
+ }
+ }
+ if ( bIsInList )
+ Seek( nOldPos );
+ else if ( !bJoinedInput )
+ Append( r );
+}
+
+
+BOOL ScRangePairList::operator==( const ScRangePairList& r ) const
+{
+ if ( this == &r )
+ return TRUE; // identische Referenz
+ if ( Count() != r.Count() )
+ return FALSE;
+ ULONG nCnt = Count();
+ for ( ULONG nIdx = 0; nIdx < nCnt; nIdx++ )
+ {
+ if ( *GetObject( nIdx ) != *r.GetObject( nIdx ) )
+ return FALSE; // auch andere Reihenfolge ist ungleich
+ }
+ return TRUE;
+}
+
+
+BOOL ScRangePairList::Store( SvStream& rStream ) const
+{
+ BOOL bOk = TRUE;
+ ULONG nCount = Count();
+ ULONG nBytes = sizeof(UINT32) + nCount * sizeof(ScRangePair);
+ ScWriteHeader aHdr( rStream, nBytes );
+ rStream << (UINT32) nCount;
+ for ( ULONG j = 0; j < nCount && bOk; j++ )
+ {
+ rStream << *GetObject( j );
+ if( rStream.GetError() != SVSTREAM_OK )
+ bOk = FALSE;
+ }
+ return bOk;
+}
+
+
+BOOL ScRangePairList::Load( SvStream& rStream, USHORT nVer )
+{
+ BOOL bOk = TRUE;
+ ScReadHeader aHdr( rStream );
+ ScRangePair aRangePair;
+ ScRange aRange;
+ UINT32 n;
+ rStream >> n;
+ ULONG nCount = n;
+ for ( ULONG j = 0; j < nCount && bOk; j++ )
+ {
+ if ( nVer < SC_COLROWNAME_RANGEPAIR )
+ { // aus technical Beta 4.0 versuchen mit altem Verhalten zu uebernehmen
+ rStream >> aRange;
+ aRangePair.GetRange(0) = aRange;
+ ScRange& r = aRangePair.GetRange(1);
+ r = aRange;
+ USHORT nCol2 = aRange.aEnd.Col();
+ USHORT nRow2 = aRange.aEnd.Row();
+ if ( nCol2 - aRange.aStart.Col() >= nRow2 - aRange.aStart.Row() )
+ { // ColNames
+ r.aStart.SetRow( (USHORT) Min( (ULONG)nRow2 + 1, (ULONG)MAXROW ) );
+ r.aEnd.SetRow( MAXROW );
+ }
+ else
+ { // RowNames
+ r.aStart.SetCol( (USHORT) Min( (ULONG)(nCol2 + 1), (ULONG)MAXCOL ) );
+ r.aEnd.SetCol( MAXCOL );
+ }
+ }
+ else
+ rStream >> aRangePair;
+ Append( aRangePair );
+ if( rStream.GetError() != SVSTREAM_OK )
+ bOk = FALSE;
+ }
+ return bOk;
+}
+
+
+BOOL ScRangePairList::UpdateReference( UpdateRefMode eUpdateRefMode,
+ ScDocument* pDoc, const ScRange& rWhere,
+ short nDx, short nDy, short nDz )
+{
+ BOOL bChanged = FALSE;
+ if ( Count() )
+ {
+ USHORT nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ rWhere.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ for ( ScRangePair* pR = First(); pR; pR = Next() )
+ {
+ for ( USHORT j=0; j<2; j++ )
+ {
+ ScRange& rRange = pR->GetRange(j);
+ USHORT theCol1, theRow1, theTab1, theCol2, theRow2, theTab2;
+ rRange.GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 );
+ if ( ScRefUpdate::Update( pDoc, eUpdateRefMode,
+ nCol1, nRow1, nTab1, nCol2, nRow2, nTab2,
+ nDx, nDy, nDz,
+ theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 )
+ != UR_NOTHING )
+ {
+ bChanged = TRUE;
+ rRange.aStart.Set( theCol1, theRow1, theTab1 );
+ rRange.aEnd.Set( theCol2, theRow2, theTab2 );
+ }
+ }
+ }
+ }
+ return bChanged;
+}
+
+
+ScRangePair* ScRangePairList::Find( const ScAddress& rAdr ) const
+{
+ ULONG nCount = Count();
+ for ( ULONG j = 0; j < nCount; j++ )
+ {
+ ScRangePair* pR = GetObject( j );
+ if ( pR->GetRange(0).In( rAdr ) )
+ return pR;
+ }
+ return NULL;
+}
+
+
+ScRangePair* ScRangePairList::Find( const ScRange& rRange ) const
+{
+ ULONG nCount = Count();
+ for ( ULONG j = 0; j < nCount; j++ )
+ {
+ ScRangePair* pR = GetObject( j );
+ if ( pR->GetRange(0) == rRange )
+ return pR;
+ }
+ return NULL;
+}
+
+
+ScRangePairList* ScRangePairList::Clone() const
+{
+ ScRangePairList* pNew = new ScRangePairList;
+ ULONG nCount = Count();
+ for ( ULONG j = 0; j < nCount; j++ )
+ {
+ pNew->Append( *GetObject( j ) );
+ }
+ return pNew;
+}
+
+
+struct ScRangePairNameSort
+{
+ ScRangePair* pPair;
+ ScDocument* pDoc;
+};
+
+
+int
+#ifdef WNT
+__cdecl
+#endif
+ScRangePairList::QsortNameCompare( const void* p1, const void* p2 )
+{
+ const ScRangePairNameSort* ps1 = (const ScRangePairNameSort*)p1;
+ const ScRangePairNameSort* ps2 = (const ScRangePairNameSort*)p2;
+ const ScAddress& rPos1 = ps1->pPair->GetRange(0).aStart;
+ const ScAddress& rPos2 = ps2->pPair->GetRange(0).aStart;
+ String aStr1, aStr2;
+ StringCompare eComp;
+ if ( rPos1.Tab() == rPos2.Tab() )
+ eComp = COMPARE_EQUAL;
+ else
+ {
+ ps1->pDoc->GetName( rPos1.Tab(), aStr1 );
+ ps2->pDoc->GetName( rPos2.Tab(), aStr2 );
+ eComp = ScGlobal::pScInternational->Compare( aStr1, aStr2,
+ INTN_COMPARE_IGNORECASE );
+ }
+ switch ( eComp )
+ {
+ case COMPARE_LESS:
+ return -1;
+ break;
+ case COMPARE_GREATER:
+ return 1;
+ break;
+ default:
+ // gleiche Tabs
+ if ( rPos1.Col() < rPos2.Col() )
+ return -1;
+ if ( rPos1.Col() > rPos2.Col() )
+ return 1;
+ // gleiche Cols
+ if ( rPos1.Row() < rPos2.Row() )
+ return -1;
+ if ( rPos1.Row() > rPos2.Row() )
+ return 1;
+ // erste Ecke gleich, zweite Ecke
+ {
+ const ScAddress& rPos1 = ps1->pPair->GetRange(0).aEnd;
+ const ScAddress& rPos2 = ps2->pPair->GetRange(0).aEnd;
+ if ( rPos1.Tab() == rPos2.Tab() )
+ eComp = COMPARE_EQUAL;
+ else
+ {
+ ps1->pDoc->GetName( rPos1.Tab(), aStr1 );
+ ps2->pDoc->GetName( rPos2.Tab(), aStr2 );
+ eComp = ScGlobal::pScInternational->Compare( aStr1, aStr2,
+ INTN_COMPARE_IGNORECASE );
+ }
+ switch ( eComp )
+ {
+ case COMPARE_LESS:
+ return -1;
+ break;
+ case COMPARE_GREATER:
+ return 1;
+ break;
+ default:
+ // gleiche Tabs
+ if ( rPos1.Col() < rPos2.Col() )
+ return -1;
+ if ( rPos1.Col() > rPos2.Col() )
+ return 1;
+ // gleiche Cols
+ if ( rPos1.Row() < rPos2.Row() )
+ return -1;
+ if ( rPos1.Row() > rPos2.Row() )
+ return 1;
+ return 0;
+ }
+ }
+ return 0;
+ }
+}
+
+
+ScRangePair** ScRangePairList::CreateNameSortedArray( ULONG& nCount,
+ ScDocument* pDoc ) const
+{
+ nCount = Count();
+ DBG_ASSERT( nCount * sizeof(ScRangePairNameSort) <= (size_t)~0x1F,
+ "ScRangePairList::CreateNameSortedArray nCount * sizeof(ScRangePairNameSort) > (size_t)~0x1F" );
+ ScRangePairNameSort* pSortArray = (ScRangePairNameSort*)
+ new BYTE [ nCount * sizeof(ScRangePairNameSort) ];
+ ULONG j;
+ for ( j=0; j < nCount; j++ )
+ {
+ pSortArray[j].pPair = GetObject( j );
+ pSortArray[j].pDoc = pDoc;
+ }
+#if !(defined(ICC ) && defined(OS2))
+ qsort( (void*)pSortArray, nCount, sizeof(ScRangePairNameSort), &ScRangePairList::QsortNameCompare );
+#else
+ qsort( (void*)pSortArray, nCount, sizeof(ScRangePairNameSort), ICCQsortRPairCompare );
+#endif
+ // ScRangePair Pointer aufruecken
+ ScRangePair** ppSortArray = (ScRangePair**)pSortArray;
+ for ( j=0; j < nCount; j++ )
+ {
+ ppSortArray[j] = pSortArray[j].pPair;
+ }
+ return ppSortArray;
+}
+
+
+
+
diff --git a/sc/source/core/tool/rangenam.cxx b/sc/source/core/tool/rangenam.cxx
new file mode 100644
index 000000000000..58340e97b85b
--- /dev/null
+++ b/sc/source/core/tool/rangenam.cxx
@@ -0,0 +1,857 @@
+/*************************************************************************
+ *
+ * $RCSfile: rangenam.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:18 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+//------------------------------------------------------------------------
+
+#include <tools/debug.hxx>
+#include <tools/intn.hxx>
+#include <string.h>
+
+#include "rangenam.hxx"
+#include "global.hxx"
+#include "compiler.hxx"
+#include "rangeutl.hxx"
+#include "rechead.hxx"
+#include "refupdat.hxx"
+#include "document.hxx"
+#include "indexmap.hxx"
+
+
+//========================================================================
+// ScRangeData
+//========================================================================
+
+// Interner ctor fuer das Suchen nach einem Index
+
+ScRangeData::ScRangeData( USHORT n )
+ : nIndex( n ), pCode( NULL ), bModified( FALSE )
+{}
+
+ScRangeData::ScRangeData( ScDocument* pDok,
+ const String& rName,
+ const String& rSymbol,
+ USHORT nCol,
+ USHORT nRow,
+ USHORT nTab,
+ RangeType nType,
+ BOOL bEnglish ) :
+ aName ( rName ),
+ aPos ( nCol, nRow, nTab ),
+ eType ( nType ),
+ pDoc ( pDok ),
+ nIndex ( 0 ),
+ nExportIndex( 0 ),
+ pCode ( NULL ),
+ bModified ( FALSE )
+{
+ if (rSymbol.Len() > 0)
+ {
+ ScCompiler aComp( pDoc, aPos );
+ aComp.SetCompileEnglish(bEnglish);
+ pCode = aComp.CompileString( rSymbol );
+ if( !pCode->GetError() )
+ {
+ pCode->Reset();
+ ScToken* p = pCode->GetNextReference();
+ if( p )// genau eine Referenz als erstes
+ {
+ if( p->GetType() == svSingleRef )
+ eType = eType | RT_ABSPOS;
+ else
+ eType = eType | RT_ABSAREA;
+ }
+ // ggf. den Fehlercode wg. unvollstaendiger Formel setzen!
+ // Dies ist fuer die manuelle Eingabe
+ aComp.CompileTokenArray();
+ pCode->DelRPN();
+ }
+ }
+}
+
+ScRangeData::ScRangeData( ScDocument* pDok,
+ const String& rName,
+ const ScTokenArray& rArr,
+ USHORT nCol,
+ USHORT nRow,
+ USHORT nTab,
+ RangeType nType ) :
+ aName ( rName ),
+ aPos ( nCol, nRow, nTab ),
+ eType ( nType ),
+ pDoc ( pDok ),
+ nIndex ( 0 ),
+ nExportIndex( 0 ),
+ pCode ( new ScTokenArray( rArr ) ),
+ bModified ( FALSE )
+{
+ if( !pCode->GetError() )
+ {
+ pCode->Reset();
+ ScToken* p = pCode->GetNextReference();
+ if( p )// genau eine Referenz als erstes
+ {
+ if( p->GetType() == svSingleRef )
+ eType = eType | RT_ABSPOS;
+ else
+ eType = eType | RT_ABSAREA;
+ }
+ // Die Importfilter haben diesen Test nicht,
+ // da die benannten Bereiche z.T. noch unvollstaendig sind.
+// if( !pCode->GetCodeLen() )
+// {
+// // ggf. den Fehlercode wg. unvollstaendiger Formel setzen!
+// ScCompiler aComp( pDok, aPos, *pCode );
+// aComp.CompileTokenArray();
+// pCode->DelRPN();
+// }
+ }
+}
+
+ScRangeData::ScRangeData( ScDocument* pDok,
+ const String& rName,
+ const ScAddress& rTarget ) :
+ aName ( rName ),
+ aPos ( rTarget ),
+ eType ( RT_NAME ),
+ pDoc ( pDok ),
+ nIndex ( 0 ),
+ nExportIndex( 0 ),
+ pCode ( new ScTokenArray ),
+ bModified ( FALSE )
+{
+ SingleRefData aRefData;
+ aRefData.InitAddress( rTarget );
+ aRefData.SetFlag3D( TRUE );
+ pCode->AddSingleReference( aRefData );
+ ScCompiler aComp( pDoc, aPos, *pCode );
+ aComp.CompileTokenArray();
+ if ( !pCode->GetError() )
+ eType |= RT_ABSPOS;
+}
+
+ScRangeData::ScRangeData(const ScRangeData& rScRangeData) :
+ aName (rScRangeData.aName),
+ aPos (rScRangeData.aPos),
+ eType (rScRangeData.eType),
+ pDoc (rScRangeData.pDoc),
+ nIndex (rScRangeData.nIndex),
+ pCode (rScRangeData.pCode->Clone()), // echte Kopie erzeugen (nicht copy-ctor)
+ bModified (rScRangeData.bModified)
+{}
+
+ScRangeData::~ScRangeData()
+{
+ delete pCode;
+}
+
+DataObject* ScRangeData::Clone() const
+{
+ return new ScRangeData(*this);
+}
+
+ScRangeData::ScRangeData
+ ( SvStream& rStream, ScMultipleReadHeader& rHdr, USHORT nVer )
+ : pCode ( new ScTokenArray ),
+ bModified (FALSE)
+
+{
+ rHdr.StartEntry();
+
+ if( nVer >= SC_NEW_TOKEN_ARRAYS )
+ {
+ UINT32 nPos;
+ BYTE nData;
+ rStream.ReadByteString( aName, rStream.GetStreamCharSet() );
+ rStream >> nPos >> eType >> nIndex >> nData;
+ if( nData & 0x0F )
+ rStream.SeekRel( nData & 0x0F );
+ aPos = ScAddress( nPos );
+ pCode->Load( rStream, nVer, aPos );
+ }
+ else
+ {
+ UINT16 nTokLen, r, c, t;
+ rStream.ReadByteString( aName, rStream.GetStreamCharSet() );
+ rStream >> c >> r >> t >> eType >> nIndex >> nTokLen;
+ aPos.Set( c, r, t );
+ if( nTokLen )
+ pCode->Load30( rStream, aPos );
+ }
+
+ rHdr.EndEntry();
+}
+
+BOOL ScRangeData::Store
+ ( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const
+{
+ rHdr.StartEntry();
+
+ rStream.WriteByteString( aName, rStream.GetStreamCharSet() );
+ rStream << (UINT32) aPos << eType << nIndex << (BYTE) 0x00;
+ pCode->Store( rStream, aPos );
+
+ rHdr.EndEntry();
+ return TRUE;
+}
+
+BOOL ScRangeData::IsBeyond( USHORT nMaxRow ) const
+{
+ if ( aPos.Row() > nMaxRow )
+ return TRUE;
+
+ ScToken* t;
+ pCode->Reset();
+ while ( t = pCode->GetNextReference() )
+ if ( t->aRef.Ref1.nRow > nMaxRow || t->aRef.Ref2.nRow > nMaxRow )
+ return TRUE;
+
+ return FALSE;
+}
+
+void ScRangeData::GuessPosition()
+{
+ // setzt eine Position, mit der alle relative Referenzen bei CalcAbsIfRel
+ // ohne Fehler verabsolutiert werden koennen
+
+ DBG_ASSERT(aPos == ScAddress(), "die Position geht jetzt verloren");
+
+ INT16 nMinCol = 0;
+ INT16 nMinRow = 0;
+ INT16 nMinTab = 0;
+
+ ScToken* t;
+ pCode->Reset();
+ while ( t = pCode->GetNextReference() )
+ {
+ ComplRefData& rRef = t->aRef;
+
+ if ( rRef.Ref1.IsColRel() && rRef.Ref1.nRelCol < nMinCol )
+ nMinCol = rRef.Ref1.nRelCol;
+ if ( rRef.Ref1.IsRowRel() && rRef.Ref1.nRelRow < nMinRow )
+ nMinRow = rRef.Ref1.nRelRow;
+ if ( rRef.Ref1.IsTabRel() && rRef.Ref1.nRelTab < nMinTab )
+ nMinTab = rRef.Ref1.nRelTab;
+
+ if ( t->GetType() == svDoubleRef )
+ {
+ if ( rRef.Ref2.IsColRel() && rRef.Ref2.nRelCol < nMinCol )
+ nMinCol = rRef.Ref2.nRelCol;
+ if ( rRef.Ref2.IsRowRel() && rRef.Ref2.nRelRow < nMinRow )
+ nMinRow = rRef.Ref2.nRelRow;
+ if ( rRef.Ref2.IsTabRel() && rRef.Ref2.nRelTab < nMinTab )
+ nMinTab = rRef.Ref2.nRelTab;
+ }
+ }
+
+ aPos = ScAddress( (USHORT)(-nMinCol), (USHORT)(-nMinRow), (USHORT)(-nMinTab) );
+
+ //! Test
+// DBG_ERROR(String("Pos ")+String((USHORT)(-nMinCol))+String("/")+
+// String((USHORT)(-nMinRow))+String("/")+String((USHORT)(-nMinTab)));
+}
+
+void ScRangeData::GetSymbol (String& rSymbol) const
+{
+ ScCompiler aScComp(pDoc, aPos, *pCode);
+ aScComp.CreateStringFromTokenArray( rSymbol );
+}
+
+void ScRangeData::GetEnglishSymbol (String& rSymbol, BOOL bCompileXML) const
+{
+ ScCompiler aScComp(pDoc, aPos, *pCode);
+ aScComp.SetCompileEnglish( TRUE );
+ aScComp.SetCompileXML( bCompileXML );
+ aScComp.CreateStringFromTokenArray( rSymbol );
+}
+
+void ScRangeData::UpdateSymbol( String& rSymbol, const ScAddress& rPos )
+{
+ ScTokenArray* pTemp = pCode->Clone();
+ ScCompiler aComp( pDoc, rPos, *pTemp );
+ aComp.MoveRelWrap();
+ aComp.CreateStringFromTokenArray( rSymbol );
+ delete pTemp;
+}
+
+void ScRangeData::UpdateReference( UpdateRefMode eUpdateRefMode,
+ const ScRange& r,
+ short nDx, short nDy, short nDz )
+{
+ BOOL bChanged = FALSE;
+
+ pCode->Reset();
+ if( pCode->GetNextReference() )
+ {
+ ScCompiler aComp( pDoc, aPos, *pCode );
+ BOOL bRelRef = aComp.UpdateNameReference( eUpdateRefMode, r,
+ nDx, nDy, nDz,
+ bChanged);
+ if (eType&RT_SHARED)
+ {
+ if (bRelRef)
+ eType = eType | RT_SHAREDMOD;
+ else
+ eType = eType & ~RT_SHAREDMOD;
+ }
+ }
+
+ bModified = bChanged;
+}
+
+
+void ScRangeData::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest )
+{
+ BOOL bChanged = FALSE;
+
+ ScToken* t;
+ pCode->Reset();
+
+ for( t = pCode->GetNextReference(); t; t = pCode->GetNextReference() )
+ {
+ if( t->GetType() != svIndex )
+ {
+ ComplRefData& rRef = t->GetReference();
+ if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() &&
+ (!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) &&
+ ( t->GetType() == svSingleRef ||
+ (!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() &&
+ (!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel()))))
+ {
+ if ( ScRefUpdate::UpdateTranspose( pDoc, rSource, rDest, t->aRef ) != UR_NOTHING )
+ bChanged = TRUE;
+ }
+ }
+ }
+
+ bModified = bChanged;
+}
+
+void ScRangeData::UpdateGrow( const ScRange& rArea, USHORT nGrowX, USHORT nGrowY )
+{
+ BOOL bChanged = FALSE;
+
+ ScToken* t;
+ pCode->Reset();
+
+ for( t = pCode->GetNextReference(); t; t = pCode->GetNextReference() )
+ {
+ if( t->GetType() != svIndex )
+ {
+ ComplRefData& rRef = t->GetReference();
+ if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() &&
+ (!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) &&
+ ( t->GetType() == svSingleRef ||
+ (!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() &&
+ (!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel()))))
+ {
+ if ( ScRefUpdate::UpdateGrow( rArea,nGrowX,nGrowY, t->aRef ) != UR_NOTHING )
+ bChanged = TRUE;
+ }
+ }
+ }
+
+ bModified = bChanged; // muss direkt hinterher ausgewertet werden
+}
+
+BOOL ScRangeData::operator== (const ScRangeData& rData) const // fuer Undo
+{
+ if ( nIndex != rData.nIndex ||
+ aName != rData.aName ||
+ aPos != rData.aPos ||
+ eType != rData.eType ) return FALSE;
+
+ USHORT nLen = pCode->GetLen();
+ if ( nLen != rData.pCode->GetLen() ) return FALSE;
+
+ ScToken** ppThis = pCode->GetArray();
+ ScToken** ppOther = rData.pCode->GetArray();
+
+ for ( USHORT i=0; i<nLen; i++ )
+ if ( ppThis[i] != ppOther[i] && !(*ppThis[i] == *ppOther[i]) )
+ return FALSE;
+
+ return TRUE;
+}
+
+BOOL ScRangeData::IsRangeAtCursor( const ScAddress& rPos, BOOL bStartOnly ) const
+{
+ BOOL bRet = FALSE;
+ ScRange aRange;
+ if ( IsReference(aRange) )
+ {
+ if ( bStartOnly )
+ bRet = ( rPos == aRange.aStart );
+ else
+ bRet = ( aRange.In( rPos ) );
+ }
+ return bRet;
+}
+
+BOOL ScRangeData::IsRangeAtBlock( const ScRange& rBlock ) const
+{
+ BOOL bRet = FALSE;
+ ScRange aRange;
+ if ( IsReference(aRange) )
+ bRet = ( rBlock == aRange );
+ return bRet;
+}
+
+BOOL ScRangeData::IsReference( ScRange& rRange ) const
+{
+ BOOL bIs = FALSE;
+ if ( eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS ) )
+ if ( pCode )
+ return pCode->IsReference( rRange );
+
+ return bIs;
+}
+
+void ScRangeData::UpdateTabRef(USHORT nOldTable, USHORT nFlag, USHORT nNewTable)
+{
+ pCode->Reset();
+ if( pCode->GetNextReference() )
+ {
+ ScRangeData* pRangeData; // darf nicht dereferenziert werden!!
+ BOOL bChanged;
+ ScCompiler aComp( pDoc, aPos, *pCode );
+ switch (nFlag)
+ {
+ case 1: // einfache InsertTab (doc.cxx)
+ pRangeData = aComp.UpdateInsertTab(nOldTable, TRUE ); // und CopyTab (doc2.cxx)
+ break;
+ case 2: // einfaches delete (doc.cxx)
+ pRangeData = aComp.UpdateDeleteTab(nOldTable, FALSE, TRUE, bChanged);
+ break;
+ case 3: // move (doc2.cxx)
+ {
+ pRangeData = aComp.UpdateMoveTab(nOldTable, nNewTable, TRUE );
+ }
+ break;
+ default:
+ {
+ DBG_ERROR("ScRangeName::UpdateTabRef: Unknown Flag");
+ }
+ break;
+ }
+ if (eType&RT_SHARED)
+ {
+ if (pRangeData)
+ eType = eType | RT_SHAREDMOD;
+ else
+ eType = eType & ~RT_SHAREDMOD;
+ }
+ }
+}
+
+// wie beim Uebernehmen von Namen in Excel
+
+void ScRangeData::MakeValidName( String& rName ) // static
+{
+ if (!ScCompiler::HasCharTable())
+ ScCompiler::Init();
+
+ // ungueltige Zeichen vorne weglassen
+ xub_StrLen nPos = 0;
+ xub_StrLen nLen = rName.Len();
+ while ( nPos < nLen && !ScCompiler::IsWordChar( rName.GetChar(nPos) ) )
+ ++nPos;
+ if ( nPos>0 )
+ rName.Erase(0,nPos);
+
+ // wenn vorne ein ungueltiges Anfangszeichen steht, '_' davor
+ if ( rName.Len() && !ScCompiler::IsCharWordChar( rName.GetChar(0) ) )
+ rName.Insert('_',0);
+
+ // ungueltige durch '_' ersetzen
+ nLen = rName.Len();
+ for (nPos=0; nPos<nLen; nPos++)
+ {
+ if ( !ScCompiler::IsWordChar( rName.GetChar(nPos) ) )
+ rName.SetChar( nPos, '_' );
+ }
+
+ // Name darf keine Referenz beinhalten, wie in IsNameValid
+ BOOL bOk;
+ do
+ {
+ bOk = TRUE;
+ ScRange aRange;
+ if( aRange.Parse( rName, NULL ) )
+ bOk = FALSE;
+ else
+ {
+ ScAddress aAddr;
+ if ( aAddr.Parse( rName, NULL ) )
+ bOk = FALSE;
+ }
+ if ( !bOk )
+ { //! Range Parse auch bei Bereich mit ungueltigem Tabellennamen gueltig
+ //! Address Parse dito, Name erzeugt deswegen bei Compile ein #REF!
+ if ( rName.SearchAndReplace( ':', '_' ) == STRING_NOTFOUND
+ && rName.SearchAndReplace( '.', '_' ) == STRING_NOTFOUND )
+ rName.Insert('_',0);
+ }
+ } while ( !bOk );
+}
+
+BOOL ScRangeData::IsNameValid( const String& rName, ScDocument* pDoc )
+{
+ xub_StrLen nPos = 0;
+ xub_StrLen nLen = rName.Len();
+ if ( !nLen || !ScCompiler::IsCharWordChar( rName.GetChar(nPos++) ) )
+ return FALSE;
+ while ( nPos < nLen )
+ {
+ if ( !ScCompiler::IsWordChar( rName.GetChar(nPos++) ) )
+ return FALSE;
+ }
+ // Parse nicht auf VALID pruefen, es reicht, wenn irgendein Bestandteil
+ // erkannt wurde
+ ScRange aRange;
+ if( aRange.Parse( rName, pDoc ) )
+ return FALSE;
+ else
+ {
+ ScAddress aAddr;
+ if ( aAddr.Parse( rName, pDoc ) )
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+USHORT ScRangeData::GetErrCode()
+{
+ return pCode ? pCode->GetError() : 0;
+}
+
+BOOL ScRangeData::HasReferences() const
+{
+ pCode->Reset();
+ return BOOL( pCode->GetNextReference() != NULL );
+}
+
+// bei TransferTab von einem in ein anderes Dokument anpassen,
+// um Referenzen auf die eigene Tabelle mitzubekommen
+
+void ScRangeData::TransferTabRef( USHORT nOldTab, USHORT nNewTab )
+{
+ short nTabDiff = nNewTab - nOldTab;
+ short nPosDiff = nNewTab - aPos.Tab();
+ aPos.SetTab( nNewTab );
+ ScToken* t;
+ pCode->Reset();
+ while ( t = pCode->GetNextReference() )
+ {
+ if ( t->aRef.Ref1.IsTabRel() )
+ t->aRef.Ref1.nTab += nPosDiff;
+ else
+ t->aRef.Ref1.nTab += nTabDiff;
+ if ( t->aRef.Ref2.IsTabRel() )
+ t->aRef.Ref2.nTab += nPosDiff;
+ else
+ t->aRef.Ref2.nTab += nTabDiff;
+ }
+}
+
+
+void ScRangeData::ReplaceRangeNamesInUse( const ScIndexMap& rMap )
+{
+ BOOL bCompile = FALSE;
+ for ( ScToken* p = pCode->First(); p; p = pCode->Next() )
+ {
+ if ( p->GetOpCode() == ocName )
+ {
+ USHORT nNewIndex = rMap.Find( p->nIndex );
+ if ( p->nIndex != nNewIndex )
+ {
+ p->nIndex = nNewIndex;
+ bCompile = TRUE;
+ }
+ }
+ }
+ if ( bCompile )
+ {
+ ScCompiler aComp( pDoc, aPos, *pCode );
+ aComp.CompileTokenArray();
+ }
+}
+
+
+int
+#ifdef WNT
+__cdecl
+#endif
+ScRangeData::QsortNameCompare( const void* p1, const void* p2 )
+{
+ switch ( ScGlobal::pScInternational->Compare(
+ (*(const ScRangeData**)p1)->aName,
+ (*(const ScRangeData**)p2)->aName, INTN_COMPARE_IGNORECASE ) )
+ {
+ case COMPARE_LESS:
+ return -1;
+ break;
+ case COMPARE_GREATER:
+ return 1;
+ break;
+ default:
+ return 0;
+ }
+}
+
+
+//========================================================================
+// ScRangeName
+//========================================================================
+
+ScRangeName::ScRangeName(const ScRangeName& rScRangeName, ScDocument* pDocument) :
+ SortedCollection ( rScRangeName ),
+ pDoc ( pDocument ),
+ nSharedMaxIndex (rScRangeName.nSharedMaxIndex)
+{
+ for (USHORT i = 0; i < nCount; i++)
+ {
+ ((ScRangeData*)At(i))->SetDocument(pDocument);
+ ((ScRangeData*)At(i))->SetIndex(((ScRangeData*)rScRangeName.At(i))->GetIndex());
+ }
+}
+
+short ScRangeName::Compare(DataObject* pKey1, DataObject* pKey2) const
+{
+ USHORT i1 = ((ScRangeData*)pKey1)->GetIndex();
+ USHORT i2 = ((ScRangeData*)pKey2)->GetIndex();
+ return (short) i1 - (short) i2;
+}
+
+BOOL ScRangeName::SearchName( const String& rName, USHORT& rIndex ) const
+{
+ USHORT i = 0;
+ while (i < nCount)
+ {
+ String aName;
+ ((*this)[i])->GetName( aName );
+ if ( ScGlobal::pScInternational->CompareEqual(
+ aName, rName, INTN_COMPARE_IGNORECASE ) )
+ {
+ rIndex = i;
+ return TRUE;
+ }
+ i++;
+ }
+ return FALSE;
+}
+
+BOOL ScRangeName::Load( SvStream& rStream, USHORT nVer )
+{
+ BOOL bSuccess = TRUE;
+ USHORT nNewCount;
+
+ while( nCount > 0 )
+ AtFree(0); // alles loeschen
+
+ ScMultipleReadHeader aHdr( rStream );
+
+ USHORT nDummy;
+ if( nVer >= SC_NEW_TOKEN_ARRAYS )
+ rStream >> nSharedMaxIndex >> nNewCount;
+ else
+ rStream >> nSharedMaxIndex >> nDummy >> nNewCount;
+ for (USHORT i=0; i<nNewCount && bSuccess; i++)
+ {
+ ScRangeData* pData = new ScRangeData( rStream, aHdr, nVer );
+ pData->SetDocument(pDoc);
+ Insert( pData );
+ if( rStream.GetError() != SVSTREAM_OK )
+ bSuccess = FALSE;
+ }
+ return bSuccess;
+}
+
+BOOL ScRangeName::Store( SvStream& rStream ) const
+{
+ ScMultipleWriteHeader aHdr( rStream );
+
+ USHORT i;
+ USHORT nSaveCount = nCount;
+ USHORT nSaveMaxRow = pDoc->GetSrcMaxRow();
+ if ( nSaveMaxRow < MAXROW )
+ {
+ nSaveCount = 0;
+ for (i=0; i<nCount; i++)
+ if ( !((const ScRangeData*)At(i))->IsBeyond(nSaveMaxRow) )
+ ++nSaveCount;
+
+ if ( nSaveCount < nCount )
+ pDoc->SetLostData(); // Warnung ausgeben
+ }
+
+ rStream << nSharedMaxIndex << nSaveCount;
+ BOOL bSuccess = TRUE;
+
+ for (i=0; i<nCount && bSuccess; i++)
+ {
+ const ScRangeData* pRangeData = (const ScRangeData*)At(i);
+ if ( nSaveMaxRow == MAXROW || !pRangeData->IsBeyond(nSaveMaxRow) )
+ bSuccess = pRangeData->Store( rStream, aHdr );
+ }
+
+ return bSuccess;
+}
+
+void ScRangeName::UpdateReference( UpdateRefMode eUpdateRefMode,
+ const ScRange& rRange,
+ short nDx, short nDy, short nDz )
+{
+ for (USHORT i=0; i<nCount; i++)
+ ((ScRangeData*)pItems[i])->UpdateReference(eUpdateRefMode, rRange,
+ nDx, nDy, nDz);
+}
+
+void ScRangeName::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest )
+{
+ for (USHORT i=0; i<nCount; i++)
+ ((ScRangeData*)pItems[i])->UpdateTranspose( rSource, rDest );
+}
+
+void ScRangeName::UpdateGrow( const ScRange& rArea, USHORT nGrowX, USHORT nGrowY )
+{
+ for (USHORT i=0; i<nCount; i++)
+ ((ScRangeData*)pItems[i])->UpdateGrow( rArea, nGrowX, nGrowY );
+}
+
+BOOL ScRangeName::IsEqual(DataObject* pKey1, DataObject* pKey2) const
+{
+ return *(ScRangeData*)pKey1 == *(ScRangeData*)pKey2;
+}
+
+BOOL ScRangeName::Insert(DataObject* pDataObject)
+{
+ if (!((ScRangeData*)pDataObject)->GetIndex()) // schon gesetzt?
+ {
+ ((ScRangeData*)pDataObject)->SetIndex( GetEntryIndex() );
+ }
+
+ return SortedCollection::Insert(pDataObject);
+}
+
+// Suche nach einem freien Index
+
+USHORT ScRangeName::GetEntryIndex()
+{
+ USHORT nLast = 0;
+ for ( USHORT i = 0; i < nCount; i++ )
+ {
+ USHORT nIdx = ((ScRangeData*)pItems[i])->GetIndex();
+ if( nIdx > nLast )
+ {
+ nLast = nIdx;
+ }
+ }
+ return nLast + 1;
+}
+
+ScRangeData* ScRangeName::FindIndex( USHORT nIndex )
+{
+ ScRangeData aDataObj( nIndex );
+ USHORT n;
+ if( Search( &aDataObj, n ) )
+ return (*this)[ n ];
+ else
+ return NULL;
+}
+
+ScRangeData* ScRangeName::GetRangeAtCursor( const ScAddress& rPos, BOOL bStartOnly ) const
+{
+ if ( pItems )
+ {
+ for ( USHORT i = 0; i < nCount; i++ )
+ if ( ((ScRangeData*)pItems[i])->IsRangeAtCursor( rPos, bStartOnly ) )
+ return (ScRangeData*)pItems[i];
+ }
+ return NULL;
+}
+
+ScRangeData* ScRangeName::GetRangeAtBlock( const ScRange& rBlock ) const
+{
+ if ( pItems )
+ {
+ for ( USHORT i = 0; i < nCount; i++ )
+ if ( ((ScRangeData*)pItems[i])->IsRangeAtBlock( rBlock ) )
+ return (ScRangeData*)pItems[i];
+ }
+ return NULL;
+}
+
+void ScRangeName::UpdateTabRef(USHORT nOldTable, USHORT nFlag, USHORT nNewTable)
+{
+ for (USHORT i=0; i<nCount; i++)
+ ((ScRangeData*)pItems[i])->UpdateTabRef(nOldTable, nFlag, nNewTable);
+}
+
+
+
+
diff --git a/sc/source/core/tool/rangeseq.cxx b/sc/source/core/tool/rangeseq.cxx
new file mode 100644
index 000000000000..4b0d956aaea5
--- /dev/null
+++ b/sc/source/core/tool/rangeseq.cxx
@@ -0,0 +1,345 @@
+/*************************************************************************
+ *
+ * $RCSfile: rangeseq.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:18 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include <svtools/zforlist.hxx>
+#include <tools/solmath.hxx>
+
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include "rangeseq.hxx"
+#include "document.hxx"
+#include "scmatrix.hxx"
+
+using namespace com::sun::star;
+
+//------------------------------------------------------------------------
+
+long lcl_DoubleToLong( double fVal )
+{
+ double fInt = (fVal >= 0.0) ? SolarMath::ApproxFloor( fVal ) :
+ SolarMath::ApproxCeil( fVal );
+ if ( fInt >= LONG_MIN && fInt <= LONG_MAX )
+ return (long)fInt;
+ else
+ return 0.0; // out of range
+}
+
+BOOL ScRangeToSequence::FillLongArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
+{
+ USHORT nTab = rRange.aStart.Tab();
+ USHORT nStartCol = rRange.aStart.Col();
+ USHORT nStartRow = rRange.aStart.Row();
+ long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
+ long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();
+
+ uno::Sequence< uno::Sequence<INT32> > aRowSeq( nRowCount );
+ uno::Sequence<INT32>* pRowAry = aRowSeq.getArray();
+ for (long nRow = 0; nRow < nRowCount; nRow++)
+ {
+ uno::Sequence<INT32> aColSeq( nColCount );
+ INT32* pColAry = aColSeq.getArray();
+ for (long nCol = 0; nCol < nColCount; nCol++)
+ pColAry[nCol] = lcl_DoubleToLong( pDoc->GetValue(
+ ScAddress( (USHORT)(nStartCol+nCol), (USHORT)(nStartRow+nRow), nTab ) ) );
+
+ pRowAry[nRow] = aColSeq;
+ }
+
+ rAny <<= aRowSeq;
+ return TRUE; //! check for errors
+}
+
+
+BOOL ScRangeToSequence::FillLongArray( uno::Any& rAny, const ScMatrix* pMatrix )
+{
+ if (!pMatrix)
+ return FALSE;
+
+ USHORT nColCount, nRowCount;
+ pMatrix->GetDimensions( nColCount, nRowCount );
+
+ uno::Sequence< uno::Sequence<INT32> > aRowSeq( nRowCount );
+ uno::Sequence<INT32>* pRowAry = aRowSeq.getArray();
+ for (USHORT nRow = 0; nRow < nRowCount; nRow++)
+ {
+ uno::Sequence<INT32> aColSeq( nColCount );
+ INT32* pColAry = aColSeq.getArray();
+ for (USHORT nCol = 0; nCol < nColCount; nCol++)
+ if ( pMatrix->IsString( nCol, nRow ) )
+ pColAry[nCol] = 0;
+ else
+ pColAry[nCol] = lcl_DoubleToLong( pMatrix->GetDouble( nCol, nRow ) );
+
+ pRowAry[nRow] = aColSeq;
+ }
+
+ rAny <<= aRowSeq;
+ return TRUE;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScRangeToSequence::FillDoubleArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
+{
+ USHORT nTab = rRange.aStart.Tab();
+ USHORT nStartCol = rRange.aStart.Col();
+ USHORT nStartRow = rRange.aStart.Row();
+ long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
+ long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();
+
+ uno::Sequence< uno::Sequence<double> > aRowSeq( nRowCount );
+ uno::Sequence<double>* pRowAry = aRowSeq.getArray();
+ for (long nRow = 0; nRow < nRowCount; nRow++)
+ {
+ uno::Sequence<double> aColSeq( nColCount );
+ double* pColAry = aColSeq.getArray();
+ for (long nCol = 0; nCol < nColCount; nCol++)
+ pColAry[nCol] = pDoc->GetValue(
+ ScAddress( (USHORT)(nStartCol+nCol), (USHORT)(nStartRow+nRow), nTab ) );
+
+ pRowAry[nRow] = aColSeq;
+ }
+
+ rAny <<= aRowSeq;
+ return TRUE; //! check for errors
+}
+
+
+BOOL ScRangeToSequence::FillDoubleArray( uno::Any& rAny, const ScMatrix* pMatrix )
+{
+ if (!pMatrix)
+ return FALSE;
+
+ USHORT nColCount, nRowCount;
+ pMatrix->GetDimensions( nColCount, nRowCount );
+
+ uno::Sequence< uno::Sequence<double> > aRowSeq( nRowCount );
+ uno::Sequence<double>* pRowAry = aRowSeq.getArray();
+ for (USHORT nRow = 0; nRow < nRowCount; nRow++)
+ {
+ uno::Sequence<double> aColSeq( nColCount );
+ double* pColAry = aColSeq.getArray();
+ for (USHORT nCol = 0; nCol < nColCount; nCol++)
+ if ( pMatrix->IsString( nCol, nRow ) )
+ pColAry[nCol] = 0.0;
+ else
+ pColAry[nCol] = pMatrix->GetDouble( nCol, nRow );
+
+ pRowAry[nRow] = aColSeq;
+ }
+
+ rAny <<= aRowSeq;
+ return TRUE;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScRangeToSequence::FillStringArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
+{
+ USHORT nTab = rRange.aStart.Tab();
+ USHORT nStartCol = rRange.aStart.Col();
+ USHORT nStartRow = rRange.aStart.Row();
+ long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
+ long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();
+
+ String aDocStr;
+
+ uno::Sequence< uno::Sequence<rtl::OUString> > aRowSeq( nRowCount );
+ uno::Sequence<rtl::OUString>* pRowAry = aRowSeq.getArray();
+ for (long nRow = 0; nRow < nRowCount; nRow++)
+ {
+ uno::Sequence<rtl::OUString> aColSeq( nColCount );
+ rtl::OUString* pColAry = aColSeq.getArray();
+ for (long nCol = 0; nCol < nColCount; nCol++)
+ {
+ pDoc->GetString( (USHORT)(nStartCol+nCol), (USHORT)(nStartRow+nRow), nTab, aDocStr );
+ pColAry[nCol] = rtl::OUString( aDocStr );
+ }
+ pRowAry[nRow] = aColSeq;
+ }
+
+ rAny <<= aRowSeq;
+ return TRUE; //! check for errors
+}
+
+
+BOOL ScRangeToSequence::FillStringArray( uno::Any& rAny, const ScMatrix* pMatrix,
+ SvNumberFormatter* pFormatter )
+{
+ if (!pMatrix)
+ return FALSE;
+
+ USHORT nColCount, nRowCount;
+ pMatrix->GetDimensions( nColCount, nRowCount );
+
+ uno::Sequence< uno::Sequence<rtl::OUString> > aRowSeq( nRowCount );
+ uno::Sequence<rtl::OUString>* pRowAry = aRowSeq.getArray();
+ for (USHORT nRow = 0; nRow < nRowCount; nRow++)
+ {
+ uno::Sequence<rtl::OUString> aColSeq( nColCount );
+ rtl::OUString* pColAry = aColSeq.getArray();
+ for (USHORT nCol = 0; nCol < nColCount; nCol++)
+ {
+ String aStr;
+ if ( pMatrix->IsString( nCol, nRow ) )
+ {
+ if ( !pMatrix->IsEmpty( nCol, nRow ) )
+ aStr = pMatrix->GetString( nCol, nRow );
+ }
+ else if ( pFormatter )
+ {
+ double fVal = pMatrix->GetDouble( nCol, nRow );
+ Color* pColor;
+ pFormatter->GetOutputString( fVal, 0, aStr, &pColor );
+ }
+ pColAry[nCol] = rtl::OUString( aStr );
+ }
+
+ pRowAry[nRow] = aColSeq;
+ }
+
+ rAny <<= aRowSeq;
+ return TRUE;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScRangeToSequence::FillMixedArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
+{
+ USHORT nTab = rRange.aStart.Tab();
+ USHORT nStartCol = rRange.aStart.Col();
+ USHORT nStartRow = rRange.aStart.Row();
+ long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
+ long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();
+
+ String aDocStr;
+
+ uno::Sequence< uno::Sequence<uno::Any> > aRowSeq( nRowCount );
+ uno::Sequence<uno::Any>* pRowAry = aRowSeq.getArray();
+ for (long nRow = 0; nRow < nRowCount; nRow++)
+ {
+ uno::Sequence<uno::Any> aColSeq( nColCount );
+ uno::Any* pColAry = aColSeq.getArray();
+ for (long nCol = 0; nCol < nColCount; nCol++)
+ {
+ if ( pDoc->HasValueData( (USHORT)(nStartCol+nCol), (USHORT)(nStartRow+nRow), nTab ) )
+ pColAry[nCol] <<= (double) pDoc->GetValue(
+ ScAddress( (USHORT)(nStartCol+nCol), (USHORT)(nStartRow+nRow), nTab ) );
+ else
+ {
+ pDoc->GetString( (USHORT)(nStartCol+nCol), (USHORT)(nStartRow+nRow), nTab, aDocStr );
+ pColAry[nCol] <<= rtl::OUString( aDocStr );
+ }
+ }
+ pRowAry[nRow] = aColSeq;
+ }
+
+ rAny <<= aRowSeq;
+ return TRUE; //! check for errors
+}
+
+
+BOOL ScRangeToSequence::FillMixedArray( uno::Any& rAny, const ScMatrix* pMatrix )
+{
+ if (!pMatrix)
+ return FALSE;
+
+ USHORT nColCount, nRowCount;
+ pMatrix->GetDimensions( nColCount, nRowCount );
+
+ uno::Sequence< uno::Sequence<uno::Any> > aRowSeq( nRowCount );
+ uno::Sequence<uno::Any>* pRowAry = aRowSeq.getArray();
+ for (USHORT nRow = 0; nRow < nRowCount; nRow++)
+ {
+ uno::Sequence<uno::Any> aColSeq( nColCount );
+ uno::Any* pColAry = aColSeq.getArray();
+ for (USHORT nCol = 0; nCol < nColCount; nCol++)
+ {
+ if ( pMatrix->IsString( nCol, nRow ) )
+ {
+ String aStr;
+ if ( !pMatrix->IsEmpty( nCol, nRow ) )
+ aStr = pMatrix->GetString( nCol, nRow );
+ pColAry[nCol] <<= rtl::OUString( aStr );
+ }
+ else
+ pColAry[nCol] <<= (double) pMatrix->GetDouble( nCol, nRow );
+ }
+
+ pRowAry[nRow] = aColSeq;
+ }
+
+ rAny <<= aRowSeq;
+ return TRUE;
+}
+
+
+//------------------------------------------------------------------------
+
+
+
diff --git a/sc/source/core/tool/rangeutl.cxx b/sc/source/core/tool/rangeutl.cxx
new file mode 100644
index 000000000000..50da4c7de519
--- /dev/null
+++ b/sc/source/core/tool/rangeutl.cxx
@@ -0,0 +1,568 @@
+/*************************************************************************
+ *
+ * $RCSfile: rangeutl.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:18 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <tools/debug.hxx>
+
+#include "rangeutl.hxx"
+#include "document.hxx"
+#include "global.hxx"
+#include "dbcolect.hxx"
+#include "rangenam.hxx"
+#include "scresid.hxx"
+#include "globstr.hrc"
+
+
+//------------------------------------------------------------------------
+
+BOOL ScRangeUtil::MakeArea( const String& rAreaStr,
+ ScArea& rArea,
+ ScDocument* pDoc,
+ USHORT nTab ) const
+{
+ // Eingabe in rAreaStr: "$Tabelle1.$A1:$D17"
+
+ BOOL nSuccess = FALSE;
+ USHORT nPointPos = rAreaStr.Search('.');
+ USHORT nColonPos = rAreaStr.Search(':');
+ String aStrArea( rAreaStr );
+ ScRefTripel startPos;
+ ScRefTripel endPos;
+
+ if ( nColonPos == STRING_NOTFOUND )
+ if ( nPointPos != STRING_NOTFOUND )
+ {
+ aStrArea += ':';
+ aStrArea += rAreaStr.Copy( nPointPos+1 ); // '.' nicht mitkopieren
+ }
+
+ nSuccess = ConvertDoubleRef( pDoc, aStrArea, nTab, startPos, endPos );
+
+ if ( nSuccess )
+ rArea = ScArea( startPos.GetTab(),
+ startPos.GetCol(), startPos.GetRow(),
+ endPos.GetCol(), endPos.GetRow() );
+
+ return nSuccess;
+}
+
+//------------------------------------------------------------------------
+
+void ScRangeUtil::MakeAreaString( const ScArea& rArea,
+ String& rAreaStr,
+ ScDocument* pDoc,
+ BOOL bRel ) const
+{
+ /*
+ * => z.B. "$Tabelle1.$A1:$D17"
+ */
+
+ DBG_ASSERT( pDoc, "Kein Dokument uebergeben!" );
+ if ( !pDoc )
+ return;
+
+ rAreaStr = ScRefTripel( rArea.nColStart,
+ rArea.nRowStart,
+ rArea.nTab,
+ bRel, bRel, bRel ).GetRefString( pDoc,
+ MAXTAB+1 );
+ if ( (rArea.nColStart != rArea.nColEnd)
+ || (rArea.nRowStart != rArea.nRowEnd) )
+ {
+ rAreaStr += ':';
+ rAreaStr += ScRefTripel( rArea.nColEnd,
+ rArea.nRowEnd,
+ rArea.nTab,
+ bRel, bRel, bRel ).GetRefString( pDoc,
+ rArea.nTab );
+ }
+}
+
+//------------------------------------------------------------------------
+
+void ScRangeUtil::MakeTabAreaString( const ScTripel& rAreaStart,
+ const ScTripel& rAreaEnd,
+ String& rAreaStr,
+ ScDocument* pDoc ) const
+{
+ DBG_ASSERT( pDoc, "Kein Dokument uebergeben!" );
+ if ( !pDoc )
+ return;
+
+ /*
+ * => z.B. "$Tabelle1.$A1:$Tabelle1.$D17"
+ */
+
+ USHORT nStartTab = rAreaStart.GetTab();
+ USHORT nEndTab = rAreaEnd.GetTab();
+
+ if ( nStartTab == nEndTab )
+ {
+ ScArea aArea( nStartTab,
+ rAreaStart.GetCol(), rAreaStart.GetRow(),
+ rAreaEnd.GetCol(), rAreaEnd.GetRow() );
+
+ MakeAreaString( aArea, rAreaStr, pDoc );
+ }
+ else
+ {
+ rAreaStr = ScRefTripel( rAreaStart.GetCol(),
+ rAreaStart.GetRow(),
+ nStartTab,
+ FALSE, FALSE, FALSE ).GetRefString( pDoc,
+ MAXTAB+1 );
+ rAreaStr += ':';
+ rAreaStr += ScRefTripel( rAreaEnd.GetCol(),
+ rAreaEnd.GetRow(),
+ nEndTab,
+ FALSE, FALSE, FALSE ).GetRefString( pDoc,
+ MAXTAB+1 );
+ }
+}
+
+//------------------------------------------------------------------------
+
+void ScRangeUtil::CutPosString( const String& theAreaStr,
+ String& thePosStr ) const
+{
+ String aPosStr;
+ USHORT nColonPos = theAreaStr.Search(':');
+
+ if ( nColonPos != STRING_NOTFOUND )
+ aPosStr = theAreaStr.Copy( 0, nColonPos ); // ':' nicht mitkopieren
+ else
+ aPosStr = theAreaStr;
+
+ thePosStr = aPosStr;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScRangeUtil::IsAbsTabArea( const String& rAreaStr,
+ ScDocument* pDoc,
+ ScArea*** pppAreas,
+ USHORT* pAreaCount ) const
+{
+ DBG_ASSERT( pDoc, "Kein Dokument uebergeben!" );
+ if ( !pDoc )
+ return FALSE;
+
+ /*
+ * Erwartet wird ein String der Form
+ * "$Tabelle1.$A$1:$Tabelle3.$D$17"
+ *
+ * als Ergebnis wird ein ScArea-Array angelegt,
+ * welches ueber ppAreas bekannt gegeben wird und auch
+ * wieder geloescht werden muss!
+ */
+
+ BOOL bStrOk = FALSE;
+ String aStartPosStr;
+ String aEndPosStr;
+
+ USHORT nColonPos = rAreaStr.Search(':');
+
+ if ( STRING_NOTFOUND != nColonPos
+ && STRING_NOTFOUND != rAreaStr.Search('.') )
+ {
+ ScRefTripel aStartPos;
+ ScRefTripel aEndPos;
+
+ aStartPosStr = rAreaStr.Copy( 0, nColonPos );
+ aEndPosStr = rAreaStr.Copy( nColonPos+1, STRING_LEN );
+
+ if ( ConvertSingleRef( pDoc, aStartPosStr, 0, aStartPos ) )
+ {
+ if ( ConvertSingleRef( pDoc, aEndPosStr, aStartPos.GetTab(), aEndPos ) )
+ {
+ aStartPos.SetRelCol( FALSE );
+ aStartPos.SetRelRow( FALSE );
+ aStartPos.SetRelTab( FALSE );
+ aEndPos.SetRelCol( FALSE );
+ aEndPos.SetRelRow( FALSE );
+ aEndPos.SetRelTab( FALSE );
+
+ bStrOk = TRUE;
+
+ if ( pppAreas && pAreaCount ) // Array zurueckgegeben?
+ {
+ USHORT nStartTab = aStartPos.GetTab();
+ USHORT nEndTab = aEndPos.GetTab();
+ USHORT nTabCount = nEndTab-nStartTab+1;
+ ScArea** theAreas = new ScArea*[nTabCount];
+ USHORT nTab = 0;
+ USHORT i = 0;
+ ScArea theArea( 0, aStartPos.GetCol(), aStartPos.GetRow(),
+ aEndPos.GetCol(), aEndPos.GetRow() );
+
+ nTab = nStartTab;
+ for ( i=0; i<nTabCount; i++ )
+ {
+ theAreas[i] = new ScArea( theArea );
+ theAreas[i]->nTab = nTab;
+ nTab++;
+ }
+ *pppAreas = theAreas;
+ *pAreaCount = nTabCount;
+ }
+ }
+ }
+ }
+
+ return bStrOk;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScRangeUtil::IsAbsArea( const String& rAreaStr,
+ ScDocument* pDoc,
+ USHORT nTab,
+ String* pCompleteStr,
+ ScRefTripel* pStartPos,
+ ScRefTripel* pEndPos ) const
+{
+ BOOL bIsAbsArea = FALSE;
+ ScRefTripel startPos;
+ ScRefTripel endPos;
+
+ bIsAbsArea = ConvertDoubleRef( pDoc, rAreaStr, nTab, startPos, endPos );
+
+ if ( bIsAbsArea )
+ {
+ startPos.SetRelCol( FALSE );
+ startPos.SetRelRow( FALSE );
+ startPos.SetRelTab( FALSE );
+ endPos .SetRelCol( FALSE );
+ endPos .SetRelRow( FALSE );
+ endPos .SetRelTab( FALSE );
+
+ if ( pCompleteStr )
+ {
+ *pCompleteStr = startPos.GetRefString( pDoc, MAXTAB+1 );
+ *pCompleteStr += ':';
+ *pCompleteStr += endPos .GetRefString( pDoc, nTab );
+ }
+
+ if ( pStartPos && pEndPos )
+ {
+ *pStartPos = startPos;
+ *pEndPos = endPos;
+ }
+ }
+
+ return bIsAbsArea;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScRangeUtil::IsAbsPos( const String& rPosStr,
+ ScDocument* pDoc,
+ USHORT nTab,
+ String* pCompleteStr,
+ ScRefTripel* pPosTripel ) const
+{
+ BOOL bIsAbsPos = FALSE;
+ ScRefTripel thePos;
+
+ bIsAbsPos = ConvertSingleRef( pDoc, rPosStr, nTab, thePos );
+
+ thePos.SetRelCol( FALSE );
+ thePos.SetRelRow( FALSE );
+ thePos.SetRelTab( FALSE );
+
+ if ( bIsAbsPos )
+ {
+ if ( pPosTripel )
+ *pPosTripel = thePos;
+ if ( pCompleteStr )
+ *pCompleteStr = thePos.GetRefString( pDoc, MAXTAB+1 );
+ }
+
+ return bIsAbsPos;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScRangeUtil::MakeRangeFromName (
+ const String& rName,
+ ScDocument* pDoc,
+ USHORT nCurTab,
+ ScRange& rRange,
+ RutlNameScope eScope
+ ) const
+{
+ BOOL bResult=FALSE;
+ ScRangeUtil aRangeUtil;
+ USHORT nTab, nColStart, nColEnd, nRowStart, nRowEnd;
+
+ if( eScope==RUTL_NAMES )
+ {
+ ScRangeName& rRangeNames = *(pDoc->GetRangeName());
+ USHORT nAt = 0;
+
+ if ( rRangeNames.SearchName( rName, nAt ) )
+ {
+ ScRangeData* pData = rRangeNames[nAt];
+ String aStrArea;
+ ScRefTripel aStartPos;
+ ScRefTripel aEndPos;
+
+ pData->GetSymbol( aStrArea );
+
+ if ( IsAbsArea( aStrArea, pDoc, nCurTab,
+ NULL, &aStartPos, &aEndPos ) )
+ {
+ nTab = aStartPos.GetTab();
+ nColStart = aStartPos.GetCol();
+ nRowStart = aStartPos.GetRow();
+ nColEnd = aEndPos.GetCol();
+ nRowEnd = aEndPos.GetRow();
+ bResult = TRUE;
+ }
+ else
+ {
+ CutPosString( aStrArea, aStrArea );
+
+ if ( IsAbsPos( aStrArea, pDoc, nCurTab,
+ NULL, &aStartPos ) )
+ {
+ nTab = aStartPos.GetTab();
+ nColStart = nColEnd = aStartPos.GetCol();
+ nRowStart = nRowEnd = aStartPos.GetRow();
+ bResult = TRUE;
+ }
+ }
+ }
+ }
+ else if( eScope==RUTL_DBASE )
+ {
+ ScDBCollection& rDbNames = *(pDoc->GetDBCollection());
+ USHORT nAt = 0;
+
+ if ( rDbNames.SearchName( rName, nAt ) )
+ {
+ ScDBData* pData = rDbNames[nAt];
+
+ pData->GetArea( nTab, nColStart, nRowStart,
+ nColEnd, nRowEnd );
+ bResult = TRUE;
+ }
+ }
+ else
+ {
+ DBG_ERROR( "ScRangeUtil::MakeRangeFromName" );
+ }
+
+ if( bResult )
+ {
+ rRange = ScRange( nColStart, nRowStart, nTab, nColEnd, nRowEnd, nTab );
+ }
+
+ return bResult;
+}
+
+//========================================================================
+
+ScArea::ScArea( USHORT tab,
+ USHORT colStart, USHORT rowStart,
+ USHORT colEnd, USHORT rowEnd ) :
+ nTab ( tab ),
+ nColStart( colStart ), nRowStart( rowStart ),
+ nColEnd ( colEnd ), nRowEnd ( rowEnd )
+{
+}
+
+//------------------------------------------------------------------------
+
+ScArea::ScArea( const ScArea& r ) :
+ nTab ( r.nTab ),
+ nColStart( r.nColStart ), nRowStart( r.nRowStart ),
+ nColEnd ( r.nColEnd ), nRowEnd ( r.nRowEnd )
+{
+}
+
+//------------------------------------------------------------------------
+
+void ScArea::Clear()
+{
+ nTab =
+ nColStart = nRowStart =
+ nColEnd = nRowEnd = 0;
+}
+
+//------------------------------------------------------------------------
+
+ScArea& ScArea::operator=( const ScArea& r )
+{
+ nTab = r.nTab;
+ nColStart = r.nColStart;
+ nRowStart = r.nRowStart;
+ nColEnd = r.nColEnd;
+ nRowEnd = r.nRowEnd;
+ return *this;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScArea::operator==( const ScArea& r ) const
+{
+ return ( (nTab == r.nTab)
+ && (nColStart == r.nColStart)
+ && (nRowStart == r.nRowStart)
+ && (nColEnd == r.nColEnd)
+ && (nRowEnd == r.nRowEnd) );
+}
+
+//------------------------------------------------------------------------
+
+SvStream& operator>> ( SvStream& rStream, ScArea& rArea )
+{
+ rStream >> rArea.nTab;
+ rStream >> rArea.nColStart;
+ rStream >> rArea.nRowStart;
+ rStream >> rArea.nColEnd;
+ rStream >> rArea.nRowEnd;
+ return rStream;
+}
+
+//------------------------------------------------------------------------
+
+SvStream& operator<< ( SvStream& rStream, const ScArea& rArea )
+{
+ rStream << rArea.nTab;
+ rStream << rArea.nColStart;
+ rStream << rArea.nRowStart;
+ rStream << rArea.nColEnd;
+ rStream << rArea.nRowEnd;
+ return rStream;
+}
+
+//------------------------------------------------------------------------
+
+void ScArea::GetString( String& rStr, BOOL bAbsolute, ScDocument* pDoc ) const
+{
+ ScRange aRange( ScAddress( nColStart, nRowStart, nTab ),
+ ScAddress( nColEnd, nRowEnd, nTab ) );
+ USHORT nFlags = bAbsolute ? SCA_COL_ABSOLUTE | SCA_ROW_ABSOLUTE : 0;
+
+ aRange.Format( rStr, nFlags, pDoc );
+}
+
+//------------------------------------------------------------------------
+
+ScAreaNameIterator::ScAreaNameIterator( ScDocument* pDoc ) :
+ aStrNoName( ScGlobal::GetRscString(STR_DB_NONAME) )
+{
+ pRangeName = pDoc->GetRangeName();
+ pDBCollection = pDoc->GetDBCollection();
+ nPos = 0;
+ bFirstPass = TRUE;
+}
+
+BOOL ScAreaNameIterator::Next( String& rName, ScRange& rRange )
+{
+ for (;;)
+ {
+ if ( bFirstPass ) // erst Bereichsnamen
+ {
+ if ( pRangeName && nPos < pRangeName->GetCount() )
+ {
+ ScRangeData* pData = (*pRangeName)[nPos++];
+ if ( pData && pData->IsReference(rRange) )
+ {
+ rName = pData->GetName();
+ return TRUE; // gefunden
+ }
+ }
+ else
+ {
+ bFirstPass = FALSE;
+ nPos = 0;
+ }
+ }
+ if ( !bFirstPass ) // dann DB-Bereiche
+ {
+ if ( pDBCollection && nPos < pDBCollection->GetCount() )
+ {
+ ScDBData* pData = (*pDBCollection)[nPos++];
+ if (pData && pData->GetName() != aStrNoName)
+ {
+ pData->GetArea( rRange );
+ rName = pData->GetName();
+ return TRUE; // gefunden
+ }
+ }
+ else
+ return FALSE; // gibt nichts mehr
+ }
+ }
+}
+
+
+
+
diff --git a/sc/source/core/tool/rechead.cxx b/sc/source/core/tool/rechead.cxx
new file mode 100644
index 000000000000..07c66ddb771b
--- /dev/null
+++ b/sc/source/core/tool/rechead.cxx
@@ -0,0 +1,264 @@
+/*************************************************************************
+ *
+ * $RCSfile: rechead.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:18 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <tools/debug.hxx>
+
+#include "rechead.hxx"
+#include "scerrors.hxx"
+
+// STATIC DATA -----------------------------------------------------------
+
+// =======================================================================
+
+ScReadHeader::ScReadHeader(SvStream& rNewStream) :
+ rStream( rNewStream )
+{
+ ULONG nDataSize;
+ rStream >> nDataSize;
+ nDataEnd = rStream.Tell() + nDataSize;
+}
+
+ScReadHeader::~ScReadHeader()
+{
+ ULONG nReadEnd = rStream.Tell();
+ DBG_ASSERT( nReadEnd <= nDataEnd, "zuviele Bytes gelesen" );
+ if ( nReadEnd != nDataEnd )
+ {
+ if ( rStream.GetError() == SVSTREAM_OK )
+ rStream.SetError( SCWARN_IMPORT_INFOLOST );
+ rStream.Seek(nDataEnd); // Rest ueberspringen
+ }
+}
+
+ULONG ScReadHeader::BytesLeft() const
+{
+ ULONG nReadEnd = rStream.Tell();
+ if (nReadEnd <= nDataEnd)
+ return nDataEnd-nReadEnd;
+
+ DBG_ERROR("Fehler bei ScReadHeader::BytesLeft");
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+ScWriteHeader::ScWriteHeader(SvStream& rNewStream, ULONG nDefault) :
+ rStream( rNewStream )
+{
+ nDataSize = nDefault;
+ rStream << nDataSize;
+
+ nDataPos = rStream.Tell();
+}
+
+ScWriteHeader::~ScWriteHeader()
+{
+ ULONG nPos = rStream.Tell();
+
+ if ( nPos - nDataPos != nDataSize ) // Default getroffen?
+ {
+ nDataSize = nPos - nDataPos;
+ rStream.Seek(nDataPos - sizeof(ULONG));
+ rStream << nDataSize; // Groesse am Anfang eintragen
+ rStream.Seek(nPos);
+ }
+}
+
+// =======================================================================
+
+ScMultipleReadHeader::ScMultipleReadHeader(SvStream& rNewStream) :
+ rStream( rNewStream )
+{
+ ULONG nDataSize;
+ rStream >> nDataSize;
+ ULONG nDataPos = rStream.Tell();
+ nTotalEnd = nDataPos + nDataSize;
+ nEntryEnd = nTotalEnd;
+
+ rStream.SeekRel(nDataSize);
+ USHORT nID;
+ rStream >> nID;
+ if (nID != SCID_SIZES)
+ {
+ DBG_ERROR("SCID_SIZES nicht gefunden");
+ if ( rStream.GetError() == SVSTREAM_OK )
+ rStream.SetError( SVSTREAM_FILEFORMAT_ERROR );
+
+ // alles auf 0, damit BytesLeft() wenigstens abbricht
+ pBuf = NULL; pMemStream = NULL;
+ nEntryEnd = nDataPos;
+ }
+ else
+ {
+ ULONG nSizeTableLen;
+ rStream >> nSizeTableLen;
+ pBuf = new BYTE[nSizeTableLen];
+ rStream.Read( pBuf, nSizeTableLen );
+ pMemStream = new SvMemoryStream( (char*)pBuf, nSizeTableLen, STREAM_READ );
+ }
+
+ nEndPos = rStream.Tell();
+ rStream.Seek( nDataPos );
+}
+
+ScMultipleReadHeader::~ScMultipleReadHeader()
+{
+ if ( pMemStream && pMemStream->Tell() != pMemStream->GetSize() )
+ {
+ DBG_ERRORFILE( "Sizes nicht vollstaendig gelesen" );
+ if ( rStream.GetError() == SVSTREAM_OK )
+ rStream.SetError( SCWARN_IMPORT_INFOLOST );
+ }
+ delete pMemStream;
+ delete pBuf;
+
+ rStream.Seek(nEndPos);
+}
+
+void ScMultipleReadHeader::EndEntry()
+{
+ ULONG nPos = rStream.Tell();
+ DBG_ASSERT( nPos <= nEntryEnd, "zuviel gelesen" );
+ if ( nPos != nEntryEnd )
+ {
+ if ( rStream.GetError() == SVSTREAM_OK )
+ rStream.SetError( SCWARN_IMPORT_INFOLOST );
+ rStream.Seek( nEntryEnd ); // Rest ueberspringen
+ }
+
+ nEntryEnd = nTotalEnd; // den ganzen Rest, wenn kein StartEntry kommt
+}
+
+void ScMultipleReadHeader::StartEntry()
+{
+ ULONG nPos = rStream.Tell();
+ ULONG nEntrySize;
+ (*pMemStream) >> nEntrySize;
+
+ nEntryEnd = nPos + nEntrySize;
+ DBG_ASSERT( nEntryEnd <= nTotalEnd, "zuviele Eintraege gelesen" );
+}
+
+ULONG ScMultipleReadHeader::BytesLeft() const
+{
+ ULONG nReadEnd = rStream.Tell();
+ if (nReadEnd <= nEntryEnd)
+ return nEntryEnd-nReadEnd;
+
+ DBG_ERROR("Fehler bei ScMultipleReadHeader::BytesLeft");
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+ScMultipleWriteHeader::ScMultipleWriteHeader(SvStream& rNewStream, ULONG nDefault) :
+ rStream( rNewStream ),
+ aMemStream( 4096, 4096 )
+{
+ nDataSize = nDefault;
+ rStream << nDataSize;
+
+ nDataPos = rStream.Tell();
+ nEntryStart = nDataPos;
+}
+
+ScMultipleWriteHeader::~ScMultipleWriteHeader()
+{
+ ULONG nDataEnd = rStream.Tell();
+
+ rStream << (USHORT) SCID_SIZES;
+ rStream << aMemStream.Tell();
+ rStream.Write( aMemStream.GetData(), aMemStream.Tell() );
+
+ if ( nDataEnd - nDataPos != nDataSize ) // Default getroffen?
+ {
+ nDataSize = nDataEnd - nDataPos;
+ ULONG nPos = rStream.Tell();
+ rStream.Seek(nDataPos-sizeof(ULONG));
+ rStream << nDataSize; // Groesse am Anfang eintragen
+ rStream.Seek(nPos);
+ }
+}
+
+void ScMultipleWriteHeader::EndEntry()
+{
+ ULONG nPos = rStream.Tell();
+ aMemStream << nPos - nEntryStart;
+}
+
+void ScMultipleWriteHeader::StartEntry()
+{
+ ULONG nPos = rStream.Tell();
+ nEntryStart = nPos;
+}
+
+
+
+
+
diff --git a/sc/source/core/tool/refdata.cxx b/sc/source/core/tool/refdata.cxx
new file mode 100644
index 000000000000..fb482fb07cb4
--- /dev/null
+++ b/sc/source/core/tool/refdata.cxx
@@ -0,0 +1,377 @@
+/*************************************************************************
+ *
+ * $RCSfile: refdata.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:18 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include <segmentc.hxx>
+
+#include "compiler.hxx"
+
+SEG_EOFGLOBALS()
+
+
+#pragma SEG_FUNCDEF(refdata_01)
+
+void SingleRefData::CalcRelFromAbs( const ScAddress& rPos )
+{
+ nRelCol = nCol - rPos.Col();
+ nRelRow = nRow - rPos.Row();
+ nRelTab = nTab - rPos.Tab();
+}
+
+
+#pragma SEG_FUNCDEF(refdata_02)
+
+void SingleRefData::SmartRelAbs( const ScAddress& rPos )
+{
+ if ( Flags.bColRel )
+ nCol = nRelCol + rPos.Col();
+ else
+ nRelCol = nCol - rPos.Col();
+
+ if ( Flags.bRowRel )
+ nRow = nRelRow + rPos.Row();
+ else
+ nRelRow = nRow - rPos.Row();
+
+ if ( Flags.bTabRel )
+ nTab = nRelTab + rPos.Tab();
+ else
+ nRelTab = nTab - rPos.Tab();
+}
+
+
+#pragma SEG_FUNCDEF(refdata_06)
+
+void SingleRefData::CalcAbsIfRel( const ScAddress& rPos )
+{
+ if ( Flags.bColRel )
+ {
+ nCol = nRelCol + rPos.Col();
+ if ( !VALIDCOL( nCol ) )
+ Flags.bColDeleted = TRUE;
+ }
+ if ( Flags.bRowRel )
+ {
+ nRow = nRelRow + rPos.Row();
+ if ( !VALIDROW( nRow ) )
+ Flags.bRowDeleted = TRUE;
+ }
+ if ( Flags.bTabRel )
+ {
+ nTab = nRelTab + rPos.Tab();
+ if ( !VALIDTAB( nTab ) )
+ Flags.bTabDeleted = TRUE;
+ }
+}
+
+
+#pragma SEG_FUNCDEF(refdata_03)
+
+void SingleRefData::OldBoolsToNewFlags( const OldSingleRefBools& rBools )
+{
+ switch ( rBools.bRelCol )
+ {
+ case SR_DELETED :
+ Flags.bColRel = TRUE; // der war verlorengegangen
+ Flags.bColDeleted = TRUE;
+ break;
+ case SR_ABSOLUTE :
+ Flags.bColRel = FALSE;
+ Flags.bColDeleted = FALSE;
+ break;
+ case SR_RELABS :
+ case SR_RELATIVE :
+ default:
+ Flags.bColRel = TRUE;
+ Flags.bColDeleted = FALSE;
+ }
+ switch ( rBools.bRelRow )
+ {
+ case SR_DELETED :
+ Flags.bRowRel = TRUE; // der war verlorengegangen
+ Flags.bRowDeleted = TRUE;
+ break;
+ case SR_ABSOLUTE :
+ Flags.bRowRel = FALSE;
+ Flags.bRowDeleted = FALSE;
+ break;
+ case SR_RELABS :
+ case SR_RELATIVE :
+ default:
+ Flags.bRowRel = TRUE;
+ Flags.bRowDeleted = FALSE;
+ }
+ switch ( rBools.bRelTab )
+ {
+ case SR_DELETED :
+ Flags.bTabRel = TRUE; // der war verlorengegangen
+ Flags.bTabDeleted = TRUE;
+ break;
+ case SR_ABSOLUTE :
+ Flags.bTabRel = FALSE;
+ Flags.bTabDeleted = FALSE;
+ break;
+ case SR_RELABS :
+ case SR_RELATIVE :
+ default:
+ Flags.bTabRel = TRUE;
+ Flags.bTabDeleted = FALSE;
+ }
+ Flags.bFlag3D = (rBools.bOldFlag3D & SRF_3D ? TRUE : FALSE);
+ Flags.bRelName = (rBools.bOldFlag3D & SRF_RELNAME ? TRUE : FALSE);
+ if ( !Flags.bFlag3D )
+ Flags.bTabRel = TRUE; // ist bei einigen aelteren Dokumenten nicht gesetzt
+}
+
+
+/*
+ bis Release 3.1 sah Store so aus
+
+ BYTE n = ( ( r.bOldFlag3D & 0x03 ) << 6 ) // RelName, 3D
+ | ( ( r.bRelTab & 0x03 ) << 4 ) // Relative, RelAbs
+ | ( ( r.bRelRow & 0x03 ) << 2 )
+ | ( r.bRelCol & 0x03 );
+
+ bis Release 3.1 sah Load so aus
+
+ r.bRelCol = ( n & 0x03 );
+ r.bRelRow = ( ( n >> 2 ) & 0x03 );
+ r.bRelTab = ( ( n >> 4 ) & 0x03 );
+ r.bOldFlag3D = ( ( n >> 6 ) & 0x03 );
+
+ bRelCol == SR_DELETED war identisch mit bRelCol == (SR_RELATIVE | SR_RELABS)
+ leider..
+ 3.1 liest Zukunft: Deleted wird nicht unbedingt erkannt, nur wenn auch Relativ.
+ Aber immer noch nCol > MAXCOL und gut sollte sein..
+ */
+
+#pragma SEG_FUNCDEF(refdata_04)
+
+BYTE SingleRefData::CreateStoreByteFromFlags() const
+{
+ return (BYTE)(
+ ( (Flags.bRelName & 0x01) << 7 )
+ | ( (Flags.bFlag3D & 0x01) << 6 )
+ | ( (Flags.bTabDeleted & 0x01) << 5 )
+ | ( (Flags.bTabRel & 0x01) << 4 )
+ | ( (Flags.bRowDeleted & 0x01) << 3 )
+ | ( (Flags.bRowRel & 0x01) << 2 )
+ | ( (Flags.bColDeleted & 0x01) << 1 )
+ | (Flags.bColRel & 0x01)
+ );
+}
+
+
+#pragma SEG_FUNCDEF(refdata_05)
+
+void SingleRefData::CreateFlagsFromLoadByte( BYTE n )
+{
+ Flags.bColRel = (n & 0x01 );
+ Flags.bColDeleted = ( (n >> 1) & 0x01 );
+ Flags.bRowRel = ( (n >> 2) & 0x01 );
+ Flags.bRowDeleted = ( (n >> 3) & 0x01 );
+ Flags.bTabRel = ( (n >> 4) & 0x01 );
+ Flags.bTabDeleted = ( (n >> 5) & 0x01 );
+ Flags.bFlag3D = ( (n >> 6) & 0x01 );
+ Flags.bRelName = ( (n >> 7) & 0x01 );
+}
+
+
+#pragma SEG_FUNCDEF(refdata_07)
+
+// Abs-Refs muessen vorher aktualisiert werden!
+// wird in refupdat.cxx mit MoveRelWrap verwendet
+void ComplRefData::PutInOrder()
+{
+ register short n1, n2;
+ register BOOL bTmp;
+ BYTE nRelState1, nRelState2;
+ if ( Ref1.Flags.bRelName )
+ nRelState1 =
+ ((Ref1.Flags.bTabRel & 0x01) << 2)
+ | ((Ref1.Flags.bRowRel & 0x01) << 1)
+ | ((Ref1.Flags.bColRel & 0x01));
+ else
+ nRelState1 = 0;
+ if ( Ref2.Flags.bRelName )
+ nRelState2 =
+ ((Ref2.Flags.bTabRel & 0x01) << 2)
+ | ((Ref2.Flags.bRowRel & 0x01) << 1)
+ | ((Ref2.Flags.bColRel & 0x01));
+ else
+ nRelState2 = 0;
+ if ( (n1 = Ref1.nCol) > (n2 = Ref2.nCol) )
+ {
+ Ref1.nCol = n2;
+ Ref2.nCol = n1;
+ n1 = Ref1.nRelCol;
+ Ref1.nRelCol = Ref2.nRelCol;
+ Ref2.nRelCol = n1;
+ if ( Ref1.Flags.bRelName && Ref1.Flags.bColRel )
+ nRelState2 |= 1;
+ else
+ nRelState2 &= ~1;
+ if ( Ref2.Flags.bRelName && Ref2.Flags.bColRel )
+ nRelState1 |= 1;
+ else
+ nRelState1 &= ~1;
+ bTmp = Ref1.Flags.bColRel;
+ Ref1.Flags.bColRel = Ref2.Flags.bColRel;
+ Ref2.Flags.bColRel = bTmp;
+ bTmp = Ref1.Flags.bColDeleted;
+ Ref1.Flags.bColDeleted = Ref2.Flags.bColDeleted;
+ Ref2.Flags.bColDeleted = bTmp;
+ }
+ if ( (n1 = Ref1.nRow) > (n2 = Ref2.nRow) )
+ {
+ Ref1.nRow = n2;
+ Ref2.nRow = n1;
+ n1 = Ref1.nRelRow;
+ Ref1.nRelRow = Ref2.nRelRow;
+ Ref2.nRelRow = n1;
+ if ( Ref1.Flags.bRelName && Ref1.Flags.bRowRel )
+ nRelState2 |= 2;
+ else
+ nRelState2 &= ~2;
+ if ( Ref2.Flags.bRelName && Ref2.Flags.bRowRel )
+ nRelState1 |= 2;
+ else
+ nRelState1 &= ~2;
+ bTmp = Ref1.Flags.bRowRel;
+ Ref1.Flags.bRowRel = Ref2.Flags.bRowRel;
+ Ref2.Flags.bRowRel = bTmp;
+ bTmp = Ref1.Flags.bRowDeleted;
+ Ref1.Flags.bRowDeleted = Ref2.Flags.bRowDeleted;
+ Ref2.Flags.bRowDeleted = bTmp;
+ }
+ if ( (n1 = Ref1.nTab) > (n2 = Ref2.nTab) )
+ {
+ Ref1.nTab = n2;
+ Ref2.nTab = n1;
+ n1 = Ref1.nRelTab;
+ Ref1.nRelTab = Ref2.nRelTab;
+ Ref2.nRelTab = n1;
+ if ( Ref1.Flags.bRelName && Ref1.Flags.bTabRel )
+ nRelState2 |= 4;
+ else
+ nRelState2 &= ~4;
+ if ( Ref2.Flags.bRelName && Ref2.Flags.bTabRel )
+ nRelState1 |= 4;
+ else
+ nRelState1 &= ~4;
+ bTmp = Ref1.Flags.bTabRel;
+ Ref1.Flags.bTabRel = Ref2.Flags.bTabRel;
+ Ref2.Flags.bTabRel = bTmp;
+ bTmp = Ref1.Flags.bTabDeleted;
+ Ref1.Flags.bTabDeleted = Ref2.Flags.bTabDeleted;
+ Ref2.Flags.bTabDeleted = bTmp;
+ bTmp = Ref1.Flags.bFlag3D;
+ Ref1.Flags.bFlag3D = Ref2.Flags.bFlag3D;
+ Ref2.Flags.bFlag3D = bTmp;
+ }
+ Ref1.Flags.bRelName = ( nRelState1 ? TRUE : FALSE );
+ Ref2.Flags.bRelName = ( nRelState2 ? TRUE : FALSE );
+}
+
+/*------------------------------------------------------------------------
+
+ $Log: not supported by cvs2svn $
+ Revision 1.10 2000/09/17 14:08:42 willem.vandorp
+ OpenOffice header added.
+
+ Revision 1.9 2000/08/31 16:38:04 willem.vandorp
+ Header and footer replaced
+
+ Revision 1.8 1997/11/13 20:06:50 NN
+ ifndef PCH raus
+
+
+ Rev 1.7 13 Nov 1997 21:06:50 NN
+ ifndef PCH raus
+
+ Rev 1.6 08 Jan 1997 20:11:54 ER
+ ScAddress als Reference (keine temporaeren Objekte ohne inlining)
+
+ Rev 1.5 14 May 1996 13:59:32 ER
+ ComplRefData PutInOrder
+
+ Rev 1.4 24 Apr 1996 21:30:48 ER
+ CalcAbsIfRel: !valid => flag deleted
+
+ Rev 1.3 24 Apr 1996 12:23:04 ER
+ unbenamster struct geht nicht
+
+ Rev 1.2 23 Apr 1996 19:23:06 ER
+ ScTokenArray::Store mit Position, CalcAbsIfRel vor ScToken::Store
+
+ Rev 1.1 23 Apr 1996 13:49:04 ER
+ RelRefs, zweite Runde
+
+ Rev 1.0 22 Apr 1996 11:29:28 ER
+ *RefData: token.cxx --> refdata.cxx
+
+------------------------------------------------------------------------*/
+#pragma SEG_EOFMODULE
diff --git a/sc/source/core/tool/reffind.cxx b/sc/source/core/tool/reffind.cxx
new file mode 100644
index 000000000000..e2477bc237e2
--- /dev/null
+++ b/sc/source/core/tool/reffind.cxx
@@ -0,0 +1,201 @@
+/*************************************************************************
+ *
+ * $RCSfile: reffind.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:18 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <string.h>
+
+#include "reffind.hxx"
+#include "global.hxx"
+#include "compiler.hxx"
+
+
+// STATIC DATA -----------------------------------------------------------
+
+// incl. Doppelpunkt -> Doppelte Referenzen werden einzeln behandelt
+const sal_Unicode __FAR_DATA ScRefFinder::pDelimiters[] = {
+ '=','(',')',';','+','-','*','/','^','&',' ','{','}',':', 0
+};
+
+// =======================================================================
+
+inline BOOL IsText( sal_Unicode c )
+{
+ return !ScGlobal::UnicodeStrChr( ScRefFinder::pDelimiters, c );
+}
+
+inline BOOL IsText( BOOL& bQuote, sal_Unicode c )
+{
+ if ( c == '\'' )
+ {
+ bQuote = !bQuote;
+ return TRUE;
+ }
+ if ( bQuote )
+ return TRUE;
+ return IsText( c );
+}
+
+ScRefFinder::ScRefFinder(const String& rFormula, ScDocument* pDocument) :
+ aFormula( rFormula ),
+ pDoc( pDocument )
+{
+ nSelStart = nSelEnd = nFound = 0;
+}
+
+ScRefFinder::~ScRefFinder()
+{
+}
+
+USHORT lcl_NextFlags( USHORT nOld )
+{
+ USHORT nNew = nOld & 7; // die drei Abs-Flags
+ nNew = ( nNew - 1 ) & 7; // weiterzaehlen
+
+ if (!(nOld & SCA_TAB_3D))
+ nNew &= ~SCA_TAB_ABSOLUTE; // nicht 3D -> nie absolut!
+
+ return ( nOld & 0xfff8 ) | nNew;
+}
+
+void ScRefFinder::ToggleRel( xub_StrLen nStartPos, xub_StrLen nEndPos )
+{
+ xub_StrLen nLen = aFormula.Len();
+ if (!nLen)
+ return;
+ const sal_Unicode* pSource = aFormula.GetBuffer(); // fuer schnellen Zugriff
+
+ // Selektion erweitern, und statt Selektion Start- und Endindex
+
+ if ( nEndPos < nStartPos )
+ {
+ xub_StrLen nTemp = nStartPos; nStartPos = nEndPos; nEndPos = nTemp;
+ }
+ while (nStartPos > 0 && IsText(pSource[nStartPos - 1]) )
+ --nStartPos;
+ if (nEndPos)
+ --nEndPos;
+ while (nEndPos+1 < nLen && IsText(pSource[nEndPos + 1]) )
+ ++nEndPos;
+
+ String aResult;
+ String aExpr;
+ String aSep;
+ ScAddress aAddr;
+ nFound = 0;
+
+ xub_StrLen nLoopStart = nStartPos;
+ while ( nLoopStart <= nEndPos )
+ {
+ // Formel zerlegen
+
+ xub_StrLen nEStart = nLoopStart;
+ while ( nEStart <= nEndPos && !IsText(pSource[nEStart]) )
+ ++nEStart;
+
+ BOOL bQuote = FALSE;
+ xub_StrLen nEEnd = nEStart;
+ while ( nEEnd <= nEndPos && IsText(bQuote,pSource[nEEnd]) )
+ ++nEEnd;
+
+ aSep = aFormula.Copy( nLoopStart, nEStart-nLoopStart );
+ aExpr = aFormula.Copy( nEStart, nEEnd-nEStart );
+
+ // Test, ob aExpr eine Referenz ist
+
+ USHORT nResult = aAddr.Parse( aExpr, pDoc );
+ if ( nResult & SCA_VALID )
+ {
+ USHORT nFlags = lcl_NextFlags( nResult );
+ aAddr.Format( aExpr, nFlags, pDoc );
+
+ xub_StrLen nAbsStart = nStartPos+aResult.Len()+aSep.Len();
+
+ if (!nFound) // erste Referenz ?
+ nSelStart = nAbsStart;
+ nSelEnd = nAbsStart+aExpr.Len(); // Selektion, keine Indizes
+ ++nFound;
+ }
+
+ // zusammenbauen
+
+ aResult += aSep;
+ aResult += aExpr;
+
+ nLoopStart = nEEnd;
+ }
+
+ String aTotal = aFormula.Copy( 0, nStartPos );
+ aTotal += aResult;
+ aTotal += aFormula.Copy( nEndPos+1 );
+
+ aFormula = aTotal;
+}
+
+
+
+
diff --git a/sc/source/core/tool/refupdat.cxx b/sc/source/core/tool/refupdat.cxx
new file mode 100644
index 000000000000..efe69e329300
--- /dev/null
+++ b/sc/source/core/tool/refupdat.cxx
@@ -0,0 +1,983 @@
+/*************************************************************************
+ *
+ * $RCSfile: refupdat.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:18 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <tools/debug.hxx>
+
+#include "refupdat.hxx"
+#include "document.hxx"
+#include "compiler.hxx"
+#include "bigrange.hxx"
+#include "chgtrack.hxx"
+
+//------------------------------------------------------------------------
+
+BOOL lcl_MoveStart( short& rRef, short nStart, short nDelta, short nMask )
+{
+ BOOL bCut = FALSE;
+ if ( rRef >= nStart )
+ rRef += nDelta;
+ else if ( nDelta < 0 && rRef >= nStart + nDelta )
+ rRef = nStart + nDelta; //! begrenzen ???
+ if ( rRef < 0 )
+ {
+ rRef = 0;
+ bCut = TRUE;
+ }
+ else if ( rRef > nMask )
+ {
+ rRef = nMask;
+ bCut = TRUE;
+ }
+ return bCut;
+}
+
+BOOL lcl_MoveEnd( short& rRef, short nStart, short nDelta, short nMask )
+{
+ BOOL bCut = FALSE;
+ if ( rRef >= nStart )
+ rRef += nDelta;
+ else if ( nDelta < 0 && rRef >= nStart + nDelta )
+ rRef = nStart + nDelta - 1; //! begrenzen ???
+ if ( rRef < 0 )
+ {
+ rRef = 0;
+ bCut = TRUE;
+ }
+ else if ( rRef > nMask )
+ {
+ rRef = nMask;
+ bCut = TRUE;
+ }
+ return bCut;
+}
+
+BOOL lcl_MoveReorder( short& rRef, short nStart, short nEnd, short nDelta )
+{
+ if ( rRef >= nStart && rRef <= nEnd )
+ {
+ rRef += nDelta;
+ return TRUE;
+ }
+
+ if ( nDelta > 0 ) // nach hinten schieben
+ {
+ if ( rRef >= nStart && rRef <= nEnd + nDelta )
+ {
+ if ( rRef <= nEnd )
+ rRef += nDelta; // verschobener Teil
+ else
+ rRef -= nEnd - nStart + 1; // nachruecken
+ return TRUE;
+ }
+ }
+ else // nach vorne schieben
+ {
+ if ( rRef >= nStart + nDelta && rRef <= nEnd )
+ {
+ if ( rRef >= nStart )
+ rRef += nDelta; // verschobener Teil
+ else
+ rRef += nEnd - nStart + 1; // nachruecken
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+BOOL lcl_MoveItCut( short& rRef, short nDelta, short nMask )
+{
+ BOOL bCut = FALSE;
+ rRef += nDelta;
+ if ( rRef < 0 )
+ {
+ rRef = 0;
+ bCut = TRUE;
+ }
+ else if ( rRef > nMask )
+ {
+ rRef = nMask;
+ bCut = TRUE;
+ }
+ return bCut;
+}
+
+void lcl_MoveItWrap( short& rRef, short nDelta, short nMask )
+{
+ rRef += nDelta;
+ if ( rRef < 0 )
+ rRef += nMask+1;
+ else if ( rRef > nMask )
+ rRef -= nMask+1;
+}
+
+BOOL lcl_MoveRefPart( short& rRef1Val, BOOL& rRef1Del,
+ short& rRef2Val, BOOL& rRef2Del,
+ short nStart, short nEnd, short nDelta, short nMask )
+{
+ if ( nDelta )
+ {
+ BOOL bDel, bCut1, bCut2;
+ bDel = bCut1 = bCut2 = FALSE;
+ short n;
+ if ( nDelta < 0 )
+ {
+ n = nStart + nDelta;
+ if ( n <= rRef1Val && rRef1Val < nStart
+ && n <= rRef2Val && rRef2Val < nStart )
+ bDel = TRUE;
+ }
+ else
+ {
+ n = nEnd + nDelta;
+ if ( nEnd < rRef1Val && rRef1Val <= n
+ && nEnd < rRef2Val && rRef2Val <= n )
+ bDel = TRUE;
+ }
+ if ( bDel )
+ { // geloeschte mitverschieben
+ rRef1Val += nDelta;
+ rRef2Val += nDelta;
+ }
+ else
+ {
+ if ( rRef1Del )
+ rRef1Val += nDelta;
+ else
+ bCut1 = lcl_MoveStart( rRef1Val, nStart, nDelta, nMask );
+ if ( rRef2Del )
+ rRef2Val += nDelta;
+ else
+ bCut2 = lcl_MoveEnd( rRef2Val, nStart, nDelta, nMask );
+ }
+ if ( bDel || (bCut1 && bCut2) )
+ rRef1Del = rRef2Del = TRUE;
+ return bDel || bCut1 || bCut2 || rRef1Del || rRef2Del;
+ }
+ else
+ return FALSE;
+}
+
+
+#ifndef DEBUG
+inline
+#endif
+BOOL IsExpand( short n1, short n2, short nStart, short nD )
+{ //! vor normalem Move...
+ return
+ nD > 0 // Insert
+ && n1 < n2 // mindestens zwei Cols/Rows/Tabs in Ref
+ && (
+ (nStart <= n1 && n1 < nStart + nD) // n1 innerhalb des Insert
+ || (n2 + 1 == nStart) // n2 direkt vor Insert
+ ); // n1 < nStart <= n2 wird sowieso expanded!
+}
+
+
+#ifndef DEBUG
+inline
+#endif
+void Expand( short& n1, short& n2, short nStart, short nD )
+{ //! nach normalem Move..., nur wenn IsExpand vorher TRUE war!
+ //! erst das Ende
+ if ( n2 + 1 == nStart )
+ { // am Ende
+ n2 += nD;
+ return;
+ }
+ // am Anfang
+ n1 -= nD;
+}
+
+
+BOOL lcl_IsWrapBig( INT32 nRef, INT32 nDelta )
+{
+ if ( nRef > 0 && nDelta > 0 )
+ return nRef + nDelta <= 0;
+ else if ( nRef < 0 && nDelta < 0 )
+ return nRef + nDelta >= 0;
+ return FALSE;
+}
+
+
+BOOL lcl_MoveBig( INT32& rRef, INT32 nStart, INT32 nDelta )
+{
+ BOOL bCut = FALSE;
+ if ( rRef >= nStart )
+ {
+ if ( nDelta > 0 )
+ bCut = lcl_IsWrapBig( rRef, nDelta );
+ if ( bCut )
+ rRef = nInt32Max;
+ else
+ rRef += nDelta;
+ }
+ return bCut;
+}
+
+BOOL lcl_MoveItCutBig( INT32& rRef, INT32 nDelta )
+{
+ BOOL bCut = lcl_IsWrapBig( rRef, nDelta );
+ rRef += nDelta;
+ return bCut;
+}
+
+
+ScRefUpdateRes ScRefUpdate::Update( ScDocument* pDoc, UpdateRefMode eUpdateRefMode,
+ USHORT nCol1, USHORT nRow1, USHORT nTab1,
+ USHORT nCol2, USHORT nRow2, USHORT nTab2,
+ short nDx, short nDy, short nDz,
+ USHORT& theCol1, USHORT& theRow1, USHORT& theTab1,
+ USHORT& theCol2, USHORT& theRow2, USHORT& theTab2 )
+{
+ ScRefUpdateRes eRet = UR_NOTHING;
+
+ USHORT oldCol1 = theCol1;
+ USHORT oldRow1 = theRow1;
+ USHORT oldTab1 = theTab1;
+ USHORT oldCol2 = theCol2;
+ USHORT oldRow2 = theRow2;
+ USHORT oldTab2 = theTab2;
+
+ BOOL bCut1, bCut2;
+
+ if (eUpdateRefMode == URM_INSDEL)
+ {
+ BOOL bExpand = pDoc->IsExpandRefs();
+ if ( nDx && (theRow1 >= nRow1) && (theRow2 <= nRow2) &&
+ (theTab1 >= nTab1) && (theTab2 <= nTab2) )
+ {
+ BOOL bExp = (bExpand && IsExpand( theCol1, theCol2, nCol1, nDx ));
+ bCut1 = lcl_MoveStart( (short&) theCol1, nCol1, nDx, MAXCOL );
+ bCut2 = lcl_MoveEnd( (short&) theCol2, nCol1, nDx, MAXCOL );
+ if ( theCol2 < theCol1 )
+ {
+ eRet = UR_INVALID;
+ theCol2 = theCol1;
+ }
+ else if ( bCut1 || bCut2 )
+ eRet = UR_UPDATED;
+ if ( bExp )
+ {
+ Expand( (short&) theCol1, (short&) theCol2, nCol1, nDx );
+ eRet = UR_UPDATED;
+ }
+ }
+ if ( nDy && (theCol1 >= nCol1) && (theCol2 <= nCol2) &&
+ (theTab1 >= nTab1) && (theTab2 <= nTab2) )
+ {
+ BOOL bExp = (bExpand && IsExpand( theRow1, theRow2, nRow1, nDy ));
+ bCut1 = lcl_MoveStart( (short&) theRow1, nRow1, nDy, MAXROW );
+ bCut2 = lcl_MoveEnd( (short&) theRow2, nRow1, nDy, MAXROW );
+ if ( theRow2 < theRow1 )
+ {
+ eRet = UR_INVALID;
+ theRow2 = theRow1;
+ }
+ else if ( bCut1 || bCut2 )
+ eRet = UR_UPDATED;
+ if ( bExp )
+ {
+ Expand( (short&) theRow1, (short&) theRow2, nRow1, nDy );
+ eRet = UR_UPDATED;
+ }
+ }
+ if ( nDz && (theCol1 >= nCol1) && (theCol2 <= nCol2) &&
+ (theRow1 >= nRow1) && (theRow2 <= nRow2) )
+ {
+ short nMaxTab = pDoc->GetTableCount() - 1;
+ nMaxTab += nDz; // auf die neue Anzahl anpassen
+ BOOL bExp = (bExpand && IsExpand( theTab1, theTab2, nTab1, nDz ));
+ bCut1 = lcl_MoveStart( (short&) theTab1, nTab1, nDz, nMaxTab );
+ bCut2 = lcl_MoveEnd( (short&) theTab2, nTab1, nDz, nMaxTab );
+ if ( theTab2 < theTab1 )
+ {
+ eRet = UR_INVALID;
+ theTab2 = theTab1;
+ }
+ else if ( bCut1 || bCut2 )
+ eRet = UR_UPDATED;
+ if ( bExp )
+ {
+ Expand( (short&) theTab1, (short&) theTab2, nTab1, nDz );
+ eRet = UR_UPDATED;
+ }
+ }
+ }
+ else if (eUpdateRefMode == URM_MOVE)
+ {
+ if ((theCol1 >= nCol1-nDx) && (theRow1 >= nRow1-nDy) && (theTab1 >= nTab1-nDz) &&
+ (theCol2 <= nCol2-nDx) && (theRow2 <= nRow2-nDy) && (theTab2 <= nTab2-nDz))
+ {
+ if ( nDx )
+ {
+ bCut1 = lcl_MoveItCut( (short&) theCol1, nDx, MAXCOL );
+ bCut2 = lcl_MoveItCut( (short&) theCol2, nDx, MAXCOL );
+ if ( bCut1 || bCut2 )
+ eRet = UR_UPDATED;
+ }
+ if ( nDy )
+ {
+ bCut1 = lcl_MoveItCut( (short&) theRow1, nDy, MAXROW );
+ bCut2 = lcl_MoveItCut( (short&) theRow2, nDy, MAXROW );
+ if ( bCut1 || bCut2 )
+ eRet = UR_UPDATED;
+ }
+ if ( nDz )
+ {
+ short nMaxTab = (short) pDoc->GetTableCount() - 1;
+ bCut1 = lcl_MoveItCut( (short&) theTab1, nDz, nMaxTab );
+ bCut2 = lcl_MoveItCut( (short&) theTab2, nDz, nMaxTab );
+ if ( bCut1 || bCut2 )
+ eRet = UR_UPDATED;
+ }
+ }
+ }
+ else if (eUpdateRefMode == URM_REORDER)
+ {
+ // bisher nur fuer nDz (MoveTab)
+ DBG_ASSERT ( !nDx && !nDy, "URM_REORDER fuer x und y noch nicht implementiert" );
+
+ if ( nDz && (theCol1 >= nCol1) && (theCol2 <= nCol2) &&
+ (theRow1 >= nRow1) && (theRow2 <= nRow2) )
+ {
+ bCut1 = lcl_MoveReorder( (short&) theTab1, nTab1, nTab2, nDz );
+ bCut2 = lcl_MoveReorder( (short&) theTab2, nTab1, nTab2, nDz );
+ if ( bCut1 || bCut2 )
+ eRet = UR_UPDATED;
+ }
+ }
+
+ if ( eRet == UR_NOTHING )
+ {
+ if (oldCol1 != theCol1
+ || oldRow1 != theRow1
+ || oldTab1 != theTab1
+ || oldCol2 != theCol2
+ || oldRow2 != theRow2
+ || oldTab2 != theTab2
+ )
+ eRet = UR_UPDATED;
+ }
+ return eRet;
+}
+
+
+// simples UpdateReference fuer ScBigRange (ScChangeAction/ScChangeTrack)
+// Referenzen koennen auch ausserhalb des Dokuments liegen!
+// Ganze Spalten/Zeilen (nInt32Min..nInt32Max) bleiben immer solche!
+ScRefUpdateRes ScRefUpdate::Update( UpdateRefMode eUpdateRefMode,
+ const ScBigRange& rWhere, INT32 nDx, INT32 nDy, INT32 nDz,
+ ScBigRange& rWhat )
+{
+ ScRefUpdateRes eRet = UR_NOTHING;
+ const ScBigRange aOldRange( rWhat );
+
+ INT32 nCol1, nRow1, nTab1, nCol2, nRow2, nTab2;
+ INT32 theCol1, theRow1, theTab1, theCol2, theRow2, theTab2;
+ rWhere.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ rWhat.GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 );
+
+ BOOL bCut1, bCut2;
+
+ if (eUpdateRefMode == URM_INSDEL)
+ {
+ if ( nDx && (theRow1 >= nRow1) && (theRow2 <= nRow2) &&
+ (theTab1 >= nTab1) && (theTab2 <= nTab2) &&
+ !(theCol1 == nInt32Min && theCol2 == nInt32Max) )
+ {
+ bCut1 = lcl_MoveBig( theCol1, nCol1, nDx );
+ bCut2 = lcl_MoveBig( theCol2, nCol1, nDx );
+ if ( bCut1 || bCut2 )
+ eRet = UR_UPDATED;
+ rWhat.aStart.SetCol( theCol1 );
+ rWhat.aEnd.SetCol( theCol2 );
+ }
+ if ( nDy && (theCol1 >= nCol1) && (theCol2 <= nCol2) &&
+ (theTab1 >= nTab1) && (theTab2 <= nTab2) &&
+ !(theRow1 == nInt32Min && theRow2 == nInt32Max) )
+ {
+ bCut1 = lcl_MoveBig( theRow1, nRow1, nDy );
+ bCut2 = lcl_MoveBig( theRow2, nRow1, nDy );
+ if ( bCut1 || bCut2 )
+ eRet = UR_UPDATED;
+ rWhat.aStart.SetRow( theRow1 );
+ rWhat.aEnd.SetRow( theRow2 );
+ }
+ if ( nDz && (theCol1 >= nCol1) && (theCol2 <= nCol2) &&
+ (theRow1 >= nRow1) && (theRow2 <= nRow2) &&
+ !(theTab1 == nInt32Min && theTab2 == nInt32Max) )
+ {
+ bCut1 = lcl_MoveBig( theTab1, nTab1, nDz );
+ bCut2 = lcl_MoveBig( theTab2, nTab1, nDz );
+ if ( bCut1 || bCut2 )
+ eRet = UR_UPDATED;
+ rWhat.aStart.SetTab( theTab1 );
+ rWhat.aEnd.SetTab( theTab2 );
+ }
+ }
+ else if (eUpdateRefMode == URM_MOVE)
+ {
+ if ( rWhere.In( rWhat ) )
+ {
+ if ( nDx && !(theCol1 == nInt32Min && theCol2 == nInt32Max) )
+ {
+ bCut1 = lcl_MoveItCutBig( theCol1, nDx );
+ bCut2 = lcl_MoveItCutBig( theCol2, nDx );
+ if ( bCut1 || bCut2 )
+ eRet = UR_UPDATED;
+ rWhat.aStart.SetCol( theCol1 );
+ rWhat.aEnd.SetCol( theCol2 );
+ }
+ if ( nDy && !(theRow1 == nInt32Min && theRow2 == nInt32Max) )
+ {
+ bCut1 = lcl_MoveItCutBig( theRow1, nDy );
+ bCut2 = lcl_MoveItCutBig( theRow2, nDy );
+ if ( bCut1 || bCut2 )
+ eRet = UR_UPDATED;
+ rWhat.aStart.SetRow( theRow1 );
+ rWhat.aEnd.SetRow( theRow2 );
+ }
+ if ( nDz && !(theTab1 == nInt32Min && theTab2 == nInt32Max) )
+ {
+ bCut1 = lcl_MoveItCutBig( theTab1, nDz );
+ bCut2 = lcl_MoveItCutBig( theTab2, nDz );
+ if ( bCut1 || bCut2 )
+ eRet = UR_UPDATED;
+ rWhat.aStart.SetTab( theTab1 );
+ rWhat.aEnd.SetTab( theTab2 );
+ }
+ }
+ }
+
+ if ( eRet == UR_NOTHING && rWhat != aOldRange )
+ eRet = UR_UPDATED;
+
+ return eRet;
+}
+
+
+// vor dem Aufruf muessen die Abs-Refs aktualisiert werden!
+ScRefUpdateRes ScRefUpdate::Update( ScDocument* pDoc, UpdateRefMode eMode,
+ const ScAddress& rPos, const ScRange& r,
+ short nDx, short nDy, short nDz,
+ ComplRefData& rRef )
+{
+ ScRefUpdateRes eRet = UR_NOTHING;
+
+ short nCol1 = r.aStart.Col();
+ short nRow1 = r.aStart.Row();
+ short nTab1 = r.aStart.Tab();
+ short nCol2 = r.aEnd.Col();
+ short nRow2 = r.aEnd.Row();
+ short nTab2 = r.aEnd.Tab();
+
+ if( eMode == URM_INSDEL )
+ {
+ BOOL bExpand = pDoc->IsExpandRefs();
+
+ const ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
+ BOOL bInDeleteUndo =
+ ( pChangeTrack ? pChangeTrack->IsInDeleteUndo() : FALSE );
+
+ USHORT oldCol1 = rRef.Ref1.nCol;
+ USHORT oldRow1 = rRef.Ref1.nRow;
+ USHORT oldTab1 = rRef.Ref1.nTab;
+ USHORT oldCol2 = rRef.Ref2.nCol;
+ USHORT oldRow2 = rRef.Ref2.nRow;
+ USHORT oldTab2 = rRef.Ref2.nTab;
+
+ BOOL bRef1ColDel = rRef.Ref1.IsColDeleted();
+ BOOL bRef2ColDel = rRef.Ref2.IsColDeleted();
+ BOOL bRef1RowDel = rRef.Ref1.IsRowDeleted();
+ BOOL bRef2RowDel = rRef.Ref2.IsRowDeleted();
+ BOOL bRef1TabDel = rRef.Ref1.IsTabDeleted();
+ BOOL bRef2TabDel = rRef.Ref2.IsTabDeleted();
+
+ if( nDx &&
+ ((rRef.Ref1.nRow >= nRow1
+ && rRef.Ref2.nRow <= nRow2) || (bRef1RowDel || bRef2RowDel))
+ &&
+ ((rRef.Ref1.nTab >= nTab1
+ && rRef.Ref2.nTab <= nTab2) || (bRef1TabDel || bRef2TabDel))
+ )
+ {
+ BOOL bExp = (bExpand && !bInDeleteUndo && IsExpand( rRef.Ref1.nCol,
+ rRef.Ref2.nCol, nCol1, nDx ));
+ if ( lcl_MoveRefPart( rRef.Ref1.nCol, bRef1ColDel,
+ rRef.Ref2.nCol, bRef2ColDel,
+ nCol1, nCol2, nDx, MAXCOL ) )
+ {
+ eRet = UR_UPDATED;
+ if ( bInDeleteUndo && (bRef1ColDel || bRef2ColDel) )
+ {
+ if ( bRef1ColDel && nCol1 <= rRef.Ref1.nCol &&
+ rRef.Ref1.nCol <= nCol1 + nDx )
+ rRef.Ref1.SetColDeleted( FALSE );
+ if ( bRef2ColDel && nCol1 <= rRef.Ref2.nCol &&
+ rRef.Ref2.nCol <= nCol1 + nDx )
+ rRef.Ref2.SetColDeleted( FALSE );
+ }
+ else
+ {
+ if ( bRef1ColDel )
+ rRef.Ref1.SetColDeleted( TRUE );
+ if ( bRef2ColDel )
+ rRef.Ref2.SetColDeleted( TRUE );
+ }
+ }
+ if ( bExp )
+ {
+ Expand( rRef.Ref1.nCol, rRef.Ref2.nCol, nCol1, nDx );
+ eRet = UR_UPDATED;
+ }
+ }
+ if( nDy &&
+ ((rRef.Ref1.nCol >= nCol1
+ && rRef.Ref2.nCol <= nCol2) || (bRef1ColDel || bRef2ColDel))
+ &&
+ ((rRef.Ref1.nTab >= nTab1
+ && rRef.Ref2.nTab <= nTab2) || (bRef1TabDel || bRef2TabDel))
+ )
+ {
+ BOOL bExp = (bExpand && !bInDeleteUndo && IsExpand( rRef.Ref1.nRow,
+ rRef.Ref2.nRow, nRow1, nDy ));
+ if ( lcl_MoveRefPart( rRef.Ref1.nRow, bRef1RowDel,
+ rRef.Ref2.nRow, bRef2RowDel,
+ nRow1, nRow2, nDy, MAXROW ) )
+ {
+ eRet = UR_UPDATED;
+ if ( bInDeleteUndo && (bRef1RowDel || bRef2RowDel) )
+ {
+ if ( bRef1RowDel && nRow1 <= rRef.Ref1.nRow &&
+ rRef.Ref1.nRow <= nRow1 + nDy )
+ rRef.Ref1.SetRowDeleted( FALSE );
+ if ( bRef2RowDel && nRow1 <= rRef.Ref2.nRow &&
+ rRef.Ref2.nRow <= nRow1 + nDy )
+ rRef.Ref2.SetRowDeleted( FALSE );
+ }
+ else
+ {
+ if ( bRef1RowDel )
+ rRef.Ref1.SetRowDeleted( TRUE );
+ if ( bRef2RowDel )
+ rRef.Ref2.SetRowDeleted( TRUE );
+ }
+ }
+ if ( bExp )
+ {
+ Expand( rRef.Ref1.nRow, rRef.Ref2.nRow, nRow1, nDy );
+ eRet = UR_UPDATED;
+ }
+ }
+ if( nDz &&
+ ((rRef.Ref1.nCol >= nCol1
+ && rRef.Ref2.nCol <= nCol2) || (bRef1ColDel || bRef2ColDel))
+ &&
+ ((rRef.Ref1.nRow >= nRow1
+ && rRef.Ref2.nRow <= nRow2) || (bRef1RowDel || bRef2RowDel))
+ )
+ {
+ BOOL bExp = (bExpand && !bInDeleteUndo && IsExpand( rRef.Ref1.nTab,
+ rRef.Ref2.nTab, nTab1, nDz ));
+ short nMaxTab = (short) pDoc->GetTableCount() - 1;
+ if ( lcl_MoveRefPart( rRef.Ref1.nTab, bRef1TabDel,
+ rRef.Ref2.nTab, bRef2TabDel,
+ nTab1, nTab2, nDz, nMaxTab ) )
+ {
+ eRet = UR_UPDATED;
+ if ( bInDeleteUndo && (bRef1TabDel || bRef2TabDel) )
+ {
+ if ( bRef1TabDel && nTab1 <= rRef.Ref1.nTab &&
+ rRef.Ref1.nTab <= nTab1 + nDz )
+ rRef.Ref1.SetTabDeleted( FALSE );
+ if ( bRef2TabDel && nTab1 <= rRef.Ref2.nTab &&
+ rRef.Ref2.nTab <= nTab1 + nDz )
+ rRef.Ref2.SetTabDeleted( FALSE );
+ }
+ else
+ {
+ if ( bRef1TabDel )
+ rRef.Ref1.SetTabDeleted( TRUE );
+ if ( bRef2TabDel )
+ rRef.Ref2.SetTabDeleted( TRUE );
+ }
+ }
+ if ( bExp )
+ {
+ Expand( rRef.Ref1.nTab, rRef.Ref2.nTab, nTab1, nDz );
+ eRet = UR_UPDATED;
+ }
+ }
+ if ( eRet == UR_NOTHING )
+ {
+ if (oldCol1 != rRef.Ref1.nCol
+ || oldRow1 != rRef.Ref1.nRow
+ || oldTab1 != rRef.Ref1.nTab
+ || oldCol2 != rRef.Ref2.nCol
+ || oldRow2 != rRef.Ref2.nRow
+ || oldTab2 != rRef.Ref2.nTab
+ )
+ eRet = UR_UPDATED;
+ }
+ rRef.CalcRelFromAbs( rPos );
+ }
+ else
+ {
+ if( eMode == URM_MOVE )
+ {
+ if ( rRef.Ref1.nCol >= nCol1-nDx
+ && rRef.Ref1.nRow >= nRow1-nDy
+ && rRef.Ref1.nTab >= nTab1-nDz
+ && rRef.Ref2.nCol <= nCol2-nDx
+ && rRef.Ref2.nRow <= nRow2-nDy
+ && rRef.Ref2.nTab <= nTab2-nDz )
+ {
+ eRet = Move( pDoc, rPos, nDx, nDy, nDz, rRef, FALSE, TRUE ); // immer verschieben
+ }
+ else if ( nDz && r.In( rPos ) )
+ {
+ rRef.Ref1.SetFlag3D( TRUE );
+ rRef.Ref2.SetFlag3D( TRUE );
+ eRet = UR_UPDATED;
+ rRef.CalcRelFromAbs( rPos );
+ }
+ else
+ rRef.CalcRelFromAbs( rPos );
+ }
+ else if( eMode == URM_COPY && r.In( rPos ) )
+ eRet = Move( pDoc, rPos, nDx, nDy, nDz, rRef, FALSE, FALSE ); // nur relative
+ // sollte nicht mehr verwendet werden muessen
+ else
+ rRef.CalcRelFromAbs( rPos );
+ }
+ return eRet;
+}
+
+// vor dem Aufruf muessen die Abs-Refs aktualisiert werden!
+ScRefUpdateRes ScRefUpdate::Move( ScDocument* pDoc, const ScAddress& rPos,
+ short nDx, short nDy, short nDz,
+ ComplRefData& rRef, BOOL bWrap, BOOL bAbsolute )
+{
+ ScRefUpdateRes eRet = UR_NOTHING;
+
+ USHORT oldCol1 = rRef.Ref1.nCol;
+ USHORT oldRow1 = rRef.Ref1.nRow;
+ USHORT oldTab1 = rRef.Ref1.nTab;
+ USHORT oldCol2 = rRef.Ref2.nCol;
+ USHORT oldRow2 = rRef.Ref2.nRow;
+ USHORT oldTab2 = rRef.Ref2.nTab;
+
+ BOOL bCut1, bCut2;
+ if ( nDx )
+ {
+ bCut1 = bCut2 = FALSE;
+ if( bAbsolute || rRef.Ref1.IsColRel() )
+ {
+ if( bWrap )
+ lcl_MoveItWrap( (short&) rRef.Ref1.nCol, nDx, MAXCOL );
+ else
+ bCut1 = lcl_MoveItCut( (short&) rRef.Ref1.nCol, nDx, MAXCOL );
+ }
+ if( bAbsolute || rRef.Ref2.IsColRel() )
+ {
+ if( bWrap )
+ lcl_MoveItWrap( (short&) rRef.Ref2.nCol, nDx, MAXCOL );
+ else
+ bCut2 = lcl_MoveItCut( (short&) rRef.Ref2.nCol, nDx, MAXCOL );
+ }
+ if ( bCut1 || bCut2 )
+ eRet = UR_UPDATED;
+ if ( bCut1 && bCut2 )
+ {
+ rRef.Ref1.SetColDeleted( TRUE );
+ rRef.Ref2.SetColDeleted( TRUE );
+ }
+ }
+ if ( nDy )
+ {
+ bCut1 = bCut2 = FALSE;
+ if( bAbsolute || rRef.Ref1.IsRowRel() )
+ {
+ if( bWrap )
+ lcl_MoveItWrap( (short&) rRef.Ref1.nRow, nDy, MAXROW );
+ else
+ bCut1 = lcl_MoveItCut( (short&) rRef.Ref1.nRow, nDy, MAXROW );
+ }
+ if( bAbsolute || rRef.Ref2.IsRowRel() )
+ {
+ if( bWrap )
+ lcl_MoveItWrap( (short&) rRef.Ref2.nRow, nDy, MAXROW );
+ else
+ bCut2 = lcl_MoveItCut( (short&) rRef.Ref2.nRow, nDy, MAXROW );
+ }
+ if ( bCut1 || bCut2 )
+ eRet = UR_UPDATED;
+ if ( bCut1 && bCut2 )
+ {
+ rRef.Ref1.SetRowDeleted( TRUE );
+ rRef.Ref2.SetRowDeleted( TRUE );
+ }
+ }
+ if ( nDz )
+ {
+ bCut1 = bCut2 = FALSE;
+ short nMaxTab = (short) pDoc->GetTableCount() - 1;
+ if( bAbsolute || rRef.Ref1.IsTabRel() )
+ {
+ if( bWrap )
+ lcl_MoveItWrap( (short&) rRef.Ref1.nTab, nDz, nMaxTab );
+ else
+ bCut1 = lcl_MoveItCut( (short&) rRef.Ref1.nTab, nDz, nMaxTab );
+ rRef.Ref1.SetFlag3D( rPos.Tab() != rRef.Ref1.nTab );
+ }
+ if( bAbsolute || rRef.Ref2.IsTabRel() )
+ {
+ if( bWrap )
+ lcl_MoveItWrap( (short&) rRef.Ref2.nTab, nDz, nMaxTab );
+ else
+ bCut2 = lcl_MoveItCut( (short&) rRef.Ref2.nTab, nDz, nMaxTab );
+ rRef.Ref2.SetFlag3D( rPos.Tab() != rRef.Ref2.nTab );
+ }
+ if ( bCut1 || bCut2 )
+ eRet = UR_UPDATED;
+ if ( bCut1 && bCut2 )
+ {
+ rRef.Ref1.SetTabDeleted( TRUE );
+ rRef.Ref2.SetTabDeleted( TRUE );
+ }
+ }
+
+ if ( eRet == UR_NOTHING )
+ {
+ if (oldCol1 != rRef.Ref1.nCol
+ || oldRow1 != rRef.Ref1.nRow
+ || oldTab1 != rRef.Ref1.nTab
+ || oldCol2 != rRef.Ref2.nCol
+ || oldRow2 != rRef.Ref2.nRow
+ || oldTab2 != rRef.Ref2.nTab
+ )
+ eRet = UR_UPDATED;
+ }
+ if ( bWrap && eRet != UR_NOTHING )
+ rRef.PutInOrder();
+ rRef.CalcRelFromAbs( rPos );
+ return eRet;
+}
+
+void ScRefUpdate::MoveRelWrap( ScDocument* pDoc, const ScAddress& rPos,
+ ComplRefData& rRef )
+{
+ if( rRef.Ref1.IsColRel() )
+ {
+ rRef.Ref1.nCol = rRef.Ref1.nRelCol + rPos.Col();
+ lcl_MoveItWrap( (short&) rRef.Ref1.nCol, 0, MAXCOL );
+ }
+ if( rRef.Ref2.IsColRel() )
+ {
+ rRef.Ref2.nCol = rRef.Ref2.nRelCol + rPos.Col();
+ lcl_MoveItWrap( (short&) rRef.Ref2.nCol, 0, MAXCOL );
+ }
+ if( rRef.Ref1.IsRowRel() )
+ {
+ rRef.Ref1.nRow = rRef.Ref1.nRelRow + rPos.Row();
+ lcl_MoveItWrap( (short&) rRef.Ref1.nRow, 0, MAXROW );
+ }
+ if( rRef.Ref2.IsRowRel() )
+ {
+ rRef.Ref2.nRow = rRef.Ref2.nRelRow + rPos.Row();
+ lcl_MoveItWrap( (short&) rRef.Ref2.nRow, 0, MAXROW );
+ }
+ short nMaxTab = (short) pDoc->GetTableCount() - 1;
+ if( rRef.Ref1.IsTabRel() )
+ {
+ rRef.Ref1.nTab = rRef.Ref1.nRelTab + rPos.Tab();
+ lcl_MoveItWrap( (short&) rRef.Ref1.nTab, 0, nMaxTab );
+ }
+ if( rRef.Ref2.IsTabRel() )
+ {
+ rRef.Ref2.nTab = rRef.Ref2.nRelTab + rPos.Tab();
+ lcl_MoveItWrap( (short&) rRef.Ref2.nTab, 0, nMaxTab );
+ }
+ rRef.PutInOrder();
+ rRef.CalcRelFromAbs( rPos );
+}
+
+//------------------------------------------------------------------
+
+void ScRefUpdate::DoTranspose( short& rCol, short& rRow, short& rTab,
+ ScDocument* pDoc, const ScRange& rSource, const ScAddress& rDest )
+{
+ short nDz = ((short)rDest.Tab())-(short)rSource.aStart.Tab();
+ if (nDz)
+ {
+ short nNewTab = rTab+nDz;
+ short nCount = pDoc->GetTableCount();
+ while (nNewTab<0) nNewTab += nCount;
+ while (nNewTab>=nCount) nNewTab -= nCount;
+ rTab = nNewTab;
+ }
+ DBG_ASSERT( rCol>=rSource.aStart.Col() && rRow>=rSource.aStart.Row(),
+ "UpdateTranspose: Pos. falsch" );
+
+ short nRelX = rCol - (short)rSource.aStart.Col();
+ short nRelY = rRow - (short)rSource.aStart.Row();
+
+ rCol = (short)rDest.Col() + nRelY;
+ rRow = (short)rDest.Row() + nRelX;
+}
+
+// vor dem Aufruf muessen die Abs-Refs aktualisiert werden!
+ScRefUpdateRes ScRefUpdate::UpdateTranspose( ScDocument* pDoc,
+ const ScRange& rSource, const ScAddress& rDest,
+ ComplRefData& rRef )
+{
+ ScRefUpdateRes eRet = UR_NOTHING;
+ if ( rRef.Ref1.nCol >= rSource.aStart.Col() && rRef.Ref2.nCol <= rSource.aEnd.Col() &&
+ rRef.Ref1.nRow >= rSource.aStart.Row() && rRef.Ref2.nRow <= rSource.aEnd.Row() &&
+ rRef.Ref1.nTab >= rSource.aStart.Tab() && rRef.Ref2.nTab <= rSource.aEnd.Tab() )
+ {
+ DoTranspose( rRef.Ref1.nCol, rRef.Ref1.nRow, rRef.Ref1.nTab, pDoc, rSource, rDest );
+ DoTranspose( rRef.Ref2.nCol, rRef.Ref2.nRow, rRef.Ref2.nTab, pDoc, rSource, rDest );
+ eRet = UR_UPDATED;
+ }
+ return eRet;
+}
+
+//------------------------------------------------------------------
+
+// UpdateGrow - erweitert Referenzen, die genau auf den Bereich zeigen
+// kommt ohne Dokument aus
+
+// vor dem Aufruf muessen die Abs-Refs aktualisiert werden!
+ScRefUpdateRes ScRefUpdate::UpdateGrow( const ScRange& rArea, USHORT nGrowX, USHORT nGrowY,
+ ComplRefData& rRef )
+{
+ ScRefUpdateRes eRet = UR_NOTHING;
+
+ // in Y-Richtung darf die Ref auch eine Zeile weiter unten anfangen,
+ // falls ein Bereich Spaltenkoepfe enthaelt
+
+ BOOL bUpdateX = ( nGrowX &&
+ rRef.Ref1.nCol == rArea.aStart.Col() && rRef.Ref2.nCol == rArea.aEnd.Col() &&
+ rRef.Ref1.nRow >= rArea.aStart.Row() && rRef.Ref2.nRow <= rArea.aEnd.Row() &&
+ rRef.Ref1.nTab >= rArea.aStart.Tab() && rRef.Ref2.nTab <= rArea.aEnd.Tab() );
+ BOOL bUpdateY = ( nGrowY &&
+ rRef.Ref1.nCol >= rArea.aStart.Col() && rRef.Ref2.nCol <= rArea.aEnd.Col() &&
+ ( rRef.Ref1.nRow == rArea.aStart.Row() || rRef.Ref1.nRow == rArea.aStart.Row()+1 ) &&
+ rRef.Ref2.nRow == rArea.aEnd.Row() &&
+ rRef.Ref1.nTab >= rArea.aStart.Tab() && rRef.Ref2.nTab <= rArea.aEnd.Tab() );
+
+ if ( bUpdateX )
+ {
+ rRef.Ref2.nCol += nGrowX;
+ eRet = UR_UPDATED;
+ }
+ if ( bUpdateY )
+ {
+ rRef.Ref2.nRow += nGrowY;
+ eRet = UR_UPDATED;
+ }
+
+ return eRet;
+}
+
+ScRefUpdateRes ScRefUpdate::DoGrow( const ScRange& rArea, USHORT nGrowX, USHORT nGrowY,
+ ScRange& rRef )
+{
+ // wie UpdateGrow, nur mit Range statt RefData
+
+ ScRefUpdateRes eRet = UR_NOTHING;
+
+ BOOL bUpdateX = ( nGrowX &&
+ rRef.aStart.Col() == rArea.aStart.Col() && rRef.aEnd.Col() == rArea.aEnd.Col() &&
+ rRef.aStart.Row() >= rArea.aStart.Row() && rRef.aEnd.Row() <= rArea.aEnd.Row() &&
+ rRef.aStart.Tab() >= rArea.aStart.Tab() && rRef.aEnd.Tab() <= rArea.aEnd.Tab() );
+ BOOL bUpdateY = ( nGrowY &&
+ rRef.aStart.Col() >= rArea.aStart.Col() && rRef.aEnd.Col() <= rArea.aEnd.Col() &&
+ ( rRef.aStart.Row() == rArea.aStart.Row() || rRef.aStart.Row() == rArea.aStart.Row()+1 ) &&
+ rRef.aEnd.Row() == rArea.aEnd.Row() &&
+ rRef.aStart.Tab() >= rArea.aStart.Tab() && rRef.aEnd.Tab() <= rArea.aEnd.Tab() );
+
+ if ( bUpdateX )
+ {
+ rRef.aEnd.SetCol( rRef.aEnd.Col() + nGrowX );
+ eRet = UR_UPDATED;
+ }
+ if ( bUpdateY )
+ {
+ rRef.aEnd.SetRow( rRef.aEnd.Row() + nGrowY );
+ eRet = UR_UPDATED;
+ }
+
+ return eRet;
+}
+
+
+
diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
new file mode 100644
index 000000000000..2b8715a62db4
--- /dev/null
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -0,0 +1,592 @@
+/*************************************************************************
+ *
+ * $RCSfile: scmatrix.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:18 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+//------------------------------------------------------------------------
+
+#include <tools/debug.hxx>
+#include <math.h>
+
+#include "scmatrix.hxx"
+#include "global.hxx"
+
+//------------------------------------------------------------------------
+
+void ScMatrix::CreateMatrix(USHORT nC, USHORT nR) // nur fuer ctor
+{
+ nAnzCol = nC;
+ nAnzRow = nR;
+ if (nC == 0 || nR == 0)
+ {
+ DBG_ERROR("ScMatrix::CreateMatrix: Dimensionsfehler");
+ pMat = NULL;
+ }
+ else
+ pMat = new MatValue[nC*nR];
+ bIsString = NULL;
+}
+
+ScMatrix::~ScMatrix()
+{
+ if (bIsString)
+ {
+ USHORT nCount = nAnzCol * nAnzRow;
+ for (USHORT i = 0; i < nCount; i++)
+ if (bIsString[i])
+ delete pMat[i].pS;
+ delete [] bIsString;
+ }
+ delete [] pMat;
+}
+
+ScMatrix* ScMatrix::Clone() const
+{
+ ScMatrix* pScMat = new ScMatrix(nAnzCol, nAnzRow);
+ MatCopy(*pScMat);
+ return pScMat;
+}
+
+//
+// Dateiformat: USHORT Spalten, USHORT Zeilen, (Spalten*Zeilen) Eintraege:
+// BYTE Typ ( CELLTYPE_NONE, CELLTYPE_VALUE, CELLTYPE_STRING ); nichts, double oder String
+//
+
+ScMatrix::ScMatrix(SvStream& rStream)
+{
+ USHORT nC, nR;
+
+ rStream >> nC;
+ rStream >> nR;
+
+ CreateMatrix(nC, nR);
+ DBG_ASSERT( pMat, "pMat == NULL" );
+
+ String aMatStr;
+ rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
+ USHORT nCount = nC * nR;
+ for (USHORT i=0; i<nCount; i++)
+ {
+ BYTE nType;
+ rStream >> nType;
+ if ( nType == CELLTYPE_VALUE )
+ rStream >> pMat[i].fVal;
+ else
+ {
+ // fuer unbekannte Typen String lesen und vergessen (Leer-String)
+ // (Aufwaerts-Kompatibilitaet)
+
+ if ( nType != CELLTYPE_NONE )
+ rStream.ReadByteString( aMatStr, eCharSet );
+
+ if (!bIsString)
+ ResetIsString(); // String-Flags initialisieren
+ bIsString[i] = ( CELLTYPE_NONE ? SC_MATVAL_EMPTY : SC_MATVAL_STRING );
+
+ if ( nType == CELLTYPE_STRING )
+ pMat[i].pS = new String(aMatStr);
+ else
+ pMat[i].pS = new String; // leer
+ }
+ }
+}
+
+void ScMatrix::Store(SvStream& rStream) const
+{
+ if (!pMat)
+ {
+ rStream << (USHORT) 0;
+ rStream << (USHORT) 0;
+ DBG_ERROR("ScMatrix::Store: pMat == NULL");
+ return;
+ }
+
+ rStream << nAnzCol;
+ rStream << nAnzRow;
+
+ String aMatStr;
+ rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
+ USHORT nCount = nAnzCol * nAnzRow;
+ for (USHORT i=0; i<nCount; i++)
+ {
+ BYTE nType = CELLTYPE_VALUE;
+ if ( bIsString && bIsString[i] )
+ {
+ if ( pMat[i].pS )
+ aMatStr = *pMat[i].pS;
+ else
+ {
+ DBG_ERROR("ScMatrix::Store: pS == NULL");
+ aMatStr.Erase();
+ }
+
+ if ( bIsString[i] == SC_MATVAL_STRING )
+ nType = CELLTYPE_STRING;
+ else
+ nType = CELLTYPE_NONE;
+ }
+ rStream << nType;
+ if ( nType == CELLTYPE_VALUE )
+ rStream << pMat[i].fVal;
+ else if ( nType == CELLTYPE_STRING )
+ rStream.WriteByteString( aMatStr, eCharSet );
+ }
+}
+
+void ScMatrix::ResetIsString()
+{
+ USHORT nCount = nAnzCol * nAnzRow;
+ if (bIsString)
+ {
+ for (USHORT i = 0; i < nCount; i++)
+ if (bIsString[i])
+ delete pMat[i].pS;
+ }
+ else
+ bIsString = new BYTE[nCount];
+ memset( bIsString, 0, nCount * sizeof( BYTE ) );
+}
+
+void ScMatrix::PutDouble(double fVal, USHORT nC, USHORT nR)
+{
+ if (nC < nAnzCol && nR < nAnzRow)
+ pMat[nC*nAnzRow+nR].fVal = fVal;
+ else
+ DBG_ERROR("ScMatrix::PutDouble: Dimensionsfehler");
+}
+
+void ScMatrix::PutString(const String& rStr, USHORT nC, USHORT nR)
+{
+ if (nC < nAnzCol && nR < nAnzRow)
+ {
+ if (bIsString == NULL)
+ ResetIsString();
+ bIsString[nC*nAnzRow+nR] = SC_MATVAL_STRING;
+ pMat[nC*nAnzRow+nR].pS = new String(rStr);
+ }
+ else
+ DBG_ERROR("ScMatrix::PutString: Dimensionsfehler");
+}
+
+void ScMatrix::PutString(const String& rStr, USHORT nIndex)
+{
+ if (bIsString == NULL)
+ ResetIsString();
+ bIsString[nIndex] = SC_MATVAL_STRING;
+ pMat[nIndex].pS = new String(rStr);
+}
+
+void ScMatrix::PutEmpty(USHORT nC, USHORT nR)
+{
+ if (nC < nAnzCol && nR < nAnzRow)
+ {
+ if (bIsString == NULL)
+ ResetIsString();
+ bIsString[nC*nAnzRow+nR] = SC_MATVAL_EMPTY;
+ pMat[nC*nAnzRow+nR].pS = new String;
+ }
+ else
+ DBG_ERROR("ScMatrix::PutString: Dimensionsfehler");
+}
+
+void ScMatrix::PutEmpty(USHORT nIndex)
+{
+ if (bIsString == NULL)
+ ResetIsString();
+ bIsString[nIndex] = SC_MATVAL_EMPTY;
+ pMat[nIndex].pS = new String;
+}
+
+double ScMatrix::GetDouble(USHORT nC, USHORT nR) const
+{
+ if (nC < nAnzCol && nR < nAnzRow)
+ return pMat[nC*nAnzRow+nR].fVal;
+ else
+ {
+ DBG_ERROR("ScMatrix::GetDouble: Dimensionsfehler");
+ return 0.0;
+ }
+}
+
+const String& ScMatrix::GetString(USHORT nC, USHORT nR) const
+{
+ if (nC < nAnzCol && nR < nAnzRow)
+ {
+ if (bIsString && bIsString[nC*nAnzRow+nR])
+ return *(pMat[nC*nAnzRow+nR].pS);
+ else
+ DBG_ERROR("ScMatrix::GetString: Zugriffsfehler");
+ }
+ else
+ DBG_ERROR("ScMatrix::GetString: Dimensionsfehler");
+ return ScGlobal::GetEmptyString();
+}
+
+const MatValue* ScMatrix::Get(USHORT nC, USHORT nR, BOOL& bString) const
+{
+ if (nC < nAnzCol && nR < nAnzRow)
+ {
+ if (bIsString && bIsString[nC*nAnzRow+nR])
+ bString = TRUE;
+ else
+ bString = FALSE;
+ return &pMat[nC*nAnzRow+nR];
+ }
+ else
+ DBG_ERROR("ScMatrix::Get: Dimensionsfehler");
+ return NULL;
+}
+
+void ScMatrix::MatCopy(ScMatrix& mRes) const
+{
+ if (nAnzCol != mRes.nAnzCol || nAnzRow != mRes.nAnzRow)
+ {
+ DBG_ERROR("ScMatrix::MatCopy: Dimensionsfehler");
+ }
+ else
+ {
+ if (bIsString)
+ {
+ mRes.ResetIsString();
+ for (USHORT i = 0; i < nAnzCol; i++)
+ {
+ for (USHORT j = 0; j < nAnzRow; j++)
+ {
+ if (bIsString && bIsString[i*nAnzRow+j])
+ {
+ mRes.pMat[i*mRes.nAnzRow+j].pS =
+ new String(*(pMat[i*nAnzRow+j].pS));
+ mRes.bIsString[i*mRes.nAnzRow+j] = bIsString[i*nAnzRow+j];
+ }
+ else
+ mRes.pMat[i*mRes.nAnzRow+j].fVal =
+ pMat[i*nAnzRow+j].fVal;
+ }
+ }
+ }
+ else
+ {
+ for (USHORT i = 0; i < nAnzCol*nAnzRow; i++)
+ mRes.pMat[i].fVal = pMat[i].fVal;
+ }
+ }
+}
+
+void ScMatrix::MatTrans(ScMatrix& mRes) const
+{
+ if (nAnzCol != mRes.nAnzRow || nAnzRow != mRes.nAnzCol)
+ {
+ DBG_ERROR("ScMatrix::MatTrans: Dimensionsfehler");
+ }
+ else
+ {
+ if (bIsString)
+ {
+ mRes.ResetIsString();
+ for (USHORT i = 0; i < nAnzCol; i++)
+ {
+ for (USHORT j = 0; j < nAnzRow; j++)
+ {
+ if (bIsString && bIsString[i*nAnzRow+j])
+ {
+ mRes.pMat[j*mRes.nAnzRow+i].pS =
+ new String(*(pMat[i*nAnzRow+j].pS));
+ mRes.bIsString[j*mRes.nAnzRow+i] = bIsString[i*nAnzRow+j];
+ }
+ else
+ mRes.pMat[j*mRes.nAnzRow+i].fVal =
+ pMat[i*nAnzRow+j].fVal;
+ }
+ }
+ }
+ else
+ {
+ for (USHORT i = 0; i < nAnzCol; i++)
+ {
+ for (USHORT j = 0; j < nAnzRow; j++)
+ mRes.pMat[j*mRes.nAnzRow+i].fVal =
+ pMat[i*nAnzRow+j].fVal;
+ }
+ }
+ }
+}
+
+void ScMatrix::MatCopyUpperLeft(ScMatrix& mRes) const
+{
+ if (nAnzCol < mRes.nAnzCol || nAnzRow < mRes.nAnzRow)
+ {
+ DBG_ERROR("ScMatrix::MatCopyUpperLeft : Dimensionsfehler");
+ }
+ else
+ {
+ if (bIsString)
+ {
+ mRes.ResetIsString();
+ for (USHORT i = 0; i < mRes.nAnzCol; i++)
+ {
+ for (USHORT j = 0; j < mRes.nAnzRow; j++)
+ {
+ if (bIsString && bIsString[i*nAnzRow+j])
+ {
+ mRes.pMat[i*mRes.nAnzRow+j].pS =
+ new String(*(pMat[i*nAnzRow+j].pS));
+ mRes.bIsString[i*mRes.nAnzRow+j] = bIsString[i*nAnzRow+j];
+ }
+ else
+ mRes.pMat[i*mRes.nAnzRow+j].fVal =
+ pMat[i*nAnzRow+j].fVal;
+ }
+ }
+ }
+ else
+ {
+ for (USHORT i = 0; i < mRes.nAnzCol; i++)
+ {
+ for (USHORT j = 0; j < mRes.nAnzRow; j++)
+ mRes.pMat[i*mRes.nAnzRow+j].fVal =
+ pMat[i*nAnzRow+j].fVal;
+ }
+ }
+ }
+}
+
+void ScMatrix::FillDouble( double fVal, USHORT nC1, USHORT nR1,
+ USHORT nC2, USHORT nR2 )
+{
+ if (nC2 < nAnzCol && nR2 < nAnzRow)
+ {
+ if ( nC1 == 0 && nR1 == 0 && nC2 == nAnzCol-1 && nR2 == nAnzRow-1 )
+ {
+ USHORT nEnd = nAnzCol * nAnzRow;
+ for ( USHORT j=0; j<nEnd; j++ )
+ pMat[j].fVal = fVal;
+ }
+ else
+ {
+ for ( USHORT i=nC1; i<=nC2; i++ )
+ {
+ USHORT nOff1 = i * nAnzRow + nR1;
+ USHORT nOff2 = nOff1 + nR2 - nR1;
+ for ( USHORT j=nOff1; j<=nOff2; j++ )
+ pMat[j].fVal = fVal;
+ }
+ }
+ }
+ else
+ DBG_ERROR("ScMatrix::FillDouble: Dimensionsfehler");
+}
+
+void ScMatrix::FillDoubleLowerLeft( double fVal, USHORT nC2 )
+{
+ if (nC2 < nAnzCol && nC2 < nAnzRow)
+ {
+ for ( USHORT i=1; i<=nC2; i++ )
+ {
+ USHORT nOff1 = i * nAnzRow;
+ USHORT nOff2 = nOff1 + i;
+ for ( USHORT j=nOff1; j<nOff2; j++ )
+ pMat[j].fVal = fVal;
+ }
+ }
+ else
+ DBG_ERROR("ScMatrix::FillDoubleLowerLeft: Dimensionsfehler");
+}
+
+void ScMatrix::CompareEqual()
+{
+ USHORT n = nAnzCol * nAnzRow;
+ if ( bIsString )
+ {
+ for ( USHORT j=0; j<n; j++ )
+ if ( !bIsString[j]) // else: #WERT!
+ pMat[j].fVal = (pMat[j].fVal == 0.0);
+ }
+ else
+ {
+ for ( USHORT j=0; j<n; j++ )
+ pMat[j].fVal = (pMat[j].fVal == 0.0);
+ }
+}
+
+void ScMatrix::CompareNotEqual()
+{
+ USHORT n = nAnzCol * nAnzRow;
+ if ( bIsString )
+ {
+ for ( USHORT j=0; j<n; j++ )
+ if ( !bIsString[j]) // else: #WERT!
+ pMat[j].fVal = (pMat[j].fVal != 0.0);
+ }
+ else
+ {
+ for ( USHORT j=0; j<n; j++ )
+ pMat[j].fVal = (pMat[j].fVal != 0.0);
+ }
+}
+
+void ScMatrix::CompareLess()
+{
+ USHORT n = nAnzCol * nAnzRow;
+ if ( bIsString )
+ {
+ for ( USHORT j=0; j<n; j++ )
+ if ( !bIsString[j]) // else: #WERT!
+ pMat[j].fVal = (pMat[j].fVal < 0.0);
+ }
+ else
+ {
+ for ( USHORT j=0; j<n; j++ )
+ pMat[j].fVal = (pMat[j].fVal < 0.0);
+ }
+}
+
+void ScMatrix::CompareGreater()
+{
+ USHORT n = nAnzCol * nAnzRow;
+ if ( bIsString )
+ {
+ for ( USHORT j=0; j<n; j++ )
+ if ( !bIsString[j]) // else: #WERT!
+ pMat[j].fVal = (pMat[j].fVal > 0.0);
+ }
+ else
+ {
+ for ( USHORT j=0; j<n; j++ )
+ pMat[j].fVal = (pMat[j].fVal > 0.0);
+ }
+}
+
+void ScMatrix::CompareLessEqual()
+{
+ USHORT n = nAnzCol * nAnzRow;
+ if ( bIsString )
+ {
+ for ( USHORT j=0; j<n; j++ )
+ if ( !bIsString[j]) // else: #WERT!
+ pMat[j].fVal = (pMat[j].fVal <= 0.0);
+ }
+ else
+ {
+ for ( USHORT j=0; j<n; j++ )
+ pMat[j].fVal = (pMat[j].fVal <= 0.0);
+ }
+}
+
+void ScMatrix::CompareGreaterEqual()
+{
+ USHORT n = nAnzCol * nAnzRow;
+ if ( bIsString )
+ {
+ for ( USHORT j=0; j<n; j++ )
+ if ( !bIsString[j]) // else: #WERT!
+ pMat[j].fVal = (pMat[j].fVal >= 0.0);
+ }
+ else
+ {
+ for ( USHORT j=0; j<n; j++ )
+ pMat[j].fVal = (pMat[j].fVal >= 0.0);
+ }
+}
+
+BOOL ScMatrix::And()
+{
+ USHORT n = nAnzCol * nAnzRow;
+ BOOL bAnd = TRUE;
+ if ( bIsString )
+ {
+ for ( USHORT j=0; bAnd && j<n; j++ )
+ if ( bIsString[j] )
+ bAnd = FALSE; // wir gehen hier von einer CompareMat aus
+ else
+ bAnd &= (pMat[j].fVal != 0.0);
+ }
+ else
+ {
+ for ( USHORT j=0; bAnd && j<n; j++ )
+ bAnd &= (pMat[j].fVal != 0.0);
+ }
+ return bAnd;
+}
+
+BOOL ScMatrix::Or()
+{
+ USHORT n = nAnzCol * nAnzRow;
+ BOOL bOr = FALSE;
+ if ( bIsString )
+ {
+ for ( USHORT j=0; !bOr && j<n; j++ )
+ if ( !bIsString[j] )
+ bOr |= (pMat[j].fVal != 0.0);
+ }
+ else
+ {
+ for ( USHORT j=0; !bOr && j<n; j++ )
+ bOr |= (pMat[j].fVal != 0.0);
+ }
+ return bOr;
+}
+
+
+
diff --git a/sc/source/core/tool/sctictac.cxx b/sc/source/core/tool/sctictac.cxx
new file mode 100644
index 000000000000..bc69cf36d6bb
--- /dev/null
+++ b/sc/source/core/tool/sctictac.cxx
@@ -0,0 +1,581 @@
+/*************************************************************************
+ *
+ * $RCSfile: sctictac.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:18 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+/* Tic-Tac-Toe program by Steve Chapel schapel@cs.ucsb.edu
+ Uses alpha-beta pruning minimax search to play a "perfect" game.
+ The alpha-beta pruning can be removed, but will increase search time.
+ The heuristic and move ordering in BestMove() can also be removed with
+ an increase in search time. */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#pragma hdrstop
+
+#include "sctictac.hxx"
+
+#ifdef TICTACTOE_SC
+#include "document.hxx"
+#include "cell.hxx"
+#endif
+
+const Square_Type ScTicTacToe::Empty = ' ';
+const Square_Type ScTicTacToe::Human = 'X';
+const Square_Type ScTicTacToe::Compi = 'O';
+const int ScTicTacToe::Infinity = 10; /* Higher value than any score */
+const int ScTicTacToe::Maximum_Moves = ScTicTacToe_Squares; /* Maximum moves in a game */
+
+/* Array describing the eight combinations of three squares in a row */
+const int ScTicTacToe::Three_in_a_Row[ScTicTacToe_Possible_Wins][3] = {
+ { 0, 1, 2 },
+ { 3, 4, 5 },
+ { 6, 7, 8 },
+ { 0, 3, 6 },
+ { 1, 4, 7 },
+ { 2, 5, 8 },
+ { 0, 4, 8 },
+ { 2, 4, 6 }
+};
+
+/* Array used in heuristic formula for each move. */
+const int ScTicTacToe::Heuristic_Array[4][4] = {
+ { 0, -10, -100, -1000 },
+ { 10, 0, 0, 0 },
+ { 100, 0, 0, 0 },
+ { 1000, 0, 0, 0 }
+};
+
+
+#ifdef TICTACTOE_SC
+ScTicTacToe::ScTicTacToe( ScDocument* pDocP, const ScAddress& rPos ) :
+ pDoc( pDocP ),
+ aPos( rPos ),
+ bInitialized( FALSE ),
+ aStdOut( "Computer plays O, you play X. " )
+{
+}
+#else
+ScTicTacToe::ScTicTacToe() :
+ bInitialized( FALSE ),
+ aStdOut( "Computer plays O, you play X. " )
+{
+}
+#endif
+
+
+/* Return the other player */
+inline Square_Type ScTicTacToe::Other(Square_Type Player)
+{
+ return Player == Human ? Compi : Human;
+}
+
+
+/* Make a move on the board */
+inline void ScTicTacToe::Play(int Square, Square_Type Player)
+{
+ Board[Square] = Player;
+}
+
+
+#ifdef TICTACTOE_STDOUT
+
+void ScTicTacToe::GetOutput( ByteString& rStr )
+{
+ rStr = aStdOut;
+ aStdOut.Erase();
+}
+
+#else // !TICTACTOE_STDOUT
+
+void ScTicTacToe::GetOutput( String& rStr )
+{
+ rStr = String( aStdOut, gsl_getSystemTextEncoding() );
+ aStdOut.Erase();
+}
+
+#endif // TICTACTOE_STDOUT
+
+
+/* Clear the board */
+void ScTicTacToe::Initialize( BOOL bHumanFirst )
+{
+ bInitialized = TRUE;
+ aPlayer = (bHumanFirst ? Human : Compi);
+ nMove = 1;
+ for (int i = 0; i < ScTicTacToe_Squares; i++)
+ Board[i] = Empty;
+}
+
+
+/* If a player has won, return the winner. If the game is a tie,
+ return 'C' (for cat). If the game is not over, return Empty. */
+Square_Type ScTicTacToe::Winner()
+{
+ int i;
+ for (i = 0; i < ScTicTacToe_Possible_Wins; i++)
+ {
+ Square_Type Possible_Winner = Board[Three_in_a_Row[i][0]];
+ if (Possible_Winner != Empty &&
+ Possible_Winner == Board[Three_in_a_Row[i][1]] &&
+ Possible_Winner == Board[Three_in_a_Row[i][2]])
+ return Possible_Winner;
+ }
+
+ for (i = 0; i < ScTicTacToe_Squares; i++)
+ {
+ if (Board[i] == Empty)
+ return Empty;
+ }
+
+ return 'C';
+}
+
+
+/* Return a heuristic used to determine the order in which the
+ children of a node are searched */
+int ScTicTacToe::Evaluate(Square_Type Player)
+{
+ int i;
+ int Heuristic = 0;
+ for (i = 0; i < ScTicTacToe_Possible_Wins; i++)
+ {
+ int j;
+ int Players = 0, Others = 0;
+ for (j = 0; j < 3; j++)
+ {
+ Square_Type Piece = Board[Three_in_a_Row[i][j]];
+ if (Piece == Player)
+ Players++;
+ else if (Piece == Other(Player))
+ Others++;
+ }
+ Heuristic += Heuristic_Array[Players][Others];
+ }
+ return Heuristic;
+}
+
+
+/* Return the score of the best move found for a board
+ The square to move to is returned in *Square */
+int ScTicTacToe::BestMove(Square_Type Player, int *Square,
+ int Move_Nbr, int Alpha, int Beta)
+{
+ int Best_Square = -1;
+ int Moves = 0;
+ int i;
+ Move_Heuristic_Type Move_Heuristic[ScTicTacToe_Squares];
+
+ Total_Nodes++;
+
+ /* Find the heuristic for each move and sort moves in descending order */
+ for (i = 0; i < ScTicTacToe_Squares; i++)
+ {
+ if (Board[i] == Empty)
+ {
+ int Heuristic;
+ int j;
+ Play(i, Player);
+ Heuristic = Evaluate(Player);
+ Play(i, Empty);
+ for (j = Moves-1; j >= 0 &&
+ Move_Heuristic[j].Heuristic < Heuristic; j--)
+ {
+ Move_Heuristic[j + 1].Heuristic = Move_Heuristic[j].Heuristic;
+ Move_Heuristic[j + 1].Square = Move_Heuristic[j].Square;
+ }
+ Move_Heuristic[j + 1].Heuristic = Heuristic;
+ Move_Heuristic[j + 1].Square = i;
+ Moves++;
+ }
+ }
+
+ for (i = 0; i < Moves; i++)
+ {
+ int Score;
+ int Sq = Move_Heuristic[i].Square;
+ Square_Type W;
+
+ /* Make a move and get its score */
+ Play(Sq, Player);
+
+ W = Winner();
+ if (W == Compi)
+ Score = (Maximum_Moves + 1) - Move_Nbr;
+ else if (W == Human)
+ Score = Move_Nbr - (Maximum_Moves + 1);
+ else if (W == 'C')
+ Score = 0;
+ else
+ Score = BestMove(Other(Player), Square, Move_Nbr + 1,
+ Alpha, Beta);
+
+ Play(Sq, Empty);
+
+ /* Perform alpha-beta pruning */
+ if (Player == Compi)
+ {
+ if (Score >= Beta)
+ {
+ *Square = Sq;
+ return Score;
+ }
+ else if (Score > Alpha)
+ {
+ Alpha = Score;
+ Best_Square = Sq;
+ }
+ }
+ else
+ {
+ if (Score <= Alpha)
+ {
+ *Square = Sq;
+ return Score;
+ }
+ else if (Score < Beta)
+ {
+ Beta = Score;
+ Best_Square = Sq;
+ }
+ }
+ }
+ *Square = Best_Square;
+ if (Player == Compi)
+ return Alpha;
+ else
+ return Beta;
+}
+
+
+/* Provide an English description of the score returned by BestMove */
+void ScTicTacToe::Describe(int Score)
+{
+ if (Score < 0)
+ aStdOut += "You have a guaranteed win. ";
+ else if (Score == 0)
+ aStdOut += "I can guarantee a tie. ";
+ else
+ {
+ aStdOut += "I have a guaranteed win by move ";
+ aStdOut += ByteString::CreateFromInt32( Maximum_Moves - Score + 1 );
+ aStdOut += ". ";
+ }
+}
+
+
+/* Have the human or the computer move */
+void ScTicTacToe::Move( int& Square )
+{
+ if (aPlayer == Compi)
+ {
+ Total_Nodes = 0;
+ Describe(BestMove(aPlayer, &Square, nMove, -Infinity, Infinity));
+ aStdOut += ByteString::CreateFromInt32( Total_Nodes );
+ aStdOut += " nodes examined. ";
+ Play(Square, aPlayer);
+ aStdOut += "Move #";
+ aStdOut += ByteString::CreateFromInt32( nMove );
+ aStdOut += " - O moves to ";
+ aStdOut += ByteString::CreateFromInt32( Square + 1 );
+ aStdOut += ". ";
+ aPlayer = Other( aPlayer );
+ nMove++;
+ }
+ else
+ {
+ if ( Square < 0 || Square >= ScTicTacToe_Squares
+ || Board[Square] != Empty )
+ Square = -1;
+ else
+ {
+ Play(Square, aPlayer);
+ aPlayer = Other( aPlayer );
+ nMove++;
+ }
+ }
+}
+
+
+// Try a move
+Square_Type ScTicTacToe::TryMove( int& Square )
+{
+ if ( !bInitialized )
+ Initialize( FALSE );
+
+ Square_Type W = Winner();
+ if ( W == Empty )
+ {
+ Move( Square );
+#ifdef TICTACTOE_STDOUT
+ if ( aStdOut.Len() )
+ {
+ puts( aStdOut.GetBuffer() );
+ aStdOut.Erase();
+ }
+#endif
+ W = Winner();
+ }
+ if ( W == Empty )
+ {
+ if ( aPlayer == Human )
+ PromptHuman();
+ }
+ else
+ {
+ if (W != 'C')
+ {
+ aStdOut += W;
+ aStdOut += " wins!";
+ }
+ else
+ aStdOut += "It's a tie.";
+ }
+ return W;
+}
+
+
+void ScTicTacToe::PromptHuman()
+{
+ aStdOut += "Move #";
+ aStdOut += ByteString::CreateFromInt32( nMove );
+ aStdOut += " - What is X's move?";
+}
+
+
+#ifdef TICTACTOE_SC
+
+void ScTicTacToe::DrawPos( int nSquare, const String& rStr )
+{
+ pDoc->SetString( aPos.Col()+(nSquare%3),
+ aPos.Row()+(nSquare/3), aPos.Tab(), rStr );
+}
+
+
+void ScTicTacToe::DrawBoard()
+{
+ String aStr;
+ for ( USHORT j = 0; j < ScTicTacToe_Squares; j++ )
+ {
+ aStr = Board[j];
+ DrawPos( j, aStr );
+ }
+}
+
+
+// -1 == Fehler/Redraw, 0 == keine Aenderung, >0 == UserMoveSquare+1
+int ScTicTacToe::GetStatus()
+{
+ USHORT nCol, nRow, nTab;
+ nCol = aPos.Col();
+ nRow = aPos.Row();
+ nTab = aPos.Tab();
+ String aStr;
+ int nDiffs = 0;
+ int nSquare;
+ for ( USHORT j = 0; j < ScTicTacToe_Squares; j++ )
+ {
+ pDoc->GetString( nCol+(j%3), nRow+(j/3), nTab, aStr );
+ if ( !aStr.Len() )
+ {
+ if ( Board[j] != Empty )
+ return -1; // wo was sein muss muss was sein
+ }
+ else
+ {
+ aStr.ToUpperAscii();
+ if ( aStr.GetChar(0) != Board[j] )
+ {
+ if ( Board[j] != Empty )
+ return -1; // bestehendes ueberschrieben
+ // bei erstem Move hat Human angefangen
+ if ( ++nDiffs > 1 )
+ return -1; // mehr als eine Aenderung
+ nSquare = j;
+ }
+ }
+ }
+ if ( nDiffs == 1 )
+ return nSquare + 1;
+ return 0;
+}
+
+
+Square_Type ScTicTacToe::CalcMove()
+{
+ Square_Type W = Winner();
+ int nStat = GetStatus();
+ if ( nStat || (W == Empty && aPlayer == Compi) )
+ {
+ if ( nStat == -1 || (nStat > 0 && aPlayer == Compi) )
+ DrawBoard();
+ if ( W == Empty && aPlayer == Human )
+ {
+ if ( nStat > 0 )
+ {
+ int nSquare = --nStat;
+ W = TryMove( nStat );
+ if ( nStat == -1 )
+ DrawPos( nSquare, String( ' ' ) );
+ else
+ DrawPos( nStat, String( Human ) );
+ }
+ else
+ PromptHuman();
+ }
+ if ( W == Empty && aPlayer == Compi )
+ {
+ W = TryMove( nStat ); // ComputerMove, nStat egal
+ DrawPos( nStat, String( Compi ) );
+ }
+ }
+ else if ( W == Empty && aPlayer == Human )
+ PromptHuman();
+ return W;
+}
+
+#endif // TICTACTOE_SC
+
+
+#ifdef TICTACTOE_STDOUT
+/* Print the board */
+void ScTicTacToe::Print()
+{
+ int i;
+ for (i = 0; i < ScTicTacToe_Squares; i += 3)
+ {
+ if (i > 0)
+ printf("---+---+---\n");
+ printf(" %c | %c | %c \n", Board[i], Board[i + 1], Board[i + 2]);
+ }
+ printf("\n");
+}
+
+
+/* Play a game of tic-tac-toe */
+void ScTicTacToe::Game()
+{
+ if ( !bInitialized )
+ Initialize( FALSE );
+
+ int Square = (aPlayer == Compi ? 0 : -1);
+ Square_Type W = Winner();
+ while( W == Empty )
+ {
+ Print();
+ W = TryMove( Square );
+ if ( W == Empty )
+ {
+ if ( aPlayer == Human )
+ {
+ if ( Square != -1 )
+ Print(); // empty board already printed if human moves first
+ do
+ {
+ puts( aStdOut.GetBuffer() );
+ aStdOut.Erase();
+ scanf("%d", &Square);
+ Square--;
+ W = TryMove( Square );
+ } while ( Square == -1 );
+ }
+ }
+ }
+ Print();
+ puts( aStdOut.GetBuffer() );
+ aStdOut.Erase();
+}
+#endif // TICTACTOE_STDOUT
+
+
+#ifdef TICTACTOE_MAIN
+int main()
+{
+ char Answer[80];
+
+ printf("Welcome to Tic-Tac-Toe!\n\n");
+ printf("Here is the board numbering:\n");
+ printf(" 1 | 2 | 3\n");
+ printf("---+---+---\n");
+ printf(" 4 | 5 | 6\n");
+ printf("---+---+---\n");
+ printf(" 7 | 8 | 9\n");
+ printf("\n");
+// printf("Computer plays X, you play O.\n");
+
+ ScTicTacToe aTTT;
+ ByteString aStr;
+ aTTT.GetOutput( aStr );
+ puts( aStr.GetBuffer() );
+
+ do
+ {
+ printf("\nDo you want to move first? ");
+ scanf("%s", Answer);
+ aTTT.Initialize( toupper(Answer[0]) == 'Y' );
+ aTTT.Game();
+ printf("\nDo you want to play again? ");
+ scanf("%s", Answer);
+ } while (toupper(Answer[0]) == 'Y');
+
+ return 0;
+}
+#endif // TICTACTOE_MAIN
+
diff --git a/sc/source/core/tool/subtotal.cxx b/sc/source/core/tool/subtotal.cxx
new file mode 100644
index 000000000000..dd2ce58b6ae1
--- /dev/null
+++ b/sc/source/core/tool/subtotal.cxx
@@ -0,0 +1,541 @@
+/*************************************************************************
+ *
+ * $RCSfile: subtotal.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:19 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+// INCLUDE ---------------------------------------------------------------
+
+#ifdef RS6000
+
+#pragma options FLTTRAP
+#include <fptrap.h>
+#include <fpxcp.h>
+
+#elif defined ( MAC )
+
+#include <MAC_START.h>
+#include <fp.h>
+#include <MAC_END.h>
+
+#endif
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include <float.h>
+#include <math.h>
+#ifdef SOLARIS
+#include <ieeefp.h>
+#endif
+#include <signal.h>
+#include "segmentc.hxx"
+
+#include "subtotal.hxx"
+#include "interpre.hxx"
+
+#include "scdll.hxx" // ScLibSignalFunc
+
+// STATIC DATA -----------------------------------------------------------
+
+jmp_buf SubTotal::aGlobalJumpBuf;
+
+SEG_EOFGLOBALS()
+
+// -----------------------------------------------------------------------
+#pragma SEG_FUNCDEF(subtotal_01)
+
+SubTotal::SubTotal()
+{
+ nIndex = 0; //! test fuer Pivot
+
+ nCount = 0;
+ nCount2 = 0;
+ nSum = 0.0;
+ nSumSqr = 0.0;
+ nMax = -MAXDOUBLE;
+ nMin = MAXDOUBLE;
+ nProduct = 1.0;
+ bSumOk = TRUE;
+ bSumSqrOk = TRUE;
+ bProductOk = TRUE;
+}
+
+#pragma SEG_FUNCDEF(subtotal_07)
+
+SubTotal::~SubTotal()
+{
+}
+
+#pragma SEG_FUNCDEF(subtotal_02)
+
+void SubTotal::UpdateNoVal()
+{
+ nCount++;
+}
+
+#pragma SEG_FUNCDEF(subtotal_03)
+
+void SubTotal::Update( double nVal )
+{
+ SOMA_FPCONTROL(); // FP-Exceptions ein-/ausschalten
+#if SOMA_FPSIGNAL_JUMP
+ ScSigCatchFunc pOldSigFunc = (ScInterpreter::pSignalFunc)( SC_SIGFPE, ScInterpreter::MySigFunc );
+ jmp_buf* pSaveBuf = ScInterpreter::pJumpBuf;
+ ScInterpreter::pJumpBuf = &aGlobalJumpBuf;
+ if (setjmp(aGlobalJumpBuf))
+ {
+ if (nProgress == 0)
+ {
+ bSumOk = FALSE;
+ bProductOk = FALSE;
+ bSumSqrOk = FALSE;
+ }
+ else if (nProgress == 1)
+ {
+ bProductOk = FALSE;
+ bSumSqrOk = FALSE;
+ }
+ else
+ {
+ bSumSqrOk = FALSE;
+ DBG_ASSERT(nProgress == 2,"subtotal.cxx: Update(1)");
+ }
+ }
+ else
+#endif // SOMA_FPSIGNAL_JUMP
+ {
+ nCount++;
+ nCount2++;
+ if (nVal > nMax) nMax = nVal;
+ if (nVal < nMin) nMin = nVal;
+ nProgress = 0;
+ if (bSumOk) nSum += nVal;
+ nProgress = 1;
+ if (bProductOk) nProduct *= nVal;
+ nProgress = 2;
+ if (bSumSqrOk) nSumSqr += nVal*nVal;
+ }
+#if !SOMA_FPSIGNAL_JUMP
+ if (!SOMA_FINITE(nSum))
+ bSumOk = FALSE;
+ if (!SOMA_FINITE(nProduct))
+ bProductOk = FALSE;
+ if (!SOMA_FINITE(nSumSqr))
+ bSumSqrOk = FALSE;
+#else // SOMA_FPSIGNAL_JUMP
+ ScInterpreter::pJumpBuf = pSaveBuf;
+ (ScInterpreter::pSignalFunc)( SC_SIGFPE, pOldSigFunc );
+#endif
+}
+
+#pragma SEG_FUNCDEF(subtotal_04)
+
+void SubTotal::Update( const SubTotal& rVal )
+{
+ SOMA_FPCONTROL(); // FP-Exceptions ein-/ausschalten
+#if SOMA_FPSIGNAL_JUMP
+ ScSigCatchFunc pOldSigFunc = (ScInterpreter::pSignalFunc)( SC_SIGFPE, ScInterpreter::MySigFunc );
+ jmp_buf* pSaveBuf = ScInterpreter::pJumpBuf;
+ ScInterpreter::pJumpBuf = &aGlobalJumpBuf;
+ if (setjmp(aGlobalJumpBuf))
+ {
+ if (nProgress == 0)
+ {
+ bSumOk = FALSE;
+ bProductOk = FALSE;
+ bSumSqrOk = FALSE;
+ }
+ else if (nProgress == 1)
+ {
+ bProductOk = FALSE;
+ bSumSqrOk = FALSE;
+ }
+ else
+ {
+ DBG_ASSERT(nProgress == 2,"subtotal.cxx: Update(2)");
+ bSumSqrOk = FALSE;
+ }
+ }
+ else
+#endif // SOMA_FPSIGNAL_JUMP
+ {
+ nCount += rVal.nCount;
+ nCount2 += rVal.nCount2;
+ if (rVal.nMax > nMax) nMax = rVal.nMax;
+ if (rVal.nMin < nMin) nMin = rVal.nMin;
+ nProgress = 0;
+ if (rVal.bSumOk && bSumOk)
+ nSum += rVal.nSum;
+ else
+ bSumOk = FALSE;
+ nProgress = 1;
+ if (rVal.bProductOk && bProductOk)
+ nProduct *= rVal.nProduct;
+ else
+ bProductOk = FALSE;
+ nProgress = 2;
+ if (rVal.bSumSqrOk && bSumSqrOk)
+ nSumSqr += rVal.nSumSqr;
+ else
+ bSumSqrOk = FALSE;
+ }
+#if !SOMA_FPSIGNAL_JUMP
+ if (!SOMA_FINITE(nSum))
+ bSumOk = FALSE;
+ if (!SOMA_FINITE(nProduct))
+ bProductOk = FALSE;
+ if (!SOMA_FINITE(nSumSqr))
+ bSumSqrOk = FALSE;
+#else // SOMA_FPSIGNAL_JUMP
+ ScInterpreter::pJumpBuf = pSaveBuf;
+ (ScInterpreter::pSignalFunc)( SC_SIGFPE, pOldSigFunc );
+#endif
+}
+
+#pragma SEG_FUNCDEF(subtotal_05)
+
+short SubTotal::Valid( USHORT nFunction ) const
+ // return 0 => Fehler, -1 => kein Wert, 1 => ok
+{
+ short nRet;
+ switch (nFunction)
+ {
+ case PIVOT_FUNC_AVERAGE:
+ if (nCount2 == 0)
+ nRet = -1;
+ else
+ nRet = bSumOk;
+ break;
+ case PIVOT_FUNC_STD_DEVP:
+ case PIVOT_FUNC_STD_VARP:
+ if (nCount2 == 0)
+ nRet = -1;
+ else
+ nRet = bSumSqrOk;
+ break;
+ case PIVOT_FUNC_STD_DEV:
+ case PIVOT_FUNC_STD_VAR:
+ if (nCount2 < 2)
+ nRet = -1;
+ else
+ nRet = bSumSqrOk;
+ break;
+ case PIVOT_FUNC_MAX:
+ if (nCount2 == 0)
+ nRet = -1;
+ else
+ nRet = 1;
+ break;
+ case PIVOT_FUNC_MIN:
+ if (nCount2 == 0)
+ nRet = -1;
+ else
+ nRet = 1;
+ break;
+ case PIVOT_FUNC_SUM:
+ if (nCount2 == 0)
+ nRet = -1;
+ else
+ nRet = bSumOk;
+ break;
+ case PIVOT_FUNC_PRODUCT:
+ if (nCount2 == 0)
+ nRet = -1;
+ else
+ nRet = bProductOk;
+ break;
+ default:
+ nRet = 1;
+ break;
+ }
+ return nRet;
+}
+
+#pragma SEG_FUNCDEF(subtotal_06)
+
+double SubTotal::Result( USHORT nFunction ) const
+{
+ double nRet = 0.0;
+ switch (nFunction)
+ {
+ case PIVOT_FUNC_COUNT: nRet = (double) nCount; break;
+ case PIVOT_FUNC_COUNT_NUM: nRet = (double) nCount2; break;
+ case PIVOT_FUNC_SUM: nRet = nSum; break;
+ case PIVOT_FUNC_MAX: nRet = nMax; break;
+ case PIVOT_FUNC_MIN: nRet = nMin; break;
+ case PIVOT_FUNC_PRODUCT: nRet = nProduct; break;
+ case PIVOT_FUNC_AVERAGE:
+ if (nCount2 > 0)
+ nRet = nSum / (double) nCount2;
+ break;
+ case PIVOT_FUNC_STD_DEV:
+ if (nCount2 > 1)
+ nRet = sqrt((nSumSqr - nSum*nSum/(double)(nCount2))
+ / (double)(nCount2-1));
+ break;
+ case PIVOT_FUNC_STD_DEVP:
+ if (nCount2 > 0)
+ nRet = sqrt((nSumSqr - nSum*nSum/(double)(nCount2))
+ / (double)nCount2);
+ break;
+ case PIVOT_FUNC_STD_VAR:
+ if (nCount2 > 1)
+ nRet = (nSumSqr - nSum*nSum/(double)(nCount2))
+ / (double)(nCount2-1);
+ break;
+ case PIVOT_FUNC_STD_VARP:
+ if (nCount2 > 0)
+ nRet = (nSumSqr - nSum*nSum/(double)(nCount2))
+ / (double)(nCount2);
+ break;
+ default:
+ DBG_ERROR("unbekannte Funktion bei SubTotal::Result");
+ }
+ return nRet;
+}
+
+#pragma SEG_FUNCDEF(subtotal_08)
+
+BOOL SubTotal::SafePlus(double& fVal1, double fVal2)
+{
+ BOOL bOk = TRUE;
+ SOMA_FPCONTROL(); // FP-Exceptions ein-/ausschalten
+#if SOMA_FPSIGNAL_JUMP
+ ScSigCatchFunc pOldSigFunc = (ScInterpreter::pSignalFunc)( SC_SIGFPE, ScInterpreter::MySigFunc );
+ jmp_buf* pSaveBuf = ScInterpreter::pJumpBuf;
+ ScInterpreter::pJumpBuf = &aGlobalJumpBuf;
+ if (setjmp(aGlobalJumpBuf))
+ {
+ bOk = FALSE;
+ if (fVal2 > 0.0)
+ fVal1 = DBL_MAX;
+ else
+ fVal1 = -DBL_MAX;
+ }
+ else
+#endif // SOMA_FPSIGNAL_JUMP
+ fVal1 += fVal2;
+#if !SOMA_FPSIGNAL_JUMP
+ if (!SOMA_FINITE(fVal1))
+ {
+ bOk = FALSE;
+ if (fVal2 > 0.0)
+ fVal1 = DBL_MAX;
+ else
+ fVal1 = -DBL_MAX;
+ }
+#else // SOMA_FPSIGNAL_JUMP
+ ScInterpreter::pJumpBuf = pSaveBuf;
+ (ScInterpreter::pSignalFunc)( SC_SIGFPE, pOldSigFunc );
+#endif
+ return bOk;
+}
+
+#pragma SEG_FUNCDEF(subtotal_09)
+
+BOOL SubTotal::SafeMult(double& fVal1, double fVal2)
+{
+ BOOL bOk = TRUE;
+ SOMA_FPCONTROL(); // FP-Exceptions ein-/ausschalten
+#if SOMA_FPSIGNAL_JUMP
+ ScSigCatchFunc pOldSigFunc = (ScInterpreter::pSignalFunc)( SC_SIGFPE, ScInterpreter::MySigFunc );
+ jmp_buf* pSaveBuf = ScInterpreter::pJumpBuf;
+ ScInterpreter::pJumpBuf = &aGlobalJumpBuf;
+ if (setjmp(aGlobalJumpBuf))
+ {
+ bOk = FALSE;
+ fVal1 = DBL_MAX;
+ }
+ else
+#endif // SOMA_FPSIGNAL_JUMP
+ fVal1 *= fVal2;
+#if !SOMA_FPSIGNAL_JUMP
+ if (!SOMA_FINITE(fVal1))
+ {
+ bOk = FALSE;
+ fVal1 = DBL_MAX;
+ }
+#else // SOMA_FPSIGNAL_JUMP
+ ScInterpreter::pJumpBuf = pSaveBuf;
+ (ScInterpreter::pSignalFunc)( SC_SIGFPE, pOldSigFunc );
+#endif
+ return bOk;
+}
+
+#pragma SEG_FUNCDEF(subtotal_0a)
+
+BOOL SubTotal::SafeDiv(double& fVal1, double fVal2)
+{
+ BOOL bOk = TRUE;
+ SOMA_FPCONTROL(); // FP-Exceptions ein-/ausschalten
+#if SOMA_FPSIGNAL_JUMP
+ ScSigCatchFunc pOldSigFunc = (ScInterpreter::pSignalFunc)( SC_SIGFPE, ScInterpreter::MySigFunc );
+ jmp_buf* pSaveBuf = ScInterpreter::pJumpBuf;
+ ScInterpreter::pJumpBuf = &aGlobalJumpBuf;
+ if (setjmp(aGlobalJumpBuf))
+ {
+ bOk = FALSE;
+ fVal1 = DBL_MAX;
+ }
+ else
+#endif // SOMA_FPSIGNAL_JUMP
+ fVal1 /= fVal2;
+#if !SOMA_FPSIGNAL_JUMP
+ if (!SOMA_FINITE(fVal1))
+ {
+ bOk = FALSE;
+ fVal1 = DBL_MAX;
+ }
+#else // SOMA_FPSIGNAL_JUMP
+ ScInterpreter::pJumpBuf = pSaveBuf;
+ (ScInterpreter::pSignalFunc)( SC_SIGFPE, pOldSigFunc );
+#endif
+ return bOk;
+}
+
+
+/*------------------------------------------------------------------------
+
+ $Log: not supported by cvs2svn $
+ Revision 1.25 2000/09/17 14:08:42 willem.vandorp
+ OpenOffice header added.
+
+ Revision 1.24 2000/08/31 16:38:04 willem.vandorp
+ Header and footer replaced
+
+ Revision 1.23 1999/05/05 19:50:32 ER
+ SC_FP... -> SOMA_FP..., SC_FINITE -> SOMA_FINITE, Approx... -> SolarMath::Approx...
+
+
+ Rev 1.22 05 May 1999 21:50:32 ER
+ SC_FP... -> SOMA_FP..., SC_FINITE -> SOMA_FINITE, Approx... -> SolarMath::Approx...
+
+ Rev 1.21 13 Jan 1998 17:24:38 ER
+ Unterteilung SC_FPRESET und SC_FPCONTROL
+
+ Rev 1.20 13 Nov 1997 21:07:54 NN
+ ifndef PCH raus
+
+ Rev 1.19 15 Sep 1997 14:21:10 HR
+ SOLARIS
+
+ Rev 1.18 09 Apr 1997 19:14:04 ER
+ #38622# define SC_FPSIGNAL_JUMP etc.; OS2 jetzt wie WNT ohne setjmp/longjmp
+
+ Rev 1.17 14 Nov 1996 16:38:18 ER
+ SC_FINITE statt einzel-ifdefs
+
+ Rev 1.16 20 Aug 1996 13:11:28 NN
+ #30412# ScInterpreter::pJumpBuf auch wieder zuruecksetzen
+
+ Rev 1.15 09 Jul 1996 12:06:50 NN
+ #29279# fpreset
+
+ Rev 1.14 08 May 1996 08:43:00 NN
+ SaveDif
+
+ Rev 1.13 08 Sep 1995 16:03:58 STE
+ Absicherung Mac und WNT
+
+ Rev 1.12 18 Aug 1995 13:12:38 mk
+ jetzt RICHTIG: includes fuer RS6000
+
+ Rev 1.11 18 Aug 1995 12:58:34 mk
+ includes fuer RS6000
+
+ Rev 1.10 24 Jul 1995 18:57:20 STE
+ ein jmp_buf weniger
+
+ Rev 1.9 12 Jul 1995 11:57:08 STE
+ nVal auf MAX_DBL gesetzt
+
+ Rev 1.8 08 Jul 1995 14:54:14 STE
+ SafeAdd und SafeMult dazu
+
+ Rev 1.7 19 Jun 1995 16:04:56 STE
+ meory.h raus
+
+ Rev 1.6 19 Jun 1995 09:19:08 STE
+ Absicherung ueberarbeitet
+
+ Rev 1.5 16 Jun 1995 13:28:52 STE
+ Umstellung numerische ABsicherung
+
+ Rev 1.4 18 May 1995 19:35:08 STE
+ Fehler bei Mult beseitigt
+
+ Rev 1.3 17 May 1995 17:47:14 STE
+ Numerische Absicherung
+
+ Rev 1.2 06 May 1995 18:29:34 STE
+ Absturz Stddev beseitigt
+
+ Rev 1.1 05 May 1995 12:54:54 STE
+ Korrektur VARP und STDDEVP
+
+ Rev 1.0 28 Apr 1995 15:55:30 NN
+ Initial revision.
+
+------------------------------------------------------------------------*/
+
+#pragma SEG_EOFMODULE
+
+
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
new file mode 100644
index 000000000000..34376484900a
--- /dev/null
+++ b/sc/source/core/tool/token.cxx
@@ -0,0 +1,1660 @@
+/*************************************************************************
+ *
+ * $RCSfile: token.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:19 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+// INCLUDE ---------------------------------------------------------------
+
+#if STLPORT_VERSION<321
+#include <stddef.h>
+#else
+#include <cstddef>
+#endif
+#include <string.h>
+
+#ifndef _SVMEMPOOL_HXX //autogen
+#include <tools/mempool.hxx>
+#endif
+#ifndef _TOOLS_DEBUG_HXX //autogen
+#include <tools/debug.hxx>
+#endif
+
+#include "compiler.hxx"
+#include "rechead.hxx"
+
+struct ImpTokenIterator
+{
+ ImpTokenIterator* pNext;
+ ScTokenArray* pArr;
+ short nPC;
+
+ DECL_FIXEDMEMPOOL_NEWDEL( ImpTokenIterator );
+};
+
+// ImpTokenIterator wird je Interpreter angelegt, mehrfache auch durch
+// SubCode via ScTokenIterator Push/Pop moeglich
+IMPL_FIXEDMEMPOOL_NEWDEL( ImpTokenIterator, 32, 16 );
+
+// Raw-ScToken Groesse ist FixMembers + MAXSTRLEN ~= 264
+IMPL_FIXEDMEMPOOL_NEWDEL( ScToken, 8, 4 );
+// ScDoubleToken werden evtl. massig gebraucht, FixMembers + sizeof(double) ~= 16
+const USHORT nMemPoolDoubleToken = (0x4000 - 64) / sizeof(ScDoubleToken);
+IMPL_FIXEDMEMPOOL_NEWDEL( ScDoubleToken, nMemPoolDoubleToken, nMemPoolDoubleToken );
+
+//-----------------------Funktionen der Klasse ScToken------------------------
+
+inline BOOL lcl_IsReference( OpCode eOp, StackVar eType )
+{
+ return
+ (eOp == ocPush && (eType == svSingleRef || eType == svDoubleRef))
+ || (eOp == ocColRowNameAuto && eType == svDoubleRef)
+ ;
+}
+
+
+xub_StrLen ScToken::GetStrLen( const sal_Unicode* pStr )
+{
+ if ( !pStr )
+ return 0;
+ register const sal_Unicode* p = pStr;
+ while ( *p )
+ p++;
+ return p - pStr;
+}
+
+
+BOOL ScToken::IsFunction() const
+{
+ return (eOp != ocPush && eOp != ocBad && eOp != ocColRowName &&
+ eOp != ocColRowNameAuto && eOp != ocName && eOp != ocDBArea &&
+ (cByte != 0 // x Parameter
+ || (ocEndUnOp < eOp && eOp <= ocEndNoPar) // kein Parameter
+ || (ocIf == eOp || ocChose == eOp ) //@ Sprung Kommandos
+ || (ocEndNoPar < eOp && eOp <= ocEnd1Par) // ein Parameter
+ || (ocEnd1Par < eOp && eOp <= ocEnd2Par) // x Parameter (cByte==0 in
+ // FuncAutoPilot)
+ || eOp == ocMacro || eOp == ocExternal // Makros, AddIns
+ || eOp == ocAnd || eOp == ocOr // ehemals binaer, jetzt x Params
+ || eOp == ocNot || eOp == ocNeg // unaer aber Function
+ || (eOp >= ocInternalBegin && eOp <= ocInternalEnd) // Internal
+ ));
+}
+
+
+BYTE ScToken::GetParamCount() const
+{
+ if ( eOp <= ocEndDiv && eOp != ocExternal && eOp != ocMacro &&
+ eOp != ocIf && eOp != ocChose )
+ return 0; // Parameter und Specials
+ // ocIf und ocChose fuer FAP nicht, haben dann cByte
+//2do: BOOL-Parameter ob FAP oder nicht?
+ else if ( cByte )
+ return cByte; // alle Funktionen, gilt auch fuer ocExternal und ocMacro
+ else if ( ocEndDiv < eOp && eOp <= ocEndBinOp )
+ return 2; // binaer
+ else if ( ocEndBinOp < eOp && eOp <= ocEndUnOp )
+ return 1; // unaer
+ else if ( ocEndUnOp < eOp && eOp <= ocEndNoPar )
+ return 0; // kein Parameter
+ else if ( ocEndNoPar < eOp && eOp <= ocEnd1Par )
+ return 1; // ein Parameter
+ else
+ return 0; // der Rest, kein Parameter, oder
+ // wenn dann sollte er in cByte sein
+}
+
+
+BOOL ScToken::IsMatrixFunction() const
+{
+ switch ( eOp )
+ {
+ case ocDde :
+ case ocGrowth :
+ case ocTrend :
+ case ocRKP :
+ case ocRGP :
+ case ocFrequency :
+ case ocMatTrans :
+ case ocMatMult :
+ case ocMatInv :
+ case ocMatrixUnit :
+ return TRUE;
+ break;
+ }
+ return FALSE;
+}
+
+
+void ScToken::SetOpCode( OpCode e )
+{
+ eOp = e;
+ if( eOp == ocIf )
+ {
+ eType = svJump; nJump[ 0 ] = 3; // If, Else, Behind
+ }
+ else if( eOp == ocChose )
+ {
+ eType = svJump; nJump[ 0 ] = MAXJUMPCOUNT+1;
+ }
+ else if( eOp == ocMissing )
+ eType = svMissing;
+ else
+ eType = svByte, cByte = 0;
+ nRefCnt = 0;
+}
+
+void ScToken::SetString( const sal_Unicode* pStr )
+{
+ eOp = ocPush;
+ eType = svString;
+ if ( pStr )
+ {
+ xub_StrLen nLen = GetStrLen( pStr ) + 1;
+ if( nLen > MAXSTRLEN )
+ nLen = MAXSTRLEN;
+ memcpy( cStr, pStr, GetStrLenBytes( nLen ) );
+ cStr[ nLen-1 ] = 0;
+ }
+ else
+ cStr[0] = 0;
+ nRefCnt = 0;
+}
+
+void ScToken::SetSingleReference( const SingleRefData& rRef )
+{
+ eOp = ocPush;
+ eType = svSingleRef;
+ aRef.Ref1 =
+ aRef.Ref2 = rRef;
+ nRefCnt = 0;
+}
+
+void ScToken::SetDoubleReference( const ComplRefData& rRef )
+{
+ eOp = ocPush;
+ eType = svDoubleRef;
+ aRef = rRef;
+ nRefCnt = 0;
+}
+
+void ScToken::SetReference( ComplRefData& rRef )
+{
+ DBG_ASSERT( lcl_IsReference( eOp, GetType() ), "SetReference: no Ref" );
+ aRef = rRef;
+ if( GetType() == svSingleRef )
+ aRef.Ref2 = aRef.Ref1;
+}
+
+void ScToken::SetByte( BYTE c )
+{
+ eOp = ocPush;
+ eType = svByte;
+ cByte = c;
+ nRefCnt = 0;
+}
+
+void ScToken::SetDouble(double rVal)
+{
+ eOp = ocPush;
+ eType = svDouble;
+ nValue = rVal;
+ nRefCnt = 0;
+}
+
+void ScToken::SetInt(int rVal)
+{
+ eOp = ocPush;
+ eType = svDouble;
+ nValue = (double)rVal;
+ nRefCnt = 0;
+}
+
+void ScToken::SetName( USHORT n )
+{
+ eOp = ocName;
+ eType = svIndex;
+ nIndex = n;
+ nRefCnt = 0;
+}
+
+ComplRefData& ScToken::GetReference()
+{
+ DBG_ASSERT( lcl_IsReference( eOp, GetType() ), "GetReference: no Ref" );
+ return aRef;
+}
+
+void ScToken::SetExternal( const sal_Unicode* pStr )
+{
+ eOp = ocExternal;
+ eType = svExternal;
+ xub_StrLen nLen = GetStrLen( pStr ) + 1;
+ if( nLen >= MAXSTRLEN )
+ nLen = MAXSTRLEN-1;
+ // Platz fuer Byte-Parameter lassen!
+ memcpy( cStr+1, pStr, GetStrLenBytes( nLen ) );
+ cStr[ nLen+1 ] = 0;
+ nRefCnt = 0;
+}
+
+void ScToken::SetMatrix( ScMatrix* p )
+{
+ eOp = ocPush;
+ eType = svMatrix;
+ pMat = p;
+ nRefCnt = 0;
+}
+
+ScToken* ScToken::Clone() const
+{
+ ScToken* p;
+ if ( eType == svDouble )
+ {
+ p = (ScToken*) new ScDoubleToken;
+ p->eOp = eOp;
+ p->eType = eType;
+ p->nValue = nValue;
+ }
+ else
+ {
+ USHORT n = offsetof( ScToken, cByte );
+ switch( eType )
+ {
+ case svByte: n++; break;
+ case svDouble: n += sizeof(double); break;
+ case svString: n += GetStrLenBytes( cStr ) + GetStrLenBytes( 1 ); break;
+ case svSingleRef:
+ case svDoubleRef: n += sizeof(aRef); break;
+ case svMatrix: n += sizeof(ScMatrix*); break;
+ case svIndex: n += sizeof(USHORT); break;
+ case svJump: n += nJump[ 0 ] * 2 + 2; break;
+ case svExternal: n += GetStrLenBytes( cStr+1 ) + GetStrLenBytes( 2 ); break;
+ default: n += (BYTE) cStr[ 0 ]; // unbekannt eingelesen!
+ }
+ p = (ScToken*) new BYTE[ n ];
+ memcpy( p, this, n * sizeof(BYTE) );
+ }
+ p->nRefCnt = 0;
+ p->bRaw = FALSE;
+ return p;
+}
+
+BOOL ScToken::operator== (const ScToken& rToken) const
+{
+ // Ref-Count und bRaw darf hier nicht mit verglichen werden!!!
+
+ USHORT n = 0;
+ switch( eType )
+ {
+ case svByte: n++; break;
+ case svDouble: n += sizeof(double); break;
+ case svString: n += GetStrLenBytes( cStr ) + GetStrLenBytes( 1 ); break;
+ case svSingleRef:
+ case svDoubleRef: n += sizeof(aRef); break;
+ case svMatrix: n += sizeof(ScMatrix*); break;
+ case svIndex: n += sizeof(USHORT); break;
+ case svJump: n += nJump[ 0 ] * 2 + 2; break;
+ case svExternal: n += GetStrLenBytes( cStr+1 ) + GetStrLenBytes( 2 ); break;
+ default: n += (BYTE) cStr[ 0 ]; // unbekannt eingelesen!
+ }
+ return eOp == rToken.eOp && eType == rToken.eType &&
+ ( n == 0 || memcmp( &cByte, &rToken.cByte, n ) == 0 );
+}
+
+void ScToken::Delete()
+{
+ if ( bRaw )
+ delete this; // FixedMemPool ScToken
+ else
+ { // per Clone erzeugt
+ switch ( eType )
+ {
+ case svDouble :
+ delete (ScDoubleToken*) this; // FixedMemPool ScDoubleToken
+ break;
+ default:
+ delete [] (BYTE*) this;
+ }
+ }
+}
+
+// TextEqual: gleiche Formel eingegeben (fuer Optimierung beim Sortieren)
+
+BOOL ScToken::TextEqual(const ScToken& rToken) const
+{
+ if ( eType == svSingleRef || eType == svDoubleRef )
+ {
+ // bei relativen Refs auch nur den relativen Teil vergleichen
+
+ if ( eOp != rToken.eOp || eType != rToken.eType )
+ return FALSE;
+
+ ComplRefData aTemp1 = aRef;
+ ComplRefData aTemp2 = rToken.aRef;
+
+ ScAddress aPos;
+ aTemp1.SmartRelAbs(aPos);
+ aTemp2.SmartRelAbs(aPos);
+
+ // memcmp geht schief wegen des Alignment-Bytes hinter bFlags
+ // nach SmartRelAbs muessen nur die absoluten Teile verglichen werden
+ return aTemp1.Ref1.nCol == aTemp2.Ref1.nCol &&
+ aTemp1.Ref1.nRow == aTemp2.Ref1.nRow &&
+ aTemp1.Ref1.nTab == aTemp2.Ref1.nTab &&
+ aTemp1.Ref1.bFlags == aTemp2.Ref1.bFlags &&
+ aTemp1.Ref2.nCol == aTemp2.Ref2.nCol &&
+ aTemp1.Ref2.nRow == aTemp2.Ref2.nRow &&
+ aTemp1.Ref2.nTab == aTemp2.Ref2.nTab &&
+ aTemp1.Ref2.bFlags == aTemp2.Ref2.bFlags;
+ }
+ else
+ return *this == rToken; // sonst normaler operator==
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+ScToken* ScTokenArray::GetNextReference()
+{
+ while( nIndex < nLen )
+ {
+ ScToken* t = pCode[ nIndex++ ];
+ switch( t->GetType() )
+ {
+ case svSingleRef:
+ case svDoubleRef:
+ return t;
+ }
+ }
+ return NULL;
+}
+
+ScToken* ScTokenArray::GetNextColRowName()
+{
+ while( nIndex < nLen )
+ {
+ ScToken* t = pCode[ nIndex++ ];
+ if ( t->GetOpCode() == ocColRowName )
+ return t;
+ }
+ return NULL;
+}
+
+ScToken* ScTokenArray::GetNextReferenceRPN()
+{
+ while( nIndex < nRPN )
+ {
+ ScToken* t = pRPN[ nIndex++ ];
+ switch( t->GetType() )
+ {
+ case svSingleRef:
+ case svDoubleRef:
+ return t;
+ }
+ }
+ return NULL;
+}
+
+ScToken* ScTokenArray::GetNextReferenceOrName()
+{
+ for( ScToken* t = Next(); t; t = Next() )
+ {
+ switch( t->GetType() )
+ {
+ case svSingleRef:
+ case svDoubleRef:
+ case svIndex:
+ return t;
+ }
+ }
+ return NULL;
+}
+
+ScToken* ScTokenArray::GetNextName()
+{
+ for( ScToken* t = Next(); t; t = Next() )
+ {
+ if( t->GetType() == svIndex )
+ return t;
+ }
+ return NULL;
+}
+
+ScToken* ScTokenArray::GetNextDBArea()
+{
+ for( ScToken* t = Next(); t; t = Next() )
+ {
+ if ( t->GetOpCode() == ocDBArea )
+ return t;
+ }
+ return NULL;
+}
+
+ScToken* ScTokenArray::GetNextOpCodeRPN( OpCode eOp )
+{
+ while( nIndex < nRPN )
+ {
+ ScToken* t = pRPN[ nIndex++ ];
+ if ( t->GetOpCode() == eOp )
+ return t;
+ }
+ return NULL;
+}
+
+ScToken* ScTokenArray::Next()
+{
+ if( pCode && nIndex < nLen )
+ return pCode[ nIndex++ ];
+ else
+ return NULL;
+}
+
+ScToken* ScTokenArray::NextRPN()
+{
+ if( pRPN && nIndex < nRPN )
+ return pRPN[ nIndex++ ];
+ else
+ return NULL;
+}
+
+ScToken* ScTokenArray::PrevRPN()
+{
+ if( pRPN && nIndex )
+ return pRPN[ --nIndex ];
+ else
+ return NULL;
+}
+
+void ScTokenArray::DelRPN()
+{
+ if( nRPN )
+ {
+ ScToken** p = pRPN;
+ for( USHORT i = 0; i < nRPN; i++ )
+ {
+ (*p++)->DecRef();
+ }
+ delete [] pRPN;
+ }
+ pRPN = NULL;
+ nRPN = nIndex = 0;
+}
+
+ScToken* ScTokenArray::PeekNext()
+{
+ if( pCode && nIndex < nLen )
+ return pCode[ nIndex ];
+ else
+ return NULL;
+}
+
+ScToken* ScTokenArray::PeekNextNoSpaces()
+{
+ if( pCode && nIndex < nLen )
+ {
+ USHORT j = nIndex;
+ while ( pCode[j]->GetOpCode() == ocSpaces && j < nLen )
+ j++;
+ if ( j < nLen )
+ return pCode[ j ];
+ else
+ return NULL;
+ }
+ else
+ return NULL;
+}
+
+ScToken* ScTokenArray::PeekPrevNoSpaces()
+{
+ if( pCode && nIndex > 1 )
+ {
+ USHORT j = nIndex - 2;
+ while ( pCode[j]->GetOpCode() == ocSpaces && j > 0 )
+ j--;
+ if ( j > 0 || pCode[j]->GetOpCode() != ocSpaces )
+ return pCode[ j ];
+ else
+ return NULL;
+ }
+ else
+ return NULL;
+}
+
+BOOL ScTokenArray::HasOpCodeRPN( OpCode eOp ) const
+{
+ for ( USHORT j=0; j < nRPN; j++ )
+ {
+ if ( pRPN[j]->GetOpCode() == eOp )
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL ScTokenArray::HasName() const
+{
+ for ( USHORT j=0; j < nLen; j++ )
+ {
+ if( pCode[j]->GetType() == svIndex )
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL ScTokenArray::IsReference( ScRange& rRange ) const
+{
+ BOOL bIs = FALSE;
+ if ( pCode && nLen == 1 )
+ {
+ ScToken* pToken = pCode[0];
+ if ( pToken )
+ {
+ if ( pToken->GetType() == svSingleRef )
+ {
+ SingleRefData& rRef = pToken->GetReference().Ref1;
+ rRange.aStart = rRange.aEnd = ScAddress( rRef.nCol, rRef.nRow, rRef.nTab );
+ bIs = TRUE;
+ }
+ else if ( pToken->GetType() == svDoubleRef )
+ {
+ ComplRefData& rCompl = pToken->GetReference();
+ SingleRefData& rRef1 = rCompl.Ref1;
+ SingleRefData& rRef2 = rCompl.Ref2;
+ rRange.aStart = ScAddress( rRef1.nCol, rRef1.nRow, rRef1.nTab );
+ rRange.aEnd = ScAddress( rRef2.nCol, rRef2.nRow, rRef2.nTab );
+ bIs = TRUE;
+ }
+ }
+ }
+ return bIs;
+}
+
+void ScTokenArray::Load30( SvStream& rStream, const ScAddress& rPos )
+{
+ Clear();
+ ScToken* pToks[ MAXCODE ];
+ ScToken t;
+ for( nLen = 0; nLen < MAXCODE; nLen++ )
+ {
+ t.Load30( rStream );
+ if( t.GetOpCode() == ocStop )
+ break;
+ else if( t.GetOpCode() == ocPush
+ && ( t.GetType() == svSingleRef || t.GetType() == svDoubleRef ) )
+ {
+ nRefs++;
+ t.aRef.CalcRelFromAbs( rPos );
+ }
+ ScToken* p = pToks[ nLen ] = t.Clone();
+ p->IncRef();
+ }
+ pCode = new ScToken*[ nLen ];
+ memcpy( pCode, pToks, nLen * sizeof( ScToken* ) );
+}
+
+void ScTokenArray::Load( SvStream& rStream, USHORT nVer, const ScAddress& rPos )
+{
+ Clear();
+ // 0x10 - nRefs
+ // 0x20 - nError
+ // 0x40 - TokenArray
+ // 0x80 - CodeArray
+ BYTE cData;
+ rStream >> cData;
+ if( cData & 0x0F )
+ rStream.SeekRel( cData & 0x0F );
+ if ( nVer < SC_RECALC_MODE_BITS )
+ {
+ BYTE cMode;
+ rStream >> cMode;
+ ImportRecalcMode40( (ScRecalcMode40) cMode );
+ }
+ else
+ rStream >> nMode;
+ if( cData & 0x10 )
+ rStream >> nRefs;
+ if( cData & 0x20 )
+ rStream >> nError;
+ ScToken* pToks[ MAXCODE ];
+ ScToken** pp = pToks;
+ ScToken t;
+ if( cData & 0x40 )
+ {
+ rStream >> nLen;
+ for( USHORT i = 0; i < nLen; i++ )
+ {
+ t.Load( rStream, nVer );
+ if ( t.GetType() == svSingleRef || t.GetType() == svDoubleRef )
+ t.aRef.CalcRelFromAbs( rPos );
+ // gespeichert wurde und wird immer absolut
+ *pp = t.Clone();
+ (*pp++)->IncRef();
+ }
+ pCode = new ScToken*[ nLen ];
+ memcpy( pCode, pToks, nLen * sizeof( ScToken* ) );
+ }
+ pp = pToks;
+ if( cData & 0x80 )
+ {
+ rStream >> nRPN;
+ for( USHORT i = 0; i < nRPN; i++, pp++ )
+ {
+ BYTE b1, b2 = 0;
+ UINT16 nIdx;
+ rStream >> b1;
+ // 0xFF - Token folgt
+ // 0x40-0x7F - untere 6 Bits, 1 Byte mit 8 weiteren Bits
+ // 0x00-0x3F - Index
+ if( b1 == 0xFF )
+ {
+ t.Load( rStream, nVer );
+ if ( t.GetType() == svSingleRef || t.GetType() == svDoubleRef )
+ t.aRef.CalcRelFromAbs( rPos );
+ // gespeichert wurde und wird immer absolut
+ *pp = t.Clone();
+ }
+ else
+ {
+ if( b1 & 0x40 )
+ {
+ rStream >> b2;
+ nIdx = ( b1 & 0x3F ) | ( b2 << 6 );
+ }
+ else
+ nIdx = b1;
+ *pp = pCode[ nIdx ];
+ }
+ (*pp)->IncRef();
+ // #73616# CONVERT function recalculated on each load
+ if ( nVer < SC_CONVERT_RECALC_ON_LOAD && (*pp)->GetOpCode() == ocConvert )
+ AddRecalcMode( RECALCMODE_ONLOAD );
+ }
+ pRPN = new ScToken*[ nRPN ];
+ memcpy( pRPN, pToks, nRPN * sizeof( ScToken* ) );
+ // Aeltere Versionen: kein UPN-Array laden
+ if( nVer < SC_NEWIF )
+ DelRPN();
+ }
+}
+
+void ScTokenArray::Store( SvStream& rStream, const ScAddress& rPos ) const
+{
+ // 0x10 - nRefs
+ // 0x20 - nError
+ // 0x40 - TokenArray
+ // 0x80 - CodeArray
+ BYTE cFlags = 0;
+ if( nRefs )
+ cFlags |= 0x10;
+ if( nError )
+ cFlags |= 0x20;
+ if( nLen )
+ cFlags |= 0x40;
+ if( nRPN )
+ cFlags |= 0x80;
+ rStream << cFlags;
+ // Hier ggf. Zusatzdaten!
+ if ( rStream.GetVersion() <= SOFFICE_FILEFORMAT_40 )
+ rStream << (BYTE) ExportRecalcMode40();
+ else
+ rStream << (BYTE) nMode;
+ if( cFlags & 0x10 )
+ rStream << (INT16) nRefs;
+ if( cFlags & 0x20 )
+ rStream << (UINT16) nError;
+ if( cFlags & 0x40 )
+ {
+ rStream << nLen;
+ ScToken** p = pCode;
+ for( USHORT i = 0; i < nLen; i++, p++ )
+ {
+ // gespeichert wurde und wird immer absolut
+ switch ( (*p)->GetType() )
+ {
+ case svSingleRef :
+ (*p)->aRef.Ref1.CalcAbsIfRel( rPos );
+ break;
+ case svDoubleRef :
+ (*p)->aRef.CalcAbsIfRel( rPos );
+ break;
+ }
+ (*p)->Store( rStream );
+ }
+ }
+ if( cFlags & 0x80 )
+ {
+ rStream << nRPN;
+ ScToken** p = pRPN;
+ for( USHORT i = 0; i < nRPN; i++, p++ )
+ {
+ ScToken* t = *p;
+ USHORT nIdx = 0xFFFF;
+ if( t->GetRef() > 1 )
+ {
+ ScToken** p2 = pCode;
+ for( USHORT j = 0; j < nLen; j++, p2++ )
+ {
+ if( *p2 == t )
+ {
+ nIdx = j; break;
+ }
+ }
+ }
+ // 0xFF - Token folgt
+ // 0x40-0x7F - untere 6 Bits, 1 Byte mit 8 weiteren Bits
+ // 0x00-0x3F - Index
+ if( nIdx == 0xFFFF )
+ {
+ // gespeichert wurde und wird immer absolut
+ switch ( t->GetType() )
+ {
+ case svSingleRef :
+ t->aRef.Ref1.CalcAbsIfRel( rPos );
+ break;
+ case svDoubleRef :
+ t->aRef.CalcAbsIfRel( rPos );
+ break;
+ }
+ rStream << (BYTE) 0xFF;
+ t->Store( rStream );
+ }
+ else
+ {
+ if( nIdx < 0x40 )
+ rStream << (BYTE) nIdx;
+ else
+ rStream << (BYTE) ( ( nIdx & 0x3F ) | 0x40 )
+ << (BYTE) ( nIdx >> 6 );
+ }
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+ScTokenArray::ScTokenArray()
+{
+ pCode = NULL; pRPN = NULL;
+ nError = nLen = nIndex = nRPN = nRefs = 0;
+ ClearRecalcMode();
+}
+
+ScTokenArray::ScTokenArray( const ScTokenArray& rArr )
+{
+ Assign( rArr );
+}
+
+ScTokenArray::~ScTokenArray()
+{
+ Clear();
+}
+
+void ScTokenArray::Assign( const ScTokenArray& r )
+{
+ nLen = r.nLen;
+ nRPN = r.nRPN;
+ nIndex = r.nIndex;
+ nError = r.nError;
+ nRefs = r.nRefs;
+ nMode = r.nMode;
+ pCode = NULL;
+ pRPN = NULL;
+ ScToken** pp;
+ if( nLen )
+ {
+ pp = pCode = new ScToken*[ nLen ];
+ memcpy( pp, r.pCode, nLen * sizeof( ScToken* ) );
+ for( USHORT i = 0; i < nLen; i++ )
+ (*pp++)->IncRef();
+ }
+ if( nRPN )
+ {
+ pp = pRPN = new ScToken*[ nRPN ];
+ memcpy( pp, r.pRPN, nRPN * sizeof( ScToken* ) );
+ for( USHORT i = 0; i < nRPN; i++ )
+ (*pp++)->IncRef();
+ }
+}
+
+ScTokenArray& ScTokenArray::operator=( const ScTokenArray& rArr )
+{
+ Clear();
+ Assign( rArr );
+ return *this;
+}
+
+ScTokenArray* ScTokenArray::Clone() const
+{
+ ScTokenArray* p = new ScTokenArray;
+ p->nLen = nLen;
+ p->nRPN = nRPN;
+ p->nRefs = nRefs;
+ p->nMode = nMode;
+ p->nError = nError;
+ ScToken** pp;
+ if( nLen )
+ {
+ pp = p->pCode = new ScToken*[ nLen ];
+ memcpy( pp, pCode, nLen * sizeof( ScToken* ) );
+ for( USHORT i = 0; i < nLen; i++, pp++ )
+ {
+ *pp = (*pp)->Clone();
+ (*pp)->IncRef();
+ }
+ }
+ if( nRPN )
+ {
+ pp = p->pRPN = new ScToken*[ nRPN ];
+ memcpy( pp, pRPN, nRPN * sizeof( ScToken* ) );
+ for( USHORT i = 0; i < nRPN; i++, pp++ )
+ {
+ ScToken* t = *pp;
+ if( t->GetRef() > 1 )
+ {
+ ScToken** p2 = pCode;
+ USHORT nIdx = 0xFFFF;
+ for( USHORT j = 0; j < nLen; j++, p2++ )
+ {
+ if( *p2 == t )
+ {
+ nIdx = j; break;
+ }
+ }
+ if( nIdx == 0xFFFF )
+ *pp = t->Clone();
+ else
+ *pp = p->pCode[ nIdx ];
+ }
+ else
+ *pp = t->Clone();
+ (*pp)->IncRef();
+ }
+ }
+ return p;
+}
+
+void ScTokenArray::Clear()
+{
+ if( nRPN ) DelRPN();
+ if( pCode )
+ {
+ ScToken** p = pCode;
+ for( USHORT i = 0; i < nLen; i++ )
+ {
+ (*p++)->DecRef();
+ }
+ delete [] pCode;
+ }
+ pCode = NULL; pRPN = NULL;
+ nError = nLen = nIndex = nRPN = nRefs = 0;
+ ClearRecalcMode();
+}
+
+ScToken* ScTokenArray::AddToken( const ScToken& r )
+{
+ return Add( r.Clone() );
+}
+
+// Wird auch vom Compiler genutzt. Das Token ist per new angelegt!
+
+ScToken* ScTokenArray::Add( ScToken* t )
+{
+ if( !pCode )
+ pCode = new ScToken*[ MAXCODE ];
+ if( nLen < MAXCODE )
+ {
+ pCode[ nLen++ ] = t;
+ if( t->GetOpCode() == ocPush
+ && ( t->GetType() == svSingleRef || t->GetType() == svDoubleRef ) )
+ nRefs++;
+ t->IncRef();
+ return t;
+ }
+ else
+ {
+ t->Delete();
+ return NULL;
+ }
+}
+
+ScToken* ScTokenArray::AddOpCode( OpCode e )
+{
+ ScToken t;
+ t.SetOpCode( e );
+ return AddToken( t );
+}
+
+ScToken* ScTokenArray::AddString( const sal_Unicode* pStr )
+{
+ ScToken t;
+ t.SetString( pStr );
+ return AddToken( t );
+}
+
+ScToken* ScTokenArray::AddDouble(double rVal )
+{
+ ScToken t;
+ t.SetDouble( rVal );
+ return AddToken( t );
+}
+
+ScToken* ScTokenArray::AddSingleReference( const SingleRefData& rRef )
+{
+ ScToken t;
+ t.SetSingleReference( rRef );
+ return AddToken( t );
+}
+
+ScToken* ScTokenArray::AddDoubleReference( const ComplRefData& rRef )
+{
+ ScToken t;
+ t.SetDoubleReference( rRef );
+ return AddToken( t );
+}
+
+ScToken* ScTokenArray::AddName( USHORT n )
+{
+ ScToken t;
+ t.SetName( n );
+ return AddToken( t );
+}
+
+ScToken* ScTokenArray::AddExternal( const sal_Unicode* pStr )
+{
+ ScToken t;
+ t.SetExternal( pStr );
+ return AddToken( t );
+}
+
+ScToken* ScTokenArray::AddMatrix( ScMatrix* p )
+{
+ ScToken t;
+ t.SetMatrix( p );
+ return AddToken( t );
+}
+
+ScToken* ScTokenArray::AddBad( const sal_Unicode* pStr )
+{
+ ScToken t;
+ t.SetString( pStr );
+ t.eOp = ocBad;
+ return AddToken( t );
+}
+
+
+BOOL ScTokenArray::GetAdjacentExtendOfOuterFuncRefs( USHORT& nExtend,
+ const ScAddress& rPos, ScDirection eDir )
+{
+ USHORT nCol, nRow;
+ switch ( eDir )
+ {
+ case DIR_BOTTOM :
+ if ( rPos.Row() < MAXROW )
+ nRow = (nExtend = rPos.Row()) + 1;
+ else
+ return FALSE;
+ break;
+ case DIR_RIGHT :
+ if ( rPos.Col() < MAXCOL )
+ nCol = (nExtend = rPos.Col()) + 1;
+ else
+ return FALSE;
+ break;
+ case DIR_TOP :
+ if ( rPos.Row() > 0 )
+ nRow = (nExtend = rPos.Row()) - 1;
+ else
+ return FALSE;
+ break;
+ case DIR_LEFT :
+ if ( rPos.Col() > 0 )
+ nCol = (nExtend = rPos.Col()) - 1;
+ else
+ return FALSE;
+ break;
+ default:
+ DBG_ERRORFILE( "unknown Direction" );
+ return FALSE;
+ }
+ if ( pRPN && nRPN )
+ {
+ ScToken* t = pRPN[nRPN-1];
+ if ( t->GetType() == svByte )
+ {
+ BYTE nParamCount = t->cByte;
+ if ( nParamCount && nRPN > nParamCount )
+ {
+ BOOL bRet = FALSE;
+ USHORT nParam = nRPN - nParamCount - 1;
+ for ( ; nParam < nRPN-1; nParam++ )
+ {
+ ScToken* p = pRPN[nParam];
+ switch ( p->GetType() )
+ {
+ case svSingleRef :
+ case svDoubleRef :
+ {
+ ComplRefData& rRef = p->GetReference();
+ rRef.CalcAbsIfRel( rPos );
+ switch ( eDir )
+ {
+ case DIR_BOTTOM :
+ if ( rRef.Ref1.nRow == nRow
+ && rRef.Ref2.nRow > nExtend )
+ {
+ nExtend = rRef.Ref2.nRow;
+ bRet = TRUE;
+ }
+ break;
+ case DIR_RIGHT :
+ if ( rRef.Ref1.nCol == nCol
+ && rRef.Ref2.nCol > nExtend )
+ {
+ nExtend = rRef.Ref2.nCol;
+ bRet = TRUE;
+ }
+ break;
+ case DIR_TOP :
+ if ( rRef.Ref2.nRow == nRow
+ && rRef.Ref1.nRow < nExtend )
+ {
+ nExtend = rRef.Ref1.nRow;
+ bRet = TRUE;
+ }
+ break;
+ case DIR_LEFT :
+ if ( rRef.Ref2.nCol == nCol
+ && rRef.Ref1.nCol < nExtend )
+ {
+ nExtend = rRef.Ref1.nCol;
+ bRet = TRUE;
+ }
+ break;
+ }
+ }
+ } // switch
+ } // for
+ return bRet;
+ }
+ }
+ }
+ return FALSE;
+}
+
+
+void ScTokenArray::ImportRecalcMode40( ScRecalcMode40 eMode )
+{
+ switch ( eMode )
+ {
+ case RC_NORMAL :
+ nMode = RECALCMODE_NORMAL;
+ break;
+ case RC_ALWAYS :
+ nMode = RECALCMODE_ALWAYS;
+ break;
+ case RC_ONLOAD :
+ nMode = RECALCMODE_ONLOAD;
+ break;
+ case RC_ONLOAD_ONCE :
+ nMode = RECALCMODE_ONLOAD_ONCE;
+ break;
+ case RC_FORCED :
+ nMode = RECALCMODE_NORMAL | RECALCMODE_FORCED;
+ break;
+ case RC_ONREFMOVE :
+ nMode = RECALCMODE_NORMAL | RECALCMODE_ONREFMOVE;
+ break;
+ default:
+ DBG_ERRORFILE( "ScTokenArray::ImportRecalcMode40: unknown ScRecalcMode40" );
+ nMode = RECALCMODE_NORMAL;
+ }
+}
+
+
+ScRecalcMode40 ScTokenArray::ExportRecalcMode40() const
+{
+ //! Reihenfolge ist wichtig
+ if ( nMode & RECALCMODE_ALWAYS )
+ return RC_ALWAYS;
+ if ( nMode & RECALCMODE_ONLOAD )
+ return RC_ONLOAD;
+ if ( nMode & RECALCMODE_FORCED )
+ return RC_FORCED;
+ if ( nMode & RECALCMODE_ONREFMOVE )
+ return RC_ONREFMOVE;
+ // kommt eigentlich nicht vor weil in Calc bereits umgesetzt,
+ // und woanders gibt es keinen 4.0-Export, deswegen als letztes
+ if ( nMode & RECALCMODE_ONLOAD_ONCE )
+ return RC_ONLOAD_ONCE;
+ return RC_NORMAL;
+}
+
+
+void ScTokenArray::AddRecalcMode( ScRecalcMode nBits )
+{
+ //! Reihenfolge ist wichtig
+ if ( nBits & RECALCMODE_ALWAYS )
+ SetRecalcModeAlways();
+ else if ( !IsRecalcModeAlways() )
+ {
+ if ( nBits & RECALCMODE_ONLOAD )
+ SetRecalcModeOnLoad();
+ else if ( nBits & RECALCMODE_ONLOAD_ONCE && !IsRecalcModeOnLoad() )
+ SetRecalcModeOnLoadOnce();
+ }
+ SetCombinedBitsRecalcMode( nBits );
+}
+
+
+BOOL ScTokenArray::HasMatrixDoubleRefOps()
+{
+ if ( pRPN && nRPN )
+ {
+ // RPN-Interpreter Simulation
+ // als Ergebnis jeder Funktion wird einfach ein Double angenommen
+ ScToken** pStack = new ScToken* [nRPN];
+ ScToken* pResult = new ScToken;
+ pResult->SetDouble( 0.0 );
+ short sp = 0;
+ for ( USHORT j = 0; j < nRPN; j++ )
+ {
+ ScToken* t = pRPN[j];
+ OpCode eOp = t->GetOpCode();
+ BYTE nParams = t->GetParamCount();
+ switch ( eOp )
+ {
+ case ocAdd :
+ case ocSub :
+ case ocMul :
+ case ocDiv :
+ case ocPow :
+ case ocPower :
+ case ocAmpersand :
+ case ocEqual :
+ case ocNotEqual :
+ case ocLess :
+ case ocGreater :
+ case ocLessEqual :
+ case ocGreaterEqual :
+ {
+ for ( BYTE k = nParams; k; k-- )
+ {
+ if ( sp >= k && pStack[sp-k]->GetType() == svDoubleRef )
+ {
+ pResult->Delete();
+ delete [] pStack;
+ return TRUE;
+ }
+ }
+ }
+ break;
+ }
+ if ( eOp == ocPush || lcl_IsReference( eOp, t->GetType() ) )
+ pStack[sp++] = t;
+ else if ( eOp == ocIf || eOp == ocChose )
+ { // Jumps ignorieren, vorheriges Result (Condition) poppen
+ if ( sp )
+ --sp;
+ }
+ else
+ { // pop parameters, push result
+ sp -= nParams;
+ if ( sp < 0 )
+ {
+ DBG_ERROR( "ScTokenArray::HasMatrixDoubleRefOps: sp < 0" );
+ sp = 0;
+ }
+ pStack[sp++] = pResult;
+ }
+ }
+ pResult->Delete();
+ delete [] pStack;
+ }
+
+ return FALSE;
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+
+void ScToken::Load30( SvStream& rStream )
+{
+ UINT16 nOp;
+ BYTE n;
+ nRefCnt = 0;
+ rStream >> nOp;
+ eOp = (OpCode) nOp;
+ switch( eOp )
+ {
+ case ocIf:
+ eType = svJump; nJump[ 0 ] = 3; break; // then, else, behind
+ case ocChose:
+ eType = svJump; nJump[ 0 ] = MAXJUMPCOUNT+1; break;
+ case ocPush:
+ rStream >> n;
+ eType = (StackVar) n;
+ switch( eType )
+ {
+ case svByte:
+ rStream >> cByte;
+ break;
+ case svDouble:
+ rStream >> nValue;
+ break;
+ case svString:
+ {
+ sal_Char c[ MAXSTRLEN+1 ];
+ rStream >> nOp;
+ if( nOp > MAXSTRLEN-1 )
+ {
+ DBG_ERROR("Dokument huehnerich");
+ USHORT nDiff = nOp - (MAXSTRLEN-1);
+ nOp = MAXSTRLEN-1;
+ rStream.Read( c, nOp );
+ rStream.SeekRel( nDiff );
+ }
+ else
+ rStream.Read( c, nOp );
+ CharSet eSrc = rStream.GetStreamCharSet();
+ for ( BYTE j=0; j<nOp; j++ )
+ cStr[j] = ByteString::ConvertToUnicode( c[j], eSrc );
+ cStr[ nOp ] = 0;
+ break;
+ }
+ case svSingleRef:
+ {
+ OldSingleRefBools aBools;
+ rStream >> aRef.Ref1.nCol
+ >> aRef.Ref1.nRow
+ >> aRef.Ref1.nTab
+ >> aBools.bRelCol
+ >> aBools.bRelRow
+ >> aBools.bRelTab
+ >> aBools.bOldFlag3D;
+ aRef.Ref1.OldBoolsToNewFlags( aBools );
+ aRef.Ref2 = aRef.Ref1;
+ break;
+ }
+ case svDoubleRef:
+ {
+ OldSingleRefBools aBools1;
+ OldSingleRefBools aBools2;
+ rStream >> aRef.Ref1.nCol
+ >> aRef.Ref1.nRow
+ >> aRef.Ref1.nTab
+ >> aRef.Ref2.nCol
+ >> aRef.Ref2.nRow
+ >> aRef.Ref2.nTab
+ >> aBools1.bRelCol
+ >> aBools1.bRelRow
+ >> aBools1.bRelTab
+ >> aBools2.bRelCol
+ >> aBools2.bRelRow
+ >> aBools2.bRelTab
+ >> aBools1.bOldFlag3D
+ >> aBools2.bOldFlag3D;
+ aRef.Ref1.OldBoolsToNewFlags( aBools1 );
+ aRef.Ref2.OldBoolsToNewFlags( aBools2 );
+ break;
+ }
+ default: DBG_ERROR("Unknown Stack Variable");
+ break;
+ }
+ break;
+ case ocName:
+ eType = svIndex;
+ rStream >> nIndex;
+ break;
+ case ocExternal:
+ {
+ sal_Char c[ MAXSTRLEN+1 ];
+ eType = svExternal;
+ rStream >> nOp;
+ // lieber ein rottes Dokument als stack overwrite
+ if( nOp > MAXSTRLEN-2 )
+ {
+ DBG_ERROR("Dokument huehnerich");
+ USHORT nDiff = nOp - (MAXSTRLEN-2);
+ nOp = MAXSTRLEN-2;
+ rStream.Read( c, nOp );
+ rStream.SeekRel( nDiff );
+ }
+ else
+ rStream.Read( c, nOp );
+ CharSet eSrc = rStream.GetStreamCharSet();
+ for ( BYTE j=1; j<nOp; j++ )
+ cStr[j] = ByteString::ConvertToUnicode( c[j-1], eSrc );
+ cStr[ 0 ] = 0; //! parameter count is what?!?
+ cStr[ nOp ] = 0;
+ break;
+ }
+ default:
+ eType = svByte;
+ cByte = 0;
+ }
+}
+
+// Bei unbekannten Tokens steht in cStr (k)ein Pascal-String (cStr[0] = Laenge),
+// der nur gepuffert wird. cStr[0] = GESAMT-Laenge inkl. [0] !!!
+
+void ScToken::Load( SvStream& rStream, USHORT nVer )
+{
+ BYTE n;
+ UINT16 nOp;
+ USHORT i;
+ rStream >> nOp >> n;
+ eOp = (OpCode) nOp;
+ eType = (StackVar) n;
+ switch( eType )
+ {
+ case svByte:
+ rStream >> cByte;
+ break;
+ case svDouble:
+ rStream >> nValue;
+ break;
+ case svExternal:
+ {
+ sal_Char c[ MAXSTRLEN+1 ];
+ rStream >> cByte >> n;
+ if( n > MAXSTRLEN-2 )
+ {
+ DBG_ERRORFILE( "bad string array boundary" );
+ USHORT nDiff = n - (MAXSTRLEN-2);
+ n = MAXSTRLEN-2;
+ rStream.Read( c+1, n );
+ rStream.SeekRel( nDiff );
+ }
+ else
+ rStream.Read( c+1, n );
+ CharSet eSrc = rStream.GetStreamCharSet();
+ for ( BYTE j=1; j<n+1; j++ )
+ cStr[j] = ByteString::ConvertToUnicode( c[j], eSrc );
+ cStr[ n+1 ] = 0;
+ break;
+ }
+ case svString:
+ {
+ sal_Char c[ MAXSTRLEN+1 ];
+ rStream >> n;
+ if( n > MAXSTRLEN-1 )
+ {
+ DBG_ERRORFILE( "bad string array boundary" );
+ USHORT nDiff = n - (MAXSTRLEN-1);
+ n = MAXSTRLEN-1;
+ rStream.Read( c, n );
+ rStream.SeekRel( nDiff );
+ }
+ else
+ rStream.Read( c, n );
+ cStr[ n ] = 0;
+ CharSet eSrc = rStream.GetStreamCharSet();
+ for ( BYTE j=0; j<n; j++ )
+ cStr[j] = ByteString::ConvertToUnicode( c[j], eSrc );
+ cStr[ n ] = 0;
+ break;
+ }
+ case svSingleRef:
+ case svDoubleRef:
+ {
+ SingleRefData& r = aRef.Ref1;
+ rStream >> r.nCol
+ >> r.nRow
+ >> r.nTab
+ >> n;
+ if ( nVer < SC_RELATIVE_REFS )
+ {
+ OldSingleRefBools aBools;
+ aBools.bRelCol = ( n & 0x03 );
+ aBools.bRelRow = ( ( n >> 2 ) & 0x03 );
+ aBools.bRelTab = ( ( n >> 4 ) & 0x03 );
+ aBools.bOldFlag3D = ( ( n >> 6 ) & 0x03 );
+ r.OldBoolsToNewFlags( aBools );
+ }
+ else
+ r.CreateFlagsFromLoadByte( n );
+ if( eType == svSingleRef )
+ aRef.Ref2 = r;
+ else
+ {
+ SingleRefData& r = aRef.Ref2;
+ rStream >> r.nCol
+ >> r.nRow
+ >> r.nTab
+ >> n;
+ if ( nVer < SC_RELATIVE_REFS )
+ {
+ OldSingleRefBools aBools;
+ aBools.bRelCol = ( n & 0x03 );
+ aBools.bRelRow = ( ( n >> 2 ) & 0x03 );
+ aBools.bRelTab = ( ( n >> 4 ) & 0x03 );
+ aBools.bOldFlag3D = ( ( n >> 6 ) & 0x03 );
+ r.OldBoolsToNewFlags( aBools );
+ }
+ else
+ r.CreateFlagsFromLoadByte( n );
+ }
+ break;
+ }
+ case svIndex:
+ rStream >> nIndex;
+ break;
+ case svJump:
+ rStream >> n;
+ nJump[ 0 ] = n;
+ for( i = 1; i <= n; i++ )
+ rStream >> nJump[ i ];
+ break;
+ case svMissing:
+ case svErr:
+ break;
+ default:
+ {
+ rStream >> n;
+ cStr[ 0 ] = n;
+ // eigentlich kann es nicht 0 sein, aber bei rottem Dokument
+ // nicht wild in den Stack lesen
+ if ( n > 1 )
+ rStream.Read( cStr+1, n-1 );
+ }
+ }
+}
+
+void ScToken::Store( SvStream& rStream ) const
+{
+ short i;
+ rStream << (UINT16) eOp << (BYTE) eType;
+ switch( eType )
+ {
+ case svByte:
+ rStream << cByte;
+ break;
+ case svDouble:
+ rStream << nValue;
+ break;
+ case svExternal:
+ {
+ ByteString aTmp( cStr+1, rStream.GetStreamCharSet() );
+ rStream << cByte
+ << (UINT8) aTmp.Len();
+ rStream.Write( aTmp.GetBuffer(), (UINT8) aTmp.Len() );
+ }
+ break;
+ case svString:
+ {
+ ByteString aTmp( cStr, rStream.GetStreamCharSet() );
+ rStream << (UINT8) aTmp.Len();
+ rStream.Write( aTmp.GetBuffer(), (UINT8) aTmp.Len() );
+ }
+ break;
+ case svSingleRef:
+ case svDoubleRef:
+ {
+ const SingleRefData& r = aRef.Ref1;
+ BYTE n = r.CreateStoreByteFromFlags();
+ rStream << (INT16) r.nCol
+ << (INT16) r.nRow
+ << (INT16) r.nTab
+ << (BYTE) n;
+ if( eType == svDoubleRef )
+ {
+ const SingleRefData& r = aRef.Ref2;
+ BYTE n = r.CreateStoreByteFromFlags();
+ rStream << (INT16) r.nCol
+ << (INT16) r.nRow
+ << (INT16) r.nTab
+ << (BYTE) n;
+ }
+ break;
+ }
+ case svIndex:
+ rStream << (UINT16) nIndex;
+ break;
+ case svJump:
+ rStream << (BYTE) nJump[ 0 ];
+ for( i = 1; i <= nJump[ 0 ]; i++ )
+ rStream << (UINT16) nJump[ i ];
+ break;
+ case svMissing:
+ case svErr:
+ break;
+ default:
+ rStream.Write( cStr, cStr[ 0 ] );
+ }
+}
+
+/*----------------------------------------------------------------------*/
+
+ScTokenIterator::ScTokenIterator( const ScTokenArray& rArr )
+{
+ pCur = NULL;
+ Push( (ScTokenArray*) &rArr );
+}
+
+ScTokenIterator::~ScTokenIterator()
+{
+ while( pCur )
+ Pop();
+}
+
+void ScTokenIterator::Push( ScTokenArray* pArr )
+{
+ ImpTokenIterator* p = new ImpTokenIterator;
+ p->pArr = pArr;
+ p->nPC = -1;
+ p->pNext = pCur;
+ pCur = p;
+}
+
+void ScTokenIterator::Pop()
+{
+ ImpTokenIterator* p = pCur;
+ if( p )
+ {
+ pCur = p->pNext;
+ delete p;
+ }
+}
+
+void ScTokenIterator::Reset()
+{
+ while( pCur->pNext )
+ Pop();
+ pCur->nPC = -1;
+}
+
+const ScToken* ScTokenIterator::First()
+{
+ Reset();
+ return Next();
+}
+
+const ScToken* ScTokenIterator::Next()
+{
+ const ScToken* t = NULL;
+ if( ++pCur->nPC < pCur->pArr->nRPN )
+ {
+ t = pCur->pArr->pRPN[ pCur->nPC ];
+ // ein derartiger Opcode endet einen WENN- oder WAHL-Bereich
+ if( t->GetOpCode() == ocSep || t->GetOpCode() == ocClose )
+ t = NULL;
+ }
+ if( !t && pCur->pNext )
+ {
+ Pop(); t = Next();
+ }
+ return t;
+}
+
+// Die PC-Werte sind -1!
+
+void ScTokenIterator::Jump( short nStart, short nNext )
+{
+ pCur->nPC = nNext;
+ if( nStart != nNext )
+ {
+ Push( pCur->pArr );
+ pCur->nPC = nStart;
+ }
+}
+
+
diff --git a/sc/source/core/tool/unitconv.cxx b/sc/source/core/tool/unitconv.cxx
new file mode 100644
index 000000000000..4b27bc704d60
--- /dev/null
+++ b/sc/source/core/tool/unitconv.cxx
@@ -0,0 +1,275 @@
+/*************************************************************************
+ *
+ * $RCSfile: unitconv.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:19 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#ifndef SC_UNITCONV_HXX
+#include "unitconv.hxx"
+#endif
+#ifndef SC_SCGLOB_HXX
+#include "global.hxx"
+#endif
+#ifndef _SFXDOCFILE_HXX
+#include <sfx2/docfile.hxx>
+#endif
+#ifndef _SFX_INIMGR_HXX //autogen
+#include <sfx2/inimgr.hxx>
+#endif
+#ifndef _SFXINIMGR_HXX //autogen
+#include <svtools/iniman.hxx>
+#endif
+#ifndef _TOOLS_SOLMATH_HXX //autogen wg. SolarMath
+#include <tools/solmath.hxx>
+#endif
+#ifndef _TOOLS_INTN_HXX //autogen wg. International
+#include <tools/intn.hxx>
+#endif
+#ifndef _STREAM_HXX //autogen
+#include <tools/stream.hxx>
+#endif
+#ifndef _URLOBJ_HXX
+#include <tools/urlobj.hxx>
+#endif
+
+const sal_Unicode cDelim = 0x01; // Delimiter zwischen From und To
+
+
+// --- ScUnitConverterData --------------------------------------------
+
+ScUnitConverterData::ScUnitConverterData( const String& rFromUnit,
+ const String& rToUnit, double fVal )
+ :
+ StrData( rFromUnit ),
+ fValue( fVal )
+{
+ String aTmp;
+ ScUnitConverterData::BuildIndexString( aTmp, rFromUnit, rToUnit );
+ SetString( aTmp );
+}
+
+
+ScUnitConverterData::ScUnitConverterData( const ScUnitConverterData& r )
+ :
+ StrData( r ),
+ fValue( r.fValue )
+{
+}
+
+
+DataObject* ScUnitConverterData::Clone() const
+{
+ return new ScUnitConverterData( *this );
+}
+
+
+// static
+void ScUnitConverterData::BuildIndexString( String& rStr,
+ const String& rFromUnit, const String& rToUnit )
+{
+#if 1
+// case sensitive
+ rStr = rFromUnit;
+ rStr += cDelim;
+ rStr += rToUnit;
+#else
+// not case sensitive
+ rStr = rFromUnit;
+ String aTo( rToUnit );
+ ScGlobal::pCharClass->toUpper( rStr );
+ ScGlobal::pCharClass->toUpper( aTo );
+ rStr += cDelim;
+ rStr += aTo;
+#endif
+}
+
+
+// --- ScUnitConverter ------------------------------------------------
+
+ScUnitConverter::ScUnitConverter( USHORT nInit, USHORT nDelta )
+ :
+ StrCollection( nInit, nDelta, FALSE )
+{
+ ReadIniFiles();
+}
+
+
+inline const sal_Unicode* SkipWhite( const sal_Unicode* p )
+{
+ while ( *p == ' ' || *p == '\t' )
+ p++;
+ return p;
+}
+
+
+void ScUnitConverter::ReadIniFiles()
+{
+ International aIntl( LANGUAGE_ENGLISH_US );
+ String aName( RTL_CONSTASCII_USTRINGPARAM("convert.ini") );
+ INetURLObject aURL;
+
+ // share/config/convert.ini first, global definitions
+ String aPath( SFX_INIMANAGER()->Get( SFX_KEY_CONFIG_DIR ) );
+ if ( aPath.Len() > 0 )
+ {
+ aURL.SetSmartURL( aPath );
+ aURL.setFinalSlash();
+ aURL.Append( aName );
+ ReadIniFile( aURL.GetMainURL(), aIntl );
+ }
+
+ // user/config/convert.ini may NOT overwrite globals (StrCollecion no dupes)
+ aPath = SFX_INIMANAGER()->Get( SFX_KEY_USERCONFIG_PATH );
+ if ( aPath.Len() > 0 )
+ {
+ aURL.SetSmartURL( aPath );
+ aURL.setFinalSlash();
+ aURL.Append( aName );
+ ReadIniFile( aURL.GetMainURL(), aIntl );
+ }
+}
+
+
+void ScUnitConverter::ReadIniFile( const String& rFileName, International& rIntl )
+{
+ SfxMedium aMedium( rFileName,
+ STREAM_READ | STREAM_NOCREATE | STREAM_SHARE_DENYWRITE, TRUE );
+ SvStream* pStream = aMedium.GetInStream();
+ if ( !pStream || pStream->GetError() != 0 )
+ return ;
+ SvStream& rStream = *pStream;
+
+ ByteString aByteLine;
+ BOOL bIsConv = FALSE;
+ while ( !bIsConv && rStream.ReadLine( aByteLine ) )
+ {
+ aByteLine.EraseAllChars( ' ' );
+ bIsConv = aByteLine.Equals( "[UnitConversion]" );
+ }
+
+ while ( bIsConv && rStream.ReadLine( aByteLine ) )
+ {
+ String aLine( aByteLine, osl_getThreadTextEncoding() );
+ const sal_Unicode* const pBeg = aLine.GetBuffer();
+ register const sal_Unicode* p = SkipWhite( pBeg );
+ // Format: "FromUnit";"ToUnit";1.23 ;evtl. Kommentar
+ if ( *p == '"' )
+ {
+ //! keine '"' in Unit
+ const sal_Unicode* const p1 = ++p;
+ while ( *p != '"' )
+ p++;
+ String aFromUnit( aLine.Copy( p1 - pBeg, p - p1 ) );
+ p = SkipWhite( ++p );
+ if ( *p == ';' )
+ {
+ p = SkipWhite( ++p );
+ if ( *p == '"' )
+ {
+ //! keine '"' in Unit
+ const sal_Unicode* const p1 = ++p;
+ while ( *p != '"' )
+ p++;
+ String aToUnit( aLine.Copy( p1 - pBeg, p - p1 ) );
+ p = SkipWhite( ++p );
+ if ( *p == ';' )
+ {
+ p = SkipWhite( ++p );
+ int nErrno;
+ const sal_Unicode* pEnd;
+ double fValue = SolarMath::StringToDouble(
+ p, rIntl, nErrno, &pEnd );
+ if ( !nErrno && pEnd > p )
+ {
+ ScUnitConverterData* pData =
+ new ScUnitConverterData( aFromUnit, aToUnit,
+ fValue );
+ if ( !Insert( pData ) )
+ delete pData;
+ }
+ }
+ }
+ }
+ }
+ else if ( *p == '[' && ScGlobal::UnicodeStrChr( p+1, ']' ) )
+ bIsConv = FALSE; // neue [Section]
+ }
+}
+
+
+BOOL ScUnitConverter::GetValue( double& fValue, const String& rFromUnit,
+ const String& rToUnit ) const
+{
+ ScUnitConverterData aSearch( rFromUnit, rToUnit );
+ USHORT nIndex;
+ if ( Search( &aSearch, nIndex ) )
+ {
+ fValue = ((const ScUnitConverterData*)(At( nIndex )))->GetValue();
+ return TRUE;
+ }
+ fValue = 1.0;
+ return FALSE;
+}
+
+
diff --git a/sc/source/core/tool/userlist.cxx b/sc/source/core/tool/userlist.cxx
new file mode 100644
index 000000000000..bdbff00bb72b
--- /dev/null
+++ b/sc/source/core/tool/userlist.cxx
@@ -0,0 +1,326 @@
+/*************************************************************************
+ *
+ * $RCSfile: userlist.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:19 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+//------------------------------------------------------------------------
+
+#include <tools/intn.hxx>
+#include <unotools/charclass.hxx>
+#include <string.h>
+
+#include "global.hxx"
+#include "userlist.hxx"
+
+// STATIC DATA -----------------------------------------------------------
+
+
+//------------------------------------------------------------------------
+
+void ScUserListData::InitTokens()
+{
+ sal_Unicode cSep = ScGlobal::cListDelimiter;
+ nTokenCount = (USHORT) aStr.GetTokenCount(cSep);
+ if (nTokenCount)
+ {
+ pSubStrings = new String[nTokenCount];
+ pUpperSub = new String[nTokenCount];
+ for (USHORT i=0; i<nTokenCount; i++)
+ {
+ pUpperSub[i] = pSubStrings[i] = aStr.GetToken((xub_StrLen)i,cSep);
+ ScGlobal::pCharClass->toUpper(pUpperSub[i]);
+ }
+ }
+ else
+ pSubStrings = pUpperSub = NULL;
+}
+
+ScUserListData::ScUserListData(const String& rStr) :
+ aStr(rStr)
+{
+ InitTokens();
+}
+
+ScUserListData::ScUserListData(const ScUserListData& rData) :
+ aStr(rData.aStr)
+{
+ InitTokens();
+}
+
+__EXPORT ScUserListData::~ScUserListData()
+{
+ delete[] pSubStrings;
+ delete[] pUpperSub;
+}
+
+ScUserListData::ScUserListData( SvStream& rStream )
+{
+ rStream.ReadByteString( aStr, rStream.GetStreamCharSet() );
+ InitTokens();
+}
+
+BOOL ScUserListData::Store( SvStream& rStream ) const
+{
+ rStream.WriteByteString( aStr, rStream.GetStreamCharSet() );
+ return TRUE;
+}
+
+void ScUserListData::SetString( const String& rStr )
+{
+ delete[] pSubStrings;
+ delete[] pUpperSub;
+
+ aStr = rStr;
+ InitTokens();
+}
+
+USHORT ScUserListData::GetSubCount() const
+{
+ return nTokenCount;
+}
+
+BOOL ScUserListData::GetSubIndex(const String& rSubStr, USHORT& rIndex) const
+{
+ USHORT i;
+ for (i=0; i<nTokenCount; i++)
+ if (rSubStr == pSubStrings[i])
+ {
+ rIndex = i;
+ return TRUE;
+ }
+
+ String aUpStr = rSubStr;
+ ScGlobal::pCharClass->toUpper(aUpStr);
+ for (i=0; i<nTokenCount; i++)
+ if (aUpStr == pUpperSub[i])
+ {
+ rIndex = i;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+String ScUserListData::GetSubStr(USHORT nIndex) const
+{
+ if (nIndex < nTokenCount)
+ return pSubStrings[nIndex];
+ else
+ return EMPTY_STRING;
+}
+
+StringCompare ScUserListData::Compare(const String& rSubStr1, const String& rSubStr2) const
+{
+ USHORT nIndex1;
+ USHORT nIndex2;
+ BOOL bFound1 = GetSubIndex(rSubStr1, nIndex1);
+ BOOL bFound2 = GetSubIndex(rSubStr2, nIndex2);
+ if (bFound1)
+ {
+ if (bFound2)
+ {
+ if (nIndex1 < nIndex2)
+ return COMPARE_LESS;
+ else if (nIndex1 > nIndex2)
+ return COMPARE_GREATER;
+ else
+ return COMPARE_EQUAL;
+ }
+ else
+ return COMPARE_LESS;
+ }
+ else if (bFound2)
+ return COMPARE_GREATER;
+ else
+ return rSubStr2.CompareTo(rSubStr1);
+}
+
+StringCompare ScUserListData::ICompare(const String& rSubStr1, const String& rSubStr2) const
+{
+ USHORT nIndex1;
+ USHORT nIndex2;
+ BOOL bFound1 = GetSubIndex(rSubStr1, nIndex1);
+ BOOL bFound2 = GetSubIndex(rSubStr2, nIndex2);
+ if (bFound1)
+ {
+ if (bFound2)
+ {
+ if (nIndex1 < nIndex2)
+ return COMPARE_LESS;
+ else if (nIndex1 > nIndex2)
+ return COMPARE_GREATER;
+ else
+ return COMPARE_EQUAL;
+ }
+ else
+ return COMPARE_LESS;
+ }
+ else if (bFound2)
+ return COMPARE_GREATER;
+ else
+ return ScGlobal::pScInternational->Compare( rSubStr1, rSubStr2, INTN_COMPARE_IGNORECASE );
+}
+
+ScUserList::ScUserList(USHORT nLim, USHORT nDel) :
+ Collection ( nLim, nDel )
+{
+ String sMonthShort, sMonthLong, sDayShort, sDayLong;
+ sal_Unicode cDelimiter = ScGlobal::cListDelimiter;
+ USHORT i;
+
+ for (i = 1; i < 12; i++)
+ {
+ sMonthShort += ScGlobal::pScInternational->GetAbbrevMonthText(i);
+ sMonthShort += cDelimiter;
+ sMonthLong += ScGlobal::pScInternational->GetMonthText(i);
+ sMonthLong += cDelimiter;
+ }
+ sMonthShort += ScGlobal::pScInternational->GetAbbrevMonthText(i);
+ sMonthLong += ScGlobal::pScInternational->GetMonthText(i);
+
+ for (i = 0; i < 6; i++)
+ {
+ sDayShort += ScGlobal::pScInternational->GetAbbrevDayText((DayOfWeek)i);
+ sDayShort += cDelimiter;
+ sDayLong += ScGlobal::pScInternational->GetDayText((DayOfWeek)i);
+ sDayLong += cDelimiter;
+ }
+ sDayShort += ScGlobal::pScInternational->GetAbbrevDayText((DayOfWeek)i);
+ sDayLong += ScGlobal::pScInternational->GetDayText((DayOfWeek)i);
+
+ Insert( new ScUserListData( sDayShort ));
+ Insert( new ScUserListData( sDayLong ));
+ Insert( new ScUserListData( sMonthShort ));
+ Insert( new ScUserListData( sMonthLong ));
+}
+
+BOOL ScUserList::Load( SvStream& rStream )
+{
+ BOOL bSuccess = TRUE;
+ USHORT nNewCount;
+
+ while( nCount > 0 )
+ AtFree(0); // alles loeschen
+
+ rStream >> nNewCount;
+
+ for ( USHORT i=0; i<nNewCount && bSuccess; i++ )
+ Insert( new ScUserListData( rStream ) );
+
+ return bSuccess;
+}
+
+BOOL ScUserList::Store( SvStream& rStream ) const
+{
+ BOOL bSuccess = TRUE;
+
+ rStream << nCount;
+
+ for ( USHORT i=0; i<nCount && bSuccess; i++ )
+ bSuccess = ((const ScUserListData*)At(i))->Store( rStream );
+
+ return bSuccess;
+}
+
+DataObject* ScUserList::Clone() const
+{
+ return ( new ScUserList( *this ) );
+}
+
+ScUserListData* ScUserList::GetData(const String& rSubStr) const
+{
+ USHORT nIndex;
+ USHORT i = 0;
+ for (i=0; i < nCount; i++)
+ if (((ScUserListData*)pItems[i])->GetSubIndex(rSubStr, nIndex))
+ return (ScUserListData*)pItems[i];
+ return NULL;
+}
+
+BOOL ScUserList::operator==( const ScUserList& r ) const
+{
+ BOOL bEqual = (nCount == r.nCount);
+
+ if ( bEqual )
+ {
+ ScUserListData* pMyData = NULL;
+ ScUserListData* pOtherData = NULL;
+
+ for ( USHORT i=0; i<nCount && bEqual; i++)
+ {
+ pMyData = (ScUserListData*)At(i);
+ pOtherData = (ScUserListData*)r.At(i);
+
+ bEqual =( (pMyData->nTokenCount == pOtherData->nTokenCount)
+ && (pMyData->aStr == pOtherData->aStr) );
+ }
+ }
+
+ return bEqual;
+}
+
+
+
+
diff --git a/sc/source/core/tool/viewopti.cxx b/sc/source/core/tool/viewopti.cxx
new file mode 100644
index 000000000000..7c3fe45ccf22
--- /dev/null
+++ b/sc/source/core/tool/viewopti.cxx
@@ -0,0 +1,915 @@
+/*************************************************************************
+ *
+ * $RCSfile: viewopti.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:19 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include <vcl/svapp.hxx>
+
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include "global.hxx"
+#include "globstr.hrc"
+#include "cfgids.hxx"
+#include "viewopti.hxx"
+#include "rechead.hxx"
+#include "scresid.hxx"
+#include "sc.hrc"
+#include "miscuno.hxx"
+
+using namespace utl;
+using namespace rtl;
+using namespace com::sun::star::uno;
+
+//------------------------------------------------------------------
+
+TYPEINIT1(ScTpViewItem, SfxPoolItem);
+
+#define SC_VERSION ((USHORT)302)
+
+
+//========================================================================
+// class ScGridOptions
+//========================================================================
+
+
+void ScGridOptions::SetDefaults()
+{
+ *this = ScGridOptions();
+
+ // Raster-Defaults sind jetzt zwischen den Apps unterschiedlich
+ // darum hier selber eintragen (alles in 1/100mm)
+
+ MeasurementSystem eSys = Application::GetAppInternational().GetMeasurementSystem();
+ if ( eSys == MEASURE_METRIC )
+ {
+ nFldDrawX = 1000; // 1cm
+ nFldDrawY = 1000;
+ nFldSnapX = 1000;
+ nFldSnapY = 1000;
+ }
+ else
+ {
+ nFldDrawX = 1270; // 0,5"
+ nFldDrawY = 1270;
+ nFldSnapX = 1270;
+ nFldSnapY = 1270;
+ }
+ nFldDivisionX = 1;
+ nFldDivisionY = 1;
+}
+
+//------------------------------------------------------------------------
+
+const ScGridOptions& ScGridOptions::operator=( const ScGridOptions& rCpy )
+{
+ nFldDrawX = rCpy.nFldDrawX; // UINT32
+ nFldDrawX = rCpy.nFldDrawX;
+ nFldDivisionX = rCpy.nFldDivisionX;
+ nFldDrawY = rCpy.nFldDrawY;
+ nFldDivisionY = rCpy.nFldDivisionY;
+ nFldSnapX = rCpy.nFldSnapX;
+ nFldSnapY = rCpy.nFldSnapY;
+ bUseGridsnap = rCpy.bUseGridsnap; // BitBool
+ bSynchronize = rCpy.bSynchronize;
+ bGridVisible = rCpy.bGridVisible;
+ bEqualGrid = rCpy.bEqualGrid;
+
+ return *this;
+}
+
+//------------------------------------------------------------------------
+
+int ScGridOptions::operator==( const ScGridOptions& rCpy ) const
+{
+ return ( nFldDrawX == rCpy.nFldDrawX
+ && nFldDrawX == rCpy.nFldDrawX
+ && nFldDivisionX == rCpy.nFldDivisionX
+ && nFldDrawY == rCpy.nFldDrawY
+ && nFldDivisionY == rCpy.nFldDivisionY
+ && nFldSnapX == rCpy.nFldSnapX
+ && nFldSnapY == rCpy.nFldSnapY
+ && bUseGridsnap == rCpy.bUseGridsnap
+ && bSynchronize == rCpy.bSynchronize
+ && bGridVisible == rCpy.bGridVisible
+ && bEqualGrid == rCpy.bEqualGrid );
+}
+
+
+//------------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rStream, ScGridOptions& rOpt )
+{
+ BYTE nDummy;
+ rStream >> rOpt.nFldDrawX;
+ rStream >> rOpt.nFldDrawY;
+ rStream >> rOpt.nFldDivisionX;
+ rStream >> rOpt.nFldDivisionY;
+ rStream >> rOpt.nFldSnapX;
+ rStream >> rOpt.nFldSnapY;
+ rStream >> nDummy; rOpt.bUseGridsnap = (BOOL)nDummy;
+ rStream >> nDummy; rOpt.bSynchronize = (BOOL)nDummy;
+ rStream >> nDummy; rOpt.bGridVisible = (BOOL)nDummy;
+ rStream >> nDummy; rOpt.bEqualGrid = (BOOL)nDummy;
+
+ return rStream;
+}
+
+//------------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rStream, const ScGridOptions& rOpt )
+{
+ rStream << rOpt.nFldDrawX;
+ rStream << rOpt.nFldDrawY;
+ rStream << rOpt.nFldDivisionX;
+ rStream << rOpt.nFldDivisionY;
+ rStream << rOpt.nFldSnapX;
+ rStream << rOpt.nFldSnapY;
+ rStream << (BOOL)rOpt.bUseGridsnap;
+ rStream << (BOOL)rOpt.bSynchronize;
+ rStream << (BOOL)rOpt.bGridVisible;
+ rStream << (BOOL)rOpt.bEqualGrid;
+
+ return rStream;
+}
+
+//========================================================================
+// class ScViewOptions
+//========================================================================
+
+ScViewOptions::ScViewOptions()
+{
+ SetDefaults();
+}
+
+//------------------------------------------------------------------------
+
+ScViewOptions::ScViewOptions( const ScViewOptions& rCpy )
+{
+ *this = rCpy;
+}
+
+//------------------------------------------------------------------------
+
+__EXPORT ScViewOptions::~ScViewOptions()
+{
+}
+
+//------------------------------------------------------------------------
+
+void ScViewOptions::SetDefaults()
+{
+ aOptArr[ VOPT_FORMULAS ] =
+ aOptArr[ VOPT_SYNTAX ] =
+ aOptArr[ VOPT_HELPLINES ] =
+ aOptArr[ VOPT_BIGHANDLES ] = FALSE;
+ aOptArr[ VOPT_NOTES ] =
+ aOptArr[ VOPT_NULLVALS ] =
+ aOptArr[ VOPT_VSCROLL ] =
+ aOptArr[ VOPT_HSCROLL ] =
+ aOptArr[ VOPT_TABCONTROLS ] =
+ aOptArr[ VOPT_OUTLINER ] =
+ aOptArr[ VOPT_HEADER ] =
+ aOptArr[ VOPT_GRID ] =
+ aOptArr[ VOPT_ANCHOR ] =
+ aOptArr[ VOPT_PAGEBREAKS ] =
+ aOptArr[ VOPT_SOLIDHANDLES] =
+ aOptArr[ VOPT_CLIPMARKS ] = TRUE;
+
+ aModeArr[VOBJ_TYPE_OLE ] =
+ aModeArr[VOBJ_TYPE_CHART] =
+ aModeArr[VOBJ_TYPE_DRAW ] = VOBJ_MODE_SHOW;
+
+ aGridCol = Color( COL_LIGHTGRAY );
+ aGridColName = ScGlobal::GetRscString( STR_GRIDCOLOR );
+
+ aGridOpt.SetDefaults();
+
+ bHideAutoSpell = FALSE;
+}
+
+//------------------------------------------------------------------------
+
+Color ScViewOptions::GetGridColor( String* pStrName ) const
+{
+ if ( pStrName )
+ *pStrName = aGridColName;
+
+ return aGridCol;
+}
+
+//------------------------------------------------------------------------
+
+const ScViewOptions& ScViewOptions::operator=( const ScViewOptions& rCpy )
+{
+ USHORT i;
+
+ for ( i=0; i<MAX_OPT; i++ ) aOptArr [i] = rCpy.aOptArr[i];
+ for ( i=0; i<MAX_TYPE; i++ ) aModeArr[i] = rCpy.aModeArr[i];
+
+ aGridCol = rCpy.aGridCol;
+ aGridColName = rCpy.aGridColName;
+ aGridOpt = rCpy.aGridOpt;
+ bHideAutoSpell = rCpy.bHideAutoSpell;
+
+ return *this;
+}
+
+//------------------------------------------------------------------------
+
+int ScViewOptions::operator==( const ScViewOptions& rOpt ) const
+{
+ BOOL bEqual = TRUE;
+ USHORT i;
+
+ for ( i=0; i<MAX_OPT && bEqual; i++ ) bEqual = (aOptArr [i] == rOpt.aOptArr[i]);
+ for ( i=0; i<MAX_TYPE && bEqual; i++ ) bEqual = (aModeArr[i] == rOpt.aModeArr[i]);
+
+ bEqual = bEqual && (aGridCol == rOpt.aGridCol);
+ bEqual = bEqual && (aGridColName == rOpt.aGridColName);
+ bEqual = bEqual && (aGridOpt == rOpt.aGridOpt);
+ bEqual = bEqual && (bHideAutoSpell == rOpt.bHideAutoSpell);
+
+ return bEqual;
+}
+
+//------------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rStream, ScViewOptions& rOpt )
+{
+ USHORT i;
+ BYTE n;
+
+ ScReadHeader aHdr( rStream );
+
+ for ( i=0; i<=VOPT_GRID; i++ ) // kompatibel bleiben -> nur bis VOPT_GRID
+ rStream >> rOpt.aOptArr[i];
+
+ for ( i=0; i<MAX_TYPE; i++ )
+ rStream >> n, rOpt.aModeArr[i] = (ScVObjMode)n;
+
+ rStream >> rOpt.aGridCol;
+ rStream.ReadByteString( rOpt.aGridColName, rStream.GetStreamCharSet() );
+
+ if( aHdr.BytesLeft() )
+ rStream >> rOpt.aOptArr[VOPT_HELPLINES];
+
+ if( aHdr.BytesLeft() )
+ rStream >> rOpt.aGridOpt;
+
+ if( aHdr.BytesLeft() )
+ rStream >> rOpt.bHideAutoSpell;
+
+ if( aHdr.BytesLeft() )
+ rStream >> rOpt.aOptArr[VOPT_ANCHOR];
+
+ if( aHdr.BytesLeft() )
+ rStream >> rOpt.aOptArr[VOPT_PAGEBREAKS];
+
+ if( aHdr.BytesLeft() )
+ rStream >> rOpt.aOptArr[VOPT_SOLIDHANDLES];
+
+ if( aHdr.BytesLeft() )
+ rStream >> rOpt.aOptArr[VOPT_CLIPMARKS];
+
+ if( aHdr.BytesLeft() )
+ rStream >> rOpt.aOptArr[VOPT_BIGHANDLES];
+
+ return rStream;
+}
+
+//------------------------------------------------------------------------
+
+void ScViewOptions::Save(SvStream& rStream, BOOL bConfig) const
+{
+ USHORT i;
+
+ ScWriteHeader aHdr( rStream, 68 );
+
+ for ( i=0; i<=VOPT_GRID; i++ ) // kompatibel bleiben -> nur bis VOPT_GRID
+ rStream << aOptArr[i];
+
+ for ( i=0; i<MAX_TYPE; i++ )
+ rStream << (BYTE)aModeArr[i];
+
+ rStream << aGridCol;
+ rStream.WriteByteString( aGridColName, rStream.GetStreamCharSet() );
+ rStream << aOptArr[VOPT_HELPLINES];
+ rStream << aGridOpt;
+ rStream << bHideAutoSpell;
+ rStream << aOptArr[VOPT_ANCHOR];
+ rStream << aOptArr[VOPT_PAGEBREAKS];
+ rStream << aOptArr[VOPT_SOLIDHANDLES];
+
+ if ( bConfig || rStream.GetVersion() > SOFFICE_FILEFORMAT_40 ) // nicht bei 4.0 Export
+ {
+ rStream << aOptArr[VOPT_CLIPMARKS];
+
+ // big handles are not saved in 5.0-documents to avoid warning messages
+ //! save to files after 5.0 !!!
+
+ if ( bConfig )
+ rStream << aOptArr[VOPT_BIGHANDLES];
+ }
+}
+
+//------------------------------------------------------------------------
+
+SvxGridItem* ScViewOptions::CreateGridItem( USHORT nId /* = SID_ATTR_GRID_OPTIONS */ ) const
+{
+ SvxGridItem* pItem = new SvxGridItem( nId );
+
+ pItem->SetFldDrawX ( aGridOpt.GetFldDrawX() );
+ pItem->SetFldDivisionX ( aGridOpt.GetFldDivisionX() );
+ pItem->SetFldDrawY ( aGridOpt.GetFldDrawY() );
+ pItem->SetFldDivisionY ( aGridOpt.GetFldDivisionY() );
+ pItem->SetFldSnapX ( aGridOpt.GetFldSnapX() );
+ pItem->SetFldSnapY ( aGridOpt.GetFldSnapY() );
+ pItem->SetUseGridSnap ( aGridOpt.GetUseGridSnap() );
+ pItem->SetSynchronize ( aGridOpt.GetSynchronize() );
+ pItem->SetGridVisible ( aGridOpt.GetGridVisible() );
+ pItem->SetEqualGrid ( aGridOpt.GetEqualGrid() );
+
+ return pItem;
+}
+
+//========================================================================
+// ScTpViewItem - Daten fuer die ViewOptions-TabPage
+//========================================================================
+
+ScTpViewItem::ScTpViewItem( USHORT nWhich ) : SfxPoolItem( nWhich )
+{
+}
+
+//------------------------------------------------------------------------
+
+ScTpViewItem::ScTpViewItem( USHORT nWhich, const ScViewOptions& rOpt )
+ : SfxPoolItem ( nWhich ),
+ theOptions ( rOpt )
+{
+}
+
+//------------------------------------------------------------------------
+
+ScTpViewItem::ScTpViewItem( const ScTpViewItem& rItem )
+ : SfxPoolItem ( rItem ),
+ theOptions ( rItem.theOptions )
+{
+}
+
+//------------------------------------------------------------------------
+
+__EXPORT ScTpViewItem::~ScTpViewItem()
+{
+}
+
+//------------------------------------------------------------------------
+
+String __EXPORT ScTpViewItem::GetValueText() const
+{
+ return String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("ScTpViewItem") );
+}
+
+//------------------------------------------------------------------------
+
+int __EXPORT ScTpViewItem::operator==( const SfxPoolItem& rItem ) const
+{
+ DBG_ASSERT( SfxPoolItem::operator==( rItem ), "unequal Which or Type" );
+
+ const ScTpViewItem& rPItem = (const ScTpViewItem&)rItem;
+
+ return ( theOptions == rPItem.theOptions );
+}
+
+//------------------------------------------------------------------------
+
+SfxPoolItem* __EXPORT ScTpViewItem::Clone( SfxItemPool * ) const
+{
+ return new ScTpViewItem( *this );
+}
+
+//------------------------------------------------------------------------
+
+ScLinkConfigItem::ScLinkConfigItem( const rtl::OUString rSubTree ) :
+ ConfigItem( rSubTree )
+{
+}
+
+void ScLinkConfigItem::SetCommitLink( const Link& rLink )
+{
+ aCommitLink = rLink;
+}
+
+void ScLinkConfigItem::Notify( const com::sun::star::uno::Sequence<rtl::OUString>& aPropertyNames )
+{
+ //! not implemented yet...
+}
+
+void ScLinkConfigItem::Commit()
+{
+ aCommitLink.Call( this );
+}
+
+//==================================================================
+// Config Item containing view options
+//==================================================================
+
+#define CFGPATH_LAYOUT "Office.Calc/Layout"
+
+#define SCLAYOUTOPT_GRIDLINES 0
+#define SCLAYOUTOPT_GRIDCOLOR 1
+#define SCLAYOUTOPT_PAGEBREAK 2
+#define SCLAYOUTOPT_GUIDE 3
+#define SCLAYOUTOPT_SIMPLECONT 4
+#define SCLAYOUTOPT_LARGECONT 5
+#define SCLAYOUTOPT_COLROWHDR 6
+#define SCLAYOUTOPT_HORISCROLL 7
+#define SCLAYOUTOPT_VERTSCROLL 8
+#define SCLAYOUTOPT_SHEETTAB 9
+#define SCLAYOUTOPT_OUTLINE 10
+#define SCLAYOUTOPT_COUNT 11
+
+#define CFGPATH_DISPLAY "Office.Calc/Content/Display"
+
+#define SCDISPLAYOPT_FORMULA 0
+#define SCDISPLAYOPT_ZEROVALUE 1
+#define SCDISPLAYOPT_NOTETAG 2
+#define SCDISPLAYOPT_VALUEHI 3
+#define SCDISPLAYOPT_ANCHOR 4
+#define SCDISPLAYOPT_TEXTOVER 5
+#define SCDISPLAYOPT_OBJECTGRA 6
+#define SCDISPLAYOPT_CHART 7
+#define SCDISPLAYOPT_DRAWING 8
+#define SCDISPLAYOPT_COUNT 9
+
+#define CFGPATH_GRID "Office.Calc/Grid"
+
+#define SCGRIDOPT_RESOLU_X 0
+#define SCGRIDOPT_RESOLU_Y 1
+#define SCGRIDOPT_SUBDIV_X 2
+#define SCGRIDOPT_SUBDIV_Y 3
+#define SCGRIDOPT_OPTION_X 4
+#define SCGRIDOPT_OPTION_Y 5
+#define SCGRIDOPT_SNAPTOGRID 6
+#define SCGRIDOPT_SYNCHRON 7
+#define SCGRIDOPT_VISIBLE 8
+#define SCGRIDOPT_SIZETOGRID 9
+#define SCGRIDOPT_COUNT 10
+
+
+Sequence<OUString> ScViewCfg::GetLayoutPropertyNames()
+{
+ static const char* aPropNames[] =
+ {
+ "Line/GridLine", // SCLAYOUTOPT_GRIDLINES
+ "Line/GridLineColor", // SCLAYOUTOPT_GRIDCOLOR
+ "Line/PageBreak", // SCLAYOUTOPT_PAGEBREAK
+ "Line/Guide", // SCLAYOUTOPT_GUIDE
+ "Line/SimpleControlPoint", // SCLAYOUTOPT_SIMPLECONT
+ "Line/LargeControlPoint", // SCLAYOUTOPT_LARGECONT
+ "Window/ColumnRowHeader", // SCLAYOUTOPT_COLROWHDR
+ "Window/HorizontalScroll", // SCLAYOUTOPT_HORISCROLL
+ "Window/VerticalScroll", // SCLAYOUTOPT_VERTSCROLL
+ "Window/SheetTab", // SCLAYOUTOPT_SHEETTAB
+ "Window/OutlineSymbol" // SCLAYOUTOPT_OUTLINE
+ };
+ Sequence<OUString> aNames(SCLAYOUTOPT_COUNT);
+ OUString* pNames = aNames.getArray();
+ for(int i = 0; i < SCLAYOUTOPT_COUNT; i++)
+ pNames[i] = OUString::createFromAscii(aPropNames[i]);
+
+ return aNames;
+}
+
+Sequence<OUString> ScViewCfg::GetDisplayPropertyNames()
+{
+ static const char* aPropNames[] =
+ {
+ "Formula", // SCDISPLAYOPT_FORMULA
+ "ZeroValue", // SCDISPLAYOPT_ZEROVALUE
+ "NoteTag", // SCDISPLAYOPT_NOTETAG
+ "ValueHighlighting", // SCDISPLAYOPT_VALUEHI
+ "Anchor", // SCDISPLAYOPT_ANCHOR
+ "TextOverflow", // SCDISPLAYOPT_TEXTOVER
+ "ObjectGraphic", // SCDISPLAYOPT_OBJECTGRA
+ "Chart", // SCDISPLAYOPT_CHART
+ "DrawingObject" // SCDISPLAYOPT_DRAWING
+ };
+ Sequence<OUString> aNames(SCDISPLAYOPT_COUNT);
+ OUString* pNames = aNames.getArray();
+ for(int i = 0; i < SCDISPLAYOPT_COUNT; i++)
+ pNames[i] = OUString::createFromAscii(aPropNames[i]);
+
+ return aNames;
+}
+
+Sequence<OUString> ScViewCfg::GetGridPropertyNames()
+{
+ static const char* aPropNames[] =
+ {
+ "Resolution/XAxis", // SCGRIDOPT_RESOLU_X
+ "Resolution/YAxis", // SCGRIDOPT_RESOLU_Y
+ "Subdivision/XAxis", // SCGRIDOPT_SUBDIV_X
+ "Subdivision/YAxis", // SCGRIDOPT_SUBDIV_Y
+ "Option/XAxis", // SCGRIDOPT_OPTION_X
+ "Option/YAxis", // SCGRIDOPT_OPTION_Y
+ "Option/SnapToGrid", // SCGRIDOPT_SNAPTOGRID
+ "Option/Synchronize", // SCGRIDOPT_SYNCHRON
+ "Option/VisibleGrid", // SCGRIDOPT_VISIBLE
+ "Option/SizeToGrid" // SCGRIDOPT_SIZETOGRID
+ };
+ Sequence<OUString> aNames(SCGRIDOPT_COUNT);
+ OUString* pNames = aNames.getArray();
+ for(int i = 0; i < SCGRIDOPT_COUNT; i++)
+ pNames[i] = OUString::createFromAscii(aPropNames[i]);
+
+ return aNames;
+}
+
+
+ScViewCfg::ScViewCfg() :
+ aLayoutItem( OUString::createFromAscii( CFGPATH_LAYOUT ) ),
+ aDisplayItem( OUString::createFromAscii( CFGPATH_DISPLAY ) ),
+ aGridItem( OUString::createFromAscii( CFGPATH_GRID ) )
+{
+ sal_Int32 nIntVal;
+
+ Sequence<OUString> aNames = GetLayoutPropertyNames();
+ Sequence<Any> aValues = aLayoutItem.GetProperties(aNames);
+ aLayoutItem.EnableNotification(aNames);
+ const Any* pValues = aValues.getConstArray();
+ DBG_ASSERT(aValues.getLength() == aNames.getLength(), "GetProperties failed")
+ if(aValues.getLength() == aNames.getLength())
+ {
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ DBG_ASSERT(pValues[nProp].hasValue(), "property value missing")
+ if(pValues[nProp].hasValue())
+ {
+ switch(nProp)
+ {
+ case SCLAYOUTOPT_GRIDCOLOR:
+ if ( pValues[nProp] >>= nIntVal )
+ SetGridColor( Color(nIntVal), EMPTY_STRING );
+ break;
+ case SCLAYOUTOPT_GRIDLINES:
+ SetOption( VOPT_GRID, ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCLAYOUTOPT_PAGEBREAK:
+ SetOption( VOPT_PAGEBREAKS, ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCLAYOUTOPT_GUIDE:
+ SetOption( VOPT_HELPLINES, ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCLAYOUTOPT_SIMPLECONT:
+ // content is reversed
+ SetOption( VOPT_SOLIDHANDLES, !ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCLAYOUTOPT_LARGECONT:
+ SetOption( VOPT_BIGHANDLES, ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCLAYOUTOPT_COLROWHDR:
+ SetOption( VOPT_HEADER, ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCLAYOUTOPT_HORISCROLL:
+ SetOption( VOPT_HSCROLL, ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCLAYOUTOPT_VERTSCROLL:
+ SetOption( VOPT_VSCROLL, ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCLAYOUTOPT_SHEETTAB:
+ SetOption( VOPT_TABCONTROLS, ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCLAYOUTOPT_OUTLINE:
+ SetOption( VOPT_OUTLINER, ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ }
+ }
+ }
+ }
+ aLayoutItem.SetCommitLink( LINK( this, ScViewCfg, LayoutCommitHdl ) );
+
+ aNames = GetDisplayPropertyNames();
+ aValues = aDisplayItem.GetProperties(aNames);
+ aDisplayItem.EnableNotification(aNames);
+ pValues = aValues.getConstArray();
+ DBG_ASSERT(aValues.getLength() == aNames.getLength(), "GetProperties failed")
+ if(aValues.getLength() == aNames.getLength())
+ {
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ DBG_ASSERT(pValues[nProp].hasValue(), "property value missing")
+ if(pValues[nProp].hasValue())
+ {
+ switch(nProp)
+ {
+ case SCDISPLAYOPT_FORMULA:
+ SetOption( VOPT_FORMULAS, ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCDISPLAYOPT_ZEROVALUE:
+ SetOption( VOPT_NULLVALS, ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCDISPLAYOPT_NOTETAG:
+ SetOption( VOPT_NOTES, ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCDISPLAYOPT_VALUEHI:
+ SetOption( VOPT_SYNTAX, ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCDISPLAYOPT_ANCHOR:
+ SetOption( VOPT_ANCHOR, ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCDISPLAYOPT_TEXTOVER:
+ SetOption( VOPT_CLIPMARKS, ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCDISPLAYOPT_OBJECTGRA:
+ if ( pValues[nProp] >>= nIntVal )
+ SetObjMode( VOBJ_TYPE_OLE, (ScVObjMode) nIntVal );
+ break;
+ case SCDISPLAYOPT_CHART:
+ if ( pValues[nProp] >>= nIntVal )
+ SetObjMode( VOBJ_TYPE_CHART, (ScVObjMode) nIntVal );
+ break;
+ case SCDISPLAYOPT_DRAWING:
+ if ( pValues[nProp] >>= nIntVal )
+ SetObjMode( VOBJ_TYPE_DRAW, (ScVObjMode) nIntVal );
+ break;
+ }
+ }
+ }
+ }
+ aDisplayItem.SetCommitLink( LINK( this, ScViewCfg, DisplayCommitHdl ) );
+
+ ScGridOptions aGrid = GetGridOptions(); //! initialization necessary?
+ aNames = GetGridPropertyNames();
+ aValues = aGridItem.GetProperties(aNames);
+ aGridItem.EnableNotification(aNames);
+ pValues = aValues.getConstArray();
+ DBG_ASSERT(aValues.getLength() == aNames.getLength(), "GetProperties failed")
+ if(aValues.getLength() == aNames.getLength())
+ {
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ DBG_ASSERT(pValues[nProp].hasValue(), "property value missing")
+ if(pValues[nProp].hasValue())
+ {
+ switch(nProp)
+ {
+ case SCGRIDOPT_RESOLU_X:
+ if (pValues[nProp] >>= nIntVal) aGrid.SetFldDrawX( nIntVal );
+ break;
+ case SCGRIDOPT_RESOLU_Y:
+ if (pValues[nProp] >>= nIntVal) aGrid.SetFldDrawY( nIntVal );
+ break;
+ case SCGRIDOPT_SUBDIV_X:
+ if (pValues[nProp] >>= nIntVal) aGrid.SetFldDivisionX( nIntVal );
+ break;
+ case SCGRIDOPT_SUBDIV_Y:
+ if (pValues[nProp] >>= nIntVal) aGrid.SetFldDivisionY( nIntVal );
+ break;
+ case SCGRIDOPT_OPTION_X:
+ if (pValues[nProp] >>= nIntVal) aGrid.SetFldSnapX( nIntVal );
+ break;
+ case SCGRIDOPT_OPTION_Y:
+ if (pValues[nProp] >>= nIntVal) aGrid.SetFldSnapY( nIntVal );
+ break;
+ case SCGRIDOPT_SNAPTOGRID:
+ aGrid.SetUseGridSnap( ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCGRIDOPT_SYNCHRON:
+ aGrid.SetSynchronize( ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCGRIDOPT_VISIBLE:
+ aGrid.SetGridVisible( ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ case SCGRIDOPT_SIZETOGRID:
+ aGrid.SetEqualGrid( ScUnoHelpFunctions::GetBoolFromAny( pValues[nProp] ) );
+ break;
+ }
+ }
+ }
+ }
+ SetGridOptions( aGrid );
+ aGridItem.SetCommitLink( LINK( this, ScViewCfg, GridCommitHdl ) );
+}
+
+IMPL_LINK( ScViewCfg, LayoutCommitHdl, void *, EMPTYARG )
+{
+ Sequence<OUString> aNames = GetLayoutPropertyNames();
+ OUString* pNames = aNames.getArray();
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ const Type& rType = ::getBooleanCppuType();
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ switch(nProp)
+ {
+ case SCLAYOUTOPT_GRIDCOLOR:
+ pValues[nProp] <<= (sal_Int32) GetGridColor().GetColor();
+ break;
+ case SCLAYOUTOPT_GRIDLINES:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetOption( VOPT_GRID ) );
+ break;
+ case SCLAYOUTOPT_PAGEBREAK:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetOption( VOPT_PAGEBREAKS ) );
+ break;
+ case SCLAYOUTOPT_GUIDE:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetOption( VOPT_HELPLINES ) );
+ break;
+ case SCLAYOUTOPT_SIMPLECONT:
+ // content is reversed
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], !GetOption( VOPT_SOLIDHANDLES ) );
+ break;
+ case SCLAYOUTOPT_LARGECONT:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetOption( VOPT_BIGHANDLES ) );
+ break;
+ case SCLAYOUTOPT_COLROWHDR:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetOption( VOPT_HEADER ) );
+ break;
+ case SCLAYOUTOPT_HORISCROLL:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetOption( VOPT_HSCROLL ) );
+ break;
+ case SCLAYOUTOPT_VERTSCROLL:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetOption( VOPT_VSCROLL ) );
+ break;
+ case SCLAYOUTOPT_SHEETTAB:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetOption( VOPT_TABCONTROLS ) );
+ break;
+ case SCLAYOUTOPT_OUTLINE:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetOption( VOPT_OUTLINER ) );
+ break;
+ }
+ }
+ aLayoutItem.PutProperties(aNames, aValues);
+
+ return 0;
+}
+
+IMPL_LINK( ScViewCfg, DisplayCommitHdl, void *, EMPTYARG )
+{
+ Sequence<OUString> aNames = GetDisplayPropertyNames();
+ OUString* pNames = aNames.getArray();
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ const Type& rType = ::getBooleanCppuType();
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ switch(nProp)
+ {
+ case SCDISPLAYOPT_FORMULA:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetOption( VOPT_FORMULAS ) );
+ break;
+ case SCDISPLAYOPT_ZEROVALUE:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetOption( VOPT_NULLVALS ) );
+ break;
+ case SCDISPLAYOPT_NOTETAG:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetOption( VOPT_NOTES ) );
+ break;
+ case SCDISPLAYOPT_VALUEHI:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetOption( VOPT_SYNTAX ) );
+ break;
+ case SCDISPLAYOPT_ANCHOR:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetOption( VOPT_ANCHOR ) );
+ break;
+ case SCDISPLAYOPT_TEXTOVER:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], GetOption( VOPT_CLIPMARKS ) );
+ break;
+ case SCDISPLAYOPT_OBJECTGRA:
+ pValues[nProp] <<= (sal_Int32) GetObjMode( VOBJ_TYPE_OLE );
+ break;
+ case SCDISPLAYOPT_CHART:
+ pValues[nProp] <<= (sal_Int32) GetObjMode( VOBJ_TYPE_CHART );
+ break;
+ case SCDISPLAYOPT_DRAWING:
+ pValues[nProp] <<= (sal_Int32) GetObjMode( VOBJ_TYPE_DRAW );
+ break;
+ }
+ }
+ aDisplayItem.PutProperties(aNames, aValues);
+
+ return 0;
+}
+
+IMPL_LINK( ScViewCfg, GridCommitHdl, void *, EMPTYARG )
+{
+ const ScGridOptions& rGrid = GetGridOptions();
+
+ Sequence<OUString> aNames = GetGridPropertyNames();
+ OUString* pNames = aNames.getArray();
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ const Type& rType = ::getBooleanCppuType();
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ switch(nProp)
+ {
+ case SCGRIDOPT_RESOLU_X:
+ pValues[nProp] <<= (sal_Int32) rGrid.GetFldDrawX();
+ break;
+ case SCGRIDOPT_RESOLU_Y:
+ pValues[nProp] <<= (sal_Int32) rGrid.GetFldDrawY();
+ break;
+ case SCGRIDOPT_SUBDIV_X:
+ pValues[nProp] <<= (sal_Int32) rGrid.GetFldDivisionX();
+ break;
+ case SCGRIDOPT_SUBDIV_Y:
+ pValues[nProp] <<= (sal_Int32) rGrid.GetFldDivisionY();
+ break;
+ case SCGRIDOPT_OPTION_X:
+ pValues[nProp] <<= (sal_Int32) rGrid.GetFldSnapX();
+ break;
+ case SCGRIDOPT_OPTION_Y:
+ pValues[nProp] <<= (sal_Int32) rGrid.GetFldSnapY();
+ break;
+ case SCGRIDOPT_SNAPTOGRID:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], rGrid.GetUseGridSnap() );
+ break;
+ case SCGRIDOPT_SYNCHRON:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], rGrid.GetSynchronize() );
+ break;
+ case SCGRIDOPT_VISIBLE:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], rGrid.GetGridVisible() );
+ break;
+ case SCGRIDOPT_SIZETOGRID:
+ ScUnoHelpFunctions::SetBoolInAny( pValues[nProp], rGrid.GetEqualGrid() );
+ break;
+ }
+ }
+ aGridItem.PutProperties(aNames, aValues);
+
+ return 0;
+}
+
+void ScViewCfg::SetOptions( const ScViewOptions& rNew )
+{
+ *(ScViewOptions*)this = rNew;
+ aLayoutItem.SetModified();
+ aDisplayItem.SetModified();
+ aGridItem.SetModified();
+}
+
+
diff --git a/sc/source/core/tool/zforauto.cxx b/sc/source/core/tool/zforauto.cxx
new file mode 100644
index 000000000000..fdffdcc31314
--- /dev/null
+++ b/sc/source/core/tool/zforauto.cxx
@@ -0,0 +1,174 @@
+/*************************************************************************
+ *
+ * $RCSfile: zforauto.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:16:19 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PCH
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+//------------------------------------------------------------------------
+
+#include <svtools/zforlist.hxx>
+#include <svtools/zformat.hxx>
+#include <vcl/system.hxx>
+#include <tools/debug.hxx>
+
+#include "zforauto.hxx"
+#include "global.hxx"
+
+static const sal_Char __FAR_DATA pStandardName[] = "Standard";
+
+//------------------------------------------------------------------------
+
+ScNumFormatAbbrev::ScNumFormatAbbrev() :
+ eLnge (LANGUAGE_SYSTEM),
+ eSysLnge (LANGUAGE_GERMAN), // sonst passt "Standard" nicht
+ sFormatstring ( RTL_CONSTASCII_USTRINGPARAM( pStandardName ) )
+{
+}
+
+ScNumFormatAbbrev::ScNumFormatAbbrev(const ScNumFormatAbbrev& aFormat) :
+ eLnge (aFormat.eLnge),
+ eSysLnge (aFormat.eSysLnge),
+ sFormatstring (aFormat.sFormatstring)
+{
+}
+
+ScNumFormatAbbrev::ScNumFormatAbbrev(SvStream& rStream)
+{
+ Load(rStream);
+}
+
+ScNumFormatAbbrev::ScNumFormatAbbrev(ULONG nFormat,
+ SvNumberFormatter& rFormatter)
+{
+ PutFormatIndex(nFormat, rFormatter);
+}
+
+void ScNumFormatAbbrev::Load( SvStream& rStream )
+{
+ USHORT nSysLang, nLang;
+ rStream.ReadByteString( sFormatstring, rStream.GetStreamCharSet() );
+ rStream >> nSysLang >> nLang;
+ eLnge = (LanguageType) nLang;
+ eSysLnge = (LanguageType) nSysLang;
+ if ( eSysLnge == LANGUAGE_SYSTEM ) // von alten Versionen
+ eSysLnge = System::GetLanguage();
+}
+
+void ScNumFormatAbbrev::Save( SvStream& rStream ) const
+{
+ rStream.WriteByteString( sFormatstring, rStream.GetStreamCharSet() );
+ rStream << (USHORT) eSysLnge << (USHORT) eLnge;
+}
+
+void ScNumFormatAbbrev::PutFormatIndex(ULONG nFormat,
+ SvNumberFormatter& rFormatter)
+{
+ const SvNumberformat* pFormat = rFormatter.GetEntry(nFormat);
+ if (pFormat)
+ {
+ eSysLnge = System::GetLanguage();
+ eLnge = pFormat->GetLanguage();
+ sFormatstring = ((SvNumberformat*)pFormat)->GetFormatstring();
+ }
+ else
+ {
+ DBG_ERROR("SCNumFormatAbbrev:: unbekanntes Zahlformat");
+ eLnge = LANGUAGE_SYSTEM;
+ eSysLnge = LANGUAGE_GERMAN; // sonst passt "Standard" nicht
+ sFormatstring.AssignAscii( RTL_CONSTASCII_STRINGPARAM( pStandardName ) );
+ }
+}
+
+ULONG ScNumFormatAbbrev::GetFormatIndex( SvNumberFormatter& rFormatter)
+{
+ // #62389# leerer Formatstring (vom Writer) -> Standardformat
+ if ( !sFormatstring.Len() )
+ return rFormatter.GetStandardIndex( eLnge );
+
+ if ( eLnge == LANGUAGE_SYSTEM && eSysLnge != System::GetLanguage() )
+ {
+ ULONG nOrig = rFormatter.GetEntryKey( sFormatstring, eSysLnge );
+ if ( nOrig != NUMBERFORMAT_ENTRY_NOT_FOUND )
+ return rFormatter.GetFormatForLanguageIfBuiltIn( nOrig, System::GetLanguage() );
+ else
+ return rFormatter.GetStandardIndex( eLnge ); // geht nicht -> Standard
+ }
+
+ xub_StrLen nCheckPos;
+ short nType;
+ ULONG nKey = rFormatter.GetEntryKey(sFormatstring, eLnge);
+ if (nKey == NUMBERFORMAT_ENTRY_NOT_FOUND)
+ {
+ BOOL res = rFormatter.PutEntry(sFormatstring,
+ nCheckPos, nType, nKey, eLnge);
+ if (nCheckPos > 0)
+ DBG_ERROR("SCNumFormatAbbrev:: unkorrekter Formatstring");
+ }
+ return nKey;
+}
+
+
+
+
+