xref: /aoo4110/main/sc/source/filter/excel/xetable.cxx (revision b1cdbd2c)
1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_sc.hxx"
26*b1cdbd2cSJim Jagielski #include "xetable.hxx"
27*b1cdbd2cSJim Jagielski 
28*b1cdbd2cSJim Jagielski #include <map>
29*b1cdbd2cSJim Jagielski #include <com/sun/star/i18n/ScriptType.hpp>
30*b1cdbd2cSJim Jagielski #include "scitems.hxx"
31*b1cdbd2cSJim Jagielski #include <svl/intitem.hxx>
32*b1cdbd2cSJim Jagielski #include "document.hxx"
33*b1cdbd2cSJim Jagielski #include "dociter.hxx"
34*b1cdbd2cSJim Jagielski #include "olinetab.hxx"
35*b1cdbd2cSJim Jagielski #include "cell.hxx"
36*b1cdbd2cSJim Jagielski #include "patattr.hxx"
37*b1cdbd2cSJim Jagielski #include "attrib.hxx"
38*b1cdbd2cSJim Jagielski #include "xehelper.hxx"
39*b1cdbd2cSJim Jagielski #include "xecontent.hxx"
40*b1cdbd2cSJim Jagielski #include "xeescher.hxx"
41*b1cdbd2cSJim Jagielski 
42*b1cdbd2cSJim Jagielski using namespace ::oox;
43*b1cdbd2cSJim Jagielski 
44*b1cdbd2cSJim Jagielski using ::rtl::OString;
45*b1cdbd2cSJim Jagielski using ::rtl::OUString;
46*b1cdbd2cSJim Jagielski using ::rtl::OUStringBuffer;
47*b1cdbd2cSJim Jagielski 
48*b1cdbd2cSJim Jagielski namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
49*b1cdbd2cSJim Jagielski 
50*b1cdbd2cSJim Jagielski // ============================================================================
51*b1cdbd2cSJim Jagielski // Helper records for cell records
52*b1cdbd2cSJim Jagielski // ============================================================================
53*b1cdbd2cSJim Jagielski 
XclExpStringRec(const XclExpRoot & rRoot,const String & rResult)54*b1cdbd2cSJim Jagielski XclExpStringRec::XclExpStringRec( const XclExpRoot& rRoot, const String& rResult ) :
55*b1cdbd2cSJim Jagielski     XclExpRecord( EXC_ID3_STRING ),
56*b1cdbd2cSJim Jagielski     mxResult( XclExpStringHelper::CreateString( rRoot, rResult ) )
57*b1cdbd2cSJim Jagielski {
58*b1cdbd2cSJim Jagielski     DBG_ASSERT( (rRoot.GetBiff() <= EXC_BIFF5) || (mxResult->Len() > 0),
59*b1cdbd2cSJim Jagielski         "XclExpStringRec::XclExpStringRec - empty result not allowed in BIFF8+" );
60*b1cdbd2cSJim Jagielski     SetRecSize( mxResult->GetSize() );
61*b1cdbd2cSJim Jagielski }
62*b1cdbd2cSJim Jagielski 
WriteBody(XclExpStream & rStrm)63*b1cdbd2cSJim Jagielski void XclExpStringRec::WriteBody( XclExpStream& rStrm )
64*b1cdbd2cSJim Jagielski {
65*b1cdbd2cSJim Jagielski     rStrm << *mxResult;
66*b1cdbd2cSJim Jagielski }
67*b1cdbd2cSJim Jagielski 
68*b1cdbd2cSJim Jagielski // Additional records for special formula ranges ==============================
69*b1cdbd2cSJim Jagielski 
XclExpRangeFmlaBase(sal_uInt16 nRecId,sal_uInt32 nRecSize,const ScAddress & rScPos)70*b1cdbd2cSJim Jagielski XclExpRangeFmlaBase::XclExpRangeFmlaBase(
71*b1cdbd2cSJim Jagielski         sal_uInt16 nRecId, sal_uInt32 nRecSize, const ScAddress& rScPos ) :
72*b1cdbd2cSJim Jagielski     XclExpRecord( nRecId, nRecSize ),
73*b1cdbd2cSJim Jagielski     maXclRange( ScAddress::UNINITIALIZED ),
74*b1cdbd2cSJim Jagielski     maBaseXclPos( ScAddress::UNINITIALIZED )
75*b1cdbd2cSJim Jagielski {
76*b1cdbd2cSJim Jagielski     maBaseXclPos.Set( static_cast< sal_uInt16 >( rScPos.Col() ), static_cast< sal_uInt16 >( rScPos.Row() ) );
77*b1cdbd2cSJim Jagielski     maXclRange.maFirst = maXclRange.maLast = maBaseXclPos;
78*b1cdbd2cSJim Jagielski }
79*b1cdbd2cSJim Jagielski 
XclExpRangeFmlaBase(sal_uInt16 nRecId,sal_uInt32 nRecSize,const ScRange & rScRange)80*b1cdbd2cSJim Jagielski XclExpRangeFmlaBase::XclExpRangeFmlaBase(
81*b1cdbd2cSJim Jagielski         sal_uInt16 nRecId, sal_uInt32 nRecSize, const ScRange& rScRange ) :
82*b1cdbd2cSJim Jagielski     XclExpRecord( nRecId, nRecSize ),
83*b1cdbd2cSJim Jagielski     maXclRange( ScAddress::UNINITIALIZED ),
84*b1cdbd2cSJim Jagielski     maBaseXclPos( ScAddress::UNINITIALIZED )
85*b1cdbd2cSJim Jagielski {
86*b1cdbd2cSJim Jagielski     maXclRange.Set(
87*b1cdbd2cSJim Jagielski         static_cast< sal_uInt16 >( rScRange.aStart.Col() ),
88*b1cdbd2cSJim Jagielski         static_cast< sal_uInt16 >( rScRange.aStart.Row() ),
89*b1cdbd2cSJim Jagielski         static_cast< sal_uInt16 >( rScRange.aEnd.Col() ),
90*b1cdbd2cSJim Jagielski         static_cast< sal_uInt16 >( rScRange.aEnd.Row() ) );
91*b1cdbd2cSJim Jagielski     maBaseXclPos = maXclRange.maFirst;
92*b1cdbd2cSJim Jagielski }
93*b1cdbd2cSJim Jagielski 
IsBasePos(sal_uInt16 nXclCol,sal_uInt16 nXclRow) const94*b1cdbd2cSJim Jagielski bool XclExpRangeFmlaBase::IsBasePos( sal_uInt16 nXclCol, sal_uInt16 nXclRow ) const
95*b1cdbd2cSJim Jagielski {
96*b1cdbd2cSJim Jagielski     return (maBaseXclPos.mnCol == nXclCol) && (maBaseXclPos.mnRow == nXclRow);
97*b1cdbd2cSJim Jagielski }
98*b1cdbd2cSJim Jagielski 
Extend(const ScAddress & rScPos)99*b1cdbd2cSJim Jagielski void XclExpRangeFmlaBase::Extend( const ScAddress& rScPos )
100*b1cdbd2cSJim Jagielski {
101*b1cdbd2cSJim Jagielski     sal_uInt16 nXclCol = static_cast< sal_uInt16 >( rScPos.Col() );
102*b1cdbd2cSJim Jagielski     sal_uInt16 nXclRow = static_cast< sal_uInt16 >( rScPos.Row() );
103*b1cdbd2cSJim Jagielski     maXclRange.maFirst.mnCol = ::std::min( maXclRange.maFirst.mnCol, nXclCol );
104*b1cdbd2cSJim Jagielski     maXclRange.maFirst.mnRow = ::std::min( maXclRange.maFirst.mnRow, nXclRow );
105*b1cdbd2cSJim Jagielski     maXclRange.maLast.mnCol  = ::std::max( maXclRange.maLast.mnCol,  nXclCol );
106*b1cdbd2cSJim Jagielski     maXclRange.maLast.mnRow  = ::std::max( maXclRange.maLast.mnRow,  nXclRow );
107*b1cdbd2cSJim Jagielski }
108*b1cdbd2cSJim Jagielski 
WriteRangeAddress(XclExpStream & rStrm) const109*b1cdbd2cSJim Jagielski void XclExpRangeFmlaBase::WriteRangeAddress( XclExpStream& rStrm ) const
110*b1cdbd2cSJim Jagielski {
111*b1cdbd2cSJim Jagielski     maXclRange.Write( rStrm, false );
112*b1cdbd2cSJim Jagielski }
113*b1cdbd2cSJim Jagielski 
114*b1cdbd2cSJim Jagielski // Array formulas =============================================================
115*b1cdbd2cSJim Jagielski 
XclExpArray(XclTokenArrayRef xTokArr,const ScRange & rScRange)116*b1cdbd2cSJim Jagielski XclExpArray::XclExpArray( XclTokenArrayRef xTokArr, const ScRange& rScRange ) :
117*b1cdbd2cSJim Jagielski     XclExpRangeFmlaBase( EXC_ID3_ARRAY, 14 + xTokArr->GetSize(), rScRange ),
118*b1cdbd2cSJim Jagielski     mxTokArr( xTokArr )
119*b1cdbd2cSJim Jagielski {
120*b1cdbd2cSJim Jagielski }
121*b1cdbd2cSJim Jagielski 
CreateCellTokenArray(const XclExpRoot & rRoot) const122*b1cdbd2cSJim Jagielski XclTokenArrayRef XclExpArray::CreateCellTokenArray( const XclExpRoot& rRoot ) const
123*b1cdbd2cSJim Jagielski {
124*b1cdbd2cSJim Jagielski     return rRoot.GetFormulaCompiler().CreateSpecialRefFormula( EXC_TOKID_EXP, maBaseXclPos );
125*b1cdbd2cSJim Jagielski }
126*b1cdbd2cSJim Jagielski 
IsVolatile() const127*b1cdbd2cSJim Jagielski bool XclExpArray::IsVolatile() const
128*b1cdbd2cSJim Jagielski {
129*b1cdbd2cSJim Jagielski     return mxTokArr->IsVolatile();
130*b1cdbd2cSJim Jagielski }
131*b1cdbd2cSJim Jagielski 
WriteBody(XclExpStream & rStrm)132*b1cdbd2cSJim Jagielski void XclExpArray::WriteBody( XclExpStream& rStrm )
133*b1cdbd2cSJim Jagielski {
134*b1cdbd2cSJim Jagielski     WriteRangeAddress( rStrm );
135*b1cdbd2cSJim Jagielski     sal_uInt16 nFlags = EXC_ARRAY_DEFAULTFLAGS;
136*b1cdbd2cSJim Jagielski     ::set_flag( nFlags, EXC_ARRAY_RECALC_ALWAYS, IsVolatile() );
137*b1cdbd2cSJim Jagielski     rStrm << nFlags << sal_uInt32( 0 ) << *mxTokArr;
138*b1cdbd2cSJim Jagielski }
139*b1cdbd2cSJim Jagielski 
140*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
141*b1cdbd2cSJim Jagielski 
XclExpArrayBuffer(const XclExpRoot & rRoot)142*b1cdbd2cSJim Jagielski XclExpArrayBuffer::XclExpArrayBuffer( const XclExpRoot& rRoot ) :
143*b1cdbd2cSJim Jagielski     XclExpRoot( rRoot )
144*b1cdbd2cSJim Jagielski {
145*b1cdbd2cSJim Jagielski }
146*b1cdbd2cSJim Jagielski 
CreateArray(const ScTokenArray & rScTokArr,const ScRange & rScRange)147*b1cdbd2cSJim Jagielski XclExpArrayRef XclExpArrayBuffer::CreateArray( const ScTokenArray& rScTokArr, const ScRange& rScRange )
148*b1cdbd2cSJim Jagielski {
149*b1cdbd2cSJim Jagielski     const ScAddress& rScPos = rScRange.aStart;
150*b1cdbd2cSJim Jagielski     XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_MATRIX, rScTokArr, &rScPos );
151*b1cdbd2cSJim Jagielski 
152*b1cdbd2cSJim Jagielski     DBG_ASSERT( maRecMap.find( rScPos ) == maRecMap.end(), "XclExpArrayBuffer::CreateArray - array exists already" );
153*b1cdbd2cSJim Jagielski     XclExpArrayRef& rxRec = maRecMap[ rScPos ];
154*b1cdbd2cSJim Jagielski     rxRec.reset( new XclExpArray( xTokArr, rScRange ) );
155*b1cdbd2cSJim Jagielski     return rxRec;
156*b1cdbd2cSJim Jagielski }
157*b1cdbd2cSJim Jagielski 
FindArray(const ScTokenArray & rScTokArr) const158*b1cdbd2cSJim Jagielski XclExpArrayRef XclExpArrayBuffer::FindArray( const ScTokenArray& rScTokArr ) const
159*b1cdbd2cSJim Jagielski {
160*b1cdbd2cSJim Jagielski     XclExpArrayRef xRec;
161*b1cdbd2cSJim Jagielski     // try to extract a matrix reference token
162*b1cdbd2cSJim Jagielski     if( rScTokArr.GetLen() == 1 )
163*b1cdbd2cSJim Jagielski     {
164*b1cdbd2cSJim Jagielski         const formula::FormulaToken* pToken = rScTokArr.GetArray()[ 0 ];
165*b1cdbd2cSJim Jagielski         if( pToken && (pToken->GetOpCode() == ocMatRef) )
166*b1cdbd2cSJim Jagielski         {
167*b1cdbd2cSJim Jagielski             const ScSingleRefData& rRef = static_cast<const ScToken*>(pToken)->GetSingleRef();
168*b1cdbd2cSJim Jagielski             ScAddress aBasePos( rRef.nCol, rRef.nRow, GetCurrScTab() );
169*b1cdbd2cSJim Jagielski             XclExpArrayMap::const_iterator aIt = maRecMap.find( aBasePos );
170*b1cdbd2cSJim Jagielski             if( aIt != maRecMap.end() )
171*b1cdbd2cSJim Jagielski                 xRec = aIt->second;
172*b1cdbd2cSJim Jagielski         }
173*b1cdbd2cSJim Jagielski     }
174*b1cdbd2cSJim Jagielski     return xRec;
175*b1cdbd2cSJim Jagielski }
176*b1cdbd2cSJim Jagielski 
177*b1cdbd2cSJim Jagielski // Shared formulas ============================================================
178*b1cdbd2cSJim Jagielski 
XclExpShrfmla(XclTokenArrayRef xTokArr,const ScAddress & rScPos)179*b1cdbd2cSJim Jagielski XclExpShrfmla::XclExpShrfmla( XclTokenArrayRef xTokArr, const ScAddress& rScPos ) :
180*b1cdbd2cSJim Jagielski     XclExpRangeFmlaBase( EXC_ID_SHRFMLA, 10 + xTokArr->GetSize(), rScPos ),
181*b1cdbd2cSJim Jagielski     mxTokArr( xTokArr ),
182*b1cdbd2cSJim Jagielski     mnUsedCount( 1 )
183*b1cdbd2cSJim Jagielski {
184*b1cdbd2cSJim Jagielski }
185*b1cdbd2cSJim Jagielski 
ExtendRange(const ScAddress & rScPos)186*b1cdbd2cSJim Jagielski void XclExpShrfmla::ExtendRange( const ScAddress& rScPos )
187*b1cdbd2cSJim Jagielski {
188*b1cdbd2cSJim Jagielski     Extend( rScPos );
189*b1cdbd2cSJim Jagielski     ++mnUsedCount;
190*b1cdbd2cSJim Jagielski }
191*b1cdbd2cSJim Jagielski 
CreateCellTokenArray(const XclExpRoot & rRoot) const192*b1cdbd2cSJim Jagielski XclTokenArrayRef XclExpShrfmla::CreateCellTokenArray( const XclExpRoot& rRoot ) const
193*b1cdbd2cSJim Jagielski {
194*b1cdbd2cSJim Jagielski     return rRoot.GetFormulaCompiler().CreateSpecialRefFormula( EXC_TOKID_EXP, maBaseXclPos );
195*b1cdbd2cSJim Jagielski }
196*b1cdbd2cSJim Jagielski 
IsVolatile() const197*b1cdbd2cSJim Jagielski bool XclExpShrfmla::IsVolatile() const
198*b1cdbd2cSJim Jagielski {
199*b1cdbd2cSJim Jagielski     return mxTokArr->IsVolatile();
200*b1cdbd2cSJim Jagielski }
201*b1cdbd2cSJim Jagielski 
WriteBody(XclExpStream & rStrm)202*b1cdbd2cSJim Jagielski void XclExpShrfmla::WriteBody( XclExpStream& rStrm )
203*b1cdbd2cSJim Jagielski {
204*b1cdbd2cSJim Jagielski     WriteRangeAddress( rStrm );
205*b1cdbd2cSJim Jagielski     rStrm << sal_uInt8( 0 ) << mnUsedCount << *mxTokArr;
206*b1cdbd2cSJim Jagielski }
207*b1cdbd2cSJim Jagielski 
208*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
209*b1cdbd2cSJim Jagielski 
XclExpShrfmlaBuffer(const XclExpRoot & rRoot)210*b1cdbd2cSJim Jagielski XclExpShrfmlaBuffer::XclExpShrfmlaBuffer( const XclExpRoot& rRoot ) :
211*b1cdbd2cSJim Jagielski     XclExpRoot( rRoot )
212*b1cdbd2cSJim Jagielski {
213*b1cdbd2cSJim Jagielski }
214*b1cdbd2cSJim Jagielski 
CreateOrExtendShrfmla(const ScTokenArray & rScTokArr,const ScAddress & rScPos)215*b1cdbd2cSJim Jagielski XclExpShrfmlaRef XclExpShrfmlaBuffer::CreateOrExtendShrfmla(
216*b1cdbd2cSJim Jagielski         const ScTokenArray& rScTokArr, const ScAddress& rScPos )
217*b1cdbd2cSJim Jagielski {
218*b1cdbd2cSJim Jagielski     XclExpShrfmlaRef xRec;
219*b1cdbd2cSJim Jagielski     if( const ScTokenArray* pShrdScTokArr = XclTokenArrayHelper::GetSharedFormula( GetRoot(), rScTokArr ) )
220*b1cdbd2cSJim Jagielski     {
221*b1cdbd2cSJim Jagielski         XclExpShrfmlaMap::iterator aIt = maRecMap.find( pShrdScTokArr );
222*b1cdbd2cSJim Jagielski         if( aIt == maRecMap.end() )
223*b1cdbd2cSJim Jagielski         {
224*b1cdbd2cSJim Jagielski             // create a new record
225*b1cdbd2cSJim Jagielski             XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_SHARED, *pShrdScTokArr, &rScPos );
226*b1cdbd2cSJim Jagielski             xRec.reset( new XclExpShrfmla( xTokArr, rScPos ) );
227*b1cdbd2cSJim Jagielski             maRecMap[ pShrdScTokArr ] = xRec;
228*b1cdbd2cSJim Jagielski         }
229*b1cdbd2cSJim Jagielski         else
230*b1cdbd2cSJim Jagielski         {
231*b1cdbd2cSJim Jagielski             // extend existing record
232*b1cdbd2cSJim Jagielski             DBG_ASSERT( aIt->second, "XclExpShrfmlaBuffer::CreateOrExtendShrfmla - missing record" );
233*b1cdbd2cSJim Jagielski             xRec = aIt->second;
234*b1cdbd2cSJim Jagielski             xRec->ExtendRange( rScPos );
235*b1cdbd2cSJim Jagielski         }
236*b1cdbd2cSJim Jagielski     }
237*b1cdbd2cSJim Jagielski     return xRec;
238*b1cdbd2cSJim Jagielski }
239*b1cdbd2cSJim Jagielski 
240*b1cdbd2cSJim Jagielski // Multiple operations ========================================================
241*b1cdbd2cSJim Jagielski 
XclExpTableop(const ScAddress & rScPos,const XclMultipleOpRefs & rRefs,sal_uInt8 nScMode)242*b1cdbd2cSJim Jagielski XclExpTableop::XclExpTableop( const ScAddress& rScPos,
243*b1cdbd2cSJim Jagielski         const XclMultipleOpRefs& rRefs, sal_uInt8 nScMode ) :
244*b1cdbd2cSJim Jagielski     XclExpRangeFmlaBase( EXC_ID3_TABLEOP, 16, rScPos ),
245*b1cdbd2cSJim Jagielski     mnLastAppXclCol( static_cast< sal_uInt16 >( rScPos.Col() ) ),
246*b1cdbd2cSJim Jagielski     mnColInpXclCol( static_cast< sal_uInt16 >( rRefs.maColFirstScPos.Col() ) ),
247*b1cdbd2cSJim Jagielski     mnColInpXclRow( static_cast< sal_uInt16 >( rRefs.maColFirstScPos.Row() ) ),
248*b1cdbd2cSJim Jagielski     mnRowInpXclCol( static_cast< sal_uInt16 >( rRefs.maRowFirstScPos.Col() ) ),
249*b1cdbd2cSJim Jagielski     mnRowInpXclRow( static_cast< sal_uInt16 >( rRefs.maRowFirstScPos.Row() ) ),
250*b1cdbd2cSJim Jagielski     mnScMode( nScMode ),
251*b1cdbd2cSJim Jagielski     mbValid( false )
252*b1cdbd2cSJim Jagielski {
253*b1cdbd2cSJim Jagielski }
254*b1cdbd2cSJim Jagielski 
TryExtend(const ScAddress & rScPos,const XclMultipleOpRefs & rRefs)255*b1cdbd2cSJim Jagielski bool XclExpTableop::TryExtend( const ScAddress& rScPos, const XclMultipleOpRefs& rRefs )
256*b1cdbd2cSJim Jagielski {
257*b1cdbd2cSJim Jagielski     sal_uInt16 nXclCol = static_cast< sal_uInt16 >( rScPos.Col() );
258*b1cdbd2cSJim Jagielski     sal_uInt16 nXclRow = static_cast< sal_uInt16 >( rScPos.Row() );
259*b1cdbd2cSJim Jagielski 
260*b1cdbd2cSJim Jagielski     bool bOk = IsAppendable( nXclCol, nXclRow );
261*b1cdbd2cSJim Jagielski     if( bOk )
262*b1cdbd2cSJim Jagielski     {
263*b1cdbd2cSJim Jagielski         SCCOL nFirstScCol  = static_cast< SCCOL >( maXclRange.maFirst.mnCol );
264*b1cdbd2cSJim Jagielski         SCROW nFirstScRow  = static_cast< SCROW >( maXclRange.maFirst.mnRow );
265*b1cdbd2cSJim Jagielski         SCCOL nColInpScCol = static_cast< SCCOL >( mnColInpXclCol );
266*b1cdbd2cSJim Jagielski         SCROW nColInpScRow = static_cast< SCROW >( mnColInpXclRow );
267*b1cdbd2cSJim Jagielski         SCCOL nRowInpScCol = static_cast< SCCOL >( mnRowInpXclCol );
268*b1cdbd2cSJim Jagielski         SCROW nRowInpScRow = static_cast< SCROW >( mnRowInpXclRow );
269*b1cdbd2cSJim Jagielski 
270*b1cdbd2cSJim Jagielski         bOk =   ((mnScMode == 2) == rRefs.mbDblRefMode) &&
271*b1cdbd2cSJim Jagielski                 (rScPos.Tab() == rRefs.maFmlaScPos.Tab()) &&
272*b1cdbd2cSJim Jagielski                 (nColInpScCol == rRefs.maColFirstScPos.Col()) &&
273*b1cdbd2cSJim Jagielski                 (nColInpScRow == rRefs.maColFirstScPos.Row()) &&
274*b1cdbd2cSJim Jagielski                 (rScPos.Tab() == rRefs.maColFirstScPos.Tab()) &&
275*b1cdbd2cSJim Jagielski                 (rScPos.Tab() == rRefs.maColRelScPos.Tab());
276*b1cdbd2cSJim Jagielski 
277*b1cdbd2cSJim Jagielski         if( bOk ) switch( mnScMode )
278*b1cdbd2cSJim Jagielski         {
279*b1cdbd2cSJim Jagielski             case 0:
280*b1cdbd2cSJim Jagielski                 bOk =   (rScPos.Col() == rRefs.maFmlaScPos.Col()) &&
281*b1cdbd2cSJim Jagielski                         (nFirstScRow  == rRefs.maFmlaScPos.Row() + 1) &&
282*b1cdbd2cSJim Jagielski                         (nFirstScCol  == rRefs.maColRelScPos.Col() + 1) &&
283*b1cdbd2cSJim Jagielski                         (rScPos.Row() == rRefs.maColRelScPos.Row());
284*b1cdbd2cSJim Jagielski             break;
285*b1cdbd2cSJim Jagielski             case 1:
286*b1cdbd2cSJim Jagielski                 bOk =   (nFirstScCol  == rRefs.maFmlaScPos.Col() + 1) &&
287*b1cdbd2cSJim Jagielski                         (rScPos.Row() == rRefs.maFmlaScPos.Row()) &&
288*b1cdbd2cSJim Jagielski                         (rScPos.Col() == rRefs.maColRelScPos.Col()) &&
289*b1cdbd2cSJim Jagielski                         (nFirstScRow  == rRefs.maColRelScPos.Row() + 1);
290*b1cdbd2cSJim Jagielski             break;
291*b1cdbd2cSJim Jagielski             case 2:
292*b1cdbd2cSJim Jagielski                 bOk =   (nFirstScCol  == rRefs.maFmlaScPos.Col() + 1) &&
293*b1cdbd2cSJim Jagielski                         (nFirstScRow  == rRefs.maFmlaScPos.Row() + 1) &&
294*b1cdbd2cSJim Jagielski                         (nFirstScCol  == rRefs.maColRelScPos.Col() + 1) &&
295*b1cdbd2cSJim Jagielski                         (rScPos.Row() == rRefs.maColRelScPos.Row()) &&
296*b1cdbd2cSJim Jagielski                         (nRowInpScCol == rRefs.maRowFirstScPos.Col()) &&
297*b1cdbd2cSJim Jagielski                         (nRowInpScRow == rRefs.maRowFirstScPos.Row()) &&
298*b1cdbd2cSJim Jagielski                         (rScPos.Tab() == rRefs.maRowFirstScPos.Tab()) &&
299*b1cdbd2cSJim Jagielski                         (rScPos.Col() == rRefs.maRowRelScPos.Col()) &&
300*b1cdbd2cSJim Jagielski                         (nFirstScRow  == rRefs.maRowRelScPos.Row() + 1) &&
301*b1cdbd2cSJim Jagielski                         (rScPos.Tab() == rRefs.maRowRelScPos.Tab());
302*b1cdbd2cSJim Jagielski             break;
303*b1cdbd2cSJim Jagielski             default:
304*b1cdbd2cSJim Jagielski                 bOk = false;
305*b1cdbd2cSJim Jagielski         }
306*b1cdbd2cSJim Jagielski 
307*b1cdbd2cSJim Jagielski         if( bOk )
308*b1cdbd2cSJim Jagielski         {
309*b1cdbd2cSJim Jagielski             // extend the cell range
310*b1cdbd2cSJim Jagielski             DBG_ASSERT( IsAppendable( nXclCol, nXclRow ), "XclExpTableop::TryExtend - wrong cell address" );
311*b1cdbd2cSJim Jagielski             Extend( rScPos );
312*b1cdbd2cSJim Jagielski             mnLastAppXclCol = nXclCol;
313*b1cdbd2cSJim Jagielski         }
314*b1cdbd2cSJim Jagielski     }
315*b1cdbd2cSJim Jagielski 
316*b1cdbd2cSJim Jagielski     return bOk;
317*b1cdbd2cSJim Jagielski }
318*b1cdbd2cSJim Jagielski 
Finalize()319*b1cdbd2cSJim Jagielski void XclExpTableop::Finalize()
320*b1cdbd2cSJim Jagielski {
321*b1cdbd2cSJim Jagielski     // is the range complete? (last appended cell is in last column)
322*b1cdbd2cSJim Jagielski     mbValid = maXclRange.maLast.mnCol == mnLastAppXclCol;
323*b1cdbd2cSJim Jagielski     // if last row is incomplete, try to shorten the used range
324*b1cdbd2cSJim Jagielski     if( !mbValid && (maXclRange.maFirst.mnRow < maXclRange.maLast.mnRow) )
325*b1cdbd2cSJim Jagielski     {
326*b1cdbd2cSJim Jagielski         --maXclRange.maLast.mnRow;
327*b1cdbd2cSJim Jagielski         mbValid = true;
328*b1cdbd2cSJim Jagielski     }
329*b1cdbd2cSJim Jagielski 
330*b1cdbd2cSJim Jagielski     // check if referred cells are outside of own range
331*b1cdbd2cSJim Jagielski     if( mbValid ) switch( mnScMode )
332*b1cdbd2cSJim Jagielski     {
333*b1cdbd2cSJim Jagielski         case 0:
334*b1cdbd2cSJim Jagielski             mbValid =   (mnColInpXclCol + 1 < maXclRange.maFirst.mnCol) || (mnColInpXclCol > maXclRange.maLast.mnCol) ||
335*b1cdbd2cSJim Jagielski                         (mnColInpXclRow     < maXclRange.maFirst.mnRow) || (mnColInpXclRow > maXclRange.maLast.mnRow);
336*b1cdbd2cSJim Jagielski         break;
337*b1cdbd2cSJim Jagielski         case 1:
338*b1cdbd2cSJim Jagielski             mbValid =   (mnColInpXclCol     < maXclRange.maFirst.mnCol) || (mnColInpXclCol > maXclRange.maLast.mnCol) ||
339*b1cdbd2cSJim Jagielski                         (mnColInpXclRow + 1 < maXclRange.maFirst.mnRow) || (mnColInpXclRow > maXclRange.maLast.mnRow);
340*b1cdbd2cSJim Jagielski         break;
341*b1cdbd2cSJim Jagielski         case 2:
342*b1cdbd2cSJim Jagielski             mbValid =   ((mnColInpXclCol + 1 < maXclRange.maFirst.mnCol) || (mnColInpXclCol > maXclRange.maLast.mnCol) ||
343*b1cdbd2cSJim Jagielski                          (mnColInpXclRow + 1 < maXclRange.maFirst.mnRow) || (mnColInpXclRow > maXclRange.maLast.mnRow)) &&
344*b1cdbd2cSJim Jagielski                         ((mnRowInpXclCol + 1 < maXclRange.maFirst.mnCol) || (mnRowInpXclCol > maXclRange.maLast.mnCol) ||
345*b1cdbd2cSJim Jagielski                          (mnRowInpXclRow + 1 < maXclRange.maFirst.mnRow) || (mnRowInpXclRow > maXclRange.maLast.mnRow));
346*b1cdbd2cSJim Jagielski         break;
347*b1cdbd2cSJim Jagielski     }
348*b1cdbd2cSJim Jagielski }
349*b1cdbd2cSJim Jagielski 
CreateCellTokenArray(const XclExpRoot & rRoot) const350*b1cdbd2cSJim Jagielski XclTokenArrayRef XclExpTableop::CreateCellTokenArray( const XclExpRoot& rRoot ) const
351*b1cdbd2cSJim Jagielski {
352*b1cdbd2cSJim Jagielski     XclExpFormulaCompiler& rFmlaComp = rRoot.GetFormulaCompiler();
353*b1cdbd2cSJim Jagielski     return mbValid ?
354*b1cdbd2cSJim Jagielski         rFmlaComp.CreateSpecialRefFormula( EXC_TOKID_TBL, maBaseXclPos ) :
355*b1cdbd2cSJim Jagielski         rFmlaComp.CreateErrorFormula( EXC_ERR_NA );
356*b1cdbd2cSJim Jagielski }
357*b1cdbd2cSJim Jagielski 
IsVolatile() const358*b1cdbd2cSJim Jagielski bool XclExpTableop::IsVolatile() const
359*b1cdbd2cSJim Jagielski {
360*b1cdbd2cSJim Jagielski     return true;
361*b1cdbd2cSJim Jagielski }
362*b1cdbd2cSJim Jagielski 
Save(XclExpStream & rStrm)363*b1cdbd2cSJim Jagielski void XclExpTableop::Save( XclExpStream& rStrm )
364*b1cdbd2cSJim Jagielski {
365*b1cdbd2cSJim Jagielski     if( mbValid )
366*b1cdbd2cSJim Jagielski         XclExpRangeFmlaBase::Save( rStrm );
367*b1cdbd2cSJim Jagielski }
368*b1cdbd2cSJim Jagielski 
IsAppendable(sal_uInt16 nXclCol,sal_uInt16 nXclRow) const369*b1cdbd2cSJim Jagielski bool XclExpTableop::IsAppendable( sal_uInt16 nXclCol, sal_uInt16 nXclRow ) const
370*b1cdbd2cSJim Jagielski {
371*b1cdbd2cSJim Jagielski     return  ((nXclCol == mnLastAppXclCol + 1) && (nXclRow == maXclRange.maFirst.mnRow)) ||
372*b1cdbd2cSJim Jagielski             ((nXclCol == mnLastAppXclCol + 1) && (nXclCol <= maXclRange.maLast.mnCol) && (nXclRow == maXclRange.maLast.mnRow)) ||
373*b1cdbd2cSJim Jagielski             ((mnLastAppXclCol == maXclRange.maLast.mnCol) && (nXclCol == maXclRange.maFirst.mnCol) && (nXclRow == maXclRange.maLast.mnRow + 1));
374*b1cdbd2cSJim Jagielski }
375*b1cdbd2cSJim Jagielski 
WriteBody(XclExpStream & rStrm)376*b1cdbd2cSJim Jagielski void XclExpTableop::WriteBody( XclExpStream& rStrm )
377*b1cdbd2cSJim Jagielski {
378*b1cdbd2cSJim Jagielski     sal_uInt16 nFlags = EXC_TABLEOP_DEFAULTFLAGS;
379*b1cdbd2cSJim Jagielski     ::set_flag( nFlags, EXC_TABLEOP_RECALC_ALWAYS, IsVolatile() );
380*b1cdbd2cSJim Jagielski     switch( mnScMode )
381*b1cdbd2cSJim Jagielski     {
382*b1cdbd2cSJim Jagielski         case 1: ::set_flag( nFlags, EXC_TABLEOP_ROW );  break;
383*b1cdbd2cSJim Jagielski         case 2: ::set_flag( nFlags, EXC_TABLEOP_BOTH ); break;
384*b1cdbd2cSJim Jagielski     }
385*b1cdbd2cSJim Jagielski 
386*b1cdbd2cSJim Jagielski     WriteRangeAddress( rStrm );
387*b1cdbd2cSJim Jagielski     rStrm << nFlags;
388*b1cdbd2cSJim Jagielski     if( mnScMode == 2 )
389*b1cdbd2cSJim Jagielski         rStrm << mnRowInpXclRow << mnRowInpXclCol << mnColInpXclRow << mnColInpXclCol;
390*b1cdbd2cSJim Jagielski     else
391*b1cdbd2cSJim Jagielski         rStrm << mnColInpXclRow << mnColInpXclCol << sal_uInt32( 0 );
392*b1cdbd2cSJim Jagielski }
393*b1cdbd2cSJim Jagielski 
394*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
395*b1cdbd2cSJim Jagielski 
XclExpTableopBuffer(const XclExpRoot & rRoot)396*b1cdbd2cSJim Jagielski XclExpTableopBuffer::XclExpTableopBuffer( const XclExpRoot& rRoot ) :
397*b1cdbd2cSJim Jagielski     XclExpRoot( rRoot )
398*b1cdbd2cSJim Jagielski {
399*b1cdbd2cSJim Jagielski }
400*b1cdbd2cSJim Jagielski 
CreateOrExtendTableop(const ScTokenArray & rScTokArr,const ScAddress & rScPos)401*b1cdbd2cSJim Jagielski XclExpTableopRef XclExpTableopBuffer::CreateOrExtendTableop(
402*b1cdbd2cSJim Jagielski         const ScTokenArray& rScTokArr, const ScAddress& rScPos )
403*b1cdbd2cSJim Jagielski {
404*b1cdbd2cSJim Jagielski     XclExpTableopRef xRec;
405*b1cdbd2cSJim Jagielski 
406*b1cdbd2cSJim Jagielski     // try to extract cell references of a multiple operations formula
407*b1cdbd2cSJim Jagielski     XclMultipleOpRefs aRefs;
408*b1cdbd2cSJim Jagielski     if( XclTokenArrayHelper::GetMultipleOpRefs( aRefs, rScTokArr ) )
409*b1cdbd2cSJim Jagielski     {
410*b1cdbd2cSJim Jagielski         // try to find an existing TABLEOP record for this cell position
411*b1cdbd2cSJim Jagielski         for( size_t nPos = 0, nSize = maTableopList.GetSize(); !xRec && (nPos < nSize); ++nPos )
412*b1cdbd2cSJim Jagielski         {
413*b1cdbd2cSJim Jagielski             XclExpTableopRef xTempRec = maTableopList.GetRecord( nPos );
414*b1cdbd2cSJim Jagielski             if( xTempRec->TryExtend( rScPos, aRefs ) )
415*b1cdbd2cSJim Jagielski                 xRec = xTempRec;
416*b1cdbd2cSJim Jagielski         }
417*b1cdbd2cSJim Jagielski 
418*b1cdbd2cSJim Jagielski         // no record found, or found record not extensible
419*b1cdbd2cSJim Jagielski         if( !xRec )
420*b1cdbd2cSJim Jagielski             xRec = TryCreate( rScPos, aRefs );
421*b1cdbd2cSJim Jagielski     }
422*b1cdbd2cSJim Jagielski 
423*b1cdbd2cSJim Jagielski     return xRec;
424*b1cdbd2cSJim Jagielski }
425*b1cdbd2cSJim Jagielski 
Finalize()426*b1cdbd2cSJim Jagielski void XclExpTableopBuffer::Finalize()
427*b1cdbd2cSJim Jagielski {
428*b1cdbd2cSJim Jagielski     for( size_t nPos = 0, nSize = maTableopList.GetSize(); nPos < nSize; ++nPos )
429*b1cdbd2cSJim Jagielski         maTableopList.GetRecord( nPos )->Finalize();
430*b1cdbd2cSJim Jagielski }
431*b1cdbd2cSJim Jagielski 
TryCreate(const ScAddress & rScPos,const XclMultipleOpRefs & rRefs)432*b1cdbd2cSJim Jagielski XclExpTableopRef XclExpTableopBuffer::TryCreate( const ScAddress& rScPos, const XclMultipleOpRefs& rRefs )
433*b1cdbd2cSJim Jagielski {
434*b1cdbd2cSJim Jagielski     sal_uInt8 nScMode = 0;
435*b1cdbd2cSJim Jagielski     bool bOk =  (rScPos.Tab() == rRefs.maFmlaScPos.Tab()) &&
436*b1cdbd2cSJim Jagielski                 (rScPos.Tab() == rRefs.maColFirstScPos.Tab()) &&
437*b1cdbd2cSJim Jagielski                 (rScPos.Tab() == rRefs.maColRelScPos.Tab());
438*b1cdbd2cSJim Jagielski 
439*b1cdbd2cSJim Jagielski     if( bOk )
440*b1cdbd2cSJim Jagielski     {
441*b1cdbd2cSJim Jagielski         if( rRefs.mbDblRefMode )
442*b1cdbd2cSJim Jagielski         {
443*b1cdbd2cSJim Jagielski             nScMode = 2;
444*b1cdbd2cSJim Jagielski             bOk =   (rScPos.Col() == rRefs.maFmlaScPos.Col() + 1) &&
445*b1cdbd2cSJim Jagielski                     (rScPos.Row() == rRefs.maFmlaScPos.Row() + 1) &&
446*b1cdbd2cSJim Jagielski                     (rScPos.Col() == rRefs.maColRelScPos.Col() + 1) &&
447*b1cdbd2cSJim Jagielski                     (rScPos.Row() == rRefs.maColRelScPos.Row()) &&
448*b1cdbd2cSJim Jagielski                     (rScPos.Tab() == rRefs.maRowFirstScPos.Tab()) &&
449*b1cdbd2cSJim Jagielski                     (rScPos.Col() == rRefs.maRowRelScPos.Col()) &&
450*b1cdbd2cSJim Jagielski                     (rScPos.Row() == rRefs.maRowRelScPos.Row() + 1) &&
451*b1cdbd2cSJim Jagielski                     (rScPos.Tab() == rRefs.maRowRelScPos.Tab());
452*b1cdbd2cSJim Jagielski         }
453*b1cdbd2cSJim Jagielski         else if( (rScPos.Col() == rRefs.maFmlaScPos.Col()) &&
454*b1cdbd2cSJim Jagielski                  (rScPos.Row() == rRefs.maFmlaScPos.Row() + 1) &&
455*b1cdbd2cSJim Jagielski                  (rScPos.Col() == rRefs.maColRelScPos.Col() + 1) &&
456*b1cdbd2cSJim Jagielski                  (rScPos.Row() == rRefs.maColRelScPos.Row()) )
457*b1cdbd2cSJim Jagielski         {
458*b1cdbd2cSJim Jagielski             nScMode = 0;
459*b1cdbd2cSJim Jagielski         }
460*b1cdbd2cSJim Jagielski         else if( (rScPos.Col() == rRefs.maFmlaScPos.Col() + 1) &&
461*b1cdbd2cSJim Jagielski                  (rScPos.Row() == rRefs.maFmlaScPos.Row()) &&
462*b1cdbd2cSJim Jagielski                  (rScPos.Col() == rRefs.maColRelScPos.Col()) &&
463*b1cdbd2cSJim Jagielski                  (rScPos.Row() == rRefs.maColRelScPos.Row() + 1) )
464*b1cdbd2cSJim Jagielski         {
465*b1cdbd2cSJim Jagielski             nScMode = 1;
466*b1cdbd2cSJim Jagielski         }
467*b1cdbd2cSJim Jagielski         else
468*b1cdbd2cSJim Jagielski         {
469*b1cdbd2cSJim Jagielski             bOk = false;
470*b1cdbd2cSJim Jagielski         }
471*b1cdbd2cSJim Jagielski     }
472*b1cdbd2cSJim Jagielski 
473*b1cdbd2cSJim Jagielski     XclExpTableopRef xRec;
474*b1cdbd2cSJim Jagielski     if( bOk )
475*b1cdbd2cSJim Jagielski     {
476*b1cdbd2cSJim Jagielski         xRec.reset( new XclExpTableop( rScPos, rRefs, nScMode ) );
477*b1cdbd2cSJim Jagielski         maTableopList.AppendRecord( xRec );
478*b1cdbd2cSJim Jagielski     }
479*b1cdbd2cSJim Jagielski 
480*b1cdbd2cSJim Jagielski     return xRec;
481*b1cdbd2cSJim Jagielski }
482*b1cdbd2cSJim Jagielski 
483*b1cdbd2cSJim Jagielski // ============================================================================
484*b1cdbd2cSJim Jagielski // Cell records
485*b1cdbd2cSJim Jagielski // ============================================================================
486*b1cdbd2cSJim Jagielski 
XclExpCellBase(sal_uInt16 nRecId,sal_Size nContSize,const XclAddress & rXclPos)487*b1cdbd2cSJim Jagielski XclExpCellBase::XclExpCellBase(
488*b1cdbd2cSJim Jagielski         sal_uInt16 nRecId, sal_Size nContSize, const XclAddress& rXclPos ) :
489*b1cdbd2cSJim Jagielski     XclExpRecord( nRecId, nContSize + 4 ),
490*b1cdbd2cSJim Jagielski     maXclPos( rXclPos )
491*b1cdbd2cSJim Jagielski {
492*b1cdbd2cSJim Jagielski }
493*b1cdbd2cSJim Jagielski 
IsMultiLineText() const494*b1cdbd2cSJim Jagielski bool XclExpCellBase::IsMultiLineText() const
495*b1cdbd2cSJim Jagielski {
496*b1cdbd2cSJim Jagielski     return false;
497*b1cdbd2cSJim Jagielski }
498*b1cdbd2cSJim Jagielski 
TryMerge(const XclExpCellBase &)499*b1cdbd2cSJim Jagielski bool XclExpCellBase::TryMerge( const XclExpCellBase& /*rCell*/ )
500*b1cdbd2cSJim Jagielski {
501*b1cdbd2cSJim Jagielski     return false;
502*b1cdbd2cSJim Jagielski }
503*b1cdbd2cSJim Jagielski 
GetBlankXFIndexes(ScfUInt16Vec &) const504*b1cdbd2cSJim Jagielski void XclExpCellBase::GetBlankXFIndexes( ScfUInt16Vec& /*rXFIndexes*/ ) const
505*b1cdbd2cSJim Jagielski {
506*b1cdbd2cSJim Jagielski     // default: do nothing
507*b1cdbd2cSJim Jagielski }
508*b1cdbd2cSJim Jagielski 
RemoveUnusedBlankCells(const ScfUInt16Vec &)509*b1cdbd2cSJim Jagielski void XclExpCellBase::RemoveUnusedBlankCells( const ScfUInt16Vec& /*rXFIndexes*/ )
510*b1cdbd2cSJim Jagielski {
511*b1cdbd2cSJim Jagielski     // default: do nothing
512*b1cdbd2cSJim Jagielski }
513*b1cdbd2cSJim Jagielski 
514*b1cdbd2cSJim Jagielski // Single cell records ========================================================
515*b1cdbd2cSJim Jagielski 
XclExpSingleCellBase(sal_uInt16 nRecId,sal_Size nContSize,const XclAddress & rXclPos,sal_uInt32 nXFId)516*b1cdbd2cSJim Jagielski XclExpSingleCellBase::XclExpSingleCellBase(
517*b1cdbd2cSJim Jagielski         sal_uInt16 nRecId, sal_Size nContSize, const XclAddress& rXclPos, sal_uInt32 nXFId ) :
518*b1cdbd2cSJim Jagielski     XclExpCellBase( nRecId, 2, rXclPos ),
519*b1cdbd2cSJim Jagielski     maXFId( nXFId ),
520*b1cdbd2cSJim Jagielski     mnContSize( nContSize )
521*b1cdbd2cSJim Jagielski {
522*b1cdbd2cSJim Jagielski }
523*b1cdbd2cSJim Jagielski 
XclExpSingleCellBase(const XclExpRoot & rRoot,sal_uInt16 nRecId,sal_Size nContSize,const XclAddress & rXclPos,const ScPatternAttr * pPattern,sal_Int16 nScript,sal_uInt32 nForcedXFId)524*b1cdbd2cSJim Jagielski XclExpSingleCellBase::XclExpSingleCellBase( const XclExpRoot& rRoot,
525*b1cdbd2cSJim Jagielski         sal_uInt16 nRecId, sal_Size nContSize, const XclAddress& rXclPos,
526*b1cdbd2cSJim Jagielski         const ScPatternAttr* pPattern, sal_Int16 nScript, sal_uInt32 nForcedXFId ) :
527*b1cdbd2cSJim Jagielski     XclExpCellBase( nRecId, 2, rXclPos ),
528*b1cdbd2cSJim Jagielski     maXFId( nForcedXFId ),
529*b1cdbd2cSJim Jagielski     mnContSize( nContSize )
530*b1cdbd2cSJim Jagielski {
531*b1cdbd2cSJim Jagielski     if( GetXFId() == EXC_XFID_NOTFOUND )
532*b1cdbd2cSJim Jagielski         SetXFId( rRoot.GetXFBuffer().Insert( pPattern, nScript ) );
533*b1cdbd2cSJim Jagielski }
534*b1cdbd2cSJim Jagielski 
GetLastXclCol() const535*b1cdbd2cSJim Jagielski sal_uInt16 XclExpSingleCellBase::GetLastXclCol() const
536*b1cdbd2cSJim Jagielski {
537*b1cdbd2cSJim Jagielski     return GetXclCol();
538*b1cdbd2cSJim Jagielski }
539*b1cdbd2cSJim Jagielski 
GetFirstXFId() const540*b1cdbd2cSJim Jagielski sal_uInt32 XclExpSingleCellBase::GetFirstXFId() const
541*b1cdbd2cSJim Jagielski {
542*b1cdbd2cSJim Jagielski     return GetXFId();
543*b1cdbd2cSJim Jagielski }
544*b1cdbd2cSJim Jagielski 
IsEmpty() const545*b1cdbd2cSJim Jagielski bool XclExpSingleCellBase::IsEmpty() const
546*b1cdbd2cSJim Jagielski {
547*b1cdbd2cSJim Jagielski     return false;
548*b1cdbd2cSJim Jagielski }
549*b1cdbd2cSJim Jagielski 
ConvertXFIndexes(const XclExpRoot & rRoot)550*b1cdbd2cSJim Jagielski void XclExpSingleCellBase::ConvertXFIndexes( const XclExpRoot& rRoot )
551*b1cdbd2cSJim Jagielski {
552*b1cdbd2cSJim Jagielski     maXFId.ConvertXFIndex( rRoot );
553*b1cdbd2cSJim Jagielski }
554*b1cdbd2cSJim Jagielski 
Save(XclExpStream & rStrm)555*b1cdbd2cSJim Jagielski void XclExpSingleCellBase::Save( XclExpStream& rStrm )
556*b1cdbd2cSJim Jagielski {
557*b1cdbd2cSJim Jagielski     DBG_ASSERT_BIFF( rStrm.GetRoot().GetBiff() >= EXC_BIFF3 );
558*b1cdbd2cSJim Jagielski     AddRecSize( mnContSize );
559*b1cdbd2cSJim Jagielski     XclExpCellBase::Save( rStrm );
560*b1cdbd2cSJim Jagielski }
561*b1cdbd2cSJim Jagielski 
WriteBody(XclExpStream & rStrm)562*b1cdbd2cSJim Jagielski void XclExpSingleCellBase::WriteBody( XclExpStream& rStrm )
563*b1cdbd2cSJim Jagielski {
564*b1cdbd2cSJim Jagielski     rStrm << GetXclRow() << GetXclCol() << maXFId.mnXFIndex;
565*b1cdbd2cSJim Jagielski     WriteContents( rStrm );
566*b1cdbd2cSJim Jagielski }
567*b1cdbd2cSJim Jagielski 
568*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
569*b1cdbd2cSJim Jagielski 
570*b1cdbd2cSJim Jagielski IMPL_FIXEDMEMPOOL_NEWDEL( XclExpNumberCell, 256, 256 )
571*b1cdbd2cSJim Jagielski 
XclExpNumberCell(const XclExpRoot & rRoot,const XclAddress & rXclPos,const ScPatternAttr * pPattern,sal_uInt32 nForcedXFId,double fValue)572*b1cdbd2cSJim Jagielski XclExpNumberCell::XclExpNumberCell(
573*b1cdbd2cSJim Jagielski         const XclExpRoot& rRoot, const XclAddress& rXclPos,
574*b1cdbd2cSJim Jagielski         const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId, double fValue ) :
575*b1cdbd2cSJim Jagielski     // #i41210# always use latin script for number cells - may look wrong for special number formats...
576*b1cdbd2cSJim Jagielski     XclExpSingleCellBase( rRoot, EXC_ID3_NUMBER, 8, rXclPos, pPattern, ApiScriptType::LATIN, nForcedXFId ),
577*b1cdbd2cSJim Jagielski     mfValue( fValue )
578*b1cdbd2cSJim Jagielski {
579*b1cdbd2cSJim Jagielski }
580*b1cdbd2cSJim Jagielski 
lcl_GetStyleId(XclExpXmlStream & rStrm,sal_uInt32 nXFIndex)581*b1cdbd2cSJim Jagielski static OString lcl_GetStyleId( XclExpXmlStream& rStrm, sal_uInt32 nXFIndex )
582*b1cdbd2cSJim Jagielski {
583*b1cdbd2cSJim Jagielski     return OString::valueOf( rStrm.GetRoot().GetXFBuffer()
584*b1cdbd2cSJim Jagielski             .GetXmlCellIndex( nXFIndex ) );
585*b1cdbd2cSJim Jagielski }
586*b1cdbd2cSJim Jagielski 
lcl_GetStyleId(XclExpXmlStream & rStrm,const XclExpCellBase & rCell)587*b1cdbd2cSJim Jagielski static OString lcl_GetStyleId( XclExpXmlStream& rStrm, const XclExpCellBase& rCell )
588*b1cdbd2cSJim Jagielski {
589*b1cdbd2cSJim Jagielski     sal_uInt32 nXFId    = rCell.GetFirstXFId();
590*b1cdbd2cSJim Jagielski     sal_uInt16 nXFIndex = rStrm.GetRoot().GetXFBuffer().GetXFIndex( nXFId );
591*b1cdbd2cSJim Jagielski     return lcl_GetStyleId( rStrm, nXFIndex );
592*b1cdbd2cSJim Jagielski }
593*b1cdbd2cSJim Jagielski 
SaveXml(XclExpXmlStream & rStrm)594*b1cdbd2cSJim Jagielski void XclExpNumberCell::SaveXml( XclExpXmlStream& rStrm )
595*b1cdbd2cSJim Jagielski {
596*b1cdbd2cSJim Jagielski     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
597*b1cdbd2cSJim Jagielski     rWorksheet->startElement( XML_c,
598*b1cdbd2cSJim Jagielski             XML_r,      XclXmlUtils::ToOString( GetXclPos() ).getStr(),
599*b1cdbd2cSJim Jagielski             XML_s,      lcl_GetStyleId( rStrm, *this ).getStr(),
600*b1cdbd2cSJim Jagielski             XML_t,      "n",
601*b1cdbd2cSJim Jagielski             // OOXTODO: XML_cm, XML_vm, XML_ph
602*b1cdbd2cSJim Jagielski             FSEND );
603*b1cdbd2cSJim Jagielski     rWorksheet->startElement( XML_v, FSEND );
604*b1cdbd2cSJim Jagielski     rWorksheet->write( mfValue );
605*b1cdbd2cSJim Jagielski     rWorksheet->endElement( XML_v );
606*b1cdbd2cSJim Jagielski     rWorksheet->endElement( XML_c );
607*b1cdbd2cSJim Jagielski }
608*b1cdbd2cSJim Jagielski 
WriteContents(XclExpStream & rStrm)609*b1cdbd2cSJim Jagielski void XclExpNumberCell::WriteContents( XclExpStream& rStrm )
610*b1cdbd2cSJim Jagielski {
611*b1cdbd2cSJim Jagielski     rStrm << mfValue;
612*b1cdbd2cSJim Jagielski }
613*b1cdbd2cSJim Jagielski 
614*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
615*b1cdbd2cSJim Jagielski 
616*b1cdbd2cSJim Jagielski IMPL_FIXEDMEMPOOL_NEWDEL( XclExpBooleanCell, 256, 256 )
617*b1cdbd2cSJim Jagielski 
XclExpBooleanCell(const XclExpRoot rRoot,const XclAddress & rXclPos,const ScPatternAttr * pPattern,sal_uInt32 nForcedXFId,bool bValue)618*b1cdbd2cSJim Jagielski XclExpBooleanCell::XclExpBooleanCell(
619*b1cdbd2cSJim Jagielski         const XclExpRoot rRoot, const XclAddress& rXclPos,
620*b1cdbd2cSJim Jagielski         const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId, bool bValue ) :
621*b1cdbd2cSJim Jagielski     // #i41210# always use latin script for boolean cells
622*b1cdbd2cSJim Jagielski     XclExpSingleCellBase( rRoot, EXC_ID3_BOOLERR, 2, rXclPos, pPattern, ApiScriptType::LATIN, nForcedXFId ),
623*b1cdbd2cSJim Jagielski     mbValue( bValue )
624*b1cdbd2cSJim Jagielski {
625*b1cdbd2cSJim Jagielski }
626*b1cdbd2cSJim Jagielski 
SaveXml(XclExpXmlStream & rStrm)627*b1cdbd2cSJim Jagielski void XclExpBooleanCell::SaveXml( XclExpXmlStream& rStrm )
628*b1cdbd2cSJim Jagielski {
629*b1cdbd2cSJim Jagielski     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
630*b1cdbd2cSJim Jagielski     rWorksheet->startElement( XML_c,
631*b1cdbd2cSJim Jagielski             XML_r,      XclXmlUtils::ToOString( GetXclPos() ).getStr(),
632*b1cdbd2cSJim Jagielski             XML_s,      lcl_GetStyleId( rStrm, *this ).getStr(),
633*b1cdbd2cSJim Jagielski             XML_t,      "b",
634*b1cdbd2cSJim Jagielski             // OOXTODO: XML_cm, XML_vm, XML_ph
635*b1cdbd2cSJim Jagielski             FSEND );
636*b1cdbd2cSJim Jagielski     rWorksheet->startElement( XML_v, FSEND );
637*b1cdbd2cSJim Jagielski     rWorksheet->write( mbValue ? "1" : "0" );
638*b1cdbd2cSJim Jagielski     rWorksheet->endElement( XML_v );
639*b1cdbd2cSJim Jagielski     rWorksheet->endElement( XML_c );
640*b1cdbd2cSJim Jagielski }
641*b1cdbd2cSJim Jagielski 
WriteContents(XclExpStream & rStrm)642*b1cdbd2cSJim Jagielski void XclExpBooleanCell::WriteContents( XclExpStream& rStrm )
643*b1cdbd2cSJim Jagielski {
644*b1cdbd2cSJim Jagielski     rStrm << sal_uInt16( mbValue ? 1 : 0 ) << EXC_BOOLERR_BOOL;
645*b1cdbd2cSJim Jagielski }
646*b1cdbd2cSJim Jagielski 
647*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
648*b1cdbd2cSJim Jagielski 
649*b1cdbd2cSJim Jagielski //UNUSED2009-05 IMPL_FIXEDMEMPOOL_NEWDEL( XclExpErrorCell, 256, 256 )
650*b1cdbd2cSJim Jagielski //UNUSED2009-05
651*b1cdbd2cSJim Jagielski //UNUSED2009-05 XclExpErrorCell::XclExpErrorCell(
652*b1cdbd2cSJim Jagielski //UNUSED2009-05         const XclExpRoot rRoot, const XclAddress& rXclPos,
653*b1cdbd2cSJim Jagielski //UNUSED2009-05         const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId, sal_uInt8 nErrCode ) :
654*b1cdbd2cSJim Jagielski //UNUSED2009-05     // #i41210# always use latin script for error cells
655*b1cdbd2cSJim Jagielski //UNUSED2009-05     XclExpSingleCellBase( rRoot, EXC_ID3_BOOLERR, 2, rXclPos, pPattern, ApiScriptType::LATIN, nForcedXFId ),
656*b1cdbd2cSJim Jagielski //UNUSED2009-05     mnErrCode( nErrCode )
657*b1cdbd2cSJim Jagielski //UNUSED2009-05 {
658*b1cdbd2cSJim Jagielski //UNUSED2009-05 }
659*b1cdbd2cSJim Jagielski //UNUSED2009-05
660*b1cdbd2cSJim Jagielski //UNUSED2009-05 void XclExpErrorCell::SaveXml( XclExpXmlStream& rStrm )
661*b1cdbd2cSJim Jagielski //UNUSED2009-05 {
662*b1cdbd2cSJim Jagielski //UNUSED2009-05     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
663*b1cdbd2cSJim Jagielski //UNUSED2009-05     rWorksheet->startElement( XML_c,
664*b1cdbd2cSJim Jagielski //UNUSED2009-05             XML_r,      XclXmlUtils::ToOString( GetXclPos() ).getStr(),
665*b1cdbd2cSJim Jagielski //UNUSED2009-05             XML_s,      lcl_GetStyleId( rStrm, *this ).getStr(),
666*b1cdbd2cSJim Jagielski //UNUSED2009-05             XML_t,      "e",
667*b1cdbd2cSJim Jagielski //UNUSED2009-05             // OOXTODO: XML_cm, XML_vm, XML_ph
668*b1cdbd2cSJim Jagielski //UNUSED2009-05             FSEND );
669*b1cdbd2cSJim Jagielski //UNUSED2009-05     rWorksheet->startElement( XML_v, FSEND );
670*b1cdbd2cSJim Jagielski //UNUSED2009-05     rWorksheet->write( (sal_Int32) mnErrCode );
671*b1cdbd2cSJim Jagielski //UNUSED2009-05     rWorksheet->endElement( XML_v );
672*b1cdbd2cSJim Jagielski //UNUSED2009-05     rWorksheet->endElement( XML_c );
673*b1cdbd2cSJim Jagielski //UNUSED2009-05 }
674*b1cdbd2cSJim Jagielski //UNUSED2009-05
675*b1cdbd2cSJim Jagielski //UNUSED2009-05 void XclExpErrorCell::WriteContents( XclExpStream& rStrm )
676*b1cdbd2cSJim Jagielski //UNUSED2009-05 {
677*b1cdbd2cSJim Jagielski //UNUSED2009-05     rStrm << mnErrCode << EXC_BOOLERR_ERROR;
678*b1cdbd2cSJim Jagielski //UNUSED2009-05 }
679*b1cdbd2cSJim Jagielski 
680*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
681*b1cdbd2cSJim Jagielski 
682*b1cdbd2cSJim Jagielski IMPL_FIXEDMEMPOOL_NEWDEL( XclExpLabelCell, 256, 256 )
683*b1cdbd2cSJim Jagielski 
XclExpLabelCell(const XclExpRoot & rRoot,const XclAddress & rXclPos,const ScPatternAttr * pPattern,sal_uInt32 nForcedXFId,const ScStringCell & rCell)684*b1cdbd2cSJim Jagielski XclExpLabelCell::XclExpLabelCell(
685*b1cdbd2cSJim Jagielski         const XclExpRoot& rRoot, const XclAddress& rXclPos,
686*b1cdbd2cSJim Jagielski         const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId, const ScStringCell& rCell ) :
687*b1cdbd2cSJim Jagielski     XclExpSingleCellBase( EXC_ID3_LABEL, 0, rXclPos, nForcedXFId )
688*b1cdbd2cSJim Jagielski {
689*b1cdbd2cSJim Jagielski     sal_uInt16 nMaxLen = (rRoot.GetBiff() == EXC_BIFF8) ? EXC_STR_MAXLEN : EXC_LABEL_MAXLEN;
690*b1cdbd2cSJim Jagielski     XclExpStringRef xText = XclExpStringHelper::CreateCellString( rRoot, rCell, pPattern, EXC_STR_DEFAULT, nMaxLen );
691*b1cdbd2cSJim Jagielski     Init( rRoot, pPattern, xText );
692*b1cdbd2cSJim Jagielski }
693*b1cdbd2cSJim Jagielski 
XclExpLabelCell(const XclExpRoot & rRoot,const XclAddress & rXclPos,const ScPatternAttr * pPattern,sal_uInt32 nForcedXFId,const ScEditCell & rCell,XclExpHyperlinkHelper & rLinkHelper)694*b1cdbd2cSJim Jagielski XclExpLabelCell::XclExpLabelCell(
695*b1cdbd2cSJim Jagielski         const XclExpRoot& rRoot, const XclAddress& rXclPos,
696*b1cdbd2cSJim Jagielski         const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId,
697*b1cdbd2cSJim Jagielski         const ScEditCell& rCell, XclExpHyperlinkHelper& rLinkHelper ) :
698*b1cdbd2cSJim Jagielski     XclExpSingleCellBase( EXC_ID3_LABEL, 0, rXclPos, nForcedXFId )
699*b1cdbd2cSJim Jagielski {
700*b1cdbd2cSJim Jagielski     sal_uInt16 nMaxLen = (rRoot.GetBiff() == EXC_BIFF8) ? EXC_STR_MAXLEN : EXC_LABEL_MAXLEN;
701*b1cdbd2cSJim Jagielski     XclExpStringRef xText = XclExpStringHelper::CreateCellString( rRoot, rCell, pPattern, rLinkHelper, EXC_STR_DEFAULT, nMaxLen );
702*b1cdbd2cSJim Jagielski     Init( rRoot, pPattern, xText );
703*b1cdbd2cSJim Jagielski }
704*b1cdbd2cSJim Jagielski 
IsMultiLineText() const705*b1cdbd2cSJim Jagielski bool XclExpLabelCell::IsMultiLineText() const
706*b1cdbd2cSJim Jagielski {
707*b1cdbd2cSJim Jagielski     return mbLineBreak || mxText->IsWrapped();
708*b1cdbd2cSJim Jagielski }
709*b1cdbd2cSJim Jagielski 
Init(const XclExpRoot & rRoot,const ScPatternAttr * pPattern,XclExpStringRef xText)710*b1cdbd2cSJim Jagielski void XclExpLabelCell::Init( const XclExpRoot& rRoot,
711*b1cdbd2cSJim Jagielski         const ScPatternAttr* pPattern, XclExpStringRef xText )
712*b1cdbd2cSJim Jagielski {
713*b1cdbd2cSJim Jagielski     DBG_ASSERT( xText.is() && xText->Len(), "XclExpLabelCell::XclExpLabelCell - empty string passed" );
714*b1cdbd2cSJim Jagielski     mxText = xText;
715*b1cdbd2cSJim Jagielski     mnSstIndex = 0;
716*b1cdbd2cSJim Jagielski 
717*b1cdbd2cSJim Jagielski     // create the cell format
718*b1cdbd2cSJim Jagielski     sal_uInt16 nXclFont = mxText->RemoveLeadingFont();
719*b1cdbd2cSJim Jagielski     if( GetXFId() == EXC_XFID_NOTFOUND )
720*b1cdbd2cSJim Jagielski     {
721*b1cdbd2cSJim Jagielski         DBG_ASSERT( nXclFont != EXC_FONT_NOTFOUND, "XclExpLabelCell::Init - leading font not found" );
722*b1cdbd2cSJim Jagielski         bool bForceLineBreak = mxText->IsWrapped();
723*b1cdbd2cSJim Jagielski         SetXFId( rRoot.GetXFBuffer().InsertWithFont( pPattern, ApiScriptType::WEAK, nXclFont, bForceLineBreak ) );
724*b1cdbd2cSJim Jagielski     }
725*b1cdbd2cSJim Jagielski 
726*b1cdbd2cSJim Jagielski     // get auto-wrap attribute from cell format
727*b1cdbd2cSJim Jagielski     const XclExpXF* pXF = rRoot.GetXFBuffer().GetXFById( GetXFId() );
728*b1cdbd2cSJim Jagielski     mbLineBreak = pXF && pXF->GetAlignmentData().mbLineBreak;
729*b1cdbd2cSJim Jagielski 
730*b1cdbd2cSJim Jagielski     // initialize the record contents
731*b1cdbd2cSJim Jagielski     switch( rRoot.GetBiff() )
732*b1cdbd2cSJim Jagielski     {
733*b1cdbd2cSJim Jagielski         case EXC_BIFF5:
734*b1cdbd2cSJim Jagielski             // BIFF5-BIFF7: create a LABEL or RSTRING record
735*b1cdbd2cSJim Jagielski             DBG_ASSERT( mxText->Len() <= EXC_LABEL_MAXLEN, "XclExpLabelCell::XclExpLabelCell - string too long" );
736*b1cdbd2cSJim Jagielski             SetContSize( mxText->GetSize() );
737*b1cdbd2cSJim Jagielski             // formatted string is exported in an RSTRING record
738*b1cdbd2cSJim Jagielski             if( mxText->IsRich() )
739*b1cdbd2cSJim Jagielski             {
740*b1cdbd2cSJim Jagielski                 DBG_ASSERT( mxText->GetFormatsCount() <= EXC_LABEL_MAXLEN, "XclExpLabelCell::WriteContents - too many formats" );
741*b1cdbd2cSJim Jagielski                 mxText->LimitFormatCount( EXC_LABEL_MAXLEN );
742*b1cdbd2cSJim Jagielski                 SetRecId( EXC_ID_RSTRING );
743*b1cdbd2cSJim Jagielski                 SetContSize( GetContSize() + 1 + 2 * mxText->GetFormatsCount() );
744*b1cdbd2cSJim Jagielski             }
745*b1cdbd2cSJim Jagielski         break;
746*b1cdbd2cSJim Jagielski         case EXC_BIFF8:
747*b1cdbd2cSJim Jagielski             // BIFF8+: create a LABELSST record
748*b1cdbd2cSJim Jagielski             mnSstIndex = rRoot.GetSst().Insert( xText );
749*b1cdbd2cSJim Jagielski             SetRecId( EXC_ID_LABELSST );
750*b1cdbd2cSJim Jagielski             SetContSize( 4 );
751*b1cdbd2cSJim Jagielski         break;
752*b1cdbd2cSJim Jagielski         default:    DBG_ERROR_BIFF();
753*b1cdbd2cSJim Jagielski     }
754*b1cdbd2cSJim Jagielski }
755*b1cdbd2cSJim Jagielski 
SaveXml(XclExpXmlStream & rStrm)756*b1cdbd2cSJim Jagielski void XclExpLabelCell::SaveXml( XclExpXmlStream& rStrm )
757*b1cdbd2cSJim Jagielski {
758*b1cdbd2cSJim Jagielski     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
759*b1cdbd2cSJim Jagielski     rWorksheet->startElement( XML_c,
760*b1cdbd2cSJim Jagielski             XML_r,      XclXmlUtils::ToOString( GetXclPos() ).getStr(),
761*b1cdbd2cSJim Jagielski             XML_s,      lcl_GetStyleId( rStrm, *this ).getStr(),
762*b1cdbd2cSJim Jagielski             XML_t,      "s",
763*b1cdbd2cSJim Jagielski             // OOXTODO: XML_cm, XML_vm, XML_ph
764*b1cdbd2cSJim Jagielski             FSEND );
765*b1cdbd2cSJim Jagielski     rWorksheet->startElement( XML_v, FSEND );
766*b1cdbd2cSJim Jagielski     rWorksheet->write( (sal_Int32) mnSstIndex );
767*b1cdbd2cSJim Jagielski     rWorksheet->endElement( XML_v );
768*b1cdbd2cSJim Jagielski     rWorksheet->endElement( XML_c );
769*b1cdbd2cSJim Jagielski }
770*b1cdbd2cSJim Jagielski 
WriteContents(XclExpStream & rStrm)771*b1cdbd2cSJim Jagielski void XclExpLabelCell::WriteContents( XclExpStream& rStrm )
772*b1cdbd2cSJim Jagielski {
773*b1cdbd2cSJim Jagielski     switch( rStrm.GetRoot().GetBiff() )
774*b1cdbd2cSJim Jagielski     {
775*b1cdbd2cSJim Jagielski         case EXC_BIFF5:
776*b1cdbd2cSJim Jagielski             rStrm << *mxText;
777*b1cdbd2cSJim Jagielski             if( mxText->IsRich() )
778*b1cdbd2cSJim Jagielski             {
779*b1cdbd2cSJim Jagielski                 rStrm << static_cast< sal_uInt8 >( mxText->GetFormatsCount() );
780*b1cdbd2cSJim Jagielski                 mxText->WriteFormats( rStrm );
781*b1cdbd2cSJim Jagielski             }
782*b1cdbd2cSJim Jagielski         break;
783*b1cdbd2cSJim Jagielski         case EXC_BIFF8:
784*b1cdbd2cSJim Jagielski             rStrm << mnSstIndex;
785*b1cdbd2cSJim Jagielski         break;
786*b1cdbd2cSJim Jagielski         default:    DBG_ERROR_BIFF();
787*b1cdbd2cSJim Jagielski     }
788*b1cdbd2cSJim Jagielski }
789*b1cdbd2cSJim Jagielski 
790*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
791*b1cdbd2cSJim Jagielski 
792*b1cdbd2cSJim Jagielski IMPL_FIXEDMEMPOOL_NEWDEL( XclExpFormulaCell, 256, 256 )
793*b1cdbd2cSJim Jagielski 
XclExpFormulaCell(const XclExpRoot & rRoot,const XclAddress & rXclPos,const ScPatternAttr * pPattern,sal_uInt32 nForcedXFId,const ScFormulaCell & rScFmlaCell,XclExpArrayBuffer & rArrayBfr,XclExpShrfmlaBuffer & rShrfmlaBfr,XclExpTableopBuffer & rTableopBfr)794*b1cdbd2cSJim Jagielski XclExpFormulaCell::XclExpFormulaCell(
795*b1cdbd2cSJim Jagielski         const XclExpRoot& rRoot, const XclAddress& rXclPos,
796*b1cdbd2cSJim Jagielski         const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId,
797*b1cdbd2cSJim Jagielski         const ScFormulaCell& rScFmlaCell,
798*b1cdbd2cSJim Jagielski         XclExpArrayBuffer& rArrayBfr,
799*b1cdbd2cSJim Jagielski         XclExpShrfmlaBuffer& rShrfmlaBfr,
800*b1cdbd2cSJim Jagielski         XclExpTableopBuffer& rTableopBfr ) :
801*b1cdbd2cSJim Jagielski     XclExpSingleCellBase( EXC_ID2_FORMULA, 0, rXclPos, nForcedXFId ),
802*b1cdbd2cSJim Jagielski     mrScFmlaCell( const_cast< ScFormulaCell& >( rScFmlaCell ) )
803*b1cdbd2cSJim Jagielski {
804*b1cdbd2cSJim Jagielski     // *** Find result number format overwriting cell number format *** -------
805*b1cdbd2cSJim Jagielski 
806*b1cdbd2cSJim Jagielski     if( GetXFId() == EXC_XFID_NOTFOUND )
807*b1cdbd2cSJim Jagielski     {
808*b1cdbd2cSJim Jagielski         SvNumberFormatter& rFormatter = rRoot.GetFormatter();
809*b1cdbd2cSJim Jagielski         XclExpNumFmtBuffer& rNumFmtBfr = rRoot.GetNumFmtBuffer();
810*b1cdbd2cSJim Jagielski 
811*b1cdbd2cSJim Jagielski         // current cell number format
812*b1cdbd2cSJim Jagielski         sal_uLong nScNumFmt = pPattern ?
813*b1cdbd2cSJim Jagielski             GETITEMVALUE( pPattern->GetItemSet(), SfxUInt32Item, ATTR_VALUE_FORMAT, sal_uLong ) :
814*b1cdbd2cSJim Jagielski             rNumFmtBfr.GetStandardFormat();
815*b1cdbd2cSJim Jagielski 
816*b1cdbd2cSJim Jagielski         // alternative number format passed to XF buffer
817*b1cdbd2cSJim Jagielski         sal_uLong nAltScNumFmt = NUMBERFORMAT_ENTRY_NOT_FOUND;
818*b1cdbd2cSJim Jagielski         /*  #73420# Xcl doesn't know Boolean number formats, we write
819*b1cdbd2cSJim Jagielski             "TRUE";"FALSE" (language dependent). Don't do it for automatic
820*b1cdbd2cSJim Jagielski             formula formats, because Excel gets them right. */
821*b1cdbd2cSJim Jagielski         /*  #i8640# Don't set text format, if we have string results. */
822*b1cdbd2cSJim Jagielski         short nFormatType = mrScFmlaCell.GetFormatType();
823*b1cdbd2cSJim Jagielski         if( ((nScNumFmt % SV_COUNTRY_LANGUAGE_OFFSET) == 0) &&
824*b1cdbd2cSJim Jagielski                 (nFormatType != NUMBERFORMAT_LOGICAL) &&
825*b1cdbd2cSJim Jagielski                 (nFormatType != NUMBERFORMAT_TEXT) )
826*b1cdbd2cSJim Jagielski             nAltScNumFmt = mrScFmlaCell.GetStandardFormat( rFormatter, nScNumFmt );
827*b1cdbd2cSJim Jagielski         /*  #73420# If cell number format is Boolean and automatic formula
828*b1cdbd2cSJim Jagielski             format is Boolean don't write that ugly special format. */
829*b1cdbd2cSJim Jagielski         else if( (nFormatType == NUMBERFORMAT_LOGICAL) &&
830*b1cdbd2cSJim Jagielski                 (rFormatter.GetType( nScNumFmt ) == NUMBERFORMAT_LOGICAL) )
831*b1cdbd2cSJim Jagielski             nAltScNumFmt = rNumFmtBfr.GetStandardFormat();
832*b1cdbd2cSJim Jagielski 
833*b1cdbd2cSJim Jagielski         // #i41420# find script type according to result type (always latin for numeric results)
834*b1cdbd2cSJim Jagielski         sal_Int16 nScript = ApiScriptType::LATIN;
835*b1cdbd2cSJim Jagielski         bool bForceLineBreak = false;
836*b1cdbd2cSJim Jagielski         if( nFormatType == NUMBERFORMAT_TEXT )
837*b1cdbd2cSJim Jagielski         {
838*b1cdbd2cSJim Jagielski             String aResult;
839*b1cdbd2cSJim Jagielski             mrScFmlaCell.GetString( aResult );
840*b1cdbd2cSJim Jagielski             bForceLineBreak = mrScFmlaCell.IsMultilineResult();
841*b1cdbd2cSJim Jagielski             nScript = XclExpStringHelper::GetLeadingScriptType( rRoot, aResult );
842*b1cdbd2cSJim Jagielski         }
843*b1cdbd2cSJim Jagielski         SetXFId( rRoot.GetXFBuffer().InsertWithNumFmt( pPattern, nScript, nAltScNumFmt, bForceLineBreak ) );
844*b1cdbd2cSJim Jagielski     }
845*b1cdbd2cSJim Jagielski 
846*b1cdbd2cSJim Jagielski     // *** Convert the formula token array *** --------------------------------
847*b1cdbd2cSJim Jagielski 
848*b1cdbd2cSJim Jagielski     ScAddress aScPos( static_cast< SCCOL >( rXclPos.mnCol ), static_cast< SCROW >( rXclPos.mnRow ), rRoot.GetCurrScTab() );
849*b1cdbd2cSJim Jagielski     const ScTokenArray& rScTokArr = *mrScFmlaCell.GetCode();
850*b1cdbd2cSJim Jagielski 
851*b1cdbd2cSJim Jagielski     // first try to create multiple operations
852*b1cdbd2cSJim Jagielski     mxAddRec = rTableopBfr.CreateOrExtendTableop( rScTokArr, aScPos );
853*b1cdbd2cSJim Jagielski 
854*b1cdbd2cSJim Jagielski     // no multiple operation found - try to create matrix formula
855*b1cdbd2cSJim Jagielski     if( !mxAddRec ) switch( static_cast< ScMatrixMode >( mrScFmlaCell.GetMatrixFlag() ) )
856*b1cdbd2cSJim Jagielski     {
857*b1cdbd2cSJim Jagielski         case MM_FORMULA:
858*b1cdbd2cSJim Jagielski         {
859*b1cdbd2cSJim Jagielski             // origin of the matrix - find the used matrix range
860*b1cdbd2cSJim Jagielski             SCCOL nMatWidth;
861*b1cdbd2cSJim Jagielski             SCROW nMatHeight;
862*b1cdbd2cSJim Jagielski             mrScFmlaCell.GetMatColsRows( nMatWidth, nMatHeight );
863*b1cdbd2cSJim Jagielski             DBG_ASSERT( nMatWidth && nMatHeight, "XclExpFormulaCell::XclExpFormulaCell - empty matrix" );
864*b1cdbd2cSJim Jagielski             ScRange aMatScRange( aScPos );
865*b1cdbd2cSJim Jagielski             ScAddress& rMatEnd = aMatScRange.aEnd;
866*b1cdbd2cSJim Jagielski             rMatEnd.IncCol( static_cast< SCsCOL >( nMatWidth - 1 ) );
867*b1cdbd2cSJim Jagielski             rMatEnd.IncRow( static_cast< SCsROW >( nMatHeight - 1 ) );
868*b1cdbd2cSJim Jagielski             // reduce to valid range (range keeps valid, because start position IS valid)
869*b1cdbd2cSJim Jagielski             rRoot.GetAddressConverter().ValidateRange( aMatScRange, true );
870*b1cdbd2cSJim Jagielski             // create the ARRAY record
871*b1cdbd2cSJim Jagielski             mxAddRec = rArrayBfr.CreateArray( rScTokArr, aMatScRange );
872*b1cdbd2cSJim Jagielski         }
873*b1cdbd2cSJim Jagielski         break;
874*b1cdbd2cSJim Jagielski         case MM_REFERENCE:
875*b1cdbd2cSJim Jagielski         {
876*b1cdbd2cSJim Jagielski             // other formula cell covered by a matrix - find the ARRAY record
877*b1cdbd2cSJim Jagielski             mxAddRec = rArrayBfr.FindArray( rScTokArr );
878*b1cdbd2cSJim Jagielski             // should always be found, if Calc document is not broken
879*b1cdbd2cSJim Jagielski             DBG_ASSERT( mxAddRec.is(), "XclExpFormulaCell::XclExpFormulaCell - no matrix found" );
880*b1cdbd2cSJim Jagielski         }
881*b1cdbd2cSJim Jagielski         break;
882*b1cdbd2cSJim Jagielski         default:;
883*b1cdbd2cSJim Jagielski     }
884*b1cdbd2cSJim Jagielski 
885*b1cdbd2cSJim Jagielski     // no matrix found - try to create shared formula
886*b1cdbd2cSJim Jagielski     if( !mxAddRec )
887*b1cdbd2cSJim Jagielski         mxAddRec = rShrfmlaBfr.CreateOrExtendShrfmla( rScTokArr, aScPos );
888*b1cdbd2cSJim Jagielski 
889*b1cdbd2cSJim Jagielski     // no shared formula found - create a simple cell formula
890*b1cdbd2cSJim Jagielski     if( !mxAddRec )
891*b1cdbd2cSJim Jagielski         mxTokArr = rRoot.GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CELL, rScTokArr, &aScPos );
892*b1cdbd2cSJim Jagielski }
893*b1cdbd2cSJim Jagielski 
Save(XclExpStream & rStrm)894*b1cdbd2cSJim Jagielski void XclExpFormulaCell::Save( XclExpStream& rStrm )
895*b1cdbd2cSJim Jagielski {
896*b1cdbd2cSJim Jagielski     // create token array for FORMULA cells with additional record
897*b1cdbd2cSJim Jagielski     if( mxAddRec.is() )
898*b1cdbd2cSJim Jagielski         mxTokArr = mxAddRec->CreateCellTokenArray( rStrm.GetRoot() );
899*b1cdbd2cSJim Jagielski 
900*b1cdbd2cSJim Jagielski     // FORMULA record itself
901*b1cdbd2cSJim Jagielski     DBG_ASSERT( mxTokArr.is(), "XclExpFormulaCell::Save - missing token array" );
902*b1cdbd2cSJim Jagielski     if( !mxTokArr )
903*b1cdbd2cSJim Jagielski         mxTokArr = rStrm.GetRoot().GetFormulaCompiler().CreateErrorFormula( EXC_ERR_NA );
904*b1cdbd2cSJim Jagielski     SetContSize( 16 + mxTokArr->GetSize() );
905*b1cdbd2cSJim Jagielski     XclExpSingleCellBase::Save( rStrm );
906*b1cdbd2cSJim Jagielski 
907*b1cdbd2cSJim Jagielski     // additional record (ARRAY, SHRFMLA, or TABLEOP), only for first FORMULA record
908*b1cdbd2cSJim Jagielski     if( mxAddRec.is() && mxAddRec->IsBasePos( GetXclCol(), GetXclRow() ) )
909*b1cdbd2cSJim Jagielski         mxAddRec->Save( rStrm );
910*b1cdbd2cSJim Jagielski 
911*b1cdbd2cSJim Jagielski     // STRING record for string result
912*b1cdbd2cSJim Jagielski     if( mxStringRec.is() )
913*b1cdbd2cSJim Jagielski         mxStringRec->Save( rStrm );
914*b1cdbd2cSJim Jagielski }
915*b1cdbd2cSJim Jagielski 
lcl_GetErrorString(sal_uInt16 nScErrCode)916*b1cdbd2cSJim Jagielski static const char* lcl_GetErrorString( sal_uInt16 nScErrCode )
917*b1cdbd2cSJim Jagielski {
918*b1cdbd2cSJim Jagielski     sal_uInt8 nXclErrCode = XclTools::GetXclErrorCode( nScErrCode );
919*b1cdbd2cSJim Jagielski     switch( nXclErrCode )
920*b1cdbd2cSJim Jagielski     {
921*b1cdbd2cSJim Jagielski         case EXC_ERR_NULL:  return "#NULL!";
922*b1cdbd2cSJim Jagielski         case EXC_ERR_DIV0:  return "#DIV/0!";
923*b1cdbd2cSJim Jagielski         case EXC_ERR_VALUE: return "#VALUE!";
924*b1cdbd2cSJim Jagielski         case EXC_ERR_REF:   return "#REF!";
925*b1cdbd2cSJim Jagielski         case EXC_ERR_NAME:  return "#NAME?";
926*b1cdbd2cSJim Jagielski         case EXC_ERR_NUM:   return "#NUM!";
927*b1cdbd2cSJim Jagielski         case EXC_ERR_NA:
928*b1cdbd2cSJim Jagielski         default:            return "#N/A";
929*b1cdbd2cSJim Jagielski     }
930*b1cdbd2cSJim Jagielski }
931*b1cdbd2cSJim Jagielski 
lcl_GetFormulaInfo(ScFormulaCell & rCell,const char ** pType,OUString & rValue)932*b1cdbd2cSJim Jagielski static void lcl_GetFormulaInfo( ScFormulaCell& rCell, const char** pType, OUString& rValue)
933*b1cdbd2cSJim Jagielski {
934*b1cdbd2cSJim Jagielski     switch( rCell.GetFormatType() )
935*b1cdbd2cSJim Jagielski     {
936*b1cdbd2cSJim Jagielski         case NUMBERFORMAT_NUMBER:
937*b1cdbd2cSJim Jagielski         {
938*b1cdbd2cSJim Jagielski             // either value or error code
939*b1cdbd2cSJim Jagielski             sal_uInt16 nScErrCode = rCell.GetErrCode();
940*b1cdbd2cSJim Jagielski             if( nScErrCode )
941*b1cdbd2cSJim Jagielski             {
942*b1cdbd2cSJim Jagielski                 *pType = "e";
943*b1cdbd2cSJim Jagielski                 rValue = XclXmlUtils::ToOUString( lcl_GetErrorString( nScErrCode ) );
944*b1cdbd2cSJim Jagielski             }
945*b1cdbd2cSJim Jagielski             else
946*b1cdbd2cSJim Jagielski             {
947*b1cdbd2cSJim Jagielski                 *pType = "n";
948*b1cdbd2cSJim Jagielski                 rValue = OUString::valueOf( rCell.GetValue() );
949*b1cdbd2cSJim Jagielski             }
950*b1cdbd2cSJim Jagielski         }
951*b1cdbd2cSJim Jagielski         break;
952*b1cdbd2cSJim Jagielski 
953*b1cdbd2cSJim Jagielski         case NUMBERFORMAT_TEXT:
954*b1cdbd2cSJim Jagielski         {
955*b1cdbd2cSJim Jagielski             *pType = "str";
956*b1cdbd2cSJim Jagielski             String aResult;
957*b1cdbd2cSJim Jagielski             rCell.GetString( aResult );
958*b1cdbd2cSJim Jagielski             rValue = XclXmlUtils::ToOUString( aResult );
959*b1cdbd2cSJim Jagielski         }
960*b1cdbd2cSJim Jagielski         break;
961*b1cdbd2cSJim Jagielski 
962*b1cdbd2cSJim Jagielski         case NUMBERFORMAT_LOGICAL:
963*b1cdbd2cSJim Jagielski         {
964*b1cdbd2cSJim Jagielski             *pType = "b";
965*b1cdbd2cSJim Jagielski             rValue = XclXmlUtils::ToOUString( rCell.GetValue() == 0.0 ? "0" : "1" );
966*b1cdbd2cSJim Jagielski         }
967*b1cdbd2cSJim Jagielski         break;
968*b1cdbd2cSJim Jagielski 
969*b1cdbd2cSJim Jagielski         default:
970*b1cdbd2cSJim Jagielski         {
971*b1cdbd2cSJim Jagielski             *pType = "inlineStr";
972*b1cdbd2cSJim Jagielski             String aResult;
973*b1cdbd2cSJim Jagielski             rCell.GetString( aResult );
974*b1cdbd2cSJim Jagielski             rValue = XclXmlUtils::ToOUString( aResult );
975*b1cdbd2cSJim Jagielski         }
976*b1cdbd2cSJim Jagielski         break;
977*b1cdbd2cSJim Jagielski     }
978*b1cdbd2cSJim Jagielski }
979*b1cdbd2cSJim Jagielski 
SaveXml(XclExpXmlStream & rStrm)980*b1cdbd2cSJim Jagielski void XclExpFormulaCell::SaveXml( XclExpXmlStream& rStrm )
981*b1cdbd2cSJim Jagielski {
982*b1cdbd2cSJim Jagielski     const char* sType = NULL;
983*b1cdbd2cSJim Jagielski     OUString    sValue;
984*b1cdbd2cSJim Jagielski 
985*b1cdbd2cSJim Jagielski     lcl_GetFormulaInfo( mrScFmlaCell, &sType, sValue );
986*b1cdbd2cSJim Jagielski     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
987*b1cdbd2cSJim Jagielski     rWorksheet->startElement( XML_c,
988*b1cdbd2cSJim Jagielski             XML_r,      XclXmlUtils::ToOString( GetXclPos() ).getStr(),
989*b1cdbd2cSJim Jagielski             XML_s,      lcl_GetStyleId( rStrm, *this ).getStr(),
990*b1cdbd2cSJim Jagielski             XML_t,      sType,
991*b1cdbd2cSJim Jagielski             // OOXTODO: XML_cm, XML_vm, XML_ph
992*b1cdbd2cSJim Jagielski             FSEND );
993*b1cdbd2cSJim Jagielski 
994*b1cdbd2cSJim Jagielski     rWorksheet->startElement( XML_f,
995*b1cdbd2cSJim Jagielski             // OOXTODO: XML_t,      ST_CellFormulaType
996*b1cdbd2cSJim Jagielski             XML_aca,    XclXmlUtils::ToPsz( mxTokArr->IsVolatile() || (mxAddRec.is() && mxAddRec->IsVolatile()) ),
997*b1cdbd2cSJim Jagielski             // OOXTODO: XML_ref,    ST_Ref
998*b1cdbd2cSJim Jagielski             // OOXTODO: XML_dt2D,   bool
999*b1cdbd2cSJim Jagielski             // OOXTODO: XML_dtr,    bool
1000*b1cdbd2cSJim Jagielski             // OOXTODO: XML_del1,   bool
1001*b1cdbd2cSJim Jagielski             // OOXTODO: XML_del2,   bool
1002*b1cdbd2cSJim Jagielski             // OOXTODO: XML_r1,     ST_CellRef
1003*b1cdbd2cSJim Jagielski             // OOXTODO: XML_r2,     ST_CellRef
1004*b1cdbd2cSJim Jagielski             // OOXTODO: XML_ca,     bool
1005*b1cdbd2cSJim Jagielski             // OOXTODO: XML_si,     uint
1006*b1cdbd2cSJim Jagielski             // OOXTODO: XML_bx      bool
1007*b1cdbd2cSJim Jagielski             FSEND );
1008*b1cdbd2cSJim Jagielski     rWorksheet->writeEscaped( XclXmlUtils::ToOUString( *mrScFmlaCell.GetDocument(), mrScFmlaCell.aPos, mrScFmlaCell.GetCode() ) );
1009*b1cdbd2cSJim Jagielski     rWorksheet->endElement( XML_f );
1010*b1cdbd2cSJim Jagielski     if( strcmp( sType, "inlineStr" ) == 0 )
1011*b1cdbd2cSJim Jagielski     {
1012*b1cdbd2cSJim Jagielski         rWorksheet->startElement( XML_is, FSEND );
1013*b1cdbd2cSJim Jagielski         rWorksheet->startElement( XML_t, FSEND );
1014*b1cdbd2cSJim Jagielski         rWorksheet->writeEscaped( sValue );
1015*b1cdbd2cSJim Jagielski         rWorksheet->endElement( XML_t );
1016*b1cdbd2cSJim Jagielski         rWorksheet->endElement( XML_is );
1017*b1cdbd2cSJim Jagielski     }
1018*b1cdbd2cSJim Jagielski     else
1019*b1cdbd2cSJim Jagielski     {
1020*b1cdbd2cSJim Jagielski         rWorksheet->startElement( XML_v, FSEND );
1021*b1cdbd2cSJim Jagielski         rWorksheet->writeEscaped( sValue );
1022*b1cdbd2cSJim Jagielski         rWorksheet->endElement( XML_v );
1023*b1cdbd2cSJim Jagielski     }
1024*b1cdbd2cSJim Jagielski     rWorksheet->endElement( XML_c );
1025*b1cdbd2cSJim Jagielski }
1026*b1cdbd2cSJim Jagielski 
WriteContents(XclExpStream & rStrm)1027*b1cdbd2cSJim Jagielski void XclExpFormulaCell::WriteContents( XclExpStream& rStrm )
1028*b1cdbd2cSJim Jagielski {
1029*b1cdbd2cSJim Jagielski     // result of the formula
1030*b1cdbd2cSJim Jagielski     switch( mrScFmlaCell.GetFormatType() )
1031*b1cdbd2cSJim Jagielski     {
1032*b1cdbd2cSJim Jagielski         case NUMBERFORMAT_NUMBER:
1033*b1cdbd2cSJim Jagielski         {
1034*b1cdbd2cSJim Jagielski             // either value or error code
1035*b1cdbd2cSJim Jagielski             sal_uInt16 nScErrCode = mrScFmlaCell.GetErrCode();
1036*b1cdbd2cSJim Jagielski             if( nScErrCode )
1037*b1cdbd2cSJim Jagielski                 rStrm << EXC_FORMULA_RES_ERROR << sal_uInt8( 0 )
1038*b1cdbd2cSJim Jagielski                       << XclTools::GetXclErrorCode( nScErrCode )
1039*b1cdbd2cSJim Jagielski                       << sal_uInt8( 0 ) << sal_uInt16( 0 )
1040*b1cdbd2cSJim Jagielski                       << sal_uInt16( 0xFFFF );
1041*b1cdbd2cSJim Jagielski             else
1042*b1cdbd2cSJim Jagielski                 rStrm << mrScFmlaCell.GetValue();
1043*b1cdbd2cSJim Jagielski         }
1044*b1cdbd2cSJim Jagielski         break;
1045*b1cdbd2cSJim Jagielski 
1046*b1cdbd2cSJim Jagielski         case NUMBERFORMAT_TEXT:
1047*b1cdbd2cSJim Jagielski         {
1048*b1cdbd2cSJim Jagielski             String aResult;
1049*b1cdbd2cSJim Jagielski             mrScFmlaCell.GetString( aResult );
1050*b1cdbd2cSJim Jagielski             if( aResult.Len() || (rStrm.GetRoot().GetBiff() <= EXC_BIFF5) )
1051*b1cdbd2cSJim Jagielski             {
1052*b1cdbd2cSJim Jagielski                 rStrm << EXC_FORMULA_RES_STRING;
1053*b1cdbd2cSJim Jagielski                 mxStringRec.reset( new XclExpStringRec( rStrm.GetRoot(), aResult ) );
1054*b1cdbd2cSJim Jagielski             }
1055*b1cdbd2cSJim Jagielski             else
1056*b1cdbd2cSJim Jagielski                 rStrm << EXC_FORMULA_RES_EMPTY;     // BIFF8 only
1057*b1cdbd2cSJim Jagielski             rStrm << sal_uInt8( 0 ) << sal_uInt32( 0 ) << sal_uInt16( 0xFFFF );
1058*b1cdbd2cSJim Jagielski         }
1059*b1cdbd2cSJim Jagielski         break;
1060*b1cdbd2cSJim Jagielski 
1061*b1cdbd2cSJim Jagielski         case NUMBERFORMAT_LOGICAL:
1062*b1cdbd2cSJim Jagielski         {
1063*b1cdbd2cSJim Jagielski             sal_uInt8 nXclValue = (mrScFmlaCell.GetValue() == 0.0) ? 0 : 1;
1064*b1cdbd2cSJim Jagielski             rStrm << EXC_FORMULA_RES_BOOL << sal_uInt8( 0 )
1065*b1cdbd2cSJim Jagielski                   << nXclValue << sal_uInt8( 0 ) << sal_uInt16( 0 )
1066*b1cdbd2cSJim Jagielski                   << sal_uInt16( 0xFFFF );
1067*b1cdbd2cSJim Jagielski         }
1068*b1cdbd2cSJim Jagielski         break;
1069*b1cdbd2cSJim Jagielski 
1070*b1cdbd2cSJim Jagielski         default:
1071*b1cdbd2cSJim Jagielski             rStrm << mrScFmlaCell.GetValue();
1072*b1cdbd2cSJim Jagielski     }
1073*b1cdbd2cSJim Jagielski 
1074*b1cdbd2cSJim Jagielski     // flags and formula token array
1075*b1cdbd2cSJim Jagielski     sal_uInt16 nFlags = EXC_FORMULA_DEFAULTFLAGS;
1076*b1cdbd2cSJim Jagielski     ::set_flag( nFlags, EXC_FORMULA_RECALC_ALWAYS, mxTokArr->IsVolatile() || (mxAddRec.is() && mxAddRec->IsVolatile()) );
1077*b1cdbd2cSJim Jagielski     ::set_flag( nFlags, EXC_FORMULA_SHARED, mxAddRec.is() && (mxAddRec->GetRecId() == EXC_ID_SHRFMLA) );
1078*b1cdbd2cSJim Jagielski     rStrm << nFlags << sal_uInt32( 0 ) << *mxTokArr;
1079*b1cdbd2cSJim Jagielski }
1080*b1cdbd2cSJim Jagielski 
1081*b1cdbd2cSJim Jagielski // Multiple cell records ======================================================
1082*b1cdbd2cSJim Jagielski 
XclExpMultiCellBase(sal_uInt16 nRecId,sal_uInt16 nMulRecId,sal_Size nContSize,const XclAddress & rXclPos)1083*b1cdbd2cSJim Jagielski XclExpMultiCellBase::XclExpMultiCellBase(
1084*b1cdbd2cSJim Jagielski         sal_uInt16 nRecId, sal_uInt16 nMulRecId, sal_Size nContSize, const XclAddress& rXclPos ) :
1085*b1cdbd2cSJim Jagielski     XclExpCellBase( nRecId, 0, rXclPos ),
1086*b1cdbd2cSJim Jagielski     mnMulRecId( nMulRecId ),
1087*b1cdbd2cSJim Jagielski     mnContSize( nContSize )
1088*b1cdbd2cSJim Jagielski {
1089*b1cdbd2cSJim Jagielski }
1090*b1cdbd2cSJim Jagielski 
GetLastXclCol() const1091*b1cdbd2cSJim Jagielski sal_uInt16 XclExpMultiCellBase::GetLastXclCol() const
1092*b1cdbd2cSJim Jagielski {
1093*b1cdbd2cSJim Jagielski     return GetXclCol() + GetCellCount() - 1;
1094*b1cdbd2cSJim Jagielski }
1095*b1cdbd2cSJim Jagielski 
GetFirstXFId() const1096*b1cdbd2cSJim Jagielski sal_uInt32 XclExpMultiCellBase::GetFirstXFId() const
1097*b1cdbd2cSJim Jagielski {
1098*b1cdbd2cSJim Jagielski     return maXFIds.empty() ? XclExpXFBuffer::GetDefCellXFId() : maXFIds.front().mnXFId;
1099*b1cdbd2cSJim Jagielski }
1100*b1cdbd2cSJim Jagielski 
IsEmpty() const1101*b1cdbd2cSJim Jagielski bool XclExpMultiCellBase::IsEmpty() const
1102*b1cdbd2cSJim Jagielski {
1103*b1cdbd2cSJim Jagielski     return maXFIds.empty();
1104*b1cdbd2cSJim Jagielski }
1105*b1cdbd2cSJim Jagielski 
ConvertXFIndexes(const XclExpRoot & rRoot)1106*b1cdbd2cSJim Jagielski void XclExpMultiCellBase::ConvertXFIndexes( const XclExpRoot& rRoot )
1107*b1cdbd2cSJim Jagielski {
1108*b1cdbd2cSJim Jagielski     for( XclExpMultiXFIdDeq::iterator aIt = maXFIds.begin(), aEnd = maXFIds.end(); aIt != aEnd; ++aIt )
1109*b1cdbd2cSJim Jagielski         aIt->ConvertXFIndex( rRoot );
1110*b1cdbd2cSJim Jagielski }
1111*b1cdbd2cSJim Jagielski 
Save(XclExpStream & rStrm)1112*b1cdbd2cSJim Jagielski void XclExpMultiCellBase::Save( XclExpStream& rStrm )
1113*b1cdbd2cSJim Jagielski {
1114*b1cdbd2cSJim Jagielski     DBG_ASSERT_BIFF( rStrm.GetRoot().GetBiff() >= EXC_BIFF3 );
1115*b1cdbd2cSJim Jagielski 
1116*b1cdbd2cSJim Jagielski     XclExpMultiXFIdDeq::const_iterator aEnd = maXFIds.end();
1117*b1cdbd2cSJim Jagielski     XclExpMultiXFIdDeq::const_iterator aRangeBeg = maXFIds.begin();
1118*b1cdbd2cSJim Jagielski     XclExpMultiXFIdDeq::const_iterator aRangeEnd = aRangeBeg;
1119*b1cdbd2cSJim Jagielski     sal_uInt16 nBegXclCol = GetXclCol();
1120*b1cdbd2cSJim Jagielski     sal_uInt16 nEndXclCol = nBegXclCol;
1121*b1cdbd2cSJim Jagielski 
1122*b1cdbd2cSJim Jagielski     while( aRangeEnd != aEnd )
1123*b1cdbd2cSJim Jagielski     {
1124*b1cdbd2cSJim Jagielski         // find begin of next used XF range
1125*b1cdbd2cSJim Jagielski         aRangeBeg = aRangeEnd;
1126*b1cdbd2cSJim Jagielski         nBegXclCol = nEndXclCol;
1127*b1cdbd2cSJim Jagielski         while( (aRangeBeg != aEnd) && (aRangeBeg->mnXFIndex == EXC_XF_NOTFOUND) )
1128*b1cdbd2cSJim Jagielski         {
1129*b1cdbd2cSJim Jagielski             nBegXclCol = nBegXclCol + aRangeBeg->mnCount;
1130*b1cdbd2cSJim Jagielski             ++aRangeBeg;
1131*b1cdbd2cSJim Jagielski         }
1132*b1cdbd2cSJim Jagielski         // find end of next used XF range
1133*b1cdbd2cSJim Jagielski         aRangeEnd = aRangeBeg;
1134*b1cdbd2cSJim Jagielski         nEndXclCol = nBegXclCol;
1135*b1cdbd2cSJim Jagielski         while( (aRangeEnd != aEnd) && (aRangeEnd->mnXFIndex != EXC_XF_NOTFOUND) )
1136*b1cdbd2cSJim Jagielski         {
1137*b1cdbd2cSJim Jagielski             nEndXclCol = nEndXclCol + aRangeEnd->mnCount;
1138*b1cdbd2cSJim Jagielski             ++aRangeEnd;
1139*b1cdbd2cSJim Jagielski         }
1140*b1cdbd2cSJim Jagielski 
1141*b1cdbd2cSJim Jagielski         // export this range as a record
1142*b1cdbd2cSJim Jagielski         if( aRangeBeg != aRangeEnd )
1143*b1cdbd2cSJim Jagielski         {
1144*b1cdbd2cSJim Jagielski             sal_uInt16 nCount = nEndXclCol - nBegXclCol;
1145*b1cdbd2cSJim Jagielski             bool bIsMulti = nCount > 1;
1146*b1cdbd2cSJim Jagielski             sal_Size nTotalSize = GetRecSize() + (2 + mnContSize) * nCount;
1147*b1cdbd2cSJim Jagielski             if( bIsMulti ) nTotalSize += 2;
1148*b1cdbd2cSJim Jagielski 
1149*b1cdbd2cSJim Jagielski             rStrm.StartRecord( bIsMulti ? mnMulRecId : GetRecId(), nTotalSize );
1150*b1cdbd2cSJim Jagielski             rStrm << GetXclRow() << nBegXclCol;
1151*b1cdbd2cSJim Jagielski 
1152*b1cdbd2cSJim Jagielski             sal_uInt16 nRelCol = nBegXclCol - GetXclCol();
1153*b1cdbd2cSJim Jagielski             for( XclExpMultiXFIdDeq::const_iterator aIt = aRangeBeg; aIt != aRangeEnd; ++aIt )
1154*b1cdbd2cSJim Jagielski             {
1155*b1cdbd2cSJim Jagielski                 for( sal_uInt16 nIdx = 0; nIdx < aIt->mnCount; ++nIdx )
1156*b1cdbd2cSJim Jagielski                 {
1157*b1cdbd2cSJim Jagielski                     rStrm << aIt->mnXFIndex;
1158*b1cdbd2cSJim Jagielski                     WriteContents( rStrm, nRelCol );
1159*b1cdbd2cSJim Jagielski                     ++nRelCol;
1160*b1cdbd2cSJim Jagielski                 }
1161*b1cdbd2cSJim Jagielski             }
1162*b1cdbd2cSJim Jagielski             if( bIsMulti )
1163*b1cdbd2cSJim Jagielski                 rStrm << static_cast< sal_uInt16 >( nEndXclCol - 1 );
1164*b1cdbd2cSJim Jagielski             rStrm.EndRecord();
1165*b1cdbd2cSJim Jagielski         }
1166*b1cdbd2cSJim Jagielski     }
1167*b1cdbd2cSJim Jagielski }
1168*b1cdbd2cSJim Jagielski 
SaveXml(XclExpXmlStream & rStrm)1169*b1cdbd2cSJim Jagielski void XclExpMultiCellBase::SaveXml( XclExpXmlStream& rStrm )
1170*b1cdbd2cSJim Jagielski {
1171*b1cdbd2cSJim Jagielski     XclExpMultiXFIdDeq::const_iterator aEnd = maXFIds.end();
1172*b1cdbd2cSJim Jagielski     XclExpMultiXFIdDeq::const_iterator aRangeBeg = maXFIds.begin();
1173*b1cdbd2cSJim Jagielski     XclExpMultiXFIdDeq::const_iterator aRangeEnd = aRangeBeg;
1174*b1cdbd2cSJim Jagielski     sal_uInt16 nBegXclCol = GetXclCol();
1175*b1cdbd2cSJim Jagielski     sal_uInt16 nEndXclCol = nBegXclCol;
1176*b1cdbd2cSJim Jagielski 
1177*b1cdbd2cSJim Jagielski     while( aRangeEnd != aEnd )
1178*b1cdbd2cSJim Jagielski     {
1179*b1cdbd2cSJim Jagielski         // find begin of next used XF range
1180*b1cdbd2cSJim Jagielski         aRangeBeg = aRangeEnd;
1181*b1cdbd2cSJim Jagielski         nBegXclCol = nEndXclCol;
1182*b1cdbd2cSJim Jagielski         while( (aRangeBeg != aEnd) && (aRangeBeg->mnXFIndex == EXC_XF_NOTFOUND) )
1183*b1cdbd2cSJim Jagielski         {
1184*b1cdbd2cSJim Jagielski             nBegXclCol = nBegXclCol + aRangeBeg->mnCount;
1185*b1cdbd2cSJim Jagielski             ++aRangeBeg;
1186*b1cdbd2cSJim Jagielski         }
1187*b1cdbd2cSJim Jagielski         // find end of next used XF range
1188*b1cdbd2cSJim Jagielski         aRangeEnd = aRangeBeg;
1189*b1cdbd2cSJim Jagielski         nEndXclCol = nBegXclCol;
1190*b1cdbd2cSJim Jagielski         while( (aRangeEnd != aEnd) && (aRangeEnd->mnXFIndex != EXC_XF_NOTFOUND) )
1191*b1cdbd2cSJim Jagielski         {
1192*b1cdbd2cSJim Jagielski             nEndXclCol = nEndXclCol + aRangeEnd->mnCount;
1193*b1cdbd2cSJim Jagielski             ++aRangeEnd;
1194*b1cdbd2cSJim Jagielski         }
1195*b1cdbd2cSJim Jagielski 
1196*b1cdbd2cSJim Jagielski         // export this range as a record
1197*b1cdbd2cSJim Jagielski         if( aRangeBeg != aRangeEnd )
1198*b1cdbd2cSJim Jagielski         {
1199*b1cdbd2cSJim Jagielski             sal_uInt16 nRelColIdx = nBegXclCol - GetXclCol();
1200*b1cdbd2cSJim Jagielski             sal_Int32  nRelCol    = 0;
1201*b1cdbd2cSJim Jagielski             for( XclExpMultiXFIdDeq::const_iterator aIt = aRangeBeg; aIt != aRangeEnd; ++aIt )
1202*b1cdbd2cSJim Jagielski             {
1203*b1cdbd2cSJim Jagielski                 for( sal_uInt16 nIdx = 0; nIdx < aIt->mnCount; ++nIdx )
1204*b1cdbd2cSJim Jagielski                 {
1205*b1cdbd2cSJim Jagielski                     WriteXmlContents(
1206*b1cdbd2cSJim Jagielski                             rStrm,
1207*b1cdbd2cSJim Jagielski                             XclAddress( static_cast<sal_uInt16>(nBegXclCol + nRelCol), GetXclRow() ),
1208*b1cdbd2cSJim Jagielski                             aIt->mnXFIndex,
1209*b1cdbd2cSJim Jagielski                             nRelColIdx );
1210*b1cdbd2cSJim Jagielski                     ++nRelCol;
1211*b1cdbd2cSJim Jagielski                     ++nRelColIdx;
1212*b1cdbd2cSJim Jagielski                 }
1213*b1cdbd2cSJim Jagielski             }
1214*b1cdbd2cSJim Jagielski         }
1215*b1cdbd2cSJim Jagielski     }
1216*b1cdbd2cSJim Jagielski }
1217*b1cdbd2cSJim Jagielski 
GetCellCount() const1218*b1cdbd2cSJim Jagielski sal_uInt16 XclExpMultiCellBase::GetCellCount() const
1219*b1cdbd2cSJim Jagielski {
1220*b1cdbd2cSJim Jagielski     sal_uInt16 nCount = 0;
1221*b1cdbd2cSJim Jagielski     for( XclExpMultiXFIdDeq::const_iterator aIt = maXFIds.begin(), aEnd = maXFIds.end(); aIt != aEnd; ++aIt )
1222*b1cdbd2cSJim Jagielski         nCount = nCount + aIt->mnCount;
1223*b1cdbd2cSJim Jagielski     return nCount;
1224*b1cdbd2cSJim Jagielski }
1225*b1cdbd2cSJim Jagielski 
AppendXFId(const XclExpMultiXFId & rXFId)1226*b1cdbd2cSJim Jagielski void XclExpMultiCellBase::AppendXFId( const XclExpMultiXFId& rXFId )
1227*b1cdbd2cSJim Jagielski {
1228*b1cdbd2cSJim Jagielski     if( maXFIds.empty() || (maXFIds.back().mnXFId != rXFId.mnXFId) )
1229*b1cdbd2cSJim Jagielski         maXFIds.push_back( rXFId );
1230*b1cdbd2cSJim Jagielski     else
1231*b1cdbd2cSJim Jagielski         maXFIds.back().mnCount = maXFIds.back().mnCount + rXFId.mnCount;
1232*b1cdbd2cSJim Jagielski }
1233*b1cdbd2cSJim Jagielski 
AppendXFId(const XclExpRoot & rRoot,const ScPatternAttr * pPattern,sal_uInt16 nScript,sal_uInt32 nForcedXFId,sal_uInt16 nCount)1234*b1cdbd2cSJim Jagielski void XclExpMultiCellBase::AppendXFId( const XclExpRoot& rRoot,
1235*b1cdbd2cSJim Jagielski         const ScPatternAttr* pPattern, sal_uInt16 nScript, sal_uInt32 nForcedXFId, sal_uInt16 nCount )
1236*b1cdbd2cSJim Jagielski {
1237*b1cdbd2cSJim Jagielski     sal_uInt32 nXFId = (nForcedXFId == EXC_XFID_NOTFOUND) ?
1238*b1cdbd2cSJim Jagielski         rRoot.GetXFBuffer().Insert( pPattern, nScript ) : nForcedXFId;
1239*b1cdbd2cSJim Jagielski     AppendXFId( XclExpMultiXFId( nXFId, nCount ) );
1240*b1cdbd2cSJim Jagielski }
1241*b1cdbd2cSJim Jagielski 
TryMergeXFIds(const XclExpMultiCellBase & rCell)1242*b1cdbd2cSJim Jagielski bool XclExpMultiCellBase::TryMergeXFIds( const XclExpMultiCellBase& rCell )
1243*b1cdbd2cSJim Jagielski {
1244*b1cdbd2cSJim Jagielski     if( GetLastXclCol() + 1 == rCell.GetXclCol() )
1245*b1cdbd2cSJim Jagielski     {
1246*b1cdbd2cSJim Jagielski         maXFIds.insert( maXFIds.end(), rCell.maXFIds.begin(), rCell.maXFIds.end() );
1247*b1cdbd2cSJim Jagielski         return true;
1248*b1cdbd2cSJim Jagielski     }
1249*b1cdbd2cSJim Jagielski     return false;
1250*b1cdbd2cSJim Jagielski }
1251*b1cdbd2cSJim Jagielski 
GetXFIndexes(ScfUInt16Vec & rXFIndexes) const1252*b1cdbd2cSJim Jagielski void XclExpMultiCellBase::GetXFIndexes( ScfUInt16Vec& rXFIndexes ) const
1253*b1cdbd2cSJim Jagielski {
1254*b1cdbd2cSJim Jagielski     DBG_ASSERT( GetLastXclCol() < rXFIndexes.size(), "XclExpMultiCellBase::GetXFIndexes - vector too small" );
1255*b1cdbd2cSJim Jagielski     ScfUInt16Vec::iterator aDestIt = rXFIndexes.begin() + GetXclCol();
1256*b1cdbd2cSJim Jagielski     for( XclExpMultiXFIdDeq::const_iterator aIt = maXFIds.begin(), aEnd = maXFIds.end(); aIt != aEnd; ++aIt )
1257*b1cdbd2cSJim Jagielski     {
1258*b1cdbd2cSJim Jagielski         ::std::fill( aDestIt, aDestIt + aIt->mnCount, aIt->mnXFIndex );
1259*b1cdbd2cSJim Jagielski         aDestIt += aIt->mnCount;
1260*b1cdbd2cSJim Jagielski     }
1261*b1cdbd2cSJim Jagielski }
1262*b1cdbd2cSJim Jagielski 
RemoveUnusedXFIndexes(const ScfUInt16Vec & rXFIndexes)1263*b1cdbd2cSJim Jagielski void XclExpMultiCellBase::RemoveUnusedXFIndexes( const ScfUInt16Vec& rXFIndexes )
1264*b1cdbd2cSJim Jagielski {
1265*b1cdbd2cSJim Jagielski     // save last column before calling maXFIds.clear()
1266*b1cdbd2cSJim Jagielski     sal_uInt16 nLastXclCol = GetLastXclCol();
1267*b1cdbd2cSJim Jagielski     DBG_ASSERT( nLastXclCol < rXFIndexes.size(), "XclExpMultiCellBase::RemoveUnusedXFIndexes - XF index vector too small" );
1268*b1cdbd2cSJim Jagielski 
1269*b1cdbd2cSJim Jagielski     // build new XF index vector, containing passed XF indexes
1270*b1cdbd2cSJim Jagielski     maXFIds.clear();
1271*b1cdbd2cSJim Jagielski     XclExpMultiXFId aXFId( 0 );
1272*b1cdbd2cSJim Jagielski     for( ScfUInt16Vec::const_iterator aIt = rXFIndexes.begin() + GetXclCol(), aEnd = rXFIndexes.begin() + nLastXclCol + 1; aIt != aEnd; ++aIt )
1273*b1cdbd2cSJim Jagielski     {
1274*b1cdbd2cSJim Jagielski         // AppendXFId() tests XclExpXFIndex::mnXFId, set it too
1275*b1cdbd2cSJim Jagielski         aXFId.mnXFId = aXFId.mnXFIndex = *aIt;
1276*b1cdbd2cSJim Jagielski         AppendXFId( aXFId );
1277*b1cdbd2cSJim Jagielski     }
1278*b1cdbd2cSJim Jagielski 
1279*b1cdbd2cSJim Jagielski     // remove leading and trailing unused XF indexes
1280*b1cdbd2cSJim Jagielski     if( !maXFIds.empty() && (maXFIds.front().mnXFIndex == EXC_XF_NOTFOUND) )
1281*b1cdbd2cSJim Jagielski     {
1282*b1cdbd2cSJim Jagielski         SetXclCol( GetXclCol() + maXFIds.front().mnCount );
1283*b1cdbd2cSJim Jagielski         maXFIds.pop_front();
1284*b1cdbd2cSJim Jagielski     }
1285*b1cdbd2cSJim Jagielski     if( !maXFIds.empty() && (maXFIds.back().mnXFIndex == EXC_XF_NOTFOUND) )
1286*b1cdbd2cSJim Jagielski         maXFIds.pop_back();
1287*b1cdbd2cSJim Jagielski 
1288*b1cdbd2cSJim Jagielski     // The Save() function will skip all XF indexes equal to EXC_XF_NOTFOUND.
1289*b1cdbd2cSJim Jagielski }
1290*b1cdbd2cSJim Jagielski 
1291*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
1292*b1cdbd2cSJim Jagielski 
1293*b1cdbd2cSJim Jagielski IMPL_FIXEDMEMPOOL_NEWDEL( XclExpBlankCell, 256, 256 )
1294*b1cdbd2cSJim Jagielski 
XclExpBlankCell(const XclAddress & rXclPos,const XclExpMultiXFId & rXFId)1295*b1cdbd2cSJim Jagielski XclExpBlankCell::XclExpBlankCell( const XclAddress& rXclPos, const XclExpMultiXFId& rXFId ) :
1296*b1cdbd2cSJim Jagielski     XclExpMultiCellBase( EXC_ID3_BLANK, EXC_ID_MULBLANK, 0, rXclPos )
1297*b1cdbd2cSJim Jagielski {
1298*b1cdbd2cSJim Jagielski     DBG_ASSERT( rXFId.mnCount > 0, "XclExpBlankCell::XclExpBlankCell - invalid count" );
1299*b1cdbd2cSJim Jagielski     AppendXFId( rXFId );
1300*b1cdbd2cSJim Jagielski }
1301*b1cdbd2cSJim Jagielski 
XclExpBlankCell(const XclExpRoot & rRoot,const XclAddress & rXclPos,sal_uInt16 nLastXclCol,const ScPatternAttr * pPattern,sal_uInt32 nForcedXFId)1302*b1cdbd2cSJim Jagielski XclExpBlankCell::XclExpBlankCell(
1303*b1cdbd2cSJim Jagielski         const XclExpRoot& rRoot, const XclAddress& rXclPos, sal_uInt16 nLastXclCol,
1304*b1cdbd2cSJim Jagielski         const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId ) :
1305*b1cdbd2cSJim Jagielski     XclExpMultiCellBase( EXC_ID3_BLANK, EXC_ID_MULBLANK, 0, rXclPos )
1306*b1cdbd2cSJim Jagielski {
1307*b1cdbd2cSJim Jagielski     DBG_ASSERT( rXclPos.mnCol <= nLastXclCol, "XclExpBlankCell::XclExpBlankCell - invalid column range" );
1308*b1cdbd2cSJim Jagielski     // #i46627# use default script type instead of ApiScriptType::WEAK
1309*b1cdbd2cSJim Jagielski     AppendXFId( rRoot, pPattern, rRoot.GetDefApiScript(), nForcedXFId, nLastXclCol - rXclPos.mnCol + 1 );
1310*b1cdbd2cSJim Jagielski }
1311*b1cdbd2cSJim Jagielski 
TryMerge(const XclExpCellBase & rCell)1312*b1cdbd2cSJim Jagielski bool XclExpBlankCell::TryMerge( const XclExpCellBase& rCell )
1313*b1cdbd2cSJim Jagielski {
1314*b1cdbd2cSJim Jagielski     const XclExpBlankCell* pBlankCell = dynamic_cast< const XclExpBlankCell* >( &rCell );
1315*b1cdbd2cSJim Jagielski     return pBlankCell && TryMergeXFIds( *pBlankCell );
1316*b1cdbd2cSJim Jagielski }
1317*b1cdbd2cSJim Jagielski 
GetBlankXFIndexes(ScfUInt16Vec & rXFIndexes) const1318*b1cdbd2cSJim Jagielski void XclExpBlankCell::GetBlankXFIndexes( ScfUInt16Vec& rXFIndexes ) const
1319*b1cdbd2cSJim Jagielski {
1320*b1cdbd2cSJim Jagielski     GetXFIndexes( rXFIndexes );
1321*b1cdbd2cSJim Jagielski }
1322*b1cdbd2cSJim Jagielski 
RemoveUnusedBlankCells(const ScfUInt16Vec & rXFIndexes)1323*b1cdbd2cSJim Jagielski void XclExpBlankCell::RemoveUnusedBlankCells( const ScfUInt16Vec& rXFIndexes )
1324*b1cdbd2cSJim Jagielski {
1325*b1cdbd2cSJim Jagielski     RemoveUnusedXFIndexes( rXFIndexes );
1326*b1cdbd2cSJim Jagielski }
1327*b1cdbd2cSJim Jagielski 
WriteContents(XclExpStream &,sal_uInt16)1328*b1cdbd2cSJim Jagielski void XclExpBlankCell::WriteContents( XclExpStream& /*rStrm*/, sal_uInt16 /*nRelCol*/ )
1329*b1cdbd2cSJim Jagielski {
1330*b1cdbd2cSJim Jagielski }
1331*b1cdbd2cSJim Jagielski 
WriteXmlContents(XclExpXmlStream & rStrm,const XclAddress & rAddress,sal_uInt32 nXFId,sal_uInt16)1332*b1cdbd2cSJim Jagielski void XclExpBlankCell::WriteXmlContents( XclExpXmlStream& rStrm, const XclAddress& rAddress, sal_uInt32 nXFId, sal_uInt16 /* nRelCol */ )
1333*b1cdbd2cSJim Jagielski {
1334*b1cdbd2cSJim Jagielski     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1335*b1cdbd2cSJim Jagielski     rWorksheet->singleElement( XML_c,
1336*b1cdbd2cSJim Jagielski             XML_r,      XclXmlUtils::ToOString( rAddress ).getStr(),
1337*b1cdbd2cSJim Jagielski             XML_s,      lcl_GetStyleId( rStrm, nXFId ).getStr(),
1338*b1cdbd2cSJim Jagielski             FSEND );
1339*b1cdbd2cSJim Jagielski }
1340*b1cdbd2cSJim Jagielski 
1341*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
1342*b1cdbd2cSJim Jagielski 
1343*b1cdbd2cSJim Jagielski IMPL_FIXEDMEMPOOL_NEWDEL( XclExpRkCell, 256, 256 )
1344*b1cdbd2cSJim Jagielski 
XclExpRkCell(const XclExpRoot & rRoot,const XclAddress & rXclPos,const ScPatternAttr * pPattern,sal_uInt32 nForcedXFId,sal_Int32 nRkValue)1345*b1cdbd2cSJim Jagielski XclExpRkCell::XclExpRkCell(
1346*b1cdbd2cSJim Jagielski         const XclExpRoot& rRoot, const XclAddress& rXclPos,
1347*b1cdbd2cSJim Jagielski         const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId, sal_Int32 nRkValue ) :
1348*b1cdbd2cSJim Jagielski     XclExpMultiCellBase( EXC_ID_RK, EXC_ID_MULRK, 4, rXclPos )
1349*b1cdbd2cSJim Jagielski {
1350*b1cdbd2cSJim Jagielski     // #i41210# always use latin script for number cells - may look wrong for special number formats...
1351*b1cdbd2cSJim Jagielski     AppendXFId( rRoot, pPattern, ApiScriptType::LATIN, nForcedXFId );
1352*b1cdbd2cSJim Jagielski     maRkValues.push_back( nRkValue );
1353*b1cdbd2cSJim Jagielski }
1354*b1cdbd2cSJim Jagielski 
TryMerge(const XclExpCellBase & rCell)1355*b1cdbd2cSJim Jagielski bool XclExpRkCell::TryMerge( const XclExpCellBase& rCell )
1356*b1cdbd2cSJim Jagielski {
1357*b1cdbd2cSJim Jagielski     const XclExpRkCell* pRkCell = dynamic_cast< const XclExpRkCell* >( &rCell );
1358*b1cdbd2cSJim Jagielski     if( pRkCell && TryMergeXFIds( *pRkCell ) )
1359*b1cdbd2cSJim Jagielski     {
1360*b1cdbd2cSJim Jagielski         maRkValues.insert( maRkValues.end(), pRkCell->maRkValues.begin(), pRkCell->maRkValues.end() );
1361*b1cdbd2cSJim Jagielski         return true;
1362*b1cdbd2cSJim Jagielski     }
1363*b1cdbd2cSJim Jagielski     return false;
1364*b1cdbd2cSJim Jagielski }
1365*b1cdbd2cSJim Jagielski 
WriteXmlContents(XclExpXmlStream & rStrm,const XclAddress & rAddress,sal_uInt32 nXFId,sal_uInt16 nRelCol)1366*b1cdbd2cSJim Jagielski void XclExpRkCell::WriteXmlContents( XclExpXmlStream& rStrm, const XclAddress& rAddress, sal_uInt32 nXFId, sal_uInt16 nRelCol )
1367*b1cdbd2cSJim Jagielski {
1368*b1cdbd2cSJim Jagielski     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1369*b1cdbd2cSJim Jagielski     rWorksheet->startElement( XML_c,
1370*b1cdbd2cSJim Jagielski             XML_r,      XclXmlUtils::ToOString( rAddress ).getStr(),
1371*b1cdbd2cSJim Jagielski             XML_s,      lcl_GetStyleId( rStrm, nXFId ).getStr(),
1372*b1cdbd2cSJim Jagielski             XML_t,      "n",
1373*b1cdbd2cSJim Jagielski             // OOXTODO: XML_cm, XML_vm, XML_ph
1374*b1cdbd2cSJim Jagielski             FSEND );
1375*b1cdbd2cSJim Jagielski     rWorksheet->startElement( XML_v, FSEND );
1376*b1cdbd2cSJim Jagielski     rWorksheet->write( XclTools::GetDoubleFromRK( maRkValues[ nRelCol ] ) );
1377*b1cdbd2cSJim Jagielski     rWorksheet->endElement( XML_v );
1378*b1cdbd2cSJim Jagielski     rWorksheet->endElement( XML_c );
1379*b1cdbd2cSJim Jagielski }
1380*b1cdbd2cSJim Jagielski 
WriteContents(XclExpStream & rStrm,sal_uInt16 nRelCol)1381*b1cdbd2cSJim Jagielski void XclExpRkCell::WriteContents( XclExpStream& rStrm, sal_uInt16 nRelCol )
1382*b1cdbd2cSJim Jagielski {
1383*b1cdbd2cSJim Jagielski     DBG_ASSERT( nRelCol < maRkValues.size(), "XclExpRkCell::WriteContents - overflow error" );
1384*b1cdbd2cSJim Jagielski     rStrm << maRkValues[ nRelCol ];
1385*b1cdbd2cSJim Jagielski }
1386*b1cdbd2cSJim Jagielski 
1387*b1cdbd2cSJim Jagielski // ============================================================================
1388*b1cdbd2cSJim Jagielski // Rows and Columns
1389*b1cdbd2cSJim Jagielski // ============================================================================
1390*b1cdbd2cSJim Jagielski 
XclExpOutlineBuffer(const XclExpRoot & rRoot,bool bRows)1391*b1cdbd2cSJim Jagielski XclExpOutlineBuffer::XclExpOutlineBuffer( const XclExpRoot& rRoot, bool bRows ) :
1392*b1cdbd2cSJim Jagielski         mpScOLArray( 0 ),
1393*b1cdbd2cSJim Jagielski         maLevelInfos( SC_OL_MAXDEPTH ),
1394*b1cdbd2cSJim Jagielski         mnCurrLevel( 0 ),
1395*b1cdbd2cSJim Jagielski         mbCurrCollapse( false )
1396*b1cdbd2cSJim Jagielski {
1397*b1cdbd2cSJim Jagielski     if( const ScOutlineTable* pOutlineTable = rRoot.GetDoc().GetOutlineTable( rRoot.GetCurrScTab() ) )
1398*b1cdbd2cSJim Jagielski         mpScOLArray = bRows ? pOutlineTable->GetRowArray() : pOutlineTable->GetColArray();
1399*b1cdbd2cSJim Jagielski 
1400*b1cdbd2cSJim Jagielski     if( mpScOLArray )
1401*b1cdbd2cSJim Jagielski         for( sal_uInt16 nLevel = 0; nLevel < SC_OL_MAXDEPTH; ++nLevel )
1402*b1cdbd2cSJim Jagielski             if( ScOutlineEntry* pEntry = mpScOLArray->GetEntryByPos( nLevel, 0 ) )
1403*b1cdbd2cSJim Jagielski                 maLevelInfos[ nLevel ].mnScEndPos = pEntry->GetEnd();
1404*b1cdbd2cSJim Jagielski }
1405*b1cdbd2cSJim Jagielski 
UpdateColRow(SCCOLROW nScPos)1406*b1cdbd2cSJim Jagielski void XclExpOutlineBuffer::UpdateColRow( SCCOLROW nScPos )
1407*b1cdbd2cSJim Jagielski {
1408*b1cdbd2cSJim Jagielski     if( mpScOLArray )
1409*b1cdbd2cSJim Jagielski     {
1410*b1cdbd2cSJim Jagielski         // find open level index for passed position
1411*b1cdbd2cSJim Jagielski         sal_uInt16 nNewOpenScLevel = 0; // new open level (0-based Calc index)
1412*b1cdbd2cSJim Jagielski         sal_uInt8 nNewLevel = 0;    // new open level (1-based Excel index)
1413*b1cdbd2cSJim Jagielski 
1414*b1cdbd2cSJim Jagielski         if( mpScOLArray->FindTouchedLevel( nScPos, nScPos, nNewOpenScLevel ) )
1415*b1cdbd2cSJim Jagielski             nNewLevel = static_cast< sal_uInt8 >( nNewOpenScLevel + 1 );
1416*b1cdbd2cSJim Jagielski         // else nNewLevel keeps 0 to show that there are no groups
1417*b1cdbd2cSJim Jagielski 
1418*b1cdbd2cSJim Jagielski         mbCurrCollapse = false;
1419*b1cdbd2cSJim Jagielski         if( nNewLevel >= mnCurrLevel )
1420*b1cdbd2cSJim Jagielski         {
1421*b1cdbd2cSJim Jagielski             // new level(s) opened, or no level closed - update all level infos
1422*b1cdbd2cSJim Jagielski             for( sal_uInt16 nScLevel = 0; nScLevel <= nNewOpenScLevel; ++nScLevel )
1423*b1cdbd2cSJim Jagielski             {
1424*b1cdbd2cSJim Jagielski                 /*  In each level: check if a new group is started (there may be
1425*b1cdbd2cSJim Jagielski                     neighbored groups without gap - therefore check ALL levels). */
1426*b1cdbd2cSJim Jagielski                 if( maLevelInfos[ nScLevel ].mnScEndPos < nScPos )
1427*b1cdbd2cSJim Jagielski                 {
1428*b1cdbd2cSJim Jagielski                     if( ScOutlineEntry* pEntry = mpScOLArray->GetEntryByPos( nScLevel, nScPos ) )
1429*b1cdbd2cSJim Jagielski                     {
1430*b1cdbd2cSJim Jagielski                         maLevelInfos[ nScLevel ].mnScEndPos = pEntry->GetEnd();
1431*b1cdbd2cSJim Jagielski                         maLevelInfos[ nScLevel ].mbHidden = pEntry->IsHidden();
1432*b1cdbd2cSJim Jagielski                     }
1433*b1cdbd2cSJim Jagielski                 }
1434*b1cdbd2cSJim Jagielski             }
1435*b1cdbd2cSJim Jagielski         }
1436*b1cdbd2cSJim Jagielski         else
1437*b1cdbd2cSJim Jagielski         {
1438*b1cdbd2cSJim Jagielski             // level(s) closed - check if any of the closed levels are collapsed
1439*b1cdbd2cSJim Jagielski             // Calc uses 0-based level indexes
1440*b1cdbd2cSJim Jagielski             sal_uInt16 nOldOpenScLevel = mnCurrLevel - 1;
1441*b1cdbd2cSJim Jagielski             for( sal_uInt16 nScLevel = nNewOpenScLevel + 1; !mbCurrCollapse && (nScLevel <= nOldOpenScLevel); ++nScLevel )
1442*b1cdbd2cSJim Jagielski                 mbCurrCollapse = maLevelInfos[ nScLevel ].mbHidden;
1443*b1cdbd2cSJim Jagielski         }
1444*b1cdbd2cSJim Jagielski 
1445*b1cdbd2cSJim Jagielski         // cache new opened level
1446*b1cdbd2cSJim Jagielski         mnCurrLevel = nNewLevel;
1447*b1cdbd2cSJim Jagielski     }
1448*b1cdbd2cSJim Jagielski }
1449*b1cdbd2cSJim Jagielski 
1450*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
1451*b1cdbd2cSJim Jagielski 
XclExpGuts(const XclExpRoot & rRoot)1452*b1cdbd2cSJim Jagielski XclExpGuts::XclExpGuts( const XclExpRoot& rRoot ) :
1453*b1cdbd2cSJim Jagielski     XclExpRecord( EXC_ID_GUTS, 8 ),
1454*b1cdbd2cSJim Jagielski     mnColLevels( 0 ),
1455*b1cdbd2cSJim Jagielski     mnColWidth( 0 ),
1456*b1cdbd2cSJim Jagielski     mnRowLevels( 0 ),
1457*b1cdbd2cSJim Jagielski     mnRowWidth( 0 )
1458*b1cdbd2cSJim Jagielski {
1459*b1cdbd2cSJim Jagielski     if( const ScOutlineTable* pOutlineTable = rRoot.GetDoc().GetOutlineTable( rRoot.GetCurrScTab() ) )
1460*b1cdbd2cSJim Jagielski     {
1461*b1cdbd2cSJim Jagielski         // column outline groups
1462*b1cdbd2cSJim Jagielski         if( const ScOutlineArray* pColArray = pOutlineTable->GetColArray() )
1463*b1cdbd2cSJim Jagielski             mnColLevels = ulimit_cast< sal_uInt16 >( pColArray->GetDepth(), EXC_OUTLINE_MAX );
1464*b1cdbd2cSJim Jagielski         if( mnColLevels )
1465*b1cdbd2cSJim Jagielski         {
1466*b1cdbd2cSJim Jagielski             ++mnColLevels;
1467*b1cdbd2cSJim Jagielski             mnColWidth = 12 * mnColLevels + 5;
1468*b1cdbd2cSJim Jagielski         }
1469*b1cdbd2cSJim Jagielski 
1470*b1cdbd2cSJim Jagielski         // row outline groups
1471*b1cdbd2cSJim Jagielski         if( const ScOutlineArray* pRowArray = pOutlineTable->GetRowArray() )
1472*b1cdbd2cSJim Jagielski             mnRowLevels = ulimit_cast< sal_uInt16 >( pRowArray->GetDepth(), EXC_OUTLINE_MAX );
1473*b1cdbd2cSJim Jagielski         if( mnRowLevels )
1474*b1cdbd2cSJim Jagielski         {
1475*b1cdbd2cSJim Jagielski             ++mnRowLevels;
1476*b1cdbd2cSJim Jagielski             mnRowWidth = 12 * mnRowLevels + 5;
1477*b1cdbd2cSJim Jagielski         }
1478*b1cdbd2cSJim Jagielski     }
1479*b1cdbd2cSJim Jagielski }
1480*b1cdbd2cSJim Jagielski 
WriteBody(XclExpStream & rStrm)1481*b1cdbd2cSJim Jagielski void XclExpGuts::WriteBody( XclExpStream& rStrm )
1482*b1cdbd2cSJim Jagielski {
1483*b1cdbd2cSJim Jagielski     rStrm << mnRowWidth << mnColWidth << mnRowLevels << mnColLevels;
1484*b1cdbd2cSJim Jagielski }
1485*b1cdbd2cSJim Jagielski 
1486*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
1487*b1cdbd2cSJim Jagielski 
XclExpDimensions(const XclExpRoot & rRoot)1488*b1cdbd2cSJim Jagielski XclExpDimensions::XclExpDimensions( const XclExpRoot& rRoot ) :
1489*b1cdbd2cSJim Jagielski     mnFirstUsedXclRow( 0 ),
1490*b1cdbd2cSJim Jagielski     mnFirstFreeXclRow( 0 ),
1491*b1cdbd2cSJim Jagielski     mnFirstUsedXclCol( 0 ),
1492*b1cdbd2cSJim Jagielski     mnFirstFreeXclCol( 0 )
1493*b1cdbd2cSJim Jagielski {
1494*b1cdbd2cSJim Jagielski     switch( rRoot.GetBiff() )
1495*b1cdbd2cSJim Jagielski     {
1496*b1cdbd2cSJim Jagielski         case EXC_BIFF2: SetRecHeader( EXC_ID2_DIMENSIONS, 8 );  break;
1497*b1cdbd2cSJim Jagielski         case EXC_BIFF3:
1498*b1cdbd2cSJim Jagielski         case EXC_BIFF4:
1499*b1cdbd2cSJim Jagielski         case EXC_BIFF5: SetRecHeader( EXC_ID3_DIMENSIONS, 10 ); break;
1500*b1cdbd2cSJim Jagielski         case EXC_BIFF8: SetRecHeader( EXC_ID3_DIMENSIONS, 14 ); break;
1501*b1cdbd2cSJim Jagielski         default:        DBG_ERROR_BIFF();
1502*b1cdbd2cSJim Jagielski     }
1503*b1cdbd2cSJim Jagielski }
1504*b1cdbd2cSJim Jagielski 
SetDimensions(sal_uInt16 nFirstUsedXclCol,sal_uInt32 nFirstUsedXclRow,sal_uInt16 nFirstFreeXclCol,sal_uInt32 nFirstFreeXclRow)1505*b1cdbd2cSJim Jagielski void XclExpDimensions::SetDimensions(
1506*b1cdbd2cSJim Jagielski         sal_uInt16 nFirstUsedXclCol, sal_uInt32 nFirstUsedXclRow,
1507*b1cdbd2cSJim Jagielski         sal_uInt16 nFirstFreeXclCol, sal_uInt32 nFirstFreeXclRow )
1508*b1cdbd2cSJim Jagielski {
1509*b1cdbd2cSJim Jagielski     mnFirstUsedXclRow = nFirstUsedXclRow;
1510*b1cdbd2cSJim Jagielski     mnFirstFreeXclRow = nFirstFreeXclRow;
1511*b1cdbd2cSJim Jagielski     mnFirstUsedXclCol = nFirstUsedXclCol;
1512*b1cdbd2cSJim Jagielski     mnFirstFreeXclCol = nFirstFreeXclCol;
1513*b1cdbd2cSJim Jagielski }
1514*b1cdbd2cSJim Jagielski 
SaveXml(XclExpXmlStream & rStrm)1515*b1cdbd2cSJim Jagielski void XclExpDimensions::SaveXml( XclExpXmlStream& rStrm )
1516*b1cdbd2cSJim Jagielski {
1517*b1cdbd2cSJim Jagielski     ScRange aRange;
1518*b1cdbd2cSJim Jagielski     aRange.aStart.SetRow( (SCROW) mnFirstUsedXclRow );
1519*b1cdbd2cSJim Jagielski     aRange.aStart.SetCol( (SCCOL) mnFirstUsedXclCol );
1520*b1cdbd2cSJim Jagielski 
1521*b1cdbd2cSJim Jagielski     if( mnFirstFreeXclRow != mnFirstUsedXclRow && mnFirstFreeXclCol != mnFirstUsedXclCol )
1522*b1cdbd2cSJim Jagielski     {
1523*b1cdbd2cSJim Jagielski         aRange.aEnd.SetRow( (SCROW) (mnFirstFreeXclRow-1) );
1524*b1cdbd2cSJim Jagielski         aRange.aEnd.SetCol( (SCCOL) (mnFirstFreeXclCol-1) );
1525*b1cdbd2cSJim Jagielski     }
1526*b1cdbd2cSJim Jagielski 
1527*b1cdbd2cSJim Jagielski     rStrm.GetCurrentStream()->singleElement( XML_dimension,
1528*b1cdbd2cSJim Jagielski             XML_ref, XclXmlUtils::ToOString( aRange ).getStr(),
1529*b1cdbd2cSJim Jagielski             FSEND );
1530*b1cdbd2cSJim Jagielski }
1531*b1cdbd2cSJim Jagielski 
WriteBody(XclExpStream & rStrm)1532*b1cdbd2cSJim Jagielski void XclExpDimensions::WriteBody( XclExpStream& rStrm )
1533*b1cdbd2cSJim Jagielski {
1534*b1cdbd2cSJim Jagielski     XclBiff eBiff = rStrm.GetRoot().GetBiff();
1535*b1cdbd2cSJim Jagielski     if( eBiff == EXC_BIFF8 )
1536*b1cdbd2cSJim Jagielski         rStrm << mnFirstUsedXclRow << mnFirstFreeXclRow;
1537*b1cdbd2cSJim Jagielski     else
1538*b1cdbd2cSJim Jagielski         rStrm << static_cast< sal_uInt16 >( mnFirstUsedXclRow ) << static_cast< sal_uInt16 >( mnFirstFreeXclRow );
1539*b1cdbd2cSJim Jagielski     rStrm << mnFirstUsedXclCol << mnFirstFreeXclCol;
1540*b1cdbd2cSJim Jagielski     if( eBiff >= EXC_BIFF3 )
1541*b1cdbd2cSJim Jagielski         rStrm << sal_uInt16( 0 );
1542*b1cdbd2cSJim Jagielski }
1543*b1cdbd2cSJim Jagielski 
1544*b1cdbd2cSJim Jagielski // ============================================================================
1545*b1cdbd2cSJim Jagielski 
1546*b1cdbd2cSJim Jagielski namespace {
1547*b1cdbd2cSJim Jagielski 
lclGetCorrectedColWidth(const XclExpRoot & rRoot,sal_uInt16 nXclColWidth)1548*b1cdbd2cSJim Jagielski double lclGetCorrectedColWidth( const XclExpRoot& rRoot, sal_uInt16 nXclColWidth )
1549*b1cdbd2cSJim Jagielski {
1550*b1cdbd2cSJim Jagielski     long nFontHt = rRoot.GetFontBuffer().GetAppFontData().mnHeight;
1551*b1cdbd2cSJim Jagielski     return nXclColWidth - XclTools::GetXclDefColWidthCorrection( nFontHt );
1552*b1cdbd2cSJim Jagielski }
1553*b1cdbd2cSJim Jagielski 
1554*b1cdbd2cSJim Jagielski } // namespace
1555*b1cdbd2cSJim Jagielski 
1556*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
1557*b1cdbd2cSJim Jagielski 
XclExpDefcolwidth(const XclExpRoot & rRoot)1558*b1cdbd2cSJim Jagielski XclExpDefcolwidth::XclExpDefcolwidth( const XclExpRoot& rRoot ) :
1559*b1cdbd2cSJim Jagielski     XclExpUInt16Record( EXC_ID_DEFCOLWIDTH, EXC_DEFCOLWIDTH_DEF ),
1560*b1cdbd2cSJim Jagielski     XclExpRoot( rRoot )
1561*b1cdbd2cSJim Jagielski {
1562*b1cdbd2cSJim Jagielski }
1563*b1cdbd2cSJim Jagielski 
IsDefWidth(sal_uInt16 nXclColWidth) const1564*b1cdbd2cSJim Jagielski bool XclExpDefcolwidth::IsDefWidth( sal_uInt16 nXclColWidth ) const
1565*b1cdbd2cSJim Jagielski {
1566*b1cdbd2cSJim Jagielski     double fNewColWidth = lclGetCorrectedColWidth( GetRoot(), nXclColWidth );
1567*b1cdbd2cSJim Jagielski     // exactly matched, if difference is less than 1/16 of a character to the left or to the right
1568*b1cdbd2cSJim Jagielski     return Abs( static_cast< long >( GetValue() * 256.0 - fNewColWidth + 0.5 ) ) < 16;
1569*b1cdbd2cSJim Jagielski }
1570*b1cdbd2cSJim Jagielski 
SetDefWidth(sal_uInt16 nXclColWidth)1571*b1cdbd2cSJim Jagielski void XclExpDefcolwidth::SetDefWidth( sal_uInt16 nXclColWidth )
1572*b1cdbd2cSJim Jagielski {
1573*b1cdbd2cSJim Jagielski     double fNewColWidth = lclGetCorrectedColWidth( GetRoot(), nXclColWidth );
1574*b1cdbd2cSJim Jagielski     SetValue( limit_cast< sal_uInt16 >( fNewColWidth / 256.0 + 0.5 ) );
1575*b1cdbd2cSJim Jagielski }
1576*b1cdbd2cSJim Jagielski 
1577*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
1578*b1cdbd2cSJim Jagielski 
XclExpColinfo(const XclExpRoot & rRoot,SCCOL nScCol,SCROW nLastScRow,XclExpColOutlineBuffer & rOutlineBfr)1579*b1cdbd2cSJim Jagielski XclExpColinfo::XclExpColinfo( const XclExpRoot& rRoot,
1580*b1cdbd2cSJim Jagielski         SCCOL nScCol, SCROW nLastScRow, XclExpColOutlineBuffer& rOutlineBfr ) :
1581*b1cdbd2cSJim Jagielski     XclExpRecord( EXC_ID_COLINFO, 12 ),
1582*b1cdbd2cSJim Jagielski     XclExpRoot( rRoot ),
1583*b1cdbd2cSJim Jagielski     mnWidth( 0 ),
1584*b1cdbd2cSJim Jagielski     mnFlags( 0 ),
1585*b1cdbd2cSJim Jagielski     mnFirstXclCol( static_cast< sal_uInt16 >( nScCol ) ),
1586*b1cdbd2cSJim Jagielski     mnLastXclCol( static_cast< sal_uInt16 >( nScCol ) )
1587*b1cdbd2cSJim Jagielski {
1588*b1cdbd2cSJim Jagielski     ScDocument& rDoc = GetDoc();
1589*b1cdbd2cSJim Jagielski     SCTAB nScTab = GetCurrScTab();
1590*b1cdbd2cSJim Jagielski 
1591*b1cdbd2cSJim Jagielski     // column default format
1592*b1cdbd2cSJim Jagielski     maXFId.mnXFId = GetXFBuffer().Insert(
1593*b1cdbd2cSJim Jagielski         rDoc.GetMostUsedPattern( nScCol, 0, nLastScRow, nScTab ), GetDefApiScript() );
1594*b1cdbd2cSJim Jagielski 
1595*b1cdbd2cSJim Jagielski     // column width
1596*b1cdbd2cSJim Jagielski     sal_uInt16 nScWidth = rDoc.GetColWidth( nScCol, nScTab );
1597*b1cdbd2cSJim Jagielski     mnWidth = XclTools::GetXclColumnWidth( nScWidth, GetCharWidth() );
1598*b1cdbd2cSJim Jagielski 
1599*b1cdbd2cSJim Jagielski     // column flags
1600*b1cdbd2cSJim Jagielski     ::set_flag( mnFlags, EXC_COLINFO_HIDDEN, rDoc.ColHidden(nScCol, nScTab) );
1601*b1cdbd2cSJim Jagielski 
1602*b1cdbd2cSJim Jagielski     // outline data
1603*b1cdbd2cSJim Jagielski     rOutlineBfr.Update( nScCol );
1604*b1cdbd2cSJim Jagielski     ::set_flag( mnFlags, EXC_COLINFO_COLLAPSED, rOutlineBfr.IsCollapsed() );
1605*b1cdbd2cSJim Jagielski     ::insert_value( mnFlags, rOutlineBfr.GetLevel(), 8, 3 );
1606*b1cdbd2cSJim Jagielski }
1607*b1cdbd2cSJim Jagielski 
ConvertXFIndexes()1608*b1cdbd2cSJim Jagielski sal_uInt16 XclExpColinfo::ConvertXFIndexes()
1609*b1cdbd2cSJim Jagielski {
1610*b1cdbd2cSJim Jagielski     maXFId.ConvertXFIndex( GetRoot() );
1611*b1cdbd2cSJim Jagielski     return maXFId.mnXFIndex;
1612*b1cdbd2cSJim Jagielski }
1613*b1cdbd2cSJim Jagielski 
IsDefault(const XclExpDefcolwidth & rDefColWidth) const1614*b1cdbd2cSJim Jagielski bool XclExpColinfo::IsDefault( const XclExpDefcolwidth& rDefColWidth ) const
1615*b1cdbd2cSJim Jagielski {
1616*b1cdbd2cSJim Jagielski     return (maXFId.mnXFIndex == EXC_XF_DEFAULTCELL) && (mnFlags == 0) && rDefColWidth.IsDefWidth( mnWidth );
1617*b1cdbd2cSJim Jagielski }
1618*b1cdbd2cSJim Jagielski 
TryMerge(const XclExpColinfo & rColInfo)1619*b1cdbd2cSJim Jagielski bool XclExpColinfo::TryMerge( const XclExpColinfo& rColInfo )
1620*b1cdbd2cSJim Jagielski {
1621*b1cdbd2cSJim Jagielski     if( (maXFId.mnXFIndex == rColInfo.maXFId.mnXFIndex) &&
1622*b1cdbd2cSJim Jagielski         (mnWidth == rColInfo.mnWidth) &&
1623*b1cdbd2cSJim Jagielski         (mnFlags == rColInfo.mnFlags) &&
1624*b1cdbd2cSJim Jagielski         (mnLastXclCol + 1 == rColInfo.mnFirstXclCol) )
1625*b1cdbd2cSJim Jagielski     {
1626*b1cdbd2cSJim Jagielski         mnLastXclCol = rColInfo.mnLastXclCol;
1627*b1cdbd2cSJim Jagielski         return true;
1628*b1cdbd2cSJim Jagielski     }
1629*b1cdbd2cSJim Jagielski     return false;
1630*b1cdbd2cSJim Jagielski }
1631*b1cdbd2cSJim Jagielski 
WriteBody(XclExpStream & rStrm)1632*b1cdbd2cSJim Jagielski void XclExpColinfo::WriteBody( XclExpStream& rStrm )
1633*b1cdbd2cSJim Jagielski {
1634*b1cdbd2cSJim Jagielski     // if last column is equal to last possible column, Excel adds one more
1635*b1cdbd2cSJim Jagielski     sal_uInt16 nLastXclCol = mnLastXclCol;
1636*b1cdbd2cSJim Jagielski     if( nLastXclCol == static_cast< sal_uInt16 >( rStrm.GetRoot().GetMaxPos().Col() ) )
1637*b1cdbd2cSJim Jagielski         ++nLastXclCol;
1638*b1cdbd2cSJim Jagielski 
1639*b1cdbd2cSJim Jagielski     rStrm   << mnFirstXclCol
1640*b1cdbd2cSJim Jagielski             << nLastXclCol
1641*b1cdbd2cSJim Jagielski             << mnWidth
1642*b1cdbd2cSJim Jagielski             << maXFId.mnXFIndex
1643*b1cdbd2cSJim Jagielski             << mnFlags
1644*b1cdbd2cSJim Jagielski             << sal_uInt16( 0 );
1645*b1cdbd2cSJim Jagielski }
1646*b1cdbd2cSJim Jagielski 
SaveXml(XclExpXmlStream & rStrm)1647*b1cdbd2cSJim Jagielski void XclExpColinfo::SaveXml( XclExpXmlStream& rStrm )
1648*b1cdbd2cSJim Jagielski {
1649*b1cdbd2cSJim Jagielski     // if last column is equal to last possible column, Excel adds one more
1650*b1cdbd2cSJim Jagielski     sal_uInt16 nLastXclCol = mnLastXclCol;
1651*b1cdbd2cSJim Jagielski     if( nLastXclCol == static_cast< sal_uInt16 >( rStrm.GetRoot().GetMaxPos().Col() ) )
1652*b1cdbd2cSJim Jagielski         ++nLastXclCol;
1653*b1cdbd2cSJim Jagielski 
1654*b1cdbd2cSJim Jagielski     rStrm.GetCurrentStream()->singleElement( XML_col,
1655*b1cdbd2cSJim Jagielski             // OOXTODO: XML_bestFit,
1656*b1cdbd2cSJim Jagielski             XML_collapsed,      XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_COLINFO_COLLAPSED ) ),
1657*b1cdbd2cSJim Jagielski             // OOXTODO: XML_customWidth,
1658*b1cdbd2cSJim Jagielski             XML_hidden,         XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_COLINFO_HIDDEN ) ),
1659*b1cdbd2cSJim Jagielski             XML_max,            OString::valueOf( (sal_Int32) (nLastXclCol+1) ).getStr(),
1660*b1cdbd2cSJim Jagielski             XML_min,            OString::valueOf( (sal_Int32) (mnFirstXclCol+1) ).getStr(),
1661*b1cdbd2cSJim Jagielski             // OOXTODO: XML_outlineLevel,
1662*b1cdbd2cSJim Jagielski             // OOXTODO: XML_phonetic,
1663*b1cdbd2cSJim Jagielski             XML_style,          lcl_GetStyleId( rStrm, maXFId.mnXFIndex ).getStr(),
1664*b1cdbd2cSJim Jagielski             XML_width,          OString::valueOf( (double) (mnWidth / 255.0) ).getStr(),
1665*b1cdbd2cSJim Jagielski             FSEND );
1666*b1cdbd2cSJim Jagielski }
1667*b1cdbd2cSJim Jagielski 
1668*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
1669*b1cdbd2cSJim Jagielski 
XclExpColinfoBuffer(const XclExpRoot & rRoot)1670*b1cdbd2cSJim Jagielski XclExpColinfoBuffer::XclExpColinfoBuffer( const XclExpRoot& rRoot ) :
1671*b1cdbd2cSJim Jagielski     XclExpRoot( rRoot ),
1672*b1cdbd2cSJim Jagielski     maDefcolwidth( rRoot ),
1673*b1cdbd2cSJim Jagielski     maOutlineBfr( rRoot )
1674*b1cdbd2cSJim Jagielski {
1675*b1cdbd2cSJim Jagielski }
1676*b1cdbd2cSJim Jagielski 
Initialize(SCROW nLastScRow)1677*b1cdbd2cSJim Jagielski void XclExpColinfoBuffer::Initialize( SCROW nLastScRow )
1678*b1cdbd2cSJim Jagielski {
1679*b1cdbd2cSJim Jagielski 
1680*b1cdbd2cSJim Jagielski     for( sal_uInt16 nScCol = 0, nLastScCol = GetMaxPos().Col(); nScCol <= nLastScCol; ++nScCol )
1681*b1cdbd2cSJim Jagielski         maColInfos.AppendNewRecord( new XclExpColinfo( GetRoot(), nScCol, nLastScRow, maOutlineBfr ) );
1682*b1cdbd2cSJim Jagielski }
1683*b1cdbd2cSJim Jagielski 
Finalize(ScfUInt16Vec & rXFIndexes)1684*b1cdbd2cSJim Jagielski void XclExpColinfoBuffer::Finalize( ScfUInt16Vec& rXFIndexes )
1685*b1cdbd2cSJim Jagielski {
1686*b1cdbd2cSJim Jagielski     rXFIndexes.clear();
1687*b1cdbd2cSJim Jagielski     rXFIndexes.reserve( maColInfos.GetSize() );
1688*b1cdbd2cSJim Jagielski 
1689*b1cdbd2cSJim Jagielski     size_t nPos, nSize;
1690*b1cdbd2cSJim Jagielski 
1691*b1cdbd2cSJim Jagielski     // do not cache the record list size, it may change in the loop
1692*b1cdbd2cSJim Jagielski     for( nPos = 0; nPos < maColInfos.GetSize(); ++nPos )
1693*b1cdbd2cSJim Jagielski     {
1694*b1cdbd2cSJim Jagielski         XclExpColinfoRef xRec = maColInfos.GetRecord( nPos );
1695*b1cdbd2cSJim Jagielski         xRec->ConvertXFIndexes();
1696*b1cdbd2cSJim Jagielski 
1697*b1cdbd2cSJim Jagielski         // try to merge with previous record
1698*b1cdbd2cSJim Jagielski         if( nPos > 0 )
1699*b1cdbd2cSJim Jagielski         {
1700*b1cdbd2cSJim Jagielski             XclExpColinfoRef xPrevRec = maColInfos.GetRecord( nPos - 1 );
1701*b1cdbd2cSJim Jagielski             if( xPrevRec->TryMerge( *xRec ) )
1702*b1cdbd2cSJim Jagielski                 // adjust nPos to get the next COLINFO record at the same position
1703*b1cdbd2cSJim Jagielski                 maColInfos.RemoveRecord( nPos-- );
1704*b1cdbd2cSJim Jagielski         }
1705*b1cdbd2cSJim Jagielski     }
1706*b1cdbd2cSJim Jagielski 
1707*b1cdbd2cSJim Jagielski     // put XF indexes into passed vector, collect use count of all different widths
1708*b1cdbd2cSJim Jagielski     typedef ::std::map< sal_uInt16, sal_uInt16 > XclExpWidthMap;
1709*b1cdbd2cSJim Jagielski     XclExpWidthMap aWidthMap;
1710*b1cdbd2cSJim Jagielski     sal_uInt16 nMaxColCount = 0;
1711*b1cdbd2cSJim Jagielski     sal_uInt16 nMaxUsedWidth = 0;
1712*b1cdbd2cSJim Jagielski     for( nPos = 0, nSize = maColInfos.GetSize(); nPos < nSize; ++nPos )
1713*b1cdbd2cSJim Jagielski     {
1714*b1cdbd2cSJim Jagielski         XclExpColinfoRef xRec = maColInfos.GetRecord( nPos );
1715*b1cdbd2cSJim Jagielski         sal_uInt16 nColCount = xRec->GetColCount();
1716*b1cdbd2cSJim Jagielski 
1717*b1cdbd2cSJim Jagielski         // add XF index to passed vector
1718*b1cdbd2cSJim Jagielski         rXFIndexes.resize( rXFIndexes.size() + nColCount, xRec->GetXFIndex() );
1719*b1cdbd2cSJim Jagielski 
1720*b1cdbd2cSJim Jagielski         // collect use count of column width
1721*b1cdbd2cSJim Jagielski         sal_uInt16 nWidth = xRec->GetColWidth();
1722*b1cdbd2cSJim Jagielski         sal_uInt16& rnMapCount = aWidthMap[ nWidth ];
1723*b1cdbd2cSJim Jagielski         rnMapCount = rnMapCount + nColCount;
1724*b1cdbd2cSJim Jagielski         if( rnMapCount > nMaxColCount )
1725*b1cdbd2cSJim Jagielski         {
1726*b1cdbd2cSJim Jagielski             nMaxColCount = rnMapCount;
1727*b1cdbd2cSJim Jagielski             nMaxUsedWidth = nWidth;
1728*b1cdbd2cSJim Jagielski         }
1729*b1cdbd2cSJim Jagielski     }
1730*b1cdbd2cSJim Jagielski     maDefcolwidth.SetDefWidth( nMaxUsedWidth );
1731*b1cdbd2cSJim Jagielski 
1732*b1cdbd2cSJim Jagielski     // remove all default COLINFO records
1733*b1cdbd2cSJim Jagielski     nPos = 0;
1734*b1cdbd2cSJim Jagielski     while( nPos < maColInfos.GetSize() )
1735*b1cdbd2cSJim Jagielski     {
1736*b1cdbd2cSJim Jagielski         XclExpColinfoRef xRec = maColInfos.GetRecord( nPos );
1737*b1cdbd2cSJim Jagielski         if( xRec->IsDefault( maDefcolwidth ) )
1738*b1cdbd2cSJim Jagielski             maColInfos.RemoveRecord( nPos );
1739*b1cdbd2cSJim Jagielski         else
1740*b1cdbd2cSJim Jagielski             ++nPos;
1741*b1cdbd2cSJim Jagielski     }
1742*b1cdbd2cSJim Jagielski }
1743*b1cdbd2cSJim Jagielski 
Save(XclExpStream & rStrm)1744*b1cdbd2cSJim Jagielski void XclExpColinfoBuffer::Save( XclExpStream& rStrm )
1745*b1cdbd2cSJim Jagielski {
1746*b1cdbd2cSJim Jagielski     // DEFCOLWIDTH
1747*b1cdbd2cSJim Jagielski     maDefcolwidth.Save( rStrm );
1748*b1cdbd2cSJim Jagielski     // COLINFO records
1749*b1cdbd2cSJim Jagielski     maColInfos.Save( rStrm );
1750*b1cdbd2cSJim Jagielski }
1751*b1cdbd2cSJim Jagielski 
SaveXml(XclExpXmlStream & rStrm)1752*b1cdbd2cSJim Jagielski void XclExpColinfoBuffer::SaveXml( XclExpXmlStream& rStrm )
1753*b1cdbd2cSJim Jagielski {
1754*b1cdbd2cSJim Jagielski     if( maColInfos.IsEmpty() )
1755*b1cdbd2cSJim Jagielski         return;
1756*b1cdbd2cSJim Jagielski 
1757*b1cdbd2cSJim Jagielski     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1758*b1cdbd2cSJim Jagielski     rWorksheet->startElement( XML_cols,
1759*b1cdbd2cSJim Jagielski             FSEND );
1760*b1cdbd2cSJim Jagielski     maColInfos.SaveXml( rStrm );
1761*b1cdbd2cSJim Jagielski     rWorksheet->endElement( XML_cols );
1762*b1cdbd2cSJim Jagielski }
1763*b1cdbd2cSJim Jagielski 
1764*b1cdbd2cSJim Jagielski // ============================================================================
1765*b1cdbd2cSJim Jagielski 
XclExpDefaultRowData()1766*b1cdbd2cSJim Jagielski XclExpDefaultRowData::XclExpDefaultRowData() :
1767*b1cdbd2cSJim Jagielski     mnFlags( EXC_DEFROW_DEFAULTFLAGS ),
1768*b1cdbd2cSJim Jagielski     mnHeight( EXC_DEFROW_DEFAULTHEIGHT )
1769*b1cdbd2cSJim Jagielski {
1770*b1cdbd2cSJim Jagielski }
1771*b1cdbd2cSJim Jagielski 
XclExpDefaultRowData(const XclExpRow & rRow)1772*b1cdbd2cSJim Jagielski XclExpDefaultRowData::XclExpDefaultRowData( const XclExpRow& rRow ) :
1773*b1cdbd2cSJim Jagielski     mnFlags( EXC_DEFROW_DEFAULTFLAGS ),
1774*b1cdbd2cSJim Jagielski     mnHeight( rRow.GetHeight() )
1775*b1cdbd2cSJim Jagielski {
1776*b1cdbd2cSJim Jagielski     ::set_flag( mnFlags, EXC_DEFROW_HIDDEN, rRow.IsHidden() );
1777*b1cdbd2cSJim Jagielski     ::set_flag( mnFlags, EXC_DEFROW_UNSYNCED, rRow.IsUnsynced() );
1778*b1cdbd2cSJim Jagielski }
1779*b1cdbd2cSJim Jagielski 
operator <(const XclExpDefaultRowData & rLeft,const XclExpDefaultRowData & rRight)1780*b1cdbd2cSJim Jagielski bool operator<( const XclExpDefaultRowData& rLeft, const XclExpDefaultRowData& rRight )
1781*b1cdbd2cSJim Jagielski {
1782*b1cdbd2cSJim Jagielski     return (rLeft.mnHeight < rRight.mnHeight) ||
1783*b1cdbd2cSJim Jagielski         ((rLeft.mnHeight == rRight.mnHeight) && (rLeft.mnFlags < rRight.mnFlags));
1784*b1cdbd2cSJim Jagielski }
1785*b1cdbd2cSJim Jagielski 
1786*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
1787*b1cdbd2cSJim Jagielski 
XclExpDefrowheight()1788*b1cdbd2cSJim Jagielski XclExpDefrowheight::XclExpDefrowheight() :
1789*b1cdbd2cSJim Jagielski     XclExpRecord( EXC_ID3_DEFROWHEIGHT, 4 )
1790*b1cdbd2cSJim Jagielski {
1791*b1cdbd2cSJim Jagielski }
1792*b1cdbd2cSJim Jagielski 
SetDefaultData(const XclExpDefaultRowData & rDefData)1793*b1cdbd2cSJim Jagielski void XclExpDefrowheight::SetDefaultData( const XclExpDefaultRowData& rDefData )
1794*b1cdbd2cSJim Jagielski {
1795*b1cdbd2cSJim Jagielski     maDefData = rDefData;
1796*b1cdbd2cSJim Jagielski }
1797*b1cdbd2cSJim Jagielski 
WriteBody(XclExpStream & rStrm)1798*b1cdbd2cSJim Jagielski void XclExpDefrowheight::WriteBody( XclExpStream& rStrm )
1799*b1cdbd2cSJim Jagielski {
1800*b1cdbd2cSJim Jagielski     DBG_ASSERT_BIFF( rStrm.GetRoot().GetBiff() >= EXC_BIFF3 );
1801*b1cdbd2cSJim Jagielski     rStrm << maDefData.mnFlags << maDefData.mnHeight;
1802*b1cdbd2cSJim Jagielski }
1803*b1cdbd2cSJim Jagielski 
1804*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
1805*b1cdbd2cSJim Jagielski 
XclExpRow(const XclExpRoot & rRoot,sal_uInt16 nXclRow,XclExpRowOutlineBuffer & rOutlineBfr,bool bAlwaysEmpty)1806*b1cdbd2cSJim Jagielski XclExpRow::XclExpRow( const XclExpRoot& rRoot, sal_uInt16 nXclRow,
1807*b1cdbd2cSJim Jagielski         XclExpRowOutlineBuffer& rOutlineBfr, bool bAlwaysEmpty ) :
1808*b1cdbd2cSJim Jagielski     XclExpRecord( EXC_ID3_ROW, 16 ),
1809*b1cdbd2cSJim Jagielski     XclExpRoot( rRoot ),
1810*b1cdbd2cSJim Jagielski     mnXclRow( nXclRow ),
1811*b1cdbd2cSJim Jagielski     mnHeight( 0 ),
1812*b1cdbd2cSJim Jagielski     mnFlags( EXC_ROW_DEFAULTFLAGS ),
1813*b1cdbd2cSJim Jagielski     mnXFIndex( EXC_XF_DEFAULTCELL ),
1814*b1cdbd2cSJim Jagielski     mnOutlineLevel( 0 ),
1815*b1cdbd2cSJim Jagielski     mbAlwaysEmpty( bAlwaysEmpty ),
1816*b1cdbd2cSJim Jagielski     mbEnabled( true )
1817*b1cdbd2cSJim Jagielski {
1818*b1cdbd2cSJim Jagielski     SCTAB nScTab = GetCurrScTab();
1819*b1cdbd2cSJim Jagielski     SCROW nScRow = static_cast< SCROW >( mnXclRow );
1820*b1cdbd2cSJim Jagielski 
1821*b1cdbd2cSJim Jagielski     // *** Row flags *** ------------------------------------------------------
1822*b1cdbd2cSJim Jagielski 
1823*b1cdbd2cSJim Jagielski     sal_uInt8 nRowFlags = GetDoc().GetRowFlags( nScRow, nScTab );
1824*b1cdbd2cSJim Jagielski     bool bUserHeight = ::get_flag< sal_uInt8 >( nRowFlags, CR_MANUALSIZE );
1825*b1cdbd2cSJim Jagielski     bool bHidden = GetDoc().RowHidden(nScRow, nScTab);
1826*b1cdbd2cSJim Jagielski     ::set_flag( mnFlags, EXC_ROW_UNSYNCED, bUserHeight );
1827*b1cdbd2cSJim Jagielski     ::set_flag( mnFlags, EXC_ROW_HIDDEN, bHidden );
1828*b1cdbd2cSJim Jagielski 
1829*b1cdbd2cSJim Jagielski     // *** Row height *** -----------------------------------------------------
1830*b1cdbd2cSJim Jagielski 
1831*b1cdbd2cSJim Jagielski     if (bUserHeight)
1832*b1cdbd2cSJim Jagielski         mnHeight = GetDoc().GetRowHeight(nScRow, nScTab, false);
1833*b1cdbd2cSJim Jagielski     else
1834*b1cdbd2cSJim Jagielski         mnHeight = EXC_ROW_DEFAULTHEIGHT;
1835*b1cdbd2cSJim Jagielski 
1836*b1cdbd2cSJim Jagielski     // #76250# not usable in Applix
1837*b1cdbd2cSJim Jagielski //    ::set_flag( mnHeight, EXC_ROW_FLAGDEFHEIGHT, !bUserHeight );
1838*b1cdbd2cSJim Jagielski 
1839*b1cdbd2cSJim Jagielski     // *** Outline data *** ---------------------------------------------------
1840*b1cdbd2cSJim Jagielski 
1841*b1cdbd2cSJim Jagielski     rOutlineBfr.Update( nScRow );
1842*b1cdbd2cSJim Jagielski     ::set_flag( mnFlags, EXC_ROW_COLLAPSED, rOutlineBfr.IsCollapsed() );
1843*b1cdbd2cSJim Jagielski     ::insert_value( mnFlags, rOutlineBfr.GetLevel(), 0, 3 );
1844*b1cdbd2cSJim Jagielski     mnOutlineLevel = rOutlineBfr.GetLevel();
1845*b1cdbd2cSJim Jagielski 
1846*b1cdbd2cSJim Jagielski     // *** Progress bar *** ---------------------------------------------------
1847*b1cdbd2cSJim Jagielski 
1848*b1cdbd2cSJim Jagielski     XclExpProgressBar& rProgress = GetProgressBar();
1849*b1cdbd2cSJim Jagielski     rProgress.IncRowRecordCount();
1850*b1cdbd2cSJim Jagielski     rProgress.Progress();
1851*b1cdbd2cSJim Jagielski }
1852*b1cdbd2cSJim Jagielski 
AppendCell(XclExpCellRef xCell,bool bIsMergedBase)1853*b1cdbd2cSJim Jagielski void XclExpRow::AppendCell( XclExpCellRef xCell, bool bIsMergedBase )
1854*b1cdbd2cSJim Jagielski {
1855*b1cdbd2cSJim Jagielski     DBG_ASSERT( !mbAlwaysEmpty, "XclExpRow::AppendCell - row is marked to be always empty" );
1856*b1cdbd2cSJim Jagielski     // try to merge with last existing cell
1857*b1cdbd2cSJim Jagielski     InsertCell( xCell, maCellList.GetSize(), bIsMergedBase );
1858*b1cdbd2cSJim Jagielski }
1859*b1cdbd2cSJim Jagielski 
Finalize(const ScfUInt16Vec & rColXFIndexes)1860*b1cdbd2cSJim Jagielski void XclExpRow::Finalize( const ScfUInt16Vec& rColXFIndexes )
1861*b1cdbd2cSJim Jagielski {
1862*b1cdbd2cSJim Jagielski     size_t nPos, nSize;
1863*b1cdbd2cSJim Jagielski 
1864*b1cdbd2cSJim Jagielski     // *** Convert XF identifiers *** -----------------------------------------
1865*b1cdbd2cSJim Jagielski 
1866*b1cdbd2cSJim Jagielski     // additionally collect the blank XF indexes
1867*b1cdbd2cSJim Jagielski     size_t nColCount = GetMaxPos().Col() + 1;
1868*b1cdbd2cSJim Jagielski     DBG_ASSERT( rColXFIndexes.size() == nColCount, "XclExpRow::Finalize - wrong column XF index count" );
1869*b1cdbd2cSJim Jagielski 
1870*b1cdbd2cSJim Jagielski     ScfUInt16Vec aXFIndexes( nColCount, EXC_XF_NOTFOUND );
1871*b1cdbd2cSJim Jagielski     for( nPos = 0, nSize = maCellList.GetSize(); nPos < nSize; ++nPos )
1872*b1cdbd2cSJim Jagielski     {
1873*b1cdbd2cSJim Jagielski         XclExpCellRef xCell = maCellList.GetRecord( nPos );
1874*b1cdbd2cSJim Jagielski         xCell->ConvertXFIndexes( GetRoot() );
1875*b1cdbd2cSJim Jagielski         xCell->GetBlankXFIndexes( aXFIndexes );
1876*b1cdbd2cSJim Jagielski     }
1877*b1cdbd2cSJim Jagielski 
1878*b1cdbd2cSJim Jagielski     // *** Fill gaps with BLANK/MULBLANK cell records *** ---------------------
1879*b1cdbd2cSJim Jagielski 
1880*b1cdbd2cSJim Jagielski     /*  This is needed because nonexistant cells in Calc are not formatted at all,
1881*b1cdbd2cSJim Jagielski         but in Excel they would have the column default format. Blank cells that
1882*b1cdbd2cSJim Jagielski         are equal to the respective column default are removed later in this function. */
1883*b1cdbd2cSJim Jagielski     if( !mbAlwaysEmpty )
1884*b1cdbd2cSJim Jagielski     {
1885*b1cdbd2cSJim Jagielski         // XF identifier representing default cell XF
1886*b1cdbd2cSJim Jagielski         XclExpMultiXFId aXFId( XclExpXFBuffer::GetDefCellXFId() );
1887*b1cdbd2cSJim Jagielski         aXFId.ConvertXFIndex( GetRoot() );
1888*b1cdbd2cSJim Jagielski 
1889*b1cdbd2cSJim Jagielski         nPos = 0;
1890*b1cdbd2cSJim Jagielski         while( nPos <= maCellList.GetSize() )  // don't cache list size, may change in the loop
1891*b1cdbd2cSJim Jagielski         {
1892*b1cdbd2cSJim Jagielski             // get column index that follows previous cell
1893*b1cdbd2cSJim Jagielski             sal_uInt16 nFirstFreeXclCol = (nPos > 0) ? (maCellList.GetRecord( nPos - 1 )->GetLastXclCol() + 1) : 0;
1894*b1cdbd2cSJim Jagielski             // get own column index
1895*b1cdbd2cSJim Jagielski             sal_uInt16 nNextUsedXclCol = (nPos < maCellList.GetSize()) ? maCellList.GetRecord( nPos )->GetXclCol() : (GetMaxPos().Col() + 1);
1896*b1cdbd2cSJim Jagielski 
1897*b1cdbd2cSJim Jagielski             // is there a gap?
1898*b1cdbd2cSJim Jagielski             if( nFirstFreeXclCol < nNextUsedXclCol )
1899*b1cdbd2cSJim Jagielski             {
1900*b1cdbd2cSJim Jagielski                 aXFId.mnCount = nNextUsedXclCol - nFirstFreeXclCol;
1901*b1cdbd2cSJim Jagielski                 XclExpCellRef xNewCell( new XclExpBlankCell( XclAddress( nFirstFreeXclCol, mnXclRow ), aXFId ) );
1902*b1cdbd2cSJim Jagielski                 // insert the cell, InsertCell() may merge it with existing BLANK records
1903*b1cdbd2cSJim Jagielski                 InsertCell( xNewCell, nPos, false );
1904*b1cdbd2cSJim Jagielski                 // insert default XF indexes into aXFIndexes
1905*b1cdbd2cSJim Jagielski                 ::std::fill( aXFIndexes.begin() + nFirstFreeXclCol,
1906*b1cdbd2cSJim Jagielski                     aXFIndexes.begin() + nNextUsedXclCol, aXFId.mnXFIndex );
1907*b1cdbd2cSJim Jagielski                 // don't step forward with nPos, InsertCell() may remove records
1908*b1cdbd2cSJim Jagielski             }
1909*b1cdbd2cSJim Jagielski             else
1910*b1cdbd2cSJim Jagielski                 ++nPos;
1911*b1cdbd2cSJim Jagielski         }
1912*b1cdbd2cSJim Jagielski     }
1913*b1cdbd2cSJim Jagielski 
1914*b1cdbd2cSJim Jagielski     // *** Find default row format *** ----------------------------------------
1915*b1cdbd2cSJim Jagielski 
1916*b1cdbd2cSJim Jagielski     ScfUInt16Vec::iterator aCellBeg = aXFIndexes.begin(), aCellEnd = aXFIndexes.end(), aCellIt;
1917*b1cdbd2cSJim Jagielski     ScfUInt16Vec::const_iterator aColBeg = rColXFIndexes.begin(), aColIt;
1918*b1cdbd2cSJim Jagielski 
1919*b1cdbd2cSJim Jagielski     // find most used XF index in the row
1920*b1cdbd2cSJim Jagielski     typedef ::std::map< sal_uInt16, size_t > XclExpXFIndexMap;
1921*b1cdbd2cSJim Jagielski     XclExpXFIndexMap aIndexMap;
1922*b1cdbd2cSJim Jagielski     sal_uInt16 nRowXFIndex = EXC_XF_DEFAULTCELL;
1923*b1cdbd2cSJim Jagielski     size_t nMaxXFCount = 0;
1924*b1cdbd2cSJim Jagielski     for( aCellIt = aCellBeg; aCellIt != aCellEnd; ++aCellIt )
1925*b1cdbd2cSJim Jagielski     {
1926*b1cdbd2cSJim Jagielski         if( *aCellIt != EXC_XF_NOTFOUND )
1927*b1cdbd2cSJim Jagielski         {
1928*b1cdbd2cSJim Jagielski             size_t& rnCount = aIndexMap[ *aCellIt ];
1929*b1cdbd2cSJim Jagielski             ++rnCount;
1930*b1cdbd2cSJim Jagielski             if( rnCount > nMaxXFCount )
1931*b1cdbd2cSJim Jagielski             {
1932*b1cdbd2cSJim Jagielski                 nRowXFIndex = *aCellIt;
1933*b1cdbd2cSJim Jagielski                 nMaxXFCount = rnCount;
1934*b1cdbd2cSJim Jagielski             }
1935*b1cdbd2cSJim Jagielski         }
1936*b1cdbd2cSJim Jagielski     }
1937*b1cdbd2cSJim Jagielski 
1938*b1cdbd2cSJim Jagielski     // decide whether to use the row default XF index or column default XF indexes
1939*b1cdbd2cSJim Jagielski     bool bUseColDefXFs = nRowXFIndex == EXC_XF_DEFAULTCELL;
1940*b1cdbd2cSJim Jagielski     if( !bUseColDefXFs )
1941*b1cdbd2cSJim Jagielski     {
1942*b1cdbd2cSJim Jagielski         // count needed XF indexes for blank cells with and without row default XF index
1943*b1cdbd2cSJim Jagielski         size_t nXFCountWithRowDefXF = 0;
1944*b1cdbd2cSJim Jagielski         size_t nXFCountWithoutRowDefXF = 0;
1945*b1cdbd2cSJim Jagielski         for( aCellIt = aCellBeg, aColIt = aColBeg; aCellIt != aCellEnd; ++aCellIt, ++aColIt )
1946*b1cdbd2cSJim Jagielski         {
1947*b1cdbd2cSJim Jagielski             sal_uInt16 nXFIndex = *aCellIt;
1948*b1cdbd2cSJim Jagielski             if( nXFIndex != EXC_XF_NOTFOUND )
1949*b1cdbd2cSJim Jagielski             {
1950*b1cdbd2cSJim Jagielski                 if( nXFIndex != nRowXFIndex )
1951*b1cdbd2cSJim Jagielski                     ++nXFCountWithRowDefXF;     // with row default XF index
1952*b1cdbd2cSJim Jagielski                 if( nXFIndex != *aColIt )
1953*b1cdbd2cSJim Jagielski                     ++nXFCountWithoutRowDefXF;  // without row default XF index
1954*b1cdbd2cSJim Jagielski             }
1955*b1cdbd2cSJim Jagielski         }
1956*b1cdbd2cSJim Jagielski 
1957*b1cdbd2cSJim Jagielski         // use column XF indexes if this would cause less or equal number of BLANK records
1958*b1cdbd2cSJim Jagielski         bUseColDefXFs = nXFCountWithoutRowDefXF <= nXFCountWithRowDefXF;
1959*b1cdbd2cSJim Jagielski     }
1960*b1cdbd2cSJim Jagielski 
1961*b1cdbd2cSJim Jagielski     // *** Remove unused BLANK cell records *** -------------------------------
1962*b1cdbd2cSJim Jagielski 
1963*b1cdbd2cSJim Jagielski     if( bUseColDefXFs )
1964*b1cdbd2cSJim Jagielski     {
1965*b1cdbd2cSJim Jagielski         // use column default XF indexes
1966*b1cdbd2cSJim Jagielski         // #i194#: remove cell XF indexes equal to column default XF indexes
1967*b1cdbd2cSJim Jagielski         for( aCellIt = aCellBeg, aColIt = aColBeg; aCellIt != aCellEnd; ++aCellIt, ++aColIt )
1968*b1cdbd2cSJim Jagielski             if( *aCellIt == *aColIt )
1969*b1cdbd2cSJim Jagielski                 *aCellIt = EXC_XF_NOTFOUND;
1970*b1cdbd2cSJim Jagielski     }
1971*b1cdbd2cSJim Jagielski     else
1972*b1cdbd2cSJim Jagielski     {
1973*b1cdbd2cSJim Jagielski         // use row default XF index
1974*b1cdbd2cSJim Jagielski         mnXFIndex = nRowXFIndex;
1975*b1cdbd2cSJim Jagielski         ::set_flag( mnFlags, EXC_ROW_USEDEFXF );
1976*b1cdbd2cSJim Jagielski         // #98133#, #i194#, #i27407#: remove cell XF indexes equal to row default XF index
1977*b1cdbd2cSJim Jagielski         for( aCellIt = aCellBeg; aCellIt != aCellEnd; ++aCellIt )
1978*b1cdbd2cSJim Jagielski             if( *aCellIt == nRowXFIndex )
1979*b1cdbd2cSJim Jagielski                 *aCellIt = EXC_XF_NOTFOUND;
1980*b1cdbd2cSJim Jagielski     }
1981*b1cdbd2cSJim Jagielski 
1982*b1cdbd2cSJim Jagielski     // remove unused parts of BLANK/MULBLANK cell records
1983*b1cdbd2cSJim Jagielski     nPos = 0;
1984*b1cdbd2cSJim Jagielski     while( nPos < maCellList.GetSize() )   // do not cache list size, may change in the loop
1985*b1cdbd2cSJim Jagielski     {
1986*b1cdbd2cSJim Jagielski         XclExpCellRef xCell = maCellList.GetRecord( nPos );
1987*b1cdbd2cSJim Jagielski         xCell->RemoveUnusedBlankCells( aXFIndexes );
1988*b1cdbd2cSJim Jagielski         if( xCell->IsEmpty() )
1989*b1cdbd2cSJim Jagielski             maCellList.RemoveRecord( nPos );
1990*b1cdbd2cSJim Jagielski         else
1991*b1cdbd2cSJim Jagielski             ++nPos;
1992*b1cdbd2cSJim Jagielski     }
1993*b1cdbd2cSJim Jagielski 
1994*b1cdbd2cSJim Jagielski     // progress bar includes disabled rows
1995*b1cdbd2cSJim Jagielski     GetProgressBar().Progress();
1996*b1cdbd2cSJim Jagielski }
1997*b1cdbd2cSJim Jagielski 
GetFirstUsedXclCol() const1998*b1cdbd2cSJim Jagielski sal_uInt16 XclExpRow::GetFirstUsedXclCol() const
1999*b1cdbd2cSJim Jagielski {
2000*b1cdbd2cSJim Jagielski     return maCellList.IsEmpty() ? 0 : maCellList.GetFirstRecord()->GetXclCol();
2001*b1cdbd2cSJim Jagielski }
2002*b1cdbd2cSJim Jagielski 
GetFirstFreeXclCol() const2003*b1cdbd2cSJim Jagielski sal_uInt16 XclExpRow::GetFirstFreeXclCol() const
2004*b1cdbd2cSJim Jagielski {
2005*b1cdbd2cSJim Jagielski     return maCellList.IsEmpty() ? 0 : (maCellList.GetLastRecord()->GetLastXclCol() + 1);
2006*b1cdbd2cSJim Jagielski }
2007*b1cdbd2cSJim Jagielski 
IsDefaultable() const2008*b1cdbd2cSJim Jagielski bool XclExpRow::IsDefaultable() const
2009*b1cdbd2cSJim Jagielski {
2010*b1cdbd2cSJim Jagielski     const sal_uInt16 nAllowedFlags = EXC_ROW_DEFAULTFLAGS | EXC_ROW_HIDDEN | EXC_ROW_UNSYNCED;
2011*b1cdbd2cSJim Jagielski     return !::get_flag( mnFlags, static_cast< sal_uInt16 >( ~nAllowedFlags ) ) && IsEmpty();
2012*b1cdbd2cSJim Jagielski }
2013*b1cdbd2cSJim Jagielski 
DisableIfDefault(const XclExpDefaultRowData & rDefRowData)2014*b1cdbd2cSJim Jagielski void XclExpRow::DisableIfDefault( const XclExpDefaultRowData& rDefRowData )
2015*b1cdbd2cSJim Jagielski {
2016*b1cdbd2cSJim Jagielski     mbEnabled = !IsDefaultable() ||
2017*b1cdbd2cSJim Jagielski         (mnHeight != rDefRowData.mnHeight) ||
2018*b1cdbd2cSJim Jagielski         (IsHidden() != rDefRowData.IsHidden()) ||
2019*b1cdbd2cSJim Jagielski         (IsUnsynced() != rDefRowData.IsUnsynced());
2020*b1cdbd2cSJim Jagielski }
2021*b1cdbd2cSJim Jagielski 
WriteCellList(XclExpStream & rStrm)2022*b1cdbd2cSJim Jagielski void XclExpRow::WriteCellList( XclExpStream& rStrm )
2023*b1cdbd2cSJim Jagielski {
2024*b1cdbd2cSJim Jagielski     DBG_ASSERT( mbEnabled || maCellList.IsEmpty(), "XclExpRow::WriteCellList - cells in disabled row" );
2025*b1cdbd2cSJim Jagielski     maCellList.Save( rStrm );
2026*b1cdbd2cSJim Jagielski }
2027*b1cdbd2cSJim Jagielski 
Save(XclExpStream & rStrm)2028*b1cdbd2cSJim Jagielski void XclExpRow::Save( XclExpStream& rStrm )
2029*b1cdbd2cSJim Jagielski {
2030*b1cdbd2cSJim Jagielski     if( mbEnabled )
2031*b1cdbd2cSJim Jagielski         XclExpRecord::Save( rStrm );
2032*b1cdbd2cSJim Jagielski }
2033*b1cdbd2cSJim Jagielski 
InsertCell(XclExpCellRef xCell,size_t nPos,bool bIsMergedBase)2034*b1cdbd2cSJim Jagielski void XclExpRow::InsertCell( XclExpCellRef xCell, size_t nPos, bool bIsMergedBase )
2035*b1cdbd2cSJim Jagielski {
2036*b1cdbd2cSJim Jagielski     DBG_ASSERT( xCell.is(), "XclExpRow::InsertCell - missing cell" );
2037*b1cdbd2cSJim Jagielski 
2038*b1cdbd2cSJim Jagielski     /*  #109751# If we have a multi-line text in a merged cell, and the resulting
2039*b1cdbd2cSJim Jagielski         row height has not been confirmed, we need to force the EXC_ROW_UNSYNCED
2040*b1cdbd2cSJim Jagielski         flag to be true to ensure Excel works correctly. */
2041*b1cdbd2cSJim Jagielski     if( bIsMergedBase && xCell->IsMultiLineText() )
2042*b1cdbd2cSJim Jagielski         ::set_flag( mnFlags, EXC_ROW_UNSYNCED );
2043*b1cdbd2cSJim Jagielski 
2044*b1cdbd2cSJim Jagielski     // try to merge with previous cell, insert the new cell if not successful
2045*b1cdbd2cSJim Jagielski     XclExpCellRef xPrevCell = maCellList.GetRecord( nPos - 1 );
2046*b1cdbd2cSJim Jagielski     if( xPrevCell.is() && xPrevCell->TryMerge( *xCell ) )
2047*b1cdbd2cSJim Jagielski         xCell = xPrevCell;
2048*b1cdbd2cSJim Jagielski     else
2049*b1cdbd2cSJim Jagielski         maCellList.InsertRecord( xCell, nPos++ );
2050*b1cdbd2cSJim Jagielski     // nPos points now to following cell
2051*b1cdbd2cSJim Jagielski 
2052*b1cdbd2cSJim Jagielski     // try to merge with following cell, remove it if successful
2053*b1cdbd2cSJim Jagielski     XclExpCellRef xNextCell = maCellList.GetRecord( nPos );
2054*b1cdbd2cSJim Jagielski     if( xNextCell.is() && xCell->TryMerge( *xNextCell ) )
2055*b1cdbd2cSJim Jagielski         maCellList.RemoveRecord( nPos );
2056*b1cdbd2cSJim Jagielski }
2057*b1cdbd2cSJim Jagielski 
WriteBody(XclExpStream & rStrm)2058*b1cdbd2cSJim Jagielski void XclExpRow::WriteBody( XclExpStream& rStrm )
2059*b1cdbd2cSJim Jagielski {
2060*b1cdbd2cSJim Jagielski     rStrm   << mnXclRow
2061*b1cdbd2cSJim Jagielski             << GetFirstUsedXclCol()
2062*b1cdbd2cSJim Jagielski             << GetFirstFreeXclCol()
2063*b1cdbd2cSJim Jagielski             << mnHeight
2064*b1cdbd2cSJim Jagielski             << sal_uInt32( 0 )
2065*b1cdbd2cSJim Jagielski             << mnFlags
2066*b1cdbd2cSJim Jagielski             << mnXFIndex;
2067*b1cdbd2cSJim Jagielski }
2068*b1cdbd2cSJim Jagielski 
SaveXml(XclExpXmlStream & rStrm)2069*b1cdbd2cSJim Jagielski void XclExpRow::SaveXml( XclExpXmlStream& rStrm )
2070*b1cdbd2cSJim Jagielski {
2071*b1cdbd2cSJim Jagielski     if( !mbEnabled )
2072*b1cdbd2cSJim Jagielski         return;
2073*b1cdbd2cSJim Jagielski     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
2074*b1cdbd2cSJim Jagielski     bool haveFormat = ::get_flag( mnFlags, EXC_ROW_USEDEFXF );
2075*b1cdbd2cSJim Jagielski     rWorksheet->startElement( XML_row,
2076*b1cdbd2cSJim Jagielski             XML_r,              OString::valueOf( (sal_Int32) (mnXclRow+1) ).getStr(),
2077*b1cdbd2cSJim Jagielski             // OOXTODO: XML_spans,          optional
2078*b1cdbd2cSJim Jagielski             XML_s,              haveFormat ? lcl_GetStyleId( rStrm, mnXFIndex ).getStr() : NULL,
2079*b1cdbd2cSJim Jagielski             XML_customFormat,   XclXmlUtils::ToPsz( haveFormat ),
2080*b1cdbd2cSJim Jagielski             XML_ht,             OString::valueOf( (double) mnHeight / 20.0 ).getStr(),
2081*b1cdbd2cSJim Jagielski             XML_hidden,         XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_ROW_HIDDEN ) ),
2082*b1cdbd2cSJim Jagielski             XML_customHeight,   XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_ROW_UNSYNCED ) ),
2083*b1cdbd2cSJim Jagielski             XML_outlineLevel,   OString::valueOf( (sal_Int32) mnOutlineLevel ).getStr(),
2084*b1cdbd2cSJim Jagielski             XML_collapsed,      XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_ROW_COLLAPSED ) ),
2085*b1cdbd2cSJim Jagielski             // OOXTODO: XML_thickTop,       bool
2086*b1cdbd2cSJim Jagielski             // OOXTODO: XML_thickBot,       bool
2087*b1cdbd2cSJim Jagielski             // OOXTODO: XML_ph,             bool
2088*b1cdbd2cSJim Jagielski             FSEND );
2089*b1cdbd2cSJim Jagielski     // OOXTODO: XML_extLst
2090*b1cdbd2cSJim Jagielski     maCellList.SaveXml( rStrm );
2091*b1cdbd2cSJim Jagielski     rWorksheet->endElement( XML_row );
2092*b1cdbd2cSJim Jagielski }
2093*b1cdbd2cSJim Jagielski 
2094*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
2095*b1cdbd2cSJim Jagielski 
XclExpRowBuffer(const XclExpRoot & rRoot)2096*b1cdbd2cSJim Jagielski XclExpRowBuffer::XclExpRowBuffer( const XclExpRoot& rRoot ) :
2097*b1cdbd2cSJim Jagielski     XclExpRoot( rRoot ),
2098*b1cdbd2cSJim Jagielski     maOutlineBfr( rRoot ),
2099*b1cdbd2cSJim Jagielski     maDimensions( rRoot ),
2100*b1cdbd2cSJim Jagielski     mpLastUsedRow( 0 ),
2101*b1cdbd2cSJim Jagielski     mnLastUsedXclRow( 0 )
2102*b1cdbd2cSJim Jagielski {
2103*b1cdbd2cSJim Jagielski }
2104*b1cdbd2cSJim Jagielski 
AppendCell(XclExpCellRef xCell,bool bIsMergedBase)2105*b1cdbd2cSJim Jagielski void XclExpRowBuffer::AppendCell( XclExpCellRef xCell, bool bIsMergedBase )
2106*b1cdbd2cSJim Jagielski {
2107*b1cdbd2cSJim Jagielski     DBG_ASSERT( xCell.is(), "XclExpRowBuffer::AppendCell - missing cell" );
2108*b1cdbd2cSJim Jagielski     GetOrCreateRow( xCell->GetXclRow(), false ).AppendCell( xCell, bIsMergedBase );
2109*b1cdbd2cSJim Jagielski }
2110*b1cdbd2cSJim Jagielski 
CreateRows(SCROW nFirstFreeScRow)2111*b1cdbd2cSJim Jagielski void XclExpRowBuffer::CreateRows( SCROW nFirstFreeScRow )
2112*b1cdbd2cSJim Jagielski {
2113*b1cdbd2cSJim Jagielski     if( nFirstFreeScRow > 0 )
2114*b1cdbd2cSJim Jagielski         GetOrCreateRow( static_cast< sal_uInt16 >( nFirstFreeScRow - 1 ), true );
2115*b1cdbd2cSJim Jagielski }
2116*b1cdbd2cSJim Jagielski 
Finalize(XclExpDefaultRowData & rDefRowData,const ScfUInt16Vec & rColXFIndexes)2117*b1cdbd2cSJim Jagielski void XclExpRowBuffer::Finalize( XclExpDefaultRowData& rDefRowData, const ScfUInt16Vec& rColXFIndexes )
2118*b1cdbd2cSJim Jagielski {
2119*b1cdbd2cSJim Jagielski     size_t nPos, nSize;
2120*b1cdbd2cSJim Jagielski 
2121*b1cdbd2cSJim Jagielski     // *** Finalize all rows *** ----------------------------------------------
2122*b1cdbd2cSJim Jagielski 
2123*b1cdbd2cSJim Jagielski     GetProgressBar().ActivateFinalRowsSegment();
2124*b1cdbd2cSJim Jagielski 
2125*b1cdbd2cSJim Jagielski     // unused blank cell records will be removed
2126*b1cdbd2cSJim Jagielski     for( nPos = 0, nSize = maRowList.GetSize(); nPos < nSize; ++nPos )
2127*b1cdbd2cSJim Jagielski         maRowList.GetRecord( nPos )->Finalize( rColXFIndexes );
2128*b1cdbd2cSJim Jagielski 
2129*b1cdbd2cSJim Jagielski     // *** Default row format *** ---------------------------------------------
2130*b1cdbd2cSJim Jagielski 
2131*b1cdbd2cSJim Jagielski     typedef ::std::map< XclExpDefaultRowData, size_t > XclExpDefRowDataMap;
2132*b1cdbd2cSJim Jagielski     XclExpDefRowDataMap aDefRowMap;
2133*b1cdbd2cSJim Jagielski 
2134*b1cdbd2cSJim Jagielski     // find default row format for rows beyond used area
2135*b1cdbd2cSJim Jagielski     sal_uInt32 nDefaultXclRow = maRowList.IsEmpty() ? 0 : (maRowList.GetLastRecord()->GetXclRow() + 1);
2136*b1cdbd2cSJim Jagielski     XclExpDefaultRowData aMaxDefData;
2137*b1cdbd2cSJim Jagielski     size_t nMaxDefCount = 0;
2138*b1cdbd2cSJim Jagielski     /*  #i30411# Files saved with SO7/OOo1.x with nonstandard default column
2139*b1cdbd2cSJim Jagielski         formatting cause big Excel files, because all rows from row 1 to row
2140*b1cdbd2cSJim Jagielski         32000 are exported. Now, if the used area goes exactly to row 32000,
2141*b1cdbd2cSJim Jagielski         ignore all rows >32000.
2142*b1cdbd2cSJim Jagielski         #i59220# Tolerance of +-128 rows for inserted/removed rows. */
2143*b1cdbd2cSJim Jagielski     if( (nDefaultXclRow < 31872) || (nDefaultXclRow > 32128) )
2144*b1cdbd2cSJim Jagielski     {
2145*b1cdbd2cSJim Jagielski         sal_uInt16 nLastXclRow = static_cast< sal_uInt16 >( GetMaxPos().Row() );
2146*b1cdbd2cSJim Jagielski         if( nDefaultXclRow <= nLastXclRow )
2147*b1cdbd2cSJim Jagielski         {
2148*b1cdbd2cSJim Jagielski             // create a dummy ROW record and fill aMaxDefData
2149*b1cdbd2cSJim Jagielski             XclExpRowOutlineBuffer aOutlineBfr( GetRoot() );
2150*b1cdbd2cSJim Jagielski             XclExpRow aRow( GetRoot(), nLastXclRow, aOutlineBfr, true );
2151*b1cdbd2cSJim Jagielski             aMaxDefData = XclExpDefaultRowData( aRow );
2152*b1cdbd2cSJim Jagielski             aDefRowMap[ aMaxDefData ] = nMaxDefCount =
2153*b1cdbd2cSJim Jagielski                 static_cast< size_t >( nLastXclRow - nDefaultXclRow + 1 );
2154*b1cdbd2cSJim Jagielski         }
2155*b1cdbd2cSJim Jagielski     }
2156*b1cdbd2cSJim Jagielski 
2157*b1cdbd2cSJim Jagielski     // only look for default format in existing rows, if there are more than unused
2158*b1cdbd2cSJim Jagielski     nSize = maRowList.GetSize();
2159*b1cdbd2cSJim Jagielski     if( nMaxDefCount < nSize )
2160*b1cdbd2cSJim Jagielski     {
2161*b1cdbd2cSJim Jagielski         for( nPos = 0; nPos < nSize; ++nPos )
2162*b1cdbd2cSJim Jagielski         {
2163*b1cdbd2cSJim Jagielski             XclExpRowRef xRow = maRowList.GetRecord( nPos );
2164*b1cdbd2cSJim Jagielski             /*  Collect formats of unused rows (rows without cells), which are able
2165*b1cdbd2cSJim Jagielski                 to be defaulted (i.e. no explicit format or outline level). */
2166*b1cdbd2cSJim Jagielski             if( xRow->IsDefaultable() )
2167*b1cdbd2cSJim Jagielski             {
2168*b1cdbd2cSJim Jagielski                 XclExpDefaultRowData aDefData( *xRow );
2169*b1cdbd2cSJim Jagielski                 size_t& rnDefCount = aDefRowMap[ aDefData ];
2170*b1cdbd2cSJim Jagielski                 ++rnDefCount;
2171*b1cdbd2cSJim Jagielski                 if( rnDefCount > nMaxDefCount )
2172*b1cdbd2cSJim Jagielski                 {
2173*b1cdbd2cSJim Jagielski                     nMaxDefCount = rnDefCount;
2174*b1cdbd2cSJim Jagielski                     aMaxDefData = aDefData;
2175*b1cdbd2cSJim Jagielski                 }
2176*b1cdbd2cSJim Jagielski             }
2177*b1cdbd2cSJim Jagielski         }
2178*b1cdbd2cSJim Jagielski     }
2179*b1cdbd2cSJim Jagielski 
2180*b1cdbd2cSJim Jagielski     // return the default row format to caller
2181*b1cdbd2cSJim Jagielski     rDefRowData = aMaxDefData;
2182*b1cdbd2cSJim Jagielski 
2183*b1cdbd2cSJim Jagielski     // *** Disable unused ROW records, find used area *** ---------------------
2184*b1cdbd2cSJim Jagielski 
2185*b1cdbd2cSJim Jagielski     sal_uInt16 nFirstUsedXclCol = SAL_MAX_UINT16;
2186*b1cdbd2cSJim Jagielski     sal_uInt16 nFirstFreeXclCol = 0;
2187*b1cdbd2cSJim Jagielski     sal_uInt32 nFirstUsedXclRow = SAL_MAX_UINT32;
2188*b1cdbd2cSJim Jagielski     sal_uInt32 nFirstFreeXclRow = 0;
2189*b1cdbd2cSJim Jagielski 
2190*b1cdbd2cSJim Jagielski     for( nPos = 0, nSize = maRowList.GetSize(); nPos < nSize; ++nPos )
2191*b1cdbd2cSJim Jagielski     {
2192*b1cdbd2cSJim Jagielski         XclExpRowRef xRow = maRowList.GetRecord( nPos );
2193*b1cdbd2cSJim Jagielski 
2194*b1cdbd2cSJim Jagielski         // disable unused rows
2195*b1cdbd2cSJim Jagielski         xRow->DisableIfDefault( aMaxDefData );
2196*b1cdbd2cSJim Jagielski 
2197*b1cdbd2cSJim Jagielski         // find used column range
2198*b1cdbd2cSJim Jagielski         if( !xRow->IsEmpty() )      // empty rows return (0...0) as used range
2199*b1cdbd2cSJim Jagielski         {
2200*b1cdbd2cSJim Jagielski             nFirstUsedXclCol = ::std::min( nFirstUsedXclCol, xRow->GetFirstUsedXclCol() );
2201*b1cdbd2cSJim Jagielski             nFirstFreeXclCol = ::std::max( nFirstFreeXclCol, xRow->GetFirstFreeXclCol() );
2202*b1cdbd2cSJim Jagielski         }
2203*b1cdbd2cSJim Jagielski 
2204*b1cdbd2cSJim Jagielski         // find used row range
2205*b1cdbd2cSJim Jagielski         if( xRow->IsEnabled() )
2206*b1cdbd2cSJim Jagielski         {
2207*b1cdbd2cSJim Jagielski             sal_uInt16 nXclRow = xRow->GetXclRow();
2208*b1cdbd2cSJim Jagielski             nFirstUsedXclRow = ::std::min< sal_uInt32 >( nFirstUsedXclRow, nXclRow );
2209*b1cdbd2cSJim Jagielski             nFirstFreeXclRow = ::std::max< sal_uInt32 >( nFirstFreeXclRow, nXclRow + 1 );
2210*b1cdbd2cSJim Jagielski         }
2211*b1cdbd2cSJim Jagielski     }
2212*b1cdbd2cSJim Jagielski 
2213*b1cdbd2cSJim Jagielski     // adjust start position, if there are no or only empty/disabled ROW records
2214*b1cdbd2cSJim Jagielski     nFirstUsedXclCol = ::std::min( nFirstUsedXclCol, nFirstFreeXclCol );
2215*b1cdbd2cSJim Jagielski     nFirstUsedXclRow = ::std::min( nFirstUsedXclRow, nFirstFreeXclRow );
2216*b1cdbd2cSJim Jagielski 
2217*b1cdbd2cSJim Jagielski     // initialize the DIMENSIONS record
2218*b1cdbd2cSJim Jagielski     maDimensions.SetDimensions(
2219*b1cdbd2cSJim Jagielski         nFirstUsedXclCol, nFirstUsedXclRow, nFirstFreeXclCol, nFirstFreeXclRow );
2220*b1cdbd2cSJim Jagielski }
2221*b1cdbd2cSJim Jagielski 
Save(XclExpStream & rStrm)2222*b1cdbd2cSJim Jagielski void XclExpRowBuffer::Save( XclExpStream& rStrm )
2223*b1cdbd2cSJim Jagielski {
2224*b1cdbd2cSJim Jagielski     // DIMENSIONS record
2225*b1cdbd2cSJim Jagielski     maDimensions.Save( rStrm );
2226*b1cdbd2cSJim Jagielski 
2227*b1cdbd2cSJim Jagielski     // save in blocks of 32 rows, each block contains first all ROWs, then all cells
2228*b1cdbd2cSJim Jagielski     size_t nSize = maRowList.GetSize();
2229*b1cdbd2cSJim Jagielski     size_t nBlockStart = 0;
2230*b1cdbd2cSJim Jagielski     sal_uInt16 nStartXclRow = (nSize == 0) ? 0 : maRowList.GetRecord( 0 )->GetXclRow();
2231*b1cdbd2cSJim Jagielski 
2232*b1cdbd2cSJim Jagielski     while( nBlockStart < nSize )
2233*b1cdbd2cSJim Jagielski     {
2234*b1cdbd2cSJim Jagielski         // find end of row block
2235*b1cdbd2cSJim Jagielski         size_t nBlockEnd = nBlockStart + 1;
2236*b1cdbd2cSJim Jagielski         while( (nBlockEnd < nSize) && (maRowList.GetRecord( nBlockEnd )->GetXclRow() - nStartXclRow < EXC_ROW_ROWBLOCKSIZE) )
2237*b1cdbd2cSJim Jagielski             ++nBlockEnd;
2238*b1cdbd2cSJim Jagielski 
2239*b1cdbd2cSJim Jagielski         // write the ROW records
2240*b1cdbd2cSJim Jagielski         size_t nPos;
2241*b1cdbd2cSJim Jagielski         for( nPos = nBlockStart; nPos < nBlockEnd; ++nPos )
2242*b1cdbd2cSJim Jagielski             maRowList.GetRecord( nPos )->Save( rStrm );
2243*b1cdbd2cSJim Jagielski 
2244*b1cdbd2cSJim Jagielski         // write the cell records
2245*b1cdbd2cSJim Jagielski         for( nPos = nBlockStart; nPos < nBlockEnd; ++nPos )
2246*b1cdbd2cSJim Jagielski             maRowList.GetRecord( nPos )->WriteCellList( rStrm );
2247*b1cdbd2cSJim Jagielski 
2248*b1cdbd2cSJim Jagielski         nBlockStart = nBlockEnd;
2249*b1cdbd2cSJim Jagielski         nStartXclRow += EXC_ROW_ROWBLOCKSIZE;
2250*b1cdbd2cSJim Jagielski     }
2251*b1cdbd2cSJim Jagielski }
2252*b1cdbd2cSJim Jagielski 
SaveXml(XclExpXmlStream & rStrm)2253*b1cdbd2cSJim Jagielski void XclExpRowBuffer::SaveXml( XclExpXmlStream& rStrm )
2254*b1cdbd2cSJim Jagielski {
2255*b1cdbd2cSJim Jagielski     sal_Int32 nNonEmpty = 0;
2256*b1cdbd2cSJim Jagielski 
2257*b1cdbd2cSJim Jagielski     size_t nRows = maRowList.GetSize();
2258*b1cdbd2cSJim Jagielski     for( size_t i = 0; i < nRows; ++i)
2259*b1cdbd2cSJim Jagielski         if( maRowList.GetRecord( i )->IsEnabled() )
2260*b1cdbd2cSJim Jagielski             ++nNonEmpty;
2261*b1cdbd2cSJim Jagielski 
2262*b1cdbd2cSJim Jagielski     if( nNonEmpty == 0 )
2263*b1cdbd2cSJim Jagielski     {
2264*b1cdbd2cSJim Jagielski         rStrm.GetCurrentStream()->singleElement( XML_sheetData, FSEND );
2265*b1cdbd2cSJim Jagielski     }
2266*b1cdbd2cSJim Jagielski     else
2267*b1cdbd2cSJim Jagielski     {
2268*b1cdbd2cSJim Jagielski         sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
2269*b1cdbd2cSJim Jagielski         rWorksheet->startElement( XML_sheetData, FSEND );
2270*b1cdbd2cSJim Jagielski         maRowList.SaveXml( rStrm );
2271*b1cdbd2cSJim Jagielski         rWorksheet->endElement( XML_sheetData );
2272*b1cdbd2cSJim Jagielski     }
2273*b1cdbd2cSJim Jagielski }
2274*b1cdbd2cSJim Jagielski 
GetDimensions()2275*b1cdbd2cSJim Jagielski XclExpDimensions* XclExpRowBuffer::GetDimensions()
2276*b1cdbd2cSJim Jagielski {
2277*b1cdbd2cSJim Jagielski     return &maDimensions;
2278*b1cdbd2cSJim Jagielski }
2279*b1cdbd2cSJim Jagielski 
GetOrCreateRow(sal_uInt16 nXclRow,bool bRowAlwaysEmpty)2280*b1cdbd2cSJim Jagielski XclExpRow& XclExpRowBuffer::GetOrCreateRow( sal_uInt16 nXclRow, bool bRowAlwaysEmpty )
2281*b1cdbd2cSJim Jagielski {
2282*b1cdbd2cSJim Jagielski     if( !mpLastUsedRow || (mnLastUsedXclRow != nXclRow) )
2283*b1cdbd2cSJim Jagielski     {
2284*b1cdbd2cSJim Jagielski         // fill up missing ROW records
2285*b1cdbd2cSJim Jagielski         // do not use sal_uInt16 for nFirstFreeXclRow, would cause loop in full sheets
2286*b1cdbd2cSJim Jagielski         for( size_t nFirstFreeXclRow = maRowList.GetSize(); nFirstFreeXclRow <= nXclRow; ++nFirstFreeXclRow )
2287*b1cdbd2cSJim Jagielski             maRowList.AppendNewRecord( new XclExpRow(
2288*b1cdbd2cSJim Jagielski                 GetRoot(), static_cast< sal_uInt16 >( nFirstFreeXclRow ), maOutlineBfr, bRowAlwaysEmpty ) );
2289*b1cdbd2cSJim Jagielski 
2290*b1cdbd2cSJim Jagielski         mpLastUsedRow = maRowList.GetRecord( nXclRow ).get();
2291*b1cdbd2cSJim Jagielski         mnLastUsedXclRow = nXclRow;
2292*b1cdbd2cSJim Jagielski     }
2293*b1cdbd2cSJim Jagielski     return *mpLastUsedRow;
2294*b1cdbd2cSJim Jagielski }
2295*b1cdbd2cSJim Jagielski 
2296*b1cdbd2cSJim Jagielski // ============================================================================
2297*b1cdbd2cSJim Jagielski // Cell Table
2298*b1cdbd2cSJim Jagielski // ============================================================================
2299*b1cdbd2cSJim Jagielski 
XclExpCellTable(const XclExpRoot & rRoot)2300*b1cdbd2cSJim Jagielski XclExpCellTable::XclExpCellTable( const XclExpRoot& rRoot ) :
2301*b1cdbd2cSJim Jagielski     XclExpRoot( rRoot ),
2302*b1cdbd2cSJim Jagielski     maColInfoBfr( rRoot ),
2303*b1cdbd2cSJim Jagielski     maRowBfr( rRoot ),
2304*b1cdbd2cSJim Jagielski     maArrayBfr( rRoot ),
2305*b1cdbd2cSJim Jagielski     maShrfmlaBfr( rRoot ),
2306*b1cdbd2cSJim Jagielski     maTableopBfr( rRoot ),
2307*b1cdbd2cSJim Jagielski     mxDefrowheight( new XclExpDefrowheight ),
2308*b1cdbd2cSJim Jagielski     mxGuts( new XclExpGuts( rRoot ) ),
2309*b1cdbd2cSJim Jagielski     mxNoteList( new XclExpNoteList ),
2310*b1cdbd2cSJim Jagielski     mxMergedcells( new XclExpMergedcells( rRoot ) ),
2311*b1cdbd2cSJim Jagielski     mxHyperlinkList( new XclExpHyperlinkList ),
2312*b1cdbd2cSJim Jagielski     mxDval( new XclExpDval( rRoot ) )
2313*b1cdbd2cSJim Jagielski {
2314*b1cdbd2cSJim Jagielski     ScDocument& rDoc = GetDoc();
2315*b1cdbd2cSJim Jagielski     SCTAB nScTab = GetCurrScTab();
2316*b1cdbd2cSJim Jagielski     SvNumberFormatter& rFormatter = GetFormatter();
2317*b1cdbd2cSJim Jagielski 
2318*b1cdbd2cSJim Jagielski     // maximum sheet limits
2319*b1cdbd2cSJim Jagielski     SCCOL nMaxScCol = GetMaxPos().Col();
2320*b1cdbd2cSJim Jagielski     SCROW nMaxScRow = GetMaxPos().Row();
2321*b1cdbd2cSJim Jagielski 
2322*b1cdbd2cSJim Jagielski     // find used area (non-empty cells)
2323*b1cdbd2cSJim Jagielski     SCCOL nLastUsedScCol;
2324*b1cdbd2cSJim Jagielski     SCROW nLastUsedScRow;
2325*b1cdbd2cSJim Jagielski     rDoc.GetTableArea( nScTab, nLastUsedScCol, nLastUsedScRow );
2326*b1cdbd2cSJim Jagielski 
2327*b1cdbd2cSJim Jagielski     ScRange aUsedRange( 0, 0, nScTab, nLastUsedScCol, nLastUsedScRow, nScTab );
2328*b1cdbd2cSJim Jagielski     GetAddressConverter().ValidateRange( aUsedRange, true );
2329*b1cdbd2cSJim Jagielski     nLastUsedScCol = aUsedRange.aEnd.Col();
2330*b1cdbd2cSJim Jagielski     nLastUsedScRow = aUsedRange.aEnd.Row();
2331*b1cdbd2cSJim Jagielski 
2332*b1cdbd2cSJim Jagielski     // first row without any set attributes (height/hidden/...)
2333*b1cdbd2cSJim Jagielski     SCROW nFirstUnflaggedScRow = rDoc.GetLastFlaggedRow( nScTab ) + 1;
2334*b1cdbd2cSJim Jagielski 
2335*b1cdbd2cSJim Jagielski     // find range of outlines
2336*b1cdbd2cSJim Jagielski     SCROW nFirstUngroupedScRow = 0;
2337*b1cdbd2cSJim Jagielski     if( const ScOutlineTable* pOutlineTable = rDoc.GetOutlineTable( nScTab ) )
2338*b1cdbd2cSJim Jagielski     {
2339*b1cdbd2cSJim Jagielski         SCCOLROW nScStartPos, nScEndPos;
2340*b1cdbd2cSJim Jagielski         if( const ScOutlineArray* pRowArray = pOutlineTable->GetRowArray() )
2341*b1cdbd2cSJim Jagielski         {
2342*b1cdbd2cSJim Jagielski             pRowArray->GetRange( nScStartPos, nScEndPos );
2343*b1cdbd2cSJim Jagielski             // +1 because open/close button is in next row in Excel, +1 for "end->first unused"
2344*b1cdbd2cSJim Jagielski             nFirstUngroupedScRow = static_cast< SCROW >( nScEndPos + 2 );
2345*b1cdbd2cSJim Jagielski         }
2346*b1cdbd2cSJim Jagielski     }
2347*b1cdbd2cSJim Jagielski 
2348*b1cdbd2cSJim Jagielski     // column settings
2349*b1cdbd2cSJim Jagielski     /*  #i30411# Files saved with SO7/OOo1.x with nonstandard default column
2350*b1cdbd2cSJim Jagielski         formatting cause big Excel files, because all rows from row 1 to row
2351*b1cdbd2cSJim Jagielski         32000 are exported. Now, if the used area goes exactly to row 32000,
2352*b1cdbd2cSJim Jagielski         use this row as default and ignore all rows >32000.
2353*b1cdbd2cSJim Jagielski         #i59220# Tolerance of +-128 rows for inserted/removed rows. */
2354*b1cdbd2cSJim Jagielski     if( (31871 <= nLastUsedScRow) && (nLastUsedScRow <= 32127) && (nFirstUnflaggedScRow < nLastUsedScRow) && (nFirstUngroupedScRow <= nLastUsedScRow) )
2355*b1cdbd2cSJim Jagielski         nMaxScRow = nLastUsedScRow;
2356*b1cdbd2cSJim Jagielski     maColInfoBfr.Initialize( nMaxScRow );
2357*b1cdbd2cSJim Jagielski 
2358*b1cdbd2cSJim Jagielski     // range for cell iterator
2359*b1cdbd2cSJim Jagielski     SCCOL nLastIterScCol = nMaxScCol;
2360*b1cdbd2cSJim Jagielski     SCROW nLastIterScRow = ulimit_cast< SCROW >( nLastUsedScRow + 128, nMaxScRow );
2361*b1cdbd2cSJim Jagielski 	// modified for 119707 by zhanglu
2362*b1cdbd2cSJim Jagielski 
2363*b1cdbd2cSJim Jagielski 	SCCOL rEndColAtt = 0;
2364*b1cdbd2cSJim Jagielski 	SCROW rEndRowAtt = 0;
2365*b1cdbd2cSJim Jagielski 	rDoc.GetLastAttrCell( nScTab, rEndColAtt,rEndRowAtt ); // To get the real last cell's row number, which has visual data or attribute.
2366*b1cdbd2cSJim Jagielski 	if( rEndRowAtt > nLastIterScRow )
2367*b1cdbd2cSJim Jagielski 		nLastIterScRow = rEndRowAtt;
2368*b1cdbd2cSJim Jagielski 
2369*b1cdbd2cSJim Jagielski 	if (nLastIterScRow > nMaxScRow)
2370*b1cdbd2cSJim Jagielski 		nLastIterScRow = nMaxScRow;
2371*b1cdbd2cSJim Jagielski 
2372*b1cdbd2cSJim Jagielski 	// modified for 119707 end
2373*b1cdbd2cSJim Jagielski     ScUsedAreaIterator aIt( &rDoc, nScTab, 0, 0, nLastIterScCol, nLastIterScRow );
2374*b1cdbd2cSJim Jagielski 
2375*b1cdbd2cSJim Jagielski     // activate the correct segment and sub segment at the progress bar
2376*b1cdbd2cSJim Jagielski     GetProgressBar().ActivateCreateRowsSegment();
2377*b1cdbd2cSJim Jagielski 
2378*b1cdbd2cSJim Jagielski     for( bool bIt = aIt.GetNext(); bIt; bIt = aIt.GetNext() )
2379*b1cdbd2cSJim Jagielski     {
2380*b1cdbd2cSJim Jagielski         SCCOL nScCol = aIt.GetStartCol();
2381*b1cdbd2cSJim Jagielski         SCROW nScRow = aIt.GetRow();
2382*b1cdbd2cSJim Jagielski         SCCOL nLastScCol = aIt.GetEndCol();
2383*b1cdbd2cSJim Jagielski         ScAddress aScPos( nScCol, nScRow, nScTab );
2384*b1cdbd2cSJim Jagielski 
2385*b1cdbd2cSJim Jagielski         XclAddress aXclPos( static_cast< sal_uInt16 >( nScCol ), static_cast< sal_uInt16 >( nScRow ) );
2386*b1cdbd2cSJim Jagielski         sal_uInt16 nLastXclCol = static_cast< sal_uInt16 >( nLastScCol );
2387*b1cdbd2cSJim Jagielski 
2388*b1cdbd2cSJim Jagielski         const ScBaseCell* pScCell = aIt.GetCell();
2389*b1cdbd2cSJim Jagielski         XclExpCellRef xCell;
2390*b1cdbd2cSJim Jagielski 
2391*b1cdbd2cSJim Jagielski         const ScPatternAttr* pPattern = aIt.GetPattern();
2392*b1cdbd2cSJim Jagielski 
2393*b1cdbd2cSJim Jagielski         // handle overlapped merged cells before creating the cell record
2394*b1cdbd2cSJim Jagielski         sal_uInt32 nMergeBaseXFId = EXC_XFID_NOTFOUND;
2395*b1cdbd2cSJim Jagielski         bool bIsMergedBase = false;
2396*b1cdbd2cSJim Jagielski         if( pPattern )
2397*b1cdbd2cSJim Jagielski         {
2398*b1cdbd2cSJim Jagielski             const SfxItemSet& rItemSet = pPattern->GetItemSet();
2399*b1cdbd2cSJim Jagielski             // base cell in a merged range
2400*b1cdbd2cSJim Jagielski             const ScMergeAttr& rMergeItem = GETITEM( rItemSet, ScMergeAttr, ATTR_MERGE );
2401*b1cdbd2cSJim Jagielski             bIsMergedBase = rMergeItem.IsMerged();
2402*b1cdbd2cSJim Jagielski             /*  overlapped cell in a merged range; in Excel all merged cells
2403*b1cdbd2cSJim Jagielski                 must contain same XF index, for correct border */
2404*b1cdbd2cSJim Jagielski             const ScMergeFlagAttr& rMergeFlagItem = GETITEM( rItemSet, ScMergeFlagAttr, ATTR_MERGE_FLAG );
2405*b1cdbd2cSJim Jagielski             if( rMergeFlagItem.IsOverlapped() )
2406*b1cdbd2cSJim Jagielski                 nMergeBaseXFId = mxMergedcells->GetBaseXFId( aScPos );
2407*b1cdbd2cSJim Jagielski         }
2408*b1cdbd2cSJim Jagielski 
2409*b1cdbd2cSJim Jagielski         String aAddNoteText;    // additional text to be appended to a note
2410*b1cdbd2cSJim Jagielski 
2411*b1cdbd2cSJim Jagielski         CellType eCellType = pScCell ? pScCell->GetCellType() : CELLTYPE_NONE;
2412*b1cdbd2cSJim Jagielski         switch( eCellType )
2413*b1cdbd2cSJim Jagielski         {
2414*b1cdbd2cSJim Jagielski             case CELLTYPE_VALUE:
2415*b1cdbd2cSJim Jagielski             {
2416*b1cdbd2cSJim Jagielski                 double fValue = static_cast< const ScValueCell* >( pScCell )->GetValue();
2417*b1cdbd2cSJim Jagielski 
2418*b1cdbd2cSJim Jagielski                 // try to create a Boolean cell
2419*b1cdbd2cSJim Jagielski                 if( pPattern && ((fValue == 0.0) || (fValue == 1.0)) )
2420*b1cdbd2cSJim Jagielski                 {
2421*b1cdbd2cSJim Jagielski                     sal_uLong nScNumFmt = GETITEMVALUE( pPattern->GetItemSet(), SfxUInt32Item, ATTR_VALUE_FORMAT, sal_uLong );
2422*b1cdbd2cSJim Jagielski                     if( rFormatter.GetType( nScNumFmt ) == NUMBERFORMAT_LOGICAL )
2423*b1cdbd2cSJim Jagielski                         xCell.reset( new XclExpBooleanCell(
2424*b1cdbd2cSJim Jagielski                             GetRoot(), aXclPos, pPattern, nMergeBaseXFId, fValue != 0.0 ) );
2425*b1cdbd2cSJim Jagielski                 }
2426*b1cdbd2cSJim Jagielski 
2427*b1cdbd2cSJim Jagielski                 // try to create an RK value (compressed floating-point number)
2428*b1cdbd2cSJim Jagielski                 sal_Int32 nRkValue;
2429*b1cdbd2cSJim Jagielski                 if( !xCell && XclTools::GetRKFromDouble( nRkValue, fValue ) )
2430*b1cdbd2cSJim Jagielski                     xCell.reset( new XclExpRkCell(
2431*b1cdbd2cSJim Jagielski                         GetRoot(), aXclPos, pPattern, nMergeBaseXFId, nRkValue ) );
2432*b1cdbd2cSJim Jagielski 
2433*b1cdbd2cSJim Jagielski                 // else: simple floating-point number cell
2434*b1cdbd2cSJim Jagielski                 if( !xCell )
2435*b1cdbd2cSJim Jagielski                     xCell.reset( new XclExpNumberCell(
2436*b1cdbd2cSJim Jagielski                         GetRoot(), aXclPos, pPattern, nMergeBaseXFId, fValue ) );
2437*b1cdbd2cSJim Jagielski             }
2438*b1cdbd2cSJim Jagielski             break;
2439*b1cdbd2cSJim Jagielski 
2440*b1cdbd2cSJim Jagielski             case CELLTYPE_STRING:
2441*b1cdbd2cSJim Jagielski             {
2442*b1cdbd2cSJim Jagielski                 const ScStringCell& rScStrCell = *static_cast< const ScStringCell* >( pScCell );
2443*b1cdbd2cSJim Jagielski                 xCell.reset( new XclExpLabelCell(
2444*b1cdbd2cSJim Jagielski                     GetRoot(), aXclPos, pPattern, nMergeBaseXFId, rScStrCell ) );
2445*b1cdbd2cSJim Jagielski             }
2446*b1cdbd2cSJim Jagielski             break;
2447*b1cdbd2cSJim Jagielski 
2448*b1cdbd2cSJim Jagielski             case CELLTYPE_EDIT:
2449*b1cdbd2cSJim Jagielski             {
2450*b1cdbd2cSJim Jagielski                 const ScEditCell& rScEditCell = *static_cast< const ScEditCell* >( pScCell );
2451*b1cdbd2cSJim Jagielski                 XclExpHyperlinkHelper aLinkHelper( GetRoot(), aScPos );
2452*b1cdbd2cSJim Jagielski                 xCell.reset( new XclExpLabelCell(
2453*b1cdbd2cSJim Jagielski                     GetRoot(), aXclPos, pPattern, nMergeBaseXFId, rScEditCell, aLinkHelper ) );
2454*b1cdbd2cSJim Jagielski 
2455*b1cdbd2cSJim Jagielski                 // add a single created HLINK record to the record list
2456*b1cdbd2cSJim Jagielski                 if( aLinkHelper.HasLinkRecord() )
2457*b1cdbd2cSJim Jagielski                     mxHyperlinkList->AppendRecord( aLinkHelper.GetLinkRecord() );
2458*b1cdbd2cSJim Jagielski                 // add list of multiple URLs to the additional cell note text
2459*b1cdbd2cSJim Jagielski                 if( aLinkHelper.HasMultipleUrls() )
2460*b1cdbd2cSJim Jagielski                     ScGlobal::AddToken( aAddNoteText, aLinkHelper.GetUrlList(), '\n', 2 );
2461*b1cdbd2cSJim Jagielski             }
2462*b1cdbd2cSJim Jagielski             break;
2463*b1cdbd2cSJim Jagielski 
2464*b1cdbd2cSJim Jagielski             case CELLTYPE_FORMULA:
2465*b1cdbd2cSJim Jagielski             {
2466*b1cdbd2cSJim Jagielski                 const ScFormulaCell& rScFmlaCell = *static_cast< const ScFormulaCell* >( pScCell );
2467*b1cdbd2cSJim Jagielski                 xCell.reset( new XclExpFormulaCell(
2468*b1cdbd2cSJim Jagielski                     GetRoot(), aXclPos, pPattern, nMergeBaseXFId,
2469*b1cdbd2cSJim Jagielski                     rScFmlaCell, maArrayBfr, maShrfmlaBfr, maTableopBfr ) );
2470*b1cdbd2cSJim Jagielski             }
2471*b1cdbd2cSJim Jagielski             break;
2472*b1cdbd2cSJim Jagielski 
2473*b1cdbd2cSJim Jagielski             default:
2474*b1cdbd2cSJim Jagielski                 DBG_ERRORFILE( "XclExpCellTable::XclExpCellTable - unknown cell type" );
2475*b1cdbd2cSJim Jagielski                 // run-through!
2476*b1cdbd2cSJim Jagielski             case CELLTYPE_NONE:
2477*b1cdbd2cSJim Jagielski             case CELLTYPE_NOTE:
2478*b1cdbd2cSJim Jagielski             {
2479*b1cdbd2cSJim Jagielski                 xCell.reset( new XclExpBlankCell(
2480*b1cdbd2cSJim Jagielski                     GetRoot(), aXclPos, nLastXclCol, pPattern, nMergeBaseXFId ) );
2481*b1cdbd2cSJim Jagielski             }
2482*b1cdbd2cSJim Jagielski             break;
2483*b1cdbd2cSJim Jagielski         }
2484*b1cdbd2cSJim Jagielski 
2485*b1cdbd2cSJim Jagielski         // insert the cell into the current row
2486*b1cdbd2cSJim Jagielski         if( xCell.is() )
2487*b1cdbd2cSJim Jagielski             maRowBfr.AppendCell( xCell, bIsMergedBase );
2488*b1cdbd2cSJim Jagielski 
2489*b1cdbd2cSJim Jagielski         // notes
2490*b1cdbd2cSJim Jagielski         const ScPostIt* pScNote = pScCell ? pScCell->GetNote() : 0;
2491*b1cdbd2cSJim Jagielski         if( pScNote || (aAddNoteText.Len() > 0) )
2492*b1cdbd2cSJim Jagielski             mxNoteList->AppendNewRecord( new XclExpNote( GetRoot(), aScPos, pScNote, aAddNoteText ) );
2493*b1cdbd2cSJim Jagielski 
2494*b1cdbd2cSJim Jagielski         // other sheet contents
2495*b1cdbd2cSJim Jagielski         if( pPattern )
2496*b1cdbd2cSJim Jagielski         {
2497*b1cdbd2cSJim Jagielski             const SfxItemSet& rItemSet = pPattern->GetItemSet();
2498*b1cdbd2cSJim Jagielski 
2499*b1cdbd2cSJim Jagielski             // base cell in a merged range
2500*b1cdbd2cSJim Jagielski             if( bIsMergedBase )
2501*b1cdbd2cSJim Jagielski             {
2502*b1cdbd2cSJim Jagielski                 const ScMergeAttr& rMergeItem = GETITEM( rItemSet, ScMergeAttr, ATTR_MERGE );
2503*b1cdbd2cSJim Jagielski                 ScRange aScRange( aScPos );
2504*b1cdbd2cSJim Jagielski                 aScRange.aEnd.IncCol( rMergeItem.GetColMerge() - 1 );
2505*b1cdbd2cSJim Jagielski                 aScRange.aEnd.IncRow( rMergeItem.GetRowMerge() - 1 );
2506*b1cdbd2cSJim Jagielski                 sal_uInt32 nXFId = xCell.is() ? xCell->GetFirstXFId() : EXC_XFID_NOTFOUND;
2507*b1cdbd2cSJim Jagielski                 // #120156# blank cells merged vertically may occur repeatedly
2508*b1cdbd2cSJim Jagielski                 DBG_ASSERT( (aScRange.aStart.Col() == aScRange.aEnd.Col()) || (nScCol == nLastScCol),
2509*b1cdbd2cSJim Jagielski                     "XclExpCellTable::XclExpCellTable - invalid repeated blank merged cell" );
2510*b1cdbd2cSJim Jagielski                 for( SCCOL nIndex = nScCol; nIndex <= nLastScCol; ++nIndex )
2511*b1cdbd2cSJim Jagielski                 {
2512*b1cdbd2cSJim Jagielski                     mxMergedcells->AppendRange( aScRange, nXFId );
2513*b1cdbd2cSJim Jagielski                     aScRange.aStart.IncCol();
2514*b1cdbd2cSJim Jagielski                     aScRange.aEnd.IncCol();
2515*b1cdbd2cSJim Jagielski                 }
2516*b1cdbd2cSJim Jagielski             }
2517*b1cdbd2cSJim Jagielski 
2518*b1cdbd2cSJim Jagielski             // data validation
2519*b1cdbd2cSJim Jagielski             if( ScfTools::CheckItem( rItemSet, ATTR_VALIDDATA, false ) )
2520*b1cdbd2cSJim Jagielski             {
2521*b1cdbd2cSJim Jagielski                 sal_uLong nScHandle = GETITEMVALUE( rItemSet, SfxUInt32Item, ATTR_VALIDDATA, sal_uLong );
2522*b1cdbd2cSJim Jagielski                 ScRange aScRange( aScPos );
2523*b1cdbd2cSJim Jagielski                 aScRange.aEnd.SetCol( nLastScCol );
2524*b1cdbd2cSJim Jagielski                 mxDval->InsertCellRange( aScRange, nScHandle );
2525*b1cdbd2cSJim Jagielski             }
2526*b1cdbd2cSJim Jagielski         }
2527*b1cdbd2cSJim Jagielski     }
2528*b1cdbd2cSJim Jagielski 
2529*b1cdbd2cSJim Jagielski     // create missing row settings for rows anyhow flagged or with outlines
2530*b1cdbd2cSJim Jagielski     maRowBfr.CreateRows( ::std::max( nFirstUnflaggedScRow, nFirstUngroupedScRow ) );
2531*b1cdbd2cSJim Jagielski }
2532*b1cdbd2cSJim Jagielski 
Finalize()2533*b1cdbd2cSJim Jagielski void XclExpCellTable::Finalize()
2534*b1cdbd2cSJim Jagielski {
2535*b1cdbd2cSJim Jagielski     // Finalize multiple operations.
2536*b1cdbd2cSJim Jagielski     maTableopBfr.Finalize();
2537*b1cdbd2cSJim Jagielski 
2538*b1cdbd2cSJim Jagielski     /*  Finalize column buffer. This calculates column default XF indexes from
2539*b1cdbd2cSJim Jagielski         the XF identifiers and fills a vector with these XF indexes. */
2540*b1cdbd2cSJim Jagielski     ScfUInt16Vec aColXFIndexes;
2541*b1cdbd2cSJim Jagielski     maColInfoBfr.Finalize( aColXFIndexes );
2542*b1cdbd2cSJim Jagielski 
2543*b1cdbd2cSJim Jagielski     /*  Finalize row buffer. This calculates all cell XF indexes from the XF
2544*b1cdbd2cSJim Jagielski         identifiers. Then the XF index vector aColXFIndexes (filled above) is
2545*b1cdbd2cSJim Jagielski         used to calculate the row default formats. With this, all unneeded blank
2546*b1cdbd2cSJim Jagielski         cell records (equal to row default or column default) will be removed.
2547*b1cdbd2cSJim Jagielski         The function returns the (most used) default row format in aDefRowData. */
2548*b1cdbd2cSJim Jagielski     XclExpDefaultRowData aDefRowData;
2549*b1cdbd2cSJim Jagielski     maRowBfr.Finalize( aDefRowData, aColXFIndexes );
2550*b1cdbd2cSJim Jagielski 
2551*b1cdbd2cSJim Jagielski     // Initialize the DEFROWHEIGHT record.
2552*b1cdbd2cSJim Jagielski     mxDefrowheight->SetDefaultData( aDefRowData );
2553*b1cdbd2cSJim Jagielski }
2554*b1cdbd2cSJim Jagielski 
CreateRecord(sal_uInt16 nRecId) const2555*b1cdbd2cSJim Jagielski XclExpRecordRef XclExpCellTable::CreateRecord( sal_uInt16 nRecId ) const
2556*b1cdbd2cSJim Jagielski {
2557*b1cdbd2cSJim Jagielski     XclExpRecordRef xRec;
2558*b1cdbd2cSJim Jagielski     switch( nRecId )
2559*b1cdbd2cSJim Jagielski     {
2560*b1cdbd2cSJim Jagielski         case EXC_ID3_DIMENSIONS:    xRec.reset( new XclExpDelegatingRecord( const_cast<XclExpRowBuffer*>(&maRowBfr)->GetDimensions() ) );   break;
2561*b1cdbd2cSJim Jagielski         case EXC_ID2_DEFROWHEIGHT:  xRec = mxDefrowheight;  break;
2562*b1cdbd2cSJim Jagielski         case EXC_ID_GUTS:           xRec = mxGuts;          break;
2563*b1cdbd2cSJim Jagielski         case EXC_ID_NOTE:           xRec = mxNoteList;      break;
2564*b1cdbd2cSJim Jagielski         case EXC_ID_MERGEDCELLS:    xRec = mxMergedcells;   break;
2565*b1cdbd2cSJim Jagielski         case EXC_ID_HLINK:          xRec = mxHyperlinkList; break;
2566*b1cdbd2cSJim Jagielski         case EXC_ID_DVAL:           xRec = mxDval;          break;
2567*b1cdbd2cSJim Jagielski         default:    DBG_ERRORFILE( "XclExpCellTable::CreateRecord - unknown record id" );
2568*b1cdbd2cSJim Jagielski     }
2569*b1cdbd2cSJim Jagielski     return xRec;
2570*b1cdbd2cSJim Jagielski }
2571*b1cdbd2cSJim Jagielski 
Save(XclExpStream & rStrm)2572*b1cdbd2cSJim Jagielski void XclExpCellTable::Save( XclExpStream& rStrm )
2573*b1cdbd2cSJim Jagielski {
2574*b1cdbd2cSJim Jagielski     // DEFCOLWIDTH and COLINFOs
2575*b1cdbd2cSJim Jagielski     maColInfoBfr.Save( rStrm );
2576*b1cdbd2cSJim Jagielski     // ROWs and cell records
2577*b1cdbd2cSJim Jagielski     maRowBfr.Save( rStrm );
2578*b1cdbd2cSJim Jagielski }
2579*b1cdbd2cSJim Jagielski 
SaveXml(XclExpXmlStream & rStrm)2580*b1cdbd2cSJim Jagielski void XclExpCellTable::SaveXml( XclExpXmlStream& rStrm )
2581*b1cdbd2cSJim Jagielski {
2582*b1cdbd2cSJim Jagielski     maColInfoBfr.SaveXml( rStrm );
2583*b1cdbd2cSJim Jagielski     maRowBfr.SaveXml( rStrm );
2584*b1cdbd2cSJim Jagielski }
2585*b1cdbd2cSJim Jagielski 
2586*b1cdbd2cSJim Jagielski // ============================================================================
2587*b1cdbd2cSJim Jagielski 
2588