diff options
author | Daniel Rentz <dr@openoffice.org> | 2002-11-21 11:23:15 +0000 |
---|---|---|
committer | Daniel Rentz <dr@openoffice.org> | 2002-11-21 11:23:15 +0000 |
commit | ff6d9945d1f4e3099c3247a6d31f28147546362f (patch) | |
tree | 65a9cca8698a8b6831589e39569579bd2e6ecb19 /sc/source/filter/excel/xecontent.cxx | |
parent | eacb79951c4b8e8b4aa0f9c109f0bd8d6178ec8d (diff) |
code review and documentation
Diffstat (limited to 'sc/source/filter/excel/xecontent.cxx')
-rw-r--r-- | sc/source/filter/excel/xecontent.cxx | 844 |
1 files changed, 844 insertions, 0 deletions
diff --git a/sc/source/filter/excel/xecontent.cxx b/sc/source/filter/excel/xecontent.cxx new file mode 100644 index 000000000000..4b10b255d25f --- /dev/null +++ b/sc/source/filter/excel/xecontent.cxx @@ -0,0 +1,844 @@ +/************************************************************************* + * + * $RCSfile: xecontent.cxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: dr $ $Date: 2002-11-21 12:12:47 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifdef PCH +#include "filt_pch.hxx" +#endif + +#pragma hdrstop + +// ============================================================================ + +#ifndef SC_XECONTENT_HXX +#include "xecontent.hxx" +#endif + +#ifndef _COM_SUN_STAR_CONTAINER_XINDEXACCESS_HPP_ +#include <com/sun/star/container/XIndexAccess.hpp> +#endif +#ifndef _COM_SUN_STAR_FRAME_XMODEL_HPP_ +#include <com/sun/star/frame/XModel.hpp> +#endif +#ifndef _COM_SUN_STAR_SHEET_XAREALINKS_HPP_ +#include <com/sun/star/sheet/XAreaLinks.hpp> +#endif +#ifndef _COM_SUN_STAR_SHEET_XAREALINK_HPP_ +#include <com/sun/star/sheet/XAreaLink.hpp> +#endif + +#ifndef _SV_GRAPH_HXX +#include <vcl/graph.hxx> +#endif +#ifndef _SV_BMPACC_HXX +#include <vcl/bmpacc.hxx> +#endif +#ifndef _SFX_OBJSH_HXX +#include <sfx2/objsh.hxx> +#endif +#ifndef _URLOBJ_HXX +#include <tools/urlobj.hxx> +#endif +#ifndef _SFXITEMSET_HXX +#include <svtools/itemset.hxx> +#endif + +#ifndef SC_ITEMS_HXX +#include "scitems.hxx" +#endif +#ifndef _EEITEM_HXX +#include <svx/eeitem.hxx> +#endif +#define ITEMID_FIELD EE_FEATURE_FIELD +#ifndef _SVX_BRSHITEM_HXX +#include <svx/brshitem.hxx> +#endif +#ifndef _SVX_FLDITEM_HXX +#include <svx/flditem.hxx> +#endif + +#ifndef SC_DOCUMENT_HXX +#include "document.hxx" +#endif +#ifndef SC_VALIDAT_HXX +#include "validat.hxx" +#endif +#ifndef SC_UNONAMES_HXX +#include "unonames.hxx" +#endif +#ifndef SC_CONVUNO_HXX +#include "convuno.hxx" +#endif +#ifndef SC_RANGENAM_HXX +#include "rangenam.hxx" +#endif + +#ifndef SC_FAPIHELPER_HXX +#include "fapihelper.hxx" +#endif + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::beans::XPropertySet; +using ::com::sun::star::container::XIndexAccess; +using ::com::sun::star::frame::XModel; +using ::com::sun::star::table::CellRangeAddress; +using ::com::sun::star::sheet::XAreaLinks; +using ::com::sun::star::sheet::XAreaLink; + +#include "excupn.hxx" +#include "excrecds.hxx" + + +// Shared string table ======================================================== + +XclExpSst::~XclExpSst() +{ +} + +sal_uInt32 XclExpSst::Insert( XclExpString* pString ) +{ + //! TODO search for the strings to prevent doubles + maStringList.Append( pString ); + return maStringList.Count() - 1; +} + +void XclExpSst::Save( XclExpStream& rStrm ) +{ + if( maStringList.Empty() ) + return; + + SvMemoryStream aExtSst( 8192 ); + + sal_uInt32 nCount = maStringList.Count(); + + sal_uInt32 nBucket = nCount; + while( nBucket > 0x0100 ) + nBucket /= 2; + + sal_uInt16 nPerBucket = static_cast< sal_uInt16 >( ::std::max( 8UL, nBucket ) ); + sal_uInt16 nBucketIndex = 0; + + // *** write the SST record *** + + rStrm.StartRecord( EXC_ID_SST, 8 ); + + rStrm << nCount << nCount; + for( const XclExpString* pString = maStringList.First(); pString; pString = maStringList.Next() ) + { + if( !nBucketIndex ) + { + // write bucket info before string to get correct record position + sal_uInt32 nStrmPos = rStrm.GetStreamPos(); + sal_uInt16 nRecPos = static_cast< sal_uInt16 >( rStrm.GetRecPos() + 4 ); + aExtSst << nStrmPos // stream position + << nRecPos // position from start of SST or CONTINUE + << sal_uInt16( 0 ); // reserved + } + + rStrm << *pString; + + if( ++nBucketIndex == nPerBucket ) + nBucketIndex = 0; + } + + rStrm.EndRecord(); + + // *** write the EXTSST record *** + + rStrm.StartRecord( EXC_ID_EXTSST, 0 ); + + rStrm << nPerBucket; + rStrm.SetSliceSize( 8 ); // size of one bucket info + aExtSst.Seek( STREAM_SEEK_TO_BEGIN ); + rStrm.CopyFromStream( aExtSst ); + + rStrm.EndRecord(); +} + + +// Background bitmap ========================================================== + +inline XclExpStream& operator<<( XclExpStream& rStrm, const BitmapColor& rBmpColor ) +{ + return rStrm << rBmpColor.GetBlue() << rBmpColor.GetGreen() << rBmpColor.GetRed(); +} + + +// ---------------------------------------------------------------------------- + +XclExpBitmap::XclExpBitmap( const XclExpRoot& rRoot ) : + XclExpRecord( EXC_ID_BITMAP ), + mpGraphic( NULL ) +{ + SfxStyleSheet* pStyleSh = rRoot.mpRD->pStyleSheet; + if( pStyleSh ) + mpGraphic = ((const SvxBrushItem&) rRoot.mpRD->pStyleSheetItemSet->Get( ATTR_BACKGROUND )).GetGraphic(); +} + +void XclExpBitmap::Save( XclExpStream& rStrm ) +{ + if( !mpGraphic ) return; + + Bitmap aBmp( mpGraphic->GetBitmap() ); + if( aBmp.GetBitCount() != 24 ) + aBmp.Convert( BMP_CONVERSION_24BIT ); + + BitmapReadAccess* pAccess = aBmp.AcquireReadAccess(); + if( !pAccess ) return; + + sal_Int32 nWidth = ::std::min( pAccess->Width(), 0xFFFFL ); + sal_Int32 nHeight = ::std::min( pAccess->Height(), 0xFFFFL ); + if( (nWidth > 0) && (nHeight > 0) ) + { + rStrm.StartRecord( EXC_ID_BITMAP, 0 ); + rStrm.SetMaxRecSize( EXC_BITMAP_MAXREC ); + rStrm.SetMaxContSize( EXC_BITMAP_MAXCONT ); + + sal_uInt8 nPadding = static_cast< sal_uInt8 >( nWidth & 0x03 ); + sal_uInt32 nTmpSize = (nWidth * 3UL + nPadding) * nHeight + 12; + + rStrm << EXC_BITMAP_UNKNOWNID + << nTmpSize // size after _this_ field + << sal_uInt32( 12 ) // unknown + << static_cast< sal_uInt16 >( nWidth ) // width + << static_cast< sal_uInt16 >( nHeight ) // height + << sal_uInt16( 1 ) // planes + << sal_uInt16( 24 ); // bits per pixel + + for( sal_Int32 nY = nHeight - 1; nY >= 0; --nY ) + { + for( sal_Int32 nX = 0; nX < nWidth; ++nX ) + rStrm << pAccess->GetPixel( nY, nX ); + rStrm.WriteZeroBytes( nPadding ); + } + + rStrm.EndRecord(); + } + aBmp.ReleaseAccess( pAccess ); +} + + +// Hyperlinks ================================================================= + +XclExpHyperlink::XclExpHyperlink( const XclExpRoot& rRoot, const SvxURLField& rUrlField ) : + XclExpRecord( EXC_ID_HLINK ), + mpVarData( new SvMemoryStream ), + mnFlags( 0 ) +{ + const String& rUrl = rUrlField.GetURL(); + const String& rRepr = rUrlField.GetRepresentation(); + INetURLObject aUrlObj( rUrl ); + const INetProtocol eProtocol = aUrlObj.GetProtocol(); + bool bWithRepr = rRepr.Len() > 0; + XclExpStream aXclStrm( *mpVarData, rRoot ); // using in raw write mode. + ::std::auto_ptr< XclExpString > pTextMark; + + // description + if( bWithRepr ) + { + XclExpString aDescr( rRepr, EXC_STR_FORCEUNICODE, 255 ); + aXclStrm << sal_uInt32( aDescr.GetLen() + 1 ); // string length + 1 trailing zero word + aDescr.WriteBuffer( aXclStrm ); // NO flags + aXclStrm << sal_uInt16( 0 ); + + mnFlags |= EXC_HLINK_DESCR; + mpRepr.reset( new String( rRepr ) ); + } + + // file link or URL + if( eProtocol == INET_PROT_FILE ) + { + String aFileName; + sal_uInt16 nLevel; + bool bRel; + BuildFileName( aFileName, nLevel, bRel, aUrlObj, rRoot ); + + if( !bRel ) + mnFlags |= EXC_HLINK_ABS; + mnFlags |= EXC_HLINK_BODY; + + ByteString aAsciiLink( aFileName, rRoot.GetCharSet() ); + XclExpString aLink( aFileName, EXC_STR_FORCEUNICODE, 255 ); + aXclStrm << XclTools::maGuidFileMoniker + << nLevel + << sal_uInt32( aAsciiLink.Len() + 1 ); // string length + 1 trailing zero byte + aXclStrm.Write( aAsciiLink.GetBuffer(), aAsciiLink.Len() ); + aXclStrm << sal_uInt8( 0 ) + << sal_uInt32( 0xDEADFFFF ); + aXclStrm.WriteZeroBytes( 20 ); + aXclStrm << sal_uInt32( aLink.GetBufferByteCount() + 6 ) + << sal_uInt32( aLink.GetBufferByteCount() ) // byte count, not string length + << sal_uInt16( 0x0003 ); + aLink.WriteBuffer( aXclStrm ); // NO flags + + if( !mpRepr.get() ) + mpRepr.reset( new String( aFileName ) ); + } + else if( eProtocol != INET_PROT_NOT_VALID ) + { + XclExpString aUrl( aUrlObj.GetURLNoMark(), EXC_STR_FORCEUNICODE, 255 ); + aXclStrm << XclTools::maGuidUrlMoniker + << sal_uInt32( aUrl.GetBufferByteCount() + 2 ); // byte count + 1 trailing zero word + aUrl.WriteBuffer( aXclStrm ); // NO flags + aXclStrm << sal_uInt16( 0 ); + + mnFlags |= EXC_HLINK_BODY | EXC_HLINK_ABS; + if( !mpRepr.get() ) + mpRepr.reset( new String( rUrl ) ); + } + else if( rUrl.GetChar( 0 ) == '#' ) // hack for #89066# + { + String aTextMark( rUrl.Copy( 1 ) ); + aTextMark.SearchAndReplace( '.', '!' ); + pTextMark.reset( new XclExpString( aTextMark, EXC_STR_FORCEUNICODE, 255 ) ); + } + + // text mark + if( !pTextMark.get() && aUrlObj.HasMark() ) + pTextMark.reset( new XclExpString( aUrlObj.GetMark(), EXC_STR_FORCEUNICODE, 255 ) ); + + if( pTextMark.get() ) + { + aXclStrm << sal_uInt32( pTextMark->GetLen() + 1 ); // string length + 1 trailing zero word + pTextMark->WriteBuffer( aXclStrm ); // NO flags + aXclStrm << sal_uInt16( 0 ); + + mnFlags |= EXC_HLINK_MARK; + } + + SetRecSize( 32 + mpVarData->Tell() ); +} + +XclExpHyperlink::~XclExpHyperlink() +{ +} + +void XclExpHyperlink::BuildFileName( + String& rName, sal_uInt16& rnLevel, bool& rbRel, + const INetURLObject& rUrlObj, const XclExpRoot& rRoot ) const +{ + rName = rUrlObj.getFSysPath( INetURLObject::FSYS_DOS ); + rnLevel = 0; + rbRel = rRoot.IsRelUrl(); + + if( rbRel ) + { + String aTmpName( rName ); + rName = rUrlObj.GetRelURL( rRoot.GetBasePath(), rName, + INetURLObject::WAS_ENCODED, INetURLObject::DECODE_WITH_CHARSET ); + + if( rName.SearchAscii( INET_FILE_SCHEME ) == 0 ) // not converted to rel -> make abs + { + rName = aTmpName; + rbRel = false; + } + else if( rName.SearchAscii( "./" ) == 0 ) + rName.Erase( 0, 2 ); + else + { + while( rName.SearchAndReplaceAscii( "../", EMPTY_STRING ) != STRING_NOTFOUND ) + ++rnLevel; + } + } +} + +void XclExpHyperlink::WriteBody( XclExpStream& rStrm ) +{ + sal_uInt16 nCol = static_cast< sal_uInt16 >( maPos.Col() ); + sal_uInt16 nRow = static_cast< sal_uInt16 >( maPos.Row() ); + mpVarData->Seek( STREAM_SEEK_TO_BEGIN ); + + rStrm << nRow << nRow << nCol << nCol + << XclTools::maGuidStdLink + << sal_uInt32( 2 ) + << mnFlags; + rStrm.CopyFromStream( *mpVarData ); +} + + +// Label ranges =============================================================== + +XclExpLabelranges::XclExpLabelranges( const XclExpRoot& rRoot ) : + XclExpRecord( EXC_ID_LABELRANGES ) +{ + sal_uInt16 nTab = rRoot.GetScTab(); + + // row label ranges + FillRangeList( maRowRanges, rRoot.GetDoc().GetRowNameRangesRef(), nTab ); + // row labels only over 1 column (restriction of Excel97/2000/XP) + for( ScRange* pRange = maRowRanges.First(); pRange; pRange = maRowRanges.Next() ) + if( pRange->aStart.Col() != pRange->aEnd.Col() ) + pRange->aEnd.SetCol( pRange->aStart.Col() ); + rRoot.CheckCellRangeList( maRowRanges ); + + // col label ranges + FillRangeList( maColRanges, rRoot.GetDoc().GetColNameRangesRef(), nTab ); + rRoot.CheckCellRangeList( maColRanges ); + + SetRecSize( 4 + 8 * (maRowRanges.Count() + maColRanges.Count()) ); +} + +void XclExpLabelranges::FillRangeList( ScRangeList& rRanges, ScRangePairListRef xLabelRangesRef, sal_uInt16 nTab ) +{ + for( const ScRangePair* pRangePair = xLabelRangesRef->First(); pRangePair; pRangePair = xLabelRangesRef->Next() ) + { + const ScRange& rRange = pRangePair->GetRange( 0 ); + if( rRange.aStart.Tab() == nTab ) + rRanges.Append( rRange ); + } +} + +void XclExpLabelranges::Save( XclExpStream& rStrm ) +{ + if( maRowRanges.Count() || maColRanges.Count() ) + XclExpRecord::Save( rStrm ); +} + +void XclExpLabelranges::WriteBody( XclExpStream& rStrm ) +{ + rStrm << maRowRanges << maColRanges; +} + + +// Validation ================================================================= + +XclExpDv::XclExpDv( const XclExpRoot& rRoot, sal_uInt32 nHandle ) : + XclExpRecord( EXC_ID_DV ), + XclExpRoot( rRoot ), + mpValData( rRoot.GetDoc().GetValidationEntry( nHandle ) ), + mnHandle( nHandle ) +{ +} + +void XclExpDv::InsertCellRange( const ScRange& rRange ) +{ + maRanges.Join( rRange ); +} + +bool XclExpDv::CheckWriteRecord() +{ + CheckCellRangeList( maRanges ); + return mpValData && maRanges.Count(); +} + +void XclExpDv::WriteBody( XclExpStream& rStrm ) +{ + DBG_ASSERT( mpValData, "XclExpDv::WriteBody - missing core data" ); + + String aTitle, aText; + + // prompt box + bool bShowPrompt = (mpValData->GetInput( aTitle, aText ) == TRUE); + XclExpString aPromptTitle( aTitle ); + // empty strings are not empty but contain a zero character (why not) + if( !aTitle.Len() ) + aPromptTitle.Assign( 0, EXC_STR_KEEPZEROCHARS ); + XclExpString aPromptText( aText ); + if( !aText.Len() ) + aPromptText.Assign( 0, EXC_STR_KEEPZEROCHARS ); + + // error box + ScValidErrorStyle eScErrorStyle; + bool bShowError = (mpValData->GetErrMsg( aTitle, aText, eScErrorStyle ) == TRUE); + XclExpString aErrorTitle( aTitle ); + if( !aTitle.Len() ) + aErrorTitle.Assign( 0, EXC_STR_KEEPZEROCHARS ); + XclExpString aErrorText( aText ); + if( !aText.Len() ) + aErrorText.Assign( 0, EXC_STR_KEEPZEROCHARS ); + + // flags + sal_uInt32 nFlags = EXC_DV_SUPPRESSDROPDOWN; + switch( mpValData->GetDataMode() ) + { + case SC_VALID_ANY: nFlags |= EXC_DV_MODE_ANY; break; + case SC_VALID_WHOLE: nFlags |= EXC_DV_MODE_WHOLE; break; + case SC_VALID_DECIMAL: nFlags |= EXC_DV_MODE_DECIMAL; break; + case SC_VALID_LIST: nFlags |= EXC_DV_MODE_LIST; break; + case SC_VALID_DATE: nFlags |= EXC_DV_MODE_DATE; break; + case SC_VALID_TIME: nFlags |= EXC_DV_MODE_TIME; break; + case SC_VALID_TEXTLEN: nFlags |= EXC_DV_MODE_TEXTLEN; break; + case SC_VALID_CUSTOM: nFlags |= EXC_DV_MODE_CUSTOM; break; + default: DBG_ERRORFILE( "XclExpDv::SaveCont - unknown mode" ); + } + switch( mpValData->GetOperation() ) + { + case SC_COND_NONE: + case SC_COND_EQUAL: nFlags |= EXC_DV_COND_EQUAL; break; + case SC_COND_LESS: nFlags |= EXC_DV_COND_LESS; break; + case SC_COND_GREATER: nFlags |= EXC_DV_COND_GREATER; break; + case SC_COND_EQLESS: nFlags |= EXC_DV_COND_EQLESS; break; + case SC_COND_EQGREATER: nFlags |= EXC_DV_COND_EQGREATER; break; + case SC_COND_NOTEQUAL: nFlags |= EXC_DV_COND_NOTEQUAL; break; + case SC_COND_BETWEEN: nFlags |= EXC_DV_COND_BETWEEN; break; + case SC_COND_NOTBETWEEN:nFlags |= EXC_DV_COND_NOTBETWEEN; break; + default: DBG_ERRORFILE( "XclExpDv::SaveCont - unknown condition" ); + } + switch( eScErrorStyle ) + { + case SC_VALERR_STOP: nFlags |= EXC_DV_ERROR_STOP; break; + case SC_VALERR_WARNING: nFlags |= EXC_DV_ERROR_WARNING; break; + case SC_VALERR_INFO: nFlags |= EXC_DV_ERROR_INFO; break; + case SC_VALERR_MACRO: bShowError = false; break; + default: DBG_ERRORFILE( "XclExpDv::SaveCont - unknown error style" ); + } + if( mpValData->IsIgnoreBlank() ) + nFlags |= EXC_DV_IGNOREBLANK; + if( bShowPrompt ) + nFlags |= EXC_DV_SHOWPROMPT; + if( bShowError ) + nFlags |= EXC_DV_SHOWERROR; + + // formulas + ExcUPN* pFmlaUPN1 = NULL; + ExcUPN* pFmlaUPN2 = NULL; + ScTokenArray* pScTokenArr = NULL; + EC_Codetype eDummy; + + pScTokenArr = mpValData->CreateTokenArry( 0 ); + if( pScTokenArr ) + pFmlaUPN1 = new ExcUPN( mpRD, *pScTokenArr, eDummy, NULL, true ); + delete pScTokenArr; + + pScTokenArr = mpValData->CreateTokenArry( 1 ); + if( pScTokenArr ) + pFmlaUPN2 = new ExcUPN( mpRD, *pScTokenArr, eDummy, NULL, true ); + delete pScTokenArr; + + sal_uInt16 nFmlaLen1 = pFmlaUPN1 ? pFmlaUPN1->GetLen() : 0; + const sal_Char* pFmlaData1 = nFmlaLen1 ? pFmlaUPN1->GetData() : NULL; + sal_uInt16 nFmlaLen2 = pFmlaUPN2 ? pFmlaUPN2->GetLen() : 0; + const sal_Char* pFmlaData2 = nFmlaLen2 ? pFmlaUPN2->GetData() : NULL; + + // write it + rStrm << nFlags << aPromptTitle << aErrorTitle << aPromptText << aErrorText; + rStrm << nFmlaLen1 << static_cast< sal_uInt16 >( 0 ); + rStrm.Write( pFmlaData1, nFmlaLen1 ); + rStrm << nFmlaLen2 << static_cast< sal_uInt16 >( 0 ); + rStrm.Write( pFmlaData2, nFmlaLen2 ); + rStrm << maRanges; +} + + +// ---------------------------------------------------------------------------- + +XclExpDval::XclExpDval( const XclExpRoot& rRoot ) : + XclExpRecord( EXC_ID_DVAL, 18 ), + XclExpRoot( rRoot ), + mpLastFoundDv( NULL ) +{ +} + +XclExpDv& XclExpDval::SearchOrCreateDv( sal_uInt32 nHandle ) +{ + // test last found record + if( mpLastFoundDv && (mpLastFoundDv->GetHandle() == nHandle) ) + return *mpLastFoundDv; + + // binary search + sal_uInt32 nCurrIndex = 0; + if( !maDvList.Empty() ) + { + sal_uInt32 nFirst = 0; + sal_uInt32 nLast = maDvList.Count() - 1; + bool bLoop = true; + sal_uInt32 nCurrHandle; + while( (nFirst <= nLast) && bLoop ) + { + nCurrIndex = (nFirst + nLast) / 2; + mpLastFoundDv = maDvList.GetObject( nCurrIndex ); + nCurrHandle = mpLastFoundDv->GetHandle(); + if( nCurrHandle == nHandle ) + bLoop = false; + else if( nCurrHandle < nHandle ) + nFirst = nCurrIndex + 1; + else if( nCurrIndex ) + nLast = nCurrIndex - 1; + else // special case for nLast = -1 + bLoop = false; + } + if( nCurrHandle == nHandle ) + return *mpLastFoundDv; + else if( nCurrHandle < nHandle ) + ++nCurrIndex; + } + + // create new DV record + mpLastFoundDv = new XclExpDv( *this, nHandle ); + maDvList.Insert( mpLastFoundDv, nCurrIndex ); + return *mpLastFoundDv; +} + +void XclExpDval::InsertCellRange( const ScRange& rRange, sal_uInt32 nHandle ) +{ + XclExpDv& rDvRec = SearchOrCreateDv( nHandle ); + rDvRec.InsertCellRange( rRange ); +} + +void XclExpDval::Save( XclExpStream& rStrm ) +{ + // check all records + sal_uInt32 nIndex = maDvList.Count(); + while( nIndex ) + { + --nIndex; // backwards to keep nIndex valid + XclExpDv* pDvRec = maDvList.GetObject( nIndex ); + if( !pDvRec->CheckWriteRecord() ) + maDvList.Delete( nIndex ); + } + + // write the DVAL and the DV's + if( !maDvList.Empty() ) + { + XclExpRecord::Save( rStrm ); + maDvList.Save( rStrm ); + } +} + +void XclExpDval::WriteBody( XclExpStream& rStrm ) +{ + rStrm.WriteZeroBytes( 10 ); + rStrm << EXC_DVAL_NOOBJ << maDvList.Count(); +} + + +// Web Queries ================================================================ + +XclExpWebQuery::XclExpWebQuery( + const String& rRangeName, + const String& rUrl, + const String& rSource, + sal_Int32 nRefrSecs ) : + maDestRange( rRangeName ), + maUrl( rUrl ), + mpQryTables( NULL ), + // refresh delay time: seconds -> minutes + mnRefresh( static_cast< sal_Int16 >( ::std::min( (nRefrSecs + 59L) / 60L, 0x7FFFL ) ) ), + mbEntireDoc( false ) +{ + // comma separated list of HTML table names or indexes + xub_StrLen nTokenCnt = rSource.GetTokenCount( ';' ); + String aNewTables, aAppendTable; + xub_StrLen nStringIx = 0; + bool bExitLoop = false; + for( xub_StrLen nToken = 0; (nToken < nTokenCnt) && !bExitLoop; ++nToken ) + { + String aToken( rSource.GetToken( 0, ';', nStringIx ) ); + mbEntireDoc = ScfTools::IsHTMLDocName( aToken ); + bExitLoop = mbEntireDoc || ScfTools::IsHTMLTablesName( aToken ); + if( !bExitLoop && ScfTools::GetHTMLNameFromName( aToken, aAppendTable ) ) + ScfTools::AddToken( aNewTables, aAppendTable, ',' ); + } + + if( !bExitLoop ) // neither HTML_all nor HTML_tables found + { + if( aNewTables.Len() ) + mpQryTables = new XclExpString( aNewTables ); + else + mbEntireDoc = true; + } +} + +XclExpWebQuery::~XclExpWebQuery() +{ + delete mpQryTables; +} + +void XclExpWebQuery::Save( XclExpStream& rStrm ) +{ + DBG_ASSERT( !mbEntireDoc || !mpQryTables, "XclExpWebQuery::Save - illegal mode" ); + sal_uInt16 nFlags; + + // QSI record + rStrm.StartRecord( EXC_ID_QSI, 10 + maDestRange.GetByteCount() ); + rStrm << EXC_QSI_DEFAULTFLAGS + << sal_uInt16( 0x0010 ) + << sal_uInt16( 0x0012 ) + << sal_uInt32( 0x00000000 ) + << maDestRange; + rStrm.EndRecord(); + + // PARAMQRY record + nFlags = EXC_PQRY_DEFAULTFLAGS | (mbEntireDoc ? EXC_PQRY_DOC : EXC_PQRY_TABLES); + rStrm.StartRecord( EXC_ID_PQRY, 12 ); + rStrm << nFlags + << sal_uInt16( 0x0000 ) + << sal_uInt16( 0x0001 ); + rStrm.WriteZeroBytes( 6 ); + rStrm.EndRecord(); + + // SXSTRING record + rStrm.StartRecord( EXC_ID_SXSTRING, maUrl.GetByteCount() ); + rStrm << maUrl; + rStrm.EndRecord(); + + // unknown record 0x0802 + rStrm.StartRecord( EXC_ID_0802, 16 + maDestRange.GetByteCount() ); + rStrm << EXC_ID_0802; // repeated record id ?!? + rStrm.WriteZeroBytes( 6 ); + rStrm << sal_uInt16( 0x0003 ) + << sal_uInt32( 0x00000000 ) + << sal_uInt16( 0x0010 ) + << maDestRange; + rStrm.EndRecord(); + + // WEBQRYSETTINGS record + nFlags = mpQryTables ? EXC_WQSETT_SPECTABLES : EXC_WQSETT_ALL; + rStrm.StartRecord( EXC_ID_WQSETT, 28 ); + rStrm << EXC_ID_WQSETT // repeated record id ?!? + << sal_uInt16( 0x0000 ) + << sal_uInt16( 0x0004 ) + << sal_uInt16( 0x0000 ) + << EXC_WQSETT_DEFAULTFLAGS + << nFlags; + rStrm.WriteZeroBytes( 10 ); + rStrm << mnRefresh // refresh delay in minutes + << EXC_WQSETT_FORMATFULL + << sal_uInt16( 0x0000 ); + rStrm.EndRecord(); + + // WEBQRYTABLES record + if( mpQryTables ) + { + rStrm.StartRecord( EXC_ID_WQTABLES, 4 + mpQryTables->GetByteCount() ); + rStrm << EXC_ID_WQTABLES // repeated record id ?!? + << sal_uInt16( 0x0000 ) + << *mpQryTables; // comma separated list of source tables + rStrm.EndRecord(); + } +} + + +// ---------------------------------------------------------------------------- + +XclExpWebQueryBuffer::XclExpWebQueryBuffer( const XclExpRoot& rRoot ) +{ + sal_uInt16 nTab = rRoot.GetScTab(); + ScDocument& rDoc = rRoot.GetDoc(); + SfxObjectShell* pShell = rRoot.GetDocShell(); + if( !pShell ) return; + Reference< XPropertySet > xPropSet( pShell->GetModel(), UNO_QUERY ); + if( !xPropSet.is() ) return; + + Reference< XAreaLinks > xAreaLinks; + ::getPropValue( xAreaLinks, xPropSet, OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_AREALINKS ) ) ); + Reference< XIndexAccess > xLinksIA( xAreaLinks, UNO_QUERY ); + if( !xLinksIA.is() ) return; + + const OUString aPropFilter( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_FILTER ) ); +// const OUString aPropFilterOpt( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_FILTOPT ) ); + const OUString aPropUrl( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_LINKURL ) ); + const OUString aPropRefresh( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_REFDELAY ) ); + OUString aFilter, /*aFilterOpt,*/ aUrl; + const OUString aWebQueryFilter( RTL_CONSTASCII_USTRINGPARAM( EXC_WEBQRY_FILTER ) ); + String aRangeName; + sal_Int32 nRefresh; + + sal_Int32 nCount = xLinksIA->getCount(); + for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex ) + { + Reference< XAreaLink > xAreaLink; + Any aLinkAny( xLinksIA->getByIndex( nIndex ) ); + if( aLinkAny >>= xAreaLink ) + { + CellRangeAddress aDestRange( xAreaLink->getDestArea() ); + if( aDestRange.Sheet == nTab ) + { + Reference< XPropertySet > xLinkProp( xAreaLink, UNO_QUERY ); + if( xLinkProp.is() && ::getPropValue( aFilter, xLinkProp, aPropFilter ) && (aFilter == aWebQueryFilter) ) + { + // get properties +// ::getPropValue( aFilterOpt, xLinkProp, aPropFilterOpt ); + ::getPropValue( aUrl, xLinkProp, aPropUrl ); + ::getPropValue( nRefresh, xLinkProp, aPropRefresh ); + + String aAbsDoc( ScGlobal::GetAbsDocName( aUrl, pShell ) ); + INetURLObject aUrlObj( aAbsDoc ); + String aWebQueryUrl( aUrlObj.getFSysPath( INetURLObject::FSYS_DOS ) ); + if( !aWebQueryUrl.Len() ) + aWebQueryUrl = aAbsDoc; + + // find range or create a new range + ScRange aScDestRange; + ScUnoConversion::FillScRange( aScDestRange, aDestRange ); + ScRangeData* pRangeData = rDoc.GetRangeName()->GetRangeAtBlock( aScDestRange ); + if( pRangeData ) + aRangeName = pRangeData->GetName(); + else + { + ExcName* pExcName = new ExcName( *rRoot.mpRD, aScDestRange, aUrlObj.getBase() ); + aRangeName = pExcName->GetName(); + rRoot.mpRD->pNameList->InsertSorted( *rRoot.mpRD, pExcName, nTab ); + } + + // create and store the web query record + Append( new XclExpWebQuery( aRangeName, aWebQueryUrl, xAreaLink->getSourceArea(), nRefresh ) ); + } + } + } + } +} + + +// ============================================================================ + |