diff options
Diffstat (limited to 'sot')
61 files changed, 19167 insertions, 0 deletions
diff --git a/sot/inc/absdev.hxx b/sot/inc/absdev.hxx new file mode 100644 index 000000000000..3d251d98e0b6 --- /dev/null +++ b/sot/inc/absdev.hxx @@ -0,0 +1,48 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SOT_ABSDEV_HXX +#define _SOT_ABSDEV_HXX + +#ifndef _TOOLS_SOLAR_H +#include <tools/solar.h> +#endif + +class JobSetup; +class AbstractDeviceData +{ +protected: + JobSetup * pJobSetup; +public: + virtual ~AbstractDeviceData() {} + virtual AbstractDeviceData * Copy() const = 0; + virtual BOOL Equals( const AbstractDeviceData & ) const = 0; + + JobSetup * GetJobSetup() const { return pJobSetup; } +}; + +#endif // _SOT_ABSDEV_HXX diff --git a/sot/inc/agg.hxx b/sot/inc/agg.hxx new file mode 100644 index 000000000000..2f8cc7587458 --- /dev/null +++ b/sot/inc/agg.hxx @@ -0,0 +1,68 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SOT_AGG_HXX +#define _SOT_AGG_HXX + +#include <tools/ownlist.hxx> + +/************** class SvAggregate ***************************************/ +/************************************************************************/ +class SotFactory; +class SotObject; +struct SvAggregate +{ + union + { + SotFactory * pFact; + SotObject * pObj; + }; + BOOL bFactory; + BOOL bMainObj; // TRUE, das Objekt, welches das casting steuert + + SvAggregate() + : pFact( NULL ) + , bFactory( FALSE ) + , bMainObj( FALSE ) {} + SvAggregate( SotObject * pObjP, BOOL bMainP ) + : pObj( pObjP ) + , bFactory( FALSE ) + , bMainObj( bMainP ) {} + SvAggregate( SotFactory * pFactP ) + : pFact( pFactP ) + , bFactory( TRUE ) + , bMainObj( FALSE ) {} +}; + +/************** class SvAggregateMemberList *****************************/ +/************************************************************************/ +class SvAggregateMemberList +{ + PRV_SV_DECL_OWNER_LIST(SvAggregateMemberList,SvAggregate) +}; + +#endif // _AGG_HXX diff --git a/sot/inc/clsids.hxx b/sot/inc/clsids.hxx new file mode 100644 index 000000000000..a64df510dd07 --- /dev/null +++ b/sot/inc/clsids.hxx @@ -0,0 +1,33 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _SOT_CLSIDS_HXX +#define _SOT_CLSIDS_HXX + +// all the definitions of the class ids are moved to the comphelper +#include <comphelper/classids.hxx> + +#endif diff --git a/sot/inc/filelist.hxx b/sot/inc/filelist.hxx new file mode 100644 index 000000000000..4c6c55534319 --- /dev/null +++ b/sot/inc/filelist.hxx @@ -0,0 +1,76 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FILELIST_HXX +#define _FILELIST_HXX + +#include <tools/stream.hxx> +#include "sot/sotdllapi.h" + +class FileStringList; + +class SOT_DLLPUBLIC FileList : public SvDataCopyStream +{ + FileStringList* pStrList; + +protected: + + // SvData-Methoden + virtual void Load( SvStream& ); + virtual void Save( SvStream& ); + virtual void Assign( const SvDataCopyStream& ); + + // Liste loeschen; + void ClearAll( void ); + +public: + + TYPEINFO(); + FileList(); + ~FileList(); + + // Zuweisungsoperator + FileList& operator=( const FileList& rFileList ); + + + // Im-/Export + SOT_DLLPUBLIC friend SvStream& operator<<( SvStream& rOStm, const FileList& rFileList ); + SOT_DLLPUBLIC friend SvStream& operator>>( SvStream& rIStm, FileList& rFileList ); + + // Clipboard, D&D usw. + static ULONG GetFormat(); + + + // Liste fuellen/abfragen + void AppendFile( const String& rStr ); + String GetFile( ULONG i ) const; + ULONG Count( void ) const; + +}; + +#endif // _FILELIST_HXX + diff --git a/sot/inc/makefile.mk b/sot/inc/makefile.mk new file mode 100644 index 000000000000..bc31cd07e06b --- /dev/null +++ b/sot/inc/makefile.mk @@ -0,0 +1,48 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=.. + +PRJNAME=sot +TARGET=inc + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk + +.IF "$(ENABLE_PCH)"!="" +ALLTAR : \ + $(SLO)$/precompiled.pch \ + $(SLO)$/precompiled_ex.pch + +.ENDIF # "$(ENABLE_PCH)"!="" + diff --git a/sot/inc/pch/precompiled_sot.cxx b/sot/inc/pch/precompiled_sot.cxx new file mode 100644 index 000000000000..fea8683f8074 --- /dev/null +++ b/sot/inc/pch/precompiled_sot.cxx @@ -0,0 +1,29 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_sot.hxx" + diff --git a/sot/inc/pch/precompiled_sot.hxx b/sot/inc/pch/precompiled_sot.hxx new file mode 100644 index 000000000000..4edee1275640 --- /dev/null +++ b/sot/inc/pch/precompiled_sot.hxx @@ -0,0 +1,32 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): Generated on 2006-09-01 17:50:02.092358 + +#ifdef PRECOMPILED_HEADERS +#endif + diff --git a/sot/inc/sot/exchange.hxx b/sot/inc/sot/exchange.hxx new file mode 100644 index 000000000000..dc67e72a4f82 --- /dev/null +++ b/sot/inc/sot/exchange.hxx @@ -0,0 +1,253 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SOT_EXCHANGE_HXX +#define _SOT_EXCHANGE_HXX + +#ifndef __SGI_STL_LIST +#include <list> +#endif +#ifndef __SGI_STL_VECTOR +#include <vector> +#endif +#include <tools/string.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/datatransfer/DataFlavor.hpp> +#ifndef _COM_SUN_STAR_DATATRANSFER_DND_DNDCONSTANTS_HDL_ +#include <com/sun/star/datatransfer/dnd/DNDConstants.hdl> +#endif +#include "sot/sotdllapi.h" + +class SotDataObject; + +namespace com { namespace sun { namespace star { namespace datatransfer { + class XTransferable; +} } } } + +// --------------------- +// - SotFormatStringId - +// --------------------- + +typedef ULONG SotFormatStringId; + +// ---------------- +// - DataFlavorEx - +// ---------------- + +struct DataFlavorEx : public ::com::sun::star::datatransfer::DataFlavor +{ + SotFormatStringId mnSotId; +}; + +typedef ::std::vector< ::com::sun::star::datatransfer::DataFlavor > DataFlavorVector; +typedef ::std::vector< DataFlavorEx > _DataFlavorExVector; + +// JP 23.03.2001 - this struct is only for "hide" the STD of the vetor, +// because our makefile filter all this symbols and so nowbody can use +// these struct in any interfacses. +struct DataFlavorExVector : public _DataFlavorExVector +{ +}; + +typedef ::std::list< ::com::sun::star::datatransfer::DataFlavor > DataFlavorList; +typedef ::std::list< DataFlavorEx > DataFlavorExList; + +SOT_DLLPUBLIC sal_Bool IsFormatSupported( const DataFlavorExVector& rDataFlavorExVector, + ULONG nId ); + +// ------------------------- +// - Vordefinierte Formate - +// ------------------------- + +// Die Reihenfolge und die Werte dürfen nicht geändert werden, +// da die Implementation sich darauf verläßt. +// Standard-Formate fuer die es auch Copy/Paste-Methoden gibt +#define FORMAT_STRING 1 +#define FORMAT_BITMAP 2 +#define FORMAT_GDIMETAFILE 3 +#define FORMAT_PRIVATE 4 +#define FORMAT_FILE 5 +#define FORMAT_FILE_LIST 6 + +// Weitere Standardformate (diese gehen nur ueber CopyData/PasteData) +#define FORMAT_RTF 10 + +// Source-Options +#define EXCHG_SOURCE_MOVEABLE ((USHORT)0x0001) +#define EXCHG_SOURCE_COPYABLE ((USHORT)0x0002) +#define EXCHG_SOURCE_LINKABLE ((USHORT)0x0004) +#define EXCHG_SOURCE_PRINTABLE ((USHORT)0x0008) +#define EXCHG_SOURCE_DISCARDABLE ((USHORT)0x0010) +#define EXCHG_SOURCE_ALL ((USHORT)0x001F) +#define EXCHG_SOURCE_DEF_COPYABLE ((USHORT)0x0020) + +// Aktionen +#define EXCHG_ACTION_MASK ((USHORT)0x00FF) +#define EXCHG_INOUT_ACTION_NONE ((USHORT)com::sun::star::datatransfer::dnd::DNDConstants::ACTION_NONE) +#define EXCHG_IN_ACTION_DEFAULT EXCHG_INOUT_ACTION_NONE +#define EXCHG_IN_ACTION_MOVE ((USHORT)com::sun::star::datatransfer::dnd::DNDConstants::ACTION_MOVE) +#define EXCHG_IN_ACTION_COPY ((USHORT)com::sun::star::datatransfer::dnd::DNDConstants::ACTION_COPY) +#define EXCHG_IN_ACTION_LINK ((USHORT)com::sun::star::datatransfer::dnd::DNDConstants::ACTION_LINK) +#define EXCHG_INOUT_ACTION_PRINT ((USHORT)8) +#define EXCHG_INOUT_ACTION_DISCARD ((USHORT)16) +#define EXCHG_OUT_ACTION_INSERT_OBJ ((USHORT)17) +#define EXCHG_OUT_ACTION_INSERT_BOOKMARK ((USHORT)18) +#define EXCHG_OUT_ACTION_INSERT_FILELINK ((USHORT)19) +#define EXCHG_OUT_ACTION_INSERT_FILE ((USHORT)20) +#define EXCHG_OUT_ACTION_INSERT_FILELIST ((USHORT)21) +#define EXCHG_OUT_ACTION_INSERT_IMAGEMAP ((USHORT)22) +#define EXCHG_OUT_ACTION_INSERT_OLE ((USHORT)23) +#define EXCHG_OUT_ACTION_INSERT_INTERACTIVE ((USHORT)24) +#define EXCHG_OUT_ACTION_INSERT_URLBUTTON ((USHORT)25) +#define EXCHG_OUT_ACTION_INSERT_CHAOSOBJ ((USHORT)26) // OBSOLET ab 500.b ? +#define EXCHG_OUT_ACTION_REPLACE_OBJ ((USHORT)27) +#define EXCHG_OUT_ACTION_REPLACE_LINK ((USHORT)28) +#define EXCHG_OUT_ACTION_REPLACE_IMAGEMAP ((USHORT)29) +#define EXCHG_OUT_ACTION_GET_ATTRIBUTES ((USHORT)30) +#define EXCHG_OUT_ACTION_UPLOAD ((USHORT)31) // OBSOLET ab 500.b ? +#define EXCHG_OUT_ACTION_MOVE_FILE ((USHORT)32) +#define EXCHG_OUT_ACTION_MOVE_FILELIST ((USHORT)33) +#define EXCHG_OUT_ACTION_UPDATE_RANGE ((USHORT)34) +#define EXCHG_OUT_ACTION_INSERT_PRIVATE ((USHORT)35) +#define EXCHG_OUT_ACTION_INSERT_HTML ((USHORT)36) +#define EXCHG_OUT_ACTION_MOVE_PRIVATE ((USHORT)37) +#define EXCHG_OUT_ACTION_INSERT_STRING ((USHORT)38) +#define EXCHG_OUT_ACTION_INSERT_DRAWOBJ ((USHORT)39) +#define EXCHG_OUT_ACTION_INSERT_SVXB ((USHORT)40) +#define EXCHG_OUT_ACTION_INSERT_GDIMETAFILE ((USHORT)41) +#define EXCHG_OUT_ACTION_INSERT_BITMAP ((USHORT)42) +#define EXCHG_OUT_ACTION_INSERT_DDE ((USHORT)43) +#define EXCHG_OUT_ACTION_INSERT_HYPERLINK ((USHORT)44) +#define EXCHG_OUT_ACTION_REPLACE_DRAWOBJ ((USHORT)45) +#define EXCHG_OUT_ACTION_REPLACE_SVXB ((USHORT)46) +#define EXCHG_OUT_ACTION_REPLACE_GDIMETAFILE ((USHORT)47) +#define EXCHG_OUT_ACTION_REPLACE_BITMAP ((USHORT)48) +#define EXCHG_OUT_ACTION_REPLACE_GRAPH ((USHORT)49) +#define EXCHG_OUT_ACTION_INSERT_GRAPH ((USHORT)50) +#define EXCHG_OUT_ACTION_INSERT_MSGATTACH ((USHORT)51) // obsolet ab 500.b ? +#define EXCHG_OUT_ACTION_COPY_CHAOSOBJ ((USHORT)52) +#define EXCHG_OUT_ACTION_MOVE_CHAOSOBJ ((USHORT)53) +#define EXCHG_OUT_ACTION_COPY_MSGATTACH ((USHORT)54) +#define EXCHG_OUT_ACTION_COPY_BOOKMARK ((USHORT)55) +#define EXCHG_OUT_ACTION_COPY_FILE ((USHORT)56) + +#define EXCHG_OUT_ACTION_FLAG_CREATE_THEME ((USHORT)0x0100) +#define EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE ((USHORT)0x0200) +#define EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP ((USHORT)0x0400) +#define EXCHG_OUT_ACTION_FLAG_REPLACE_IMAGEMAP ((USHORT)0x0800) +#define EXCHG_OUT_ACTION_FLAG_FILL ((USHORT)0x1000) +#define EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL ((USHORT)0x2000) + +// Ziele +#define EXCHG_DEST_DOC_OLEOBJ 1 +#define EXCHG_DEST_CHARTDOC_OLEOBJ 2 +#define EXCHG_DEST_DOC_TEXTFRAME 3 +#define EXCHG_DEST_DOC_GRAPHOBJ 4 +#define EXCHG_DEST_DOC_LNKD_GRAPHOBJ 5 +#define EXCHG_DEST_DOC_GRAPH_W_IMAP 6 +#define EXCHG_DEST_DOC_LNKD_GRAPH_W_IMAP 7 +#define EXCHG_DEST_DOC_IMAPREGION 8 +#define EXCHG_DEST_DOC_DRAWOBJ 9 +#define EXCHG_DEST_DOC_URLBUTTON 10 +#define EXCHG_DEST_DOC_URLFIELD 11 +#define EXCHG_DEST_DOC_GROUPOBJ 12 +#define EXCHG_DEST_SWDOC_FREE_AREA 13 +#define EXCHG_DEST_SCDOC_FREE_AREA 14 +#define EXCHG_DEST_SDDOC_FREE_AREA 15 +#define EXCHG_DEST_DOC_TEXTFRAME_WEB 16 +#define EXCHG_DEST_SWDOC_FREE_AREA_WEB 17 + +// ------------ +// - Exchange - +// ------------ +class SvGlobalName; +class SOT_DLLPUBLIC SotExchange +{ +public: + static ULONG RegisterFormat( const ::com::sun::star::datatransfer::DataFlavor& rFlavor ); + static ULONG RegisterFormatName( const String& rName ); + static ULONG RegisterFormatMimeType( const String& rMimeType ); + + static ULONG GetFormat( const ::com::sun::star::datatransfer::DataFlavor& rFlavor ); + static String GetFormatName( ULONG nFormat ); + static sal_Bool GetFormatDataFlavor( ULONG nFormat, ::com::sun::star::datatransfer::DataFlavor& rFlavor ); + static String GetFormatMimeType( ULONG nFormat ); + static BOOL IsInternal( const SvGlobalName& ); + static ULONG GetFormatIdFromMimeType( const String& rMimeType ); + + // bestimme die SotFormatStringId von dem registrierten Format + //JP 12.11.98: diese 3 Methoden sind ab sofort ueberfluessig, da + // die ClipboardIds statisch sind und aequivalent zur + // SotFormatStringId ist! + static SotFormatStringId GetFormatStringId( ULONG nFormat ) + { return nFormat; } + static SotFormatStringId GetFormatStringId( const String& rName ) + { return SotExchange::RegisterFormatMimeType( rName ); } + static ULONG RegisterSotFormatName( SotFormatStringId nId ) + { return nId; } + + // same for XTransferable interface + static USHORT GetExchangeAction( + // XTransferable + const DataFlavorExVector& rDataFlavorExVector, + // Ziel der Aktion (EXCHG_DEST_*) + USHORT nDestination, + // Aktionen, die Quelle unterstuetzt (EXCHG_SOURCE_...) + USHORT nSourceOptions, + // vom Anwender gewaehlte Aktion (EXCHG_IN_*, EXCHG_INOUT_*) + USHORT nUserAction, + // In:- Out: Zu benutzendes Format + ULONG& rFormat, + // In:- Out: Default-Action (EXCHG_IN_*, EXCHG_INOUT_*) + USHORT& rDefaultAction, + // In:- optional - check only for this specific format + ULONG nOnlyTestFormat = 0, + // In:- optional - check the contents of Xtransferable + const ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable >* pxTransferable = NULL ); + + // same for XTransferable interface + static USHORT GetExchangeAction( + // XTransferable + const ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable >& rxTransferable, + // Ziel der Aktion (EXCHG_DEST_*) + USHORT nDestination, + // Aktionen, die Quelle unterstuetzt (EXCHG_SOURCE_...) + USHORT nSourceOptions, + // vom Anwender gewaehlte Aktion (EXCHG_IN_*, EXCHG_INOUT_*) + USHORT nUserAction, + // In:- Out: Zu benutzendes Format + ULONG& rFormat, + // In:- Out: Default-Action (EXCHG_IN_*, EXCHG_INOUT_*) + USHORT& rDefaultAction, + // In:- optional - check only for this specific format + ULONG nOnlyTestFormat = 0 ); + + static USHORT IsChart( const SvGlobalName& rName ); + static USHORT IsMath( const SvGlobalName& rName ); +}; + +#endif // _EXCHANGE_HXX diff --git a/sot/inc/sot/factory.hxx b/sot/inc/sot/factory.hxx new file mode 100644 index 000000000000..08dd21a88aa5 --- /dev/null +++ b/sot/inc/sot/factory.hxx @@ -0,0 +1,91 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SOT_FACTORY_HXX +#define _SOT_FACTORY_HXX + +#ifndef _TOOLS_GLOBNAME_HXX +#include <tools/globname.hxx> +#endif +#ifndef _TOOLS_RTTI_HXX +#include <tools/rtti.hxx> +#endif +#include "sot/sotdllapi.h" + +/************************************************************************* +*************************************************************************/ +class SotObject; +class SotFactory; + +DECLARE_LIST( SotFactoryList, SotFactory * ) +typedef void * (*CreateInstanceType)( SotObject ** ); + +//==================class SotFactory======================================= +class SOT_DLLPUBLIC SotFactory : public SvGlobalName +{ + USHORT nSuperCount; // Anzahl der Superklassen + const SotFactory ** pSuperClasses; // Superklassen + CreateInstanceType pCreateFunc; + + String aClassName; + + static BOOL ExistTest( const SvGlobalName & ); +protected: + virtual ~SotFactory(); +public: + TYPEINFO(); + static void DeInit(); + static void IncSvObjectCount( SotObject * = NULL ); + static void DecSvObjectCount( SotObject * = NULL ); + static UINT32 GetSvObjectCount(); + static void TestInvariant(); + + static const SotFactory * Find( const SvGlobalName & ); + static const SotFactoryList * GetFactoryList(); + + SotFactory( const SvGlobalName &, + const String & rClassName, CreateInstanceType ); + + void PutSuperClass( const SotFactory * ); + virtual void * CreateInstance( SotObject ** ppObj = NULL ) const; + void * CastAndAddRef( SotObject * ) const; + void * AggCastAndAddRef( SotObject * ) const; + + BOOL Is( const SotFactory * pSuperClass ) const; + const SotFactory * GetSuper( USHORT nPos ) const + { + return nPos < nSuperCount ? + pSuperClasses[ nPos ] + : NULL; + } + +private: + SOT_DLLPRIVATE SotFactory( const SotFactory & ); + SOT_DLLPRIVATE SotFactory & operator = ( const SotFactory & ); +}; + +#endif // _FACTORY_HXX diff --git a/sot/inc/sot/formats.hxx b/sot/inc/sot/formats.hxx new file mode 100644 index 000000000000..c9d7a3e69d78 --- /dev/null +++ b/sot/inc/sot/formats.hxx @@ -0,0 +1,191 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SOT_FORMATS_HXX +#define _SOT_FORMATS_HXX + +#ifdef _SOT_FORMATS_INCLUDE_SYSTEMFORMATS + +#ifdef WNT +#ifdef _MSC_VER +#pragma warning(push, 1) +#pragma warning(disable: 4917) +#endif +#include <tools/prewin.h> +#include <shlobj.h> +#include <tools/postwin.h> +#ifdef _MSC_VER +#pragma warning(pop) +#endif +#endif + +#endif +#include <sot/exchange.hxx> + +#define SOT_FORMAT_SYSTEM_START ((ULONG)0) +#define SOT_FORMAT_STRING ((ULONG)FORMAT_STRING) +#define SOT_FORMAT_BITMAP ((ULONG)FORMAT_BITMAP) +#define SOT_FORMAT_GDIMETAFILE ((ULONG)FORMAT_GDIMETAFILE) +#define SOT_FORMAT_PRIVATE ((ULONG)FORMAT_PRIVATE) +#define SOT_FORMAT_FILE ((ULONG)FORMAT_FILE) +#define SOT_FORMAT_FILE_LIST ((ULONG)FORMAT_FILE_LIST) +#define SOT_FORMAT_RTF ((ULONG)FORMAT_RTF) + +#define SOT_FORMATSTR_ID_DRAWING ((ULONG)11) +#define SOT_FORMATSTR_ID_SVXB ((ULONG)12) +#define SOT_FORMATSTR_ID_SVIM ((ULONG)13) +#define SOT_FORMATSTR_ID_XFA ((ULONG)14) +#define SOT_FORMATSTR_ID_EDITENGINE ((ULONG)15) +#define SOT_FORMATSTR_ID_INTERNALLINK_STATE ((ULONG)16) +#define SOT_FORMATSTR_ID_SOLK ((ULONG)17) +#define SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ((ULONG)18) +#define SOT_FORMATSTR_ID_TREELISTBOX ((ULONG)19) +#define SOT_FORMATSTR_ID_NATIVE ((ULONG)20) +#define SOT_FORMATSTR_ID_OWNERLINK ((ULONG)21) +#define SOT_FORMATSTR_ID_STARSERVER ((ULONG)22) +#define SOT_FORMATSTR_ID_STAROBJECT ((ULONG)23) +#define SOT_FORMATSTR_ID_APPLETOBJECT ((ULONG)24) +#define SOT_FORMATSTR_ID_PLUGIN_OBJECT ((ULONG)25) +#define SOT_FORMATSTR_ID_STARWRITER_30 ((ULONG)26) +#define SOT_FORMATSTR_ID_STARWRITER_40 ((ULONG)27) +#define SOT_FORMATSTR_ID_STARWRITER_50 ((ULONG)28) +#define SOT_FORMATSTR_ID_STARWRITERWEB_40 ((ULONG)29) +#define SOT_FORMATSTR_ID_STARWRITERWEB_50 ((ULONG)30) +#define SOT_FORMATSTR_ID_STARWRITERGLOB_40 ((ULONG)31) +#define SOT_FORMATSTR_ID_STARWRITERGLOB_50 ((ULONG)32) +#define SOT_FORMATSTR_ID_STARDRAW ((ULONG)33) +#define SOT_FORMATSTR_ID_STARDRAW_40 ((ULONG)34) +#define SOT_FORMATSTR_ID_STARIMPRESS_50 ((ULONG)35) +#define SOT_FORMATSTR_ID_STARDRAW_50 ((ULONG)36) +#define SOT_FORMATSTR_ID_STARCALC ((ULONG)37) +#define SOT_FORMATSTR_ID_STARCALC_40 ((ULONG)38) +#define SOT_FORMATSTR_ID_STARCALC_50 ((ULONG)39) +#define SOT_FORMATSTR_ID_STARCHART ((ULONG)40) +#define SOT_FORMATSTR_ID_STARCHART_40 ((ULONG)41) +#define SOT_FORMATSTR_ID_STARCHART_50 ((ULONG)42) +#define SOT_FORMATSTR_ID_STARIMAGE ((ULONG)43) +#define SOT_FORMATSTR_ID_STARIMAGE_40 ((ULONG)44) +#define SOT_FORMATSTR_ID_STARIMAGE_50 ((ULONG)45) +#define SOT_FORMATSTR_ID_STARMATH ((ULONG)46) +#define SOT_FORMATSTR_ID_STARMATH_40 ((ULONG)47) +#define SOT_FORMATSTR_ID_STARMATH_50 ((ULONG)48) +#define SOT_FORMATSTR_ID_STAROBJECT_PAINTDOC ((ULONG)49) +#define SOT_FORMATSTR_ID_FILLED_AREA ((ULONG)50) +#define SOT_FORMATSTR_ID_HTML ((ULONG)51) +#define SOT_FORMATSTR_ID_HTML_SIMPLE ((ULONG)52) +#define SOT_FORMATSTR_ID_CHAOS ((ULONG)53) +#define SOT_FORMATSTR_ID_CNT_MSGATTACHFILE ((ULONG)54) +#define SOT_FORMATSTR_ID_BIFF_5 ((ULONG)55) +#define SOT_FORMATSTR_ID_BIFF__5 ((ULONG)56) +#define SOT_FORMATSTR_ID_SYLK ((ULONG)57) +#define SOT_FORMATSTR_ID_SYLK_BIGCAPS ((ULONG)58) +#define SOT_FORMATSTR_ID_LINK ((ULONG)59) +#define SOT_FORMATSTR_ID_DIF ((ULONG)60) +#define SOT_FORMATSTR_ID_STARDRAW_TABBAR ((ULONG)61) +#define SOT_FORMATSTR_ID_SONLK ((ULONG)62) +#define SOT_FORMATSTR_ID_MSWORD_DOC ((ULONG)63) +#define SOT_FORMATSTR_ID_STAR_FRAMESET_DOC ((ULONG)64) +#define SOT_FORMATSTR_ID_OFFICE_DOC ((ULONG)65) +#define SOT_FORMATSTR_ID_NOTES_DOCINFO ((ULONG)66) +#define SOT_FORMATSTR_ID_NOTES_HNOTE ((ULONG)67) +#define SOT_FORMATSTR_ID_NOTES_NATIVE ((ULONG)68) +#define SOT_FORMATSTR_ID_SFX_DOC ((ULONG)69) +#define SOT_FORMATSTR_ID_EVDF ((ULONG)70) +#define SOT_FORMATSTR_ID_ESDF ((ULONG)71) +#define SOT_FORMATSTR_ID_IDF ((ULONG)72) +#define SOT_FORMATSTR_ID_EFTP ((ULONG)73) +#define SOT_FORMATSTR_ID_EFD ((ULONG)74) +#define SOT_FORMATSTR_ID_SVX_FORMFIELDEXCH ((ULONG)75) +#define SOT_FORMATSTR_ID_EXTENDED_TABBAR ((ULONG)76) +#define SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ((ULONG)77) +#define SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ((ULONG)78) +#define SOT_FORMATSTR_ID_SBA_PRIVATE_URL ((ULONG)79) +#define SOT_FORMATSTR_ID_SBA_TABED ((ULONG)80) +#define SOT_FORMATSTR_ID_SBA_TABID ((ULONG)81) +#define SOT_FORMATSTR_ID_SBA_JOIN ((ULONG)82) +#define SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ((ULONG)83) +#define SOT_FORMATSTR_ID_LINKSRCDESCRIPTOR ((ULONG)84) +#define SOT_FORMATSTR_ID_EMBED_SOURCE ((ULONG)85) +#define SOT_FORMATSTR_ID_LINK_SOURCE ((ULONG)86) +#define SOT_FORMATSTR_ID_EMBEDDED_OBJ ((ULONG)87) +#define SOT_FORMATSTR_ID_FILECONTENT ((ULONG)88) +#define SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ((ULONG)89) +#define SOT_FORMATSTR_ID_FILENAME ((ULONG)90) +#define SOT_FORMATSTR_ID_SD_OLE ((ULONG)91) +#define SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ((ULONG)92) +#define SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ((ULONG)93) +#define SOT_FORMATSTR_ID_OBJECTDESCRIPTOR_OLE ((ULONG)94) +#define SOT_FORMATSTR_ID_LINKSRCDESCRIPTOR_OLE ((ULONG)95) +#define SOT_FORMATSTR_ID_LINK_SOURCE_OLE ((ULONG)96) +#define SOT_FORMATSTR_ID_SBA_CTRLDATAEXCHANGE ((ULONG)97) +#define SOT_FORMATSTR_ID_OUTPLACE_OBJ ((ULONG)98) +#define SOT_FORMATSTR_ID_CNT_OWN_CLIP ((ULONG)99) +#define SOT_FORMATSTR_ID_INET_IMAGE ((ULONG)100) +#define SOT_FORMATSTR_ID_NETSCAPE_IMAGE ((ULONG)101) +#define SOT_FORMATSTR_ID_SBA_FORMEXCHANGE ((ULONG)102) +#define SOT_FORMATSTR_ID_SBA_REPORTEXCHANGE ((ULONG)103) +#define SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ((ULONG)104) +#define SOT_FORMATSTR_ID_STARCHARTDOCUMENT_50 ((ULONG)105) +#define SOT_FORMATSTR_ID_GRAPHOBJ ((ULONG)106) +#define SOT_FORMATSTR_ID_STARWRITER_60 ((ULONG)107) +#define SOT_FORMATSTR_ID_STARWRITERWEB_60 ((ULONG)108) +#define SOT_FORMATSTR_ID_STARWRITERGLOB_60 ((ULONG)109) +#define SOT_FORMATSTR_ID_STARDRAW_60 ((ULONG)110) +#define SOT_FORMATSTR_ID_STARIMPRESS_60 ((ULONG)111) +#define SOT_FORMATSTR_ID_STARCALC_60 ((ULONG)112) +#define SOT_FORMATSTR_ID_STARCHART_60 ((ULONG)113) +#define SOT_FORMATSTR_ID_STARMATH_60 ((ULONG)114) +#define SOT_FORMATSTR_ID_WMF ((ULONG)115) +#define SOT_FORMATSTR_ID_DBACCESS_QUERY ((ULONG)116) +#define SOT_FORMATSTR_ID_DBACCESS_TABLE ((ULONG)117) +#define SOT_FORMATSTR_ID_DBACCESS_COMMAND ((ULONG)118) +#define SOT_FORMATSTR_ID_DIALOG_60 ((ULONG)119) +#define SOT_FORMATSTR_ID_EMF ((ULONG)120) +#define SOT_FORMATSTR_ID_BIFF_8 ((ULONG)121) +#define SOT_FORMATSTR_ID_BMP ((ULONG)122) +#define SOT_FORMATSTR_ID_HTML_NO_COMMENT ((ULONG)123) +#define SOT_FORMATSTR_ID_STARWRITER_8 ((ULONG)124) +#define SOT_FORMATSTR_ID_STARWRITERWEB_8 ((ULONG)125) +#define SOT_FORMATSTR_ID_STARWRITERGLOB_8 ((ULONG)126) +#define SOT_FORMATSTR_ID_STARDRAW_8 ((ULONG)127) +#define SOT_FORMATSTR_ID_STARIMPRESS_8 ((ULONG)128) +#define SOT_FORMATSTR_ID_STARCALC_8 ((ULONG)129) +#define SOT_FORMATSTR_ID_STARCHART_8 ((ULONG)130) +#define SOT_FORMATSTR_ID_STARMATH_8 ((ULONG)131) +#define SOT_FORMATSTR_ID_XFORMS ((ULONG)132) +#define SOT_FORMATSTR_ID_STARWRITER_8_TEMPLATE ((ULONG)133) +#define SOT_FORMATSTR_ID_STARDRAW_8_TEMPLATE ((ULONG)134) +#define SOT_FORMATSTR_ID_STARIMPRESS_8_TEMPLATE ((ULONG)135) +#define SOT_FORMATSTR_ID_STARCALC_8_TEMPLATE ((ULONG)136) +#define SOT_FORMATSTR_ID_STARCHART_8_TEMPLATE ((ULONG)137) +#define SOT_FORMATSTR_ID_STARMATH_8_TEMPLATE ((ULONG)138) +#define SOT_FORMATSTR_ID_STARBASE_8 ((ULONG)139) +#define SOT_FORMATSTR_ID_HC_GDIMETAFILE ((ULONG)140) +#define SOT_FORMATSTR_ID_USER_END SOT_FORMATSTR_ID_HC_GDIMETAFILE + +#endif // _SOT_FORMATS_HXX + diff --git a/sot/inc/sot/object.hxx b/sot/inc/sot/object.hxx new file mode 100644 index 000000000000..db2ac3b30ffc --- /dev/null +++ b/sot/inc/sot/object.hxx @@ -0,0 +1,470 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SOT_OBJECT_HXX +#define _SOT_OBJECT_HXX + +#include <sot/sotref.hxx> +#ifndef _SOT_SOTDATA_HXX +#include <sot/sotdata.hxx> +#endif +#ifndef _TOOLS_GLOBNAME_HXX +#include <tools/globname.hxx> +#endif +#include "sot/sotdllapi.h" + +/************************************************************************* +*************************************************************************/ + +#define TEST_INVARIANT +#ifdef TEST_INVARIANT +#define SO2_DECL_INVARIANT() \ + virtual void TestObjRef( BOOL bFree ); \ + void TestMemberObjRef( BOOL bFree ); \ + virtual void TestInvariant( BOOL bPrint ); \ + void TestMemberInvariant( BOOL bPrint ); + +#define SO2_IMPL_INVARIANT(ClassName) \ +void __EXPORT ClassName::TestObjRef( BOOL bFree ) \ +{ \ + TestMemberObjRef( bFree ); \ +} \ +void __EXPORT ClassName::TestInvariant( BOOL bPrint ) \ +{ \ + TestMemberInvariant( bPrint ); \ +} + +#define SO2_IMPL_INVARIANT1(ClassName,Super1) \ +void __EXPORT ClassName::TestObjRef( BOOL bFree ) \ +{ \ + TestMemberObjRef( bFree ); \ + Super1::TestObjRef( bFree ); \ +} \ +void __EXPORT ClassName::TestInvariant( BOOL bPrint ) \ +{ \ + TestMemberInvariant( bPrint ); \ + Super1::TestInvariant( bPrint ); \ +} + +#define SO2_IMPL_INVARIANT2(ClassName,Super1,Super2) \ +void __EXPORT ClassName::TestObjRef( BOOL bFree ) \ +{ \ + TestMemberObjRef( bFree ); \ + Super1::TestObjRef( bFree ); \ + Super2::TestObjRef( bFree ); \ +} \ +void __EXPORT ClassName::TestInvariant( BOOL bPrint ) \ +{ \ + TestMemberInvariant( bPrint ); \ + Super1::TestInvariant( bPrint ); \ + Super2::TestInvariant( bPrint ); \ +} + +#define SO2_IMPL_INVARIANT3(ClassName,Super1,Super2,Super3) \ +void __EXPORT ClassName::TestObjRef( BOOL bFree ) \ +{ \ + TestMemberObjRef( bFree ); \ + Super1::TestObjRef( bFree ); \ + Super2::TestObjRef( bFree ); \ + Super3::TestObjRef( bFree ); \ +} \ +void __EXPORT ClassName::TestInvariant( BOOL bPrint ) \ +{ \ + TestMemberInvariant( bPrint ); \ + Super1::TestInvariant( bPrint ); \ + Super2::TestInvariant( bPrint ); \ + Super3::TestInvariant( bPrint ); \ +} + +#define SO2_IMPL_INVARIANT4(ClassName,Super1,Super2,Super3,Super4) \ +void __EXPORT ClassName::TestObjRef( BOOL bFree ) \ +{ \ + TestMemberObjRef( bFree ); \ + Super1::TestObjRef( bFree ); \ + Super2::TestObjRef( bFree ); \ + Super3::TestObjRef( bFree ); \ + Super4::TestObjRef( bFree ); \ +} \ +void __EXPORT ClassName::TestInvariant( BOOL bPrint ) \ +{ \ + TestMemberInvariant( bPrint ); \ + Super1::TestInvariant( bPrint ); \ + Super2::TestInvariant( bPrint ); \ + Super3::TestInvariant( bPrint ); \ + Super4::TestInvariant( bPrint ); \ +} + +#ifdef DBG_UTIL +#define CALL_TEST_INVARIANT() SotFactory::TestInvariant() +#else +#define CALL_TEST_INVARIANT() +#endif // DBG_UTIL + +#else // TEST_INVARIANT + +#define SO2_DECL_INVARIANT() + +#define SO2_IMPL_INVARIANT(ClassName) +#define SO2_IMPL_INVARIANT1(ClassName,Super1) +#define SO2_IMPL_INVARIANT2(ClassName,Super1,Super2) +#define SO2_IMPL_INVARIANT3(ClassName,Super1,Super2,Super3) +#define SO2_IMPL_INVARIANT4(ClassName,Super1,Super2,Super3,Super4) + +#define CALL_TEST_INVARIANT() + +#endif // TEST_INVARIANT + +/************************************************************************** +**************************************************************************/ +#define SO2_DECL_BASIC_CLASS_DLL(ClassName,FacName) \ +private: \ + static SotFactory ** GetFactoryAdress() \ + { return &(FacName->p##ClassName##Factory); } \ +public: \ + static void * CreateInstance( SotObject ** = NULL ); \ + static SotFactory * ClassFactory(); \ + virtual const SotFactory * GetSvFactory() const; \ + virtual void * Cast( const SotFactory * ); + +#define SO2_DECL_BASIC_CLASS(ClassName) \ +private: \ + static SotFactory * pFactory; \ + static SotFactory ** GetFactoryAdress() { return &pFactory; } \ +public: \ + static void * CreateInstance( SotObject ** = NULL ); \ + static SotFactory * ClassFactory(); \ + virtual const SotFactory * GetSvFactory() const; \ + virtual void * Cast( const SotFactory * ); + +/************************************************************************** +**************************************************************************/ +#define SO2_IMPL_BASIC_CLASS_DLL(ClassName,FactoryName,GlobalName) \ +SotFactory * ClassName::ClassFactory() \ +{ \ + SotFactory **ppFactory = GetFactoryAdress(); \ + if( !*ppFactory ) \ + { \ + *ppFactory = new FactoryName( GlobalName, \ + String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( #ClassName ) ), \ + ClassName::CreateInstance ); \ + } \ + return *ppFactory; \ +} \ +void * __EXPORT ClassName::CreateInstance( SotObject ** ppObj ) \ +{ \ + ClassName * p = new ClassName(); \ + if( ppObj ) \ + *ppObj = p; \ + return p; \ +} \ +const SotFactory * __EXPORT ClassName::GetSvFactory() const \ +{ \ + return ClassFactory(); \ +} \ +void * __EXPORT ClassName::Cast( const SotFactory * pFact ) \ +{ \ + void * pRet = NULL; \ + if( !pFact || pFact == ClassFactory() ) \ + pRet = this; \ + return pRet; \ +} + +#define SO2_IMPL_BASIC_CLASS(ClassName,FactoryName,GlobalName) \ +SotFactory * ClassName::pFactory = NULL; \ + SO2_IMPL_BASIC_CLASS_DLL(ClassName,FactoryName,GlobalName) + +/************************************************************************** +**************************************************************************/ +#define SO2_IMPL_BASIC_CLASS1_DLL(ClassName,FactoryName,Super1,GlobalName)\ +SotFactory * ClassName::ClassFactory() \ +{ \ + SotFactory **ppFactory = GetFactoryAdress(); \ + if( !*ppFactory ) \ + { \ + *ppFactory = new FactoryName( GlobalName, \ + String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( #ClassName ) ), \ + ClassName::CreateInstance ); \ + (*ppFactory)->PutSuperClass( Super1::ClassFactory() ); \ + } \ + return *ppFactory; \ +} \ +void * __EXPORT ClassName::CreateInstance( SotObject ** ppObj ) \ +{ \ + ClassName * p = new ClassName(); \ + Super1* pSuper1 = p; \ + SotObject* pBasicObj = pSuper1; \ + if( ppObj ) \ + *ppObj = pBasicObj; \ + return p; \ +} \ +const SotFactory * __EXPORT ClassName::GetSvFactory() const \ +{ \ + return ClassFactory(); \ +} \ +void * __EXPORT ClassName::Cast( const SotFactory * pFact ) \ +{ \ + void * pRet = NULL; \ + if( !pFact || pFact == ClassFactory() ) \ + pRet = this; \ + if( !pRet ) \ + pRet = Super1::Cast( pFact ); \ + return pRet; \ +} + +#define SO2_IMPL_BASIC_CLASS1(ClassName,FactoryName,Super1,GlobalName) \ +SotFactory * ClassName::pFactory = NULL; \ + SO2_IMPL_BASIC_CLASS1_DLL(ClassName,FactoryName,Super1,GlobalName) + +/************************************************************************** +**************************************************************************/ +#define SO2_IMPL_BASIC_CLASS2_DLL(ClassName,FactoryName,Super1,Super2,GlobalName) \ +SotFactory * ClassName::ClassFactory() \ +{ \ + SotFactory **ppFactory = GetFactoryAdress(); \ + if( !*ppFactory ) \ + { \ + *ppFactory = new FactoryName( GlobalName, \ + String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( #ClassName ) ), \ + ClassName::CreateInstance ); \ + (*ppFactory)->PutSuperClass( Super1::ClassFactory() ); \ + (*ppFactory)->PutSuperClass( Super2::ClassFactory() ); \ + } \ + return *ppFactory; \ +} \ +void * __EXPORT ClassName::CreateInstance( SotObject ** ppObj ) \ +{ \ + ClassName * p = new ClassName(); \ + if( ppObj ) \ + *ppObj = p; \ + return p; \ +} \ +const SotFactory * __EXPORT ClassName::GetSvFactory() const \ +{ \ + return ClassFactory(); \ +} \ +void * __EXPORT ClassName::Cast( const SotFactory * pFact ) \ +{ \ + void * pRet = NULL; \ + if( !pFact || pFact == ClassFactory() ) \ + pRet = this; \ + if( !pRet ) \ + pRet = Super1::Cast( pFact ); \ + if( !pRet ) \ + pRet = Super2::Cast( pFact ); \ + return pRet; \ +} +#define SO2_IMPL_BASIC_CLASS2(ClassName,FactoryName,Super1,Super2,GlobalName) \ +SotFactory * ClassName::pFactory = NULL; \ + SO2_IMPL_BASIC_CLASS2_DLL(ClassName,FactoryName,Super1,Super2,GlobalName) + +/************************************************************************** +**************************************************************************/ +#define SO2_IMPL_BASIC_CLASS3_DLL(ClassName,FactoryName,Super1,Super2,Super3,GlobalName) \ +SotFactory * ClassName::ClassFactory() \ +{ \ + SotFactory **ppFactory = GetFactoryAdress(); \ + if( !*ppFactory ) \ + { \ + *ppFactory = new FactoryName( GlobalName, \ + String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( #ClassName ) ), \ + ClassName::CreateInstance );\ + (*ppFactory)->PutSuperClass( Super1::ClassFactory() ); \ + (*ppFactory)->PutSuperClass( Super2::ClassFactory() ); \ + (*ppFactory)->PutSuperClass( Super3::ClassFactory() ); \ + } \ + return *pFactory; \ +} \ +void * __EXPORT ClassName::CreateInstance( SotObject ** ppObj ) \ +{ \ + ClassName * p = new ClassName(); \ + if( ppObj ) \ + *ppObj = p; \ + return p; \ +} \ +const SotFactory * __EXPORT ClassName::GetSvFactory() const \ +{ \ + return ClassFactory(); \ +} \ +void * __EXPORT ClassName::Cast( const SotFactory * pFact ) \ +{ \ + void * pRet = NULL; \ + if( !pFact || pFact == ClassFactory() ) \ + pRet = this; \ + if( !pRet ) \ + pRet = Super1::Cast( pFact ); \ + if( !pRet ) \ + pRet = Super2::Cast( pFact ); \ + if( !pRet ) \ + pRet = Super3::Cast( pFact ); \ + return pRet; \ +} + +#define SO2_IMPL_BASIC_CLASS3(ClassName,FactoryName,Super1,Super2,Super3,GlobalName) \ +SotFactory * ClassName::pFactory = NULL; \ + SO2_IMPL_BASIC_CLASS3_DLL(ClassName,FactoryName,Super1,Super2,Super3,GlobalName) + +/************************************************************************** +**************************************************************************/ +#define SO2_IMPL_BASIC_CLASS4_DLL(ClassName,FactoryName,Super1,Super2,Super3,Super4,GlobalName) \ +SotFactory * ClassName::ClassFactory() \ +{ \ + SotFactory **ppFactory = GetFactoryAdress(); \ + if( !*ppFactory ) \ + { \ + *ppFactory = new SotFactory( GlobalName, \ + String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( #ClassName ) ), \ + ClassName::CreateInstance );\ + (*ppFactory)->PutSuperClass( Super1::ClassFactory() ); \ + (*ppFactory)->PutSuperClass( Super2::ClassFactory() ); \ + (*ppFactory)->PutSuperClass( Super3::ClassFactory() ); \ + (*ppFactory)->PutSuperClass( Super4::ClassFactory() ); \ + } \ + return *ppFactory; \ +} \ +void * __EXPORT ClassName::CreateInstance( SotObject ** ppObj ) \ +{ \ + ClassName * p = new ClassName(); \ + if( ppObj ) \ + *ppObj = p; \ + return p; \ +} \ +const SotFactory * __EXPORT ClassName::GetSvFactory() const \ +{ \ + return ClassFactory(); \ +} \ +void * __EXPORT ClassName::Cast( const SotFactory * pFact ) \ +{ \ + void * pRet = NULL; \ + if( !pFact || pFact == ClassFactory() ) \ + pRet = this; \ + if( !pRet ) \ + pRet = Super1::Cast( pFact ); \ + if( !pRet ) \ + pRet = Super2::Cast( pFact ); \ + if( !pRet ) \ + pRet = Super3::Cast( pFact ); \ + if( !pRet ) \ + pRet = Super4::Cast( pFact ); \ + return pRet; \ +} + +#define SO2_IMPL_BASIC_CLASS4(ClassName,FactoryName,Super1,Super2,Super3,Super4,GlobalName) \ +SotFactory * ClassName::pFactory = NULL; \ + SO2_IMPL_BASIC_CLASS4_DLL(ClassName,FactoryName,Super1,Super2,Super3,Super4,GlobalName) + +//==================class SotObject======================================== +#ifdef _MSC_VER +#pragma warning(disable: 4250) +#endif + +class SvAggregateMemberList; +struct IUnknown; +class SOT_DLLPUBLIC SotObject : virtual public SvRefBase +{ +friend class SotFactory; +friend class SvObject; + SvAggregateMemberList * pAggList; // fuer Aggregation, erstes ist das MainObj + USHORT nStrongLockCount; + USHORT nOwnerLockCount; + BOOL bOwner:1, + bSVObject:1, // Ist Proxy, dann TRUE wenn andere Seite SV ist + bInClose:1; // TRUE, im DoClose + + void * DownAggCast( const SotFactory * pFact ); + void RemoveInterface( ULONG ); + void RemoveInterface( SotObject * ); +#if defined (GCC) && (defined (C281) || defined (C290) || defined (C291)) +public: +#else +protected: +#endif + virtual ~SotObject(); + void SetExtern() { bOwner = FALSE; } + virtual BOOL Close(); +public: + SotObject(); + SO2_DECL_BASIC_CLASS_DLL(SotObject,SOTDATA()) + SO2_DECL_INVARIANT() + + // Nur damit die Makros in So3 nicht ganz ausufern + virtual IUnknown * GetInterface( const SvGlobalName & ); + + BOOL Owner() const { return bOwner; } + BOOL IsSvObject() const; + + // Methoden fuer die Aggregation (siehe OLE2-Spec) + BOOL ShouldDelete(); + virtual void QueryDelete(); + SvAggregateMemberList & GetAggList(); + void AddInterface( SotObject * ); + void AddInterface( SotFactory * ); + virtual SotObjectRef CreateAggObj( const SotFactory * ); + void * AggCast( const SotFactory * pFact ); + void * CastAndAddRef( const SotFactory * pFact ); + SotObject * GetMainObj() const; + + // !!! Read the Manual !!! + virtual USHORT FuzzyLock( BOOL bLock, BOOL bIntern, BOOL bClose ); + void Lock( BOOL bLock ) + { + FuzzyLock( bLock, TRUE, TRUE ); + } + USHORT GetOwnerLockCount() const { return nOwnerLockCount; } + USHORT GetStrongLockCount() const { return nStrongLockCount; } + + void OwnerLock( BOOL bLock ); + void RemoveOwnerLock(); + BOOL DoClose(); + BOOL IsInClose() const { return bInClose; } + +private: + // Kopieren und Zuweisen dieses Objekttyps ist nicht erlaubt + SOT_DLLPRIVATE SotObject & operator = ( const SotObject & ); + SOT_DLLPRIVATE SotObject( const SotObject & ); +}; + +//==================class SotObjectRef====================================== +SV_IMPL_REF(SotObject) + +inline SotObjectRef::SotObjectRef( SotObject * pObjP, SvCastEnum ) +{ + if( pObjP ) + { + pObj = (SotObject *)pObjP->AggCast( SotObject::ClassFactory() ); + if( pObj ) + pObj->AddRef(); + } + else + pObj = NULL; +} + +//==================class SotObject*List==================================== +SV_DECL_REF_LIST(SotObject,SotObject*) +SV_IMPL_REF_LIST(SotObject,SotObject*) + +#endif // _IFACE_HXX + diff --git a/sot/inc/sot/sotdata.hxx b/sot/inc/sot/sotdata.hxx new file mode 100644 index 000000000000..8d8775b5e181 --- /dev/null +++ b/sot/inc/sot/sotdata.hxx @@ -0,0 +1,60 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SOT_DATA_HXX +#define _SOT_DATA_HXX + +/************************************************************************* +*************************************************************************/ + +#ifndef _TOOLS_SOLAR_H +#include <tools/solar.h> +#endif +#include "sot/sotdllapi.h" + +//==================class SotData_Impl==================================== + +class List; +class SotFactory; +class SotFactoryList; +class SotObjectList; + +struct SotData_Impl +{ + UINT32 nSvObjCount; + SotObjectList * pObjectList; + SotFactoryList * pFactoryList; + SotFactory * pSotObjectFactory; + SotFactory * pSotStorageStreamFactory; + SotFactory * pSotStorageFactory; + List* pDataFlavorList; + SotData_Impl(); +}; + +SOT_DLLPUBLIC SotData_Impl* SOTDATA(); + +#endif diff --git a/sot/inc/sot/sotdllapi.h b/sot/inc/sot/sotdllapi.h new file mode 100644 index 000000000000..032fef762715 --- /dev/null +++ b/sot/inc/sot/sotdllapi.h @@ -0,0 +1,41 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_SOTDLLAPI_H +#define INCLUDED_SOTDLLAPI_H + +#include "sal/types.h" + +#if defined(SOT_DLLIMPLEMENTATION) +#define SOT_DLLPUBLIC SAL_DLLPUBLIC_EXPORT +#else +#define SOT_DLLPUBLIC SAL_DLLPUBLIC_IMPORT +#endif +#define SOT_DLLPRIVATE SAL_DLLPRIVATE + +#endif /* INCLUDED_SOTDLLAPI_H */ + diff --git a/sot/inc/sot/sotref.hxx b/sot/inc/sot/sotref.hxx new file mode 100644 index 000000000000..ae03032e286e --- /dev/null +++ b/sot/inc/sot/sotref.hxx @@ -0,0 +1,77 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SOT_SOTREF_HXX +#define _SOT_SOTREF_HXX + +#ifndef _TOOLS_REF_HXX +#include <tools/ref.hxx> +#endif + +//======================================================================== +enum SvCastEnum { SV_AGGREGATION_CAST }; +#ifndef SVT_DECL_SOTOBJECT_DEFINED +#define SVT_DECL_SOTOBJECT_DEFINED +class SotObject; +class SotObjectRef +{ + PRV_SV_DECL_REF(SotObject) + inline SotObjectRef( SotObject * pObjP, SvCastEnum ); +}; +#endif + +//======================================================================== +#define SO2_DECL_REF(ClassName) \ +class ClassName; \ +class ClassName##Ref \ +{ \ + PRV_SV_DECL_REF(ClassName) \ + inline ClassName##Ref( const SotObjectRef & ); \ + inline ClassName##Ref( SotObject * pObjP ); \ + inline ClassName##Ref( SotObject * pObjP, SvCastEnum ); \ +}; + +#define SO2_IMPL_REF(ClassName) \ +SV_IMPL_REF(ClassName) \ +inline ClassName##Ref::ClassName##Ref( const SotObjectRef & r ) \ +{ \ + pObj = (ClassName *)ClassName::ClassFactory()->CastAndAddRef( &r ); \ +} \ +inline ClassName##Ref::ClassName##Ref( SotObject * pObjP ) \ +{ \ + pObj = (ClassName *)ClassName::ClassFactory()->CastAndAddRef( pObjP );\ +} \ +inline ClassName##Ref::ClassName##Ref( SotObject * pObjP, SvCastEnum ) \ +{ \ + pObj = (ClassName *)ClassName::ClassFactory()->AggCastAndAddRef( pObjP );\ +} + +#define SO2_DECL_IMPL_REF(ClassName) \ + SO2_DECL_REF(ClassName) \ + SO2_IMPL_REF(ClassName) + +#endif // _SO2REF_HXX diff --git a/sot/inc/sot/storage.hxx b/sot/inc/sot/storage.hxx new file mode 100644 index 000000000000..572e100c7299 --- /dev/null +++ b/sot/inc/sot/storage.hxx @@ -0,0 +1,272 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SOT_STORAGE_HXX +#define _SOT_STORAGE_HXX + +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Reference.h> + +#ifndef _COM_SUN_STAR_IO_XINPUTSTREAM_H_ +#include <com/sun/star/io/XInputStream.hpp> +#endif +#include <com/sun/star/embed/XStorage.hpp> +#include <sot/object.hxx> +#include <sot/factory.hxx> +#ifndef _TOOLS_STREAM_HXX +#include <tools/stream.hxx> +#endif +#ifndef _TOOLS_ERRCODE_HXX +#include <tools/errcode.hxx> +#endif +#include "sot/sotdllapi.h" + +#define STORAGE_FAILIFTHERE 0x02 +#define STORAGE_TRANSACTED 0x04 +#define STORAGE_PRIORITY 0x08 +#define STORAGE_DELETEONRELEASE 0x10 +#define STORAGE_CONVERT 0x20 +#define STORAGE_UNPACKED_MODE 0x40 +#define STORAGE_DISKSPANNED_MODE 0x80 +#define STORAGE_CREATE_UNPACKED 0x44 +typedef short StorageMode; + +class SvStorage; +namespace binfilter +{ + class SvStorage; +} + +/************************************************************************* +*************************************************************************/ +class SotStorage; +class BaseStorageStream; +class SOT_DLLPUBLIC SotStorageStream : virtual public SotObject, public SvStream +{ +friend class SotStorage; +friend class ImpStream; + BaseStorageStream * pOwnStm;// Zeiger auf den eigenen Stream +protected: + virtual ULONG GetData( void* pData, ULONG nSize ); + virtual ULONG PutData( const void* pData, ULONG nSize ); + virtual ULONG SeekPos( ULONG nPos ); + virtual void FlushData(); + ~SotStorageStream(); +public: + SotStorageStream( const String &, + StreamMode = STREAM_STD_READWRITE, + StorageMode = 0 ); + SotStorageStream( BaseStorageStream *pStm ); + SotStorageStream(); + SO2_DECL_BASIC_CLASS_DLL(SotStorageStream,SOTDATA()) + SO2_DECL_INVARIANT() + + using SvStream::SyncSvStream; + virtual void SyncSvStream(); + void SyncSysStream() { SvStream::SyncSysStream(); } + + virtual void ResetError(); + + virtual void SetSize( ULONG nNewSize ); + UINT32 GetSize() const; + BOOL CopyTo( SotStorageStream * pDestStm ); + virtual BOOL Commit(); + virtual BOOL Revert(); + BOOL SetProperty( const String& rName, const ::com::sun::star::uno::Any& rValue ); + BOOL GetProperty( const String& rName, ::com::sun::star::uno::Any& rValue ); + ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > + GetXInputStream() const; +}; + +#ifndef SOT_DECL_SOTSTORAGESTREAM_DEFINED +#define SOT_DECL_SOTSTORAGESTREAM_DEFINED +SO2_DECL_REF(SotStorageStream) +#endif +SO2_IMPL_REF(SotStorageStream) + +namespace ucbhelper +{ + class Content; +} + +class SvStorageInfoList; +class BaseStorage; +class UNOStorageHolder; +class SOT_DLLPUBLIC SotStorage : virtual public SotObject +{ +friend class SotStorageStream; +friend class SvStorage; +friend class ::binfilter::SvStorage; + + BaseStorage * m_pTmpStg; // Temp-Storage fuer Transacted, nur auf diesem schreiben! ??? Useless ??? + BaseStorage * m_pOwnStg; // Zielstorage + SvStream * m_pStorStm; // nur fuer SDSTORAGES + ULONG m_nError; + String m_aName; // Name des Storage + BOOL m_bIsRoot:1, // z.B.: File-Storage + m_bDelStm:1; + ByteString m_aKey; // aKey.Len != 0 -> Verschluesselung + long m_nVersion; + +protected: + ~SotStorage(); + void CreateStorage( BOOL bUCBStorage, StreamMode, StorageMode ); +public: + SotStorage( const String &, + StreamMode = STREAM_STD_READWRITE, + StorageMode = 0 ); + SotStorage( BOOL bUCBStorage, const String &, + StreamMode = STREAM_STD_READWRITE, + StorageMode = 0 ); + SotStorage( const ::ucbhelper::Content& rContent, const String &, + StreamMode = STREAM_STD_READWRITE, + StorageMode = 0 ); + SotStorage( BaseStorage * ); + SotStorage( SvStream & rStm ); + SotStorage( BOOL bUCBStorage, SvStream & rStm ); + SotStorage( SvStream * pStm, BOOL bDelete ); + SotStorage(); + SO2_DECL_BASIC_CLASS_DLL(SotStorage,SOTDATA()) + SO2_DECL_INVARIANT() + + SvMemoryStream * CreateMemoryStream(); + const SvStream * GetSvStream(); + + static BOOL IsStorageFile( const String & rFileName ); + static BOOL IsStorageFile( SvStream* pStream ); + + virtual const String & GetName() const; + + virtual BOOL Validate(); + + void SetKey( const ByteString& rKey ); + const ByteString & GetKey() const { return m_aKey; } + + void SetVersion( long nVers ) + { + m_nVersion = nVers; + } + long GetVersion() const + { + return m_nVersion; + } + + ULONG GetErrorCode() const { return m_nError; } + ULONG GetError() const { return ERRCODE_TOERROR(m_nError); } + void SetError( ULONG nErrorCode ) + { + if( m_nError == SVSTREAM_OK ) + m_nError = nErrorCode; + } + virtual void ResetError(); + + BOOL IsRoot() const { return m_bIsRoot; } + void SignAsRoot( BOOL b = TRUE ) { m_bIsRoot = b; } + void SetDeleteStream( BOOL bDelete ) { m_bDelStm = bDelete; } + + // eigener Datenbereich + virtual void SetClass( const SvGlobalName & rClass, + ULONG bOriginalClipFormat, + const String & rUserTypeName ); + virtual void SetConvertClass( const SvGlobalName & rConvertClass, + ULONG bOriginalClipFormat, + const String & rUserTypeName ); + virtual SvGlobalName GetClassName();// Typ der Daten im Storage + virtual ULONG GetFormat(); + virtual String GetUserName(); + virtual BOOL ShouldConvert(); + void SetName( const String& rName ); + + // Liste aller Elemente + virtual void FillInfoList( SvStorageInfoList * ) const; + virtual BOOL CopyTo( SotStorage * pDestStg ); + virtual BOOL Commit(); + virtual BOOL Revert(); + + /* Element Methoden */ + // Stream mit Verbindung zu Storage erzeugen, + // in etwa eine Parent-Child Beziehung + SotStorageStream * OpenSotStream( const String & rEleName, + StreamMode = STREAM_STD_READWRITE, + StorageMode = 0 ); + SotStorageStream * OpenEncryptedSotStream( const String & rEleName, const ByteString& rKey, + StreamMode = STREAM_STD_READWRITE, + StorageMode = 0 ); + SotStorage * OpenSotStorage( const String & rEleName, + StreamMode = STREAM_STD_READWRITE, + StorageMode = STORAGE_TRANSACTED ); + SotStorage * OpenUCBStorage( const String & rEleName, + StreamMode = STREAM_STD_READWRITE, + StorageMode = STORAGE_TRANSACTED ); + SotStorage * OpenOLEStorage( const String & rEleName, + StreamMode = STREAM_STD_READWRITE, + StorageMode = STORAGE_TRANSACTED ); + // Abfrage auf Storage oder Stream + virtual BOOL IsStream( const String & rEleName ) const; + virtual BOOL IsStorage( const String & rEleName ) const; + virtual BOOL IsContained( const String & rEleName ) const; + // Element loeschen + virtual BOOL Remove( const String & rEleName ); + // Elementnamen aendern + virtual BOOL Rename( const String & rEleName, + const String & rNewName ); + virtual BOOL CopyTo( const String & rEleName, SotStorage * pDest, + const String & rNewName ); + virtual BOOL MoveTo( const String & rEleName, SotStorage * pDest, + const String & rNewName ); + + SvStream* GetTargetSvStream() const; + BOOL SetProperty( const String& rName, const ::com::sun::star::uno::Any& rValue ); + BOOL GetProperty( const String& rName, ::com::sun::star::uno::Any& rValue ); + BOOL GetProperty( const String& rEleName, const String& rName, ::com::sun::star::uno::Any& rValue ); + BOOL IsOLEStorage() const; + static BOOL IsOLEStorage( const String & rFileName ); + static BOOL IsOLEStorage( SvStream* pStream ); + + // this is temporary HACK, _MUST_ be removed before release + ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > + GetUNOAPIDuplicate( const String& rEleName, sal_Int32 nUNOStorageMode ); + void RemoveUNOStorageHolder( UNOStorageHolder* pHolder ); + + static SotStorage* OpenOLEStorage( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& xStorage, + const String& rEleName, StreamMode = STREAM_STD_READWRITE ); + static sal_Int32 GetFormatID( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& xStorage ); + static sal_Int32 GetVersion( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& xStorage ); +}; + +#ifndef SOT_DECL_SOTSTORAGE_DEFINED +#define SOT_DECL_SOTSTORAGE_DEFINED +SO2_DECL_REF(SotStorage) +#endif +SO2_IMPL_REF(SotStorage) + +#define SvStorage SotStorage +#define SvStorageRef SotStorageRef +#define SvStorageStream SotStorageStream +#define SvStorageStreamRef SotStorageStreamRef + +#endif // _SVSTOR_HXX diff --git a/sot/inc/stg.hxx b/sot/inc/stg.hxx new file mode 100644 index 000000000000..84373e26d596 --- /dev/null +++ b/sot/inc/stg.hxx @@ -0,0 +1,398 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _STG_HXX +#define _STG_HXX + +#include <com/sun/star/uno/Any.h> +#include <com/sun/star/uno/Reference.h> + +#ifndef _COM_SUN_STAR_IO_XINPUTSTREAM_H_ +#include <com/sun/star/io/XInputStream.hpp> +#endif + +#ifndef _COM_SUN_STAR_UCB_XCOMMANDENVIRONMENT_H_ +#include <com/sun/star/ucb/XCommandEnvironment.hpp> +#endif + +#ifndef _COM_SUN_STAR_EMBED_XSTORAGE_H_ +#include <com/sun/star/embed/XStorage.hpp> +#endif + + +#include <tools/rtti.hxx> +#ifndef _TOOLS_STREAM_HXX //autogen +#include <tools/stream.hxx> +#endif +#ifndef _TOOLS_GLOBNAME_HXX //autogen +#include <tools/globname.hxx> +#endif +#include "sot/sotdllapi.h" + +#include <list> +class UNOStorageHolder; +typedef ::std::list< UNOStorageHolder* > UNOStorageHolderList; + +class Storage; +class StorageStream; +class StgIo; +class StgDirEntry; +class StgStrm; +class SvGlobalName; +struct ClsId +{ + INT32 n1; + INT16 n2, n3; + UINT8 n4, n5, n6, n7, n8, n9, n10, n11; +}; + +class SOT_DLLPUBLIC StorageBase : public SvRefBase +{ +protected: + ULONG m_nError; // error code + StreamMode m_nMode; // open mode + BOOL m_bAutoCommit; + StorageBase(); + virtual ~StorageBase(); +public: + TYPEINFO(); + virtual const SvStream* GetSvStream() const = 0; + virtual BOOL Validate( BOOL=FALSE ) const = 0; + virtual BOOL ValidateMode( StreamMode ) const = 0; + void ResetError() const; + void SetError( ULONG ) const; + ULONG GetError() const; + BOOL Good() const { return BOOL( m_nError == SVSTREAM_OK ); } + StreamMode GetMode() const { return m_nMode; } + void SetAutoCommit( BOOL bSet ) + { m_bAutoCommit = bSet; } +}; + +class BaseStorageStream : public StorageBase +{ +public: + TYPEINFO(); + virtual ULONG Read( void * pData, ULONG nSize ) = 0; + virtual ULONG Write( const void* pData, ULONG nSize ) = 0; + virtual ULONG Seek( ULONG nPos ) = 0; + virtual ULONG Tell() = 0; + virtual void Flush() = 0; + virtual BOOL SetSize( ULONG nNewSize ) = 0; + virtual BOOL CopyTo( BaseStorageStream * pDestStm ) = 0; + virtual BOOL Commit() = 0; + virtual BOOL Revert() = 0; + virtual BOOL Equals( const BaseStorageStream& rStream ) const = 0; +}; + +class SvStorageInfoList; +class BaseStorage : public StorageBase +{ +public: + TYPEINFO(); + virtual const String& GetName() const = 0; + virtual BOOL IsRoot() const = 0; + virtual void SetClassId( const ClsId& ) = 0; + virtual const ClsId& GetClassId() const = 0; + virtual void SetDirty() = 0; + virtual void SetClass( const SvGlobalName & rClass, + ULONG nOriginalClipFormat, + const String & rUserTypeName ) = 0; + virtual void SetConvertClass( const SvGlobalName & rConvertClass, + ULONG nOriginalClipFormat, + const String & rUserTypeName ) = 0; + virtual SvGlobalName GetClassName() = 0; + virtual ULONG GetFormat() = 0; + virtual String GetUserName() = 0; + virtual BOOL ShouldConvert() = 0; + virtual void FillInfoList( SvStorageInfoList* ) const = 0; + virtual BOOL CopyTo( BaseStorage* pDestStg ) const = 0; + virtual BOOL Commit() = 0; + virtual BOOL Revert() = 0; + virtual BaseStorageStream* OpenStream( const String & rEleName, + StreamMode = STREAM_STD_READWRITE, + BOOL bDirect = TRUE, const ByteString* pKey=0 ) = 0; + virtual BaseStorage* OpenStorage( const String & rEleName, + StreamMode = STREAM_STD_READWRITE, + BOOL bDirect = FALSE ) = 0; + virtual BaseStorage* OpenUCBStorage( const String & rEleName, + StreamMode = STREAM_STD_READWRITE, + BOOL bDirect = FALSE ) = 0; + virtual BaseStorage* OpenOLEStorage( const String & rEleName, + StreamMode = STREAM_STD_READWRITE, + BOOL bDirect = FALSE ) = 0; + virtual BOOL IsStream( const String& rEleName ) const = 0; + virtual BOOL IsStorage( const String& rEleName ) const = 0; + virtual BOOL IsContained( const String& rEleName ) const = 0; + virtual BOOL Remove( const String & rEleName ) = 0; + virtual BOOL Rename( const String & rEleName, const String & rNewName ) = 0; + virtual BOOL CopyTo( const String & rEleName, BaseStorage * pDest, const String & rNewName ) = 0; + virtual BOOL MoveTo( const String & rEleName, BaseStorage * pDest, const String & rNewName ) = 0; + virtual BOOL ValidateFAT() = 0; + virtual BOOL Equals( const BaseStorage& rStream ) const = 0; +}; + +class OLEStorageBase +{ +protected: + StreamMode& nStreamMode; // open mode + StgIo* pIo; // I/O subsystem + StgDirEntry* pEntry; // the dir entry + OLEStorageBase( StgIo*, StgDirEntry*, StreamMode& ); + ~OLEStorageBase(); + BOOL Validate_Impl( BOOL=FALSE ) const; + BOOL ValidateMode_Impl( StreamMode, StgDirEntry* p = NULL ) const ; + const SvStream* GetSvStream_Impl() const; +public: +}; + +class StorageStream : public BaseStorageStream, public OLEStorageBase +{ +//friend class Storage; + ULONG nPos; // current position +protected: + ~StorageStream(); +public: + TYPEINFO(); + StorageStream( StgIo*, StgDirEntry*, StreamMode ); + virtual ULONG Read( void * pData, ULONG nSize ); + virtual ULONG Write( const void* pData, ULONG nSize ); + virtual ULONG Seek( ULONG nPos ); + virtual ULONG Tell() { return nPos; } + virtual void Flush(); + virtual BOOL SetSize( ULONG nNewSize ); + virtual BOOL CopyTo( BaseStorageStream * pDestStm ); + virtual BOOL Commit(); + virtual BOOL Revert(); + virtual BOOL Validate( BOOL=FALSE ) const; + virtual BOOL ValidateMode( StreamMode ) const; + BOOL ValidateMode( StreamMode, StgDirEntry* p ) const; + const SvStream* GetSvStream() const; + virtual BOOL Equals( const BaseStorageStream& rStream ) const; +}; + +class UCBStorageStream; + +class SOT_DLLPUBLIC Storage : public BaseStorage, public OLEStorageBase +{ + String aName; + BOOL bIsRoot; + void Init( BOOL bCreate ); + Storage( StgIo*, StgDirEntry*, StreamMode ); +protected: + ~Storage(); +public: + TYPEINFO(); + Storage( const String &, StreamMode = STREAM_STD_READWRITE, BOOL bDirect = TRUE ); + Storage( SvStream& rStrm, BOOL bDirect = TRUE ); + Storage( UCBStorageStream& rStrm, BOOL bDirect = TRUE ); + + static BOOL IsStorageFile( const String & rFileName ); + static BOOL IsStorageFile( SvStream* ); + + virtual const String& GetName() const; + virtual BOOL IsRoot() const { return bIsRoot; } + virtual void SetClassId( const ClsId& ); + virtual const ClsId& GetClassId() const; + virtual void SetDirty(); + virtual void SetClass( const SvGlobalName & rClass, + ULONG nOriginalClipFormat, + const String & rUserTypeName ); + virtual void SetConvertClass( const SvGlobalName & rConvertClass, + ULONG nOriginalClipFormat, + const String & rUserTypeName ); + virtual SvGlobalName GetClassName(); + virtual ULONG GetFormat(); + virtual String GetUserName(); + virtual BOOL ShouldConvert(); + virtual void FillInfoList( SvStorageInfoList* ) const; + virtual BOOL CopyTo( BaseStorage* pDestStg ) const; + virtual BOOL Commit(); + virtual BOOL Revert(); + virtual BaseStorageStream* OpenStream( const String & rEleName, + StreamMode = STREAM_STD_READWRITE, + BOOL bDirect = TRUE, const ByteString* pKey=0 ); + virtual BaseStorage* OpenStorage( const String & rEleName, + StreamMode = STREAM_STD_READWRITE, + BOOL bDirect = FALSE ); + virtual BaseStorage* OpenUCBStorage( const String & rEleName, + StreamMode = STREAM_STD_READWRITE, + BOOL bDirect = FALSE ); + virtual BaseStorage* OpenOLEStorage( const String & rEleName, + StreamMode = STREAM_STD_READWRITE, + BOOL bDirect = FALSE ); + virtual BOOL IsStream( const String& rEleName ) const; + virtual BOOL IsStorage( const String& rEleName ) const; + virtual BOOL IsContained( const String& rEleName ) const; + virtual BOOL Remove( const String & rEleName ); + virtual BOOL Rename( const String & rEleName, const String & rNewName ); + virtual BOOL CopyTo( const String & rEleName, BaseStorage * pDest, const String & rNewName ); + virtual BOOL MoveTo( const String & rEleName, BaseStorage * pDest, const String & rNewName ); + virtual BOOL ValidateFAT(); + virtual BOOL Validate( BOOL=FALSE ) const; + virtual BOOL ValidateMode( StreamMode ) const; + BOOL ValidateMode( StreamMode, StgDirEntry* p ) const; + virtual const SvStream* GetSvStream() const; + virtual BOOL Equals( const BaseStorage& rStream ) const; +}; + +class UCBStorageStream_Impl; +class UCBStorageStream : public BaseStorageStream +{ +friend class UCBStorage; + + UCBStorageStream_Impl* + pImp; +protected: + ~UCBStorageStream(); +public: + TYPEINFO(); + UCBStorageStream( const String& rName, StreamMode nMode, BOOL bDirect, const ByteString* pKey=0 ); + UCBStorageStream( const String& rName, StreamMode nMode, BOOL bDirect, const ByteString* pKey, BOOL bRepair, ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XProgressHandler > xProgress ); + UCBStorageStream( UCBStorageStream_Impl* ); + + virtual ULONG Read( void * pData, ULONG nSize ); + virtual ULONG Write( const void* pData, ULONG nSize ); + virtual ULONG Seek( ULONG nPos ); + virtual ULONG Tell(); + virtual void Flush(); + virtual BOOL SetSize( ULONG nNewSize ); + virtual BOOL CopyTo( BaseStorageStream * pDestStm ); + virtual BOOL Commit(); + virtual BOOL Revert(); + virtual BOOL Validate( BOOL=FALSE ) const; + virtual BOOL ValidateMode( StreamMode ) const; + const SvStream* GetSvStream() const; + virtual BOOL Equals( const BaseStorageStream& rStream ) const; + BOOL SetProperty( const String& rName, const ::com::sun::star::uno::Any& rValue ); + BOOL GetProperty( const String& rName, ::com::sun::star::uno::Any& rValue ); + + SvStream* GetModifySvStream(); + + ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > GetXInputStream() const; +}; + +namespace ucbhelper +{ + class Content; +} + +class UCBStorage_Impl; +struct UCBStorageElement_Impl; +class SOT_DLLPUBLIC UCBStorage : public BaseStorage +{ + UCBStorage_Impl* pImp; + +protected: + ~UCBStorage(); +public: + static BOOL IsStorageFile( SvStream* ); + static BOOL IsStorageFile( const String& rName ); + static BOOL IsDiskSpannedFile( SvStream* ); + static String GetLinkedFile( SvStream& ); + static String CreateLinkFile( const String& rName ); + + UCBStorage( const ::ucbhelper::Content& rContent, const String& rName, StreamMode nMode, BOOL bDirect = TRUE, BOOL bIsRoot = TRUE ); + UCBStorage( const String& rName, + StreamMode nMode, + BOOL bDirect = TRUE, + BOOL bIsRoot = TRUE ); + + UCBStorage( const String& rName, + StreamMode nMode, + BOOL bDirect, + BOOL bIsRoot, + BOOL bIsRepair, + ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XProgressHandler > + xProgressHandler ); + + UCBStorage( UCBStorage_Impl* ); + UCBStorage( SvStream& rStrm, BOOL bDirect = TRUE ); + + TYPEINFO(); + virtual const String& GetName() const; + virtual BOOL IsRoot() const; + virtual void SetClassId( const ClsId& ); + virtual const ClsId& GetClassId() const; + virtual void SetDirty(); + virtual void SetClass( const SvGlobalName & rClass, + ULONG nOriginalClipFormat, + const String & rUserTypeName ); + virtual void SetConvertClass( const SvGlobalName & rConvertClass, + ULONG nOriginalClipFormat, + const String & rUserTypeName ); + virtual SvGlobalName GetClassName(); + virtual ULONG GetFormat(); + virtual String GetUserName(); + virtual BOOL ShouldConvert(); + virtual void FillInfoList( SvStorageInfoList* ) const; + virtual BOOL CopyTo( BaseStorage* pDestStg ) const; + virtual BOOL Commit(); + virtual BOOL Revert(); + virtual BaseStorageStream* OpenStream( const String & rEleName, + StreamMode = STREAM_STD_READWRITE, + BOOL bDirect = TRUE, const ByteString* pKey=0 ); + virtual BaseStorage* OpenStorage( const String & rEleName, + StreamMode = STREAM_STD_READWRITE, + BOOL bDirect = FALSE ); + virtual BaseStorage* OpenUCBStorage( const String & rEleName, + StreamMode = STREAM_STD_READWRITE, + BOOL bDirect = FALSE ); + virtual BaseStorage* OpenOLEStorage( const String & rEleName, + StreamMode = STREAM_STD_READWRITE, + BOOL bDirect = FALSE ); + virtual BOOL IsStream( const String& rEleName ) const; + virtual BOOL IsStorage( const String& rEleName ) const; + virtual BOOL IsContained( const String& rEleName ) const; + virtual BOOL Remove( const String & rEleName ); + virtual BOOL Rename( const String & rEleName, const String & rNewName ); + virtual BOOL CopyTo( const String & rEleName, BaseStorage * pDest, const String & rNewName ); + virtual BOOL MoveTo( const String & rEleName, BaseStorage * pDest, const String & rNewName ); + virtual BOOL ValidateFAT(); + virtual BOOL Validate( BOOL=FALSE ) const; + virtual BOOL ValidateMode( StreamMode ) const; + virtual const SvStream* GetSvStream() const; + virtual BOOL Equals( const BaseStorage& rStream ) const; + BOOL SetProperty( const String& rName, const ::com::sun::star::uno::Any& rValue ); + BOOL GetProperty( const String& rName, ::com::sun::star::uno::Any& rValue ); + BOOL GetProperty( const String& rEleName, const String& rName, ::com::sun::star::uno::Any& rValue ); + + // HACK to avoid incompatible build, can be done since this feature is only for development + // should be removed before release + UNOStorageHolderList* GetUNOStorageHolderList(); + +//#if _SOLAR__PRIVATE + UCBStorageElement_Impl* FindElement_Impl( const String& rName ) const; + BOOL CopyStorageElement_Impl( UCBStorageElement_Impl& rElement, + BaseStorage* pDest, const String& rNew ) const; + BaseStorage* OpenStorage_Impl( const String & rEleName, + StreamMode, BOOL bDirect, BOOL bForceUCBStorage ); +//#endif + +}; + + +#endif diff --git a/sot/inc/storinfo.hxx b/sot/inc/storinfo.hxx new file mode 100644 index 000000000000..dab1f6d4540e --- /dev/null +++ b/sot/inc/storinfo.hxx @@ -0,0 +1,72 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SOT_STORINFO_HXX +#define _SOT_STORINFO_HXX + +#include <tools/pstm.hxx> +#include <tools/globname.hxx> +#include <tools/ownlist.hxx> +#include "sot/sotdllapi.h" + +class StgDirEntry; +class SvStorageInfo +{ +friend class SvStorage; + String aName; + SvGlobalName aClassName; + ULONG nSize; + BOOL bStream:1, + bStorage:1; + + SvStorageInfo(){}; // Fuer SvStorage +public: + SvStorageInfo( const StgDirEntry& ); + SvStorageInfo( const String& rName, ULONG nSz, BOOL bIsStorage ) + : aName( rName ) + , nSize( nSz ) + , bStream( !bIsStorage ) + , bStorage( bIsStorage ) + {} + + const SvGlobalName & GetClassName() const { return aClassName; } + const String & GetName() const { return aName; } + BOOL IsStream() const { return bStream; } + BOOL IsStorage() const { return bStorage; } + ULONG GetSize() const { return nSize; } +}; + +class SOT_DLLPUBLIC SvStorageInfoList +{ + PRV_SV_DECL_OWNER_LIST(SvStorageInfoList,SvStorageInfo) + const SvStorageInfo * Get( const String & rName ); +}; + +SOT_DLLPUBLIC ULONG ReadClipboardFormat( SvStream & rStm ); +SOT_DLLPUBLIC void WriteClipboardFormat( SvStream & rStm, ULONG nFormat ); + +#endif // _STORINFO_HXX diff --git a/sot/prj/build.lst b/sot/prj/build.lst new file mode 100644 index 000000000000..f2696155fd97 --- /dev/null +++ b/sot/prj/build.lst @@ -0,0 +1,8 @@ +to sot : tools ucbhelper unotools NULL +to sot usr1 - all sot_mkout NULL +to sot\inc nmake - all sot_inc NULL +to sot\prj get - all sot_prj NULL +to sot\source\base nmake - all sot_base sot_inc NULL +to sot\source\sdstor nmake - all sot_sdst sot_inc NULL +to sot\source\unoolestorage nmake - all sot_unoolestor sot_inc NULL +to sot\util nmake - all sot_ut sot_base sot_sdst sot_unoolestor NULL diff --git a/sot/prj/d.lst b/sot/prj/d.lst new file mode 100644 index 000000000000..10bed8c9fe5e --- /dev/null +++ b/sot/prj/d.lst @@ -0,0 +1,28 @@ +mkdir: %_DEST%\inc%_EXT%\sot +..\inc\clsids.hxx %_DEST%\inc%_EXT%\sot\clsids.hxx +..\inc\sot\object.hxx %_DEST%\inc%_EXT%\sot\object.hxx +..\inc\sot\factory.hxx %_DEST%\inc%_EXT%\sot\factory.hxx +..\inc\sot\sotdata.hxx %_DEST%\inc%_EXT%\sot\sotdata.hxx +..\inc\agg.hxx %_DEST%\inc%_EXT%\sot\agg.hxx +..\inc\sot\storage.hxx %_DEST%\inc%_EXT%\sot\storage.hxx +..\inc\storinfo.hxx %_DEST%\inc%_EXT%\sot\storinfo.hxx +..\inc\sot\sotref.hxx %_DEST%\inc%_EXT%\sot\sotref.hxx +..\inc\sot\exchange.hxx %_DEST%\inc%_EXT%\sot\exchange.hxx +..\inc\sot\formats.hxx %_DEST%\inc%_EXT%\sot\formats.hxx +..\inc\absdev.hxx %_DEST%\inc%_EXT%\sot\absdev.hxx +..\inc\stg.hxx %_DEST%\inc%_EXT%\sot\stg.hxx +..\inc\filelist.hxx %_DEST%\inc%_EXT%\sot\filelist.hxx +..\inc\sot\sotdllapi.h %_DEST%\inc%_EXT%\sot\sotdllapi.h + +..\%__SRC%\inc\sdintern.hxx %_DEST%\inc%_EXT%\sot\sdintern.hxx +..\%__SRC%\lib\sot.lib %_DEST%\lib%_EXT%\sot.lib +..\%__SRC%\lib\lib*.so %_DEST%\lib%_EXT% +..\%__SRC%\lib\lib*.so.* %_DEST%\lib%_EXT% +..\%__SRC%\lib\*.dylib %_DEST%\lib%_EXT%\*.dylib +..\%__SRC%\lib\*.sl %_DEST%\lib%_EXT%\*.sl +..\%__SRC%\lib\*.a %_DEST%\lib%_EXT%\*.a +..\%__SRC%\slb\sot.lib %_DEST%\lib%_EXT%\xsot.lib +..\%__SRC%\bin\sot?????.dll %_DEST%\bin%_EXT%\sot?????.dll +..\%__SRC%\bin\sot?????.sym %_DEST%\bin%_EXT%\sot?????.sym +..\%__SRC%\misc\sot?????.map %_DEST%\bin%_EXT%\sot?????.map +..\%__SRC%\misc\sot.component %_DEST%\xml%_EXT%\sot.component diff --git a/sot/qa/complex/olesimplestorage/OLESimpleStorageTest.java b/sot/qa/complex/olesimplestorage/OLESimpleStorageTest.java new file mode 100644 index 000000000000..a2d8bee83713 --- /dev/null +++ b/sot/qa/complex/olesimplestorage/OLESimpleStorageTest.java @@ -0,0 +1,5 @@ +package complex.olesimplestorage; + +public interface OLESimpleStorageTest { + boolean test(); +} diff --git a/sot/qa/complex/olesimplestorage/OLESimpleStorageUnitTest.java b/sot/qa/complex/olesimplestorage/OLESimpleStorageUnitTest.java new file mode 100644 index 000000000000..054480d377d1 --- /dev/null +++ b/sot/qa/complex/olesimplestorage/OLESimpleStorageUnitTest.java @@ -0,0 +1,67 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package complex.olesimplestorage; + +import complexlib.ComplexTestCase; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.UnoRuntime; + +/* Document. + */ + +public class OLESimpleStorageUnitTest extends ComplexTestCase { + private XMultiServiceFactory m_xMSF = null; + + public String[] getTestMethodNames() { + return new String[] { + "ExecuteTest01"}; + } + + public String getTestObjectName() { + return "OLESimpleStorageUnitTest"; + } + + public void before () { + try { + m_xMSF = (XMultiServiceFactory)param.getMSF(); + } catch ( Exception e ){ + failed ( "Cannot create service factory!" ); + } + if ( m_xMSF == null ) { + failed ( "Cannot create service factory!" ); + } + } + + public void after () { + m_xMSF = null; + } + + public void ExecuteTest01() { + OLESimpleStorageTest aTest = new Test01( m_xMSF, log ); + assure( "Test01 failed!", aTest.test() ); + } +}
\ No newline at end of file diff --git a/sot/qa/complex/olesimplestorage/Test01.java b/sot/qa/complex/olesimplestorage/Test01.java new file mode 100644 index 000000000000..c9010e61231a --- /dev/null +++ b/sot/qa/complex/olesimplestorage/Test01.java @@ -0,0 +1,126 @@ +package complex.olesimplestorage; + +import complexlib.ComplexTestCase; + +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.io.XInputStream; +import com.sun.star.io.XOutputStream; +import com.sun.star.io.XTempFile; +import com.sun.star.embed.XOLESimpleStorage; +import com.sun.star.uno.UnoRuntime; + +import java.util.Random; +import share.LogWriter; + +public class Test01 implements OLESimpleStorageTest +{ + XMultiServiceFactory m_xMSF = null; + TestHelper m_aTestHelper = null; + final int pStreamCnt = 5; + final int pBytesCnt = 10; + + public Test01 ( XMultiServiceFactory xMSF, LogWriter aLogWriter ) + { + m_xMSF = xMSF; + m_aTestHelper = new TestHelper (aLogWriter, "Test01: "); + } + + public boolean test () + { + try + { + //create a new temporary stream + Object oTempFile = m_xMSF.createInstance ( "com.sun.star.io.TempFile" ); + XTempFile xTempFile = (XTempFile) UnoRuntime.queryInterface ( XTempFile.class, oTempFile ); + m_aTestHelper.Message ( "A new temporary stream created." ); + + //create OLESimpleStorage based on it + Object pArgs[] = new Object[2]; + pArgs[0] = (Object) xTempFile; + pArgs[1] = new Boolean( true ); + Object oOLESimpleStorage = m_xMSF.createInstanceWithArguments ( "com.sun.star.embed.OLESimpleStorage", pArgs ); + XOLESimpleStorage xOLESimpleStorage = (XOLESimpleStorage) UnoRuntime.queryInterface ( XOLESimpleStorage.class, oOLESimpleStorage ); + m_aTestHelper.Message ( "OLESimpleStorage based on XStream created." ); + + //fill it with some streams + Object oStream[] = new Object[pStreamCnt]; + byte pBytesIn[][][] = new byte [pStreamCnt][1][pBytesCnt]; + byte pBytesOut[][] = new byte [pStreamCnt][pBytesCnt]; + XTempFile xTempStream[] = new XTempFile[pStreamCnt]; + Random oRandom = new Random (); + final String sSubStreamPrefix = "SubStream"; + for ( int i = 0; i < pStreamCnt; i++ ) + { + oRandom.nextBytes (pBytesOut[i]); + oStream[i] = m_xMSF.createInstance ( "com.sun.star.io.TempFile" ); + xTempStream[i] = (XTempFile) UnoRuntime.queryInterface ( XTempFile.class, oStream[i] ); + xTempStream[i].getOutputStream ().writeBytes (pBytesOut[i]); + xTempStream[i].seek (0); + m_aTestHelper.Message ( "Substream " + i + " initialized." ); + if (xOLESimpleStorage.hasByName (sSubStreamPrefix + i)) + { + xOLESimpleStorage.replaceByName ( sSubStreamPrefix + i, xTempStream[i] ); + } + else + { + xOLESimpleStorage.insertByName ( sSubStreamPrefix + i, xTempStream[i] ); + m_aTestHelper.Message ( "Substream " + i + " inserted." ); + } + } + + //commit the storage and close it + xOLESimpleStorage.commit (); + m_aTestHelper.Message ( "Storage commited." ); + xOLESimpleStorage.dispose (); + for ( int i = 0; i < pStreamCnt; ++i ) + { + xTempStream[i].setRemoveFile ( true ); + xTempStream[i].getInputStream ().closeInput (); + xTempStream[i].getOutputStream ().closeOutput (); + } + m_aTestHelper.Message ( "Storage closed." ); + + //open the same stream with the constructor for inputstream + pArgs[0] = (Object)xTempFile.getInputStream (); + oOLESimpleStorage = m_xMSF.createInstanceWithArguments ( "com.sun.star.embed.OLESimpleStorage", pArgs ); + xOLESimpleStorage = (XOLESimpleStorage)UnoRuntime.queryInterface ( XOLESimpleStorage.class, oOLESimpleStorage ); + m_aTestHelper.Message ( "Storage reopened, based on XInputStream." ); + + //check that all the streams contain correct information + m_aTestHelper.Message ( "Checking data contained in all the substreams..." ); + for ( int i = 0; i < pStreamCnt; ++i ) + { + if ( xOLESimpleStorage.hasByName (sSubStreamPrefix + i) ) + { + xTempStream[i] = (XTempFile)UnoRuntime.queryInterface ( + XTempFile.class, xOLESimpleStorage.getByName (sSubStreamPrefix + i) ); + xTempStream[i].seek (0); + xTempStream[i].getInputStream ().readBytes (pBytesIn[i], pBytesIn[i][0].length + 1 ); + for ( int j = 0; j < pBytesCnt; ++j ) + { + if ( pBytesIn[i][0][j] != pBytesOut[i][j] ) + { + m_aTestHelper.Error ( "Stream " + i + " byte " + j + ": INCORRECT DATA!"); + return false; + } + else + { + m_aTestHelper.Message ( "Stream " + i + " byte " + j + ": CORRECT." ); + } + } + } + else + { + m_aTestHelper.Error( "Stream " + i + " is lost!"); + return false; + } + } + m_aTestHelper.Message ( "All substreams contain correct data. SUCCESS." ); + } + catch ( Exception e ) + { + m_aTestHelper.Error ( "Exception: " + e ); + } + return true; + } +} diff --git a/sot/qa/complex/olesimplestorage/TestHelper.java b/sot/qa/complex/olesimplestorage/TestHelper.java new file mode 100644 index 000000000000..4b29ed15e393 --- /dev/null +++ b/sot/qa/complex/olesimplestorage/TestHelper.java @@ -0,0 +1,26 @@ +package complex.olesimplestorage; + +import share.LogWriter; + +public class TestHelper +{ + LogWriter m_aLogWriter; + String m_sTestPrefix; + + /** Creates a new instance of TestHelper */ + public TestHelper ( LogWriter aLogWriter, String sTestPrefix ) + { + m_aLogWriter = aLogWriter; + m_sTestPrefix = sTestPrefix; + } + + public void Error ( String sError ) + { + m_aLogWriter.println ( m_sTestPrefix + "Error: " + sError ); + } + + public void Message ( String sMessage ) + { + m_aLogWriter.println ( m_sTestPrefix + sMessage ); + } +} diff --git a/sot/qa/complex/olesimplestorage/makefile.mk b/sot/qa/complex/olesimplestorage/makefile.mk new file mode 100644 index 000000000000..3420d798c9bc --- /dev/null +++ b/sot/qa/complex/olesimplestorage/makefile.mk @@ -0,0 +1,84 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ = ..$/..$/.. +TARGET = OLESimpleStorageUnitTest +PRJNAME = sot +PACKAGE = complex$/olesimplestorage + +# --- Settings ----------------------------------------------------- +.INCLUDE: settings.mk + + +#----- compile .java files ----------------------------------------- + +JARFILES = ridl.jar unoil.jar jurt.jar juh.jar java_uno.jar OOoRunner.jar + +JAVAFILES =\ + OLESimpleStorageUnitTest.java\ + OLESimpleStorageTest.java\ + TestHelper.java\ + Test01.java + +JAVACLASSFILES = $(foreach,i,$(JAVAFILES) $(CLASSDIR)$/$(PACKAGE)$/$(i:b).class) + +#----- make a jar from compiled files ------------------------------ + +MAXLINELENGTH = 100000 + +JARCLASSDIRS = $(PACKAGE) +JARTARGET = $(TARGET).jar +JARCOMPRESS = TRUE + +# --- Parameters for the test -------------------------------------- + +# start an office if the parameter is set for the makefile +.IF "$(OFFICE)" == "" +CT_APPEXECCOMMAND = +.ELSE +CT_APPEXECCOMMAND = -AppExecutionCommand "$(OFFICE)$/soffice -accept=socket,host=localhost,port=8100;urp;" +.ENDIF + +# test base is java complex +CT_TESTBASE = -TestBase java_complex + +# test looks something like the.full.package.TestName +CT_TEST = -o $(PACKAGE:s\$/\.\).$(JAVAFILES:b) + +# start the runner application +CT_APP = org.openoffice.Runner + +# --- Targets ------------------------------------------------------ + +.INCLUDE: target.mk + +RUN: run + +run: + +java -cp $(CLASSPATH) $(CT_APP) $(CT_TESTBASE) $(CT_APPEXECCOMMAND) $(CT_TEST) + + diff --git a/sot/source/base/exchange.cxx b/sot/source/base/exchange.cxx new file mode 100644 index 000000000000..67c2b64f105f --- /dev/null +++ b/sot/source/base/exchange.cxx @@ -0,0 +1,508 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sot.hxx" +#define _SOT_EXCHANGE_CXX +#define SOT_STRING_LIST +#define _SOT_FORMATS_INCLUDE_SYSTEMFORMATS +#include <tools/debug.hxx> +#include <tools/solar.h> +#include <tools/globname.hxx> +#include <tools/string.hxx> +#include <sot/sotdata.hxx> +#include <sot/exchange.hxx> +#include <sot/formats.hxx> +#include <clsids.hxx> +#include <rtl/instance.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/datatransfer/DataFlavor.hpp> +#include <comphelper/documentconstants.hxx> + +using namespace::com::sun::star::uno; +using namespace::com::sun::star::datatransfer; + +/* + In diesen Tabellen stehen alle im Office verwendeten MimeTypes, + Format-Bezeichner und Types. + Die Tabelle ist nach den Formatstring-Ids sortiert und jede Id + ist um genau 1 groesser als ihre Vorgaenger-Id, damit die Id als + Tabellenindex benutzt werden kann. +*/ +struct DataFlavorRepresentation +{ + const char* pMimeType; + const char* pName; + const ::com::sun::star::uno::Type* pType; +}; + +// ----------------------------------------------------------------------------- + +namespace +{ + struct ImplFormatArray_Impl + { + const DataFlavorRepresentation* operator()() + { + static const DataFlavorRepresentation aInstance[] = + { + /* 0 SOT_FORMAT_SYSTEM_START*/ { "", "", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 1 SOT_FORMAT_STRING*/ { "text/plain;charset=utf-16", "Text", &::getCppuType( (const ::rtl::OUString*) 0 ) }, + /* 2 SOT_FORMAT_BITMAP*/ { "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"", "Bitmap", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 3 SOT_FORMAT_GDIMETAFILE*/ { "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"", "GDIMetaFile", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 4 SOT_FORMAT_PRIVATE*/ { "application/x-openoffice-private;windows_formatname=\"Private\"", "Private", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 5 SOT_FORMAT_FILE*/ { "application/x-openoffice-file;windows_formatname=\"FileName\"", "FileName", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 6 SOT_FORMAT_FILE_LIST*/ { "application/x-openoffice-filelist;windows_formatname=\"FileList\"", "FileList", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 7 EMPTY*/ { "", "", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 8 EMPTY*/ { "", "", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 9 EMPTY*/ { "", "", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 10 SOT_FORMAT_RTF*/ { "text/richtext", "Rich Text Format", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 11 SOT_FORMATSTR_ID_DRAWING*/ { "application/x-openoffice-drawing;windows_formatname=\"Drawing Format\"", "Drawing Format", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 12 SOT_FORMATSTR_ID_SVXB*/ { "application/x-openoffice-svxb;windows_formatname=\"SVXB (StarView Bitmap/Animation)\"", "SVXB (StarView Bitmap/Animation)", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 13 SOT_FORMATSTR_ID_SVIM*/ { "application/x-openoffice-svim;windows_formatname=\"SVIM (StarView ImageMap)\"", "SVIM (StarView ImageMap)", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 14 SOT_FORMATSTR_ID_XFA*/ { "application/x-openoffice-xfa;windows_formatname=\"XFA (XOutDev FillAttr)\"", "XFA (XOutDev FillAttr)", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 15 SOT_FORMATSTR_ID_EDITENGINE*/ { "application/x-openoffice-editengine;windows_formatname=\"EditEngineFormat\"", "EditEngineFormat", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 16 SOT_FORMATSTR_ID_INTERNALLINK_STATE*/ { "application/x-openoffice-internallink-state;windows_formatname=\"StatusInfo vom SvxInternalLink\"", "StatusInfo vom SvxInternalLink", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 17 SOT_FORMATSTR_ID_SOLK*/ { "application/x-openoffice-solk;windows_formatname=\"SOLK (StarOffice Link)\"", "SOLK (StarOffice Link)", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 18 SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK*/ { "application/x-openoffice-netscape-bookmark;windows_formatname=\"Netscape Bookmark\"", "Netscape Bookmark", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 19 SOT_FORMATSTR_ID_TREELISTBOX*/ { "application/x-openoffice-treelistbox;windows_formatname=\"SV_LBOX_DD_FORMAT\"", "SV_LBOX_DD_FORMAT", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 20 SOT_FORMATSTR_ID_NATIVE*/ { "application/x-openoffice-native;windows_formatname=\"Native\"", "Native", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 21 SOT_FORMATSTR_ID_OWNERLINK*/ { "application/x-openoffice-ownerlink;windows_formatname=\"OwnerLink\"", "OwnerLink", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 22 SOT_FORMATSTR_ID_STARSERVER*/ { "application/x-openoffice-starserver;windows_formatname=\"StarServerFormat\"", "StarServerFormat", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 23 SOT_FORMATSTR_ID_STAROBJECT*/ { "application/x-openoffice-starobject;windows_formatname=\"StarObjectFormat\"", "StarObjectFormat", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 24 SOT_FORMATSTR_ID_APPLETOBJECT*/ { "application/x-openoffice-appletobject;windows_formatname=\"Applet Object\"", "Applet Object", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 25 SOT_FORMATSTR_ID_PLUGIN_OBJECT*/ { "application/x-openoffice-plugin-object;windows_formatname=\"PlugIn Object\"", "PlugIn Object", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 26 SOT_FORMATSTR_ID_STARWRITER_30*/ { "application/x-openoffice-starwriter-30;windows_formatname=\"StarWriter 3.0\"", "StarWriter 3.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 27 SOT_FORMATSTR_ID_STARWRITER_40*/ { "application/x-openoffice-starwriter-40;windows_formatname=\"StarWriter 4.0\"", "StarWriter 4.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 28 SOT_FORMATSTR_ID_STARWRITER_50*/ { "application/x-openoffice-starwriter-50;windows_formatname=\"StarWriter 5.0\"", "StarWriter 5.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 29 SOT_FORMATSTR_ID_STARWRITERWEB_40*/ { "application/x-openoffice-starwriterweb-40;windows_formatname=\"StarWriter/Web 4.0\"", "StarWriter/Web 4.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 30 SOT_FORMATSTR_ID_STARWRITERWEB_50*/ { "application/x-openoffice-starwriterweb-50;windows_formatname=\"StarWriter/Web 5.0\"", "StarWriter/Web 5.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 31 SOT_FORMATSTR_ID_STARWRITERGLOB_40*/ { "application/x-openoffice-starwriterglob-40;windows_formatname=\"StarWriter/Global 4.0\"", "StarWriter/Global 4.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 32 SOT_FORMATSTR_ID_STARWRITERGLOB_50*/ { "application/x-openoffice-starwriterglob-50;windows_formatname=\"StarWriter/Global 5.0\"", "StarWriter/Global 5.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 33 SOT_FORMATSTR_ID_STARDRAW*/ { "application/x-openoffice-stardraw;windows_formatname=\"StarDrawDocument\"", "StarDrawDocument", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 34 SOT_FORMATSTR_ID_STARDRAW_40*/ { "application/x-openoffice-stardraw-40;windows_formatname=\"StarDrawDocument 4.0\"", "StarDrawDocument 4.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 35 SOT_FORMATSTR_ID_STARIMPRESS_50*/ { "application/x-openoffice-starimpress-50;windows_formatname=\"StarImpress 5.0\"", "StarImpress 5.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 36 SOT_FORMATSTR_ID_STARDRAW_50*/ { "application/x-openoffice-stardraw-50;windows_formatname=\"StarDraw 5.0\"", "StarDraw 5.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 37 SOT_FORMATSTR_ID_STARCALC*/ { "application/x-openoffice-starcalc;windows_formatname=\"StarCalcDocument\"", "StarCalcDocument", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 38 SOT_FORMATSTR_ID_STARCALC_40*/ { "application/x-openoffice-starcalc-40;windows_formatname=\"StarCalc 4.0\"", "StarCalc 4.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 39 SOT_FORMATSTR_ID_STARCALC_50*/ { "application/x-openoffice-starcalc-50;windows_formatname=\"StarCalc 5.0\"", "StarCalc 5.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 40 SOT_FORMATSTR_ID_STARCHART*/ { "application/x-openoffice-starchart;windows_formatname=\"StarChartDocument\"", "StarChartDocument", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 41 SOT_FORMATSTR_ID_STARCHART_40*/ { "application/x-openoffice-starchart-40;windows_formatname=\"StarChartDocument 4.0\"", "StarChartDocument 4.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 42 SOT_FORMATSTR_ID_STARCHART_50*/ { "application/x-openoffice-starchart-50;windows_formatname=\"StarChart 5.0\"", "StarChart 5.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 43 SOT_FORMATSTR_ID_STARIMAGE*/ { "application/x-openoffice-starimage;windows_formatname=\"StarImageDocument\"", "StarImageDocument", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 44 SOT_FORMATSTR_ID_STARIMAGE_40*/ { "application/x-openoffice-starimage-40;windows_formatname=\"StarImageDocument 4.0\"", "StarImageDocument 4.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 45 SOT_FORMATSTR_ID_STARIMAGE_50*/ { "application/x-openoffice-starimage-50;windows_formatname=\"StarImage 5.0\"", "StarImage 5.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 46 SOT_FORMATSTR_ID_STARMATH*/ { "application/x-openoffice-starmath;windows_formatname=\"StarMath\"", "StarMath", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 47 SOT_FORMATSTR_ID_STARMATH_40*/ { "application/x-openoffice-starmath-40;windows_formatname=\"StarMathDocument 4.0\"", "StarMathDocument 4.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 48 SOT_FORMATSTR_ID_STARMATH_50*/ { "application/x-openoffice-starmath-50;windows_formatname=\"StarMath 5.0\"", "StarMath 5.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 49 SOT_FORMATSTR_ID_STAROBJECT_PAINTDOC*/ { "application/x-openoffice-starobject-paintdoc;windows_formatname=\"StarObjectPaintDocument\"", "StarObjectPaintDocument", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 50 SOT_FORMATSTR_ID_FILLED_AREA*/ { "application/x-openoffice-filled-area;windows_formatname=\"FilledArea\"", "FilledArea", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 51 SOT_FORMATSTR_ID_HTML*/ { "text/html", "HTML (HyperText Markup Language)", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 52 SOT_FORMATSTR_ID_HTML_SIMPLE*/ { "application/x-openoffice-html-simple;windows_formatname=\"HTML Format\"", "HTML Format", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 53 SOT_FORMATSTR_ID_CHAOS*/ { "application/x-openoffice-chaos;windows_formatname=\"FORMAT_CHAOS\"", "FORMAT_CHAOS", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 54 SOT_FORMATSTR_ID_CNT_MSGATTACHFILE*/ { "application/x-openoffice-cnt-msgattachfile;windows_formatname=\"CNT_MSGATTACHFILE_FORMAT\"", "CNT_MSGATTACHFILE_FORMAT", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 55 SOT_FORMATSTR_ID_BIFF_5*/ { "application/x-openoffice-biff5;windows_formatname=\"Biff5\"", "Biff5", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 56 SOT_FORMATSTR_ID_BIFF__5*/ { "application/x-openoffice-biff-5;windows_formatname=\"Biff 5\"", "Biff 5", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 57 SOT_FORMATSTR_ID_SYLK*/ { "application/x-openoffice-sylk;windows_formatname=\"Sylk\"", "Sylk", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 58 SOT_FORMATSTR_ID_SYLK_BIGCAPS*/ { "application/x-openoffice-sylk-bigcaps;windows_formatname=\"SYLK\"", "SYLK", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 59 SOT_FORMATSTR_ID_LINK*/ { "application/x-openoffice-link;windows_formatname=\"Link\"", "Link", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 60 SOT_FORMATSTR_ID_DIF*/ { "application/x-openoffice-dif;windows_formatname=\"DIF\"", "DIF", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 61 SOT_FORMATSTR_ID_STARDRAW_TABBAR*/ { "application/x-openoffice-stardraw-tabbar;windows_formatname=\"StarDraw TabBar\"", "StarDraw TabBar", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 62 SOT_FORMATSTR_ID_SONLK*/ { "application/x-openoffice-sonlk;windows_formatname=\"SONLK (StarOffice Navi Link)\"", "SONLK (StarOffice Navi Link)", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 63 SOT_FORMATSTR_ID_MSWORD_DOC*/ { "application/msword", "MSWordDoc", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 64 SOT_FORMATSTR_ID_STAR_FRAMESET_DOC*/ { "application/x-openoffice-star-frameset-doc;windows_formatname=\"StarFrameSetDocument\"", "StarFrameSetDocument", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 65 SOT_FORMATSTR_ID_OFFICE_DOC*/ { "application/x-openoffice-office-doc;windows_formatname=\"OfficeDocument\"", "OfficeDocument", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 66 SOT_FORMATSTR_ID_NOTES_DOCINFO*/ { "application/x-openoffice-notes-docinfo;windows_formatname=\"NotesDocInfo\"", "NotesDocInfo", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 67 SOT_FORMATSTR_ID_NOTES_HNOTE*/ { "application/x-openoffice-notes-hnote;windows_formatname=\"NoteshNote\"", "NoteshNote", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 68 SOT_FORMATSTR_ID_NOTES_NATIVE*/ { "application/x-openoffice-notes-native;windows_formatname=\"Native\"", "Native", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 69 SOT_FORMATSTR_ID_SFX_DOC*/ { "application/x-openoffice-sfx-doc;windows_formatname=\"SfxDocument\"", "SfxDocument", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 70 SOT_FORMATSTR_ID_EVDF*/ { "application/x-openoffice-evdf;windows_formatname=\"EVDF (Explorer View Dummy Format)\"", "EVDF (Explorer View Dummy Format)", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 71 SOT_FORMATSTR_ID_ESDF*/ { "application/x-openoffice-esdf;windows_formatname=\"ESDF (Explorer Search Dummy Format)\"", "ESDF (Explorer Search Dummy Format)", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 72 SOT_FORMATSTR_ID_IDF*/ { "application/x-openoffice-idf;windows_formatname=\"IDF (Iconview Dummy Format)\"", "IDF (Iconview Dummy Format)", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 73 SOT_FORMATSTR_ID_EFTP*/ { "application/x-openoffice-eftp;windows_formatname=\"EFTP (Explorer Ftp File)\"", "EFTP (Explorer Ftp File)", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 74 SOT_FORMATSTR_ID_EFD*/ { "application/x-openoffice-efd;windows_formatname=\"EFD (Explorer Ftp Dir)\"", "EFD (Explorer Ftp Dir)", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 75 SOT_FORMATSTR_ID_SVX_FORMFIELDEXCH*/ { "application/x-openoffice-svx-formfieldexch;windows_formatname=\"SvxFormFieldExch\"", "SvxFormFieldExch", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 76 SOT_FORMATSTR_ID_EXTENDED_TABBAR*/ { "application/x-openoffice-extended-tabbar;windows_formatname=\"ExtendedTabBar\"", "ExtendedTabBar", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 77 SOT_FORMATSTR_ID_SBA_DATAEXCHANGE*/ { "application/x-openoffice-sba-dataexchange;windows_formatname=\"SBA-DATAFORMAT\"", "SBA-DATAFORMAT", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 78 SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE*/ { "application/x-openoffice-sba-fielddataexchange;windows_formatname=\"SBA-FIELDFORMAT\"", "SBA-FIELDFORMAT", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 79 SOT_FORMATSTR_ID_SBA_PRIVATE_URL*/ { "application/x-openoffice-sba-private-url;windows_formatname=\"SBA-PRIVATEURLFORMAT\"", "SBA-PRIVATEURLFORMAT", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 80 SOT_FORMATSTR_ID_SBA_TABED*/ { "application/x-openofficesba-tabed;windows_formatname=\"Tabed\"", "Tabed", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 81 SOT_FORMATSTR_ID_SBA_TABID*/ { "application/x-openoffice-sba-tabid;windows_formatname=\"Tabid\"", "Tabid", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 82 SOT_FORMATSTR_ID_SBA_JOIN*/ { "application/x-openoffice-sba-join;windows_formatname=\"SBA-JOINFORMAT\"", "SBA-JOINFORMAT", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 83 SOT_FORMATSTR_ID_OBJECTDESCRIPTOR*/ { "application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star Object Descriptor (XML)\"", "Star Object Descriptor (XML)", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 84 SOT_FORMATSTR_ID_LINKSRCDESCRIPTOR*/ { "application/x-openoffice-linksrcdescriptor-xml;windows_formatname=\"Star Link Source Descriptor (XML)\"", "Star Link Source Descriptor (XML)", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 85 SOT_FORMATSTR_ID_EMBED_SOURCE*/ { "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\"", "Star Embed Source (XML)", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 86 SOT_FORMATSTR_ID_LINK_SOURCE*/ { "application/x-openoffice-link-source-xml;windows_formatname=\"Star Link Source (XML)\"", "Star Link Source (XML)", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 87 SOT_FORMATSTR_ID_EMBEDDED_OBJ*/ { "application/x-openoffice-embedded-obj-xml;windows_formatname=\"Star Embedded Object (XML)\"", "Star Embedded Object (XML)", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 88 SOT_FORMATSTR_ID_FILECONTENT*/ { "application/x-openoffice-filecontent;windows_formatname=\"FileContents\"", "FileContents", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 89 SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR*/ { "application/x-openoffice-filegrpdescriptor;windows_formatname=\"FileGroupDescriptor\"", "FileGroupDescriptor", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 90 SOT_FORMATSTR_ID_FILENAME*/ { "application/x-openoffice-filename;windows_formatname=\"FileName\"", "FileName", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 91 SOT_FORMATSTR_ID_SD_OLE*/ { "application/x-openoffice-sd-ole;windows_formatname=\"SD-OLE\"", "SD-OLE", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 92 SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE*/ { "application/x-openoffice-embedded-obj-ole;windows_formatname=\"Embedded Object\"", "Embedded Object", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 93 SOT_FORMATSTR_ID_EMBED_SOURCE_OLE*/ { "application/x-openoffice-embed-source-ole;windows_formatname=\"Embed Source\"", "Embed Source", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 94 SOT_FORMATSTR_ID_OBJECTDESCRIPTOR_OLE*/ { "application/x-openoffice-objectdescriptor-ole;windows_formatname=\"Object Descriptor\"", "Object Descriptor", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 95 SOT_FORMATSTR_ID_LINKSRCDESCRIPTOR_OLE*/ { "application/x-openoffice-linkdescriptor-ole;windows_formatname=\"Link Source Descriptor\"", "Link Source Descriptor", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 96 SOT_FORMATSTR_ID_LINK_SOURCE_OLE*/ { "application/x-openoffice-link-source-ole;windows_formatname=\"Link Source\"", "Link Source", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 97 SOT_FORMATSTR_ID_SBA_CTRLDATAEXCHANGE*/ { "application/x-openoffice-sba-ctrldataexchange;windows_formatname=\"SBA-CTRLFORMAT\"", "SBA-CTRLFORMAT", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 98 SOT_FORMATSTR_ID_OUTPLACE_OBJ*/ { "application/x-openoffice-outplace-obj;windows_formatname=\"OutPlace Object\"", "OutPlace Object", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /* 99 SOT_FORMATSTR_ID_CNT_OWN_CLIP*/ { "application/x-openoffice-cnt-own-clip;windows_formatname=\"CntOwnClipboard\"", "CntOwnClipboard", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*100 SOT_FORMATSTR_ID_INET_IMAGE*/ { "application/x-openoffice-inet-image;windows_formatname=\"SO-INet-Image\"", "SO-INet-Image", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*101 SOT_FORMATSTR_ID_NETSCAPE_IMAGE*/ { "application/x-openoffice-netscape-image;windows_formatname=\"Netscape Image Format\"", "Netscape Image Format", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*102 SOT_FORMATSTR_ID_SBA_FORMEXCHANGE*/ { "application/x-openoffice-sba-formexchange;windows_formatname=\"SBA_FORMEXCHANGE\"", "SBA_FORMEXCHANGE", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*103 SOT_FORMATSTR_ID_SBA_REPORTEXCHANGE*/ { "application/x-openoffice-sba-reportexchange;windows_formatname=\"SBA_REPORTEXCHANGE\"", "SBA_REPORTEXCHANGE", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*104 SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR*/ { "application/x-openoffice-uniformresourcelocator;windows_formatname=\"UniformResourceLocator\"", "UniformResourceLocator", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*105 SOT_FORMATSTR_ID_STARCHARTDOCUMENT_50*/ { "application/x-openoffice-starchartdocument-50;windows_formatname=\"StarChartDocument 5.0\"", "StarChartDocument 5.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*106 SOT_FORMATSTR_ID_GRAPHOBJ*/ { "application/x-openoffice-graphobj;windows_formatname=\"Graphic Object\"", "Graphic Object", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*107 SOT_FORMATSTR_ID_STARWRITER_60*/ { MIMETYPE_VND_SUN_XML_WRITER_ASCII, "Writer 6.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*108 SOT_FORMATSTR_ID_STARWRITERWEB_60*/ { MIMETYPE_VND_SUN_XML_WRITER_WEB_ASCII, "Writer/Web 6.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*109 SOT_FORMATSTR_ID_STARWRITERGLOB_60*/ { MIMETYPE_VND_SUN_XML_WRITER_GLOBAL_ASCII, "Writer/Global 6.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*110 SOT_FORMATSTR_ID_STARWDRAW_60*/ { MIMETYPE_VND_SUN_XML_DRAW_ASCII, "Draw 6.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*111 SOT_FORMATSTR_ID_STARIMPRESS_60*/ { MIMETYPE_VND_SUN_XML_IMPRESS_ASCII, "Impress 6.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*112 SOT_FORMATSTR_ID_STARCALC_60*/ { MIMETYPE_VND_SUN_XML_CALC_ASCII, "Calc 6.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*113 SOT_FORMATSTR_ID_STARCHART_60*/ { MIMETYPE_VND_SUN_XML_CHART_ASCII, "Chart 6.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*114 SOT_FORMATSTR_ID_STARMATH_60*/ { MIMETYPE_VND_SUN_XML_MATH_ASCII, "Math 6.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*115 SOT_FORMATSTR_ID_WMF*/ { "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"", "Windows MetaFile", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*116 SOT_FORMATSTR_ID_DBACCESS_QUERY*/ { "application/x-openoffice-dbaccess-query;windows_formatname=\"Data source Query Object\"", "Data source Query Object", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*117 SOT_FORMATSTR_ID_DBACCESS_TABLE*/ { "application/x-openoffice-dbaccess-table;windows_formatname=\"Data source Table\"", "Data source Table", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*118 SOT_FORMATSTR_ID_DBACCESS_COMMAND*/ { "application/x-openoffice-dbaccess-command;windows_formatname=\"SQL query\"", "SQL query", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*119 SOT_FORMATSTR_ID_DIALOG_60*/ { "application/vnd.sun.xml.dialog", "Dialog 6.0", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*120 SOT_FORMATSTR_ID_EMF*/ { "application/x-openoffice-emf;windows_formatname=\"Image EMF\"", "Windows Enhanced MetaFile", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*121 SOT_FORMATSTR_ID_BIFF_8*/ { "application/x-openoffice-biff-8;windows_formatname=\"Biff8\"", "Biff8", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*122 SOT_FORMATSTR_ID_BMP*/ { "image/bmp", "Windows Bitmap", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*123 SOT_FORMATSTR_ID_HTML_NO_COMMENT */ { "application/x-openoffice-html-no-comment;windows_formatname=\"HTML Format\"", "HTML (no comment)", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*124 SOT_FORMATSTR_ID_STARWRITER_8*/ { MIMETYPE_OASIS_OPENDOCUMENT_TEXT_ASCII, "Writer 8", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*125 SOT_FORMATSTR_ID_STARWRITERWEB_8*/ { MIMETYPE_OASIS_OPENDOCUMENT_TEXT_WEB_ASCII, "Writer/Web 8", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*126 SOT_FORMATSTR_ID_STARWRITERGLOB_8*/ { MIMETYPE_OASIS_OPENDOCUMENT_TEXT_GLOBAL_ASCII, "Writer/Global 8", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*127 SOT_FORMATSTR_ID_STARWDRAW_8*/ { MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_ASCII, "Draw 8", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*128 SOT_FORMATSTR_ID_STARIMPRESS_8*/ { MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_ASCII, "Impress 8", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*129 SOT_FORMATSTR_ID_STARCALC_8*/ { MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_ASCII, "Calc 8", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*130 SOT_FORMATSTR_ID_STARCHART_8*/ { MIMETYPE_OASIS_OPENDOCUMENT_CHART_ASCII, "Chart 8", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*131 SOT_FORMATSTR_ID_STARMATH_8*/ { MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_ASCII, "Math 8", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*132 SOT_FORMATSTR_ID_XFORMS */ { "application/x-openoffice-xforms;windows_formatname=\"??? Format\"", "???", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*133 SOT_FORMATSTR_ID_STARWRITER_8_TEMPLATE*/ { MIMETYPE_OASIS_OPENDOCUMENT_TEXT_TEMPLATE_ASCII, "Writer 8 Template", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*134 SOT_FORMATSTR_ID_STARWDRAW_8_TEMPLATE*/ { MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_TEMPLATE_ASCII, "Draw 8 Template", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*135 SOT_FORMATSTR_ID_STARIMPRESS_8_TEMPLATE*/ { MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE_ASCII, "Impress 8 Template", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*136 SOT_FORMATSTR_ID_STARCALC_8_TEMPLATE*/ { MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_TEMPLATE_ASCII, "Calc 8 Template", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*137 SOT_FORMATSTR_ID_STARCHART_8_TEMPLATE*/ { MIMETYPE_OASIS_OPENDOCUMENT_CHART_TEMPLATE_ASCII, "Chart 8 Template", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*138 SOT_FORMATSTR_ID_STARMATH_8_TEMPLATE*/ { MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_TEMPLATE_ASCII, "Math 8 Template", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*139 SOT_FORMATSTR_ID_STARBASE_8*/ { MIMETYPE_OASIS_OPENDOCUMENT_DATABASE_ASCII, "StarBase 8", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + /*140 SOT_FORMAT_GDIMETAFILE*/ { "application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"", "High Contrast GDIMetaFile", &::getCppuType( (const Sequence< sal_Int8 >*) 0 ) }, + }; + return &aInstance[0]; + } + }; + + struct FormatArray_Impl + : public rtl::StaticAggregate< + const DataFlavorRepresentation, ImplFormatArray_Impl > {}; +} + +//----------------------------------------------------------------------- + +static List& InitFormats_Impl() +{ + SotData_Impl * pSotData = SOTDATA(); + if( !pSotData->pDataFlavorList ) + pSotData->pDataFlavorList = new List(); + return *pSotData->pDataFlavorList; +} + +/************************************************************************* +|* +|* SotExchange::RegisterFormatName() +|* +|* Beschreibung CLIP.SDW +*************************************************************************/ +ULONG SotExchange::RegisterFormatName( const String& rName ) +{ + const DataFlavorRepresentation *pFormatArray_Impl = FormatArray_Impl::get(); + // teste zuerst die Standard - Name + ULONG i, nMax = SOT_FORMAT_FILE_LIST; + for( i = SOT_FORMAT_STRING; i <= nMax; ++i ) + if( COMPARE_EQUAL == rName.CompareToAscii( pFormatArray_Impl[ i ].pName ) ) + return i; + + // BM: the chart format 105 ("StarChartDocument 5.0") was written + // only into 5.1 chart documents - in 5.0 and 5.2 it was 42 ("StarChart 5.0") + // The registry only contains the entry for the 42 format id. + nMax = SOT_FORMATSTR_ID_USER_END; + for( i = SOT_FORMAT_RTF; i <= nMax; ++i ) + if( rName.EqualsAscii( pFormatArray_Impl[ i ].pName ) ) + return ( (i == SOT_FORMATSTR_ID_STARCHARTDOCUMENT_50) + ? SOT_FORMATSTR_ID_STARCHART_50 + : i ); + + // dann in der dynamischen Liste + List& rL = InitFormats_Impl(); + for( i = 0, nMax = rL.Count(); i < nMax; i++ ) + { + DataFlavor* pFlavor = (DataFlavor*) rL.GetObject( i ); + if( pFlavor && rName == String( pFlavor->HumanPresentableName ) ) + return i + SOT_FORMATSTR_ID_USER_END + 1; + } + + // nMax ist der neue Platz + DataFlavor* pNewFlavor = new DataFlavor; + + pNewFlavor->MimeType = rName; + pNewFlavor->HumanPresentableName = rName; + pNewFlavor->DataType = ::getCppuType( (const ::rtl::OUString*) 0 ); + + rL.Insert( pNewFlavor, LIST_APPEND ); + + return nMax + SOT_FORMATSTR_ID_USER_END + 1; +} + +ULONG SotExchange::RegisterFormatMimeType( const String& rMimeType ) +{ + const DataFlavorRepresentation *pFormatArray_Impl = FormatArray_Impl::get(); + // teste zuerst die Standard - Name + ULONG i, nMax = SOT_FORMAT_FILE_LIST; + for( i = SOT_FORMAT_STRING; i <= nMax; ++i ) + if( rMimeType.EqualsAscii( pFormatArray_Impl[ i ].pMimeType ) ) + return i; + + nMax = SOT_FORMATSTR_ID_USER_END; + for( i = SOT_FORMAT_RTF; i <= nMax; ++i ) + if( rMimeType.EqualsAscii( pFormatArray_Impl[ i ].pMimeType ) ) + return i; + + // dann in der dynamischen Liste + List& rL = InitFormats_Impl(); + for( i = 0, nMax = rL.Count(); i < nMax; i++ ) + { + DataFlavor* pFlavor = (DataFlavor*) rL.GetObject( i ); + if( pFlavor && rMimeType == String( pFlavor->MimeType ) ) + return i + SOT_FORMATSTR_ID_USER_END + 1; + } + + // nMax ist der neue Platz + DataFlavor* pNewFlavor = new DataFlavor; + + pNewFlavor->MimeType = rMimeType; + pNewFlavor->HumanPresentableName = rMimeType; + pNewFlavor->DataType = ::getCppuType( (const ::rtl::OUString*) 0 ); + + rL.Insert( pNewFlavor, LIST_APPEND ); + + return nMax + SOT_FORMATSTR_ID_USER_END + 1; +} + +/************************************************************************* +|* +|* SotExchange::RegisterFormatName() +|* +|* Beschreibung CLIP.SDW +*************************************************************************/ +ULONG SotExchange::RegisterFormat( const DataFlavor& rFlavor ) +{ + ULONG nRet = GetFormat( rFlavor ); + + if( !nRet ) + { + List& rL = InitFormats_Impl(); + nRet = rL.Count() + SOT_FORMATSTR_ID_USER_END + 1; + rL.Insert( new DataFlavor( rFlavor ), LIST_APPEND ); + } + + return nRet; +} + +/************************************************************************* +|* +|* SotExchange::GetFormatDataFlavor() +|* +*************************************************************************/ + +sal_Bool SotExchange::GetFormatDataFlavor( ULONG nFormat, DataFlavor& rFlavor ) +{ + sal_Bool bRet; + + if( SOT_FORMATSTR_ID_USER_END >= nFormat ) + { + const DataFlavorRepresentation& rData = FormatArray_Impl::get()[nFormat]; + rFlavor.MimeType = ::rtl::OUString::createFromAscii( rData.pMimeType ); + rFlavor.HumanPresentableName = ::rtl::OUString::createFromAscii( rData.pName ); + rFlavor.DataType = *rData.pType; + + bRet = sal_True; + } + else + { + List& rL = InitFormats_Impl(); + + nFormat -= SOT_FORMATSTR_ID_USER_END + 1; + + if( rL.Count() > nFormat ) + { + rFlavor = *(DataFlavor*) rL.GetObject( nFormat ); + bRet = sal_True; + } + else + { + rFlavor = DataFlavor(); + bRet = sal_False; + } + } + + DBG_ASSERT( bRet, "SotExchange::GetFormatDataFlavor(): DataFlavor not initialized" ); + + return bRet; +} + +/************************************************************************* +|* +|* SotExchange::GetFormatMimeType( ULONG nFormat ) +|* +*************************************************************************/ + +String SotExchange::GetFormatMimeType( ULONG nFormat ) +{ + String sMimeType; + if( SOT_FORMATSTR_ID_USER_END >= nFormat ) + sMimeType.AssignAscii( FormatArray_Impl::get()[nFormat].pMimeType ); + else + { + List& rL = InitFormats_Impl(); + + nFormat -= SOT_FORMATSTR_ID_USER_END + 1; + + if( rL.Count() > nFormat ) + sMimeType = ((DataFlavor*) rL.GetObject( nFormat ))->MimeType; + } + + DBG_ASSERT( sMimeType.Len(), "SotExchange::GetFormatMimeType(): DataFlavor not initialized" ); + + return sMimeType; +} + +/************************************************************************* +|* +|* SotExchange::GetFormatIdFromMimeType( const String& rMimeType ) +|* +*************************************************************************/ + +ULONG SotExchange::GetFormatIdFromMimeType( const String& rMimeType ) +{ + const DataFlavorRepresentation *pFormatArray_Impl = FormatArray_Impl::get(); + ULONG i, nMax = SOT_FORMAT_FILE_LIST; + for( i = SOT_FORMAT_STRING; i <= nMax; ++i ) + if( rMimeType.EqualsAscii( pFormatArray_Impl[ i ].pMimeType ) ) + return i; + + // BM: the chart format 105 ("StarChartDocument 5.0") was written + // only into 5.1 chart documents - in 5.0 and 5.2 it was 42 ("StarChart 5.0") + // The registry only contains the entry for the 42 format id. + nMax = SOT_FORMATSTR_ID_USER_END; + for( i = SOT_FORMAT_RTF; i <= nMax; ++i ) + if( rMimeType.EqualsAscii( pFormatArray_Impl[ i ].pMimeType ) ) + return ( (i == SOT_FORMATSTR_ID_STARCHARTDOCUMENT_50) + ? SOT_FORMATSTR_ID_STARCHART_50 + : i ); + + // dann in der dynamischen Liste + List& rL = InitFormats_Impl(); + ::rtl::OUString aMimeType( rMimeType ); + for( i = 0, nMax = rL.Count(); i < nMax; i++ ) + { + DataFlavor* pFlavor = (DataFlavor*) rL.GetObject( i ); + if( pFlavor && aMimeType == pFlavor->MimeType ) + return i + SOT_FORMATSTR_ID_USER_END + 1; + } + + return 0; +} + +/************************************************************************* +|* +|* SotExchange::GetFormatName() +|* +|* Beschreibung CLIP.SDW +*************************************************************************/ +ULONG SotExchange::GetFormat( const DataFlavor& rFlavor ) +{ + // teste zuerst die Standard - Name + const ::rtl::OUString& rMimeType = rFlavor.MimeType; + const String aMimeType( rMimeType ); + ULONG i, nMax = SOT_FORMAT_FILE_LIST; + const DataFlavorRepresentation *pFormatArray_Impl = FormatArray_Impl::get(); + for( i = SOT_FORMAT_STRING; i <= nMax; ++i ) + if( aMimeType.EqualsAscii( pFormatArray_Impl[ i ].pMimeType ) ) + return i; + + // BM: the chart format 105 ("StarChartDocument 5.0") was written + // only into 5.1 chart documents - in 5.0 and 5.2 it was 42 ("StarChart 5.0") + // The registry only contains the entry for the 42 format id. + nMax = SOT_FORMATSTR_ID_USER_END; + for( i = SOT_FORMAT_RTF; i <= nMax; ++i ) + if( aMimeType.EqualsAscii( pFormatArray_Impl[ i ].pMimeType ) ) + return ( (i == SOT_FORMATSTR_ID_STARCHARTDOCUMENT_50) + ? SOT_FORMATSTR_ID_STARCHART_50 + : i ); + + // dann in der dynamischen Liste + List& rL = InitFormats_Impl(); + for( i = 0, nMax = rL.Count(); i < nMax; i++ ) + { + DataFlavor* pFlavor = (DataFlavor*) rL.GetObject( i ); + if( pFlavor && rMimeType == pFlavor->MimeType ) + return i + SOT_FORMATSTR_ID_USER_END + 1; + } + + return 0; +} + +/************************************************************************* +|* +|* SotExchange::GetFormatName() +|* +|* Beschreibung CLIP.SDW +*************************************************************************/ +String SotExchange::GetFormatName( ULONG nFormat ) +{ + DataFlavor aFlavor; + String aRet; + + if( GetFormatDataFlavor( nFormat, aFlavor ) ) + aRet = aFlavor.HumanPresentableName; + + return aRet; +} + +BOOL SotExchange::IsInternal( const SvGlobalName& rName ) +{ + if ( rName == SvGlobalName(SO3_SW_CLASSID_60) || + rName == SvGlobalName(SO3_SC_CLASSID_60) || + rName == SvGlobalName(SO3_SIMPRESS_CLASSID_60) || + rName == SvGlobalName(SO3_SDRAW_CLASSID_60) || + rName == SvGlobalName(SO3_SCH_CLASSID_60) || + rName == SvGlobalName(SO3_SM_CLASSID_60) || + rName == SvGlobalName(SO3_SWWEB_CLASSID_60) || + rName == SvGlobalName(SO3_SWGLOB_CLASSID_60) ) + return TRUE; + return FALSE; +} diff --git a/sot/source/base/factory.cxx b/sot/source/base/factory.cxx new file mode 100644 index 000000000000..4934f99e78c6 --- /dev/null +++ b/sot/source/base/factory.cxx @@ -0,0 +1,406 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sot.hxx" + +#define _SOT_FACTORY_CXX +#define SOT_STRING_LIST + +#include <sot/factory.hxx> +#include <tools/debug.hxx> +#include <tools/string.hxx> +#include <sot/object.hxx> +#include <sot/sotdata.hxx> +#include <clsids.hxx> +#include <rtl/instance.hxx> +#include <com/sun/star/datatransfer/DataFlavor.hpp> + +/************** class SotData_Impl *********************************************/ +/************************************************************************* +|* SotData_Impl::SotData_Impl +|* +|* Beschreibung +*************************************************************************/ +SotData_Impl::SotData_Impl() + : nSvObjCount( 0 ) + , pObjectList( NULL ) + , pFactoryList( NULL ) + , pSotObjectFactory( NULL ) + , pSotStorageStreamFactory( NULL ) + , pSotStorageFactory( NULL ) + , pDataFlavorList( NULL ) +{ +} +/************************************************************************* +|* SOTDATA() +|* +|* Beschreibung +*************************************************************************/ +namespace { struct ImplData : public rtl::Static<SotData_Impl, ImplData> {}; } +SotData_Impl * SOTDATA() +{ + return &ImplData::get(); +} + +/************************************************************************* +|* SotFactory::DeInit() +|* +|* Beschreibung +*************************************************************************/ +void SotFactory::DeInit() +{ + SotData_Impl * pSotData = SOTDATA(); + + if( pSotData->nSvObjCount ) + { +#ifdef DBG_UTIL + ByteString aStr( "Objects alive: " ); + aStr.Append( ByteString::CreateFromInt32( pSotData->nSvObjCount ) ); + DBG_WARNING( aStr.GetBuffer() ); + +/* + SotObjectList *pObjList = pSotData->pObjectList; + + if( pObjList ) + { + SotObject * p = pObjList->First(); + while( p ) + { + String aStr( "Factory: " ); + aStr += p->GetSvFactory()->GetClassName(); + aStr += " Count: "; + aStr += p->GetRefCount(); + DBG_TRACE( "\tReferences:" ); + p->TestObjRef( FALSE ); +#ifdef TEST_INVARIANT + DBG_TRACE( "\tInvariant:" ); + p->TestInvariant( TRUE ); +#endif + p = pObjList->Next(); + } + } +*/ +#endif + return; + } + + // Muss von hinten nach vorne zerstoert werden. Das ist die umgekehrte + // Reihenfolge der Erzeugung + SotFactoryList* pFactoryList = pSotData->pFactoryList; + if( pFactoryList ) + { + SotFactory * pFact = pFactoryList->Last(); + while( NULL != (pFact = pFactoryList->Remove()) ) + { + delete pFact; + pFact = pFactoryList->Last(); + } + delete pFactoryList; + pSotData->pFactoryList = NULL; + } + + delete pSotData->pObjectList; + pSotData->pObjectList = NULL; + if( pSotData->pDataFlavorList ) + { + + for( ULONG i = 0, nMax = pSotData->pDataFlavorList->Count(); i < nMax; i++ ) + delete (::com::sun::star::datatransfer::DataFlavor*) pSotData->pDataFlavorList->GetObject( i ); + delete pSotData->pDataFlavorList; + pSotData->pDataFlavorList = NULL; + } + //delete pSOTDATA(); + //SOTDATA() = NULL; +} + + +/************** class SotFactory *****************************************/ +/************************************************************************* +|* SotFactory::SotFactory() +|* +|* Beschreibung +*************************************************************************/ +TYPEINIT0(SotFactory); + +SotFactory::SotFactory( const SvGlobalName & rName, + const String & rClassName, + CreateInstanceType pCreateFuncP ) + : SvGlobalName ( rName ) + , nSuperCount ( 0 ) + , pSuperClasses ( NULL ) + , pCreateFunc ( pCreateFuncP ) + , aClassName ( rClassName ) +{ +#ifdef DBG_UTIL + SvGlobalName aEmptyName; + if( aEmptyName != *this ) + { // wegen Sfx-BasicFactories + DBG_ASSERT( aEmptyName != *this, "create factory without SvGlobalName" ); + if( Find( *this ) ) + { + /* + String aStr( GetClassName() ); + aStr += ", UniqueName: "; + aStr += GetHexName(); + aStr += ", create factories with the same unique name"; + DBG_ERROR( aStr ); + */ + DBG_ERROR( "create factories with the same unique name" ); + } + } +#endif + SotData_Impl * pSotData = SOTDATA(); + if( !pSotData->pFactoryList ) + pSotData->pFactoryList = new SotFactoryList(); + // muss nach hinten, wegen Reihenfolge beim zerstoeren + pSotData->pFactoryList->Insert( this, LIST_APPEND ); +} + + +//========================================================================= +SotFactory::~SotFactory() +{ + delete [] pSuperClasses; +} + + +/************************************************************************* +|* SotFactory:: +|* +|* Beschreibung Zugriffsmethoden auf SotData_Impl-Daten +*************************************************************************/ +UINT32 SotFactory::GetSvObjectCount() +{ + return SOTDATA()->nSvObjCount; +} + + +const SotFactoryList * SotFactory::GetFactoryList() +{ + return SOTDATA()->pFactoryList; +} + +/************************************************************************* +|* SotFactory::Find() +|* +|* Beschreibung +*************************************************************************/ +const SotFactory* SotFactory::Find( const SvGlobalName & rFactName ) +{ + SvGlobalName aEmpty; + SotData_Impl * pSotData = SOTDATA(); + if( rFactName != aEmpty && pSotData->pFactoryList ) + { + SotFactory * pFact = pSotData->pFactoryList->First(); + while( pFact ) + { + if( *pFact == rFactName ) + return pFact; + pFact = pSotData->pFactoryList->Next(); + } + } + + return 0; +} + +/************************************************************************* +|* SotFactory::PutSuperClass() +|* +|* Beschreibung +*************************************************************************/ +void SotFactory::PutSuperClass( const SotFactory * pFact ) +{ + nSuperCount++; + if( !pSuperClasses ) + pSuperClasses = new const SotFactory * [ nSuperCount ]; + else + { + const SotFactory ** pTmp = new const SotFactory * [ nSuperCount ]; + memcpy( (void *)pTmp, (void *)pSuperClasses, + sizeof( void * ) * (nSuperCount -1) ); + delete [] pSuperClasses; + pSuperClasses = pTmp; + } + pSuperClasses[ nSuperCount -1 ] = pFact; +} + + +/************************************************************************* +|* SotFactory::IncSvObjectCount() +|* +|* Beschreibung +*************************************************************************/ +void SotFactory::IncSvObjectCount( SotObject * pObj ) +{ + SotData_Impl * pSotData = SOTDATA(); + pSotData->nSvObjCount++; + if( !pSotData->pObjectList ) + pSotData->pObjectList = new SotObjectList(); + if( pObj ) + pSotData->pObjectList->Insert( pObj ); +} + + +/************************************************************************* +|* SotFactory::DecSvObjectCount() +|* +|* Beschreibung +*************************************************************************/ +void SotFactory::DecSvObjectCount( SotObject * pObj ) +{ + SotData_Impl * pSotData = SOTDATA(); + pSotData->nSvObjCount--; + if( pObj ) + pSotData->pObjectList->Remove( pObj ); + if( !pSotData->nSvObjCount ) + { + //keine internen und externen Referenzen mehr + } +} + + +/************************************************************************* +|* SotFactory::TestInvariant() +|* +|* Beschreibung +*************************************************************************/ +void SotFactory::TestInvariant() +{ +#ifdef TEST_INVARIANT + SotData_Impl * pSotData = SOTDATA(); + if( pSotData->pObjectList ) + { + ULONG nCount = pSotData->pObjectList->Count(); + for( ULONG i = 0; i < nCount ; i++ ) + { + pSotData->pObjectList->GetObject( i )->TestInvariant( FALSE ); + } + } +#endif +} + +/************************************************************************* +|* SotFactory::CreateInstance() +|* +|* Beschreibung +*************************************************************************/ +void * SotFactory::CreateInstance( SotObject ** ppObj ) const +{ + DBG_ASSERT( pCreateFunc, "SotFactory::CreateInstance: pCreateFunc == 0" ); + return pCreateFunc( ppObj ); +} + +//========================================================================= +void * SotFactory::CastAndAddRef +( + SotObject * pObj /* Das Objekt von dem der Typ gepr"uft wird. */ +) const +/* [Beschreibung] + + Ist eine Optimierung, damit die Ref-Klassen k"urzer implementiert + werden k"onnen. pObj wird auf den Typ der Factory gecastet. + In c++ (wenn es immer erlaubt w"are) w"urde der void * wie im + Beispiel gebildet. + Factory der Klasse SvPersist. + void * p = (void *)(SvPersist *)pObj; + + [R"uckgabewert] + + void *, NULL, pObj war NULL oder das Objekt war nicht vom Typ + der Factory. + Ansonsten wird pObj zuerst auf den Typ der Factory + gecastet und dann auf void *. + + [Querverweise] + + <SotObject::CastAndAddRef> +*/ +{ + return pObj ? pObj->CastAndAddRef( this ) : NULL; +} + +//========================================================================= +void * SotFactory::AggCastAndAddRef +( + SotObject * pObj /* Das Objekt von dem der Typ gepr"uft wird. */ +) const +/* [Beschreibung] + + Ist eine Optimierung, damit die Ref-Klassen k"urzer implementiert + werden k"onnen. pObj wird auf den Typ der Factory gecastet. + In c++ (wenn es immer erlaubt w"are) w"urde der void * wie im + Beispiel gebildet. + Factory der Klasse SvPersist. + void * p = (void *)(SvPersist *)pObj; + Hinzu kommt noch, dass ein Objekt aus meheren c++ Objekten + zusammengesetzt sein kann. Diese Methode sucht nach einem + passenden Objekt. + + [R"uckgabewert] + + void *, NULL, pObj war NULL oder das Objekt war nicht vom Typ + der Factory. + Ansonsten wird pObj zuerst auf den Typ der Factory + gecastet und dann auf void *. + + [Querverweise] + + <SvObject::AggCast> +*/ +{ + void * pRet = NULL; + if( pObj ) + { + pRet = pObj->AggCast( this ); + if( pRet ) + pObj->AddRef(); + } + return pRet; +} + +/************************************************************************* +|* SotFactory::Is() +|* +|* Beschreibung +*************************************************************************/ +BOOL SotFactory::Is( const SotFactory * pSuperCl ) const +{ + if( this == pSuperCl ) + return TRUE; + + for( USHORT i = 0; i < nSuperCount; i++ ) + { + if( pSuperClasses[ i ]->Is( pSuperCl ) ) + return TRUE; + } + return FALSE; +} + + + + diff --git a/sot/source/base/filelist.cxx b/sot/source/base/filelist.cxx new file mode 100644 index 000000000000..4f854add304d --- /dev/null +++ b/sot/source/base/filelist.cxx @@ -0,0 +1,199 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sot.hxx" + +#include<tools/list.hxx> +#include<tools/stream.hxx> +#include<tools/string.hxx> +#include<tools/rtti.hxx> +#include<sot/exchange.hxx> +#include<filelist.hxx> +#include <osl/thread.h> + +TYPEINIT1_AUTOFACTORY( FileList, SvDataCopyStream ); + +// String-Liste zum Speichern der Namen deklarieren +DECLARE_LIST( FileStringList, String* ) + + +/************************************************************************* +|* +|* FileList - Ctor/Dtor +|* +\*************************************************************************/ + +FileList::FileList() +{ + pStrList = new FileStringList(); +} + +FileList::~FileList() +{ + ClearAll(); +} + +void FileList::ClearAll( void ) +{ + // Strings in der Liste loeschen + ULONG nCount = pStrList->Count(); + for( ULONG i = 0 ; i < nCount ; i++ ) + delete pStrList->GetObject( i ); + + // Liste loeschen + delete pStrList; +} + +/************************************************************************* +|* +|* FileList - Zuweisungsoperator +|* +\*************************************************************************/ + +FileList& FileList::operator=( const FileList& rFileList ) +{ + // Liste duplizieren + *pStrList = *rFileList.pStrList; + + // Strings in der Liste kopieren + ULONG nCount = pStrList->Count(); + for( ULONG i = 0 ; i < nCount ; i++ ) + pStrList->Replace( new String( *rFileList.pStrList->GetObject( i ) ), i ); + + return *this; +} + +/************************************************************************* +|* +|* FileList::GetFormatName() +|* +\*************************************************************************/ + +ULONG FileList::GetFormat() +{ + return FORMAT_FILE_LIST; +} + +/****************************************************************************** +|* +|* virtuelle SvData-Methoden +|* +\******************************************************************************/ + +void FileList::Load( SvStream& rIStm ) +{ + rIStm >> *this; +} + +void FileList::Save( SvStream& rOStm ) +{ + rOStm << *this; +} + +void FileList::Assign( const SvDataCopyStream& rCopyStream ) +{ + *this = (const FileList&)rCopyStream; +} + +/****************************************************************************** +|* +|* Stream-Operatoren +|* +\******************************************************************************/ + +/* + * NOTE: to correctly handle this Protocol with Unicode, native Win32 must be called: + * e.g. DropQueryFile + */ + +SvStream& operator<<( SvStream& rOStm, const FileList& /*rFileList*/ ) +{ + OSL_ENSURE(false, "Not implemented!"); + return rOStm; +} + +/* #i28176# + The Windows clipboard bridge now provides a double '\0' + terminated list of file names for format SOT_FORMAT_FILE_LIST + instead of the original Windows Sv_DROPFILES structure. All strings + in this list are UTF16 strings. Shell link files will be already + resolved by the Windows clipboard bridge.*/ +SvStream& operator>>( SvStream& rIStm, FileList& rFileList ) +{ + rFileList.ClearAll(); + rFileList.pStrList = new FileStringList(); + + String aStr; + sal_uInt16 c; + + while (!rIStm.IsEof()) + { + aStr.Erase(); + + // read first character of filepath; c==0 > reach end of stream + rIStm >> c; + if (!c) + break; + + // read string till c==0 + while (c && !rIStm.IsEof()) + { + aStr += (sal_Unicode)c; + rIStm >> c; + } + + // append the filepath + rFileList.AppendFile(aStr); + } + return rIStm; +} + +/****************************************************************************** +|* +|* Liste fuellen/abfragen +|* +\******************************************************************************/ + +void FileList::AppendFile( const String& rStr ) +{ + pStrList->Insert( new String( rStr ) , pStrList->Count() ); +} + +String FileList::GetFile( ULONG i ) const +{ + String aStr; + if( i < pStrList->Count() ) + aStr = *pStrList->GetObject( i ); + return aStr; +} + +ULONG FileList::Count( void ) const +{ + return pStrList->Count(); +} + diff --git a/sot/source/base/formats.cxx b/sot/source/base/formats.cxx new file mode 100644 index 000000000000..baddde6e716f --- /dev/null +++ b/sot/source/base/formats.cxx @@ -0,0 +1,1663 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sot.hxx" + +#define _SOT_FORMATS_INCLUDE_SYSTEMFORMATS +#include <tools/debug.hxx> +#include <tools/solar.h> + +#include <sot/exchange.hxx> +#include <sot/formats.hxx> +#include "filelist.hxx" +#include "clsids.hxx" + +#include <tools/globname.hxx> +#include <com/sun/star/datatransfer/DataFlavor.hpp> +#include <com/sun/star/datatransfer/XTransferable.hpp> + +using namespace::com::sun::star::uno; +using namespace::com::sun::star::datatransfer; + +struct SotAction_Impl +{ + ULONG nFormatId; // Clipboard Id + USHORT nAction; // Action Id + BYTE nContextCheckId; // additional check of content in clipboard +}; + + +// define a context check Id for every formatid +#define FILEGRPDSC_ONLY_URL 1 + +/* + Fuer jedes Ziel existiert in der Tabelle genau ein SotDestinationEntry_Impl. + Dieser Eintrag enthaelt u.a. fuer jedes vom Ziel auswertbare Format eine + Default-Action. Die Default-Aktionen verweisen fuer jedes Format auf + die auszuwertende Tabelle, d.h. sie enthalten nur EXCHG_IN_ACTION_MOVE, + EXCHG_IN_ACTION_COPY oder EXCHG_IN_ACTION_LINK. Entsprechend dieser Aktion + ist dann aMoveActions, aCopyActions oder aLinkActions auszuwerten. + Die Aktionen sind nach Prioritaet sortiert, d.h. je "wichtiger" das + Format ist, desto eher erscheint es in der Liste. +*/ + +struct SotDestinationEntry_Impl +{ + USHORT nDestination; + const SotAction_Impl* aDefaultActions; + const SotAction_Impl* aMoveActions; + const SotAction_Impl* aCopyActions; + const SotAction_Impl* aLinkActions; +}; + + +/* + Ueber diese Tabelle erfolgt die Zuordnung von Destination, vorhandenen + Datenformaten sowie gewuenschter Aktion zu einer Aktion und dem in + ihr zu benutzenden Datenformat. Die Tabelle ist nach den Exchange-Zielen + (EXCHG_DEST_*) sortiert. Innerhalb des Zieleintrages befinden sich genau + vier Tabellen fuer Default-, Move-, Copy- und Linkaktionen. Ueber + die Default-Tabelle erfolgt das Mapping zwischen Default-Aktion + (DropEvent::IsDefaultAction()) und daraus resultierender wirklicher + Aktion. Diese Tabelle enthaelt deshalb nur die Aktionen + EXCHG_IN_ACTION_COPY, EXCHG_IN_ACTION_MOVE und EXCHG_IN_ACTION_LINK, + die auf die spezielle Tabelle verweisen. Die uebrigen Tabellen + koennen beliebige Aktionen enthalten. Jede Tabelle ist nach der + Format-Prioritaet sortiert. Eintrag Null hat die hoechste Prioritaet. +*/ + +#define EXCHG_EMPYT_ARRAY \ +static SotAction_Impl __READONLY_DATA aEmptyArr[] = \ + { \ + { 0xffff, 0, 0 } \ + }; + +/* */ +#define EXCHG_DEST_DOC_OLEOBJ_ARRAY \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_OLEOBJ_Def[] = \ + { \ + { SOT_FORMATSTR_ID_INET_IMAGE, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_IMAGE, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_IN_ACTION_LINK, FILEGRPDSC_ONLY_URL }, \ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_IN_ACTION_LINK, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_OLEOBJ_Move[] = \ + { \ + { SOT_FORMATSTR_ID_SVIM, EXCHG_OUT_ACTION_INSERT_IMAGEMAP, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_OLEOBJ_Link[] = \ + { \ + { SOT_FORMATSTR_ID_INET_IMAGE, EXCHG_OUT_ACTION_INSERT_INTERACTIVE, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_IMAGE, EXCHG_OUT_ACTION_INSERT_INTERACTIVE, 0 }, \ + { SOT_FORMAT_FILE_LIST, EXCHG_OUT_ACTION_INSERT_INTERACTIVE, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_INTERACTIVE, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_INTERACTIVE, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_INTERACTIVE, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_INTERACTIVE, 0 },\ + { SOT_FORMATSTR_ID_SVIM, EXCHG_OUT_ACTION_INSERT_IMAGEMAP, 0 }, \ + { 0xffff, 0, 0 } \ + }; + +/* */ +#define EXCHG_DEST_CHARTDOC_OLEOBJ_ARRAY \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_CHARTDOC_OLEOBJ_Def[] = \ + { \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMATSTR_ID_INET_IMAGE, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_IMAGE, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_IN_ACTION_LINK, FILEGRPDSC_ONLY_URL }, \ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_IN_ACTION_LINK, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_CHARTDOC_OLEOBJ_Move[] = \ + { \ + { SOT_FORMATSTR_ID_SVIM, EXCHG_OUT_ACTION_INSERT_IMAGEMAP, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_CHARTDOC_OLEOBJ_Link[] = \ + { \ + { SOT_FORMAT_FILE_LIST, EXCHG_OUT_ACTION_INSERT_INTERACTIVE, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_INTERACTIVE, 0 }, \ + { SOT_FORMATSTR_ID_INET_IMAGE, EXCHG_OUT_ACTION_INSERT_INTERACTIVE, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_IMAGE, EXCHG_OUT_ACTION_INSERT_INTERACTIVE, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_INTERACTIVE, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_INTERACTIVE, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_INTERACTIVE, 0 },\ + { SOT_FORMATSTR_ID_SVIM, EXCHG_OUT_ACTION_INSERT_IMAGEMAP, 0 }, \ + { 0xffff, 0, 0 } \ + }; + +/* */ +#define EXCHG_DEST_DOC_TEXTFRAME_ARRAY \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_TEXTFRAME_Def[] = \ + { \ + { SOT_FORMAT_GDIMETAFILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_BITMAP, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SVXB, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_STRING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SONLK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_INET_IMAGE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_IMAGE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SOLK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_IN_ACTION_COPY, FILEGRPDSC_ONLY_URL }, \ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SD_OLE, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMATSTR_ID_EMBED_SOURCE, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMATSTR_ID_EMBED_SOURCE_OLE, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMATSTR_ID_LINK, EXCHG_IN_ACTION_MOVE, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_TEXTFRAME_Move[] = \ + { \ + { SOT_FORMATSTR_ID_SONLK, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_MOVE, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_FILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_INSERT_DRAWOBJ| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_INSERT_SVXB| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SD_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_EMBED_SOURCE, EXCHG_OUT_ACTION_INSERT_OLE, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ, EXCHG_OUT_ACTION_INSERT_OLE, 0 }, \ + { SOT_FORMATSTR_ID_HTML, EXCHG_OUT_ACTION_INSERT_HTML| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_OUT_ACTION_INSERT_HTML| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_OUT_ACTION_INSERT_HTML| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_RTF, EXCHG_IN_ACTION_COPY| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_IMAGE, EXCHG_IN_ACTION_COPY | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMAT_STRING, EXCHG_OUT_ACTION_INSERT_STRING| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_INSERT_GDIMETAFILE| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_INSERT_BITMAP| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_EMBED_SOURCE_OLE, EXCHG_OUT_ACTION_INSERT_OLE, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE, EXCHG_OUT_ACTION_INSERT_OLE, 0 }, \ + { SOT_FORMATSTR_ID_LINK, EXCHG_OUT_ACTION_INSERT_DDE, 0 }, \ + { SOT_FORMATSTR_ID_SVIM, EXCHG_OUT_ACTION_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_TEXTFRAME_Copy[] = \ + { \ + { SOT_FORMATSTR_ID_SBA_DATAEXCHANGE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SBA_CTRLDATAEXCHANGE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_XFORMS, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SONLK, EXCHG_IN_ACTION_COPY | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_COPY, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_FILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_INSERT_DRAWOBJ| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_INSERT_SVXB| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SD_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_EMBED_SOURCE, EXCHG_OUT_ACTION_INSERT_OLE, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ, EXCHG_OUT_ACTION_INSERT_OLE, 0 }, \ + { SOT_FORMATSTR_ID_HTML, EXCHG_OUT_ACTION_INSERT_HTML| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_OUT_ACTION_INSERT_HTML| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_OUT_ACTION_INSERT_HTML| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_RTF, EXCHG_IN_ACTION_COPY| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_IMAGE, EXCHG_IN_ACTION_COPY | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMAT_STRING, EXCHG_OUT_ACTION_INSERT_STRING| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_INSERT_GDIMETAFILE| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_EMBED_SOURCE_OLE, EXCHG_OUT_ACTION_INSERT_OLE, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE, EXCHG_OUT_ACTION_INSERT_OLE, 0 }, \ + { SOT_FORMATSTR_ID_LINK, EXCHG_OUT_ACTION_INSERT_DDE, 0 }, \ + { SOT_FORMATSTR_ID_SVIM, EXCHG_OUT_ACTION_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_TEXTFRAME_Link[] = \ + { \ + { SOT_FORMATSTR_ID_SONLK, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMATSTR_ID_SBA_DATAEXCHANGE, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMATSTR_ID_SBA_CTRLDATAEXCHANGE, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_LINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_LINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_LINK, EXCHG_OUT_ACTION_INSERT_DDE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBED_SOURCE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBED_SOURCE_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; + +#define EXCHG_DEST_DOC_TEXTFRAME_WEB_ARRAY \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_TEXTFRAME_WEB_Def[] = \ + { \ + { SOT_FORMAT_GDIMETAFILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_BITMAP, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SVXB, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_STRING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SONLK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_INET_IMAGE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_IMAGE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SOLK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_IN_ACTION_COPY, FILEGRPDSC_ONLY_URL }, \ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_LINK, EXCHG_IN_ACTION_MOVE, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_TEXTFRAME_WEB_Move[] = \ + { \ + { SOT_FORMATSTR_ID_SONLK, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_MOVE, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_FILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_INSERT_SVXB| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML, EXCHG_OUT_ACTION_INSERT_HTML| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_OUT_ACTION_INSERT_HTML| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_OUT_ACTION_INSERT_HTML| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_RTF, EXCHG_IN_ACTION_COPY| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_IMAGE, EXCHG_IN_ACTION_COPY | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMAT_STRING, EXCHG_OUT_ACTION_INSERT_STRING| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_INSERT_GDIMETAFILE| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_INSERT_BITMAP| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_LINK, EXCHG_OUT_ACTION_INSERT_DDE, 0 }, \ + { SOT_FORMATSTR_ID_SVIM, EXCHG_OUT_ACTION_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_TEXTFRAME_WEB_Copy[] = \ + { \ + { SOT_FORMATSTR_ID_SBA_DATAEXCHANGE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SBA_CTRLDATAEXCHANGE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_XFORMS, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SONLK, EXCHG_IN_ACTION_COPY | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_COPY, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_FILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_INSERT_SVXB| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML, EXCHG_OUT_ACTION_INSERT_HTML| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_OUT_ACTION_INSERT_HTML| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_OUT_ACTION_INSERT_HTML| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_RTF, EXCHG_IN_ACTION_COPY| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_IMAGE, EXCHG_IN_ACTION_COPY | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMAT_STRING, EXCHG_OUT_ACTION_INSERT_STRING| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_INSERT_GDIMETAFILE| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_LINK, EXCHG_OUT_ACTION_INSERT_DDE, 0 }, \ + { SOT_FORMATSTR_ID_SVIM, EXCHG_OUT_ACTION_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_TEXTFRAME_WEB_Link[] = \ + { \ + { SOT_FORMATSTR_ID_SONLK, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_LINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_LINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_LINK, EXCHG_OUT_ACTION_INSERT_DDE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; + +/* */ +#define EXCHG_DEST_DOC_GRAPHOBJ_ARRAY \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_GRAPHOBJ_Def[] = \ + { \ + { SOT_FORMAT_GDIMETAFILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_BITMAP, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SVXB, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_STRING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SOLK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_IN_ACTION_COPY, FILEGRPDSC_ONLY_URL }, \ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_IN_ACTION_COPY, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_GRAPHOBJ_Move[] = \ + { \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_REPLACE_DRAWOBJ | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_REPLACE_SVXB| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_REPLACE_GDIMETAFILE| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_REPLACE_BITMAP| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_GRAPHOBJ_Copy[] = \ + { \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_INSERT_DRAWOBJ | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_INSERT_SVXB| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_INSERT_GDIMETAFILE| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_INSERT_BITMAP| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_FILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_GRAPHOBJ_Link[] = \ + { \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_GET_ATTRIBUTES| EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_GET_ATTRIBUTES| EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { 0xffff, 0, 0 } \ + }; + +/* */ +#define EXCHG_DEST_DOC_LNKD_GRAPHOBJ_ARRAY \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_LNKD_GRAPHOBJ_Def[] = \ + { \ + { SOT_FORMAT_GDIMETAFILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_BITMAP, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SVXB, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_STRING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SOLK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_IN_ACTION_COPY, FILEGRPDSC_ONLY_URL }, \ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_LNKD_GRAPHOBJ_Move[] =\ + { \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_REPLACE_DRAWOBJ | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_REPLACE_SVXB| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_REPLACE_GDIMETAFILE| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_REPLACE_BITMAP| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_LNKD_GRAPHOBJ_Copy[] =\ + { \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_INSERT_DRAWOBJ | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_INSERT_SVXB| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_INSERT_GDIMETAFILE| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_INSERT_BITMAP| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_FILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_LNKD_GRAPHOBJ_Link[] =\ + { \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_GET_ATTRIBUTES| EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_GET_ATTRIBUTES| EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { 0xffff, 0, 0 } \ + }; + +/* */ +#define EXCHG_DEST_DOC_GRAPH_W_IMAP_ARRAY \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_GRAPH_W_IMAP_Def[] = \ + { \ + { SOT_FORMAT_GDIMETAFILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_BITMAP, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SVXB, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_STRING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SOLK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_IN_ACTION_COPY, FILEGRPDSC_ONLY_URL }, \ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_GRAPH_W_IMAP_Move[] = \ + { \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_REPLACE_DRAWOBJ | EXCHG_OUT_ACTION_FLAG_REPLACE_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_REPLACE_SVXB| EXCHG_OUT_ACTION_FLAG_REPLACE_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_REPLACE_GDIMETAFILE| EXCHG_OUT_ACTION_FLAG_REPLACE_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_REPLACE_BITMAP| EXCHG_OUT_ACTION_FLAG_REPLACE_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_REPLACE_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_REPLACE_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_REPLACE_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_REPLACE_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_REPLACE_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_GRAPH_W_IMAP_Copy[] = \ + { \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_INSERT_DRAWOBJ | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_INSERT_SVXB| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_INSERT_GDIMETAFILE| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_INSERT_BITMAP| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_FILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_GRAPH_W_IMAP_Link[] = \ + { \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_GET_ATTRIBUTES| EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_GET_ATTRIBUTES| EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; + +/* */ +#define EXCHG_DEST_DOC_LNKD_GRAPH_W_IMAP_ARRAY \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_LNKD_GRAPH_W_IMAP_Def[] =\ + { \ + { SOT_FORMAT_GDIMETAFILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_BITMAP, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SVXB, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_STRING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SOLK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_IN_ACTION_COPY, FILEGRPDSC_ONLY_URL }, \ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_LNKD_GRAPH_W_IMAP_Move[] =\ + { \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_REPLACE_DRAWOBJ | EXCHG_OUT_ACTION_FLAG_REPLACE_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_REPLACE_SVXB| EXCHG_OUT_ACTION_FLAG_REPLACE_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_REPLACE_GDIMETAFILE| EXCHG_OUT_ACTION_FLAG_REPLACE_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_REPLACE_BITMAP| EXCHG_OUT_ACTION_FLAG_REPLACE_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_REPLACE_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_REPLACE_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_REPLACE_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_REPLACE_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_REPLACE_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_LNKD_GRAPH_W_IMAP_Copy[] =\ + { \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_INSERT_DRAWOBJ | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_INSERT_SVXB| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_INSERT_GDIMETAFILE| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_INSERT_BITMAP| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_FILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_LNKD_GRAPH_W_IMAP_Link[] =\ + { \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_GET_ATTRIBUTES| EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_GET_ATTRIBUTES| EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; + + +/* */ +#define EXCHG_DEST_DOC_IMAPREGION_ARRAY \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_IMAPREGION_Def[] = \ + { \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_IN_ACTION_COPY, FILEGRPDSC_ONLY_URL }, \ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_IMAPREGION_Copy[] = \ + { \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_FILE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; + + +/* */ +#define EXCHG_DEST_DOC_DRAWOBJ_ARRAY \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_DRAWOBJ_Def[] = \ + { \ + { SOT_FORMAT_GDIMETAFILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_BITMAP, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SVXB, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_STRING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SOLK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_IN_ACTION_COPY, FILEGRPDSC_ONLY_URL }, \ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_IN_ACTION_COPY, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_DRAWOBJ_Copy[] = \ + { \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_REPLACE_DRAWOBJ | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_REPLACE_SVXB| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_REPLACE_GDIMETAFILE| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_REPLACE_BITMAP| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_DRAWOBJ_Move[] = \ + { \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_INSERT_DRAWOBJ | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_INSERT_SVXB| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_INSERT_GDIMETAFILE| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_INSERT_BITMAP| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_FILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_DRAWOBJ_Link[] = \ + { \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_GET_ATTRIBUTES| EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_GET_ATTRIBUTES| EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { 0xffff, 0, 0 } \ + }; + + +/* */ +#define EXCHG_DEST_DOC_URLBUTTON_ARRAY \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_URLBUTTON_Def[] = \ + { \ + { SOT_FORMAT_GDIMETAFILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_BITMAP, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SVXB, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SOLK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_IN_ACTION_COPY, FILEGRPDSC_ONLY_URL }, \ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_IN_ACTION_COPY, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_URLBUTTON_Move[] = \ + { \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_REPLACE_DRAWOBJ | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_REPLACE_SVXB | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_REPLACE_GDIMETAFILE | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_URLBUTTON_Copy[] = \ + { \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_INSERT_DRAWOBJ | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_INSERT_SVXB | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_INSERT_GDIMETAFILE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_INSERT_BITMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_FILE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; + + +/* */ +#define EXCHG_DEST_DOC_URLFIELD_ARRAY \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_URLFIELD_Def[] = \ + { \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_IN_ACTION_COPY, FILEGRPDSC_ONLY_URL }, \ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_IN_ACTION_COPY, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_URLFIELD_Copy[] = \ + { \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_FILE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_URLFIELD_Link[] = \ + { \ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_HYPERLINK, 0 }, \ + { 0xffff, 0, 0 } \ + }; + +/* */ +#define EXCHG_DEST_DOC_GROUPOBJ_ARRAY \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_GROUPOBJ_Def[] = \ + { \ + { SOT_FORMAT_GDIMETAFILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_BITMAP, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SVXB, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_STRING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SOLK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_IN_ACTION_COPY, FILEGRPDSC_ONLY_URL }, \ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_IN_ACTION_COPY, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_GROUPOBJ_Move[] = \ + { \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_REPLACE_DRAWOBJ | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_REPLACE_SVXB| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_REPLACE_GDIMETAFILE| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_REPLACE_BITMAP| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_REPLACE_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_KEEP_POSSIZE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_GROUPOBJ_Copy[] = \ + { \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_INSERT_DRAWOBJ | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_INSERT_SVXB| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_INSERT_GDIMETAFILE| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_INSERT_BITMAP| EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_GRAPH | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_FILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_DOC_GROUPOBJ_Link[] = \ + { \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_GET_ATTRIBUTES| EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_GET_ATTRIBUTES| EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_GET_ATTRIBUTES | EXCHG_OUT_ACTION_FLAG_FILL | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { 0xffff, 0, 0 } \ + }; + + +/* */ +#define EXCHG_DEST_SWDOC_FREE_AREA_ARRAY \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_SWDOC_FREE_AREA_Def[] = \ + { \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_RTF, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SVIM, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_IMAGE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_STRING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_IN_ACTION_COPY, FILEGRPDSC_ONLY_URL }, \ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SVXB, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_GDIMETAFILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_BITMAP, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SONLK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SOLK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SD_OLE, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMATSTR_ID_EMBED_SOURCE, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMATSTR_ID_EMBED_SOURCE_OLE, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMATSTR_ID_LINK, EXCHG_IN_ACTION_MOVE, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_SWDOC_FREE_AREA_Move[] = \ + { \ + { SOT_FORMATSTR_ID_SONLK, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_MOVE, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_FILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_INSERT_DRAWOBJ | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_INSERT_SVXB | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SD_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_EMBED_SOURCE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_HTML, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_RTF, EXCHG_IN_ACTION_COPY | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMAT_STRING, EXCHG_OUT_ACTION_INSERT_STRING, 0 }, \ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_INSERT_GDIMETAFILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_INSERT_BITMAP | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_EMBED_SOURCE_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_LINK, EXCHG_OUT_ACTION_INSERT_DDE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_SVIM, EXCHG_OUT_ACTION_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_SWDOC_FREE_AREA_Copy[] = \ + { \ + { SOT_FORMATSTR_ID_SBA_DATAEXCHANGE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SBA_CTRLDATAEXCHANGE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_XFORMS, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_COPY, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_FILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SONLK, EXCHG_IN_ACTION_COPY | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_INSERT_DRAWOBJ | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_INSERT_SVXB | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SD_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_EMBED_SOURCE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_HTML, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_RTF, EXCHG_IN_ACTION_COPY | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_IMAGE, EXCHG_IN_ACTION_COPY | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMAT_STRING, EXCHG_OUT_ACTION_INSERT_STRING | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_INSERT_GDIMETAFILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_INSERT_BITMAP | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_EMBED_SOURCE_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_LINK, EXCHG_OUT_ACTION_INSERT_DDE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_SVIM, EXCHG_OUT_ACTION_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_SWDOC_FREE_AREA_Link[] = \ + { \ + { SOT_FORMATSTR_ID_SONLK, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMATSTR_ID_SBA_DATAEXCHANGE, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMATSTR_ID_SBA_CTRLDATAEXCHANGE, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_LINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_LINK, EXCHG_OUT_ACTION_INSERT_DDE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBED_SOURCE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBED_SOURCE_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; + +#define EXCHG_DEST_SWDOC_FREE_AREA_WEB_ARRAY \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_SWDOC_FREE_AREA_WEB_Def[] = \ + { \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SOLK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_RTF, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SVIM, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_IMAGE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_STRING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_IN_ACTION_COPY, FILEGRPDSC_ONLY_URL }, \ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SVXB, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_GDIMETAFILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_BITMAP, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SONLK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_LINK, EXCHG_IN_ACTION_MOVE, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_SWDOC_FREE_AREA_WEB_Move[] = \ + { \ + { SOT_FORMATSTR_ID_SONLK, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_MOVE, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_FILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_INSERT_SVXB | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_RTF, EXCHG_IN_ACTION_COPY | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMAT_STRING, EXCHG_OUT_ACTION_INSERT_STRING, 0 }, \ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_INSERT_GDIMETAFILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_INSERT_BITMAP | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_LINK, EXCHG_OUT_ACTION_INSERT_DDE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_SVIM, EXCHG_OUT_ACTION_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_SWDOC_FREE_AREA_WEB_Copy[] = \ + { \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_COPY, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_FILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SONLK, EXCHG_IN_ACTION_COPY | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_INSERT_SVXB | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_RTF, EXCHG_IN_ACTION_COPY | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_IMAGE, EXCHG_IN_ACTION_COPY | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMAT_STRING, EXCHG_OUT_ACTION_INSERT_STRING | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_INSERT_GDIMETAFILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_INSERT_BITMAP | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_LINK, EXCHG_OUT_ACTION_INSERT_DDE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_SVIM, EXCHG_OUT_ACTION_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_SWDOC_FREE_AREA_WEB_Link[] = \ + { \ + { SOT_FORMATSTR_ID_SONLK, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_LINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_SOLK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_LINK, EXCHG_OUT_ACTION_INSERT_DDE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; + + +/* */ +#define EXCHG_DEST_SCDOC_FREE_AREA_ARRAY \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_SCDOC_FREE_AREA_Def[] = \ + { \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SVIM, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_STRING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_IN_ACTION_COPY, FILEGRPDSC_ONLY_URL }, \ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SVXB, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_GDIMETAFILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_BITMAP, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SD_OLE, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMATSTR_ID_EMBED_SOURCE, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMATSTR_ID_EMBED_SOURCE_OLE, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMATSTR_ID_LINK, EXCHG_IN_ACTION_MOVE, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_SCDOC_FREE_AREA_Move[] = \ + { \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_MOVE, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_FILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_INSERT_DRAWOBJ | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_INSERT_SVXB | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SD_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_EMBED_SOURCE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_BIFF_5, EXCHG_IN_ACTION_MOVE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_BIFF__5,EXCHG_IN_ACTION_MOVE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_HTML, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_STRING, EXCHG_OUT_ACTION_INSERT_STRING | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_INSERT_GDIMETAFILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_INSERT_BITMAP | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_EMBED_SOURCE_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_LINK, EXCHG_OUT_ACTION_INSERT_DDE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_SVIM, EXCHG_OUT_ACTION_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_BIFF_8, EXCHG_IN_ACTION_MOVE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_SCDOC_FREE_AREA_Copy[] = \ + { \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_COPY, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_FILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_INSERT_DRAWOBJ | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_INSERT_SVXB | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SD_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_EMBED_SOURCE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_BIFF_5, EXCHG_IN_ACTION_COPY | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_BIFF__5,EXCHG_IN_ACTION_COPY | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_HTML, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_STRING, EXCHG_OUT_ACTION_INSERT_STRING | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_INSERT_GDIMETAFILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_INSERT_BITMAP | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_EMBED_SOURCE_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_LINK, EXCHG_OUT_ACTION_INSERT_DDE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_SVIM, EXCHG_OUT_ACTION_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_BIFF_8, EXCHG_IN_ACTION_COPY | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_SCDOC_FREE_AREA_Link[] = \ + { \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_LINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_LINK, EXCHG_OUT_ACTION_INSERT_DDE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBED_SOURCE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBED_SOURCE_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; + + +/* */ +#define EXCHG_DEST_SDDOC_FREE_AREA_ARRAY \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_SDDOC_FREE_AREA_Def[] = \ + { \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SVIM, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_STRING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_IN_ACTION_COPY, FILEGRPDSC_ONLY_URL }, \ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SVXB, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_GDIMETAFILE, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMAT_BITMAP, EXCHG_IN_ACTION_COPY, 0 }, \ + { SOT_FORMATSTR_ID_SD_OLE, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMATSTR_ID_EMBED_SOURCE, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMATSTR_ID_EMBED_SOURCE_OLE, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE, EXCHG_IN_ACTION_MOVE, 0 }, \ + { SOT_FORMATSTR_ID_LINK, EXCHG_IN_ACTION_MOVE, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_SDDOC_FREE_AREA_Move[] = \ + { \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_MOVE, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_FILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_INSERT_DRAWOBJ | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_INSERT_SVXB | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SD_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_EMBED_SOURCE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_HTML, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_STRING, EXCHG_OUT_ACTION_INSERT_STRING | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_INSERT_GDIMETAFILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_INSERT_BITMAP | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_EMBED_SOURCE_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_LINK, EXCHG_OUT_ACTION_INSERT_DDE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_SVIM, EXCHG_OUT_ACTION_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_SDDOC_FREE_AREA_Copy[] = \ + { \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_COPY, 0 },\ + { SOT_FORMAT_FILE, EXCHG_OUT_ACTION_INSERT_FILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_DRAWING, EXCHG_OUT_ACTION_INSERT_DRAWOBJ | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SVXB, EXCHG_OUT_ACTION_INSERT_SVXB | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_SD_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_EMBED_SOURCE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_HTML, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_NO_COMMENT, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_HTML_SIMPLE, EXCHG_OUT_ACTION_INSERT_HTML | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_STRING, EXCHG_OUT_ACTION_INSERT_STRING | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_GDIMETAFILE, EXCHG_OUT_ACTION_INSERT_GDIMETAFILE | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMAT_BITMAP, EXCHG_OUT_ACTION_INSERT_BITMAP | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_EMBED_SOURCE_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_LINK, EXCHG_OUT_ACTION_INSERT_DDE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_SVIM, EXCHG_OUT_ACTION_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; \ +static SotAction_Impl __READONLY_DATA aEXCHG_DEST_SDDOC_FREE_AREA_Link[] = \ + { \ + { SOT_FORMAT_FILE_LIST, EXCHG_IN_ACTION_LINK, 0 }, \ + { SOT_FORMAT_FILE, EXCHG_IN_ACTION_LINK | EXCHG_OUT_ACTION_FLAG_INSERT_IMAGEMAP | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, FILEGRPDSC_ONLY_URL },\ + { SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR, EXCHG_OUT_ACTION_INSERT_HYPERLINK | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 },\ + { SOT_FORMATSTR_ID_LINK, EXCHG_OUT_ACTION_INSERT_DDE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBED_SOURCE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBED_SOURCE_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE, EXCHG_OUT_ACTION_INSERT_OLE | EXCHG_OUT_ACTION_FLAG_INSERT_TARGETURL, 0 }, \ + { 0xffff, 0, 0 } \ + }; + + +/* */ + +#define IMPL_DATA_ARRAY_1 \ +EXCHG_EMPYT_ARRAY \ +EXCHG_DEST_DOC_OLEOBJ_ARRAY \ +EXCHG_DEST_CHARTDOC_OLEOBJ_ARRAY \ +EXCHG_DEST_DOC_TEXTFRAME_ARRAY \ +EXCHG_DEST_DOC_GRAPHOBJ_ARRAY \ +EXCHG_DEST_DOC_LNKD_GRAPHOBJ_ARRAY \ +EXCHG_DEST_DOC_TEXTFRAME_WEB_ARRAY + +#define IMPL_DATA_ARRAY_2 \ +EXCHG_DEST_DOC_GRAPH_W_IMAP_ARRAY \ +EXCHG_DEST_DOC_LNKD_GRAPH_W_IMAP_ARRAY \ +EXCHG_DEST_DOC_IMAPREGION_ARRAY \ +EXCHG_DEST_DOC_DRAWOBJ_ARRAY \ +EXCHG_DEST_DOC_URLBUTTON_ARRAY \ +EXCHG_DEST_DOC_URLFIELD_ARRAY \ +EXCHG_DEST_DOC_GROUPOBJ_ARRAY \ +EXCHG_DEST_SWDOC_FREE_AREA_ARRAY \ +EXCHG_DEST_SCDOC_FREE_AREA_ARRAY \ +EXCHG_DEST_SDDOC_FREE_AREA_ARRAY \ +EXCHG_DEST_SWDOC_FREE_AREA_WEB_ARRAY \ + +#define IMPL_DATA_ARRAY_3 \ +static SotDestinationEntry_Impl __READONLY_DATA aDestinationArray[] = \ +{ \ + { EXCHG_DEST_DOC_OLEOBJ, \ + aEXCHG_DEST_DOC_OLEOBJ_Def, \ + aEXCHG_DEST_DOC_OLEOBJ_Move, \ + aEmptyArr, \ + aEXCHG_DEST_DOC_OLEOBJ_Link \ + }, \ + { EXCHG_DEST_CHARTDOC_OLEOBJ, \ + aEXCHG_DEST_CHARTDOC_OLEOBJ_Def, \ + aEXCHG_DEST_CHARTDOC_OLEOBJ_Move, \ + aEmptyArr, \ + aEXCHG_DEST_CHARTDOC_OLEOBJ_Link \ + }, \ + { EXCHG_DEST_DOC_TEXTFRAME, \ + aEXCHG_DEST_DOC_TEXTFRAME_Def, \ + aEXCHG_DEST_DOC_TEXTFRAME_Move, \ + aEXCHG_DEST_DOC_TEXTFRAME_Copy, \ + aEXCHG_DEST_DOC_TEXTFRAME_Link \ + }, \ + { EXCHG_DEST_DOC_GRAPHOBJ, \ + aEXCHG_DEST_DOC_GRAPHOBJ_Def, \ + aEXCHG_DEST_DOC_GRAPHOBJ_Move, \ + aEXCHG_DEST_DOC_GRAPHOBJ_Copy, \ + aEXCHG_DEST_DOC_GRAPHOBJ_Link \ + }, \ + { EXCHG_DEST_DOC_LNKD_GRAPHOBJ, \ + aEXCHG_DEST_DOC_LNKD_GRAPHOBJ_Def, \ + aEXCHG_DEST_DOC_LNKD_GRAPHOBJ_Move, \ + aEXCHG_DEST_DOC_LNKD_GRAPHOBJ_Copy, \ + aEXCHG_DEST_DOC_LNKD_GRAPHOBJ_Link \ + }, \ + { EXCHG_DEST_DOC_GRAPH_W_IMAP, \ + aEXCHG_DEST_DOC_GRAPH_W_IMAP_Def, \ + aEXCHG_DEST_DOC_GRAPH_W_IMAP_Move, \ + aEXCHG_DEST_DOC_GRAPH_W_IMAP_Copy, \ + aEXCHG_DEST_DOC_GRAPH_W_IMAP_Link \ + }, \ + { EXCHG_DEST_DOC_LNKD_GRAPH_W_IMAP, \ + aEXCHG_DEST_DOC_LNKD_GRAPH_W_IMAP_Def, \ + aEXCHG_DEST_DOC_LNKD_GRAPH_W_IMAP_Move, \ + aEXCHG_DEST_DOC_LNKD_GRAPH_W_IMAP_Copy, \ + aEXCHG_DEST_DOC_LNKD_GRAPH_W_IMAP_Link \ + }, \ + { EXCHG_DEST_DOC_IMAPREGION, \ + aEXCHG_DEST_DOC_IMAPREGION_Def, \ + aEXCHG_DEST_DOC_IMAPREGION_Copy, \ + aEmptyArr, \ + aEmptyArr \ + }, \ + { EXCHG_DEST_DOC_DRAWOBJ, \ + aEXCHG_DEST_DOC_DRAWOBJ_Def, \ + aEXCHG_DEST_DOC_DRAWOBJ_Copy, \ + aEXCHG_DEST_DOC_DRAWOBJ_Move, \ + aEXCHG_DEST_DOC_DRAWOBJ_Link \ + }, \ + { EXCHG_DEST_DOC_URLBUTTON, \ + aEXCHG_DEST_DOC_URLBUTTON_Def, \ + aEXCHG_DEST_DOC_URLBUTTON_Move, \ + aEXCHG_DEST_DOC_URLBUTTON_Copy, \ + aEmptyArr \ + }, \ + { EXCHG_DEST_DOC_URLFIELD, \ + aEXCHG_DEST_DOC_URLFIELD_Def, \ + aEmptyArr, \ + aEXCHG_DEST_DOC_URLFIELD_Copy, \ + aEXCHG_DEST_DOC_URLFIELD_Link \ + }, \ + { EXCHG_DEST_DOC_GROUPOBJ, \ + aEXCHG_DEST_DOC_GROUPOBJ_Def, \ + aEXCHG_DEST_DOC_GROUPOBJ_Move, \ + aEXCHG_DEST_DOC_GROUPOBJ_Copy, \ + aEXCHG_DEST_DOC_GROUPOBJ_Link \ + }, \ + { EXCHG_DEST_SWDOC_FREE_AREA, \ + aEXCHG_DEST_SWDOC_FREE_AREA_Def, \ + aEXCHG_DEST_SWDOC_FREE_AREA_Move, \ + aEXCHG_DEST_SWDOC_FREE_AREA_Copy, \ + aEXCHG_DEST_SWDOC_FREE_AREA_Link \ + }, \ + { EXCHG_DEST_SCDOC_FREE_AREA, \ + aEXCHG_DEST_SCDOC_FREE_AREA_Def, \ + aEXCHG_DEST_SCDOC_FREE_AREA_Move, \ + aEXCHG_DEST_SCDOC_FREE_AREA_Copy, \ + aEXCHG_DEST_SCDOC_FREE_AREA_Link \ + }, \ + { EXCHG_DEST_SDDOC_FREE_AREA, \ + aEXCHG_DEST_SDDOC_FREE_AREA_Def, \ + aEXCHG_DEST_SDDOC_FREE_AREA_Move, \ + aEXCHG_DEST_SDDOC_FREE_AREA_Copy, \ + aEXCHG_DEST_SDDOC_FREE_AREA_Link \ + }, \ + { EXCHG_DEST_DOC_TEXTFRAME_WEB, \ + aEXCHG_DEST_DOC_TEXTFRAME_WEB_Def, \ + aEXCHG_DEST_DOC_TEXTFRAME_WEB_Move, \ + aEXCHG_DEST_DOC_TEXTFRAME_WEB_Copy, \ + aEXCHG_DEST_DOC_TEXTFRAME_WEB_Link \ + }, \ + { EXCHG_DEST_SWDOC_FREE_AREA_WEB, \ + aEXCHG_DEST_SWDOC_FREE_AREA_WEB_Def, \ + aEXCHG_DEST_SWDOC_FREE_AREA_WEB_Move, \ + aEXCHG_DEST_SWDOC_FREE_AREA_WEB_Copy, \ + aEXCHG_DEST_SWDOC_FREE_AREA_WEB_Link \ + }, \ + { \ + 0xffff, 0, 0, 0, 0 \ + } \ +}; + + + + +// --------------------------------- +// - new style GetExchange methods - +// --------------------------------- + +sal_Bool IsFormatSupported( const DataFlavorExVector& rDataFlavorExVector, ULONG nId ) +{ + DataFlavorExVector::iterator aIter( ( (DataFlavorExVector&) rDataFlavorExVector ).begin() ); + DataFlavorExVector::iterator aEnd( ( (DataFlavorExVector&) rDataFlavorExVector ).end() ); + sal_Bool bRet = sal_False; + + while( aIter != aEnd ) + { + if( nId == (*aIter++).mnSotId ) + { + bRet = sal_True; + aIter = aEnd; + } + } + + return bRet; +} + +// ----------------------------------------------------------------------------- + +static BOOL CheckTransferableContext_Impl( const Reference< XTransferable >* pxTransferable, const SotAction_Impl& +#ifdef WNT +rEntry +#endif +) +{ + DataFlavor aFlavor; + BOOL bRet = TRUE; + + try + { + if( pxTransferable && (*pxTransferable).is() && + SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR, aFlavor ) && + (*pxTransferable)->isDataFlavorSupported( aFlavor ) ) + { +#ifdef WNT + switch( rEntry.nContextCheckId ) + { + case FILEGRPDSC_ONLY_URL: + { + bRet = FALSE; + + if( SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_FILECONTENT, aFlavor ) && + (*pxTransferable)->isDataFlavorSupported( aFlavor ) && + SotExchange::GetFormatDataFlavor( rEntry.nFormatId, aFlavor ) && + (*pxTransferable)->isDataFlavorSupported( aFlavor ) ) + { + Any aAny( (*pxTransferable)->getTransferData( aFlavor ) ); + + if( aAny.hasValue() ) + { + Sequence< sal_Int8 > aSeq; aAny >>= aSeq; + + if( aSeq.getLength() ) + { + FILEGROUPDESCRIPTOR* pFDesc = (FILEGROUPDESCRIPTOR*) aSeq.getConstArray(); + + if( pFDesc->cItems ) + { + ByteString sDesc( pFDesc->fgd[ 0 ].cFileName ); + bRet = 4 < sDesc.Len() && sDesc.Copy( sDesc.Len()-4 ).EqualsIgnoreCaseAscii( ".URL" ); + } + } + } + } + } + break; + } +#endif + } + } + catch( const UnsupportedFlavorException& ) + { + } + catch( const RuntimeException& ) + { + } + + + return bRet; +} + +// ----------------------------------------------------------------------------- + +static USHORT GetTransferableAction_Impl( + const DataFlavorExVector& rDataFlavorExVector, + const SotAction_Impl* pArray, + ULONG& rFormat, + ULONG nOnlyTestFormat, + const Reference< XTransferable >* pxTransferable ) +{ + try + { + if( rDataFlavorExVector.size() ) + { + DataFlavor aFlavor; + const SotAction_Impl* pArrayStart = pArray; + ULONG nId = pArray->nFormatId; + +#if OSL_DEBUG_LEVEL > 1 +// used for testing a specific format - change in the debugger the value + static ULONG nChkFormat = 0; + if( nChkFormat ) + { + for( ; 0xffff != pArray->nFormatId && + nChkFormat != pArray->nFormatId; ++pArray ) + ; + nId = pArray->nFormatId; + } +#endif + + while( nId != 0xffff ) + { + rFormat = nId; + + if( ( !nOnlyTestFormat || nOnlyTestFormat == nId ) && + IsFormatSupported( rDataFlavorExVector, nId ) && + ( !pArray->nContextCheckId || CheckTransferableContext_Impl( pxTransferable, *pArray ) ) ) + { + if( pxTransferable && (*pxTransferable).is() && ( SOT_FORMAT_FILE_LIST == rFormat ) ) + { + if( IsFormatSupported( rDataFlavorExVector, SOT_FORMAT_FILE ) ) + { + DataFlavor aFileListFlavor; + SotExchange::GetFormatDataFlavor( SOT_FORMAT_FILE_LIST, aFileListFlavor ); + Any aAny( (*pxTransferable)->getTransferData( aFileListFlavor ) ); + + if( aAny.hasValue() ) + { + Sequence< sal_Int8 > aSeq; aAny >>= aSeq; + SvMemoryStream aMemStm( (void*) aSeq.getConstArray(), aSeq.getLength(), STREAM_READ ); + FileList aFileList; + + aMemStm >> aFileList; + + if( !aMemStm.GetError() && ( aFileList.Count() == 1 ) ) + { + const SotAction_Impl* pCur = pArrayStart; + + while( pCur->nFormatId != 0xffff ) + { + if( pCur->nFormatId == SOT_FORMAT_FILE ) + { + rFormat = SOT_FORMAT_FILE; + return pCur->nAction; + } + pCur++; + } + } + } + } + } + return pArray->nAction; + } + pArray++; + nId = pArray->nFormatId; + } + } + } + catch( const UnsupportedFlavorException& ) + { + } + catch( const RuntimeException& ) + { + } + + return EXCHG_INOUT_ACTION_NONE; +} + +// ----------------------------------------------------------------------------- + +USHORT SotExchange::GetExchangeAction( const DataFlavorExVector& rDataFlavorExVector, + USHORT nDestination, + USHORT nSourceOptions, + USHORT nUserAction, + ULONG& rFormat, + USHORT& rDefaultAction, + ULONG nOnlyTestFormat, + const Reference< XTransferable >* pxTransferable ) +{ + // hier wird jetzt die oben definierte Tabelle "implementiert" + IMPL_DATA_ARRAY_1; + IMPL_DATA_ARRAY_2; + IMPL_DATA_ARRAY_3; + + rFormat = SOT_FORMAT_STRING; + + //Todo: Binaere Suche einbauen + const SotDestinationEntry_Impl* pEntry = aDestinationArray; + while( 0xffff != pEntry->nDestination ) + { + if( pEntry->nDestination == nDestination ) + break; + ++pEntry; + } + + if( 0xffff == pEntry->nDestination ) + { + return EXCHG_INOUT_ACTION_NONE; + } + + nUserAction &= EXCHG_ACTION_MASK; + rFormat = 0; + + /* Behandlung der Default-Action nach folgender Vorgehensweise: + + - Das Ziel wird nach der Default-Action gefragt + - Unterstuetzt die Quelle diese Aktion so wird sie uebernommen + - Anderenfalls wird aus den von der Quelle zur Verfuegung gestellten + Aktionen eine ausgewaehlt, die zu einer moeglichst nicht leeren + Ergebnisaktion fuehrt. Hierbei wird in dieser Reihenfolge + vorgegangen: Copy -> Link -> Move + */ + if( nUserAction == EXCHG_IN_ACTION_DEFAULT ) + { + nUserAction = GetTransferableAction_Impl( + rDataFlavorExVector, pEntry->aDefaultActions, + rFormat, nOnlyTestFormat, pxTransferable ); + // Unterstuetzt die Quelle die Aktion? + if( !(nUserAction & nSourceOptions )) + { + // Nein -> Alle Aktionen der Quelle checken + rDefaultAction = (EXCHG_IN_ACTION_COPY & nSourceOptions); + if( rDefaultAction ) + { + nUserAction = GetTransferableAction_Impl( + rDataFlavorExVector, pEntry->aCopyActions, + rFormat, nOnlyTestFormat, pxTransferable ); + if ( nUserAction ) + return nUserAction; + } + rDefaultAction = (EXCHG_IN_ACTION_LINK & nSourceOptions); + if( rDefaultAction ) + { + nUserAction = GetTransferableAction_Impl( + rDataFlavorExVector, pEntry->aLinkActions, + rFormat, nOnlyTestFormat, pxTransferable ); + if ( nUserAction ) + return nUserAction; + } + rDefaultAction = (EXCHG_IN_ACTION_MOVE & nSourceOptions); + if( rDefaultAction ) + { + nUserAction = GetTransferableAction_Impl( + rDataFlavorExVector, pEntry->aMoveActions, + rFormat, nOnlyTestFormat, pxTransferable ); + if ( nUserAction ) + return nUserAction; + } + rDefaultAction = 0; + return 0; + } + rDefaultAction = nUserAction; + } + else + rDefaultAction = nUserAction; + + switch( nUserAction ) + { + case EXCHG_IN_ACTION_MOVE: + nUserAction = GetTransferableAction_Impl( + rDataFlavorExVector, pEntry->aMoveActions, + rFormat, nOnlyTestFormat, pxTransferable ); + break; + + case EXCHG_IN_ACTION_COPY: + nUserAction = GetTransferableAction_Impl( + rDataFlavorExVector, pEntry->aCopyActions, + rFormat, nOnlyTestFormat, pxTransferable ); + break; + + case EXCHG_IN_ACTION_LINK: + nUserAction = GetTransferableAction_Impl( + rDataFlavorExVector, pEntry->aLinkActions, + rFormat, nOnlyTestFormat, pxTransferable ); + break; + + default: + nUserAction = EXCHG_INOUT_ACTION_NONE; + } + return nUserAction; +} + +// ----------------------------------------------------------------------------- + +USHORT SotExchange::GetExchangeAction( + const Reference< XTransferable >& rxTransferable, + USHORT nDestination, USHORT nSourceOptions, + USHORT nUserAction, ULONG& rFormat, + USHORT& rDefaultAction, ULONG nOnlyTestFormat ) +{ + DataFlavorExVector aVector; + + if( rxTransferable.is() ) + { + try + { + const Sequence< DataFlavor > aFlavors( rxTransferable->getTransferDataFlavors() ); + + for( sal_Int32 i = 0; i < aFlavors.getLength(); i++ ) + { + DataFlavorEx aFlavorEx; + const DataFlavor& rFlavor = aFlavors[ i ]; + + aFlavorEx.MimeType = rFlavor.MimeType; + aFlavorEx.HumanPresentableName = rFlavor.HumanPresentableName; + aFlavorEx.DataType = rFlavor.DataType; + aFlavorEx.mnSotId = SotExchange::RegisterFormat( rFlavor ); + + aVector.push_back( aFlavorEx ); + + if( ( SOT_FORMATSTR_ID_BMP == aFlavorEx.mnSotId ) && + !IsFormatSupported( aVector, SOT_FORMAT_BITMAP ) ) + { + if( SotExchange::GetFormatDataFlavor( SOT_FORMAT_BITMAP, aFlavorEx ) ) + { + aFlavorEx.mnSotId = SOT_FORMAT_BITMAP; + aVector.push_back( aFlavorEx ); + } + } + else if( ( ( SOT_FORMATSTR_ID_WMF == aFlavorEx.mnSotId ) || + ( SOT_FORMATSTR_ID_EMF == aFlavorEx.mnSotId ) ) && + !IsFormatSupported( aVector, SOT_FORMAT_GDIMETAFILE ) ) + { + if( SotExchange::GetFormatDataFlavor( SOT_FORMAT_GDIMETAFILE, aFlavorEx ) ) + { + aFlavorEx.mnSotId = SOT_FORMAT_GDIMETAFILE; + aVector.push_back( aFlavorEx ); + } + } + } + } + catch( const ::com::sun::star::uno::Exception& ) + { + } + } + + return( SotExchange::GetExchangeAction( aVector, nDestination, nSourceOptions, + nUserAction, rFormat, rDefaultAction, + nOnlyTestFormat, &rxTransferable ) ); +} + +USHORT SotExchange::IsChart( const SvGlobalName& rName ) +{ + USHORT nRet=0; +// if ( rName == SvGlobalName( SO3_SCH_CLASSID_8 ) ) +// nRet = SOFFICE_FILEFORMAT_8; +// else + if ( rName == SvGlobalName( SO3_SCH_CLASSID_60 ) ) + nRet = SOFFICE_FILEFORMAT_60; + else if ( rName == SvGlobalName( SO3_SCH_CLASSID_50 ) ) + nRet = SOFFICE_FILEFORMAT_50; + else if ( rName == SvGlobalName( SO3_SCH_CLASSID_40 ) ) + nRet = SOFFICE_FILEFORMAT_40; + else if ( rName == SvGlobalName( SO3_SCH_CLASSID_30 ) ) + nRet = SOFFICE_FILEFORMAT_31; + + return nRet; +} + +USHORT SotExchange::IsMath( const SvGlobalName& rName ) +{ + USHORT nRet=0; +// if ( rName == SvGlobalName( SO3_SM_CLASSID_8 ) ) +// nRet = SOFFICE_FILEFORMAT_8; +// else + if ( rName == SvGlobalName( SO3_SM_CLASSID_60 ) ) + nRet = SOFFICE_FILEFORMAT_60; + else if ( rName == SvGlobalName( SO3_SM_CLASSID_50 ) ) + nRet = SOFFICE_FILEFORMAT_50; + else if ( rName == SvGlobalName( SO3_SM_CLASSID_40 ) ) + nRet = SOFFICE_FILEFORMAT_40; + else if ( rName == SvGlobalName( SO3_SM_CLASSID_30 ) ) + nRet = SOFFICE_FILEFORMAT_31; + + return nRet; +} + diff --git a/sot/source/base/makefile.mk b/sot/source/base/makefile.mk new file mode 100644 index 000000000000..861b7cc5969b --- /dev/null +++ b/sot/source/base/makefile.mk @@ -0,0 +1,58 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=sot +TARGET=base + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +.IF "$(COM)"=="GCC" +NOOPTFILES= \ + $(SLO)$/exchange.obj +.ENDIF # GCC + +SLOFILES= \ + $(SLO)$/factory.obj \ + $(SLO)$/object.obj \ + $(SLO)$/exchange.obj \ + $(SLO)$/filelist.obj \ + $(SLO)$/formats.obj + +EXCEPTIONSFILES= \ + $(SLO)$/formats.obj + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk + diff --git a/sot/source/base/object.cxx b/sot/source/base/object.cxx new file mode 100644 index 000000000000..403a1c6bb61d --- /dev/null +++ b/sot/source/base/object.cxx @@ -0,0 +1,489 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sot.hxx" + +#define _SOT_OBJECT_CXX + +#include <tools/debug.hxx> +#include <sot/object.hxx> +#include <sot/factory.hxx> +#include <agg.hxx> + +/************** class SvAggregateMemberList *****************************/ +/************************************************************************/ +PRV_SV_IMPL_OWNER_LIST(SvAggregateMemberList,SvAggregate); + +/************** class SotObject ******************************************/ +class SotObjectFactory : public SotFactory +{ +public: + TYPEINFO(); + SotObjectFactory( const SvGlobalName & rName, + const String & rClassName, + CreateInstanceType pCreateFuncP ) + : SotFactory( rName, rClassName, pCreateFuncP ) + {} +}; +TYPEINIT1(SotObjectFactory,SotFactory); + + +SO2_IMPL_BASIC_CLASS_DLL(SotObject,SotObjectFactory, + SvGlobalName( 0xf44b7830, 0xf83c, 0x11d0, + 0xaa, 0xa1, 0x0, 0xa0, 0x24, 0x9d, 0x55, 0x90 ) ) +SO2_IMPL_INVARIANT(SotObject) + +/************************************************************************* +|* SotObject::TestMemberObjRef() +|* +|* Beschreibung: +*************************************************************************/ +void SotObject::TestMemberObjRef( BOOL /*bFree*/ ) +{ +} + +/************************************************************************* +|* SotObject::TestMemberObjRef() +|* +|* Beschreibung: +*************************************************************************/ +#ifdef TEST_INVARIANT +void SotObject::TestMemberInvariant( BOOL /*bPrint*/ ) +{ +} +#endif + +/************************************************************************* +|* SotObject::SotObject() +|* +|* Beschreibung +*************************************************************************/ +SotObject::SotObject() + : pAggList ( NULL ) + , nStrongLockCount( 0 ) + , nOwnerLockCount( 0 ) + , bOwner ( TRUE ) + , bSVObject ( FALSE ) + , bInClose ( FALSE ) +{ + SotFactory::IncSvObjectCount( this ); +} + +/************************************************************************* +|* +|* SotObject::~SotObject() +|* +|* Beschreibung +|* Ersterstellung MM 05.06.94 +|* Letzte Aenderung MM 05.06.94 +|* +*************************************************************************/ +SotObject::~SotObject() +{ + SotFactory::DecSvObjectCount( this ); +} + +/************************************************************************* +|* SotObject::GetInterface() +|* +|* Beschreibung: Um so3 zu helfen +*************************************************************************/ +IUnknown * SotObject::GetInterface( const SvGlobalName & ) +{ + return NULL; +} + +/************************************************************************* +|* SotObject::IsSvClass() +|* +|* Beschreibung +*************************************************************************/ +BOOL SotObject::IsSvObject() const +{ + return Owner() || bSVObject; +} + +/************************************************************************* +|* SotObject::QueryDelete() +|* +|* Beschreibung: Bei allen aggregierten Objekte muss der RefCount auf +|* 0 gehen, damit das Gesammt-Objekt zerstoert wird. Das +|* zerst�ren von Teilen ist verboten. Da der Aggregator +|* (oder Cast-Verwalter) den Zaehler der aggregierten +|* Objekte um 1 erhoeht, muss dies bei der Berechnung +|* des 0-RefCounts beruecksichtigt werden. +*************************************************************************/ +BOOL SotObject::ShouldDelete() +{ + if( !pAggList ) + return TRUE; + + SvAggregate & rMO = pAggList->GetObject( 0 ); + if( rMO.bMainObj ) + { + AddRef(); + pAggList->GetObject( 0 ).pObj->ReleaseRef(); + return FALSE; + } + + ULONG i; + for( i = 1; i < pAggList->Count(); i++ ) + { + SvAggregate & rAgg = pAggList->GetObject( i ); + // Groesser 1, wegen AddRef() bei AddInterface + if( !rAgg.bFactory && rAgg.pObj->GetRefCount() > 1 ) + { + // den eigenen hochzaehelen + AddRef(); + // einen Aggregierten runterzaehlen + rAgg.pObj->ReleaseRef(); + return FALSE; + } + } + AddNextRef(); // rekursion stoppen + for( i = pAggList->Count() -1; i > 0; i-- ) + { + // Referenzen aufloesen + DBG_ASSERT( !pAggList->GetObject( i ).bMainObj, "main object reference is opened" ); + RemoveInterface( i ); + } + delete pAggList; + pAggList = NULL; + // und zerstoeren, dies ist unabhaengig vom RefCount + return TRUE; +} + +/************************************************************************* +|* SotObject::QueryDelete() +|* +|* Beschreibung +*************************************************************************/ +void SotObject::QueryDelete() +{ + if( ShouldDelete() ) + SvRefBase::QueryDelete(); +} + + + +/************************************************************************* +|* SotObject::GetAggList() +|* +|* Beschreibung +*************************************************************************/ +SvAggregateMemberList & SotObject::GetAggList() +{ + if( !pAggList ) + { + pAggList = new SvAggregateMemberList( 2, 1 ); + pAggList->Append( SvAggregate() ); + } + return *pAggList; +} + + +/************************************************************************* +|* SotObject::RemoveInterface() +|* +|* Beschreibung +*************************************************************************/ +void SotObject::RemoveInterface( ULONG nPos ) +{ + SvAggregate & rAgg = pAggList->GetObject( nPos ); + if( !rAgg.bFactory ) + { + DBG_ASSERT( rAgg.pObj->pAggList, "no aggregation list" ); + DBG_ASSERT( rAgg.pObj->pAggList->GetObject( 0 ).pObj == this, + "not owner of aggregated object" ); + // sich selbst als Cast-Verwalter austragen + rAgg.pObj->pAggList->GetObject( 0 ) = SvAggregate(); + // Referenz aufloesen + rAgg.pObj->ReleaseRef(); + // Aus der eigenen List austragen + pAggList->Remove( nPos ); + } +} + +/************************************************************************* +|* SotObject::RemoveInterface() +|* +|* Beschreibung +*************************************************************************/ +void SotObject::RemoveInterface( SotObject * pObjP ) +{ + DBG_ASSERT( pObjP, "null pointer" ); + DBG_ASSERT( pAggList, "no aggregation list" ); + ULONG i; + for( i = 0; i < pAggList->Count(); i++ ) + { + SvAggregate & rAgg = pAggList->GetObject( i ); + if( !rAgg.bFactory && pObjP == rAgg.pObj ) + RemoveInterface( i ); + } + DBG_ASSERT( i < pAggList->Count(), "object not found" ); +} + +/************************************************************************* +|* SotObject::AddInterface() +|* +|* Beschreibung +*************************************************************************/ +void SotObject::AddInterface( SotObject * pObjP ) +{ + pObjP->AddRef(); // Objekt festhalten + GetAggList(); + pAggList->Append( SvAggregate( pObjP, FALSE ) ); + + // sich selbst als Typecast-Verwalter eintragen + SvAggregateMemberList & rAList = pObjP->GetAggList(); + DBG_ASSERT( !rAList.GetObject( 0 ).bMainObj, "try to aggregate twice" ); + rAList[ 0 ] = SvAggregate( this, TRUE ); +} + +/************************************************************************* +|* SotObject::AddInterface() +|* +|* Beschreibung +*************************************************************************/ +void SotObject::AddInterface( SotFactory * pFactP ) +{ + GetAggList(); + pAggList->Append( SvAggregate( pFactP ) ); +} + +/************************************************************************* +|* SotObject::CreateAggObj() +|* +|* Beschreibung +*************************************************************************/ +SotObjectRef SotObject::CreateAggObj( const SotFactory * ) +{ + return SotObjectRef(); +} + + +/************************************************************************* +|* SotObject::DownAggCast() +|* +|* Beschreibung +*************************************************************************/ +void * SotObject::DownAggCast( const SotFactory * pFact ) +{ + void * pCast = NULL; + // geht den Pfad nur Richtung aggregierte Objekte + if( pAggList ) + { + for( ULONG i = 1; !pCast || i < pAggList->Count(); i++ ) + { + SvAggregate & rAgg = pAggList->GetObject( i ); + if( rAgg.bFactory ) + { + if( rAgg.pFact->Is( pFact ) ) + { + // On-Demand erzeugen, wenn Typ gebraucht + SotObjectRef aObj( CreateAggObj( rAgg.pFact ) ); + rAgg.bFactory = FALSE; + rAgg.pObj = aObj; + rAgg.pObj->AddRef(); + + // sich selbst als Typecast-Verwalter eintragen + SvAggregateMemberList & rAList = rAgg.pObj->GetAggList(); + DBG_ASSERT( !rAList.GetObject( 0 ).bMainObj, "try to aggregate twice" ); + rAList[ 0 ] = SvAggregate( this, TRUE ); + } + } + if( !rAgg.bFactory ) + { + // muss der (void *) auf Klasse pFact sein + pCast = rAgg.pObj->Cast( pFact ); + if( !pCast ) + pCast = rAgg.pObj->DownAggCast( pFact ); + if( pCast ) + break; + } + } + } + return pCast; +} + +/************************************************************************* +|* SotObject::AggCast() +|* +|* Beschreibung +*************************************************************************/ +void * SotObject::AggCast( const SotFactory * pFact ) +{ + void * pCast = NULL; + if( pAggList ) + { + SvAggregate & rAgg = pAggList->GetObject( 0 ); + if( rAgg.bMainObj ) + return rAgg.pObj->AggCast( pFact ); + pCast = Cast( pFact ); + if( !pCast ) + pCast = DownAggCast( pFact ); + } + else + pCast = Cast( pFact ); + return pCast; +} + +/************************************************************************* +|* SotObject::CastAndAddRef() +|* +|* Beschreibung +*************************************************************************/ +void * SotObject::CastAndAddRef( const SotFactory * pFact ) +{ + void * pCast = Cast( pFact ); + if( pCast ) + AddRef(); + return pCast; +} + +/************************************************************************* +|* SotObject::GetMainObj() +|* +|* Beschreibung +*************************************************************************/ +SotObject * SotObject::GetMainObj() const +{ + if( pAggList ) + { + if( pAggList->GetObject( 0 ).bMainObj ) + return pAggList->GetObject( 0 ).pObj->GetMainObj(); + } + return (SotObject *)this; +} + +//========================================================================= +USHORT SotObject::FuzzyLock +( + BOOL bLock, /* TRUE, lock. FALSE, unlock. */ + BOOL /*bIntern*/, /* TRUE, es handelt sich um einen internen Lock. + FALSE, der Lock kam von aussen (Ole2, Ipc2) */ + BOOL bClose /* TRUE, Close aufrufen wenn letzte Lock */ +) +/* [Beschreibung] + + Erlaubte Parameterkombinationen: + ( TRUE, TRUE, * ) -> interner Lock. + ( FALSE, TRUE, TRUE ) -> interner Unlock mit Close, + wenn LockCount() == 0 + ( TRUE, FALSE, * ) -> externer Lock. + ( FALSE, FALSE, TRUE ) -> externer Unlock mit Close, + wenn LockCount() == 0 + ( FALSE, FALSE, FALSE ) -> externer Unlock + + F"ur !Owner() wird der Aufruf an das externe Objekt weitergeleitet. + F"ur diese muss das <IOleItemContainer>-Interface zur Vef"ugung stehen. + bIntern und bClose werden dann ignoriert. + Wenn der LockCount auf 0 wechselt, wird <SotObject::DoClose> + gerufen, wenn kein OwnerLock besteht. + + [Anmerkung] + +*/ +{ + SotObjectRef xHoldAlive( this ); + USHORT nRet; + if( bLock ) + { + AddRef(); + nRet = ++nStrongLockCount; + } + else + { + nRet = --nStrongLockCount; + ReleaseRef(); + } + + if( !nRet && bClose && !nOwnerLockCount ) + DoClose(); + return nRet; +} + +//========================================================================= +void SotObject::OwnerLock +( + BOOL bLock /* TRUE, lock. FALSE, unlock. */ +) +/* [Beschreibung] + + Wenn der OwnerLock auf Null dekrementiert, dann wird die Methode + DoClose gerufen. Dies geschieht unabh"angig vom Lock. bzw. RefCount. + Ist der OwnerLock-Z"ahler != Null, dann wird kein DoClose durch + <SotObject::FuzzyLock> gerufen. +*/ +{ + if( bLock ) + { + nOwnerLockCount++; + AddRef(); + } + else if ( nOwnerLockCount ) + { + if( 0 == --nOwnerLockCount ) + DoClose(); + ReleaseRef(); + } +} + +void SotObject::RemoveOwnerLock() +{ + if ( nOwnerLockCount ) + { + --nOwnerLockCount; + ReleaseRef(); + } + else { + DBG_ERROR("OwnerLockCount underflow!"); + } +} + +//========================================================================= +BOOL SotObject::DoClose() +{ + BOOL bRet = FALSE; + if( !bInClose ) + { + SotObjectRef xHoldAlive( this ); + bInClose = TRUE; + bRet = Close(); + bInClose = FALSE; + } + return bRet; +} + +//========================================================================= +BOOL SotObject::Close() +{ + return TRUE; +} + + diff --git a/sot/source/sdstor/makefile.mk b/sot/source/sdstor/makefile.mk new file mode 100644 index 000000000000..f5c6d81548c9 --- /dev/null +++ b/sot/source/sdstor/makefile.mk @@ -0,0 +1,64 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=sot +TARGET=sdstor + +# --- Settings ----------------------------------------------------- + +ENABLE_EXCEPTIONS=true + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/unostorageholder.obj \ + $(SLO)$/ucbstorage.obj \ + $(SLO)$/stg.obj \ + $(SLO)$/stgcache.obj \ + $(SLO)$/stgstrms.obj \ + $(SLO)$/stgelem.obj \ + $(SLO)$/stgio.obj \ + $(SLO)$/stgole.obj \ + $(SLO)$/stgdir.obj \ + $(SLO)$/stgavl.obj \ + $(SLO)$/storinfo.obj \ + $(SLO)$/storage.obj + +EXCEPTIONSFILES= \ + $(SLO)$/unostorageholder.obj\ + $(SLO)$/ucbstorage.obj\ + $(SLO)$/storage.obj + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk + diff --git a/sot/source/sdstor/stg.cxx b/sot/source/sdstor/stg.cxx new file mode 100644 index 000000000000..1c749aa05cb8 --- /dev/null +++ b/sot/source/sdstor/stg.cxx @@ -0,0 +1,1091 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sot.hxx" + +#include <storinfo.hxx> +#include <osl/file.hxx> +#include <tools/tempfile.hxx> +#include <tools/ownlist.hxx> +#include <tools/string.hxx> +#ifndef _TOOLS_FSYS_HXX +#include <tools/fsys.hxx> +#endif +#ifndef _TOOLS_STREAM_HXX +#include <tools/stream.hxx> +#endif +#include <tools/pstm.hxx> +#include <tools/debug.hxx> + +#include "stg.hxx" +#include "stgelem.hxx" +#include "stgcache.hxx" +#include "stgstrms.hxx" +#include "stgdir.hxx" +#include "stgio.hxx" +#include "stgole.hxx" + +static long nTmpCount = 0; + +// The internal open mode is STREAM_READ | STREAM_TRUNC, which is silly +// by itself. It inhibits the checking of sharing modes and is used +// during CopyTo() and MoveTo() for opening a stream in read mode +// although it may be open in DENYALL mode + +#define INTERNAL_MODE ( STREAM_READ | STREAM_TRUNC ) + +///////////////////////// class StorageBase ////////////////////////////// + +TYPEINIT0( StorageBase ); +TYPEINIT1( BaseStorageStream, StorageBase ); +TYPEINIT1( BaseStorage, StorageBase ); + +StorageBase::StorageBase() + : m_bAutoCommit( FALSE ) +{ + m_nMode = STREAM_READ; + m_nError = SVSTREAM_OK; +} + +StorageBase::~StorageBase() +{ +} + +// The following three methods are declared as const, since they +// may be called from within a const method. + +ULONG StorageBase::GetError() const +{ + ULONG n = m_nError; + ((StorageBase*) this)->m_nError = SVSTREAM_OK; + return n; +} + +void StorageBase::SetError( ULONG n ) const +{ + if( !m_nError ) + ((StorageBase*) this)->m_nError = n; +} + +void StorageBase::ResetError() const +{ + ((StorageBase*) this)->m_nError = SVSTREAM_OK; +} + +// Retrieve the underlying SvStream for info purposes + +const SvStream* OLEStorageBase::GetSvStream_Impl() const +{ + return pIo ? pIo->GetStrm() : NULL; +} + +OLEStorageBase::OLEStorageBase( StgIo* p, StgDirEntry* pe, StreamMode& nMode ) + : nStreamMode( nMode ), pIo( p ), pEntry( pe ) +{ + p->IncRef(); + if( pe ) + pe->nRefCnt++; +} + +OLEStorageBase::~OLEStorageBase() +{ + if( pEntry ) + { + DBG_ASSERT( pEntry->nRefCnt, "RefCount unter 0" ); + if( !--pEntry->nRefCnt ) + { + if( pEntry->bZombie ) + delete pEntry; + else + pEntry->Close(); + } + } + + + if( !pIo->DecRef() ) + delete pIo; +} + +// Validate the instance for I/O + +BOOL OLEStorageBase::Validate_Impl( BOOL bWrite ) const +{ + if( pEntry + && !pEntry->bInvalid + && ( !bWrite || !pEntry->bDirect || ( nStreamMode & STREAM_WRITE ) ) ) + return TRUE; + return FALSE; +} + +BOOL OLEStorageBase::ValidateMode_Impl( StreamMode m, StgDirEntry* p ) const +{ + if( m == INTERNAL_MODE ) + return TRUE; + USHORT nCurMode = ( p && p->nRefCnt ) ? p->nMode : 0xFFFF; + if( ( m & 3 ) == STREAM_READ ) + { + // only SHARE_DENYWRITE or SHARE_DENYALL allowed + if( ( ( m & STREAM_SHARE_DENYWRITE ) + && ( nCurMode & STREAM_SHARE_DENYWRITE ) ) + || ( ( m & STREAM_SHARE_DENYALL ) + && ( nCurMode & STREAM_SHARE_DENYALL ) ) ) + return TRUE; + } + else + { + // only SHARE_DENYALL allowed + // storages open in r/o mode are OK, since only + // the commit may fail + if( ( m & STREAM_SHARE_DENYALL ) + && ( nCurMode & STREAM_SHARE_DENYALL ) ) + return TRUE; + } + return FALSE; +} + + +//////////////////////// class StorageStream ///////////////////////////// + +TYPEINIT1( StorageStream, BaseStorageStream ); + +StorageStream::StorageStream( StgIo* p, StgDirEntry* q, StreamMode m ) + : OLEStorageBase( p, q, m_nMode ), nPos( 0L ) +{ + // The dir entry may be 0; this means that the stream is invalid. + if( q ) + { + if( q->nRefCnt == 1 ) + { + q->nMode = m; + q->OpenStream( *p ); + } + } + else + m &= ~STREAM_READWRITE; + m_nMode = m; +} + +StorageStream::~StorageStream() +{ + // Do an auto-commit if the entry is open in direct mode + if( m_bAutoCommit ) + Commit(); + if( pEntry && pEntry->nRefCnt && pEntry->bDirect && (m_nMode & STREAM_WRITE) ) + pEntry->Commit(); +} + +BOOL StorageStream::Equals( const BaseStorageStream& rStream ) const +{ + const StorageStream* pOther = PTR_CAST( StorageStream, &rStream ); + return pOther && ( pOther->pEntry == pEntry ); +} + +ULONG StorageStream::Read( void* pData, ULONG nSize ) +{ + if( Validate() ) + { + pEntry->Seek( nPos ); + nSize = pEntry->Read( pData, (INT32) nSize ); + pIo->MoveError( *this ); + nPos += nSize; + } + else + nSize = 0L; + return nSize; +} + +ULONG StorageStream::Write( const void* pData, ULONG nSize ) +{ + if( Validate( TRUE ) ) + { + pEntry->Seek( nPos ); + nSize = pEntry->Write( pData, (INT32) nSize ); + pIo->MoveError( *this ); + nPos += nSize; + } + else + nSize = 0L; + return nSize; +} + +ULONG StorageStream::Seek( ULONG n ) +{ + if( Validate() ) + return nPos = pEntry->Seek( n ); + else + return n; +} + +void StorageStream::Flush() +{ + // Flushing means committing, since streams are never transacted + Commit(); +} + +BOOL StorageStream::SetSize( ULONG nNewSize ) +{ + if( Validate( TRUE ) ) + { + BOOL b = pEntry->SetSize( (INT32) nNewSize ); + pIo->MoveError( *this ); + return b; + } + else + return FALSE; +} + +BOOL StorageStream::Commit() +{ + if( !Validate() ) + return FALSE; + if( !( m_nMode & STREAM_WRITE ) ) + { + SetError( SVSTREAM_ACCESS_DENIED ); + return FALSE; + } + else + { + pEntry->Commit(); + pIo->MoveError( *this ); + return Good(); + } +} + +BOOL StorageStream::Revert() +{ + pEntry->Revert(); + pIo->MoveError( *this ); + return Good(); +} + +BOOL StorageStream::CopyTo( BaseStorageStream* pDest ) +{ + if( !Validate() || !pDest->Validate( TRUE ) || Equals( *pDest ) ) + return FALSE; + pEntry->Copy( *pDest ); + pDest->Commit(); + pIo->MoveError( *this ); + SetError( pDest->GetError() ); + return BOOL( Good() && pDest->Good() ); +} + +const SvStream* StorageStream::GetSvStream() const +{ + return GetSvStream_Impl(); +} + +BOOL StorageStream::Validate( BOOL bValidate ) const +{ + BOOL bRet = Validate_Impl( bValidate ); + if ( !bRet ) + SetError( SVSTREAM_ACCESS_DENIED ); + return bRet; +} + +BOOL StorageStream::ValidateMode( StreamMode nMode ) const +{ + BOOL bRet = ValidateMode_Impl( nMode, NULL ); + if ( !bRet ) + SetError( SVSTREAM_ACCESS_DENIED ); + return bRet; +} + +BOOL StorageStream::ValidateMode( StreamMode nMode, StgDirEntry* p ) const +{ + BOOL bRet = ValidateMode_Impl( nMode, p ); + if ( !bRet ) + SetError( SVSTREAM_ACCESS_DENIED ); + return bRet; +} + +///////////////////////// class SvStorageInfo ////////////////////////////// + +SvStorageInfo::SvStorageInfo( const StgDirEntry& rE ) +{ + rE.aEntry.GetName( aName ); + bStorage = BOOL( rE.aEntry.GetType() == STG_STORAGE ); + bStream = BOOL( rE.aEntry.GetType() == STG_STREAM ); + nSize = bStorage ? 0 : rE.aEntry.GetSize(); +} + +/////////////////////////// class Storage //////////////////////////////// + +BOOL Storage::IsStorageFile( const String & rFileName ) +{ + StgIo aIo; + if( aIo.Open( rFileName, STREAM_STD_READ ) ) + return aIo.Load(); + return FALSE; +} + +BOOL Storage::IsStorageFile( SvStream* pStream ) +{ + StgHeader aHdr; + ULONG nPos = pStream->Tell(); + BOOL bRet = ( aHdr.Load( *pStream ) && aHdr.Check() ); + + // It's not a stream error if it is too small for a OLE storage header + if ( pStream->GetErrorCode() == ERRCODE_IO_CANTSEEK ) + pStream->ResetError(); + pStream->Seek( nPos ); + return bRet; +} + +// Open the storage file. If writing is permitted and the file is not +// a storage file, initialize it. + +TYPEINIT1( Storage, BaseStorage ); + +Storage::Storage( const String& rFile, StreamMode m, BOOL bDirect ) + : OLEStorageBase( new StgIo, NULL, m_nMode ), aName( rFile ), bIsRoot( FALSE ) +{ + BOOL bTemp = FALSE; + if( !aName.Len() ) + { + // no name = temporary name! + aName = TempFile::CreateTempName(); + bTemp = TRUE; + } + // the root storage creates the I/O system + m_nMode = m; + if( pIo->Open( aName, m ) ) + { + Init( BOOL( ( m & ( STREAM_TRUNC | STREAM_NOCREATE ) ) == STREAM_TRUNC ) ); + if( pEntry ) + { + pEntry->bDirect = bDirect; + pEntry->nMode = m; + pEntry->bTemp = bTemp; + } + } + else + { + pIo->MoveError( *this ); + pEntry = NULL; + } +} + +// Create a storage on a given stream. + +Storage::Storage( SvStream& r, BOOL bDirect ) + : OLEStorageBase( new StgIo, NULL, m_nMode ), bIsRoot( FALSE ) +{ + m_nMode = STREAM_READ; + if( r.IsWritable() ) + m_nMode = STREAM_READ | STREAM_WRITE; + if( r.GetError() == SVSTREAM_OK ) + { + pIo->SetStrm( &r, FALSE ); + ULONG nSize = r.Seek( STREAM_SEEK_TO_END ); + r.Seek( 0L ); + // Initializing is OK if the stream is empty + Init( BOOL( nSize == 0 ) ); + if( pEntry ) + { + pEntry->bDirect = bDirect; + pEntry->nMode = m_nMode; + } + pIo->MoveError( *this ); + } + else + { + SetError( r.GetError() ); + pEntry = NULL; + } +} + + +Storage::Storage( UCBStorageStream& rStrm, BOOL bDirect ) + : OLEStorageBase( new StgIo, NULL, m_nMode ), bIsRoot( FALSE ) +{ + m_nMode = STREAM_READ; + + if ( rStrm.GetError() != SVSTREAM_OK ) + { + SetError( rStrm.GetError() ); + pEntry = NULL; + return; + } + + SvStream* pStream = rStrm.GetModifySvStream(); + if ( !pStream ) + { + OSL_ENSURE( FALSE, "UCBStorageStream can not provide SvStream implementation!\n" ); + SetError( SVSTREAM_GENERALERROR ); + pEntry = NULL; + return; + } + + if( pStream->IsWritable() ) + m_nMode = STREAM_READ | STREAM_WRITE; + + pIo->SetStrm( &rStrm ); + + ULONG nSize = pStream->Seek( STREAM_SEEK_TO_END ); + pStream->Seek( 0L ); + // Initializing is OK if the stream is empty + Init( BOOL( nSize == 0 ) ); + if( pEntry ) + { + pEntry->bDirect = bDirect; + pEntry->nMode = m_nMode; + } + + pIo->MoveError( *this ); +} + + +// Perform common code for both ctors above. + +void Storage::Init( BOOL bCreate ) +{ + pEntry = NULL; + BOOL bHdrLoaded = FALSE; + bIsRoot = TRUE; + if( pIo->Good() ) + { + ULONG nSize = pIo->GetStrm()->Seek( STREAM_SEEK_TO_END ); + pIo->GetStrm()->Seek( 0L ); + if( nSize ) + { + bHdrLoaded = pIo->Load(); + if( !bHdrLoaded && !bCreate ) + { + // File is not a storage and not empty; do not destroy! + SetError( SVSTREAM_FILEFORMAT_ERROR ); + return; + } + } + } + // file is a storage, empty or should be overwritten + pIo->ResetError(); + // we have to set up the data structures, since + // the file is empty + if( !bHdrLoaded ) + pIo->Init(); + if( pIo->Good() ) + { + pEntry = pIo->pTOC->GetRoot(); + pEntry->nRefCnt++; + } +} + +// Internal ctor + +Storage::Storage( StgIo* p, StgDirEntry* q, StreamMode m ) + : OLEStorageBase( p, q, m_nMode ), bIsRoot( FALSE ) +{ + if( q ) + q->aEntry.GetName( aName ); + else + m &= ~STREAM_READWRITE; + m_nMode = m; + if( q && q->nRefCnt == 1 ) + q->nMode = m; +} + +Storage::~Storage() +{ + // Invalidate all open substorages + if( m_bAutoCommit ) + Commit(); + if( pEntry ) + { + // Do an auto-commit if the entry is open in direct mode + if( pEntry->nRefCnt && pEntry->bDirect && (m_nMode & STREAM_WRITE) ) + Commit(); + if( pEntry->nRefCnt == 1 ) + pEntry->Invalidate(); + } + // close the stream is root storage + if( bIsRoot ) + pIo->Close(); + // remove the file if temporary root storage + if( bIsRoot && pEntry && pEntry->bTemp ) + { + osl::File::remove( GetName() ); + } +} + +const String& Storage::GetName() const +{ + if( !bIsRoot && Validate() ) + pEntry->aEntry.GetName( ((Storage*) this)->aName ); + return aName; +} + +// Fill in the info list for this storage + +void Storage::FillInfoList( SvStorageInfoList* pList ) const +{ + if( Validate() ) + { + StgIterator aIter( *pEntry ); + StgDirEntry* p = aIter.First(); + while( p ) + { + if( !p->bInvalid ) + { + SvStorageInfo aInfo( *p ); + pList->Append( aInfo ); + } + p = aIter.Next(); + } + } +} + +// Open or create a substorage + +BaseStorage* Storage::OpenUCBStorage( const String& rName, StreamMode m, BOOL bDirect ) +{ + DBG_ERROR("Not supported!"); +/* + BaseStorage* pStorage = new Storage( pIo, NULL, m ); + SetError( ERRCODE_IO_NOTSUPPORTED ); + return pStorage; + */ + return OpenStorage( rName, m, bDirect ); +} + +BaseStorage* Storage::OpenOLEStorage( const String& rName, StreamMode m, BOOL bDirect ) +{ + return OpenStorage( rName, m, bDirect ); +} + +BaseStorage* Storage::OpenStorage( const String& rName, StreamMode m, BOOL bDirect ) +{ + if( !Validate() || !ValidateMode( m ) ) + return new Storage( pIo, NULL, m ); + BOOL bSetAutoCommit = FALSE; + if( bDirect && !pEntry->bDirect ) + { + bSetAutoCommit = TRUE; + bDirect = FALSE; + } + + StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName ); + if( !p ) + { + if( !( m & STREAM_NOCREATE ) ) + { + BOOL bTemp = FALSE; + // create a new storage + String aNewName = rName; + if( !aNewName.Len() ) + { + aNewName.AssignAscii( "Temp Stg " ); + aNewName.Append( String::CreateFromInt32( ++nTmpCount ) ); + bTemp = TRUE; + } + p = pIo->pTOC->Create( *pEntry, aNewName, STG_STORAGE ); + if( p ) + p->bTemp = bTemp; + } + if( !p ) + pIo->SetError( ( m & STREAM_WRITE ) + ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND ); + } + else if( !ValidateMode( m, p ) ) + p = NULL; + if( p && p->aEntry.GetType() != STG_STORAGE ) + { + pIo->SetError( SVSTREAM_FILE_NOT_FOUND ); + p = NULL; + } + + // Either direct or transacted mode is supported + if( p && pEntry->nRefCnt == 1 ) + p->bDirect = bDirect; + + // Dont check direct conflict if opening readonly + if( p && (m & STREAM_WRITE )) + { + if( p->bDirect != bDirect ) + SetError( SVSTREAM_ACCESS_DENIED ); + } + Storage* pStg = new Storage( pIo, p, m ); + pIo->MoveError( *pStg ); + if( m & STREAM_WRITE ) pStg->m_bAutoCommit = TRUE; + return pStg; +} + +// Open a stream + +BaseStorageStream* Storage::OpenStream( const String& rName, StreamMode m, BOOL, +const ByteString* +#ifdef DBG_UTIL +pB +#endif +) +{ + DBG_ASSERT(!pB, "Encryption not supported"); + + if( !Validate() || !ValidateMode( m ) ) + return new StorageStream( pIo, NULL, m ); + StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName ); + BOOL bTemp = FALSE; + if( !p ) + { + if( !( m & STREAM_NOCREATE ) ) + { + // create a new stream + // make a name if the stream is temporary (has no name) + String aNewName( rName ); + if( !aNewName.Len() ) + { + aNewName.AssignAscii( "Temp Strm " ); + aNewName.Append( String::CreateFromInt32( ++nTmpCount ) ); + bTemp = TRUE; + } + p = pIo->pTOC->Create( *pEntry, aNewName, STG_STREAM ); + } + if( !p ) + pIo->SetError( ( m & STREAM_WRITE ) + ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND ); + } + else if( !ValidateMode( m, p ) ) + p = NULL; + if( p && p->aEntry.GetType() != STG_STREAM ) + { + pIo->SetError( SVSTREAM_FILE_NOT_FOUND ); + p = NULL; + } + if( p ) + { + p->bTemp = bTemp; + p->bDirect = pEntry->bDirect; + } + StorageStream* pStm = new StorageStream( pIo, p, m ); + if( p && !p->bDirect ) + pStm->SetAutoCommit( TRUE ); + pIo->MoveError( *pStm ); + return pStm; +} + +// Delete a stream or substorage by setting the temp bit. + +BOOL Storage::Remove( const String& rName ) +{ + if( !Validate( TRUE ) ) + return FALSE; + StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName ); + if( p ) + { + p->Invalidate( TRUE ); + return TRUE; + } + else + { + SetError( SVSTREAM_FILE_NOT_FOUND ); + return FALSE; + } +} + +// Rename a storage element + +BOOL Storage::Rename( const String& rOld, const String& rNew ) +{ + if( Validate( TRUE ) ) + { + BOOL b = pIo->pTOC->Rename( *pEntry, rOld, rNew ); + pIo->MoveError( *this ); + return b; + } + else + return FALSE; +} + +// Copy one element + +BOOL Storage::CopyTo( const String& rElem, BaseStorage* pDest, const String& rNew ) +{ + if( !Validate() || !pDest || !pDest->Validate( TRUE ) ) + return FALSE; + StgDirEntry* pElem = pIo->pTOC->Find( *pEntry, rElem ); + if( pElem ) + { + /* + this lines are misterious !!! MM + if( !pElem->IsContained( pDest->pEntry ) ) + { + SetError( SVSTREAM_ACCESS_DENIED ); + return FALSE; + } + */ + if( pElem->aEntry.GetType() == STG_STORAGE ) + { + // copy the entire storage + BaseStorage* p1 = OpenStorage( rElem, INTERNAL_MODE ); + BaseStorage* p2 = pDest->OpenOLEStorage( rNew, STREAM_WRITE | STREAM_SHARE_DENYALL, pEntry->bDirect ); + + ULONG nTmpErr = p2->GetError(); + if( !nTmpErr ) + { + p2->SetClassId( p1->GetClassId() ); + p1->CopyTo( p2 ); + SetError( p1->GetError() ); + + nTmpErr = p2->GetError(); + if( !nTmpErr ) + p2->Commit(); + else + pDest->SetError( nTmpErr ); + } + else + pDest->SetError( nTmpErr ); + + delete p1; + delete p2; + return BOOL( Good() && pDest->Good() ); + } + else + { + // stream copy + BaseStorageStream* p1 = OpenStream( rElem, INTERNAL_MODE ); + BaseStorageStream* p2 = pDest->OpenStream( rNew, STREAM_WRITE | STREAM_SHARE_DENYALL, pEntry->bDirect ); + + ULONG nTmpErr = p2->GetError(); + if( !nTmpErr ) + { + p1->CopyTo( p2 ); + SetError( p1->GetError() ); + + nTmpErr = p2->GetError(); + if( !nTmpErr ) + p2->Commit(); + else + pDest->SetError( nTmpErr ); + } + else + pDest->SetError( nTmpErr ); + + delete p1; + delete p2; + return BOOL( Good() && pDest->Good() ); + } + } + SetError( SVSTREAM_FILE_NOT_FOUND ); + return FALSE; +} + +BOOL Storage::CopyTo( BaseStorage* pDest ) const +{ + if( !Validate() || !pDest || !pDest->Validate( TRUE ) || Equals( *pDest ) ) + { + SetError( SVSTREAM_ACCESS_DENIED ); + return FALSE; + } + Storage* pThis = (Storage*) this; + /* + if( !pThis->pEntry->IsContained( pDest->pEntry ) ) + { + SetError( SVSTREAM_ACCESS_DENIED ); + return FALSE; + } + */ + pDest->SetClassId( GetClassId() ); + pDest->SetDirty(); + SvStorageInfoList aList; + FillInfoList( &aList ); + BOOL bRes = TRUE; + for( USHORT i = 0; i < aList.Count() && bRes; i++ ) + { + SvStorageInfo& rInfo = aList.GetObject( i ); + bRes = pThis->CopyTo( rInfo.GetName(), pDest, rInfo.GetName() ); + } + if( !bRes ) + SetError( pDest->GetError() ); + return BOOL( Good() && pDest->Good() ); +} + +// Move one element + +BOOL Storage::MoveTo( const String& rElem, BaseStorage* pODest, const String& rNew ) +{ + if( !Validate() || !pODest || !pODest->Validate( TRUE ) || Equals( *pODest ) ) + { + SetError( SVSTREAM_ACCESS_DENIED ); + return FALSE; + } + + StgDirEntry* pElem = pIo->pTOC->Find( *pEntry, rElem ); + if( pElem ) + { + // Simplest case: both storages share the same file + BOOL bRes; + Storage *pOther = PTR_CAST( Storage, pODest ); + if( pOther && pIo == pOther->pIo && rElem == rNew ) + { + Storage *p = (Storage*) pODest; + Storage *pDest = p; + // both storages are conventional storages, use implementation dependent code + if( !pElem->IsContained( pDest->pEntry ) ) + { + // cyclic move + SetError( SVSTREAM_ACCESS_DENIED ); + return FALSE; + } + bRes = pIo->pTOC->Move( *pEntry, *pDest->pEntry, rNew ); + if( !bRes ) + { + pIo->MoveError( *this ); + pDest->pIo->MoveError( *pDest ); + ULONG nErr = GetError(); + if( !nErr ) + nErr = pDest->GetError(); + SetError( nErr ); + pDest->SetError( nErr ); + } + } + else + { + bRes = CopyTo( rElem, pODest, rNew ); + if( bRes ) + bRes = Remove( rElem ); + } + if( !bRes ) + SetError( pIo->GetError() ); + return bRes; + } + SetError( SVSTREAM_FILE_NOT_FOUND ); + return FALSE; +} + +BOOL Storage::IsStorage( const String& rName ) const +{ + if( Validate() ) + { + StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName ); + if( p ) + return BOOL( p->aEntry.GetType() == STG_STORAGE ); + } + return FALSE; +} + +BOOL Storage::IsStream( const String& rName ) const +{ + if( Validate() ) + { + StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName ); + if( p ) + return BOOL( p->aEntry.GetType() == STG_STREAM ); + } + return FALSE; +} + +BOOL Storage::IsContained( const String& rName ) const +{ + if( Validate() ) + return BOOL( pIo->pTOC->Find( *pEntry, rName ) != NULL ); + else + return FALSE; +} + +// Commit all sub-elements within this storage. If this is +// the root, commit the FAT, the TOC and the header as well. + +BOOL Storage::Commit() +{ + BOOL bRes = TRUE; + if( !Validate() ) + return FALSE; + if( !( m_nMode & STREAM_WRITE ) ) + { + SetError( SVSTREAM_ACCESS_DENIED ); + return FALSE; + } + else + { + // Also commit the sub-streams and Storages + StgIterator aIter( *pEntry ); + for( StgDirEntry* p = aIter.First(); p && bRes; p = aIter.Next() ) + bRes = p->Commit(); + if( bRes && bIsRoot ) + { + bRes = pEntry->Commit(); + if( bRes ) + bRes = pIo->CommitAll(); + } + pIo->MoveError( *this ); + } + return bRes; +} + +BOOL Storage::Revert() +{ + return TRUE; +} + +///////////////////////////// OLE Support //////////////////////////////// + +// Set the storage type + +void Storage::SetClass( const SvGlobalName & rClass, + ULONG nOriginalClipFormat, + const String & rUserTypeName ) +{ + if( Validate( TRUE ) ) + { + // set the class name in the root entry + pEntry->aEntry.SetClassId( (const ClsId&) rClass.GetCLSID() ); + pEntry->SetDirty(); + // then create the streams + StgCompObjStream aCompObj( *this, TRUE ); + aCompObj.GetClsId() = (const ClsId&) rClass.GetCLSID(); + aCompObj.GetCbFormat() = nOriginalClipFormat; + aCompObj.GetUserName() = rUserTypeName; + if( !aCompObj.Store() ) + SetError( aCompObj.GetError() ); + else + { + StgOleStream aOle( *this, STREAM_WRITE ); + if( !aOle.Store() ) + SetError( aOle.GetError() ); + } + } + else + SetError( SVSTREAM_ACCESS_DENIED ); +} + +void Storage::SetConvertClass( const SvGlobalName & rConvertClass, + ULONG nOriginalClipFormat, + const String & rUserTypeName ) +{ + if( Validate( TRUE ) ) + { + SetClass( rConvertClass, nOriginalClipFormat, rUserTypeName ); + // plus the convert flag: + StgOleStream aOle( *this, TRUE ); + aOle.GetFlags() |= 4; + if( !aOle.Store() ) + SetError( aOle.GetError() ); + } +} + +SvGlobalName Storage::GetClassName() +{ + StgCompObjStream aCompObj( *this, FALSE ); + if( aCompObj.Load() ) + return SvGlobalName( (const CLSID&) aCompObj.GetClsId() ); + pIo->ResetError(); + + if ( pEntry ) + return SvGlobalName( (const CLSID&) pEntry->aEntry.GetClassId() ); + + return SvGlobalName(); +} + +ULONG Storage::GetFormat() +{ + StgCompObjStream aCompObj( *this, FALSE ); + if( aCompObj.Load() ) + return aCompObj.GetCbFormat(); + pIo->ResetError(); + return 0; +} + +String Storage::GetUserName() +{ + StgCompObjStream aCompObj( *this, FALSE ); + if( aCompObj.Load() ) + return aCompObj.GetUserName(); + pIo->ResetError(); + return String(); +} + +BOOL Storage::ShouldConvert() +{ + StgOleStream aOle( *this, FALSE ); + if( aOle.Load() ) + return BOOL( ( aOle.GetFlags() & 4 ) != 0 ); + else + { + pIo->ResetError(); + return FALSE; + } +} + +BOOL Storage::ValidateFAT() +{ + Link aLink = StgIo::GetErrorLink(); + ErrCode nErr = pIo->ValidateFATs(); + StgIo::SetErrorLink( aLink ); + return nErr == ERRCODE_NONE; +} + +void Storage::SetDirty() +{ + pEntry->SetDirty(); +} + +void Storage::SetClassId( const ClsId& rId ) +{ + pEntry->aEntry.SetClassId( rId ); +} + +const ClsId& Storage::GetClassId() const +{ + return pEntry->aEntry.GetClassId(); +} + +const SvStream* Storage::GetSvStream() const +{ + return GetSvStream_Impl(); +} + +BOOL Storage::Validate( BOOL bValidate ) const +{ + BOOL bRet = Validate_Impl( bValidate ); + if ( !bRet ) + SetError( SVSTREAM_ACCESS_DENIED ); + return bRet; +} + +BOOL Storage::ValidateMode( StreamMode nMode ) const +{ + BOOL bRet = ValidateMode_Impl( nMode ); + if ( !bRet ) + SetError( SVSTREAM_ACCESS_DENIED ); + return bRet; +} + +BOOL Storage::ValidateMode( StreamMode nMode, StgDirEntry* p ) const +{ + BOOL bRet = ValidateMode_Impl( nMode, p ); + if ( !bRet ) + SetError( SVSTREAM_ACCESS_DENIED ); + return bRet; +} + +BOOL Storage::Equals( const BaseStorage& rStorage ) const +{ + const Storage* pOther = PTR_CAST( Storage, &rStorage ); + return pOther && ( pOther->pEntry == pEntry ); +} + + diff --git a/sot/source/sdstor/stgavl.cxx b/sot/source/sdstor/stgavl.cxx new file mode 100644 index 000000000000..3542a965da33 --- /dev/null +++ b/sot/source/sdstor/stgavl.cxx @@ -0,0 +1,419 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sot.hxx" + + +#include "stgavl.hxx" + +StgAvlNode::StgAvlNode() +{ + pLeft = pRight = NULL; + nBalance = nId = 0; +} + +StgAvlNode::~StgAvlNode() +{ + delete pLeft; + delete pRight; +} + +StgAvlNode* StgAvlNode::Find( StgAvlNode* pFind ) +{ + StgAvlNode* p = this; + while( p ) + { + short nRes = p->Compare( pFind ); + if( !nRes ) + return p; + else p = ( nRes < 0 ) ? p->pLeft : p->pRight; + } + return NULL; +} + +// find point to add node to AVL tree and returns +// +/0/- for >/=/< previous + +short StgAvlNode::Locate + ( StgAvlNode* pFind, + StgAvlNode** pPivot, StgAvlNode **pParent, StgAvlNode** pPrev ) +{ + short nRes = 0; + StgAvlNode* pCur = this; + *pParent = *pPrev = NULL; + *pPivot = this; + + // search tree for insertion point + + while( pCur != NULL ) + { + // check for pPivot + if( pCur->nBalance != 0 ) + *pPivot = pCur, *pParent = *pPrev; + // save pPrev location and see what direction to go + *pPrev = pCur; + nRes = pCur->Compare( pFind ); + if( nRes == 0 ) + break; + else pCur = ( nRes < 0 ) ? pCur->pLeft : pCur->pRight; + } + return( nRes ); +} + +// adjust balance factors in AVL tree from pivot down. +// Returns delta balance. + +short StgAvlNode::Adjust( StgAvlNode** pHeavy, StgAvlNode* pNew ) +{ + StgAvlNode* pCur = this; + short nDelta; + // no traversing + if( pCur == pNew ) + return nBalance; + short nRes = Compare( pNew ); + if( nRes > 0 ) + { + *pHeavy = pCur = pRight; + nDelta = -1; + } + else + { + *pHeavy = pCur = pLeft; + nDelta = 1; + } + nBalance = 0; + while( pCur != pNew ) + { + nRes = pCur->Compare( pNew ); + if( nRes > 0 ) + { + // height of right increases by 1 + pCur->nBalance = -1; + pCur = pCur->pRight; + } + else + { + // height of left increases by 1 + pCur->nBalance = 1; + pCur = pCur->pLeft; + } + } + nBalance = nBalance + nDelta; + return nDelta; +} + +// perform LL rotation and return new root + +StgAvlNode* StgAvlNode::RotLL() +{ + StgAvlNode *pHeavy = pLeft; + pLeft = pHeavy->pRight; + pHeavy->pRight = this; + pHeavy->nBalance = nBalance = 0; + return pHeavy; +} + +// perform LR rotation and return new root + +StgAvlNode* StgAvlNode::RotLR() +{ + + StgAvlNode* pHeavy = pLeft; + StgAvlNode* pNewRoot = pHeavy->pRight; + + pHeavy->pRight = pNewRoot->pLeft; + pLeft = pNewRoot->pRight; + pNewRoot->pLeft = pHeavy; + pNewRoot->pRight = this; + + switch( pNewRoot->nBalance ) + { + case 1: // LR( b ) + nBalance = -1; + pHeavy->nBalance = 0; + break; + case -1: // LR( c ) + pHeavy->nBalance = 1; + nBalance = 0; + break; + case 0: // LR( a ) + nBalance = 0; + pHeavy->nBalance = 0; + break; + } + pNewRoot->nBalance = 0; + return pNewRoot; +} + +// perform RR rotation and return new root + +StgAvlNode* StgAvlNode::RotRR() +{ + StgAvlNode* pHeavy = pRight; + pRight = pHeavy->pLeft; + pHeavy->pLeft = this; + nBalance = pHeavy->nBalance = 0; + return pHeavy; +} + +// perform the RL rotation and return the new root + +StgAvlNode* StgAvlNode::RotRL() +{ + StgAvlNode* pHeavy = pRight; + StgAvlNode* pNewRoot = pHeavy->pLeft; + pHeavy->pLeft = pNewRoot->pRight; + pRight = pNewRoot->pLeft; + pNewRoot->pRight = pHeavy; + pNewRoot->pLeft = this; + switch( pNewRoot->nBalance ) + { + case -1: // RL( b ) + nBalance = 1; + pHeavy->nBalance = 0; + break; + case 1: // RL( c ) + pHeavy->nBalance = -1; + nBalance = 0; + break; + case 0: // RL( a ) + nBalance = 0; + pHeavy->nBalance = 0; + break; + } + pNewRoot->nBalance = 0; + return pNewRoot; +} + +// Remove a tree element. Return the removed element or NULL. + +StgAvlNode* StgAvlNode::Rem( StgAvlNode** p, StgAvlNode* pDel, BOOL bPtrs ) +{ + if( *p ) + { + StgAvlNode* pCur = *p; + short nRes = bPtrs ? short( pCur == pDel ) : short(pCur->Compare( pDel )); + if( !nRes ) + { + // Element found: remove + if( !pCur->pRight ) + { + *p = pCur->pLeft; pCur->pLeft = NULL; + } + else if( !pCur->pLeft ) + { + *p = pCur->pRight; pCur->pRight = NULL; + } + else + { + // The damn element has two leaves. Get the + // rightmost element of the left subtree (which + // is lexically before this element) and replace + // this element with the element found. + StgAvlNode* last = pCur; + StgAvlNode* l; + for( l = pCur->pLeft; + l->pRight; last = l, l = l->pRight ) {} + // remove the element from chain + if( l == last->pRight ) + last->pRight = l->pLeft; + else + last->pLeft = l->pLeft; + // perform the replacement + l->pLeft = pCur->pLeft; + l->pRight = pCur->pRight; + *p = l; + // delete the element + pCur->pLeft = pCur->pRight = NULL; + } + return pCur; + } + else + { + if( nRes < 0 ) + return Rem( &pCur->pLeft, pDel, bPtrs ); + else + return Rem( &pCur->pRight, pDel, bPtrs ); + } + } + return NULL; +} + +// Enumerate the tree for later iteration + +void StgAvlNode::StgEnum( short& n ) +{ + if( this ) + { + if( pLeft ) + pLeft->StgEnum( n ); + nId = n++; + if( pRight ) + pRight->StgEnum( n ); + } +} + +// Add node to AVL tree. +// Return FALSE if the element already exists. + +BOOL StgAvlNode::Insert( StgAvlNode** pRoot, StgAvlNode* pIns ) +{ + StgAvlNode* pPivot, *pHeavy, *pNewRoot, *pParent, *pPrev; + // special case - empty tree + if( *pRoot == NULL ) + { + *pRoot = pIns; + return TRUE; + } + // find insertion point and return if already present + short nRes = (*pRoot)->Locate( pIns, &pPivot, &pParent, &pPrev ); + if( !nRes ) + return FALSE; + // add new node + if( nRes < 0 ) + pPrev->pLeft = pIns; + else + pPrev->pRight = pIns; + // rebalance tree + short nDelta = pPivot->Adjust( &pHeavy, pIns ); + if( pPivot->nBalance >= 2 || pPivot->nBalance <= -2 ) + { + pHeavy = ( nDelta < 0 ) ? pPivot->pRight : pPivot->pLeft; + // left imbalance + if( nDelta > 0 ) + if( pHeavy->nBalance == 1 ) + pNewRoot = pPivot->RotLL(); + else + pNewRoot = pPivot->RotLR(); + // right imbalance + else if( pHeavy->nBalance == -1 ) + pNewRoot = pPivot->RotRR(); + else + pNewRoot = pPivot->RotRL(); + // relink balanced subtree + if( pParent == NULL ) + *pRoot = pNewRoot; + else if( pPivot == pParent->pLeft ) + pParent->pLeft = pNewRoot; + else if( pPivot == pParent->pRight ) + pParent->pRight = pNewRoot; + } + return TRUE; +} + +// Remove node from tree. Returns TRUE is found and removed. +// Actually delete if bDel + +BOOL StgAvlNode::Remove( StgAvlNode** pRoot, StgAvlNode* pDel, BOOL bDel ) +{ + // special case - empty tree + if( *pRoot == NULL ) + return FALSE; + // delete the element + pDel = Rem( pRoot, pDel, FALSE ); + if( pDel ) + { + if( bDel ) + delete pDel; + // Rebalance the tree the hard way + // OS 22.09.95: Auf MD's Wunsch auskommentiert wg. Absturz +/* StgAvlNode* pNew = NULL; + while( *pRoot ) + { + StgAvlNode* p = Rem( pRoot, *pRoot, FALSE ); + Insert( &pNew, p ); + } + *pRoot = pNew;*/ + return TRUE; + } + else + return FALSE; +} + +// Move node to a different tree. Returns TRUE is found and moved. This routine +// may be called when the key has changed. + +BOOL StgAvlNode::Move + ( StgAvlNode** pRoot1, StgAvlNode** pRoot2, StgAvlNode* pMove ) +{ + // special case - empty tree + if( *pRoot1 == NULL ) + return FALSE; + pMove = Rem( pRoot1, pMove, FALSE ); + if( pMove ) + return Insert( pRoot2, pMove ); + else + return FALSE; +} + +////////////////////////// class AvlIterator ///////////////////////// + +// The iterator walks through a tree one entry by one. + +StgAvlIterator::StgAvlIterator( StgAvlNode* p ) +{ + pRoot = p; + nCount = 0; + if( p ) + p->StgEnum( nCount ); +} + +StgAvlNode* StgAvlIterator::Find( short n ) +{ + StgAvlNode* p = pRoot; + while( p ) + { + if( n == p->nId ) + break; + else p = ( n < p->nId ) ? p->pLeft : p->pRight; + } + return p; +} + +StgAvlNode* StgAvlIterator::First() +{ + nCur = -1; + return Next(); +} + +StgAvlNode* StgAvlIterator::Last() +{ + nCur = nCount; + return Prev(); +} + +StgAvlNode* StgAvlIterator::Next() +{ + return Find( ++nCur ); +} + +StgAvlNode* StgAvlIterator::Prev() +{ + return Find( --nCur ); +} + diff --git a/sot/source/sdstor/stgavl.hxx b/sot/source/sdstor/stgavl.hxx new file mode 100644 index 000000000000..66f424888e6d --- /dev/null +++ b/sot/source/sdstor/stgavl.hxx @@ -0,0 +1,79 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _STGAVL_HXX +#define _STGAVL_HXX + +#ifndef _TOOLS_SOLAR_H +#include <tools/solar.h> +#endif + +// This class must be overloaded to define real, living nodes. +// Especially, the compare function must be implemented. + +class StgAvlNode +{ + friend class StgAvlIterator; +private: + short Locate( StgAvlNode*, StgAvlNode**, StgAvlNode**, StgAvlNode** ); + short Adjust( StgAvlNode**, StgAvlNode* ); + StgAvlNode* RotLL(); + StgAvlNode* RotLR(); + StgAvlNode* RotRR(); + StgAvlNode* RotRL(); + void StgEnum( short& ); + static StgAvlNode* Rem( StgAvlNode**, StgAvlNode*, BOOL ); +protected: + short nId; // iterator ID + short nBalance; // indicates tree balance + StgAvlNode* pLeft, *pRight; // leaves + StgAvlNode(); +public: + virtual ~StgAvlNode(); + StgAvlNode* Find( StgAvlNode* ); + static BOOL Insert( StgAvlNode**, StgAvlNode* ); + static BOOL Remove( StgAvlNode**, StgAvlNode*, BOOL bDel = TRUE ); + static BOOL Move( StgAvlNode**, StgAvlNode**, StgAvlNode* ); + virtual short Compare( const StgAvlNode* ) const = 0; +}; + +// The iterator class provides single stepping through an AVL tree. + +class StgAvlIterator { + StgAvlNode* pRoot; // root entry (parent) + short nCount; // tree size + short nCur; // current element + StgAvlNode* Find( short ); +public: + StgAvlIterator( StgAvlNode* ); + StgAvlNode* First(); + StgAvlNode* Last(); + StgAvlNode* Next(); + StgAvlNode* Prev(); +}; + +#endif diff --git a/sot/source/sdstor/stgcache.cxx b/sot/source/sdstor/stgcache.cxx new file mode 100644 index 000000000000..88a8187ee9dd --- /dev/null +++ b/sot/source/sdstor/stgcache.cxx @@ -0,0 +1,546 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sot.hxx" + +#if defined(_MSC_VER) && (_MSC_VER<1200) +#include <tools/presys.h> +#endif +#include <hash_map> +#if defined(_MSC_VER) && (_MSC_VER<1200) +#include <tools/postsys.h> +#endif +#include <vos/macros.hxx> + +#include <string.h> +#include <osl/endian.h> +#include <tools/string.hxx> + +#include "stg.hxx" +#include "stgelem.hxx" +#include "stgcache.hxx" +#include "stgstrms.hxx" +#include "stgdir.hxx" +#include "stgio.hxx" + +/*************************************************************************/ +//----------------------------------------------------------------------------- +typedef std::hash_map +< + INT32, + StgPage *, + std::hash< INT32 >, + NAMESPACE_STD(equal_to)< INT32 > +> UsrStgPagePtr_Impl; +#ifdef _MSC_VER +#pragma warning( disable: 4786 ) +#endif + +//#define CHECK_DIRTY 1 +//#define READ_AFTER_WRITE 1 + +////////////////////////////// class StgPage ///////////////////////////// +// This class implements buffer functionality. The cache will always return +// a page buffer, even if a read fails. It is up to the caller to determine +// the correctness of the I/O. + +StgPage::StgPage( StgCache* p, short n ) +{ + pCache = p; + nData = n; + bDirty = FALSE; + nPage = 0; + pData = new BYTE[ nData ]; + pNext1 = + pNext2 = + pLast1 = + pLast2 = NULL; + pOwner = NULL; +} + +StgPage::~StgPage() +{ + delete [] pData; +} + +void StgPage::SetPage( short nOff, INT32 nVal ) +{ + if( ( nOff < (short) ( nData / sizeof( INT32 ) ) ) && nOff >= 0 ) + { +#ifdef OSL_BIGENDIAN + nVal = SWAPLONG(nVal); +#endif + ((INT32*) pData )[ nOff ] = nVal; + bDirty = TRUE; + } +} + +//////////////////////////////// class StgCache //////////////////////////// + +// The disk cache holds the cached sectors. The sector type differ according +// to their purpose. + +INT32 lcl_GetPageCount( ULONG nFileSize, short nPageSize ) +{ +// return (nFileSize >= 512) ? (nFileSize - 512) / nPageSize : 0; + // #i61980# reallife: last page may be incomplete, return number of *started* pages + return (nFileSize >= 512) ? (nFileSize - 512 + nPageSize - 1) / nPageSize : 0; +} + +StgCache::StgCache() +{ + nRef = 0; + pStrm = NULL; + pCur = pElem1 = NULL; + nPageSize = 512; + nError = SVSTREAM_OK; + bMyStream = FALSE; + bFile = FALSE; + pLRUCache = NULL; + pStorageStream = NULL; +} + +StgCache::~StgCache() +{ + Clear(); + SetStrm( NULL, FALSE ); + delete (UsrStgPagePtr_Impl*)pLRUCache; +} + +void StgCache::SetPhysPageSize( short n ) +{ + nPageSize = n; + ULONG nPos = pStrm->Tell(); + ULONG nFileSize = pStrm->Seek( STREAM_SEEK_TO_END ); + nPages = lcl_GetPageCount( nFileSize, nPageSize ); + pStrm->Seek( nPos ); +} + +// Create a new cache element +// pCur points to this element + +StgPage* StgCache::Create( INT32 nPg ) +{ + StgPage* pElem = new StgPage( this, nPageSize ); + pElem->nPage = nPg; + // For data security, clear the buffer contents + memset( pElem->pData, 0, pElem->nData ); + + // insert to LRU + if( pCur ) + { + pElem->pNext1 = pCur; + pElem->pLast1 = pCur->pLast1; + pElem->pNext1->pLast1 = + pElem->pLast1->pNext1 = pElem; + } + else + pElem->pNext1 = pElem->pLast1 = pElem; + if( !pLRUCache ) + pLRUCache = new UsrStgPagePtr_Impl(); + (*(UsrStgPagePtr_Impl*)pLRUCache)[pElem->nPage] = pElem; + pCur = pElem; + + // insert to Sorted + if( !pElem1 ) + pElem1 = pElem->pNext2 = pElem->pLast2 = pElem; + else + { + StgPage* p = pElem1; + do + { + if( pElem->nPage < p->nPage ) + break; + p = p->pNext2; + } while( p != pElem1 ); + pElem->pNext2 = p; + pElem->pLast2 = p->pLast2; + pElem->pNext2->pLast2 = + pElem->pLast2->pNext2 = pElem; + if( p->nPage < pElem1->nPage ) + pElem1 = pElem; + } + return pElem; +} + +// Delete the given element + +void StgCache::Erase( StgPage* pElem ) +{ + //remove from LRU + pElem->pNext1->pLast1 = pElem->pLast1; + pElem->pLast1->pNext1 = pElem->pNext1; + if( pCur == pElem ) + pCur = ( pElem->pNext1 == pElem ) ? NULL : pElem->pNext1; + if( pLRUCache ) + ((UsrStgPagePtr_Impl*)pLRUCache)->erase( pElem->nPage ); + // remove from Sorted + pElem->pNext2->pLast2 = pElem->pLast2; + pElem->pLast2->pNext2 = pElem->pNext2; + if( pElem1 == pElem ) + pElem1 = ( pElem->pNext2 == pElem ) ? NULL : pElem->pNext2; + delete pElem; +} + +// remove all cache elements without flushing them + +void StgCache::Clear() +{ + StgPage* pElem = pCur; + if( pCur ) do + { + StgPage* pDelete = pElem; + pElem = pElem->pNext1; + delete pDelete; + } + while( pCur != pElem ); + pCur = NULL; + pElem1 = NULL; + delete (UsrStgPagePtr_Impl*)pLRUCache; + pLRUCache = NULL; +} + +// Look for a cached page + +StgPage* StgCache::Find( INT32 nPage ) +{ + if( !pLRUCache ) + return NULL; + UsrStgPagePtr_Impl::iterator aIt = ((UsrStgPagePtr_Impl*)pLRUCache)->find( nPage ); + if( aIt != ((UsrStgPagePtr_Impl*)pLRUCache)->end() ) + { + // page found + StgPage* pFound = (*aIt).second; + + if( pFound != pCur ) + { + // remove from LRU + pFound->pNext1->pLast1 = pFound->pLast1; + pFound->pLast1->pNext1 = pFound->pNext1; + // insert to LRU + pFound->pNext1 = pCur; + pFound->pLast1 = pCur->pLast1; + pFound->pNext1->pLast1 = + pFound->pLast1->pNext1 = pFound; + } + return pFound; + } + return NULL; +} + +// Load a page into the cache + +StgPage* StgCache::Get( INT32 nPage, BOOL bForce ) +{ + StgPage* p = Find( nPage ); + if( !p ) + { + p = Create( nPage ); + if( !Read( nPage, p->pData, 1 ) && bForce ) + { + Erase( p ); + p = NULL; + SetError( SVSTREAM_READ_ERROR ); + } + } + return p; +} + +// Copy an existing page into a new page. Use this routine +// to duplicate an existing stream or to create new entries. +// The new page is initially marked dirty. No owner is copied. + +StgPage* StgCache::Copy( INT32 nNew, INT32 nOld ) +{ + StgPage* p = Find( nNew ); + if( !p ) + p = Create( nNew ); + if( nOld >= 0 ) + { + // old page: we must have this data! + StgPage* q = Get( nOld, TRUE ); + if( q ) + memcpy( p->pData, q->pData, p->nData ); + } + p->SetDirty(); + return p; +} + +// Flush the cache whose owner is given. NULL flushes all. + +BOOL StgCache::Commit( StgDirEntry* ) +{ + StgPage* p = pElem1; + if( p ) do + { + if( p->bDirty ) + { + BOOL b = Write( p->nPage, p->pData, 1 ); + if( !b ) + return FALSE; + p->bDirty = FALSE; + } + p = p->pNext2; + } while( p != pElem1 ); + pStrm->Flush(); + SetError( pStrm->GetError() ); +#ifdef CHECK_DIRTY + p = pElem1; + if( p ) do + { + if( p->bDirty ) + { + ErrorBox( NULL, WB_OK, String("SO2: Dirty Block in Ordered List") ).Execute(); + BOOL b = Write( p->nPage, p->pData, 1 ); + if( !b ) + return FALSE; + p->bDirty = FALSE; + } + p = p->pNext2; + } while( p != pElem1 ); + p = pElem1; + if( p ) do + { + if( p->bDirty ) + { + ErrorBox( NULL, WB_OK, String("SO2: Dirty Block in LRU List") ).Execute(); + BOOL b = Write( p->nPage, p->pData, 1 ); + if( !b ) + return FALSE; + p->bDirty = FALSE; + } + p = p->pNext1; + } while( p != pElem1 ); +#endif + return TRUE; +} + +void StgCache::Revert( StgDirEntry* ) +{} + +// Set a stream + +void StgCache::SetStrm( SvStream* p, BOOL bMy ) +{ + if( pStorageStream ) + { + pStorageStream->ReleaseRef(); + pStorageStream = NULL; + } + + if( bMyStream ) + delete pStrm; + pStrm = p; + bMyStream = bMy; +} + +void StgCache::SetStrm( UCBStorageStream* pStgStream ) +{ + if( pStorageStream ) + pStorageStream->ReleaseRef(); + pStorageStream = pStgStream; + + if( bMyStream ) + delete pStrm; + + pStrm = NULL; + + if ( pStorageStream ) + { + pStorageStream->AddRef(); + pStrm = pStorageStream->GetModifySvStream(); + } + + bMyStream = FALSE; +} + +// Open/close the disk file + +BOOL StgCache::Open( const String& rName, StreamMode nMode ) +{ + // do not open in exclusive mode! + if( nMode & STREAM_SHARE_DENYALL ) + nMode = ( ( nMode & ~STREAM_SHARE_DENYALL ) | STREAM_SHARE_DENYWRITE ); + SvFileStream* pFileStrm = new SvFileStream( rName, nMode ); + // SvStream "Feature" Write Open auch erfolgreich, wenns nicht klappt + BOOL bAccessDenied = FALSE; + if( ( nMode & STREAM_WRITE ) && !pFileStrm->IsWritable() ) + { + pFileStrm->Close(); + bAccessDenied = TRUE; + } + SetStrm( pFileStrm, TRUE ); + if( pFileStrm->IsOpen() ) + { + ULONG nFileSize = pStrm->Seek( STREAM_SEEK_TO_END ); + nPages = lcl_GetPageCount( nFileSize, nPageSize ); + pStrm->Seek( 0L ); + } + else + nPages = 0; + bFile = TRUE; + SetError( bAccessDenied ? ERRCODE_IO_ACCESSDENIED : pStrm->GetError() ); + return Good(); +} + +void StgCache::Close() +{ + if( bFile ) + { + ((SvFileStream*) pStrm)->Close(); + SetError( pStrm->GetError() ); + } +} + +// low level I/O + +BOOL StgCache::Read( INT32 nPage, void* pBuf, INT32 nPg ) +{ + if( Good() ) + { + /* #i73846# real life: a storage may refer to a page one-behind the + last valid page (see document attached to the issue). In that case + (if nPage==nPages), just do nothing here and let the caller work on + the empty zero-filled buffer. */ + if ( nPage > nPages ) + SetError( SVSTREAM_READ_ERROR ); + else if ( nPage < nPages ) + { + ULONG nPos = Page2Pos( nPage ); + INT32 nPg2 = ( ( nPage + nPg ) > nPages ) ? nPages - nPage : nPg; + ULONG nBytes = nPg2 * nPageSize; + // fixed address and size for the header + if( nPage == -1 ) + { + nPos = 0L, nBytes = 512; + nPg2 = nPg; + } + if( pStrm->Tell() != nPos ) + { + if( pStrm->Seek( nPos ) != nPos ) { + #ifdef CHECK_DIRTY + ErrorBox( NULL, WB_OK, String("SO2: Seek failed") ).Execute(); + #endif + } + } + pStrm->Read( pBuf, nBytes ); + if ( nPg != nPg2 ) + SetError( SVSTREAM_READ_ERROR ); + else + SetError( pStrm->GetError() ); + } + } + return Good(); +} + +BOOL StgCache::Write( INT32 nPage, void* pBuf, INT32 nPg ) +{ + if( Good() ) + { + ULONG nPos = Page2Pos( nPage ); + ULONG nBytes = nPg * nPageSize; + // fixed address and size for the header + if( nPage == -1 ) + nPos = 0L, nBytes = 512; + if( pStrm->Tell() != nPos ) + { + if( pStrm->Seek( nPos ) != nPos ) { +#ifdef CHECK_DIRTY + ErrorBox( NULL, WB_OK, String("SO2: Seek failed") ).Execute(); +#endif + } + } + ULONG nRes = pStrm->Write( pBuf, nBytes ); + if( nRes != nBytes ) + SetError( SVSTREAM_WRITE_ERROR ); + else + SetError( pStrm->GetError() ); +#ifdef READ_AFTER_WRITE + BYTE cBuf[ 512 ]; + pStrm->Flush(); + pStrm->Seek( nPos ); + BOOL bRes = ( pStrm->Read( cBuf, 512 ) == 512 ); + if( bRes ) + bRes = !memcmp( cBuf, pBuf, 512 ); + if( !bRes ) + { + ErrorBox( NULL, WB_OK, String("SO2: Read after Write failed") ).Execute(); + pStrm->SetError( SVSTREAM_WRITE_ERROR ); + } +#endif + } + return Good(); +} + +// set the file size in pages + +BOOL StgCache::SetSize( INT32 n ) +{ + // Add the file header + INT32 nSize = n * nPageSize + 512; + pStrm->SetStreamSize( nSize ); + SetError( pStrm->GetError() ); + if( !nError ) + nPages = n; + return Good(); +} + +void StgCache::SetError( ULONG n ) +{ + if( n && !nError ) + nError = n; +} + +void StgCache::ResetError() +{ + nError = SVSTREAM_OK; + pStrm->ResetError(); +} + +void StgCache::MoveError( StorageBase& r ) +{ + if( nError != SVSTREAM_OK ) + { + r.SetError( nError ); + ResetError(); + } +} + +// Utility functions + +INT32 StgCache::Page2Pos( INT32 nPage ) +{ + if( nPage < 0 ) nPage = 0; + return( nPage * nPageSize ) + nPageSize; +} + +INT32 StgCache::Pos2Page( INT32 nPos ) +{ + return ( ( nPos + nPageSize - 1 ) / nPageSize ) * nPageSize - 1; +} + diff --git a/sot/source/sdstor/stgcache.hxx b/sot/source/sdstor/stgcache.hxx new file mode 100644 index 000000000000..5379f837b8b1 --- /dev/null +++ b/sot/source/sdstor/stgcache.hxx @@ -0,0 +1,132 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _STGCACHE_HXX +#define _STGCACHE_HXX + +#include <osl/endian.h> +#ifndef _TOOLS_SOLAR_H +#include <tools/solar.h> +#endif +#ifndef _TOOLS_STREAM_HXX +#include <tools/stream.hxx> +#endif +#include <stgelem.hxx> + +class UCBStorageStream; + +class StgIo; +class StgPage; +class StgDirEntry; +class StorageBase; + +class StgCache { + StgPage* pCur; // top of LRU list + StgPage* pElem1; // top of ordered list + ULONG nError; // error code + INT32 nPages; // size of data area in pages + USHORT nRef; // reference count + void * pLRUCache; // hash table of cached objects + short nPageSize; // page size of the file + UCBStorageStream* pStorageStream; // holds reference to UCB storage stream + + void Erase( StgPage* ); // delete a cache element + void InsertToLRU( StgPage* ); // insert into LRU list + void InsertToOrdered( StgPage* ); // insert into ordered list + StgPage* Create( INT32 ); // create a cached page +protected: + SvStream* pStrm; // physical stream + BOOL bMyStream; // TRUE: delete stream in dtor + BOOL bFile; // TRUE: file stream + INT32 Page2Pos( INT32 ); // page address --> file position + INT32 Pos2Page( INT32 ); // file position --> page address +public: + StgCache(); + ~StgCache(); + void IncRef() { nRef++; } + USHORT DecRef() { return --nRef; } + void SetPhysPageSize( short ); + INT32 GetPhysPages() { return nPages; } + short GetPhysPageSize() { return nPageSize; } + SvStream* GetStrm() { return pStrm; } + void SetStrm( SvStream*, BOOL ); + void SetStrm( UCBStorageStream* ); + BOOL IsWritable() { return pStrm->IsWritable(); } + BOOL Good() { return BOOL( nError == SVSTREAM_OK ); } + BOOL Bad() { return BOOL( nError != SVSTREAM_OK ); } + ULONG GetError() { return nError; } + void MoveError( StorageBase& ); + void SetError( ULONG ); + void ResetError(); + BOOL Open( const String& rName, StreamMode ); + void Close(); + BOOL Read( INT32 nPage, void* pBuf, INT32 nPages ); + BOOL Write( INT32 nPage, void* pBuf, INT32 nPages ); + BOOL SetSize( INT32 nPages ); + StgPage* Find( INT32 ); // find a cached page + StgPage* Get( INT32, BOOL ); // get a cached page + StgPage* Copy( INT32, INT32=STG_FREE ); // copy a page + BOOL Commit( StgDirEntry* = NULL ); // flush all pages + void Revert( StgDirEntry* = NULL ); // revert dirty pages + void Clear(); // clear the cache +}; + +class StgPage { + friend class StgCache; + StgCache* pCache; // the cache + StgPage *pNext1, *pLast1; // LRU chain + StgPage *pNext2, *pLast2; // ordered chain + StgDirEntry* pOwner; // owner + INT32 nPage; // page # + BYTE* pData; // nPageSize characters + short nData; // size of this page + BOOL bDirty; // dirty flag + StgPage( StgCache*, short ); + ~StgPage(); +public: + void SetDirty() { bDirty = TRUE; } + INT32 GetPage() { return nPage; } + void* GetData() { return pData; } + short GetSize() { return nData; } + void SetOwner( StgDirEntry* p ) { pOwner = p; } + // routines for accessing FAT pages + // Assume that the data is a FAT page and get/put FAT data. + INT32 GetPage( short nOff ) + { + if( ( nOff >= (short) ( nData / sizeof( INT32 ) ) ) || nOff < 0 ) + return -1; + INT32 n = ((INT32*) pData )[ nOff ]; +#ifdef OSL_BIGENDIAN + return SWAPLONG(n); +#else + return n; +#endif + } + void SetPage( short, INT32 ); // put an element +}; + +#endif diff --git a/sot/source/sdstor/stgdir.cxx b/sot/source/sdstor/stgdir.cxx new file mode 100644 index 000000000000..f093dc60cbe7 --- /dev/null +++ b/sot/source/sdstor/stgdir.cxx @@ -0,0 +1,1054 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sot.hxx" + +#include <string.h> // memcpy() + +#include "stg.hxx" +#include "stgelem.hxx" +#include "stgcache.hxx" +#include "stgstrms.hxx" +#include "stgdir.hxx" +#include "stgio.hxx" + + +//////////////////////////// class StgDirEntry ///////////////////////////// + +// This class holds the dir entry data and maintains dirty flags for both +// the entry and the data. + +// Transacted mode for streams: On the first write, a temp stream pTmpStrm +// is created and operated on. A commit moves pTmpStrm to pCurStrm, which +// is used for subsequent reads. A new write creates a new copy of pTmpStrm +// based on pCurStrm. Reverting throws away pTmpStrm. +// Transacted mode for storages: A copy of the dir ents is kept in aSave. +// Committing means copying aEntry to aSave. Reverting means to copy aSave +// to aEntry, delete newly created entries and to reactivate removed entries. + +// Problem der Implementation: Keine Hierarchischen commits. Daher nur +// insgesamt transaktionsorientert oder direkt. + +StgDirEntry::StgDirEntry( const void* pFrom, BOOL * pbOk ) : StgAvlNode() +{ + *pbOk = aEntry.Load( pFrom ); + + InitMembers(); +} + +StgDirEntry::StgDirEntry( const StgEntry& r ) : StgAvlNode(), aEntry( r ) +{ + InitMembers(); +} + +// Helper for all ctors + +void StgDirEntry::InitMembers() +{ + aSave = aEntry; + pUp = + pDown = NULL; + ppRoot = NULL; + pStgStrm = NULL; + pCurStrm = + pTmpStrm = NULL; + nPos = + nEntry = + nRefCnt = 0; + nMode = STREAM_READ; + bDirect = TRUE; + bInvalid = + bCreated = + bRenamed = + bRemoved = + bTemp = + bDirty = + bZombie = FALSE; +} + +StgDirEntry::~StgDirEntry() +{ + Close(); + delete pCurStrm; + delete pStgStrm; + delete pDown; +} + +// Comparison function + +short StgDirEntry::Compare( const StgAvlNode* p ) const +{ + const StgDirEntry* pEntry = (const StgDirEntry*) p; + return aEntry.Compare( pEntry->aEntry ); +} + +// Enumerate the entry numbers. +// n is incremented to show the total # of entries. +// These number are later used as page numbers when storing +// the TOC tree into the TOC stream. Remember that aSave is +// stored, not aEntry. + +void StgDirEntry::Enum( INT32& n ) +{ + INT32 nLeft = STG_FREE, nRight = STG_FREE, nDown = STG_FREE; + nEntry = n++; + if( pLeft ) + { + ((StgDirEntry*) pLeft)->Enum( n ); nLeft = ((StgDirEntry*) pLeft)->nEntry; + } + if( pRight ) + { + ((StgDirEntry*) pRight)->Enum( n ); nRight = ((StgDirEntry*) pRight)->nEntry; + } + if( pDown ) + { + pDown->Enum( n ); nDown = pDown->nEntry; + } + aSave.SetLeaf( STG_LEFT, nLeft ); + aSave.SetLeaf( STG_RIGHT, nRight ); + aSave.SetLeaf( STG_CHILD, nDown ); +} + +// Delete all temporary entries before writing the TOC stream. +// Until now Deltem is never called with bForce True + +void StgDirEntry::DelTemp( BOOL bForce ) +{ + if( pLeft ) + ((StgDirEntry*) pLeft)->DelTemp( FALSE ); + if( pRight ) + ((StgDirEntry*) pRight)->DelTemp( FALSE ); + if( pDown ) + { + // If the storage is dead, of course all elements are dead, too + if( bInvalid && aEntry.GetType() == STG_STORAGE ) + bForce = TRUE; + pDown->DelTemp( bForce ); + } + if( ( bForce || bInvalid ) + && ( aEntry.GetType() != STG_ROOT ) /* && ( nRefCnt <= 1 ) */ ) + { + Close(); + if( pUp ) + { + // this deletes the element if refcnt == 0! + BOOL bDel = nRefCnt == 0; + StgAvlNode::Remove( (StgAvlNode**) &pUp->pDown, this, bDel ); + if( !bDel ) + { + pLeft = pRight = pDown = 0; + bInvalid = bZombie = TRUE; + } + } + } +} + +// Save the tree into the given dir stream + +BOOL StgDirEntry::Store( StgDirStrm& rStrm ) +{ + void* pEntry = rStrm.GetEntry( nEntry, TRUE ); + if( !pEntry ) + return FALSE; + // Do not store the current (maybe not commited) entry + aSave.Store( pEntry ); + if( pLeft ) + if( !((StgDirEntry*) pLeft)->Store( rStrm ) ) + return FALSE; + if( pRight ) + if( !((StgDirEntry*) pRight)->Store( rStrm ) ) + return FALSE; + if( pDown ) + if( !pDown->Store( rStrm ) ) + return FALSE; + return TRUE; +} + +BOOL StgDirEntry::StoreStream( StgIo& rIo ) +{ + if( aEntry.GetType() == STG_STREAM || aEntry.GetType() == STG_ROOT ) + { + if( bInvalid ) + { + // Delete the stream if needed + if( !pStgStrm ) + { + OpenStream( rIo ); + delete pStgStrm, pStgStrm = NULL; + } + else + pStgStrm->SetSize( 0 ); + } + // or write the data stream + else if( !Tmp2Strm() ) + return FALSE; + } + return TRUE; +} + +// Save all dirty streams + +BOOL StgDirEntry::StoreStreams( StgIo& rIo ) +{ + if( !StoreStream( rIo ) ) + return FALSE; + if( pLeft ) + if( !((StgDirEntry*) pLeft)->StoreStreams( rIo ) ) + return FALSE; + if( pRight ) + if( !((StgDirEntry*) pRight)->StoreStreams( rIo ) ) + return FALSE; + if( pDown ) + if( !pDown->StoreStreams( rIo ) ) + return FALSE; + return TRUE; +} + +// Revert all directory entries after failure to write the TOC stream + +void StgDirEntry::RevertAll() +{ + aEntry = aSave; + if( pLeft ) + ((StgDirEntry*) pLeft)->RevertAll(); + if( pRight ) + ((StgDirEntry*) pRight)->RevertAll(); + if( pDown ) + pDown->RevertAll(); +} + +// Look if any element of the tree is dirty + +BOOL StgDirEntry::IsDirty() +{ + if( bDirty || bInvalid ) + return TRUE; + if( pLeft && ((StgDirEntry*) pLeft)->IsDirty() ) + return TRUE; + if( pRight && ((StgDirEntry*) pRight)->IsDirty() ) + return TRUE; + if( pDown && pDown->IsDirty() ) + return TRUE; + return FALSE; +} + +// Set up a stream. + +void StgDirEntry::OpenStream( StgIo& rIo, BOOL bForceBig ) +{ + INT32 nThreshold = (USHORT) rIo.aHdr.GetThreshold(); + delete pStgStrm; + if( !bForceBig && aEntry.GetSize() < nThreshold ) + pStgStrm = new StgSmallStrm( rIo, this ); + else + pStgStrm = new StgDataStrm( rIo, this ); + if( bInvalid && aEntry.GetSize() ) + { + // This entry has invalid data, so delete that data + SetSize( 0L ); +// bRemoved = bInvalid = FALSE; + } + nPos = 0; +} + +// Close the open stream without committing. If the entry is marked as +// temporary, delete it. +// Do not delete pCurStrm here! +// (TLX:??? Zumindest pStgStrm muss deleted werden.) + +void StgDirEntry::Close() +{ + delete pTmpStrm; + pTmpStrm = NULL; +// nRefCnt = 0; + bInvalid = bTemp; +} + +// Get the current stream size + +INT32 StgDirEntry::GetSize() +{ + INT32 n; + if( pTmpStrm ) + n = pTmpStrm->GetSize(); + else if( pCurStrm ) + n = pCurStrm->GetSize(); + else n = aEntry.GetSize(); + return n; +} + +// Set the stream size. This means also creating a temp stream. + +BOOL StgDirEntry::SetSize( INT32 nNewSize ) +{ + if ( + !( nMode & STREAM_WRITE ) || + (!bDirect && !pTmpStrm && !Strm2Tmp()) + ) + { + return FALSE; + } + + if( nNewSize < nPos ) + nPos = nNewSize; + if( pTmpStrm ) + { + pTmpStrm->SetSize( nNewSize ); + pStgStrm->GetIo().SetError( pTmpStrm->GetError() ); + return BOOL( pTmpStrm->GetError() == SVSTREAM_OK ); + } + else + { + BOOL bRes = FALSE; + StgIo& rIo = pStgStrm->GetIo(); + INT32 nThreshold = rIo.aHdr.GetThreshold(); + // ensure the correct storage stream! + StgStrm* pOld = NULL; + USHORT nOldSize = 0; + if( nNewSize >= nThreshold && pStgStrm->IsSmallStrm() ) + { + pOld = pStgStrm; + nOldSize = (USHORT) pOld->GetSize(); + pStgStrm = new StgDataStrm( rIo, STG_EOF, 0 ); + } + else if( nNewSize < nThreshold && !pStgStrm->IsSmallStrm() ) + { + pOld = pStgStrm; + nOldSize = (USHORT) nNewSize; + pStgStrm = new StgSmallStrm( rIo, STG_EOF, 0 ); + } + // now set the new size + if( pStgStrm->SetSize( nNewSize ) ) + { + // did we create a new stream? + if( pOld ) + { + // if so, we probably need to copy the old data + if( nOldSize ) + { + void* pBuf = new BYTE[ nOldSize ]; + pOld->Pos2Page( 0L ); + pStgStrm->Pos2Page( 0L ); + if( pOld->Read( pBuf, nOldSize ) + && pStgStrm->Write( pBuf, nOldSize ) ) + bRes = TRUE; + delete[] static_cast<BYTE*>(pBuf); + } + else + bRes = TRUE; + if( bRes ) + { + pOld->SetSize( 0 ); + delete pOld; + pStgStrm->Pos2Page( nPos ); + pStgStrm->SetEntry( *this ); + } + else + { + pStgStrm->SetSize( 0 ); + delete pStgStrm; + pStgStrm = pOld; + } + } + else + { + pStgStrm->Pos2Page( nPos ); + bRes = TRUE; + } + } + return bRes; + } +} + +// Seek. On negative values, seek to EOF. + +INT32 StgDirEntry::Seek( INT32 nNew ) +{ + if( pTmpStrm ) + { + if( nNew < 0 ) + nNew = pTmpStrm->GetSize(); + nNew = pTmpStrm->Seek( nNew ); + } + else if( pCurStrm ) + { + if( nNew < 0 ) + nNew = pCurStrm->GetSize(); + nNew = pCurStrm->Seek( nNew ); + } + else + { + INT32 nSize = aEntry.GetSize(); + + if( nNew < 0 ) + nNew = nSize; + + // try to enlarge, the readonly streams should not allow this + if( nNew > nSize ) + { + if ( !( nMode & STREAM_WRITE ) || !SetSize( nNew ) ) + { + OSL_ENSURE( nMode & STREAM_WRITE, "Trying to resize readonly stream by seeking, could be a wrong offset!" ); + return nPos; + } + else + return Seek( nNew ); + } + pStgStrm->Pos2Page( nNew ); + nNew = pStgStrm->GetPos(); + } + return nPos = nNew; +} + +// Read + +INT32 StgDirEntry::Read( void* p, INT32 nLen ) +{ + if( nLen <= 0 ) + return 0; + if( pTmpStrm ) + nLen = pTmpStrm->Read( p, nLen ); + else if( pCurStrm ) + nLen = pCurStrm->Read( p, nLen ); + else + nLen = pStgStrm->Read( p, nLen ); + nPos += nLen; + return nLen; +} + +// Write + +INT32 StgDirEntry::Write( const void* p, INT32 nLen ) +{ + if( nLen <= 0 || !( nMode & STREAM_WRITE ) ) + return 0; + + // Was this stream committed internally and reopened in direct mode? + if( bDirect && ( pCurStrm || pTmpStrm ) && !Tmp2Strm() ) + return 0; + // Is this stream opened in transacted mode? Do we have to make a copy? + if( !bDirect && !pTmpStrm && !Strm2Tmp() ) + return 0; + if( pTmpStrm ) + { + nLen = pTmpStrm->Write( p, nLen ); + pStgStrm->GetIo().SetError( pTmpStrm->GetError() ); + } + else + { + INT32 nNew = nPos + nLen; + if( nNew > pStgStrm->GetSize() ) + { + if( !SetSize( nNew ) ) + return 0L; + pStgStrm->Pos2Page( nPos ); + } + nLen = pStgStrm->Write( p, nLen ); + } + nPos += nLen; + return nLen; +} + +// Copy the data of one entry into another entry. + +void StgDirEntry::Copy( StgDirEntry& rDest ) +{ + INT32 n = GetSize(); + if( rDest.SetSize( n ) && n ) + { + BYTE aTempBytes[ 4096 ]; + void* p = static_cast<void*>( aTempBytes ); + Seek( 0L ); + rDest.Seek( 0L ); + while( n ) + { + INT32 nn = n; + if( nn > 4096 ) + nn = 4096; + if( Read( p, nn ) != nn ) + break; + if( rDest.Write( p, nn ) != nn ) + break; + n -= nn; + } + } +} + +void StgDirEntry::Copy( BaseStorageStream& rDest ) +{ + INT32 n = GetSize(); + if( rDest.SetSize( n ) && n ) + { + ULONG Pos = rDest.Tell(); + BYTE aTempBytes[ 4096 ]; + void* p = static_cast<void*>( aTempBytes ); + Seek( 0L ); + rDest.Seek( 0L ); + while( n ) + { + INT32 nn = n; + if( nn > 4096 ) + nn = 4096; + if( Read( p, nn ) != nn ) + break; + if( sal::static_int_cast<INT32>(rDest.Write( p, nn )) != nn ) + break; + n -= nn; + } + rDest.Seek( Pos ); // ?! Seems to be undocumented ! + } +} + +// Commit this entry + +BOOL StgDirEntry::Commit() +{ + // OSL_ENSURE( nMode & STREAM_WRITE, "Trying to commit readonly stream!" ); + + aSave = aEntry; + BOOL bRes = TRUE; + if( aEntry.GetType() == STG_STREAM ) + { + if( pTmpStrm ) + delete pCurStrm, pCurStrm = pTmpStrm, pTmpStrm = NULL; + if( bRemoved ) + // Delete the stream if needed + if( pStgStrm ) + pStgStrm->SetSize( 0 ); + } + else if( aEntry.GetType() == STG_STORAGE && bDirect && bRes ) + { + StgIterator aIter( *this ); + for( StgDirEntry* p = aIter.First(); p && bRes; p = aIter.Next() ) + bRes = p->Commit(); + } + return bRes; +} + +// Revert the entry + +BOOL StgDirEntry::Revert() +{ + aEntry = aSave; + switch( aEntry.GetType() ) + { + case STG_STREAM: + if( pCurStrm ) + delete pTmpStrm, pTmpStrm = pCurStrm, pCurStrm = NULL; + break; + case STG_STORAGE: + { + BOOL bSomeRenamed = FALSE; + StgIterator aOIter( *this ); + StgDirEntry* op = aOIter.First(); + while( op ) + { + op->aEntry = op->aSave; + op->bDirty = FALSE; + bSomeRenamed = BOOL( bSomeRenamed | op->bRenamed ); + // Remove any new entries + if( op->bCreated ) + { + op->bCreated = FALSE; + op->Close(); + op->bInvalid = TRUE; + } + // Reactivate any removed entries + else if( op->bRemoved ) + op->bRemoved = op->bInvalid = op->bTemp = FALSE; + op = aOIter.Next(); + } + // Resort all renamed entries + if( bSomeRenamed ) + { + StgIterator aIter( *this ); + StgDirEntry* p = aIter.First(); + while( p ) + { + if( p->bRenamed ) + { + StgAvlNode::Move + ( (StgAvlNode**) &p->pUp->pDown, + (StgAvlNode**) &p->pUp->pDown, p ); + p->bRenamed = FALSE; + } + p = aIter.Next(); + } + } + DelTemp( FALSE ); + break; + } + case STG_EMPTY: + case STG_LOCKBYTES: + case STG_PROPERTY: + case STG_ROOT: + break; + } + return TRUE; +} + +// Copy the stg stream to the temp stream + +BOOL StgDirEntry::Strm2Tmp() +{ + if( !pTmpStrm ) + { + ULONG n = 0; + if( pCurStrm ) + { + // It was already commited once + pTmpStrm = new StgTmpStrm; + if( pTmpStrm->GetError() == SVSTREAM_OK && pTmpStrm->Copy( *pCurStrm ) ) + return TRUE; + n = 1; // indicates error + } + else + { + n = aEntry.GetSize(); + pTmpStrm = new StgTmpStrm( n ); + if( pTmpStrm->GetError() == SVSTREAM_OK ) + { + if( n ) + { + BYTE aTempBytes[ 4096 ]; + void* p = static_cast<void*>( aTempBytes ); + pStgStrm->Pos2Page( 0L ); + while( n ) + { + ULONG nn = n; + if( nn > 4096 ) + nn = 4096; + if( (ULONG) pStgStrm->Read( p, nn ) != nn ) + break; + if( pTmpStrm->Write( p, nn ) != nn ) + break; + n -= nn; + } + pStgStrm->Pos2Page( nPos ); + pTmpStrm->Seek( nPos ); + } + } + else + n = 1; + } + if( n ) + { + pStgStrm->GetIo().SetError( pTmpStrm->GetError() ); + delete pTmpStrm; + pTmpStrm = NULL; + return FALSE; + } + } + return TRUE; +} + +// Copy the temp stream to the stg stream during the final commit + +BOOL StgDirEntry::Tmp2Strm() +{ + // We did commit once, but have not written since then + if( !pTmpStrm ) + pTmpStrm = pCurStrm, pCurStrm = NULL; + if( pTmpStrm ) + { + ULONG n = pTmpStrm->GetSize(); + StgStrm* pNewStrm; + StgIo& rIo = pStgStrm->GetIo(); + ULONG nThreshold = (ULONG) rIo.aHdr.GetThreshold(); + if( n < nThreshold ) + pNewStrm = new StgSmallStrm( rIo, STG_EOF, 0 ); + else + pNewStrm = new StgDataStrm( rIo, STG_EOF, 0 ); + if( pNewStrm->SetSize( n ) ) + { + BYTE p[ 4096 ]; + pTmpStrm->Seek( 0L ); + while( n ) + { + ULONG nn = n; + if( nn > 4096 ) + nn = 4096; + if( pTmpStrm->Read( p, nn ) != nn ) + break; + if( (ULONG) pNewStrm->Write( p, nn ) != nn ) + break; + n -= nn; + } + if( n ) + { + pTmpStrm->Seek( nPos ); + pStgStrm->GetIo().SetError( pTmpStrm->GetError() ); + delete pNewStrm; + return FALSE; + } + else + { + pStgStrm->SetSize( 0L ); + delete pStgStrm; + pStgStrm = pNewStrm; + pNewStrm->SetEntry( *this ); + pNewStrm->Pos2Page( nPos ); + delete pTmpStrm; + delete pCurStrm; + pTmpStrm = pCurStrm = NULL; + aSave = aEntry; + } + } + } + return TRUE; +} + +// Check if the given entry is contained in this entry + +BOOL StgDirEntry::IsContained( StgDirEntry* pStg ) +{ + if( aEntry.GetType() == STG_STORAGE ) + { + StgIterator aIter( *this ); + StgDirEntry* p = aIter.First(); + while( p ) + { + if( !p->aEntry.Compare( pStg->aEntry ) ) + return FALSE; + if( p->aEntry.GetType() == STG_STORAGE ) + if( !p->IsContained( pStg ) ) + return FALSE; + p = aIter.Next(); + } + } + return TRUE; +} + +// Invalidate all open entries by setting the RefCount to 0. If the bDel +// flag is set, also set the invalid flag to indicate deletion during the +// next dir stream flush. + +void StgDirEntry::Invalidate( BOOL bDel ) +{ +// nRefCnt = 0; + if( bDel ) + bRemoved = bInvalid = TRUE; + switch( aEntry.GetType() ) + { + case STG_STORAGE: + case STG_ROOT: + { + StgIterator aIter( *this ); + for( StgDirEntry* p = aIter.First(); p; p = aIter.Next() ) + p->Invalidate( bDel ); + break; + } + default: + break; + } +} + +///////////////////////////// class StgDirStrm //////////////////////////// + +// This specialized stream is the maintenance stream for the directory tree. + +StgDirStrm::StgDirStrm( StgIo& r ) + : StgDataStrm( r, r.aHdr.GetTOCStart(), -1 ) + , pRoot( NULL ) + , nEntries( 0 ) +{ + if( r.GetError() ) + return; + nEntries = nPageSize / STGENTRY_SIZE; + if( nStart == STG_EOF ) + { + StgEntry aRoot; + aRoot.Init(); + aRoot.SetName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "Root Entry" ) ) ); + aRoot.SetType( STG_ROOT ); + pRoot = new StgDirEntry( aRoot ); + pRoot->SetDirty(); + } + else + { + // temporarily use this instance as owner, so + // the TOC pages can be removed. + pEntry = (StgDirEntry*) this; // just for a bit pattern + SetupEntry( 0, pRoot ); + rIo.Revert( pEntry ); + pEntry = NULL; + } +} + +StgDirStrm::~StgDirStrm() +{ + delete pRoot; +} + +// Recursively parse the directory tree during reading the TOC stream + +void StgDirStrm::SetupEntry( INT32 n, StgDirEntry* pUpper ) +{ + void* p = ( n == STG_FREE ) ? NULL : GetEntry( n ); + if( p ) + { + BOOL bOk(FALSE); + StgDirEntry* pCur = new StgDirEntry( p, &bOk ); + + if( !bOk ) + { + delete pCur; + rIo.SetError( SVSTREAM_GENERALERROR ); + // an error occured + return; + } + + // better it is + if( !pUpper ) + pCur->aEntry.SetType( STG_ROOT ); + + INT32 nLeft = pCur->aEntry.GetLeaf( STG_LEFT ); + INT32 nRight = pCur->aEntry.GetLeaf( STG_RIGHT ); + // substorage? + INT32 nLeaf = STG_FREE; + if( pCur->aEntry.GetType() == STG_STORAGE || pCur->aEntry.GetType() == STG_ROOT ) + { + nLeaf = pCur->aEntry.GetLeaf( STG_CHILD ); + if (nLeaf != STG_FREE && nLeaf == n) + { + delete pCur; + rIo.SetError( SVSTREAM_GENERALERROR ); + return; + } + } + + if( nLeaf != 0 && nLeft != 0 && nRight != 0 ) + { + if( StgAvlNode::Insert + ( (StgAvlNode**) ( pUpper ? &pUpper->pDown : &pRoot ), pCur ) ) + { + pCur->pUp = pUpper; + pCur->ppRoot = &pRoot; + } + else + { + rIo.SetError( SVSTREAM_CANNOT_MAKE ); + delete pCur; pCur = NULL; + return; + } + SetupEntry( nLeft, pUpper ); + SetupEntry( nRight, pUpper ); + SetupEntry( nLeaf, pCur ); + } + } +} + +// Extend or shrink the directory stream. + +BOOL StgDirStrm::SetSize( INT32 nBytes ) +{ + // Always allocate full pages + nBytes = ( ( nBytes + nPageSize - 1 ) / nPageSize ) * nPageSize; + return StgStrm::SetSize( nBytes ); +} + +// Save the TOC stream into a new substream after saving all data streams + +BOOL StgDirStrm::Store() +{ + if( !pRoot->IsDirty() ) + return TRUE; + if( !pRoot->StoreStreams( rIo ) ) + return FALSE; + // After writing all streams, the data FAT stream has changed, + // so we have to commit the root again + pRoot->Commit(); + // We want a completely new stream, so fake an empty stream + INT32 nOldStart = nStart; // save for later deletion + INT32 nOldSize = nSize; + nStart = nPage = STG_EOF; + nSize = nPos = 0; + nOffset = 0; + // Delete all temporary entries + pRoot->DelTemp( FALSE ); + // set the entry numbers + INT32 n = 0; + pRoot->Enum( n ); + if( !SetSize( n * STGENTRY_SIZE ) ) + { + nStart = nOldStart; nSize = nOldSize; + pRoot->RevertAll(); + return FALSE; + } + // set up the cache elements for the new stream + if( !Copy( STG_FREE, nSize ) ) + { + pRoot->RevertAll(); + return FALSE; + } + // Write the data to the new stream + if( !pRoot->Store( *this ) ) + { + pRoot->RevertAll(); + return FALSE; + } + // fill any remaining entries with empty data + INT32 ne = nSize / STGENTRY_SIZE; + StgEntry aEmpty; + aEmpty.Init(); + while( n < ne ) + { + void* p = GetEntry( n++, TRUE ); + if( !p ) + { + pRoot->RevertAll(); + return FALSE; + } + aEmpty.Store( p ); + } + // Now we can release the old stream + pFat->FreePages( nOldStart, TRUE ); + rIo.aHdr.SetTOCStart( nStart ); + return TRUE; +} + +// Get a dir entry. + +void* StgDirStrm::GetEntry( INT32 n, BOOL bDirty ) +{ + n *= STGENTRY_SIZE; + if( n >= nSize ) + return NULL; + return GetPtr( n, TRUE, bDirty ); +} + +// Find a dir entry. + +StgDirEntry* StgDirStrm::Find( StgDirEntry& rStg, const String& rName ) +{ + if( rStg.pDown ) + { + StgEntry aEntry; + aEntry.Init(); + if( !aEntry.SetName( rName ) ) + { + rIo.SetError( SVSTREAM_GENERALERROR ); + return NULL; + } + // Look in the directory attached to the entry + StgDirEntry aTest( aEntry ); + return (StgDirEntry*) rStg.pDown->Find( &aTest ); + } + else + return NULL; +} + +// Create a new entry. + +StgDirEntry* StgDirStrm::Create + ( StgDirEntry& rStg, const String& rName, StgEntryType eType ) +{ + StgEntry aEntry; + aEntry.Init(); + aEntry.SetType( eType ); + if( !aEntry.SetName( rName ) ) + { + rIo.SetError( SVSTREAM_GENERALERROR ); + return NULL; + } + StgDirEntry* pRes = Find( rStg, rName ); + if( pRes ) + { + if( !pRes->bInvalid ) + { + rIo.SetError( SVSTREAM_CANNOT_MAKE ); + return NULL; + } + pRes->bInvalid = + pRes->bRemoved = + pRes->bTemp = FALSE; + pRes->bCreated = + pRes->bDirty = TRUE; + } + else + { + pRes = new StgDirEntry( aEntry ); + if( StgAvlNode::Insert( (StgAvlNode**) &rStg.pDown, pRes ) ) + { + pRes->pUp = &rStg; + pRes->ppRoot = &pRoot; + pRes->bCreated = + pRes->bDirty = TRUE; + } + else + { + rIo.SetError( SVSTREAM_CANNOT_MAKE ); + delete pRes; pRes = NULL; + } + } + return pRes; +} + +// Rename the given entry. + +BOOL StgDirStrm::Rename( StgDirEntry& rStg, const String& rOld, const String& rNew ) +{ + StgDirEntry* p = Find( rStg, rOld ); + if( p ) + { + + if( !StgAvlNode::Remove( (StgAvlNode**) &rStg.pDown, p, FALSE ) ) + return FALSE; + p->aEntry.SetName( rNew ); + if( !StgAvlNode::Insert( (StgAvlNode**) &rStg.pDown, p ) ) + return FALSE; + p->bRenamed = p->bDirty = TRUE; + return TRUE; + } + else + { + rIo.SetError( SVSTREAM_FILE_NOT_FOUND ); + return FALSE; + } +} + +// Move the given entry to a different storage. + +BOOL StgDirStrm::Move( StgDirEntry& rStg1, StgDirEntry& rStg2, const String& rName ) +{ + StgDirEntry* p = Find( rStg1, rName ); + if( p ) + { + if( !StgAvlNode::Move + ( (StgAvlNode**) &rStg1.pDown, (StgAvlNode**) &rStg2.pDown, p ) ) + return FALSE; + p->bDirty = TRUE; + return TRUE; + } + else + { + rIo.SetError( SVSTREAM_FILE_NOT_FOUND ); + return FALSE; + } +} + diff --git a/sot/source/sdstor/stgdir.hxx b/sot/source/sdstor/stgdir.hxx new file mode 100644 index 000000000000..3ef510a12e50 --- /dev/null +++ b/sot/source/sdstor/stgdir.hxx @@ -0,0 +1,132 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _STGDIR_HXX +#define _STGDIR_HXX + +#include "stgavl.hxx" +#include "stgelem.hxx" +#include "stgstrms.hxx" + +class StgIo; +class StgEntry; +class StgDirEntry; +class StgDirStrm; + +class BaseStorageStream; +class StgDirEntry : public StgAvlNode +{ + friend class StgIterator; + friend class StgDirStrm; + StgEntry aSave; // original dir entry + StgDirEntry* pUp; // parent directory + StgDirEntry* pDown; // child directory for storages + StgDirEntry** ppRoot; // root of TOC tree + StgStrm* pStgStrm; // storage stream + StgTmpStrm* pTmpStrm; // temporary stream + StgTmpStrm* pCurStrm; // temp stream after commit + INT32 nEntry; // entry # in TOC stream (temp) + INT32 nPos; // current position + BOOL bDirty; // dirty directory entry + BOOL bCreated; // newly created entry + BOOL bRemoved; // removed per Invalidate() + BOOL bRenamed; // renamed + void InitMembers(); // ctor helper + virtual short Compare( const StgAvlNode* ) const; + BOOL StoreStream( StgIo& ); // store the stream + BOOL StoreStreams( StgIo& ); // store all streams + void RevertAll(); // revert the whole tree + BOOL Strm2Tmp(); // copy stgstream to temp file + BOOL Tmp2Strm(); // copy temp file to stgstream +public: + StgEntry aEntry; // entry data + INT32 nRefCnt; // reference count + StreamMode nMode; // open mode + BOOL bTemp; // TRUE: delete on dir flush + BOOL bDirect; // TRUE: direct mode + BOOL bZombie; // TRUE: Removed From StgIo + BOOL bInvalid; // TRUE: invalid entry + StgDirEntry( const void*, BOOL * pbOk ); + StgDirEntry( const StgEntry& ); + ~StgDirEntry(); + + void Invalidate( BOOL=FALSE ); // invalidate all open entries + void Enum( INT32& ); // enumerate entries for iteration + void DelTemp( BOOL ); // delete temporary entries + BOOL Store( StgDirStrm& ); // save entry into dir strm + BOOL IsContained( StgDirEntry* ); // check if subentry + + void SetDirty() { bDirty = TRUE; } + BOOL IsDirty(); + void ClearDirty(); + + BOOL Commit(); + BOOL Revert(); + + void OpenStream( StgIo&, BOOL=FALSE ); // set up an approbiate stream + void Close(); + INT32 GetSize(); + BOOL SetSize( INT32 ); + INT32 Seek( INT32 ); + INT32 Tell() { return nPos; } + INT32 Read( void*, INT32 ); + INT32 Write( const void*, INT32 ); + void Copy( StgDirEntry& ); + void Copy( BaseStorageStream& ); +}; + +class StgDirStrm : public StgDataStrm +{ + friend class StgIterator; + StgDirEntry* pRoot; // root of dir tree + short nEntries; // entries per page + void SetupEntry( INT32, StgDirEntry* ); +public: + StgDirStrm( StgIo& ); + ~StgDirStrm(); + virtual BOOL SetSize( INT32 ); // change the size + BOOL Store(); + void* GetEntry( INT32 n, BOOL=FALSE );// get an entry + StgDirEntry* GetRoot() { return pRoot; } + StgDirEntry* Find( StgDirEntry&, const String& ); + StgDirEntry* Create( StgDirEntry&, const String&, StgEntryType ); + BOOL Remove( StgDirEntry&, const String& ); + BOOL Rename( StgDirEntry&, const String&, const String& ); + BOOL Move( StgDirEntry&, StgDirEntry&, const String& ); +}; + +class StgIterator : public StgAvlIterator +{ +public: + StgIterator( StgDirEntry& rStg ) : StgAvlIterator( rStg.pDown ) {} + StgDirEntry* First() { return (StgDirEntry*) StgAvlIterator::First(); } + StgDirEntry* Next() { return (StgDirEntry*) StgAvlIterator::Next(); } + StgDirEntry* Last() { return (StgDirEntry*) StgAvlIterator::Last(); } + StgDirEntry* Prev() { return (StgDirEntry*) StgAvlIterator::Prev(); } +}; + +#endif diff --git a/sot/source/sdstor/stgelem.cxx b/sot/source/sdstor/stgelem.cxx new file mode 100644 index 000000000000..46d7f1803140 --- /dev/null +++ b/sot/source/sdstor/stgelem.cxx @@ -0,0 +1,425 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sot.hxx" + +#include <string.h> // memset(), memcpy() +#include <rtl/ustring.hxx> +#include <com/sun/star/lang/Locale.hpp> +#include <unotools/charclass.hxx> +#include "stg.hxx" +#include "stgelem.hxx" +#include "stgcache.hxx" +#include "stgstrms.hxx" +#include "stgdir.hxx" +#include "stgio.hxx" + +static BYTE cStgSignature[ 8 ] = { 0xD0,0xCF,0x11,0xE0,0xA1,0xB1,0x1A,0xE1 }; + +////////////////////////////// struct ClsId ///////////////////////////// + +SvStream& operator >>( SvStream& r, ClsId& rId ) +{ + r >> rId.n1 + >> rId.n2 + >> rId.n3 + >> rId.n4 + >> rId.n5 + >> rId.n6 + >> rId.n7 + >> rId.n8 + >> rId.n9 + >> rId.n10 + >> rId.n11; + return r; +} + +SvStream& operator <<( SvStream& r, const ClsId& rId ) +{ + return + r << (INT32) rId.n1 + << (INT16) rId.n2 + << (INT16) rId.n3 + << (UINT8) rId.n4 + << (UINT8) rId.n5 + << (UINT8) rId.n6 + << (UINT8) rId.n7 + << (UINT8) rId.n8 + << (UINT8) rId.n9 + << (UINT8) rId.n10 + << (UINT8) rId.n11; +} + +///////////////////////////// class StgHeader //////////////////////////// + +StgHeader::StgHeader() +{ + memset( this, 0, sizeof( StgHeader ) ); +} + +void StgHeader::Init() +{ + memset( this, 0, sizeof( StgHeader ) ); + memcpy( cSignature, cStgSignature, 8 ); + nVersion = 0x0003003B; + nByteOrder = 0xFFFE; + nPageSize = 9; // 512 bytes + nDataPageSize = 6; // 64 bytes + nThreshold = 4096; + nDataFATSize = 0; + nMasterChain = STG_EOF; + SetTOCStart( STG_EOF ); + SetDataFATStart( STG_EOF ); + for( short i = 0; i < 109; i++ ) + SetFATPage( i, STG_FREE ); +} + +BOOL StgHeader::Load( StgIo& rIo ) +{ + SvStream& r = *rIo.GetStrm(); + Load( r ); + return rIo.Good(); +} + +BOOL StgHeader::Load( SvStream& r ) +{ + r.Seek( 0L ); + r.Read( cSignature, 8 ); + r >> aClsId // 08 Class ID + >> nVersion // 1A version number + >> nByteOrder // 1C Unicode byte order indicator + >> nPageSize // 1E 1 << nPageSize = block size + >> nDataPageSize; // 20 1 << this size == data block size + r.SeekRel( 10 ); + r >> nFATSize // 2C total number of FAT pages + >> nTOCstrm // 30 starting page for the TOC stream + >> nReserved // 34 + >> nThreshold // 38 minimum file size for big data + >> nDataFAT // 3C page # of 1st data FAT block + >> nDataFATSize // 40 # of data FATpages + >> nMasterChain // 44 chain to the next master block + >> nMaster; // 48 # of additional master blocks + for( short i = 0; i < 109; i++ ) + r >> nMasterFAT[ i ]; + return r.GetErrorCode() == ERRCODE_NONE; +} + +BOOL StgHeader::Store( StgIo& rIo ) +{ + if( !bDirty ) + return TRUE; + SvStream& r = *rIo.GetStrm(); + r.Seek( 0L ); + r.Write( cSignature, 8 + 16 ); + r << nVersion // 1A version number + << nByteOrder // 1C Unicode byte order indicator + << nPageSize // 1E 1 << nPageSize = block size + << nDataPageSize // 20 1 << this size == data block size + << (INT32) 0 << (INT32) 0 << (INT16) 0 + << nFATSize // 2C total number of FAT pages + << nTOCstrm // 30 starting page for the TOC stream + << nReserved // 34 + << nThreshold // 38 minimum file size for big data + << nDataFAT // 3C page # of 1st data FAT block + << nDataFATSize // 40 # of data FAT pages + << nMasterChain // 44 chain to the next master block + << nMaster; // 48 # of additional master blocks + for( short i = 0; i < 109; i++ ) + r << nMasterFAT[ i ]; + bDirty = !rIo.Good(); + return BOOL( !bDirty ); +} + +static bool lcl_wontoverflow(short shift) +{ + return shift >= 0 && shift < (short)sizeof(short) * 8 - 1; +} + +// Perform thorough checks also on unknown variables +BOOL StgHeader::Check() +{ + return BOOL( memcmp( cSignature, cStgSignature, 8 ) == 0 + && (short) ( nVersion >> 16 ) == 3 ) + && lcl_wontoverflow(nPageSize) + && lcl_wontoverflow(nDataPageSize); +} + +INT32 StgHeader::GetFATPage( short n ) const +{ + if( n >= 0 && n < 109 ) + return nMasterFAT[ n ]; + else + return STG_EOF; +} + +void StgHeader::SetFATPage( short n, INT32 nb ) +{ + if( n >= 0 && n < 109 ) + { + if( nMasterFAT[ n ] != nb ) + bDirty = TRUE, nMasterFAT[ n ] = nb; + } +} + +void StgHeader::SetClassId( const ClsId& r ) +{ + if( memcmp( &aClsId, &r, sizeof( ClsId ) ) ) + bDirty = TRUE, memcpy( &aClsId, &r, sizeof( ClsId ) ); +} + +void StgHeader::SetTOCStart( INT32 n ) +{ + if( n != nTOCstrm ) bDirty = TRUE, nTOCstrm = n; +} + +void StgHeader::SetDataFATStart( INT32 n ) +{ + if( n != nDataFAT ) bDirty = TRUE, nDataFAT = n; +} + +void StgHeader::SetDataFATSize( INT32 n ) +{ + if( n != nDataFATSize ) bDirty = TRUE, nDataFATSize = n; +} + +void StgHeader::SetFATSize( INT32 n ) +{ + if( n != nFATSize ) bDirty = TRUE, nFATSize = n; +} + +void StgHeader::SetFATChain( INT32 n ) +{ + if( n != nMasterChain ) + bDirty = TRUE, nMasterChain = n; +} + +void StgHeader::SetMasters( INT32 n ) +{ + if( n != nMaster ) bDirty = TRUE, nMaster = n; +} + +///////////////////////////// class StgEntry ///////////////////////////// + +// This class is only a wrapper around teh dir entry structure +// which retrieves and sets data. + +// The name must be smaller than 32 chars. Conversion into Unicode +// is easy, since the 1st 256 characters of the Windows ANSI set +// equal the 1st 256 Unicode characters. +/* +void ToUnicode_Impl( String& rName ) +{ + rName.Erase( 32 ); + rName.Convert( ::GetSystemCharSet(), CHARSET_ANSI ); + // brute force is OK + BYTE* p = (BYTE*) rName.GetCharStr(); + for( USHORT i = 0; i < rName.Len(); i++, p++ ) + { + // check each character and substitute blanks for illegal ones + BYTE cChar = *p; + if( cChar == '!' || cChar == ':' || cChar == '\\' || cChar == '/' ) + *p = ' '; + } +} +*/ +/* +static void FromUnicode( String& rName ) +{ + rName.Convert( CHARSET_ANSI, ::GetSystemCharSet() ); +} +*/ +BOOL StgEntry::Init() +{ + memset( this, 0, sizeof (StgEntry) - sizeof( String ) ); + SetLeaf( STG_LEFT, STG_FREE ); + SetLeaf( STG_RIGHT, STG_FREE ); + SetLeaf( STG_CHILD, STG_FREE ); + SetLeaf( STG_DATA, STG_EOF ); + return TRUE; +} + +static String ToUpperUnicode( const String & rStr ) +{ + // I don't know the locale, so en_US is hopefully fine + /* + com.sun.star.lang.Locale aLocale; + aLocale.Language = OUString::createFromAscii( "en" ); + aLocale.Country = OUString::createFromAscii( "US" ); + */ + static rtl::OUString aEN=rtl::OUString::createFromAscii( "en" ); + static rtl::OUString aUS=rtl::OUString::createFromAscii( "US" ); + static CharClass aCC( com::sun::star::lang::Locale( aEN, aUS, rtl::OUString() ) ); + return aCC.toUpper( rStr, 0, rStr.Len() ); +} + + +BOOL StgEntry::SetName( const String& rName ) +{ + // I don't know the locale, so en_US is hopefully fine + aName = ToUpperUnicode( rName ); + aName.Erase( 31 ); + + int i; + for( i = 0; i < aName.Len() && i < 32; i++ ) + nName[ i ] = rName.GetChar( sal_uInt16( i )); + while( i < 32 ) + nName[ i++ ] = 0; + nNameLen = ( aName.Len() + 1 ) << 1; + return TRUE; +} + +INT32 StgEntry::GetLeaf( StgEntryRef eRef ) const +{ + INT32 n = -1; + switch( eRef ) + { + case STG_LEFT: n = nLeft; break; + case STG_RIGHT: n = nRight; break; + case STG_CHILD: n = nChild; break; + case STG_DATA: n = nPage1; break; + } + return n; +} + +void StgEntry::SetLeaf( StgEntryRef eRef, INT32 nPage ) +{ + switch( eRef ) + { + case STG_LEFT: nLeft = nPage; break; + case STG_RIGHT: nRight = nPage; break; + case STG_CHILD: nChild = nPage; break; + case STG_DATA: nPage1 = nPage; break; + } +} + +const INT32* StgEntry::GetTime( StgEntryTime eTime ) const +{ + return( eTime == STG_MODIFIED ) ? nMtime : nAtime; +} + +void StgEntry::SetTime( StgEntryTime eTime, INT32* pTime ) +{ + if( eTime == STG_MODIFIED ) + nMtime[ 0 ] = *pTime++, nMtime[ 1 ] = *pTime; + else + nAtime[ 0 ] = *pTime++, nAtime[ 1 ] = *pTime; +} + +void StgEntry::SetClassId( const ClsId& r ) +{ + memcpy( &aClsId, &r, sizeof( ClsId ) ); +} + +void StgEntry::GetName( String& rName ) const +{ + UINT16 n = nNameLen; + if( n ) + n = ( n >> 1 ) - 1; + rName = String( nName, n ); +} + +// Compare two entries. Do this case-insensitive. + +short StgEntry::Compare( const StgEntry& r ) const +{ + /* + short nRes = r.nNameLen - nNameLen; + if( !nRes ) return strcmp( r.aName, aName ); + else return nRes; + */ + sal_Int32 nRes = r.nNameLen - nNameLen; + if( !nRes ) + nRes = r.aName.CompareTo( aName ); + return (short)nRes; + //return aName.CompareTo( r.aName ); +} + +// These load/store operations are a bit more complicated, +// since they have to copy their contents into a packed structure. + +BOOL StgEntry::Load( const void* pFrom ) +{ + SvMemoryStream r( (sal_Char*) pFrom, 128, STREAM_READ ); + for( short i = 0; i < 32; i++ ) + r >> nName[ i ]; // 00 name as WCHAR + r >> nNameLen // 40 size of name in bytes including 00H + >> cType // 42 entry type + >> cFlags // 43 0 or 1 (tree balance?) + >> nLeft // 44 left node entry + >> nRight // 48 right node entry + >> nChild // 4C 1st child entry if storage + >> aClsId // 50 class ID (optional) + >> nFlags // 60 state flags(?) + >> nMtime[ 0 ] // 64 modification time + >> nMtime[ 1 ] // 64 modification time + >> nAtime[ 0 ] // 6C creation and access time + >> nAtime[ 1 ] // 6C creation and access time + >> nPage1 // 74 starting block (either direct or translated) + >> nSize // 78 file size + >> nUnknown; // 7C unknown + + UINT16 n = nNameLen; + if( n ) + n = ( n >> 1 ) - 1; + if( n > 31 || (nSize < 0 && cType != STG_STORAGE) ) + { + // the size makes no sence for the substorage + // TODO/LATER: actually the size should be an unsigned value, but in this case it would mean a stream of more than 2Gb + return FALSE; + } + + aName = String( nName, n ); + // I don't know the locale, so en_US is hopefully fine + aName = ToUpperUnicode( aName ); + aName.Erase( 31 ); + + return TRUE; +} + +void StgEntry::Store( void* pTo ) +{ + SvMemoryStream r( (sal_Char *)pTo, 128, STREAM_WRITE ); + for( short i = 0; i < 32; i++ ) + r << nName[ i ]; // 00 name as WCHAR + r << nNameLen // 40 size of name in bytes including 00H + << cType // 42 entry type + << cFlags // 43 0 or 1 (tree balance?) + << nLeft // 44 left node entry + << nRight // 48 right node entry + << nChild // 4C 1st child entry if storage; + << aClsId // 50 class ID (optional) + << nFlags // 60 state flags(?) + << nMtime[ 0 ] // 64 modification time + << nMtime[ 1 ] // 64 modification time + << nAtime[ 0 ] // 6C creation and access time + << nAtime[ 1 ] // 6C creation and access time + << nPage1 // 74 starting block (either direct or translated) + << nSize // 78 file size + << nUnknown; // 7C unknown +} + diff --git a/sot/source/sdstor/stgelem.hxx b/sot/source/sdstor/stgelem.hxx new file mode 100644 index 000000000000..7a5b7bc52b26 --- /dev/null +++ b/sot/source/sdstor/stgelem.hxx @@ -0,0 +1,166 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// This file reflects the structure of MS file elements. +// It is very sensitive to alignment! + +#ifndef _STGELEM_HXX +#define _STGELEM_HXX + +#ifndef _TOOLS_SOLAR_H +#include <tools/solar.h> +#endif + +#include <stg.hxx> + +class StgIo; +class SvStream; +class String; + +SvStream& operator>>( SvStream&, ClsId& ); +SvStream& operator<<( SvStream&, const ClsId& ); + +class StgHeader +{ + BYTE cSignature[ 8 ]; // 00 signature (see below) + ClsId aClsId; // 08 Class ID + INT32 nVersion; // 18 version number + UINT16 nByteOrder; // 1C Unicode byte order indicator + INT16 nPageSize; // 1E 1 << nPageSize = block size + INT16 nDataPageSize; // 20 1 << this size == data block size + BYTE bDirty; // 22 internal dirty flag + BYTE cReserved[ 9 ]; // 23 + INT32 nFATSize; // 2C total number of FAT pages + INT32 nTOCstrm; // 30 starting page for the TOC stream + INT32 nReserved; // 34 + INT32 nThreshold; // 38 minimum file size for big data + INT32 nDataFAT; // 3C page # of 1st data FAT block + INT32 nDataFATSize; // 40 # of data fat blocks + INT32 nMasterChain; // 44 chain to the next master block + INT32 nMaster; // 48 # of additional master blocks + INT32 nMasterFAT[ 109 ]; // 4C first 109 master FAT pages +public: + StgHeader(); + void Init(); // initialize the header + BOOL Load( StgIo& ); + BOOL Load( SvStream& ); + BOOL Store( StgIo& ); + BOOL Check(); // check the signature and version + short GetByteOrder() const { return nByteOrder; } + INT32 GetTOCStart() const { return nTOCstrm; } + void SetTOCStart( INT32 n ); + INT32 GetDataFATStart() const { return nDataFAT; } + void SetDataFATStart( INT32 n ); + INT32 GetDataFATSize() const { return nDataFATSize; } + void SetDataFATSize( INT32 n ); + INT32 GetThreshold() const { return nThreshold; } + short GetPageSize() const { return nPageSize; } + short GetDataPageSize() const { return nDataPageSize; } + INT32 GetFATSize() const { return nFATSize; } + void SetFATSize( INT32 n ); + INT32 GetFATChain() const { return nMasterChain; } + void SetFATChain( INT32 n ); + INT32 GetMasters() const { return nMaster; } + void SetMasters( INT32 n ); + short GetFAT1Size() const { return 109; } + const ClsId& GetClassId() const { return aClsId; } + void SetClassId( const ClsId& ); + INT32 GetFATPage( short ) const; + void SetFATPage( short, INT32 ); +}; + +enum StgEntryType { // dir entry types: + STG_EMPTY = 0, + STG_STORAGE = 1, + STG_STREAM = 2, + STG_LOCKBYTES = 3, + STG_PROPERTY = 4, + STG_ROOT = 5 +}; + +enum StgEntryRef { // reference blocks: + STG_LEFT = 0, // left + STG_RIGHT = 1, // right + STG_CHILD = 2, // child + STG_DATA = 3 // data start +}; + +enum StgEntryTime { // time codes: + STG_MODIFIED = 0, // last modification + STG_ACCESSED = 1 // last access +}; + +class StgStream; + +#define STGENTRY_SIZE 128 + +class StgEntry { // directory enty + UINT16 nName[ 32 ]; // 00 name as WCHAR + INT16 nNameLen; // 40 size of name in bytes including 00H + BYTE cType; // 42 entry type + BYTE cFlags; // 43 0 or 1 (tree balance?) + INT32 nLeft; // 44 left node entry + INT32 nRight; // 48 right node entry + INT32 nChild; // 4C 1st child entry if storage + ClsId aClsId; // 50 class ID (optional) + INT32 nFlags; // 60 state flags(?) + INT32 nMtime[ 2 ]; // 64 modification time + INT32 nAtime[ 2 ]; // 6C creation and access time + INT32 nPage1; // 74 starting block (either direct or translated) + INT32 nSize; // 78 file size + INT32 nUnknown; // 7C unknown + String aName; // Name as Compare String (ascii, upper) +public: + BOOL Init(); // initialize the data + BOOL SetName( const String& ); // store a name (ASCII, up to 32 chars) + void GetName( String& rName ) const; + // fill in the name + short Compare( const StgEntry& ) const; // compare two entries + BOOL Load( const void* ); + void Store( void* ); + StgEntryType GetType() const { return (StgEntryType) cType; } + INT32 GetStartPage() const { return nPage1; } + void SetType( StgEntryType t ) { cType = (BYTE) t; } + BYTE GetFlags() const { return cFlags; } + void SetFlags( BYTE c ) { cFlags = c; } + INT32 GetSize() const { return nSize; } + void SetSize( INT32 n ) { nSize = n; } + const ClsId& GetClassId() const { return aClsId; } + void SetClassId( const ClsId& ); + INT32 GetLeaf( StgEntryRef ) const; + void SetLeaf( StgEntryRef, INT32 ); + const INT32* GetTime( StgEntryTime ) const; + void SetTime( StgEntryTime, INT32* ); +}; + + +#define STG_FREE -1L // page is free +#define STG_EOF -2L // page is last page in chain +#define STG_FAT -3L // page is FAT page +#define STG_MASTER -4L // page is master FAT page + +#endif diff --git a/sot/source/sdstor/stgio.cxx b/sot/source/sdstor/stgio.cxx new file mode 100644 index 000000000000..2c18429b9d64 --- /dev/null +++ b/sot/source/sdstor/stgio.cxx @@ -0,0 +1,389 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sot.hxx" + +#include "stg.hxx" +#include "stgelem.hxx" +#include "stgcache.hxx" +#include "stgstrms.hxx" +#include "stgdir.hxx" +#include "stgio.hxx" +#include <rtl/instance.hxx> + +///////////////////////////// class StgIo ////////////////////////////// + +// This class holds the storage header and all internal streams. + +StgIo::StgIo() : StgCache() +{ + pTOC = NULL; + pDataFAT = NULL; + pDataStrm = NULL; + pFAT = NULL; + bCopied = FALSE; +} + +StgIo::~StgIo() +{ + delete pTOC; + delete pDataFAT; + delete pDataStrm; + delete pFAT; +} + +// Load the header. Do not set an error code if the header is invalid. + +BOOL StgIo::Load() +{ + if( pStrm ) + { + if( aHdr.Load( *this ) ) + { + if( aHdr.Check() ) + SetupStreams(); + else + return FALSE; + } + } + return Good(); +} + +// Set up an initial, empty storage + +BOOL StgIo::Init() +{ + aHdr.Init(); + SetupStreams(); + return CommitAll(); +} + +void StgIo::SetupStreams() +{ + delete pTOC; + delete pDataFAT; + delete pDataStrm; + delete pFAT; + pTOC = NULL; + pDataFAT = NULL; + pDataStrm = NULL; + pFAT = NULL; + ResetError(); + SetPhysPageSize( 1 << aHdr.GetPageSize() ); + pFAT = new StgFATStrm( *this ); + pTOC = new StgDirStrm( *this ); + if( !GetError() ) + { + StgDirEntry* pRoot = pTOC->GetRoot(); + if( pRoot ) + { + pDataFAT = new StgDataStrm( *this, aHdr.GetDataFATStart(), -1 ); + pDataStrm = new StgDataStrm( *this, pRoot ); + pDataFAT->SetIncrement( 1 << aHdr.GetPageSize() ); + pDataStrm->SetIncrement( GetDataPageSize() ); + pDataStrm->SetEntry( *pRoot ); + } + else + SetError( SVSTREAM_FILEFORMAT_ERROR ); + } +} + +// get the logical data page size + +short StgIo::GetDataPageSize() +{ + return 1 << aHdr.GetDataPageSize(); +} + +// Commit everything + +BOOL StgIo::CommitAll() +{ + // Store the data (all streams and the TOC) + if( pTOC->Store() ) + { + if( Commit( NULL ) ) + { + aHdr.SetDataFATStart( pDataFAT->GetStart() ); + aHdr.SetDataFATSize( pDataFAT->GetPages() ); + aHdr.SetTOCStart( pTOC->GetStart() ); + if( aHdr.Store( *this ) ) + { + pStrm->Flush(); + ULONG n = pStrm->GetError(); + SetError( n ); +#ifdef DBG_UTIL + if( n==0 ) ValidateFATs(); +#endif + return BOOL( n == 0 ); + } + } + } + SetError( SVSTREAM_WRITE_ERROR ); + return FALSE; +} + + +class EasyFat +{ + INT32 *pFat; + BOOL *pFree; + INT32 nPages; + INT32 nPageSize; + +public: + EasyFat( StgIo & rIo, StgStrm *pFatStream, INT32 nPSize ); + ~EasyFat() { delete[] pFat; delete[] pFree; } + INT32 GetPageSize() { return nPageSize; } + INT32 Count() { return nPages; } + INT32 operator[]( INT32 nOffset ) { return pFat[ nOffset ]; } + + ULONG Mark( INT32 nPage, INT32 nCount, INT32 nExpect ); + BOOL HasUnrefChains(); +}; + +EasyFat::EasyFat( StgIo& rIo, StgStrm* pFatStream, INT32 nPSize ) +{ + nPages = pFatStream->GetSize() >> 2; + nPageSize = nPSize; + pFat = new INT32[ nPages ]; + pFree = new BOOL[ nPages ]; + + StgPage *pPage = NULL; + INT32 nFatPageSize = (1 << rIo.aHdr.GetPageSize()) - 2; + + for( INT32 nPage = 0; nPage < nPages; nPage++ ) + { + if( ! (nPage % nFatPageSize) ) + { + pFatStream->Pos2Page( nPage << 2 ); + INT32 nPhysPage = pFatStream->GetPage(); + pPage = rIo.Get( nPhysPage, TRUE ); + } + + pFat[ nPage ] = pPage->GetPage( short( nPage % nFatPageSize ) ); + pFree[ nPage ] = TRUE; + } +} + +BOOL EasyFat::HasUnrefChains() +{ + for( INT32 nPage = 0; nPage < nPages; nPage++ ) + { + if( pFree[ nPage ] && pFat[ nPage ] != -1 ) + return TRUE; + } + return FALSE; +} + +ULONG EasyFat::Mark( INT32 nPage, INT32 nCount, INT32 nExpect ) +{ + if( nCount > 0 ) + --nCount /= GetPageSize(), nCount++; + + INT32 nCurPage = nPage; + while( nCount != 0 ) + { + pFree[ nCurPage ] = FALSE; + nCurPage = pFat[ nCurPage ]; + //Stream zu lang + if( nCurPage != nExpect && nCount == 1 ) + return FAT_WRONGLENGTH; + //Stream zu kurz + if( nCurPage == nExpect && nCount != 1 && nCount != -1 ) + return FAT_WRONGLENGTH; + // letzter Block bei Stream ohne Laenge + if( nCurPage == nExpect && nCount == -1 ) + nCount = 1; + if( nCount != -1 ) + nCount--; + // Naechster Block nicht in der FAT + if( nCount && ( nCurPage < 0 || nCurPage >= nPages ) ) + return FAT_OUTOFBOUNDS; + } + return FAT_OK; +} + +class Validator +{ + ULONG nError; + + EasyFat aSmallFat; + EasyFat aFat; + + StgIo &rIo; + + ULONG ValidateMasterFATs(); + ULONG ValidateDirectoryEntries(); + ULONG FindUnrefedChains(); + ULONG MarkAll( StgDirEntry *pEntry ); + +public: + + Validator( StgIo &rIo ); + BOOL IsError() { return nError != 0; } +}; + +Validator::Validator( StgIo &rIoP ) + : aSmallFat( rIoP, rIoP.pDataFAT, 1 << rIoP.aHdr.GetDataPageSize() ), + aFat( rIoP, rIoP.pFAT, 1 << rIoP.aHdr.GetPageSize() ), + rIo( rIoP ) +{ + ULONG nErr = nError = FAT_OK; + + if( ( nErr = ValidateMasterFATs() ) != FAT_OK ) + nError = nErr; + else if( ( nErr = ValidateDirectoryEntries() ) != FAT_OK ) + nError = nErr; + else if( ( nErr = FindUnrefedChains()) != FAT_OK ) + nError = nErr; +} + +ULONG Validator::ValidateMasterFATs() +{ + INT32 nCount = rIo.aHdr.GetFATSize(); + ULONG nErr; + for( INT32 i = 0; i < nCount; i++ ) + { + if( ( nErr = aFat.Mark(rIo.pFAT->GetPage( short(i), FALSE ), aFat.GetPageSize(), -3 )) != FAT_OK ) + return nErr; + } + if( rIo.aHdr.GetMasters() ) + if( ( nErr = aFat.Mark(rIo.aHdr.GetFATChain( ), aFat.GetPageSize(), -4 )) != FAT_OK ) + return nErr; + return FAT_OK; +} + +ULONG Validator::MarkAll( StgDirEntry *pEntry ) +{ + StgIterator aIter( *pEntry ); + ULONG nErr = FAT_OK; + for( StgDirEntry* p = aIter.First(); p ; p = aIter.Next() ) + { + if( p->aEntry.GetType() == STG_STORAGE ) + { + nErr = MarkAll( p ); + if( nErr != FAT_OK ) + return nErr; + } + else + { + INT32 nSize = p->aEntry.GetSize(); + if( nSize < rIo.aHdr.GetThreshold() ) + nErr = aSmallFat.Mark( p->aEntry.GetStartPage(),nSize, -2 ); + else + nErr = aFat.Mark( p->aEntry.GetStartPage(),nSize, -2 ); + if( nErr != FAT_OK ) + return nErr; + } + } + return FAT_OK; +} + +ULONG Validator::ValidateDirectoryEntries() +{ + // Normale DirEntries + ULONG nErr = MarkAll( rIo.pTOC->GetRoot() ); + if( nErr != FAT_OK ) + return nErr; + // Small Data + nErr = aFat.Mark( rIo.pTOC->GetRoot()->aEntry.GetStartPage(), + rIo.pTOC->GetRoot()->aEntry.GetSize(), -2 ); + if( nErr != FAT_OK ) + return nErr; + // Small Data FAT + nErr = aFat.Mark( + rIo.aHdr.GetDataFATStart(), + rIo.aHdr.GetDataFATSize() * aFat.GetPageSize(), -2 ); + if( nErr != FAT_OK ) + return nErr; + // TOC + nErr = aFat.Mark( + rIo.aHdr.GetTOCStart(), -1, -2 ); + return nErr; +} + +ULONG Validator::FindUnrefedChains() +{ + if( aSmallFat.HasUnrefChains() || + aFat.HasUnrefChains() ) + return FAT_UNREFCHAIN; + else + return FAT_OK; +} + +namespace { struct ErrorLink : public rtl::Static<Link, ErrorLink > {}; } + +void StgIo::SetErrorLink( const Link& rLink ) +{ + ErrorLink::get() = rLink; +} + +const Link& StgIo::GetErrorLink() +{ + return ErrorLink::get(); +} + +ULONG StgIo::ValidateFATs() +{ + if( bFile ) + { + Validator *pV = new Validator( *this ); + BOOL bRet1 = !pV->IsError(), bRet2 = TRUE ; + delete pV; + SvFileStream *pFileStrm = ( SvFileStream *) GetStrm(); + StgIo aIo; + if( aIo.Open( pFileStrm->GetFileName(), + STREAM_READ | STREAM_SHARE_DENYNONE) && + aIo.Load() ) + { + pV = new Validator( aIo ); + bRet2 = !pV->IsError(); + delete pV; + } + + ULONG nErr; + if( bRet1 != bRet2 ) + nErr = bRet1 ? FAT_ONFILEERROR : FAT_INMEMORYERROR; + else nErr = bRet1 ? FAT_OK : FAT_BOTHERROR; + if( nErr != FAT_OK && !bCopied ) + { + StgLinkArg aArg; + aArg.aFile = pFileStrm->GetFileName(); + aArg.nErr = nErr; + ErrorLink::get().Call( &aArg ); + bCopied = TRUE; + } +// DBG_ASSERT( nErr == FAT_OK ,"Storage kaputt"); + return nErr; + } +// DBG_ERROR("Validiere nicht (kein FileStorage)"); + return FAT_OK; +} + + diff --git a/sot/source/sdstor/stgio.hxx b/sot/source/sdstor/stgio.hxx new file mode 100644 index 000000000000..db1c00b8d521 --- /dev/null +++ b/sot/source/sdstor/stgio.hxx @@ -0,0 +1,80 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _STGIO_HXX +#define _STGIO_HXX + +#include <stgcache.hxx> +#include <stgelem.hxx> +#include <tools/string.hxx> + +class StgFATStrm; +class StgDataStrm; +class StgDirStrm; +class String; + +enum FAT_ERROR +{ + FAT_OK, + FAT_WRONGLENGTH, + FAT_UNREFCHAIN, + FAT_OVERWRITE, + FAT_OUTOFBOUNDS, + + FAT_INMEMORYERROR, + FAT_ONFILEERROR, + FAT_BOTHERROR +}; + +struct StgLinkArg +{ + String aFile; + ULONG nErr; +}; + +class StgIo : public StgCache { + void SetupStreams(); // load all internal streams + BOOL bCopied; +public: + StgIo(); + ~StgIo(); + StgHeader aHdr; // storage file header + StgFATStrm* pFAT; // FAT stream + StgDirStrm* pTOC; // TOC stream + StgDataStrm* pDataFAT; // small data FAT stream + StgDataStrm* pDataStrm; // small data stream + short GetDataPageSize(); // get the logical data page size + BOOL Load(); // load a storage file + BOOL Init(); // set up an empty file + BOOL CommitAll(); // commit everything (root commit) + + static void SetErrorLink( const Link& ); + static const Link& GetErrorLink(); + ULONG ValidateFATs( ); +}; + +#endif diff --git a/sot/source/sdstor/stgole.cxx b/sot/source/sdstor/stgole.cxx new file mode 100644 index 000000000000..148f1e87585c --- /dev/null +++ b/sot/source/sdstor/stgole.cxx @@ -0,0 +1,230 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sot.hxx" + +#include "rtl/string.h" +#include "rtl/string.h" +#include "stgole.hxx" +#include "storinfo.hxx" // Read/WriteClipboardFormat() + +#include <tools/debug.hxx> +#if defined(_MSC_VER) && (_MSC_VER>=1400) +#pragma warning(disable: 4342) +#endif +///////////////////////// class StgInternalStream //////////////////////// + +StgInternalStream::StgInternalStream + ( BaseStorage& rStg, const String& rName, BOOL bWr ) +{ + bIsWritable = TRUE; + USHORT nMode = bWr + ? STREAM_WRITE | STREAM_SHARE_DENYALL + : STREAM_READ | STREAM_SHARE_DENYWRITE | STREAM_NOCREATE; + pStrm = rStg.OpenStream( rName, nMode ); + + // set the error code right here in the stream + SetError( rStg.GetError() ); + SetBufferSize( 1024 ); +} + +StgInternalStream::~StgInternalStream() +{ + delete pStrm; +} + +ULONG StgInternalStream::GetData( void* pData, ULONG nSize ) +{ + if( pStrm ) + { + nSize = pStrm->Read( pData, nSize ); + SetError( pStrm->GetError() ); + return nSize; + } + else + return 0; +} + +ULONG StgInternalStream::PutData( const void* pData, ULONG nSize ) +{ + if( pStrm ) + { + nSize = pStrm->Write( pData, nSize ); + SetError( pStrm->GetError() ); + return nSize; + } + else + return 0; +} + +ULONG StgInternalStream::SeekPos( ULONG nPos ) +{ + return pStrm ? pStrm->Seek( nPos ) : 0; +} + +void StgInternalStream::FlushData() +{ + if( pStrm ) + { + pStrm->Flush(); + SetError( pStrm->GetError() ); + } +} + +void StgInternalStream::Commit() +{ + Flush(); + pStrm->Commit(); +} + +///////////////////////// class StgCompObjStream ///////////////////////// + +StgCompObjStream::StgCompObjStream( BaseStorage& rStg, BOOL bWr ) + : StgInternalStream( rStg, String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "\1CompObj" ) ), bWr ) +{ + memset( &aClsId, 0, sizeof( ClsId ) ); + nCbFormat = 0; +} + +BOOL StgCompObjStream::Load() +{ + memset( &aClsId, 0, sizeof( ClsId ) ); + nCbFormat = 0; + aUserName.Erase(); + if( GetError() != SVSTREAM_OK ) + return FALSE; + Seek( 8L ); // skip the first part + INT32 nMarker = 0; + *this >> nMarker; + if( nMarker == -1L ) + { + *this >> aClsId; + INT32 nLen1 = 0; + *this >> nLen1; + // higher bits are ignored + nLen1 &= 0xFFFF; + sal_Char* p = new sal_Char[ (USHORT) nLen1 ]; + if( Read( p, nLen1 ) == (ULONG) nLen1 ) + { + aUserName = nLen1 ? String( p, gsl_getSystemTextEncoding() ) : String(); +/* // Now we can read the CB format + INT32 nLen2 = 0; + *this >> nLen2; + if( nLen2 > 0 ) + { + // get a string name + if( nLen2 > nLen1 ) + delete p, p = new char[ nLen2 ]; + if( Read( p, nLen2 ) == (ULONG) nLen2 && nLen2 ) + nCbFormat = Exchange::RegisterFormatName( String( p ) ); + else + SetError( SVSTREAM_GENERALERROR ); + } + else if( nLen2 == -1L ) + // Windows clipboard format + *this >> nCbFormat; + else + // unknown identifier + SetError( SVSTREAM_GENERALERROR ); +*/ + nCbFormat = ReadClipboardFormat( *this ); + } + else + SetError( SVSTREAM_GENERALERROR ); + delete [] p; + } + return BOOL( GetError() == SVSTREAM_OK ); +} + +BOOL StgCompObjStream::Store() +{ + if( GetError() != SVSTREAM_OK ) + return FALSE; + Seek( 0L ); + ByteString aAsciiUserName( aUserName, RTL_TEXTENCODING_ASCII_US ); + *this << (INT16) 1 // Version? + << (INT16) -2 // 0xFFFE = Byte Order Indicator + << (INT32) 0x0A03 // Windows 3.10 + << (INT32) -1L + << aClsId // Class ID + << (INT32) (aAsciiUserName.Len() + 1) + << (const char *)aAsciiUserName.GetBuffer() + << (UINT8) 0; // string terminator +/* // determine the clipboard format string + String aCbFmt; + if( nCbFormat > FORMAT_GDIMETAFILE ) + aCbFmt = Exchange::GetFormatName( nCbFormat ); + if( aCbFmt.Len() ) + *this << (INT32) aCbFmt.Len() + 1 + << (const char*) aCbFmt + << (UINT8) 0; + else if( nCbFormat ) + *this << (INT32) -1 // for Windows + << (INT32) nCbFormat; + else + *this << (INT32) 0; // no clipboard format +*/ + WriteClipboardFormat( *this, nCbFormat ); + *this << (INT32) 0; // terminator + Commit(); + return BOOL( GetError() == SVSTREAM_OK ); +} + +/////////////////////////// class StgOleStream /////////////////////////// + +StgOleStream::StgOleStream( BaseStorage& rStg, BOOL bWr ) + : StgInternalStream( rStg, String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "\1Ole" ) ), bWr ) +{ + nFlags = 0; +} + +BOOL StgOleStream::Load() +{ + nFlags = 0; + if( GetError() != SVSTREAM_OK ) + return FALSE; + INT32 version = 0; + Seek( 0L ); + *this >> version >> nFlags; + return BOOL( GetError() == SVSTREAM_OK ); +} + +BOOL StgOleStream::Store() +{ + if( GetError() != SVSTREAM_OK ) + return FALSE; + Seek( 0L ); + *this << (INT32) 0x02000001 // OLE version, format + << (INT32) nFlags // Object flags + << (INT32) 0 // Update Options + << (INT32) 0 // reserved + << (INT32) 0; // Moniker 1 + Commit(); + return BOOL( GetError() == SVSTREAM_OK ); +} + diff --git a/sot/source/sdstor/stgole.hxx b/sot/source/sdstor/stgole.hxx new file mode 100644 index 000000000000..346f21035f06 --- /dev/null +++ b/sot/source/sdstor/stgole.hxx @@ -0,0 +1,77 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SDSTOR_STGOLE_HXX +#define _SDSTOR_STGOLE_HXX + +#include <string.h> // memset() + +#include "stg.hxx" +#include "stgelem.hxx" + +class StgInternalStream : public SvStream +{ + BaseStorageStream* pStrm; + virtual ULONG GetData( void* pData, ULONG nSize ); + virtual ULONG PutData( const void* pData, ULONG nSize ); + virtual ULONG SeekPos( ULONG nPos ); + virtual void FlushData(); +public: + StgInternalStream( BaseStorage&, const String&, BOOL ); + ~StgInternalStream(); + void Commit(); +}; + +// standard stream "\1CompObj" + +class StgCompObjStream : public StgInternalStream +{ + ClsId aClsId; + String aUserName; + ULONG nCbFormat; +public: + StgCompObjStream( BaseStorage&, BOOL ); + ClsId& GetClsId() { return aClsId; } + String& GetUserName() { return aUserName; } + ULONG& GetCbFormat() { return nCbFormat; } + BOOL Load(); + BOOL Store(); +}; + +// standard stream "\1Ole" + +class StgOleStream : public StgInternalStream +{ + sal_uInt32 nFlags; +public: + StgOleStream( BaseStorage&, BOOL ); + sal_uInt32& GetFlags() { return nFlags; } + BOOL Load(); + BOOL Store(); +}; + +#endif diff --git a/sot/source/sdstor/stgstrms.cxx b/sot/source/sdstor/stgstrms.cxx new file mode 100644 index 000000000000..dd6ba6202bbe --- /dev/null +++ b/sot/source/sdstor/stgstrms.cxx @@ -0,0 +1,1241 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sot.hxx" + +#include <string.h> // memcpy() + +#include <osl/file.hxx> +#include <tools/tempfile.hxx> +#include <tools/debug.hxx> + +#include "stg.hxx" +#include "stgelem.hxx" +#include "stgcache.hxx" +#include "stgstrms.hxx" +#include "stgdir.hxx" +#include "stgio.hxx" + +#define __HUGE + +///////////////////////////// class StgFAT /////////////////////////////// + +// The FAT class performs FAT operations on an underlying storage stream. +// This stream is either the master FAT stream (m == TRUE ) or a normal +// storage stream, which then holds the FAT for small data allocations. + +StgFAT::StgFAT( StgStrm& r, BOOL m ) : rStrm( r ) +{ + bPhys = m; + nPageSize = rStrm.GetIo().GetPhysPageSize(); + nEntries = nPageSize >> 2; + nOffset = 0; + nMaxPage = 0; + nLimit = 0; +} + +// Retrieve the physical page for a given byte offset. + +StgPage* StgFAT::GetPhysPage( INT32 nByteOff ) +{ + StgPage* pPg = NULL; + // Position within the underlying stream + // use the Pos2Page() method of the stream + if( rStrm.Pos2Page( nByteOff ) ) + { + nOffset = rStrm.GetOffset(); + INT32 nPhysPage = rStrm.GetPage(); + // get the physical page (must be present) + pPg = rStrm.GetIo().Get( nPhysPage, TRUE ); + } + return pPg; +} + +// Get the follow page for a certain FAT page. + +INT32 StgFAT::GetNextPage( INT32 nPg ) +{ + if( nPg >= 0 ) + { + StgPage* pPg = GetPhysPage( nPg << 2 ); + nPg = pPg ? pPg->GetPage( nOffset >> 2 ) : STG_EOF; + } + return nPg; +} + +// Find the best fit block for the given size. Return +// the starting block and its size or STG_EOF and 0. +// nLastPage is a stopper which tells the current +// underlying stream size. It is treated as a recommendation +// to abort the search to inhibit excessive file growth. + +INT32 StgFAT::FindBlock( INT32& nPgs ) +{ + INT32 nMinStart = STG_EOF, nMinLen = 0; + INT32 nMaxStart = STG_EOF, nMaxLen = 0x7FFFFFFFL; + INT32 nTmpStart = STG_EOF, nTmpLen = 0; + INT32 nPages = rStrm.GetSize() >> 2; + BOOL bFound = FALSE; + StgPage* pPg = NULL; + short nEntry = 0; + for( INT32 i = 0; i < nPages; i++, nEntry++ ) + { + if( !( nEntry % nEntries ) ) + { + // load the next page for that stream + nEntry = 0; + pPg = GetPhysPage( i << 2 ); + if( !pPg ) + return STG_EOF; + } + INT32 nCur = pPg->GetPage( nEntry ); + if( nCur == STG_FREE ) + { + // count the size of this area + if( nTmpLen ) + nTmpLen++; + else + nTmpStart = i, + nTmpLen = 1; + if( nTmpLen == nPgs + // If we already did find a block, stop when reaching the limit + || ( bFound && ( nEntry >= nLimit ) ) ) + break; + } + else if( nTmpLen ) + { + if( nTmpLen > nPgs && nTmpLen < nMaxLen ) + // block > requested size + nMaxLen = nTmpLen, nMaxStart = nTmpStart, bFound = TRUE; + else if( nTmpLen >= nMinLen ) + { + // block < requested size + nMinLen = nTmpLen, nMinStart = nTmpStart; + bFound = TRUE; + if( nTmpLen == nPgs ) + break; + } + nTmpStart = STG_EOF; + nTmpLen = 0; + } + } + // Determine which block to use. + if( nTmpLen ) + { + if( nTmpLen > nPgs && nTmpLen < nMaxLen ) + // block > requested size + nMaxLen = nTmpLen, nMaxStart = nTmpStart; + else if( nTmpLen >= nMinLen ) + // block < requested size + nMinLen = nTmpLen, nMinStart = nTmpStart; + } + if( nMinStart != STG_EOF && nMaxStart != STG_EOF ) + { + // two areas found; return the best fit area + INT32 nMinDiff = nPgs - nMinLen; + INT32 nMaxDiff = nMaxLen - nPgs; + if( nMinDiff > nMaxDiff ) + nMinStart = STG_EOF; + } + if( nMinStart != STG_EOF ) + { + nPgs = nMinLen; return nMinStart; + } + else + { + return nMaxStart; + } +} + +// Set up the consecutive chain for a given block. + +BOOL StgFAT::MakeChain( INT32 nStart, INT32 nPgs ) +{ + INT32 nPos = nStart << 2; + StgPage* pPg = GetPhysPage( nPos ); + if( !pPg || !nPgs ) + return FALSE; + while( --nPgs ) + { + if( nOffset >= nPageSize ) + { + pPg = GetPhysPage( nPos ); + if( !pPg ) + return FALSE; + } + pPg->SetPage( nOffset >> 2, ++nStart ); + nOffset += 4; + nPos += 4; + } + if( nOffset >= nPageSize ) + { + pPg = GetPhysPage( nPos ); + if( !pPg ) + return FALSE; + } + pPg->SetPage( nOffset >> 2, STG_EOF ); + return TRUE; +} + +// Allocate a block of data from the given page number on. +// It the page number is != STG_EOF, chain the block. + +INT32 StgFAT::AllocPages( INT32 nBgn, INT32 nPgs ) +{ + INT32 nOrig = nBgn; + INT32 nLast = nBgn; + INT32 nBegin = STG_EOF; + INT32 nAlloc; + INT32 nPages = rStrm.GetSize() >> 2; + short nPasses = 0; + // allow for two passes + while( nPasses < 2 ) + { + // try to satisfy the request from the pool of free pages + while( nPgs ) + { + nAlloc = nPgs; + nBegin = FindBlock( nAlloc ); + // no more blocks left in present alloc chain + if( nBegin == STG_EOF ) + break; + if( ( nBegin + nAlloc ) > nMaxPage ) + nMaxPage = nBegin + nAlloc; + if( !MakeChain( nBegin, nAlloc ) ) + return STG_EOF; + if( nOrig == STG_EOF ) + nOrig = nBegin; + else + { + // Patch the chain + StgPage* pPg = GetPhysPage( nLast << 2 ); + if( !pPg ) + return STG_EOF; + pPg->SetPage( nOffset >> 2, nBegin ); + } + nLast = nBegin + nAlloc - 1; + nPgs -= nAlloc; + } + if( nPgs && !nPasses ) + { + // we need new, fresh space, so allocate and retry + if( !rStrm.SetSize( ( nPages + nPgs ) << 2 ) ) + return STG_EOF; + if( !bPhys && !InitNew( nPages ) ) + return FALSE; + nPages = rStrm.GetSize() >> 2; + nPasses++; + } + else + break; + } + // now we should have a chain for the complete block + if( nBegin == STG_EOF || nPgs ) + { + rStrm.GetIo().SetError( SVSTREAM_FILEFORMAT_ERROR ); + return STG_EOF; // bad structure + } + return nOrig; +} + +// Initialize newly allocated pages for a standard FAT stream +// It can be assumed that the stream size is always on +// a page boundary + +BOOL StgFAT::InitNew( INT32 nPage1 ) +{ + INT32 n = ( ( rStrm.GetSize() >> 2 ) - nPage1 ) / nEntries; + while( n-- ) + { + StgPage* pPg = NULL; + // Position within the underlying stream + // use the Pos2Page() method of the stream + rStrm.Pos2Page( nPage1 << 2 ); + // Initialize the page + pPg = rStrm.GetIo().Copy( rStrm.GetPage(), STG_FREE ); + if ( !pPg ) + return FALSE; + for( short i = 0; i < nEntries; i++ ) + pPg->SetPage( i, STG_FREE ); + nPage1++; + } + return TRUE; +} + +// Release a chain + +BOOL StgFAT::FreePages( INT32 nStart, BOOL bAll ) +{ + while( nStart >= 0 ) + { + StgPage* pPg = GetPhysPage( nStart << 2 ); + if( !pPg ) + return FALSE; + nStart = pPg->GetPage( nOffset >> 2 ); + // The first released page is either set to EOF or FREE + pPg->SetPage( nOffset >> 2, bAll ? STG_FREE : STG_EOF ); + bAll = TRUE; + } + return TRUE; +} + +///////////////////////////// class StgStrm //////////////////////////////// + +// The base stream class provides basic functionality for seeking +// and accessing the data on a physical basis. It uses the built-in +// FAT class for the page allocations. + +StgStrm::StgStrm( StgIo& r ) : rIo( r ) +{ + pFat = NULL; + nStart = nPage = STG_EOF; + nOffset = 0; + pEntry = NULL; + nPos = nSize = 0; + nPageSize = rIo.GetPhysPageSize(); +} + +StgStrm::~StgStrm() +{ + delete pFat; +} + +// Attach the stream to the given entry. + +void StgStrm::SetEntry( StgDirEntry& r ) +{ + r.aEntry.SetLeaf( STG_DATA, nStart ); + r.aEntry.SetSize( nSize ); + pEntry = &r; + r.SetDirty(); +} + +// Compute page number and offset for the given byte position. +// If the position is behind the size, set the stream right +// behind the EOF. + +BOOL StgStrm::Pos2Page( INT32 nBytePos ) +{ + INT32 nRel, nBgn; + // Values < 0 seek to the end + if( nBytePos < 0 || nBytePos >= nSize ) + nBytePos = nSize; + // Adjust the position back to offset 0 + nPos -= nOffset; + INT32 nMask = ~( nPageSize - 1 ); + INT32 nOld = nPos & nMask; + INT32 nNew = nBytePos & nMask; + nOffset = (short) ( nBytePos & ~nMask ); + nPos = nBytePos; + if( nOld == nNew ) + return TRUE; + if( nNew > nOld ) + { + // the new position is behind the current, so an incremental + // positioning is OK. Set the page relative position + nRel = nNew - nOld; + nBgn = nPage; + } + else + { + // the new position is before the current, so we have to scan + // the entire chain. + nRel = nNew; + nBgn = nStart; + } + // now, traverse the FAT chain. + nRel /= nPageSize; + INT32 nLast = STG_EOF; + while( nRel && nBgn >= 0 ) + { + nLast = nBgn; + nBgn = pFat->GetNextPage( nBgn ); + nRel--; + } + // special case: seek to 1st byte of new, unallocated page + // (in case the file size is a multiple of the page size) + if( nBytePos == nSize && nBgn == STG_EOF && !nRel && !nOffset ) + nBgn = nLast, nOffset = nPageSize; + if( nBgn < 0 && nBgn != STG_EOF ) + { + rIo.SetError( SVSTREAM_FILEFORMAT_ERROR ); + nBgn = STG_EOF; + nOffset = nPageSize; + } + nPage = nBgn; + return BOOL( nRel == 0 && nPage >= 0 ); +} + +// Retrieve the physical page for a given byte offset. + +StgPage* StgStrm::GetPhysPage( INT32 nBytePos, BOOL bForce ) +{ + if( !Pos2Page( nBytePos ) ) + return NULL; + return rIo.Get( nPage, bForce ); +} + +// Copy an entire stream. Both streams are allocated in the FAT. +// The target stream is this stream. + +BOOL StgStrm::Copy( INT32 nFrom, INT32 nBytes ) +{ + INT32 nTo = nStart; + INT32 nPgs = ( nBytes + nPageSize - 1 ) / nPageSize; + while( nPgs-- ) + { + if( nTo < 0 ) + { + rIo.SetError( SVSTREAM_FILEFORMAT_ERROR ); + return FALSE; + } + rIo.Copy( nTo, nFrom ); + if( nFrom >= 0 ) + { + nFrom = pFat->GetNextPage( nFrom ); + if( nFrom < 0 ) + { + rIo.SetError( SVSTREAM_FILEFORMAT_ERROR ); + return FALSE; + } + } + nTo = pFat->GetNextPage( nTo ); + } + return TRUE; +} + +BOOL StgStrm::SetSize( INT32 nBytes ) +{ + // round up to page size + INT32 nOld = ( ( nSize + nPageSize - 1 ) / nPageSize ) * nPageSize; + INT32 nNew = ( ( nBytes + nPageSize - 1 ) / nPageSize ) * nPageSize; + if( nNew > nOld ) + { + if( !Pos2Page( nSize ) ) + return FALSE; + INT32 nBgn = pFat->AllocPages( nPage, ( nNew - nOld ) / nPageSize ); + if( nBgn == STG_EOF ) + return FALSE; + if( nStart == STG_EOF ) + nStart = nPage = nBgn; + } + else if( nNew < nOld ) + { + BOOL bAll = BOOL( nBytes == 0 ); + if( !Pos2Page( nBytes ) || !pFat->FreePages( nPage, bAll ) ) + return FALSE; + if( bAll ) + nStart = nPage = STG_EOF; + } + if( pEntry ) + { + // change the dir entry? + if( !nSize || !nBytes ) + pEntry->aEntry.SetLeaf( STG_DATA, nStart ); + pEntry->aEntry.SetSize( nBytes ); + pEntry->SetDirty(); + } + nSize = nBytes; + pFat->SetLimit( GetPages() ); + return TRUE; +} + +// Return the # of allocated pages + +INT32 StgStrm::GetPages() +{ + return ( nSize + nPageSize - 1 ) / nPageSize; +} + +//////////////////////////// class StgFATStrm ////////////////////////////// + +// The FAT stream class provides physical access to the master FAT. +// Since this access is implemented as a StgStrm, we can use the +// FAT allocator. + +StgFATStrm::StgFATStrm( StgIo& r ) : StgStrm( r ) +{ + pFat = new StgFAT( *this, TRUE ); + nSize = rIo.aHdr.GetFATSize() * nPageSize; +} + +BOOL StgFATStrm::Pos2Page( INT32 nBytePos ) +{ + // Values < 0 seek to the end + if( nBytePos < 0 || nBytePos >= nSize ) + nBytePos = nSize ? nSize - 1 : 0; + nPage = nBytePos / nPageSize; + nOffset = (short) ( nBytePos % nPageSize ); + nPos = nBytePos; + nPage = GetPage( (short) nPage, FALSE ); + return BOOL( nPage >= 0 ); +} + +// Retrieve the physical page for a given byte offset. +// Since Pos2Page() already has computed the physical offset, +// use the byte offset directly. + +StgPage* StgFATStrm::GetPhysPage( INT32 nBytePos, BOOL bForce ) +{ + return rIo.Get( nBytePos / ( nPageSize >> 2 ), bForce ); +} + +// Get the page number entry for the given page offset. + +INT32 StgFATStrm::GetPage( short nOff, BOOL bMake, USHORT *pnMasterAlloc ) +{ + if( pnMasterAlloc ) *pnMasterAlloc = 0; + if( nOff < rIo.aHdr.GetFAT1Size() ) + return rIo.aHdr.GetFATPage( nOff ); + INT32 nMaxPage = nSize >> 2; + nOff = nOff - rIo.aHdr.GetFAT1Size(); + // Anzahl der Masterpages, durch die wir iterieren muessen + USHORT nMasterCount = ( nPageSize >> 2 ) - 1; + USHORT nBlocks = nOff / nMasterCount; + // Offset in letzter Masterpage + nOff = nOff % nMasterCount; + + StgPage* pOldPage = 0; + StgPage* pMaster = 0; + INT32 nFAT = rIo.aHdr.GetFATChain(); + for( USHORT nCount = 0; nCount <= nBlocks; nCount++ ) + { + if( nFAT == STG_EOF || nFAT == STG_FREE ) + { + if( bMake ) + { + // create a new master page + nFAT = nMaxPage++; + pMaster = rIo.Copy( nFAT, STG_FREE ); + if ( pMaster ) + { + for( short k = 0; k < ( nPageSize >> 2 ); k++ ) + pMaster->SetPage( k, STG_FREE ); + // Verkettung herstellen + if( !pOldPage ) + rIo.aHdr.SetFATChain( nFAT ); + else + pOldPage->SetPage( nMasterCount, nFAT ); + if( nMaxPage >= rIo.GetPhysPages() ) + if( !rIo.SetSize( nMaxPage ) ) + return STG_EOF; + // mark the page as used + // Platz fuer Masterpage schaffen + if( !pnMasterAlloc ) // Selbst Platz schaffen + { + if( !Pos2Page( nFAT << 2 ) ) + return STG_EOF; + StgPage* pPg = rIo.Get( nPage, TRUE ); + if( !pPg ) + return STG_EOF; + pPg->SetPage( nOffset >> 2, STG_MASTER ); + } + else + (*pnMasterAlloc)++; + rIo.aHdr.SetMasters( nCount + 1 ); + pOldPage = pMaster; + } + } + } + else + { + pMaster = rIo.Get( nFAT, TRUE ); + if ( pMaster ) + { + nFAT = pMaster->GetPage( nMasterCount ); + pOldPage = pMaster; + } + } + } + if( pMaster ) + return pMaster->GetPage( nOff ); + rIo.SetError( SVSTREAM_GENERALERROR ); + return STG_EOF; +} + + +// Set the page number entry for the given page offset. + +BOOL StgFATStrm::SetPage( short nOff, INT32 nNewPage ) +{ + BOOL bRes = TRUE; + if( nOff < rIo.aHdr.GetFAT1Size() ) + rIo.aHdr.SetFATPage( nOff, nNewPage ); + else + { + nOff = nOff - rIo.aHdr.GetFAT1Size(); + // Anzahl der Masterpages, durch die wir iterieren muessen + USHORT nMasterCount = ( nPageSize >> 2 ) - 1; + USHORT nBlocks = nOff / nMasterCount; + // Offset in letzter Masterpage + nOff = nOff % nMasterCount; + + StgPage* pMaster = 0; + INT32 nFAT = rIo.aHdr.GetFATChain(); + for( USHORT nCount = 0; nCount <= nBlocks; nCount++ ) + { + if( nFAT == STG_EOF || nFAT == STG_FREE ) + { + pMaster = 0; + break; + } + pMaster = rIo.Get( nFAT, TRUE ); + if ( pMaster ) + nFAT = pMaster->GetPage( nMasterCount ); + } + if( pMaster ) + pMaster->SetPage( nOff, nNewPage ); + else + { + rIo.SetError( SVSTREAM_GENERALERROR ); + bRes = FALSE; + } + } + + // lock the page against access + if( bRes ) + { + Pos2Page( nNewPage << 2 ); + StgPage* pPg = rIo.Get( nPage, TRUE ); + if( pPg ) + pPg->SetPage( nOffset >> 2, STG_FAT ); + else + bRes = FALSE; + } + return bRes; +} + +BOOL StgFATStrm::SetSize( INT32 nBytes ) +{ + // Set the number of entries to a multiple of the page size + short nOld = (short) ( ( nSize + ( nPageSize - 1 ) ) / nPageSize ); + short nNew = (short) ( + ( nBytes + ( nPageSize - 1 ) ) / nPageSize ) ; + if( nNew < nOld ) + { + // release master pages + for( short i = nNew; i < nOld; i++ ) + SetPage( i, STG_FREE ); + } + else + { + while( nOld < nNew ) + { + // allocate master pages + // find a free master page slot + INT32 nPg = 0; + USHORT nMasterAlloc = 0; + nPg = GetPage( nOld, TRUE, &nMasterAlloc ); + if( nPg == STG_EOF ) + return FALSE; + // 4 Bytes have been used for Allocation of each MegaMasterPage + nBytes += nMasterAlloc << 2; + + // find a free page using the FAT allocator + INT32 n = 1; + INT32 nNewPage = pFat->FindBlock( n ); + if( nNewPage == STG_EOF ) + { + // no free pages found; create a new page + // Since all pages are allocated, extend + // the file size for the next page! + nNewPage = nSize >> 2; + // if a MegaMasterPage was created avoid taking + // the same Page + nNewPage += nMasterAlloc; + // adjust the file size if necessary + if( nNewPage >= rIo.GetPhysPages() ) + if( !rIo.SetSize( nNewPage + 1 ) ) + return FALSE; + } + // Set up the page with empty entries + StgPage* pPg = rIo.Copy( nNewPage, STG_FREE ); + if ( !pPg ) + return FALSE; + for( short j = 0; j < ( nPageSize >> 2 ); j++ ) + pPg->SetPage( j, STG_FREE ); + + // store the page number into the master FAT + // Set the size before so the correct FAT can be found + nSize = ( nOld + 1 ) * nPageSize; + SetPage( nOld, nNewPage ); + + // MegaMasterPages were created, mark it them as used + + UINT32 nMax = rIo.aHdr.GetMasters( ); + UINT32 nFAT = rIo.aHdr.GetFATChain(); + if( nMasterAlloc ) + for( USHORT nCount = 0; nCount < nMax; nCount++ ) + { + if( !Pos2Page( nFAT << 2 ) ) + return FALSE; + if( nMax - nCount <= nMasterAlloc ) + { + StgPage* piPg = rIo.Get( nPage, TRUE ); + if( !piPg ) + return FALSE; + piPg->SetPage( nOffset >> 2, STG_MASTER ); + } + StgPage* pPage = rIo.Get( nFAT, TRUE ); + if( !pPage ) return FALSE; + nFAT = pPage->GetPage( (nPageSize >> 2 ) - 1 ); + } + + nOld++; + // We have used up 4 bytes for the STG_FAT entry + nBytes += 4; + nNew = (short) ( + ( nBytes + ( nPageSize - 1 ) ) / nPageSize ); + } + } + nSize = nNew * nPageSize; + rIo.aHdr.SetFATSize( nNew ); + return TRUE; +} + +/////////////////////////// class StgDataStrm ////////////////////////////// + +// This class is a normal physical stream which can be initialized +// either with an existing dir entry or an existing FAT chain. +// The stream has a size increment which normally is 1, but which can be +// set to any value is you want the size to be incremented by certain values. + +StgDataStrm::StgDataStrm( StgIo& r, INT32 nBgn, INT32 nLen ) : StgStrm( r ) +{ + Init( nBgn, nLen ); +} + +StgDataStrm::StgDataStrm( StgIo& r, StgDirEntry* p ) : StgStrm( r ) +{ + pEntry = p; + Init( p->aEntry.GetLeaf( STG_DATA ), + p->aEntry.GetSize() ); +} + +void StgDataStrm::Init( INT32 nBgn, INT32 nLen ) +{ + pFat = new StgFAT( *rIo.pFAT, TRUE ); + nStart = nPage = nBgn; + nSize = nLen; + nIncr = 1; + nOffset = 0; + if( nLen < 0 ) + { + // determine the actual size of the stream by scanning + // the FAT chain and counting the # of pages allocated + nSize = 0; + INT32 nOldBgn = -1; + while( nBgn >= 0 && nBgn != nOldBgn ) + { + nOldBgn = nBgn; + nBgn = pFat->GetNextPage( nBgn ); + if( nBgn == nOldBgn ) + rIo.SetError( ERRCODE_IO_WRONGFORMAT ); + nSize += nPageSize; + } + } +} + +// Set the size of a physical stream. + +BOOL StgDataStrm::SetSize( INT32 nBytes ) +{ + nBytes = ( ( nBytes + nIncr - 1 ) / nIncr ) * nIncr; + INT32 nOldSz = nSize; + if( ( nOldSz != nBytes ) ) + { + if( !StgStrm::SetSize( nBytes ) ) + return FALSE; + INT32 nMaxPage = pFat->GetMaxPage(); + if( nMaxPage > rIo.GetPhysPages() ) + if( !rIo.SetSize( nMaxPage ) ) + return FALSE; + // If we only allocated one page or less, create this + // page in the cache for faster throughput. The current + // position is the former EOF point. + if( ( nSize - 1 ) / nPageSize - ( nOldSz - 1 ) / nPageSize == 1 ) + { + Pos2Page( nBytes ); + if( nPage >= 0 ) + rIo.Copy( nPage, STG_FREE ); + } + } + return TRUE; +} + +// Get the address of the data byte at a specified offset. +// If bForce = TRUE, a read of non-existent data causes +// a read fault. + +void* StgDataStrm::GetPtr( INT32 Pos, BOOL bForce, BOOL bDirty ) +{ + if( Pos2Page( Pos ) ) + { + StgPage* pPg = rIo.Get( nPage, bForce ); + if( pPg ) + { + pPg->SetOwner( pEntry ); + if( bDirty ) + pPg->SetDirty(); + return ((BYTE *)pPg->GetData()) + nOffset; + } + } + return NULL; +} + +// This could easily be adapted to a better algorithm by determining +// the amount of consecutable blocks before doing a read. The result +// is the number of bytes read. No error is generated on EOF. + +INT32 StgDataStrm::Read( void* pBuf, INT32 n ) +{ + if ( n < 0 ) + return 0; + + if( ( nPos + n ) > nSize ) + n = nSize - nPos; + INT32 nDone = 0; + while( n ) + { + short nBytes = nPageSize - nOffset; + short nRes; + StgPage* pPg; + if( (INT32) nBytes > n ) + nBytes = (short) n; + if( nBytes ) + { + void *p = (BYTE *) pBuf + nDone; + if( nBytes == nPageSize ) + { + pPg = rIo.Find( nPage ); + if( pPg ) + { + // data is present, so use the cached data + pPg->SetOwner( pEntry ); + memcpy( p, pPg->GetData(), nBytes ); + nRes = nBytes; + } + else + // do a direct (unbuffered) read + nRes = (short) rIo.Read( nPage, p, 1 ) * nPageSize; + } + else + { + // partial block read thru the cache. + pPg = rIo.Get( nPage, FALSE ); + if( !pPg ) + break; + pPg->SetOwner( pEntry ); + memcpy( p, (BYTE*)pPg->GetData() + nOffset, nBytes ); + nRes = nBytes; + } + nDone += nRes; + nPos += nRes; + n -= nRes; + nOffset = nOffset + nRes; + if( nRes != nBytes ) + break; // read error or EOF + } + // Switch to next page if necessary + if( nOffset >= nPageSize && !Pos2Page( nPos ) ) + break; + } + return nDone; +} + +INT32 StgDataStrm::Write( const void* pBuf, INT32 n ) +{ + INT32 nDone = 0; + if( ( nPos + n ) > nSize ) + { + INT32 nOld = nPos; + if( !SetSize( nPos + n ) ) + return FALSE; + Pos2Page( nOld ); + } + while( n ) + { + short nBytes = nPageSize - nOffset; + short nRes; + StgPage* pPg; + if( (INT32) nBytes > n ) + nBytes = (short) n; + if( nBytes ) + { + const void *p = (const BYTE *) pBuf + nDone; + if( nBytes == nPageSize ) + { + pPg = rIo.Find( nPage ); + if( pPg ) + { + // data is present, so use the cached data + pPg->SetOwner( pEntry ); + memcpy( pPg->GetData(), p, nBytes ); + pPg->SetDirty(); + nRes = nBytes; + } + else + // do a direct (unbuffered) write + nRes = (short) rIo.Write( nPage, (void*) p, 1 ) * nPageSize; + } + else + { + // partial block read thru the cache. + pPg = rIo.Get( nPage, FALSE ); + if( !pPg ) + break; + pPg->SetOwner( pEntry ); + memcpy( (BYTE*)pPg->GetData() + nOffset, p, nBytes ); + pPg->SetDirty(); + nRes = nBytes; + } + nDone += nRes; + nPos += nRes; + n -= nRes; + nOffset = nOffset + nRes; + if( nRes != nBytes ) + break; // read error + } + // Switch to next page if necessary + if( nOffset >= nPageSize && !Pos2Page( nPos ) ) + break; + } + return nDone; +} + +//////////////////////////// class StgSmallStream /////////////////////////// + +// The small stream class provides access to streams with a size < 4096 bytes. +// This stream is a StgStream containing small pages. The FAT for this stream +// is also a StgStream. The start of the FAT is in the header at DataRootPage, +// the stream itself is pointed to by the root entry (it holds start & size). + +StgSmallStrm::StgSmallStrm( StgIo& r, INT32 nBgn, INT32 nLen ) : StgStrm( r ) +{ + Init( nBgn, nLen ); +} + +StgSmallStrm::StgSmallStrm( StgIo& r, StgDirEntry* p ) : StgStrm( r ) +{ + pEntry = p; + Init( p->aEntry.GetLeaf( STG_DATA ), + p->aEntry.GetSize() ); +} + +void StgSmallStrm::Init( INT32 nBgn, INT32 nLen ) +{ + pFat = new StgFAT( *rIo.pDataFAT, FALSE ); + pData = rIo.pDataStrm; + nPageSize = rIo.GetDataPageSize(); + nStart = + nPage = nBgn; + nSize = nLen; +} + +// This could easily be adapted to a better algorithm by determining +// the amount of consecutable blocks before doing a read. The result +// is the number of bytes read. No error is generated on EOF. + +INT32 StgSmallStrm::Read( void* pBuf, INT32 n ) +{ + // We can safely assume that reads are not huge, since the + // small stream is likely to be < 64 KBytes. + if( ( nPos + n ) > nSize ) + n = nSize - nPos; + short nDone = 0; + while( n ) + { + short nBytes = nPageSize - nOffset; + if( (INT32) nBytes > n ) + nBytes = (short) n; + if( nBytes ) + { + if( !pData->Pos2Page( nPage * nPageSize + nOffset ) ) + break; + // all reading thru the stream + short nRes = (short) pData->Read( (BYTE*)pBuf + nDone, nBytes ); + nDone = nDone + nRes; + nPos += nRes; + n -= nRes; + nOffset = nOffset + nRes; + // read problem? + if( nRes != nBytes ) + break; + } + // Switch to next page if necessary + if( nOffset >= nPageSize && !Pos2Page( nPos ) ) + break; + } + return nDone; +} + +INT32 StgSmallStrm::Write( const void* pBuf, INT32 n ) +{ + // you can safely assume that reads are not huge, since the + // small stream is likely to be < 64 KBytes. + short nDone = 0; + if( ( nPos + n ) > nSize ) + { + INT32 nOld = nPos; + if( !SetSize( nPos + n ) ) + return FALSE; + Pos2Page( nOld ); + } + while( n ) + { + short nBytes = nPageSize - nOffset; + if( (INT32) nBytes > n ) + nBytes = (short) n; + if( nBytes ) + { + // all writing goes thru the stream + INT32 nDataPos = nPage * nPageSize + nOffset; + if( pData->GetSize() < ( nDataPos + nBytes ) ) + if( !pData->SetSize( nDataPos + nBytes ) ) + break; + if( !pData->Pos2Page( nDataPos ) ) + break; + short nRes = (short) pData->Write( (BYTE*)pBuf + nDone, nBytes ); + nDone = nDone + nRes; + nPos += nRes; + n -= nRes; + nOffset = nOffset + nRes; + // write problem? + if( nRes != nBytes ) + break; + } + // Switch to next page if necessary + if( nOffset >= nPageSize && !Pos2Page( nPos ) ) + break; + } + return nDone; +} + +/////////////////////////// class StgTmpStrm ///////////////////////////// + +// The temporary stream uses a memory stream if < 32K, otherwise a +// temporary file. + +#define THRESHOLD 32768L + +StgTmpStrm::StgTmpStrm( ULONG nInitSize ) + : SvMemoryStream( nInitSize > THRESHOLD + ? 16 + : ( nInitSize ? nInitSize : 16 ), 4096 ) +{ + pStrm = NULL; + // this calls FlushData, so all members should be set by this time + SetBufferSize( 0 ); + if( nInitSize > THRESHOLD ) + SetSize( nInitSize ); +} + +BOOL StgTmpStrm::Copy( StgTmpStrm& rSrc ) +{ + ULONG n = rSrc.GetSize(); + ULONG nCur = rSrc.Tell(); + SetSize( n ); + if( GetError() == SVSTREAM_OK ) + { + BYTE* p = new BYTE[ 4096 ]; + rSrc.Seek( 0L ); + Seek( 0L ); + while( n ) + { + ULONG nn = n; + if( nn > 4096 ) + nn = 4096; + if( rSrc.Read( p, nn ) != nn ) + break; + if( Write( p, nn ) != nn ) + break; + n -= nn; + } + delete [] p; + rSrc.Seek( nCur ); + Seek( nCur ); + return BOOL( n == 0 ); + } + else + return FALSE; +} + +StgTmpStrm::~StgTmpStrm() +{ + if( pStrm ) + { + pStrm->Close(); + osl::File::remove( aName ); + delete pStrm; + } +} + +ULONG StgTmpStrm::GetSize() const +{ + ULONG n; + if( pStrm ) + { + ULONG old = pStrm->Tell(); + n = pStrm->Seek( STREAM_SEEK_TO_END ); + pStrm->Seek( old ); + } + else + n = nEndOfData; + return n; +} + +void StgTmpStrm::SetSize( ULONG n ) +{ + if( pStrm ) + pStrm->SetStreamSize( n ); + else + { + if( n > THRESHOLD ) + { + aName = TempFile::CreateTempName(); + SvFileStream* s = new SvFileStream( aName, STREAM_READWRITE ); + ULONG nCur = Tell(); + ULONG i = nEndOfData; + if( i ) + { + BYTE* p = new BYTE[ 4096 ]; + Seek( 0L ); + while( i ) + { + ULONG nb = ( i > 4096 ) ? 4096 : i; + if( Read( p, nb ) == nb + && s->Write( p, nb ) == nb ) + i -= nb; + else + break; + } + delete [] p; + } + if( !i && n > nEndOfData ) + { + // We have to write one byte at the end of the file + // if the file is bigger than the memstream to see + // if it fits on disk + s->Seek( n - 1 ); + s->Write( &i, 1 ); + s->Flush(); + if( s->GetError() != SVSTREAM_OK ) + i = 1; + } + Seek( nCur ); + s->Seek( nCur ); + if( i ) + { + SetError( s->GetError() ); + delete s; + return; + } + pStrm = s; + // Shrink the memory to 16 bytes, which seems to be the minimum + ReAllocateMemory( - ( (long) nEndOfData - 16 ) ); + } + else + { + if( n > nEndOfData ) + { + ULONG nCur = Tell(); + Seek( nEndOfData - 1 ); + *this << (BYTE) 0; + Seek( nCur ); + } + else + nEndOfData = n; + } + } +} + +ULONG StgTmpStrm::GetData( void* pData, ULONG n ) +{ + if( pStrm ) + { + n = pStrm->Read( pData, n ); + SetError( pStrm->GetError() ); + return n; + } + else + return SvMemoryStream::GetData( (sal_Char *)pData, n ); +} + +ULONG StgTmpStrm::PutData( const void* pData, ULONG n ) +{ + UINT32 nCur = Tell(); + UINT32 nNew = nCur + n; + if( nNew > THRESHOLD && !pStrm ) + { + SetSize( nNew ); + if( GetError() != SVSTREAM_OK ) + return 0; + } + if( pStrm ) + { + nNew = pStrm->Write( pData, n ); + SetError( pStrm->GetError() ); + } + else + nNew = SvMemoryStream::PutData( (sal_Char*)pData, n ); + return nNew; +} + +ULONG StgTmpStrm::SeekPos( ULONG n ) +{ + if( n == STREAM_SEEK_TO_END ) + n = GetSize(); + if( n && n > THRESHOLD && !pStrm ) + { + SetSize( n ); + if( GetError() != SVSTREAM_OK ) + return Tell(); + else + return n; + } + else if( pStrm ) + { + n = pStrm->Seek( n ); + SetError( pStrm->GetError() ); + return n; + } + else + return SvMemoryStream::SeekPos( n ); +} + +void StgTmpStrm::FlushData() +{ + if( pStrm ) + { + pStrm->Flush(); + SetError( pStrm->GetError() ); + } + else + SvMemoryStream::FlushData(); +} + diff --git a/sot/source/sdstor/stgstrms.hxx b/sot/source/sdstor/stgstrms.hxx new file mode 100644 index 000000000000..9b09f51db43f --- /dev/null +++ b/sot/source/sdstor/stgstrms.hxx @@ -0,0 +1,170 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _STGSTRMS_HXX +#define _STGSTRMS_HXX + +#ifndef _TOOLS_STREAM_HXX +#include <tools/stream.hxx> +#endif + +class StgIo; +class StgStrm; +class StgPage; +class StgDirEntry; + +// The FAT class performs FAT operations on an underlying storage stream. +// This stream is either the physical FAT stream (bPhys == TRUE ) or a normal +// storage stream, which then holds the FAT for small data allocations. + +class StgFAT +{ // FAT allocator + StgStrm& rStrm; // underlying stream + INT32 nMaxPage; // highest page allocated so far + short nPageSize; // physical page size + short nEntries; // FAT entries per page + short nOffset; // current offset within page + INT32 nLimit; // search limit recommendation + BOOL bPhys; // TRUE: physical FAT + StgPage* GetPhysPage( INT32 nPage ); + BOOL MakeChain( INT32 nStart, INT32 nPages ); + BOOL InitNew( INT32 nPage1 ); +public: + StgFAT( StgStrm& rStrm, BOOL bMark ); + INT32 FindBlock( INT32& nPages ); + INT32 GetNextPage( INT32 nPg ); + INT32 AllocPages( INT32 nStart, INT32 nPages ); + BOOL FreePages( INT32 nStart, BOOL bAll ); + INT32 GetMaxPage() { return nMaxPage; } + void SetLimit( INT32 n ) { nLimit = n; } +}; + +// The base stream class provides basic functionality for seeking +// and accessing the data on a physical basis. It uses the built-in +// FAT class for the page allocations. + +class StgStrm { // base class for all streams +protected: + StgIo& rIo; // I/O system + StgFAT* pFat; // FAT stream for allocations + StgDirEntry* pEntry; // dir entry (for ownership) + INT32 nStart; // 1st data page + INT32 nSize; // stream size in bytes + INT32 nPos; // current byte position + INT32 nPage; // current logical page + short nOffset; // offset into current page + short nPageSize; // logical page size + BOOL Copy( INT32 nFrom, INT32 nBytes ); + StgStrm( StgIo& ); +public: + virtual ~StgStrm(); + StgIo& GetIo() { return rIo; } + INT32 GetPos() { return nPos; } + INT32 GetStart() { return nStart; } + INT32 GetSize() { return nSize; } + INT32 GetPage() { return nPage; } + short GetPageSize() { return nPageSize; } + INT32 GetPages(); + short GetOffset() { return nOffset;} + void SetEntry( StgDirEntry& ); + virtual BOOL SetSize( INT32 ); + virtual BOOL Pos2Page( INT32 nBytePos ); + virtual INT32 Read( void*, INT32 ) { return 0; } + virtual INT32 Write( const void*, INT32 ) { return 0; } + virtual StgPage* GetPhysPage( INT32 nBytePos, BOOL bForce = FALSE ); + virtual BOOL IsSmallStrm() { return FALSE; } +}; + +// The FAT stream class provides physical access to the master FAT. +// Since this access is implemented as a StgStrm, we can use the +// FAT allocator. + +class StgFATStrm : public StgStrm { // the master FAT stream + virtual BOOL Pos2Page( INT32 nBytePos ); + BOOL SetPage( short, INT32 ); +public: + StgFATStrm( StgIo& ); + virtual ~StgFATStrm() {} + using StgStrm::GetPage; + INT32 GetPage( short, BOOL, USHORT *pnMasterAlloc = 0); + virtual BOOL SetSize( INT32 ); + virtual StgPage* GetPhysPage( INT32 nBytePos, BOOL bForce = FALSE ); +}; + +// The stream has a size increment which normally is 1, but which can be +// set to any value is you want the size to be incremented by certain values. + +class StgDataStrm : public StgStrm // a physical data stream +{ + short nIncr; // size adjust increment + void Init( INT32 nBgn, INT32 nLen ); +public: + StgDataStrm( StgIo&, INT32 nBgn, INT32 nLen=-1 ); + StgDataStrm( StgIo&, StgDirEntry* ); + void* GetPtr( INT32 nPos, BOOL bForce, BOOL bDirty ); + void SetIncrement( short n ) { nIncr = n ; } + virtual BOOL SetSize( INT32 ); + virtual INT32 Read( void*, INT32 ); + virtual INT32 Write( const void*, INT32 ); +}; + +// The small stream class provides access to streams with a size < 4096 bytes. +// This stream is a StgStream containing small pages. The FAT for this stream +// is also a StgStream. The start of the FAT is in the header at DataRootPage, +// the stream itself is pointed to by the root entry (it holds start & size). + +class StgSmallStrm : public StgStrm // a logical data stream +{ + StgStrm* pData; // the data stream + void Init( INT32 nBgn, INT32 nLen ); +public: + StgSmallStrm( StgIo&, INT32 nBgn, INT32 nLen ); + StgSmallStrm( StgIo&, StgDirEntry* ); + virtual INT32 Read( void*, INT32 ); + virtual INT32 Write( const void*, INT32 ); + virtual BOOL IsSmallStrm() { return TRUE; } +}; + +class StgTmpStrm : public SvMemoryStream +{ + String aName; + SvFileStream* pStrm; + using SvMemoryStream::GetData; + virtual ULONG GetData( void* pData, ULONG nSize ); + virtual ULONG PutData( const void* pData, ULONG nSize ); + virtual ULONG SeekPos( ULONG nPos ); + virtual void FlushData(); + +public: + StgTmpStrm( ULONG=16 ); + ~StgTmpStrm(); + BOOL Copy( StgTmpStrm& ); + void SetSize( ULONG ); + ULONG GetSize() const; +}; + +#endif diff --git a/sot/source/sdstor/storage.cxx b/sot/source/sdstor/storage.cxx new file mode 100644 index 000000000000..136abb29a98e --- /dev/null +++ b/sot/source/sdstor/storage.cxx @@ -0,0 +1,1563 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sot.hxx" +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +#include <rtl/digest.h> +#include <osl/file.hxx> +#include <stg.hxx> +#include <storinfo.hxx> +#include <sot/storage.hxx> +#include <sot/formats.hxx> +#include <sot/exchange.hxx> +#include <unotools/ucbstreamhelper.hxx> +#ifndef _TOOLS_FSYS_HXX +#include <tools/fsys.hxx> +#endif +#include <tools/cachestr.hxx> +#include <tools/debug.hxx> +#include <tools/urlobj.hxx> +#include <unotools/localfilehelper.hxx> +#include <unotools/ucbhelper.hxx> +#include <comphelper/processfactory.hxx> + +#include "unostorageholder.hxx" + +using namespace ::com::sun::star; + +/************** class SotStorageStream ***********************************/ +class SotStorageStreamFactory : public SotFactory +{ +public: + TYPEINFO(); + SotStorageStreamFactory( const SvGlobalName & rName, + const String & rClassName, + CreateInstanceType pCreateFuncP ) + : SotFactory( rName, rClassName, pCreateFuncP ) + {} +}; +TYPEINIT1(SotStorageStreamFactory,SotFactory); + + +SO2_IMPL_BASIC_CLASS1_DLL(SotStorageStream,SotStorageStreamFactory,SotObject, + SvGlobalName( 0xd7deb420, 0xf902, 0x11d0, + 0xaa, 0xa1, 0x0, 0xa0, 0x24, 0x9d, 0x55, 0x90 ) ) +SO2_IMPL_INVARIANT(SotStorageStream) + + +void SotStorageStream::TestMemberObjRef( BOOL /*bFree*/ ) +{ +} + +#ifdef TEST_INVARIANT +void SotStorageStream::TestMemberInvariant( BOOL /*bPrint*/ ) +{ +} +#endif + +/************************************************************************ +|* SotStorageStream::SotStorageStream() +|* +|* Beschreibung +*************************************************************************/ +SvLockBytesRef MakeLockBytes_Impl( const String & rName, StreamMode nMode ) +{ + SvLockBytesRef xLB; + if( rName.Len() ) + { + SvStream * pFileStm = new SvFileStream( rName, nMode ); + xLB = new SvLockBytes( pFileStm, TRUE ); + } + else + { + SvStream * pCacheStm = new SvCacheStream(); + xLB = new SvLockBytes( pCacheStm, TRUE ); + } + return xLB; +} + +SotStorageStream::SotStorageStream( const String & rName, StreamMode nMode, + StorageMode + #ifdef DBG_UTIL + nStorageMode + #endif + ) + : SvStream( MakeLockBytes_Impl( rName, nMode ) ) + , pOwnStm( NULL ) +{ + if( nMode & STREAM_WRITE ) + bIsWritable = TRUE; + else + bIsWritable = FALSE; + + DBG_ASSERT( !nStorageMode,"StorageModes ignored" ); +} + +SotStorageStream::SotStorageStream( BaseStorageStream * pStm ) +{ + if( pStm ) + { + if( STREAM_WRITE & pStm->GetMode() ) + bIsWritable = TRUE; + else + bIsWritable = FALSE; + + pOwnStm = pStm; + SetError( pStm->GetError() ); + pStm->ResetError(); + } + else + { + pOwnStm = NULL; + bIsWritable = TRUE; + SetError( SVSTREAM_INVALID_PARAMETER ); + } +} + +SotStorageStream::SotStorageStream() + : pOwnStm( NULL ) +{ + // ??? wenn Init virtuell ist, entsprechen setzen + bIsWritable = TRUE; +} + +/************************************************************************ +|* SotStorageStream::~SotStorageStream() +|* +|* Beschreibung +*************************************************************************/ +SotStorageStream::~SotStorageStream() +{ + Flush(); //SetBufferSize(0); + delete pOwnStm; +} + +/************************************************************************* +|* SotStorageStream::SyncSvStream() +|* +|* Beschreibung: Der SvStream wird auf den Zustand des Standard-Streams +|* gesetzt. Der Puffer des SvStreams wird weggeworfen. +*************************************************************************/ +void SotStorageStream::SyncSvStream() +{ + ULONG nPos = 0; + if( pOwnStm ) + { + pOwnStm->Flush(); + nPos = pOwnStm->Tell(); + SetError( pOwnStm->GetError() ); + SvStream::SyncSvStream( nPos ); + } +} + +/************************************************************************* +|* SotStorageStream::ResetError() +|* +|* Beschreibung +*************************************************************************/ +void SotStorageStream::ResetError() +{ + SvStream::ResetError(); + if( pOwnStm ) + pOwnStm->ResetError(); +} + +/************************************************************************* +|* SotStorageStream::GetData() +|* +|* Beschreibung +*************************************************************************/ +ULONG SotStorageStream::GetData( void* pData, ULONG nSize ) +{ + ULONG nRet = 0; + + if( pOwnStm ) + { + nRet = pOwnStm->Read( pData, nSize ); + SetError( pOwnStm->GetError() ); + } + else + nRet = SvStream::GetData( (sal_Char *)pData, nSize ); + return nRet; +} + +/************************************************************************* +|* SotStorageStream::PutData() +|* +|* Beschreibung +*************************************************************************/ +ULONG SotStorageStream::PutData( const void* pData, ULONG nSize ) +{ + ULONG nRet = 0; + + if( pOwnStm ) + { + nRet = pOwnStm->Write( pData, nSize ); + SetError( pOwnStm->GetError() ); + } + else + nRet = SvStream::PutData( (sal_Char *)pData, nSize ); + return nRet; +} + +/************************************************************************* +|* SotStorageStream::SeekPos() +|* +|* Beschreibung +*************************************************************************/ +ULONG SotStorageStream::SeekPos( ULONG nPos ) +{ + ULONG nRet = 0; + + if( pOwnStm ) + { + nRet = pOwnStm->Seek( nPos ); + SetError( pOwnStm->GetError() ); + } + else + nRet = SvStream::SeekPos( nPos ); + return nRet; +} + +/************************************************************************* +|* SotStorageStream::Flush() +|* +|* Beschreibung +*************************************************************************/ +void SotStorageStream::FlushData() +{ + if( pOwnStm ) + { + pOwnStm->Flush(); + SetError( pOwnStm->GetError() ); + } + else + SvStream::FlushData(); +} + +/************************************************************************* +|* SotStorageStream::SetSize() +|* +|* Beschreibung +*************************************************************************/ +void SotStorageStream::SetSize( ULONG nNewSize ) +{ + ULONG nPos = Tell(); + if( pOwnStm ) + { + pOwnStm->SetSize( nNewSize ); + SetError( pOwnStm->GetError() ); + } + else + SvStream::SetSize( nNewSize ); + + if( nNewSize < nPos ) + // ans Ende setzen + Seek( nNewSize ); + + //return GetError() == SVSTREAM_OK; +} + +/************************************************************************* +|* +|* SotStorageStream::GetSize() +|* +|* Beschreibung +|* +*************************************************************************/ +UINT32 SotStorageStream::GetSize() const +{ + ULONG nPos = Tell(); + ((SotStorageStream *)this)->Seek( STREAM_SEEK_TO_END ); + ULONG nSize = Tell(); + ((SotStorageStream *)this)->Seek( nPos ); + return nSize; +} + +/************************************************************************* +|* SotStorageStream::CopyTo() +|* +|* Beschreibung +*************************************************************************/ +BOOL SotStorageStream::CopyTo( SotStorageStream * pDestStm ) +{ + Flush(); // alle Daten schreiben + pDestStm->ClearBuffer(); + if( !pOwnStm || !pDestStm->pOwnStm ) + { // Wenn Ole2 oder nicht nur eigene StorageStreams + + ULONG nPos = Tell(); // Position merken + Seek( 0L ); + pDestStm->SetSize( 0 ); // Ziel-Stream leeren + + void * pMem = new BYTE[ 8192 ]; + ULONG nRead; + while( 0 != (nRead = Read( pMem, 8192 )) ) + { + if( nRead != pDestStm->Write( pMem, nRead ) ) + { + SetError( SVSTREAM_GENERALERROR ); + break; + } + } + delete [] static_cast<BYTE*>(pMem); + // Position setzen + pDestStm->Seek( nPos ); + Seek( nPos ); + } + else + { + /* + // Kopieren + nErr = pObjI->CopyTo( pDestStm->pObjI, uSize, NULL, &uWrite ); + if( SUCCEEDED( nErr ) ) + { + // Ziel-Streamzeiger steht hinter den Daten + // SvSeek abgleichen + pDestStm->Seek( uWrite.LowPart ); + } + else if( GetScode( nErr ) == E_NOTIMPL ) + { // Eines Tages werden alle MS... ?!# + */ + pOwnStm->CopyTo( pDestStm->pOwnStm ); + SetError( pOwnStm->GetError() ); + } + return GetError() == SVSTREAM_OK; +} + +/************************************************************************* +|* SotStorageStream::Commit() +|* SotStorageStream::Revert() +|* +|* Beschreibung +*************************************************************************/ +BOOL SotStorageStream::Commit() +{ + if( pOwnStm ) + { + pOwnStm->Flush(); + if( pOwnStm->GetError() == SVSTREAM_OK ) + pOwnStm->Commit(); + SetError( pOwnStm->GetError() ); + } + return GetError() == SVSTREAM_OK; +} + +BOOL SotStorageStream::Revert() +{ + if( !pOwnStm ) + { + pOwnStm->Revert(); + SetError( pOwnStm->GetError() ); + } + return GetError() == SVSTREAM_OK; +} + +BOOL SotStorageStream::SetProperty( const String& rName, const ::com::sun::star::uno::Any& rValue ) +{ + UCBStorageStream* pStg = PTR_CAST( UCBStorageStream, pOwnStm ); + if ( pStg ) + { + return pStg->SetProperty( rName, rValue ); + } + else + { + DBG_ERROR("Not implemented!"); + return FALSE; + } +} + +BOOL SotStorageStream::GetProperty( const String& rName, ::com::sun::star::uno::Any& rValue ) +{ + UCBStorageStream* pStg = PTR_CAST( UCBStorageStream, pOwnStm ); + if ( pStg ) + { + return pStg->GetProperty( rName, rValue ); + } + else + { + DBG_ERROR("Not implemented!"); + return FALSE; + } +} + +::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SotStorageStream::GetXInputStream() const +{ + UCBStorageStream* pStg = PTR_CAST( UCBStorageStream, pOwnStm ); + if ( pStg ) + { + return pStg->GetXInputStream(); + } + else + { + DBG_ERROR("Not implemented!"); + return ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >(); + } +} + + + +/************** class SotStorage ****************************************** +*************************************************************************/ +class SotStorageFactory : public SotFactory +{ +public: + TYPEINFO(); + SotStorageFactory( const SvGlobalName & rName, + const String & rClassName, + CreateInstanceType pCreateFuncP ) + : SotFactory( rName, rClassName, pCreateFuncP ) + {} +}; +TYPEINIT1(SotStorageFactory,SotFactory); + + +SO2_IMPL_BASIC_CLASS1_DLL(SotStorage,SotStorageFactory,SotObject, + SvGlobalName( 0x980ce7e0, 0xf905, 0x11d0, + 0xaa, 0xa1, 0x0, 0xa0, 0x24, 0x9d, 0x55, 0x90 ) ) +SO2_IMPL_INVARIANT(SotStorage) + + +/************************************************************************ +|* +|* SotStorage::Tes*() +|* +|* Beschreibung +*************************************************************************/ +void SotStorage::TestMemberObjRef( BOOL /*bFree*/ ) +{ +} + +#ifdef TEST_INVARIANT +void SotStorage::TestMemberInvariant( BOOL /*bPrint*/ ) +{ +} +#endif + +/************************************************************************ +|* +|* SotStorage::SotStorage() +|* +|* Beschreibung Es muss ein I... Objekt an SvObject uebergeben +|* werden, da es sonst selbst ein IUnknown anlegt und +|* festlegt, dass alle weiteren I... Objekte mit +|* delete zerstoert werden (Owner() == TRUE). +|* Es werden aber nur IStorage Objekte benutzt und nicht +|* selbst implementiert, deshalb wird so getan, als ob +|* das IStorage Objekt von aussen kam und es wird mit +|* Release() freigegeben. +|* Die CreateStorage Methoden werden benoetigt, um +|* ein IStorage Objekt vor dem Aufruf von SvObject +|* zu erzeugen (Own, !Own automatik). +|* Hat CreateStorage ein Objekt erzeugt, dann wurde +|* der RefCounter schon um 1 erhoet. +|* Die Uebergabe erfolgt in pStorageCTor. Die Variable +|* ist NULL, wenn es nicht geklappt hat. +|* Ersterstellung MM 23.06.94 +|* Letzte Aenderung MM 23.06.94 +|* +*************************************************************************/ +#define INIT_SotStorage() \ + : m_pOwnStg( NULL ) \ + , m_pStorStm( NULL ) \ + , m_nError( SVSTREAM_OK ) \ + , m_bIsRoot( FALSE ) \ + , m_bDelStm( FALSE ) \ + , m_nVersion( SOFFICE_FILEFORMAT_CURRENT ) + +SotStorage::SotStorage() + INIT_SotStorage() +{ + // ??? What's this ??? +} + +#define ERASEMASK ( STREAM_TRUNC | STREAM_WRITE | STREAM_SHARE_DENYALL ) +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/ucb/XCommandEnvironment.hpp> +#include <ucbhelper/content.hxx> + +SotStorage::SotStorage( const ::ucbhelper::Content& rContent, const String & rName, StreamMode nMode, StorageMode nStorageMode ) + INIT_SotStorage() +{ + m_aName = rName; // Namen merken + m_pOwnStg = new UCBStorage( rContent, m_aName, nMode, (nStorageMode & STORAGE_TRANSACTED) ? FALSE : TRUE ); + + SetError( m_pOwnStg->GetError() ); + + if ( IsOLEStorage() ) + m_nVersion = SOFFICE_FILEFORMAT_50; + + SignAsRoot( m_pOwnStg->IsRoot() ); +} + +SotStorage::SotStorage( const String & rName, StreamMode nMode, StorageMode nStorageMode ) + INIT_SotStorage() +{ + m_aName = rName; // Namen merken + CreateStorage( TRUE, nMode, nStorageMode ); + if ( IsOLEStorage() ) + m_nVersion = SOFFICE_FILEFORMAT_50; +} + +void SotStorage::CreateStorage( BOOL bForceUCBStorage, StreamMode nMode, StorageMode nStorageMode ) +{ + DBG_ASSERT( !m_pStorStm && !m_pOwnStg, "Use only in ctor!" ); + if( m_aName.Len() ) + { + // named storage + if( ( ( nMode & ERASEMASK ) == ERASEMASK ) ) + ::utl::UCBContentHelper::Kill( m_aName ); + + INetURLObject aObj( m_aName ); + if ( aObj.GetProtocol() == INET_PROT_NOT_VALID ) + { + String aURL; + ::utl::LocalFileHelper::ConvertPhysicalNameToURL( m_aName, aURL ); + aObj.SetURL( aURL ); + m_aName = aObj.GetMainURL( INetURLObject::NO_DECODE ); + } + + // a new unpacked storage should be created + if ( nStorageMode == STORAGE_CREATE_UNPACKED ) + { + // don't open stream readwrite, content provider may not support this ! + String aURL = UCBStorage::CreateLinkFile( m_aName ); + if ( aURL.Len() ) + { + ::ucbhelper::Content aContent( aURL, ::com::sun::star::uno::Reference < ::com::sun::star::ucb::XCommandEnvironment >() ); + m_pOwnStg = new UCBStorage( aContent, aURL, nMode, FALSE ); + } + else + { + m_pOwnStg = new Storage( m_aName, nMode, (nStorageMode & STORAGE_TRANSACTED) ? FALSE : TRUE ); + SetError( ERRCODE_IO_NOTSUPPORTED ); + } + } + else + { + // check the stream + m_pStorStm = ::utl::UcbStreamHelper::CreateStream( m_aName, nMode ); + if ( m_pStorStm && m_pStorStm->GetError() ) + DELETEZ( m_pStorStm ); + + if ( m_pStorStm ) + { + // try as UCBStorage, next try as OLEStorage + BOOL bIsUCBStorage = UCBStorage::IsStorageFile( m_pStorStm ); + if ( !bIsUCBStorage && bForceUCBStorage ) + // if UCBStorage has priority, it should not be used only if it is really an OLEStorage + bIsUCBStorage = !Storage::IsStorageFile( m_pStorStm ); + + if ( bIsUCBStorage ) + { + if ( UCBStorage::GetLinkedFile( *m_pStorStm ).Len() ) + { + // detect special unpacked storages + m_pOwnStg = new UCBStorage( *m_pStorStm, (nStorageMode & STORAGE_TRANSACTED) ? FALSE : TRUE ); + m_bDelStm = TRUE; + } + else + { + // detect special disk spanned storages + if ( UCBStorage::IsDiskSpannedFile( m_pStorStm ) ) + nMode |= STORAGE_DISKSPANNED_MODE; + + // UCBStorage always works directly on the UCB content, so discard the stream first + DELETEZ( m_pStorStm ); + m_pOwnStg = new UCBStorage( m_aName, nMode, (nStorageMode & STORAGE_TRANSACTED) ? FALSE : TRUE ); + } + } + else + { + // OLEStorage can be opened with a stream + m_pOwnStg = new Storage( *m_pStorStm, (nStorageMode & STORAGE_TRANSACTED) ? FALSE : TRUE ); + m_bDelStm = TRUE; + } + } + else if ( bForceUCBStorage ) + { + m_pOwnStg = new UCBStorage( m_aName, nMode, (nStorageMode & STORAGE_TRANSACTED) ? FALSE : TRUE ); + SetError( ERRCODE_IO_NOTSUPPORTED ); + } + else + { + m_pOwnStg = new Storage( m_aName, nMode, (nStorageMode & STORAGE_TRANSACTED) ? FALSE : TRUE ); + SetError( ERRCODE_IO_NOTSUPPORTED ); + } + } + } + else + { + // temporary storage + if ( bForceUCBStorage ) + m_pOwnStg = new UCBStorage( m_aName, nMode, (nStorageMode & STORAGE_TRANSACTED) ? FALSE : TRUE ); + else + m_pOwnStg = new Storage( m_aName, nMode, (nStorageMode & STORAGE_TRANSACTED) ? FALSE : TRUE ); + m_aName = m_pOwnStg->GetName(); + } + + SetError( m_pOwnStg->GetError() ); + + SignAsRoot( m_pOwnStg->IsRoot() ); +} + +SotStorage::SotStorage( BOOL bUCBStorage, const String & rName, StreamMode nMode, StorageMode nStorageMode ) + INIT_SotStorage() +{ + m_aName = rName; + CreateStorage( bUCBStorage, nMode, nStorageMode ); + if ( IsOLEStorage() ) + m_nVersion = SOFFICE_FILEFORMAT_50; +} + +SotStorage::SotStorage( BaseStorage * pStor ) + INIT_SotStorage() +{ + if ( pStor ) + { + m_aName = pStor->GetName(); // Namen merken + SignAsRoot( pStor->IsRoot() ); + SetError( pStor->GetError() ); + } + + m_pOwnStg = pStor; + ULONG nErr = m_pOwnStg ? m_pOwnStg->GetError() : SVSTREAM_CANNOT_MAKE; + SetError( nErr ); + if ( IsOLEStorage() ) + m_nVersion = SOFFICE_FILEFORMAT_50; +} + +SotStorage::SotStorage( BOOL bUCBStorage, SvStream & rStm ) + INIT_SotStorage() +{ + SetError( rStm.GetError() ); + + // try as UCBStorage, next try as OLEStorage + if ( UCBStorage::IsStorageFile( &rStm ) || bUCBStorage ) + m_pOwnStg = new UCBStorage( rStm, FALSE ); + else + m_pOwnStg = new Storage( rStm, FALSE ); + + SetError( m_pOwnStg->GetError() ); + + if ( IsOLEStorage() ) + m_nVersion = SOFFICE_FILEFORMAT_50; + + SignAsRoot( m_pOwnStg->IsRoot() ); +} + +SotStorage::SotStorage( SvStream & rStm ) + INIT_SotStorage() +{ + SetError( rStm.GetError() ); + + // try as UCBStorage, next try as OLEStorage + if ( UCBStorage::IsStorageFile( &rStm ) ) + m_pOwnStg = new UCBStorage( rStm, FALSE ); + else + m_pOwnStg = new Storage( rStm, FALSE ); + + SetError( m_pOwnStg->GetError() ); + + if ( IsOLEStorage() ) + m_nVersion = SOFFICE_FILEFORMAT_50; + + SignAsRoot( m_pOwnStg->IsRoot() ); +} + +SotStorage::SotStorage( SvStream * pStm, BOOL bDelete ) + INIT_SotStorage() +{ + SetError( pStm->GetError() ); + + // try as UCBStorage, next try as OLEStorage + if ( UCBStorage::IsStorageFile( pStm ) ) + m_pOwnStg = new UCBStorage( *pStm, FALSE ); + else + m_pOwnStg = new Storage( *pStm, FALSE ); + + SetError( m_pOwnStg->GetError() ); + + m_pStorStm = pStm; + m_bDelStm = bDelete; + if ( IsOLEStorage() ) + m_nVersion = SOFFICE_FILEFORMAT_50; + + SignAsRoot( m_pOwnStg->IsRoot() ); +} + +/************************************************************************* +|* SotStorage::~SotStorage() +|* +|* Beschreibung +*************************************************************************/ +SotStorage::~SotStorage() +{ + delete m_pOwnStg; + if( m_bDelStm ) + delete m_pStorStm; +} + +/************************************************************************* +|* SotStorage::RemoveUNOStorageHolder() +|* +|* Beschreibung +*************************************************************************/ +void SotStorage::RemoveUNOStorageHolder( UNOStorageHolder* pHolder ) +{ + UCBStorage* pStg = PTR_CAST( UCBStorage, m_pOwnStg ); + if ( pStg ) + { + pStg->GetUNOStorageHolderList()->remove( pHolder ); + pHolder->release(); + } + else + { + DBG_ERROR("Not implemented!"); + } +} + +/************************************************************************* +|* SotStorage::GetUNOAPIDuplicate() +|* +|* Beschreibung +*************************************************************************/ +uno::Reference< embed::XStorage > SotStorage::GetUNOAPIDuplicate( const String& rEleName, sal_Int32 nUNOStorageMode ) +{ + // after we create a duplicate we will register wrapper + // for storage messages, the wrapper will control the real storage + // the real storage will be able to ask the duplicate to dispose if it's parent is disposed + + uno::Reference< embed::XStorage > xResult; + + UCBStorage* pStg = PTR_CAST( UCBStorage, m_pOwnStg ); + if ( !pStg ) + return xResult; + + UNOStorageHolderList* pUNOStorageHolderList = pStg->GetUNOStorageHolderList(); + if ( !pUNOStorageHolderList ) + return xResult; + + for ( UNOStorageHolderList::iterator aIter = pUNOStorageHolderList->begin(); + aIter != pUNOStorageHolderList->end(); aIter++ ) + if ( (*aIter) && (*aIter)->GetStorageName().Equals( rEleName ) ) + { + // the storage is already in use + return xResult; + } + + if ( IsStream( rEleName ) ) + return xResult; + + if ( GetError() == ERRCODE_NONE ) + { + StreamMode nMode = ( ( nUNOStorageMode & embed::ElementModes::WRITE ) == embed::ElementModes::WRITE ) ? + STREAM_WRITE : ( STREAM_READ | STREAM_NOCREATE ); + if ( nUNOStorageMode & embed::ElementModes::NOCREATE ) + nMode |= STREAM_NOCREATE; + + sal_Bool bStorageReady = !IsStorage( rEleName ); + SotStorageRef pChildStorage = OpenUCBStorage( rEleName, nMode, STORAGE_TRANSACTED ); + if ( pChildStorage->GetError() == ERRCODE_NONE && pChildStorage->m_pOwnStg ) + { + ::utl::TempFile* pTempFile = new ::utl::TempFile(); + if ( pTempFile->GetURL().Len() ) + { + if ( !bStorageReady ) + { + UCBStorage* pChildUCBStg = PTR_CAST( UCBStorage, pChildStorage->m_pOwnStg ); + if ( pChildUCBStg ) + { + UCBStorage* pTempStorage = new UCBStorage( pTempFile->GetURL(), STREAM_WRITE, FALSE, TRUE ); + if ( pTempStorage ) + { + pChildUCBStg->CopyTo( pTempStorage ); + + // CopyTo does not transport unknown media type + // just workaround it + uno::Any aMediaType; + + if ( pChildUCBStg->GetProperty( + ::rtl::OUString::createFromAscii( "MediaType" ), aMediaType ) ) + pTempStorage->SetProperty( ::rtl::OUString::createFromAscii( "MediaType" ), aMediaType ); + + bStorageReady = !pChildUCBStg->GetError() && !pTempStorage->GetError() + && pTempStorage->Commit(); + + delete ((BaseStorage*)pTempStorage); + pTempStorage = NULL; + } + } + + OSL_ENSURE( bStorageReady, "Problem on storage copy!\n" ); + } + + if ( bStorageReady ) + { + try { + uno::Reference< lang::XSingleServiceFactory > xStorageFactory( + ::comphelper::getProcessServiceFactory()->createInstance( + ::rtl::OUString::createFromAscii( "com.sun.star.embed.StorageFactory" ) ), + uno::UNO_QUERY ); + + OSL_ENSURE( xStorageFactory.is(), "Can't create storage factory!\n" ); + if ( xStorageFactory.is() ) + { + uno::Sequence< uno::Any > aArg( 2 ); + aArg[0] <<= ::rtl::OUString( pTempFile->GetURL() ); + aArg[1] <<= nUNOStorageMode; + uno::Reference< embed::XStorage > xDuplStorage( + xStorageFactory->createInstanceWithArguments( aArg ), + uno::UNO_QUERY ); + + OSL_ENSURE( xDuplStorage.is(), "Can't open storage!\n" ); + if ( xDuplStorage.is() ) + { + UNOStorageHolder* pHolder = + new UNOStorageHolder( *this, *pChildStorage, xDuplStorage, pTempFile ); + pHolder->acquire(); + pTempFile = NULL; + pUNOStorageHolderList->push_back( pHolder ); + xResult = xDuplStorage; + } + } + } + catch( uno::Exception& e ) + { + (void)e; + OSL_ENSURE( sal_False, ::rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ) ); + } + } + } + + if ( pTempFile != NULL ) + delete pTempFile; + } + else + SetError( pChildStorage->GetError() ); + } + + return xResult; +} + +/************************************************************************* +|* SotStorage::CreateMemoryStream() +|* +|* Beschreibung +*************************************************************************/ +SvMemoryStream * SotStorage::CreateMemoryStream() +{ + SvMemoryStream * pStm = NULL; + pStm = new SvMemoryStream( 0x8000, 0x8000 ); + SotStorageRef aStg = new SotStorage( *pStm ); + if( CopyTo( aStg ) ) + aStg->Commit(); + else + { + aStg.Clear(); // Storage vorher freigeben + delete pStm; + pStm = NULL; + } + return pStm; +} + +/************************************************************************* +|* SotStorage::GetStorage() +|* +|* Beschreibung +*************************************************************************/ +BOOL SotStorage::IsStorageFile( const String & rFileName ) +{ + String aName( rFileName ); + INetURLObject aObj( aName ); + if ( aObj.GetProtocol() == INET_PROT_NOT_VALID ) + { + String aURL; + ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aURL ); + aObj.SetURL( aURL ); + aName = aObj.GetMainURL( INetURLObject::NO_DECODE ); + } + + SvStream * pStm = ::utl::UcbStreamHelper::CreateStream( aName, STREAM_STD_READ ); + BOOL bRet = SotStorage::IsStorageFile( pStm ); + delete pStm; + return bRet; +} + +BOOL SotStorage::IsStorageFile( SvStream* pStream ) +{ + /** code for new storages must come first! **/ + if ( pStream ) + { + long nPos = pStream->Tell(); + BOOL bRet = UCBStorage::IsStorageFile( pStream ); + if ( !bRet ) + bRet = Storage::IsStorageFile( pStream ); + pStream->Seek( nPos ); + return bRet; + } + else + return FALSE; +} +/************************************************************************* +|* SotStorage::GetStorage() +|* +|* Beschreibung +*************************************************************************/ +const String & SotStorage::GetName() const +{ + if( !m_aName.Len() ) + { + DBG_ASSERT( Owner(), "must be owner" ); + if( m_pOwnStg ) + ((SotStorage *)this)->m_aName = m_pOwnStg->GetName(); + } + return m_aName; +} + +void SotStorage::SetName( const String& rName ) +{ + // This method is necessary because most storages will not be opened with a FileName, but an external stream instead + // This stream is a stream opened by a UCP and so aName is only used as a transport for all client code of the SotStorage + // class that depends on the fact that a root storage has a name + DBG_ASSERT( !GetName().Len(), "SetName() must not be called when the storage already has a name!" ); + m_aName = rName; +} + +/************************************************************************* +|* SotStorage::ResetError() +|* +|* Beschreibung +*************************************************************************/ +void SotStorage::ResetError() +{ + m_nError = SVSTREAM_OK; + if( m_pOwnStg ) + m_pOwnStg->ResetError(); +} + +/************************************************************************* +|* SotStorage::SetClass() +|* SotStorage::SetConvertClass() +|* +|* Beschreibung +*************************************************************************/ +void SotStorage::SetClass( const SvGlobalName & rName, + ULONG nOriginalClipFormat, + const String & rUserTypeName ) +{ + DBG_ASSERT( Owner(), "must be owner" ); + if( m_pOwnStg ) + m_pOwnStg->SetClass( rName, nOriginalClipFormat, rUserTypeName ); + else + SetError( SVSTREAM_GENERALERROR ); +} + +void SotStorage::SetConvertClass( const SvGlobalName & rName, + ULONG nOriginalClipFormat, + const String & rUserTypeName ) +{ + DBG_ASSERT( Owner(), "must be owner" ); + if( m_pOwnStg ) + m_pOwnStg->SetConvertClass( rName, nOriginalClipFormat, rUserTypeName ); + else + SetError( SVSTREAM_GENERALERROR ); +} + +/************************************************************************* +|* SotStorage::GetClassName() +|* SotStorage::GetFormat() +|* SotStorage::GetUserName() +|* SotStorage::ShouldConvert() +|* +|* Beschreibung +*************************************************************************/ +SvGlobalName SotStorage::GetClassName() +{ + SvGlobalName aGN; + DBG_ASSERT( Owner(), "must be owner" ); + if( m_pOwnStg ) + aGN = m_pOwnStg->GetClassName(); + else + SetError( SVSTREAM_GENERALERROR ); + return aGN; +} + +ULONG SotStorage::GetFormat() +{ + ULONG nFormat = 0; + DBG_ASSERT( Owner(), "must be owner" ); + if( m_pOwnStg ) + nFormat = m_pOwnStg->GetFormat(); + else + SetError( SVSTREAM_GENERALERROR ); + return nFormat; +} + +String SotStorage::GetUserName() +{ + String aName; + DBG_ASSERT( Owner(), "must be owner" ); + if( m_pOwnStg ) + aName = m_pOwnStg->GetUserName(); + else + SetError( SVSTREAM_GENERALERROR ); + return aName; +} + +BOOL SotStorage::ShouldConvert() +{ + DBG_ASSERT( Owner(), "must be owner" ); + if( m_pOwnStg ) + return m_pOwnStg->ShouldConvert(); + else + SetError( SVSTREAM_GENERALERROR ); + return FALSE; +} + +/************************************************************************* +|* SotStorage::FillInfoList() +|* +|* Beschreibung +*************************************************************************/ +void SotStorage::FillInfoList( SvStorageInfoList * pFillList ) const +{ + DBG_ASSERT( Owner(), "must be owner" ); + if( m_pOwnStg ) + m_pOwnStg->FillInfoList( pFillList ); +} + +/************************************************************************* +|* SotStorage::CopyTo() +|* +|* Beschreibung +*************************************************************************/ +BOOL SotStorage::CopyTo( SotStorage * pDestStg ) +{ + DBG_ASSERT( Owner(), "must be owner" ); + DBG_ASSERT( pDestStg->Owner(), "must be owner" ); + if( m_pOwnStg && pDestStg->m_pOwnStg ) + { + m_pOwnStg->CopyTo( pDestStg->m_pOwnStg ); + SetError( m_pOwnStg->GetError() ); + pDestStg->m_aKey = m_aKey; + pDestStg->m_nVersion = m_nVersion; + } + else + SetError( SVSTREAM_GENERALERROR ); + return SVSTREAM_OK == GetError(); +} + +/************************************************************************* +|* SotStorage::Commit() +|* +|* Beschreibung +*************************************************************************/ +BOOL SotStorage::Commit() +{ + DBG_ASSERT( Owner(), "must be owner" ); + if( m_pOwnStg ) + { + if( !m_pOwnStg->Commit() ) + SetError( m_pOwnStg->GetError() ); + } + else + SetError( SVSTREAM_GENERALERROR ); + return SVSTREAM_OK == GetError(); +} + +/************************************************************************* +|* SotStorage::Revert() +|* +|* Beschreibung +*************************************************************************/ +BOOL SotStorage::Revert() +{ + DBG_ASSERT( Owner(), "must be owner" ); + if( m_pOwnStg ) + { + if( !m_pOwnStg->Revert() ) + SetError( m_pOwnStg->GetError() ); + } + else + SetError( SVSTREAM_GENERALERROR ); + return SVSTREAM_OK == GetError(); +} + +/************************************************************************* +|* SotStorage::OpenStream() +|* +|* Beschreibung +*************************************************************************/ +SotStorageStream * SotStorage::OpenEncryptedSotStream( const String & rEleName, const ByteString& rKey, + StreamMode nMode, + StorageMode nStorageMode ) +{ + DBG_ASSERT( !nStorageMode, "StorageModes ignored" ); + SotStorageStream * pStm = NULL; + DBG_ASSERT( Owner(), "must be owner" ); + if( m_pOwnStg ) + { + // volle Ole-Patches einschalten + // egal was kommt, nur exclusiv gestattet + nMode |= STREAM_SHARE_DENYALL; + ErrCode nE = m_pOwnStg->GetError(); + BaseStorageStream* p = m_pOwnStg->OpenStream( rEleName, nMode, + (nStorageMode & STORAGE_TRANSACTED) ? FALSE : TRUE, &rKey ); + pStm = new SotStorageStream( p ); + + if( !nE ) + m_pOwnStg->ResetError(); // kein Fehler setzen + if( nMode & STREAM_TRUNC ) + pStm->SetSize( 0 ); + } + else + SetError( SVSTREAM_GENERALERROR ); + return pStm; +} + +SotStorageStream * SotStorage::OpenSotStream( const String & rEleName, + StreamMode nMode, + StorageMode nStorageMode ) +{ + DBG_ASSERT( !nStorageMode, "StorageModes ignored" ); + SotStorageStream * pStm = NULL; + DBG_ASSERT( Owner(), "must be owner" ); + if( m_pOwnStg ) + { + // volle Ole-Patches einschalten + // egal was kommt, nur exclusiv gestattet + nMode |= STREAM_SHARE_DENYALL; + ErrCode nE = m_pOwnStg->GetError(); + BaseStorageStream * p = m_pOwnStg->OpenStream( rEleName, nMode, + (nStorageMode & STORAGE_TRANSACTED) ? FALSE : TRUE ); + pStm = new SotStorageStream( p ); + + if( !nE ) + m_pOwnStg->ResetError(); // kein Fehler setzen + if( nMode & STREAM_TRUNC ) + pStm->SetSize( 0 ); + } + else + SetError( SVSTREAM_GENERALERROR ); + return pStm; +} + +/************************************************************************* +|* SotStorage::OpenStorage() +|* +|* Beschreibung +*************************************************************************/ +SotStorage * SotStorage::OpenSotStorage( const String & rEleName, + StreamMode nMode, + StorageMode nStorageMode ) +{ + SotStorage * pStor = NULL; + DBG_ASSERT( Owner(), "must be owner" ); + if( m_pOwnStg ) + { + nMode |= STREAM_SHARE_DENYALL; + ErrCode nE = m_pOwnStg->GetError(); + BaseStorage * p = m_pOwnStg->OpenStorage( rEleName, nMode, + (nStorageMode & STORAGE_TRANSACTED) ? FALSE : TRUE ); + if( p ) + { + pStor = new SotStorage( p ); + if( !nE ) + m_pOwnStg->ResetError(); // kein Fehler setzen + + return pStor; + } + } + + SetError( SVSTREAM_GENERALERROR ); + + return NULL; +} + +SotStorage * SotStorage::OpenUCBStorage( const String & rEleName, + StreamMode nMode, + StorageMode nStorageMode ) +{ + SotStorage * pStor = NULL; + DBG_ASSERT( Owner(), "must be owner" ); + if( m_pOwnStg ) + { + nMode |= STREAM_SHARE_DENYALL; + ErrCode nE = m_pOwnStg->GetError(); + BaseStorage * p = m_pOwnStg->OpenUCBStorage( rEleName, nMode, + (nStorageMode & STORAGE_TRANSACTED) ? FALSE : TRUE ); + pStor = new SotStorage( p ); + if( !nE ) + m_pOwnStg->ResetError(); // kein Fehler setzen + } + else + SetError( SVSTREAM_GENERALERROR ); + return pStor; +} + +SotStorage * SotStorage::OpenOLEStorage( const String & rEleName, + StreamMode nMode, + StorageMode nStorageMode ) +{ + SotStorage * pStor = NULL; + DBG_ASSERT( Owner(), "must be owner" ); + if( m_pOwnStg ) + { + nMode |= STREAM_SHARE_DENYALL; + ErrCode nE = m_pOwnStg->GetError(); + BaseStorage * p = m_pOwnStg->OpenOLEStorage( rEleName, nMode, + (nStorageMode & STORAGE_TRANSACTED) ? FALSE : TRUE ); + pStor = new SotStorage( p ); + if( !nE ) + m_pOwnStg->ResetError(); // kein Fehler setzen + } + else + SetError( SVSTREAM_GENERALERROR ); + return pStor; +} + +/************************************************************************* +|* SotStorage::IsStream() +|* SotStorage::IsStorage() +|* SotStorage::IsContained() +|* +|* Beschreibung +*************************************************************************/ +BOOL SotStorage::IsStorage( const String & rEleName ) const +{ + DBG_ASSERT( Owner(), "must be owner" ); + // ein bisschen schneller + if( m_pOwnStg ) + return m_pOwnStg->IsStorage( rEleName ); + return FALSE; +} + +BOOL SotStorage::IsStream( const String & rEleName ) const +{ + DBG_ASSERT( Owner(), "must be owner" ); + // ein bisschen schneller + if( m_pOwnStg ) + return m_pOwnStg->IsStream( rEleName ); + return FALSE; +} + +BOOL SotStorage::IsContained( const String & rEleName ) const +{ + DBG_ASSERT( Owner(), "must be owner" ); + // ein bisschen schneller + if( m_pOwnStg ) + return m_pOwnStg->IsContained( rEleName ); + return FALSE; +} + +/************************************************************************* +|* SotStorage::Remove() +|* +|* Beschreibung +*************************************************************************/ +BOOL SotStorage::Remove( const String & rEleName ) +{ + DBG_ASSERT( Owner(), "must be owner" ); + if( m_pOwnStg ) + { + m_pOwnStg->Remove( rEleName ); + SetError( m_pOwnStg->GetError() ); + } + else + SetError( SVSTREAM_GENERALERROR ); + return SVSTREAM_OK == GetError(); +} + +/************************************************************************* +|* SotStorage::Rename() +|* +|* Beschreibung +*************************************************************************/ +BOOL SotStorage::Rename( const String & rEleName, const String & rNewName ) +{ + DBG_ASSERT( Owner(), "must be owner" ); + if( m_pOwnStg ) + { + m_pOwnStg->Rename( rEleName, rNewName ); + SetError( m_pOwnStg->GetError() ); + } + else + SetError( SVSTREAM_GENERALERROR ); + return SVSTREAM_OK == GetError(); +} + +/************************************************************************* +|* SotStorage::CopyTo() +|* +|* Beschreibung +*************************************************************************/ +BOOL SotStorage::CopyTo( const String & rEleName, + SotStorage * pNewSt, const String & rNewName ) +{ + DBG_ASSERT( Owner(), "must be owner" ); + DBG_ASSERT( pNewSt->Owner(), "must be owner" ); + if( m_pOwnStg ) + { + m_pOwnStg->CopyTo( rEleName, pNewSt->m_pOwnStg, rNewName ); + SetError( m_pOwnStg->GetError() ); + SetError( pNewSt->GetError() ); + } + else + SetError( SVSTREAM_GENERALERROR ); + return SVSTREAM_OK == GetError(); +} + +/************************************************************************* +|* SotStorage::MoveTo() +|* +|* Beschreibung +*************************************************************************/ +BOOL SotStorage::MoveTo( const String & rEleName, + SotStorage * pNewSt, const String & rNewName ) +{ + DBG_ASSERT( Owner(), "must be owner" ); + DBG_ASSERT( pNewSt->Owner(), "must be owner" ); + if( m_pOwnStg ) + { + m_pOwnStg->MoveTo( rEleName, pNewSt->m_pOwnStg, rNewName ); + SetError( m_pOwnStg->GetError() ); + SetError( pNewSt->GetError() ); + } + else + SetError( SVSTREAM_GENERALERROR ); + return SVSTREAM_OK == GetError(); +} + +const SvStream* SotStorage::GetSvStream() +{ + const SvStream* pResult = 0; + DBG_ASSERT( Owner(), "must be owner" ); + if( m_pOwnStg ) + pResult = m_pOwnStg->GetSvStream(); + return pResult; +} + +SvStream* SotStorage::GetTargetSvStream() const +{ + SvStream* pResult = 0; + DBG_ASSERT( Owner(), "must be owner" ); + if( m_pOwnStg ) + pResult = (SvStream*)(m_pOwnStg->GetSvStream()); + return pResult; +} + + +BOOL SotStorage::Validate() +{ + DBG_ASSERT( m_bIsRoot, "Validate nur an Rootstorage" ); + if( m_pOwnStg ) + return m_pOwnStg->ValidateFAT(); + else + return TRUE; +} + +BOOL SotStorage::SetProperty( const String& rName, const ::com::sun::star::uno::Any& rValue ) +{ + UCBStorage* pStg = PTR_CAST( UCBStorage, m_pOwnStg ); + if ( pStg ) + { + return pStg->SetProperty( rName, rValue ); + } + else + { + DBG_WARNING("W1:Not implemented!"); + return FALSE; + } +} + +BOOL SotStorage::GetProperty( const String& rName, ::com::sun::star::uno::Any& rValue ) +{ + UCBStorage* pStg = PTR_CAST( UCBStorage, m_pOwnStg ); + if ( pStg ) + { + return pStg->GetProperty( rName, rValue ); + } + else if ( rName.CompareToAscii("MediaType") == COMPARE_EQUAL ) + { + String aStr = SotExchange::GetFormatMimeType( GetFormat() ); + USHORT nPos = aStr.Search(';'); + if ( nPos != STRING_NOTFOUND ) + aStr = aStr.Copy( 0, nPos ); + rValue <<= (::rtl::OUString) aStr; + return TRUE; + } + else + { + DBG_WARNING("W1:Not implemented!"); + return FALSE; + } +} + +BOOL SotStorage::GetProperty( const String& rEleName, const String& rName, ::com::sun::star::uno::Any& rValue ) +{ + UCBStorage* pStg = PTR_CAST( UCBStorage, m_pOwnStg ); + if ( pStg ) + { + return pStg->GetProperty( rEleName, rName, rValue ); + } + else + { + DBG_WARNING("W1:Not implemented!"); + return FALSE; + } +} + +BOOL SotStorage::IsOLEStorage() const +{ + UCBStorage* pStg = PTR_CAST( UCBStorage, m_pOwnStg ); + return !pStg; +} + +BOOL SotStorage::IsOLEStorage( const String & rFileName ) +{ + return Storage::IsStorageFile( rFileName ); +} + +BOOL SotStorage::IsOLEStorage( SvStream* pStream ) +{ + return Storage::IsStorageFile( pStream ); +} + +void SotStorage::SetKey( const ByteString& rKey ) +{ + m_aKey = rKey; + if ( !IsOLEStorage() ) + { + sal_uInt8 aBuffer[RTL_DIGEST_LENGTH_SHA1]; + rtlDigestError nError = rtl_digest_SHA1( m_aKey.GetBuffer(), m_aKey.Len(), aBuffer, RTL_DIGEST_LENGTH_SHA1 ); + if ( nError == rtl_Digest_E_None ) + { + sal_uInt8* pBuffer = aBuffer; + ::com::sun::star::uno::Sequence < sal_Int8 > aSequ( (sal_Int8*) pBuffer, RTL_DIGEST_LENGTH_SHA1 ); + ::com::sun::star::uno::Any aAny; + aAny <<= aSequ; + SetProperty( ::rtl::OUString::createFromAscii("EncryptionKey"), aAny ); + } + } +} + +SotStorage* SotStorage::OpenOLEStorage( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& xStorage, + const String& rEleName, StreamMode nMode ) +{ + sal_Int32 nEleMode = embed::ElementModes::SEEKABLEREAD; + if ( nMode & STREAM_WRITE ) + nEleMode |= embed::ElementModes::WRITE; + if ( nMode & STREAM_TRUNC ) + nEleMode |= embed::ElementModes::TRUNCATE; + if ( nMode & STREAM_NOCREATE ) + nEleMode |= embed::ElementModes::NOCREATE; + + SvStream* pStream = NULL; + try + { + uno::Reference < io::XStream > xStream = xStorage->openStreamElement( rEleName, nEleMode ); + + // TODO/LATER: should it be done this way? + if ( nMode & STREAM_WRITE ) + { + uno::Reference < beans::XPropertySet > xStreamProps( xStream, uno::UNO_QUERY_THROW ); + xStreamProps->setPropertyValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), + uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.sun.star.oleobject" ) ) ) ); + } + + pStream = utl::UcbStreamHelper::CreateStream( xStream ); + } + catch ( uno::Exception& ) + { + //TODO/LATER: ErrorHandling + pStream = new SvMemoryStream; + pStream->SetError( ERRCODE_IO_GENERAL ); + } + + return new SotStorage( pStream, TRUE ); +} + +sal_Int32 SotStorage::GetFormatID( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& xStorage ) +{ + uno::Reference< beans::XPropertySet > xProps( xStorage, uno::UNO_QUERY ); + if ( !xProps.is() ) + return 0; + + ::rtl::OUString aMediaType; + xProps->getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) ) >>= aMediaType; + if ( aMediaType.getLength() ) + { + ::com::sun::star::datatransfer::DataFlavor aDataFlavor; + aDataFlavor.MimeType = aMediaType; + return SotExchange::GetFormat( aDataFlavor ); + } + + return 0; +} + +sal_Int32 SotStorage::GetVersion( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& xStorage ) +{ + sal_Int32 nSotFormatID = SotStorage::GetFormatID( xStorage ); + switch( nSotFormatID ) + { + case SOT_FORMATSTR_ID_STARWRITER_8: + case SOT_FORMATSTR_ID_STARWRITER_8_TEMPLATE: + case SOT_FORMATSTR_ID_STARWRITERWEB_8: + case SOT_FORMATSTR_ID_STARWRITERGLOB_8: + case SOT_FORMATSTR_ID_STARDRAW_8: + case SOT_FORMATSTR_ID_STARDRAW_8_TEMPLATE: + case SOT_FORMATSTR_ID_STARIMPRESS_8: + case SOT_FORMATSTR_ID_STARIMPRESS_8_TEMPLATE: + case SOT_FORMATSTR_ID_STARCALC_8: + case SOT_FORMATSTR_ID_STARCALC_8_TEMPLATE: + case SOT_FORMATSTR_ID_STARCHART_8: + case SOT_FORMATSTR_ID_STARCHART_8_TEMPLATE: + case SOT_FORMATSTR_ID_STARMATH_8: + case SOT_FORMATSTR_ID_STARMATH_8_TEMPLATE: + return SOFFICE_FILEFORMAT_8; + case SOT_FORMATSTR_ID_STARWRITER_60: + case SOT_FORMATSTR_ID_STARWRITERWEB_60: + case SOT_FORMATSTR_ID_STARWRITERGLOB_60: + case SOT_FORMATSTR_ID_STARDRAW_60: + case SOT_FORMATSTR_ID_STARIMPRESS_60: + case SOT_FORMATSTR_ID_STARCALC_60: + case SOT_FORMATSTR_ID_STARCHART_60: + case SOT_FORMATSTR_ID_STARMATH_60: + return SOFFICE_FILEFORMAT_60; + } + + return 0; +} + diff --git a/sot/source/sdstor/storinfo.cxx b/sot/source/sdstor/storinfo.cxx new file mode 100644 index 000000000000..2aaaadd5a151 --- /dev/null +++ b/sot/source/sdstor/storinfo.cxx @@ -0,0 +1,111 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sot.hxx" + +#include <stg.hxx> +#include <storinfo.hxx> +#include <sot/exchange.hxx> + + +/************** class SvStorageInfoList ********************************** +*************************************************************************/ +PRV_SV_IMPL_OWNER_LIST(SvStorageInfoList,SvStorageInfo) + +const SvStorageInfo * SvStorageInfoList::Get( const String & rEleName ) +{ + for( ULONG i = 0; i < Count(); i++ ) + { + const SvStorageInfo & rType = GetObject( i ); + if( rType.GetName() == rEleName ) + return &rType; + } + return NULL; +} + +/************** class SvStorageInfo ************************************** +*************************************************************************/ +ULONG ReadClipboardFormat( SvStream & rStm ) +{ + sal_uInt32 nFormat = 0; + INT32 nLen = 0; + rStm >> nLen; + if( rStm.IsEof() ) + rStm.SetError( SVSTREAM_GENERALERROR ); + if( nLen > 0 ) + { + // get a string name + sal_Char * p = new sal_Char[ nLen ]; + if( rStm.Read( p, nLen ) == (ULONG) nLen ) + { + nFormat = SotExchange::RegisterFormatName( String::CreateFromAscii( p, short(nLen-1) ) ); + } + else + rStm.SetError( SVSTREAM_GENERALERROR ); + delete [] p; + } + else if( nLen == -1L ) + // Windows clipboard format + // SV und Win stimmen ueberein (bis einschl. FORMAT_GDIMETAFILE) + rStm >> nFormat; + else if( nLen == -2L ) + { + rStm >> nFormat; + // Mac clipboard format + // ??? not implemented + rStm.SetError( SVSTREAM_GENERALERROR ); + } + else if( nLen != 0 ) + { + // unknown identifier + rStm.SetError( SVSTREAM_GENERALERROR ); + } + return nFormat; +} + +void WriteClipboardFormat( SvStream & rStm, ULONG nFormat ) +{ + // determine the clipboard format string + String aCbFmt; + if( nFormat > FORMAT_GDIMETAFILE ) + aCbFmt = SotExchange::GetFormatName( nFormat ); + if( aCbFmt.Len() ) + { + ByteString aAsciiCbFmt( aCbFmt, RTL_TEXTENCODING_ASCII_US ); + rStm << (INT32) (aAsciiCbFmt.Len() + 1); + rStm << (const char *)aAsciiCbFmt.GetBuffer(); + rStm << (UINT8) 0; + } + else if( nFormat ) + rStm << (INT32) -1 // for Windows + << (INT32) nFormat; + else + rStm << (INT32) 0; // no clipboard format +} + + diff --git a/sot/source/sdstor/ucbstorage.cxx b/sot/source/sdstor/ucbstorage.cxx new file mode 100644 index 000000000000..ea3b656272db --- /dev/null +++ b/sot/source/sdstor/ucbstorage.cxx @@ -0,0 +1,3600 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sot.hxx" +#include <com/sun/star/io/NotConnectedException.hpp> +#include <com/sun/star/io/BufferSizeExceededException.hpp> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <ucbhelper/content.hxx> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/ucb/XCommandEnvironment.hpp> +#include <unotools/tempfile.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/ucb/InsertCommandArgument.hpp> +#include <com/sun/star/ucb/ResultSetException.hpp> +#include <com/sun/star/uno/Sequence.h> +#include <com/sun/star/sdbc/XResultSet.hdl> +#include <com/sun/star/ucb/XContentAccess.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/ucb/CommandAbortedException.hpp> +#include <com/sun/star/datatransfer/DataFlavor.hpp> +#include <com/sun/star/ucb/ContentInfo.hpp> +#include <com/sun/star/ucb/ContentInfoAttribute.hpp> +#include <com/sun/star/beans/Property.hpp> +#include <com/sun/star/packages/manifest/XManifestWriter.hpp> +#include <com/sun/star/packages/manifest/XManifestReader.hpp> +#include <com/sun/star/ucb/InteractiveIOException.hpp> + +#include <rtl/digest.h> +#include <tools/ref.hxx> +#include <tools/debug.hxx> +#include <unotools/streamhelper.hxx> +#include <unotools/streamwrap.hxx> +#include <unotools/ucbhelper.hxx> +#include <unotools/localfilehelper.hxx> +#include <tools/list.hxx> +#include <tools/urlobj.hxx> +#include <unotools/streamwrap.hxx> +#include <comphelper/processfactory.hxx> +#include <cppuhelper/implbase2.hxx> +#include <ucbhelper/commandenvironment.hxx> + +#include "stg.hxx" +#include "storinfo.hxx" +#include <sot/storage.hxx> +#include <sot/exchange.hxx> +#include <sot/formats.hxx> +#include "clsids.hxx" + +#include "unostorageholder.hxx" + +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::sdbc; +using namespace ::ucbhelper; + +#if OSL_DEBUG_LEVEL > 1 +#include <stdio.h> +static int nOpenFiles=0; +static int nOpenStreams=0; +#endif + +typedef ::cppu::WeakImplHelper2 < XInputStream, XSeekable > FileInputStreamWrapper_Base; +class FileStreamWrapper_Impl : public FileInputStreamWrapper_Base +{ +protected: + ::osl::Mutex m_aMutex; + String m_aURL; + SvStream* m_pSvStream; + +public: + FileStreamWrapper_Impl( const String& rName ); + virtual ~FileStreamWrapper_Impl(); + + //DECLARE_UNO3_AGG_DEFAULTS( FileStreamWrapper_Impl, FileInputStreamWrapper_Base); + + virtual void SAL_CALL seek( sal_Int64 _nLocation ) throw ( IllegalArgumentException, IOException, RuntimeException); + virtual sal_Int64 SAL_CALL getPosition( ) throw ( IOException, RuntimeException); + virtual sal_Int64 SAL_CALL getLength( ) throw ( IOException, RuntimeException); + virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) throw( NotConnectedException, BufferSizeExceededException, RuntimeException ); + virtual sal_Int32 SAL_CALL readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) throw( NotConnectedException, BufferSizeExceededException, RuntimeException ); + virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) throw( NotConnectedException, BufferSizeExceededException, RuntimeException); + virtual sal_Int32 SAL_CALL available() throw( NotConnectedException, RuntimeException ); + virtual void SAL_CALL closeInput() throw( NotConnectedException, RuntimeException ); + +protected: + void checkConnected(); + void checkError(); +}; + +//------------------------------------------------------------------ +FileStreamWrapper_Impl::FileStreamWrapper_Impl( const String& rName ) + : m_aURL( rName ) + , m_pSvStream(0) +{ + // if no URL is provided the stream is empty +} + +//------------------------------------------------------------------ +FileStreamWrapper_Impl::~FileStreamWrapper_Impl() +{ + if ( m_pSvStream ) + { + delete m_pSvStream; +#if OSL_DEBUG_LEVEL > 1 + --nOpenFiles; +#endif + } + + if ( m_aURL.Len() ) + ::utl::UCBContentHelper::Kill( m_aURL ); +} + +//------------------------------------------------------------------------------ +sal_Int32 SAL_CALL FileStreamWrapper_Impl::readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) + throw( NotConnectedException, BufferSizeExceededException, RuntimeException ) +{ + if ( !m_aURL.Len() ) + { + aData.realloc( 0 ); + return 0; + } + + checkConnected(); + + if (nBytesToRead < 0) + throw BufferSizeExceededException(::rtl::OUString(),static_cast<XWeak*>(this)); + + ::osl::MutexGuard aGuard( m_aMutex ); + + aData.realloc(nBytesToRead); + + sal_uInt32 nRead = m_pSvStream->Read((void*)aData.getArray(), nBytesToRead); + checkError(); + + // Wenn gelesene Zeichen < MaxLength, Sequence anpassen + if (nRead < (sal_uInt32)nBytesToRead) + aData.realloc( nRead ); + + return nRead; +} + +//------------------------------------------------------------------------------ +sal_Int32 SAL_CALL FileStreamWrapper_Impl::readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) throw( NotConnectedException, BufferSizeExceededException, RuntimeException ) +{ + if ( !m_aURL.Len() ) + { + aData.realloc( 0 ); + return 0; + } + + checkError(); + + if (nMaxBytesToRead < 0) + throw BufferSizeExceededException(::rtl::OUString(),static_cast<XWeak*>(this)); + + if (m_pSvStream->IsEof()) + { + aData.realloc(0); + return 0; + } + else + return readBytes(aData, nMaxBytesToRead); +} + +//------------------------------------------------------------------------------ +void SAL_CALL FileStreamWrapper_Impl::skipBytes(sal_Int32 nBytesToSkip) throw( NotConnectedException, BufferSizeExceededException, RuntimeException ) +{ + if ( !m_aURL.Len() ) + return; + + ::osl::MutexGuard aGuard( m_aMutex ); + checkError(); + +#ifdef DBG_UTIL + sal_uInt32 nCurrentPos = m_pSvStream->Tell(); +#endif + + m_pSvStream->SeekRel(nBytesToSkip); + checkError(); + +#ifdef DBG_UTIL + nCurrentPos = m_pSvStream->Tell(); +#endif +} + +//------------------------------------------------------------------------------ +sal_Int32 SAL_CALL FileStreamWrapper_Impl::available() throw( NotConnectedException, RuntimeException ) +{ + if ( !m_aURL.Len() ) + return 0; + + ::osl::MutexGuard aGuard( m_aMutex ); + checkConnected(); + + sal_uInt32 nPos = m_pSvStream->Tell(); + checkError(); + + m_pSvStream->Seek(STREAM_SEEK_TO_END); + checkError(); + + sal_Int32 nAvailable = (sal_Int32)m_pSvStream->Tell() - nPos; + m_pSvStream->Seek(nPos); + checkError(); + + return nAvailable; +} + +//------------------------------------------------------------------------------ +void SAL_CALL FileStreamWrapper_Impl::closeInput() throw( NotConnectedException, RuntimeException ) +{ + if ( !m_aURL.Len() ) + return; + + ::osl::MutexGuard aGuard( m_aMutex ); + checkConnected(); + DELETEZ( m_pSvStream ); +#if OSL_DEBUG_LEVEL > 1 + --nOpenFiles; +#endif + ::utl::UCBContentHelper::Kill( m_aURL ); + m_aURL.Erase(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL FileStreamWrapper_Impl::seek( sal_Int64 _nLocation ) throw (IllegalArgumentException, IOException, RuntimeException) +{ + if ( !m_aURL.Len() ) + return; + + ::osl::MutexGuard aGuard( m_aMutex ); + checkConnected(); + + m_pSvStream->Seek((sal_uInt32)_nLocation); + checkError(); +} + +//------------------------------------------------------------------------------ +sal_Int64 SAL_CALL FileStreamWrapper_Impl::getPosition( ) throw (IOException, RuntimeException) +{ + if ( !m_aURL.Len() ) + return 0; + + ::osl::MutexGuard aGuard( m_aMutex ); + checkConnected(); + + sal_uInt32 nPos = m_pSvStream->Tell(); + checkError(); + return (sal_Int64)nPos; +} + +//------------------------------------------------------------------------------ +sal_Int64 SAL_CALL FileStreamWrapper_Impl::getLength( ) throw (IOException, RuntimeException) +{ + if ( !m_aURL.Len() ) + return 0; + + ::osl::MutexGuard aGuard( m_aMutex ); + checkConnected(); + + sal_uInt32 nCurrentPos = m_pSvStream->Tell(); + checkError(); + + m_pSvStream->Seek(STREAM_SEEK_TO_END); + sal_uInt32 nEndPos = m_pSvStream->Tell(); + m_pSvStream->Seek(nCurrentPos); + + checkError(); + + return (sal_Int64)nEndPos; +} + +//------------------------------------------------------------------------------ +void FileStreamWrapper_Impl::checkConnected() +{ + if ( !m_aURL.Len() ) + throw NotConnectedException(::rtl::OUString(), const_cast<XWeak*>(static_cast<const XWeak*>(this))); + if ( !m_pSvStream ) + { + m_pSvStream = ::utl::UcbStreamHelper::CreateStream( m_aURL, STREAM_STD_READ ); +#if OSL_DEBUG_LEVEL > 1 + ++nOpenFiles; +#endif + } +} + +//------------------------------------------------------------------------------ +void FileStreamWrapper_Impl::checkError() +{ + checkConnected(); + + if (m_pSvStream->SvStream::GetError() != ERRCODE_NONE) + // TODO: really evaluate the error + throw NotConnectedException(::rtl::OUString(), const_cast<XWeak*>(static_cast<const XWeak*>(this))); +} + +TYPEINIT1( UCBStorageStream, BaseStorageStream ); +TYPEINIT1( UCBStorage, BaseStorage ); + +#define COMMIT_RESULT_FAILURE 0 +#define COMMIT_RESULT_NOTHING_TO_DO 1 +#define COMMIT_RESULT_SUCCESS 2 + +#define min( x, y ) (( x < y ) ? x : y) +#define max( x, y ) (( x > y ) ? x : y) + +sal_Int32 GetFormatId_Impl( SvGlobalName aName ) +{ +// if ( aName == SvGlobalName( SO3_SW_CLASSID_8 ) ) +// return SOT_FORMATSTR_ID_STARWRITER_8; +// if ( aName == SvGlobalName( SO3_SWWEB_CLASSID_8 ) ) +// return SOT_FORMATSTR_ID_STARWRITERWEB_8; +// if ( aName == SvGlobalName( SO3_SWGLOB_CLASSID_8 ) ) +// return SOT_FORMATSTR_ID_STARWRITERGLOB_8; +// if ( aName == SvGlobalName( SO3_SDRAW_CLASSID_8 ) ) +// return SOT_FORMATSTR_ID_STARDRAW_8; +// if ( aName == SvGlobalName( SO3_SIMPRESS_CLASSID_8 ) ) +// return SOT_FORMATSTR_ID_STARIMPRESS_8; +// if ( aName == SvGlobalName( SO3_SC_CLASSID_8 ) ) +// return SOT_FORMATSTR_ID_STARCALC_8; +// if ( aName == SvGlobalName( SO3_SCH_CLASSID_8 ) ) +// return SOT_FORMATSTR_ID_STARCHART_8; +// if ( aName == SvGlobalName( SO3_SM_CLASSID_8 ) ) +// return SOT_FORMATSTR_ID_STARMATH_8; + if ( aName == SvGlobalName( SO3_SW_CLASSID_60 ) ) + return SOT_FORMATSTR_ID_STARWRITER_60; + if ( aName == SvGlobalName( SO3_SWWEB_CLASSID_60 ) ) + return SOT_FORMATSTR_ID_STARWRITERWEB_60; + if ( aName == SvGlobalName( SO3_SWGLOB_CLASSID_60 ) ) + return SOT_FORMATSTR_ID_STARWRITERGLOB_60; + if ( aName == SvGlobalName( SO3_SDRAW_CLASSID_60 ) ) + return SOT_FORMATSTR_ID_STARDRAW_60; + if ( aName == SvGlobalName( SO3_SIMPRESS_CLASSID_60 ) ) + return SOT_FORMATSTR_ID_STARIMPRESS_60; + if ( aName == SvGlobalName( SO3_SC_CLASSID_60 ) ) + return SOT_FORMATSTR_ID_STARCALC_60; + if ( aName == SvGlobalName( SO3_SCH_CLASSID_60 ) ) + return SOT_FORMATSTR_ID_STARCHART_60; + if ( aName == SvGlobalName( SO3_SM_CLASSID_60 ) ) + return SOT_FORMATSTR_ID_STARMATH_60; + if ( aName == SvGlobalName( SO3_OUT_CLASSID ) || + aName == SvGlobalName( SO3_APPLET_CLASSID ) || + aName == SvGlobalName( SO3_PLUGIN_CLASSID ) || + aName == SvGlobalName( SO3_IFRAME_CLASSID ) ) + // allowed, but not supported + return 0; + else + { + DBG_ERROR( "Unknown UCB storage format!" ); + return 0; + } +} + + +SvGlobalName GetClassId_Impl( sal_Int32 nFormat ) +{ + switch ( nFormat ) + { + case SOT_FORMATSTR_ID_STARWRITER_8 : + case SOT_FORMATSTR_ID_STARWRITER_8_TEMPLATE : + return SvGlobalName( SO3_SW_CLASSID_60 ); + case SOT_FORMATSTR_ID_STARWRITERWEB_8 : + return SvGlobalName( SO3_SWWEB_CLASSID_60 ); + case SOT_FORMATSTR_ID_STARWRITERGLOB_8 : + return SvGlobalName( SO3_SWGLOB_CLASSID_60 ); + case SOT_FORMATSTR_ID_STARDRAW_8 : + case SOT_FORMATSTR_ID_STARDRAW_8_TEMPLATE : + return SvGlobalName( SO3_SDRAW_CLASSID_60 ); + case SOT_FORMATSTR_ID_STARIMPRESS_8 : + case SOT_FORMATSTR_ID_STARIMPRESS_8_TEMPLATE : + return SvGlobalName( SO3_SIMPRESS_CLASSID_60 ); + case SOT_FORMATSTR_ID_STARCALC_8 : + case SOT_FORMATSTR_ID_STARCALC_8_TEMPLATE : + return SvGlobalName( SO3_SC_CLASSID_60 ); + case SOT_FORMATSTR_ID_STARCHART_8 : + case SOT_FORMATSTR_ID_STARCHART_8_TEMPLATE : + return SvGlobalName( SO3_SCH_CLASSID_60 ); + case SOT_FORMATSTR_ID_STARMATH_8 : + case SOT_FORMATSTR_ID_STARMATH_8_TEMPLATE : + return SvGlobalName( SO3_SM_CLASSID_60 ); + case SOT_FORMATSTR_ID_STARWRITER_60 : + return SvGlobalName( SO3_SW_CLASSID_60 ); + case SOT_FORMATSTR_ID_STARWRITERWEB_60 : + return SvGlobalName( SO3_SWWEB_CLASSID_60 ); + case SOT_FORMATSTR_ID_STARWRITERGLOB_60 : + return SvGlobalName( SO3_SWGLOB_CLASSID_60 ); + case SOT_FORMATSTR_ID_STARDRAW_60 : + return SvGlobalName( SO3_SDRAW_CLASSID_60 ); + case SOT_FORMATSTR_ID_STARIMPRESS_60 : + return SvGlobalName( SO3_SIMPRESS_CLASSID_60 ); + case SOT_FORMATSTR_ID_STARCALC_60 : + return SvGlobalName( SO3_SC_CLASSID_60 ); + case SOT_FORMATSTR_ID_STARCHART_60 : + return SvGlobalName( SO3_SCH_CLASSID_60 ); + case SOT_FORMATSTR_ID_STARMATH_60 : + return SvGlobalName( SO3_SM_CLASSID_60 ); + default : + //DBG_ERROR( "Unknown UCB storage format!" ); + return SvGlobalName(); + } +} + +// All storage and streams are refcounted internally; outside of this classes they are only accessible through a handle +// class, that uses the refcounted object as impl-class. + +enum RepresentModes { + nonset, + svstream, + xinputstream +}; + +class UCBStorageStream_Impl : public SvRefBase, public SvStream +{ + ~UCBStorageStream_Impl(); +public: + + virtual ULONG GetData( void* pData, ULONG nSize ); + virtual ULONG PutData( const void* pData, ULONG nSize ); + virtual ULONG SeekPos( ULONG nPos ); + virtual void SetSize( ULONG nSize ); + virtual void FlushData(); + virtual void ResetError(); + + UCBStorageStream* m_pAntiImpl; // only valid if an external reference exists + + String m_aOriginalName;// the original name before accessing the stream + String m_aName; // the actual name ( changed with a Rename command at the parent ) + String m_aURL; // the full path name to create the content + String m_aContentType; + String m_aOriginalContentType; + ByteString m_aKey; + ::ucbhelper::Content* m_pContent; // the content that provides the data + Reference<XInputStream> m_rSource; // the stream covering the original data of the content + SvStream* m_pStream; // the stream worked on; for readonly streams it is the original stream of the content + // for read/write streams it's a copy into a temporary file + String m_aTempURL; // URL of this temporary stream + RepresentModes m_nRepresentMode; // should it be used as XInputStream or as SvStream + long m_nError; + StreamMode m_nMode; // open mode ( read/write/trunc/nocreate/sharing ) + BOOL m_bSourceRead; // Source still contains useful information + BOOL m_bModified; // only modified streams will be sent to the original content + BOOL m_bCommited; // sending the streams is coordinated by the root storage of the package + BOOL m_bDirect; // the storage and its streams are opened in direct mode; for UCBStorages + // this means that the root storage does an autocommit when its external + // reference is destroyed + BOOL m_bIsOLEStorage;// an OLEStorage on a UCBStorageStream makes this an Autocommit-stream + + UCBStorageStream_Impl( const String&, StreamMode, UCBStorageStream*, BOOL, const ByteString* pKey=0, BOOL bRepair = FALSE, Reference< XProgressHandler > xProgress = Reference< XProgressHandler >() ); + + void Free(); + BOOL Init(); + BOOL Clear(); + sal_Int16 Commit(); // if modified and commited: transfer an XInputStream to the content + BOOL Revert(); // discard all changes + BaseStorage* CreateStorage();// create an OLE Storage on the UCBStorageStream + ULONG GetSize(); + + ULONG ReadSourceWriteTemporary( ULONG aLength ); // read aLength from source and copy to temporary, + // no seeking is produced + ULONG ReadSourceWriteTemporary(); // read source till the end and copy to temporary, + // no seeking is produced +#if 0 + ULONG CopySourceToTemporary( ULONG aLength ); // same as ReadSourceWriteToTemporary( aLength ) + // but the writing is done at the end of temporary + // pointer position is not changed +#endif + + ULONG CopySourceToTemporary(); // same as ReadSourceWriteToTemporary() + // but the writing is done at the end of temporary + // pointer position is not changed + Reference<XInputStream> GetXInputStream(); // return XInputStream, after that + // this class is close to be unusable + // since it can not read and write + using SvStream::SetError; + void SetError( sal_uInt32 nError ); + void PrepareCachedForReopen( StreamMode nMode ); +}; + +SV_DECL_IMPL_REF( UCBStorageStream_Impl ); + +struct UCBStorageElement_Impl; +DECLARE_LIST( UCBStorageElementList_Impl, UCBStorageElement_Impl* ) + +class UCBStorage_Impl : public SvRefBase +{ + ~UCBStorage_Impl(); +public: + UCBStorage* m_pAntiImpl; // only valid if external references exists + + String m_aOriginalName;// the original name before accessing the storage + String m_aName; // the actual name ( changed with a Rename command at the parent ) + String m_aURL; // the full path name to create the content + String m_aContentType; + String m_aOriginalContentType; + ::ucbhelper::Content* m_pContent; // the content that provides the storage elements + ::utl::TempFile* m_pTempFile; // temporary file, only for storages on stream + SvStream* m_pSource; // original stream, only for storages on a stream + //SvStream* m_pStream; // the corresponding editable stream, only for storage on a stream + long m_nError; + StreamMode m_nMode; // open mode ( read/write/trunc/nocreate/sharing ) + BOOL m_bModified; // only modified elements will be sent to the original content + BOOL m_bCommited; // sending the streams is coordinated by the root storage of the package + BOOL m_bDirect; // the storage and its streams are opened in direct mode; for UCBStorages + // this means that the root storage does an autocommit when its external + // reference is destroyed + BOOL m_bIsRoot; // marks this storage as root storages that manages all oommits and reverts + BOOL m_bDirty; // ??? + BOOL m_bIsLinked; + BOOL m_bListCreated; + ULONG m_nFormat; + String m_aUserTypeName; + SvGlobalName m_aClassId; + + UCBStorageElementList_Impl m_aChildrenList; + + BOOL m_bRepairPackage; + Reference< XProgressHandler > m_xProgressHandler; + + UNOStorageHolderList* m_pUNOStorageHolderList; + UCBStorage_Impl( const ::ucbhelper::Content&, const String&, StreamMode, UCBStorage*, BOOL, BOOL, BOOL = FALSE, Reference< XProgressHandler > = Reference< XProgressHandler >() ); + UCBStorage_Impl( const String&, StreamMode, UCBStorage*, BOOL, BOOL, BOOL = FALSE, Reference< XProgressHandler > = Reference< XProgressHandler >() ); + UCBStorage_Impl( SvStream&, UCBStorage*, BOOL ); + void Init(); + sal_Int16 Commit(); + BOOL Revert(); + BOOL Insert( ::ucbhelper::Content *pContent ); + UCBStorage_Impl* OpenStorage( UCBStorageElement_Impl* pElement, StreamMode nMode, BOOL bDirect ); + UCBStorageStream_Impl* OpenStream( UCBStorageElement_Impl*, StreamMode, BOOL, const ByteString* pKey=0 ); + void SetProps( const Sequence < Sequence < PropertyValue > >& rSequence, const String& ); + void GetProps( sal_Int32&, Sequence < Sequence < PropertyValue > >& rSequence, const String& ); + sal_Int32 GetObjectCount(); + void ReadContent(); + void CreateContent(); + ::ucbhelper::Content* GetContent() + { if ( !m_pContent ) CreateContent(); return m_pContent; } + UCBStorageElementList_Impl& GetChildrenList() + { + long nError = m_nError; + ReadContent(); + if ( m_nMode & STREAM_WRITE ) + { + m_nError = nError; + if ( m_pAntiImpl ) + { + m_pAntiImpl->ResetError(); + m_pAntiImpl->SetError( nError ); + } + } + + return m_aChildrenList; + } + + void SetError( long nError ); +}; + +SV_DECL_IMPL_REF( UCBStorage_Impl ); + +// this struct contains all neccessary information on an element inside a UCBStorage +struct UCBStorageElement_Impl +{ + String m_aName; // the actual URL relative to the root "folder" + String m_aOriginalName;// the original name in the content + ULONG m_nSize; + BOOL m_bIsFolder; // Only TRUE when it is a UCBStorage ! + BOOL m_bIsStorage; // Also TRUE when it is an OLEStorage ! + BOOL m_bIsRemoved; // element will be removed on commit + BOOL m_bIsInserted; // element will be removed on revert + UCBStorage_ImplRef m_xStorage; // reference to the "real" storage + UCBStorageStream_ImplRef m_xStream; // reference to the "real" stream + + UCBStorageElement_Impl( const ::rtl::OUString& rName, + BOOL bIsFolder = FALSE, ULONG nSize = 0 ) + : m_aName( rName ) + , m_aOriginalName( rName ) + , m_nSize( nSize ) + , m_bIsFolder( bIsFolder ) + , m_bIsStorage( bIsFolder ) + , m_bIsRemoved( FALSE ) + , m_bIsInserted( FALSE ) + { + } + + ::ucbhelper::Content* GetContent(); + BOOL IsModified(); + String GetContentType(); + void SetContentType( const String& ); + String GetOriginalContentType(); + BOOL IsLoaded() + { return m_xStream.Is() || m_xStorage.Is(); } +}; + +::ucbhelper::Content* UCBStorageElement_Impl::GetContent() +{ + if ( m_xStream.Is() ) + return m_xStream->m_pContent; + else if ( m_xStorage.Is() ) + return m_xStorage->GetContent(); + else + return NULL; +} + +String UCBStorageElement_Impl::GetContentType() +{ + if ( m_xStream.Is() ) + return m_xStream->m_aContentType; + else if ( m_xStorage.Is() ) + return m_xStorage->m_aContentType; + else + { + DBG_ERROR("Element not loaded!"); + return String(); + } +} + +void UCBStorageElement_Impl::SetContentType( const String& rType ) +{ + if ( m_xStream.Is() ) { + m_xStream->m_aContentType = m_xStream->m_aOriginalContentType = rType; + } + else if ( m_xStorage.Is() ) { + m_xStorage->m_aContentType = m_xStorage->m_aOriginalContentType = rType; + } + else { + DBG_ERROR("Element not loaded!"); + } +} + +String UCBStorageElement_Impl::GetOriginalContentType() +{ + if ( m_xStream.Is() ) + return m_xStream->m_aOriginalContentType; + else if ( m_xStorage.Is() ) + return m_xStorage->m_aOriginalContentType; + else + return String(); +} + +BOOL UCBStorageElement_Impl::IsModified() +{ + BOOL bModified = m_bIsRemoved || m_bIsInserted || m_aName != m_aOriginalName; + if ( bModified ) + { + if ( m_xStream.Is() ) + bModified = m_xStream->m_aContentType != m_xStream->m_aOriginalContentType; + else if ( m_xStorage.Is() ) + bModified = m_xStorage->m_aContentType != m_xStorage->m_aOriginalContentType; + } + + return bModified; +} + +UCBStorageStream_Impl::UCBStorageStream_Impl( const String& rName, StreamMode nMode, UCBStorageStream* pStream, BOOL bDirect, const ByteString* pKey, BOOL bRepair, Reference< XProgressHandler > xProgress ) + : m_pAntiImpl( pStream ) + , m_aURL( rName ) + , m_pContent( NULL ) + , m_pStream( NULL ) + , m_nRepresentMode( nonset ) + , m_nError( 0 ) + , m_nMode( nMode ) + , m_bSourceRead( !( nMode & STREAM_TRUNC ) ) + , m_bModified( FALSE ) + , m_bCommited( FALSE ) + , m_bDirect( bDirect ) + , m_bIsOLEStorage( FALSE ) +{ + // name is last segment in URL + INetURLObject aObj( rName ); + m_aName = m_aOriginalName = aObj.GetLastName(); + try + { + // create the content + Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv; + + ::rtl::OUString aTemp( rName ); + + if ( bRepair ) + { + xComEnv = new ::ucbhelper::CommandEnvironment( Reference< ::com::sun::star::task::XInteractionHandler >(), + xProgress ); + aTemp += rtl::OUString::createFromAscii("?repairpackage"); + } + + m_pContent = new ::ucbhelper::Content( aTemp, xComEnv ); + + if ( pKey ) + { + m_aKey = *pKey; + + // stream is encrypted and should be decrypted (without setting the key we'll get the raw data) + sal_uInt8 aBuffer[RTL_DIGEST_LENGTH_SHA1]; + rtlDigestError nErr = rtl_digest_SHA1( pKey->GetBuffer(), pKey->Len(), aBuffer, RTL_DIGEST_LENGTH_SHA1 ); + if ( nErr == rtl_Digest_E_None ) + { + sal_uInt8* pBuffer = aBuffer; + ::com::sun::star::uno::Sequence < sal_Int8 > aSequ( (sal_Int8*) pBuffer, RTL_DIGEST_LENGTH_SHA1 ); + ::com::sun::star::uno::Any aAny; + aAny <<= aSequ; + m_pContent->setPropertyValue( ::rtl::OUString::createFromAscii("EncryptionKey"), aAny ); + } + } + } + catch ( ContentCreationException& ) + { + // content could not be created + SetError( SVSTREAM_CANNOT_MAKE ); + } + catch ( RuntimeException& ) + { + // any other error - not specified + SetError( ERRCODE_IO_GENERAL ); + } +} + +UCBStorageStream_Impl::~UCBStorageStream_Impl() +{ + if( m_rSource.is() ) + m_rSource = Reference< XInputStream >(); + + if( m_pStream ) + delete m_pStream; + + if ( m_aTempURL.Len() ) + ::utl::UCBContentHelper::Kill( m_aTempURL ); + + if( m_pContent ) + delete m_pContent; +} + + +Reference<XInputStream> UCBStorageStream_Impl::GetXInputStream() +{ + Reference< XInputStream > aResult; + + if( m_pAntiImpl && m_nRepresentMode != nonset ) + { + DBG_ERROR( "Misuse of the XInputstream!" ); + SetError( ERRCODE_IO_ACCESSDENIED ); + } + else + { + if( m_bModified ) + { + // use wrapper around temporary stream + if( Init() ) + { + CopySourceToTemporary(); + + // owner transfer of stream to wrapper + aResult = new ::utl::OInputStreamWrapper( m_pStream, TRUE ); + m_pStream->Seek(0); + + if( aResult.is() ) + { + // temporary stream can not be used here any more + // and can not be opened untill wrapper is closed + // stream is deleted by wrapper after use + m_pStream = NULL; + m_nRepresentMode = xinputstream; + } + } + } + else + { + Free(); + + // open a new instance of XInputStream + try + { + aResult = m_pContent->openStream(); + } + catch ( Exception& ) + { + // usually means that stream could not be opened + } + + if( aResult.is() ) + m_nRepresentMode = xinputstream; + else + SetError( ERRCODE_IO_ACCESSDENIED ); + } + } + + return aResult; +} + +BOOL UCBStorageStream_Impl::Init() +{ + if( m_nRepresentMode == xinputstream ) + { + DBG_ERROR( "XInputStream misuse!" ); + SetError( ERRCODE_IO_ACCESSDENIED ); + return FALSE; + } + + if( !m_pStream ) + { + // no temporary stream was created + // create one + + m_nRepresentMode = svstream; // can not be used as XInputStream + + if ( !m_aTempURL.Len() ) + m_aTempURL = ::utl::TempFile().GetURL(); + + m_pStream = ::utl::UcbStreamHelper::CreateStream( m_aTempURL, STREAM_STD_READWRITE, sal_True /* bFileExists */ ); +#if OSL_DEBUG_LEVEL > 1 + ++nOpenFiles; +#endif + + if( !m_pStream ) + { + DBG_ERROR( "Suspicious temporary stream creation!" ); + SetError( SVSTREAM_CANNOT_MAKE ); + return FALSE; + } + + SetError( m_pStream->GetError() ); + } + + if( m_bSourceRead && !m_rSource.is() ) + { + // source file contain usefull information and is not opened + // open it from the point of noncopied data + + try + { + m_rSource = m_pContent->openStream(); + } + catch ( Exception& ) + { + // usually means that stream could not be opened + } + + if( m_rSource.is() ) + { + m_pStream->Seek( STREAM_SEEK_TO_END ); + + try + { + m_rSource->skipBytes( m_pStream->Tell() ); + } + catch( BufferSizeExceededException& ) + { + // the temporary stream already contain all the data + m_bSourceRead = FALSE; + } + catch( Exception& ) + { + // something is really wrong + m_bSourceRead = FALSE; + DBG_ERROR( "Can not operate original stream!" ); + SetError( SVSTREAM_CANNOT_MAKE ); + } + + m_pStream->Seek( 0 ); + } + else + { + // if the new file is edited than no source exist + m_bSourceRead = FALSE; + //SetError( SVSTREAM_CANNOT_MAKE ); + } + } + + DBG_ASSERT( m_rSource.is() || !m_bSourceRead, "Unreadable source stream!" ); + + return sal_True; +} + +ULONG UCBStorageStream_Impl::ReadSourceWriteTemporary() +{ + // read source stream till the end and copy all the data to + // the current position of the temporary stream + + ULONG aResult = 0; + + if( m_bSourceRead ) + { + Sequence<sal_Int8> aData(32000); + + try + { + ULONG aReaded; + do + { + aReaded = m_rSource->readBytes( aData, 32000 ); + aResult += m_pStream->Write( aData.getArray(), aReaded ); + } while( aReaded == 32000 ); + } +#if OSL_DEBUG_LEVEL > 1 + catch( Exception & e ) + { + OSL_ENSURE( FALSE, ::rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); +#else + catch( Exception & ) + { +#endif + } + } + + m_bSourceRead = FALSE; + + return aResult; + +} + +ULONG UCBStorageStream_Impl::ReadSourceWriteTemporary( ULONG aLength ) +{ + // read aLength bite from the source stream and copy them to the current + // position of the temporary stream + + ULONG aResult = 0; + + if( m_bSourceRead ) + { + Sequence<sal_Int8> aData(32000); + + try + { + + ULONG aReaded = 32000; + + for( ULONG pInd = 0; pInd < aLength && aReaded == 32000 ; pInd += 32000 ) + { + ULONG aToCopy = min( aLength - pInd, 32000 ); + aReaded = m_rSource->readBytes( aData, aToCopy ); + aResult += m_pStream->Write( aData.getArray(), aReaded ); + } + + if( aResult < aLength ) + m_bSourceRead = FALSE; + } +#if OSL_DEBUG_LEVEL > 1 + catch( Exception & e ) + { + OSL_ENSURE( FALSE, ::rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); +#else + catch( Exception & ) + { +#endif + } + } + + return aResult; +} + +ULONG UCBStorageStream_Impl::CopySourceToTemporary() +{ + // current position of the temporary stream is not changed + ULONG aResult = 0; + + if( m_bSourceRead ) + { + ULONG aPos = m_pStream->Tell(); + m_pStream->Seek( STREAM_SEEK_TO_END ); + aResult = ReadSourceWriteTemporary(); + m_pStream->Seek( aPos ); + } + + return aResult; + +} + +#if 0 +ULONG UCBStorageStream_Impl::CopySourceToTemporary( ULONG aLength ) +{ + // current position of the temporary stream is not changed + ULONG aResult = 0; + + if( m_bSourceRead ) + { + ULONG aPos = m_pStream->Tell(); + m_pStream->Seek( STREAM_SEEK_TO_END ); + aResult = ReadSourceWriteTemporary( aLength ); + m_pStream->Seek( aPos ); + } + + return aResult; + +} +#endif + +// UCBStorageStream_Impl must have a SvStream interface, because it then can be used as underlying stream +// of an OLEStorage; so every write access caused by storage operations marks the UCBStorageStream as modified +ULONG UCBStorageStream_Impl::GetData( void* pData, ULONG nSize ) +{ + ULONG aResult = 0; + + if( !Init() ) + return 0; + + + // read data that is in temporary stream + aResult = m_pStream->Read( pData, nSize ); + if( m_bSourceRead && aResult < nSize ) + { + // read the tail of the data from original stream + // copy this tail to the temporary stream + + ULONG aToRead = nSize - aResult; + pData = (void*)( (char*)pData + aResult ); + + try + { + Sequence<sal_Int8> aData( aToRead ); + ULONG aReaded = m_rSource->readBytes( aData, aToRead ); + aResult += m_pStream->Write( (void*)aData.getArray(), aReaded ); + memcpy( pData, aData.getArray(), aReaded ); + } +#if OSL_DEBUG_LEVEL > 1 + catch( Exception & e ) + { + OSL_ENSURE( FALSE, ::rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); +#else + catch( Exception & ) + { +#endif + } + + if( aResult < nSize ) + m_bSourceRead = FALSE; + } + + return aResult; +} + +ULONG UCBStorageStream_Impl::PutData( const void* pData, ULONG nSize ) +{ + if ( !(m_nMode & STREAM_WRITE) ) + { + SetError( ERRCODE_IO_ACCESSDENIED ); + return 0; // ?mav? + } + + if( !nSize || !Init() ) + return 0; + + ULONG aResult = m_pStream->Write( pData, nSize ); + + m_bModified = aResult > 0; + + return aResult; + +} + +ULONG UCBStorageStream_Impl::SeekPos( ULONG nPos ) +{ + if( !Init() ) + return 0; + + ULONG aResult; + + if( nPos == STREAM_SEEK_TO_END ) + { + m_pStream->Seek( STREAM_SEEK_TO_END ); + ReadSourceWriteTemporary(); + aResult = m_pStream->Tell(); + } + else + { + // the problem is that even if nPos is larger the the length + // of the stream the stream pointer will be moved to this position + // so we have to check if temporary stream does not contain required position + + if( m_pStream->Tell() > nPos + || m_pStream->Seek( STREAM_SEEK_TO_END ) > nPos ) + { + // no copiing is required + aResult = m_pStream->Seek( nPos ); + } + else + { + // the temp stream pointer points to the end now + aResult = m_pStream->Tell(); + + if( aResult < nPos ) + { + if( m_bSourceRead ) + { + aResult += ReadSourceWriteTemporary( nPos - aResult ); + if( aResult < nPos ) + m_bSourceRead = FALSE; + + DBG_ASSERT( aResult == m_pStream->Tell(), "Error in stream arithmetic!\n" ); + } + + if( (m_nMode & STREAM_WRITE) && !m_bSourceRead && aResult < nPos ) + { + // it means that all the Source stream was copied already + // but the required position still was not reached + // for writable streams it should be done + m_pStream->SetStreamSize( nPos ); + aResult = m_pStream->Seek( STREAM_SEEK_TO_END ); + DBG_ASSERT( aResult == nPos, "Error in stream arithmetic!\n" ); + } + } + } + } + + return aResult; +} + +void UCBStorageStream_Impl::SetSize( ULONG nSize ) +{ + if ( !(m_nMode & STREAM_WRITE) ) + { + SetError( ERRCODE_IO_ACCESSDENIED ); + return; + } + + if( !Init() ) + return; + + m_bModified = TRUE; + + if( m_bSourceRead ) + { + ULONG aPos = m_pStream->Tell(); + m_pStream->Seek( STREAM_SEEK_TO_END ); + if( m_pStream->Tell() < nSize ) + ReadSourceWriteTemporary( nSize - m_pStream->Tell() ); + m_pStream->Seek( aPos ); + } + + m_pStream->SetStreamSize( nSize ); + m_bSourceRead = FALSE; +} + +void UCBStorageStream_Impl::FlushData() +{ + if( m_pStream ) + { + CopySourceToTemporary(); + m_pStream->Flush(); + } + + m_bCommited = TRUE; +} + +void UCBStorageStream_Impl::SetError( sal_uInt32 nErr ) +{ + if ( !m_nError ) + { + m_nError = nErr; + SvStream::SetError( nErr ); + if ( m_pAntiImpl ) m_pAntiImpl->SetError( nErr ); + } +} + +void UCBStorageStream_Impl::ResetError() +{ + m_nError = 0; + SvStream::ResetError(); + if ( m_pAntiImpl ) + m_pAntiImpl->ResetError(); +} + +ULONG UCBStorageStream_Impl::GetSize() +{ + if( !Init() ) + return 0; + + ULONG nPos = m_pStream->Tell(); + m_pStream->Seek( STREAM_SEEK_TO_END ); + ReadSourceWriteTemporary(); + ULONG nRet = m_pStream->Tell(); + m_pStream->Seek( nPos ); + + return nRet; +} + +BaseStorage* UCBStorageStream_Impl::CreateStorage() +{ + // create an OLEStorage on a SvStream ( = this ) + // it gets the root attribute because otherwise it would probably not write before my root is commited + UCBStorageStream* pNewStorageStream = new UCBStorageStream( this ); + Storage *pStorage = new Storage( *pNewStorageStream, m_bDirect ); + + // GetError() call cleares error code for OLE storages, must be changed in future + long nTmpErr = pStorage->GetError(); + pStorage->SetError( nTmpErr ); + + m_bIsOLEStorage = !nTmpErr; + return static_cast< BaseStorage* > ( pStorage ); +} + +sal_Int16 UCBStorageStream_Impl::Commit() +{ + // send stream to the original content + // the parent storage is responsible for the correct handling of deleted contents + if ( m_bCommited || m_bIsOLEStorage || m_bDirect ) + { + // modified streams with OLEStorages on it have autocommit; it is assumed that the OLEStorage + // was commited as well ( if not opened in direct mode ) + + if ( m_bModified ) + { + try + { + CopySourceToTemporary(); + + // release all stream handles + Free(); + + // the temporary file does not exist only for truncated streams + DBG_ASSERT( m_aTempURL.Len() || ( m_nMode & STREAM_TRUNC ), "No temporary file to read from!"); + if ( !m_aTempURL.Len() && !( m_nMode & STREAM_TRUNC ) ) + throw RuntimeException(); + + // create wrapper to stream that is only used while reading inside package component + Reference < XInputStream > xStream = new FileStreamWrapper_Impl( m_aTempURL ); + + Any aAny; + InsertCommandArgument aArg; + aArg.Data = xStream; + aArg.ReplaceExisting = sal_True; + aAny <<= aArg; + m_pContent->executeCommand( ::rtl::OUString::createFromAscii("insert"), aAny ); + + // wrapper now controls lifetime of temporary file + m_aTempURL.Erase(); + + INetURLObject aObj( m_aURL ); + aObj.SetName( m_aName ); + m_aURL = aObj.GetMainURL( INetURLObject::NO_DECODE ); + m_bModified = FALSE; + m_bSourceRead = TRUE; + } + catch ( CommandAbortedException& ) + { + // any command wasn't executed successfully - not specified + SetError( ERRCODE_IO_GENERAL ); + return COMMIT_RESULT_FAILURE; + } + catch ( RuntimeException& ) + { + // any other error - not specified + SetError( ERRCODE_IO_GENERAL ); + return COMMIT_RESULT_FAILURE; + } + catch ( Exception& ) + { + // any other error - not specified + SetError( ERRCODE_IO_GENERAL ); + return COMMIT_RESULT_FAILURE; + } + + m_bCommited = FALSE; + return COMMIT_RESULT_SUCCESS; + } + } + + return COMMIT_RESULT_NOTHING_TO_DO; +} + +BOOL UCBStorageStream_Impl::Revert() +{ + // if an OLEStorage is created on this stream, no "revert" is neccessary because OLEStorages do nothing on "Revert" ! + if ( m_bCommited ) + { + DBG_ERROR("Revert while commit is in progress!" ); + return FALSE; // ??? + } + + Free(); + if ( m_aTempURL.Len() ) + { + ::utl::UCBContentHelper::Kill( m_aTempURL ); + m_aTempURL.Erase(); + } + + m_bSourceRead = FALSE; + try + { + m_rSource = m_pContent->openStream(); + if( m_rSource.is() ) + { + if ( m_pAntiImpl && ( m_nMode & STREAM_TRUNC ) ) + // stream is in use and should be truncated + m_bSourceRead = FALSE; + else + { + m_nMode &= ~STREAM_TRUNC; + m_bSourceRead = TRUE; + } + } + else + SetError( SVSTREAM_CANNOT_MAKE ); + } + catch ( ContentCreationException& ) + { + SetError( ERRCODE_IO_GENERAL ); + } + catch ( RuntimeException& ) + { + SetError( ERRCODE_IO_GENERAL ); + } + catch ( Exception& ) + { + } + + m_bModified = FALSE; + m_aName = m_aOriginalName; + m_aContentType = m_aOriginalContentType; + return ( GetError() == ERRCODE_NONE ); +} + +BOOL UCBStorageStream_Impl::Clear() +{ + BOOL bRet = ( m_pAntiImpl == NULL ); + DBG_ASSERT( bRet, "Removing used stream!" ); + if( bRet ) + { + Free(); + } + + return bRet; +} + +void UCBStorageStream_Impl::Free() +{ +#if OSL_DEBUG_LEVEL > 1 + if ( m_pStream ) + { + if ( m_aTempURL.Len() ) + --nOpenFiles; + else + --nOpenStreams; + } +#endif + + m_nRepresentMode = nonset; + m_rSource = Reference< XInputStream >(); + DELETEZ( m_pStream ); +} + +void UCBStorageStream_Impl::PrepareCachedForReopen( StreamMode nMode ) +{ + sal_Bool isWritable = (( m_nMode & STREAM_WRITE ) != 0 ); + if ( isWritable ) + { + // once stream was writable, never reset to readonly + nMode |= STREAM_WRITE; + } + + m_nMode = nMode; + Free(); + + if ( nMode & STREAM_TRUNC ) + { + m_bSourceRead = 0; // usually it should be 0 already but just in case... + + if ( m_aTempURL.Len() ) + { + ::utl::UCBContentHelper::Kill( m_aTempURL ); + m_aTempURL.Erase(); + } + } +} + +UCBStorageStream::UCBStorageStream( const String& rName, StreamMode nMode, BOOL bDirect, const ByteString* pKey ) +{ + // pImp must be initialized in the body, because otherwise the vtable of the stream is not initialized + // to class UCBStorageStream ! + pImp = new UCBStorageStream_Impl( rName, nMode, this, bDirect, pKey ); + pImp->AddRef(); // use direct refcounting because in header file only a pointer should be used + StorageBase::m_nMode = pImp->m_nMode; +} + +UCBStorageStream::UCBStorageStream( const String& rName, StreamMode nMode, BOOL bDirect, const ByteString* pKey, BOOL bRepair, Reference< XProgressHandler > xProgress ) +{ + // pImp must be initialized in the body, because otherwise the vtable of the stream is not initialized + // to class UCBStorageStream ! + pImp = new UCBStorageStream_Impl( rName, nMode, this, bDirect, pKey, bRepair, xProgress ); + pImp->AddRef(); // use direct refcounting because in header file only a pointer should be used + StorageBase::m_nMode = pImp->m_nMode; +} + +UCBStorageStream::UCBStorageStream( UCBStorageStream_Impl *pImpl ) + : pImp( pImpl ) +{ + pImp->AddRef(); // use direct refcounting because in header file only a pointer should be used + pImp->m_pAntiImpl = this; + SetError( pImp->m_nError ); + StorageBase::m_nMode = pImp->m_nMode; +} + +UCBStorageStream::~UCBStorageStream() +{ + if ( pImp->m_nMode & STREAM_WRITE ) + pImp->Flush(); + pImp->m_pAntiImpl = NULL; + pImp->Free(); + pImp->ReleaseRef(); +} + +ULONG UCBStorageStream::Read( void * pData, ULONG nSize ) +{ + //return pImp->m_pStream->Read( pData, nSize ); + return pImp->GetData( pData, nSize ); +} + +ULONG UCBStorageStream::Write( const void* pData, ULONG nSize ) +{ +/* + // mba: does occur in writer ! + if ( pImp->m_bCommited ) + { + DBG_ERROR("Writing while commit is in progress!" ); + return 0; + } +*/ + // pImp->m_bModified = TRUE; + //return pImp->m_pStream->Write( pData, nSize ); + return pImp->PutData( pData, nSize ); +} + +ULONG UCBStorageStream::Seek( ULONG nPos ) +{ + //return pImp->m_pStream->Seek( nPos ); + return pImp->Seek( nPos ); +} + +ULONG UCBStorageStream::Tell() +{ + if( !pImp->Init() ) + return 0; + return pImp->m_pStream->Tell(); +} + +void UCBStorageStream::Flush() +{ + // streams are never really transacted, so flush also means commit ! + Commit(); +} + +BOOL UCBStorageStream::SetSize( ULONG nNewSize ) +{ +/* + if ( pImp->m_bCommited ) + { + DBG_ERROR("Changing stream size while commit is in progress!" ); + return FALSE; + } +*/ + // pImp->m_bModified = TRUE; + //return pImp->m_pStream->SetStreamSize( nNewSize ); + pImp->SetSize( nNewSize ); + return !pImp->GetError(); +} + +BOOL UCBStorageStream::Validate( BOOL bWrite ) const +{ + return ( !bWrite || ( pImp->m_nMode & STREAM_WRITE ) ); +} + +BOOL UCBStorageStream::ValidateMode( StreamMode m ) const +{ + // ??? + if( m == ( STREAM_READ | STREAM_TRUNC ) ) // from stg.cxx + return TRUE; + USHORT nCurMode = 0xFFFF; + if( ( m & 3 ) == STREAM_READ ) + { + // only SHARE_DENYWRITE or SHARE_DENYALL allowed + if( ( ( m & STREAM_SHARE_DENYWRITE ) + && ( nCurMode & STREAM_SHARE_DENYWRITE ) ) + || ( ( m & STREAM_SHARE_DENYALL ) + && ( nCurMode & STREAM_SHARE_DENYALL ) ) ) + return TRUE; + } + else + { + // only SHARE_DENYALL allowed + // storages open in r/o mode are OK, since only + // the commit may fail + if( ( m & STREAM_SHARE_DENYALL ) + && ( nCurMode & STREAM_SHARE_DENYALL ) ) + return TRUE; + } + + return TRUE; +} + +const SvStream* UCBStorageStream::GetSvStream() const +{ + if( !pImp->Init() ) + return NULL; + + pImp->CopySourceToTemporary(); + return pImp->m_pStream; // should not live longer then pImp!!! +} + +SvStream* UCBStorageStream::GetModifySvStream() +{ + return (SvStream*)pImp; +} + +Reference< XInputStream > UCBStorageStream::GetXInputStream() const +{ + return pImp->GetXInputStream(); +} + +BOOL UCBStorageStream::Equals( const BaseStorageStream& rStream ) const +{ + // ??? + return ((BaseStorageStream*) this ) == &rStream; +} + +BOOL UCBStorageStream::Commit() +{ + // mark this stream for sending it on root commit + pImp->FlushData(); + return TRUE; +} + +BOOL UCBStorageStream::Revert() +{ + return pImp->Revert(); +} + +BOOL UCBStorageStream::CopyTo( BaseStorageStream* pDestStm ) +{ + if( !pImp->Init() ) + return FALSE; + + UCBStorageStream* pStg = PTR_CAST( UCBStorageStream, pDestStm ); + if ( pStg ) + pStg->pImp->m_aContentType = pImp->m_aContentType; + + pDestStm->SetSize( 0 ); + Seek( STREAM_SEEK_TO_END ); + INT32 n = Tell(); + if( n < 0 ) + return FALSE; + + if( pDestStm->SetSize( n ) && n ) + { + BYTE* p = new BYTE[ 4096 ]; + Seek( 0L ); + pDestStm->Seek( 0L ); + while( n ) + { + UINT32 nn = n; + if( nn > 4096 ) + nn = 4096; + if( Read( p, nn ) != nn ) + break; + if( pDestStm->Write( p, nn ) != nn ) + break; + n -= nn; + } + + delete[] p; + } + + return TRUE; +} + +BOOL UCBStorageStream::SetProperty( const String& rName, const ::com::sun::star::uno::Any& rValue ) +{ + if ( rName.CompareToAscii("Title") == COMPARE_EQUAL ) + return FALSE; + + if ( rName.CompareToAscii("MediaType") == COMPARE_EQUAL ) + { + ::rtl::OUString aTmp; + rValue >>= aTmp; + pImp->m_aContentType = aTmp; + } + + try + { + if ( pImp->m_pContent ) + { + pImp->m_pContent->setPropertyValue( rName, rValue ); + return TRUE; + } + } + catch ( Exception& ) + { + } + + return FALSE; +} + +BOOL UCBStorageStream::GetProperty( const String& rName, ::com::sun::star::uno::Any& rValue ) +{ + try + { + if ( pImp->m_pContent ) + { + rValue = pImp->m_pContent->getPropertyValue( rName ); + return TRUE; + } + } + catch ( Exception& ) + { + } + + return FALSE; +} + +UCBStorage::UCBStorage( SvStream& rStrm, BOOL bDirect ) +{ + String aURL = GetLinkedFile( rStrm ); + if ( aURL.Len() ) + { + StreamMode nMode = STREAM_READ; + if( rStrm.IsWritable() ) + nMode = STREAM_READ | STREAM_WRITE; + + ::ucbhelper::Content aContent( aURL, Reference < XCommandEnvironment >() ); + pImp = new UCBStorage_Impl( aContent, aURL, nMode, this, bDirect, TRUE ); + } + else + { + // pImp must be initialized in the body, because otherwise the vtable of the stream is not initialized + // to class UCBStorage ! + pImp = new UCBStorage_Impl( rStrm, this, bDirect ); + } + + pImp->AddRef(); + pImp->Init(); + StorageBase::m_nMode = pImp->m_nMode; +} + +UCBStorage::UCBStorage( const ::ucbhelper::Content& rContent, const String& rName, StreamMode nMode, BOOL bDirect, BOOL bIsRoot ) +{ + // pImp must be initialized in the body, because otherwise the vtable of the stream is not initialized + // to class UCBStorage ! + pImp = new UCBStorage_Impl( rContent, rName, nMode, this, bDirect, bIsRoot ); + pImp->AddRef(); + pImp->Init(); + StorageBase::m_nMode = pImp->m_nMode; +} + +UCBStorage::UCBStorage( const String& rName, StreamMode nMode, BOOL bDirect, BOOL bIsRoot, BOOL bIsRepair, Reference< XProgressHandler > xProgressHandler ) +{ + // pImp must be initialized in the body, because otherwise the vtable of the stream is not initialized + // to class UCBStorage ! + pImp = new UCBStorage_Impl( rName, nMode, this, bDirect, bIsRoot, bIsRepair, xProgressHandler ); + pImp->AddRef(); + pImp->Init(); + StorageBase::m_nMode = pImp->m_nMode; +} + +UCBStorage::UCBStorage( const String& rName, StreamMode nMode, BOOL bDirect, BOOL bIsRoot ) +{ + // pImp must be initialized in the body, because otherwise the vtable of the stream is not initialized + // to class UCBStorage ! + pImp = new UCBStorage_Impl( rName, nMode, this, bDirect, bIsRoot, sal_False, Reference< XProgressHandler >() ); + pImp->AddRef(); + pImp->Init(); + StorageBase::m_nMode = pImp->m_nMode; +} + +UCBStorage::UCBStorage( UCBStorage_Impl *pImpl ) + : pImp( pImpl ) +{ + pImp->m_pAntiImpl = this; + SetError( pImp->m_nError ); + pImp->AddRef(); // use direct refcounting because in header file only a pointer should be used + StorageBase::m_nMode = pImp->m_nMode; +} + +UCBStorage::~UCBStorage() +{ + if ( pImp->m_bIsRoot && pImp->m_bDirect && ( !pImp->m_pTempFile || pImp->m_pSource ) ) + // DirectMode is simulated with an AutoCommit + Commit(); + + pImp->m_pAntiImpl = NULL; + pImp->ReleaseRef(); +} + +UCBStorage_Impl::UCBStorage_Impl( const ::ucbhelper::Content& rContent, const String& rName, StreamMode nMode, UCBStorage* pStorage, BOOL bDirect, BOOL bIsRoot, BOOL bIsRepair, Reference< XProgressHandler > xProgressHandler ) + : m_pAntiImpl( pStorage ) + , m_pContent( new ::ucbhelper::Content( rContent ) ) + , m_pTempFile( NULL ) + , m_pSource( NULL ) + //, m_pStream( NULL ) + , m_nError( 0 ) + , m_nMode( nMode ) + , m_bModified( FALSE ) + , m_bCommited( FALSE ) + , m_bDirect( bDirect ) + , m_bIsRoot( bIsRoot ) + , m_bDirty( FALSE ) + , m_bIsLinked( TRUE ) + , m_bListCreated( FALSE ) + , m_nFormat( 0 ) + , m_aClassId( SvGlobalName() ) + , m_bRepairPackage( bIsRepair ) + , m_xProgressHandler( xProgressHandler ) + , m_pUNOStorageHolderList( NULL ) + +{ + String aName( rName ); + if( !aName.Len() ) + { + // no name given = use temporary name! + DBG_ASSERT( m_bIsRoot, "SubStorage must have a name!" ); + m_pTempFile = new ::utl::TempFile; + m_pTempFile->EnableKillingFile( TRUE ); + m_aName = m_aOriginalName = aName = m_pTempFile->GetURL(); + } + + m_aURL = rName; +} + +UCBStorage_Impl::UCBStorage_Impl( const String& rName, StreamMode nMode, UCBStorage* pStorage, BOOL bDirect, BOOL bIsRoot, BOOL bIsRepair, Reference< XProgressHandler > xProgressHandler ) + : m_pAntiImpl( pStorage ) + , m_pContent( NULL ) + , m_pTempFile( NULL ) + , m_pSource( NULL ) + //, m_pStream( NULL ) + , m_nError( 0 ) + , m_nMode( nMode ) + , m_bModified( FALSE ) + , m_bCommited( FALSE ) + , m_bDirect( bDirect ) + , m_bIsRoot( bIsRoot ) + , m_bDirty( FALSE ) + , m_bIsLinked( FALSE ) + , m_bListCreated( FALSE ) + , m_nFormat( 0 ) + , m_aClassId( SvGlobalName() ) + , m_bRepairPackage( bIsRepair ) + , m_xProgressHandler( xProgressHandler ) + , m_pUNOStorageHolderList( NULL ) +{ + String aName( rName ); + if( !aName.Len() ) + { + // no name given = use temporary name! + DBG_ASSERT( m_bIsRoot, "SubStorage must have a name!" ); + m_pTempFile = new ::utl::TempFile; + m_pTempFile->EnableKillingFile( TRUE ); + m_aName = m_aOriginalName = aName = m_pTempFile->GetURL(); + } + + if ( m_bIsRoot ) + { + // create the special package URL for the package content + String aTemp = String::CreateFromAscii("vnd.sun.star.pkg://"); + aTemp += String(INetURLObject::encode( aName, INetURLObject::PART_AUTHORITY, '%', INetURLObject::ENCODE_ALL )); + m_aURL = aTemp; + + if ( m_nMode & STREAM_WRITE ) + { + // the root storage opens the package, so make sure that there is any + SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( aName, STREAM_STD_READWRITE, m_pTempFile != 0 /* bFileExists */ ); + delete pStream; + } + } + else + { + // substorages are opened like streams: the URL is a "child URL" of the root package URL + m_aURL = rName; + if ( m_aURL.CompareToAscii( "vnd.sun.star.pkg://", 19 ) != 0 ) + m_bIsLinked = TRUE; + } +} + +UCBStorage_Impl::UCBStorage_Impl( SvStream& rStream, UCBStorage* pStorage, BOOL bDirect ) + : m_pAntiImpl( pStorage ) + , m_pContent( NULL ) + , m_pTempFile( new ::utl::TempFile ) + , m_pSource( &rStream ) + , m_nError( 0 ) + , m_bModified( FALSE ) + , m_bCommited( FALSE ) + , m_bDirect( bDirect ) + , m_bIsRoot( TRUE ) + , m_bDirty( FALSE ) + , m_bIsLinked( FALSE ) + , m_bListCreated( FALSE ) + , m_nFormat( 0 ) + , m_aClassId( SvGlobalName() ) + , m_bRepairPackage( FALSE ) + , m_pUNOStorageHolderList( NULL ) +{ + // opening in direct mode is too fuzzy because the data is transferred to the stream in the Commit() call, + // which will be called in the storages' dtor + m_pTempFile->EnableKillingFile( TRUE ); + DBG_ASSERT( !bDirect, "Storage on a stream must not be opened in direct mode!" ); + + // UCBStorages work on a content, so a temporary file for a content must be created, even if the stream is only + // accessed readonly + // the root storage opens the package; create the special package URL for the package content + String aTemp = String::CreateFromAscii("vnd.sun.star.pkg://"); + aTemp += String(INetURLObject::encode( m_pTempFile->GetURL(), INetURLObject::PART_AUTHORITY, '%', INetURLObject::ENCODE_ALL )); + m_aURL = aTemp; + + // copy data into the temporary file + SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( m_pTempFile->GetURL(), STREAM_STD_READWRITE, sal_True /* bFileExists */ ); + if ( pStream ) + { + rStream.Seek(0); + rStream >> *pStream; + pStream->Flush(); + DELETEZ( pStream ); + } + + // close stream and let content access the file + m_pSource->Seek(0); + + // check opening mode + m_nMode = STREAM_READ; + if( rStream.IsWritable() ) + m_nMode = STREAM_READ | STREAM_WRITE; +} + +void UCBStorage_Impl::Init() +{ + // name is last segment in URL + INetURLObject aObj( m_aURL ); + if ( !m_aName.Len() ) + // if the name was not already set to a temp name + m_aName = m_aOriginalName = aObj.GetLastName(); + + // don't create the content for disk spanned files, avoid too early access to directory and/or manifest + if ( !m_pContent && !( m_nMode & STORAGE_DISKSPANNED_MODE ) ) + CreateContent(); + + if ( m_nMode & STORAGE_DISKSPANNED_MODE ) + { + // Hack! Avoid access to the manifest file until mediatype is not available in the first segment of a + // disk spanned file + m_aContentType = m_aOriginalContentType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("application/vnd.sun.xml.impress") ); + } + else if ( m_pContent ) + { + if ( m_bIsLinked ) + { + if( m_bIsRoot ) + { + ReadContent(); + if ( m_nError == ERRCODE_NONE ) + { + // read the manifest.xml file + aObj.Append( String( RTL_CONSTASCII_USTRINGPARAM("META-INF") ) ); + aObj.Append( String( RTL_CONSTASCII_USTRINGPARAM("manifest.xml") ) ); + + // create input stream + SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( aObj.GetMainURL( INetURLObject::NO_DECODE ), STREAM_STD_READ ); + // no stream means no manifest.xml + if ( pStream ) + { + if ( !pStream->GetError() ) + { + ::utl::OInputStreamWrapper* pHelper = new ::utl::OInputStreamWrapper( *pStream ); + com::sun::star::uno::Reference < ::com::sun::star::io::XInputStream > xInputStream( pHelper ); + + // create a manifest reader object that will read in the manifest from the stream + Reference < ::com::sun::star::packages::manifest::XManifestReader > xReader = + Reference< ::com::sun::star::packages::manifest::XManifestReader > + ( ::comphelper::getProcessServiceFactory()->createInstance( + ::rtl::OUString::createFromAscii( "com.sun.star.packages.manifest.ManifestReader" )), UNO_QUERY) ; + Sequence < Sequence < PropertyValue > > aProps = xReader->readManifestSequence( xInputStream ); + + // cleanup + xReader = NULL; + xInputStream = NULL; + SetProps( aProps, String() ); + } + + delete pStream; + } + } + } + else + ReadContent(); + } + else + { + // get the manifest information from the package + try { + Any aAny = m_pContent->getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) ); + rtl::OUString aTmp; + if ( ( aAny >>= aTmp ) && aTmp.getLength() ) + m_aContentType = m_aOriginalContentType = aTmp; + } + catch( Exception& ) + { + DBG_ASSERT( sal_False, + "getPropertyValue has thrown an exception! Please let developers know the scenario!" ); + } + } + } + + if ( m_aContentType.Len() ) + { + // get the clipboard format using the content type + ::com::sun::star::datatransfer::DataFlavor aDataFlavor; + aDataFlavor.MimeType = m_aContentType; + m_nFormat = SotExchange::GetFormat( aDataFlavor ); + + // get the ClassId using the clipboard format ( internal table ) + m_aClassId = GetClassId_Impl( m_nFormat ); + + // get human presentable name using the clipboard format + SotExchange::GetFormatDataFlavor( m_nFormat, aDataFlavor ); + m_aUserTypeName = aDataFlavor.HumanPresentableName; + + if( m_pContent && !m_bIsLinked && m_aClassId != SvGlobalName() ) + ReadContent(); + } +} + +void UCBStorage_Impl::CreateContent() +{ + try + { + // create content; where to put StreamMode ?! ( already done when opening the file of the package ? ) + Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv; + + ::rtl::OUString aTemp( m_aURL ); + + if ( m_bRepairPackage ) + { + xComEnv = new ::ucbhelper::CommandEnvironment( Reference< ::com::sun::star::task::XInteractionHandler >(), + m_xProgressHandler ); + aTemp += rtl::OUString::createFromAscii("?repairpackage"); + } + + m_pContent = new ::ucbhelper::Content( aTemp, xComEnv ); + } + catch ( ContentCreationException& ) + { + // content could not be created + SetError( SVSTREAM_CANNOT_MAKE ); + } + catch ( RuntimeException& ) + { + // any other error - not specified + SetError( SVSTREAM_CANNOT_MAKE ); + } +} + +void UCBStorage_Impl::ReadContent() +{ + if ( m_bListCreated ) + return; + + m_bListCreated = TRUE; + + // create cursor for access to children + Sequence< ::rtl::OUString > aProps(4); + ::rtl::OUString* pProps = aProps.getArray(); + pProps[0] = ::rtl::OUString::createFromAscii( "Title" ); + pProps[1] = ::rtl::OUString::createFromAscii( "IsFolder" ); + pProps[2] = ::rtl::OUString::createFromAscii( "MediaType" ); + pProps[3] = ::rtl::OUString::createFromAscii( "Size" ); + ::ucbhelper::ResultSetInclude eInclude = ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS; + + try + { + GetContent(); + if ( !m_pContent ) + return; + + Reference< XResultSet > xResultSet = m_pContent->createCursor( aProps, eInclude ); + Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY ); + Reference< XRow > xRow( xResultSet, UNO_QUERY ); + if ( xResultSet.is() ) + { + while ( xResultSet->next() ) + { + // insert all into the children list + ::rtl::OUString aTitle( xRow->getString(1) ); + ::rtl::OUString aContentType; + if ( m_bIsLinked ) + { + // unpacked storages have to deal with the meta-inf folder by themselves + if( aTitle.equalsAscii("META-INF") ) + continue; + } + else + { + aContentType = xRow->getString(3); + } + + BOOL bIsFolder( xRow->getBoolean(2) ); + sal_Int64 nSize = xRow->getLong(4); + UCBStorageElement_Impl* pElement = new UCBStorageElement_Impl( aTitle, bIsFolder, (ULONG) nSize ); + m_aChildrenList.Insert( pElement, LIST_APPEND ); + + sal_Bool bIsOfficeDocument = m_bIsLinked || ( m_aClassId != SvGlobalName() ); + if ( bIsFolder ) + { + if ( m_bIsLinked ) + OpenStorage( pElement, m_nMode, m_bDirect ); + if ( pElement->m_xStorage.Is() ) + pElement->m_xStorage->Init(); + } + else if ( bIsOfficeDocument ) + { + // streams can be external OLE objects, so they are now folders, but storages! + String aName( m_aURL ); + aName += '/'; + aName += String( xRow->getString(1) ); + + Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv; + if ( m_bRepairPackage ) + { + xComEnv = new ::ucbhelper::CommandEnvironment( Reference< ::com::sun::star::task::XInteractionHandler >(), + m_xProgressHandler ); + aName += String( RTL_CONSTASCII_USTRINGPARAM( "?repairpackage" ) ); + } + + ::ucbhelper::Content aContent( aName, xComEnv ); + + ::rtl::OUString aMediaType; + Any aAny = aContent.getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) ); + if ( ( aAny >>= aMediaType ) && ( aMediaType.compareToAscii("application/vnd.sun.star.oleobject") == 0 ) ) + pElement->m_bIsStorage = TRUE; + else if ( !aMediaType.getLength() ) + { + // older files didn't have that special content type, so they must be detected + OpenStream( pElement, STREAM_STD_READ, m_bDirect ); + if ( Storage::IsStorageFile( pElement->m_xStream ) ) + pElement->m_bIsStorage = TRUE; + else + pElement->m_xStream->Free(); + } + } + } + } + } + catch ( InteractiveIOException& r ) + { + if ( r.Code != IOErrorCode_NOT_EXISTING ) + SetError( ERRCODE_IO_GENERAL ); + } + catch ( CommandAbortedException& ) + { + // any command wasn't executed successfully - not specified + if ( !( m_nMode & STREAM_WRITE ) ) + // if the folder was just inserted and not already commited, this is not an error! + SetError( ERRCODE_IO_GENERAL ); + } + catch ( RuntimeException& ) + { + // any other error - not specified + SetError( ERRCODE_IO_GENERAL ); + } + catch ( ResultSetException& ) + { + // means that the package file is broken + SetError( ERRCODE_IO_BROKENPACKAGE ); + } + catch ( SQLException& ) + { + // means that the file can be broken + SetError( ERRCODE_IO_WRONGFORMAT ); + } + catch ( Exception& ) + { + // any other error - not specified + SetError( ERRCODE_IO_GENERAL ); + } +} + +void UCBStorage_Impl::SetError( long nError ) +{ + if ( !m_nError ) + { + m_nError = nError; + if ( m_pAntiImpl ) m_pAntiImpl->SetError( nError ); + } +} + +sal_Int32 UCBStorage_Impl::GetObjectCount() +{ + sal_Int32 nCount = m_aChildrenList.Count(); + UCBStorageElement_Impl* pElement = m_aChildrenList.First(); + while ( pElement ) + { + DBG_ASSERT( !pElement->m_bIsFolder || pElement->m_xStorage.Is(), "Storage should be open!" ); + if ( pElement->m_bIsFolder && pElement->m_xStorage.Is() ) + nCount += pElement->m_xStorage->GetObjectCount(); + pElement = m_aChildrenList.Next(); + } + + return nCount; +} + +::rtl::OUString Find_Impl( const Sequence < Sequence < PropertyValue > >& rSequence, const ::rtl::OUString& rPath ) +{ + BOOL bFound = FALSE; + for ( sal_Int32 nSeqs=0; nSeqs<rSequence.getLength(); nSeqs++ ) + { + const Sequence < PropertyValue >& rMyProps = rSequence[nSeqs]; + ::rtl::OUString aType; + + for ( sal_Int32 nProps=0; nProps<rMyProps.getLength(); nProps++ ) + { + const PropertyValue& rAny = rMyProps[nProps]; + if ( rAny.Name.equalsAscii("FullPath") ) + { + rtl::OUString aTmp; + if ( ( rAny.Value >>= aTmp ) && aTmp == rPath ) + bFound = TRUE; + if ( aType.getLength() ) + break; + } + else if ( rAny.Name.equalsAscii("MediaType") ) + { + if ( ( rAny.Value >>= aType ) && aType.getLength() && bFound ) + break; + } + } + + if ( bFound ) + return aType; + } + + return ::rtl::OUString(); +} + +void UCBStorage_Impl::SetProps( const Sequence < Sequence < PropertyValue > >& rSequence, const String& rPath ) +{ + String aPath( rPath ); + if ( !m_bIsRoot ) + aPath += m_aName; + aPath += '/'; + + m_aContentType = m_aOriginalContentType = Find_Impl( rSequence, aPath ); + + if ( m_bIsRoot ) + // the "FullPath" of a child always starts without '/' + aPath.Erase(); + + UCBStorageElement_Impl* pElement = m_aChildrenList.First(); + while ( pElement ) + { + DBG_ASSERT( !pElement->m_bIsFolder || pElement->m_xStorage.Is(), "Storage should be open!" ); + if ( pElement->m_bIsFolder && pElement->m_xStorage.Is() ) + pElement->m_xStorage->SetProps( rSequence, aPath ); + else + { + String aElementPath( aPath ); + aElementPath += pElement->m_aName; + pElement->SetContentType( Find_Impl( rSequence, aElementPath ) ); + } + + pElement = m_aChildrenList.Next(); + } + + if ( m_aContentType.Len() ) + { + // get the clipboard format using the content type + ::com::sun::star::datatransfer::DataFlavor aDataFlavor; + aDataFlavor.MimeType = m_aContentType; + m_nFormat = SotExchange::GetFormat( aDataFlavor ); + + // get the ClassId using the clipboard format ( internal table ) + m_aClassId = GetClassId_Impl( m_nFormat ); + + // get human presentable name using the clipboard format + SotExchange::GetFormatDataFlavor( m_nFormat, aDataFlavor ); + m_aUserTypeName = aDataFlavor.HumanPresentableName; + } +} + +void UCBStorage_Impl::GetProps( sal_Int32& nProps, Sequence < Sequence < PropertyValue > >& rSequence, const String& rPath ) +{ + // first my own properties + Sequence < PropertyValue > aProps(2); + + // first property is the "FullPath" name + // it's '/' for the root storage and m_aName for each element, followed by a '/' if it's a folder + String aPath( rPath ); + if ( !m_bIsRoot ) + aPath += m_aName; + aPath += '/'; + aProps[0].Name = ::rtl::OUString::createFromAscii("MediaType"); + aProps[0].Value <<= (::rtl::OUString ) m_aContentType; + aProps[1].Name = ::rtl::OUString::createFromAscii("FullPath"); + aProps[1].Value <<= (::rtl::OUString ) aPath; + rSequence[ nProps++ ] = aProps; + + if ( m_bIsRoot ) + // the "FullPath" of a child always starts without '/' + aPath.Erase(); + + // now the properties of my elements + UCBStorageElement_Impl* pElement = m_aChildrenList.First(); + while ( pElement ) + { + DBG_ASSERT( !pElement->m_bIsFolder || pElement->m_xStorage.Is(), "Storage should be open!" ); + if ( pElement->m_bIsFolder && pElement->m_xStorage.Is() ) + // storages add there properties by themselves ( see above ) + pElement->m_xStorage->GetProps( nProps, rSequence, aPath ); + else + { + // properties of streams + String aElementPath( aPath ); + aElementPath += pElement->m_aName; + aProps[0].Name = ::rtl::OUString::createFromAscii("MediaType"); + aProps[0].Value <<= (::rtl::OUString ) pElement->GetContentType(); + aProps[1].Name = ::rtl::OUString::createFromAscii("FullPath"); + aProps[1].Value <<= (::rtl::OUString ) aElementPath; + rSequence[ nProps++ ] = aProps; + } + + pElement = m_aChildrenList.Next(); + } +} + +UCBStorage_Impl::~UCBStorage_Impl() +{ + if ( m_pUNOStorageHolderList ) + { + for ( UNOStorageHolderList::iterator aIter = m_pUNOStorageHolderList->begin(); + aIter != m_pUNOStorageHolderList->end(); aIter++ ) + if ( *aIter ) + { + (*aIter)->InternalDispose(); + (*aIter)->release(); + (*aIter) = NULL; + } + + m_pUNOStorageHolderList->clear(); + DELETEZ( m_pUNOStorageHolderList ); + } + + // first delete elements! + UCBStorageElement_Impl* pElement = m_aChildrenList.First(); + while ( pElement ) + { + delete pElement; + pElement = m_aChildrenList.Next(); + } + + m_aChildrenList.Clear(); + delete m_pContent; + delete m_pTempFile; +} + +BOOL UCBStorage_Impl::Insert( ::ucbhelper::Content *pContent ) +{ + // a new substorage is inserted into a UCBStorage ( given by the parameter pContent ) + // it must be inserted with a title and a type + BOOL bRet = FALSE; + + try + { + Sequence< ContentInfo > aInfo = pContent->queryCreatableContentsInfo(); + sal_Int32 nCount = aInfo.getLength(); + if ( nCount == 0 ) + return sal_False; + + for ( sal_Int32 i = 0; i < nCount; ++i ) + { + // Simply look for the first KIND_FOLDER... + const ContentInfo & rCurr = aInfo[i]; + if ( rCurr.Attributes & ContentInfoAttribute::KIND_FOLDER ) + { + // Make sure the only required bootstrap property is "Title", + const Sequence< Property > & rProps = rCurr.Properties; + if ( rProps.getLength() != 1 ) + continue; + + if ( !rProps[ 0 ].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + continue; + + Sequence < ::rtl::OUString > aNames(1); + ::rtl::OUString* pNames = aNames.getArray(); + pNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ); + Sequence < Any > aValues(1); + Any* pValues = aValues.getArray(); + pValues[0] = makeAny( ::rtl::OUString( m_aName ) ); + + Content aNewFolder; + if ( !pContent->insertNewContent( rCurr.Type, aNames, aValues, aNewFolder ) ) + continue; + + // remove old content, create an "empty" new one and initialize it with the new inserted + DELETEZ( m_pContent ); + m_pContent = new ::ucbhelper::Content( aNewFolder ); + bRet = TRUE; + } + } + } + catch ( CommandAbortedException& ) + { + // any command wasn't executed successfully - not specified + SetError( ERRCODE_IO_GENERAL ); + } + catch ( RuntimeException& ) + { + // any other error - not specified + SetError( ERRCODE_IO_GENERAL ); + } + catch ( Exception& ) + { + // any other error - not specified + SetError( ERRCODE_IO_GENERAL ); + } + + return bRet; +} + +sal_Int16 UCBStorage_Impl::Commit() +{ + // send all changes to the package + UCBStorageElement_Impl* pElement = m_aChildrenList.First(); + sal_Int16 nRet = COMMIT_RESULT_NOTHING_TO_DO; + + // there is nothing to do if the storage has been opened readonly or if it was opened in transacted mode and no + // commit command has been sent + if ( ( m_nMode & STREAM_WRITE ) && ( m_bCommited || m_bDirect ) ) + { + try + { + // all errors will be caught in the "catch" statement outside the loop + while ( pElement && nRet ) + { + ::ucbhelper::Content* pContent = pElement->GetContent(); + BOOL bDeleteContent = FALSE; + if ( !pContent && pElement->IsModified() ) + { + // if the element has never been opened, no content has been created until now + bDeleteContent = TRUE; // remember to delete it later + String aName( m_aURL ); + aName += '/'; + aName += pElement->m_aOriginalName; + pContent = new ::ucbhelper::Content( aName, Reference< ::com::sun::star::ucb::XCommandEnvironment > () ); + } + + if ( pElement->m_bIsRemoved ) + { + // was it inserted, then removed (so there would be nothing to do!) + if ( !pElement->m_bIsInserted ) + { + // first remove all open stream handles + if( !pElement->m_xStream.Is() || pElement->m_xStream->Clear() ) + { + pContent->executeCommand( ::rtl::OUString::createFromAscii("delete"), makeAny( sal_Bool( sal_True ) ) ); + nRet = COMMIT_RESULT_SUCCESS; + } + else + // couldn't release stream because there are external references to it + nRet = COMMIT_RESULT_FAILURE; + } + } + else + { + sal_Int16 nLocalRet = COMMIT_RESULT_NOTHING_TO_DO; + if ( pElement->m_xStorage.Is() ) + { + // element is a storage + // do a commit in the following cases: + // - if storage is already inserted, and changed + // - storage is not in a package + // - it's a new storage, try to insert and commit if successful inserted + if ( !pElement->m_bIsInserted || m_bIsLinked || pElement->m_xStorage->Insert( m_pContent ) ) + { + nLocalRet = pElement->m_xStorage->Commit(); + pContent = pElement->GetContent(); + } + } + else if ( pElement->m_xStream.Is() ) + { + // element is a stream + nLocalRet = pElement->m_xStream->Commit(); + if ( pElement->m_xStream->m_bIsOLEStorage ) + { + // OLE storage should be stored encrytped, if the storage uses encryption + pElement->m_xStream->m_aContentType = String::CreateFromAscii("application/vnd.sun.star.oleobject"); + Any aValue; + aValue <<= (BOOL) TRUE; + pElement->m_xStream->m_pContent->setPropertyValue(String::CreateFromAscii("Encrypted"), aValue ); + } + + pContent = pElement->GetContent(); + } + + if ( pElement->m_aName != pElement->m_aOriginalName ) + { + // name ( title ) of the element was changed + nLocalRet = COMMIT_RESULT_SUCCESS; + Any aAny; + aAny <<= (rtl::OUString) pElement->m_aName; + pContent->setPropertyValue( ::rtl::OUString::createFromAscii("Title"), aAny ); + } + + if ( pElement->IsLoaded() && pElement->GetContentType() != pElement->GetOriginalContentType() ) + { + // mediatype of the element was changed + nLocalRet = COMMIT_RESULT_SUCCESS; + Any aAny; + aAny <<= (rtl::OUString) pElement->GetContentType(); + pContent->setPropertyValue( ::rtl::OUString::createFromAscii("MediaType"), aAny ); + } + + if ( nLocalRet != COMMIT_RESULT_NOTHING_TO_DO ) + nRet = nLocalRet; + } + + if ( bDeleteContent ) + // content was created inside the loop + delete pContent; + + if ( nRet == COMMIT_RESULT_FAILURE ) + break; + + pElement = m_aChildrenList.Next(); + } + } + catch ( ContentCreationException& ) + { + // content could not be created + SetError( ERRCODE_IO_NOTEXISTS ); + return COMMIT_RESULT_FAILURE; + } + catch ( CommandAbortedException& ) + { + // any command wasn't executed successfully - not specified + SetError( ERRCODE_IO_GENERAL ); + return COMMIT_RESULT_FAILURE; + } + catch ( RuntimeException& ) + { + // any other error - not specified + SetError( ERRCODE_IO_GENERAL ); + return COMMIT_RESULT_FAILURE; + } + catch ( Exception& ) + { + // any other error - not specified + SetError( ERRCODE_IO_GENERAL ); + return COMMIT_RESULT_FAILURE; + } + + if ( m_bIsRoot && m_pContent ) + { + // the root storage must flush the root package content + if ( nRet == COMMIT_RESULT_SUCCESS ) + { + try + { + // commit the media type to the JAR file + // clipboard format and ClassId will be retrieved from the media type when the file is loaded again + Any aType; + aType <<= (rtl::OUString) m_aContentType; + m_pContent->setPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ), aType ); + + if ( m_bIsLinked ) + { + // write a manifest file + // first create a subfolder "META-inf" + Content aNewSubFolder; + BOOL bRet = ::utl::UCBContentHelper::MakeFolder( *m_pContent, String::CreateFromAscii("META-INF"), aNewSubFolder ); + if ( bRet ) + { + // create a stream to write the manifest file - use a temp file + String aURL( aNewSubFolder.getURL() ); + ::utl::TempFile* pTempFile = new ::utl::TempFile( &aURL ); + + // get the stream from the temp file and create an output stream wrapper + SvStream* pStream = pTempFile->GetStream( STREAM_STD_READWRITE ); + ::utl::OOutputStreamWrapper* pHelper = new ::utl::OOutputStreamWrapper( *pStream ); + com::sun::star::uno::Reference < ::com::sun::star::io::XOutputStream > xOutputStream( pHelper ); + + // create a manifest writer object that will fill the stream + Reference < ::com::sun::star::packages::manifest::XManifestWriter > xWriter = + Reference< ::com::sun::star::packages::manifest::XManifestWriter > + ( ::comphelper::getProcessServiceFactory()->createInstance( + ::rtl::OUString::createFromAscii( "com.sun.star.packages.manifest.ManifestWriter" )), UNO_QUERY) ; + sal_Int32 nCount = GetObjectCount() + 1; + Sequence < Sequence < PropertyValue > > aProps( nCount ); + sal_Int32 nProps = 0; + GetProps( nProps, aProps, String() ); + xWriter->writeManifestSequence( xOutputStream, aProps ); + + // move the stream to its desired location + Content aSource( pTempFile->GetURL(), Reference < XCommandEnvironment >() ); + xWriter = NULL; + xOutputStream = NULL; + DELETEZ( pTempFile ); + aNewSubFolder.transferContent( aSource, InsertOperation_MOVE, ::rtl::OUString::createFromAscii("manifest.xml"), NameClash::OVERWRITE ); + } + } + else + { +#if OSL_DEBUG_LEVEL > 1 + fprintf ( stderr, "Files: %i\n", nOpenFiles ); + fprintf ( stderr, "Streams: %i\n", nOpenStreams ); +#endif + // force writing + Any aAny; + m_pContent->executeCommand( ::rtl::OUString::createFromAscii("flush"), aAny ); + if ( m_pSource != 0 ) + { + SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( m_pTempFile->GetURL(), STREAM_STD_READ ); + m_pSource->SetStreamSize(0); + // m_pSource->Seek(0); + *pStream >> *m_pSource; + DELETEZ( pStream ); + m_pSource->Seek(0); + } + } + } + catch ( CommandAbortedException& ) + { + // how to tell the content : forget all changes ?! + // or should we assume that the content does it by itself because he throwed an exception ?! + // any command wasn't executed successfully - not specified + SetError( ERRCODE_IO_GENERAL ); + return COMMIT_RESULT_FAILURE; + } + catch ( RuntimeException& ) + { + // how to tell the content : forget all changes ?! + // or should we assume that the content does it by itself because he throwed an exception ?! + // any other error - not specified + SetError( ERRCODE_IO_GENERAL ); + return COMMIT_RESULT_FAILURE; + } + catch ( InteractiveIOException& r ) + { + if ( r.Code == IOErrorCode_ACCESS_DENIED || r.Code == IOErrorCode_LOCKING_VIOLATION ) + SetError( ERRCODE_IO_ACCESSDENIED ); + else if ( r.Code == IOErrorCode_NOT_EXISTING ) + SetError( ERRCODE_IO_NOTEXISTS ); + else if ( r.Code == IOErrorCode_CANT_READ ) + SetError( ERRCODE_IO_CANTREAD ); + else if ( r.Code == IOErrorCode_CANT_WRITE ) + SetError( ERRCODE_IO_CANTWRITE ); + else + SetError( ERRCODE_IO_GENERAL ); + + return COMMIT_RESULT_FAILURE; + } + catch ( Exception& ) + { + // how to tell the content : forget all changes ?! + // or should we assume that the content does it by itself because he throwed an exception ?! + // any other error - not specified + SetError( ERRCODE_IO_GENERAL ); + return COMMIT_RESULT_FAILURE; + } + } + else if ( nRet != COMMIT_RESULT_NOTHING_TO_DO ) + { + // how to tell the content : forget all changes ?! Should we ?! + SetError( ERRCODE_IO_GENERAL ); + return nRet; + } + + // after successfull root commit all elements names and types are adjusted and all removed elements + // are also removed from the lists + UCBStorageElement_Impl* pInnerElement = m_aChildrenList.First(); + BOOL bRet = TRUE; + while ( pInnerElement && bRet ) + { + UCBStorageElement_Impl* pNext = m_aChildrenList.Next(); + if ( pInnerElement->m_bIsRemoved ) + { + // is this correct use of our list class ?! + m_aChildrenList.Remove( pInnerElement ); + } + else + { + pInnerElement->m_aOriginalName = pInnerElement->m_aName; + pInnerElement->m_bIsInserted = FALSE; + } + + pInnerElement = pNext; + } + } + + m_bCommited = FALSE; + } + + return nRet; +} + +BOOL UCBStorage_Impl::Revert() +{ + UCBStorageElement_Impl* pElement = m_aChildrenList.First(); + BOOL bRet = TRUE; + while ( pElement && bRet ) + { + pElement->m_bIsRemoved = FALSE; + if ( pElement->m_bIsInserted ) + { + m_aChildrenList.Remove( pElement ); // correct usage of list ??? + } + else + { + if ( pElement->m_xStream.Is() ) + { + pElement->m_xStream->m_bCommited = sal_False; + pElement->m_xStream->Revert(); + } + else if ( pElement->m_xStorage.Is() ) + { + pElement->m_xStorage->m_bCommited = sal_False; + pElement->m_xStorage->Revert(); + } + + pElement->m_aName = pElement->m_aOriginalName; + pElement->m_bIsRemoved = FALSE; + } + + pElement = m_aChildrenList.Next(); + } + + return bRet; +} + +const String& UCBStorage::GetName() const +{ + return pImp->m_aName; // pImp->m_aURL ?! +} + +BOOL UCBStorage::IsRoot() const +{ + return pImp->m_bIsRoot; +} + +void UCBStorage::SetDirty() +{ + pImp->m_bDirty = TRUE; +} + +void UCBStorage::SetClass( const SvGlobalName & rClass, ULONG nOriginalClipFormat, const String & rUserTypeName ) +{ + pImp->m_aClassId = rClass; + pImp->m_nFormat = nOriginalClipFormat; + pImp->m_aUserTypeName = rUserTypeName; + + // in UCB storages only the content type will be stored, all other information can be reconstructed + // ( see the UCBStorage_Impl::Init() method ) + ::com::sun::star::datatransfer::DataFlavor aDataFlavor; + SotExchange::GetFormatDataFlavor( pImp->m_nFormat, aDataFlavor ); + pImp->m_aContentType = aDataFlavor.MimeType; +} + +void UCBStorage::SetClassId( const ClsId& rClsId ) +{ + pImp->m_aClassId = SvGlobalName( (const CLSID&) rClsId ); + if ( pImp->m_aClassId == SvGlobalName() ) + return; + + // in OLE storages the clipboard format an the user name will be transferred when a storage is copied because both are + // stored in one the substreams + // UCB storages store the content type information as content type in the manifest file and so this information must be + // kept up to date, and also the other type information that is hold only at runtime because it can be reconstructed from + // the content type + pImp->m_nFormat = GetFormatId_Impl( pImp->m_aClassId ); + if ( pImp->m_nFormat ) + { + ::com::sun::star::datatransfer::DataFlavor aDataFlavor; + SotExchange::GetFormatDataFlavor( pImp->m_nFormat, aDataFlavor ); + pImp->m_aUserTypeName = aDataFlavor.HumanPresentableName; + pImp->m_aContentType = aDataFlavor.MimeType; + } +} + +const ClsId& UCBStorage::GetClassId() const +{ + return ( const ClsId& ) pImp->m_aClassId.GetCLSID(); +} + +void UCBStorage::SetConvertClass( const SvGlobalName & /*rConvertClass*/, ULONG /*nOriginalClipFormat*/, const String & /*rUserTypeName*/ ) +{ + // ??? +} + +BOOL UCBStorage::ShouldConvert() +{ + // ??? + return FALSE; +} + +SvGlobalName UCBStorage::GetClassName() +{ + return pImp->m_aClassId; +} + +ULONG UCBStorage::GetFormat() +{ + return pImp->m_nFormat; +} + +String UCBStorage::GetUserName() +{ + DBG_ERROR("UserName is not implemented in UCB storages!" ); + return pImp->m_aUserTypeName; +} + +void UCBStorage::FillInfoList( SvStorageInfoList* pList ) const +{ + // put information in childrenlist into StorageInfoList + UCBStorageElement_Impl* pElement = pImp->GetChildrenList().First(); + while ( pElement ) + { + if ( !pElement->m_bIsRemoved ) + { + // problem: what about the size of a substorage ?! + ULONG nSize = pElement->m_nSize; + if ( pElement->m_xStream.Is() ) + nSize = pElement->m_xStream->GetSize(); + SvStorageInfo aInfo( pElement->m_aName, nSize, pElement->m_bIsStorage ); + pList->Append( aInfo ); + } + + pElement = pImp->m_aChildrenList.Next(); + } +} + +BOOL UCBStorage::CopyStorageElement_Impl( UCBStorageElement_Impl& rElement, BaseStorage* pDest, const String& rNew ) const +{ + // insert stream or storage into the list or stream of the destination storage + // not into the content, this will be done on commit ! + // be aware of name changes ! + if ( !rElement.m_bIsStorage ) + { + // copy the streams data + // the destination stream must not be open + BaseStorageStream* pOtherStream = pDest->OpenStream( rNew, STREAM_WRITE | STREAM_SHARE_DENYALL, pImp->m_bDirect ); + BaseStorageStream* pStream = NULL; + BOOL bDeleteStream = FALSE; + + // if stream is already open, it is allowed to copy it, so be aware of this + if ( rElement.m_xStream.Is() ) + pStream = rElement.m_xStream->m_pAntiImpl; + if ( !pStream ) + { + pStream = ( const_cast < UCBStorage* > (this) )->OpenStream( rElement.m_aName, STREAM_STD_READ, pImp->m_bDirect ); + bDeleteStream = TRUE; + } + + pStream->CopyTo( pOtherStream ); + SetError( pStream->GetError() ); + if( pOtherStream->GetError() ) + pDest->SetError( pOtherStream->GetError() ); + else + pOtherStream->Commit(); + + if ( bDeleteStream ) + delete pStream; + delete pOtherStream; + } + else + { + // copy the storage content + // the destination storage must not be open + BaseStorage* pStorage = NULL; + + // if stream is already open, it is allowed to copy it, so be aware of this + BOOL bDeleteStorage = FALSE; + if ( rElement.m_xStorage.Is() ) + pStorage = rElement.m_xStorage->m_pAntiImpl; + if ( !pStorage ) + { + pStorage = ( const_cast < UCBStorage* > (this) )->OpenStorage( rElement.m_aName, pImp->m_nMode, pImp->m_bDirect ); + bDeleteStorage = TRUE; + } + + UCBStorage* pUCBDest = PTR_CAST( UCBStorage, pDest ); + UCBStorage* pUCBCopy = PTR_CAST( UCBStorage, pStorage ); + + BOOL bOpenUCBStorage = pUCBDest && pUCBCopy; + BaseStorage* pOtherStorage = bOpenUCBStorage ? + pDest->OpenUCBStorage( rNew, STREAM_WRITE | STREAM_SHARE_DENYALL, pImp->m_bDirect ) : + pDest->OpenOLEStorage( rNew, STREAM_WRITE | STREAM_SHARE_DENYALL, pImp->m_bDirect ); + + // For UCB storages, the class id and the format id may differ, + // do passing the class id is not sufficient. + if( bOpenUCBStorage ) + pOtherStorage->SetClass( pStorage->GetClassName(), + pStorage->GetFormat(), + pUCBCopy->pImp->m_aUserTypeName ); + else + pOtherStorage->SetClassId( pStorage->GetClassId() ); + pStorage->CopyTo( pOtherStorage ); + SetError( pStorage->GetError() ); + if( pOtherStorage->GetError() ) + pDest->SetError( pOtherStorage->GetError() ); + else + pOtherStorage->Commit(); + + if ( bDeleteStorage ) + delete pStorage; + delete pOtherStorage; + } + + return BOOL( Good() && pDest->Good() ); +} + +UCBStorageElement_Impl* UCBStorage::FindElement_Impl( const String& rName ) const +{ + DBG_ASSERT( rName.Len(), "Name is empty!" ); + UCBStorageElement_Impl* pElement = pImp->GetChildrenList().First(); + while ( pElement ) + { + if ( pElement->m_aName == rName && !pElement->m_bIsRemoved ) + break; + pElement = pImp->m_aChildrenList.Next(); + } + + return pElement; +} + +BOOL UCBStorage::CopyTo( BaseStorage* pDestStg ) const +{ + DBG_ASSERT( pDestStg != ((BaseStorage*)this), "Self-Copying is not possible!" ); + if ( pDestStg == ((BaseStorage*)this) ) + return FALSE; + + // perhaps it's also a problem if one storage is a parent of the other ?! + // or if not: could be optimized ?! + + // For UCB storages, the class id and the format id may differ, + // do passing the class id is not sufficient. + if( pDestStg->ISA( UCBStorage ) ) + pDestStg->SetClass( pImp->m_aClassId, pImp->m_nFormat, + pImp->m_aUserTypeName ); + else + pDestStg->SetClassId( GetClassId() ); + pDestStg->SetDirty(); + + BOOL bRet = TRUE; + UCBStorageElement_Impl* pElement = pImp->GetChildrenList().First(); + while ( pElement && bRet ) + { + if ( !pElement->m_bIsRemoved ) + bRet = CopyStorageElement_Impl( *pElement, pDestStg, pElement->m_aName ); + pElement = pImp->m_aChildrenList.Next(); + } + + if( !bRet ) + SetError( pDestStg->GetError() ); + return BOOL( Good() && pDestStg->Good() ); +} + +BOOL UCBStorage::CopyTo( const String& rElemName, BaseStorage* pDest, const String& rNew ) +{ + if( !rElemName.Len() ) + return FALSE; + + if ( pDest == ((BaseStorage*) this) ) + { + // can't double an element + return FALSE; + } + else + { + // for copying no optimization is usefull, because in every case the stream data must be copied + UCBStorageElement_Impl* pElement = FindElement_Impl( rElemName ); + if ( pElement ) + return CopyStorageElement_Impl( *pElement, pDest, rNew ); + else + { + SetError( SVSTREAM_FILE_NOT_FOUND ); + return FALSE; + } + } +} + +BOOL UCBStorage::Commit() +{ + // mark this storage for sending it on root commit + pImp->m_bCommited = TRUE; + if ( pImp->m_bIsRoot ) + // the root storage coordinates commiting by sending a Commit command to its content + return ( pImp->Commit() != COMMIT_RESULT_FAILURE ); + else + return TRUE; +} + +BOOL UCBStorage::Revert() +{ + return pImp->Revert(); +} + +BaseStorageStream* UCBStorage::OpenStream( const String& rEleName, StreamMode nMode, BOOL bDirect, const ByteString* pKey ) +{ + if( !rEleName.Len() ) + return NULL; + + // try to find the storage element + UCBStorageElement_Impl *pElement = FindElement_Impl( rEleName ); + if ( !pElement ) + { + // element does not exist, check if creation is allowed + if( ( nMode & STREAM_NOCREATE ) ) + { + SetError( ( nMode & STREAM_WRITE ) ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND ); + String aName( pImp->m_aURL ); + aName += '/'; + aName += rEleName; + UCBStorageStream* pStream = new UCBStorageStream( aName, nMode, bDirect, pKey, pImp->m_bRepairPackage, pImp->m_xProgressHandler ); + pStream->SetError( GetError() ); + pStream->pImp->m_aName = rEleName; + return pStream; + } + else + { + // create a new UCBStorageElement and insert it into the list + pElement = new UCBStorageElement_Impl( rEleName ); + pElement->m_bIsInserted = TRUE; + pImp->m_aChildrenList.Insert( pElement, LIST_APPEND ); + } + } + + if ( pElement && !pElement->m_bIsFolder ) + { + // check if stream is already created + if ( pElement->m_xStream.Is() ) + { + // stream has already been created; if it has no external reference, it may be opened another time + if ( pElement->m_xStream->m_pAntiImpl ) + { + DBG_ERROR("Stream is already open!" ); + SetError( SVSTREAM_ACCESS_DENIED ); // ??? + return NULL; + } + else + { + // check if stream is opened with the same keyword as before + // if not, generate a new stream because it could be encrypted vs. decrypted! + ByteString aKey; + if ( pKey ) + aKey = *pKey; + if ( pElement->m_xStream->m_aKey == aKey ) + { + pElement->m_xStream->PrepareCachedForReopen( nMode ); + + // DBG_ASSERT( bDirect == pElement->m_xStream->m_bDirect, "Wrong DirectMode!" ); + return new UCBStorageStream( pElement->m_xStream ); + } + } + } + + // stream is opened the first time + pImp->OpenStream( pElement, nMode, bDirect, pKey ); + + // if name has been changed before creating the stream: set name! + pElement->m_xStream->m_aName = rEleName; + return new UCBStorageStream( pElement->m_xStream ); + } + + return NULL; +} + +UCBStorageStream_Impl* UCBStorage_Impl::OpenStream( UCBStorageElement_Impl* pElement, StreamMode nMode, BOOL bDirect, const ByteString* pKey ) +{ + String aName( m_aURL ); + aName += '/'; + aName += pElement->m_aOriginalName; + pElement->m_xStream = new UCBStorageStream_Impl( aName, nMode, NULL, bDirect, pKey, m_bRepairPackage, m_xProgressHandler ); + return pElement->m_xStream; +} + +BaseStorage* UCBStorage::OpenUCBStorage( const String& rEleName, StreamMode nMode, BOOL bDirect ) +{ + if( !rEleName.Len() ) + return NULL; + + return OpenStorage_Impl( rEleName, nMode, bDirect, TRUE ); +} + +BaseStorage* UCBStorage::OpenOLEStorage( const String& rEleName, StreamMode nMode, BOOL bDirect ) +{ + if( !rEleName.Len() ) + return NULL; + + return OpenStorage_Impl( rEleName, nMode, bDirect, FALSE ); +} + +BaseStorage* UCBStorage::OpenStorage( const String& rEleName, StreamMode nMode, BOOL bDirect ) +{ + if( !rEleName.Len() ) + return NULL; + + return OpenStorage_Impl( rEleName, nMode, bDirect, TRUE ); +} + +BaseStorage* UCBStorage::OpenStorage_Impl( const String& rEleName, StreamMode nMode, BOOL bDirect, BOOL bForceUCBStorage ) +{ + // try to find the storage element + UCBStorageElement_Impl *pElement = FindElement_Impl( rEleName ); + if ( !pElement ) + { + // element does not exist, check if creation is allowed + if( ( nMode & STREAM_NOCREATE ) ) + { + SetError( ( nMode & STREAM_WRITE ) ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND ); + String aName( pImp->m_aURL ); + aName += '/'; + aName += rEleName; // ??? + UCBStorage *pStorage = new UCBStorage( aName, nMode, bDirect, FALSE, pImp->m_bRepairPackage, pImp->m_xProgressHandler ); + pStorage->pImp->m_bIsRoot = FALSE; + pStorage->pImp->m_bListCreated = sal_True; // the storage is pretty new, nothing to read + pStorage->SetError( GetError() ); + return pStorage; + } + + // create a new UCBStorageElement and insert it into the list + // problem: perhaps an OLEStorage should be created ?! + // Because nothing is known about the element that should be created, an external parameter is needed ! + pElement = new UCBStorageElement_Impl( rEleName ); + pElement->m_bIsInserted = TRUE; + pImp->m_aChildrenList.Insert( pElement, LIST_APPEND ); + } + + if ( !pElement->m_bIsFolder && ( pElement->m_bIsStorage || !bForceUCBStorage ) ) + { + // create OLE storages on a stream ( see ctor of SotStorage ) + // Such a storage will be created on a UCBStorageStream; it will write into the stream + // if it is opened in direct mode or when it is committed. In this case the stream will be + // modified and then it MUST be treated as commited. + if ( !pElement->m_xStream.Is() ) + { + BaseStorageStream* pStr = OpenStream( rEleName, nMode, bDirect ); + UCBStorageStream* pStream = PTR_CAST( UCBStorageStream, pStr ); + if ( !pStream ) + { + SetError( ( nMode & STREAM_WRITE ) ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND ); + return NULL; + } + + pElement->m_xStream = pStream->pImp; + delete pStream; + } + + pElement->m_xStream->PrepareCachedForReopen( nMode ); + pElement->m_xStream->Init(); + + pElement->m_bIsStorage = TRUE; + return pElement->m_xStream->CreateStorage(); // can only be created in transacted mode + } + else if ( pElement->m_xStorage.Is() ) + { + // storage has already been opened; if it has no external reference, it may be opened another time + if ( pElement->m_xStorage->m_pAntiImpl ) + { + DBG_ERROR("Storage is already open!" ); + SetError( SVSTREAM_ACCESS_DENIED ); // ??? + } + else + { + BOOL bIsWritable = (( pElement->m_xStorage->m_nMode & STREAM_WRITE ) != 0); + if ( !bIsWritable && (( nMode & STREAM_WRITE ) != 0 )) + { + String aName( pImp->m_aURL ); + aName += '/'; + aName += pElement->m_aOriginalName; + UCBStorage* pStorage = new UCBStorage( aName, nMode, bDirect, FALSE, pImp->m_bRepairPackage, pImp->m_xProgressHandler ); + pElement->m_xStorage = pStorage->pImp; + return pStorage; + } + else + { +// DBG_ASSERT( bDirect == pElement->m_xStorage->m_bDirect, "Wrong DirectMode!" ); + return new UCBStorage( pElement->m_xStorage ); + } + } + } + else if ( !pElement->m_xStream.Is() ) + { + // storage is opened the first time + BOOL bIsWritable = (( pImp->m_nMode & STREAM_WRITE ) != 0 ); + if ( pImp->m_bIsLinked && pImp->m_bIsRoot && bIsWritable ) + { + // make sure that the root storage object has been created before substorages will be created + INetURLObject aFolderObj( pImp->m_aURL ); + String aName = aFolderObj.GetName(); + aFolderObj.removeSegment(); + + Content aFolder( aFolderObj.GetMainURL( INetURLObject::NO_DECODE ), Reference < XCommandEnvironment >() ); + pImp->m_pContent = new Content; + BOOL bRet = ::utl::UCBContentHelper::MakeFolder( aFolder, pImp->m_aName, *pImp->m_pContent ); + if ( !bRet ) + { + SetError( SVSTREAM_CANNOT_MAKE ); + return NULL; + } + } + + UCBStorage_Impl* pStor = pImp->OpenStorage( pElement, nMode, bDirect ); + if ( pStor ) + { + if ( pElement->m_bIsInserted ) + pStor->m_bListCreated = sal_True; // the storage is pretty new, nothing to read + + return new UCBStorage( pStor ); + } + } + + return NULL; +} + +UCBStorage_Impl* UCBStorage_Impl::OpenStorage( UCBStorageElement_Impl* pElement, StreamMode nMode, BOOL bDirect ) +{ + UCBStorage_Impl* pRet = NULL; + String aName( m_aURL ); + aName += '/'; + aName += pElement->m_aOriginalName; // ??? + + pElement->m_bIsStorage = pElement->m_bIsFolder = TRUE; + + if ( m_bIsLinked && !::utl::UCBContentHelper::Exists( aName ) ) + { + Content aNewFolder; + BOOL bRet = ::utl::UCBContentHelper::MakeFolder( *m_pContent, pElement->m_aOriginalName, aNewFolder ); + if ( bRet ) + pRet = new UCBStorage_Impl( aNewFolder, aName, nMode, NULL, bDirect, FALSE, m_bRepairPackage, m_xProgressHandler ); + } + else + { + pRet = new UCBStorage_Impl( aName, nMode, NULL, bDirect, FALSE, m_bRepairPackage, m_xProgressHandler ); + } + + if ( pRet ) + { + pRet->m_bIsLinked = m_bIsLinked; + pRet->m_bIsRoot = FALSE; + + // if name has been changed before creating the stream: set name! + pRet->m_aName = pElement->m_aOriginalName; + pElement->m_xStorage = pRet; + } + + if ( pRet ) + pRet->Init(); + + return pRet; +} + +BOOL UCBStorage::IsStorage( const String& rEleName ) const +{ + if( !rEleName.Len() ) + return FALSE; + + const UCBStorageElement_Impl *pElement = FindElement_Impl( rEleName ); + return ( pElement && pElement->m_bIsStorage ); +} + +BOOL UCBStorage::IsStream( const String& rEleName ) const +{ + if( !rEleName.Len() ) + return FALSE; + + const UCBStorageElement_Impl *pElement = FindElement_Impl( rEleName ); + return ( pElement && !pElement->m_bIsStorage ); +} + +BOOL UCBStorage::IsContained( const String & rEleName ) const +{ + if( !rEleName.Len() ) + return FALSE; + const UCBStorageElement_Impl *pElement = FindElement_Impl( rEleName ); + return ( pElement != NULL ); +} + +BOOL UCBStorage::Remove( const String& rEleName ) +{ + if( !rEleName.Len() ) + return FALSE; + + UCBStorageElement_Impl *pElement = FindElement_Impl( rEleName ); + if ( pElement ) + { + pElement->m_bIsRemoved = TRUE; + } + else + SetError( SVSTREAM_FILE_NOT_FOUND ); + + return ( pElement != NULL ); +} + +BOOL UCBStorage::Rename( const String& rEleName, const String& rNewName ) +{ + if( !rEleName.Len()|| !rNewName.Len() ) + return FALSE; + + UCBStorageElement_Impl *pAlreadyExisting = FindElement_Impl( rNewName ); + if ( pAlreadyExisting ) + { + SetError( SVSTREAM_ACCESS_DENIED ); + return FALSE; // can't change to a name that is already used + } + + UCBStorageElement_Impl *pElement = FindElement_Impl( rEleName ); + if ( pElement ) + { + pElement->m_aName = rNewName; + } + else + SetError( SVSTREAM_FILE_NOT_FOUND ); + + return pElement != NULL; +} + +BOOL UCBStorage::MoveTo( const String& rEleName, BaseStorage* pNewSt, const String& rNewName ) +{ + if( !rEleName.Len() || !rNewName.Len() ) + return FALSE; + + if ( pNewSt == ((BaseStorage*) this) && !FindElement_Impl( rNewName ) ) + { + return Rename( rEleName, rNewName ); + } + else + { +/* + if ( PTR_CAST( UCBStorage, pNewSt ) ) + { + // because the element is moved, not copied, a special optimization is possible : + // first copy the UCBStorageElement; flag old element as "Removed" and new as "Inserted", + // clear original name/type of the new element + // if moved element is open: copy content, but change absolute URL ( and those of all children of the element! ), + // clear original name/type of new content, keep the old original stream/storage, but forget its working streams, + // close original UCBContent and original stream, only the TempFile and its stream may remain unchanged, but now + // belong to the new content + // if original and editable stream are identical ( readonly element ), it has to be copied to the editable + // stream of the destination object + // Not implemented at the moment ( risky?! ), perhaps later + } +*/ + // MoveTo is done by first copying to the new destination and then removing the old element + BOOL bRet = CopyTo( rEleName, pNewSt, rNewName ); + if ( bRet ) + bRet = Remove( rEleName ); + return bRet; + } +} + +BOOL UCBStorage::ValidateFAT() +{ + // ??? + return TRUE; +} + +BOOL UCBStorage::Validate( BOOL bWrite ) const +{ + // ??? + return ( !bWrite || ( pImp->m_nMode & STREAM_WRITE ) ); +} + +BOOL UCBStorage::ValidateMode( StreamMode m ) const +{ + // ??? + if( m == ( STREAM_READ | STREAM_TRUNC ) ) // from stg.cxx + return TRUE; + USHORT nCurMode = 0xFFFF; + if( ( m & 3 ) == STREAM_READ ) + { + // only SHARE_DENYWRITE or SHARE_DENYALL allowed + if( ( ( m & STREAM_SHARE_DENYWRITE ) + && ( nCurMode & STREAM_SHARE_DENYWRITE ) ) + || ( ( m & STREAM_SHARE_DENYALL ) + && ( nCurMode & STREAM_SHARE_DENYALL ) ) ) + return TRUE; + } + else + { + // only SHARE_DENYALL allowed + // storages open in r/o mode are OK, since only + // the commit may fail + if( ( m & STREAM_SHARE_DENYALL ) + && ( nCurMode & STREAM_SHARE_DENYALL ) ) + return TRUE; + } + + return TRUE; +} + +const SvStream* UCBStorage::GetSvStream() const +{ + // this would cause a complete download of the file + // as it looks, this method is NOT used inside of SOT, only exported by class SotStorage - but for what ??? + return pImp->m_pSource; +} + +BOOL UCBStorage::Equals( const BaseStorage& rStorage ) const +{ + // ??? + return ((BaseStorage*)this) == &rStorage; +} + +BOOL UCBStorage::IsStorageFile( const String& rFileName ) +{ + String aFileURL = rFileName; + INetURLObject aObj( aFileURL ); + if ( aObj.GetProtocol() == INET_PROT_NOT_VALID ) + { + ::utl::LocalFileHelper::ConvertPhysicalNameToURL( rFileName, aFileURL ); + aObj.SetURL( aFileURL ); + aFileURL = aObj.GetMainURL( INetURLObject::NO_DECODE ); + } + + SvStream * pStm = ::utl::UcbStreamHelper::CreateStream( aFileURL, STREAM_STD_READ ); + BOOL bRet = UCBStorage::IsStorageFile( pStm ); + delete pStm; + return bRet; +} + +BOOL UCBStorage::IsStorageFile( SvStream* pFile ) +{ + if ( !pFile ) + return FALSE; + + ULONG nPos = pFile->Tell(); + pFile->Seek( STREAM_SEEK_TO_END ); + if ( pFile->Tell() < 4 ) + return FALSE; + + pFile->Seek(0); + UINT32 nBytes; + *pFile >> nBytes; + + // search for the magic bytes + BOOL bRet = ( nBytes == 0x04034b50 ); + if ( !bRet ) + { + // disk spanned file have an additional header in front of the usual one + bRet = ( nBytes == 0x08074b50 ); + if ( bRet ) + { + *pFile >> nBytes; + bRet = ( nBytes == 0x04034b50 ); + } + } + + pFile->Seek( nPos ); + return bRet; +} + +BOOL UCBStorage::IsDiskSpannedFile( SvStream* pFile ) +{ + if ( !pFile ) + return FALSE; + + ULONG nPos = pFile->Tell(); + pFile->Seek( STREAM_SEEK_TO_END ); + if ( !pFile->Tell() ) + return FALSE; + + pFile->Seek(0); + UINT32 nBytes; + *pFile >> nBytes; + + // disk spanned file have an additional header in front of the usual one + BOOL bRet = ( nBytes == 0x08074b50 ); + if ( bRet ) + { + *pFile >> nBytes; + bRet = ( nBytes == 0x04034b50 ); + } + + pFile->Seek( nPos ); + return bRet; +} + +String UCBStorage::GetLinkedFile( SvStream &rStream ) +{ + String aString; + ULONG nPos = rStream.Tell(); + rStream.Seek( STREAM_SEEK_TO_END ); + if ( !rStream.Tell() ) + return aString; + + rStream.Seek(0); + UINT32 nBytes; + rStream >> nBytes; + if( nBytes == 0x04034b50 ) + { + ByteString aTmp; + rStream.ReadByteString( aTmp ); + if ( aTmp.CompareTo( "ContentURL=", 11 ) == COMPARE_EQUAL ) + { + aTmp.Erase( 0, 11 ); + aString = String( aTmp, RTL_TEXTENCODING_UTF8 ); + } + } + + rStream.Seek( nPos ); + return aString; +} + +String UCBStorage::CreateLinkFile( const String& rName ) +{ + // create a stream to write the link file - use a temp file, because it may be no file content + INetURLObject aFolderObj( rName ); + String aName = aFolderObj.GetName(); + aFolderObj.removeSegment(); + String aFolderURL( aFolderObj.GetMainURL( INetURLObject::NO_DECODE ) ); + ::utl::TempFile* pTempFile = new ::utl::TempFile( &aFolderURL ); + + // get the stream from the temp file + SvStream* pStream = pTempFile->GetStream( STREAM_STD_READWRITE | STREAM_TRUNC ); + + // write header + *pStream << ( UINT32 ) 0x04034b50; + + // assemble a new folder name in the destination folder + INetURLObject aObj( rName ); + String aTmpName = aObj.GetName(); + String aTitle = String::CreateFromAscii( "content." ); + aTitle += aTmpName; + + // create a folder and store its URL + Content aFolder( aFolderURL, Reference < XCommandEnvironment >() ); + Content aNewFolder; + BOOL bRet = ::utl::UCBContentHelper::MakeFolder( aFolder, aTitle, aNewFolder ); + if ( !bRet ) + { + aFolderObj.insertName( aTitle ); + if ( ::utl::UCBContentHelper::Exists( aFolderObj.GetMainURL( INetURLObject::NO_DECODE ) ) ) + { + // Hack, because already existing files give the same CommandAbortedException as any other error ! + // append a number until the name can be used for a new folder + aTitle += '.'; + for ( sal_Int32 i=0; !bRet; i++ ) + { + String aTmp( aTitle ); + aTmp += String::CreateFromInt32( i ); + bRet = ::utl::UCBContentHelper::MakeFolder( aFolder, aTmp, aNewFolder ); + if ( bRet ) + aTitle = aTmp; + else + { + aFolderObj.SetName( aTmp ); + if ( !::utl::UCBContentHelper::Exists( aFolderObj.GetMainURL( INetURLObject::NO_DECODE ) ) ) + // Hack, because already existing files give the same CommandAbortedException as any other error ! + break; + } + } + } + } + + if ( bRet ) + { + // get the URL + aObj.SetName( aTitle ); + String aURL = aObj.GetMainURL( INetURLObject::NO_DECODE ); + + // store it as key/value pair + String aLink = String::CreateFromAscii("ContentURL="); + aLink += aURL; + pStream->WriteByteString( aLink, RTL_TEXTENCODING_UTF8 ); + pStream->Flush(); + + // move the stream to its desired location + Content aSource( pTempFile->GetURL(), Reference < XCommandEnvironment >() ); + DELETEZ( pTempFile ); + aFolder.transferContent( aSource, InsertOperation_MOVE, aName, NameClash::OVERWRITE ); + return aURL; + } + + pTempFile->EnableKillingFile( TRUE ); + delete pTempFile; + return String(); +} + +BOOL UCBStorage::SetProperty( const String& rName, const ::com::sun::star::uno::Any& rValue ) +{ + if ( rName.CompareToAscii("Title") == COMPARE_EQUAL ) + return FALSE; + + if ( rName.CompareToAscii("MediaType") == COMPARE_EQUAL ) + { + ::rtl::OUString aTmp; + rValue >>= aTmp; + pImp->m_aContentType = aTmp; + } + + try + { + if ( pImp->GetContent() ) + { + pImp->m_pContent->setPropertyValue( rName, rValue ); + return TRUE; + } + } + catch ( Exception& ) + { + } + + return FALSE; +} + +BOOL UCBStorage::GetProperty( const String& rName, ::com::sun::star::uno::Any& rValue ) +{ + try + { + if ( pImp->GetContent() ) + { + rValue = pImp->m_pContent->getPropertyValue( rName ); + return TRUE; + } + } + catch ( Exception& ) + { + } + + return FALSE; +} + +BOOL UCBStorage::GetProperty( const String& rEleName, const String& rName, ::com::sun::star::uno::Any& rValue ) +{ + UCBStorageElement_Impl *pEle = FindElement_Impl( rEleName ); + if ( !pEle ) + return FALSE; + + if ( !pEle->m_bIsFolder ) + { + if ( !pEle->m_xStream.Is() ) + pImp->OpenStream( pEle, pImp->m_nMode, pImp->m_bDirect ); + if ( pEle->m_xStream->m_nError ) + { + pEle->m_xStream.Clear(); + return FALSE; + } + + try + { + if ( pEle->m_xStream->m_pContent ) + { + rValue = pEle->m_xStream->m_pContent->getPropertyValue( rName ); + return TRUE; + } + } + catch ( Exception& ) + { + } + } + else + { + if ( !pEle->m_xStorage.Is() ) + pImp->OpenStorage( pEle, pImp->m_nMode, pImp->m_bDirect ); + if ( pEle->m_xStorage->m_nError ) + { + pEle->m_xStorage.Clear(); + return FALSE; + } + + try + { + if ( pEle->m_xStorage->GetContent() ) + { + rValue = pEle->m_xStorage->m_pContent->getPropertyValue( rName ); + return TRUE; + } + } + catch ( Exception& ) + { + } + } + + return FALSE; +} + +UNOStorageHolderList* UCBStorage::GetUNOStorageHolderList() +{ + if ( !pImp->m_pUNOStorageHolderList ) + pImp->m_pUNOStorageHolderList = new UNOStorageHolderList; + + return pImp->m_pUNOStorageHolderList; +} + diff --git a/sot/source/sdstor/unostorageholder.cxx b/sot/source/sdstor/unostorageholder.cxx new file mode 100644 index 000000000000..55c205557648 --- /dev/null +++ b/sot/source/sdstor/unostorageholder.cxx @@ -0,0 +1,197 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sot.hxx" +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/embed/XTransactionBroadcaster.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> + +#include <comphelper/processfactory.hxx> + +#include "unostorageholder.hxx" +#include <storinfo.hxx> + + +using namespace ::com::sun::star; + +UNOStorageHolder::UNOStorageHolder( SotStorage& aParentStorage, + SotStorage& aStorage, + uno::Reference< embed::XStorage > xStorage, + ::utl::TempFile* pTempFile ) +: m_pParentStorage( &aParentStorage ) +, m_rSotStorage( &aStorage ) +, m_xStorage( xStorage ) +, m_pTempFile( pTempFile ) +{ + OSL_ENSURE( m_xStorage.is() && m_pTempFile, "Wrong initialization!\n" ); + if ( !m_xStorage.is() || !m_pTempFile ) + throw uno::RuntimeException(); + + uno::Reference< embed::XTransactionBroadcaster > xTrBroadcast( m_xStorage, uno::UNO_QUERY ); + if ( !xTrBroadcast.is() ) + throw uno::RuntimeException(); + + xTrBroadcast->addTransactionListener( (embed::XTransactionListener*)this ); +} + +void UNOStorageHolder::InternalDispose() +{ + uno::Reference< embed::XTransactionBroadcaster > xTrBroadcast( m_xStorage, uno::UNO_QUERY ); + if ( xTrBroadcast.is() ) + xTrBroadcast->removeTransactionListener( (embed::XTransactionListener*)this ); + + uno::Reference< lang::XComponent > xComponent( m_xStorage, uno::UNO_QUERY ); + if ( xComponent.is() ) + xComponent->dispose(); + m_xStorage = uno::Reference< embed::XStorage >(); + + if ( m_pParentStorage ) + m_pParentStorage = NULL; + + if ( m_pTempFile ) + { + delete m_pTempFile; + m_pTempFile = NULL; + } + + if ( m_rSotStorage.Is() ) + m_rSotStorage = NULL; +} + +String UNOStorageHolder::GetStorageName() +{ + if ( m_rSotStorage.Is() ) + return m_rSotStorage->GetName(); + + return String(); +} + +void SAL_CALL UNOStorageHolder::preCommit( const lang::EventObject& /*aEvent*/ ) + throw ( uno::Exception, + uno::RuntimeException ) +{ + // do nothing +} + +void SAL_CALL UNOStorageHolder::commited( const lang::EventObject& /*aEvent*/ ) + throw ( uno::RuntimeException ) +{ + ::utl::TempFile aTmpStorFile; + if ( !aTmpStorFile.GetURL().Len() ) + throw uno::RuntimeException(); + + uno::Reference< lang::XSingleServiceFactory > xStorageFactory( + ::comphelper::getProcessServiceFactory()->createInstance( + ::rtl::OUString::createFromAscii( "com.sun.star.embed.StorageFactory" ) ), + uno::UNO_QUERY ); + + OSL_ENSURE( xStorageFactory.is(), "Can't create storage factory!\n" ); + if ( !xStorageFactory.is() ) + throw uno::RuntimeException(); + + uno::Sequence< uno::Any > aArg( 2 ); + aArg[0] <<= ::rtl::OUString( aTmpStorFile.GetURL() ); + aArg[1] <<= embed::ElementModes::READWRITE; + uno::Reference< embed::XStorage > xTempStorage( xStorageFactory->createInstanceWithArguments( aArg ), uno::UNO_QUERY ); + + OSL_ENSURE( xTempStorage.is(), "Can't open storage!\n" ); + if ( !xTempStorage.is() ) + throw uno::RuntimeException(); + + m_xStorage->copyToStorage( xTempStorage ); + + uno::Reference< lang::XComponent > xComp( xTempStorage, uno::UNO_QUERY ); + if ( !xComp.is() ) + throw uno::RuntimeException(); + + xComp->dispose(); + + SotStorageRef rTempStorage = new SotStorage( TRUE, aTmpStorFile.GetURL(), STREAM_WRITE, STORAGE_TRANSACTED ); + if ( !rTempStorage.Is() || rTempStorage->GetError() != ERRCODE_NONE ) + throw uno::RuntimeException(); + + SvStorageInfoList aSubStorInfoList; + m_rSotStorage->FillInfoList( &aSubStorInfoList ); + for ( sal_uInt32 nInd = 0; nInd < aSubStorInfoList.Count(); nInd++ ) + { + m_rSotStorage->Remove( aSubStorInfoList[nInd].GetName() ); + if ( m_rSotStorage->GetError() ) + { + m_rSotStorage->ResetError(); + throw uno::RuntimeException(); + } + } + + rTempStorage->CopyTo( m_rSotStorage ); + + // CopyTo does not transport unknown media type + // just workaround it + uno::Any aMediaType; + if ( rTempStorage->GetProperty( ::rtl::OUString::createFromAscii( "MediaType" ), aMediaType ) ) + m_rSotStorage->SetProperty( ::rtl::OUString::createFromAscii( "MediaType" ), aMediaType ); + + m_rSotStorage->Commit(); +} + +void SAL_CALL UNOStorageHolder::preRevert( const lang::EventObject& /*aEvent*/ ) + throw ( uno::Exception, + uno::RuntimeException ) +{ + // do nothing +} + +void SAL_CALL UNOStorageHolder::reverted( const lang::EventObject& /*aEvent*/ ) + throw ( uno::RuntimeException ) +{ + // do nothing, since reverting of the duplicate storage just means + // not to copy changes done for it to the original storage +} + +void SAL_CALL UNOStorageHolder::disposing( const lang::EventObject& /*Source*/ ) + throw ( uno::RuntimeException ) +{ + if ( m_pTempFile ) + { + delete m_pTempFile; + m_pTempFile = NULL; + } + + if ( m_rSotStorage.Is() ) + m_rSotStorage = NULL; + + if ( m_pParentStorage ) + { + SotStorage* pTmp = m_pParentStorage; + m_pParentStorage = NULL; + pTmp->RemoveUNOStorageHolder( this ); // this statement can lead to destruction of the holder + } +} + + diff --git a/sot/source/sdstor/unostorageholder.hxx b/sot/source/sdstor/unostorageholder.hxx new file mode 100644 index 000000000000..5e70804745a8 --- /dev/null +++ b/sot/source/sdstor/unostorageholder.hxx @@ -0,0 +1,77 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _UNOSTORAGEHOLDER_HXX +#define _UNOSTORAGEHOLDER_HXX + +#include <com/sun/star/embed/XTransactionListener.hpp> +#include <cppuhelper/implbase1.hxx> + +#include <unotools/tempfile.hxx> +#include <sot/storage.hxx> + +class SotStorage; +class UNOStorageHolder : public ::cppu::WeakImplHelper1< + ::com::sun::star::embed::XTransactionListener > + +{ + SotStorage* m_pParentStorage; // parent storage + SotStorageRef m_rSotStorage; // original substorage + ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > m_xStorage; // duplicate storage + ::utl::TempFile* m_pTempFile; // temporary file used by duplicate storage + +public: + UNOStorageHolder( SotStorage& aParentStorage, + SotStorage& aStorage, + ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > xStorage, + ::utl::TempFile* pTempFile ); + + void InternalDispose(); + String GetStorageName(); + + ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > GetDuplicateStorage() { return m_xStorage; } + + virtual void SAL_CALL preCommit( const ::com::sun::star::lang::EventObject& aEvent ) + throw ( ::com::sun::star::uno::Exception, + ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL commited( const ::com::sun::star::lang::EventObject& aEvent ) + throw ( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL preRevert( const ::com::sun::star::lang::EventObject& aEvent ) + throw ( ::com::sun::star::uno::Exception, + ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL reverted( const ::com::sun::star::lang::EventObject& aEvent ) + throw ( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) + throw ( ::com::sun::star::uno::RuntimeException ); +}; + +#endif + diff --git a/sot/source/unoolestorage/makefile.mk b/sot/source/unoolestorage/makefile.mk new file mode 100644 index 000000000000..d88f72f14e51 --- /dev/null +++ b/sot/source/unoolestorage/makefile.mk @@ -0,0 +1,51 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=sot +TARGET=unoolestorage + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/xolesimplestorage.obj \ + $(SLO)$/register.obj + +EXCEPTIONSFILES= \ + $(SLO)$/xolesimplestorage.obj \ + $(SLO)$/register.obj + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk + diff --git a/sot/source/unoolestorage/register.cxx b/sot/source/unoolestorage/register.cxx new file mode 100644 index 000000000000..083a4d585ca1 --- /dev/null +++ b/sot/source/unoolestorage/register.cxx @@ -0,0 +1,73 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sot.hxx" + + +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/registry/InvalidRegistryException.hpp> +#include <cppuhelper/factory.hxx> + +#include "xolesimplestorage.hxx" + +using namespace ::com::sun::star; + + +extern "C" { + +SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment( const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ ) +{ + void * pRet = 0; + + ::rtl::OUString aImplName( ::rtl::OUString::createFromAscii( pImplName ) ); + uno::Reference< lang::XSingleServiceFactory > xFactory; + + if ( pServiceManager && aImplName.equals( OLESimpleStorage::impl_staticGetImplementationName() ) ) + { + xFactory= ::cppu::createSingleFactory( reinterpret_cast< lang::XMultiServiceFactory*>( pServiceManager ), + OLESimpleStorage::impl_staticGetImplementationName(), + OLESimpleStorage::impl_staticCreateSelfInstance, + OLESimpleStorage::impl_staticGetSupportedServiceNames() ); + } + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} + +} // extern "C" + diff --git a/sot/source/unoolestorage/xolesimplestorage.cxx b/sot/source/unoolestorage/xolesimplestorage.cxx new file mode 100644 index 000000000000..1780e45c5ed6 --- /dev/null +++ b/sot/source/unoolestorage/xolesimplestorage.cxx @@ -0,0 +1,811 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sot.hxx" +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/io/XStream.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/io/XTruncate.hpp> + +#include <comphelper/storagehelper.hxx> + +#include <unotools/ucbstreamhelper.hxx> + +#include <cppuhelper/exc_hlp.hxx> + +#include <storinfo.hxx> + +#include "xolesimplestorage.hxx" + + +using namespace ::com::sun::star; + +const sal_Int32 nBytesCount = 32000; + + +// -------------------------------------------------------------------------------- +OLESimpleStorage::OLESimpleStorage( uno::Reference< lang::XMultiServiceFactory > xFactory ) +: m_bDisposed( sal_False ) +, m_pStream( NULL ) +, m_pStorage( NULL ) +, m_pListenersContainer( NULL ) +, m_xFactory( xFactory ) +, m_bNoTemporaryCopy( sal_False ) +{ + OSL_ENSURE( m_xFactory.is(), "No factory is provided on creation!\n" ); + if ( !m_xFactory.is() ) + throw uno::RuntimeException(); +} + +// -------------------------------------------------------------------------------- +OLESimpleStorage::~OLESimpleStorage() +{ + try { + m_refCount++; + dispose(); + } catch( uno::Exception& ) + {} + + if ( m_pListenersContainer ) + { + delete m_pListenersContainer; + m_pListenersContainer = NULL; + } +} + +//------------------------------------------------------------------------- +uno::Sequence< ::rtl::OUString > SAL_CALL OLESimpleStorage::impl_staticGetSupportedServiceNames() +{ + uno::Sequence< ::rtl::OUString > aRet(1); + aRet[0] = ::rtl::OUString::createFromAscii("com.sun.star.embed.OLESimpleStorage"); + return aRet; +} + +//------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OLESimpleStorage::impl_staticGetImplementationName() +{ + return ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.OLESimpleStorage"); +} + +//------------------------------------------------------------------------- +uno::Reference< uno::XInterface > SAL_CALL OLESimpleStorage::impl_staticCreateSelfInstance( + const uno::Reference< lang::XMultiServiceFactory >& xServiceManager ) +{ + return uno::Reference< uno::XInterface >( *new OLESimpleStorage( xServiceManager ) ); +} + +//------------------------------------------------------------------------- +void OLESimpleStorage::UpdateOriginal_Impl() +{ + if ( !m_bNoTemporaryCopy ) + { + uno::Reference< io::XSeekable > xSeek( m_xStream, uno::UNO_QUERY_THROW ); + xSeek->seek( 0 ); + + uno::Reference< io::XSeekable > xTempSeek( m_xTempStream, uno::UNO_QUERY_THROW ); + sal_Int64 nPos = xTempSeek->getPosition(); + xTempSeek->seek( 0 ); + + uno::Reference< io::XInputStream > xTempInp = m_xTempStream->getInputStream(); + uno::Reference< io::XOutputStream > xOutputStream = m_xStream->getOutputStream(); + if ( !xTempInp.is() || !xOutputStream.is() ) + throw uno::RuntimeException(); + + uno::Reference< io::XTruncate > xTrunc( xOutputStream, uno::UNO_QUERY_THROW ); + xTrunc->truncate(); + + ::comphelper::OStorageHelper::CopyInputToOutput( xTempInp, xOutputStream ); + xOutputStream->flush(); + xTempSeek->seek( nPos ); + } +} + +//------------------------------------------------------------------------- +void OLESimpleStorage::InsertInputStreamToStorage_Impl( BaseStorage* pStorage, ::rtl::OUString aName, const uno::Reference< io::XInputStream >& xInputStream ) + throw ( uno::Exception ) +{ + if ( !pStorage || !aName.getLength() || !xInputStream.is() ) + throw uno::RuntimeException(); + + if ( pStorage->IsContained( aName ) ) + throw container::ElementExistException(); // TODO: + + BaseStorageStream* pNewStream = pStorage->OpenStream( aName ); + if ( !pNewStream || pNewStream->GetError() || pStorage->GetError() ) + { + if ( pNewStream ) + DELETEZ( pNewStream ); + pStorage->ResetError(); + throw io::IOException(); // TODO + } + + try + { + uno::Sequence< sal_Int8 > aData( nBytesCount ); + sal_Int32 nRead = 0; + do + { + nRead = xInputStream->readBytes( aData, nBytesCount ); + if ( nRead < nBytesCount ) + aData.realloc( nRead ); + + sal_Int32 nWritten = pNewStream->Write( aData.getArray(), nRead ); + if ( nWritten < nRead ) + throw io::IOException(); + } while( nRead == nBytesCount ); + } + catch( uno::Exception& ) + { + DELETEZ( pNewStream ); + pStorage->Remove( aName ); + + throw; + } + + DELETEZ( pNewStream ); +} + +//------------------------------------------------------------------------- +void OLESimpleStorage::InsertNameAccessToStorage_Impl( BaseStorage* pStorage, ::rtl::OUString aName, const uno::Reference< container::XNameAccess >& xNameAccess ) + throw ( uno::Exception ) +{ + if ( !pStorage || !aName.getLength() || !xNameAccess.is() ) + throw uno::RuntimeException(); + + if ( pStorage->IsContained( aName ) ) + throw container::ElementExistException(); // TODO: + + BaseStorage* pNewStorage = pStorage->OpenStorage( aName ); + if ( !pNewStorage || pNewStorage->GetError() || pStorage->GetError() ) + { + if ( pNewStorage ) + DELETEZ( pNewStorage ); + pStorage->ResetError(); + throw io::IOException(); // TODO + } + + try + { + uno::Sequence< ::rtl::OUString > aElements = xNameAccess->getElementNames(); + for ( sal_Int32 nInd = 0; nInd < aElements.getLength(); nInd++ ) + { + uno::Reference< io::XInputStream > xInputStream; + uno::Reference< container::XNameAccess > xSubNameAccess; + uno::Any aAny = xNameAccess->getByName( aElements[nInd] ); + if ( aAny >>= xInputStream ) + InsertInputStreamToStorage_Impl( pNewStorage, aElements[nInd], xInputStream ); + else if ( aAny >>= xSubNameAccess ) + InsertNameAccessToStorage_Impl( pNewStorage, aElements[nInd], xSubNameAccess ); + } + } + catch( uno::Exception& ) + { + DELETEZ( pNewStorage ); + pStorage->Remove( aName ); + + throw; + } + + DELETEZ( pNewStorage ); +} + +//____________________________________________________________________________________________________ +// XInitialization +//____________________________________________________________________________________________________ + +void SAL_CALL OLESimpleStorage::initialize( const uno::Sequence< uno::Any >& aArguments ) + throw ( uno::Exception, + uno::RuntimeException) +{ + if ( m_pStream || m_pStorage ) + throw io::IOException(); // TODO: already initilized + + sal_Int32 nArgNum = aArguments.getLength(); + OSL_ENSURE( nArgNum >= 1 && nArgNum <= 2, "Wrong parameter number" ); + + if ( nArgNum < 1 || nArgNum > 2 ) + throw lang::IllegalArgumentException(); // TODO: + + uno::Reference< io::XStream > xStream; + uno::Reference< io::XInputStream > xInputStream; + if ( !( aArguments[0] >>= xStream ) && !( aArguments[0] >>= xInputStream ) ) + throw lang::IllegalArgumentException(); // TODO: + + if ( nArgNum == 2 ) + { + if ( !( aArguments[1] >>= m_bNoTemporaryCopy ) ) + throw lang::IllegalArgumentException(); // TODO: + } + + if ( m_bNoTemporaryCopy ) + { + // TODO: ??? + // If the temporary stream is not created, the original stream must be wrapped + // since SvStream wrapper closes the stream is owns + if ( xInputStream.is() ) + { + // the stream must be seekable for direct access + uno::Reference< io::XSeekable > xSeek( xInputStream, uno::UNO_QUERY_THROW ); + m_pStream = ::utl::UcbStreamHelper::CreateStream( xInputStream, sal_False ); + } + else if ( xStream.is() ) + { + // the stream must be seekable for direct access + uno::Reference< io::XSeekable > xSeek( xStream, uno::UNO_QUERY_THROW ); + m_pStream = ::utl::UcbStreamHelper::CreateStream( xStream, sal_False ); + } + else + throw lang::IllegalArgumentException(); // TODO: + } + else + { + uno::Reference < io::XStream > xTempFile( + m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), + uno::UNO_QUERY_THROW ); + uno::Reference < io::XSeekable > xTempSeek( xTempFile, uno::UNO_QUERY_THROW ); + uno::Reference< io::XOutputStream > xTempOut = xTempFile->getOutputStream(); + if ( !xTempOut.is() ) + throw uno::RuntimeException(); + + if ( xInputStream.is() ) + { + try + { + uno::Reference< io::XSeekable > xSeek( xInputStream, uno::UNO_QUERY_THROW ); + xSeek->seek( 0 ); + } + catch( uno::Exception& ) + {} + + ::comphelper::OStorageHelper::CopyInputToOutput( xInputStream, xTempOut ); + xTempOut->closeOutput(); + xTempSeek->seek( 0 ); + uno::Reference< io::XInputStream > xTempInput = xTempFile->getInputStream(); + m_pStream = ::utl::UcbStreamHelper::CreateStream( xTempInput, sal_False ); + } + else if ( xStream.is() ) + { + // not sure that the storage flashes the stream on commit + m_xStream = xStream; + m_xTempStream = xTempFile; + + uno::Reference< io::XSeekable > xSeek( xStream, uno::UNO_QUERY_THROW ); + xSeek->seek( 0 ); + uno::Reference< io::XInputStream > xInpStream = xStream->getInputStream(); + if ( !xInpStream.is() || !xStream->getOutputStream().is() ) + throw uno::RuntimeException(); + + ::comphelper::OStorageHelper::CopyInputToOutput( xInpStream, xTempOut ); + xTempOut->flush(); + xTempSeek->seek( 0 ); + + m_pStream = ::utl::UcbStreamHelper::CreateStream( xTempFile, sal_False ); + } + else + throw lang::IllegalArgumentException(); // TODO: + } + + if ( !m_pStream || m_pStream->GetError() ) + throw io::IOException(); // TODO + + m_pStorage = new Storage( *m_pStream, sal_False ); +} + + +//____________________________________________________________________________________________________ +// XNameContainer +//____________________________________________________________________________________________________ + +// -------------------------------------------------------------------------------- +void SAL_CALL OLESimpleStorage::insertByName( const ::rtl::OUString& aName, const uno::Any& aElement ) + throw ( lang::IllegalArgumentException, + container::ElementExistException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_pStorage ) + throw uno::RuntimeException(); + + uno::Reference< io::XStream > xStream; + uno::Reference< io::XInputStream > xInputStream; + uno::Reference< container::XNameAccess > xNameAccess; + + try + { + if ( !m_bNoTemporaryCopy && !m_xStream.is() ) + throw io::IOException(); // TODO + + if ( aElement >>= xStream ) + xInputStream = xStream->getInputStream(); + else if ( !( aElement >>= xInputStream ) && !( aElement >>= xNameAccess ) ) + throw lang::IllegalArgumentException(); // TODO: + + if ( xInputStream.is() ) + InsertInputStreamToStorage_Impl( m_pStorage, aName, xInputStream ); + else if ( xNameAccess.is() ) + InsertNameAccessToStorage_Impl( m_pStorage, aName, xNameAccess ); + else + throw uno::RuntimeException(); + } + catch( uno::RuntimeException& ) + { + throw; + } + catch( container::ElementExistException& ) + { + throw; + } + catch( uno::Exception& e ) + { + throw lang::WrappedTargetException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Insert has failed!" ) ), + uno::Reference< uno::XInterface >(), + uno::makeAny( e ) ); + } +} + +// -------------------------------------------------------------------------------- +void SAL_CALL OLESimpleStorage::removeByName( const ::rtl::OUString& aName ) + throw ( container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_pStorage ) + throw uno::RuntimeException(); + + if ( !m_bNoTemporaryCopy && !m_xStream.is() ) + throw lang::WrappedTargetException(); // io::IOException(); // TODO + + if ( !m_pStorage->IsContained( aName ) ) + throw container::NoSuchElementException(); // TODO: + + m_pStorage->Remove( aName ); + + if ( m_pStorage->GetError() ) + { + m_pStorage->ResetError(); + throw lang::WrappedTargetException(); // io::IOException(); // TODO + } +} + +// -------------------------------------------------------------------------------- +void SAL_CALL OLESimpleStorage::replaceByName( const ::rtl::OUString& aName, const uno::Any& aElement ) + throw ( lang::IllegalArgumentException, + container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + removeByName( aName ); + + try + { + insertByName( aName, aElement ); + } + catch( container::ElementExistException& ) + { + uno::Any aCaught( ::cppu::getCaughtException() ); + + throw lang::WrappedTargetException( ::rtl::OUString::createFromAscii( "Can't copy raw stream" ), + uno::Reference< uno::XInterface >(), + aCaught ); + } +} + +// -------------------------------------------------------------------------------- +uno::Any SAL_CALL OLESimpleStorage::getByName( const ::rtl::OUString& aName ) + throw ( container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_pStorage ) + throw uno::RuntimeException(); + + if ( !m_pStorage->IsContained( aName ) ) + throw container::NoSuchElementException(); // TODO: + + uno::Any aResult; + + uno::Reference< io::XStream > xTempFile( + m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), + uno::UNO_QUERY ); + uno::Reference< io::XSeekable > xSeekable( xTempFile, uno::UNO_QUERY_THROW ); + uno::Reference< io::XOutputStream > xOutputStream = xTempFile->getOutputStream(); + uno::Reference< io::XInputStream > xInputStream = xTempFile->getInputStream(); + if ( !xOutputStream.is() || !xInputStream.is() ) + throw uno::RuntimeException(); + + if ( m_pStorage->IsStorage( aName ) ) + { + BaseStorage* pStrg = m_pStorage->OpenStorage( aName ); + m_pStorage->ResetError(); + if ( !pStrg ) + throw io::IOException(); + + SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xTempFile, sal_False ); // do not close the original stream + if ( !pStream ) + throw uno::RuntimeException(); + + BaseStorage* pNewStor = new Storage( *pStream, sal_False ); + sal_Bool bSuccess = + ( pStrg->CopyTo( pNewStor ) && pNewStor->Commit() && !pNewStor->GetError() && !pStrg->GetError() ); + + DELETEZ( pNewStor ); + DELETEZ( pStrg ); + DELETEZ( pStream ); + + if ( !bSuccess ) + throw uno::RuntimeException(); + + uno::Sequence< uno::Any > aArgs( 2 ); + aArgs[0] <<= xInputStream; // allow readonly access only + aArgs[1] <<= (sal_Bool)sal_True; // do not create copy + + uno::Reference< container::XNameContainer > xResultNameContainer( + m_xFactory->createInstanceWithArguments( + ::rtl::OUString::createFromAscii( "com.sun.star.embed.OLESimpleStorage" ), + aArgs ), + uno::UNO_QUERY_THROW ); + + aResult <<= xResultNameContainer; + } + else + { + BaseStorageStream* pStream = m_pStorage->OpenStream( aName, STREAM_READ | STREAM_SHARE_DENYALL | STREAM_NOCREATE ); + if ( !pStream || pStream->GetError() || m_pStorage->GetError() ) + { + m_pStorage->ResetError(); + DELETEZ( pStream ); + throw io::IOException(); // TODO + } + + try + { + uno::Sequence< sal_Int8 > aData( nBytesCount ); + sal_Int32 nSize = nBytesCount; + sal_Int32 nRead = 0; + while( 0 != ( nRead = pStream->Read( aData.getArray(), nSize ) ) ) + { + if ( nRead < nSize ) + { + nSize = nRead; + aData.realloc( nSize ); + } + + xOutputStream->writeBytes( aData ); + } + + if ( pStream->GetError() ) + throw io::IOException(); // TODO + + xOutputStream->closeOutput(); + xSeekable->seek( 0 ); + } + catch( uno::RuntimeException& ) + { + DELETEZ( pStream ); + throw; + } + catch( uno::Exception& ) + { + DELETEZ( pStream ); + throw lang::WrappedTargetException(); // TODO: + } + + DELETEZ( pStream ); + + aResult <<= xInputStream; + } + + return aResult; +} + +// -------------------------------------------------------------------------------- +uno::Sequence< ::rtl::OUString > SAL_CALL OLESimpleStorage::getElementNames() + throw ( uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_pStorage ) + throw uno::RuntimeException(); + + SvStorageInfoList aList; + m_pStorage->FillInfoList( &aList ); + + if ( m_pStorage->GetError() ) + { + m_pStorage->ResetError(); + throw uno::RuntimeException(); // TODO: + } + + uno::Sequence< ::rtl::OUString > aSeq( aList.Count() ); + for ( sal_uInt32 nInd = 0; nInd < aList.Count(); nInd++ ) + aSeq[nInd] = aList[nInd].GetName(); + + return aSeq; +} + +// -------------------------------------------------------------------------------- +sal_Bool SAL_CALL OLESimpleStorage::hasByName( const ::rtl::OUString& aName ) + throw ( uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_pStorage ) + throw uno::RuntimeException(); + + sal_Bool bResult = m_pStorage->IsContained( aName ); + + if ( m_pStorage->GetError() ) + { + m_pStorage->ResetError(); + throw uno::RuntimeException(); // TODO: + } + + return bResult; +} + +// -------------------------------------------------------------------------------- +uno::Type SAL_CALL OLESimpleStorage::getElementType() + throw ( uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + return getCppuType( (const uno::Reference< io::XInputStream >*)NULL ); +} + +// -------------------------------------------------------------------------------- +sal_Bool SAL_CALL OLESimpleStorage::hasElements() + throw ( uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_pStorage ) + throw uno::RuntimeException(); + + SvStorageInfoList aList; + m_pStorage->FillInfoList( &aList ); + + if ( m_pStorage->GetError() ) + { + m_pStorage->ResetError(); + throw uno::RuntimeException(); // TODO: + } + + return ( aList.Count() != 0 ); +} + +//____________________________________________________________________________________________________ +// XComponent +//____________________________________________________________________________________________________ + +// -------------------------------------------------------------------------------- +void SAL_CALL OLESimpleStorage::dispose() + throw ( uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( m_pListenersContainer ) + { + lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) ); + m_pListenersContainer->disposeAndClear( aSource ); + } + + DELETEZ( m_pStorage ); + DELETEZ( m_pStream ); + + m_xStream = uno::Reference< io::XStream >(); + m_xTempStream = uno::Reference< io::XStream >(); + + m_bDisposed = sal_True; +} + +// -------------------------------------------------------------------------------- +void SAL_CALL OLESimpleStorage::addEventListener( + const uno::Reference< lang::XEventListener >& xListener ) + throw ( uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_pListenersContainer ) + m_pListenersContainer = new ::cppu::OInterfaceContainerHelper( m_aMutex ); + + m_pListenersContainer->addInterface( xListener ); +} + +// -------------------------------------------------------------------------------- +void SAL_CALL OLESimpleStorage::removeEventListener( + const uno::Reference< lang::XEventListener >& xListener ) + throw ( uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( m_pListenersContainer ) + m_pListenersContainer->removeInterface( xListener ); +} + +//____________________________________________________________________________________________________ +// XTransactedObject +//____________________________________________________________________________________________________ + +// -------------------------------------------------------------------------------- +void SAL_CALL OLESimpleStorage::commit() + throw ( ::com::sun::star::io::IOException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_pStorage ) + throw uno::RuntimeException(); + + if ( !m_bNoTemporaryCopy && !m_xStream.is() ) + throw io::IOException(); // TODO + + if ( !m_pStorage->Commit() || m_pStorage->GetError() ) + { + m_pStorage->ResetError(); + throw io::IOException(); // TODO + } + + UpdateOriginal_Impl(); +} + +// -------------------------------------------------------------------------------- +void SAL_CALL OLESimpleStorage::revert() + throw ( ::com::sun::star::io::IOException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_pStorage ) + throw uno::RuntimeException(); + + if ( !m_bNoTemporaryCopy && !m_xStream.is() ) + throw io::IOException(); // TODO + + if ( !m_pStorage->Revert() || m_pStorage->GetError() ) + { + m_pStorage->ResetError(); + throw io::IOException(); // TODO + } + + UpdateOriginal_Impl(); +} + +//____________________________________________________________________________________________________ +// XClassifiedObject +//____________________________________________________________________________________________________ + +uno::Sequence< sal_Int8 > SAL_CALL OLESimpleStorage::getClassID() + throw ( uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_pStorage ) + throw uno::RuntimeException(); + + return m_pStorage->GetClassName().GetByteSequence(); +} + +::rtl::OUString SAL_CALL OLESimpleStorage::getClassName() + throw ( uno::RuntimeException ) +{ + return ::rtl::OUString(); +} + +void SAL_CALL OLESimpleStorage::setClassInfo( const uno::Sequence< sal_Int8 >& /*aClassID*/, + const ::rtl::OUString& /*sClassName*/ ) + throw ( lang::NoSupportException, + uno::RuntimeException ) +{ + throw lang::NoSupportException(); +} + +//____________________________________________________________________________________________________ +// XServiceInfo +//____________________________________________________________________________________________________ + +// -------------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OLESimpleStorage::getImplementationName() + throw ( uno::RuntimeException ) +{ + return impl_staticGetImplementationName(); +} + +// -------------------------------------------------------------------------------- +::sal_Bool SAL_CALL OLESimpleStorage::supportsService( const ::rtl::OUString& ServiceName ) + throw ( uno::RuntimeException ) +{ + uno::Sequence< ::rtl::OUString > aSeq = impl_staticGetSupportedServiceNames(); + + for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ ) + if ( ServiceName.compareTo( aSeq[nInd] ) == 0 ) + return sal_True; + + return sal_False; +} + +// -------------------------------------------------------------------------------- +uno::Sequence< ::rtl::OUString > SAL_CALL OLESimpleStorage::getSupportedServiceNames() + throw ( uno::RuntimeException ) +{ + return impl_staticGetSupportedServiceNames(); +} + + diff --git a/sot/source/unoolestorage/xolesimplestorage.hxx b/sot/source/unoolestorage/xolesimplestorage.hxx new file mode 100644 index 000000000000..c9f1b5c68b0a --- /dev/null +++ b/sot/source/unoolestorage/xolesimplestorage.hxx @@ -0,0 +1,195 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef __XOLESIMPLESTORAGE_HXX_ +#define __XOLESIMPLESTORAGE_HXX_ + +#include <com/sun/star/embed/XOLESimpleStorage.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/embed/XClassifiedObject.hpp> + + +#include <com/sun/star/io/XOutputStream.hpp> +#include <cppuhelper/implbase3.hxx> +#include <cppuhelper/interfacecontainer.h> + +#include <osl/mutex.hxx> + +#include <stg.hxx> + + +class OLESimpleStorage : public ::cppu::WeakImplHelper3 + < ::com::sun::star::embed::XOLESimpleStorage + , ::com::sun::star::lang::XInitialization + , ::com::sun::star::lang::XServiceInfo > +{ + ::osl::Mutex m_aMutex; + + sal_Bool m_bDisposed; + + ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream > m_xStream; + ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream > m_xTempStream; + SvStream* m_pStream; + BaseStorage* m_pStorage; + + ::cppu::OInterfaceContainerHelper* m_pListenersContainer; // list of listeners + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xFactory; + + sal_Bool m_bNoTemporaryCopy; + + void UpdateOriginal_Impl(); + + static void InsertInputStreamToStorage_Impl( BaseStorage* pStorage, ::rtl::OUString aName, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xInputStream ) + throw ( ::com::sun::star::uno::Exception ); + + static void InsertNameAccessToStorage_Impl( BaseStorage* pStorage, ::rtl::OUString aName, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& xNameAccess ) + throw ( ::com::sun::star::uno::Exception ); + +public: + + OLESimpleStorage( ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xFactory ); + + virtual ~OLESimpleStorage(); + + static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL impl_staticGetSupportedServiceNames(); + static ::rtl::OUString SAL_CALL impl_staticGetImplementationName(); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL + impl_staticCreateSelfInstance( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ); + + + //____________________________________________________________________________________________________ + // XInitialization + //____________________________________________________________________________________________________ + + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw ( ::com::sun::star::uno::Exception, + ::com::sun::star::uno::RuntimeException); + + //____________________________________________________________________________________________________ + // XNameContainer + //____________________________________________________________________________________________________ + + virtual void SAL_CALL insertByName( const ::rtl::OUString& aName, const ::com::sun::star::uno::Any& aElement ) + throw ( ::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::container::ElementExistException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL removeByName( const ::rtl::OUString& Name ) + throw ( ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL replaceByName( const ::rtl::OUString& aName, const ::com::sun::star::uno::Any& aElement ) + throw ( ::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) + throw ( ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException ); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames() + throw ( ::com::sun::star::uno::RuntimeException ); + + virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) + throw ( ::com::sun::star::uno::RuntimeException ); + + virtual ::com::sun::star::uno::Type SAL_CALL getElementType() + throw ( ::com::sun::star::uno::RuntimeException ); + + virtual sal_Bool SAL_CALL hasElements() + throw ( ::com::sun::star::uno::RuntimeException ); + + //____________________________________________________________________________________________________ + // XComponent + //____________________________________________________________________________________________________ + + virtual void SAL_CALL dispose() + throw ( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL addEventListener( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& xListener ) + throw ( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL removeEventListener( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& xListener ) + throw ( ::com::sun::star::uno::RuntimeException ); + + //____________________________________________________________________________________________________ + // XTransactedObject + //____________________________________________________________________________________________________ + + virtual void SAL_CALL commit() + throw ( ::com::sun::star::io::IOException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL revert() + throw ( ::com::sun::star::io::IOException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException ); + + //____________________________________________________________________________________________________ + // XClassifiedObject + //____________________________________________________________________________________________________ + + virtual ::com::sun::star::uno::Sequence< ::sal_Int8 > SAL_CALL getClassID() + throw ( ::com::sun::star::uno::RuntimeException ); + + virtual ::rtl::OUString SAL_CALL getClassName() + throw ( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setClassInfo( const ::com::sun::star::uno::Sequence< ::sal_Int8 >& aClassID, + const ::rtl::OUString& sClassName ) + throw ( ::com::sun::star::lang::NoSupportException, + ::com::sun::star::uno::RuntimeException ); + + //____________________________________________________________________________________________________ + // XServiceInfo + //____________________________________________________________________________________________________ + + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw ( ::com::sun::star::uno::RuntimeException ); + + virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw ( ::com::sun::star::uno::RuntimeException ); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() + throw ( ::com::sun::star::uno::RuntimeException ); + +}; + +#endif + diff --git a/sot/util/makefile.mk b/sot/util/makefile.mk new file mode 100644 index 000000000000..72d17db189be --- /dev/null +++ b/sot/util/makefile.mk @@ -0,0 +1,89 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=.. + +PRJNAME=sot +TARGET=sot + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +LIB1TARGET= $(SLB)$/$(TARGET).lib +.IF "$(GUI)$(COM)"=="WNTGCC" +LIB1ARCHIV= $(LB)$/lib$(TARGET)$(DLLPOSTFIX)_static.a +.ELSE +LIB1ARCHIV= $(LB)$/lib$(TARGET)$(DLLPOSTFIX).a +.ENDIF +LIB1FILES= $(SLB)$/base.lib \ + $(SLB)$/sdstor.lib \ + $(SLB)$/unoolestorage.lib + +SHL1TARGET= $(TARGET)$(DLLPOSTFIX) +SHL1IMPLIB= $(TARGET) +SHL1USE_EXPORTS=name +SHL1LIBS= $(SLB)$/$(TARGET).lib + +SHL1STDLIBS=$(TOOLSLIB) $(SALLIB) $(UNOTOOLSLIB) $(CPPUHELPERLIB) $(COMPHELPERLIB) $(UCBHELPERLIB) $(CPPULIB) + +SHL1DEF= $(MISC)$/$(SHL1TARGET).def + +DEF1NAME =$(SHL1TARGET) +DEF1DEPN =$(MISC)$/$(SHL1TARGET).flt \ + $(PRJ)$/inc$/absdev.hxx \ + $(PRJ)$/inc$/agg.hxx \ + $(PRJ)$/inc$/sot$/exchange.hxx \ + $(PRJ)$/inc$/sot$/factory.hxx \ + $(PRJ)$/inc$/sot$/object.hxx \ + $(PRJ)$/inc$/sot$/sotdata.hxx \ + $(PRJ)$/inc$/sot$/sotref.hxx \ + $(PRJ)$/inc$/stg.hxx \ + $(PRJ)$/inc$/sot$/storage.hxx \ + $(PRJ)$/inc$/storinfo.hxx +DEFLIB1NAME =$(TARGET) +DEF1DES =StarObjectsTools + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk + +$(MISC)$/$(SHL1TARGET).flt: makefile.mk + @echo ------------------------------ + @echo Making: $@ + $(TYPE) sot.flt > $@ + + +ALLTAR : $(MISC)/sot.component + +$(MISC)/sot.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + sot.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt sot.component diff --git a/sot/util/makefile.pmk b/sot/util/makefile.pmk new file mode 100644 index 000000000000..2d79b8068815 --- /dev/null +++ b/sot/util/makefile.pmk @@ -0,0 +1,31 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +# define SOT_DLLIMPLEMENTATION (see @ = sotdllapi.h) +CDEFS += -DSOT_DLLIMPLEMENTATION + +VISIBILITY_HIDDEN=TRUE diff --git a/sot/util/sot.component b/sot/util/sot.component new file mode 100644 index 000000000000..7d17c7d54475 --- /dev/null +++ b/sot/util/sot.component @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org 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 version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.embed.OLESimpleStorage"> + <service name="com.sun.star.embed.OLESimpleStorage"/> + </implementation> +</component> diff --git a/sot/util/sot.flt b/sot/util/sot.flt new file mode 100644 index 000000000000..ac2ea9c6a19d --- /dev/null +++ b/sot/util/sot.flt @@ -0,0 +1,6 @@ +WEP +LIBMAIN +LibMain +CT??_R0?AV +CTA2?AV +CTA3?AV diff --git a/sot/workben/makefile.mk b/sot/workben/makefile.mk new file mode 100644 index 000000000000..c1c8a8d0a2ca --- /dev/null +++ b/sot/workben/makefile.mk @@ -0,0 +1,53 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=.. + +PRJNAME=sot +TARGET=workben +LIBTARGET=NO +TARGETTYPE=CUI + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +OBJFILES= \ + $(OBJ)$/testsot.obj + +APP1TARGET= testsot +APP1OBJS= $(OBJ)$/testsot.obj +APP1STDLIBS=$(SOTLIB) \ + $(TOOLSLIB) + +APP1DEF= $(MISC)$/$(APP1TARGET).def + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/sot/workben/testsot.cxx b/sot/workben/testsot.cxx new file mode 100644 index 000000000000..0bdc3113870f --- /dev/null +++ b/sot/workben/testsot.cxx @@ -0,0 +1,55 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sot.hxx" + +#include <sot/storage.hxx> + +/* + * main. + */ +int main (int argc, sal_Char **argv) +{ + SotStorageRef xStor = new SotStorage( "c:\\temp\\65254.ppt" ); +/* + SotStorageRef xStor = new SotStorage( "c:\\temp\\video.sdb" ); + SotStorageRef xStor = new SotStorage( "c:\\temp\\video.sdb" ); + SotStorageRef x2Stor = xStor->OpenSotStorage( "1117" ); + + SotStorageStreamRef xStm = x2Stor->OpenSotStream( "Genres", STREAM_STD_READWRITE | STREAM_TRUNC); + //BYTE szData[100]; + //xStm->Write( szData, 100 ); + UINT32 nSize = xStm->GetSize(); + xStm->SetSize( 0 ); + nSize = xStm->GetSize(); + x2Stor->Commit(); + xStor->Commit(); +*/ + return 0; +} + |