diff options
Diffstat (limited to 'filter/source/msfilter')
27 files changed, 32681 insertions, 0 deletions
diff --git a/filter/source/msfilter/countryid.cxx b/filter/source/msfilter/countryid.cxx new file mode 100644 index 000000000000..3239e5020cfb --- /dev/null +++ b/filter/source/msfilter/countryid.cxx @@ -0,0 +1,342 @@ +/************************************************************************* + * + * 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_filter.hxx" + +// ============================================================================ +#include "filter/msfilter/countryid.hxx" + +#include <algorithm> + +// ---------------------------------------------------------------------------- + +namespace msfilter { + +// Mapping table ============================================================== + +namespace { + +// ---------------------------------------------------------------------------- + +/** Table entry for Windows country ID <-> language type conversion. + + The first member is the Windows country ID, as defined in the header. + + The second member contains the corresponding language type for each country + ID. This must be a full language, not only the primary language type. + + The last bool flag defines, if the sub language type should be evaluated to + find the country ID from a language. If not set, all languages map to the + country which contain the given primary language type. + + Example: The language entry (COUNTRY_USA,LANGUAGE_ENGLISH_US,false) maps + the country ID for USA to the language LANGUAGE_ENGLISH_US. The clear sub + language flag causes all english languages LANGUAGE_ENGLISH_*** to map to + this country ID by default. To map the special case LANGUAGE_ENGLISH_EIRE + to the country ID COUNTRY_IRELAND, the sub language flag must be set in the + respective table entry, here (COUNTRY_IRELAND,LANGUAGE_ENGLISH_EIRE,true). + */ +struct CountryEntry +{ + CountryId meCountry; /// Windows country ID. + LanguageType meLanguage; /// Corresponding language type. + bool mbUseSubLang; /// false = Primary only, true = Primary and sub language. +}; + +// ---------------------------------------------------------------------------- + +/** Table for Windows country ID <-> language type conversion. + + To map the same language to different country IDs, some of the entries + should contain a set sub language flag (see description of CountryEntry). + All table entries with a set flag take priority over the entry with the + same primary language, but cleared sub language flag, regardless of the + position in the table. + + To map different languages to the same country ID, several entries with the + same country ID may be inserted. In this case the conversion to a language + is done with the first found entry (starting from top) containing the given + country ID. + + For now all entries are sorted by country ID, but this is not required. + */ +static const CountryEntry pTable[] = +{ + { COUNTRY_USA, LANGUAGE_ENGLISH_US, false }, + { COUNTRY_DOMINICAN_REPUBLIC, LANGUAGE_SPANISH_DOMINICAN_REPUBLIC, true }, + { COUNTRY_JAMAICA, LANGUAGE_ENGLISH_JAMAICA, true }, + { COUNTRY_PUERTO_RICO, LANGUAGE_SPANISH_PUERTO_RICO, true }, + { COUNTRY_TRINIDAD_Y_TOBAGO, LANGUAGE_ENGLISH_TRINIDAD, true }, + { COUNTRY_CANADA, LANGUAGE_ENGLISH_CAN, true }, + { COUNTRY_CANADA, LANGUAGE_FRENCH_CANADIAN, true }, + { COUNTRY_RUSSIA, LANGUAGE_RUSSIAN, false }, + { COUNTRY_KAZAKHSTAN, LANGUAGE_KAZAK, false }, + { COUNTRY_TATARSTAN, LANGUAGE_TATAR, false }, + { COUNTRY_EGYPT, LANGUAGE_ARABIC_EGYPT, true }, + { COUNTRY_SOUTH_AFRICA, LANGUAGE_AFRIKAANS, false }, + { COUNTRY_SOUTH_AFRICA, LANGUAGE_ENGLISH_SAFRICA, true }, + { COUNTRY_SOUTH_AFRICA, LANGUAGE_TSONGA, false }, + { COUNTRY_SOUTH_AFRICA, LANGUAGE_VENDA, false }, + { COUNTRY_SOUTH_AFRICA, LANGUAGE_XHOSA, false }, + { COUNTRY_SOUTH_AFRICA, LANGUAGE_ZULU, false }, + { COUNTRY_GREECE, LANGUAGE_GREEK, false }, + { COUNTRY_NETHERLANDS, LANGUAGE_DUTCH, false }, + { COUNTRY_NETHERLANDS, LANGUAGE_FRISIAN_NETHERLANDS, false }, + { COUNTRY_BELGIUM, LANGUAGE_DUTCH_BELGIAN, true }, + { COUNTRY_BELGIUM, LANGUAGE_FRENCH_BELGIAN, true }, + { COUNTRY_FRANCE, LANGUAGE_FRENCH, false }, + { COUNTRY_SPAIN, LANGUAGE_SPANISH_MODERN, false }, + { COUNTRY_SPAIN, LANGUAGE_SPANISH_DATED, false }, + { COUNTRY_SPAIN, LANGUAGE_CATALAN, false }, + { COUNTRY_SPAIN, LANGUAGE_BASQUE, false }, + { COUNTRY_SPAIN, LANGUAGE_GALICIAN, false }, + { COUNTRY_HUNGARY, LANGUAGE_HUNGARIAN, false }, + { COUNTRY_ITALY, LANGUAGE_ITALIAN, false }, + { COUNTRY_ROMANIA, LANGUAGE_ROMANIAN, false }, + { COUNTRY_SWITZERLAND, LANGUAGE_GERMAN_SWISS, true }, + { COUNTRY_SWITZERLAND, LANGUAGE_FRENCH_SWISS, true }, + { COUNTRY_SWITZERLAND, LANGUAGE_ITALIAN_SWISS, true }, + { COUNTRY_SWITZERLAND, LANGUAGE_RHAETO_ROMAN, false }, + { COUNTRY_AUSTRIA, LANGUAGE_GERMAN_AUSTRIAN, true }, + { COUNTRY_UNITED_KINGDOM, LANGUAGE_ENGLISH_UK, true }, + { COUNTRY_UNITED_KINGDOM, LANGUAGE_GAELIC_SCOTLAND, true }, + { COUNTRY_UNITED_KINGDOM, LANGUAGE_WELSH, false }, + { COUNTRY_DENMARK, LANGUAGE_DANISH, false }, + { COUNTRY_SWEDEN, LANGUAGE_SWEDISH, false }, + { COUNTRY_SWEDEN, LANGUAGE_SAMI_LAPPISH, false }, + { COUNTRY_NORWAY, LANGUAGE_NORWEGIAN_BOKMAL, false }, + { COUNTRY_POLAND, LANGUAGE_POLISH, false }, + { COUNTRY_GERMANY, LANGUAGE_GERMAN, false }, + { COUNTRY_GERMANY, LANGUAGE_SORBIAN, false }, + { COUNTRY_PERU, LANGUAGE_SPANISH_PERU, true }, + { COUNTRY_MEXICO, LANGUAGE_SPANISH_MEXICAN, true }, + { COUNTRY_ARGENTINIA, LANGUAGE_SPANISH_ARGENTINA, true }, + { COUNTRY_BRAZIL, LANGUAGE_PORTUGUESE_BRAZILIAN, true }, + { COUNTRY_CHILE, LANGUAGE_SPANISH_CHILE, true }, + { COUNTRY_COLOMBIA, LANGUAGE_SPANISH_COLOMBIA, true }, + { COUNTRY_VENEZUELA, LANGUAGE_SPANISH_VENEZUELA, true }, + { COUNTRY_MALAYSIA, LANGUAGE_MALAY_MALAYSIA, false }, + { COUNTRY_AUSTRALIA, LANGUAGE_ENGLISH_AUS, true }, + { COUNTRY_INDONESIA, LANGUAGE_INDONESIAN, false }, + { COUNTRY_PHILIPPINES, LANGUAGE_ENGLISH_PHILIPPINES, true }, + { COUNTRY_NEW_ZEALAND, LANGUAGE_MAORI_NEW_ZEALAND, false }, + { COUNTRY_NEW_ZEALAND, LANGUAGE_ENGLISH_NZ, true }, + { COUNTRY_SINGAPORE, LANGUAGE_CHINESE_SINGAPORE, true }, + { COUNTRY_THAILAND, LANGUAGE_THAI, false }, + { COUNTRY_JAPAN, LANGUAGE_JAPANESE, false }, + { COUNTRY_SOUTH_KOREA, LANGUAGE_KOREAN, false }, + { COUNTRY_VIET_NAM, LANGUAGE_VIETNAMESE, false }, + { COUNTRY_PR_CHINA, LANGUAGE_CHINESE_SIMPLIFIED, false }, + { COUNTRY_TIBET, LANGUAGE_TIBETAN, false }, + { COUNTRY_TURKEY, LANGUAGE_TURKISH, false }, + { COUNTRY_INDIA, LANGUAGE_HINDI, false }, + { COUNTRY_INDIA, LANGUAGE_URDU_INDIA, true }, + { COUNTRY_INDIA, LANGUAGE_PUNJABI, false }, + { COUNTRY_INDIA, LANGUAGE_GUJARATI, false }, + { COUNTRY_INDIA, LANGUAGE_ORIYA, false }, + { COUNTRY_INDIA, LANGUAGE_TAMIL, false }, + { COUNTRY_INDIA, LANGUAGE_TELUGU, false }, + { COUNTRY_INDIA, LANGUAGE_KANNADA, false }, + { COUNTRY_INDIA, LANGUAGE_MALAYALAM, false }, + { COUNTRY_INDIA, LANGUAGE_ASSAMESE, false }, + { COUNTRY_INDIA, LANGUAGE_MARATHI, false }, + { COUNTRY_INDIA, LANGUAGE_SANSKRIT, false }, + { COUNTRY_INDIA, LANGUAGE_KONKANI, false }, + { COUNTRY_INDIA, LANGUAGE_MANIPURI, false }, + { COUNTRY_INDIA, LANGUAGE_SINDHI, false }, + { COUNTRY_INDIA, LANGUAGE_KASHMIRI, false }, + { COUNTRY_PAKISTAN, LANGUAGE_URDU_PAKISTAN, false }, + { COUNTRY_MYANMAR, LANGUAGE_BURMESE, false }, + { COUNTRY_MOROCCO, LANGUAGE_ARABIC_MOROCCO, true }, + { COUNTRY_ALGERIA, LANGUAGE_ARABIC_ALGERIA, true }, + { COUNTRY_TUNISIA, LANGUAGE_ARABIC_TUNISIA, true }, + { COUNTRY_LIBYA, LANGUAGE_ARABIC_LIBYA, true }, + { COUNTRY_SENEGAL, LANGUAGE_FRENCH_SENEGAL, true }, + { COUNTRY_MALI, LANGUAGE_FRENCH_MALI, true }, + { COUNTRY_COTE_D_IVOIRE, LANGUAGE_FRENCH_COTE_D_IVOIRE, true }, + { COUNTRY_CAMEROON, LANGUAGE_FRENCH_CAMEROON, true }, + { COUNTRY_ZAIRE, LANGUAGE_FRENCH_ZAIRE, true }, + { COUNTRY_RWANDA, LANGUAGE_KINYARWANDA_RWANDA, false }, + { COUNTRY_KENYA, LANGUAGE_SWAHILI, false }, + { COUNTRY_REUNION, LANGUAGE_FRENCH_REUNION, true }, + { COUNTRY_ZIMBABWE, LANGUAGE_ENGLISH_ZIMBABWE, true }, + { COUNTRY_LESOTHO, LANGUAGE_SESOTHO, false }, + { COUNTRY_BOTSWANA, LANGUAGE_TSWANA, false }, + { COUNTRY_FAEROE_ISLANDS, LANGUAGE_FAEROESE, false }, + { COUNTRY_PORTUGAL, LANGUAGE_PORTUGUESE, false }, + { COUNTRY_LUXEMBOURG, LANGUAGE_GERMAN_LUXEMBOURG, true }, + { COUNTRY_LUXEMBOURG, LANGUAGE_FRENCH_LUXEMBOURG, true }, + { COUNTRY_IRELAND, LANGUAGE_ENGLISH_EIRE, true }, + { COUNTRY_IRELAND, LANGUAGE_GAELIC_IRELAND, true }, + { COUNTRY_ICELAND, LANGUAGE_ICELANDIC, false }, + { COUNTRY_ALBANIA, LANGUAGE_ALBANIAN, false }, + { COUNTRY_MALTA, LANGUAGE_MALTESE, false }, + { COUNTRY_FINLAND, LANGUAGE_FINNISH, false }, + { COUNTRY_FINLAND, LANGUAGE_SWEDISH_FINLAND, true }, + { COUNTRY_BULGARIA, LANGUAGE_BULGARIAN, false }, + { COUNTRY_LITHUANIA, LANGUAGE_LITHUANIAN, false }, + { COUNTRY_LATVIA, LANGUAGE_LATVIAN, false }, + { COUNTRY_ESTONIA, LANGUAGE_ESTONIAN, false }, + { COUNTRY_MOLDOVA, LANGUAGE_ROMANIAN_MOLDOVA, true }, + { COUNTRY_MOLDOVA, LANGUAGE_RUSSIAN_MOLDOVA, true }, + { COUNTRY_ARMENIA, LANGUAGE_ARMENIAN, false }, + { COUNTRY_BELARUS, LANGUAGE_BELARUSIAN, false }, + { COUNTRY_MONACO, LANGUAGE_FRENCH_MONACO, true }, + { COUNTRY_UKRAINE, LANGUAGE_UKRAINIAN, false }, + { COUNTRY_SERBIA, LANGUAGE_SERBIAN_LATIN, false }, + { COUNTRY_CROATIA, LANGUAGE_CROATIAN, true }, // sub type of LANGUAGE_SERBIAN + { COUNTRY_SLOVENIA, LANGUAGE_SLOVENIAN, false }, + { COUNTRY_MACEDONIA, LANGUAGE_MACEDONIAN, false }, + { COUNTRY_CZECH, LANGUAGE_CZECH, false }, + { COUNTRY_SLOVAK, LANGUAGE_SLOVAK, false }, + { COUNTRY_LIECHTENSTEIN, LANGUAGE_GERMAN_LIECHTENSTEIN, true }, + { COUNTRY_BELIZE, LANGUAGE_ENGLISH_BELIZE, true }, + { COUNTRY_GUATEMALA, LANGUAGE_SPANISH_GUATEMALA, true }, + { COUNTRY_EL_SALVADOR, LANGUAGE_SPANISH_EL_SALVADOR, true }, + { COUNTRY_HONDURAS, LANGUAGE_SPANISH_HONDURAS, true }, + { COUNTRY_NICARAGUA, LANGUAGE_SPANISH_NICARAGUA, true }, + { COUNTRY_COSTA_RICA, LANGUAGE_SPANISH_COSTARICA, true }, + { COUNTRY_PANAMA, LANGUAGE_SPANISH_PANAMA, true }, + { COUNTRY_BOLIVIA, LANGUAGE_SPANISH_BOLIVIA, true }, + { COUNTRY_ECUADOR, LANGUAGE_SPANISH_ECUADOR, true }, + { COUNTRY_PARAGUAY, LANGUAGE_SPANISH_PARAGUAY, true }, + { COUNTRY_URUGUAY, LANGUAGE_SPANISH_URUGUAY, true }, + { COUNTRY_BRUNEI_DARUSSALAM, LANGUAGE_MALAY_BRUNEI_DARUSSALAM, true }, + { COUNTRY_HONG_KONG, LANGUAGE_CHINESE_HONGKONG, true }, + { COUNTRY_MACAU, LANGUAGE_CHINESE_MACAU, true }, + { COUNTRY_CAMBODIA, LANGUAGE_KHMER, false }, + { COUNTRY_LAOS, LANGUAGE_LAO, false }, + { COUNTRY_BANGLADESH, LANGUAGE_BENGALI, false }, + { COUNTRY_TAIWAN, LANGUAGE_CHINESE_TRADITIONAL, true }, + { COUNTRY_MALDIVES, LANGUAGE_DHIVEHI, false }, + { COUNTRY_LEBANON, LANGUAGE_ARABIC_LEBANON, true }, + { COUNTRY_JORDAN, LANGUAGE_ARABIC_JORDAN, true }, + { COUNTRY_SYRIA, LANGUAGE_ARABIC_SYRIA, true }, + { COUNTRY_IRAQ, LANGUAGE_ARABIC_IRAQ, true }, + { COUNTRY_KUWAIT, LANGUAGE_ARABIC_KUWAIT, true }, + { COUNTRY_SAUDI_ARABIA, LANGUAGE_ARABIC_SAUDI_ARABIA, true }, + { COUNTRY_YEMEN, LANGUAGE_ARABIC_YEMEN, true }, + { COUNTRY_OMAN, LANGUAGE_ARABIC_OMAN, true }, + { COUNTRY_UAE, LANGUAGE_ARABIC_UAE, true }, + { COUNTRY_ISRAEL, LANGUAGE_HEBREW, false }, + { COUNTRY_BAHRAIN, LANGUAGE_ARABIC_BAHRAIN, true }, + { COUNTRY_QATAR, LANGUAGE_ARABIC_QATAR, true }, + { COUNTRY_MONGOLIA, LANGUAGE_MONGOLIAN, false }, + { COUNTRY_NEPAL, LANGUAGE_NEPALI, false }, + { COUNTRY_IRAN, LANGUAGE_FARSI, false }, + { COUNTRY_TAJIKISTAN, LANGUAGE_TAJIK, false }, + { COUNTRY_TURKMENISTAN, LANGUAGE_TURKMEN, false }, + { COUNTRY_AZERBAIJAN, LANGUAGE_AZERI_LATIN, false }, + { COUNTRY_GEORGIA, LANGUAGE_GEORGIAN, false }, + { COUNTRY_KYRGYZSTAN, LANGUAGE_KIRGHIZ, false }, + { COUNTRY_UZBEKISTAN, LANGUAGE_UZBEK_LATIN, false } +}; + +const CountryEntry * const pEnd = pTable + sizeof( pTable ) / sizeof( pTable[ 0 ] ); + +// ---------------------------------------------------------------------------- + +/** Predicate comparing a country ID with the member of a CountryEntry. */ +struct CountryEntryPred_Country +{ + CountryId meCountry; + + inline explicit CountryEntryPred_Country( CountryId eCountry ) : + meCountry( eCountry ) {} + + inline bool operator()( const CountryEntry& rCmp ) const + { return rCmp.meCountry == meCountry; } +}; + +// ---------------------------------------------------------------------------- + +/** Predicate comparing a language type with the member of a CountryEntry. + + Compares by primary language only, if the passed CountryEntry allows it + (the member mbUseSubLang is cleared), otherwise by full language type. */ +struct CountryEntryPred_Language +{ + LanguageType meLanguage; + + inline explicit CountryEntryPred_Language( LanguageType eLanguage ) : + meLanguage( eLanguage ) {} + + inline bool operator()( const CountryEntry& rCmp ) const; +}; + +inline bool CountryEntryPred_Language::operator()( const CountryEntry& rCmp ) const +{ + // rCmp.mbUseSubLang==true -> compare full language type + // rCmp.mbUseSubLang==false -> compare primary language only + return rCmp.mbUseSubLang ? (meLanguage == rCmp.meLanguage) : + ((meLanguage & 0x03FF) == (rCmp.meLanguage & 0x03FF)); +} + +// ---------------------------------------------------------------------------- + +} // namespace + +// Country ID <-> Language type conversion ==================================== + +CountryId ConvertLanguageToCountry( LanguageType eLanguage ) +{ + // country of a found primary language type + CountryId ePrimCountry = COUNTRY_DONTKNOW; + + // find an exact match and a primary-language-only match, in one pass + const CountryEntry* pEntry = pTable; + do + { + pEntry = std::find_if( pEntry, pEnd, CountryEntryPred_Language( eLanguage ) ); + if( pEntry != pEnd ) + { + if( pEntry->mbUseSubLang ) + return pEntry->meCountry; // exact match found -> return + if( ePrimCountry == COUNTRY_DONTKNOW ) + ePrimCountry = pEntry->meCountry; + ++pEntry; // one entry forward for next find_if() call + } + } + while( pEntry != pEnd ); + + return ePrimCountry; +} + +LanguageType ConvertCountryToLanguage( CountryId eCountry ) +{ + // just find the first occurance of eCountry and return the language type + const CountryEntry* pEntry = std::find_if( pTable, pEnd, CountryEntryPred_Country( eCountry ) ); + return (pEntry != pEnd) ? pEntry->meLanguage : LANGUAGE_DONTKNOW; +} + +// ============================================================================ + +} // namespace svx + +// ============================================================================ + diff --git a/filter/source/msfilter/escherex.cxx b/filter/source/msfilter/escherex.cxx new file mode 100644 index 000000000000..d8e3b3762f00 --- /dev/null +++ b/filter/source/msfilter/escherex.cxx @@ -0,0 +1,4949 @@ +/************************************************************************* + * + * 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_filter.hxx" +#include "eschesdo.hxx" +#include <filter/msfilter/escherex.hxx> +#include <svx/unoapi.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdoashp.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdmodel.hxx> +#include <vcl/gradient.hxx> +#include <vcl/graph.hxx> +#include <vcl/cvtgrf.hxx> +#include <vcl/svapp.hxx> +#include <vcl/wrkwin.hxx> +#include <tools/stream.hxx> +#include <tools/zcodec.hxx> +#include <svx/svdopath.hxx> +#include <stdlib.h> +#include <svtools/filter.hxx> +#include "svx/EnhancedCustomShapeTypeNames.hxx" +#include "svx/EnhancedCustomShapeGeometry.hxx" +#include <svx/EnhancedCustomShapeFunctionParser.hxx> +#include "svx/EnhancedCustomShape2d.hxx" +#include <com/sun/star/beans/PropertyValues.hpp> +#include <com/sun/star/beans/XPropertyState.hpp> +#include <com/sun/star/awt/GradientStyle.hpp> +#include <com/sun/star/awt/RasterOperation.hpp> +#include <com/sun/star/awt/Gradient.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/drawing/LineJoint.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/drawing/LineDash.hpp> +#include <com/sun/star/drawing/BezierPoint.hpp> +#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp> +#include <com/sun/star/drawing/ConnectorType.hpp> +#include <com/sun/star/drawing/ConnectionType.hpp> +#include <com/sun/star/drawing/CircleKind.hpp> +#include <com/sun/star/drawing/PointSequence.hpp> +#include <com/sun/star/drawing/FlagSequence.hpp> +#include <com/sun/star/drawing/PolygonFlags.hpp> +#include <com/sun/star/text/WritingMode.hpp> +#include <com/sun/star/drawing/TextVerticalAdjust.hpp> +#include <com/sun/star/drawing/TextHorizontalAdjust.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeGluePointType.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp> +#include <com/sun/star/drawing/ProjectionMode.hpp> +#include <com/sun/star/text/XSimpleText.hpp> +#include <com/sun/star/drawing/ShadeMode.hpp> +#include <vcl/hatch.hxx> +#include <com/sun/star/awt/XGraphics.hpp> +#include <com/sun/star/awt/FontSlant.hpp> +#include <com/sun/star/awt/FontWeight.hpp> +#include <com/sun/star/drawing/ColorMode.hpp> +#include <com/sun/star/drawing/Position3D.hpp> +#include <com/sun/star/drawing/Direction3D.hpp> +#include <com/sun/star/text/GraphicCrop.hpp> +#include <unotools/ucbstreamhelper.hxx> +#include <unotools/localfilehelper.hxx> +#include <comphelper/extract.hxx> +#include <toolkit/unohlp.hxx> +#include <vcl/virdev.hxx> +#include <rtl/crc.h> +#include <vos/xception.hxx> +using namespace vos; + +using namespace ::rtl; +using namespace ::com::sun::star; + + +// --------------------------------------------------------------------------------------------- + +EscherExContainer::EscherExContainer( SvStream& rSt, const sal_uInt16 nRecType, const sal_uInt16 nInstance ) : + rStrm ( rSt ) +{ + rStrm << (sal_uInt32)( ( 0xf | ( nInstance << 4 ) ) | ( nRecType << 16 ) ) << (sal_uInt32)0; + nContPos = rStrm.Tell(); +} +EscherExContainer::~EscherExContainer() +{ + sal_uInt32 nPos = rStrm.Tell(); + sal_uInt32 nSize= nPos - nContPos; + if ( nSize ) + { + rStrm.Seek( nContPos - 4 ); + rStrm << nSize; + rStrm.Seek( nPos ); + } +} + +EscherExAtom::EscherExAtom( SvStream& rSt, const sal_uInt16 nRecType, const sal_uInt16 nInstance, const sal_uInt8 nVersion ) : + rStrm ( rSt ) +{ + rStrm << (sal_uInt32)( ( nVersion | ( nInstance << 4 ) ) | ( nRecType << 16 ) ) << (sal_uInt32)0; + nContPos = rStrm.Tell(); +} +EscherExAtom::~EscherExAtom() +{ + sal_uInt32 nPos = rStrm.Tell(); + sal_uInt32 nSize= nPos - nContPos; + if ( nSize ) + { + rStrm.Seek( nContPos - 4 ); + rStrm << nSize; + rStrm.Seek( nPos ); + } +} + +// --------------------------------------------------------------------------------------------- + +EscherExClientRecord_Base::~EscherExClientRecord_Base() +{ +} + +EscherExClientAnchor_Base::~EscherExClientAnchor_Base() +{ +} + +// --------------------------------------------------------------------------------------------- + +void EscherPropertyContainer::ImplInit() +{ + nSortCount = 0; + nCountCount = 0; + nCountSize = 0; + nSortBufSize = 64; + bHasComplexData = sal_False; + bSuppressRotation = sal_False; + pSortStruct = new EscherPropSortStruct[ nSortBufSize ]; +} + +EscherPropertyContainer::EscherPropertyContainer() : + pGraphicProvider ( NULL ), + pPicOutStrm ( NULL ) +{ + ImplInit(); +}; + +EscherPropertyContainer::EscherPropertyContainer( + EscherGraphicProvider& rGraphProv, + SvStream* pPiOutStrm, + Rectangle& rBoundRect ) : + + pGraphicProvider ( &rGraphProv ), + pPicOutStrm ( pPiOutStrm ), + pShapeBoundRect ( &rBoundRect ) +{ + ImplInit(); +} + +EscherPropertyContainer::~EscherPropertyContainer() +{ + if ( bHasComplexData ) + { + while ( nSortCount-- ) + delete[] pSortStruct[ nSortCount ].pBuf; + } + delete[] pSortStruct; +}; + +void EscherPropertyContainer::AddOpt( sal_uInt16 nPropID, sal_uInt32 nPropValue, sal_Bool bBlib ) +{ + AddOpt( nPropID, bBlib, nPropValue, NULL, 0 ); +} + +void EscherPropertyContainer::AddOpt( sal_uInt16 nPropID, const rtl::OUString& rString ) +{ + sal_Int32 j, i, nLen = rString.getLength() * 2 + 2; + sal_uInt8* pBuf = new sal_uInt8[ nLen ]; + for ( j = i = 0; i < rString.getLength(); i++ ) + { + sal_uInt16 nChar = (sal_uInt16)rString[ i ]; + pBuf[ j++ ] = (sal_uInt8)nChar; + pBuf[ j++ ] = (sal_uInt8)( nChar >> 8 ); + } + pBuf[ j++ ] = 0; + pBuf[ j++ ] = 0; + AddOpt( nPropID, sal_True, nLen, pBuf, nLen ); +} + +void EscherPropertyContainer::AddOpt( sal_uInt16 nPropID, sal_Bool bBlib, sal_uInt32 nPropValue, sal_uInt8* pProp, sal_uInt32 nPropSize ) +{ + if ( bBlib ) // bBlib is only valid when fComplex = 0 + nPropID |= 0x4000; + if ( pProp ) + nPropID |= 0x8000; // fComplex = sal_True; + + sal_uInt32 i; + for( i = 0; i < nSortCount; i++ ) + { + if ( ( pSortStruct[ i ].nPropId &~0xc000 ) == ( nPropID &~0xc000 ) ) // pruefen, ob Property nur ersetzt wird + { + pSortStruct[ i ].nPropId = nPropID; + if ( pSortStruct[ i ].pBuf ) + { + nCountSize -= pSortStruct[ i ].nPropSize; + delete[] pSortStruct[ i ].pBuf; + } + pSortStruct[ i ].pBuf = pProp; + pSortStruct[ i ].nPropSize = nPropSize; + pSortStruct[ i ].nPropValue = nPropValue; + if ( pProp ) + nCountSize += nPropSize; + return; + } + } + nCountCount++; + nCountSize += 6; + if ( nSortCount == nSortBufSize ) // buffer vergroessern + { + nSortBufSize <<= 1; + EscherPropSortStruct* pTemp = new EscherPropSortStruct[ nSortBufSize ]; + for( i = 0; i < nSortCount; i++ ) + { + pTemp[ i ] = pSortStruct[ i ]; + } + delete pSortStruct; + pSortStruct = pTemp; + } + pSortStruct[ nSortCount ].nPropId = nPropID; // property einfuegen + pSortStruct[ nSortCount ].pBuf = pProp; + pSortStruct[ nSortCount ].nPropSize = nPropSize; + pSortStruct[ nSortCount++ ].nPropValue = nPropValue; + + if ( pProp ) + { + nCountSize += nPropSize; + bHasComplexData = sal_True; + } +} + +sal_Bool EscherPropertyContainer::GetOpt( sal_uInt16 nPropId, sal_uInt32& rPropValue ) const +{ + EscherPropSortStruct aPropStruct; + + if ( GetOpt( nPropId, aPropStruct ) ) + { + rPropValue = aPropStruct.nPropValue; + return sal_True; + } + return sal_False; +} + +sal_Bool EscherPropertyContainer::GetOpt( sal_uInt16 nPropId, EscherPropSortStruct& rPropValue ) const +{ + for( sal_uInt32 i = 0; i < nSortCount; i++ ) + { + if ( ( pSortStruct[ i ].nPropId &~0xc000 ) == ( nPropId &~0xc000 ) ) + { + rPropValue = pSortStruct[ i ]; + return sal_True; + } + } + return sal_False; +} + +EscherProperties EscherPropertyContainer::GetOpts() const +{ + EscherProperties aVector; + + for ( sal_uInt32 i = 0; i < nSortCount; ++i ) + aVector.push_back( pSortStruct[ i ] ); + + return aVector; +} + +extern "C" int __LOADONCALLAPI EscherPropSortFunc( const void* p1, const void* p2 ) +{ + sal_Int16 nID1 = ((EscherPropSortStruct*)p1)->nPropId &~0xc000; + sal_Int16 nID2 = ((EscherPropSortStruct*)p2)->nPropId &~0xc000; + + if( nID1 < nID2 ) + return -1; + else if( nID1 > nID2 ) + return 1; + else + return 0; +} + +void EscherPropertyContainer::Commit( SvStream& rSt, sal_uInt16 nVersion, sal_uInt16 nRecType ) +{ + rSt << (sal_uInt16)( ( nCountCount << 4 ) | ( nVersion & 0xf ) ) << nRecType << nCountSize; + if ( nSortCount ) + { + qsort( pSortStruct, nSortCount, sizeof( EscherPropSortStruct ), EscherPropSortFunc ); + sal_uInt32 i; + + for ( i = 0; i < nSortCount; i++ ) + { + sal_uInt32 nPropValue = pSortStruct[ i ].nPropValue; + sal_uInt16 nPropId = pSortStruct[ i ].nPropId; + + if ( bSuppressRotation && ( nPropId == ESCHER_Prop_Rotation ) ) + nPropValue = 0; + + rSt << nPropId + << nPropValue; + } + if ( bHasComplexData ) + { + for ( i = 0; i < nSortCount; i++ ) + { + if ( pSortStruct[ i ].pBuf ) + rSt.Write( pSortStruct[ i ].pBuf, pSortStruct[ i ].nPropSize ); + } + } + } +} + +sal_Bool EscherPropertyContainer::IsFontWork() const +{ + sal_uInt32 nTextPathFlags = 0; + GetOpt( DFF_Prop_gtextFStrikethrough, nTextPathFlags ); + return ( nTextPathFlags & 0x4000 ) != 0; +} + +sal_uInt32 EscherPropertyContainer::ImplGetColor( const sal_uInt32 nSOColor, sal_Bool bSwap ) +{ + if ( bSwap ) + { + sal_uInt32 nColor = nSOColor & 0xff00; // GRUEN + nColor |= (sal_uInt8)( nSOColor ) << 16; // ROT + nColor |= (sal_uInt8)( nSOColor >> 16 ); // BLAU + return nColor; + } + else + return nSOColor & 0xffffff; +} + +sal_uInt32 EscherPropertyContainer::GetGradientColor( + const ::com::sun::star::awt::Gradient* pGradient, + sal_uInt32 nStartColor ) +{ + sal_uInt32 nIntensity = 100; + Color aColor; + + if ( pGradient ) + { + if ( nStartColor & 1 ) + { + nIntensity = pGradient->StartIntensity; + aColor = pGradient->StartColor; + } + else + { + nIntensity = pGradient->EndIntensity; + aColor = pGradient->EndColor; + } + } + sal_uInt32 nRed = ( ( aColor.GetRed() * nIntensity ) / 100 ); + sal_uInt32 nGreen = ( ( aColor.GetGreen() * nIntensity ) / 100 ) << 8; + sal_uInt32 nBlue = ( ( aColor.GetBlue() * nIntensity ) / 100 ) << 16; + return nRed | nGreen | nBlue; +} + +void EscherPropertyContainer::CreateGradientProperties( + const ::com::sun::star::awt::Gradient & rGradient ) +{ + sal_uInt32 nFillType = ESCHER_FillShadeScale; + sal_uInt32 nAngle = 0; + sal_uInt32 nFillFocus = 0; + sal_uInt32 nFillLR = 0; + sal_uInt32 nFillTB = 0; + sal_uInt32 nFirstColor = 0; + bool bWriteFillTo = false; + + switch ( rGradient.Style ) + { + case ::com::sun::star::awt::GradientStyle_LINEAR : + case ::com::sun::star::awt::GradientStyle_AXIAL : + { + nFillType = ESCHER_FillShadeScale; + nAngle = (rGradient.Angle * 0x10000) / 10; + nFillFocus = (sal::static_int_cast<int>(rGradient.Style) == + sal::static_int_cast<int>(GradientStyle_LINEAR)) ? 0 : 50; + } + break; + case ::com::sun::star::awt::GradientStyle_RADIAL : + case ::com::sun::star::awt::GradientStyle_ELLIPTICAL : + case ::com::sun::star::awt::GradientStyle_SQUARE : + case ::com::sun::star::awt::GradientStyle_RECT : + { + nFillLR = (rGradient.XOffset * 0x10000) / 100; + nFillTB = (rGradient.YOffset * 0x10000) / 100; + if ( ((nFillLR > 0) && (nFillLR < 0x10000)) || ((nFillTB > 0) && (nFillTB < 0x10000)) ) + nFillType = ESCHER_FillShadeShape; + else + nFillType = ESCHER_FillShadeCenter; + nFirstColor = 1; + bWriteFillTo = true; + } + break; + case ::com::sun::star::awt::GradientStyle_MAKE_FIXED_SIZE : break; + } + AddOpt( ESCHER_Prop_fillType, nFillType ); + AddOpt( ESCHER_Prop_fillAngle, nAngle ); + AddOpt( ESCHER_Prop_fillColor, GetGradientColor( &rGradient, nFirstColor ) ); + AddOpt( ESCHER_Prop_fillBackColor, GetGradientColor( &rGradient, nFirstColor ^ 1 ) ); + AddOpt( ESCHER_Prop_fillFocus, nFillFocus ); + if ( bWriteFillTo ) + { + AddOpt( ESCHER_Prop_fillToLeft, nFillLR ); + AddOpt( ESCHER_Prop_fillToTop, nFillTB ); + AddOpt( ESCHER_Prop_fillToRight, nFillLR ); + AddOpt( ESCHER_Prop_fillToBottom, nFillTB ); + } +} + +void EscherPropertyContainer::CreateGradientProperties( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet ) +{ + ::com::sun::star::uno::Any aAny; + ::com::sun::star::awt::Gradient aGradient; + if ( EscherPropertyValueHelper::GetPropertyValue( + aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillGradient" ) ), sal_False ) ) + { + aGradient = *static_cast< const ::com::sun::star::awt::Gradient* >( aAny.getValue() ); + } + CreateGradientProperties( aGradient ); +}; + +void EscherPropertyContainer::CreateFillProperties( + const uno::Reference< beans::XPropertySet > & rXPropSet, + sal_Bool bEdge ) +{ + ::com::sun::star::uno::Any aAny; + AddOpt( ESCHER_Prop_WrapText, ESCHER_WrapNone ); + AddOpt( ESCHER_Prop_AnchorText, ESCHER_AnchorMiddle ); + + sal_uInt32 nFillBackColor = 0; + + const rtl::OUString aPropName( String( RTL_CONSTASCII_USTRINGPARAM( "FillStyle" ) ) ); + if ( EscherPropertyValueHelper::GetPropertyValue( + aAny, rXPropSet, aPropName, sal_False ) ) + { + ::com::sun::star::drawing::FillStyle eFS; + if ( ! ( aAny >>= eFS ) ) + eFS = ::com::sun::star::drawing::FillStyle_SOLID; + switch( eFS ) + { + case ::com::sun::star::drawing::FillStyle_GRADIENT : + { + CreateGradientProperties( rXPropSet ); + AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 ); + } + break; + + case ::com::sun::star::drawing::FillStyle_BITMAP : + { + CreateGraphicProperties( rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillBitmapURL" ) ), sal_True ); + AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 ); + AddOpt( ESCHER_Prop_fillBackColor, nFillBackColor ); + } + break; + case ::com::sun::star::drawing::FillStyle_HATCH : + { + CreateGraphicProperties( rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillHatch" ) ), sal_True ); + } + break; + case ::com::sun::star::drawing::FillStyle_SOLID : + default: + { + ::com::sun::star::beans::PropertyState ePropState = EscherPropertyValueHelper::GetPropertyState( + rXPropSet, aPropName ); + if ( ePropState == ::com::sun::star::beans::PropertyState_DIRECT_VALUE ) + AddOpt( ESCHER_Prop_fillType, ESCHER_FillSolid ); + + if ( EscherPropertyValueHelper::GetPropertyValue( + aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillColor" ) ), sal_False ) ) + { + sal_uInt32 nFillColor = ImplGetColor( *((sal_uInt32*)aAny.getValue()) ); + nFillBackColor = nFillColor ^ 0xffffff; + AddOpt( ESCHER_Prop_fillColor, nFillColor ); + } + AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100010 ); + AddOpt( ESCHER_Prop_fillBackColor, nFillBackColor ); + break; + } + case ::com::sun::star::drawing::FillStyle_NONE : + AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 ); + break; + } + if ( eFS != ::com::sun::star::drawing::FillStyle_NONE ) + { + sal_uInt16 nTransparency = ( EscherPropertyValueHelper::GetPropertyValue( + aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillTransparence" ) ), sal_True ) ) + ? *((sal_Int16*)aAny.getValue() ) + : 0; + if ( nTransparency ) + AddOpt( ESCHER_Prop_fillOpacity, ( ( 100 - nTransparency ) << 16 ) / 100 ); + } + } + CreateLineProperties( rXPropSet, bEdge ); +} + +void EscherPropertyContainer::CreateTextProperties( + const uno::Reference< beans::XPropertySet > & rXPropSet, sal_uInt32 nTextId, + const sal_Bool bIsCustomShape, const sal_Bool bIsTextFrame ) +{ + uno::Any aAny; + text::WritingMode eWM( text::WritingMode_LR_TB ); + drawing::TextVerticalAdjust eVA( drawing::TextVerticalAdjust_TOP ); + drawing::TextHorizontalAdjust eHA( drawing::TextHorizontalAdjust_LEFT ); + + sal_Int32 nLeft ( 0 ); + sal_Int32 nTop ( 0 ); + sal_Int32 nRight ( 0 ); + sal_Int32 nBottom ( 0 ); + + // used with normal shapes: + sal_Bool bAutoGrowWidth ( sal_False ); + sal_Bool bAutoGrowHeight ( sal_False ); + // used with ashapes: + sal_Bool bWordWrap ( sal_False ); + sal_Bool bAutoGrowSize ( sal_False ); + + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextWritingMode" ) ), sal_True ) ) + aAny >>= eWM; + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextVerticalAdjust" ) ), sal_True ) ) + aAny >>= eVA; + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextHorizontalAdjust" ) ), sal_True ) ) + aAny >>= eHA; + if ( bIsCustomShape ) + { + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextWordWrap" ) ), sal_False ) ) + aAny >>= bWordWrap; + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextAutoGrowHeight" ) ), sal_True ) ) + aAny >>= bAutoGrowSize; + } + else if ( bIsTextFrame ) + { + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextAutoGrowWidth" ) ), sal_True ) ) + aAny >>= bAutoGrowWidth; + +// i63936 not setting autogrowheight, because otherwise +// the minframeheight of the text will be ignored +// +// if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextAutoGrowHeight" ) ), sal_True ) ) +// aAny >>= bAutoGrowHeight; + } + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextLeftDistance" ) ) ) ) + aAny >>= nLeft; + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextUpperDistance" ) ) ) ) + aAny >>= nTop; + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextRightDistance" ) ) ) ) + aAny >>= nRight; + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextLowerDistance" ) ) ) ) + aAny >>= nBottom; + +/* + if ( rObj.ImplGetPropertyValue( + ::rtl::OUString::createFromAscii("TextWritingMode") ) ) + { + ::com::sun::star::text::WritingMode eMode; + rObj.GetUsrAny() >>= eMode; + switch (eMode) + { + case ::com::sun::star::text::WritingMode_TB_RL: + //Well if it so happens that we are fliped 180 we can use + //this instead. + if (rObj.GetAngle() == 18000) + eFlow = ESCHER_txflBtoT; + else + eFlow = ESCHER_txflTtoBA; + break; + case ::com::sun::star::text::WritingMode_RL_TB: + eDir = ESCHER_txdirRTL; + break; + } + } +*/ + + ESCHER_AnchorText eAnchor = ESCHER_AnchorTop; + ESCHER_WrapMode eWrapMode = ESCHER_WrapSquare; + sal_uInt32 nTextAttr = 0x40004; // rotate text with shape + + if ( eWM == text::WritingMode_TB_RL ) + { // verical writing + switch ( eHA ) + { + case drawing::TextHorizontalAdjust_LEFT : + eAnchor = ESCHER_AnchorBottom; + break; + case drawing::TextHorizontalAdjust_CENTER : + eAnchor = ESCHER_AnchorMiddle; + break; + default : + case drawing::TextHorizontalAdjust_BLOCK : + case drawing::TextHorizontalAdjust_RIGHT : + eAnchor = ESCHER_AnchorTop; + break; + } + if ( eVA == drawing::TextVerticalAdjust_CENTER ) + { + switch ( eAnchor ) + { + case ESCHER_AnchorMiddle : + eAnchor = ESCHER_AnchorMiddleCentered; + break; + case ESCHER_AnchorBottom : + eAnchor = ESCHER_AnchorBottomCentered; + break; + default : + case ESCHER_AnchorTop : + eAnchor = ESCHER_AnchorTopCentered; + break; + } + } + if ( bIsCustomShape ) + { + if ( bWordWrap ) + eWrapMode = ESCHER_WrapSquare; + else + eWrapMode = ESCHER_WrapNone; + if ( bAutoGrowSize ) + nTextAttr |= 0x20002; + } + else + { + if ( bAutoGrowHeight ) + eWrapMode = ESCHER_WrapNone; + if ( bAutoGrowWidth ) + nTextAttr |= 0x20002; + } + + AddOpt( ESCHER_Prop_txflTextFlow, ESCHER_txflTtoBA ); // rotate text within shape by 90 + } + else + { // normal from left to right + switch ( eVA ) + { + case drawing::TextVerticalAdjust_CENTER : + eAnchor = ESCHER_AnchorMiddle; + break; + + case drawing::TextVerticalAdjust_BOTTOM : + eAnchor = ESCHER_AnchorBottom; + break; + + default : + case drawing::TextVerticalAdjust_TOP : + eAnchor = ESCHER_AnchorTop; + break; + } + if ( eHA == drawing::TextHorizontalAdjust_CENTER ) + { + switch( eAnchor ) + { + case ESCHER_AnchorMiddle : + eAnchor = ESCHER_AnchorMiddleCentered; + break; + case ESCHER_AnchorBottom : + eAnchor = ESCHER_AnchorBottomCentered; + break; + case ESCHER_AnchorTop : + eAnchor = ESCHER_AnchorTopCentered; + break; + default: break; + } + } + if ( bIsCustomShape ) + { + if ( bWordWrap ) + eWrapMode = ESCHER_WrapSquare; + else + eWrapMode = ESCHER_WrapNone; + if ( bAutoGrowSize ) + nTextAttr |= 0x20002; + } + else + { + if ( bAutoGrowWidth ) + eWrapMode = ESCHER_WrapNone; + if ( bAutoGrowHeight ) + nTextAttr |= 0x20002; + } + } + AddOpt( ESCHER_Prop_dxTextLeft, nLeft * 360 ); + AddOpt( ESCHER_Prop_dxTextRight, nRight * 360 ); + AddOpt( ESCHER_Prop_dyTextTop, nTop * 360 ); + AddOpt( ESCHER_Prop_dyTextBottom, nBottom * 360 ); + + AddOpt( ESCHER_Prop_WrapText, eWrapMode ); + AddOpt( ESCHER_Prop_AnchorText, eAnchor ); + AddOpt( ESCHER_Prop_FitTextToShape, nTextAttr ); + + if ( nTextId ) + AddOpt( ESCHER_Prop_lTxid, nTextId ); +} + +sal_Bool EscherPropertyContainer::GetLineArrow( const sal_Bool bLineStart, + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet, + ESCHER_LineEnd& reLineEnd, sal_Int32& rnArrowLength, sal_Int32& rnArrowWidth ) +{ + static String sLineStart ( RTL_CONSTASCII_USTRINGPARAM( "LineStart" ) ); + static String sLineStartName( RTL_CONSTASCII_USTRINGPARAM( "LineStartName" ) ); + static String sLineEnd ( RTL_CONSTASCII_USTRINGPARAM( "LineEnd" ) ); + static String sLineEndName ( RTL_CONSTASCII_USTRINGPARAM( "LineEndName" ) ); + + const String sLine ( bLineStart ? sLineStart : sLineEnd ); + const String sLineName ( bLineStart ? sLineStartName : sLineEndName ); + + sal_Bool bIsArrow = sal_False; + + ::com::sun::star::uno::Any aAny; + if ( EscherPropertyValueHelper::GetPropertyValue( + aAny, rXPropSet, sLine, sal_False ) ) + { + PolyPolygon aPolyPoly( EscherPropertyContainer::GetPolyPolygon( aAny ) ); + if ( aPolyPoly.Count() && aPolyPoly[ 0 ].GetSize() ) + { + bIsArrow = sal_True; + + reLineEnd = ESCHER_LineArrowEnd; + rnArrowLength = 1; + rnArrowWidth = 1; + + if ( EscherPropertyValueHelper::GetPropertyValue( + aAny, rXPropSet, sLineName, sal_False ) ) + { + String aArrowStartName = *(::rtl::OUString*)aAny.getValue(); + rtl::OUString aApiName; + sal_Int16 nWhich = bLineStart ? XATTR_LINESTART : XATTR_LINEEND; + + SvxUnogetApiNameForItem( nWhich, aArrowStartName, aApiName ); + if ( aApiName.getLength() ) + { + + /* todo: + calculate the best option for ArrowLenght and ArrowWidth + */ + if ( aApiName.equalsAscii( "Arrow concave" ) ) + reLineEnd = ESCHER_LineArrowStealthEnd; + else if ( aApiName.equalsAscii( "Square 45" ) ) + reLineEnd = ESCHER_LineArrowDiamondEnd; + else if ( aApiName.equalsAscii( "Small Arrow" ) ) + reLineEnd = ESCHER_LineArrowEnd; + else if ( aApiName.equalsAscii( "Dimension Lines" ) ) + { + rnArrowLength = 0; + rnArrowWidth = 2; + reLineEnd = ESCHER_LineArrowOvalEnd; + } + else if ( aApiName.equalsAscii( "Double Arrow" ) ) + reLineEnd = ESCHER_LineArrowEnd; + else if ( aApiName.equalsAscii( "Rounded short Arrow" ) ) + reLineEnd = ESCHER_LineArrowEnd; + else if ( aApiName.equalsAscii( "Symmetric Arrow" ) ) + reLineEnd = ESCHER_LineArrowEnd; + else if ( aApiName.equalsAscii( "Line Arrow" ) ) + reLineEnd = ESCHER_LineArrowOpenEnd; + else if ( aApiName.equalsAscii( "Rounded large Arrow" ) ) + reLineEnd = ESCHER_LineArrowEnd; + else if ( aApiName.equalsAscii( "Circle" ) ) + reLineEnd = ESCHER_LineArrowOvalEnd; + else if ( aApiName.equalsAscii( "Square" ) ) + reLineEnd = ESCHER_LineArrowDiamondEnd; + else if ( aApiName.equalsAscii( "Arrow" ) ) + reLineEnd = ESCHER_LineArrowEnd; + } + else if ( aArrowStartName.GetTokenCount( ' ' ) == 2 ) + { + sal_Bool b = sal_True; + String aArrowName( aArrowStartName.GetToken( 0, ' ' ) ); + if ( aArrowName.EqualsAscii( "msArrowEnd" ) ) + reLineEnd = ESCHER_LineArrowEnd; + else if ( aArrowName.EqualsAscii( "msArrowOpenEnd" ) ) + reLineEnd = ESCHER_LineArrowOpenEnd; + else if ( aArrowName.EqualsAscii( "msArrowStealthEnd" ) ) + reLineEnd = ESCHER_LineArrowStealthEnd; + else if ( aArrowName.EqualsAscii( "msArrowDiamondEnd" ) ) + reLineEnd = ESCHER_LineArrowDiamondEnd; + else if ( aArrowName.EqualsAscii( "msArrowOvalEnd" ) ) + reLineEnd = ESCHER_LineArrowOvalEnd; + else + b = sal_False; + + // now we have the arrow, and try to determine the arrow size; + if ( b ) + { + String aArrowSize( aArrowStartName.GetToken( 1, ' ' ) ); + sal_Int32 nArrowSize = aArrowSize.ToInt32(); + rnArrowWidth = ( nArrowSize - 1 ) / 3; + rnArrowLength = nArrowSize - ( rnArrowWidth * 3 ) - 1; + } + } + } + } + } + return bIsArrow; +} + +void EscherPropertyContainer::CreateLineProperties( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet, + sal_Bool bEdge ) +{ + ::com::sun::star::uno::Any aAny; + sal_uInt32 nLineFlags = 0x80008; + + ESCHER_LineEnd eLineEnd; + sal_Int32 nArrowLength; + sal_Int32 nArrowWidth; + + sal_Bool bSwapLineEnds = sal_False; + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CircleKind" ) ), sal_True ) ) + { + ::com::sun::star::drawing::CircleKind eCircleKind; + if ( aAny >>= eCircleKind ) + { + if ( eCircleKind == ::com::sun::star::drawing::CircleKind_ARC ) + bSwapLineEnds = sal_True; + } + } + if ( GetLineArrow( bSwapLineEnds ? sal_False : sal_True, rXPropSet, eLineEnd, nArrowLength, nArrowWidth ) ) + { + AddOpt( ESCHER_Prop_lineStartArrowLength, nArrowLength ); + AddOpt( ESCHER_Prop_lineStartArrowWidth, nArrowWidth ); + AddOpt( ESCHER_Prop_lineStartArrowhead, eLineEnd ); + nLineFlags |= 0x100010; + } + if ( GetLineArrow( bSwapLineEnds ? sal_True : sal_False, rXPropSet, eLineEnd, nArrowLength, nArrowWidth ) ) + { + AddOpt( ESCHER_Prop_lineEndArrowLength, nArrowLength ); + AddOpt( ESCHER_Prop_lineEndArrowWidth, nArrowWidth ); + AddOpt( ESCHER_Prop_lineEndArrowhead, eLineEnd ); + nLineFlags |= 0x100010; + } + if ( EscherPropertyValueHelper::GetPropertyValue( + aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineStyle" ) ), sal_False ) ) + { + ::com::sun::star::drawing::LineStyle eLS; + if ( aAny >>= eLS ) + { + switch ( eLS ) + { + case ::com::sun::star::drawing::LineStyle_NONE : + AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 ); // 80000 + break; + + case ::com::sun::star::drawing::LineStyle_DASH : + { + if ( EscherPropertyValueHelper::GetPropertyValue( + aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineDash" ) ), sal_False ) ) + { + ESCHER_LineDashing eDash = ESCHER_LineSolid; + ::com::sun::star::drawing::LineDash* pLineDash = (::com::sun::star::drawing::LineDash*)aAny.getValue(); + sal_Int32 nDistance = pLineDash->Distance << 1; + switch ( pLineDash->Style ) + { + case ::com::sun::star::drawing::DashStyle_ROUND : + case ::com::sun::star::drawing::DashStyle_ROUNDRELATIVE : + AddOpt( ESCHER_Prop_lineEndCapStyle, 0 ); // Style Round setzen + break; + default : break; + } + if ( ((!(pLineDash->Dots )) || (!(pLineDash->Dashes )) ) || ( pLineDash->DotLen == pLineDash->DashLen ) ) + { + sal_Int32 nLen = pLineDash->DotLen; + if ( pLineDash->Dashes ) + nLen = pLineDash->DashLen; + + if ( nLen >= nDistance ) + eDash = ESCHER_LineLongDashGEL; + else if ( pLineDash->Dots ) + eDash = ESCHER_LineDotSys; + else + eDash = ESCHER_LineDashGEL; + } + else // X Y + { + if ( pLineDash->Dots != pLineDash->Dashes ) + { + if ( ( pLineDash->DashLen > nDistance ) || ( pLineDash->DotLen > nDistance ) ) + eDash = ESCHER_LineLongDashDotDotGEL; + else + eDash = ESCHER_LineDashDotDotSys; + } + else // X Y Y + { + if ( ( pLineDash->DashLen > nDistance ) || ( pLineDash->DotLen > nDistance ) ) + eDash = ESCHER_LineLongDashDotGEL; + else + eDash = ESCHER_LineDashDotGEL; + + } + } + AddOpt( ESCHER_Prop_lineDashing, eDash ); + } + } + case ::com::sun::star::drawing::LineStyle_SOLID : + default: + { + AddOpt( ESCHER_Prop_fNoLineDrawDash, nLineFlags ); + } + break; + } + } + if ( EscherPropertyValueHelper::GetPropertyValue( + aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineColor" ) ), sal_False ) ) + { + sal_uInt32 nLineColor = ImplGetColor( *((sal_uInt32*)aAny.getValue()) ); + AddOpt( ESCHER_Prop_lineColor, nLineColor ); + AddOpt( ESCHER_Prop_lineBackColor, nLineColor ^ 0xffffff ); + } + } + + sal_uInt32 nLineSize = ( EscherPropertyValueHelper::GetPropertyValue( + aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineWidth" ) ), sal_False ) ) + ? *((sal_uInt32*)aAny.getValue()) + : 0; + if ( nLineSize > 1 ) + AddOpt( ESCHER_Prop_lineWidth, nLineSize * 360 ); // 100TH MM -> PT , 1PT = 12700 EMU + + ESCHER_LineJoin eLineJoin = ESCHER_LineJoinMiter; + if ( EscherPropertyValueHelper::GetPropertyValue( + aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineJoint" ) ), sal_True ) ) + { + ::com::sun::star::drawing::LineJoint eLJ; + if ( aAny >>= eLJ ) + { + switch ( eLJ ) + { + case com::sun::star::drawing::LineJoint_NONE : + case com::sun::star::drawing::LineJoint_MIDDLE : + case com::sun::star::drawing::LineJoint_BEVEL : + eLineJoin = ESCHER_LineJoinBevel; + break; + default: + case com::sun::star::drawing::LineJoint_MITER : + eLineJoin = ESCHER_LineJoinMiter; + break; + case com::sun::star::drawing::LineJoint_ROUND : + eLineJoin = ESCHER_LineJoinRound; + break; + } + } + } + AddOpt( ESCHER_Prop_lineJoinStyle, eLineJoin ); + + if ( bEdge == sal_False ) + { + AddOpt( ESCHER_Prop_fFillOK, 0x1001 ); + AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 ); + } +} + +static Size lcl_SizeToEmu(Size aPrefSize, MapMode aPrefMapMode) +{ + Size aRetSize; + if (aPrefMapMode == MAP_PIXEL) + aRetSize = Application::GetDefaultDevice()->PixelToLogic( aPrefSize, MAP_100TH_MM ); + else + aRetSize = Application::GetDefaultDevice()->LogicToLogic( aPrefSize, aPrefMapMode, MAP_100TH_MM ); + return aRetSize; +} + +void EscherPropertyContainer::ImplCreateGraphicAttributes( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet, + sal_uInt32 nBlibId, sal_Bool bCreateCroppingAttributes ) +{ + ::com::sun::star::uno::Any aAny; + + sal_uInt32 nPicFlags = 0; + ::com::sun::star::drawing::ColorMode eColorMode( ::com::sun::star::drawing::ColorMode_STANDARD ); + sal_Int16 nLuminance = 0; + sal_Int32 nContrast = 0; + sal_Int16 nRed = 0; + sal_Int16 nGreen = 0; + sal_Int16 nBlue = 0; + double fGamma = 1.0; + sal_Int16 nTransparency = 0; + + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "GraphicColorMode" ) ) ) ) + aAny >>= eColorMode; + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "AdjustLuminance" ) ) ) ) + aAny >>= nLuminance; + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "AdjustContrast" ) ) ) ) + { + sal_Int16 nC = sal_Int16(); + aAny >>= nC; + nContrast = nC; + } + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "AdjustRed" ) ) ) ) + aAny >>= nRed; + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "AdjustGreen" ) ) ) ) + aAny >>= nGreen; + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "AdjustBlue" ) ) ) ) + aAny >>= nBlue; + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "Gamma" ) ) ) ) + aAny >>= fGamma; + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "Transparency" ) ) ) ) + aAny >>= nTransparency; + + if ( eColorMode == ::com::sun::star::drawing::ColorMode_WATERMARK ) + { + eColorMode = ::com::sun::star::drawing::ColorMode_STANDARD; + nLuminance += 70; + if ( nLuminance > 100 ) + nLuminance = 100; + nContrast -= 70; + if ( nContrast < -100 ) + nContrast = -100; + } + if ( eColorMode == ::com::sun::star::drawing::ColorMode_GREYS ) + nPicFlags |= 0x40004; + else if ( eColorMode == ::com::sun::star::drawing::ColorMode_MONO ) + nPicFlags |= 0x60006; + + if ( nContrast ) + { + nContrast += 100; + if ( nContrast == 100) + nContrast = 0x10000; + else if ( nContrast < 100 ) + { + nContrast *= 0x10000; + nContrast /= 100; + } + else if ( nContrast < 200 ) + nContrast = ( 100 * 0x10000 ) / ( 200 - nContrast ); + else + nContrast = 0x7fffffff; + AddOpt( ESCHER_Prop_pictureContrast, nContrast ); + } + if ( nLuminance ) + AddOpt( ESCHER_Prop_pictureBrightness, nLuminance * 327 ); + if ( nPicFlags ) + AddOpt( ESCHER_Prop_pictureActive, nPicFlags ); + + if ( bCreateCroppingAttributes && pGraphicProvider ) + { + Size aPrefSize; + MapMode aPrefMapMode; + if ( pGraphicProvider->GetPrefSize( nBlibId, aPrefSize, aPrefMapMode ) ) + { + Size aCropSize(lcl_SizeToEmu(aPrefSize, aPrefMapMode)); + if ( aCropSize.Width() && aCropSize.Height() ) + { + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "GraphicCrop" ) ) ) ) + { + ::com::sun::star::text::GraphicCrop aGraphCrop; + if ( aAny >>= aGraphCrop ) + { + if ( aGraphCrop.Left ) + { + sal_uInt32 nLeft = ( aGraphCrop.Left * 65536 ) / aCropSize.Width(); + AddOpt( ESCHER_Prop_cropFromLeft, nLeft ); + } + if ( aGraphCrop.Top ) + { + sal_uInt32 nTop = ( aGraphCrop.Top * 65536 ) / aCropSize.Height(); + AddOpt( ESCHER_Prop_cropFromTop, nTop ); + } + if ( aGraphCrop.Right ) + { + sal_uInt32 nRight = ( aGraphCrop.Right * 65536 ) / aCropSize.Width(); + AddOpt( ESCHER_Prop_cropFromRight, nRight ); + } + if ( aGraphCrop.Bottom ) + { + sal_uInt32 nBottom = ( aGraphCrop.Bottom * 65536 ) / aCropSize.Height(); + AddOpt( ESCHER_Prop_cropFromBottom, nBottom ); + } + } + } + } + } + } +} + +sal_Bool EscherPropertyContainer::CreateShapeProperties( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape ) +{ + uno::Reference< beans::XPropertySet > aXPropSet( rXShape, uno::UNO_QUERY ); + if ( aXPropSet.is() ) + { + sal_Bool bVal = false; + ::com::sun::star::uno::Any aAny; + sal_uInt32 nShapeAttr = 0; + EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "Visible" ) ), sal_True ); + if ( aAny >>= bVal ) + { + if ( !bVal ) + nShapeAttr |= 0x20002; // set fHidden = true + } + EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "Printable" ) ), sal_True ); + if ( aAny >>= bVal ) + { + if ( !bVal ) + nShapeAttr |= 0x10000; // set fPrint = false; + } + if ( nShapeAttr ) + AddOpt( ESCHER_Prop_fPrint, nShapeAttr ); + } + return sal_True; +} + +sal_Bool EscherPropertyContainer::CreateOLEGraphicProperties( + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape ) +{ + sal_Bool bRetValue = sal_False; + + if ( rXShape.is() ) + { + SdrObject* pSdrOLE2( GetSdrObjectFromXShape( rXShape ) ); // SJ: leaving unoapi, because currently there is + if ( pSdrOLE2 && pSdrOLE2->ISA( SdrOle2Obj ) ) // no access to the native graphic object + { + Graphic* pGraphic = ((SdrOle2Obj*)pSdrOLE2)->GetGraphic(); + if ( pGraphic ) + { + GraphicObject aGraphicObject( *pGraphic ); + ByteString aUniqueId( aGraphicObject.GetUniqueID() ); + if ( aUniqueId.Len() ) + { + AddOpt( ESCHER_Prop_fillType, ESCHER_FillPicture ); + uno::Reference< beans::XPropertySet > aXPropSet( rXShape, uno::UNO_QUERY ); + + if ( pGraphicProvider && pPicOutStrm && pShapeBoundRect && aXPropSet.is() ) + { + ::com::sun::star::uno::Any aAny; + ::com::sun::star::awt::Rectangle* pVisArea = NULL; + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "VisibleArea" ) ) ) ) + { + pVisArea = new ::com::sun::star::awt::Rectangle; + aAny >>= (*pVisArea); + } + Rectangle aRect( Point( 0, 0 ), pShapeBoundRect->GetSize() ); + sal_uInt32 nBlibId = pGraphicProvider->GetBlibID( *pPicOutStrm, aUniqueId, aRect, pVisArea, NULL ); + if ( nBlibId ) + { + AddOpt( ESCHER_Prop_pib, nBlibId, sal_True ); + ImplCreateGraphicAttributes( aXPropSet, nBlibId, sal_False ); + bRetValue = sal_True; + } + delete pVisArea; + } + } + } + } + } + return bRetValue; +} + + +sal_Bool EscherPropertyContainer::ImplCreateEmbeddedBmp( const ByteString& rUniqueId ) +{ + if( rUniqueId.Len() > 0 ) + { + EscherGraphicProvider aProvider; + SvMemoryStream aMemStrm; + Rectangle aRect; + if ( aProvider.GetBlibID( aMemStrm, rUniqueId, aRect ) ) + { + // grab BLIP from stream and insert directly as complex property + // ownership of stream memory goes to complex property + aMemStrm.ObjectOwnsMemory( sal_False ); + sal_uInt8* pBuf = (sal_uInt8*) aMemStrm.GetData(); + sal_uInt32 nSize = aMemStrm.Seek( STREAM_SEEK_TO_END ); + AddOpt( ESCHER_Prop_fillBlip, sal_True, nSize, pBuf, nSize ); + return sal_True; + } + } + return sal_False; +} + +sal_Bool EscherPropertyContainer::CreateEmbeddedBitmapProperties( + const ::rtl::OUString& rBitmapUrl, ::com::sun::star::drawing::BitmapMode eBitmapMode ) +{ + sal_Bool bRetValue = sal_False; + String aVndUrl( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.GraphicObject:" ) ); + String aBmpUrl( rBitmapUrl ); + xub_StrLen nIndex = aBmpUrl.Search( aVndUrl, 0 ); + if( nIndex != STRING_NOTFOUND ) + { + // note: += ist not defined for xub_StrLen -> conversion to int and back to xub_StrLen + nIndex = nIndex + aVndUrl.Len(); + if( aBmpUrl.Len() > nIndex ) + { + ByteString aUniqueId( aBmpUrl, nIndex, aBmpUrl.Len() - nIndex, RTL_TEXTENCODING_UTF8 ); + bRetValue = ImplCreateEmbeddedBmp( aUniqueId ); + if( bRetValue ) + { + // bitmap mode property + bool bRepeat = eBitmapMode == ::com::sun::star::drawing::BitmapMode_REPEAT; + AddOpt( ESCHER_Prop_fillType, bRepeat ? ESCHER_FillTexture : ESCHER_FillPicture ); + } + } + } + return bRetValue; +} + + +namespace { + +GraphicObject lclDrawHatch( const ::com::sun::star::drawing::Hatch& rHatch, const Color& rBackColor, bool bFillBackground ) +{ + const MapMode aMap100( MAP_100TH_MM ); + VirtualDevice aVDev( *Application::GetDefaultDevice(), 0, 1 ); + aVDev.SetMapMode( aMap100 ); + + const Size aOutSize = aVDev.PixelToLogic( Size( 28, 28 ) ); + aVDev.SetOutputSize( aOutSize ); + + Rectangle aRectangle( Point( 0, 0 ), aOutSize ); + const PolyPolygon aPolyPoly( aRectangle ); + + aVDev.SetLineColor(); + aVDev.SetFillColor( bFillBackground ? rBackColor : Color( COL_TRANSPARENT ) ); + aVDev.DrawRect( Rectangle( Point(), aOutSize ) ); + + Hatch aVclHatch( (HatchStyle) rHatch.Style, Color( rHatch.Color ), rHatch.Distance, (sal_uInt16)rHatch.Angle ); + aVDev.DrawHatch( aPolyPoly, aVclHatch ); + + return GraphicObject( Graphic( aVDev.GetBitmapEx( Point(), aOutSize ) ) ); +} + +} // namespace + + +sal_Bool EscherPropertyContainer::CreateEmbeddedHatchProperties( const ::com::sun::star::drawing::Hatch& rHatch, const Color& rBackColor, bool bFillBackground ) +{ + GraphicObject aGraphicObject = lclDrawHatch( rHatch, rBackColor, bFillBackground ); + ByteString aUniqueId = aGraphicObject.GetUniqueID(); + sal_Bool bRetValue = ImplCreateEmbeddedBmp( aUniqueId ); + if ( bRetValue ) + AddOpt( ESCHER_Prop_fillType, ESCHER_FillTexture ); + return bRetValue; +} + + +sal_Bool EscherPropertyContainer::CreateGraphicProperties( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet, + const String& rSource, const sal_Bool bCreateFillBitmap, const sal_Bool bCreateCroppingAttributes, + const sal_Bool bFillBitmapModeAllowed ) +{ + sal_Bool bRetValue = sal_False; + sal_Bool bCreateFillStyles = sal_False; + + sal_Bool bMirrored = sal_False; + sal_Bool bRotate = sal_True; + sal_uInt16 nAngle = 0; + GraphicAttr* pGraphicAttr = NULL; + GraphicObject aGraphicObject; + String aGraphicUrl; + ByteString aUniqueId; + bool bIsGraphicMtf(false); + + ::com::sun::star::drawing::BitmapMode eBitmapMode( ::com::sun::star::drawing::BitmapMode_NO_REPEAT ); + ::com::sun::star::uno::Any aAny; + + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, rSource ) ) + { + if ( rSource == String( RTL_CONSTASCII_USTRINGPARAM( "MetaFile" ) ) ) + { + ::com::sun::star::uno::Sequence<sal_uInt8> aSeq = *(::com::sun::star::uno::Sequence<sal_uInt8>*)aAny.getValue(); + const sal_uInt8* pAry = aSeq.getArray(); + sal_uInt32 nAryLen = aSeq.getLength(); + + // the metafile is already rotated + bRotate = sal_False; + + if ( pAry && nAryLen ) + { + Graphic aGraphic; + SvMemoryStream aTemp( (void*)pAry, nAryLen, STREAM_READ ); + sal_uInt32 nErrCode = GraphicConverter::Import( aTemp, aGraphic, CVT_WMF ); + if ( nErrCode == ERRCODE_NONE ) + { + aGraphicObject = aGraphic; + aUniqueId = aGraphicObject.GetUniqueID(); + bIsGraphicMtf = aGraphicObject.GetType() == GRAPHIC_GDIMETAFILE; + } + } + } + else if ( rSource == String( RTL_CONSTASCII_USTRINGPARAM( "Bitmap" ) ) ) + { + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap >xBitmap; + if ( ::cppu::extractInterface( xBitmap, aAny ) ) + { + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap > xBmp; + if ( aAny >>= xBmp ) + { + BitmapEx aBitmapEx( VCLUnoHelper::GetBitmap( xBmp ) ); + Graphic aGraphic( aBitmapEx ); + aGraphicObject = aGraphic; + aUniqueId = aGraphicObject.GetUniqueID(); + bIsGraphicMtf = aGraphicObject.GetType() == GRAPHIC_GDIMETAFILE; + } + } + } + else if ( rSource == String( RTL_CONSTASCII_USTRINGPARAM( "FillBitmapURL" ) ) ) + { + aGraphicUrl = *(::rtl::OUString*)aAny.getValue(); + } + else if ( rSource == String( RTL_CONSTASCII_USTRINGPARAM( "GraphicURL" ) ) ) + { + aGraphicUrl = *(::rtl::OUString*)aAny.getValue(); + bCreateFillStyles = sal_True; + } + else if ( rSource == String( RTL_CONSTASCII_USTRINGPARAM( "FillHatch" ) ) ) + { + ::com::sun::star::drawing::Hatch aHatch; + if ( aAny >>= aHatch ) + { + Color aBackColor; + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, + String( RTL_CONSTASCII_USTRINGPARAM( "FillColor" ) ), sal_False ) ) + { + aBackColor = ImplGetColor( *((sal_uInt32*)aAny.getValue()), sal_False ); + } + bool bFillBackground = false; + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, + String( RTL_CONSTASCII_USTRINGPARAM( "FillBackground" ) ), sal_True ) ) + { + aAny >>= bFillBackground; + } + aGraphicObject = lclDrawHatch( aHatch, aBackColor, bFillBackground ); + aUniqueId = aGraphicObject.GetUniqueID(); + eBitmapMode = ::com::sun::star::drawing::BitmapMode_REPEAT; + bIsGraphicMtf = aGraphicObject.GetType() == GRAPHIC_GDIMETAFILE; + } + } + + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "IsMirrored" ) ), sal_True ) ) + aAny >>= bMirrored; + + if ( bCreateFillBitmap && bFillBitmapModeAllowed ) + { + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillBitmapMode" ) ), sal_True ) ) + aAny >>= eBitmapMode; + } + else + { + nAngle = bRotate && EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, + String( RTL_CONSTASCII_USTRINGPARAM( "RotateAngle" ) ), sal_True ) + ? (sal_uInt16)( ( *((sal_Int32*)aAny.getValue() ) ) + 5 ) / 10 + : 0; + } + + if ( aGraphicUrl.Len() ) + { + String aVndUrl( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.GraphicObject:" ) ); + xub_StrLen nIndex = aGraphicUrl.Search( aVndUrl, 0 ); + if ( nIndex != STRING_NOTFOUND ) + { + nIndex = nIndex + aVndUrl.Len(); + if ( aGraphicUrl.Len() > nIndex ) + aUniqueId = ByteString( aGraphicUrl, nIndex, aGraphicUrl.Len() - nIndex, RTL_TEXTENCODING_UTF8 ); + } + else + { + // externally, linked graphic? convert to embedded + // one, if transformations are needed. this is because + // everything < msoxp cannot even handle rotated + // bitmaps. + // And check whether the graphic link target is + // actually supported by mso. + INetURLObject aTmp( aGraphicUrl ); + GraphicDescriptor aDescriptor(aTmp); + aDescriptor.Detect(); + const sal_uInt16 nFormat = aDescriptor.GetFileFormat(); + + // can MSO handle it? + if ( bMirrored || nAngle || + (nFormat != GFF_BMP && + nFormat != GFF_GIF && + nFormat != GFF_JPG && + nFormat != GFF_PNG && + nFormat != GFF_TIF && + nFormat != GFF_PCT && + nFormat != GFF_WMF && + nFormat != GFF_EMF) ) + { + SvStream* pIn = ::utl::UcbStreamHelper::CreateStream( + aTmp.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READ ); + if ( pIn ) + { + Graphic aGraphic; + sal_uInt32 nErrCode = GraphicConverter::Import( *pIn, aGraphic ); + + if ( nErrCode == ERRCODE_NONE ) + { + // no. + aGraphicObject = aGraphic; + aUniqueId = aGraphicObject.GetUniqueID(); + } + // else: simply keep the graphic link + delete pIn; + } + } + } + } + + if ( aGraphicUrl.Len() || aUniqueId.Len() ) + { + if ( bMirrored || nAngle ) + { + pGraphicAttr = new GraphicAttr; + if ( bMirrored ) + pGraphicAttr->SetMirrorFlags( BMP_MIRROR_HORZ ); + if ( bIsGraphicMtf ) + AddOpt( ESCHER_Prop_Rotation, ( ( ((sal_Int32)nAngle << 16 ) / 10 ) + 0x8000 ) &~ 0xffff ); + else + { + pGraphicAttr->SetRotation( nAngle ); + if ( nAngle && pShapeBoundRect ) // up to xp ppoint does not rotate bitmaps ! + { + Polygon aPoly( *pShapeBoundRect ); + aPoly.Rotate( pShapeBoundRect->TopLeft(), nAngle ); + *pShapeBoundRect = aPoly.GetBoundRect(); + bSuppressRotation = sal_True; + } + } + } + + if ( eBitmapMode == ::com::sun::star::drawing::BitmapMode_REPEAT ) + AddOpt( ESCHER_Prop_fillType, ESCHER_FillTexture ); + else + AddOpt( ESCHER_Prop_fillType, ESCHER_FillPicture ); + + if ( aUniqueId.Len() ) + { + // write out embedded graphic + if ( pGraphicProvider && pPicOutStrm && pShapeBoundRect ) + { + Rectangle aRect( Point( 0, 0 ), pShapeBoundRect->GetSize() ); + + sal_uInt32 nBlibId = 0; + nBlibId = pGraphicProvider->GetBlibID( *pPicOutStrm, aUniqueId, aRect, NULL, pGraphicAttr ); + if ( nBlibId ) + { + if ( bCreateFillBitmap ) + AddOpt( ESCHER_Prop_fillBlip, nBlibId, sal_True ); + else + { + AddOpt( ESCHER_Prop_pib, nBlibId, sal_True ); + ImplCreateGraphicAttributes( rXPropSet, nBlibId, bCreateCroppingAttributes ); + } + bRetValue = sal_True; + } + } + else + { + EscherGraphicProvider aProvider; + SvMemoryStream aMemStrm; + Rectangle aRect; + + if ( aProvider.GetBlibID( aMemStrm, aUniqueId, aRect, NULL, pGraphicAttr ) ) + { + // grab BLIP from stream and insert directly as complex property + // ownership of stream memory goes to complex property + aMemStrm.ObjectOwnsMemory( sal_False ); + sal_uInt8* pBuf = (sal_uInt8*) aMemStrm.GetData(); + sal_uInt32 nSize = aMemStrm.Seek( STREAM_SEEK_TO_END ); + AddOpt( ESCHER_Prop_fillBlip, sal_True, nSize, pBuf, nSize ); + bRetValue = sal_True; + } + } + } + // write out link to graphic + else + { + OSL_ASSERT(aGraphicUrl.Len()); + + AddOpt( ESCHER_Prop_pibName, aGraphicUrl ); + sal_uInt32 nPibFlags=0; + GetOpt( ESCHER_Prop_pibFlags, nPibFlags ); + AddOpt( ESCHER_Prop_pibFlags, + ESCHER_BlipFlagLinkToFile|ESCHER_BlipFlagFile|ESCHER_BlipFlagDoNotSave | nPibFlags ); + } + } + } + delete pGraphicAttr; + if ( bCreateFillStyles ) + CreateFillProperties( rXPropSet, sal_True ); + + return bRetValue; +} + +PolyPolygon EscherPropertyContainer::GetPolyPolygon( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape ) +{ + PolyPolygon aRetPolyPoly; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > aXPropSet; + ::com::sun::star::uno::Any aAny( rXShape->queryInterface( + ::getCppuType( (const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >*) 0 ) )); + + String sPolyPolygonBezier( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygonBezier" ) ); + String sPolyPolygon ( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygon" ) ); + String sPolygon ( RTL_CONSTASCII_USTRINGPARAM( "Polygon" ) ); + + if ( aAny >>= aXPropSet ) + { + sal_Bool bHasProperty = EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sPolyPolygonBezier, sal_True ); + if ( !bHasProperty ) + bHasProperty = EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sPolyPolygon, sal_True ); + if ( !bHasProperty ) + bHasProperty = EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sPolygon, sal_True ); + if ( bHasProperty ) + aRetPolyPoly = GetPolyPolygon( aAny ); + } + return aRetPolyPoly; +} + +PolyPolygon EscherPropertyContainer::GetPolyPolygon( const ::com::sun::star::uno::Any& rAny ) +{ + sal_Bool bNoError = sal_True; + + Polygon aPolygon; + PolyPolygon aPolyPolygon; + + if ( rAny.getValueType() == ::getCppuType( ( const ::com::sun::star::drawing::PolyPolygonBezierCoords* ) 0 ) ) + { + ::com::sun::star::drawing::PolyPolygonBezierCoords* pSourcePolyPolygon + = (::com::sun::star::drawing::PolyPolygonBezierCoords*)rAny.getValue(); + sal_uInt16 nOuterSequenceCount = (sal_uInt16)pSourcePolyPolygon->Coordinates.getLength(); + + // Zeiger auf innere sequences holen + ::com::sun::star::drawing::PointSequence* pOuterSequence = pSourcePolyPolygon->Coordinates.getArray(); + ::com::sun::star::drawing::FlagSequence* pOuterFlags = pSourcePolyPolygon->Flags.getArray(); + + bNoError = pOuterSequence && pOuterFlags; + if ( bNoError ) + { + sal_uInt16 a, b, nInnerSequenceCount; + ::com::sun::star::awt::Point* pArray; + + // dies wird ein Polygon set + for ( a = 0; a < nOuterSequenceCount; a++ ) + { + ::com::sun::star::drawing::PointSequence* pInnerSequence = pOuterSequence++; + ::com::sun::star::drawing::FlagSequence* pInnerFlags = pOuterFlags++; + + bNoError = pInnerSequence && pInnerFlags; + if ( bNoError ) + { + // Zeiger auf Arrays holen + pArray = pInnerSequence->getArray(); + ::com::sun::star::drawing::PolygonFlags* pFlags = pInnerFlags->getArray(); + + if ( pArray && pFlags ) + { + nInnerSequenceCount = (sal_uInt16)pInnerSequence->getLength(); + aPolygon = Polygon( nInnerSequenceCount ); + for( b = 0; b < nInnerSequenceCount; b++) + { + PolyFlags ePolyFlags( *( (PolyFlags*)pFlags++ ) ); + ::com::sun::star::awt::Point aPoint( (::com::sun::star::awt::Point)*(pArray++) ); + aPolygon[ b ] = Point( aPoint.X, aPoint.Y ); + aPolygon.SetFlags( b, ePolyFlags ); + + if ( ePolyFlags == POLY_CONTROL ) + continue; + } + aPolyPolygon.Insert( aPolygon, POLYPOLY_APPEND ); + } + } + } + } + } + else if ( rAny.getValueType() == ::getCppuType( ( const ::com::sun::star::drawing::PointSequenceSequence* ) 0 ) ) + { + ::com::sun::star::drawing::PointSequenceSequence* pSourcePolyPolygon + = (::com::sun::star::drawing::PointSequenceSequence*)rAny.getValue(); + sal_uInt16 nOuterSequenceCount = (sal_uInt16)pSourcePolyPolygon->getLength(); + + // Zeiger auf innere sequences holen + ::com::sun::star::drawing::PointSequence* pOuterSequence = pSourcePolyPolygon->getArray(); + bNoError = pOuterSequence != NULL; + if ( bNoError ) + { + sal_uInt16 a, b, nInnerSequenceCount; + + // dies wird ein Polygon set + for( a = 0; a < nOuterSequenceCount; a++ ) + { + ::com::sun::star::drawing::PointSequence* pInnerSequence = pOuterSequence++; + bNoError = pInnerSequence != NULL; + if ( bNoError ) + { + // Zeiger auf Arrays holen + ::com::sun::star::awt::Point* pArray = + pInnerSequence->getArray(); + if ( pArray != NULL ) + { + nInnerSequenceCount = (sal_uInt16)pInnerSequence->getLength(); + aPolygon = Polygon( nInnerSequenceCount ); + for( b = 0; b < nInnerSequenceCount; b++) + { + aPolygon[ b ] = Point( pArray->X, pArray->Y ); + pArray++; + } + aPolyPolygon.Insert( aPolygon, POLYPOLY_APPEND ); + } + } + } + } + } + else if ( rAny.getValueType() == ::getCppuType( ( const ::com::sun::star::drawing::PointSequence* ) 0 ) ) + { + ::com::sun::star::drawing::PointSequence* pInnerSequence = + (::com::sun::star::drawing::PointSequence*)rAny.getValue(); + + bNoError = pInnerSequence != NULL; + if ( bNoError ) + { + sal_uInt16 a, nInnerSequenceCount; + + // Zeiger auf Arrays holen + ::com::sun::star::awt::Point* pArray = pInnerSequence->getArray(); + if ( pArray != NULL ) + { + nInnerSequenceCount = (sal_uInt16)pInnerSequence->getLength(); + aPolygon = Polygon( nInnerSequenceCount ); + for( a = 0; a < nInnerSequenceCount; a++) + { + aPolygon[ a ] = Point( pArray->X, pArray->Y ); + pArray++; + } + aPolyPolygon.Insert( aPolygon, POLYPOLY_APPEND ); + } + } + } + return aPolyPolygon; +} + +sal_Bool EscherPropertyContainer::CreatePolygonProperties( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet, + sal_uInt32 nFlags, + sal_Bool bBezier, + ::com::sun::star::awt::Rectangle& rGeoRect, + Polygon* pPolygon ) +{ + static String sPolyPolygonBezier( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygonBezier" ) ); + static String sPolyPolygon ( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygon" ) ); + + sal_Bool bRetValue = sal_True; + sal_Bool bLine = ( nFlags & ESCHER_CREATEPOLYGON_LINE ) != 0; + + PolyPolygon aPolyPolygon; + + if ( pPolygon ) + aPolyPolygon.Insert( *pPolygon, POLYPOLY_APPEND ); + else + { + ::com::sun::star::uno::Any aAny; + bRetValue = EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, + ( bBezier ) ? sPolyPolygonBezier : sPolyPolygon, sal_True ); + if ( bRetValue ) + { + aPolyPolygon = GetPolyPolygon( aAny ); + bRetValue = aPolyPolygon.Count() != 0; + } + } + if ( bRetValue ) + { + if ( bLine ) + { + if ( ( aPolyPolygon.Count() == 1 ) && ( aPolyPolygon[ 0 ].GetSize() == 2 ) ) + { + const Polygon& rPoly = aPolyPolygon[ 0 ]; + rGeoRect = ::com::sun::star::awt::Rectangle( + rPoly[ 0 ].X(), + rPoly[ 0 ].Y(), + rPoly[ 1 ].X() - rPoly[ 0 ].X(), + rPoly[ 1 ].Y() - rPoly[ 0 ].Y() ); + } + else + bRetValue = sal_False; + } + else + { + Polygon aPolygon; + + sal_uInt16 i, j, k, nPoints, nBezPoints, nPolyCount = aPolyPolygon.Count(); + Rectangle aRect( aPolyPolygon.GetBoundRect() ); + rGeoRect = ::com::sun::star::awt::Rectangle( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight() ); + + for ( nBezPoints = nPoints = i = 0; i < nPolyCount; i++ ) + { + k = aPolyPolygon[ i ].GetSize(); + nPoints = nPoints + k; + for ( j = 0; j < k; j++ ) + { + if ( aPolyPolygon[ i ].GetFlags( j ) != POLY_CONTROL ) + nBezPoints++; + } + } + sal_uInt32 nVerticesBufSize = ( nPoints << 2 ) + 6; + sal_uInt8* pVerticesBuf = new sal_uInt8[ nVerticesBufSize ]; + + + sal_uInt32 nSegmentBufSize = ( ( nBezPoints << 2 ) + 8 ); + if ( nPolyCount > 1 ) + nSegmentBufSize += ( nPolyCount << 1 ); + sal_uInt8* pSegmentBuf = new sal_uInt8[ nSegmentBufSize ]; + + sal_uInt8* pPtr = pVerticesBuf; + *pPtr++ = (sal_uInt8)( nPoints ); // Little endian + *pPtr++ = (sal_uInt8)( nPoints >> 8 ); + *pPtr++ = (sal_uInt8)( nPoints ); + *pPtr++ = (sal_uInt8)( nPoints >> 8 ); + *pPtr++ = (sal_uInt8)0xf0; + *pPtr++ = (sal_uInt8)0xff; + + for ( j = 0; j < nPolyCount; j++ ) + { + aPolygon = aPolyPolygon[ j ]; + nPoints = aPolygon.GetSize(); + for ( i = 0; i < nPoints; i++ ) // Punkte aus Polygon in Buffer schreiben + { + Point aPoint = aPolygon[ i ]; + aPoint.X() -= rGeoRect.X; + aPoint.Y() -= rGeoRect.Y; + + *pPtr++ = (sal_uInt8)( aPoint.X() ); + *pPtr++ = (sal_uInt8)( aPoint.X() >> 8 ); + *pPtr++ = (sal_uInt8)( aPoint.Y() ); + *pPtr++ = (sal_uInt8)( aPoint.Y() >> 8 ); + } + } + + pPtr = pSegmentBuf; + *pPtr++ = (sal_uInt8)( ( nSegmentBufSize - 6 ) >> 1 ); + *pPtr++ = (sal_uInt8)( ( nSegmentBufSize - 6 ) >> 9 ); + *pPtr++ = (sal_uInt8)( ( nSegmentBufSize - 6 ) >> 1 ); + *pPtr++ = (sal_uInt8)( ( nSegmentBufSize - 6 ) >> 9 ); + *pPtr++ = (sal_uInt8)2; + *pPtr++ = (sal_uInt8)0; + + for ( j = 0; j < nPolyCount; j++ ) + { + *pPtr++ = 0x0; // Polygon start + *pPtr++ = 0x40; + aPolygon = aPolyPolygon[ j ]; + nPoints = aPolygon.GetSize(); + for ( i = 0; i < nPoints; i++ ) // Polyflags in Buffer schreiben + { + *pPtr++ = 0; + if ( bBezier ) + *pPtr++ = 0xb3; + else + *pPtr++ = 0xac; + if ( ( i + 1 ) != nPoints ) + { + *pPtr++ = 1; + if ( aPolygon.GetFlags( i + 1 ) == POLY_CONTROL ) + { + *pPtr++ = 0x20; + i += 2; + } + else + *pPtr++ = 0; + } + } + if ( nPolyCount > 1 ) + { + *pPtr++ = 1; // end of polygon + *pPtr++ = 0x60; + } + } + *pPtr++ = 0; + *pPtr++ = 0x80; + + AddOpt( ESCHER_Prop_geoRight, rGeoRect.Width ); + AddOpt( ESCHER_Prop_geoBottom, rGeoRect.Height ); + + AddOpt( ESCHER_Prop_shapePath, ESCHER_ShapeComplex ); + AddOpt( ESCHER_Prop_pVertices, sal_True, nVerticesBufSize - 6, (sal_uInt8*)pVerticesBuf, nVerticesBufSize ); + AddOpt( ESCHER_Prop_pSegmentInfo, sal_True, nSegmentBufSize, (sal_uInt8*)pSegmentBuf, nSegmentBufSize ); + } + } + return bRetValue; +} + +sal_Bool EscherPropertyContainer::CreateConnectorProperties( + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape, + EscherSolverContainer& rSolverContainer, ::com::sun::star::awt::Rectangle& rGeoRect, + sal_uInt16& rShapeType, sal_uInt16& rShapeFlags ) +{ + static String sEdgeKind ( RTL_CONSTASCII_USTRINGPARAM( "EdgeKind" ) ); + static String sEdgeStartPoint ( RTL_CONSTASCII_USTRINGPARAM( "EdgeStartPoint" ) ); + static String sEdgeEndPoint ( RTL_CONSTASCII_USTRINGPARAM( "EdgeEndPoint" ) ); + static String sEdgeStartConnection ( RTL_CONSTASCII_USTRINGPARAM( "EdgeStartConnection" ) ); + static String sEdgeEndConnection ( RTL_CONSTASCII_USTRINGPARAM( "EdgeEndConnection" ) ); + + sal_Bool bRetValue = sal_False; + rShapeType = rShapeFlags = 0; + + if ( rXShape.is() ) + { + ::com::sun::star::awt::Point aStartPoint, aEndPoint; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > aXPropSet; + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > aShapeA, aShapeB; + ::com::sun::star::uno::Any aAny( rXShape->queryInterface( ::getCppuType( (const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >*) 0 ) )); + if ( aAny >>= aXPropSet ) + { + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sEdgeKind, sal_True ) ) + { + ::com::sun::star::drawing::ConnectorType eCt; + aAny >>= eCt; + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sEdgeStartPoint ) ) + { + aStartPoint = *(::com::sun::star::awt::Point*)aAny.getValue(); + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sEdgeEndPoint ) ) + { + aEndPoint = *(::com::sun::star::awt::Point*)aAny.getValue(); + + rShapeFlags = SHAPEFLAG_HAVEANCHOR | SHAPEFLAG_HAVESPT | SHAPEFLAG_CONNECTOR; + rGeoRect = ::com::sun::star::awt::Rectangle( aStartPoint.X, aStartPoint.Y, + ( aEndPoint.X - aStartPoint.X ) + 1, ( aEndPoint.Y - aStartPoint.Y ) + 1 ); + if ( rGeoRect.Height < 0 ) // justify + { + rShapeFlags |= SHAPEFLAG_FLIPV; + rGeoRect.Y = aEndPoint.Y; + rGeoRect.Height = -rGeoRect.Height; + } + if ( rGeoRect.Width < 0 ) + { + rShapeFlags |= SHAPEFLAG_FLIPH; + rGeoRect.X = aEndPoint.X; + rGeoRect.Width = -rGeoRect.Width; + } + sal_uInt32 nAdjustValue1, nAdjustValue2, nAdjustValue3; + nAdjustValue1 = nAdjustValue2 = nAdjustValue3 = 0x2a30; + + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sEdgeStartConnection ) ) + aAny >>= aShapeA; + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sEdgeEndConnection ) ) + aAny >>= aShapeB; +/* + if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeLine1Delta" ) ) ) ) + { + } + if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeLine2Delta" ) ) ) ) + { + } + if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeLine3Delta" ) ) ) ) + { + } + if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeNode1HorzDist" ) ) ) ) + { + } + if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeNode1VertDist" ) ) ) ) + { + } + if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeNode2HorzDist" ) ) ) ) + { + } + if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeNode2VertDist" ) ) ) ) + { + } +*/ + rSolverContainer.AddConnector( rXShape, aStartPoint, aShapeA, aEndPoint, aShapeB ); + switch ( eCt ) + { + case ::com::sun::star::drawing::ConnectorType_CURVE : + { + rShapeType = ESCHER_ShpInst_CurvedConnector3; + AddOpt( ESCHER_Prop_cxstyle, ESCHER_cxstyleCurved ); + AddOpt( ESCHER_Prop_adjustValue, nAdjustValue1 ); + AddOpt( ESCHER_Prop_adjust2Value, -(sal_Int32)nAdjustValue2 ); + } + break; + + case ::com::sun::star::drawing::ConnectorType_STANDARD :// Connector 2->5 + { + rShapeType = ESCHER_ShpInst_BentConnector3; + AddOpt( ESCHER_Prop_cxstyle, ESCHER_cxstyleBent ); + } + break; + + default: + case ::com::sun::star::drawing::ConnectorType_LINE : + case ::com::sun::star::drawing::ConnectorType_LINES : // Connector 2->5 + { + rShapeType = ESCHER_ShpInst_StraightConnector1; + AddOpt( ESCHER_Prop_cxstyle, ESCHER_cxstyleStraight ); + } + break; + } + CreateLineProperties( aXPropSet, sal_False ); + bRetValue = bSuppressRotation = sal_True; + } + } + } + } + } + return bRetValue; +} + +sal_Bool EscherPropertyContainer::CreateShadowProperties( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet ) +{ + ::com::sun::star::uno::Any aAny; + + sal_Bool bHasShadow = sal_False; // shadow is possible only if at least a fillcolor, linecolor or graphic is set + sal_uInt32 nLineFlags = 0; // default : shape has no line + sal_uInt32 nFillFlags = 0x10; // shape is filled + + GetOpt( ESCHER_Prop_fNoLineDrawDash, nLineFlags ); + GetOpt( ESCHER_Prop_fNoFillHitTest, nFillFlags ); + + sal_uInt32 nDummy; + sal_Bool bGraphic = GetOpt( DFF_Prop_pib, nDummy ) || GetOpt( DFF_Prop_pibName, nDummy ) || GetOpt( DFF_Prop_pibFlags, nDummy ); + + sal_uInt32 nShadowFlags = 0x20000; + if ( ( nLineFlags & 8 ) || ( nFillFlags & 0x10 ) || bGraphic ) + { + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, + String( RTL_CONSTASCII_USTRINGPARAM( "Shadow" ) ), sal_True ) ) + { + if ( aAny >>= bHasShadow ) + { + if ( bHasShadow ) + { + nShadowFlags |= 2; + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, + String( RTL_CONSTASCII_USTRINGPARAM( "ShadowColor" ) ), sal_False ) ) + AddOpt( ESCHER_Prop_shadowColor, ImplGetColor( *((sal_uInt32*)aAny.getValue()) ) ); + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, + String( RTL_CONSTASCII_USTRINGPARAM( "ShadowXDistance" ) ), sal_False ) ) + AddOpt( ESCHER_Prop_shadowOffsetX, *((sal_Int32*)aAny.getValue()) * 360 ); + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, + String( RTL_CONSTASCII_USTRINGPARAM( "ShadowYDistance" ) ), sal_False ) ) + AddOpt( ESCHER_Prop_shadowOffsetY, *((sal_Int32*)aAny.getValue()) * 360 ); + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, + String( RTL_CONSTASCII_USTRINGPARAM( "ShadowTransparence" ) ), sal_False ) ) + AddOpt( ESCHER_Prop_shadowOpacity, 0x10000 - (((sal_uInt32)*((sal_uInt16*)aAny.getValue())) * 655 ) ); + } + } + } + } + AddOpt( ESCHER_Prop_fshadowObscured, nShadowFlags ); + return bHasShadow; +} + +// --------------------------------------------------------------------------------------------- + +sal_Int32 GetValueForEnhancedCustomShapeParameter( const com::sun::star::drawing::EnhancedCustomShapeParameter& rParameter, const std::vector< sal_Int32 >& rEquationOrder ) +{ + sal_Int32 nValue = 0; + if ( rParameter.Value.getValueTypeClass() == uno::TypeClass_DOUBLE ) + { + double fValue; + if ( rParameter.Value >>= fValue ) + nValue = (sal_Int32)fValue; + } + else + rParameter.Value >>= nValue; + + switch( rParameter.Type ) + { + case com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION : + { + nValue = (sal_uInt16)rEquationOrder[ nValue ]; + nValue |= (sal_uInt32)0x80000000; + } + break; + case com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL : + { + + } + break; +/* not sure if it is allowed to set following values +(but they are not yet used) + case com::sun::star::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT : + case com::sun::star::drawing::EnhancedCustomShapeParameterType::BOTTOM : + case com::sun::star::drawing::EnhancedCustomShapeParameterType::RIGHT : + case com::sun::star::drawing::EnhancedCustomShapeParameterType::TOP : + case com::sun::star::drawing::EnhancedCustomShapeParameterType::LEFT : +*/ + } + return nValue; +} + +sal_Bool GetValueForEnhancedCustomShapeHandleParameter( sal_Int32& nRetValue, const com::sun::star::drawing::EnhancedCustomShapeParameter& rParameter ) +{ + sal_Bool bSpecial = sal_False; + nRetValue = 0; + if ( rParameter.Value.getValueTypeClass() == uno::TypeClass_DOUBLE ) + { + double fValue; + if ( rParameter.Value >>= fValue ) + nRetValue = (sal_Int32)fValue; + } + else + rParameter.Value >>= nRetValue; + + switch( rParameter.Type ) + { + case com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION : + { + nRetValue += 3; + bSpecial = sal_True; + } + break; + case com::sun::star::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT : + { + nRetValue += 0x100; + bSpecial = sal_True; + } + break; + case com::sun::star::drawing::EnhancedCustomShapeParameterType::TOP : + case com::sun::star::drawing::EnhancedCustomShapeParameterType::LEFT : + { + nRetValue = 0; + bSpecial = sal_True; + } + break; + case com::sun::star::drawing::EnhancedCustomShapeParameterType::RIGHT : + case com::sun::star::drawing::EnhancedCustomShapeParameterType::BOTTOM : + { + nRetValue = 1; + bSpecial = sal_True; + } + break; + case com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL : + { + + } + break; + } + return bSpecial; +} + +void ConvertEnhancedCustomShapeEquation( SdrObjCustomShape* pCustoShape, + std::vector< EnhancedCustomShapeEquation >& rEquations, std::vector< sal_Int32 >& rEquationOrder ) +{ + if ( pCustoShape ) + { + uno::Sequence< rtl::OUString > sEquationSource; + const rtl::OUString sEquations( RTL_CONSTASCII_USTRINGPARAM( "Equations" ) ); + SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)(const SdrCustomShapeGeometryItem&) + pCustoShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ); + const uno::Any* pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sEquations ); + if ( pAny ) + *pAny >>= sEquationSource; + sal_Int32 nEquationSourceCount = sEquationSource.getLength(); + if ( nEquationSourceCount ) + { + sal_Int32 i; + for ( i = 0; i < nEquationSourceCount; i++ ) + { + EnhancedCustomShape2d aCustoShape2d( pCustoShape ); + try + { + ::boost::shared_ptr< EnhancedCustomShape::ExpressionNode > aExpressNode( + EnhancedCustomShape::FunctionParser::parseFunction( sEquationSource[ i ], aCustoShape2d ) ); + com::sun::star::drawing::EnhancedCustomShapeParameter aPara( aExpressNode->fillNode( rEquations, NULL, 0 ) ); + if ( aPara.Type != com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION ) + { + EnhancedCustomShapeEquation aEquation; + aEquation.nOperation = 0; + EnhancedCustomShape::FillEquationParameter( aPara, 0, aEquation ); + rEquations.push_back( aEquation ); + } + } + catch ( EnhancedCustomShape::ParseError& ) + { + EnhancedCustomShapeEquation aEquation; // ups, we should not be here, + aEquation.nOperation = 0; // creating a default equation with value 1 + aEquation.nPara[ 0 ] = 1; // hoping that this will not break anything + rEquations.push_back( aEquation ); + } + catch ( ... ) + { + EnhancedCustomShapeEquation aEquation; // #i112309# EnhancedCustomShape::Parse error + aEquation.nOperation = 0; // not catched on linux platform + aEquation.nPara[ 0 ] = 1; + rEquations.push_back( aEquation ); + } + rEquationOrder.push_back( rEquations.size() - 1 ); + } + // now updating our old equation indices, they are marked with a bit in the hiword of nOperation + std::vector< EnhancedCustomShapeEquation >::iterator aIter( rEquations.begin() ); + std::vector< EnhancedCustomShapeEquation >::iterator aEnd ( rEquations.end() ); + while( aIter != aEnd ) + { + sal_Int32 nMask = 0x20000000; + for( i = 0; i < 3; i++ ) + { + if ( aIter->nOperation & nMask ) + { + aIter->nOperation ^= nMask; + aIter->nPara[ i ] = rEquationOrder[ aIter->nPara[ i ] & 0x3ff ] | 0x400; + } + nMask <<= 1; + } + aIter++; + } + } + } +} + +sal_Bool EscherPropertyContainer::IsDefaultObject( SdrObjCustomShape* pCustoShape ) +{ + sal_Bool bIsDefaultObject = sal_False; + if ( pCustoShape ) + { + if ( pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_EQUATIONS ) + && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_VIEWBOX ) + && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_PATH ) + && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_GLUEPOINTS ) + && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_SEGMENTS ) + && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_STRETCHX ) + && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_STRETCHY ) +// && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_HANDLES ) + && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_TEXTFRAMES ) ) + bIsDefaultObject = sal_True; + } + + return bIsDefaultObject; +} + +void EscherPropertyContainer::LookForPolarHandles( const MSO_SPT eShapeType, sal_Int32& nAdjustmentsWhichNeedsToBeConverted ) +{ + const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eShapeType ); + if ( pDefCustomShape && pDefCustomShape->nHandles && pDefCustomShape->pHandles ) + { + sal_Int32 k, nkCount = pDefCustomShape->nHandles; + const SvxMSDffHandle* pData = pDefCustomShape->pHandles; + for ( k = 0; k < nkCount; k++, pData++ ) + { + if ( pData->nFlags & MSDFF_HANDLE_FLAGS_POLAR ) + { + if ( ( pData->nPositionY >= 0x256 ) || ( pData->nPositionY <= 0x107 ) ) + nAdjustmentsWhichNeedsToBeConverted |= ( 1 << k ); + } + } + } +} + +sal_Bool EscherPropertyContainer::GetAdjustmentValue( const com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue & rkProp, sal_Int32 nIndex, sal_Int32 nAdjustmentsWhichNeedsToBeConverted, sal_Int32& nValue ) +{ + if ( rkProp.State != beans::PropertyState_DIRECT_VALUE ) + return sal_False; + + sal_Bool bUseFixedFloat = ( nAdjustmentsWhichNeedsToBeConverted & ( 1 << nIndex ) ) != 0; + if ( rkProp.Value.getValueTypeClass() == uno::TypeClass_DOUBLE ) + { + double fValue(0.0); + rkProp.Value >>= fValue; + if ( bUseFixedFloat ) + fValue *= 65536.0; + nValue = (sal_Int32)fValue; + } + else + { + rkProp.Value >>= nValue; + if ( bUseFixedFloat ) + nValue <<= 16; + } + + return sal_True; +} + +void EscherPropertyContainer::CreateCustomShapeProperties( const MSO_SPT eShapeType, const uno::Reference< drawing::XShape > & rXShape ) +{ + uno::Reference< beans::XPropertySet > aXPropSet( rXShape, uno::UNO_QUERY ); + if ( aXPropSet.is() ) + { + SdrObjCustomShape* pCustoShape = (SdrObjCustomShape*)GetSdrObjectFromXShape( rXShape ); + const rtl::OUString sCustomShapeGeometry( RTL_CONSTASCII_USTRINGPARAM( "CustomShapeGeometry" ) ); + uno::Any aGeoPropSet = aXPropSet->getPropertyValue( sCustomShapeGeometry ); + uno::Sequence< beans::PropertyValue > aGeoPropSeq; + if ( aGeoPropSet >>= aGeoPropSeq ) + { + const rtl::OUString sViewBox ( RTL_CONSTASCII_USTRINGPARAM( "ViewBox" ) ); + const rtl::OUString sTextRotateAngle ( RTL_CONSTASCII_USTRINGPARAM( "TextRotateAngle" ) ); + const rtl::OUString sExtrusion ( RTL_CONSTASCII_USTRINGPARAM( "Extrusion" ) ); + const rtl::OUString sEquations ( RTL_CONSTASCII_USTRINGPARAM( "Equations" ) ); + const rtl::OUString sPath ( RTL_CONSTASCII_USTRINGPARAM( "Path" ) ); + const rtl::OUString sTextPath ( RTL_CONSTASCII_USTRINGPARAM( "TextPath" ) ); + const rtl::OUString sHandles ( RTL_CONSTASCII_USTRINGPARAM( "Handles" ) ); + const rtl::OUString sAdjustmentValues ( RTL_CONSTASCII_USTRINGPARAM( "AdjustmentValues" ) ); + + const beans::PropertyValue* pAdjustmentValuesProp = NULL; + sal_Int32 nAdjustmentsWhichNeedsToBeConverted = 0; + uno::Sequence< beans::PropertyValues > aHandlesPropSeq; + sal_Bool bPredefinedHandlesUsed = sal_True; + sal_Bool bIsDefaultObject = IsDefaultObject( pCustoShape ); + + // convert property "Equations" into std::vector< EnhancedCustomShapeEquationEquation > + std::vector< EnhancedCustomShapeEquation > aEquations; + std::vector< sal_Int32 > aEquationOrder; + ConvertEnhancedCustomShapeEquation( pCustoShape, aEquations, aEquationOrder ); + + sal_Int32 i, nCount = aGeoPropSeq.getLength(); + for ( i = 0; i < nCount; i++ ) + { + const beans::PropertyValue& rProp = aGeoPropSeq[ i ]; + if ( rProp.Name.equals( sViewBox ) ) + { + if ( !bIsDefaultObject ) + { + awt::Rectangle aViewBox; + if ( rProp.Value >>= aViewBox ) + { + AddOpt( DFF_Prop_geoLeft, aViewBox.X ); + AddOpt( DFF_Prop_geoTop, aViewBox.Y ); + AddOpt( DFF_Prop_geoRight, aViewBox.X + aViewBox.Width ); + AddOpt( DFF_Prop_geoBottom,aViewBox.Y + aViewBox.Height ); + } + } + } + else if ( rProp.Name.equals( sTextRotateAngle ) ) + { + double f = 0, fTextRotateAngle; + if ( rProp.Value >>= f ) + { + fTextRotateAngle = fmod( f, 360.0 ); + if ( fTextRotateAngle < 0 ) + fTextRotateAngle = 360 + fTextRotateAngle; + if ( ( fTextRotateAngle < 271.0 ) && ( fTextRotateAngle > 269.0 ) ) + AddOpt( DFF_Prop_cdirFont, mso_cdir90 ); + else if ( ( fTextRotateAngle < 181.0 ) && ( fTextRotateAngle > 179.0 ) ) + AddOpt( DFF_Prop_cdirFont, mso_cdir180 ); + else if ( ( fTextRotateAngle < 91.0 ) && ( fTextRotateAngle > 79.0 ) ) + AddOpt( DFF_Prop_cdirFont, mso_cdir270 ); + } + } + else if ( rProp.Name.equals( sExtrusion ) ) + { + uno::Sequence< beans::PropertyValue > aExtrusionPropSeq; + if ( rProp.Value >>= aExtrusionPropSeq ) + { + sal_uInt32 nLightFaceFlagsOrg, nLightFaceFlags; + sal_uInt32 nFillHarshFlagsOrg, nFillHarshFlags; + nLightFaceFlagsOrg = nLightFaceFlags = 0x000001; + nFillHarshFlagsOrg = nFillHarshFlags = 0x00001e; + if ( GetOpt( DFF_Prop_fc3DLightFace, nLightFaceFlags ) ) + nLightFaceFlagsOrg = nLightFaceFlags; + if ( GetOpt( DFF_Prop_fc3DFillHarsh, nFillHarshFlags ) ) + nFillHarshFlagsOrg = nFillHarshFlags; + + sal_Int32 r, nrCount = aExtrusionPropSeq.getLength(); + for ( r = 0; r < nrCount; r++ ) + { + const beans::PropertyValue& rrProp = aExtrusionPropSeq[ r ]; + const rtl::OUString sExtrusionBrightness ( RTL_CONSTASCII_USTRINGPARAM( "Brightness" ) ); + const rtl::OUString sExtrusionDepth ( RTL_CONSTASCII_USTRINGPARAM( "Depth" ) ); + const rtl::OUString sExtrusionDiffusion ( RTL_CONSTASCII_USTRINGPARAM( "Diffusion" ) ); + const rtl::OUString sExtrusionNumberOfLineSegments ( RTL_CONSTASCII_USTRINGPARAM( "NumberOfLineSegments" ) ); + const rtl::OUString sExtrusionLightFace ( RTL_CONSTASCII_USTRINGPARAM( "LightFace" ) ); + const rtl::OUString sExtrusionFirstLightHarsh ( RTL_CONSTASCII_USTRINGPARAM( "FirstLightHarsh" ) ); + const rtl::OUString sExtrusionSecondLightHarsh ( RTL_CONSTASCII_USTRINGPARAM( "SecondLightHarsh" ) ); + const rtl::OUString sExtrusionFirstLightLevel ( RTL_CONSTASCII_USTRINGPARAM( "FirstLightLevel" ) ); + const rtl::OUString sExtrusionSecondLightLevel ( RTL_CONSTASCII_USTRINGPARAM( "SecondLightLevel" ) ); + const rtl::OUString sExtrusionFirstLightDirection ( RTL_CONSTASCII_USTRINGPARAM( "FirstLightDirection" ) ); + const rtl::OUString sExtrusionSecondLightDirection ( RTL_CONSTASCII_USTRINGPARAM( "SecondLightDirection" ) ); + const rtl::OUString sExtrusionMetal ( RTL_CONSTASCII_USTRINGPARAM( "Metal" ) ); + const rtl::OUString sExtrusionShadeMode ( RTL_CONSTASCII_USTRINGPARAM( "ShadeMode" ) ); + const rtl::OUString sExtrusionRotateAngle ( RTL_CONSTASCII_USTRINGPARAM( "RotateAngle" ) ); + const rtl::OUString sExtrusionRotationCenter ( RTL_CONSTASCII_USTRINGPARAM( "RotationCenter" ) ); + const rtl::OUString sExtrusionShininess ( RTL_CONSTASCII_USTRINGPARAM( "Shininess" ) ); + const rtl::OUString sExtrusionSkew ( RTL_CONSTASCII_USTRINGPARAM( "Skew" ) ); + const rtl::OUString sExtrusionSpecularity ( RTL_CONSTASCII_USTRINGPARAM( "Specularity" ) ); + const rtl::OUString sExtrusionProjectionMode ( RTL_CONSTASCII_USTRINGPARAM( "ProjectionMode" ) ); + const rtl::OUString sExtrusionViewPoint ( RTL_CONSTASCII_USTRINGPARAM( "ViewPoint" ) ); + const rtl::OUString sExtrusionOrigin ( RTL_CONSTASCII_USTRINGPARAM( "Origin" ) ); + const rtl::OUString sExtrusionColor ( RTL_CONSTASCII_USTRINGPARAM( "Color" ) ); + + if ( rrProp.Name.equals( sExtrusion ) ) + { + sal_Bool bExtrusionOn = sal_Bool(); + if ( rrProp.Value >>= bExtrusionOn ) + { + nLightFaceFlags |= 0x80000; + if ( bExtrusionOn ) + nLightFaceFlags |= 8; + else + nLightFaceFlags &=~8; + } + } + else if ( rrProp.Name.equals( sExtrusionBrightness ) ) + { + double fExtrusionBrightness = 0; + if ( rrProp.Value >>= fExtrusionBrightness ) + AddOpt( DFF_Prop_c3DAmbientIntensity, (sal_Int32)( fExtrusionBrightness * 655.36 ) ); + } + else if ( rrProp.Name.equals( sExtrusionDepth ) ) + { + double fDepth = 0; + double fFraction = 0; + com::sun::star::drawing::EnhancedCustomShapeParameterPair aDepthParaPair; + if ( ( rrProp.Value >>= aDepthParaPair ) && ( aDepthParaPair.First.Value >>= fDepth ) && ( aDepthParaPair.Second.Value >>= fFraction ) ) + { + double fForeDepth = fDepth * fFraction; + double fBackDepth = fDepth - fForeDepth; + + fBackDepth *= 360.0; + AddOpt( DFF_Prop_c3DExtrudeBackward, (sal_Int32)fBackDepth ); + + if ( fForeDepth != 0.0 ) + { + fForeDepth *= 360.0; + AddOpt( DFF_Prop_c3DExtrudeForward, (sal_Int32)fForeDepth ); + } + } + } + else if ( rrProp.Name.equals( sExtrusionDiffusion ) ) + { + double fExtrusionDiffusion = 0; + if ( rrProp.Value >>= fExtrusionDiffusion ) + AddOpt( DFF_Prop_c3DDiffuseAmt, (sal_Int32)( fExtrusionDiffusion * 655.36 ) ); + } + else if ( rrProp.Name.equals( sExtrusionNumberOfLineSegments ) ) + { + sal_Int32 nExtrusionNumberOfLineSegments = 0; + if ( rrProp.Value >>= nExtrusionNumberOfLineSegments ) + AddOpt( DFF_Prop_c3DTolerance, nExtrusionNumberOfLineSegments ); + } + else if ( rrProp.Name.equals( sExtrusionLightFace ) ) + { + sal_Bool bExtrusionLightFace = sal_Bool(); + if ( rrProp.Value >>= bExtrusionLightFace ) + { + nLightFaceFlags |= 0x10000; + if ( bExtrusionLightFace ) + nLightFaceFlags |= 1; + else + nLightFaceFlags &=~1; + } + } + else if ( rrProp.Name.equals( sExtrusionFirstLightHarsh ) ) + { + sal_Bool bExtrusionFirstLightHarsh = sal_Bool(); + if ( rrProp.Value >>= bExtrusionFirstLightHarsh ) + { + nFillHarshFlags |= 0x20000; + if ( bExtrusionFirstLightHarsh ) + nFillHarshFlags |= 2; + else + nFillHarshFlags &=~2; + } + } + else if ( rrProp.Name.equals( sExtrusionSecondLightHarsh ) ) + { + sal_Bool bExtrusionSecondLightHarsh = sal_Bool(); + if ( rrProp.Value >>= bExtrusionSecondLightHarsh ) + { + nFillHarshFlags |= 0x10000; + if ( bExtrusionSecondLightHarsh ) + nFillHarshFlags |= 1; + else + nFillHarshFlags &=~1; + } + } + else if ( rrProp.Name.equals( sExtrusionFirstLightLevel ) ) + { + double fExtrusionFirstLightLevel = 0; + if ( rrProp.Value >>= fExtrusionFirstLightLevel ) + AddOpt( DFF_Prop_c3DKeyIntensity, (sal_Int32)( fExtrusionFirstLightLevel * 655.36 ) ); + } + else if ( rrProp.Name.equals( sExtrusionSecondLightLevel ) ) + { + double fExtrusionSecondLightLevel = 0; + if ( rrProp.Value >>= fExtrusionSecondLightLevel ) + AddOpt( DFF_Prop_c3DFillIntensity, (sal_Int32)( fExtrusionSecondLightLevel * 655.36 ) ); + } + else if ( rrProp.Name.equals( sExtrusionFirstLightDirection ) ) + { + drawing::Direction3D aExtrusionFirstLightDirection; + if ( rrProp.Value >>= aExtrusionFirstLightDirection ) + { + AddOpt( DFF_Prop_c3DKeyX, (sal_Int32)aExtrusionFirstLightDirection.DirectionX ); + AddOpt( DFF_Prop_c3DKeyY, (sal_Int32)aExtrusionFirstLightDirection.DirectionY ); + AddOpt( DFF_Prop_c3DKeyZ, (sal_Int32)aExtrusionFirstLightDirection.DirectionZ ); + } + } + else if ( rrProp.Name.equals( sExtrusionSecondLightDirection ) ) + { + drawing::Direction3D aExtrusionSecondLightPosition; + if ( rrProp.Value >>= aExtrusionSecondLightPosition ) + { + AddOpt( DFF_Prop_c3DFillX, (sal_Int32)aExtrusionSecondLightPosition.DirectionX ); + AddOpt( DFF_Prop_c3DFillY, (sal_Int32)aExtrusionSecondLightPosition.DirectionY ); + AddOpt( DFF_Prop_c3DFillZ, (sal_Int32)aExtrusionSecondLightPosition.DirectionZ ); + } + } + else if ( rrProp.Name.equals( sExtrusionMetal ) ) + { + sal_Bool bExtrusionMetal = sal_Bool(); + if ( rrProp.Value >>= bExtrusionMetal ) + { + nLightFaceFlags |= 0x40000; + if ( bExtrusionMetal ) + nLightFaceFlags |= 4; + else + nLightFaceFlags &=~4; + } + } + else if ( rrProp.Name.equals( sExtrusionShadeMode ) ) + { + drawing::ShadeMode eExtrusionShadeMode; + if ( rrProp.Value >>= eExtrusionShadeMode ) + { + sal_uInt32 nRenderMode; + switch( eExtrusionShadeMode ) + { + default: + case drawing::ShadeMode_FLAT : + case drawing::ShadeMode_PHONG : + case drawing::ShadeMode_SMOOTH : + nRenderMode = mso_FullRender; + break; + case drawing::ShadeMode_DRAFT : + { + nRenderMode = mso_Wireframe; + } + break; + } + AddOpt( DFF_Prop_c3DRenderMode, nRenderMode ); + } + } + else if ( rrProp.Name.equals( sExtrusionRotateAngle ) ) + { + double fExtrusionAngleX = 0; + double fExtrusionAngleY = 0; + com::sun::star::drawing::EnhancedCustomShapeParameterPair aRotateAnglePair; + if ( ( rrProp.Value >>= aRotateAnglePair ) && ( aRotateAnglePair.First.Value >>= fExtrusionAngleX ) && ( aRotateAnglePair.Second.Value >>= fExtrusionAngleY ) ) + { + fExtrusionAngleX *= 65536; + fExtrusionAngleY *= 65536; + AddOpt( DFF_Prop_c3DXRotationAngle, (sal_Int32)fExtrusionAngleX ); + AddOpt( DFF_Prop_c3DYRotationAngle, (sal_Int32)fExtrusionAngleY ); + } + } + else if ( rrProp.Name.equals( sExtrusionRotationCenter ) ) + { + drawing::Direction3D aExtrusionRotationCenter; + if ( rrProp.Value >>= aExtrusionRotationCenter ) + { + AddOpt( DFF_Prop_c3DRotationCenterX, (sal_Int32)( aExtrusionRotationCenter.DirectionX * 360.0 ) ); + AddOpt( DFF_Prop_c3DRotationCenterY, (sal_Int32)( aExtrusionRotationCenter.DirectionY * 360.0 ) ); + AddOpt( DFF_Prop_c3DRotationCenterZ, (sal_Int32)( aExtrusionRotationCenter.DirectionZ * 360.0 ) ); + nFillHarshFlags &=~8; // don't use AutoRotationCenter; + } + } + else if ( rrProp.Name.equals( sExtrusionShininess ) ) + { + double fExtrusionShininess = 0; + if ( rrProp.Value >>= fExtrusionShininess ) + AddOpt( DFF_Prop_c3DShininess, (sal_Int32)( fExtrusionShininess * 655.36 ) ); + } + else if ( rrProp.Name.equals( sExtrusionSkew ) ) + { + double fSkewAmount = 0; + double fSkewAngle = 0; + com::sun::star::drawing::EnhancedCustomShapeParameterPair aSkewParaPair; + if ( ( rrProp.Value >>= aSkewParaPair ) && ( aSkewParaPair.First.Value >>= fSkewAmount ) && ( aSkewParaPair.Second.Value >>= fSkewAngle ) ) + { + AddOpt( DFF_Prop_c3DSkewAmount, (sal_Int32)fSkewAmount ); + AddOpt( DFF_Prop_c3DSkewAngle, (sal_Int32)( fSkewAngle * 65536 ) ); + } + } + else if ( rrProp.Name.equals( sExtrusionSpecularity ) ) + { + double fExtrusionSpecularity = 0; + if ( rrProp.Value >>= fExtrusionSpecularity ) + AddOpt( DFF_Prop_c3DSpecularAmt, (sal_Int32)( fExtrusionSpecularity * 1333 ) ); + } + else if ( rrProp.Name.equals( sExtrusionProjectionMode ) ) + { + drawing::ProjectionMode eExtrusionProjectionMode; + if ( rrProp.Value >>= eExtrusionProjectionMode ) + { + nFillHarshFlags |= 0x40000; + if ( eExtrusionProjectionMode == drawing::ProjectionMode_PARALLEL ) + nFillHarshFlags |= 4; + else + nFillHarshFlags &=~4; + } + } + else if ( rrProp.Name.equals( sExtrusionViewPoint ) ) + { + drawing::Position3D aExtrusionViewPoint; + if ( rrProp.Value >>= aExtrusionViewPoint ) + { + aExtrusionViewPoint.PositionX *= 360.0; + aExtrusionViewPoint.PositionY *= 360.0; + aExtrusionViewPoint.PositionZ *= 360.0; + AddOpt( DFF_Prop_c3DXViewpoint, (sal_Int32)aExtrusionViewPoint.PositionX ); + AddOpt( DFF_Prop_c3DYViewpoint, (sal_Int32)aExtrusionViewPoint.PositionY ); + AddOpt( DFF_Prop_c3DZViewpoint, (sal_Int32)aExtrusionViewPoint.PositionZ ); + } + } + else if ( rrProp.Name.equals( sExtrusionOrigin ) ) + { + double fExtrusionOriginX = 0; + double fExtrusionOriginY = 0; + com::sun::star::drawing::EnhancedCustomShapeParameterPair aOriginPair; + if ( ( rrProp.Value >>= aOriginPair ) && ( aOriginPair.First.Value >>= fExtrusionOriginX ) && ( aOriginPair.Second.Value >>= fExtrusionOriginY ) ) + { + AddOpt( DFF_Prop_c3DOriginX, (sal_Int32)( fExtrusionOriginX * 65536 ) ); + AddOpt( DFF_Prop_c3DOriginY, (sal_Int32)( fExtrusionOriginY * 65536 ) ); + } + } + else if ( rrProp.Name.equals( sExtrusionColor ) ) + { + sal_Bool bExtrusionColor = sal_Bool(); + if ( rrProp.Value >>= bExtrusionColor ) + { + nLightFaceFlags |= 0x20000; + if ( bExtrusionColor ) + { + nLightFaceFlags |= 2; + uno::Any aFillColor2; + if ( EscherPropertyValueHelper::GetPropertyValue( aFillColor2, aXPropSet, + String( RTL_CONSTASCII_USTRINGPARAM( "FillColor2" ) ), sal_True ) ) + { + sal_uInt32 nFillColor = ImplGetColor( *((sal_uInt32*)aFillColor2.getValue()) ); + AddOpt( DFF_Prop_c3DExtrusionColor, nFillColor ); + } + } + else + nLightFaceFlags &=~2; + } + } + } + if ( nLightFaceFlags != nLightFaceFlagsOrg ) + AddOpt( DFF_Prop_fc3DLightFace, nLightFaceFlags ); + if ( nFillHarshFlags != nFillHarshFlagsOrg ) + AddOpt( DFF_Prop_fc3DFillHarsh, nFillHarshFlags ); + } + } + else if ( rProp.Name.equals( sEquations ) ) + { + if ( !bIsDefaultObject ) + { + sal_uInt16 nElements = (sal_uInt16)aEquations.size(); + if ( nElements ) + { + sal_uInt16 nElementSize = 8; + sal_uInt32 nStreamSize = nElementSize * nElements + 6; + SvMemoryStream aOut( nStreamSize ); + aOut << nElements + << nElements + << nElementSize; + + std::vector< EnhancedCustomShapeEquation >::const_iterator aIter( aEquations.begin() ); + std::vector< EnhancedCustomShapeEquation >::const_iterator aEnd ( aEquations.end() ); + while( aIter != aEnd ) + { + aOut << (sal_uInt16)aIter->nOperation + << (sal_Int16)aIter->nPara[ 0 ] + << (sal_Int16)aIter->nPara[ 1 ] + << (sal_Int16)aIter->nPara[ 2 ]; + aIter++; + } + sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ]; + memcpy( pBuf, aOut.GetData(), nStreamSize ); + AddOpt( DFF_Prop_pFormulas, sal_True, nStreamSize - 6, pBuf, nStreamSize ); + } + else + { + sal_uInt8* pBuf = new sal_uInt8[ 1 ]; + AddOpt( DFF_Prop_pFormulas, sal_True, 0, pBuf, 0 ); + } + } + } + else if ( rProp.Name.equals( sPath ) ) + { + uno::Sequence< beans::PropertyValue > aPathPropSeq; + if ( rProp.Value >>= aPathPropSeq ) + { + sal_uInt32 nPathFlags, nPathFlagsOrg; + nPathFlagsOrg = nPathFlags = 0x39; + if ( GetOpt( DFF_Prop_fFillOK, nPathFlags ) ) + nPathFlagsOrg = nPathFlags; + + sal_Int32 r, nrCount = aPathPropSeq.getLength(); + for ( r = 0; r < nrCount; r++ ) + { + const beans::PropertyValue& rrProp = aPathPropSeq[ r ]; + const rtl::OUString sPathExtrusionAllowed ( RTL_CONSTASCII_USTRINGPARAM( "ExtrusionAllowed" ) ); + const rtl::OUString sPathConcentricGradientFillAllowed ( RTL_CONSTASCII_USTRINGPARAM( "ConcentricGradientFillAllowed" ) ); + const rtl::OUString sPathTextPathAllowed ( RTL_CONSTASCII_USTRINGPARAM( "TextPathAllowed" ) ); + const rtl::OUString sPathCoordinates ( RTL_CONSTASCII_USTRINGPARAM( "Coordinates" ) ); + const rtl::OUString sPathGluePoints ( RTL_CONSTASCII_USTRINGPARAM( "GluePoints" ) ); + const rtl::OUString sPathGluePointType ( RTL_CONSTASCII_USTRINGPARAM( "GluePointType" ) ); + const rtl::OUString sPathSegments ( RTL_CONSTASCII_USTRINGPARAM( "Segments" ) ); + const rtl::OUString sPathStretchX ( RTL_CONSTASCII_USTRINGPARAM( "StretchX" ) ); + const rtl::OUString sPathStretchY ( RTL_CONSTASCII_USTRINGPARAM( "StretchY" ) ); + const rtl::OUString sPathTextFrames ( RTL_CONSTASCII_USTRINGPARAM( "TextFrames" ) ); + + if ( rrProp.Name.equals( sPathExtrusionAllowed ) ) + { + sal_Bool bExtrusionAllowed = sal_Bool(); + if ( rrProp.Value >>= bExtrusionAllowed ) + { + nPathFlags |= 0x100000; + if ( bExtrusionAllowed ) + nPathFlags |= 16; + else + nPathFlags &=~16; + } + } + else if ( rrProp.Name.equals( sPathConcentricGradientFillAllowed ) ) + { + sal_Bool bConcentricGradientFillAllowed = sal_Bool(); + if ( rrProp.Value >>= bConcentricGradientFillAllowed ) + { + nPathFlags |= 0x20000; + if ( bConcentricGradientFillAllowed ) + nPathFlags |= 2; + else + nPathFlags &=~2; + } + } + else if ( rrProp.Name.equals( sPathTextPathAllowed ) ) + { + sal_Bool bTextPathAllowed = sal_Bool(); + if ( rrProp.Value >>= bTextPathAllowed ) + { + nPathFlags |= 0x40000; + if ( bTextPathAllowed ) + nPathFlags |= 4; + else + nPathFlags &=~4; + } + } + else if ( rrProp.Name.equals( sPathCoordinates ) ) + { + if ( !bIsDefaultObject ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair > aCoordinates; + if ( rrProp.Value >>= aCoordinates ) + { + // creating the vertices + if ( (sal_uInt16)aCoordinates.getLength() ) + { + sal_uInt16 j, nElements = (sal_uInt16)aCoordinates.getLength(); + sal_uInt16 nElementSize = 8; + sal_uInt32 nStreamSize = nElementSize * nElements + 6; + SvMemoryStream aOut( nStreamSize ); + aOut << nElements + << nElements + << nElementSize; + for( j = 0; j < nElements; j++ ) + { + sal_Int32 X = GetValueForEnhancedCustomShapeParameter( aCoordinates[ j ].First, aEquationOrder ); + sal_Int32 Y = GetValueForEnhancedCustomShapeParameter( aCoordinates[ j ].Second, aEquationOrder ); + aOut << X + << Y; + } + sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ]; + memcpy( pBuf, aOut.GetData(), nStreamSize ); + AddOpt( DFF_Prop_pVertices, sal_True, nStreamSize - 6, pBuf, nStreamSize ); // -6 + } + else + { + sal_uInt8* pBuf = new sal_uInt8[ 1 ]; + AddOpt( DFF_Prop_pVertices, sal_True, 0, pBuf, 0 ); + } + } + } + } + else if ( rrProp.Name.equals( sPathGluePoints ) ) + { + if ( !bIsDefaultObject ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> aGluePoints; + if ( rrProp.Value >>= aGluePoints ) + { + // creating the vertices + sal_uInt16 nElements = (sal_uInt16)aGluePoints.getLength(); + if ( nElements ) + { + sal_uInt16 j, nElementSize = 8; + sal_uInt32 nStreamSize = nElementSize * nElements + 6; + SvMemoryStream aOut( nStreamSize ); + aOut << nElements + << nElements + << nElementSize; + for( j = 0; j < nElements; j++ ) + { + sal_Int32 X = GetValueForEnhancedCustomShapeParameter( aGluePoints[ j ].First, aEquationOrder ); + sal_Int32 Y = GetValueForEnhancedCustomShapeParameter( aGluePoints[ j ].Second, aEquationOrder ); + aOut << X + << Y; + } + sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ]; + memcpy( pBuf, aOut.GetData(), nStreamSize ); + AddOpt( DFF_Prop_connectorPoints, sal_True, nStreamSize - 6, pBuf, nStreamSize ); // -6 + } + else + { + sal_uInt8* pBuf = new sal_uInt8[ 1 ]; + AddOpt( DFF_Prop_connectorPoints, sal_True, 0, pBuf, 0 ); + } + } + } + } + else if ( rrProp.Name.equals( sPathGluePointType ) ) + { + sal_Int16 nGluePointType = sal_Int16(); + if ( rrProp.Value >>= nGluePointType ) + AddOpt( DFF_Prop_connectorType, (sal_uInt16)nGluePointType ); + } + else if ( rrProp.Name.equals( sPathSegments ) ) + { + if ( !bIsDefaultObject ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment > aSegments; + if ( rrProp.Value >>= aSegments ) + { + // creating seginfo + if ( (sal_uInt16)aSegments.getLength() ) + { + sal_uInt16 j, nElements = (sal_uInt16)aSegments.getLength(); + sal_uInt16 nElementSize = 2; + sal_uInt32 nStreamSize = nElementSize * nElements + 6; + SvMemoryStream aOut( nStreamSize ); + aOut << nElements + << nElements + << nElementSize; + for ( j = 0; j < nElements; j++ ) + { + sal_uInt16 nVal = (sal_uInt16)aSegments[ j ].Count; + switch( aSegments[ j ].Command ) + { + case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::UNKNOWN : + case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::LINETO : break; + case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::MOVETO : + { + nVal = 0x4000; + } + break; + case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CURVETO : + { + nVal |= 0x2000; + } + break; + case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH : + { + nVal = 0x6001; + } + break; + case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH : + { + nVal = 0x8000; + } + break; + case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::NOFILL : + { + nVal = 0xaa00; + } + break; + case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::NOSTROKE : + { + nVal = 0xab00; + } + break; + case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO : + { + nVal *= 3; + nVal |= 0xa100; + } + break; + case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE : + { + nVal *= 3; + nVal |= 0xa200; + } + break; + case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ARCTO : + { + nVal <<= 2; + nVal |= 0xa300; + } + break; + case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ARC : + { + nVal <<= 2; + nVal |= 0xa400; + } + break; + case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO : + { + nVal <<= 2; + nVal |= 0xa500; + } + break; + case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC : + { + nVal <<= 2; + nVal |= 0xa600; + } + break; + case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX : + { + nVal |= 0xa700; + } + break; + case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY : + { + nVal |= 0xa800; + } + break; + } + aOut << nVal; + } + sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ]; + memcpy( pBuf, aOut.GetData(), nStreamSize ); + AddOpt( DFF_Prop_pSegmentInfo, sal_False, nStreamSize - 6, pBuf, nStreamSize ); + } + else + { + sal_uInt8* pBuf = new sal_uInt8[ 1 ]; + AddOpt( DFF_Prop_pSegmentInfo, sal_True, 0, pBuf, 0 ); + } + } + } + } + else if ( rrProp.Name.equals( sPathStretchX ) ) + { + if ( !bIsDefaultObject ) + { + sal_Int32 nStretchX = 0; + if ( rrProp.Value >>= nStretchX ) + AddOpt( DFF_Prop_stretchPointX, nStretchX ); + } + } + else if ( rrProp.Name.equals( sPathStretchY ) ) + { + if ( !bIsDefaultObject ) + { + sal_Int32 nStretchY = 0; + if ( rrProp.Value >>= nStretchY ) + AddOpt( DFF_Prop_stretchPointY, nStretchY ); + } + } + else if ( rrProp.Name.equals( sPathTextFrames ) ) + { + if ( !bIsDefaultObject ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame > aPathTextFrames; + if ( rrProp.Value >>= aPathTextFrames ) + { + if ( (sal_uInt16)aPathTextFrames.getLength() ) + { + sal_uInt16 j, nElements = (sal_uInt16)aPathTextFrames.getLength(); + sal_uInt16 nElementSize = 16; + sal_uInt32 nStreamSize = nElementSize * nElements + 6; + SvMemoryStream aOut( nStreamSize ); + aOut << nElements + << nElements + << nElementSize; + for ( j = 0; j < nElements; j++ ) + { + sal_Int32 nLeft = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].TopLeft.First, aEquationOrder ); + sal_Int32 nTop = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].TopLeft.Second, aEquationOrder ); + sal_Int32 nRight = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].BottomRight.First, aEquationOrder ); + sal_Int32 nBottom = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].BottomRight.Second, aEquationOrder ); + + aOut << nLeft + << nTop + << nRight + << nBottom; + } + sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ]; + memcpy( pBuf, aOut.GetData(), nStreamSize ); + AddOpt( DFF_Prop_textRectangles, sal_True, nStreamSize - 6, pBuf, nStreamSize ); + } + else + { + sal_uInt8* pBuf = new sal_uInt8[ 1 ]; + AddOpt( DFF_Prop_textRectangles, sal_True, 0, pBuf, 0 ); + } + } + } + } + } + if ( nPathFlags != nPathFlagsOrg ) + AddOpt( DFF_Prop_fFillOK, nPathFlags ); + } + } + else if ( rProp.Name.equals( sTextPath ) ) + { + uno::Sequence< beans::PropertyValue > aTextPathPropSeq; + if ( rProp.Value >>= aTextPathPropSeq ) + { + sal_uInt32 nTextPathFlagsOrg, nTextPathFlags; + nTextPathFlagsOrg = nTextPathFlags = 0xffff1000; // default + if ( GetOpt( DFF_Prop_gtextFStrikethrough, nTextPathFlags ) ) + nTextPathFlagsOrg = nTextPathFlags; + + sal_Int32 r, nrCount = aTextPathPropSeq.getLength(); + for ( r = 0; r < nrCount; r++ ) + { + const beans::PropertyValue& rrProp = aTextPathPropSeq[ r ]; + const rtl::OUString sTextPathMode ( RTL_CONSTASCII_USTRINGPARAM( "TextPathMode" ) ); + const rtl::OUString sTextPathScaleX ( RTL_CONSTASCII_USTRINGPARAM( "ScaleX" ) ); + const rtl::OUString sSameLetterHeights ( RTL_CONSTASCII_USTRINGPARAM( "SameLetterHeights" ) ); + + if ( rrProp.Name.equals( sTextPath ) ) + { + sal_Bool bTextPathOn = sal_Bool(); + if ( rrProp.Value >>= bTextPathOn ) + { + nTextPathFlags |= 0x40000000; + if ( bTextPathOn ) + { + nTextPathFlags |= 0x4000; + + sal_uInt32 nPathFlags = 0x39; + GetOpt( DFF_Prop_fFillOK, nPathFlags ); // SJ: can be removed if we are supporting the TextPathAllowed property in XML + nPathFlags |= 0x40004; + AddOpt( DFF_Prop_fFillOK, nPathFlags ); + } + else + nTextPathFlags &=~0x4000; + } + } + else if ( rrProp.Name.equals( sTextPathMode ) ) + { + com::sun::star::drawing::EnhancedCustomShapeTextPathMode eTextPathMode; + if ( rrProp.Value >>= eTextPathMode ) + { + nTextPathFlags |= 0x05000000; + nTextPathFlags &=~0x500; // TextPathMode_NORMAL + if ( eTextPathMode == com::sun::star::drawing::EnhancedCustomShapeTextPathMode_PATH ) + nTextPathFlags |= 0x100; + else if ( eTextPathMode == com::sun::star::drawing::EnhancedCustomShapeTextPathMode_SHAPE ) + nTextPathFlags |= 0x500; + } + } + else if ( rrProp.Name.equals( sTextPathScaleX ) ) + { + sal_Bool bTextPathScaleX = sal_Bool(); + if ( rrProp.Value >>= bTextPathScaleX ) + { + nTextPathFlags |= 0x00400000; + if ( bTextPathScaleX ) + nTextPathFlags |= 0x40; + else + nTextPathFlags &=~0x40; + } + } + else if ( rrProp.Name.equals( sSameLetterHeights ) ) + { + sal_Bool bSameLetterHeights = sal_Bool(); + if ( rrProp.Value >>= bSameLetterHeights ) + { + nTextPathFlags |= 0x00800000; + if ( bSameLetterHeights ) + nTextPathFlags |= 0x80; + else + nTextPathFlags &=~0x80; + } + } + } + if ( nTextPathFlags & 0x4000 ) // Is FontWork ? + { + // FontWork Text + rtl::OUString aText; + uno::Reference< text::XSimpleText > xText( rXShape, uno::UNO_QUERY ); + if ( xText.is() ) + aText = xText->getString(); + if ( !aText.getLength() ) + aText = ::rtl::OUString::createFromAscii( "your text" ); // todo: moving into a resource + AddOpt( DFF_Prop_gtextUNICODE, aText ); + + // FontWork Font + rtl::OUString aFontName; + const rtl::OUString sCharFontName ( RTL_CONSTASCII_USTRINGPARAM( "CharFontName" ) ); + uno::Any aAny = aXPropSet->getPropertyValue( sCharFontName ); + aAny >>= aFontName; + if ( !aFontName.getLength() ) + aFontName = ::rtl::OUString::createFromAscii( "Arial Black" ); + AddOpt( DFF_Prop_gtextFont, aFontName ); + + sal_Int16 nCharScaleWidth = 100; + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharScaleWidth" ) ), sal_True ) ) + { + if ( aAny >>= nCharScaleWidth ) + { + if ( nCharScaleWidth != 100 ) + { + sal_Int32 nVal = nCharScaleWidth * 655; + AddOpt( DFF_Prop_gtextSpacing, nVal ); + } + } + } + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharKerning" ) ), sal_True ) ) + { + sal_Int16 nCharKerning = sal_Int16(); + if ( aAny >>= nCharKerning ) + { + nTextPathFlags |= 0x10000000; + if ( nCharKerning ) + nTextPathFlags |= 0x1000; + else + nTextPathFlags &=~0x1000; + } + } + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharPosture" ) ), sal_True ) ) + { + awt::FontSlant eFontSlant; + if ( aAny >>= eFontSlant ) + { + nTextPathFlags |= 0x100010; + if ( eFontSlant != awt::FontSlant_NONE ) + nTextPathFlags |= 0x10; + else + nTextPathFlags &=~0x10; + } + } + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharWeight" ) ), sal_True ) ) + { + float fFontWidth = 0; + if ( aAny >>= fFontWidth ) + { + nTextPathFlags |= 0x200020; + if ( fFontWidth > awt::FontWeight::NORMAL ) + nTextPathFlags |= 0x20; + else + nTextPathFlags &=~0x20; + } + } + } + if ( nTextPathFlags != nTextPathFlagsOrg ) + AddOpt( DFF_Prop_gtextFStrikethrough, nTextPathFlags ); + } + } + else if ( rProp.Name.equals( sHandles ) ) + { + if ( !bIsDefaultObject ) + { + bPredefinedHandlesUsed = sal_False; + if ( rProp.Value >>= aHandlesPropSeq ) + { + sal_uInt16 nElements = (sal_uInt16)aHandlesPropSeq.getLength(); + if ( nElements ) + { + const rtl::OUString sHandle ( RTL_CONSTASCII_USTRINGPARAM( "Handle" ) ); + + sal_uInt16 k, j, nElementSize = 36; + sal_uInt32 nStreamSize = nElementSize * nElements + 6; + SvMemoryStream aOut( nStreamSize ); + aOut << nElements + << nElements + << nElementSize; + + for ( k = 0; k < nElements; k++ ) + { + sal_uInt32 nFlags = 0; + sal_Int32 nXPosition = 0; + sal_Int32 nYPosition = 0; + sal_Int32 nXMap = 0; + sal_Int32 nYMap = 0; + sal_Int32 nXRangeMin = 0x80000000; + sal_Int32 nXRangeMax = 0x7fffffff; + sal_Int32 nYRangeMin = 0x80000000; + sal_Int32 nYRangeMax = 0x7fffffff; + + const uno::Sequence< beans::PropertyValue >& rPropSeq = aHandlesPropSeq[ k ]; + for ( j = 0; j < rPropSeq.getLength(); j++ ) + { + const beans::PropertyValue& rPropVal = rPropSeq[ j ]; + + const rtl::OUString sPosition ( RTL_CONSTASCII_USTRINGPARAM( "Position" ) ); + const rtl::OUString sMirroredX ( RTL_CONSTASCII_USTRINGPARAM( "MirroredX" ) ); + const rtl::OUString sMirroredY ( RTL_CONSTASCII_USTRINGPARAM( "MirroredY" ) ); + const rtl::OUString sSwitched ( RTL_CONSTASCII_USTRINGPARAM( "Switched" ) ); + const rtl::OUString sPolar ( RTL_CONSTASCII_USTRINGPARAM( "Polar" ) ); + // const rtl::OUString sMap ( RTL_CONSTASCII_USTRINGPARAM( "Map" ) ); + const rtl::OUString sRadiusRangeMinimum ( RTL_CONSTASCII_USTRINGPARAM( "RadiusRangeMinimum" ) ); + const rtl::OUString sRadiusRangeMaximum ( RTL_CONSTASCII_USTRINGPARAM( "RadiusRangeMaximum" ) ); + const rtl::OUString sRangeXMinimum ( RTL_CONSTASCII_USTRINGPARAM( "RangeXMinimum" ) ); + const rtl::OUString sRangeXMaximum ( RTL_CONSTASCII_USTRINGPARAM( "RangeXMaximum" ) ); + const rtl::OUString sRangeYMinimum ( RTL_CONSTASCII_USTRINGPARAM( "RangeYMinimum" ) ); + const rtl::OUString sRangeYMaximum ( RTL_CONSTASCII_USTRINGPARAM( "RangeYMaximum" ) ); + + if ( rPropVal.Name.equals( sPosition ) ) + { + com::sun::star::drawing::EnhancedCustomShapeParameterPair aPosition; + if ( rPropVal.Value >>= aPosition ) + { + GetValueForEnhancedCustomShapeHandleParameter( nXPosition, aPosition.First ); + GetValueForEnhancedCustomShapeHandleParameter( nYPosition, aPosition.Second ); + } + } + else if ( rPropVal.Name.equals( sMirroredX ) ) + { + sal_Bool bMirroredX = sal_Bool(); + if ( rPropVal.Value >>= bMirroredX ) + { + if ( bMirroredX ) + nFlags |= 1; + } + } + else if ( rPropVal.Name.equals( sMirroredY ) ) + { + sal_Bool bMirroredY = sal_Bool(); + if ( rPropVal.Value >>= bMirroredY ) + { + if ( bMirroredY ) + nFlags |= 2; + } + } + else if ( rPropVal.Name.equals( sSwitched ) ) + { + sal_Bool bSwitched = sal_Bool(); + if ( rPropVal.Value >>= bSwitched ) + { + if ( bSwitched ) + nFlags |= 4; + } + } + else if ( rPropVal.Name.equals( sPolar ) ) + { + com::sun::star::drawing::EnhancedCustomShapeParameterPair aPolar; + if ( rPropVal.Value >>= aPolar ) + { + if ( GetValueForEnhancedCustomShapeHandleParameter( nXMap, aPolar.First ) ) + nFlags |= 0x800; + if ( GetValueForEnhancedCustomShapeHandleParameter( nYMap, aPolar.Second ) ) + nFlags |= 0x1000; + nFlags |= 8; + } + } + /* seems not to be used. + else if ( rPropVal.Name.equals( sMap ) ) + { + com::sun::star::drawing::EnhancedCustomShapeParameterPair aMap; + if ( rPropVal.Value >>= aMap ) + { + if ( GetValueForEnhancedCustomShapeHandleParameter( nXMap, aMap.First ) ) + nFlags |= 0x800; + if ( GetValueForEnhancedCustomShapeHandleParameter( nYMap, aMap.Second ) ) + nFlags |= 0x1000; + nFlags |= 0x10; + } + } + */ + else if ( rPropVal.Name.equals( sRadiusRangeMinimum ) ) + { + nYRangeMin = (sal_Int32)0xff4c0000; // the range of angles seems to be a not + nYRangeMax = (sal_Int32)0x00b40000; // used feature, so we are defaulting this + + com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMinimum; + if ( rPropVal.Value >>= aRadiusRangeMinimum ) + { + if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMin, aRadiusRangeMinimum ) ) + nFlags |= 0x80; + nFlags |= 0x2000; + } + } + else if ( rPropVal.Name.equals( sRadiusRangeMaximum ) ) + { + nYRangeMin = (sal_Int32)0xff4c0000; // the range of angles seems to be a not + nYRangeMax = (sal_Int32)0x00b40000; // used feature, so we are defaulting this + + com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMaximum; + if ( rPropVal.Value >>= aRadiusRangeMaximum ) + { + if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMax, aRadiusRangeMaximum ) ) + nFlags |= 0x100; + nFlags |= 0x2000; + } + } + else if ( rPropVal.Name.equals( sRangeXMinimum ) ) + { + com::sun::star::drawing::EnhancedCustomShapeParameter aXRangeMinimum; + if ( rPropVal.Value >>= aXRangeMinimum ) + { + if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMin, aXRangeMinimum ) ) + nFlags |= 0x80; + nFlags |= 0x20; + } + } + else if ( rPropVal.Name.equals( sRangeXMaximum ) ) + { + com::sun::star::drawing::EnhancedCustomShapeParameter aXRangeMaximum; + if ( rPropVal.Value >>= aXRangeMaximum ) + { + if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMax, aXRangeMaximum ) ) + nFlags |= 0x100; + nFlags |= 0x20; + } + } + else if ( rPropVal.Name.equals( sRangeYMinimum ) ) + { + com::sun::star::drawing::EnhancedCustomShapeParameter aYRangeMinimum; + if ( rPropVal.Value >>= aYRangeMinimum ) + { + if ( GetValueForEnhancedCustomShapeHandleParameter( nYRangeMin, aYRangeMinimum ) ) + nFlags |= 0x200; + nFlags |= 0x20; + } + } + else if ( rPropVal.Name.equals( sRangeYMaximum ) ) + { + com::sun::star::drawing::EnhancedCustomShapeParameter aYRangeMaximum; + if ( rPropVal.Value >>= aYRangeMaximum ) + { + if ( GetValueForEnhancedCustomShapeHandleParameter( nYRangeMax, aYRangeMaximum ) ) + nFlags |= 0x400; + nFlags |= 0x20; + } + } + } + aOut << nFlags + << nXPosition + << nYPosition + << nXMap + << nYMap + << nXRangeMin + << nXRangeMax + << nYRangeMin + << nYRangeMax; + + if ( nFlags & 8 ) + nAdjustmentsWhichNeedsToBeConverted |= ( 1 << ( nYPosition - 0x100 ) ); + } + sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ]; + memcpy( pBuf, aOut.GetData(), nStreamSize ); + AddOpt( DFF_Prop_Handles, sal_True, nStreamSize - 6, pBuf, nStreamSize ); + } + else + { + sal_uInt8* pBuf = new sal_uInt8[ 1 ]; + AddOpt( DFF_Prop_Handles, sal_True, 0, pBuf, 0 ); + } + } + } + } + else if ( rProp.Name.equals( sAdjustmentValues ) ) + { + // it is required, that the information which handle is polar has already be read, + // so we are able to change the polar value to a fixed float + pAdjustmentValuesProp = &rProp; + } + } + if ( pAdjustmentValuesProp ) + { + uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq; + if ( pAdjustmentValuesProp->Value >>= aAdjustmentSeq ) + { + if ( bPredefinedHandlesUsed ) + LookForPolarHandles( eShapeType, nAdjustmentsWhichNeedsToBeConverted ); + + sal_Int32 k, nValue = 0, nAdjustmentValues = aAdjustmentSeq.getLength(); + for ( k = 0; k < nAdjustmentValues; k++ ) + if( GetAdjustmentValue( aAdjustmentSeq[ k ], k, nAdjustmentsWhichNeedsToBeConverted, nValue ) ) + AddOpt( (sal_uInt16)( DFF_Prop_adjustValue + k ), (sal_uInt32)nValue ); + } + } + } + } +} + +// --------------------------------------------------------------------------------------------- + +MSO_SPT EscherPropertyContainer::GetCustomShapeType( const uno::Reference< drawing::XShape > & rXShape, sal_uInt32& nMirrorFlags, rtl::OUString& rShapeType ) +{ + MSO_SPT eShapeType = mso_sptNil; + nMirrorFlags = 0; + uno::Reference< beans::XPropertySet > aXPropSet( rXShape, uno::UNO_QUERY ); + if ( aXPropSet.is() ) + { + try + { + const OUString sCustomShapeGeometry( RTL_CONSTASCII_USTRINGPARAM ( "CustomShapeGeometry" ) ); + uno::Any aGeoPropSet = aXPropSet->getPropertyValue( sCustomShapeGeometry ); + uno::Sequence< beans::PropertyValue > aGeoPropSeq; + if ( aGeoPropSet >>= aGeoPropSeq ) + { + sal_Int32 i, nCount = aGeoPropSeq.getLength(); + for ( i = 0; i < nCount; i++ ) + { + const beans::PropertyValue& rProp = aGeoPropSeq[ i ]; + if ( rProp.Name.equalsAscii( "Type" ) ) + { + if ( rProp.Value >>= rShapeType ) + eShapeType = EnhancedCustomShapeTypeNames::Get( rShapeType ); + } + else if ( rProp.Name.equalsAscii( "MirroredX" ) ) + { + sal_Bool bMirroredX = sal_Bool(); + if ( ( rProp.Value >>= bMirroredX ) && bMirroredX ) + nMirrorFlags |= SHAPEFLAG_FLIPH; + } + else if ( rProp.Name.equalsAscii( "MirroredY" ) ) + { + sal_Bool bMirroredY = sal_Bool(); + if ( ( rProp.Value >>= bMirroredY ) && bMirroredY ) + nMirrorFlags |= SHAPEFLAG_FLIPV; + } + } + } + } + catch( ::com::sun::star::uno::Exception& ) + { + } + } + return eShapeType; +} + +MSO_SPT EscherPropertyContainer::GetCustomShapeType( const uno::Reference< drawing::XShape > & rXShape, sal_uInt32& nMirrorFlags ) +{ + rtl::OUString aShapeType; + return GetCustomShapeType( rXShape, nMirrorFlags, aShapeType ); +} + +// --------------------------------------------------------------------------------------------- + +EscherPersistTable::EscherPersistTable() +{ +} + +// --------------------------------------------------------------------------------------------- + +EscherPersistTable::~EscherPersistTable() +{ + for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() ) + delete (EscherPersistEntry*)pPtr; +} + +// --------------------------------------------------------------------------------------------- + +sal_Bool EscherPersistTable::PtIsID( sal_uInt32 nID ) +{ + for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() ) + { + if ( ((EscherPersistEntry*)pPtr)->mnID == nID ) + return sal_True; + } + return sal_False; +} + +// --------------------------------------------------------------------------------------------- + +void EscherPersistTable::PtInsert( sal_uInt32 nID, sal_uInt32 nOfs ) +{ + maPersistTable.Insert( new EscherPersistEntry( nID, nOfs ) ); +} + +// --------------------------------------------------------------------------------------------- + +sal_uInt32 EscherPersistTable::PtDelete( sal_uInt32 nID ) +{ + for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() ) + { + if ( ((EscherPersistEntry*)pPtr)->mnID == nID ) + { +// sal_uInt32 nRetValue = ((EscherPersistEntry*)pPtr)->mnOffset; + delete (EscherPersistEntry*) maPersistTable.Remove(); + } + } + return 0; +} + +// --------------------------------------------------------------------------------------------- + +sal_uInt32 EscherPersistTable::PtGetOffsetByID( sal_uInt32 nID ) +{ + for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() ) + { + if ( ((EscherPersistEntry*)pPtr)->mnID == nID ) + return ((EscherPersistEntry*)pPtr)->mnOffset; + } + return 0; +}; + +// --------------------------------------------------------------------------------------------- + +sal_uInt32 EscherPersistTable::PtReplace( sal_uInt32 nID, sal_uInt32 nOfs ) +{ + for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() ) + { + if ( ((EscherPersistEntry*)pPtr)->mnID == nID ) + { + sal_uInt32 nRetValue = ((EscherPersistEntry*)pPtr)->mnOffset; + ((EscherPersistEntry*)pPtr)->mnOffset = nOfs; + return nRetValue; + } + } + return 0; +} + +// --------------------------------------------------------------------------------------------- + +sal_uInt32 EscherPersistTable::PtReplaceOrInsert( sal_uInt32 nID, sal_uInt32 nOfs ) +{ + for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() ) + { + if ( ((EscherPersistEntry*)pPtr)->mnID == nID ) + { + sal_uInt32 nRetValue = ((EscherPersistEntry*)pPtr)->mnOffset; + ((EscherPersistEntry*)pPtr)->mnOffset = nOfs; + return nRetValue; + } + } + PtInsert( nID, nOfs ); + return 0; +} + +sal_Bool EscherPropertyValueHelper::GetPropertyValue( + ::com::sun::star::uno::Any& rAny, + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet, + const String& rString, + sal_Bool bTestPropertyAvailability ) +{ + sal_Bool bRetValue = sal_True; + if ( bTestPropertyAvailability ) + { + bRetValue = sal_False; + try + { + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > + aXPropSetInfo( rXPropSet->getPropertySetInfo() ); + if ( aXPropSetInfo.is() ) + bRetValue = aXPropSetInfo->hasPropertyByName( rString ); + } + catch( ::com::sun::star::uno::Exception& ) + { + bRetValue = sal_False; + } + } + if ( bRetValue ) + { + try + { + rAny = rXPropSet->getPropertyValue( rString ); + if ( !rAny.hasValue() ) + bRetValue = sal_False; + } + catch( ::com::sun::star::uno::Exception& ) + { + bRetValue = sal_False; + } + } + return bRetValue; +} + +// --------------------------------------------------------------------------------------------- + +::com::sun::star::beans::PropertyState EscherPropertyValueHelper::GetPropertyState( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet, + const String& rPropertyName ) +{ + ::com::sun::star::beans::PropertyState eRetValue = ::com::sun::star::beans::PropertyState_AMBIGUOUS_VALUE; + try + { + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyState > aXPropState + ( rXPropSet, ::com::sun::star::uno::UNO_QUERY ); + if ( aXPropState.is() ) + eRetValue = aXPropState->getPropertyState( rPropertyName ); + } + catch( ::com::sun::star::uno::Exception& ) + { + //... + } + return eRetValue; +} + +// --------------------------------------------------------------------------------------------- +// --------------------------------------------------------------------------------------------- +// --------------------------------------------------------------------------------------------- + +EscherBlibEntry::EscherBlibEntry( sal_uInt32 nPictureOffset, const GraphicObject& rObject, const ByteString& rId, + const GraphicAttr* pGraphicAttr ) : + mnPictureOffset ( nPictureOffset ), + mnRefCount ( 1 ), + mnSizeExtra ( 0 ), + maPrefSize ( rObject.GetPrefSize() ), + maPrefMapMode ( rObject.GetPrefMapMode() ), + mbIsEmpty ( sal_True ) +{ + mbIsNativeGraphicPossible = ( pGraphicAttr == NULL ); + meBlibType = UNKNOWN; + mnSize = 0; + + sal_uInt32 nLen = rId.Len(); + const sal_Char* pData = rId.GetBuffer(); + GraphicType eType( rObject.GetType() ); + if ( nLen && pData && ( eType != GRAPHIC_NONE ) ) + { + mnIdentifier[ 0 ] = rtl_crc32( 0,pData, nLen ); + mnIdentifier[ 1 ] = 0; + + if ( pGraphicAttr ) + { + if ( pGraphicAttr->IsSpecialDrawMode() + || pGraphicAttr->IsMirrored() + || pGraphicAttr->IsCropped() + || pGraphicAttr->IsRotated() + || pGraphicAttr->IsTransparent() + || pGraphicAttr->IsAdjusted() ) + { + SvMemoryStream aSt( sizeof( GraphicAttr ) ); + aSt << static_cast<sal_uInt16>(pGraphicAttr->GetDrawMode()) + << static_cast<sal_uInt32>(pGraphicAttr->GetMirrorFlags()) + << pGraphicAttr->GetLeftCrop() + << pGraphicAttr->GetTopCrop() + << pGraphicAttr->GetRightCrop() + << pGraphicAttr->GetBottomCrop() + << pGraphicAttr->GetRotation() + << pGraphicAttr->GetLuminance() + << pGraphicAttr->GetContrast() + << pGraphicAttr->GetChannelR() + << pGraphicAttr->GetChannelG() + << pGraphicAttr->GetChannelB() + << pGraphicAttr->GetGamma() + << (sal_Bool)( pGraphicAttr->IsInvert() == sal_True ) + << pGraphicAttr->GetTransparency(); + mnIdentifier[ 1 ] = rtl_crc32( 0, aSt.GetData(), aSt.Tell() ); + } + else + mbIsNativeGraphicPossible = sal_True; + } + sal_uInt32 i, nTmp, n1, n2; + n1 = n2 = 0; + for ( i = 0; i < nLen; i++ ) + { + nTmp = n2 >> 28; // rotating 4 bit + n2 <<= 4; + n2 |= n1 >> 28; + n1 <<= 4; + n1 |= nTmp; + n1 ^= *pData++ - '0'; + } + mnIdentifier[ 2 ] = n1; + mnIdentifier[ 3 ] = n2; + mbIsEmpty = sal_False; + } +}; + +// --------------------------------------------------------------------------------------------- + +void EscherBlibEntry::WriteBlibEntry( SvStream& rSt, sal_Bool bWritePictureOffset, sal_uInt32 nResize ) +{ + sal_uInt32 nPictureOffset = ( bWritePictureOffset ) ? mnPictureOffset : 0; + + rSt << (sal_uInt32)( ( ESCHER_BSE << 16 ) | ( ( (sal_uInt16)meBlibType << 4 ) | 2 ) ) + << (sal_uInt32)( 36 + nResize ) + << (sal_uInt8)meBlibType; + + switch ( meBlibType ) + { + case EMF : + case WMF : // EMF/WMF auf OS2 zu Pict Konvertieren + rSt << (sal_uInt8)PICT; + break; + default: + rSt << (sal_uInt8)meBlibType; + }; + + rSt.Write( &mnIdentifier[ 0 ], 16 ); + rSt << (sal_uInt16)0 + << (sal_uInt32)( mnSize + mnSizeExtra ) + << mnRefCount + << nPictureOffset + << (sal_uInt32)0; +} + +// --------------------------------------------------------------------------------------------- + +EscherBlibEntry::~EscherBlibEntry() +{ +}; + +// --------------------------------------------------------------------------------------------- + +sal_Bool EscherBlibEntry::operator==( const EscherBlibEntry& rEscherBlibEntry ) const +{ + for ( int i = 0; i < 3; i++ ) + { + if ( mnIdentifier[ i ] != rEscherBlibEntry.mnIdentifier[ i ] ) + return sal_False; + } + return sal_True; +} + +// --------------------------------------------------------------------------------------------- +// --------------------------------------------------------------------------------------------- +// --------------------------------------------------------------------------------------------- + +EscherGraphicProvider::EscherGraphicProvider( sal_uInt32 nFlags ) : + mnFlags ( nFlags ), + mpBlibEntrys ( NULL ), + mnBlibBufSize ( 0 ), + mnBlibEntrys ( 0 ) +{ +} + +EscherGraphicProvider::~EscherGraphicProvider() +{ + for ( sal_uInt32 i = 0; i < mnBlibEntrys; delete mpBlibEntrys[ i++ ] ) ; + delete[] mpBlibEntrys; +} + +void EscherGraphicProvider::SetNewBlipStreamOffset( sal_Int32 nOffset ) +{ + for( sal_uInt32 i = 0; i < mnBlibEntrys; i++ ) + { + EscherBlibEntry* pBlibEntry = mpBlibEntrys[ i ]; + pBlibEntry->mnPictureOffset += nOffset; + } +} + +sal_uInt32 EscherGraphicProvider::ImplInsertBlib( EscherBlibEntry* p_EscherBlibEntry ) +{ + if ( mnBlibBufSize == mnBlibEntrys ) + { + mnBlibBufSize += 64; + EscherBlibEntry** pTemp = new EscherBlibEntry*[ mnBlibBufSize ]; + for ( sal_uInt32 i = 0; i < mnBlibEntrys; i++ ) + { + pTemp[ i ] = mpBlibEntrys[ i ]; + } + delete[] mpBlibEntrys; + mpBlibEntrys = pTemp; + } + mpBlibEntrys[ mnBlibEntrys++ ] = p_EscherBlibEntry; + return mnBlibEntrys; +} + +sal_uInt32 EscherGraphicProvider::GetBlibStoreContainerSize( SvStream* pMergePicStreamBSE ) const +{ + sal_uInt32 nSize = 44 * mnBlibEntrys + 8; + if ( pMergePicStreamBSE ) + { + for ( sal_uInt32 i = 0; i < mnBlibEntrys; i++ ) + nSize += mpBlibEntrys[ i ]->mnSize + mpBlibEntrys[ i ]->mnSizeExtra; + } + return nSize; +} + +sal_Bool EscherGraphicProvider::WriteBlibStoreEntry(SvStream& rSt, + sal_uInt32 nBlipId, sal_Bool bWritePictureOffSet, sal_uInt32 nResize) +{ + if (nBlipId > mnBlibEntrys || nBlipId == 0) + return sal_False; + mpBlibEntrys[nBlipId-1]->WriteBlibEntry(rSt, bWritePictureOffSet, nResize); + return sal_True; +} + +void EscherGraphicProvider::WriteBlibStoreContainer( SvStream& rSt, SvStream* pMergePicStreamBSE ) +{ + sal_uInt32 nSize = GetBlibStoreContainerSize( pMergePicStreamBSE ); + if ( nSize ) + { + rSt << (sal_uInt32)( ( ESCHER_BstoreContainer << 16 ) | 0x1f ) + << (sal_uInt32)( nSize - 8 ); + + if ( pMergePicStreamBSE ) + { + sal_uInt32 i, nBlipSize, nOldPos = pMergePicStreamBSE->Tell(); + const sal_uInt32 nBuf = 0x40000; // 256KB buffer + sal_uInt8* pBuf = new sal_uInt8[ nBuf ]; + + for ( i = 0; i < mnBlibEntrys; i++ ) + { + EscherBlibEntry* pBlibEntry = mpBlibEntrys[ i ]; + + ESCHER_BlibType nBlibType = pBlibEntry->meBlibType; + nBlipSize = pBlibEntry->mnSize + pBlibEntry->mnSizeExtra; + pBlibEntry->WriteBlibEntry( rSt, sal_False, nBlipSize ); + + // BLIP + pMergePicStreamBSE->Seek( pBlibEntry->mnPictureOffset ); + sal_uInt16 n16; + // record version and instance + *pMergePicStreamBSE >> n16; + rSt << n16; + // record type + *pMergePicStreamBSE >> n16; + rSt << sal_uInt16( ESCHER_BlipFirst + nBlibType ); + DBG_ASSERT( n16 == ESCHER_BlipFirst + nBlibType , "EscherGraphicProvider::WriteBlibStoreContainer: BLIP record types differ" ); + sal_uInt32 n32; + // record size + *pMergePicStreamBSE >> n32; + nBlipSize -= 8; + rSt << nBlipSize; + DBG_ASSERT( nBlipSize == n32, "EscherGraphicProvider::WriteBlibStoreContainer: BLIP sizes differ" ); + // record + while ( nBlipSize ) + { + sal_uInt32 nBytes = ( nBlipSize > nBuf ? nBuf : nBlipSize ); + pMergePicStreamBSE->Read( pBuf, nBytes ); + rSt.Write( pBuf, nBytes ); + nBlipSize -= nBytes; + } + } + delete[] pBuf; + pMergePicStreamBSE->Seek( nOldPos ); + } + else + { + for ( sal_uInt32 i = 0; i < mnBlibEntrys; i++ ) + mpBlibEntrys[ i ]->WriteBlibEntry( rSt, sal_True ); + } + } +} + +sal_Bool EscherGraphicProvider::GetPrefSize( const sal_uInt32 nBlibId, Size& rPrefSize, MapMode& rPrefMapMode ) +{ + sal_Bool bInRange = nBlibId && ( ( nBlibId - 1 ) < mnBlibEntrys ); + if ( bInRange ) + { + EscherBlibEntry* pEntry = mpBlibEntrys[ nBlibId - 1 ]; + rPrefSize = pEntry->maPrefSize; + rPrefMapMode = pEntry->maPrefMapMode; + } + return bInRange; +} + +sal_uInt32 EscherGraphicProvider::GetBlibID( SvStream& rPicOutStrm, const ByteString& rId, + const Rectangle& /* rBoundRect */, const com::sun::star::awt::Rectangle* pVisArea, const GraphicAttr* pGraphicAttr ) +{ + sal_uInt32 nBlibId = 0; + GraphicObject aGraphicObject( rId ); + + EscherBlibEntry* p_EscherBlibEntry = new EscherBlibEntry( rPicOutStrm.Tell(), aGraphicObject, rId, pGraphicAttr ); + if ( !p_EscherBlibEntry->IsEmpty() ) + { + for ( sal_uInt32 i = 0; i < mnBlibEntrys; i++ ) + { + if ( *( mpBlibEntrys[ i ] ) == *p_EscherBlibEntry ) + { + mpBlibEntrys[ i ]->mnRefCount++; + delete p_EscherBlibEntry; + return i + 1; + } + } + + sal_Bool bUseNativeGraphic( sal_False ); + + Graphic aGraphic( aGraphicObject.GetTransformedGraphic( pGraphicAttr ) ); + GfxLink aGraphicLink; + SvMemoryStream aStream; + + const sal_uInt8* pGraphicAry = NULL; + + if ( p_EscherBlibEntry->mbIsNativeGraphicPossible && aGraphic.IsLink() ) + { + aGraphicLink = aGraphic.GetLink(); + + p_EscherBlibEntry->mnSize = aGraphicLink.GetDataSize(); + pGraphicAry = aGraphicLink.GetData(); + + if ( p_EscherBlibEntry->mnSize && pGraphicAry ) + { + switch ( aGraphicLink.GetType() ) + { + case GFX_LINK_TYPE_NATIVE_JPG : p_EscherBlibEntry->meBlibType = PEG; break; + case GFX_LINK_TYPE_NATIVE_PNG : p_EscherBlibEntry->meBlibType = PNG; break; + case GFX_LINK_TYPE_NATIVE_WMF : + { + if ( pGraphicAry && ( p_EscherBlibEntry->mnSize > 0x2c ) ) + { + if ( ( pGraphicAry[ 0x28 ] == 0x20 ) && ( pGraphicAry[ 0x29 ] == 0x45 ) // check the magic + && ( pGraphicAry[ 0x2a ] == 0x4d ) && ( pGraphicAry[ 0x2b ] == 0x46 ) ) // number ( emf detection ) + { + p_EscherBlibEntry->meBlibType = EMF; + } + else + { + p_EscherBlibEntry->meBlibType = WMF; + if ( ( pGraphicAry[ 0 ] == 0xd7 ) && ( pGraphicAry[ 1 ] == 0xcd ) + && ( pGraphicAry[ 2 ] == 0xc6 ) && ( pGraphicAry[ 3 ] == 0x9a ) ) + { // we have to get rid of the metafileheader + pGraphicAry += 22; + p_EscherBlibEntry->mnSize -= 22; + } + } + } + } + break; + default: break; + } + if ( p_EscherBlibEntry->meBlibType != UNKNOWN ) + bUseNativeGraphic = sal_True; + } + } + if ( !bUseNativeGraphic ) + { + GraphicType eGraphicType = aGraphic.GetType(); + if ( ( eGraphicType == GRAPHIC_BITMAP ) || ( eGraphicType == GRAPHIC_GDIMETAFILE ) ) + { + sal_uInt32 nErrCode; + if ( !aGraphic.IsAnimated() ) +// !EMF nErrCode = GraphicConverter::Export( aStream, aGraphic, ( eGraphicType == GRAPHIC_BITMAP ) ? CVT_PNG : CVT_WMF ); + nErrCode = GraphicConverter::Export( aStream, aGraphic, ( eGraphicType == GRAPHIC_BITMAP ) ? CVT_PNG : CVT_EMF ); + else + { // to store a animation, a gif has to be included into the msOG chunk of a png #I5583# + GraphicFilter* pFilter = GraphicFilter::GetGraphicFilter(); + SvMemoryStream aGIFStream; + ByteString aVersion( "MSOFFICE9.0" ); + aGIFStream.Write( aVersion.GetBuffer(), aVersion.Len() ); + nErrCode = pFilter->ExportGraphic( aGraphic, String(), aGIFStream, + pFilter->GetExportFormatNumberForShortName( String( RTL_CONSTASCII_USTRINGPARAM( "GIF" ) ) ), NULL ); + com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > aFilterData( 1 ); + com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > aAdditionalChunkSequence( 1 ); + sal_uInt32 nGIFSreamLen = aGIFStream.Tell(); + com::sun::star::uno::Sequence< sal_Int8 > aGIFSeq( nGIFSreamLen ); + sal_Int8* pSeq = aGIFSeq.getArray(); + aGIFStream.Seek( STREAM_SEEK_TO_BEGIN ); + aGIFStream.Read( pSeq, nGIFSreamLen ); + com::sun::star::beans::PropertyValue aChunkProp, aFilterProp; + aChunkProp.Name = String( RTL_CONSTASCII_USTRINGPARAM( "msOG" ) ); + aChunkProp.Value <<= aGIFSeq; + aAdditionalChunkSequence[ 0 ] = aChunkProp; + aFilterProp.Name = String( RTL_CONSTASCII_USTRINGPARAM( "AdditionalChunks" ) ); + aFilterProp.Value <<= aAdditionalChunkSequence; + aFilterData[ 0 ] = aFilterProp; + nErrCode = pFilter->ExportGraphic( aGraphic, String(), aStream, + pFilter->GetExportFormatNumberForShortName( String( RTL_CONSTASCII_USTRINGPARAM( "PNG" ) ) ), &aFilterData ); + } + if ( nErrCode == ERRCODE_NONE ) + { +// !EMF p_EscherBlibEntry->meBlibType = ( eGraphicType == GRAPHIC_BITMAP ) ? PNG : WMF; + p_EscherBlibEntry->meBlibType = ( eGraphicType == GRAPHIC_BITMAP ) ? PNG : EMF; + aStream.Seek( STREAM_SEEK_TO_END ); + p_EscherBlibEntry->mnSize = aStream.Tell(); + pGraphicAry = (sal_uInt8*)aStream.GetData(); + + if ( p_EscherBlibEntry->meBlibType == WMF ) // the fileheader is not used + { + p_EscherBlibEntry->mnSize -= 22; + pGraphicAry += 22; + } + } + } + } + + ESCHER_BlibType eBlibType = p_EscherBlibEntry->meBlibType; + if ( p_EscherBlibEntry->mnSize && pGraphicAry && ( eBlibType != UNKNOWN ) ) + { + sal_uInt32 nExtra, nAtomSize = 0; + sal_uInt32 nInstance, nUncompressedSize = p_EscherBlibEntry->mnSize; + + if ( mnFlags & _E_GRAPH_PROV_USE_INSTANCES ) + { + rPicOutStrm << (sal_uInt32)( 0x7f90000 | (sal_uInt16)( mnBlibEntrys << 4 ) ) + << (sal_uInt32)0; + nAtomSize = rPicOutStrm.Tell(); + if ( eBlibType == PNG ) + rPicOutStrm << (sal_uInt16)0x0606; + else if ( eBlibType == WMF ) + rPicOutStrm << (sal_uInt16)0x0403; + else if ( eBlibType == EMF ) + rPicOutStrm << (sal_uInt16)0x0402; + else if ( eBlibType == PEG ) + rPicOutStrm << (sal_uInt16)0x0505; + } + if ( ( eBlibType == PEG ) || ( eBlibType == PNG ) ) + { + nExtra = 17; + p_EscherBlibEntry->mnSizeExtra = nExtra + 8; + nInstance = ( eBlibType == PNG ) ? 0xf01e6e00 : 0xf01d46a0; + rPicOutStrm << nInstance << (sal_uInt32)( p_EscherBlibEntry->mnSize + nExtra ); + rPicOutStrm.Write( p_EscherBlibEntry->mnIdentifier, 16 ); + rPicOutStrm << (sal_uInt8)0xff; + rPicOutStrm.Write( pGraphicAry, p_EscherBlibEntry->mnSize ); + } + else + { + ZCodec aZCodec( 0x8000, 0x8000 ); + aZCodec.BeginCompression(); + SvMemoryStream aDestStrm; + aZCodec.Write( aDestStrm, pGraphicAry, p_EscherBlibEntry->mnSize ); + aZCodec.EndCompression(); + aDestStrm.Seek( STREAM_SEEK_TO_END ); + p_EscherBlibEntry->mnSize = aDestStrm.Tell(); + pGraphicAry = (sal_uInt8*)aDestStrm.GetData(); + if ( p_EscherBlibEntry->mnSize && pGraphicAry ) + { + nExtra = eBlibType == WMF ? 0x42 : 0x32; // !EMF -> no change + p_EscherBlibEntry->mnSizeExtra = nExtra + 8; + nInstance = ( eBlibType == WMF ) ? 0xf01b2170 : 0xf01a3d40; // !EMF -> no change + rPicOutStrm << nInstance << (sal_uInt32)( p_EscherBlibEntry->mnSize + nExtra ); + if ( eBlibType == WMF ) // !EMF -> no change + rPicOutStrm.Write( p_EscherBlibEntry->mnIdentifier, 16 ); + rPicOutStrm.Write( p_EscherBlibEntry->mnIdentifier, 16 ); + + /* + ##913## + For Word the stored size of the graphic is critical the + metafile boundaries must match the actual graphics + boundaries, and the width and height must be in EMU's + + If you don't do it this way then objects edited in the + msoffice app may show strange behaviour as the size jumps + around, and the original size and scaling factor in word + will be a very strange figure + */ + sal_uInt32 nPrefWidth = p_EscherBlibEntry->maPrefSize.Width(); + sal_uInt32 nPrefHeight = p_EscherBlibEntry->maPrefSize.Height(); + sal_uInt32 nWidth, nHeight; + if ( pVisArea ) + { + nWidth = pVisArea->Width * 360; + nHeight = pVisArea->Height * 360; + } + else + { + Size aPrefSize(lcl_SizeToEmu(p_EscherBlibEntry->maPrefSize, p_EscherBlibEntry->maPrefMapMode)); + nWidth = aPrefSize.Width() * 360; + nHeight = aPrefSize.Height() * 360; + } + rPicOutStrm << nUncompressedSize // WMFSize without FileHeader + << (sal_Int32)0 // da die Originalgroesse des WMF's (ohne FileHeader) + << (sal_Int32)0 // nicht mehr feststellbar ist, schreiben wir 10cm / x + << nPrefWidth + << nPrefHeight + << nWidth + << nHeight + << p_EscherBlibEntry->mnSize + << (sal_uInt16)0xfe00; // compression Flags + rPicOutStrm.Write( pGraphicAry, p_EscherBlibEntry->mnSize ); + } + } + if ( nAtomSize ) + { + sal_uInt32 nPos = rPicOutStrm.Tell(); + rPicOutStrm.Seek( nAtomSize - 4 ); + rPicOutStrm << (sal_uInt32)( nPos - nAtomSize ); + rPicOutStrm.Seek( nPos ); + } + nBlibId = ImplInsertBlib( p_EscherBlibEntry ), p_EscherBlibEntry = NULL; + } + } + if ( p_EscherBlibEntry ) + delete p_EscherBlibEntry; + return nBlibId; +} + +// --------------------------------------------------------------------------------------------- +// --------------------------------------------------------------------------------------------- +// --------------------------------------------------------------------------------------------- + +struct EscherConnectorRule +{ + sal_uInt32 nRuleId; + sal_uInt32 nShapeA; // SPID of shape A + sal_uInt32 nShapeB; // SPID of shape B + sal_uInt32 nShapeC; // SPID of connector shape + sal_uInt32 ncptiA; // Connection site Index of shape A + sal_uInt32 ncptiB; // Connection site Index of shape B +}; + +struct EscherShapeListEntry +{ + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > aXShape; + sal_uInt32 n_EscherId; + + EscherShapeListEntry( const ::com::sun::star::uno::Reference + < ::com::sun::star::drawing::XShape > & rShape, sal_uInt32 nId ) : + aXShape ( rShape ), + n_EscherId ( nId ) {} +}; + +sal_uInt32 EscherConnectorListEntry::GetClosestPoint( const Polygon& rPoly, const ::com::sun::star::awt::Point& rPoint ) +{ + sal_uInt16 nCount = rPoly.GetSize(); + sal_uInt16 nClosest = nCount; + double fDist = (sal_uInt32)0xffffffff; + while( nCount-- ) + { + double fDistance = hypot( rPoint.X - rPoly[ nCount ].X(), rPoint.Y - rPoly[ nCount ].Y() ); + if ( fDistance < fDist ) + { + nClosest = nCount; + fDist = fDistance; + } + } + return nClosest; +}; + +// --------------------------------------------------------------------------------------------- +// bei Rechtecken bei Ellipsen bei Polygonen +// +// nRule = 0 ->Top 0 ->Top nRule = Index auf ein (Poly)Polygon Punkt +// 1 ->Left 2 ->Left +// 2 ->Bottom 4 ->Bottom +// 3 ->Right 6 ->Right + +sal_uInt32 EscherConnectorListEntry::GetConnectorRule( sal_Bool bFirst ) +{ + sal_uInt32 nRule = 0; + + ::com::sun::star::uno::Any aAny; + ::com::sun::star::awt::Point aRefPoint( ( bFirst ) ? maPointA : maPointB ); + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > + aXShape( ( bFirst ) ? mXConnectToA : mXConnectToB ); + + String aString( (::rtl::OUString)aXShape->getShapeType() ); + ByteString aType( aString, RTL_TEXTENCODING_UTF8 ); + aType.Erase( 0, 13 ); // removing "com.sun.star." + sal_uInt16 nPos = aType.Search( "Shape" ); + aType.Erase( nPos, 5 ); + + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + aPropertySet( aXShape, ::com::sun::star::uno::UNO_QUERY ); + + if ( aType == "drawing.PolyPolygon" || aType == "drawing.PolyLine" ) + { + if ( aPropertySet.is() ) + { + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, + aPropertySet, String( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygon" ) ) ) ) + { + ::com::sun::star::drawing::PointSequenceSequence* pSourcePolyPolygon = + (::com::sun::star::drawing::PointSequenceSequence*)aAny.getValue(); + sal_Int32 nOuterSequenceCount = pSourcePolyPolygon->getLength(); + ::com::sun::star::drawing::PointSequence* pOuterSequence = pSourcePolyPolygon->getArray(); + + if ( pOuterSequence ) + { + sal_Int32 a, b, nIndex = 0; + sal_uInt32 nDistance = 0xffffffff; + for( a = 0; a < nOuterSequenceCount; a++ ) + { + ::com::sun::star::drawing::PointSequence* pInnerSequence = pOuterSequence++; + if ( pInnerSequence ) + { + ::com::sun::star::awt::Point* pArray = pInnerSequence->getArray(); + if ( pArray ) + { + for ( b = 0; b < pInnerSequence->getLength(); b++, nIndex++, pArray++ ) + { + sal_uInt32 nDist = (sal_uInt32)hypot( aRefPoint.X - pArray->X, aRefPoint.Y - pArray->Y ); + if ( nDist < nDistance ) + { + nRule = nIndex; + nDistance = nDist; + } + } + } + } + } + } + } + } + } + else if ( ( aType == "drawing.OpenBezier" ) || ( aType == "drawing.OpenFreeHand" ) || ( aType == "drawing.PolyLinePath" ) + || ( aType == "drawing.ClosedBezier" ) || ( aType == "drawing.ClosedFreeHand" ) || ( aType == "drawing.PolyPolygonPath" ) ) + { + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + aPropertySet2( aXShape, ::com::sun::star::uno::UNO_QUERY ); + if ( aPropertySet2.is() ) + { + if ( EscherPropertyValueHelper::GetPropertyValue( aAny, + aPropertySet2, String( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygonBezier" ) ) ) ) + { + ::com::sun::star::drawing::PolyPolygonBezierCoords* pSourcePolyPolygon = + (::com::sun::star::drawing::PolyPolygonBezierCoords*)aAny.getValue(); + sal_Int32 nOuterSequenceCount = pSourcePolyPolygon->Coordinates.getLength(); + + // Zeiger auf innere sequences holen + ::com::sun::star::drawing::PointSequence* pOuterSequence = + pSourcePolyPolygon->Coordinates.getArray(); + ::com::sun::star::drawing::FlagSequence* pOuterFlags = + pSourcePolyPolygon->Flags.getArray(); + + if ( pOuterSequence && pOuterFlags ) + { + sal_Int32 a, b, nIndex = 0; + sal_uInt32 nDistance = 0xffffffff; + + for ( a = 0; a < nOuterSequenceCount; a++ ) + { + ::com::sun::star::drawing::PointSequence* pInnerSequence = pOuterSequence++; + ::com::sun::star::drawing::FlagSequence* pInnerFlags = pOuterFlags++; + if ( pInnerSequence && pInnerFlags ) + { + ::com::sun::star::awt::Point* pArray = pInnerSequence->getArray(); + ::com::sun::star::drawing::PolygonFlags* pFlags = pInnerFlags->getArray(); + if ( pArray && pFlags ) + { + for ( b = 0; b < pInnerSequence->getLength(); b++, pArray++ ) + { + PolyFlags ePolyFlags = *( (PolyFlags*)pFlags++ ); + if ( ePolyFlags == POLY_CONTROL ) + continue; + sal_uInt32 nDist = (sal_uInt32)hypot( aRefPoint.X - pArray->X, aRefPoint.Y - pArray->Y ); + if ( nDist < nDistance ) + { + nRule = nIndex; + nDistance = nDist; + } + nIndex++; + } + } + } + } + } + } + } + } + else + { + bool bRectangularConnection = true; + + if ( aType == "drawing.Custom" ) + { + SdrObject* pCustoShape( GetSdrObjectFromXShape( aXShape ) ); + if ( pCustoShape && pCustoShape->ISA( SdrObjCustomShape ) ) + { + SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)(const SdrCustomShapeGeometryItem&) + pCustoShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ); + + const rtl::OUString sPath( RTL_CONSTASCII_USTRINGPARAM( "Path" ) ); + const rtl::OUString sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) ); + const rtl::OUString sGluePointType( RTL_CONSTASCII_USTRINGPARAM( "GluePointType" ) ); + + rtl::OUString sShapeType; + uno::Any* pType = rGeometryItem.GetPropertyValueByName( sType ); + if ( pType ) + *pType >>= sShapeType; + MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType ); + + uno::Any* pGluePointType = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sGluePointType ); + + sal_Int16 nGluePointType = sal_Int16(); + if ( !( pGluePointType && + ( *pGluePointType >>= nGluePointType ) ) ) + nGluePointType = GetCustomShapeConnectionTypeDefault( eSpType ); + + if ( nGluePointType == com::sun::star::drawing::EnhancedCustomShapeGluePointType::CUSTOM ) + { + const SdrGluePointList* pList = pCustoShape->GetGluePointList(); + if ( pList ) + { + Polygon aPoly; + sal_uInt16 nNum, nAnz = pList->GetCount(); + if ( nAnz ) + { + for ( nNum = 0; nNum < nAnz; nNum++ ) + { + const SdrGluePoint& rGP = (*pList)[ nNum ]; + Point aPt( rGP.GetAbsolutePos( *pCustoShape ) ); + aPoly.Insert( POLY_APPEND, aPt ); + } + nRule = GetClosestPoint( aPoly, aRefPoint ); + bRectangularConnection = false; + } + } + } + else if ( nGluePointType == com::sun::star::drawing::EnhancedCustomShapeGluePointType::SEGMENTS ) + { + SdrObject* pPoly = pCustoShape->DoConvertToPolyObj( sal_True ); + if ( pPoly && pPoly->ISA( SdrPathObj ) ) + { + sal_Int16 a, b, nIndex = 0; + sal_uInt32 nDistance = 0xffffffff; + + // #i74631# use explicit constructor here. Also XPolyPolygon is not necessary, + // reducing to PolyPolygon + const PolyPolygon aPolyPoly(((SdrPathObj*)pPoly)->GetPathPoly()); + + for ( a = 0; a < aPolyPoly.Count(); a++ ) + { + const Polygon& rPoly = aPolyPoly.GetObject( a ); + for ( b = 0; b < rPoly.GetSize(); b++ ) + { + if ( rPoly.GetFlags( b ) != POLY_NORMAL ) + continue; + const Point& rPt = rPoly[ b ]; + sal_uInt32 nDist = (sal_uInt32)hypot( aRefPoint.X - rPt.X(), aRefPoint.Y - rPt.Y() ); + if ( nDist < nDistance ) + { + nRule = nIndex; + nDistance = nDist; + } + nIndex++; + } + } + if ( nDistance != 0xffffffff ) + bRectangularConnection = false; + } + } + } + } + if ( bRectangularConnection ) + { + ::com::sun::star::awt::Point aPoint( aXShape->getPosition() ); + ::com::sun::star::awt::Size aSize( aXShape->getSize() ); + + Rectangle aRect( Point( aPoint.X, aPoint.Y ), Size( aSize.Width, aSize.Height ) ); + Point aCenter( aRect.Center() ); + Polygon aPoly( 4 ); + + aPoly[ 0 ] = Point( aCenter.X(), aRect.Top() ); + aPoly[ 1 ] = Point( aRect.Left(), aCenter.Y() ); + aPoly[ 2 ] = Point( aCenter.X(), aRect.Bottom() ); + aPoly[ 3 ] = Point( aRect.Right(), aCenter.Y() ); + + sal_Int32 nAngle = ( EscherPropertyValueHelper::GetPropertyValue( aAny, + aPropertySet, String( RTL_CONSTASCII_USTRINGPARAM( "RotateAngle" ) ), sal_True ) ) + ? *((sal_Int32*)aAny.getValue() ) + : 0; + if ( nAngle ) + aPoly.Rotate( aRect.TopLeft(), (sal_uInt16)( ( nAngle + 5 ) / 10 ) ); + nRule = GetClosestPoint( aPoly, aRefPoint ); + + if ( aType == "drawing.Ellipse" ) + nRule <<= 1; // In PPT hat eine Ellipse 8 M?glichkeiten sich zu connecten + } + } + return nRule; +} + +EscherSolverContainer::~EscherSolverContainer() +{ + void* pP; + + for( pP = maShapeList.First(); pP; pP = maShapeList.Next() ) + delete (EscherShapeListEntry*)pP; + for( pP = maConnectorList.First(); pP; pP = maConnectorList.Next() ) + delete (EscherConnectorListEntry*)pP; +} + +void EscherSolverContainer::AddShape( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape, sal_uInt32 nId ) +{ + maShapeList.Insert( new EscherShapeListEntry( rXShape, nId ), LIST_APPEND ); +} + +void EscherSolverContainer::AddConnector( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rConnector, + const ::com::sun::star::awt::Point& rPA, + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rConA, + const ::com::sun::star::awt::Point& rPB, + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rConB ) +{ + maConnectorList.Insert( new EscherConnectorListEntry( rConnector, rPA, rConA, rPB, rConB ), LIST_APPEND ); +} + +sal_uInt32 EscherSolverContainer::GetShapeId( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape ) const +{ + for ( EscherShapeListEntry* pPtr = (EscherShapeListEntry*)((List&)maShapeList).First(); + pPtr; pPtr = (EscherShapeListEntry*)((List&)maShapeList).Next() ) + { + if ( rXShape == pPtr->aXShape ) + return ( pPtr->n_EscherId ); + } + return 0; +} + +void EscherSolverContainer::WriteSolver( SvStream& rStrm ) +{ + sal_uInt32 nCount = maConnectorList.Count(); + if ( nCount ) + { + sal_uInt32 nRecHdPos, nCurrentPos, nSize; + rStrm << (sal_uInt16)( ( nCount << 4 ) | 0xf ) // open an ESCHER_SolverContainer + << (sal_uInt16)ESCHER_SolverContainer // + << (sal_uInt32)0; // + + nRecHdPos = rStrm.Tell() - 4; + + EscherConnectorRule aConnectorRule; + aConnectorRule.nRuleId = 2; + for ( EscherConnectorListEntry* pPtr = (EscherConnectorListEntry*)maConnectorList.First(); + pPtr; pPtr = (EscherConnectorListEntry*)maConnectorList.Next() ) + { + aConnectorRule.ncptiA = aConnectorRule.ncptiB = 0xffffffff; + aConnectorRule.nShapeC = GetShapeId( pPtr->mXConnector ); + aConnectorRule.nShapeA = GetShapeId( pPtr->mXConnectToA ); + aConnectorRule.nShapeB = GetShapeId( pPtr->mXConnectToB ); + + if ( aConnectorRule.nShapeC ) + { + if ( aConnectorRule.nShapeA ) + aConnectorRule.ncptiA = pPtr->GetConnectorRule( sal_True ); + if ( aConnectorRule.nShapeB ) + aConnectorRule.ncptiB = pPtr->GetConnectorRule( sal_False ); + } + rStrm << (sal_uInt32)( ( ESCHER_ConnectorRule << 16 ) | 1 ) // atom hd + << (sal_uInt32)24 // + << aConnectorRule.nRuleId + << aConnectorRule.nShapeA + << aConnectorRule.nShapeB + << aConnectorRule.nShapeC + << aConnectorRule.ncptiA + << aConnectorRule.ncptiB; + + aConnectorRule.nRuleId += 2; + } + + nCurrentPos = rStrm.Tell(); // close the ESCHER_SolverContainer + nSize = ( nCurrentPos - nRecHdPos ) - 4;// + rStrm.Seek( nRecHdPos ); // + rStrm << nSize; // + rStrm.Seek( nCurrentPos ); // + } +} + +// --------------------------------------------------------------------------------------------- + +EscherExGlobal::EscherExGlobal( sal_uInt32 nGraphicProvFlags ) : + EscherGraphicProvider( nGraphicProvFlags ), + mpPicStrm( 0 ), + mbHasDggCont( false ), + mbPicStrmQueried( false ) +{ +} + +EscherExGlobal::~EscherExGlobal() +{ +} + +sal_uInt32 EscherExGlobal::GenerateDrawingId() +{ + // new drawing starts a new cluster in the cluster table (cluster identifiers are one-based) + sal_uInt32 nClusterId = static_cast< sal_uInt32 >( maClusterTable.size() + 1 ); + // drawing identifiers are one-based + sal_uInt32 nDrawingId = static_cast< sal_uInt32 >( maDrawingInfos.size() + 1 ); + // prepare new entries in the tables + maClusterTable.push_back( ClusterEntry( nDrawingId ) ); + maDrawingInfos.push_back( DrawingInfo( nClusterId ) ); + // return the new drawing identifier + return nDrawingId; +} + +sal_uInt32 EscherExGlobal::GenerateShapeId( sal_uInt32 nDrawingId, bool bIsInSpgr ) +{ + // drawing identifier is one-based + size_t nDrawingIdx = nDrawingId - 1; + OSL_ENSURE( nDrawingIdx < maDrawingInfos.size(), "EscherExGlobal::GenerateShapeId - invalid drawing ID" ); + if( nDrawingIdx >= maDrawingInfos.size() ) + return 0; + DrawingInfo& rDrawingInfo = maDrawingInfos[ nDrawingIdx ]; + + // cluster identifier in drawing info struct is one-based + ClusterEntry* pClusterEntry = &maClusterTable[ rDrawingInfo.mnClusterId - 1 ]; + + // check cluster overflow, create new cluster entry + if( pClusterEntry->mnNextShapeId == DFF_DGG_CLUSTER_SIZE ) + { + // start a new cluster in the cluster table + maClusterTable.push_back( ClusterEntry( nDrawingId ) ); + pClusterEntry = &maClusterTable.back(); + // new size of maClusterTable is equal to one-based identifier of the new cluster + rDrawingInfo.mnClusterId = static_cast< sal_uInt32 >( maClusterTable.size() ); + } + + // build shape identifier from cluster identifier and next free cluster shape identifier + rDrawingInfo.mnLastShapeId = static_cast< sal_uInt32 >( rDrawingInfo.mnClusterId * DFF_DGG_CLUSTER_SIZE + pClusterEntry->mnNextShapeId ); + // update free shape identifier in cluster entry + ++pClusterEntry->mnNextShapeId; + /* Old code has counted the shapes only, if we are in a SPGRCONTAINER. Is + this really intended? Maybe it's always true... */ + if( bIsInSpgr ) + ++rDrawingInfo.mnShapeCount; + + // return the new shape identifier + return rDrawingInfo.mnLastShapeId; +} + +sal_uInt32 EscherExGlobal::GetDrawingShapeCount( sal_uInt32 nDrawingId ) const +{ + size_t nDrawingIdx = nDrawingId - 1; + OSL_ENSURE( nDrawingIdx < maDrawingInfos.size(), "EscherExGlobal::GetDrawingShapeCount - invalid drawing ID" ); + return (nDrawingIdx < maDrawingInfos.size()) ? maDrawingInfos[ nDrawingIdx ].mnShapeCount : 0; +} + +sal_uInt32 EscherExGlobal::GetLastShapeId( sal_uInt32 nDrawingId ) const +{ + size_t nDrawingIdx = nDrawingId - 1; + OSL_ENSURE( nDrawingIdx < maDrawingInfos.size(), "EscherExGlobal::GetLastShapeId - invalid drawing ID" ); + return (nDrawingIdx < maDrawingInfos.size()) ? maDrawingInfos[ nDrawingIdx ].mnLastShapeId : 0; +} + +sal_uInt32 EscherExGlobal::GetDggAtomSize() const +{ + // 8 bytes header, 16 bytes fixed DGG data, 8 bytes for each cluster + return static_cast< sal_uInt32 >( 24 + 8 * maClusterTable.size() ); +} + +void EscherExGlobal::WriteDggAtom( SvStream& rStrm ) const +{ + sal_uInt32 nDggSize = GetDggAtomSize(); + + // write the DGG record header (do not include the 8 bytes of the header in the data size) + rStrm << static_cast< sal_uInt32 >( ESCHER_Dgg << 16 ) << static_cast< sal_uInt32 >( nDggSize - 8 ); + + // claculate and write the fixed DGG data + sal_uInt32 nShapeCount = 0; + sal_uInt32 nLastShapeId = 0; + for( DrawingInfoVector::const_iterator aIt = maDrawingInfos.begin(), aEnd = maDrawingInfos.end(); aIt != aEnd; ++aIt ) + { + nShapeCount += aIt->mnShapeCount; + nLastShapeId = ::std::max( nLastShapeId, aIt->mnLastShapeId ); + } + // the non-existing cluster with index #0 is counted too + sal_uInt32 nClusterCount = static_cast< sal_uInt32 >( maClusterTable.size() + 1 ); + sal_uInt32 nDrawingCount = static_cast< sal_uInt32 >( maDrawingInfos.size() ); + rStrm << nLastShapeId << nClusterCount << nShapeCount << nDrawingCount; + + // write the cluster table + for( ClusterTable::const_iterator aIt = maClusterTable.begin(), aEnd = maClusterTable.end(); aIt != aEnd; ++aIt ) + rStrm << aIt->mnDrawingId << aIt->mnNextShapeId; +} + +SvStream* EscherExGlobal::QueryPictureStream() +{ + if( !mbPicStrmQueried ) + { + mpPicStrm = ImplQueryPictureStream(); + mbPicStrmQueried = true; + } + return mpPicStrm; +} + +SvStream* EscherExGlobal::ImplQueryPictureStream() +{ + return 0; +} + +// --------------------------------------------------------------------------------------------- +// --------------------------------------------------------------------------------------------- +// --------------------------------------------------------------------------------------------- + +EscherEx::EscherEx( const EscherExGlobalRef& rxGlobal, SvStream& rOutStrm ) : + mxGlobal ( rxGlobal ), + mpOutStrm ( &rOutStrm ), + + mnGroupLevel ( 0 ), + mnHellLayerId ( USHRT_MAX ), + + mbEscherSpgr ( sal_False ), + mbEscherDg ( sal_False ) +{ + mnStrmStartOfs = mpOutStrm->Tell(); + mpImplEscherExSdr.reset( new ImplEscherExSdr( *this ) ); +} + +EscherEx::~EscherEx() +{ +} + +// --------------------------------------------------------------------------------------------- + +void EscherEx::Flush( SvStream* pPicStreamMergeBSE /* = NULL */ ) +{ + if ( mxGlobal->HasDggContainer() ) + { + // store the current stream position at ESCHER_Persist_CurrentPosition key + PtReplaceOrInsert( ESCHER_Persist_CurrentPosition, mpOutStrm->Tell() ); + if ( DoSeek( ESCHER_Persist_Dgg ) ) + { + /* The DGG record is still not written. ESCHER_Persist_Dgg seeks + to the place where the complete record has to be inserted. */ + InsertAtCurrentPos( mxGlobal->GetDggAtomSize(), false ); + mxGlobal->WriteDggAtom( *mpOutStrm ); + + if ( mxGlobal->HasGraphics() ) + { + /* Calculate the total size of the BSTORECONTAINER including + all BSE records containing the picture data contained in + the passed in pPicStreamMergeBSE. */ + sal_uInt32 nBSCSize = mxGlobal->GetBlibStoreContainerSize( pPicStreamMergeBSE ); + if ( nBSCSize > 0 ) + { + InsertAtCurrentPos( nBSCSize, false ); + mxGlobal->WriteBlibStoreContainer( *mpOutStrm, pPicStreamMergeBSE ); + } + } + + /* Forget the stream position stored for the DGG which is invalid + after the call to InsertAtCurrentPos() anyway. */ + PtDelete( ESCHER_Persist_Dgg ); + } + // seek to initial position (may be different due to inserted DGG and BLIPs) + mpOutStrm->Seek( PtGetOffsetByID( ESCHER_Persist_CurrentPosition ) ); + } +} + +// --------------------------------------------------------------------------------------------- + +void EscherEx::InsertAtCurrentPos( sal_uInt32 nBytes, bool bExpandEndOfAtom ) +{ + sal_uInt32 nSize, nType, nSource, nBufSize, nToCopy, nCurPos = mpOutStrm->Tell(); + sal_uInt8* pBuf; + + // Persist table anpassen + for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() ) + { + sal_uInt32 nOfs = ((EscherPersistEntry*)pPtr)->mnOffset; + if ( nOfs >= nCurPos ) + ((EscherPersistEntry*)pPtr)->mnOffset += nBytes; + } + + // container und atom sizes anpassen + mpOutStrm->Seek( mnStrmStartOfs ); + while ( mpOutStrm->Tell() < nCurPos ) + { + *mpOutStrm >> nType >> nSize; + sal_uInt32 nEndOfRecord = mpOutStrm->Tell() + nSize; + bool bContainer = (nType & 0x0F) == 0x0F; + /* Expand the record, if the insertion position is inside, or if the + position is at the end of a container (expands always), or at the + end of an atom and bExpandEndOfAtom is set. */ + if ( (nCurPos < nEndOfRecord) || ((nCurPos == nEndOfRecord) && (bContainer || bExpandEndOfAtom)) ) + { + mpOutStrm->SeekRel( -4 ); + *mpOutStrm << (sal_uInt32)( nSize + nBytes ); + if ( !bContainer ) + mpOutStrm->SeekRel( nSize ); + } + else + mpOutStrm->SeekRel( nSize ); + } + std::vector< sal_uInt32 >::iterator aIter( mOffsets.begin() ); + std::vector< sal_uInt32 >::iterator aEnd( mOffsets.end() ); + while( aIter != aEnd ) + { + if ( *aIter > nCurPos ) + *aIter += nBytes; + aIter++; + } + mpOutStrm->Seek( STREAM_SEEK_TO_END ); + nSource = mpOutStrm->Tell(); + nToCopy = nSource - nCurPos; // Stream um nBytes vergroessern + pBuf = new sal_uInt8[ 0x40000 ]; // 256KB Buffer + while ( nToCopy ) + { + nBufSize = ( nToCopy >= 0x40000 ) ? 0x40000 : nToCopy; + nToCopy -= nBufSize; + nSource -= nBufSize; + mpOutStrm->Seek( nSource ); + mpOutStrm->Read( pBuf, nBufSize ); + mpOutStrm->Seek( nSource + nBytes ); + mpOutStrm->Write( pBuf, nBufSize ); + } + delete[] pBuf; + mpOutStrm->Seek( nCurPos ); +} + +// --------------------------------------------------------------------------------------------- + +sal_Bool EscherEx::SeekBehindRecHeader( sal_uInt16 nRecType ) +{ + sal_uInt32 nOldPos, nStreamEnd, nType, nSize; + + nOldPos = mpOutStrm->Tell(); + nStreamEnd = mpOutStrm->Seek( STREAM_SEEK_TO_END ); + mpOutStrm->Seek( nOldPos ); + while ( mpOutStrm->Tell() < nStreamEnd ) + { + *mpOutStrm >> nType >> nSize; + if ( ( nType >> 16 ) == nRecType ) + return sal_True; + if ( ( nType & 0xf ) != 0xf ) + mpOutStrm->SeekRel( nSize ); + } + mpOutStrm->Seek( nOldPos ); + return sal_False; +} + +// --------------------------------------------------------------------------------------------- + +void EscherEx::InsertPersistOffset( sal_uInt32 nKey, sal_uInt32 nOffset ) +{ + PtInsert( ESCHER_Persist_PrivateEntry | nKey, nOffset ); +} + +void EscherEx::ReplacePersistOffset( sal_uInt32 nKey, sal_uInt32 nOffset ) +{ + PtReplace( ESCHER_Persist_PrivateEntry | nKey, nOffset ); +} + +sal_uInt32 EscherEx::GetPersistOffset( sal_uInt32 nKey ) +{ + return PtGetOffsetByID( ESCHER_Persist_PrivateEntry | nKey ); +} + +// --------------------------------------------------------------------------------------------- + +sal_Bool EscherEx::DoSeek( sal_uInt32 nKey ) +{ + sal_uInt32 nPos = PtGetOffsetByID( nKey ); + if ( nPos ) + mpOutStrm->Seek( nPos ); + else + { + if (! PtIsID( nKey ) ) + return sal_False; + mpOutStrm->Seek( 0 ); + } + return sal_True; +} + +// --------------------------------------------------------------------------------------------- + +sal_Bool EscherEx::SeekToPersistOffset( sal_uInt32 nKey ) +{ + return DoSeek( ESCHER_Persist_PrivateEntry | nKey ); +} + +// --------------------------------------------------------------------------------------------- + +sal_Bool EscherEx::InsertAtPersistOffset( sal_uInt32 nKey, sal_uInt32 nValue ) +{ + sal_uInt32 nOldPos = mpOutStrm->Tell(); + sal_Bool bRetValue = SeekToPersistOffset( nKey ); + if ( bRetValue ) + { + *mpOutStrm << nValue; + mpOutStrm->Seek( nOldPos ); + } + return bRetValue; +} + +// --------------------------------------------------------------------------------------------- + +void EscherEx::OpenContainer( sal_uInt16 nEscherContainer, int nRecInstance ) +{ + *mpOutStrm << (sal_uInt16)( ( nRecInstance << 4 ) | 0xf ) << nEscherContainer << (sal_uInt32)0; + mOffsets.push_back( mpOutStrm->Tell() - 4 ); + mRecTypes.push_back( nEscherContainer ); + switch( nEscherContainer ) + { + case ESCHER_DggContainer : + { + mxGlobal->SetDggContainer(); + mnCurrentDg = 0; + /* Remember the current position as start position of the DGG + record and BSTORECONTAINER, but do not write them actually. + This will be done later in Flush() when the number of drawings, + the size and contents of the FIDCL cluster table, and the size + of the BLIP container are known. */ + PtReplaceOrInsert( ESCHER_Persist_Dgg, mpOutStrm->Tell() ); + } + break; + + case ESCHER_DgContainer : + { + if ( mxGlobal->HasDggContainer() ) + { + if ( !mbEscherDg ) + { + mbEscherDg = sal_True; + mnCurrentDg = mxGlobal->GenerateDrawingId(); + AddAtom( 8, ESCHER_Dg, 0, mnCurrentDg ); + PtReplaceOrInsert( ESCHER_Persist_Dg | mnCurrentDg, mpOutStrm->Tell() ); + *mpOutStrm << (sal_uInt32)0 // The number of shapes in this drawing + << (sal_uInt32)0; // The last MSOSPID given to an SP in this DG + } + } + } + break; + + case ESCHER_SpgrContainer : + { + if ( mbEscherDg ) + { + mbEscherSpgr = sal_True; + } + } + break; + + case ESCHER_SpContainer : + { + } + break; + + default: + break; + } +} + +// --------------------------------------------------------------------------------------------- + +void EscherEx::CloseContainer() +{ + sal_uInt32 nSize, nPos = mpOutStrm->Tell(); + nSize = ( nPos - mOffsets.back() ) - 4; + mpOutStrm->Seek( mOffsets.back() ); + *mpOutStrm << nSize; + + switch( mRecTypes.back() ) + { + case ESCHER_DgContainer : + { + if ( mbEscherDg ) + { + mbEscherDg = sal_False; + if ( DoSeek( ESCHER_Persist_Dg | mnCurrentDg ) ) + *mpOutStrm << mxGlobal->GetDrawingShapeCount( mnCurrentDg ) << mxGlobal->GetLastShapeId( mnCurrentDg ); + } + } + break; + + case ESCHER_SpgrContainer : + { + if ( mbEscherSpgr ) + { + mbEscherSpgr = sal_False; + + } + } + break; + + default: + break; + } + mOffsets.pop_back(); + mRecTypes.pop_back(); + mpOutStrm->Seek( nPos ); +} + +// --------------------------------------------------------------------------------------------- + +void EscherEx::BeginAtom() +{ + mnCountOfs = mpOutStrm->Tell(); + *mpOutStrm << (sal_uInt32)0 << (sal_uInt32)0; // record header wird spaeter geschrieben +} + +// --------------------------------------------------------------------------------------------- + +void EscherEx::EndAtom( sal_uInt16 nRecType, int nRecVersion, int nRecInstance ) +{ + sal_uInt32 nOldPos = mpOutStrm->Tell(); + mpOutStrm->Seek( mnCountOfs ); + sal_uInt32 nSize = nOldPos - mnCountOfs; + *mpOutStrm << (sal_uInt16)( ( nRecInstance << 4 ) | ( nRecVersion & 0xf ) ) << nRecType << (sal_uInt32)( nSize - 8 ); + mpOutStrm->Seek( nOldPos ); +} + +// --------------------------------------------------------------------------------------------- + +void EscherEx::AddAtom( sal_uInt32 nAtomSize, sal_uInt16 nRecType, int nRecVersion, int nRecInstance ) +{ + *mpOutStrm << (sal_uInt16)( ( nRecInstance << 4 ) | ( nRecVersion & 0xf ) ) << nRecType << nAtomSize; +} + +// --------------------------------------------------------------------------------------------- + +void EscherEx::AddChildAnchor( const Rectangle& rRect ) +{ + AddAtom( 16, ESCHER_ChildAnchor ); + *mpOutStrm << (sal_Int32)rRect.Left() + << (sal_Int32)rRect.Top() + << (sal_Int32)rRect.Right() + << (sal_Int32)rRect.Bottom(); +} + +// --------------------------------------------------------------------------------------------- + +void EscherEx::AddClientAnchor( const Rectangle& rRect ) +{ + AddAtom( 8, ESCHER_ClientAnchor ); + *mpOutStrm << (sal_Int16)rRect.Top() + << (sal_Int16)rRect.Left() + << (sal_Int16)( rRect.GetWidth() + rRect.Left() ) + << (sal_Int16)( rRect.GetHeight() + rRect.Top() ); +} + +// --------------------------------------------------------------------------------------------- + +EscherExHostAppData* EscherEx::EnterAdditionalTextGroup() +{ + return NULL; +} + +// --------------------------------------------------------------------------------------------- + +sal_uInt32 EscherEx::EnterGroup( const String& rShapeName, const Rectangle* pBoundRect ) +{ + Rectangle aRect; + if( pBoundRect ) + aRect = *pBoundRect; + + OpenContainer( ESCHER_SpgrContainer ); + OpenContainer( ESCHER_SpContainer ); + AddAtom( 16, ESCHER_Spgr, 1 ); + PtReplaceOrInsert( ESCHER_Persist_Grouping_Snap | mnGroupLevel, + mpOutStrm->Tell() ); + *mpOutStrm << (sal_Int32)aRect.Left() // Bounding box fuer die Gruppierten shapes an die sie attached werden + << (sal_Int32)aRect.Top() + << (sal_Int32)aRect.Right() + << (sal_Int32)aRect.Bottom(); + + sal_uInt32 nShapeId = GenerateShapeId(); + if ( !mnGroupLevel ) + AddShape( ESCHER_ShpInst_Min, 5, nShapeId ); // Flags: Group | Patriarch + else + { + AddShape( ESCHER_ShpInst_Min, 0x201, nShapeId ); // Flags: Group | HaveAnchor + EscherPropertyContainer aPropOpt; + aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x00040004 ); + aPropOpt.AddOpt( ESCHER_Prop_dxWrapDistLeft, 0 ); + aPropOpt.AddOpt( ESCHER_Prop_dxWrapDistRight, 0 ); + + // #i51348# shape name + if( rShapeName.Len() > 0 ) + aPropOpt.AddOpt( ESCHER_Prop_wzName, rShapeName ); + + Commit( aPropOpt, aRect ); + if ( mnGroupLevel > 1 ) + AddChildAnchor( aRect ); + + EscherExHostAppData* pAppData = mpImplEscherExSdr->ImplGetHostData(); + if( pAppData ) + { + if ( mnGroupLevel <= 1 ) + pAppData->WriteClientAnchor( *this, aRect ); + pAppData->WriteClientData( *this ); + } + } + CloseContainer(); // ESCHER_SpContainer + mnGroupLevel++; + return nShapeId; +} + +sal_uInt32 EscherEx::EnterGroup( const Rectangle* pBoundRect ) +{ + return EnterGroup( String::EmptyString(), pBoundRect ); +} + +// --------------------------------------------------------------------------------------------- + +sal_Bool EscherEx::SetGroupSnapRect( sal_uInt32 nGroupLevel, const Rectangle& rRect ) +{ + sal_Bool bRetValue = sal_False; + if ( nGroupLevel ) + { + sal_uInt32 nCurrentPos = mpOutStrm->Tell(); + if ( DoSeek( ESCHER_Persist_Grouping_Snap | ( nGroupLevel - 1 ) ) ) + { + *mpOutStrm << (sal_Int32)rRect.Left() // Bounding box fuer die Gruppierten shapes an die sie attached werden + << (sal_Int32)rRect.Top() + << (sal_Int32)rRect.Right() + << (sal_Int32)rRect.Bottom(); + mpOutStrm->Seek( nCurrentPos ); + } + } + return bRetValue; +} + +// --------------------------------------------------------------------------------------------- + +sal_Bool EscherEx::SetGroupLogicRect( sal_uInt32 nGroupLevel, const Rectangle& rRect ) +{ + sal_Bool bRetValue = sal_False; + if ( nGroupLevel ) + { + sal_uInt32 nCurrentPos = mpOutStrm->Tell(); + if ( DoSeek( ESCHER_Persist_Grouping_Logic | ( nGroupLevel - 1 ) ) ) + { + *mpOutStrm << (sal_Int16)rRect.Top() << (sal_Int16)rRect.Left() << (sal_Int16)rRect.Right() << (sal_Int16)rRect.Bottom(); + mpOutStrm->Seek( nCurrentPos ); + } + } + return bRetValue; +} + +// --------------------------------------------------------------------------------------------- + +void EscherEx::LeaveGroup() +{ + --mnGroupLevel; + PtDelete( ESCHER_Persist_Grouping_Snap | mnGroupLevel ); + PtDelete( ESCHER_Persist_Grouping_Logic | mnGroupLevel ); + CloseContainer(); +} + +// --------------------------------------------------------------------------------------------- + +void EscherEx::AddShape( sal_uInt32 nShpInstance, sal_uInt32 nFlags, sal_uInt32 nShapeID ) +{ + AddAtom( 8, ESCHER_Sp, 2, nShpInstance ); + + if ( !nShapeID ) + nShapeID = GenerateShapeId(); + + if ( nFlags ^ 1 ) // is this a group shape ? + { // if not + if ( mnGroupLevel > 1 ) + nFlags |= 2; // this not a topmost shape + } + *mpOutStrm << nShapeID << nFlags; +} + +// --------------------------------------------------------------------------------------------- + +void EscherEx::Commit( EscherPropertyContainer& rProps, const Rectangle& ) +{ + rProps.Commit( GetStream() ); +} + +// --------------------------------------------------------------------------------------------- + +sal_uInt32 EscherEx::GetColor( const sal_uInt32 nSOColor, sal_Bool bSwap ) +{ + if ( bSwap ) + { + sal_uInt32 nColor = nSOColor & 0xff00; // GRUEN + nColor |= (sal_uInt8)( nSOColor ) << 16; // ROT + nColor |= (sal_uInt8)( nSOColor >> 16 ); // BLAU + return nColor; + } + else + return nSOColor & 0xffffff; +} + +// --------------------------------------------------------------------------------------------- + +sal_uInt32 EscherEx::GetColor( const Color& rSOColor, sal_Bool bSwap ) +{ + sal_uInt32 nColor = ( rSOColor.GetRed() << 16 ); + nColor |= ( rSOColor.GetGreen() << 8 ); + nColor |= rSOColor.GetBlue(); + + if ( !bSwap ) + nColor = GetColor( nColor, sal_True ); + + return nColor; +} + +// --------------------------------------------------------------------------------------------- + diff --git a/filter/source/msfilter/eschesdo.cxx b/filter/source/msfilter/eschesdo.cxx new file mode 100644 index 000000000000..ec06fcefaf6f --- /dev/null +++ b/filter/source/msfilter/eschesdo.cxx @@ -0,0 +1,1255 @@ +/************************************************************************* + * + * 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_filter.hxx" +#include "eschesdo.hxx" +#include <svx/svdobj.hxx> +#include <svx/unoapi.hxx> +#include <svx/svdoashp.hxx> +#include <svx/unoshape.hxx> +#include <vcl/outdev.hxx> +#include <tools/poly.hxx> +#include <vcl/bitmapex.hxx> +#include <vcl/graph.hxx> +#include <tools/debug.hxx> +#include <svx/fmdpage.hxx> +#include <toolkit/unohlp.hxx> +#include <com/sun/star/style/VerticalAlignment.hpp> +#include <com/sun/star/awt/Gradient.hpp> +#include <com/sun/star/drawing/PointSequence.hpp> +#include <com/sun/star/drawing/PointSequenceSequence.hpp> +#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp> +#include <com/sun/star/drawing/FlagSequence.hpp> +#include <com/sun/star/drawing/TextAdjust.hpp> +#include <com/sun/star/drawing/LineDash.hpp> +#include <com/sun/star/text/XText.hpp> +#include <com/sun/star/drawing/CircleKind.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/task/XStatusIndicator.hpp> +#include <comphelper/extract.hxx> +#include <svtools/fltcall.hxx> +#include <vcl/cvtgrf.hxx> + +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::task; +using namespace ::com::sun::star::style; + +#define EES_MAP_FRACTION 1440 // 1440 dpi + +// =================================================================== + +ImplEESdrWriter::ImplEESdrWriter( EscherEx& rEx ) + : + mpEscherEx ( &rEx ), + maMapModeSrc ( MAP_100TH_MM ), + // PowerPoint: 576 dpi, WinWord: 1440 dpi, Excel: 1440 dpi + maMapModeDest( MAP_INCH, Point(), Fraction( 1, EES_MAP_FRACTION ), Fraction( 1, EES_MAP_FRACTION ) ), +// mXStatusIndicator ( rXStatInd ), + mpPicStrm ( NULL ), + mpHostAppData ( NULL ), + mnPagesWritten ( 0 ), + mnShapeMasterTitle ( 0 ), + mnShapeMasterBody ( 0 ), + mbStatusIndicator ( sal_False ), + mbStatus ( sal_False ) +{ +} + + +// ------------------------------------------------------------------- + +Point ImplEESdrWriter::ImplMapPoint( const Point& rPoint ) +{ + return OutputDevice::LogicToLogic( rPoint, maMapModeSrc, maMapModeDest ); +} + + +// ------------------------------------------------------------------- + +Size ImplEESdrWriter::ImplMapSize( const Size& rSize ) +{ + Size aRetSize( OutputDevice::LogicToLogic( rSize, maMapModeSrc, maMapModeDest ) ); + + if ( !aRetSize.Width() ) + aRetSize.Width()++; + if ( !aRetSize.Height() ) + aRetSize.Height()++; + return aRetSize; +} + +// ------------------------------------------------------------------- + +void ImplEESdrWriter::ImplFlipBoundingBox( ImplEESdrObject& rObj, EscherPropertyContainer& rPropOpt ) +{ + sal_Int32 nAngle = rObj.GetAngle(); + Rectangle aRect( rObj.GetRect() ); + + if ( nAngle < 0 ) + nAngle = ( 36000 + nAngle ) % 36000; + else + nAngle = ( 36000 - ( nAngle % 36000 ) ); + + double fVal = (double)nAngle * F_PI18000; + double fCos = cos( fVal ); + double fSin = sin( fVal ); + + double nWidthHalf = (double) aRect.GetWidth() / 2; + double nHeightHalf = (double) aRect.GetHeight() / 2; + + double nXDiff = fCos * nWidthHalf + fSin * (-nHeightHalf); + double nYDiff = - ( fSin * nWidthHalf - fCos * ( -nHeightHalf ) ); + + aRect.Move( (sal_Int32)( -( nWidthHalf - nXDiff ) ), (sal_Int32)( - ( nHeightHalf + nYDiff ) ) ); + + nAngle *= 655; + nAngle += 0x8000; + nAngle &=~0xffff; // nAngle auf volle Gradzahl runden + rPropOpt.AddOpt( ESCHER_Prop_Rotation, nAngle ); + + rObj.SetAngle( nAngle ); + rObj.SetRect( aRect ); +} + +// ----------------------------------------------------------------------- + +#define ADD_SHAPE( nType, nFlags ) \ +{ \ + nShapeType = nType; \ + nShapeID = mpEscherEx->GenerateShapeId(); \ + rObj.SetShapeId( nShapeID ); \ + mpEscherEx->AddShape( (sal_uInt32)nType, (sal_uInt32)nFlags, nShapeID ); \ + rSolverContainer.AddShape( rObj.GetShapeRef(), nShapeID ); \ +} + +#define SHAPE_TEXT( bFill ) \ +{ \ + mpEscherEx->OpenContainer( ESCHER_SpContainer ); \ + ADD_SHAPE( ESCHER_ShpInst_TextBox, 0xa00 ); \ + if ( bFill ) \ + aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True ); \ + if( rObj.ImplGetText() ) \ + aPropOpt.CreateTextProperties( rObj.mXPropSet, \ + mpEscherEx->QueryTextID( rObj.GetShapeRef(), \ + rObj.GetShapeId() ) ); \ +} + +//Map from twips to export units, generally twips as well, only excel and word +//export is happening here, so native units are export units, leave as +//placeholder if required in future +void ImplEESdrWriter::MapRect(ImplEESdrObject& /* rObj */ ) +{ +} + +sal_uInt32 ImplEESdrWriter::ImplWriteShape( ImplEESdrObject& rObj, + EscherSolverContainer& rSolverContainer, + ImplEESdrPageType ePageType ) +{ + sal_uInt32 nShapeID = 0; + sal_uInt16 nShapeType = 0; + sal_Bool bDontWriteText = sal_False; // if a metafile is written as shape replacement, then the text is already part of the metafile + sal_Bool bAdditionalText = sal_False; + sal_uInt32 nGrpShapeID = 0; + + do { + mpHostAppData = mpEscherEx->StartShape( rObj.GetShapeRef(), (mpEscherEx->GetGroupLevel() > 1) ? &rObj.GetRect() : 0 ); + if ( mpHostAppData && mpHostAppData->DontWriteShape() ) + break; + + // #i51348# get shape name + String aShapeName; + if( const SdrObject* pSdrObj = rObj.GetSdrObject() ) + if( pSdrObj->GetName().Len() > 0 ) + aShapeName = pSdrObj->GetName(); + + Point aTextRefPoint; + + if( rObj.GetType().EqualsAscii( "drawing.Group" )) + { + Reference< XIndexAccess > xXIndexAccess( rObj.GetShapeRef(), UNO_QUERY ); + + if( xXIndexAccess.is() && 0 != xXIndexAccess->getCount() ) + { + nShapeID = mpEscherEx->EnterGroup( aShapeName, &rObj.GetRect() ); + nShapeType = ESCHER_ShpInst_Min; + + for( sal_uInt32 n = 0, nCnt = xXIndexAccess->getCount(); + n < nCnt; ++n ) + { + ImplEESdrObject aObj( *this, *(Reference< XShape >*) + xXIndexAccess->getByIndex( n ).getValue() ); + if( aObj.IsValid() ) + ImplWriteShape( aObj, rSolverContainer, ePageType ); + } + mpEscherEx->LeaveGroup(); + } + break; + } + rObj.SetAngle( rObj.ImplGetInt32PropertyValue( ::rtl::OUString::createFromAscii("RotateAngle") )); + + if( ( rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("IsFontwork") ) && + ::cppu::any2bool( rObj.GetUsrAny() ) ) || + rObj.GetType().EqualsAscii( "drawing.Measure" ) || rObj.GetType().EqualsAscii( "drawing.Caption" ) ) + { +/* + if( rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("BoundRect") ) ) + { + ::com::sun::star::awt::Rectangle aRect( *(::com::sun::star::awt::Rectangle*)rObj.GetUsrAny().getValue() ); + rObj.SetRect( ImplMapPoint( Point( aRect.X, aRect.Y ) ), + ImplMapSize( Size( aRect.Width, aRect.Height ) ) ); + } +*/ + rObj.SetType( String( RTL_CONSTASCII_STRINGPARAM( + "drawing.dontknow" ), + RTL_TEXTENCODING_MS_1252 )); + } + + const ::com::sun::star::awt::Size aSize100thmm( rObj.GetShapeRef()->getSize() ); + const ::com::sun::star::awt::Point aPoint100thmm( rObj.GetShapeRef()->getPosition() ); + Rectangle aRect100thmm( Point( aPoint100thmm.X, aPoint100thmm.Y ), Size( aSize100thmm.Width, aSize100thmm.Height ) ); + if ( !mpPicStrm ) + mpPicStrm = mpEscherEx->QueryPictureStream(); + EscherPropertyContainer aPropOpt( mpEscherEx->GetGraphicProvider(), mpPicStrm, aRect100thmm ); + + // #i51348# shape name + if( aShapeName.Len() > 0 ) + aPropOpt.AddOpt( ESCHER_Prop_wzName, aShapeName ); + + if ( rObj.GetType().EqualsAscii( "drawing.Custom" ) ) + { + mpEscherEx->OpenContainer( ESCHER_SpContainer ); + sal_uInt32 nMirrorFlags; + + rtl::OUString sCustomShapeType; + MSO_SPT eShapeType = aPropOpt.GetCustomShapeType( rObj.GetShapeRef(), nMirrorFlags, sCustomShapeType ); + if ( sCustomShapeType.equalsAscii( "col-502ad400" ) || sCustomShapeType.equalsAscii( "col-60da8460" ) ) + { + ADD_SHAPE( ESCHER_ShpInst_PictureFrame, 0xa00 ); + if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "MetaFile" ) ), sal_False ) ) + { + aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 ); + aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 ); // no fill + aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 ); // no linestyle + SdrObject* pObj = GetSdrObjectFromXShape( rObj.GetShapeRef() ); + if ( pObj ) + { + Rectangle aBound = pObj->GetCurrentBoundRect(); + Point aPosition( ImplMapPoint( aBound.TopLeft() ) ); + Size aSize( ImplMapSize( aBound.GetSize() ) ); + rObj.SetRect( Rectangle( aPosition, aSize ) ); + rObj.SetAngle( 0 ); + bDontWriteText = sal_True; + } + } + } + else + { + ADD_SHAPE( + sal::static_int_cast< sal_uInt16 >(eShapeType), + nMirrorFlags | 0xa00 ); + aPropOpt.CreateCustomShapeProperties( eShapeType, rObj.GetShapeRef() ); + aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True ); + if ( rObj.ImplGetText() ) + { + if ( !aPropOpt.IsFontWork() ) + aPropOpt.CreateTextProperties( rObj.mXPropSet, mpEscherEx->QueryTextID( + rObj.GetShapeRef(), rObj.GetShapeId() ), sal_True, sal_False ); + } + } + } + else if ( rObj.GetType().EqualsAscii( "drawing.Rectangle" )) + { + mpEscherEx->OpenContainer( ESCHER_SpContainer ); + sal_Int32 nRadius = (sal_Int32)rObj.ImplGetInt32PropertyValue( + ::rtl::OUString::createFromAscii("CornerRadius")); + if( nRadius ) + { + nRadius = ImplMapSize( Size( nRadius, 0 )).Width(); + ADD_SHAPE( ESCHER_ShpInst_RoundRectangle, 0xa00 ); // Flags: Connector | HasSpt + sal_Int32 nLenght = rObj.GetRect().GetWidth(); + if ( nLenght > rObj.GetRect().GetHeight() ) + nLenght = rObj.GetRect().GetHeight(); + nLenght >>= 1; + if ( nRadius >= nLenght ) + nRadius = 0x2a30; // 0x2a30 ist PPTs maximum radius + else + nRadius = ( 0x2a30 * nRadius ) / nLenght; + aPropOpt.AddOpt( ESCHER_Prop_adjustValue, nRadius ); + } + else + { + ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0xa00 ); // Flags: Connector | HasSpt + } + aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True ); + if( rObj.ImplGetText() ) + aPropOpt.CreateTextProperties( rObj.mXPropSet, + mpEscherEx->QueryTextID( rObj.GetShapeRef(), + rObj.GetShapeId() ), sal_False, sal_False ); + } + else if ( rObj.GetType().EqualsAscii( "drawing.Ellipse" )) + { + CircleKind eCircleKind = CircleKind_FULL; + PolyStyle ePolyKind = PolyStyle(); + if ( rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("CircleKind") ) ) + { + eCircleKind = *( (CircleKind*)rObj.GetUsrAny().getValue() ); + switch ( eCircleKind ) + { + case CircleKind_SECTION : + { + ePolyKind = POLY_PIE; + } + break; + case CircleKind_ARC : + { + ePolyKind = POLY_ARC; + } + break; + + case CircleKind_CUT : + { + ePolyKind = POLY_CHORD; + } + break; + + default: + eCircleKind = CircleKind_FULL; + } + } + if ( eCircleKind == CircleKind_FULL ) + { + mpEscherEx->OpenContainer( ESCHER_SpContainer ); + ADD_SHAPE( ESCHER_ShpInst_Ellipse, 0xa00 ); // Flags: Connector | HasSpt + aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );; + } + else + { + sal_Int32 nStartAngle, nEndAngle; + if ( !rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("CircleStartAngle") ) ) + break; + nStartAngle = *( (sal_Int32*)rObj.GetUsrAny().getValue() ); + if( !rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("CircleEndAngle") ) ) + break; + nEndAngle = *( (sal_Int32*)rObj.GetUsrAny().getValue() ); + + Point aStart, aEnd, aCenter; + aStart.X() = (sal_Int32)( ( cos( (double)( nStartAngle * + F_PI18000 ) ) * 100.0 ) ); + aStart.Y() = - (sal_Int32)( ( sin( (double)( nStartAngle * + F_PI18000 ) ) * 100.0 ) ); + aEnd.X() = (sal_Int32)( ( cos( (double)( nEndAngle * + F_PI18000 ) ) * 100.0 ) ); + aEnd.Y() = - (sal_Int32)( ( sin( (double)( nEndAngle * + F_PI18000 ) ) * 100.0 ) ); + const Rectangle& rRect = aRect100thmm; + aCenter.X() = rRect.Left() + ( rRect.GetWidth() / 2 ); + aCenter.Y() = rRect.Top() + ( rRect.GetHeight() / 2 ); + aStart.X() += aCenter.X(); + aStart.Y() += aCenter.Y(); + aEnd.X() += aCenter.X(); + aEnd.Y() += aCenter.Y(); + Polygon aPolygon( rRect, aStart, aEnd, ePolyKind ); + if( rObj.GetAngle() ) + { + aPolygon.Rotate( rRect.TopLeft(), (sal_uInt16)( rObj.GetAngle() / 10 ) ); + rObj.SetAngle( 0 ); + } + mpEscherEx->OpenContainer( ESCHER_SpContainer ); + ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 ); // Flags: Connector | HasSpt + ::com::sun::star::awt::Rectangle aNewRect; + switch ( ePolyKind ) + { + case POLY_PIE : + case POLY_CHORD : + { + aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, sal_False, aNewRect, &aPolygon ); + aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True ); + } + break; + + case POLY_ARC : + { + aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, sal_False, aNewRect, &aPolygon ); + aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False ); + } + break; + } + rObj.SetRect( Rectangle( ImplMapPoint( Point( aNewRect.X, aNewRect.Y ) ), + ImplMapSize( Size( aNewRect.Width, aNewRect.Height ) ) ) ); + } + if ( rObj.ImplGetText() ) + aPropOpt.CreateTextProperties( rObj.mXPropSet, + mpEscherEx->QueryTextID( rObj.GetShapeRef(), + rObj.GetShapeId() ), sal_False, sal_False ); + + } + else if ( rObj.GetType().EqualsAscii( "drawing.Control" )) + { + break; + } + else if ( rObj.GetType().EqualsAscii( "drawing.Connector" )) + { + sal_uInt16 nSpType, nSpFlags; + ::com::sun::star::awt::Rectangle aNewRect; + if ( aPropOpt.CreateConnectorProperties( rObj.GetShapeRef(), + rSolverContainer, aNewRect, nSpType, nSpFlags ) == sal_False ) + break; + rObj.SetRect( Rectangle( ImplMapPoint( Point( aNewRect.X, aNewRect.Y ) ), + ImplMapSize( Size( aNewRect.Width, aNewRect.Height ) ) ) ); + + mpEscherEx->OpenContainer( ESCHER_SpContainer ); + ADD_SHAPE( nSpType, nSpFlags ); + } + else if ( rObj.GetType().EqualsAscii( "drawing.Measure" )) + { +/* + if ( ImplGetPropertyValue( L"MeasureKind" ) ) + { + mpEscherEx->EnterGroup( &maRect ); + mpEscherEx->OpenContainer( ESCHER_SpContainer ); + ImplWriteAny( ANY_FLAGS_LINE, sal_False ); + sal_uInt32 nFlags = 0xa00; // Flags: Connector | HasSpt + if ( maRect.Top() > maRect.Bottom() ) + nFlags |= 0x80; // Flags: VertMirror + if ( maRect.Left() > maRect.Right() ) + nFlags |= 0x40; // Flags: HorzMirror + + ADD_SHAPE( ESCHER_ShpInst_Line, nFlags ); + aPropOpt.AddOpt( ESCHER_Prop_shapePath, ESCHER_ShapeComplex ); + aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False ); + mpEscherEx->EndCount( ESCHER_OPT, 3 ); + maRect.Justify(); + mpEscherEx->AddClientAnchor( maRect ); + mpEscherEx->CloseContainer(); // ESCHER_SpContainer + + if ( ImplGetPropertyValue( L"MeasureTextHorizontalPosition" ) ) + { + } + if ( ImplGetPropertyValue( L"MeasureTextVerticalPosition" ) ) + { + } + if ( ImplGetPropertyValue( L"MeasureLineDistance" ) ) + { + } + if ( ImplGetPropertyValue( L"MeasureHelpLineOverhang" ) ) + { + } + if ( ImplGetPropertyValue( L"MeasureHelpLineDistance" ) ) + { + } + if ( ImplGetPropertyValue( L"MeasureHelpLine1Length" ) ) + { + } + if ( ImplGetPropertyValue( L"MeasureHelpLine2Length" ) ) + { + } + if ( ImplGetPropertyValue( L"MeasureBelowReferenceEdge" ) ) + { + } + if ( ImplGetPropertyValue( L"MeasureTextRotate90" ) ) + { + } + if ( ImplGetPropertyValue( L"MeasureTextUpsideDown" ) ) + { + } + if ( ImplGetPropertyValue( L"MeasureOverhang" ) ) + { + } + if ( ImplGetPropertyValue( L"MeasureUnit" ) ) + { + } + if ( ImplGetPropertyValue( L"MeasureScale" ) ) + { + } + if ( ImplGetPropertyValue( L"MeasureShowUnit" ) ) + { + } + if ( ImplGetPropertyValue( L"MeasureFormatString" ) ) + { + } + if ( ImplGetPropertyValue( L"MeasureTextAutoAngle" ) ) + { + } + if ( ImplGetPropertyValue( L"MeasureTextAutoAngleView" ) ) + { + } + if ( ImplGetPropertyValue( L"MeasureTextIsFixedAngle" ) ) + { + } + if ( ImplGetPropertyValue( L"MeasureTextFixedAngle" ) ) + { + } + mpEscherEx->LeaveGroup(); + } +*/ + break; + } + else if ( rObj.GetType().EqualsAscii( "drawing.Line" )) + { + ::com::sun::star::awt::Rectangle aNewRect; + aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_LINE, sal_False, aNewRect, NULL ); + MapRect(rObj); + //i27942: Poly/Lines/Bezier do not support text. + + mpEscherEx->OpenContainer( ESCHER_SpContainer ); + sal_uInt32 nFlags = 0xa00; // Flags: Connector | HasSpt + if( aNewRect.Height < 0 ) + nFlags |= 0x80; // Flags: VertMirror + if( aNewRect.Width < 0 ) + nFlags |= 0x40; // Flags: HorzMirror + + ADD_SHAPE( ESCHER_ShpInst_Line, nFlags ); + aPropOpt.AddOpt( ESCHER_Prop_shapePath, ESCHER_ShapeComplex ); + aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False ); + rObj.SetAngle( 0 ); + } + else if ( rObj.GetType().EqualsAscii( "drawing.PolyPolygon" )) + { + if( rObj.ImplHasText() ) + { + nGrpShapeID = ImplEnterAdditionalTextGroup( rObj.GetShapeRef(), &rObj.GetRect() ); + bAdditionalText = sal_True; + } + mpEscherEx->OpenContainer( ESCHER_SpContainer ); + ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 ); // Flags: Connector | HasSpt + ::com::sun::star::awt::Rectangle aNewRect; + aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, sal_False, aNewRect, NULL ); + MapRect(rObj); + aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True ); + rObj.SetAngle( 0 ); + } + else if ( rObj.GetType().EqualsAscii( "drawing.PolyLine" )) + { + //i27942: Poly/Lines/Bezier do not support text. + + mpEscherEx->OpenContainer( ESCHER_SpContainer ); + ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 ); // Flags: Connector | HasSpt + ::com::sun::star::awt::Rectangle aNewRect; + aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, sal_False, aNewRect, NULL ); + MapRect(rObj); + aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False ); + rObj.SetAngle( 0 ); + } + else if ( rObj.GetType().EqualsAscii( "drawing.OpenBezier" ) ) + { + //i27942: Poly/Lines/Bezier do not support text. + + mpEscherEx->OpenContainer( ESCHER_SpContainer ); + ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 ); // Flags: Connector | HasSpt + ::com::sun::star::awt::Rectangle aNewRect; + aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, sal_True, aNewRect, NULL ); + MapRect(rObj); + aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False ); + rObj.SetAngle( 0 ); + } + else if ( rObj.GetType().EqualsAscii( "drawing.ClosedBezier" ) ) + { + if ( rObj.ImplHasText() ) + { + nGrpShapeID = ImplEnterAdditionalTextGroup( rObj.GetShapeRef(), &rObj.GetRect() ); + bAdditionalText = sal_True; + } + mpEscherEx->OpenContainer( ESCHER_SpContainer ); + ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 ); // Flags: Connector | HasSpt + ::com::sun::star::awt::Rectangle aNewRect; + aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, sal_True, aNewRect, NULL ); + MapRect(rObj); + aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True ); + rObj.SetAngle( 0 ); + } + else if ( rObj.GetType().EqualsAscii( "drawing.GraphicObject" )) + { + mpEscherEx->OpenContainer( ESCHER_SpContainer ); + + // ein GraphicObject kann auch ein ClickMe Element sein + if( rObj.IsEmptyPresObj() && ( ePageType == NORMAL ) ) + { + ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0x220 ); // Flags: HaveAnchor | HaveMaster + sal_uInt32 nTxtBxId = mpEscherEx->QueryTextID( rObj.GetShapeRef(), + rObj.GetShapeId() ); + aPropOpt.AddOpt( ESCHER_Prop_lTxid, nTxtBxId ); + aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x10001 ); + aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x10001 ); + aPropOpt.AddOpt( ESCHER_Prop_hspMaster, mnShapeMasterBody ); + } + else + { + if( rObj.ImplGetText() ) + { + /* SJ #i34951#: because M. documents are not allowing GraphicObjects containing text, we + have to create a simpe Rectangle with fill bitmap instead (while not allowing BitmapMode_Repeat). + */ + ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0xa00 ); // Flags: Connector | HasSpt + if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "GraphicURL" ) ), sal_True, sal_True, sal_False ) ) + { + aPropOpt.AddOpt( ESCHER_Prop_WrapText, ESCHER_WrapNone ); + aPropOpt.AddOpt( ESCHER_Prop_AnchorText, ESCHER_AnchorMiddle ); + aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 ); + aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x8000000 ); + aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 ); + if ( rObj.ImplGetText() ) + aPropOpt.CreateTextProperties( rObj.mXPropSet, + mpEscherEx->QueryTextID( rObj.GetShapeRef(), + rObj.GetShapeId() ), sal_False, sal_False ); + } + } + else + { + ADD_SHAPE( ESCHER_ShpInst_PictureFrame, 0xa00 ); + if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "GraphicURL" ) ), sal_False, sal_True ) ) + aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 ); + } + } + } + else if ( rObj.GetType().EqualsAscii( "drawing.Text" )) + { + SHAPE_TEXT( sal_True ); + } + else if ( rObj.GetType().EqualsAscii( "drawing.Page" )) + { + mpEscherEx->OpenContainer( ESCHER_SpContainer ); + ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0xa00 ); + aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x40004 ); + aPropOpt.AddOpt( ESCHER_Prop_fFillOK, 0x100001 ); + aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x110011 ); + aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90008 ); + aPropOpt.AddOpt( ESCHER_Prop_fshadowObscured, 0x10001 ); + } + else if ( rObj.GetType().EqualsAscii( "drawing.Frame" )) + { + break; + } + else if ( rObj.GetType().EqualsAscii( "drawing.OLE2" )) + { + mpEscherEx->OpenContainer( ESCHER_SpContainer ); + if( rObj.IsEmptyPresObj() && ( ePageType == NORMAL ) ) + { + ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0x220 ); // Flags: HaveAnchor | HaveMaster + sal_uInt32 nTxtBxId = mpEscherEx->QueryTextID( rObj.GetShapeRef(), + rObj.GetShapeId() ); + aPropOpt.AddOpt( ESCHER_Prop_lTxid, nTxtBxId ); + aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x10001 ); + aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x10001 ); + aPropOpt.AddOpt( ESCHER_Prop_hspMaster, mnShapeMasterBody ); + } + else + { + //2do: could be made an option in HostAppData whether OLE object should be written or not + sal_Bool bAppOLE = sal_True; + ADD_SHAPE( ESCHER_ShpInst_PictureFrame, + 0xa00 | (bAppOLE ? SHAPEFLAG_OLESHAPE : 0) ); + if ( aPropOpt.CreateOLEGraphicProperties( rObj.GetShapeRef() ) ) + { + if ( bAppOLE ) + { // snooped from Xcl hex dump, nobody knows the trouble I have seen + aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x00080008 ); + aPropOpt.AddOpt( ESCHER_Prop_pictureId, 0x00000001 ); + aPropOpt.AddOpt( ESCHER_Prop_fillColor, 0x08000041 ); + aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x08000041 ); + aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x00110010 ); + aPropOpt.AddOpt( ESCHER_Prop_lineColor, 0x08000040 ); + aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash,0x00080008 ); +// aPropOpt.AddOpt( ESCHER_Prop_fshadowObscured,0x00020000 ); + aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x00080000 ); + } + aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 ); + } + } + } + else if( '3' == rObj.GetType().GetChar(8 ) && + 'D' == rObj.GetType().GetChar( 9 ) ) // drawing.3D + { + // SceneObject, CubeObject, SphereObject, LatheObject, ExtrudeObject, PolygonObject + if ( !rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("Bitmap") ) ) + break; + + mpEscherEx->OpenContainer( ESCHER_SpContainer ); + ADD_SHAPE( ESCHER_ShpInst_PictureFrame, 0xa00 ); + + if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "Bitmap" ) ), sal_False ) ) + aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 ); + } + else if ( rObj.GetType().EqualsAscii( "drawing.dontknow" )) + { + rObj.SetAngle( 0 ); + mpEscherEx->OpenContainer( ESCHER_SpContainer ); + ADD_SHAPE( ESCHER_ShpInst_PictureFrame, 0xa00 ); + if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "MetaFile" ) ), sal_False ) ) + aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 ); + } + else + { + break; + } + aPropOpt.CreateShadowProperties( rObj.mXPropSet ); + + if( USHRT_MAX != mpEscherEx->GetHellLayerId() && + rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("LayerID") ) && + (*((sal_uInt16*)rObj.GetUsrAny().getValue()) ) == mpEscherEx->GetHellLayerId() ) + { + aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x200020 ); + } + + { + Rectangle aRect( rObj.GetRect() ); + aRect.Justify(); + rObj.SetRect( aRect ); + } + + if( rObj.GetAngle() ) + ImplFlipBoundingBox( rObj, aPropOpt ); + + aPropOpt.CreateShapeProperties( rObj.GetShapeRef() ); + mpEscherEx->Commit( aPropOpt, rObj.GetRect() ); + if( mpEscherEx->GetGroupLevel() > 1 ) + mpEscherEx->AddChildAnchor( rObj.GetRect() ); + + if ( mpHostAppData ) + { //! with AdditionalText the App has to control whether these are written or not + mpHostAppData->WriteClientAnchor( *mpEscherEx, rObj.GetRect() ); + mpHostAppData->WriteClientData( *mpEscherEx ); + if ( !bDontWriteText ) + mpHostAppData->WriteClientTextbox( *mpEscherEx ); + } + mpEscherEx->CloseContainer(); // ESCHER_SpContainer + + if( bAdditionalText ) + { + mpEscherEx->EndShape( nShapeType, nShapeID ); + ImplWriteAdditionalText( rObj, aTextRefPoint ); + } + + } while ( 0 ); + + if ( bAdditionalText ) + mpEscherEx->EndShape( ESCHER_ShpInst_Min, nGrpShapeID ); + else + mpEscherEx->EndShape( nShapeType, nShapeID ); + return nShapeID; +} + +void ImplEESdrWriter::ImplWriteAdditionalText( ImplEESdrObject& rObj, + const Point& rTextRefPoint ) +{ + sal_uInt32 nShapeID = 0; + sal_uInt16 nShapeType = 0; + do + { + mpHostAppData = mpEscherEx->StartShape( rObj.GetShapeRef(), (mpEscherEx->GetGroupLevel() > 1) ? &rObj.GetRect() : 0 ); + if ( mpHostAppData && mpHostAppData->DontWriteShape() ) + break; + + const ::com::sun::star::awt::Size aSize100thmm( rObj.GetShapeRef()->getSize() ); + const ::com::sun::star::awt::Point aPoint100thmm( rObj.GetShapeRef()->getPosition() ); + Rectangle aRect100thmm( Point( aPoint100thmm.X, aPoint100thmm.Y ), Size( aSize100thmm.Width, aSize100thmm.Height ) ); + if ( !mpPicStrm ) + mpPicStrm = mpEscherEx->QueryPictureStream(); + EscherPropertyContainer aPropOpt( mpEscherEx->GetGraphicProvider(), mpPicStrm, aRect100thmm ); + rObj.SetAngle( rObj.ImplGetInt32PropertyValue( ::rtl::OUString::createFromAscii("RotateAngle"))); + sal_Int32 nAngle = rObj.GetAngle(); + if( rObj.GetType().EqualsAscii( "drawing.Line" )) + { +//2do: this does not work right + double fDist = hypot( rObj.GetRect().GetWidth(), + rObj.GetRect().GetHeight() ); + rObj.SetRect( Rectangle( rTextRefPoint, + Point( (sal_Int32)( rTextRefPoint.X() + fDist ), rTextRefPoint.Y() - 1 ) ) ); + + mpEscherEx->OpenContainer( ESCHER_SpContainer ); + mpEscherEx->AddShape( ESCHER_ShpInst_TextBox, 0xa00 ); + if ( rObj.ImplGetText() ) + aPropOpt.CreateTextProperties( rObj.mXPropSet, + mpEscherEx->QueryTextID( rObj.GetShapeRef(), + rObj.GetShapeId() ) ); + + aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 ); + aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 ); + aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x60006 ); // Size Shape To Fit Text + if ( nAngle < 0 ) + nAngle = ( 36000 + nAngle ) % 36000; + if ( nAngle ) + ImplFlipBoundingBox( rObj, aPropOpt ); + } + else + { + mpEscherEx->OpenContainer( ESCHER_SpContainer ); + nShapeID = mpEscherEx->GenerateShapeId(); + mpEscherEx->AddShape( nShapeType = ESCHER_ShpInst_TextBox, 0xa00, nShapeID ); + if ( rObj.ImplGetText() ) + aPropOpt.CreateTextProperties( rObj.mXPropSet, + mpEscherEx->QueryTextID( rObj.GetShapeRef(), + rObj.GetShapeId() ) ); + aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 ); + aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 ); + + if( nAngle < 0 ) + nAngle = ( 36000 + nAngle ) % 36000; + else + nAngle = ( 36000 - ( nAngle % 36000 ) ); + + nAngle *= 655; + nAngle += 0x8000; + nAngle &=~0xffff; // nAngle auf volle Gradzahl runden + aPropOpt.AddOpt( ESCHER_Prop_Rotation, nAngle ); + mpEscherEx->SetGroupSnapRect( mpEscherEx->GetGroupLevel(), + rObj.GetRect() ); + mpEscherEx->SetGroupLogicRect( mpEscherEx->GetGroupLevel(), + rObj.GetRect() ); + } + rObj.SetAngle( nAngle ); + aPropOpt.CreateShapeProperties( rObj.GetShapeRef() ); + mpEscherEx->Commit( aPropOpt, rObj.GetRect() ); + + // write the childanchor + mpEscherEx->AddChildAnchor( rObj.GetRect() ); + +#if defined EES_WRITE_EPP + // ClientAnchor + mpEscherEx->AddClientAnchor( maRect ); + // ClientTextbox + mpEscherEx->OpenContainer( ESCHER_ClientTextbox ); + mpEscherEx->AddAtom( 4, EPP_TextHeaderAtom ); + *mpStrm << (sal_uInt32)EPP_TEXTTYPE_Other; // Text in a Shape + ImplWriteTextStyleAtom(); + mpEscherEx->CloseContainer(); // ESCHER_ClientTextBox +#else // !EES_WRITE_EPP + if ( mpHostAppData ) + { //! the App has to control whether these are written or not + mpHostAppData->WriteClientAnchor( *mpEscherEx, rObj.GetRect() ); + mpHostAppData->WriteClientData( *mpEscherEx ); + mpHostAppData->WriteClientTextbox( *mpEscherEx ); + } +#endif // EES_WRITE_EPP + mpEscherEx->CloseContainer(); // ESCHER_SpContainer + } while ( 0 ); + mpEscherEx->LeaveGroup(); + mpEscherEx->EndShape( nShapeType, nShapeID ); +} + + +// ------------------------------------------------------------------- + +sal_uInt32 ImplEESdrWriter::ImplEnterAdditionalTextGroup( const Reference< XShape >& rShape, + const Rectangle* pBoundRect ) +{ + mpHostAppData = mpEscherEx->EnterAdditionalTextGroup(); + sal_uInt32 nGrpId = mpEscherEx->EnterGroup( pBoundRect ); + mpHostAppData = mpEscherEx->StartShape( rShape, pBoundRect ); + return nGrpId; +} + + +// ------------------------------------------------------------------- + +sal_Bool ImplEESdrWriter::ImplInitPageValues() +{ + mnIndices = 0; + mnOutlinerCount = 0; // die gliederungsobjekte muessen dem layout entsprechen, + mnEffectCount = 0; + mbIsTitlePossible = sal_True; // bei mehr als einem title geht powerpoint in die knie + + return sal_True; +} + + +// ------------------------------------------------------------------- + +void ImplEESdrWriter::ImplWritePage( + EscherSolverContainer& rSolverContainer, + ImplEESdrPageType ePageType, sal_Bool /* bBackGround */ ) +{ + ImplInitPageValues(); + + sal_uInt32 nLastPer = 0, nShapes = mXShapes->getCount(); + for( sal_uInt32 n = 0; n < nShapes; ++n ) + { + sal_uInt32 nPer = ( 5 * n ) / nShapes; + if( nPer != nLastPer ) + { + nLastPer = nPer; + sal_uInt32 nValue = mnPagesWritten * 5 + nPer; + if( nValue > mnStatMaxValue ) + nValue = mnStatMaxValue; + if( mbStatusIndicator ) + mXStatusIndicator->setValue( nValue ); + } + + ImplEESdrObject aObj( *this, *(Reference< XShape >*) + mXShapes->getByIndex( n ).getValue() ); + if( aObj.IsValid() ) + { + ImplWriteShape( aObj, rSolverContainer, ePageType ); + } + } + mnPagesWritten++; +} + +// =================================================================== + +ImplEscherExSdr::ImplEscherExSdr( EscherEx& rEx ) + : + ImplEESdrWriter( rEx ), + mpSdrPage( NULL ), + mpSolverContainer( NULL ) +{ +} + + +// ------------------------------------------------------------------- + +ImplEscherExSdr::~ImplEscherExSdr() +{ + DBG_ASSERT( !mpSolverContainer, "ImplEscherExSdr::~ImplEscherExSdr: unwritten SolverContainer" ); + delete mpSolverContainer; +} + + +// ------------------------------------------------------------------- + +bool ImplEscherExSdr::ImplInitPage( const SdrPage& rPage ) +{ + do + { + SvxDrawPage* pSvxDrawPage; + if ( mpSdrPage != &rPage || !mXDrawPage.is() ) + { + // eventually write SolverContainer of current page, deletes the Solver + ImplFlushSolverContainer(); + + mpSdrPage = NULL; + // why not declare a const parameter if the object will not be modified? +// mXDrawPage = pSvxDrawPage = new SvxDrawPage( (SdrPage*) &rPage ); + mXDrawPage = pSvxDrawPage = new SvxFmDrawPage( (SdrPage*) &rPage ); + mXShapes = Reference< XShapes >::query( mXDrawPage ); + if ( !mXShapes.is() ) + break; + if ( !ImplInitPageValues() ) // ImplEESdrWriter + break; + mpSdrPage = &rPage; + + mpSolverContainer = new EscherSolverContainer; + } + else + pSvxDrawPage = SvxDrawPage::getImplementation(mXDrawPage); + + return pSvxDrawPage != 0; + } while ( 0 ); + + return false; +} + +// ------------------------------------------------------------------- + +bool ImplEscherExSdr::ImplInitUnoShapes( const Reference< XShapes >& rxShapes ) +{ + // eventually write SolverContainer of current page, deletes the Solver + ImplFlushSolverContainer(); + + if( !rxShapes.is() ) + return false; + + mpSdrPage = 0; + mXDrawPage.clear(); + mXShapes = rxShapes; + + if( !ImplInitPageValues() ) // ImplEESdrWriter + return false; + + mpSolverContainer = new EscherSolverContainer; + return true; +} + +// ------------------------------------------------------------------- + +void ImplEscherExSdr::ImplExitPage() +{ + // close all groups before the solver container is written + while( mpEscherEx->GetGroupLevel() ) + mpEscherEx->LeaveGroup(); + + ImplFlushSolverContainer(); + mpSdrPage = NULL; // reset page for next init +} + + +// ------------------------------------------------------------------- + +void ImplEscherExSdr::ImplFlushSolverContainer() +{ + if ( mpSolverContainer ) + { + mpSolverContainer->WriteSolver( mpEscherEx->GetStream() ); + delete mpSolverContainer; + mpSolverContainer = NULL; + } +} + + +// ------------------------------------------------------------------- + +void ImplEscherExSdr::ImplWriteCurrentPage() +{ + DBG_ASSERT( mpSolverContainer, "ImplEscherExSdr::ImplWriteCurrentPage: no SolverContainer" ); + ImplWritePage( *mpSolverContainer, NORMAL ); + ImplExitPage(); +} + + +// ------------------------------------------------------------------- + +sal_uInt32 ImplEscherExSdr::ImplWriteTheShape( ImplEESdrObject& rObj ) +{ + DBG_ASSERT( mpSolverContainer, "ImplEscherExSdr::ImplWriteShape: no SolverContainer" ); + return ImplWriteShape( rObj, *mpSolverContainer, NORMAL ); +} + + +// =================================================================== + +void EscherEx::AddSdrPage( const SdrPage& rPage ) +{ + if ( mpImplEscherExSdr->ImplInitPage( rPage ) ) + mpImplEscherExSdr->ImplWriteCurrentPage(); +} + +// ------------------------------------------------------------------- + +void EscherEx::AddUnoShapes( const Reference< XShapes >& rxShapes ) +{ + if ( mpImplEscherExSdr->ImplInitUnoShapes( rxShapes ) ) + mpImplEscherExSdr->ImplWriteCurrentPage(); +} + +// ------------------------------------------------------------------- + +sal_uInt32 EscherEx::AddSdrObject( const SdrObject& rObj ) +{ + ImplEESdrObject aObj( *mpImplEscherExSdr, rObj ); + if( aObj.IsValid() ) + return mpImplEscherExSdr->ImplWriteTheShape( aObj ); + return 0; +} + + +// ------------------------------------------------------------------- + +void EscherEx::EndSdrObjectPage() +{ + mpImplEscherExSdr->ImplExitPage(); +} + +// ------------------------------------------------------------------- + +EscherExHostAppData* EscherEx::StartShape( const Reference< XShape >& /* rShape */, const Rectangle* /*pChildAnchor*/ ) +{ + return NULL; +} + +// ------------------------------------------------------------------- + +void EscherEx::EndShape( sal_uInt16 /* nShapeType */, sal_uInt32 /* nShapeID */ ) +{ +} + +// ------------------------------------------------------------------- + +sal_uInt32 EscherEx::QueryTextID( const Reference< XShape >&, sal_uInt32 ) +{ + return 0; +} + +// ------------------------------------------------------------------- +// add an dummy rectangle shape into the escher stream +sal_uInt32 EscherEx::AddDummyShape() +{ + OpenContainer( ESCHER_SpContainer ); + sal_uInt32 nShapeID = GenerateShapeId(); + AddShape( ESCHER_ShpInst_Rectangle, 0xa00, nShapeID ); +//?? aSolverContainer.AddShape( mXShape, nShapeID ); + CloseContainer(); + + return nShapeID; +} + +// ------------------------------------------------------------------- + +// static +const SdrObject* EscherEx::GetSdrObject( const Reference< XShape >& rShape ) +{ + const SdrObject* pRet = 0; + const SvxShape* pSvxShape = SvxShape::getImplementation( rShape ); + DBG_ASSERT( pSvxShape, "EscherEx::GetSdrObject: no SvxShape" ); + if( pSvxShape ) + { + pRet = pSvxShape->GetSdrObject(); + DBG_ASSERT( pRet, "EscherEx::GetSdrObject: no SdrObj" ); + } + return pRet; +} + + +// ------------------------------------------------------------------- + +ImplEESdrObject::ImplEESdrObject( ImplEscherExSdr& rEx, + const SdrObject& rObj ) : + mnShapeId( 0 ), + mnTextSize( 0 ), + mnAngle( 0 ), + mbValid( sal_False ), + mbPresObj( sal_False ), + mbEmptyPresObj( sal_False ) +{ + SdrPage* pPage = rObj.GetPage(); + DBG_ASSERT( pPage, "ImplEESdrObject::ImplEESdrObject: no SdrPage" ); + if( pPage && rEx.ImplInitPage( *pPage ) ) + { + // why not declare a const parameter if the object will + // not be modified? + mXShape = uno::Reference< drawing::XShape >::query( ((SdrObject*)&rObj)->getUnoShape() );; + Init( rEx ); + } +} + +ImplEESdrObject::ImplEESdrObject( ImplEESdrWriter& rEx, + const Reference< XShape >& rShape ) : + mXShape( rShape ), + mnShapeId( 0 ), + mnTextSize( 0 ), + mnAngle( 0 ), + mbValid( sal_False ), + mbPresObj( sal_False ), + mbEmptyPresObj( sal_False ) +{ + Init( rEx ); +} + + +ImplEESdrObject::~ImplEESdrObject() +{ +} + +void ImplEESdrObject::Init( ImplEESdrWriter& rEx ) +{ + mXPropSet = Reference< XPropertySet >::query( mXShape ); + if( mXPropSet.is() ) + { + static const sal_Char aPrefix[] = "com.sun.star."; + static const xub_StrLen nPrefix = sizeof(aPrefix)-1; + SetRect( rEx.ImplMapPoint( Point( mXShape->getPosition().X, mXShape->getPosition().Y ) ), + rEx.ImplMapSize( Size( mXShape->getSize().Width, mXShape->getSize().Height ) ) ); + mType = String( mXShape->getShapeType() ); + mType.Erase( 0, nPrefix ); // strip "com.sun.star." + xub_StrLen nPos = mType.SearchAscii( "Shape" ); + mType.Erase( nPos, 5 ); + + static const OUString sPresStr(rtl::OUString::createFromAscii("IsPresentationObject")); + static const OUString sEmptyPresStr(rtl::OUString::createFromAscii("IsEmptyPresentationObject")); + + if( ImplGetPropertyValue( sPresStr ) ) + mbPresObj = ::cppu::any2bool( mAny ); + + if( mbPresObj && ImplGetPropertyValue( sEmptyPresStr ) ) + mbEmptyPresObj = ::cppu::any2bool( mAny ); + + mbValid = sal_True; + } +} + +//sal_Bool ImplEESdrObject::ImplGetPropertyValue( const OUString& rString ) +sal_Bool ImplEESdrObject::ImplGetPropertyValue( const sal_Unicode* rString ) +{ + sal_Bool bRetValue = sal_False; + if( mbValid ) + { + try + { + mAny = mXPropSet->getPropertyValue( rString ); + if( mAny.hasValue() ) + bRetValue = sal_True; + } + catch( ::com::sun::star::uno::Exception& ) + { + bRetValue = sal_False; + } + } + return bRetValue; +} + +#ifdef USED +sal_Bool ImplEESdrObject::ImplGetPropertyValue( const Reference< XPropertySet >& rXPropSet, + const OUString& rString ) +{ + sal_Bool bRetValue = sal_False; + if( mbValid ) + { + try + { + mAny = rXPropSet->getPropertyValue( rString ); + if( 0 != mAny.get() ) + bRetValue = sal_True; + } + catch( ::com::sun::star::uno::Exception& ) + { + bRetValue = sal_False; + } + } + return bRetValue; +} +#endif + +void ImplEESdrObject::SetRect( const Point& rPos, const Size& rSz ) +{ + maRect = Rectangle( rPos, rSz ); +} + +const SdrObject* ImplEESdrObject::GetSdrObject() const +{ + return EscherEx::GetSdrObject( mXShape ); +} + +// laedt und konvertiert text aus shape, ergebnis ist mnTextSize gespeichert +sal_uInt32 ImplEESdrObject::ImplGetText() +{ + Reference< XText > xXText( mXShape, UNO_QUERY ); + mnTextSize = 0; + if( xXText.is() ) + mnTextSize = xXText->getString().getLength(); + return mnTextSize; +} + +sal_Bool ImplEESdrObject::ImplHasText() const +{ + Reference< XText > xXText( mXShape, UNO_QUERY ); + return xXText.is() && xXText->getString().getLength(); +} + diff --git a/filter/source/msfilter/eschesdo.hxx b/filter/source/msfilter/eschesdo.hxx new file mode 100644 index 000000000000..d203982b4736 --- /dev/null +++ b/filter/source/msfilter/eschesdo.hxx @@ -0,0 +1,206 @@ +/************************************************************************* + * + * 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 _ESCHESDO_HXX +#define _ESCHESDO_HXX +#include <filter/msfilter/escherex.hxx> +#include <svx/unopage.hxx> +#include <vcl/mapmod.hxx> + +// =================================================================== +// fractions of Draw PPTWriter etc. + +enum ImplEESdrPageType { NORMAL = 0, MASTER = 1, NOTICE = 2, UNDEFINED = 3 }; + +class ImplEESdrWriter; +class ImplEscherExSdr; + +class ImplEESdrObject +{ + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > mXShape; +// XTextRef mXText; // TextRef des globalen Text + ::com::sun::star::uno::Any mAny; + Rectangle maRect; + String mType; + sal_uInt32 mnShapeId; + sal_uInt32 mnTextSize; + sal_Int32 mnAngle; + sal_Bool mbValid : 1; + sal_Bool mbPresObj : 1; + sal_Bool mbEmptyPresObj : 1; + + void Init( ImplEESdrWriter& rEx ); +public: + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > mXPropSet; + + ImplEESdrObject( ImplEscherExSdr& rEx, const SdrObject& rObj ); + ImplEESdrObject( ImplEESdrWriter& rEx, const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& rShape ); + ~ImplEESdrObject(); + + sal_Bool ImplGetPropertyValue( const sal_Unicode* pString ); + + sal_Int32 ImplGetInt32PropertyValue( const sal_Unicode* pStr, sal_uInt32 nDef = 0 ) + { return ImplGetPropertyValue( pStr ) ? *(sal_Int32*)mAny.getValue() : nDef; } + + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& GetShapeRef() const { return mXShape; } + const ::com::sun::star::uno::Any& GetUsrAny() const { return mAny; } + const String& GetType() const { return mType; } + void SetType( const String& rS ) { mType = rS; } + + const Rectangle& GetRect() const { return maRect; } + void SetRect( const Point& rPos, const Size& rSz ); + void SetRect( const Rectangle& rRect ) + { maRect = rRect; } + + sal_Int32 GetAngle() const { return mnAngle; } + void SetAngle( sal_Int32 nVal ) { mnAngle = nVal; } + + sal_uInt32 GetTextSize() const { return mnTextSize; } + + sal_Bool IsValid() const { return mbValid; } + sal_Bool IsPresObj() const { return mbPresObj; } + sal_Bool IsEmptyPresObj() const { return mbEmptyPresObj; } + sal_uInt32 GetShapeId() const { return mnShapeId; } + void SetShapeId( sal_uInt32 nVal ) { mnShapeId = nVal; } + + const SdrObject* GetSdrObject() const; + + sal_uInt32 ImplGetText(); + sal_Bool ImplHasText() const; +}; + + + +// ------------------------------------------------------------------- +// fractions of the Draw PPTWriter + +class EscherEx; +namespace com { namespace sun { namespace star { + namespace drawing { + class XDrawPage; + class XShape; + } + namespace task { + class XStatusIndicator; + } +}}} +class EscherExHostAppData; +class Polygon; + +class ImplEESdrWriter +{ +protected: + EscherEx* mpEscherEx; + MapMode maMapModeSrc; + MapMode maMapModeDest; + + ::com::sun::star::uno::Reference< ::com::sun::star::task::XStatusIndicator > mXStatusIndicator; + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage > mXDrawPage; + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > mXShapes; + + SvStream* mpPicStrm; + + // own extensions + + EscherExHostAppData* mpHostAppData; + + sal_uInt32 mnPagesWritten; + + sal_uInt32 mnShapeMasterTitle; + sal_uInt32 mnShapeMasterBody; + + // per page values + sal_uInt32 mnIndices; + sal_uInt32 mnOutlinerCount; + sal_uInt32 mnPrevTextStyle; + sal_uInt32 mnStatMaxValue; + + sal_uInt16 mnEffectCount; + + sal_Bool mbIsTitlePossible; + sal_Bool mbStatusIndicator; + sal_Bool mbStatus; + + + ImplEESdrWriter( EscherEx& rEx ); + + sal_Bool ImplInitPageValues(); + + void ImplWritePage( + EscherSolverContainer& rSolver, + ImplEESdrPageType ePageType, + sal_Bool bBackGround = sal_False ); + + sal_uInt32 ImplWriteShape( ImplEESdrObject& rObj, + EscherSolverContainer& rSolver, + ImplEESdrPageType ePageType ); // returns ShapeID + + void ImplFlipBoundingBox( ImplEESdrObject& rObj, EscherPropertyContainer& rPropOpt ); + sal_Bool ImplGetText( ImplEESdrObject& rObj ); + void ImplWriteAdditionalText( + ImplEESdrObject& rObj, + const Point& rTextRefPoint ); + sal_uInt32 ImplEnterAdditionalTextGroup( + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& rShape, + const Rectangle* pBoundRect = NULL ); + + +public: + Point ImplMapPoint( const Point& rPoint ); + Size ImplMapSize( const Size& rSize ); + EscherExHostAppData* ImplGetHostData() { return mpHostAppData; } + void MapRect(ImplEESdrObject& rObj); +}; + + +// =================================================================== + +class SdrObject; +class SdrPage; + +class ImplEscherExSdr : public ImplEESdrWriter +{ +private: + const SdrPage* mpSdrPage; + EscherSolverContainer* mpSolverContainer; + +public: + ImplEscherExSdr( EscherEx& rEx ); + virtual ~ImplEscherExSdr(); + + bool ImplInitPage( const SdrPage& rPage ); + bool ImplInitUnoShapes( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes ); + void ImplWriteCurrentPage(); + + sal_uInt32 ImplWriteTheShape( ImplEESdrObject& rObj ); + + void ImplExitPage(); + void ImplFlushSolverContainer(); +}; + + + +#endif // _ESCHESDO_HXX diff --git a/filter/source/msfilter/makefile.mk b/filter/source/msfilter/makefile.mk new file mode 100644 index 000000000000..96a4a616bfb2 --- /dev/null +++ b/filter/source/msfilter/makefile.mk @@ -0,0 +1,94 @@ +#************************************************************************* +# +# 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=filter +TARGET=msfilter + +ENABLE_EXCEPTIONS=TRUE +LIBTARGET=NO + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES= \ + $(SLO)$/countryid.obj \ + $(SLO)$/escherex.obj \ + $(SLO)$/eschesdo.obj \ + $(SLO)$/mscodec.obj \ + $(SLO)$/msdffimp.obj \ + $(SLO)$/msfiltertracer.obj \ + $(SLO)$/msocximex.obj \ + $(SLO)$/msoleexp.obj \ + $(SLO)$/msvbahelper.obj \ + $(SLO)$/msvbasic.obj \ + $(SLO)$/services.obj \ + $(SLO)$/svdfppt.obj \ + $(SLO)$/svxmsbas.obj \ + $(SLO)$/svxmsbas2.obj + +SHL1TARGET= msfilter$(DLLPOSTFIX) +SHL1IMPLIB= i$(TARGET) +SHL1OBJS= $(SLOFILES) +SHL1USE_EXPORTS=name +SHL1STDLIBS= \ + $(EDITENGLIB) \ + $(SVXCORELIB) \ + $(SFX2LIB) \ + $(XMLOFFLIB) \ + $(BASEGFXLIB) \ + $(BASICLIB) \ + $(SVTOOLLIB) \ + $(TKLIB) \ + $(VCLLIB) \ + $(SVLLIB) \ + $(SOTLIB) \ + $(UNOTOOLSLIB) \ + $(TOOLSLIB) \ + $(XMLSCRIPTLIB) \ + $(COMPHELPERLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) + +SHL1DEF= $(MISC)$/$(SHL1TARGET).def +DEF1NAME= $(SHL1TARGET) + +.INCLUDE : target.mk + +ALLTAR : $(MISC)/msfilter.component + +$(MISC)/msfilter.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + msfilter.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt msfilter.component diff --git a/filter/source/msfilter/makefile.pmk b/filter/source/msfilter/makefile.pmk new file mode 100644 index 000000000000..1b3ae0c70ae0 --- /dev/null +++ b/filter/source/msfilter/makefile.pmk @@ -0,0 +1,30 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +# Reduction of exported symbols: +CDEFS += -DMSFILTER_DLLIMPLEMENTATION +VISIBILITY_HIDDEN=TRUE diff --git a/filter/source/msfilter/mscodec.cxx b/filter/source/msfilter/mscodec.cxx new file mode 100644 index 000000000000..c6feb4fb57dd --- /dev/null +++ b/filter/source/msfilter/mscodec.cxx @@ -0,0 +1,574 @@ +/************************************************************************* + * + * 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_filter.hxx" +#include "filter/msfilter/mscodec.hxx" + +#include <osl/diagnose.h> +#include <algorithm> +#include <string.h> +#include <tools/solar.h> + +#include <comphelper/sequenceashashmap.hxx> +#include <comphelper/docpasswordhelper.hxx> + +#define DEBUG_MSO_ENCRYPTION_STD97 0 + +#if DEBUG_MSO_ENCRYPTION_STD97 +#include <stdio.h> +#endif + +using namespace ::com::sun::star; + +namespace msfilter { + +// ============================================================================ + +namespace { + +/** Rotates rnValue left by nBits bits. */ +template< typename Type > +inline void lclRotateLeft( Type& rnValue, int nBits ) +{ + OSL_ASSERT( + nBits >= 0 && + sal::static_int_cast< unsigned int >(nBits) < sizeof( Type ) * 8 ); + rnValue = static_cast< Type >( (rnValue << nBits) | (rnValue >> (sizeof( Type ) * 8 - nBits)) ); +} + +/** Rotates the lower nWidth bits of rnValue left by nBits bits. */ +template< typename Type > +inline void lclRotateLeft( Type& rnValue, sal_uInt8 nBits, sal_uInt8 nWidth ) +{ + OSL_ASSERT( (nBits < nWidth) && (nWidth < sizeof( Type ) * 8) ); + Type nMask = static_cast< Type >( (1UL << nWidth) - 1 ); + rnValue = static_cast< Type >( + ((rnValue << nBits) | ((rnValue & nMask) >> (nWidth - nBits))) & nMask ); +} + +sal_Size lclGetLen( const sal_uInt8* pnPassData, sal_Size nBufferSize ) +{ + sal_Size nLen = 0; + while( (nLen < nBufferSize) && pnPassData[ nLen ] ) ++nLen; + return nLen; +} + +sal_uInt16 lclGetKey( const sal_uInt8* pnPassData, sal_Size nBufferSize ) +{ + sal_Size nLen = lclGetLen( pnPassData, nBufferSize ); + if( !nLen ) return 0; + + sal_uInt16 nKey = 0; + sal_uInt16 nKeyBase = 0x8000; + sal_uInt16 nKeyEnd = 0xFFFF; + const sal_uInt8* pnChar = pnPassData + nLen - 1; + for( sal_Size nIndex = 0; nIndex < nLen; ++nIndex, --pnChar ) + { + sal_uInt8 cChar = *pnChar & 0x7F; + for( sal_uInt8 nBit = 0; nBit < 8; ++nBit ) + { + lclRotateLeft( nKeyBase, 1 ); + if( nKeyBase & 1 ) nKeyBase ^= 0x1020; + if( cChar & 1 ) nKey ^= nKeyBase; + cChar >>= 1; + lclRotateLeft( nKeyEnd, 1 ); + if( nKeyEnd & 1 ) nKeyEnd ^= 0x1020; + } + } + return nKey ^ nKeyEnd; +} + +sal_uInt16 lclGetHash( const sal_uInt8* pnPassData, sal_Size nBufferSize ) +{ + sal_Size nLen = lclGetLen( pnPassData, nBufferSize ); + + sal_uInt16 nHash = static_cast< sal_uInt16 >( nLen ); + if( nLen ) + nHash ^= 0xCE4B; + + const sal_uInt8* pnChar = pnPassData; + for( sal_Size nIndex = 0; nIndex < nLen; ++nIndex, ++pnChar ) + { + sal_uInt16 cChar = *pnChar; + sal_uInt8 nRot = static_cast< sal_uInt8 >( (nIndex + 1) % 15 ); + lclRotateLeft( cChar, nRot, 15 ); + nHash ^= cChar; + } + return nHash; +} + + +} // namespace + +// ============================================================================ + +MSCodec_Xor95::MSCodec_Xor95(int nRotateDistance) : + mnOffset( 0 ), + mnKey( 0 ), + mnHash( 0 ), + mnRotateDistance( nRotateDistance ) +{ + (void)memset( mpnKey, 0, sizeof( mpnKey ) ); +} + +MSCodec_Xor95::~MSCodec_Xor95() +{ + (void)memset( mpnKey, 0, sizeof( mpnKey ) ); + mnKey = mnHash = 0; +} + +void MSCodec_Xor95::InitKey( const sal_uInt8 pnPassData[ 16 ] ) +{ + mnKey = lclGetKey( pnPassData, 16 ); + mnHash = lclGetHash( pnPassData, 16 ); + + (void)memcpy( mpnKey, pnPassData, 16 ); + + static const sal_uInt8 spnFillChars[] = + { + 0xBB, 0xFF, 0xFF, 0xBA, + 0xFF, 0xFF, 0xB9, 0x80, + 0x00, 0xBE, 0x0F, 0x00, + 0xBF, 0x0F, 0x00 + }; + + sal_Size nIndex; + sal_Size nLen = lclGetLen( pnPassData, 16 ); + const sal_uInt8* pnFillChar = spnFillChars; + for( nIndex = nLen; nIndex < sizeof( mpnKey ); ++nIndex, ++pnFillChar ) + mpnKey[ nIndex ] = *pnFillChar; + + SVBT16 pnOrigKey; + ShortToSVBT16( mnKey, pnOrigKey ); + sal_uInt8* pnKeyChar = mpnKey; + for( nIndex = 0; nIndex < sizeof( mpnKey ); ++nIndex, ++pnKeyChar ) + { + *pnKeyChar ^= pnOrigKey[ nIndex & 0x01 ]; + lclRotateLeft( *pnKeyChar, mnRotateDistance ); + } +} + +sal_Bool MSCodec_Xor95::InitCodec( const uno::Sequence< beans::NamedValue >& aData ) +{ + sal_Bool bResult = sal_False; + + ::comphelper::SequenceAsHashMap aHashData( aData ); + uno::Sequence< sal_Int8 > aKey = aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95EncryptionKey" ) ), uno::Sequence< sal_Int8 >() ); + + if ( aKey.getLength() == 16 ) + { + (void)memcpy( mpnKey, aKey.getConstArray(), 16 ); + bResult = sal_True; + + mnKey = (sal_uInt16)aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95BaseKey" ) ), (sal_Int16)0 ); + mnHash = (sal_uInt16)aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95PasswordHash" ) ), (sal_Int16)0 ); + } + else + OSL_ENSURE( sal_False, "Unexpected key size!\n" ); + + return bResult; +} + +uno::Sequence< beans::NamedValue > MSCodec_Xor95::GetEncryptionData() +{ + ::comphelper::SequenceAsHashMap aHashData; + aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95EncryptionKey" ) ) ] <<= uno::Sequence<sal_Int8>( (sal_Int8*)mpnKey, 16 ); + aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95BaseKey" ) ) ] <<= (sal_Int16)mnKey; + aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95PasswordHash" ) ) ] <<= (sal_Int16)mnHash; + + return aHashData.getAsConstNamedValueList(); +} + +bool MSCodec_Xor95::VerifyKey( sal_uInt16 nKey, sal_uInt16 nHash ) const +{ + return (nKey == mnKey) && (nHash == mnHash); +} + +void MSCodec_Xor95::InitCipher() +{ + mnOffset = 0; +} + +void MSCodec_XorXLS95::Decode( sal_uInt8* pnData, sal_Size nBytes ) +{ + const sal_uInt8* pnCurrKey = mpnKey + mnOffset; + const sal_uInt8* pnKeyLast = mpnKey + 0x0F; + + for( const sal_uInt8* pnDataEnd = pnData + nBytes; pnData < pnDataEnd; ++pnData ) + { + lclRotateLeft( *pnData, 3 ); + *pnData ^= *pnCurrKey; + if( pnCurrKey < pnKeyLast ) ++pnCurrKey; else pnCurrKey = mpnKey; + } + + // update mnOffset + Skip( nBytes ); +} + +void MSCodec_XorWord95::Decode( sal_uInt8* pnData, sal_Size nBytes ) +{ + const sal_uInt8* pnCurrKey = mpnKey + mnOffset; + const sal_uInt8* pnKeyLast = mpnKey + 0x0F; + + for( const sal_uInt8* pnDataEnd = pnData + nBytes; pnData < pnDataEnd; ++pnData ) + { + const sal_uInt8 cChar = *pnData ^ *pnCurrKey; + if (*pnData && cChar) + *pnData = cChar; + if( pnCurrKey < pnKeyLast ) ++pnCurrKey; else pnCurrKey = mpnKey; + } + + // update mnOffset + Skip( nBytes ); +} + + +void MSCodec_Xor95::Skip( sal_Size nBytes ) +{ + mnOffset = (mnOffset + nBytes) & 0x0F; +} + +// ============================================================================ + +MSCodec_Std97::MSCodec_Std97 () +{ + m_hCipher = rtl_cipher_create ( + rtl_Cipher_AlgorithmARCFOUR, rtl_Cipher_ModeStream); + OSL_ASSERT(m_hCipher != 0); + + m_hDigest = rtl_digest_create ( + rtl_Digest_AlgorithmMD5); + OSL_ASSERT(m_hDigest != 0); + + (void)memset (m_pDigestValue, 0, sizeof(m_pDigestValue)); + (void)memset (m_pDocId, 0, sizeof(m_pDocId)); +} + +MSCodec_Std97::~MSCodec_Std97 () +{ + (void)memset (m_pDigestValue, 0, sizeof(m_pDigestValue)); + (void)memset (m_pDocId, 0, sizeof(m_pDocId)); + rtl_digest_destroy (m_hDigest); + rtl_cipher_destroy (m_hCipher); +} + +#if 0 +#if DEBUG_MSO_ENCRYPTION_STD97 +static void lcl_PrintKeyData(const sal_uInt8* pKeyData, const char* msg) +{ + printf("pKeyData: (%s)\n", msg); + for (int j = 0; j < 4; ++j) + { + for (int i = 0; i < 16; ++i) + printf("%2.2x ", pKeyData[j*16+i]); + printf("\n"); + } +} +#else +static void lcl_PrintKeyData(const sal_uInt8* /*pKeyData*/, const char* /*msg*/) +{ +} +#endif +#endif + +#if DEBUG_MSO_ENCRYPTION_STD97 +static void lcl_PrintDigest(const sal_uInt8* pDigest, const char* msg) +{ + printf("digest: (%s)\n", msg); + for (int i = 0; i < 16; ++i) + printf("%2.2x ", pDigest[i]); + printf("\n"); +} +#else +static void lcl_PrintDigest(const sal_uInt8* /*pDigest*/, const char* /*msg*/) +{ +} +#endif + +sal_Bool MSCodec_Std97::InitCodec( const uno::Sequence< beans::NamedValue >& aData ) +{ +#if DEBUG_MSO_ENCRYPTION_STD97 + fprintf(stdout, "MSCodec_Std97::InitCodec: --begin\n");fflush(stdout); +#endif + sal_Bool bResult = sal_False; + + ::comphelper::SequenceAsHashMap aHashData( aData ); + uno::Sequence< sal_Int8 > aKey = aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97EncryptionKey" ) ), uno::Sequence< sal_Int8 >() ); + + if ( aKey.getLength() == RTL_DIGEST_LENGTH_MD5 ) + { + (void)memcpy( m_pDigestValue, aKey.getConstArray(), RTL_DIGEST_LENGTH_MD5 ); + uno::Sequence< sal_Int8 > aUniqueID = aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97UniqueID" ) ), uno::Sequence< sal_Int8 >() ); + if ( aUniqueID.getLength() == 16 ) + { + (void)memcpy( m_pDocId, aUniqueID.getConstArray(), 16 ); + bResult = sal_True; + lcl_PrintDigest(m_pDigestValue, "digest value"); + lcl_PrintDigest(m_pDocId, "DocId value"); + } + else + OSL_ENSURE( sal_False, "Unexpected document ID!\n" ); + } + else + OSL_ENSURE( sal_False, "Unexpected key size!\n" ); + + return bResult; +} + +uno::Sequence< beans::NamedValue > MSCodec_Std97::GetEncryptionData() +{ + ::comphelper::SequenceAsHashMap aHashData; + aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97EncryptionKey" ) ) ] <<= uno::Sequence< sal_Int8 >( (sal_Int8*)m_pDigestValue, RTL_DIGEST_LENGTH_MD5 ); + aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97UniqueID" ) ) ] <<= uno::Sequence< sal_Int8 >( (sal_Int8*)m_pDocId, 16 ); + + return aHashData.getAsConstNamedValueList(); +} + +void MSCodec_Std97::InitKey ( + const sal_uInt16 pPassData[16], + const sal_uInt8 pDocId[16]) +{ +#if DEBUG_MSO_ENCRYPTION_STD97 + fprintf(stdout, "MSCodec_Std97::InitKey: --begin\n");fflush(stdout); +#endif + uno::Sequence< sal_Int8 > aKey = ::comphelper::DocPasswordHelper::GenerateStd97Key( pPassData, uno::Sequence< sal_Int8 >( (sal_Int8*)pDocId, 16 ) ); + // Fill raw digest of above updates into DigestValue. + + if ( aKey.getLength() == sizeof(m_pDigestValue) ) + (void)memcpy ( m_pDigestValue, aKey.getConstArray(), sizeof(m_pDigestValue) ); + else + memset( m_pDigestValue, 0, sizeof(m_pDigestValue) ); + + lcl_PrintDigest(m_pDigestValue, "digest value"); + + (void)memcpy (m_pDocId, pDocId, 16); + + lcl_PrintDigest(m_pDocId, "DocId value"); +} + +bool MSCodec_Std97::VerifyKey ( + const sal_uInt8 pSaltData[16], + const sal_uInt8 pSaltDigest[16]) +{ + // both the salt data and salt digest (hash) come from the document being imported. + +#if DEBUG_MSO_ENCRYPTION_STD97 + fprintf(stdout, "MSCodec_Std97::VerifyKey: \n"); + lcl_PrintDigest(pSaltData, "salt data"); + lcl_PrintDigest(pSaltDigest, "salt hash"); +#endif + bool result = false; + + if (InitCipher(0)) + { + sal_uInt8 pDigest[RTL_DIGEST_LENGTH_MD5]; + GetDigestFromSalt(pSaltData, pDigest); + + sal_uInt8 pBuffer[16]; + // Decode original SaltDigest into Buffer. + rtl_cipher_decode ( + m_hCipher, pSaltDigest, 16, pBuffer, sizeof(pBuffer)); + + // Compare Buffer with computed Digest. + result = (memcmp (pBuffer, pDigest, sizeof(pDigest)) == 0); + + // Erase Buffer and Digest arrays. + (void)memset (pBuffer, 0, sizeof(pBuffer)); + (void)memset (pDigest, 0, sizeof(pDigest)); + } + + return (result); +} + +bool MSCodec_Std97::InitCipher (sal_uInt32 nCounter) +{ + rtlCipherError result; + sal_uInt8 pKeyData[64]; // 512-bit message block + + // Initialize KeyData array. + (void)memset (pKeyData, 0, sizeof(pKeyData)); + + // Fill 40 bit of DigestValue into [0..4]. + (void)memcpy (pKeyData, m_pDigestValue, 5); + + // Fill counter into [5..8]. + pKeyData[ 5] = sal_uInt8((nCounter >> 0) & 0xff); + pKeyData[ 6] = sal_uInt8((nCounter >> 8) & 0xff); + pKeyData[ 7] = sal_uInt8((nCounter >> 16) & 0xff); + pKeyData[ 8] = sal_uInt8((nCounter >> 24) & 0xff); + + pKeyData[ 9] = 0x80; + pKeyData[56] = 0x48; + + // Fill raw digest of KeyData into KeyData. + (void)rtl_digest_updateMD5 ( + m_hDigest, pKeyData, sizeof(pKeyData)); + (void)rtl_digest_rawMD5 ( + m_hDigest, pKeyData, RTL_DIGEST_LENGTH_MD5); + + // Initialize Cipher with KeyData (for decoding). + result = rtl_cipher_init ( + m_hCipher, rtl_Cipher_DirectionBoth, + pKeyData, RTL_DIGEST_LENGTH_MD5, 0, 0); + + // Erase KeyData array and leave. + (void)memset (pKeyData, 0, sizeof(pKeyData)); + + return (result == rtl_Cipher_E_None); +} + +bool MSCodec_Std97::CreateSaltDigest( const sal_uInt8 nSaltData[16], sal_uInt8 nSaltDigest[16] ) +{ +#if DEBUG_MSO_ENCRYPTION_STD97 + lcl_PrintDigest(nSaltData, "salt data"); +#endif + bool result = false; + + if (InitCipher(0)) + { + sal_uInt8 pDigest[RTL_DIGEST_LENGTH_MD5]; + GetDigestFromSalt(nSaltData, pDigest); + + rtl_cipher_decode ( + m_hCipher, pDigest, 16, pDigest, sizeof(pDigest)); + + (void)memcpy(nSaltDigest, pDigest, 16); + } + + return (result); +} + +bool MSCodec_Std97::Encode ( + const void *pData, sal_Size nDatLen, + sal_uInt8 *pBuffer, sal_Size nBufLen) +{ + rtlCipherError result; + + result = rtl_cipher_encode ( + m_hCipher, pData, nDatLen, pBuffer, nBufLen); + + return (result == rtl_Cipher_E_None); +} + +bool MSCodec_Std97::Decode ( + const void *pData, sal_Size nDatLen, + sal_uInt8 *pBuffer, sal_Size nBufLen) +{ + rtlCipherError result; + + result = rtl_cipher_decode ( + m_hCipher, pData, nDatLen, pBuffer, nBufLen); + + return (result == rtl_Cipher_E_None); +} + +bool MSCodec_Std97::Skip( sal_Size nDatLen ) +{ + sal_uInt8 pnDummy[ 1024 ]; + sal_Size nDatLeft = nDatLen; + bool bResult = true; + + while (bResult && nDatLeft) + { + sal_Size nBlockLen = ::std::min< sal_Size >( nDatLeft, sizeof(pnDummy) ); + bResult = Decode( pnDummy, nBlockLen, pnDummy, nBlockLen ); + nDatLeft -= nBlockLen; + } + + return bResult; +} + +void MSCodec_Std97::GetDigestFromSalt( const sal_uInt8 pSaltData[16], sal_uInt8 pDigest[16] ) +{ + sal_uInt8 pBuffer[64]; + sal_uInt8 pDigestLocal[16]; + + // Decode SaltData into Buffer. + rtl_cipher_decode ( + m_hCipher, pSaltData, 16, pBuffer, sizeof(pBuffer)); + + // set the 129th bit to make the buffer 128-bit in length. + pBuffer[16] = 0x80; + + // erase the rest of the buffer with zeros. + (void)memset (pBuffer + 17, 0, sizeof(pBuffer) - 17); + + // set the 441st bit. + pBuffer[56] = 0x80; + + // Fill raw digest of Buffer into Digest. + rtl_digest_updateMD5 ( + m_hDigest, pBuffer, sizeof(pBuffer)); + rtl_digest_rawMD5 ( + m_hDigest, pDigestLocal, sizeof(pDigestLocal)); + + memcpy(pDigest, pDigestLocal, 16); +} + +void MSCodec_Std97::GetEncryptKey ( + const sal_uInt8 pSalt[16], + sal_uInt8 pSaltData[16], + sal_uInt8 pSaltDigest[16]) +{ + if (InitCipher(0)) + { + sal_uInt8 pDigest[RTL_DIGEST_LENGTH_MD5]; + sal_uInt8 pBuffer[64]; + + rtl_cipher_encode ( + m_hCipher, pSalt, 16, pSaltData, sizeof(pBuffer)); + + (void)memcpy( pBuffer, pSalt, 16 ); + + pBuffer[16] = 0x80; + (void)memset (pBuffer + 17, 0, sizeof(pBuffer) - 17); + pBuffer[56] = 0x80; + + rtl_digest_updateMD5 ( + m_hDigest, pBuffer, sizeof(pBuffer)); + rtl_digest_rawMD5 ( + m_hDigest, pDigest, sizeof(pDigest)); + + rtl_cipher_encode ( + m_hCipher, pDigest, 16, pSaltDigest, 16); + + (void)memset (pBuffer, 0, sizeof(pBuffer)); + (void)memset (pDigest, 0, sizeof(pDigest)); + } +} + +void MSCodec_Std97::GetDocId( sal_uInt8 pDocId[16] ) +{ + if ( sizeof( m_pDocId ) == 16 ) + (void)memcpy( pDocId, m_pDocId, 16 ); +} + +// ============================================================================ + +} // namespace svx + diff --git a/filter/source/msfilter/msdffimp.cxx b/filter/source/msfilter/msdffimp.cxx new file mode 100644 index 000000000000..8bf056e9dddd --- /dev/null +++ b/filter/source/msfilter/msdffimp.cxx @@ -0,0 +1,8149 @@ +/************************************************************************* + * + * 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_filter.hxx" +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */ +#include <com/sun/star/embed/Aspects.hpp> + +#include <math.h> +#include <limits.h> +#include <vector> +#include <osl/endian.h> +#include <tools/solar.h> // UINTXX +#include <rtl/math.hxx> + +#include <sot/clsids.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <unotools/streamwrap.hxx> +#include <comphelper/processfactory.hxx> +#include <sot/exchange.hxx> +#include <sot/storinfo.hxx> +#include <vcl/cvtgrf.hxx> +#include "viscache.hxx" + +// SvxItem-Mapping. Wird benoetigt um die SvxItem-Header erfolgreich zu includen +#include <editeng/eeitem.hxx> +#include <editeng/editdata.hxx> +#include <svl/urihelper.hxx> +#include <tools/stream.hxx> +#include <tools/debug.hxx> +#include <tools/zcodec.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <unotools/localfilehelper.hxx> +#include <filter/msfilter/escherex.hxx> +#include <basegfx/range/b2drange.hxx> +#include <com/sun/star/container/XIdentifierContainer.hpp> +#include <com/sun/star/drawing/XGluePointsSupplier.hpp> +#include <com/sun/star/drawing/Position3D.hpp> +#include <com/sun/star/drawing/Direction3D.hpp> +#include <com/sun/star/drawing/GluePoint2.hpp> +#include <com/sun/star/drawing/XShapes.hpp> +#include <editeng/charscaleitem.hxx> +#include <editeng/kernitem.hxx> +#include <svtools/filter.hxx> +#include <tools/string.hxx> +#include <tools/urlobj.hxx> +#include <vcl/virdev.hxx> +#include <vcl/bmpacc.hxx> +#include <sot/storage.hxx> +#include <sfx2/docfac.hxx> +#include <sfx2/docfilt.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/fcontnr.hxx> +#include <sfx2/module.hxx> +#include <svx/sdgcpitm.hxx> +#include <svx/sdgmoitm.hxx> +#include <editeng/tstpitem.hxx> +#include <svx/fmmodel.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdogrp.hxx> +#include <svx/svdograf.hxx> +#include <svx/svdotext.hxx> +#include <svx/svdorect.hxx> +#include <svx/svdocapt.hxx> +#include <svx/svdoedge.hxx> +#include <svx/svdocirc.hxx> +#include <svx/svdoutl.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdopath.hxx> +#include <editeng/frmdir.hxx> +#include <editeng/frmdiritem.hxx> +#include <svx/svdtrans.hxx> +#include <svx/sxenditm.hxx> +#include <svx/sdgluitm.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/crsditem.hxx> +#include <editeng/shdditem.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/colritem.hxx> +#include <svx/sxekitm.hxx> +#include <editeng/bulitem.hxx> +#include <svx/polysc3d.hxx> +#include <svx/extrud3d.hxx> +#include "svx/svditer.hxx" +#include <svx/xpoly.hxx> +#include "svx/xattr.hxx" +#include <filter/msfilter/msdffimp.hxx> // extern sichtbare Header-Datei +#include <editeng/outliner.hxx> +#include <editeng/outlobj.hxx> +#include <editeng/editobj.hxx> +#include <editeng/editeng.hxx> +#include "svx/gallery.hxx" +#include <com/sun/star/drawing/ShadeMode.hpp> +#include <svl/itempool.hxx> +#include <vcl/svapp.hxx> +#include <svx/svx3ditems.hxx> +#include <svx/svdoashp.hxx> +#include <svx/sdasaitm.hxx> +#include <ucbhelper/content.hxx> +#include <ucbhelper/contentbroker.hxx> +#include <vos/xception.hxx> +using namespace vos; +#include "svx/EnhancedCustomShapeTypeNames.hxx" +#include "svx/EnhancedCustomShapeGeometry.hxx" +#include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeGluePointType.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp> +#include <com/sun/star/beans/PropertyValues.hpp> +#include <com/sun/star/drawing/ProjectionMode.hpp> +#include "svx/EnhancedCustomShape2d.hxx" + +using namespace ::com::sun::star ; +using namespace ::com::sun::star::drawing; +using namespace uno ; +using namespace beans ; +using namespace drawing ; +using namespace container ; + +#define ITEMVALUE(ItemSet,Id,Cast) ((const Cast&)(ItemSet).Get(Id)).GetValue() + +// static counter for OLE-Objects +static sal_uInt32 nMSOleObjCntr = 0; +#define MSO_OLE_Obj "MSO_OLE_Obj" + + +/*************************************************************************/ +sal_Bool Impl_OlePres::Read( SvStream & rStm ) +{ + sal_uLong nBeginPos = rStm.Tell(); + sal_Int32 n; + rStm >> n; + if( n != -1 ) + { + pBmp = new Bitmap; + rStm >> *pBmp; + if( rStm.GetError() == SVSTREAM_OK ) + { + nFormat = FORMAT_BITMAP; + aSize = pBmp->GetPrefSize(); + MapMode aMMSrc; + if( !aSize.Width() || !aSize.Height() ) + { + // letzte Chance + aSize = pBmp->GetSizePixel(); + aMMSrc = MAP_PIXEL; + } + else + aMMSrc = pBmp->GetPrefMapMode(); + MapMode aMMDst( MAP_100TH_MM ); + aSize = OutputDevice::LogicToLogic( aSize, aMMSrc, aMMDst ); + return sal_True; + } + else + { + delete pBmp; + pBmp = NULL; + + pMtf = new GDIMetaFile(); + rStm.ResetError(); + rStm >> *pMtf; + if( rStm.GetError() == SVSTREAM_OK ) + { + nFormat = FORMAT_GDIMETAFILE; + aSize = pMtf->GetPrefSize(); + MapMode aMMSrc = pMtf->GetPrefMapMode(); + MapMode aMMDst( MAP_100TH_MM ); + aSize = OutputDevice::LogicToLogic( aSize, aMMSrc, aMMDst ); + return sal_True; + } + else + { + delete pMtf; + pMtf = NULL; + } + } + + } + + rStm.ResetError(); + rStm.Seek( nBeginPos ); + nFormat = ReadClipboardFormat( rStm ); + // JobSetup, bzw. TargetDevice ueberlesen + // Information aufnehmen, um sie beim Schreiben nicht zu verlieren + nJobLen = 0; + rStm >> nJobLen; + if( nJobLen >= 4 ) + { + nJobLen -= 4; + if( nJobLen ) + { + pJob = new sal_uInt8[ nJobLen ]; + rStm.Read( pJob, nJobLen ); + } + } + else + { + rStm.SetError( SVSTREAM_GENERALERROR ); + return sal_False; + } + sal_uInt32 nAsp; + rStm >> nAsp; + sal_uInt16 nSvAsp = sal_uInt16( nAsp ); + SetAspect( nSvAsp ); + rStm.SeekRel( 4 ); //L-Index ueberlesen + rStm >> nAdvFlags; + rStm.SeekRel( 4 ); //Compression + sal_uInt32 nWidth = 0; + sal_uInt32 nHeight = 0; + sal_uInt32 nSize = 0; + rStm >> nWidth >> nHeight >> nSize; + aSize.Width() = nWidth; + aSize.Height() = nHeight; + + if( nFormat == FORMAT_GDIMETAFILE ) + { + pMtf = new GDIMetaFile(); + ReadWindowMetafile( rStm, *pMtf, NULL ); + } + else if( nFormat == FORMAT_BITMAP ) + { + pBmp = new Bitmap(); + rStm >> *pBmp; + } + else + { + sal_uInt8 * p = new sal_uInt8[ nSize ]; + rStm.Read( p, nSize ); + delete [] p; + return sal_False; + } + return sal_True; +} + +/************************************************************************/ +void Impl_OlePres::Write( SvStream & rStm ) +{ + WriteClipboardFormat( rStm, FORMAT_GDIMETAFILE ); + rStm << (sal_Int32)(nJobLen +4); // immer leeres TargetDevice + if( nJobLen ) + rStm.Write( pJob, nJobLen ); + rStm << (sal_uInt32)nAspect; + rStm << (sal_Int32)-1; //L-Index immer -1 + rStm << (sal_Int32)nAdvFlags; + rStm << (sal_Int32)0; //Compression + rStm << (sal_Int32)aSize.Width(); + rStm << (sal_Int32)aSize.Height(); + sal_uLong nPos = rStm.Tell(); + rStm << (sal_Int32)0; + + if( GetFormat() == FORMAT_GDIMETAFILE && pMtf ) + { + // Immer auf 1/100 mm, bis Mtf-Loesung gefunden + // Annahme (keine Skalierung, keine Org-Verschiebung) + DBG_ASSERT( pMtf->GetPrefMapMode().GetScaleX() == Fraction( 1, 1 ), + "X-Skalierung im Mtf" ); + DBG_ASSERT( pMtf->GetPrefMapMode().GetScaleY() == Fraction( 1, 1 ), + "Y-Skalierung im Mtf" ); + DBG_ASSERT( pMtf->GetPrefMapMode().GetOrigin() == Point(), + "Origin-Verschiebung im Mtf" ); + MapUnit nMU = pMtf->GetPrefMapMode().GetMapUnit(); + if( MAP_100TH_MM != nMU ) + { + Size aPrefS( pMtf->GetPrefSize() ); + Size aS( aPrefS ); + aS = OutputDevice::LogicToLogic( aS, nMU, MAP_100TH_MM ); + + pMtf->Scale( Fraction( aS.Width(), aPrefS.Width() ), + Fraction( aS.Height(), aPrefS.Height() ) ); + pMtf->SetPrefMapMode( MAP_100TH_MM ); + pMtf->SetPrefSize( aS ); + } + WriteWindowMetafileBits( rStm, *pMtf ); + } + else + { + DBG_ERROR( "unknown format" ); + } + sal_uLong nEndPos = rStm.Tell(); + rStm.Seek( nPos ); + rStm << (sal_uInt32)(nEndPos - nPos - 4); + rStm.Seek( nEndPos ); +} + +Impl_OlePres * CreateCache_Impl( SotStorage * pStor ) +{ + SotStorageStreamRef xOleObjStm =pStor->OpenSotStream( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "Ole-Object" ) ), + STREAM_READ | STREAM_NOCREATE ); + if( xOleObjStm->GetError() ) + return NULL; + SotStorageRef xOleObjStor = new SotStorage( *xOleObjStm ); + if( xOleObjStor->GetError() ) + return NULL; + + String aStreamName; + if( xOleObjStor->IsContained( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "\002OlePres000" ) ) ) ) + aStreamName = String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "\002OlePres000" ) ); + else if( xOleObjStor->IsContained( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "\1Ole10Native" ) ) ) ) + aStreamName = String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "\1Ole10Native" ) ); + + if( aStreamName.Len() == 0 ) + return NULL; + + + for( sal_uInt16 i = 1; i < 10; i++ ) + { + SotStorageStreamRef xStm = xOleObjStor->OpenSotStream( aStreamName, + STREAM_READ | STREAM_NOCREATE ); + if( xStm->GetError() ) + break; + + xStm->SetBufferSize( 8192 ); + Impl_OlePres * pEle = new Impl_OlePres( 0 ); + if( pEle->Read( *xStm ) && !xStm->GetError() ) + { + if( pEle->GetFormat() == FORMAT_GDIMETAFILE || pEle->GetFormat() == FORMAT_BITMAP ) + return pEle; + } + delete pEle; + aStreamName = String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "\002OlePres00" ) ); + aStreamName += String( i ); + }; + return NULL; +} + + + +//--------------------------------------------------------------------------- +// Hilfs Klassen aus MSDFFDEF.HXX +//--------------------------------------------------------------------------- + +SvStream& operator>>( SvStream& rIn, DffRecordHeader& rRec ) +{ + rRec.nFilePos = rIn.Tell(); + sal_uInt16 nTmp(0); + rIn >> nTmp; + rRec.nImpVerInst = nTmp; + rRec.nRecVer = sal::static_int_cast< sal_uInt8 >(nTmp & 0x000F); + rRec.nRecInstance = nTmp >> 4; + rIn >> rRec.nRecType; + rIn >> rRec.nRecLen; + return rIn; +} + +// Masse fuer dashed lines +#define LLEN_MIDDLE (450) +#define LLEN_SPACE_MIDDLE (360) +#define LLEN_LONG (LLEN_MIDDLE * 2) +#define LLEN_SPACE_LONG (LLEN_SPACE_MIDDLE + 20) +#define LLEN_POINT (LLEN_MIDDLE / 4) +#define LLEN_SPACE_POINT (LLEN_SPACE_MIDDLE / 4) + +SvStream& operator>>( SvStream& rIn, DffPropSet& rRec ) +{ + rRec.InitializePropSet(); + + DffRecordHeader aHd; + rIn >> aHd; + sal_uInt32 nPropCount = aHd.nRecInstance; + + // FilePos der ComplexData merken + sal_uInt32 nComplexDataFilePos = rIn.Tell() + ( nPropCount * 6 ); + + for( sal_uInt32 nPropNum = 0; nPropNum < nPropCount; nPropNum++ ) + { + sal_uInt16 nTmp; + sal_uInt32 nRecType, nContent, nContentEx = 0xffff0000; + rIn >> nTmp + >> nContent; + + nRecType = nTmp & 0x3fff; + + if ( nRecType > 0x3ff ) + break; + if ( ( nRecType & 0x3f ) == 0x3f ) + { // clear flags that have to be cleared + rRec.mpContents[ nRecType ] &= ( ( nContent >> 16 ) ^ 0xffffffff ); + // set flags that have to be set + rRec.mpContents[ nRecType ] |= nContent; + nContentEx |= ( nContent >> 16 ); + rRec.Replace( nRecType, (void*)nContentEx ); + } + else + { + DffPropFlags aPropFlag = { 1, 0, 0, 0 }; + if ( nTmp & 0x4000 ) + aPropFlag.bBlip = sal_True; + if ( nTmp & 0x8000 ) + aPropFlag.bComplex = sal_True; + if ( aPropFlag.bComplex && nContent && ( nComplexDataFilePos < aHd.GetRecEndFilePos() ) ) + { + // normally nContent is the complete size of the complex property, + // but this is not always true for IMsoArrays ( what the hell is a IMsoArray ? ) + + // I love special threatments :-( + if ( ( nRecType == DFF_Prop_pVertices ) || ( nRecType == DFF_Prop_pSegmentInfo ) + || ( nRecType == DFF_Prop_fillShadeColors ) || ( nRecType == DFF_Prop_lineDashStyle ) + || ( nRecType == DFF_Prop_pWrapPolygonVertices ) || ( nRecType == DFF_Prop_connectorPoints ) + || ( nRecType == DFF_Prop_Handles ) || ( nRecType == DFF_Prop_pFormulas ) + || ( nRecType == DFF_Prop_textRectangles ) ) + { + // now check if the current content size is possible, or 6 bytes too small + sal_uInt32 nOldPos = rIn.Tell(); + sal_Int16 nNumElem, nNumElemReserved, nSize; + + rIn.Seek( nComplexDataFilePos ); + rIn >> nNumElem >> nNumElemReserved >> nSize; + if ( nNumElemReserved >= nNumElem ) + { + // the size of these array elements is nowhere defined, + // what if the size is negative ? + // ok, we will make it positive and shift it. + // for -16 this works + if ( nSize < 0 ) + nSize = ( -nSize ) >> 2; + sal_uInt32 nDataSize = (sal_uInt32)( nSize * nNumElem ); + + // sometimes the content size is 6 bytes too small (array header information is missing ) + if ( nDataSize == nContent ) + nContent += 6; + + // check if array fits into the PropertyContainer + if ( ( nComplexDataFilePos + nContent ) > aHd.GetRecEndFilePos() ) + nContent = 0; + } + else + nContent = 0; + rIn.Seek( nOldPos ); + } + if ( nContent ) + { + nContentEx = nComplexDataFilePos; // insert the filepos of this property; + nComplexDataFilePos += nContent; // store filepos, that is used for the next complex property + } + else // a complex property needs content + aPropFlag.bSet = sal_False; // otherwise something is wrong + } + rRec.mpContents[ nRecType ] = nContent; + rRec.mpFlags[ nRecType ] = aPropFlag; + rRec.Insert( nRecType, (void*)nContentEx ); + } + } + aHd.SeekToEndOfRecord( rIn ); + return rIn; +} + +void DffPropSet::InitializePropSet() const +{ + /* + cmc: + " Boolean properties are grouped in bitfields by property set; note that + the Boolean properties in each property set are contiguous. They are saved + under the property ID of the last Boolean property in the set, and are + placed in the value field in reverse order starting with the last property + in the low bit. " + + e.g. + + fEditedWrap + fBehindDocument + fOnDblClickNotify + fIsButton + fOneD + fHidden + fPrint + + are all part of a group and all are by default false except for fPrint, + which equates to a default bit sequence for the group of 0000001 -> 0x1 + + If at a later stage word sets fBehindDocument away from the default it + will be done by having a property named fPrint whose bitsequence will have + the fBehindDocument bit set. e.g. a DFF_Prop_fPrint with value 0x200020 + has set bit 6 on so as to enable fBehindDocument (as well as disabling + everything else) + */ + + memset( ( (DffPropSet*) this )->mpFlags, 0, 0x400 * sizeof(DffPropFlags) ); + ( (DffPropSet*) this )->Clear(); + + DffPropFlags nFlags = { 1, 0, 0, 1 }; + + ( (DffPropSet*) this )->mpContents[ DFF_Prop_LockAgainstGrouping ] = 0x0000; //0x01ff0000; + ( (DffPropSet*) this )->mpFlags[ DFF_Prop_LockAgainstGrouping ] = nFlags; + ( (DffPropSet*) this )->Insert( DFF_Prop_LockAgainstGrouping, (void*)0xffff0000 ); + + ( (DffPropSet*) this )->mpContents[ DFF_Prop_FitTextToShape ] = 0x0010; //0x001f0010; + ( (DffPropSet*) this )->mpFlags[ DFF_Prop_FitTextToShape ] = nFlags; + ( (DffPropSet*) this )->Insert( DFF_Prop_FitTextToShape, (void*)0xffff0000 ); + + ( (DffPropSet*) this )->mpContents[ DFF_Prop_gtextFStrikethrough ] = 0x0000; //0xffff0000; + ( (DffPropSet*) this )->mpFlags[ DFF_Prop_gtextFStrikethrough ] = nFlags; + ( (DffPropSet*) this )->Insert( DFF_Prop_gtextFStrikethrough, (void*)0xffff0000 ); + + ( (DffPropSet*) this )->mpContents[ DFF_Prop_pictureActive ] = 0x0000; //0x000f0000; + ( (DffPropSet*) this )->mpFlags[ DFF_Prop_pictureActive ] = nFlags; + ( (DffPropSet*) this )->Insert( DFF_Prop_pictureActive, (void*)0xffff0000 ); + + ( (DffPropSet*) this )->mpContents[ DFF_Prop_fFillOK ] = 0x0039; //0x003f0039; + ( (DffPropSet*) this )->mpFlags[ DFF_Prop_fFillOK ] = nFlags; + ( (DffPropSet*) this )->Insert( DFF_Prop_fFillOK, (void*)0xffff0000 ); + + ( (DffPropSet*) this )->mpContents[ DFF_Prop_fNoFillHitTest ] = 0x001c; //0x001f001c; + ( (DffPropSet*) this )->mpFlags[ DFF_Prop_fNoFillHitTest ] = nFlags; + ( (DffPropSet*) this )->Insert( DFF_Prop_fNoFillHitTest, (void*)0xffff0000 ); + + ( (DffPropSet*) this )->mpContents[ DFF_Prop_fNoLineDrawDash ] = 0x001e; //0x001f000e; + ( (DffPropSet*) this )->mpFlags[ DFF_Prop_fNoLineDrawDash ] = nFlags; + ( (DffPropSet*) this )->Insert( DFF_Prop_fNoLineDrawDash, (void*)0xffff0000 ); + + ( (DffPropSet*) this )->mpContents[ DFF_Prop_fshadowObscured ] = 0x0000; //0x00030000; + ( (DffPropSet*) this )->mpFlags[ DFF_Prop_fshadowObscured ] = nFlags; + ( (DffPropSet*) this )->Insert( DFF_Prop_fshadowObscured, (void*)0xffff0000 ); + + ( (DffPropSet*) this )->mpContents[ DFF_Prop_fPerspective ] = 0x0000; //0x00010000; + ( (DffPropSet*) this )->mpFlags[ DFF_Prop_fPerspective ] = nFlags; + ( (DffPropSet*) this )->Insert( DFF_Prop_fPerspective, (void*)0xffff0000 ); + + ( (DffPropSet*) this )->mpContents[ DFF_Prop_fc3DLightFace ] = 0x0001; //0x000f0001; + ( (DffPropSet*) this )->mpFlags[ DFF_Prop_fc3DLightFace ] = nFlags; + ( (DffPropSet*) this )->Insert( DFF_Prop_fc3DLightFace, (void*)0xffff0000 ); + + ( (DffPropSet*) this )->mpContents[ DFF_Prop_fc3DFillHarsh ] = 0x0016; //0x001f0016; + ( (DffPropSet*) this )->mpFlags[ DFF_Prop_fc3DFillHarsh ] = nFlags; + ( (DffPropSet*) this )->Insert( DFF_Prop_fc3DFillHarsh, (void*)0xffff0000 ); + + ( (DffPropSet*) this )->mpContents[ DFF_Prop_fBackground ] = 0x0000; //0x001f0000; + ( (DffPropSet*) this )->mpFlags[ DFF_Prop_fBackground ] = nFlags; + ( (DffPropSet*) this )->Insert( DFF_Prop_fBackground, (void*)0xffff0000 ); + + ( (DffPropSet*) this )->mpContents[ DFF_Prop_fCalloutLengthSpecified ] = 0x0010; //0x00ef0010; + ( (DffPropSet*) this )->mpFlags[ DFF_Prop_fCalloutLengthSpecified ] = nFlags; + ( (DffPropSet*) this )->Insert( DFF_Prop_fCalloutLengthSpecified, (void*)0xffff0000 ); + + ( (DffPropSet*) this )->mpContents[ DFF_Prop_fPrint ] = 0x0001; //0x00ef0001; + ( (DffPropSet*) this )->mpFlags[ DFF_Prop_fPrint ] = nFlags; + ( (DffPropSet*) this )->Insert( DFF_Prop_fPrint, (void*)0xffff0000 ); + + ( (DffPropSet*) this )->mpContents[ DFF_Prop_fillColor ] = 0xffffff; + ( (DffPropSet*) this )->mpFlags[ DFF_Prop_fillColor ] = nFlags; + ( (DffPropSet*) this )->Insert( DFF_Prop_fillColor, (void*)0xffff0000 ); +} + +void DffPropSet::Merge( DffPropSet& rMaster ) const +{ + for ( void* pDummy = rMaster.First(); pDummy; pDummy = rMaster.Next() ) + { + sal_uInt32 nRecType = rMaster.GetCurKey(); + if ( ( nRecType & 0x3f ) == 0x3f ) // this is something called FLAGS + { + sal_uInt32 nCurrentFlags = mpContents[ nRecType ]; + sal_uInt32 nMergeFlags = rMaster.mpContents[ nRecType ]; + nMergeFlags &= ( nMergeFlags >> 16 ) | 0xffff0000; // clearing low word + nMergeFlags &= ( ( nCurrentFlags & 0xffff0000 ) // remove allready hard set + | ( nCurrentFlags >> 16 ) ) ^ 0xffffffff; // attributes from mergeflags + nCurrentFlags &= ( ( nMergeFlags & 0xffff0000 ) // apply zero master bits + | ( nMergeFlags >> 16 ) ) ^ 0xffffffff; + nCurrentFlags |= (sal_uInt16)nMergeFlags; // apply filled master bits + ( (DffPropSet*) this )->mpContents[ nRecType ] = nCurrentFlags; + + + sal_uInt32 nNewContentEx = (sal_uInt32)(sal_uIntPtr)rMaster.GetCurObject(); + if ( ((DffPropSet*)this)->Seek( nRecType ) ) + nNewContentEx |= (sal_uInt32)(sal_uIntPtr)GetCurObject(); + ( (DffPropSet*) this )->Replace( nRecType, (void*)nNewContentEx ); + } + else + { + if ( !IsProperty( nRecType ) || !IsHardAttribute( nRecType ) ) + { + ( (DffPropSet*) this )->mpContents[ nRecType ] = rMaster.mpContents[ nRecType ]; + DffPropFlags nFlags( rMaster.mpFlags[ nRecType ] ); + nFlags.bSoftAttr = sal_True; + ( (DffPropSet*) this )->mpFlags[ nRecType ] = nFlags; + ( (DffPropSet*) this )->Insert( nRecType, pDummy ); + } + } + } +} + +sal_Bool DffPropSet::IsHardAttribute( sal_uInt32 nId ) const +{ + sal_Bool bRetValue = sal_True; + nId &= 0x3ff; + if ( ( nId & 0x3f ) >= 48 ) // is this a flag id + { + if ( ((DffPropSet*)this)->Seek( nId | 0x3f ) ) + { + sal_uInt32 nContentEx = (sal_uInt32)(sal_uIntPtr)GetCurObject(); + bRetValue = ( nContentEx & ( 1 << ( 0xf - ( nId & 0xf ) ) ) ) != 0; + } + } + else + bRetValue = ( mpFlags[ nId ].bSoftAttr == 0 ); + return bRetValue; +}; + +sal_uInt32 DffPropSet::GetPropertyValue( sal_uInt32 nId, sal_uInt32 nDefault ) const +{ + nId &= 0x3ff; + return ( mpFlags[ nId ].bSet ) ? mpContents[ nId ] : nDefault; +}; + +bool DffPropSet::GetPropertyBool( sal_uInt32 nId, bool bDefault ) const +{ + sal_uInt32 nBaseId = nId | 31; // base ID to get the sal_uInt32 property value + sal_uInt32 nMask = 1 << (nBaseId - nId); // bit mask of the boolean property + + sal_uInt32 nPropValue = GetPropertyValue( nBaseId, bDefault ? nMask : 0 ); + return (nPropValue & nMask) != 0; +} + +::rtl::OUString DffPropSet::GetPropertyString( sal_uInt32 nId, SvStream& rStrm ) const +{ + sal_Size nOldPos = rStrm.Tell(); + ::rtl::OUStringBuffer aBuffer; + sal_uInt32 nBufferSize = GetPropertyValue( nId ); + if( (nBufferSize > 0) && SeekToContent( nId, rStrm ) ) + { + sal_Int32 nStrLen = static_cast< sal_Int32 >( nBufferSize / 2 ); + aBuffer.ensureCapacity( nStrLen ); + for( sal_Int32 nCharIdx = 0; nCharIdx < nStrLen; ++nCharIdx ) + { + sal_uInt16 nChar = 0; + rStrm >> nChar; + if( nChar > 0 ) + aBuffer.append( static_cast< sal_Unicode >( nChar ) ); + else + break; + } + } + rStrm.Seek( nOldPos ); + return aBuffer.makeStringAndClear(); +} + +void DffPropSet::SetPropertyValue( sal_uInt32 nId, sal_uInt32 nValue ) const +{ + if ( !mpFlags[ nId ].bSet ) + { + ( (DffPropSet*) this )->Insert( nId, (void*)nValue ); + ( (DffPropSet*) this )->mpFlags[ nId ].bSet = sal_True; + } + ( (DffPropSet*) this )->mpContents[ nId ] = nValue; +}; + +sal_Bool DffPropSet::SeekToContent( sal_uInt32 nRecType, SvStream& rStrm ) const +{ + nRecType &= 0x3ff; + if ( mpFlags[ nRecType ].bSet ) + { + if ( mpFlags[ nRecType ].bComplex ) + { + if ( ((DffPropSet*)this)->Seek( nRecType ) ) + { + sal_uInt32 nOffset = (sal_uInt32)(sal_uIntPtr)GetCurObject(); + if ( nOffset && ( ( nOffset & 0xffff0000 ) != 0xffff0000 ) ) + { + rStrm.Seek( nOffset ); + return sal_True; + } + } + } + } + return sal_False; +} + +DffPropertyReader::DffPropertyReader( const SvxMSDffManager& rMan ) : + rManager( rMan ), + pDefaultPropSet( NULL ) +{ + InitializePropSet(); +} + +void DffPropertyReader::SetDefaultPropSet( SvStream& rStCtrl, sal_uInt32 nOffsDgg ) const +{ + delete pDefaultPropSet; + sal_uInt32 nMerk = rStCtrl.Tell(); + rStCtrl.Seek( nOffsDgg ); + DffRecordHeader aRecHd; + rStCtrl >> aRecHd; + if ( aRecHd.nRecType == DFF_msofbtDggContainer ) + { + if ( rManager.SeekToRec( rStCtrl, DFF_msofbtOPT, aRecHd.GetRecEndFilePos() ) ) + { + ( (DffPropertyReader*) this )->pDefaultPropSet = new DffPropSet; + rStCtrl >> *pDefaultPropSet; + } + } + rStCtrl.Seek( nMerk ); +} + +#ifdef DBG_CUSTOMSHAPE +void DffPropertyReader::ReadPropSet( SvStream& rIn, void* pClientData, sal_uInt32 nShapeId ) const +#else +void DffPropertyReader::ReadPropSet( SvStream& rIn, void* pClientData ) const +#endif +{ + sal_uLong nFilePos = rIn.Tell(); + rIn >> (DffPropertyReader&)*this; + + if ( IsProperty( DFF_Prop_hspMaster ) ) + { + if ( rManager.SeekToShape( rIn, pClientData, GetPropertyValue( DFF_Prop_hspMaster ) ) ) + { + DffRecordHeader aRecHd; + rIn >> aRecHd; + if ( rManager.SeekToRec( rIn, DFF_msofbtOPT, aRecHd.GetRecEndFilePos() ) ) + { + DffPropSet aMasterPropSet; + rIn >> aMasterPropSet; + Merge( aMasterPropSet ); + } + } + } +// if ( pDefaultPropSet ) +// Merge( *( pDefaultPropSet ) ); + + ( (DffPropertyReader*) this )->mnFix16Angle = Fix16ToAngle( GetPropertyValue( DFF_Prop_Rotation, 0 ) ); + +#ifdef DBG_CUSTOMSHAPE + + String aURLStr; + + if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( String( RTL_CONSTASCII_STRINGPARAM( "d:\\ashape.dbg" ) ), aURLStr ) ) + { + SvStream* pOut = ::utl::UcbStreamHelper::CreateStream( aURLStr, STREAM_WRITE ); + + if( pOut ) + { + pOut->Seek( STREAM_SEEK_TO_END ); + + if ( IsProperty( DFF_Prop_adjustValue ) || IsProperty( DFF_Prop_pVertices ) ) + { + pOut->WriteLine( "" ); + ByteString aString( "ShapeId: " ); + aString.Append( ByteString::CreateFromInt32( nShapeId ) ); + pOut->WriteLine( aString ); + } + for ( sal_uInt32 i = DFF_Prop_adjustValue; i <= DFF_Prop_adjust10Value; i++ ) + { + if ( IsProperty( i ) ) + { + ByteString aString( "Prop_adjustValue" ); + aString.Append( ByteString::CreateFromInt32( ( i - DFF_Prop_adjustValue ) + 1 ) ); + aString.Append( ":" ); + aString.Append( ByteString::CreateFromInt32( GetPropertyValue( i ) ) ); + pOut->WriteLine( aString ); + } + } + sal_Int32 i; + for ( i = 320; i < 383; i++ ) + { + if ( ( i >= DFF_Prop_adjustValue ) && ( i <= DFF_Prop_adjust10Value ) ) + continue; + if ( IsProperty( i ) ) + { + if ( SeekToContent( i, rIn ) ) + { + sal_Int32 nLen = (sal_Int32)GetPropertyValue( i ); + if ( nLen ) + { + pOut->WriteLine( "" ); + ByteString aDesc( "Property:" ); + aDesc.Append( ByteString::CreateFromInt32( i ) ); + aDesc.Append( ByteString( " Size:" ) ); + aDesc.Append( ByteString::CreateFromInt32( nLen ) ); + pOut->WriteLine( aDesc ); + sal_Int16 nNumElem, nNumElemMem, nNumSize; + rIn >> nNumElem >> nNumElemMem >> nNumSize; + aDesc = ByteString( "Entries: " ); + aDesc.Append( ByteString::CreateFromInt32( nNumElem ) ); + aDesc.Append( ByteString( " Size:" ) ); + aDesc.Append( ByteString::CreateFromInt32( nNumSize ) ); + pOut->WriteLine( aDesc ); + if ( nNumSize < 0 ) + nNumSize = ( ( -nNumSize ) >> 2 ); + if ( !nNumSize ) + nNumSize = 16; + nLen -= 6; + while ( nLen > 0 ) + { + ByteString aString; + for ( sal_uInt32 j = 0; nLen && ( j < ( nNumSize >> 1 ) ); j++ ) + { + for ( sal_uInt32 k = 0; k < 2; k++ ) + { + if ( nLen ) + { + sal_uInt8 nVal; + rIn >> nVal; + if ( ( nVal >> 4 ) > 9 ) + *pOut << (sal_uInt8)( ( nVal >> 4 ) + 'A' - 10 ); + else + *pOut << (sal_uInt8)( ( nVal >> 4 ) + '0' ); + + if ( ( nVal & 0xf ) > 9 ) + *pOut << (sal_uInt8)( ( nVal & 0xf ) + 'A' - 10 ); + else + *pOut << (sal_uInt8)( ( nVal & 0xf ) + '0' ); + + nLen--; + } + } + *pOut << (char)( ' ' ); + } + pOut->WriteLine( aString ); + } + } + } + else + { + ByteString aString( "Property" ); + aString.Append( ByteString::CreateFromInt32( i ) ); + aString.Append( ":" ); + aString.Append( ByteString::CreateFromInt32( GetPropertyValue( i ) ) ); + pOut->WriteLine( aString ); + } + } + } + + delete pOut; + } + } + +#endif + + rIn.Seek( nFilePos ); +} + + +sal_Int32 DffPropertyReader::Fix16ToAngle( sal_Int32 nContent ) const +{ + sal_Int32 nAngle = 0; + if ( nContent ) + { + nAngle = ( (sal_Int16)( nContent >> 16) * 100L ) + ( ( ( nContent & 0x0000ffff) * 100L ) >> 16 ); + nAngle = NormAngle360( -nAngle ); + } + return nAngle; +} + +DffPropertyReader::~DffPropertyReader() +{ + delete pDefaultPropSet; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SvStream& operator>>( SvStream& rIn, SvxMSDffConnectorRule& rRule ) +{ + rIn >> rRule.nRuleId + >> rRule.nShapeA + >> rRule.nShapeB + >> rRule.nShapeC + >> rRule.ncptiA + >> rRule.ncptiB; + + return rIn; +} + +SvxMSDffSolverContainer::SvxMSDffSolverContainer() +{ +} + +SvxMSDffSolverContainer::~SvxMSDffSolverContainer() +{ + for ( SvxMSDffConnectorRule* pPtr = (SvxMSDffConnectorRule*)aCList.First(); + pPtr; pPtr = (SvxMSDffConnectorRule*)aCList.Next() ) + delete pPtr; +} + +SvStream& operator>>( SvStream& rIn, SvxMSDffSolverContainer& rContainer ) +{ + DffRecordHeader aHd; + rIn >> aHd; + if ( aHd.nRecType == DFF_msofbtSolverContainer ) + { + DffRecordHeader aCRule; + while ( ( rIn.GetError() == 0 ) && ( rIn.Tell() < aHd.GetRecEndFilePos() ) ) + { + rIn >> aCRule; + if ( aCRule.nRecType == DFF_msofbtConnectorRule ) + { + SvxMSDffConnectorRule* pRule = new SvxMSDffConnectorRule; + rIn >> *pRule; + rContainer.aCList.Insert( pRule, LIST_APPEND ); + } + aCRule.SeekToEndOfRecord( rIn ); + } + } + return rIn; +} + +void SvxMSDffManager::SolveSolver( const SvxMSDffSolverContainer& rSolver ) +{ + sal_Int32 i, nCnt; + for ( i = 0, nCnt = rSolver.aCList.Count(); i < nCnt; i++ ) + { + SvxMSDffConnectorRule* pPtr = (SvxMSDffConnectorRule*)rSolver.aCList.GetObject( i ); + if ( pPtr->pCObj ) + { + for ( int nN = 0; nN < 2; nN++ ) + { + SdrObject* pO; + sal_uInt32 nC, nSpFlags; + sal_Bool bTail; + if ( !nN ) + { + bTail = sal_True; + pO = pPtr->pAObj; + nC = pPtr->ncptiA; + nSpFlags = pPtr->nSpFlagsA; + } + else + { + bTail = sal_False; + pO = pPtr->pBObj; + nC = pPtr->ncptiB; + nSpFlags = pPtr->nSpFlagsB; + } + if ( pO ) + { + Any aAny; + SdrGluePoint aGluePoint; + Reference< XShape > aXShape( pO->getUnoShape(), UNO_QUERY ); + Reference< XShape > aXConnector( pPtr->pCObj->getUnoShape(), UNO_QUERY ); + SdrGluePointList* pList = pO->ForceGluePointList(); + + sal_Bool bValidGluePoint = sal_False; + sal_Int32 nId = nC; + sal_uInt32 nInventor = pO->GetObjInventor(); + + if( nInventor == SdrInventor ) + { + sal_uInt32 nObjId = pO->GetObjIdentifier(); + switch( nObjId ) + { + case OBJ_GRUP : + case OBJ_GRAF : + case OBJ_RECT : + case OBJ_TEXT : + case OBJ_PAGE : + case OBJ_TEXTEXT : + case OBJ_wegFITTEXT : + case OBJ_wegFITALLTEXT : + case OBJ_TITLETEXT : + case OBJ_OUTLINETEXT : + { + if ( nC & 1 ) + { + if ( nSpFlags & SP_FFLIPH ) + nC ^= 2; // 1 <-> 3 + } + else + { + if ( nSpFlags & SP_FFLIPV ) + nC ^= 1; // 0 <-> 2 + } + switch( nC ) + { + case 0 : + nId = 0; // SDRVERTALIGN_TOP; + break; + case 1 : + nId = 3; // SDRHORZALIGN_RIGHT; + break; + case 2 : + nId = 2; // SDRVERTALIGN_BOTTOM; + break; + case 3 : + nId = 1; // SDRHORZALIGN_LEFT; + break; + } + if ( nId <= 3 ) + bValidGluePoint = sal_True; + } + break; + case OBJ_POLY : + case OBJ_PLIN : + case OBJ_LINE : + case OBJ_PATHLINE : + case OBJ_PATHFILL : + case OBJ_FREELINE : + case OBJ_FREEFILL : + case OBJ_SPLNLINE : + case OBJ_SPLNFILL : + case OBJ_PATHPOLY : + case OBJ_PATHPLIN : + { + if ( pList && ( pList->GetCount() > nC ) ) + { + bValidGluePoint = sal_True; + nId = (sal_Int32)((*pList)[ (sal_uInt16)nC].GetId() + 3 ); + } + else + { + sal_Bool bNotFound = sal_True; + + PolyPolygon aPolyPoly( EscherPropertyContainer::GetPolyPolygon( aXShape ) ); + sal_uInt16 k, j, nPolySize = aPolyPoly.Count(); + if ( nPolySize ) + { + sal_uInt32 nPointCount = 0; + Rectangle aBoundRect( aPolyPoly.GetBoundRect() ); + if ( aBoundRect.GetWidth() && aBoundRect.GetHeight() ) + { + for ( k = 0; bNotFound && ( k < nPolySize ); k++ ) + { + const Polygon& rPolygon = aPolyPoly.GetObject( k ); + for ( j = 0; bNotFound && ( j < rPolygon.GetSize() ); j++ ) + { + PolyFlags eFlags = rPolygon.GetFlags( j ); + if ( eFlags == POLY_NORMAL ) + { + if ( nC == nPointCount ) + { + const Point& rPoint = rPolygon.GetPoint( j ); + double fXRel = rPoint.X() - aBoundRect.Left(); + double fYRel = rPoint.Y() - aBoundRect.Top(); + sal_Int32 nWidth = aBoundRect.GetWidth(); + if ( !nWidth ) + nWidth = 1; + sal_Int32 nHeight= aBoundRect.GetHeight(); + if ( !nHeight ) + nHeight = 1; + fXRel /= (double)nWidth; + fXRel *= 10000; + fYRel /= (double)nHeight; + fYRel *= 10000; + aGluePoint.SetPos( Point( (sal_Int32)fXRel, (sal_Int32)fYRel ) ); + aGluePoint.SetPercent( sal_True ); + aGluePoint.SetAlign( SDRVERTALIGN_TOP | SDRHORZALIGN_LEFT ); + aGluePoint.SetEscDir( SDRESC_SMART ); + nId = (sal_Int32)((*pList)[ pList->Insert( aGluePoint ) ].GetId() + 3 ); + bNotFound = sal_False; + } + nPointCount++; + } + } + } + } + } + if ( !bNotFound ) + { + bValidGluePoint = sal_True; + } + } + } + break; + + case OBJ_CUSTOMSHAPE : + { + SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)((SdrObjCustomShape*)pO)->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + const rtl::OUString sPath( RTL_CONSTASCII_USTRINGPARAM ( "Path" ) ); + const rtl::OUString sGluePointType( RTL_CONSTASCII_USTRINGPARAM ( "GluePointType" ) ); + sal_Int16 nGluePointType = EnhancedCustomShapeGluePointType::SEGMENTS; + com::sun::star::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sPath, sGluePointType ); + if ( pAny ) + *pAny >>= nGluePointType; + else + { + const rtl::OUString sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) ); + rtl::OUString sShapeType; + pAny = aGeometryItem.GetPropertyValueByName( sType ); + if ( pAny ) + *pAny >>= sShapeType; + MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType ); + nGluePointType = GetCustomShapeConnectionTypeDefault( eSpType ); + } + if ( nGluePointType == EnhancedCustomShapeGluePointType::CUSTOM ) + { + if ( pList && ( pList->GetCount() > nC ) ) + { + bValidGluePoint = sal_True; + nId = (sal_Int32)((*pList)[ (sal_uInt16)nC].GetId() + 3 ); + } + } + else if ( nGluePointType == EnhancedCustomShapeGluePointType::RECT ) + { + if ( nC & 1 ) + { + if ( nSpFlags & SP_FFLIPH ) + nC ^= 2; // 1 <-> 3 + } + else + { + if ( nSpFlags & SP_FFLIPV ) + nC ^= 1; // 0 <-> 2 + } + switch( nC ) + { + case 0 : + nId = 0; // SDRVERTALIGN_TOP; + break; + case 1 : + nId = 3; // SDRHORZALIGN_RIGHT; + break; + case 2 : + nId = 2; // SDRVERTALIGN_BOTTOM; + break; + case 3 : + nId = 1; // SDRHORZALIGN_LEFT; + break; + } + if ( nId <= 3 ) + bValidGluePoint = sal_True; + } + else if ( nGluePointType == EnhancedCustomShapeGluePointType::SEGMENTS ) + { + const rtl::OUString sSegments( RTL_CONSTASCII_USTRINGPARAM ( "Segments" ) ); + const rtl::OUString sCoordinates( RTL_CONSTASCII_USTRINGPARAM ( "Coordinates" ) ); + + sal_uInt32 k, nPt = nC; + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment > aSegments; + pAny = aGeometryItem.GetPropertyValueByName( sPath, sSegments ); + if ( pAny ) + { + if ( *pAny >>= aSegments ) + { + for ( nPt = 0, k = 1; nC && ( k < (sal_uInt32)aSegments.getLength() ); k++ ) + { + sal_Int16 j, nCnt2 = aSegments[ k ].Count; + if ( aSegments[ k ].Command != EnhancedCustomShapeSegmentCommand::UNKNOWN ) + { + for ( j = 0; nC && ( j < nCnt2 ); j++ ) + { + switch( aSegments[ k ].Command ) + { + case EnhancedCustomShapeSegmentCommand::ENDSUBPATH : + case EnhancedCustomShapeSegmentCommand::CLOSESUBPATH : + case EnhancedCustomShapeSegmentCommand::LINETO : + case EnhancedCustomShapeSegmentCommand::MOVETO : + { + nC--; + nPt++; + } + break; + case EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX : + case EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY : + break; + + case EnhancedCustomShapeSegmentCommand::CURVETO : + { + nC--; + nPt += 3; + } + break; + + case EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO : + case EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE : + { + nC--; + nPt += 3; + } + break; + case EnhancedCustomShapeSegmentCommand::ARCTO : + case EnhancedCustomShapeSegmentCommand::ARC : + case EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO : + case EnhancedCustomShapeSegmentCommand::CLOCKWISEARC : + { + nC--; + nPt += 4; + } + break; + } + } + } + } + } + } + pAny = aGeometryItem.GetPropertyValueByName( sPath, sCoordinates ); + if ( pAny ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair > aCoordinates; + *pAny >>= aCoordinates; + if ( nPt < (sal_uInt32)aCoordinates.getLength() ) + { + nId = 4; + com::sun::star::drawing::EnhancedCustomShapeParameterPair& rPara = aCoordinates[ nPt ]; + sal_Int32 nX = 0, nY = 0; + if ( ( rPara.First.Value >>= nX ) && ( rPara.Second.Value >>= nY ) ) + { + const rtl::OUString sGluePoints( RTL_CONSTASCII_USTRINGPARAM ( "GluePoints" ) ); + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair > aGluePoints; + pAny = aGeometryItem.GetPropertyValueByName( sPath, sGluePoints ); + if ( pAny ) + *pAny >>= aGluePoints; + sal_Int32 nGluePoints = aGluePoints.getLength(); + aGluePoints.realloc( nGluePoints + 1 ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aGluePoints[ nGluePoints ].First, nX ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aGluePoints[ nGluePoints ].Second, nY ); + PropertyValue aProp; + aProp.Name = sGluePoints; + aProp.Value <<= aGluePoints; + aGeometryItem.SetPropertyValue( sPath, aProp ); + bValidGluePoint = sal_True; + ((SdrObjCustomShape*)pO)->SetMergedItem( aGeometryItem ); + SdrGluePointList* pLst = pO->ForceGluePointList(); + if ( pLst->GetCount() > nGluePoints ) + nId = (sal_Int32)((*pLst)[ (sal_uInt16)nGluePoints ].GetId() + 3 ); + } + } + } + } + } + break; + } + if ( bValidGluePoint ) + { + Reference< XPropertySet > xPropSet( aXConnector, UNO_QUERY ); + if ( xPropSet.is() ) + { + if ( nN ) + { + String aPropName( RTL_CONSTASCII_USTRINGPARAM( "EndShape" ) ); + aAny <<= aXShape; + SetPropValue( aAny, xPropSet, aPropName, sal_True ); + aPropName = String( RTL_CONSTASCII_USTRINGPARAM( "EndGluePointIndex" ) ); + aAny <<= nId; + SetPropValue( aAny, xPropSet, aPropName, sal_True ); + } + else + { + String aPropName( RTL_CONSTASCII_USTRINGPARAM( "StartShape" ) ); + aAny <<= aXShape; + SetPropValue( aAny, xPropSet, aPropName, sal_True ); + aPropName = String( RTL_CONSTASCII_USTRINGPARAM( "StartGluePointIndex" ) ); + aAny <<= nId; + SetPropValue( aAny, xPropSet, aPropName, sal_True ); + } + + // Not sure what this is good for, repaint or broadcast of object change. + //( Thus i am adding repaint here + pO->SetChanged(); + pO->BroadcastObjectChange(); + } + } + } + } + } + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +static basegfx::B2DPolygon GetLineArrow( const sal_Int32 nLineWidth, const MSO_LineEnd eLineEnd, + const MSO_LineEndWidth eLineWidth, const MSO_LineEndLength eLineLenght, + sal_Int32& rnArrowWidth, sal_Bool& rbArrowCenter, + String& rsArrowName, sal_Bool bScaleArrow ) +{ + basegfx::B2DPolygon aRetval; + double fLineWidth = nLineWidth < 70 ? 70.0 : nLineWidth; + double fLenghtMul, fWidthMul; + sal_Int32 nLineNumber; + switch( eLineLenght ) + { + default : + case mso_lineMediumLenArrow : fLenghtMul = 3.0; nLineNumber = 2; break; + case mso_lineShortArrow : fLenghtMul = 2.0; nLineNumber = 1; break; + case mso_lineLongArrow : fLenghtMul = 5.0; nLineNumber = 3; break; + } + switch( eLineWidth ) + { + default : + case mso_lineMediumWidthArrow : fWidthMul = 3.0; nLineNumber += 3; break; + case mso_lineNarrowArrow : fWidthMul = 2.0; break; + case mso_lineWideArrow : fWidthMul = 5.0; nLineNumber += 6; break; + } + + if ( bScaleArrow ) // #i33630 arrows imported from Word are too big + { + fWidthMul /= 1.75; + fLenghtMul/= 1.75; + } + + rbArrowCenter = sal_False; + switch ( eLineEnd ) + { + case mso_lineArrowEnd : + { + basegfx::B2DPolygon aTriangle; + aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50, 0.0 )); + aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth, fLenghtMul * fLineWidth )); + aTriangle.append(basegfx::B2DPoint( 0.0, fLenghtMul * fLineWidth )); + aTriangle.setClosed(true); + aRetval = aTriangle; + rsArrowName = String( RTL_CONSTASCII_STRINGPARAM( "msArrowEnd " ), RTL_TEXTENCODING_UTF8 ); + } + break; + + case mso_lineArrowOpenEnd : + { + switch( eLineLenght ) + { + default : + case mso_lineMediumLenArrow : fLenghtMul = 4.5; break; + case mso_lineShortArrow : fLenghtMul = 3.5; break; + case mso_lineLongArrow : fLenghtMul = 6.0; break; + } + switch( eLineWidth ) + { + default : + case mso_lineMediumWidthArrow : fWidthMul = 4.5; break; + case mso_lineNarrowArrow : fWidthMul = 3.5; break; + case mso_lineWideArrow : fWidthMul = 6.0; break; + } + basegfx::B2DPolygon aTriangle; + aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50 , 0.0 )); + aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth, fLenghtMul * fLineWidth * 0.91 )); + aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.85, fLenghtMul * fLineWidth )); + aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50, fLenghtMul * fLineWidth * 0.36 )); + aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.15, fLenghtMul * fLineWidth )); + aTriangle.append(basegfx::B2DPoint( 0.0, fLenghtMul * fLineWidth * 0.91 )); + aTriangle.setClosed(true); + aRetval = aTriangle; + rsArrowName = String( RTL_CONSTASCII_STRINGPARAM( "msArrowOpenEnd " ), RTL_TEXTENCODING_UTF8 ); + } + break; + case mso_lineArrowStealthEnd : + { + basegfx::B2DPolygon aTriangle; + aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50 , 0.0 )); + aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth , fLenghtMul * fLineWidth )); + aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50 , fLenghtMul * fLineWidth * 0.60 )); + aTriangle.append(basegfx::B2DPoint( 0.0, fLenghtMul * fLineWidth )); + aTriangle.setClosed(true); + aRetval = aTriangle; + rsArrowName = String( RTL_CONSTASCII_STRINGPARAM( "msArrowStealthEnd " ), RTL_TEXTENCODING_UTF8 ); + } + break; + case mso_lineArrowDiamondEnd : + { + basegfx::B2DPolygon aTriangle; + aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50 , 0.0 )); + aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth , fLenghtMul * fLineWidth * 0.50 )); + aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50 , fLenghtMul * fLineWidth )); + aTriangle.append(basegfx::B2DPoint( 0.0, fLenghtMul * fLineWidth * 0.50 )); + aTriangle.setClosed(true); + aRetval = aTriangle; + rbArrowCenter = sal_True; + rsArrowName = String( RTL_CONSTASCII_STRINGPARAM( "msArrowDiamondEnd " ), RTL_TEXTENCODING_UTF8 ); + } + break; + case mso_lineArrowOvalEnd : + { + aRetval = XPolygon( Point( (sal_Int32)( fWidthMul * fLineWidth * 0.50 ), 0 ), + (sal_Int32)( fWidthMul * fLineWidth * 0.50 ), + (sal_Int32)( fLenghtMul * fLineWidth * 0.50 ), 0, 3600 ).getB2DPolygon(); + rbArrowCenter = sal_True; + rsArrowName = String( RTL_CONSTASCII_STRINGPARAM( "msArrowOvalEnd " ), RTL_TEXTENCODING_UTF8 ); + } + break; + default: break; + } + rsArrowName.Append( String::CreateFromInt32( nLineNumber ) ); + rnArrowWidth = (sal_Int32)( fLineWidth * fWidthMul ); + + return aRetval; +} + +void DffPropertyReader::ApplyLineAttributes( SfxItemSet& rSet, const MSO_SPT eShapeType ) const // #i28269# +{ + sal_uInt32 nLineFlags(GetPropertyValue( DFF_Prop_fNoLineDrawDash )); + + if(!IsHardAttribute( DFF_Prop_fLine ) && !IsCustomShapeStrokedByDefault( eShapeType )) + { + nLineFlags &= ~0x08; + } + + if ( nLineFlags & 8 ) + { + // Linienattribute + sal_Int32 nLineWidth = (sal_Int32)GetPropertyValue( DFF_Prop_lineWidth, 9525 ); + + MSO_LineDashing eLineDashing = (MSO_LineDashing)GetPropertyValue( DFF_Prop_lineDashing, mso_lineSolid ); + if ( eLineDashing == mso_lineSolid ) + rSet.Put(XLineStyleItem( XLINE_SOLID ) ); + else + { +// MSO_LineCap eLineCap = (MSO_LineCap)GetPropertyValue( DFF_Prop_lineEndCapStyle, mso_lineEndCapSquare ); + + XDashStyle eDash = XDASH_RECT; + sal_uInt16 nDots = 1; + sal_uInt32 nDotLen = nLineWidth / 360; + sal_uInt16 nDashes = 0; + sal_uInt32 nDashLen = ( 8 * nLineWidth ) / 360; + sal_uInt32 nDistance = ( 3 * nLineWidth ) / 360;; + + switch ( eLineDashing ) + { + default: + case mso_lineDotSys : + { + nDots = 1; + nDashes = 0; + nDistance = nDotLen; + } + break; + + case mso_lineDashGEL : + { + nDots = 0; + nDashes = 1; + nDashLen = ( 4 * nLineWidth ) / 360; + } + break; + + case mso_lineDashDotGEL : + { + nDots = 1; + nDashes = 1; + nDashLen = ( 4 * nLineWidth ) / 360; + } + break; + + case mso_lineLongDashGEL : + { + nDots = 0; + nDashes = 1; + } + break; + + case mso_lineLongDashDotGEL : + { + nDots = 1; + nDashes = 1; + } + break; + + case mso_lineLongDashDotDotGEL: + { + nDots = 2; + nDashes = 1; + } + break; + } + + rSet.Put( XLineDashItem( String(), XDash( eDash, nDots, nDotLen, nDashes, nDashLen, nDistance ) ) ); + rSet.Put( XLineStyleItem( XLINE_DASH ) ); + } + rSet.Put( XLineColorItem( String(), rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_lineColor ), DFF_Prop_lineColor ) ) ); + if ( IsProperty( DFF_Prop_lineOpacity ) ) + { + double nTrans = GetPropertyValue(DFF_Prop_lineOpacity, 0x10000); + nTrans = (nTrans * 100) / 65536; + rSet.Put(XLineTransparenceItem( + sal_uInt16(100 - ::rtl::math::round(nTrans)))); + } + + rManager.ScaleEmu( nLineWidth ); + rSet.Put( XLineWidthItem( nLineWidth ) ); + + // SJ: LineJoint (setting each time a line is set, because our internal joint type has another default) + MSO_LineJoin eLineJointDefault = mso_lineJoinMiter; + if ( eShapeType == mso_sptMin ) + eLineJointDefault = mso_lineJoinRound; + MSO_LineJoin eLineJoint = (MSO_LineJoin)GetPropertyValue( DFF_Prop_lineJoinStyle, eLineJointDefault ); + XLineJoint eXLineJoint( XLINEJOINT_MITER ); + if ( eLineJoint == mso_lineJoinBevel ) + eXLineJoint = XLINEJOINT_BEVEL; + else if ( eLineJoint == mso_lineJoinRound ) + eXLineJoint = XLINEJOINT_ROUND; + rSet.Put( XLineJointItem( eXLineJoint ) ); + + if ( nLineFlags & 0x10 ) + { + sal_Bool bScaleArrows = rManager.pSdrModel->GetScaleUnit() == MAP_TWIP; + /////////////// + // LineStart // + /////////////// + if ( IsProperty( DFF_Prop_lineStartArrowhead ) ) + { + MSO_LineEnd eLineEnd = (MSO_LineEnd)GetPropertyValue( DFF_Prop_lineStartArrowhead ); + MSO_LineEndWidth eWidth = (MSO_LineEndWidth)GetPropertyValue( DFF_Prop_lineStartArrowWidth, mso_lineMediumWidthArrow ); + MSO_LineEndLength eLenght = (MSO_LineEndLength)GetPropertyValue( DFF_Prop_lineStartArrowLength, mso_lineMediumLenArrow ); + + sal_Int32 nArrowWidth; + sal_Bool bArrowCenter; + String aArrowName; + basegfx::B2DPolygon aPoly(GetLineArrow( nLineWidth, eLineEnd, eWidth, eLenght, nArrowWidth, bArrowCenter, aArrowName, bScaleArrows )); + + rSet.Put( XLineStartWidthItem( nArrowWidth ) ); + rSet.Put( XLineStartItem( aArrowName, basegfx::B2DPolyPolygon(aPoly) ) ); + rSet.Put( XLineStartCenterItem( bArrowCenter ) ); + } + ///////////// + // LineEnd // + ///////////// + if ( IsProperty( DFF_Prop_lineEndArrowhead ) ) + { + MSO_LineEnd eLineEnd = (MSO_LineEnd)GetPropertyValue( DFF_Prop_lineEndArrowhead ); + MSO_LineEndWidth eWidth = (MSO_LineEndWidth)GetPropertyValue( DFF_Prop_lineEndArrowWidth, mso_lineMediumWidthArrow ); + MSO_LineEndLength eLenght = (MSO_LineEndLength)GetPropertyValue( DFF_Prop_lineEndArrowLength, mso_lineMediumLenArrow ); + + sal_Int32 nArrowWidth; + sal_Bool bArrowCenter; + String aArrowName; + basegfx::B2DPolygon aPoly(GetLineArrow( nLineWidth, eLineEnd, eWidth, eLenght, nArrowWidth, bArrowCenter, aArrowName, bScaleArrows )); + + rSet.Put( XLineEndWidthItem( nArrowWidth ) ); + rSet.Put( XLineEndItem( aArrowName, basegfx::B2DPolyPolygon(aPoly) ) ); + rSet.Put( XLineEndCenterItem( bArrowCenter ) ); + } + if ( IsProperty( DFF_Prop_lineEndCapStyle ) ) + { + MSO_LineCap eLineCap = (MSO_LineCap)GetPropertyValue( DFF_Prop_lineEndCapStyle ); + const SfxPoolItem* pPoolItem = NULL; + if ( rSet.GetItemState( XATTR_LINEDASH, sal_False, &pPoolItem ) == SFX_ITEM_SET ) + { + XDashStyle eNewStyle = XDASH_RECT; + if ( eLineCap == mso_lineEndCapRound ) + eNewStyle = XDASH_ROUND; + const XDash& rOldDash = ( (const XLineDashItem*)pPoolItem )->GetDashValue(); + if ( rOldDash.GetDashStyle() != eNewStyle ) + { + XDash aNew( rOldDash ); + aNew.SetDashStyle( eNewStyle ); + rSet.Put( XLineDashItem( XubString(), aNew ) ); + } + } + } + } + } + else + rSet.Put( XLineStyleItem( XLINE_NONE ) ); +} + +struct ShadeColor +{ + Color aColor; + double fDist; + + ShadeColor( const Color& rC, double fR ) : aColor( rC ), fDist( fR ) {}; +}; + +void GetShadeColors( const SvxMSDffManager& rManager, const DffPropertyReader& rProperties, SvStream& rIn, std::vector< ShadeColor >& rShadeColors ) +{ + sal_uInt32 nPos = rIn.Tell(); + if ( rProperties.IsProperty( DFF_Prop_fillShadeColors ) ) + { + if ( rProperties.SeekToContent( DFF_Prop_fillShadeColors, rIn ) ) + { + sal_uInt16 i = 0, nNumElem = 0, nNumElemReserved = 0, nSize = 0; + rIn >> nNumElem >> nNumElemReserved >> nSize; + for ( ; i < nNumElem; i++ ) + { + sal_Int32 nColor; + sal_Int32 nDist; + + rIn >> nColor >> nDist; + rShadeColors.push_back( ShadeColor( rManager.MSO_CLR_ToColor( nColor, DFF_Prop_fillColor ), 1.0 - ( nDist / 65536.0 ) ) ); + } + } + } + if ( !rShadeColors.size() ) + { + rShadeColors.push_back( ShadeColor( rManager.MSO_CLR_ToColor( rProperties.GetPropertyValue( DFF_Prop_fillBackColor, COL_WHITE ), DFF_Prop_fillBackColor ), 0 ) ); + rShadeColors.push_back( ShadeColor( rManager.MSO_CLR_ToColor( rProperties.GetPropertyValue( DFF_Prop_fillColor, COL_WHITE ), DFF_Prop_fillColor ), 1 ) ); + } + rIn.Seek( nPos ); +} + +struct QuantErr +{ + double fRed; + double fGreen; + double fBlue; + + QuantErr() : fRed( 0.0 ), fGreen( 0.0 ), fBlue( 0.0 ){}; +}; + +void ApplyRectangularGradientAsBitmap( const SvxMSDffManager& rManager, SvStream& rIn, SfxItemSet& rSet, const std::vector< ShadeColor >& rShadeColors, const DffObjData& rObjData, sal_Int32 nFix16Angle ) +{ + Size aBitmapSizePixel( static_cast< sal_Int32 >( ( rObjData.aBoundRect.GetWidth() / 2540.0 ) * 90.0 ), // we will create a bitmap with 90 dpi + static_cast< sal_Int32 >( ( rObjData.aBoundRect.GetHeight() / 2540.0 ) * 90.0 ) ); + if ( aBitmapSizePixel.Width() && aBitmapSizePixel.Height() && ( aBitmapSizePixel.Width() <= 1024 ) && ( aBitmapSizePixel.Height() <= 1024 ) ) + { +// std::vector< QuantErr > aQuantErrCurrScan( aBitmapSizePixel.Width() + 1 ); +// std::vector< QuantErr > aQuantErrNextScan( aBitmapSizePixel.Width() + 1 ); + + double fFocusX = rManager.GetPropertyValue( DFF_Prop_fillToRight, 0 ) / 65536.0; + double fFocusY = rManager.GetPropertyValue( DFF_Prop_fillToBottom, 0 ) / 65536.0; + + Bitmap aBitmap( aBitmapSizePixel, 24 ); + BitmapWriteAccess* pAcc = aBitmap.AcquireWriteAccess(); + if ( pAcc ) + { + sal_Int32 nX, nY; + for ( nY = 0; nY < aBitmapSizePixel.Height(); nY++ ) + { + for ( nX = 0; nX < aBitmapSizePixel.Width(); nX++ ) + { + double fX = static_cast< double >( nX ) / aBitmapSizePixel.Width(); + double fY = static_cast< double >( nY ) / aBitmapSizePixel.Height(); + + double fD, fDist; + if ( fX < fFocusX ) + { + if ( fY < fFocusY ) + { + if ( fX > fY ) + fDist = fY, fD = fFocusY; + else + fDist = fX, fD = fFocusX; + } + else + { + if ( fX > ( 1 - fY ) ) + fDist = ( 1 - fY ), fD = 1 - fFocusY; + else + fDist = fX, fD = fFocusX; + } + } + else + { + if ( fY < fFocusY ) + { + if ( ( 1 - fX ) > fY ) + fDist = fY, fD = fFocusY; + else + fDist = ( 1 - fX ), fD = 1 - fFocusX; + } + else + { + if ( ( 1 - fX ) > ( 1 - fY ) ) + fDist = ( 1 - fY ), fD = 1 - fFocusY; + else + fDist = ( 1 - fX ), fD = 1 - fFocusX; + } + } + if ( fD != 0.0 ) + fDist /= fD; + + std::vector< ShadeColor >::const_iterator aIter( rShadeColors.begin() ); + double fA = 0.0; + Color aColorA = aIter->aColor; + double fB = 1.0; + Color aColorB( aColorA ); + while ( aIter != rShadeColors.end() ) + { + if ( aIter->fDist <= fDist ) + { + if ( aIter->fDist >= fA ) + { + fA = aIter->fDist; + aColorA = aIter->aColor; + } + } + if ( aIter->fDist > fDist ) + { + if ( aIter->fDist <= fB ) + { + fB = aIter->fDist; + aColorB = aIter->aColor; + } + } + aIter++; + } + double fRed = aColorA.GetRed(), fGreen = aColorA.GetGreen(), fBlue = aColorA.GetBlue(); + double fD1 = fB - fA; + if ( fD1 != 0.0 ) + { + fRed += ( ( ( fDist - fA ) * ( aColorB.GetRed() - aColorA.GetRed() ) ) / fD1 ); // + aQuantErrCurrScan[ nX ].fRed; + fGreen += ( ( ( fDist - fA ) * ( aColorB.GetGreen() - aColorA.GetGreen() ) ) / fD1 ); // + aQuantErrCurrScan[ nX ].fGreen; + fBlue += ( ( ( fDist - fA ) * ( aColorB.GetBlue() - aColorA.GetBlue() ) ) / fD1 ); // + aQuantErrCurrScan[ nX ].fBlue; + } + sal_Int16 nRed = static_cast< sal_Int16 >( fRed + 0.5 ); + sal_Int16 nGreen = static_cast< sal_Int16 >( fGreen + 0.5 ); + sal_Int16 nBlue = static_cast< sal_Int16 >( fBlue + 0.5 ); +/* + double fErr = fRed - nRed; + aQuantErrCurrScan[ nX + 1 ].fRed += 7.0 * fErr / 16.0; + if ( nX ) + aQuantErrNextScan[ nX - 1 ].fRed += 3.0 * fErr / 16.0; + aQuantErrNextScan[ nX ].fRed += 5.0 * fErr / 16.0; + aQuantErrNextScan[ nX + 1 ].fRed += 1.0 * fErr / 16.0; + + fErr = fGreen - nGreen; + aQuantErrCurrScan[ nX + 1 ].fGreen += 7.0 * fErr / 16.0; + if ( nX ) + aQuantErrNextScan[ nX - 1 ].fGreen += 3.0 * fErr / 16.0; + aQuantErrNextScan[ nX ].fGreen += 5.0 * fErr / 16.0; + aQuantErrNextScan[ nX + 1 ].fGreen += 1.0 * fErr / 16.0; + + fErr = fBlue - nBlue; + aQuantErrCurrScan[ nX + 1 ].fBlue += 7.0 * fErr / 16.0; + if ( nX ) + aQuantErrNextScan[ nX - 1 ].fBlue += 3.0 * fErr / 16.0; + aQuantErrNextScan[ nX ].fBlue += 5.0 * fErr / 16.0; + aQuantErrNextScan[ nX + 1 ].fBlue += 1.0 * fErr / 16.0; +*/ + if ( nRed < 0 ) + nRed = 0; + if ( nRed > 255 ) + nRed = 255; + if ( nGreen < 0 ) + nGreen = 0; + if ( nGreen > 255 ) + nGreen = 255; + if ( nBlue < 0 ) + nBlue = 0; + if ( nBlue > 255 ) + nBlue = 255; + + pAcc->SetPixel( nY, nX, BitmapColor( static_cast< sal_Int8 >( nRed ), static_cast< sal_Int8 >( nGreen ), static_cast< sal_Int8 >( nBlue ) ) ); + } +/* + aQuantErrCurrScan.swap( aQuantErrNextScan ); + std::vector< QuantErr >::iterator aIter( aQuantErrNextScan.begin() ); + while( aIter != aQuantErrNextScan.end() ) + { + *aIter = QuantErr(); + aIter++; + } +*/ + } + aBitmap.ReleaseAccess( pAcc ); + + if ( nFix16Angle ) + { + sal_Bool bRotateWithShape = sal_True; // sal_True seems to be default + sal_uInt32 nPos = rIn.Tell(); + if ( const_cast< SvxMSDffManager& >( rManager ).maShapeRecords.SeekToContent( rIn, DFF_msofbtUDefProp, SEEK_FROM_CURRENT_AND_RESTART ) ) + { + const_cast< SvxMSDffManager& >( rManager ).maShapeRecords.Current()->SeekToBegOfRecord( rIn ); + DffPropertyReader aSecPropSet( rManager ); + aSecPropSet.ReadPropSet( rIn, NULL ); + sal_Int32 nSecFillProperties = aSecPropSet.GetPropertyValue( DFF_Prop_fNoFillHitTest, 0x200020 ); + bRotateWithShape = ( nSecFillProperties & 0x0020 ); + } + rIn.Seek( nPos ); + if ( bRotateWithShape ) + { + aBitmap.Rotate( nFix16Angle / 10, rShadeColors[ 0 ].aColor ); + + sal_uLong nMirrorFlags = BMP_MIRROR_NONE; + if ( rObjData.nSpFlags & SP_FFLIPV ) + nMirrorFlags |= BMP_MIRROR_VERT; + if ( rObjData.nSpFlags & SP_FFLIPH ) + nMirrorFlags |= BMP_MIRROR_HORZ; + if ( nMirrorFlags != BMP_MIRROR_NONE ) + aBitmap.Mirror( nMirrorFlags ); + } + } + + XOBitmap aXBmp( aBitmap, XBITMAP_STRETCH ); + rSet.Put( XFillBmpTileItem( sal_False ) ); + rSet.Put( XFillBitmapItem( String(), aXBmp ) ); + } + } +} + +void DffPropertyReader::ApplyFillAttributes( SvStream& rIn, SfxItemSet& rSet, const DffObjData& rObjData ) const +{ + sal_uInt32 nFillFlags(GetPropertyValue( DFF_Prop_fNoFillHitTest )); + + std::vector< ShadeColor > aShadeColors; + GetShadeColors( rManager, *this, rIn, aShadeColors ); + + if(!IsHardAttribute( DFF_Prop_fFilled ) && !IsCustomShapeFilledByDefault( rObjData.eShapeType )) + { + nFillFlags &= ~0x10; + } + + if ( nFillFlags & 0x10 ) + { + MSO_FillType eMSO_FillType = (MSO_FillType)GetPropertyValue( DFF_Prop_fillType, mso_fillSolid ); + XFillStyle eXFill = XFILL_NONE; + switch( eMSO_FillType ) + { + case mso_fillSolid : // Fill with a solid color + eXFill = XFILL_SOLID; + break; + case mso_fillPattern : // Fill with a pattern (bitmap) + case mso_fillTexture : // A texture (pattern with its own color map) + case mso_fillPicture : // Center a picture in the shape + eXFill = XFILL_BITMAP; + break; + case mso_fillShadeCenter : // Shade from bounding rectangle to end point + { + if ( rObjData.aBoundRect.IsEmpty() )// size of object needed to be able + eXFill = XFILL_GRADIENT; // to create a bitmap substitution + else + eXFill = XFILL_BITMAP; + } + break; + case mso_fillShade : // Shade from start to end points + case mso_fillShadeShape : // Shade from shape outline to end point + case mso_fillShadeScale : // Similar to mso_fillShade, but the fillAngle + case mso_fillShadeTitle : // special type - shade to title --- for PP + eXFill = XFILL_GRADIENT; + break; +// case mso_fillBackground : // Use the background fill color/pattern + default: break; + } + rSet.Put( XFillStyleItem( eXFill ) ); + + if (IsProperty(DFF_Prop_fillOpacity)) + { + double nTrans = GetPropertyValue(DFF_Prop_fillOpacity); + nTrans = (nTrans * 100) / 65536; + rSet.Put(XFillTransparenceItem( + sal_uInt16(100 - ::rtl::math::round(nTrans)))); + } + + if ( ( eMSO_FillType == mso_fillShadeCenter ) && ( eXFill == XFILL_BITMAP ) ) + { + ApplyRectangularGradientAsBitmap( rManager, rIn, rSet, aShadeColors, rObjData, mnFix16Angle ); + } + else if ( eXFill == XFILL_GRADIENT ) + { + sal_Int32 nAngle = 3600 - ( ( Fix16ToAngle( GetPropertyValue( DFF_Prop_fillAngle, 0 ) ) + 5 ) / 10 ); + + // Rotationswinkel in Bereich zwingen + while ( nAngle >= 3600 ) + nAngle -= 3600; + while ( nAngle < 0 ) + nAngle += 3600; + + sal_Int32 nFocus = GetPropertyValue( DFF_Prop_fillFocus, 0 ); + XGradientStyle eGrad = XGRAD_LINEAR; + sal_Int32 nChgColors = 0; + + if ( nFocus < 0 ) // Bei negativem Focus sind die Farben zu tauschen + { + nFocus =- nFocus; + nChgColors ^= 1; + } + if( nFocus > 40 && nFocus < 60 ) + { + eGrad = XGRAD_AXIAL; // Besser gehts leider nicht + } + + sal_uInt16 nFocusX = (sal_uInt16)nFocus; + sal_uInt16 nFocusY = (sal_uInt16)nFocus; + + switch( eMSO_FillType ) + { + case mso_fillShadeShape : + { + eGrad = XGRAD_RECT; + nFocusY = nFocusX = 50; + nChgColors ^= 1; + } + break; + case mso_fillShadeCenter : + { + eGrad = XGRAD_RECT; + nFocusX = ( IsProperty( DFF_Prop_fillToRight ) ) ? 100 : 0; + nFocusY = ( IsProperty( DFF_Prop_fillToBottom ) ) ? 100 : 0; + nChgColors ^= 1; + } + break; + default: break; + } + Color aCol1( rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillColor, COL_WHITE ), DFF_Prop_fillColor ) ); + Color aCol2( rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillBackColor, COL_WHITE ), DFF_Prop_fillBackColor ) ); + + if ( nChgColors ) + { + Color aZwi( aCol1 ); + aCol1 = aCol2; + aCol2 = aZwi; + } + XGradient aGrad( aCol2, aCol1, eGrad, nAngle, nFocusX, nFocusY ); + aGrad.SetStartIntens( 100 ); + aGrad.SetEndIntens( 100 ); + rSet.Put( XFillGradientItem( String(), aGrad ) ); + } + else if ( eXFill == XFILL_BITMAP ) + { + if( IsProperty( DFF_Prop_fillBlip ) ) + { + Graphic aGraf; + // first try to get BLIP from cache + sal_Bool bOK = rManager.GetBLIP( GetPropertyValue( DFF_Prop_fillBlip ), aGraf, NULL ); + // then try directly from stream (i.e. Excel chart hatches/bitmaps) + if ( !bOK ) + bOK = SeekToContent( DFF_Prop_fillBlip, rIn ) && rManager.GetBLIPDirect( rIn, aGraf, NULL ); + if ( bOK ) + { + Bitmap aBmp( aGraf.GetBitmap() ); + + if ( eMSO_FillType == mso_fillPattern ) + { + Color aCol1( COL_WHITE ), aCol2( COL_WHITE ); + if ( IsProperty( DFF_Prop_fillColor ) ) + aCol1 = rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillColor ), DFF_Prop_fillColor ); + if ( IsProperty( DFF_Prop_fillBackColor ) ) + aCol2 = rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillBackColor ), DFF_Prop_fillBackColor ); + + XOBitmap aXOBitmap; + + // Bitmap einsetzen + aXOBitmap.SetBitmap( aBmp ); + aXOBitmap.SetBitmapType( XBITMAP_IMPORT ); + + if( aBmp.GetSizePixel().Width() == 8 && aBmp.GetSizePixel().Height() == 8 && aBmp.GetColorCount() == 2) + { + aXOBitmap.Bitmap2Array(); + aXOBitmap.SetBitmapType( XBITMAP_8X8 ); + aXOBitmap.SetPixelSize( aBmp.GetSizePixel() ); + + if( aXOBitmap.GetBackgroundColor() == COL_BLACK ) + { + aXOBitmap.SetPixelColor( aCol1 ); + aXOBitmap.SetBackgroundColor( aCol2 ); + } + else + { + aXOBitmap.SetPixelColor( aCol2 ); + aXOBitmap.SetBackgroundColor( aCol1 ); + } + } + rSet.Put( XFillBitmapItem( String(), aXOBitmap ) ); + } + else if ( eMSO_FillType == mso_fillTexture ) + { + XOBitmap aXBmp( aBmp, XBITMAP_STRETCH ); + rSet.Put( XFillBmpTileItem( sal_True ) ); + rSet.Put( XFillBitmapItem( String(), aXBmp ) ); + rSet.Put( XFillBmpSizeXItem( GetPropertyValue( DFF_Prop_fillWidth, 0 ) / 360 ) ); + rSet.Put( XFillBmpSizeYItem( GetPropertyValue( DFF_Prop_fillHeight, 0 ) / 360 ) ); + rSet.Put( XFillBmpSizeLogItem( sal_True ) ); + } + else + { + XOBitmap aXBmp( aBmp, XBITMAP_STRETCH ); + rSet.Put( XFillBitmapItem( String(), aXBmp ) ); + rSet.Put( XFillBmpTileItem( sal_False ) ); + } + } + } + } + } + else + rSet.Put( XFillStyleItem( XFILL_NONE ) ); +} + +void DffPropertyReader::ApplyCustomShapeTextAttributes( SfxItemSet& rSet ) const +{ +// sal_uInt32 nTextFlags = aTextObj.GetTextFlags(); + sal_Bool bVerticalText = sal_False; + sal_Int32 nTextLeft = GetPropertyValue( DFF_Prop_dxTextLeft, 25 * 3600 ) / 360; // 0.25 cm (emu) + sal_Int32 nTextRight = GetPropertyValue( DFF_Prop_dxTextRight, 25 * 3600 ) / 360; // 0.25 cm (emu) + sal_Int32 nTextTop = GetPropertyValue( DFF_Prop_dyTextTop, 13 * 3600 ) / 360; // 0.13 cm (emu) + sal_Int32 nTextBottom = GetPropertyValue( DFF_Prop_dyTextBottom, 13 * 3600 ) /360; // 0.13 cm (emu) + + SdrTextVertAdjust eTVA; + SdrTextHorzAdjust eTHA; + + if ( IsProperty( DFF_Prop_txflTextFlow ) ) + { + MSO_TextFlow eTextFlow = (MSO_TextFlow)( GetPropertyValue( DFF_Prop_txflTextFlow ) & 0xFFFF ); + switch( eTextFlow ) + { + case mso_txflTtoBA : /* #68110# */ // Top to Bottom @-font, oben -> unten + case mso_txflTtoBN : // Top to Bottom non-@, oben -> unten + case mso_txflVertN : // Vertical, non-@, oben -> unten + bVerticalText = sal_True; // nTextRotationAngle += 27000; + break; + default: break; + } + } + sal_Int32 nFontDirection = GetPropertyValue( DFF_Prop_cdirFont, mso_cdir0 ); + if ( ( nFontDirection == 1 ) || ( nFontDirection == 3 ) ) + bVerticalText = !bVerticalText; + + if ( bVerticalText ) + { + eTVA = SDRTEXTVERTADJUST_BLOCK; + eTHA = SDRTEXTHORZADJUST_CENTER; + + // Textverankerung lesen + MSO_Anchor eTextAnchor = (MSO_Anchor)GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop ); + + switch( eTextAnchor ) + { + case mso_anchorTop: + case mso_anchorTopCentered: + case mso_anchorTopBaseline: + case mso_anchorTopCenteredBaseline: + eTHA = SDRTEXTHORZADJUST_RIGHT; + break; + + case mso_anchorMiddle : + case mso_anchorMiddleCentered: + eTHA = SDRTEXTHORZADJUST_CENTER; + break; + + case mso_anchorBottom: + case mso_anchorBottomCentered: + case mso_anchorBottomBaseline: + case mso_anchorBottomCenteredBaseline: + eTHA = SDRTEXTHORZADJUST_LEFT; + break; + } + // if there is a 100% use of following attributes, the textbox can been aligned also in vertical direction + switch ( eTextAnchor ) + { + case mso_anchorTopCentered : + case mso_anchorMiddleCentered : + case mso_anchorBottomCentered : + case mso_anchorTopCenteredBaseline: + case mso_anchorBottomCenteredBaseline: + eTVA = SDRTEXTVERTADJUST_CENTER; + break; + + default : + eTVA = SDRTEXTVERTADJUST_TOP; + break; + } + } + else + { + eTVA = SDRTEXTVERTADJUST_CENTER; + eTHA = SDRTEXTHORZADJUST_BLOCK; + + // Textverankerung lesen + MSO_Anchor eTextAnchor = (MSO_Anchor)GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop ); + + switch( eTextAnchor ) + { + case mso_anchorTop: + case mso_anchorTopCentered: + case mso_anchorTopBaseline: + case mso_anchorTopCenteredBaseline: + eTVA = SDRTEXTVERTADJUST_TOP; + break; + + case mso_anchorMiddle : + case mso_anchorMiddleCentered: + eTVA = SDRTEXTVERTADJUST_CENTER; + break; + + case mso_anchorBottom: + case mso_anchorBottomCentered: + case mso_anchorBottomBaseline: + case mso_anchorBottomCenteredBaseline: + eTVA = SDRTEXTVERTADJUST_BOTTOM; + break; + } + // if there is a 100% usage of following attributes, the textbox can be aligned also in horizontal direction + switch ( eTextAnchor ) + { + case mso_anchorTopCentered : + case mso_anchorMiddleCentered : + case mso_anchorBottomCentered : + case mso_anchorTopCenteredBaseline: + case mso_anchorBottomCenteredBaseline: + eTHA = SDRTEXTHORZADJUST_CENTER; // the text has to be displayed using the full width; + break; + + default : + eTHA = SDRTEXTHORZADJUST_LEFT; + break; + } + } + rSet.Put( SvxFrameDirectionItem( bVerticalText ? FRMDIR_VERT_TOP_RIGHT : FRMDIR_HORI_LEFT_TOP, EE_PARA_WRITINGDIR ) ); + + rSet.Put( SdrTextVertAdjustItem( eTVA ) ); + rSet.Put( SdrTextHorzAdjustItem( eTHA ) ); + + rSet.Put( SdrTextLeftDistItem( nTextLeft ) ); + rSet.Put( SdrTextRightDistItem( nTextRight ) ); + rSet.Put( SdrTextUpperDistItem( nTextTop ) ); + rSet.Put( SdrTextLowerDistItem( nTextBottom ) ); + + rSet.Put( SdrTextWordWrapItem( (MSO_WrapMode)GetPropertyValue( DFF_Prop_WrapText, mso_wrapSquare ) != mso_wrapNone ? sal_True : sal_False ) ); + rSet.Put( SdrTextAutoGrowHeightItem( ( GetPropertyValue( DFF_Prop_FitTextToShape ) & 2 ) != 0 ) ); + +// rSet.Put( SdrTextAutoGrowWidthItem( (MSO_WrapMode)GetPropertyValue( DFF_Prop_WrapText, mso_wrapSquare ) != mso_wrapNone ? sal_False : sal_True ) ); +// rSet.Put( SdrTextAutoGrowHeightItem( ( GetPropertyValue( DFF_Prop_FitTextToShape ) & 2 ) != 0 ) ); +} + +void DffPropertyReader::ApplyCustomShapeGeometryAttributes( SvStream& rIn, SfxItemSet& rSet, const DffObjData& rObjData ) const +{ + + sal_uInt32 nAdjustmentsWhichNeedsToBeConverted = 0; + + /////////////////////////////////////// + // creating SdrCustomShapeGeometryItem // + /////////////////////////////////////// + typedef uno::Sequence< beans::PropertyValue > PropSeq; + typedef std::vector< beans::PropertyValue > PropVec; + typedef PropVec::iterator PropVecIter; + PropVecIter aIter; + PropVecIter aEnd; + + + // aPropVec will be filled with all PropertyValues + PropVec aPropVec; + PropertyValue aProp; + + ///////////////////////////////////////////////////////////////////// + // "Type" property, including the predefined CustomShape type name // + ///////////////////////////////////////////////////////////////////// + const rtl::OUString sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) ); + aProp.Name = sType; + aProp.Value <<= EnhancedCustomShapeTypeNames::Get( rObjData.eShapeType ); + aPropVec.push_back( aProp ); + +/* + ///////////////// + // "MirroredX" // + ///////////////// + if ( nShapeFlags & SP_FFLIPH ) + { + const rtl::OUString sMirroredX( RTL_CONSTASCII_USTRINGPARAM ( "MirroredX" ) ); + sal_Bool bMirroredX = sal_True; + aProp.Name = sMirroredX; + aProp.Value <<= bMirroredX; + aPropVec.push_back( aProp ); + } + ///////////////// + // "MirroredY" // + ///////////////// + if ( nShapeFlags & SP_FFLIPV ) + { + const rtl::OUString sMirroredY( RTL_CONSTASCII_USTRINGPARAM ( "MirroredY" ) ); + sal_Bool bMirroredY = sal_True; + aProp.Name = sMirroredY; + aProp.Value <<= bMirroredY; + aPropVec.push_back( aProp ); + } +*/ + /////////////// + // "ViewBox" // + /////////////// + + sal_Int32 nCoordWidth = 21600; // needed to replace handle type center with absolute value + sal_Int32 nCoordHeight= 21600; + if ( IsProperty( DFF_Prop_geoLeft ) || IsProperty( DFF_Prop_geoTop ) || IsProperty( DFF_Prop_geoRight ) || IsProperty( DFF_Prop_geoBottom ) ) + { + com::sun::star::awt::Rectangle aViewBox; + const rtl::OUString sViewBox( RTL_CONSTASCII_USTRINGPARAM ( "ViewBox" ) ); + aViewBox.X = GetPropertyValue( DFF_Prop_geoLeft, 0 ); + aViewBox.Y = GetPropertyValue( DFF_Prop_geoTop, 0 ); + aViewBox.Width = nCoordWidth = ((sal_Int32)GetPropertyValue( DFF_Prop_geoRight, 21600 ) ) - aViewBox.X; + aViewBox.Height = nCoordHeight = ((sal_Int32)GetPropertyValue( DFF_Prop_geoBottom, 21600 ) ) - aViewBox.Y; + aProp.Name = sViewBox; + aProp.Value <<= aViewBox; + aPropVec.push_back( aProp ); + } + ///////////////////// + // TextRotateAngle // + ///////////////////// + if ( IsProperty( DFF_Prop_txflTextFlow ) || IsProperty( DFF_Prop_cdirFont ) ) + { + sal_Int32 nTextRotateAngle = 0; + MSO_TextFlow eTextFlow = (MSO_TextFlow)( GetPropertyValue( DFF_Prop_txflTextFlow ) & 0xFFFF ); +/* sal_Int32 nFontDirection = GetPropertyValue( DFF_Prop_cdirFont, mso_cdir0 ); */ + + if ( eTextFlow == mso_txflBtoT ) // Bottom to Top non-@, unten -> oben + nTextRotateAngle += 90; + switch( GetPropertyValue( DFF_Prop_cdirFont, mso_cdir0 ) ) // SJ: mso_cdir90 and mso_cdir270 will be simulated by + { // activating vertical writing for the text objects + case mso_cdir90 : + { + if ( eTextFlow == mso_txflTtoBA ) + nTextRotateAngle -= 180; + } + break; + case mso_cdir180: nTextRotateAngle -= 180; break; + case mso_cdir270: + { + if ( eTextFlow != mso_txflTtoBA ) + nTextRotateAngle -= 180; + } + break; + default: break; + } + if ( nTextRotateAngle ) + { + double fTextRotateAngle = nTextRotateAngle; + const rtl::OUString sTextRotateAngle( RTL_CONSTASCII_USTRINGPARAM ( "TextRotateAngle" ) ); + aProp.Name = sTextRotateAngle; + aProp.Value <<= fTextRotateAngle; + aPropVec.push_back( aProp ); + } + } + ////////////////////////////////////////// + // "Extrusion" PropertySequence element // + ////////////////////////////////////////// + sal_Bool bExtrusionOn = ( GetPropertyValue( DFF_Prop_fc3DLightFace ) & 8 ) != 0; + if ( bExtrusionOn ) + { + PropVec aExtrusionPropVec; + + // "Extrusion" + const rtl::OUString sExtrusionOn( RTL_CONSTASCII_USTRINGPARAM ( "Extrusion" ) ); + aProp.Name = sExtrusionOn; + aProp.Value <<= bExtrusionOn; + aExtrusionPropVec.push_back( aProp ); + + // "Brightness" + if ( IsProperty( DFF_Prop_c3DAmbientIntensity ) ) + { + const rtl::OUString sExtrusionBrightness( RTL_CONSTASCII_USTRINGPARAM ( "Brightness" ) ); + double fBrightness = (sal_Int32)GetPropertyValue( DFF_Prop_c3DAmbientIntensity ); + fBrightness /= 655.36; + aProp.Name = sExtrusionBrightness; + aProp.Value <<= fBrightness; + aExtrusionPropVec.push_back( aProp ); + } + // "Depth" in 1/100mm + if ( IsProperty( DFF_Prop_c3DExtrudeBackward ) || IsProperty( DFF_Prop_c3DExtrudeForward ) ) + { + const rtl::OUString sDepth( RTL_CONSTASCII_USTRINGPARAM ( "Depth" ) ); + double fBackDepth = (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DExtrudeBackward, 1270 * 360 )) / 360.0; + double fForeDepth = (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DExtrudeForward ), 0 ) / 360.0; + double fDepth = fBackDepth + fForeDepth; + double fFraction = fDepth != 0.0 ? fForeDepth / fDepth : 0; + EnhancedCustomShapeParameterPair aDepthParaPair; + aDepthParaPair.First.Value <<= fDepth; + aDepthParaPair.First.Type = EnhancedCustomShapeParameterType::NORMAL; + aDepthParaPair.Second.Value <<= fFraction; + aDepthParaPair.Second.Type = EnhancedCustomShapeParameterType::NORMAL; + aProp.Name = sDepth; + aProp.Value <<= aDepthParaPair; + aExtrusionPropVec.push_back( aProp ); + } + // "Diffusion" + if ( IsProperty( DFF_Prop_c3DDiffuseAmt ) ) + { + const rtl::OUString sExtrusionDiffusion( RTL_CONSTASCII_USTRINGPARAM ( "Diffusion" ) ); + double fDiffusion = (sal_Int32)GetPropertyValue( DFF_Prop_c3DDiffuseAmt ); + fDiffusion /= 655.36; + aProp.Name = sExtrusionDiffusion; + aProp.Value <<= fDiffusion; + aExtrusionPropVec.push_back( aProp ); + } + // "NumberOfLineSegments" + if ( IsProperty( DFF_Prop_c3DTolerance ) ) + { + const rtl::OUString sExtrusionNumberOfLineSegments( RTL_CONSTASCII_USTRINGPARAM ( "NumberOfLineSegments" ) ); + aProp.Name = sExtrusionNumberOfLineSegments; + aProp.Value <<= (sal_Int32)GetPropertyValue( DFF_Prop_c3DTolerance ); + aExtrusionPropVec.push_back( aProp ); + } + // "LightFace" + const rtl::OUString sExtrusionLightFace( RTL_CONSTASCII_USTRINGPARAM ( "LightFace" ) ); + sal_Bool bExtrusionLightFace = ( GetPropertyValue( DFF_Prop_fc3DLightFace ) & 1 ) != 0; + aProp.Name = sExtrusionLightFace; + aProp.Value <<= bExtrusionLightFace; + aExtrusionPropVec.push_back( aProp ); + // "FirstLightHarsh" + const rtl::OUString sExtrusionFirstLightHarsh( RTL_CONSTASCII_USTRINGPARAM ( "FirstLightHarsh" ) ); + sal_Bool bExtrusionFirstLightHarsh = ( GetPropertyValue( DFF_Prop_fc3DFillHarsh ) & 2 ) != 0; + aProp.Name = sExtrusionFirstLightHarsh; + aProp.Value <<= bExtrusionFirstLightHarsh; + aExtrusionPropVec.push_back( aProp ); + // "SecondLightHarsh" + const rtl::OUString sExtrusionSecondLightHarsh( RTL_CONSTASCII_USTRINGPARAM ( "SecondLightHarsh" ) ); + sal_Bool bExtrusionSecondLightHarsh = ( GetPropertyValue( DFF_Prop_fc3DFillHarsh ) & 1 ) != 0; + aProp.Name = sExtrusionSecondLightHarsh; + aProp.Value <<= bExtrusionSecondLightHarsh; + aExtrusionPropVec.push_back( aProp ); + // "FirstLightLevel" + if ( IsProperty( DFF_Prop_c3DKeyIntensity ) ) + { + const rtl::OUString sExtrusionFirstLightLevel( RTL_CONSTASCII_USTRINGPARAM ( "FirstLightLevel" ) ); + double fFirstLightLevel = (sal_Int32)GetPropertyValue( DFF_Prop_c3DKeyIntensity ); + fFirstLightLevel /= 655.36; + aProp.Name = sExtrusionFirstLightLevel; + aProp.Value <<= fFirstLightLevel; + aExtrusionPropVec.push_back( aProp ); + } + // "SecondLightLevel" + if ( IsProperty( DFF_Prop_c3DFillIntensity ) ) + { + const rtl::OUString sExtrusionSecondLightLevel( RTL_CONSTASCII_USTRINGPARAM ( "SecondLightLevel" ) ); + double fSecondLightLevel = (sal_Int32)GetPropertyValue( DFF_Prop_c3DFillIntensity ); + fSecondLightLevel /= 655.36; + aProp.Name = sExtrusionSecondLightLevel; + aProp.Value <<= fSecondLightLevel; + aExtrusionPropVec.push_back( aProp ); + } + // "FirtstLightDirection" + if ( IsProperty( DFF_Prop_c3DKeyX ) || IsProperty( DFF_Prop_c3DKeyY ) || IsProperty( DFF_Prop_c3DKeyZ ) ) + { + double fLightX = (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DKeyX, 50000 )); + double fLightY = (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DKeyY, 0 )); + double fLightZ = (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DKeyZ, 10000 )); + ::com::sun::star::drawing::Direction3D aExtrusionFirstLightDirection( fLightX, fLightY, fLightZ ); + const rtl::OUString sExtrusionFirstLightDirection( RTL_CONSTASCII_USTRINGPARAM ( "FirstLightDirection" ) ); + aProp.Name = sExtrusionFirstLightDirection; + aProp.Value <<= aExtrusionFirstLightDirection; + aExtrusionPropVec.push_back( aProp ); + } + // "SecondLightDirection" + if ( IsProperty( DFF_Prop_c3DFillX ) || IsProperty( DFF_Prop_c3DFillY ) || IsProperty( DFF_Prop_c3DFillZ ) ) + { + double fLight2X = (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DFillX, (sal_uInt32)-50000 )); + double fLight2Y = (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DFillY, 0 )); + double fLight2Z = (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DFillZ, 10000 )); + ::com::sun::star::drawing::Direction3D aExtrusionSecondLightDirection( fLight2X, fLight2Y, fLight2Z ); + const rtl::OUString sExtrusionSecondLightDirection( RTL_CONSTASCII_USTRINGPARAM ( "SecondLightDirection" ) ); + aProp.Name = sExtrusionSecondLightDirection; + aProp.Value <<= aExtrusionSecondLightDirection; + aExtrusionPropVec.push_back( aProp ); + } + +/* LockRotationCenter, OrientationAngle and Orientation needs to be converted to use the properties AngleX, AngleY and RotationAngle instead. + // "LockRotationCenter" + const rtl::OUString sExtrusionLockRotationCenter( RTL_CONSTASCII_USTRINGPARAM ( "LockRotationCenter" ) ); + sal_Bool bExtrusionLockRotationCenter = ( GetPropertyValue( DFF_Prop_fc3DFillHarsh ) & 16 ) != 0; + aProp.Name = sExtrusionLockRotationCenter; + aProp.Value <<= bExtrusionLockRotationCenter; + aExtrusionPropVec.push_back( aProp ); + + // "Orientation" + if ( IsProperty( DFF_Prop_c3DRotationAxisX ) || IsProperty( DFF_Prop_c3DRotationAxisY ) || IsProperty( DFF_Prop_c3DRotationAxisZ ) ) + { + double fRotX = (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DRotationAxisX, 100 )); + double fRotY = (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DRotationAxisY, 0 )); + double fRotZ = (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DRotationAxisZ, 0 )); + ::com::sun::star::drawing::Direction3D aExtrusionDirection( fRotX, fRotY, fRotZ ); + const rtl::OUString sExtrusionDirection( RTL_CONSTASCII_USTRINGPARAM ( "Orientation" ) ); + aProp.Name = sExtrusionDirection; + aProp.Value <<= aExtrusionDirection; + aExtrusionPropVec.push_back( aProp ); + } + // "OrientationAngle" in Grad + if ( IsProperty( DFF_Prop_c3DRotationAngle ) ) + { + const rtl::OUString sExtrusionOrientationAngle( RTL_CONSTASCII_USTRINGPARAM ( "OrientationAngle" ) ); + double fOrientationAngle = (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DRotationAngle )) / 65536.0; + aProp.Name = sExtrusionOrientationAngle; + aProp.Value <<= fOrientationAngle; + aExtrusionPropVec.push_back( aProp ); + } +*/ + + // "Metal" + const rtl::OUString sExtrusionMetal( RTL_CONSTASCII_USTRINGPARAM ( "Metal" ) ); + sal_Bool bExtrusionMetal = ( GetPropertyValue( DFF_Prop_fc3DLightFace ) & 4 ) != 0; + aProp.Name = sExtrusionMetal; + aProp.Value <<= bExtrusionMetal; + aExtrusionPropVec.push_back( aProp ); +// if ( IsProperty( DFF_Prop_c3DExtrudePlane ) ) +// { +// UPS +// } + // "ShadeMode" + if ( IsProperty( DFF_Prop_c3DRenderMode ) ) + { + const rtl::OUString sExtrusionShadeMode( RTL_CONSTASCII_USTRINGPARAM ( "ShadeMode" ) ); + sal_uInt32 nExtrusionRenderMode = GetPropertyValue( DFF_Prop_c3DRenderMode ); + com::sun::star::drawing::ShadeMode eExtrusionShadeMode( com::sun::star::drawing::ShadeMode_FLAT ); + if ( nExtrusionRenderMode == mso_Wireframe ) + eExtrusionShadeMode = com::sun::star::drawing::ShadeMode_DRAFT; + + aProp.Name = sExtrusionShadeMode; + aProp.Value <<= eExtrusionShadeMode; + aExtrusionPropVec.push_back( aProp ); + } + // "RotateAngle" in Grad + if ( IsProperty( DFF_Prop_c3DXRotationAngle ) || IsProperty( DFF_Prop_c3DYRotationAngle ) ) + { + const rtl::OUString sExtrusionAngle( RTL_CONSTASCII_USTRINGPARAM ( "RotateAngle" ) ); + double fAngleX = (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DXRotationAngle, 0 )) / 65536.0; + double fAngleY = (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DYRotationAngle, 0 )) / 65536.0; + EnhancedCustomShapeParameterPair aRotateAnglePair; + aRotateAnglePair.First.Value <<= fAngleX; + aRotateAnglePair.First.Type = EnhancedCustomShapeParameterType::NORMAL; + aRotateAnglePair.Second.Value <<= fAngleY; + aRotateAnglePair.Second.Type = EnhancedCustomShapeParameterType::NORMAL; + aProp.Name = sExtrusionAngle; + aProp.Value <<= aRotateAnglePair; + aExtrusionPropVec.push_back( aProp ); + } + + // "AutoRotationCenter" + if ( ( GetPropertyValue( DFF_Prop_fc3DFillHarsh ) & 8 ) == 0 ) + { + // "RotationCenter" + if ( IsProperty( DFF_Prop_c3DRotationCenterX ) || IsProperty( DFF_Prop_c3DRotationCenterY ) || IsProperty( DFF_Prop_c3DRotationCenterZ ) ) + { + ::com::sun::star::drawing::Direction3D aRotationCenter( + (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DRotationCenterX, 0 )) / 360.0, + (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DRotationCenterY, 0 )) / 360.0, + (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DRotationCenterZ, 0 )) / 360.0 ); + + const rtl::OUString sExtrusionRotationCenter( RTL_CONSTASCII_USTRINGPARAM ( "RotationCenter" ) ); + aProp.Name = sExtrusionRotationCenter; + aProp.Value <<= aRotationCenter; + aExtrusionPropVec.push_back( aProp ); + } + } + // "Shininess" + if ( IsProperty( DFF_Prop_c3DShininess ) ) + { + const rtl::OUString sExtrusionShininess( RTL_CONSTASCII_USTRINGPARAM ( "Shininess" ) ); + double fShininess = (sal_Int32)GetPropertyValue( DFF_Prop_c3DShininess ); + fShininess /= 655.36; + aProp.Name = sExtrusionShininess; + aProp.Value <<= fShininess; + aExtrusionPropVec.push_back( aProp ); + } + // "Skew" + if ( IsProperty( DFF_Prop_c3DSkewAmount ) || IsProperty( DFF_Prop_c3DSkewAngle ) ) + { + const rtl::OUString sExtrusionSkew( RTL_CONSTASCII_USTRINGPARAM ( "Skew" ) ); + double fSkewAmount = (sal_Int32)GetPropertyValue( DFF_Prop_c3DSkewAmount, 50 ); + double fSkewAngle = (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DSkewAngle, sal::static_int_cast< sal_uInt32 >(-135 * 65536) )) / 65536.0; + + EnhancedCustomShapeParameterPair aSkewPair; + aSkewPair.First.Value <<= fSkewAmount; + aSkewPair.First.Type = EnhancedCustomShapeParameterType::NORMAL; + aSkewPair.Second.Value <<= fSkewAngle; + aSkewPair.Second.Type = EnhancedCustomShapeParameterType::NORMAL; + aProp.Name = sExtrusionSkew; + aProp.Value <<= aSkewPair; + aExtrusionPropVec.push_back( aProp ); + } + // "Specularity" + if ( IsProperty( DFF_Prop_c3DSpecularAmt ) ) + { + const rtl::OUString sExtrusionSpecularity( RTL_CONSTASCII_USTRINGPARAM ( "Specularity" ) ); + double fSpecularity = (sal_Int32)GetPropertyValue( DFF_Prop_c3DSpecularAmt ); + fSpecularity /= 1333; + aProp.Name = sExtrusionSpecularity; + aProp.Value <<= fSpecularity; + aExtrusionPropVec.push_back( aProp ); + } + // "ProjectionMode" + const rtl::OUString sExtrusionProjectionMode( RTL_CONSTASCII_USTRINGPARAM ( "ProjectionMode" ) ); + ProjectionMode eProjectionMode = GetPropertyValue( DFF_Prop_fc3DFillHarsh ) & 4 ? ProjectionMode_PARALLEL : ProjectionMode_PERSPECTIVE; + aProp.Name = sExtrusionProjectionMode; + aProp.Value <<= eProjectionMode; + aExtrusionPropVec.push_back( aProp ); + + // "ViewPoint" in 1/100mm + if ( IsProperty( DFF_Prop_c3DXViewpoint ) || IsProperty( DFF_Prop_c3DYViewpoint ) || IsProperty( DFF_Prop_c3DZViewpoint ) ) + { + double fViewX = (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DXViewpoint, 1249920 )) / 360.0; + double fViewY = (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DYViewpoint, (sal_uInt32)-1249920 ))/ 360.0; + double fViewZ = (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DZViewpoint, 9000000 )) / 360.0; + ::com::sun::star::drawing::Position3D aExtrusionViewPoint( fViewX, fViewY, fViewZ ); + const rtl::OUString sExtrusionViewPoint( RTL_CONSTASCII_USTRINGPARAM ( "ViewPoint" ) ); + aProp.Name = sExtrusionViewPoint; + aProp.Value <<= aExtrusionViewPoint; + aExtrusionPropVec.push_back( aProp ); + } + // "Origin" + if ( IsProperty( DFF_Prop_c3DOriginX ) || IsProperty( DFF_Prop_c3DOriginY ) ) + { + const rtl::OUString sExtrusionOrigin( RTL_CONSTASCII_USTRINGPARAM ( "Origin" ) ); + double fOriginX = (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DOriginX, 0 )); + double fOriginY = (double)((sal_Int32)GetPropertyValue( DFF_Prop_c3DOriginY, 0 )); + fOriginX /= 65536; + fOriginY /= 65536; + EnhancedCustomShapeParameterPair aOriginPair; + aOriginPair.First.Value <<= fOriginX; + aOriginPair.First.Type = EnhancedCustomShapeParameterType::NORMAL; + aOriginPair.Second.Value <<= fOriginY; + aOriginPair.Second.Type = EnhancedCustomShapeParameterType::NORMAL; + aProp.Name = sExtrusionOrigin; + aProp.Value <<= aOriginPair; + aExtrusionPropVec.push_back( aProp ); + } + // "ExtrusionColor" + const rtl::OUString sExtrusionColor( RTL_CONSTASCII_USTRINGPARAM ( "Color" ) ); + sal_Bool bExtrusionColor = IsProperty( DFF_Prop_c3DExtrusionColor ); // ( GetPropertyValue( DFF_Prop_fc3DLightFace ) & 2 ) != 0; + aProp.Name = sExtrusionColor; + aProp.Value <<= bExtrusionColor; + aExtrusionPropVec.push_back( aProp ); + if ( IsProperty( DFF_Prop_c3DExtrusionColor ) ) + rSet.Put( XSecondaryFillColorItem( String(), rManager.MSO_CLR_ToColor( + GetPropertyValue( DFF_Prop_c3DExtrusionColor ), DFF_Prop_c3DExtrusionColor ) ) ); + // pushing the whole Extrusion element + const rtl::OUString sExtrusion( RTL_CONSTASCII_USTRINGPARAM ( "Extrusion" ) ); + PropSeq aExtrusionPropSeq( aExtrusionPropVec.size() ); + aIter = aExtrusionPropVec.begin(); + aEnd = aExtrusionPropVec.end(); + beans::PropertyValue* pExtrusionValues = aExtrusionPropSeq.getArray(); + while ( aIter != aEnd ) + *pExtrusionValues++ = *aIter++; + aProp.Name = sExtrusion; + aProp.Value <<= aExtrusionPropSeq; + aPropVec.push_back( aProp ); + } + + ///////////////////////////////////////// + // "Equations" PropertySequence element // + ///////////////////////////////////////// + if ( IsProperty( DFF_Prop_pFormulas ) ) + { + sal_uInt16 i; + sal_uInt16 nNumElem = 0; + sal_uInt16 nNumElemMem = 0; + sal_uInt16 nElemSize = 8; + + if ( SeekToContent( DFF_Prop_pFormulas, rIn ) ) + rIn >> nNumElem >> nNumElemMem >> nElemSize; + + sal_Int16 nP1, nP2, nP3; + sal_uInt16 nFlags; + + uno::Sequence< rtl::OUString > aEquations( nNumElem ); + for ( i = 0; i < nNumElem; i++ ) + { + rIn >> nFlags >> nP1 >> nP2 >> nP3; + aEquations[ i ] = EnhancedCustomShape2d::GetEquation( nFlags, nP1, nP2, nP3 ); + } + // pushing the whole Equations element + const rtl::OUString sEquations( RTL_CONSTASCII_USTRINGPARAM ( "Equations" ) ); + aProp.Name = sEquations; + aProp.Value <<= aEquations; + aPropVec.push_back( aProp ); + } + + //////////////////////////////////////// + // "Handles" PropertySequence element // + //////////////////////////////////////// + if ( IsProperty( DFF_Prop_Handles ) ) + { + sal_uInt16 i; + sal_uInt16 nNumElem = 0; + sal_uInt16 nNumElemMem = 0; + sal_uInt16 nElemSize = 36; + + if ( SeekToContent( DFF_Prop_Handles, rIn ) ) + rIn >> nNumElem >> nNumElemMem >> nElemSize; + if ( nElemSize == 36 ) + { + uno::Sequence< beans::PropertyValues > aHandles( nNumElem ); + for ( i = 0; i < nNumElem; i++ ) + { + PropVec aHandlePropVec; + sal_uInt32 nFlags; + sal_Int32 nPositionX, nPositionY, nCenterX, nCenterY, nRangeXMin, nRangeXMax, nRangeYMin, nRangeYMax; + rIn >> nFlags + >> nPositionX + >> nPositionY + >> nCenterX + >> nCenterY + >> nRangeXMin + >> nRangeXMax + >> nRangeYMin + >> nRangeYMax; + + if ( nPositionX == 2 ) // replacing center position with absolute value + nPositionX = nCoordWidth / 2; + if ( nPositionY == 2 ) + nPositionY = nCoordHeight / 2; + EnhancedCustomShapeParameterPair aPosition; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.First, nPositionX, sal_True, sal_True ); + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.Second, nPositionY, sal_True, sal_False ); + const rtl::OUString sHandlePosition( RTL_CONSTASCII_USTRINGPARAM ( "Position" ) ); + aProp.Name = sHandlePosition; + aProp.Value <<= aPosition; + aHandlePropVec.push_back( aProp ); + + if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_X ) + { + sal_Bool bMirroredX = sal_True; + const rtl::OUString sHandleMirroredX( RTL_CONSTASCII_USTRINGPARAM ( "MirroredX" ) ); + aProp.Name = sHandleMirroredX; + aProp.Value <<= bMirroredX; + aHandlePropVec.push_back( aProp ); + } + if ( nFlags & MSDFF_HANDLE_FLAGS_MIRRORED_Y ) + { + sal_Bool bMirroredY = sal_True; + const rtl::OUString sHandleMirroredY( RTL_CONSTASCII_USTRINGPARAM ( "MirroredY" ) ); + aProp.Name = sHandleMirroredY; + aProp.Value <<= bMirroredY; + aHandlePropVec.push_back( aProp ); + } + if ( nFlags & MSDFF_HANDLE_FLAGS_SWITCHED ) + { + sal_Bool bSwitched = sal_True; + const rtl::OUString sHandleSwitched( RTL_CONSTASCII_USTRINGPARAM ( "Switched" ) ); + aProp.Name = sHandleSwitched; + aProp.Value <<= bSwitched; + aHandlePropVec.push_back( aProp ); + } + if ( nFlags & MSDFF_HANDLE_FLAGS_POLAR ) + { + if ( nCenterX == 2 ) + nCenterX = nCoordWidth / 2; + if ( nCenterY == 2 ) + nCenterY = nCoordHeight / 2; + if ( ( nPositionY >= 0x256 ) || ( nPositionY <= 0x107 ) ) // position y + nAdjustmentsWhichNeedsToBeConverted |= ( 1 << i ); + EnhancedCustomShapeParameterPair aPolar; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPolar.First, nCenterX, ( nFlags & 0x800 ) != 0, sal_True ); + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPolar.Second, nCenterY, ( nFlags & 0x1000 ) != 0, sal_False ); + const rtl::OUString sHandlePolar( RTL_CONSTASCII_USTRINGPARAM ( "Polar" ) ); + aProp.Name = sHandlePolar; + aProp.Value <<= aPolar; + aHandlePropVec.push_back( aProp ); + } + if ( nFlags & MSDFF_HANDLE_FLAGS_MAP ) + { + if ( nCenterX == 2 ) + nCenterX = nCoordWidth / 2; + if ( nCenterY == 2 ) + nCenterY = nCoordHeight / 2; + EnhancedCustomShapeParameterPair aMap; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aMap.First, nCenterX, ( nFlags & 0x800 ) != 0, sal_True ); + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aMap.Second, nCenterY, ( nFlags & 0x1000 ) != 0, sal_False ); + const rtl::OUString sHandleMap( RTL_CONSTASCII_USTRINGPARAM ( "Map" ) ); + aProp.Name = sHandleMap; + aProp.Value <<= aMap; + aHandlePropVec.push_back( aProp ); + } + if ( nFlags & MSDFF_HANDLE_FLAGS_RANGE ) + { + if ( (sal_uInt32)nRangeXMin != 0x80000000 ) + { + if ( nRangeXMin == 2 ) + nRangeXMin = nCoordWidth / 2; + EnhancedCustomShapeParameter aRangeXMinimum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMinimum, nRangeXMin, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MIN_IS_SPECIAL ) != 0, sal_True ); + const rtl::OUString sHandleRangeXMinimum( RTL_CONSTASCII_USTRINGPARAM ( "RangeXMinimum" ) ); + aProp.Name = sHandleRangeXMinimum; + aProp.Value <<= aRangeXMinimum; + aHandlePropVec.push_back( aProp ); + } + if ( (sal_uInt32)nRangeXMax != 0x7fffffff ) + { + if ( nRangeXMax == 2 ) + nRangeXMax = nCoordWidth / 2; + EnhancedCustomShapeParameter aRangeXMaximum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMaximum, nRangeXMax, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MAX_IS_SPECIAL ) != 0, sal_False ); + const rtl::OUString sHandleRangeXMaximum( RTL_CONSTASCII_USTRINGPARAM ( "RangeXMaximum" ) ); + aProp.Name = sHandleRangeXMaximum; + aProp.Value <<= aRangeXMaximum; + aHandlePropVec.push_back( aProp ); + } + if ( (sal_uInt32)nRangeYMin != 0x80000000 ) + { + if ( nRangeYMin == 2 ) + nRangeYMin = nCoordHeight / 2; + EnhancedCustomShapeParameter aRangeYMinimum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMinimum, nRangeYMin, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_Y_MIN_IS_SPECIAL ) != 0, sal_True ); + const rtl::OUString sHandleRangeYMinimum( RTL_CONSTASCII_USTRINGPARAM ( "RangeYMinimum" ) ); + aProp.Name = sHandleRangeYMinimum; + aProp.Value <<= aRangeYMinimum; + aHandlePropVec.push_back( aProp ); + } + if ( (sal_uInt32)nRangeYMax != 0x7fffffff ) + { + if ( nRangeYMax == 2 ) + nRangeYMax = nCoordHeight / 2; + EnhancedCustomShapeParameter aRangeYMaximum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMaximum, nRangeYMax, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_Y_MAX_IS_SPECIAL ) != 0, sal_False ); + const rtl::OUString sHandleRangeYMaximum( RTL_CONSTASCII_USTRINGPARAM ( "RangeYMaximum" ) ); + aProp.Name = sHandleRangeYMaximum; + aProp.Value <<= aRangeYMaximum; + aHandlePropVec.push_back( aProp ); + } + } + if ( nFlags & MSDFF_HANDLE_FLAGS_RADIUS_RANGE ) + { + if ( (sal_uInt32)nRangeXMin != 0x7fffffff ) + { + if ( nRangeXMin == 2 ) + nRangeXMin = nCoordWidth / 2; + EnhancedCustomShapeParameter aRadiusRangeMinimum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMinimum, nRangeXMin, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MIN_IS_SPECIAL ) != 0, sal_True ); + const rtl::OUString sHandleRadiusRangeMinimum( RTL_CONSTASCII_USTRINGPARAM ( "RadiusRangeMinimum" ) ); + aProp.Name = sHandleRadiusRangeMinimum; + aProp.Value <<= aRadiusRangeMinimum; + aHandlePropVec.push_back( aProp ); + } + if ( (sal_uInt32)nRangeXMax != 0x80000000 ) + { + if ( nRangeXMax == 2 ) + nRangeXMax = nCoordWidth / 2; + EnhancedCustomShapeParameter aRadiusRangeMaximum; + EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMaximum, nRangeXMax, + ( nFlags & MSDFF_HANDLE_FLAGS_RANGE_X_MAX_IS_SPECIAL ) != 0, sal_False ); + const rtl::OUString sHandleRadiusRangeMaximum( RTL_CONSTASCII_USTRINGPARAM ( "RadiusRangeMaximum" ) ); + aProp.Name = sHandleRadiusRangeMaximum; + aProp.Value <<= aRadiusRangeMaximum; + aHandlePropVec.push_back( aProp ); + } + } + if ( aHandlePropVec.size() ) + { + PropSeq aHandlePropSeq( aHandlePropVec.size() ); + aIter = aHandlePropVec.begin(); + aEnd = aHandlePropVec.end(); + beans::PropertyValue* pHandleValues = aHandlePropSeq.getArray(); + while ( aIter != aEnd ) + *pHandleValues++ = *aIter++; + aHandles[ i ] = aHandlePropSeq; + } + } + // pushing the whole Handles element + const rtl::OUString sHandles( RTL_CONSTASCII_USTRINGPARAM ( "Handles" ) ); + aProp.Name = sHandles; + aProp.Value <<= aHandles; + aPropVec.push_back( aProp ); + } + } + else + { + const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( rObjData.eShapeType ); + if ( pDefCustomShape && pDefCustomShape->nHandles && pDefCustomShape->pHandles ) + { + sal_Int32 i, nCnt = pDefCustomShape->nHandles; + const SvxMSDffHandle* pData = pDefCustomShape->pHandles; + for ( i = 0; i < nCnt; i++, pData++ ) + { + if ( pData->nFlags & MSDFF_HANDLE_FLAGS_POLAR ) + { + if ( ( pData->nPositionY >= 0x256 ) || ( pData->nPositionY <= 0x107 ) ) + nAdjustmentsWhichNeedsToBeConverted |= ( 1 << i ); + } + } + } + } + ///////////////////////////////////// + // "Path" PropertySequence element // + ///////////////////////////////////// + { + PropVec aPathPropVec; + + // "Path/ExtrusionAllowed" + if ( IsHardAttribute( DFF_Prop_f3DOK ) ) + { + const rtl::OUString sExtrusionAllowed( RTL_CONSTASCII_USTRINGPARAM ( "ExtrusionAllowed" ) ); + sal_Bool bExtrusionAllowed = ( GetPropertyValue( DFF_Prop_fFillOK ) & 16 ) != 0; + aProp.Name = sExtrusionAllowed; + aProp.Value <<= bExtrusionAllowed; + aPathPropVec.push_back( aProp ); + } + // "Path/ConcentricGradientFillAllowed" + if ( IsHardAttribute( DFF_Prop_fFillShadeShapeOK ) ) + { + const rtl::OUString sConcentricGradientFillAllowed( RTL_CONSTASCII_USTRINGPARAM ( "ConcentricGradientFillAllowed" ) ); + sal_Bool bConcentricGradientFillAllowed = ( GetPropertyValue( DFF_Prop_fFillOK ) & 2 ) != 0; + aProp.Name = sConcentricGradientFillAllowed; + aProp.Value <<= bConcentricGradientFillAllowed; + aPathPropVec.push_back( aProp ); + } + // "Path/TextPathAllowed" + if ( IsHardAttribute( DFF_Prop_fGtextOK ) || ( GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 ) & 0x4000 ) ) + { + const rtl::OUString sTextPathAllowed( RTL_CONSTASCII_USTRINGPARAM ( "TextPathAllowed" ) ); + sal_Bool bTextPathAllowed = ( GetPropertyValue( DFF_Prop_fFillOK ) & 4 ) != 0; + aProp.Name = sTextPathAllowed; + aProp.Value <<= bTextPathAllowed; + aPathPropVec.push_back( aProp ); + } + // Path/Coordinates + if ( IsProperty( DFF_Prop_pVertices ) ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair > aCoordinates; + + sal_uInt16 i; + sal_uInt16 nNumElemVert = 0; + sal_uInt16 nNumElemMemVert = 0; + sal_uInt16 nElemSizeVert = 8; + + if ( SeekToContent( DFF_Prop_pVertices, rIn ) ) + rIn >> nNumElemVert >> nNumElemMemVert >> nElemSizeVert; + if ( nNumElemVert ) + { + sal_Int32 nX, nY; + sal_Int16 nTmpA, nTmpB; + aCoordinates.realloc( nNumElemVert ); + for ( i = 0; i < nNumElemVert; i++ ) + { + if ( nElemSizeVert == 8 ) + { + rIn >> nX + >> nY; + } + else + { + rIn >> nTmpA + >> nTmpB; + + nX = nTmpA; + nY = nTmpB; + } + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aCoordinates[ i ].First, nX ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aCoordinates[ i ].Second, nY ); + } + } + const rtl::OUString sCoordinates( RTL_CONSTASCII_USTRINGPARAM ( "Coordinates" ) ); + aProp.Name = sCoordinates; + aProp.Value <<= aCoordinates; + aPathPropVec.push_back( aProp ); + } + // Path/Segments + if ( IsProperty( DFF_Prop_pSegmentInfo ) ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment > aSegments; + + sal_uInt16 i, nTmp; + sal_uInt16 nNumElemSeg = 0; + sal_uInt16 nNumElemMemSeg = 0; + sal_uInt16 nElemSizeSeg = 2; + + if ( SeekToContent( DFF_Prop_pSegmentInfo, rIn ) ) + rIn >> nNumElemSeg >> nNumElemMemSeg >> nElemSizeSeg; + if ( nNumElemSeg ) + { + sal_Int16 nCommand; + sal_Int16 nCnt; + aSegments.realloc( nNumElemSeg ); + for ( i = 0; i < nNumElemSeg; i++ ) + { + rIn >> nTmp; + nCommand = EnhancedCustomShapeSegmentCommand::UNKNOWN; + nCnt = (sal_Int16)( nTmp & 0xfff ); + switch( nTmp >> 12 ) + { + case 0x0: nCommand = EnhancedCustomShapeSegmentCommand::LINETO; if ( !nCnt ) nCnt = 1; break; + case 0x1: nCommand = EnhancedCustomShapeSegmentCommand::LINETO; if ( !nCnt ) nCnt = 1; break; // seems to the relative lineto + case 0x4: nCommand = EnhancedCustomShapeSegmentCommand::MOVETO; if ( !nCnt ) nCnt = 1; break; + case 0x2: nCommand = EnhancedCustomShapeSegmentCommand::CURVETO; if ( !nCnt ) nCnt = 1; break; + case 0x3: nCommand = EnhancedCustomShapeSegmentCommand::CURVETO; if ( !nCnt ) nCnt = 1; break; // seems to be the relative curveto + case 0x8: nCommand = EnhancedCustomShapeSegmentCommand::ENDSUBPATH; nCnt = 0; break; + case 0x6: nCommand = EnhancedCustomShapeSegmentCommand::CLOSESUBPATH; nCnt = 0; break; + case 0xa: + case 0xb: + { + switch ( ( nTmp >> 8 ) & 0xf ) + { + case 0x0: + { + nCommand = EnhancedCustomShapeSegmentCommand::LINETO; + if ( !nCnt ) + nCnt = 1; + } + break; + case 0x1: + { + nCommand = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO; + nCnt = ( nTmp & 0xff ) / 3; + } + break; + case 0x2: + { + nCommand = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE; + nCnt = ( nTmp & 0xff ) / 3; + } + break; + case 0x3: + { + nCommand = EnhancedCustomShapeSegmentCommand::ARCTO; + nCnt = ( nTmp & 0xff ) >> 2; + }; + break; + case 0x4: + { + nCommand = EnhancedCustomShapeSegmentCommand::ARC; + nCnt = ( nTmp & 0xff ) >> 2; + } + break; + case 0x5: + { + nCommand = EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO; + nCnt = ( nTmp & 0xff ) >> 2; + } + break; + case 0x6: + { + nCommand = EnhancedCustomShapeSegmentCommand::CLOCKWISEARC; + nCnt = ( nTmp & 0xff ) >> 2; + } + break; + case 0x7: + { + nCommand = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX; + nCnt = nTmp & 0xff; + } + break; + case 0x8: + { + nCommand = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY; + nCnt = nTmp & 0xff; + } + break; + case 0xa: nCommand = EnhancedCustomShapeSegmentCommand::NOFILL; nCnt = 0; break; + case 0xb: nCommand = EnhancedCustomShapeSegmentCommand::NOSTROKE; nCnt = 0; break; + } + } + break; + } + // if the command is unknown, we will store all the data in nCnt, so it will be possible to export without loss + if ( nCommand == EnhancedCustomShapeSegmentCommand::UNKNOWN ) + nCnt = (sal_Int16)nTmp; + aSegments[ i ].Command = nCommand; + aSegments[ i ].Count = nCnt; + } + } + const rtl::OUString sSegments( RTL_CONSTASCII_USTRINGPARAM ( "Segments" ) ); + aProp.Name = sSegments; + aProp.Value <<= aSegments; + aPathPropVec.push_back( aProp ); + } + // Path/StretchX + if ( IsProperty( DFF_Prop_stretchPointX ) ) + { + const rtl::OUString sStretchX( RTL_CONSTASCII_USTRINGPARAM ( "StretchX" ) ); + sal_Int32 nStretchX = GetPropertyValue( DFF_Prop_stretchPointX, 0 ); + aProp.Name = sStretchX; + aProp.Value <<= nStretchX; + aPathPropVec.push_back( aProp ); + } + // Path/StretchX + if ( IsProperty( DFF_Prop_stretchPointY ) ) + { + const rtl::OUString sStretchY( RTL_CONSTASCII_USTRINGPARAM ( "StretchY" ) ); + sal_Int32 nStretchY = GetPropertyValue( DFF_Prop_stretchPointY, 0 ); + aProp.Name = sStretchY; + aProp.Value <<= nStretchY; + aPathPropVec.push_back( aProp ); + } + // Path/TextFrames + if ( IsProperty( DFF_Prop_textRectangles ) ) + { + sal_uInt16 i; + sal_uInt16 nNumElem = 0; + sal_uInt16 nNumElemMem = 0; + sal_uInt16 nElemSize = 16; + + if ( SeekToContent( DFF_Prop_textRectangles, rIn ) ) + rIn >> nNumElem >> nNumElemMem >> nElemSize; + if ( nElemSize == 16 ) + { + sal_Int32 nLeft, nTop, nRight, nBottom; + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame > aTextFrames( nNumElem ); + for ( i = 0; i < nNumElem; i++ ) + { + rIn >> nLeft + >> nTop + >> nRight + >> nBottom; + + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrames[ i ].TopLeft.First, nLeft ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrames[ i ].TopLeft.Second, nTop ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrames[ i ].BottomRight.First, nRight ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrames[ i ].BottomRight.Second, nBottom); + } + const rtl::OUString sTextFrames( RTL_CONSTASCII_USTRINGPARAM ( "TextFrames" ) ); + aProp.Name = sTextFrames; + aProp.Value <<= aTextFrames; + aPathPropVec.push_back( aProp ); + } + } + //Path/GluePoints + if ( IsProperty( DFF_Prop_connectorPoints ) ) + { + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair > aGluePoints; + + sal_uInt16 i; + sal_uInt16 nNumElemVert = 0; + sal_uInt16 nNumElemMemVert = 0; + sal_uInt16 nElemSizeVert = 8; + + if ( SeekToContent( DFF_Prop_connectorPoints, rIn ) ) + rIn >> nNumElemVert >> nNumElemMemVert >> nElemSizeVert; + + sal_Int32 nX, nY; + sal_Int16 nTmpA, nTmpB; + aGluePoints.realloc( nNumElemVert ); + for ( i = 0; i < nNumElemVert; i++ ) + { + if ( nElemSizeVert == 8 ) + { + rIn >> nX + >> nY; + } + else + { + rIn >> nTmpA + >> nTmpB; + + nX = nTmpA; + nY = nTmpB; + } + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aGluePoints[ i ].First, nX ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aGluePoints[ i ].Second, nY ); + } + const rtl::OUString sGluePoints( RTL_CONSTASCII_USTRINGPARAM ( "GluePoints" ) ); + aProp.Name = sGluePoints; + aProp.Value <<= aGluePoints; + aPathPropVec.push_back( aProp ); + } + if ( IsProperty( DFF_Prop_connectorType ) ) + { + sal_Int16 nGluePointType = (sal_uInt16)GetPropertyValue( DFF_Prop_connectorType ); + const rtl::OUString sGluePointType( RTL_CONSTASCII_USTRINGPARAM ( "GluePointType" ) ); + aProp.Name = sGluePointType; + aProp.Value <<= nGluePointType; + aPathPropVec.push_back( aProp ); + } + // pushing the whole Path element + if ( aPathPropVec.size() ) + { + const rtl::OUString sPath( RTL_CONSTASCII_USTRINGPARAM ( "Path" ) ); + PropSeq aPathPropSeq( aPathPropVec.size() ); + aIter = aPathPropVec.begin(); + aEnd = aPathPropVec.end(); + beans::PropertyValue* pPathValues = aPathPropSeq.getArray(); + while ( aIter != aEnd ) + *pPathValues++ = *aIter++; + aProp.Name = sPath; + aProp.Value <<= aPathPropSeq; + aPropVec.push_back( aProp ); + } + } + ///////////////////////////////////////// + // "TextPath" PropertySequence element // + ///////////////////////////////////////// + sal_Bool bTextPathOn = ( GetPropertyValue( DFF_Prop_gtextFStrikethrough ) & 0x4000 ) != 0; + if ( bTextPathOn ) + { + PropVec aTextPathPropVec; + + // TextPath + const rtl::OUString sTextPathOn( RTL_CONSTASCII_USTRINGPARAM ( "TextPath" ) ); + aProp.Name = sTextPathOn; + aProp.Value <<= bTextPathOn; + aTextPathPropVec.push_back( aProp ); + + // TextPathMode + const rtl::OUString sTextPathMode( RTL_CONSTASCII_USTRINGPARAM ( "TextPathMode" ) ); + sal_Bool bTextPathFitPath = ( GetPropertyValue( DFF_Prop_gtextFStrikethrough ) & 0x100 ) != 0; + + sal_Bool bTextPathFitShape; + if ( IsHardAttribute( DFF_Prop_gtextFStretch ) ) + bTextPathFitShape = ( GetPropertyValue( DFF_Prop_gtextFStrikethrough ) & 0x400 ) != 0; + else + { + bTextPathFitShape = true; + switch( rObjData.eShapeType ) + { + case mso_sptTextArchUpCurve : + case mso_sptTextArchDownCurve : + case mso_sptTextCircleCurve : + case mso_sptTextButtonCurve : + bTextPathFitShape = false; + default : break; + } + } + EnhancedCustomShapeTextPathMode eTextPathMode( EnhancedCustomShapeTextPathMode_NORMAL ); + if ( bTextPathFitShape ) + eTextPathMode = EnhancedCustomShapeTextPathMode_SHAPE; + else if ( bTextPathFitPath ) + eTextPathMode = EnhancedCustomShapeTextPathMode_PATH; + aProp.Name = sTextPathMode; + aProp.Value <<= eTextPathMode; + aTextPathPropVec.push_back( aProp ); + + // ScaleX + const rtl::OUString sTextPathScaleX( RTL_CONSTASCII_USTRINGPARAM ( "ScaleX" ) ); + sal_Bool bTextPathScaleX = ( GetPropertyValue( DFF_Prop_gtextFStrikethrough ) & 0x40 ) != 0; + aProp.Name = sTextPathScaleX; + aProp.Value <<= bTextPathScaleX; + aTextPathPropVec.push_back( aProp ); + // SameLetterHeights + const rtl::OUString sSameLetterHeight( RTL_CONSTASCII_USTRINGPARAM ( "SameLetterHeights" ) ); + sal_Bool bSameLetterHeight = ( GetPropertyValue( DFF_Prop_gtextFStrikethrough ) & 0x80 ) != 0; + aProp.Name = sSameLetterHeight; + aProp.Value <<= bSameLetterHeight; + aTextPathPropVec.push_back( aProp ); + + // pushing the whole TextPath element + const rtl::OUString sTextPath( RTL_CONSTASCII_USTRINGPARAM ( "TextPath" ) ); + PropSeq aTextPathPropSeq( aTextPathPropVec.size() ); + aIter = aTextPathPropVec.begin(); + aEnd = aTextPathPropVec.end(); + beans::PropertyValue* pTextPathValues = aTextPathPropSeq.getArray(); + while ( aIter != aEnd ) + *pTextPathValues++ = *aIter++; + aProp.Name = sTextPath; + aProp.Value <<= aTextPathPropSeq; + aPropVec.push_back( aProp ); + } + //////////////////////// + // "AdjustmentValues" // The AdjustmentValues are imported at last, because depending to the type of the + //////////////////////// handle (POLAR) we will convert the adjustment value from a fixed float to double + + // checking the last used adjustment handle, so we can determine how many handles are to allocate + sal_Int32 i = DFF_Prop_adjust10Value; + while ( ( i >= DFF_Prop_adjustValue ) && !IsProperty( i ) ) + i--; + sal_Int32 nAdjustmentValues = ( i - DFF_Prop_adjustValue ) + 1; + if ( nAdjustmentValues ) + { + uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq( nAdjustmentValues ); + while( --nAdjustmentValues >= 0 ) + { + sal_Int32 nValue = 0; + beans::PropertyState ePropertyState = beans::PropertyState_DEFAULT_VALUE; + if ( IsProperty( i ) ) + { + nValue = GetPropertyValue( i ); + ePropertyState = beans::PropertyState_DIRECT_VALUE; + } + if ( nAdjustmentsWhichNeedsToBeConverted & ( 1 << ( i - DFF_Prop_adjustValue ) ) ) + { + double fValue = nValue; + fValue /= 65536; + aAdjustmentSeq[ nAdjustmentValues ].Value <<= fValue; + } + else + aAdjustmentSeq[ nAdjustmentValues ].Value <<= nValue; + aAdjustmentSeq[ nAdjustmentValues ].State = ePropertyState; + i--; + } + const rtl::OUString sAdjustmentValues( RTL_CONSTASCII_USTRINGPARAM ( "AdjustmentValues" ) ); + aProp.Name = sAdjustmentValues; + aProp.Value <<= aAdjustmentSeq; + aPropVec.push_back( aProp ); + } + + // creating the whole property set + PropSeq aSeq( aPropVec.size() ); + beans::PropertyValue* pValues = aSeq.getArray(); + aIter = aPropVec.begin(); + aEnd = aPropVec.end(); + while ( aIter != aEnd ) + *pValues++ = *aIter++; + rSet.Put( SdrCustomShapeGeometryItem( aSeq ) ); +} + +void DffPropertyReader::ApplyAttributes( SvStream& rIn, SfxItemSet& rSet ) const +{ + Rectangle aEmptyRect; + DffRecordHeader aHdTemp; + DffObjData aDffObjTemp( aHdTemp, aEmptyRect, 0 ); + ApplyAttributes( rIn, rSet, aDffObjTemp ); +} + +void DffPropertyReader::ApplyAttributes( SvStream& rIn, SfxItemSet& rSet, const DffObjData& rObjData ) const +{ +// MapUnit eMap( rManager.GetModel()->GetScaleUnit() ); + + sal_Bool bHasShadow = sal_False; + + for ( void* pDummy = ((DffPropertyReader*)this)->First(); pDummy; pDummy = ((DffPropertyReader*)this)->Next() ) + { + sal_uInt32 nRecType = GetCurKey(); + sal_uInt32 nContent = mpContents[ nRecType ]; + switch ( nRecType ) + { + case DFF_Prop_gtextSize : + rSet.Put( SvxFontHeightItem( rManager.ScalePt( nContent ), 100, EE_CHAR_FONTHEIGHT ) ); + break; + // GeoText + case DFF_Prop_gtextFStrikethrough : + { + if ( nContent & 0x20 ) + rSet.Put( SvxWeightItem( nContent ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT ) ); + if ( nContent & 0x10 ) + rSet.Put( SvxPostureItem( nContent ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC ) ); + if ( nContent & 0x08 ) + rSet.Put( SvxUnderlineItem( nContent ? UNDERLINE_SINGLE : UNDERLINE_NONE, EE_CHAR_UNDERLINE ) ); + if ( nContent & 0x40 ) + rSet.Put(SvxShadowedItem( nContent != 0, EE_CHAR_SHADOW ) ); +// if ( nContent & 0x02 ) +// rSet.Put( SvxCaseMapItem( nContent ? SVX_CASEMAP_KAPITAELCHEN : SVX_CASEMAP_NOT_MAPPED ) ); + if ( nContent & 0x01 ) + rSet.Put( SvxCrossedOutItem( nContent ? STRIKEOUT_SINGLE : STRIKEOUT_NONE, EE_CHAR_STRIKEOUT ) ); + } + break; + + case DFF_Prop_fillColor : + rSet.Put( XFillColorItem( String(), rManager.MSO_CLR_ToColor( nContent, DFF_Prop_fillColor ) ) ); + break; + + // ShadowStyle + case DFF_Prop_shadowType : + { + MSO_ShadowType eShadowType = (MSO_ShadowType)nContent; + if( eShadowType != mso_shadowOffset ) + { + // mso_shadowDouble + // mso_shadowRich + // mso_shadowEmbossOrEngrave + // koennen wir nicht, kreiere Default-Schatten mit default- + // Abstand + rSet.Put( SdrShadowXDistItem( 35 ) ); // 0,35 mm Schattendistanz + rSet.Put( SdrShadowYDistItem( 35 ) ); + } + } + break; + case DFF_Prop_shadowColor : + rSet.Put( SdrShadowColorItem( String(), rManager.MSO_CLR_ToColor( nContent, DFF_Prop_shadowColor ) ) ); + break; + case DFF_Prop_shadowOpacity : + rSet.Put( SdrShadowTransparenceItem( (sal_uInt16)( ( 0x10000 - nContent ) / 655 ) ) ); + break; + case DFF_Prop_shadowOffsetX : + { + sal_Int32 nVal = (sal_Int32)nContent; + rManager.ScaleEmu( nVal ); + if ( nVal ) + rSet.Put( SdrShadowXDistItem( nVal ) ); + } + break; + case DFF_Prop_shadowOffsetY : + { + sal_Int32 nVal = (sal_Int32)nContent; + rManager.ScaleEmu( nVal ); + if ( nVal ) + rSet.Put( SdrShadowYDistItem( nVal ) ); + } + break; + case DFF_Prop_fshadowObscured : + { + bHasShadow = ( nContent & 2 ) != 0; + if ( bHasShadow ) + { + if ( !IsProperty( DFF_Prop_shadowOffsetX ) ) + rSet.Put( SdrShadowXDistItem( 35 ) ); + if ( !IsProperty( DFF_Prop_shadowOffsetY ) ) + rSet.Put( SdrShadowYDistItem( 35 ) ); + } + } + break; + } + } + + if ( bHasShadow ) + { + // #160376# sj: activating shadow only if fill and or linestyle is used + // this is required because of the latest drawing layer core changes. + // Issue i104085 is related to this. + sal_uInt32 nLineFlags(GetPropertyValue( DFF_Prop_fNoLineDrawDash )); + if(!IsHardAttribute( DFF_Prop_fLine ) && !IsCustomShapeStrokedByDefault( rObjData.eShapeType )) + nLineFlags &= ~0x08; + sal_uInt32 nFillFlags(GetPropertyValue( DFF_Prop_fNoFillHitTest )); + if(!IsHardAttribute( DFF_Prop_fFilled ) && !IsCustomShapeFilledByDefault( rObjData.eShapeType )) + nFillFlags &= ~0x10; + if ( nFillFlags & 0x10 ) + { + MSO_FillType eMSO_FillType = (MSO_FillType)GetPropertyValue( DFF_Prop_fillType, mso_fillSolid ); + switch( eMSO_FillType ) + { + case mso_fillSolid : + case mso_fillPattern : + case mso_fillTexture : + case mso_fillPicture : + case mso_fillShade : + case mso_fillShadeCenter : + case mso_fillShadeShape : + case mso_fillShadeScale : + case mso_fillShadeTitle : + break; + // case mso_fillBackground : + default: + nFillFlags &=~0x10; // no fillstyle used + break; + } + } + if ( ( ( nLineFlags & 0x08 ) == 0 ) && ( ( nFillFlags & 0x10 ) == 0 ) ) // if there is no fillstyle and linestyle + bHasShadow = sal_False; // we are turning shadow off. + + if ( bHasShadow ) + rSet.Put( SdrShadowItem( bHasShadow ) ); + } + ApplyLineAttributes( rSet, rObjData.eShapeType ); // #i28269# + ApplyFillAttributes( rIn, rSet, rObjData ); + if ( rObjData.eShapeType != mso_sptNil ) + { + ApplyCustomShapeGeometryAttributes( rIn, rSet, rObjData ); + ApplyCustomShapeTextAttributes( rSet ); + } +} + +//--------------------------------------------------------------------------- +//- Record Manager ---------------------------------------------------------- +//--------------------------------------------------------------------------- + +DffRecordList::DffRecordList( DffRecordList* pList ) : + nCount ( 0 ), + nCurrent ( 0 ), + pPrev ( pList ), + pNext ( NULL ) +{ + if ( pList ) + pList->pNext = this; +} + +DffRecordList::~DffRecordList() +{ + delete pNext; +} + +DffRecordManager::DffRecordManager() : + DffRecordList ( NULL ), + pCList ( (DffRecordList*)this ) +{ +} + +DffRecordManager::DffRecordManager( SvStream& rIn ) : + DffRecordList ( NULL ), + pCList ( (DffRecordList*)this ) +{ + Consume( rIn ); +} + +DffRecordManager::~DffRecordManager() +{ +}; + + +void DffRecordManager::Consume( SvStream& rIn, sal_Bool bAppend, sal_uInt32 nStOfs ) +{ + if ( !bAppend ) + Clear(); + sal_uInt32 nOldPos = rIn.Tell(); + if ( !nStOfs ) + { + DffRecordHeader aHd; + rIn >> aHd; + if ( aHd.nRecVer == DFF_PSFLAG_CONTAINER ) + nStOfs = aHd.GetRecEndFilePos(); + } + if ( nStOfs ) + { + pCList = (DffRecordList*)this; + while ( pCList->pNext ) + pCList = pCList->pNext; + while ( ( rIn.GetError() == 0 ) && ( ( rIn.Tell() + 8 ) <= nStOfs ) ) + { + if ( pCList->nCount == DFF_RECORD_MANAGER_BUF_SIZE ) + pCList = new DffRecordList( pCList ); + rIn >> pCList->mHd[ pCList->nCount ]; + pCList->mHd[ pCList->nCount++ ].SeekToEndOfRecord( rIn ); + } + rIn.Seek( nOldPos ); + } +} + +void DffRecordManager::Clear() +{ + pCList = (DffRecordList*)this; + delete pNext, pNext = NULL; + nCurrent = 0; + nCount = 0; +} + +DffRecordHeader* DffRecordManager::Current() +{ + DffRecordHeader* pRet = NULL; + if ( pCList->nCurrent < pCList->nCount ) + pRet = &pCList->mHd[ pCList->nCurrent ]; + return pRet; +} + +DffRecordHeader* DffRecordManager::First() +{ + DffRecordHeader* pRet = NULL; + pCList = (DffRecordList*)this; + if ( pCList->nCount ) + { + pCList->nCurrent = 0; + pRet = &pCList->mHd[ 0 ]; + } + return pRet; +} + +DffRecordHeader* DffRecordManager::Next() +{ + DffRecordHeader* pRet = NULL; + sal_uInt32 nC = pCList->nCurrent + 1; + if ( nC < pCList->nCount ) + { + pCList->nCurrent++; + pRet = &pCList->mHd[ nC ]; + } + else if ( pCList->pNext ) + { + pCList = pCList->pNext; + pCList->nCurrent = 0; + pRet = &pCList->mHd[ 0 ]; + } + return pRet; +} + +DffRecordHeader* DffRecordManager::Prev() +{ + DffRecordHeader* pRet = NULL; + sal_uInt32 nCur = pCList->nCurrent; + if ( !nCur && pCList->pPrev ) + { + pCList = pCList->pPrev; + nCur = pCList->nCount; + } + if ( nCur-- ) + { + pCList->nCurrent = nCur; + pRet = &pCList->mHd[ nCur ]; + } + return pRet; +} + +DffRecordHeader* DffRecordManager::Last() +{ + DffRecordHeader* pRet = NULL; + while ( pCList->pNext ) + pCList = pCList->pNext; + sal_uInt32 nCnt = pCList->nCount; + if ( nCnt-- ) + { + pCList->nCurrent = nCnt; + pRet = &pCList->mHd[ nCnt ]; + } + return pRet; +} + +sal_Bool DffRecordManager::SeekToContent( SvStream& rIn, sal_uInt16 nRecId, DffSeekToContentMode eMode ) +{ + DffRecordHeader* pHd = GetRecordHeader( nRecId, eMode ); + if ( pHd ) + { + pHd->SeekToContent( rIn ); + return sal_True; + } + else + return sal_False; +} + +DffRecordHeader* DffRecordManager::GetRecordHeader( sal_uInt16 nRecId, DffSeekToContentMode eMode ) +{ + sal_uInt32 nOldCurrent = pCList->nCurrent; + DffRecordList* pOldList = pCList; + DffRecordHeader* pHd; + + if ( eMode == SEEK_FROM_BEGINNING ) + pHd = First(); + else + pHd = Next(); + + while ( pHd ) + { + if ( pHd->nRecType == nRecId ) + break; + pHd = Next(); + } + if ( !pHd && eMode == SEEK_FROM_CURRENT_AND_RESTART ) + { + DffRecordHeader* pBreak = &pOldList->mHd[ nOldCurrent ]; + pHd = First(); + if ( pHd ) + { + while ( pHd != pBreak ) + { + if ( pHd->nRecType == nRecId ) + break; + pHd = Next(); + } + if ( pHd->nRecType != nRecId ) + pHd = NULL; + } + } + if ( !pHd ) + { + pCList = pOldList; + pOldList->nCurrent = nOldCurrent; + } + return pHd; +} + +//--------------------------------------------------------------------------- +// private Methoden +//--------------------------------------------------------------------------- + +struct EscherBlipCacheEntry +{ + ByteString aUniqueID; + sal_uInt32 nBlip; + + EscherBlipCacheEntry( sal_uInt32 nBlipId, const ByteString& rUniqueID ) : + aUniqueID( rUniqueID ), + nBlip( nBlipId ) {} +}; + +void SvxMSDffManager::Scale( sal_Int32& rVal ) const +{ + if ( bNeedMap ) + rVal = BigMulDiv( rVal, nMapMul, nMapDiv ); +} + +void SvxMSDffManager::Scale( Point& rPos ) const +{ + rPos.X() += nMapXOfs; + rPos.Y() += nMapYOfs; + if ( bNeedMap ) + { + rPos.X() = BigMulDiv( rPos.X(), nMapMul, nMapDiv ); + rPos.Y() = BigMulDiv( rPos.Y(), nMapMul, nMapDiv ); + } +} + +void SvxMSDffManager::Scale( Size& rSiz ) const +{ + if ( bNeedMap ) + { + rSiz.Width() = BigMulDiv( rSiz.Width(), nMapMul, nMapDiv ); + rSiz.Height() = BigMulDiv( rSiz.Height(), nMapMul, nMapDiv ); + } +} + +void SvxMSDffManager::Scale( Rectangle& rRect ) const +{ + rRect.Move( nMapXOfs, nMapYOfs ); + if ( bNeedMap ) + { + rRect.Left() =BigMulDiv( rRect.Left() , nMapMul, nMapDiv ); + rRect.Top() =BigMulDiv( rRect.Top() , nMapMul, nMapDiv ); + rRect.Right() =BigMulDiv( rRect.Right() , nMapMul, nMapDiv ); + rRect.Bottom()=BigMulDiv( rRect.Bottom(), nMapMul, nMapDiv ); + } +} + +void SvxMSDffManager::Scale( Polygon& rPoly ) const +{ + if ( !bNeedMap ) + return; + sal_uInt16 nPointAnz = rPoly.GetSize(); + for ( sal_uInt16 nPointNum = 0; nPointNum < nPointAnz; nPointNum++ ) + Scale( rPoly[ nPointNum ] ); +} + +void SvxMSDffManager::Scale( PolyPolygon& rPoly ) const +{ + if ( !bNeedMap ) + return; + sal_uInt16 nPolyAnz = rPoly.Count(); + for ( sal_uInt16 nPolyNum = 0; nPolyNum < nPolyAnz; nPolyNum++ ) + Scale( rPoly[ nPolyNum ] ); +} + +void SvxMSDffManager::ScaleEmu( sal_Int32& rVal ) const +{ + rVal = BigMulDiv( rVal, nEmuMul, nEmuDiv ); +} + +sal_uInt32 SvxMSDffManager::ScalePt( sal_uInt32 nVal ) const +{ + MapUnit eMap = pSdrModel->GetScaleUnit(); + Fraction aFact( GetMapFactor( MAP_POINT, eMap ).X() ); + long aMul = aFact.GetNumerator(); + long aDiv = aFact.GetDenominator() * 65536; + aFact = Fraction( aMul, aDiv ); // nochmal versuchen zu kuerzen + return BigMulDiv( nVal, aFact.GetNumerator(), aFact.GetDenominator() ); +} + +sal_Int32 SvxMSDffManager::ScalePoint( sal_Int32 nVal ) const +{ + return BigMulDiv( nVal, nPntMul, nPntDiv ); +}; + +void SvxMSDffManager::SetModel(SdrModel* pModel, long nApplicationScale) +{ + pSdrModel = pModel; + if( pModel && (0 < nApplicationScale) ) + { + // PPT arbeitet nur mit Einheiten zu 576DPI + // WW hingegen verwendet twips, dh. 1440DPI. + MapUnit eMap = pSdrModel->GetScaleUnit(); + Fraction aFact( GetMapFactor(MAP_INCH, eMap).X() ); + long nMul=aFact.GetNumerator(); + long nDiv=aFact.GetDenominator()*nApplicationScale; + aFact=Fraction(nMul,nDiv); // nochmal versuchen zu kuerzen + // Bei 100TH_MM -> 2540/576=635/144 + // Bei Twip -> 1440/576=5/2 + nMapMul = aFact.GetNumerator(); + nMapDiv = aFact.GetDenominator(); + bNeedMap = nMapMul!=nMapDiv; + + // MS-DFF-Properties sind grossteils in EMU (English Metric Units) angegeben + // 1mm=36000emu, 1twip=635emu + aFact=GetMapFactor(MAP_100TH_MM,eMap).X(); + nMul=aFact.GetNumerator(); + nDiv=aFact.GetDenominator()*360; + aFact=Fraction(nMul,nDiv); // nochmal versuchen zu kuerzen + // Bei 100TH_MM -> 1/360 + // Bei Twip -> 14,40/(25,4*360)=144/91440=1/635 + nEmuMul=aFact.GetNumerator(); + nEmuDiv=aFact.GetDenominator(); + + // Und noch was fuer typografische Points + aFact=GetMapFactor(MAP_POINT,eMap).X(); + nPntMul=aFact.GetNumerator(); + nPntDiv=aFact.GetDenominator(); + } + else + { + pModel = 0; + nMapMul = nMapDiv = nMapXOfs = nMapYOfs = nEmuMul = nEmuDiv = nPntMul = nPntDiv = 0; + bNeedMap = sal_False; + } +} + +sal_Bool SvxMSDffManager::SeekToShape( SvStream& rSt, void* /* pClientData */, sal_uInt32 nId ) const +{ + sal_Bool bRet = sal_False; + if ( mpFidcls ) + { + sal_uInt32 nMerk = rSt.Tell(); + sal_uInt32 nShapeId, nSec = ( nId >> 10 ) - 1; + if ( nSec < mnIdClusters ) + { + sal_IntPtr nOfs = (sal_IntPtr)maDgOffsetTable.Get( mpFidcls[ nSec ].dgid ); + if ( nOfs ) + { + rSt.Seek( nOfs ); + DffRecordHeader aEscherF002Hd; + rSt >> aEscherF002Hd; + sal_uLong nEscherF002End = aEscherF002Hd.GetRecEndFilePos(); + DffRecordHeader aEscherObjListHd; + while ( rSt.Tell() < nEscherF002End ) + { + rSt >> aEscherObjListHd; + if ( aEscherObjListHd.nRecVer != 0xf ) + aEscherObjListHd.SeekToEndOfRecord( rSt ); + else if ( aEscherObjListHd.nRecType == DFF_msofbtSpContainer ) + { + DffRecordHeader aShapeHd; + if ( SeekToRec( rSt, DFF_msofbtSp, aEscherObjListHd.GetRecEndFilePos(), &aShapeHd ) ) + { + rSt >> nShapeId; + if ( nId == nShapeId ) + { + aEscherObjListHd.SeekToBegOfRecord( rSt ); + bRet = sal_True; + break; + } + } + aEscherObjListHd.SeekToEndOfRecord( rSt ); + } + } + } + } + if ( !bRet ) + rSt.Seek( nMerk ); + } + return bRet; +} + +FASTBOOL SvxMSDffManager::SeekToRec( SvStream& rSt, sal_uInt16 nRecId, sal_uLong nMaxFilePos, DffRecordHeader* pRecHd, sal_uLong nSkipCount ) const +{ + FASTBOOL bRet = sal_False; + sal_uLong nFPosMerk = rSt.Tell(); // FilePos merken fuer ggf. spaetere Restauration + DffRecordHeader aHd; + do + { + rSt >> aHd; + if ( aHd.nRecType == nRecId ) + { + if ( nSkipCount ) + nSkipCount--; + else + { + bRet = sal_True; + if ( pRecHd != NULL ) + *pRecHd = aHd; + else + aHd.SeekToBegOfRecord( rSt ); + } + } + if ( !bRet ) + aHd.SeekToEndOfRecord( rSt ); + } + while ( rSt.GetError() == 0 && rSt.Tell() < nMaxFilePos && !bRet ); + if ( !bRet ) + rSt.Seek( nFPosMerk ); // FilePos restaurieren + return bRet; +} + +FASTBOOL SvxMSDffManager::SeekToRec2( sal_uInt16 nRecId1, sal_uInt16 nRecId2, sal_uLong nMaxFilePos, DffRecordHeader* pRecHd, sal_uLong nSkipCount ) const +{ + FASTBOOL bRet = sal_False; + sal_uLong nFPosMerk = rStCtrl.Tell(); // FilePos merken fuer ggf. spaetere Restauration + DffRecordHeader aHd; + do + { + rStCtrl >> aHd; + if ( aHd.nRecType == nRecId1 || aHd.nRecType == nRecId2 ) + { + if ( nSkipCount ) + nSkipCount--; + else + { + bRet = sal_True; + if ( pRecHd ) + *pRecHd = aHd; + else + aHd.SeekToBegOfRecord( rStCtrl ); + } + } + if ( !bRet ) + aHd.SeekToEndOfRecord( rStCtrl ); + } + while ( rStCtrl.GetError() == 0 && rStCtrl.Tell() < nMaxFilePos && !bRet ); + if ( !bRet ) + rStCtrl.Seek( nFPosMerk ); // FilePos restaurieren + return bRet; +} + + +FASTBOOL SvxMSDffManager::GetColorFromPalette( sal_uInt16 /* nNum */, Color& rColor ) const +{ + // diese Methode ist in der zum Excel-Import + // abgeleiteten Klasse zu ueberschreiben... + rColor.SetColor( COL_WHITE ); + return sal_True; +} + +// sj: the documentation is not complete, especially in ppt the normal rgb for text +// color is written as 0xfeRRGGBB, this can't be explained by the documentation, nearly +// every bit in the upper code is set -> so there seems to be a special handling for +// ppt text colors, i decided not to fix this in MSO_CLR_ToColor because of possible +// side effects, instead MSO_TEXT_CLR_ToColor is called for PPT text colors, to map +// the color code to something that behaves like the other standard color codes used by +// fill and line color +Color SvxMSDffManager::MSO_TEXT_CLR_ToColor( sal_uInt32 nColorCode ) const +{ + // Fuer Textfarben: Header ist 0xfeRRGGBB + if ( ( nColorCode & 0xfe000000 ) == 0xfe000000 ) + nColorCode &= 0x00ffffff; + else + { + // for colorscheme colors the color index are the lower three bits of the upper byte + if ( ( nColorCode & 0xf8000000 ) == 0 ) // this must be a colorscheme index + { + nColorCode >>= 24; + nColorCode |= 0x8000000; + } + } + return MSO_CLR_ToColor( nColorCode ); +} + +Color SvxMSDffManager::MSO_CLR_ToColor( sal_uInt32 nColorCode, sal_uInt16 nContentProperty ) const +{ + Color aColor( mnDefaultColor ); + + // Fuer Textfarben: Header ist 0xfeRRGGBB + if ( ( nColorCode & 0xfe000000 ) == 0xfe000000 ) // sj: it needs to be checked if 0xfe is used in + nColorCode &= 0x00ffffff; // other cases than ppt text -> if not this code can be removed + + sal_uInt8 nUpper = (sal_uInt8)( nColorCode >> 24 ); + + // sj: below change from 0x1b to 0x19 was done because of i84812 (0x02 -> rgb color), + // now I have some problems to fix i104685 (there the color value is 0x02000000 whichs requires + // a 0x2 scheme color to be displayed properly), the color docu seems to be incomplete + if( nUpper & 0x19 ) // if( nUpper & 0x1f ) + { + if( ( nUpper & 0x08 ) || ( ( nUpper & 0x10 ) == 0 ) ) + { + // SCHEMECOLOR + if ( !GetColorFromPalette( ( nUpper & 8 ) ? (sal_uInt16)nColorCode : nUpper, aColor ) ) + { + switch( nContentProperty ) + { + case DFF_Prop_pictureTransparent : + case DFF_Prop_shadowColor : + case DFF_Prop_fillBackColor : + case DFF_Prop_fillColor : + aColor = Color( COL_WHITE ); + break; + case DFF_Prop_lineColor : + { + aColor = Color( COL_BLACK ); + } + break; + } + } + } + else // SYSCOLOR + { + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + +// sal_uInt16 nParameter = (sal_uInt8)( nColorCode >> 16); // SJ: nice compiler optimization bug on windows, though downcasting + sal_uInt16 nParameter = sal_uInt16(( nColorCode >> 16 ) & 0x00ff); // the HiByte of nParameter is not zero, an exclusive AND is helping :o + sal_uInt16 nFunctionBits = (sal_uInt16)( ( nColorCode & 0x00000f00 ) >> 8 ); + sal_uInt16 nAdditionalFlags = (sal_uInt16)( ( nColorCode & 0x0000f000) >> 8 ); + sal_uInt16 nColorIndex = sal_uInt16(nColorCode & 0x00ff); + sal_uInt32 nPropColor = 0; + + sal_uInt16 nCProp = 0; + + switch ( nColorIndex ) + { + case mso_syscolorButtonFace : aColor = rStyleSettings.GetFaceColor(); break; + case mso_syscolorWindowText : aColor = rStyleSettings.GetWindowTextColor(); break; + case mso_syscolorMenu : aColor = rStyleSettings.GetMenuColor(); break; + case mso_syscolor3DLight : + case mso_syscolorButtonHighlight : + case mso_syscolorHighlight : aColor = rStyleSettings.GetHighlightColor(); break; + case mso_syscolorHighlightText : aColor = rStyleSettings.GetHighlightTextColor(); break; + case mso_syscolorCaptionText : aColor = rStyleSettings.GetMenuTextColor(); break; + case mso_syscolorActiveCaption : aColor = rStyleSettings.GetHighlightColor(); break; + case mso_syscolorButtonShadow : aColor = rStyleSettings.GetShadowColor(); break; + case mso_syscolorButtonText : aColor = rStyleSettings.GetButtonTextColor(); break; + case mso_syscolorGrayText : aColor = rStyleSettings.GetDeactiveColor(); break; + case mso_syscolorInactiveCaption : aColor = rStyleSettings.GetDeactiveColor(); break; + case mso_syscolorInactiveCaptionText : aColor = rStyleSettings.GetDeactiveColor(); break; + case mso_syscolorInfoBackground : aColor = rStyleSettings.GetFaceColor(); break; + case mso_syscolorInfoText : aColor = rStyleSettings.GetInfoTextColor(); break; + case mso_syscolorMenuText : aColor = rStyleSettings.GetMenuTextColor(); break; + case mso_syscolorScrollbar : aColor = rStyleSettings.GetFaceColor(); break; + case mso_syscolorWindow : aColor = rStyleSettings.GetWindowColor(); break; + case mso_syscolorWindowFrame : aColor = rStyleSettings.GetWindowColor(); break; + + case mso_colorFillColor : + { + nPropColor = GetPropertyValue( DFF_Prop_fillColor, 0xffffff ); + nCProp = DFF_Prop_fillColor; + } + break; + case mso_colorLineOrFillColor : // ( use the line color only if there is a line ) + { + if ( GetPropertyValue( DFF_Prop_fNoLineDrawDash ) & 8 ) + { + nPropColor = GetPropertyValue( DFF_Prop_lineColor, 0 ); + nCProp = DFF_Prop_lineColor; + } + else + { + nPropColor = GetPropertyValue( DFF_Prop_fillColor, 0xffffff ); + nCProp = DFF_Prop_fillColor; + } + } + break; + case mso_colorLineColor : + { + nPropColor = GetPropertyValue( DFF_Prop_lineColor, 0 ); + nCProp = DFF_Prop_lineColor; + } + break; + case mso_colorShadowColor : + { + nPropColor = GetPropertyValue( DFF_Prop_shadowColor, 0x808080 ); + nCProp = DFF_Prop_shadowColor; + } + break; + case mso_colorThis : // ( use this color ... ) + { + nPropColor = GetPropertyValue( DFF_Prop_fillColor, 0xffffff ); //????????????? + nCProp = DFF_Prop_fillColor; + } + break; + case mso_colorFillBackColor : + { + nPropColor = GetPropertyValue( DFF_Prop_fillBackColor, 0xffffff ); + nCProp = DFF_Prop_fillBackColor; + } + break; + case mso_colorLineBackColor : + { + nPropColor = GetPropertyValue( DFF_Prop_lineBackColor, 0xffffff ); + nCProp = DFF_Prop_lineBackColor; + } + break; + case mso_colorFillThenLine : // ( use the fillcolor unless no fill and line ) + { + nPropColor = GetPropertyValue( DFF_Prop_fillColor, 0xffffff ); //????????????? + nCProp = DFF_Prop_fillColor; + } + break; + case mso_colorIndexMask : // ( extract the color index ) ? + { + nPropColor = GetPropertyValue( DFF_Prop_fillColor, 0xffffff ); //????????????? + nCProp = DFF_Prop_fillColor; + } + break; + } + if ( nCProp && ( nPropColor & 0x10000000 ) == 0 ) // beware of looping recursive + aColor = MSO_CLR_ToColor( nPropColor, nCProp ); + + if( nAdditionalFlags & 0x80 ) // make color gray + { + sal_uInt8 nZwi = aColor.GetLuminance(); + aColor = Color( nZwi, nZwi, nZwi ); + } + switch( nFunctionBits ) + { + case 0x01 : // darken color by parameter + { + aColor.SetRed( sal::static_int_cast< sal_uInt8 >( ( nParameter * aColor.GetRed() ) >> 8 ) ); + aColor.SetGreen( sal::static_int_cast< sal_uInt8 >( ( nParameter * aColor.GetGreen() ) >> 8 ) ); + aColor.SetBlue( sal::static_int_cast< sal_uInt8 >( ( nParameter * aColor.GetBlue() ) >> 8 ) ); + } + break; + case 0x02 : // lighten color by parameter + { + sal_uInt16 nInvParameter = ( 0x00ff - nParameter ) * 0xff; + aColor.SetRed( sal::static_int_cast< sal_uInt8 >( ( nInvParameter + ( nParameter * aColor.GetRed() ) ) >> 8 ) ); + aColor.SetGreen( sal::static_int_cast< sal_uInt8 >( ( nInvParameter + ( nParameter * aColor.GetGreen() ) ) >> 8 ) ); + aColor.SetBlue( sal::static_int_cast< sal_uInt8 >( ( nInvParameter + ( nParameter * aColor.GetBlue() ) ) >> 8 ) ); + } + break; + case 0x03 : // add grey level RGB(p,p,p) + { + sal_Int16 nR = (sal_Int16)aColor.GetRed() + (sal_Int16)nParameter; + sal_Int16 nG = (sal_Int16)aColor.GetGreen() + (sal_Int16)nParameter; + sal_Int16 nB = (sal_Int16)aColor.GetBlue() + (sal_Int16)nParameter; + if ( nR > 0x00ff ) + nR = 0x00ff; + if ( nG > 0x00ff ) + nG = 0x00ff; + if ( nB > 0x00ff ) + nB = 0x00ff; + aColor = Color( (sal_uInt8)nR, (sal_uInt8)nG, (sal_uInt8)nB ); + } + break; + case 0x04 : // substract grey level RGB(p,p,p) + { + sal_Int16 nR = (sal_Int16)aColor.GetRed() - (sal_Int16)nParameter; + sal_Int16 nG = (sal_Int16)aColor.GetGreen() - (sal_Int16)nParameter; + sal_Int16 nB = (sal_Int16)aColor.GetBlue() - (sal_Int16)nParameter; + if ( nR < 0 ) + nR = 0; + if ( nG < 0 ) + nG = 0; + if ( nB < 0 ) + nB = 0; + aColor = Color( (sal_uInt8)nR, (sal_uInt8)nG, (sal_uInt8)nB ); + } + break; + case 0x05 : // substract from grey level RGB(p,p,p) + { + sal_Int16 nR = (sal_Int16)nParameter - (sal_Int16)aColor.GetRed(); + sal_Int16 nG = (sal_Int16)nParameter - (sal_Int16)aColor.GetGreen(); + sal_Int16 nB = (sal_Int16)nParameter - (sal_Int16)aColor.GetBlue(); + if ( nR < 0 ) + nR = 0; + if ( nG < 0 ) + nG = 0; + if ( nB < 0 ) + nB = 0; + aColor = Color( (sal_uInt8)nR, (sal_uInt8)nG, (sal_uInt8)nB ); + } + break; + case 0x06 : // per component: black if < p, white if >= p + { + aColor.SetRed( aColor.GetRed() < nParameter ? 0x00 : 0xff ); + aColor.SetGreen( aColor.GetGreen() < nParameter ? 0x00 : 0xff ); + aColor.SetBlue( aColor.GetBlue() < nParameter ? 0x00 : 0xff ); + } + break; + } + if ( nAdditionalFlags & 0x40 ) // top-bit invert + aColor = Color( aColor.GetRed() ^ 0x80, aColor.GetGreen() ^ 0x80, aColor.GetBlue() ^ 0x80 ); + + if ( nAdditionalFlags & 0x20 ) // invert color + aColor = Color(0xff - aColor.GetRed(), 0xff - aColor.GetGreen(), 0xff - aColor.GetBlue()); + } + } + else if ( ( nUpper & 4 ) && ( ( nColorCode & 0xfffff8 ) == 0 ) ) + { // case of nUpper == 4 powerpoint takes this as agrument for a colorschemecolor + GetColorFromPalette( nUpper, aColor ); + } + else // hart attributiert, eventuell mit Hinweis auf SYSTEMRGB + aColor = Color( (sal_uInt8)nColorCode, (sal_uInt8)( nColorCode >> 8 ), (sal_uInt8)( nColorCode >> 16 ) ); + return aColor; +} + +FASTBOOL SvxMSDffManager::ReadDffString(SvStream& rSt, String& rTxt) const +{ + FASTBOOL bRet=sal_False; + DffRecordHeader aStrHd; + if( !ReadCommonRecordHeader(aStrHd, rSt) ) + rSt.Seek( aStrHd.nFilePos ); + else if ( aStrHd.nRecType == DFF_PST_TextBytesAtom || aStrHd.nRecType == DFF_PST_TextCharsAtom ) + { + FASTBOOL bUniCode=aStrHd.nRecType==DFF_PST_TextCharsAtom; + bRet=sal_True; + sal_uLong nBytes = aStrHd.nRecLen; + MSDFFReadZString( rSt, rTxt, nBytes, bUniCode ); + if( !bUniCode ) + { + for ( xub_StrLen n = 0; n < nBytes; n++ ) + { + if( rTxt.GetChar( n ) == 0x0B ) + rTxt.SetChar( n, ' ' ); // Weicher Umbruch + // TODO: Zeilenumbruch im Absatz via Outliner setzen. + } + } + aStrHd.SeekToEndOfRecord( rSt ); + } + else + aStrHd.SeekToBegOfRecord( rSt ); + return bRet; +} + +// sj: I just want to set a string for a text object that may contain multiple +// paragraphs. If I now take a look at the follwing code I get the impression that +// our outliner is too complicate to be used properly, +void SvxMSDffManager::ReadObjText( const String& rText, SdrObject* pObj ) const +{ + SdrTextObj* pText = PTR_CAST( SdrTextObj, pObj ); + if ( pText ) + { + SdrOutliner& rOutliner = pText->ImpGetDrawOutliner(); + rOutliner.Init( OUTLINERMODE_TEXTOBJECT ); + + sal_Bool bOldUpdateMode = rOutliner.GetUpdateMode(); + rOutliner.SetUpdateMode( sal_False ); + rOutliner.SetVertical( pText->IsVerticalWriting() ); + + sal_uInt16 nParaIndex = 0; + sal_uInt32 nParaSize; + const sal_Unicode* pCurrent, *pBuf = rText.GetBuffer(); + const sal_Unicode* pEnd = rText.GetBuffer() + rText.Len(); + + while( pBuf < pEnd ) + { + pCurrent = pBuf; + + for ( nParaSize = 0; pBuf < pEnd; ) + { + sal_Unicode nChar = *pBuf++; + if ( nChar == 0xa ) + { + if ( ( pBuf < pEnd ) && ( *pBuf == 0xd ) ) + pBuf++; + break; + } + else if ( nChar == 0xd ) + { + if ( ( pBuf < pEnd ) && ( *pBuf == 0xa ) ) + pBuf++; + break; + } + else + nParaSize++; + } + ESelection aSelection( nParaIndex, 0, nParaIndex, 0 ); + String aParagraph( pCurrent, (sal_uInt16)nParaSize ); + if ( !nParaIndex && !aParagraph.Len() ) // SJ: we are crashing if the first paragraph is empty ? + aParagraph += (sal_Unicode)' '; // otherwise these two lines can be removed. + rOutliner.Insert( aParagraph, nParaIndex, 0 ); + rOutliner.SetParaAttribs( nParaIndex, rOutliner.GetEmptyItemSet() ); + + SfxItemSet aParagraphAttribs( rOutliner.GetEmptyItemSet() ); + if ( !aSelection.nStartPos ) + aParagraphAttribs.Put( SfxBoolItem( EE_PARA_BULLETSTATE, sal_False ) ); + aSelection.nStartPos = 0; + rOutliner.QuickSetAttribs( aParagraphAttribs, aSelection ); + nParaIndex++; + } + OutlinerParaObject* pNewText = rOutliner.CreateParaObject(); + rOutliner.Clear(); + rOutliner.SetUpdateMode( bOldUpdateMode ); + pText->SetOutlinerParaObject( pNewText ); + } +} + +FASTBOOL SvxMSDffManager::ReadObjText(SvStream& rSt, SdrObject* pObj) const +{ + FASTBOOL bRet=sal_False; + SdrTextObj* pText = PTR_CAST(SdrTextObj, pObj); + if( pText ) + { + DffRecordHeader aTextHd; + if( !ReadCommonRecordHeader(aTextHd, rSt) ) + rSt.Seek( aTextHd.nFilePos ); + else if ( aTextHd.nRecType==DFF_msofbtClientTextbox ) + { + bRet=sal_True; + sal_uLong nRecEnd=aTextHd.GetRecEndFilePos(); + DffRecordHeader aHd; + String aText; +// sal_uInt32 nInvent=pText->GetObjInventor(); +// sal_uInt16 nIdent=pText->GetObjIdentifier(); + + SdrOutliner& rOutliner=pText->ImpGetDrawOutliner(); +// sal_Int16 nMinDepth = rOutliner.GetMinDepth(); + sal_uInt16 nOutlMode = rOutliner.GetMode(); + + { // Wohl 'nen kleiner Bug der EditEngine, das die + // Absastzattribute bei Clear() nicht entfernt werden. + FASTBOOL bClearParaAttribs = sal_True; + rOutliner.SetStyleSheet( 0, NULL ); + SfxItemSet aSet(rOutliner.GetEmptyItemSet()); + aSet.Put(SvxColorItem( COL_BLACK )); + rOutliner.SetParaAttribs(0,aSet); + pText->SetMergedItemSet(aSet); + + bClearParaAttribs = sal_False; + if( bClearParaAttribs ) + { + // Wohl 'nen kleiner Bug der EditEngine, dass die + // Absastzattribute bei Clear() nicht entfernt werden. + rOutliner.SetParaAttribs(0,rOutliner.GetEmptyItemSet()); + } + } + rOutliner.Init( OUTLINERMODE_TEXTOBJECT ); + +// sal_uLong nFilePosMerker=rSt.Tell(); + //////////////////////////////////// + // TextString und MetaChars lesen // + //////////////////////////////////// + do + { + if( !ReadCommonRecordHeader(aHd, rSt) ) + rSt.Seek( aHd.nFilePos ); + else + { + switch (aHd.nRecType) + { + //case TextHeaderAtom + //case TextSpecInfoAtom + case DFF_PST_TextBytesAtom: + case DFF_PST_TextCharsAtom: + { + aHd.SeekToBegOfRecord(rSt); + ReadDffString(rSt, aText); + } + break; + case DFF_PST_TextRulerAtom : + { + sal_uInt16 nLen = (sal_uInt16)aHd.nRecLen; + if(nLen) + { + sal_uInt16 nVal1, nVal2, nVal3; + sal_uInt16 nDefaultTab = 2540; // PPT def: 1 Inch //rOutliner.GetDefTab(); + sal_uInt16 nMostrightTab = 0; + SfxItemSet aSet(rOutliner.GetEmptyItemSet()); + SvxTabStopItem aTabItem(0, 0, SVX_TAB_ADJUST_DEFAULT, EE_PARA_TABS); + + rSt >> nVal1; + rSt >> nVal2; + nLen -= 4; + + // Allg. TAB verstellt auf Wert in nVal3 + if(nLen && (nVal1 & 0x0001)) + { + rSt >> nVal3; + nLen -= 2; + nDefaultTab = (sal_uInt16)(((sal_uInt32)nVal3 * 1000) / 240); + } + + // Weitere, frei gesetzte TABs + if(nLen && (nVal1 & 0x0004)) + { + rSt >> nVal1; + nLen -= 2; + + // fest gesetzte TABs importieren + while(nLen && nVal1--) + { + rSt >> nVal2; + rSt >> nVal3; + nLen -= 4; + + sal_uInt16 nNewTabPos = (sal_uInt16)(((sal_uInt32)nVal2 * 1000) / 240); + if(nNewTabPos > nMostrightTab) + nMostrightTab = nNewTabPos; + + SvxTabStop aTabStop(nNewTabPos); + aTabItem.Insert(aTabStop); + } + } + + // evtl. noch default-TABs ergaenzen (immer) + sal_uInt16 nObjWidth = sal_uInt16(pObj->GetSnapRect().GetWidth() + 1); + sal_uInt16 nDefaultTabPos = nDefaultTab; + + while(nDefaultTabPos <= nObjWidth && nDefaultTabPos <= nMostrightTab) + nDefaultTabPos = + nDefaultTabPos + nDefaultTab; + + while(nDefaultTabPos <= nObjWidth) + { + SvxTabStop aTabStop(nDefaultTabPos); + aTabItem.Insert(aTabStop); + nDefaultTabPos = + nDefaultTabPos + nDefaultTab; + } + + // Falls TABs angelegt wurden, setze diese + if(aTabItem.Count()) + { + aSet.Put(aTabItem); + rOutliner.SetParaAttribs(0, aSet); + } + } + } + break; + } + aHd.SeekToEndOfRecord( rSt ); + } + } + while ( rSt.GetError() == 0 && rSt.Tell() < nRecEnd ); + + //////////////////////// + // SHIFT-Ret ersetzen // + //////////////////////// + if ( aText.Len() ) + { + aText += ' '; + aText.SetChar( aText.Len()-1, 0x0D ); + rOutliner.SetText( aText, rOutliner.GetParagraph( 0 ) ); + + // SHIFT-Ret ersetzen im Outliner + if(aText.GetTokenCount(0x0B) > 1) + { + sal_uInt32 nParaCount = rOutliner.GetParagraphCount(); + for(sal_uInt16 a=0;a<nParaCount;a++) + { + Paragraph* pActPara = rOutliner.GetParagraph(a); + String aParaText = rOutliner.GetText(pActPara); + for(sal_uInt16 b=0;b<aParaText.Len();b++) + { + if( aParaText.GetChar( b ) == 0x0B) + { + ESelection aSelection(a, b, a, b+1); + rOutliner.QuickInsertLineBreak(aSelection); + } + } + } + } + } + OutlinerParaObject* pNewText=rOutliner.CreateParaObject(); + rOutliner.Init( nOutlMode ); + pText->NbcSetOutlinerParaObject(pNewText); + } + else + aTextHd.SeekToBegOfRecord(rSt); + + } + return bRet; +} + +//static +void SvxMSDffManager::MSDFFReadZString( SvStream& rIn, String& rStr, + sal_uLong nRecLen, FASTBOOL bUniCode ) +{ + sal_uInt16 nLen = (sal_uInt16)nRecLen; + if( nLen ) + { + if ( bUniCode ) + nLen >>= 1; + + String sBuf; + sal_Unicode* pBuf = sBuf.AllocBuffer( nLen ); + + if( bUniCode ) + { + rIn.Read( (sal_Char*)pBuf, nLen << 1 ); + +#ifdef OSL_BIGENDIAN + for( sal_uInt16 n = 0; n < nLen; ++n, ++pBuf ) + *pBuf = SWAPSHORT( *pBuf ); +#endif // ifdef OSL_BIGENDIAN + } + else + { + // use the String-Data as buffer for the 8bit characters and + // change then all to unicode + sal_Char* pReadPos = ((sal_Char*)pBuf) + nLen; + rIn.Read( (sal_Char*)pReadPos, nLen ); + for( sal_uInt16 n = 0; n < nLen; ++n, ++pBuf, ++pReadPos ) + *pBuf = ByteString::ConvertToUnicode( *pReadPos, RTL_TEXTENCODING_MS_1252 ); + } + + rStr = sBuf.EraseTrailingChars( 0 ); + } + else + rStr.Erase(); +} + +SdrObject* SvxMSDffManager::ImportFontWork( SvStream& rStCt, SfxItemSet& rSet, Rectangle& rBoundRect ) const +{ + SdrObject* pRet = NULL; + String aObjectText; + String aFontName; + sal_Bool bTextRotate = sal_False; + + ((SvxMSDffManager*)this)->mnFix16Angle = 0; // we don't want to use this property in future + if ( SeekToContent( DFF_Prop_gtextUNICODE, rStCt ) ) + MSDFFReadZString( rStCt, aObjectText, GetPropertyValue( DFF_Prop_gtextUNICODE ), sal_True ); + if ( SeekToContent( DFF_Prop_gtextFont, rStCt ) ) + MSDFFReadZString( rStCt, aFontName, GetPropertyValue( DFF_Prop_gtextFont ), sal_True ); + if ( GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 ) & 0x2000 ) + { + // Text ist senkrecht formatiert, Box Kippen + sal_Int32 nHalfWidth = ( rBoundRect.GetWidth() + 1) >> 1; + sal_Int32 nHalfHeight = ( rBoundRect.GetHeight() + 1) >> 1; + Point aTopLeft( rBoundRect.Left() + nHalfWidth - nHalfHeight, + rBoundRect.Top() + nHalfHeight - nHalfWidth); + Size aNewSize( rBoundRect.GetHeight(), rBoundRect.GetWidth() ); + Rectangle aNewRect( aTopLeft, aNewSize ); + rBoundRect = aNewRect; + + String aSrcText( aObjectText ); + aObjectText.Erase(); + for( sal_uInt16 a = 0; a < aSrcText.Len(); a++ ) + { + aObjectText += aSrcText.GetChar( a ); + aObjectText += '\n'; + } + rSet.Put( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_CENTER ) ); + bTextRotate = sal_True; + } + if ( aObjectText.Len() ) + { // FontWork-Objekt Mit dem Text in aObjectText erzeugen + SdrObject* pNewObj = new SdrRectObj( OBJ_TEXT, rBoundRect ); + if( pNewObj ) + { + pNewObj->SetModel( pSdrModel ); + ((SdrRectObj*)pNewObj)->SetText( aObjectText ); + SdrFitToSizeType eFTS = SDRTEXTFIT_PROPORTIONAL; + rSet.Put( SdrTextFitToSizeTypeItem( eFTS ) ); + rSet.Put( SdrTextAutoGrowHeightItem( sal_False ) ); + rSet.Put( SdrTextAutoGrowWidthItem( sal_False ) ); + rSet.Put( SvxFontItem( FAMILY_DONTKNOW, aFontName, String(), + PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW, EE_CHAR_FONTINFO )); + + pNewObj->SetMergedItemSet(rSet); + + pRet = pNewObj->ConvertToPolyObj( sal_False, sal_False ); + if( !pRet ) + pRet = pNewObj; + else + { + pRet->NbcSetSnapRect( rBoundRect ); + SdrObject::Free( pNewObj ); + } + if( bTextRotate ) + { + double a = 9000 * nPi180; + pRet->NbcRotate( rBoundRect.Center(), 9000, sin( a ), cos( a ) ); + } + } + } + return pRet; +} + +static Size lcl_GetPrefSize(const Graphic& rGraf, MapMode aWanted) +{ + MapMode aPrefMapMode(rGraf.GetPrefMapMode()); + if (aPrefMapMode == aWanted) + return rGraf.GetPrefSize(); + Size aRetSize; + if (aPrefMapMode == MAP_PIXEL) + { + aRetSize = Application::GetDefaultDevice()->PixelToLogic( + rGraf.GetPrefSize(), aWanted); + } + else + { + aRetSize = Application::GetDefaultDevice()->LogicToLogic( + rGraf.GetPrefSize(), rGraf.GetPrefMapMode(), aWanted); + } + return aRetSize; +} + +// sj: if the parameter pSet is null, then the resulting crop bitmap will be stored in rGraf, +// otherwise rGraf is untouched and pSet is used to store the corresponding SdrGrafCropItem +static void lcl_ApplyCropping( const DffPropSet& rPropSet, SfxItemSet* pSet, Graphic& rGraf ) +{ + sal_Int32 nCropTop = (sal_Int32)rPropSet.GetPropertyValue( DFF_Prop_cropFromTop, 0 ); + sal_Int32 nCropBottom = (sal_Int32)rPropSet.GetPropertyValue( DFF_Prop_cropFromBottom, 0 ); + sal_Int32 nCropLeft = (sal_Int32)rPropSet.GetPropertyValue( DFF_Prop_cropFromLeft, 0 ); + sal_Int32 nCropRight = (sal_Int32)rPropSet.GetPropertyValue( DFF_Prop_cropFromRight, 0 ); + + if( nCropTop || nCropBottom || nCropLeft || nCropRight ) + { + double fFactor; + Size aCropSize; + BitmapEx aCropBitmap; + sal_uInt32 nTop( 0 ), nBottom( 0 ), nLeft( 0 ), nRight( 0 ); + + if ( pSet ) // use crop attributes ? + aCropSize = lcl_GetPrefSize( rGraf, MAP_100TH_MM ); + else + { + aCropBitmap = rGraf.GetBitmapEx(); + aCropSize = aCropBitmap.GetSizePixel(); + } + if ( nCropTop ) + { + fFactor = (double)nCropTop / 65536.0; + nTop = (sal_uInt32)( ( (double)( aCropSize.Height() + 1 ) * fFactor ) + 0.5 ); + } + if ( nCropBottom ) + { + fFactor = (double)nCropBottom / 65536.0; + nBottom = (sal_uInt32)( ( (double)( aCropSize.Height() + 1 ) * fFactor ) + 0.5 ); + } + if ( nCropLeft ) + { + fFactor = (double)nCropLeft / 65536.0; + nLeft = (sal_uInt32)( ( (double)( aCropSize.Width() + 1 ) * fFactor ) + 0.5 ); + } + if ( nCropRight ) + { + fFactor = (double)nCropRight / 65536.0; + nRight = (sal_uInt32)( ( (double)( aCropSize.Width() + 1 ) * fFactor ) + 0.5 ); + } + if ( pSet ) // use crop attributes ? + pSet->Put( SdrGrafCropItem( nLeft, nTop, nRight, nBottom ) ); + else + { + Rectangle aCropRect( nLeft, nTop, aCropSize.Width() - nRight, aCropSize.Height() - nBottom ); + aCropBitmap.Crop( aCropRect ); + rGraf = aCropBitmap; + } + } +} + +SdrObject* SvxMSDffManager::ImportGraphic( SvStream& rSt, SfxItemSet& rSet, const DffObjData& rObjData ) const +{ + SdrObject* pRet = NULL; + String aFilename; + String aLinkFileName, aLinkFilterName; + Rectangle aVisArea; + + MSO_BlipFlags eFlags = (MSO_BlipFlags)GetPropertyValue( DFF_Prop_pibFlags, mso_blipflagDefault ); + sal_uInt32 nBlipId = GetPropertyValue( DFF_Prop_pib, 0 ); + sal_Bool bGrfRead = sal_False, + + // Grafik verlinkt + bLinkGrf = 0 != ( eFlags & mso_blipflagLinkToFile ); + { + Graphic aGraf; // be sure this graphic is deleted before swapping out + if( SeekToContent( DFF_Prop_pibName, rSt ) ) + MSDFFReadZString( rSt, aFilename, GetPropertyValue( DFF_Prop_pibName ), sal_True ); + + // UND, ODER folgendes: + if( !( eFlags & mso_blipflagDoNotSave ) ) // Grafik embedded + { + bGrfRead = GetBLIP( nBlipId, aGraf, &aVisArea ); + if ( !bGrfRead ) + { + /* + Still no luck, lets look at the end of this record for a FBSE pool, + this fallback is a specific case for how word does it sometimes + */ + rObjData.rSpHd.SeekToEndOfRecord( rSt ); + DffRecordHeader aHd; + rSt >> aHd; + if( DFF_msofbtBSE == aHd.nRecType ) + { + const sal_uLong nSkipBLIPLen = 20; + const sal_uLong nSkipShapePos = 4; + const sal_uLong nSkipBLIP = 4; + const sal_uLong nSkip = + nSkipBLIPLen + 4 + nSkipShapePos + 4 + nSkipBLIP; + + if (nSkip <= aHd.nRecLen) + { + rSt.SeekRel(nSkip); + if (0 == rSt.GetError()) + bGrfRead = GetBLIPDirect( rSt, aGraf, &aVisArea ); + } + } + } + } + if ( bGrfRead ) + { + // the writer is doing it's own cropping, so this part affects only impress and calc + if ( GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_CROP_BITMAPS ) + lcl_ApplyCropping( *this, ( rObjData.nSpFlags & SP_FOLESHAPE ) == 0 ? &rSet : NULL, aGraf ); + + if ( IsProperty( DFF_Prop_pictureTransparent ) ) + { + sal_uInt32 nTransColor = GetPropertyValue( DFF_Prop_pictureTransparent, 0 ); + + if ( aGraf.GetType() == GRAPHIC_BITMAP ) + { + BitmapEx aBitmapEx( aGraf.GetBitmapEx() ); + Bitmap aBitmap( aBitmapEx.GetBitmap() ); + Bitmap aMask( aBitmap.CreateMask( MSO_CLR_ToColor( nTransColor, DFF_Prop_pictureTransparent ), 9 ) ); + if ( aBitmapEx.IsTransparent() ) + aMask.CombineSimple( aBitmapEx.GetMask(), BMP_COMBINE_OR ); + aGraf = BitmapEx( aBitmap, aMask ); + } + } + + sal_Int32 nContrast = GetPropertyValue( DFF_Prop_pictureContrast, 0x10000 ); + /* + 0x10000 is msoffice 50% + < 0x10000 is in units of 1/50th of 0x10000 per 1% + > 0x10000 is in units where + a msoffice x% is stored as 50/(100-x) * 0x10000 + + plus, a (ui) microsoft % ranges from 0 to 100, OOO + from -100 to 100, so also normalize into that range + */ + if ( nContrast > 0x10000 ) + { + double fX = nContrast; + fX /= 0x10000; + fX /= 51; // 50 + 1 to round + fX = 1/fX; + nContrast = static_cast<sal_Int32>(fX); + nContrast -= 100; + nContrast = -nContrast; + nContrast = (nContrast-50)*2; + } + else if ( nContrast == 0x10000 ) + nContrast = 0; + else + { + nContrast *= 101; //100 + 1 to round + nContrast /= 0x10000; + nContrast -= 100; + } + sal_Int16 nBrightness = (sal_Int16)( (sal_Int32)GetPropertyValue( DFF_Prop_pictureBrightness, 0 ) / 327 ); + sal_Int32 nGamma = GetPropertyValue( DFF_Prop_pictureGamma, 0x10000 ); + GraphicDrawMode eDrawMode = GRAPHICDRAWMODE_STANDARD; + switch ( GetPropertyValue( DFF_Prop_pictureActive ) & 6 ) + { + case 4 : eDrawMode = GRAPHICDRAWMODE_GREYS; break; + case 6 : eDrawMode = GRAPHICDRAWMODE_MONO; break; + case 0 : + { + //office considers the converted values of (in OOo) 70 to be the + //"watermark" values, which can vary slightly due to rounding from the + //above values + if (( nContrast == -70 ) && ( nBrightness == 70 )) + { + nContrast = 0; + nBrightness = 0; + eDrawMode = GRAPHICDRAWMODE_WATERMARK; + }; + } + break; + } + + if ( nContrast || nBrightness || ( nGamma != 0x10000 ) || ( eDrawMode != GRAPHICDRAWMODE_STANDARD ) ) + { + if ( ( rObjData.nSpFlags & SP_FOLESHAPE ) == 0 ) + { + if ( nBrightness ) + rSet.Put( SdrGrafLuminanceItem( nBrightness ) ); + if ( nContrast ) + rSet.Put( SdrGrafContrastItem( (sal_Int16)nContrast ) ); + if ( nGamma != 0x10000 ) + rSet.Put( SdrGrafGamma100Item( nGamma / 655 ) ); + if ( eDrawMode != GRAPHICDRAWMODE_STANDARD ) + rSet.Put( SdrGrafModeItem( eDrawMode ) ); + } + else + { + if ( eDrawMode == GRAPHICDRAWMODE_WATERMARK ) + { + nContrast = 60; + nBrightness = 70; + eDrawMode = GRAPHICDRAWMODE_STANDARD; + } + switch ( aGraf.GetType() ) + { + case GRAPHIC_BITMAP : + { + BitmapEx aBitmapEx( aGraf.GetBitmapEx() ); + if ( nBrightness || nContrast || ( nGamma != 0x10000 ) ) + aBitmapEx.Adjust( nBrightness, (sal_Int16)nContrast, 0, 0, 0, (double)nGamma / 0x10000, sal_False ); + if ( eDrawMode == GRAPHICDRAWMODE_GREYS ) + aBitmapEx.Convert( BMP_CONVERSION_8BIT_GREYS ); + else if ( eDrawMode == GRAPHICDRAWMODE_MONO ) + aBitmapEx.Convert( BMP_CONVERSION_1BIT_THRESHOLD ); + aGraf = aBitmapEx; + + } + break; + + case GRAPHIC_GDIMETAFILE : + { + GDIMetaFile aGdiMetaFile( aGraf.GetGDIMetaFile() ); + if ( nBrightness || nContrast || ( nGamma != 0x10000 ) ) + aGdiMetaFile.Adjust( nBrightness, (sal_Int16)nContrast, 0, 0, 0, (double)nGamma / 0x10000, sal_False ); + if ( eDrawMode == GRAPHICDRAWMODE_GREYS ) + aGdiMetaFile.Convert( MTF_CONVERSION_8BIT_GREYS ); + else if ( eDrawMode == GRAPHICDRAWMODE_MONO ) + aGdiMetaFile.Convert( MTF_CONVERSION_1BIT_THRESHOLD ); + aGraf = aGdiMetaFile; + } + break; + default: break; + } + } + } + } + + // sollte es ein OLE-Object sein? + if( bGrfRead && !bLinkGrf && IsProperty( DFF_Prop_pictureId ) ) + { + // TODO/LATER: in future probably the correct aspect should be provided here + sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT; + // --> OD 2004-12-14 #i32596# - pass <nCalledByGroup> to method + pRet = ImportOLE( GetPropertyValue( DFF_Prop_pictureId ), aGraf, rObjData.aBoundRect, aVisArea, rObjData.nCalledByGroup, nAspect ); + // <-- + } + if( !pRet ) + { + pRet = new SdrGrafObj; + if( bGrfRead ) + ((SdrGrafObj*)pRet)->SetGraphic( aGraf ); + + if( bLinkGrf && !bGrfRead ) // sj: #i55484# if the graphic was embedded ( bGrfRead == true ) then + { // we do not need to set a link. TODO: not to lose the information where the graphic is linked from + UniString aName( ::URIHelper::SmartRel2Abs( INetURLObject(maBaseURL), aFilename, URIHelper::GetMaybeFileHdl(), true, false, + INetURLObject::WAS_ENCODED, + INetURLObject::DECODE_UNAMBIGUOUS ) ); + + String aFilterName; + INetURLObject aURLObj( aName ); + + if( aURLObj.GetProtocol() == INET_PROT_NOT_VALID ) + { + String aValidURL; + + if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aValidURL ) ) + aURLObj = INetURLObject( aValidURL ); + } + + if( aURLObj.GetProtocol() != INET_PROT_NOT_VALID ) + { + GraphicFilter* pGrfFilter = GraphicFilter::GetGraphicFilter(); + aFilterName = pGrfFilter->GetImportFormatName( + pGrfFilter->GetImportFormatNumberForShortName( aURLObj.getExtension() ) ); + } + + aLinkFileName = aName; + aLinkFilterName = aFilterName; + } + } + + // set the size from BLIP if there is one + if ( pRet && bGrfRead && !aVisArea.IsEmpty() ) + pRet->SetBLIPSizeRectangle( aVisArea ); + + if ( !pRet->GetName().Len() ) // SJ 22.02.00 : PPT OLE IMPORT: + { // name is already set in ImportOLE !! + // JP 01.12.99: SetName before SetModel - because in the other order the Bug 70098 is active + if ( ( eFlags & mso_blipflagType ) != mso_blipflagComment ) + { + INetURLObject aURL; + aURL.SetSmartURL( aFilename ); + pRet->SetName( aURL.getBase() ); + } + else + pRet->SetName( aFilename ); + } + } + pRet->SetModel( pSdrModel ); // fuer GraphicLink erforderlich + pRet->SetLogicRect( rObjData.aBoundRect ); + + if ( pRet->ISA( SdrGrafObj ) ) + { + if( aLinkFileName.Len() ) + ((SdrGrafObj*)pRet)->SetGraphicLink( aLinkFileName, aLinkFilterName ); + + if ( bLinkGrf && !bGrfRead ) + { + ((SdrGrafObj*)pRet)->ForceSwapIn(); + Graphic aGraf(((SdrGrafObj*)pRet)->GetGraphic()); + lcl_ApplyCropping( *this, &rSet, aGraf ); + } + ((SdrGrafObj*)pRet)->ForceSwapOut(); + } + + return pRet; +} + +// PptSlidePersistEntry& rPersistEntry, SdPage* pPage +SdrObject* SvxMSDffManager::ImportObj( SvStream& rSt, void* pClientData, + Rectangle& rClientRect, const Rectangle& rGlobalChildRect, int nCalledByGroup, sal_Int32* pShapeId ) +{ + SdrObject* pRet = NULL; + DffRecordHeader aObjHd; + rSt >> aObjHd; + if ( aObjHd.nRecType == DFF_msofbtSpgrContainer ) + { + pRet = ImportGroup( aObjHd, rSt, pClientData, rClientRect, rGlobalChildRect, nCalledByGroup, pShapeId ); + } + else if ( aObjHd.nRecType == DFF_msofbtSpContainer ) + { + pRet = ImportShape( aObjHd, rSt, pClientData, rClientRect, rGlobalChildRect, nCalledByGroup, pShapeId ); + } + aObjHd.SeekToBegOfRecord( rSt ); // FilePos restaurieren + return pRet; +} + +SdrObject* SvxMSDffManager::ImportGroup( const DffRecordHeader& rHd, SvStream& rSt, void* pClientData, + Rectangle& rClientRect, const Rectangle& rGlobalChildRect, + int nCalledByGroup, sal_Int32* pShapeId ) +{ + SdrObject* pRet = NULL; + + if( pShapeId ) + *pShapeId = 0; + + rHd.SeekToContent( rSt ); + DffRecordHeader aRecHd; // the first atom has to be the SpContainer for the GroupObject + rSt >> aRecHd; + if ( aRecHd.nRecType == DFF_msofbtSpContainer ) + { + sal_Int32 nGroupRotateAngle = 0; + sal_Int32 nSpFlags = 0; + mnFix16Angle = 0; + aRecHd.SeekToBegOfRecord( rSt ); + pRet = ImportObj( rSt, pClientData, rClientRect, rGlobalChildRect, nCalledByGroup + 1, pShapeId ); + if ( pRet ) + { + nSpFlags = nGroupShapeFlags; + nGroupRotateAngle = mnFix16Angle; + + Rectangle aClientRect( rClientRect ); + + Rectangle aGlobalChildRect; + if ( !nCalledByGroup || rGlobalChildRect.IsEmpty() ) + aGlobalChildRect = GetGlobalChildAnchor( rHd, rSt, aClientRect ); + else + aGlobalChildRect = rGlobalChildRect; + + if ( ( nGroupRotateAngle > 4500 && nGroupRotateAngle <= 13500 ) + || ( nGroupRotateAngle > 22500 && nGroupRotateAngle <= 31500 ) ) + { + sal_Int32 nHalfWidth = ( aClientRect.GetWidth() + 1 ) >> 1; + sal_Int32 nHalfHeight = ( aClientRect.GetHeight() + 1 ) >> 1; + Point aTopLeft( aClientRect.Left() + nHalfWidth - nHalfHeight, + aClientRect.Top() + nHalfHeight - nHalfWidth ); + Size aNewSize( aClientRect.GetHeight(), aClientRect.GetWidth() ); + Rectangle aNewRect( aTopLeft, aNewSize ); + aClientRect = aNewRect; + } + + // now importing the inner objects of the group + aRecHd.SeekToEndOfRecord( rSt ); + while ( ( rSt.GetError() == 0 ) && ( rSt.Tell() < rHd.GetRecEndFilePos() ) ) + { + DffRecordHeader aRecHd2; + rSt >> aRecHd2; + if ( aRecHd2.nRecType == DFF_msofbtSpgrContainer ) + { + Rectangle aGroupClientAnchor, aGroupChildAnchor; + GetGroupAnchors( aRecHd2, rSt, aGroupClientAnchor, aGroupChildAnchor, aClientRect, aGlobalChildRect ); + aRecHd2.SeekToBegOfRecord( rSt ); + sal_Int32 nShapeId; + SdrObject* pTmp = ImportGroup( aRecHd2, rSt, pClientData, aGroupClientAnchor, aGroupChildAnchor, nCalledByGroup + 1, &nShapeId ); + if ( pTmp ) + { + ((SdrObjGroup*)pRet)->GetSubList()->NbcInsertObject( pTmp ); + if( nShapeId ) + insertShapeId( nShapeId, pTmp ); + } + } + else if ( aRecHd2.nRecType == DFF_msofbtSpContainer ) + { + aRecHd2.SeekToBegOfRecord( rSt ); + sal_Int32 nShapeId; + SdrObject* pTmp = ImportShape( aRecHd2, rSt, pClientData, aClientRect, aGlobalChildRect, nCalledByGroup + 1, &nShapeId ); + if ( pTmp ) + { + ((SdrObjGroup*)pRet)->GetSubList()->NbcInsertObject( pTmp ); + if( nShapeId ) + insertShapeId( nShapeId, pTmp ); + } + } + aRecHd2.SeekToEndOfRecord( rSt ); + } + + // pRet->NbcSetSnapRect( aGroupBound ); + if ( nGroupRotateAngle ) + { + double a = nGroupRotateAngle * nPi180; + pRet->NbcRotate( aClientRect.Center(), nGroupRotateAngle, sin( a ), cos( a ) ); + } + if ( nSpFlags & SP_FFLIPV ) // Vertikal gespiegelt? + { // BoundRect in aBoundRect + Point aLeft( aClientRect.Left(), ( aClientRect.Top() + aClientRect.Bottom() ) >> 1 ); + Point aRight( aLeft.X() + 1000, aLeft.Y() ); + pRet->NbcMirror( aLeft, aRight ); + } + if ( nSpFlags & SP_FFLIPH ) // Horizontal gespiegelt? + { // BoundRect in aBoundRect + Point aTop( ( aClientRect.Left() + aClientRect.Right() ) >> 1, aClientRect.Top() ); + Point aBottom( aTop.X(), aTop.Y() + 1000 ); + pRet->NbcMirror( aTop, aBottom ); + } + } + } + return pRet; +} + +SdrObject* SvxMSDffManager::ImportShape( const DffRecordHeader& rHd, SvStream& rSt, void* pClientData, + Rectangle& rClientRect, const Rectangle& rGlobalChildRect, + int nCalledByGroup, sal_Int32* pShapeId ) +{ + SdrObject* pRet = NULL; + + if( pShapeId ) + *pShapeId = 0; + + rHd.SeekToBegOfRecord( rSt ); + DffObjData aObjData( rHd, rClientRect, nCalledByGroup ); + maShapeRecords.Consume( rSt, sal_False ); + aObjData.bShapeType = maShapeRecords.SeekToContent( rSt, DFF_msofbtSp, SEEK_FROM_BEGINNING ); + if ( aObjData.bShapeType ) + { + rSt >> aObjData.nShapeId + >> aObjData.nSpFlags; + aObjData.eShapeType = (MSO_SPT)maShapeRecords.Current()->nRecInstance; + } + else + { + aObjData.nShapeId = 0; + aObjData.nSpFlags = 0; + aObjData.eShapeType = mso_sptNil; + } + + if( pShapeId ) + *pShapeId = aObjData.nShapeId; + + if ( mbTracing ) + mpTracer->AddAttribute( aObjData.nSpFlags & SP_FGROUP + ? rtl::OUString::createFromAscii( "GroupShape" ) + : rtl::OUString::createFromAscii( "Shape" ), + rtl::OUString::valueOf( (sal_Int32)aObjData.nShapeId ) ); + aObjData.bOpt = maShapeRecords.SeekToContent( rSt, DFF_msofbtOPT, SEEK_FROM_CURRENT_AND_RESTART ); + if ( aObjData.bOpt ) + { + maShapeRecords.Current()->SeekToBegOfRecord( rSt ); +#ifdef DBG_AUTOSHAPE + ReadPropSet( rSt, pClientData, (sal_uInt32)aObjData.eShapeType ); +#else + ReadPropSet( rSt, pClientData ); +#endif + } + else + { + InitializePropSet(); // get the default PropSet + ( (DffPropertyReader*) this )->mnFix16Angle = 0; + } + + aObjData.bChildAnchor = maShapeRecords.SeekToContent( rSt, DFF_msofbtChildAnchor, SEEK_FROM_CURRENT_AND_RESTART ); + if ( aObjData.bChildAnchor ) + { + sal_Int32 l, o, r, u; + rSt >> l >> o >> r >> u; + Scale( l ); + Scale( o ); + Scale( r ); + Scale( u ); + aObjData.aChildAnchor = Rectangle( l, o, r, u ); + if ( !rGlobalChildRect.IsEmpty() && !rClientRect.IsEmpty() && rGlobalChildRect.GetWidth() && rGlobalChildRect.GetHeight() ) + { + double fl = l; + double fo = o; + double fWidth = r - l; + double fHeight= u - o; + double fXScale = (double)rClientRect.GetWidth() / (double)rGlobalChildRect.GetWidth(); + double fYScale = (double)rClientRect.GetHeight() / (double)rGlobalChildRect.GetHeight(); + fl = ( ( l - rGlobalChildRect.Left() ) * fXScale ) + rClientRect.Left(); + fo = ( ( o - rGlobalChildRect.Top() ) * fYScale ) + rClientRect.Top(); + fWidth *= fXScale; + fHeight *= fYScale; + aObjData.aChildAnchor = Rectangle( Point( (sal_Int32)fl, (sal_Int32)fo ), Size( (sal_Int32)( fWidth + 1 ), (sal_Int32)( fHeight + 1 ) ) ); + } + } + + aObjData.bClientAnchor = maShapeRecords.SeekToContent( rSt, DFF_msofbtClientAnchor, SEEK_FROM_CURRENT_AND_RESTART ); + if ( aObjData.bClientAnchor ) + ProcessClientAnchor2( rSt, *maShapeRecords.Current(), pClientData, aObjData ); + + if ( aObjData.bChildAnchor ) + aObjData.aBoundRect = aObjData.aChildAnchor; + + if ( aObjData.nSpFlags & SP_FBACKGROUND ) + aObjData.aBoundRect = Rectangle( Point(), Size( 1, 1 ) ); + + Rectangle aTextRect; + if ( !aObjData.aBoundRect.IsEmpty() ) + { // Rotation auf BoundingBox anwenden, BEVOR ien Objekt generiert wurde + if( mnFix16Angle ) + { + long nAngle = mnFix16Angle; + if ( ( nAngle > 4500 && nAngle <= 13500 ) || ( nAngle > 22500 && nAngle <= 31500 ) ) + { + sal_Int32 nHalfWidth = ( aObjData.aBoundRect.GetWidth() + 1 ) >> 1; + sal_Int32 nHalfHeight = ( aObjData.aBoundRect.GetHeight() + 1 ) >> 1; + Point aTopLeft( aObjData.aBoundRect.Left() + nHalfWidth - nHalfHeight, + aObjData.aBoundRect.Top() + nHalfHeight - nHalfWidth ); + Size aNewSize( aObjData.aBoundRect.GetHeight(), aObjData.aBoundRect.GetWidth() ); + Rectangle aNewRect( aTopLeft, aNewSize ); + aObjData.aBoundRect = aNewRect; + } + } + aTextRect = aObjData.aBoundRect; + FASTBOOL bGraphic = IsProperty( DFF_Prop_pib ) || + IsProperty( DFF_Prop_pibName ) || + IsProperty( DFF_Prop_pibFlags ); + + if ( aObjData.nSpFlags & SP_FGROUP ) + { + pRet = new SdrObjGroup; + /* After CWS aw033 has been integrated, an empty group object + cannot store its resulting bounding rectangle anymore. We have + to return this rectangle via rClientRect now, but only, if + caller has not passed an own bounding ractangle. */ + if ( rClientRect.IsEmpty() ) + rClientRect = aObjData.aBoundRect; + nGroupShapeFlags = aObjData.nSpFlags; // #73013# + } + else if ( ( aObjData.eShapeType != mso_sptNil ) || IsProperty( DFF_Prop_pVertices ) || bGraphic ) + { + SfxItemSet aSet( pSdrModel->GetItemPool() ); + + sal_Bool bIsConnector = ( ( aObjData.eShapeType >= mso_sptStraightConnector1 ) && ( aObjData.eShapeType <= mso_sptCurvedConnector5 ) ); + sal_Bool bIsCustomShape = sal_False; + sal_Int32 nObjectRotation = mnFix16Angle; + sal_uInt32 nSpFlags = aObjData.nSpFlags; + + if ( bGraphic ) + { + pRet = ImportGraphic( rSt, aSet, aObjData ); // SJ: #68396# is no longer true (fixed in ppt2000) + ApplyAttributes( rSt, aSet, aObjData ); + pRet->SetMergedItemSet(aSet); + } + else if ( aObjData.eShapeType == mso_sptLine ) + { + basegfx::B2DPolygon aPoly; + aPoly.append(basegfx::B2DPoint(aObjData.aBoundRect.Left(), aObjData.aBoundRect.Top())); + aPoly.append(basegfx::B2DPoint(aObjData.aBoundRect.Right(), aObjData.aBoundRect.Bottom())); + pRet = new SdrPathObj(OBJ_LINE, basegfx::B2DPolyPolygon(aPoly)); + pRet->SetModel( pSdrModel ); + ApplyAttributes( rSt, aSet, aObjData ); + pRet->SetMergedItemSet(aSet); + } + else + { + if ( GetCustomShapeContent( aObjData.eShapeType ) || IsProperty( DFF_Prop_pVertices ) ) + { + + ApplyAttributes( rSt, aSet, aObjData ); + +// the com.sun.star.drawing.EnhancedCustomShapeEngine is default, so we do not need to set a hard attribute +// aSet.Put( SdrCustomShapeEngineItem( String::CreateFromAscii( "com.sun.star.drawing.EnhancedCustomShapeEngine" ) ) ); + pRet = new SdrObjCustomShape(); + pRet->SetModel( pSdrModel ); + + sal_Bool bIsFontwork = ( GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 ) & 0x4000 ) != 0; + + // in case of a FontWork, the text is set by the escher import + if ( bIsFontwork ) + { + String aObjectText; + String aFontName; + MSO_GeoTextAlign eGeoTextAlign; + + if ( SeekToContent( DFF_Prop_gtextFont, rSt ) ) + { + SvxFontItem aLatin(EE_CHAR_FONTINFO), aAsian(EE_CHAR_FONTINFO_CJK), aComplex(EE_CHAR_FONTINFO_CTL); + GetDefaultFonts( aLatin, aAsian, aComplex ); + + MSDFFReadZString( rSt, aFontName, GetPropertyValue( DFF_Prop_gtextFont ), sal_True ); + aSet.Put( SvxFontItem( aLatin.GetFamily(), aFontName, aLatin.GetStyleName(), + PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW, EE_CHAR_FONTINFO )); + aSet.Put( SvxFontItem( aLatin.GetFamily(), aFontName, aLatin.GetStyleName(), + PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW, EE_CHAR_FONTINFO_CJK ) ); + aSet.Put( SvxFontItem( aLatin.GetFamily(), aFontName, aLatin.GetStyleName(), + PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW, EE_CHAR_FONTINFO_CTL ) ); + } + + // SJ: applying fontattributes for Fontwork : + if ( IsHardAttribute( DFF_Prop_gtextFItalic ) ) + aSet.Put( SvxPostureItem( ( GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 ) & 0x0010 ) != 0 ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC ) ); + + if ( IsHardAttribute( DFF_Prop_gtextFBold ) ) + aSet.Put( SvxWeightItem( ( GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 ) & 0x0020 ) != 0 ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT ) ); + + // SJ TODO: Vertical Writing is not correct, instead this should be + // replaced through "CharacterRotation" by 90°, therefore a new Item has to be + // supported by svx core, api and xml file format + ((SdrObjCustomShape*)pRet)->SetVerticalWriting( ( GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 ) & 0x2000 ) != 0 ); + + if ( SeekToContent( DFF_Prop_gtextUNICODE, rSt ) ) + { + MSDFFReadZString( rSt, aObjectText, GetPropertyValue( DFF_Prop_gtextUNICODE ), sal_True ); + ReadObjText( aObjectText, pRet ); + } + + eGeoTextAlign = ( (MSO_GeoTextAlign)GetPropertyValue( DFF_Prop_gtextAlign, mso_alignTextCenter ) ); + { + SdrTextHorzAdjust eHorzAdjust; + switch( eGeoTextAlign ) + { + case mso_alignTextLetterJust : + case mso_alignTextWordJust : + case mso_alignTextStretch : eHorzAdjust = SDRTEXTHORZADJUST_BLOCK; break; + default: + case mso_alignTextInvalid : + case mso_alignTextCenter : eHorzAdjust = SDRTEXTHORZADJUST_CENTER; break; + case mso_alignTextLeft : eHorzAdjust = SDRTEXTHORZADJUST_LEFT; break; + case mso_alignTextRight : eHorzAdjust = SDRTEXTHORZADJUST_RIGHT; break; + } + aSet.Put( SdrTextHorzAdjustItem( eHorzAdjust ) ); + + SdrFitToSizeType eFTS = SDRTEXTFIT_NONE; + if ( eGeoTextAlign == mso_alignTextStretch ) + eFTS = SDRTEXTFIT_ALLLINES; + aSet.Put( SdrTextFitToSizeTypeItem( eFTS ) ); + } + if ( IsProperty( DFF_Prop_gtextSpacing ) ) + { + sal_Int32 nTextWidth = GetPropertyValue( DFF_Prop_gtextSpacing, 100 < 16 ) / 655; + if ( nTextWidth != 100 ) + aSet.Put( SvxCharScaleWidthItem( (sal_uInt16)nTextWidth, EE_CHAR_FONTWIDTH ) ); + } + if ( GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 ) & 0x1000 ) // SJ: Font Kerning On ? + aSet.Put( SvxKerningItem( 1, EE_CHAR_KERNING ) ); + } + pRet->SetMergedItemSet( aSet ); + + // sj: taking care of rtl, ltr. In case of fontwork mso. seems not to be able to set + // proper text directions, instead the text default is depending to the string. + // so we have to calculate the a text direction from string: + if ( bIsFontwork ) + { + OutlinerParaObject* pParaObj = ((SdrObjCustomShape*)pRet)->GetOutlinerParaObject(); + if ( pParaObj ) + { + SdrOutliner& rOutliner = ((SdrObjCustomShape*)pRet)->ImpGetDrawOutliner(); + sal_Bool bOldUpdateMode = rOutliner.GetUpdateMode(); + SdrModel* pModel = pRet->GetModel(); + if ( pModel ) + rOutliner.SetStyleSheetPool( (SfxStyleSheetPool*)pModel->GetStyleSheetPool() ); + rOutliner.SetUpdateMode( sal_False ); + rOutliner.SetText( *pParaObj ); + VirtualDevice aVirDev( 1 ); + aVirDev.SetMapMode( MAP_100TH_MM ); + sal_uInt32 i, nParagraphs = rOutliner.GetParagraphCount(); + if ( nParagraphs ) + { + sal_Bool bCreateNewParaObject = sal_False; + for ( i = 0; i < nParagraphs; i++ ) + { + sal_Bool bIsRTL = aVirDev.GetTextIsRTL( rOutliner.GetText( rOutliner.GetParagraph( i ) ), 0, STRING_LEN ); + if ( bIsRTL ) + { + SfxItemSet aSet2( rOutliner.GetParaAttribs( (sal_uInt16)i ) ); + aSet2.Put( SvxFrameDirectionItem( FRMDIR_HORI_RIGHT_TOP, EE_PARA_WRITINGDIR ) ); + rOutliner.SetParaAttribs( (sal_uInt16)i, aSet2 ); + bCreateNewParaObject = sal_True; + } + } + if ( bCreateNewParaObject ) + { + OutlinerParaObject* pNewText = rOutliner.CreateParaObject(); + rOutliner.Init( OUTLINERMODE_TEXTOBJECT ); + ((SdrObjCustomShape*)pRet)->NbcSetOutlinerParaObject( pNewText ); + } + } + rOutliner.Clear(); + rOutliner.SetUpdateMode( bOldUpdateMode ); + } + } + + // mso_sptArc special treating: + // sj: since we actually can't render the arc because of its weird SnapRect settings, + // we will create a new CustomShape, that can be saved/loaded without problems. + // We will change the shape type, so this code applys only if importing arcs from msoffice. + if ( aObjData.eShapeType == mso_sptArc ) + { + const rtl::OUString sAdjustmentValues( RTL_CONSTASCII_USTRINGPARAM ( "AdjustmentValues" ) ); + const rtl::OUString sCoordinates( RTL_CONSTASCII_USTRINGPARAM ( "Coordinates" ) ); + const rtl::OUString sHandles( RTL_CONSTASCII_USTRINGPARAM ( "Handles" ) ); + const rtl::OUString sEquations( RTL_CONSTASCII_USTRINGPARAM ( "Equations" ) ); + const rtl::OUString sViewBox( RTL_CONSTASCII_USTRINGPARAM ( "ViewBox" ) ); + const rtl::OUString sPath( RTL_CONSTASCII_USTRINGPARAM ( "Path" ) ); + const rtl::OUString sTextFrames( RTL_CONSTASCII_USTRINGPARAM ( "TextFrames" ) ); + SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)((SdrObjCustomShape*)pRet)->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqCoordinates; + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > seqAdjustmentValues; + + // before clearing the GeometryItem we have to store the current Coordinates + const uno::Any* pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sPath, sCoordinates ); + Rectangle aPolyBoundRect; + if ( pAny && ( *pAny >>= seqCoordinates ) && ( seqCoordinates.getLength() >= 4 ) ) + { + sal_Int32 nPtNum, nNumElemVert = seqCoordinates.getLength(); + XPolygon aXP( (sal_uInt16)nNumElemVert ); +// const EnhancedCustomShapeParameterPair* pTmp = seqCoordinates.getArray(); + for ( nPtNum = 0; nPtNum < nNumElemVert; nPtNum++ ) + { + Point aP; + sal_Int32 nX = 0, nY = 0; + seqCoordinates[ nPtNum ].First.Value >>= nX; + seqCoordinates[ nPtNum ].Second.Value >>= nY; + aP.X() = nX; + aP.Y() = nY; + aXP[ (sal_uInt16)nPtNum ] = aP; + } + aPolyBoundRect = Rectangle( aXP.GetBoundRect() ); + } + else + aPolyBoundRect = Rectangle( -21600, 0, 21600, 43200 ); // defaulting + + // clearing items, so MergeDefaultAttributes will set the corresponding defaults from EnhancedCustomShapeGeometry + aGeometryItem.ClearPropertyValue( sHandles ); + aGeometryItem.ClearPropertyValue( sEquations ); + aGeometryItem.ClearPropertyValue( sViewBox ); + aGeometryItem.ClearPropertyValue( sPath ); + + sal_Int32 nEndAngle = 9000; + sal_Int32 nStartAngle = 0; + pAny = ((SdrCustomShapeGeometryItem&)aGeometryItem).GetPropertyValueByName( sAdjustmentValues ); + if ( pAny && ( *pAny >>= seqAdjustmentValues ) && seqAdjustmentValues.getLength() > 1 ) + { + double fNumber; + if ( seqAdjustmentValues[ 0 ].State == com::sun::star::beans::PropertyState_DIRECT_VALUE ) + { + seqAdjustmentValues[ 0 ].Value >>= fNumber; + nEndAngle = NormAngle360( - (sal_Int32)fNumber * 100 ); + } + else + { + fNumber = 270.0; + seqAdjustmentValues[ 0 ].Value <<= fNumber; + seqAdjustmentValues[ 0 ].State = com::sun::star::beans::PropertyState_DIRECT_VALUE; // so this value will properly be stored + } + + if ( seqAdjustmentValues[ 1 ].State == com::sun::star::beans::PropertyState_DIRECT_VALUE ) + { + seqAdjustmentValues[ 1 ].Value >>= fNumber; + nStartAngle = NormAngle360( - (sal_Int32)fNumber * 100 ); + } + else + { + fNumber = 0.0; + seqAdjustmentValues[ 1 ].Value <<= fNumber; + seqAdjustmentValues[ 1 ].State = com::sun::star::beans::PropertyState_DIRECT_VALUE; + } + + PropertyValue aPropVal; + aPropVal.Name = sAdjustmentValues; + aPropVal.Value <<= seqAdjustmentValues; + aGeometryItem.SetPropertyValue( aPropVal ); // storing the angle attribute + } + if ( nStartAngle != nEndAngle ) + { + XPolygon aXPoly( aPolyBoundRect.Center(), aPolyBoundRect.GetWidth() / 2, aPolyBoundRect.GetHeight() / 2, + (sal_uInt16)nStartAngle / 10, (sal_uInt16)nEndAngle / 10, sal_True ); + Rectangle aPolyPieRect( aXPoly.GetBoundRect() ); + + double fYScale, fXScale; + double fYOfs, fXOfs; + + Point aP( aObjData.aBoundRect.Center() ); + Size aS( aObjData.aBoundRect.GetSize() ); + aP.X() -= aS.Width() / 2; + aP.Y() -= aS.Height() / 2; + Rectangle aLogicRect( aP, aS ); + + fYOfs = fXOfs = 0.0; + + if ( aPolyBoundRect.GetWidth() && aPolyPieRect.GetWidth() ) + { + fXScale = (double)aLogicRect.GetWidth() / (double)aPolyPieRect.GetWidth(); + if ( nSpFlags & SP_FFLIPH ) + fXOfs = ( (double)aPolyPieRect.Right() - (double)aPolyBoundRect.Right() ) * fXScale; + else + fXOfs = ( (double)aPolyBoundRect.Left() - (double)aPolyPieRect.Left() ) * fXScale; + } + if ( aPolyBoundRect.GetHeight() && aPolyPieRect.GetHeight() ) + { + fYScale = (double)aLogicRect.GetHeight() / (double)aPolyPieRect.GetHeight(); + if ( nSpFlags & SP_FFLIPV ) + fYOfs = ( (double)aPolyPieRect.Bottom() - (double)aPolyBoundRect.Bottom() ) * fYScale; + else + fYOfs = ((double)aPolyBoundRect.Top() - (double)aPolyPieRect.Top() ) * fYScale; + } + + fXScale = (double)aPolyBoundRect.GetWidth() / (double)aPolyPieRect.GetWidth(); + fYScale = (double)aPolyBoundRect.GetHeight() / (double)aPolyPieRect.GetHeight(); + + Rectangle aOldBoundRect( aObjData.aBoundRect ); + aObjData.aBoundRect = Rectangle( Point( aLogicRect.Left() + (sal_Int32)fXOfs, aLogicRect.Top() + (sal_Int32)fYOfs ), + Size( (sal_Int32)( aLogicRect.GetWidth() * fXScale ), (sal_Int32)( aLogicRect.GetHeight() * fYScale ) ) ); + + // creating the text frame -> scaling into (0,0),(21600,21600) destination coordinate system + double fTextFrameScaleX = (double)21600 / (double)aPolyBoundRect.GetWidth(); + double fTextFrameScaleY = (double)21600 / (double)aPolyBoundRect.GetHeight(); + sal_Int32 nLeft = (sal_Int32)(( aPolyPieRect.Left() - aPolyBoundRect.Left() ) * fTextFrameScaleX ); + sal_Int32 nTop = (sal_Int32)(( aPolyPieRect.Top() - aPolyBoundRect.Top() ) * fTextFrameScaleY ); + sal_Int32 nRight = (sal_Int32)(( aPolyPieRect.Right() - aPolyBoundRect.Left() ) * fTextFrameScaleX ); + sal_Int32 nBottom= (sal_Int32)(( aPolyPieRect.Bottom()- aPolyBoundRect.Top() ) * fTextFrameScaleY ); + com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame > aTextFrame( 1 ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrame[ 0 ].TopLeft.First, nLeft ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrame[ 0 ].TopLeft.Second, nTop ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrame[ 0 ].BottomRight.First, nRight ); + EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrame[ 0 ].BottomRight.Second,nBottom ); + PropertyValue aProp; + aProp.Name = sTextFrames; + aProp.Value <<= aTextFrame; + aGeometryItem.SetPropertyValue( sPath, aProp ); + + // sj: taking care of the different rotation points, since the new arc is having a bigger snaprect + if ( mnFix16Angle ) + { + sal_Int32 nAngle = mnFix16Angle; + if ( nSpFlags & SP_FFLIPH ) + nAngle = 36000 - nAngle; + if ( nSpFlags & SP_FFLIPV ) + nAngle = -nAngle; + double a = nAngle * F_PI18000; + double ss = sin( a ); + double cc = cos( a ); + Point aP1( aOldBoundRect.TopLeft() ); + Point aC1( aObjData.aBoundRect.Center() ); + Point aP2( aOldBoundRect.TopLeft() ); + Point aC2( aOldBoundRect.Center() ); + RotatePoint( aP1, aC1, ss, cc ); + RotatePoint( aP2, aC2, ss, cc ); + aObjData.aBoundRect.Move( aP2.X() - aP1.X(), aP2.Y() - aP1.Y() ); + } + } + ((SdrObjCustomShape*)pRet)->SetMergedItem( aGeometryItem ); + ((SdrObjCustomShape*)pRet)->MergeDefaultAttributes(); + + // now setting a new name, so the above correction is only done once when importing from ms + SdrCustomShapeGeometryItem aGeoName( (SdrCustomShapeGeometryItem&)((SdrObjCustomShape*)pRet)->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + const rtl::OUString sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) ); + const rtl::OUString sName( RTL_CONSTASCII_USTRINGPARAM ( "mso-spt100" ) ); + PropertyValue aPropVal; + aPropVal.Name = sType; + aPropVal.Value <<= sName; + aGeoName.SetPropertyValue( aPropVal ); + ((SdrObjCustomShape*)pRet)->SetMergedItem( aGeoName ); + } + else + ((SdrObjCustomShape*)pRet)->MergeDefaultAttributes(); + + pRet->SetSnapRect( aObjData.aBoundRect ); + EnhancedCustomShape2d aCustomShape2d( pRet ); + aTextRect = aCustomShape2d.GetTextRect(); + + bIsCustomShape = sal_True; + + if( bIsConnector ) + { + if( nObjectRotation ) + { + double a = nObjectRotation * nPi180; + pRet->NbcRotate( aObjData.aBoundRect.Center(), nObjectRotation, sin( a ), cos( a ) ); + } + // Horizontal gespiegelt? + if ( nSpFlags & SP_FFLIPH ) + { + Rectangle aBndRect( pRet->GetSnapRect() ); + Point aTop( ( aBndRect.Left() + aBndRect.Right() ) >> 1, aBndRect.Top() ); + Point aBottom( aTop.X(), aTop.Y() + 1000 ); + pRet->NbcMirror( aTop, aBottom ); + } + // Vertikal gespiegelt? + if ( nSpFlags & SP_FFLIPV ) + { + Rectangle aBndRect( pRet->GetSnapRect() ); + Point aLeft( aBndRect.Left(), ( aBndRect.Top() + aBndRect.Bottom() ) >> 1 ); + Point aRight( aLeft.X() + 1000, aLeft.Y() ); + pRet->NbcMirror( aLeft, aRight ); + } + basegfx::B2DPolyPolygon aPoly( SdrObjCustomShape::GetLineGeometry( (SdrObjCustomShape*)pRet, sal_True ) ); + SdrObject::Free( pRet ); + + pRet = new SdrEdgeObj(); + ApplyAttributes( rSt, aSet, aObjData ); + pRet->SetLogicRect( aObjData.aBoundRect ); + pRet->SetMergedItemSet(aSet); + + // Konnektoren + MSO_ConnectorStyle eConnectorStyle = (MSO_ConnectorStyle)GetPropertyValue( DFF_Prop_cxstyle, mso_cxstyleStraight ); + + ((SdrEdgeObj*)pRet)->ConnectToNode(sal_True, NULL); + ((SdrEdgeObj*)pRet)->ConnectToNode(sal_False, NULL); + + Point aPoint1( aObjData.aBoundRect.TopLeft() ); + Point aPoint2( aObjData.aBoundRect.BottomRight() ); + + // Rotationen beachten + if ( nObjectRotation ) + { + double a = nObjectRotation * nPi180; + Point aCenter( aObjData.aBoundRect.Center() ); + double ss = sin(a); + double cc = cos(a); + + RotatePoint(aPoint1, aCenter, ss, cc); + RotatePoint(aPoint2, aCenter, ss, cc); + } + + // Linie innerhalb des Bereiches zurechtdrehen/spiegeln + if ( nSpFlags & SP_FFLIPH ) + { + sal_Int32 n = aPoint1.X(); + aPoint1.X() = aPoint2.X(); + aPoint2.X() = n; + } + if ( nSpFlags & SP_FFLIPV ) + { + sal_Int32 n = aPoint1.Y(); + aPoint1.Y() = aPoint2.Y(); + aPoint2.Y() = n; + } + nSpFlags &= ~( SP_FFLIPV | SP_FFLIPH ); + + pRet->NbcSetPoint(aPoint1, 0L); // Startpunkt + pRet->NbcSetPoint(aPoint2, 1L); // Endpunkt + + sal_Int32 n1HorzDist, n1VertDist, n2HorzDist, n2VertDist; + n1HorzDist = n1VertDist = n2HorzDist = n2VertDist = 0; + switch( eConnectorStyle ) + { + case mso_cxstyleBent: + { + aSet.Put( SdrEdgeKindItem( SDREDGE_ORTHOLINES ) ); + n1HorzDist = n1VertDist = n2HorzDist = n2VertDist = 630; + } + break; + case mso_cxstyleCurved: + aSet.Put( SdrEdgeKindItem( SDREDGE_BEZIER ) ); + break; + default: // mso_cxstyleStraight || mso_cxstyleNone + aSet.Put( SdrEdgeKindItem( SDREDGE_ONELINE ) ); + break; + } + aSet.Put( SdrEdgeNode1HorzDistItem( n1HorzDist ) ); + aSet.Put( SdrEdgeNode1VertDistItem( n1VertDist ) ); + aSet.Put( SdrEdgeNode2HorzDistItem( n2HorzDist ) ); + aSet.Put( SdrEdgeNode2VertDistItem( n2VertDist ) ); + + ((SdrEdgeObj*)pRet)->SetEdgeTrackPath( aPoly ); + pRet->SetMergedItemSet( aSet ); + } + } + } + + if ( pRet ) + { + if( nObjectRotation ) + { + double a = nObjectRotation * nPi180; + pRet->NbcRotate( aObjData.aBoundRect.Center(), nObjectRotation, sin( a ), cos( a ) ); + } + // Horizontal gespiegelt? + if ( nSpFlags & SP_FFLIPH ) + { + Rectangle aBndRect( pRet->GetSnapRect() ); + Point aTop( ( aBndRect.Left() + aBndRect.Right() ) >> 1, aBndRect.Top() ); + Point aBottom( aTop.X(), aTop.Y() + 1000 ); + pRet->NbcMirror( aTop, aBottom ); + } + // Vertikal gespiegelt? + if ( nSpFlags & SP_FFLIPV ) + { + Rectangle aBndRect( pRet->GetSnapRect() ); + Point aLeft( aBndRect.Left(), ( aBndRect.Top() + aBndRect.Bottom() ) >> 1 ); + Point aRight( aLeft.X() + 1000, aLeft.Y() ); + pRet->NbcMirror( aLeft, aRight ); + } + } + } + } + + // #i51348# #118052# name of the shape + if( pRet ) + { + ::rtl::OUString aObjName = GetPropertyString( DFF_Prop_wzName, rSt ); + if( aObjName.getLength() > 0 ) + pRet->SetName( aObjName ); + } + + pRet = + ProcessObj( rSt, aObjData, pClientData, aTextRect, pRet); + + if ( pRet ) + { + sal_Int32 nGroupProperties( GetPropertyValue( DFF_Prop_fPrint ) ); + pRet->SetVisible( ( nGroupProperties & 2 ) == 0 ); + pRet->SetPrintable( ( nGroupProperties & 1 ) != 0 ); + } + + if ( mbTracing ) + mpTracer->RemoveAttribute( aObjData.nSpFlags & SP_FGROUP + ? rtl::OUString::createFromAscii( "GroupShape" ) + : rtl::OUString::createFromAscii( "Shape" ) ); + return pRet; +} + +Rectangle SvxMSDffManager::GetGlobalChildAnchor( const DffRecordHeader& rHd, SvStream& rSt, Rectangle& aClientRect ) +{ + Rectangle aChildAnchor; + rHd.SeekToContent( rSt ); + while ( ( rSt.GetError() == 0 ) && ( rSt.Tell() < rHd.GetRecEndFilePos() ) ) + { + DffRecordHeader aShapeHd; + rSt >> aShapeHd; + if ( ( aShapeHd.nRecType == DFF_msofbtSpContainer ) || + ( aShapeHd.nRecType == DFF_msofbtSpgrContainer ) ) + { + DffRecordHeader aShapeHd2( aShapeHd ); + if ( aShapeHd.nRecType == DFF_msofbtSpgrContainer ) + rSt >> aShapeHd2; + while( ( rSt.GetError() == 0 ) && ( rSt.Tell() < aShapeHd2.GetRecEndFilePos() ) ) + { + DffRecordHeader aShapeAtom; + rSt >> aShapeAtom; + + if ( aShapeAtom.nRecType == DFF_msofbtClientAnchor ) + { + if ( GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_IMPORT_PPT ) + { + sal_Int32 l, t, r, b; + if ( aShapeAtom.nRecLen == 16 ) + { + rSt >> l >> t >> r >> b; + } + else + { + sal_Int16 ls, ts, rs, bs; + rSt >> ts >> ls >> rs >> bs; // etwas seltsame Koordinatenreihenfolge ... + l = ls, t = ts, r = rs, b = bs; + } + Scale( l ); + Scale( t ); + Scale( r ); + Scale( b ); + aClientRect = Rectangle( l, t, r, b ); + } + break; + } + else if ( aShapeAtom.nRecType == DFF_msofbtChildAnchor ) + { + sal_Int32 l, o, r, u; + rSt >> l >> o >> r >> u; + Scale( l ); + Scale( o ); + Scale( r ); + Scale( u ); + Rectangle aChild( l, o, r, u ); + aChildAnchor.Union( aChild ); + break; + } + aShapeAtom.SeekToEndOfRecord( rSt ); + } + } + aShapeHd.SeekToEndOfRecord( rSt ); + } + return aChildAnchor; +} + +void SvxMSDffManager::GetGroupAnchors( const DffRecordHeader& rHd, SvStream& rSt, + Rectangle& rGroupClientAnchor, Rectangle& rGroupChildAnchor, + const Rectangle& rClientRect, const Rectangle& rGlobalChildRect ) +{ + sal_Bool bFirst = sal_True; + rHd.SeekToContent( rSt ); + DffRecordHeader aShapeHd; + while ( ( rSt.GetError() == 0 ) && ( rSt.Tell() < rHd.GetRecEndFilePos() ) ) + { + rSt >> aShapeHd; + if ( ( aShapeHd.nRecType == DFF_msofbtSpContainer ) || + ( aShapeHd.nRecType == DFF_msofbtSpgrContainer ) ) + { + DffRecordHeader aShapeHd2( aShapeHd ); + if ( aShapeHd.nRecType == DFF_msofbtSpgrContainer ) + rSt >> aShapeHd2; + while( ( rSt.GetError() == 0 ) && ( rSt.Tell() < aShapeHd2.GetRecEndFilePos() ) ) + { + DffRecordHeader aShapeAtom; + rSt >> aShapeAtom; + if ( aShapeAtom.nRecType == DFF_msofbtChildAnchor ) + { + sal_Int32 l, o, r, u; + rSt >> l >> o >> r >> u; + Scale( l ); + Scale( o ); + Scale( r ); + Scale( u ); + Rectangle aChild( l, o, r, u ); + + if ( bFirst ) + { + if ( !rGlobalChildRect.IsEmpty() && !rClientRect.IsEmpty() && rGlobalChildRect.GetWidth() && rGlobalChildRect.GetHeight() ) + { + double fl = l; + double fo = o; + double fWidth = r - l; + double fHeight= u - o; + double fXScale = (double)rClientRect.GetWidth() / (double)rGlobalChildRect.GetWidth(); + double fYScale = (double)rClientRect.GetHeight() / (double)rGlobalChildRect.GetHeight(); + fl = ( ( l - rGlobalChildRect.Left() ) * fXScale ) + rClientRect.Left(); + fo = ( ( o - rGlobalChildRect.Top() ) * fYScale ) + rClientRect.Top(); + fWidth *= fXScale; + fHeight *= fYScale; + rGroupClientAnchor = Rectangle( Point( (sal_Int32)fl, (sal_Int32)fo ), Size( (sal_Int32)( fWidth + 1 ), (sal_Int32)( fHeight + 1 ) ) ); + } + bFirst = sal_False; + } + else + rGroupChildAnchor.Union( aChild ); + break; + } + aShapeAtom.SeekToEndOfRecord( rSt ); + } + } + aShapeHd.SeekToEndOfRecord( rSt ); + } +} + +SdrObject* SvxMSDffManager::ProcessObj(SvStream& rSt, + DffObjData& rObjData, + void* pData, + Rectangle& rTextRect, + SdrObject* pObj + ) +{ + if( !rTextRect.IsEmpty() ) + { + SvxMSDffImportData& rImportData = *(SvxMSDffImportData*)pData; + SvxMSDffImportRec* pImpRec = new SvxMSDffImportRec; + SvxMSDffImportRec* pTextImpRec = pImpRec; + + // fill Import Record with data + pImpRec->nShapeId = rObjData.nShapeId; + pImpRec->eShapeType = rObjData.eShapeType; + + MSO_WrapMode eWrapMode( (MSO_WrapMode)GetPropertyValue( + DFF_Prop_WrapText, + mso_wrapSquare ) ); + rObjData.bClientAnchor = maShapeRecords.SeekToContent( rSt, + DFF_msofbtClientAnchor, + SEEK_FROM_CURRENT_AND_RESTART ); + if( rObjData.bClientAnchor ) + ProcessClientAnchor( rSt, + maShapeRecords.Current()->nRecLen, + pImpRec->pClientAnchorBuffer, pImpRec->nClientAnchorLen ); + + rObjData.bClientData = maShapeRecords.SeekToContent( rSt, + DFF_msofbtClientData, + SEEK_FROM_CURRENT_AND_RESTART ); + if( rObjData.bClientData ) + ProcessClientData( rSt, + maShapeRecords.Current()->nRecLen, + pImpRec->pClientDataBuffer, pImpRec->nClientDataLen ); + + + // process user (== Winword) defined parameters in 0xF122 record + if( maShapeRecords.SeekToContent( rSt, + DFF_msofbtUDefProp, + SEEK_FROM_CURRENT_AND_RESTART ) + && maShapeRecords.Current()->nRecLen ) + { + sal_uInt32 nBytesLeft = maShapeRecords.Current()->nRecLen; + sal_uInt32 nUDData; + sal_uInt16 nPID; + while( 5 < nBytesLeft ) + { + rSt >> nPID; + if ( rSt.GetError() != 0 ) + break; + rSt >> nUDData; + switch( nPID ) + { + case 0x038F: pImpRec->nXAlign = nUDData; break; + case 0x0390: pImpRec->nXRelTo = nUDData; break; + case 0x0391: pImpRec->nYAlign = nUDData; break; + case 0x0392: pImpRec->nYRelTo = nUDData; break; + case 0x03BF: pImpRec->nLayoutInTableCell = nUDData; break; + } + if ( rSt.GetError() != 0 ) + break; + pImpRec->bHasUDefProp = sal_True; + nBytesLeft -= 6; + } + } + + // Textrahmen, auch Title oder Outline + SdrObject* pOrgObj = pObj; + SdrRectObj* pTextObj = 0; + sal_uInt32 nTextId = GetPropertyValue( DFF_Prop_lTxid, 0 ); + if( nTextId ) + { + SfxItemSet aSet( pSdrModel->GetItemPool() ); + + //Originally anything that as a mso_sptTextBox was created as a + //textbox, this was changed for #88277# to be created as a simple + //rect to keep impress happy. For the rest of us we'd like to turn + //it back into a textbox again. + FASTBOOL bTextFrame = (pImpRec->eShapeType == mso_sptTextBox); + if (!bTextFrame) + { + //Either + //a) its a simple text object or + //b) its a rectangle with text and square wrapping. + bTextFrame = + ( + (pImpRec->eShapeType == mso_sptTextSimple) || + ( + (pImpRec->eShapeType == mso_sptRectangle) + && (eWrapMode == mso_wrapSquare) + && ShapeHasText(pImpRec->nShapeId, rObjData.rSpHd.GetRecBegFilePos() ) + ) + ); + } + + if (bTextFrame) + { + SdrObject::Free( pObj ); + pObj = pOrgObj = 0; + } + + // Distance of Textbox to it's surrounding Customshape + sal_Int32 nTextLeft = GetPropertyValue( DFF_Prop_dxTextLeft, 91440L); + sal_Int32 nTextRight = GetPropertyValue( DFF_Prop_dxTextRight, 91440L ); + sal_Int32 nTextTop = GetPropertyValue( DFF_Prop_dyTextTop, 45720L ); + sal_Int32 nTextBottom = GetPropertyValue( DFF_Prop_dyTextBottom, 45720L ); + + ScaleEmu( nTextLeft ); + ScaleEmu( nTextRight ); + ScaleEmu( nTextTop ); + ScaleEmu( nTextBottom ); + + sal_Int32 nTextRotationAngle=0; + bool bVerticalText = false; + if ( IsProperty( DFF_Prop_txflTextFlow ) ) + { + MSO_TextFlow eTextFlow = (MSO_TextFlow)(GetPropertyValue( + DFF_Prop_txflTextFlow) & 0xFFFF); + switch( eTextFlow ) + { + case mso_txflBtoT: + nTextRotationAngle = 9000; + break; + case mso_txflVertN: + case mso_txflTtoBN: + nTextRotationAngle = 27000; + break; + case mso_txflTtoBA: + bVerticalText = true; + break; + case mso_txflHorzA: + bVerticalText = true; + nTextRotationAngle = 9000; + case mso_txflHorzN: + default : + break; + } + } + + if (nTextRotationAngle) + { + while (nTextRotationAngle > 360000) + nTextRotationAngle-=9000; + switch (nTextRotationAngle) + { + case 9000: + { + long nWidth = rTextRect.GetWidth(); + rTextRect.Right() = rTextRect.Left() + rTextRect.GetHeight(); + rTextRect.Bottom() = rTextRect.Top() + nWidth; + + sal_Int32 nOldTextLeft = nTextLeft; + sal_Int32 nOldTextRight = nTextRight; + sal_Int32 nOldTextTop = nTextTop; + sal_Int32 nOldTextBottom = nTextBottom; + + nTextLeft = nOldTextBottom; + nTextRight = nOldTextTop; + nTextTop = nOldTextLeft; + nTextBottom = nOldTextRight; + } + break; + case 27000: + { + long nWidth = rTextRect.GetWidth(); + rTextRect.Right() = rTextRect.Left() + rTextRect.GetHeight(); + rTextRect.Bottom() = rTextRect.Top() + nWidth; + + sal_Int32 nOldTextLeft = nTextLeft; + sal_Int32 nOldTextRight = nTextRight; + sal_Int32 nOldTextTop = nTextTop; + sal_Int32 nOldTextBottom = nTextBottom; + + nTextLeft = nOldTextTop; + nTextRight = nOldTextBottom; + nTextTop = nOldTextRight; + nTextBottom = nOldTextLeft; + } + break; + default: + break; + } + } + + pTextObj = new SdrRectObj(OBJ_TEXT, rTextRect); + pTextImpRec = new SvxMSDffImportRec(*pImpRec); + + // Die vertikalen Absatzeinrueckungen sind im BoundRect mit drin, + // hier rausrechnen + Rectangle aNewRect(rTextRect); + aNewRect.Bottom() -= nTextTop + nTextBottom; + aNewRect.Right() -= nTextLeft + nTextRight; + + // Nur falls es eine einfache Textbox ist, darf der Writer + // das Objekt durch einen Rahmen ersetzen, ansonsten + if( bTextFrame ) + { + SvxMSDffShapeInfo aTmpRec( 0, pImpRec->nShapeId ); + aTmpRec.bSortByShapeId = sal_True; + + sal_uInt16 nFound; + if( pShapeInfos->Seek_Entry( &aTmpRec, &nFound ) ) + { + SvxMSDffShapeInfo& rInfo = *pShapeInfos->GetObject(nFound); + pTextImpRec->bReplaceByFly = rInfo.bReplaceByFly; + pTextImpRec->bLastBoxInChain = rInfo.bLastBoxInChain; + } + } + + if( !pObj ) + ApplyAttributes( rSt, aSet, rObjData ); + + bool bFitText = false; + if (GetPropertyValue(DFF_Prop_FitTextToShape) & 2) + { + aSet.Put( SdrTextAutoGrowHeightItem( sal_True ) ); + aSet.Put( SdrTextMinFrameHeightItem( + aNewRect.Bottom() - aNewRect.Top() ) ); + aSet.Put( SdrTextMinFrameWidthItem( + aNewRect.Right() - aNewRect.Left() ) ); + bFitText = true; + } + else + { + aSet.Put( SdrTextAutoGrowHeightItem( sal_False ) ); + aSet.Put( SdrTextAutoGrowWidthItem( sal_False ) ); + } + + switch ( (MSO_WrapMode) + GetPropertyValue( DFF_Prop_WrapText, mso_wrapSquare ) ) + { + case mso_wrapNone : + aSet.Put( SdrTextAutoGrowWidthItem( sal_True ) ); + if (bFitText) + { + //can't do autowidth in flys #i107184# + pTextImpRec->bReplaceByFly = false; + } + break; + case mso_wrapByPoints : + aSet.Put( SdrTextContourFrameItem( sal_True ) ); + break; + default: break; + } + + // Abstaende an den Raendern der Textbox setzen + aSet.Put( SdrTextLeftDistItem( nTextLeft ) ); + aSet.Put( SdrTextRightDistItem( nTextRight ) ); + aSet.Put( SdrTextUpperDistItem( nTextTop ) ); + aSet.Put( SdrTextLowerDistItem( nTextBottom ) ); + pTextImpRec->nDxTextLeft = nTextLeft; + pTextImpRec->nDyTextTop = nTextTop; + pTextImpRec->nDxTextRight = nTextRight; + pTextImpRec->nDyTextBottom = nTextBottom; + + // Textverankerung lesen + if ( IsProperty( DFF_Prop_anchorText ) ) + { + MSO_Anchor eTextAnchor = + (MSO_Anchor)GetPropertyValue( DFF_Prop_anchorText ); + + SdrTextVertAdjust eTVA = SDRTEXTVERTADJUST_CENTER; + sal_Bool bTVASet(sal_False); + SdrTextHorzAdjust eTHA = SDRTEXTHORZADJUST_CENTER; + sal_Bool bTHASet(sal_False); + + switch( eTextAnchor ) + { + case mso_anchorTop: + { + eTVA = SDRTEXTVERTADJUST_TOP; + bTVASet = sal_True; + } + break; + case mso_anchorTopCentered: + { + eTVA = SDRTEXTVERTADJUST_TOP; + bTVASet = sal_True; + bTHASet = sal_True; + } + break; + + case mso_anchorMiddle: + bTVASet = sal_True; + break; + case mso_anchorMiddleCentered: + { + bTVASet = sal_True; + bTHASet = sal_True; + } + break; + case mso_anchorBottom: + { + eTVA = SDRTEXTVERTADJUST_BOTTOM; + bTVASet = sal_True; + } + break; + case mso_anchorBottomCentered: + { + eTVA = SDRTEXTVERTADJUST_BOTTOM; + bTVASet = sal_True; + bTHASet = sal_True; + } + break; + /* + case mso_anchorTopBaseline: + case mso_anchorBottomBaseline: + case mso_anchorTopCenteredBaseline: + case mso_anchorBottomCenteredBaseline: + break; + */ + default : break; + } + // Einsetzen + if ( bTVASet ) + aSet.Put( SdrTextVertAdjustItem( eTVA ) ); + if ( bTHASet ) + aSet.Put( SdrTextHorzAdjustItem( eTHA ) ); + } + + pTextObj->SetMergedItemSet(aSet); + pTextObj->SetModel(pSdrModel); + + if (bVerticalText) + pTextObj->SetVerticalWriting(sal_True); + + if (nTextRotationAngle) + { + long nMinWH = rTextRect.GetWidth() < rTextRect.GetHeight() ? + rTextRect.GetWidth() : rTextRect.GetHeight(); + nMinWH /= 2; + Point aPivot(rTextRect.TopLeft()); + aPivot.X() += nMinWH; + aPivot.Y() += nMinWH; + double a = nTextRotationAngle * nPi180; + pTextObj->NbcRotate(aPivot, nTextRotationAngle, sin(a), cos(a)); + } + + // rotate text with shape ? + if ( mnFix16Angle ) + { + double a = mnFix16Angle * nPi180; + pTextObj->NbcRotate( rObjData.aBoundRect.Center(), mnFix16Angle, + sin( a ), cos( a ) ); + } + + if( !pObj ) + { + pObj = pTextObj; + } + else + { + if( pTextObj != pObj ) + { + SdrObject* pGroup = new SdrObjGroup; + pGroup->GetSubList()->NbcInsertObject( pObj ); + pGroup->GetSubList()->NbcInsertObject( pTextObj ); + if (pOrgObj == pObj) + pOrgObj = pGroup; + else + pOrgObj = pObj; + pObj = pGroup; + } + } + } + else if( !pObj ) + { + // simple rectangular objects are ignored by ImportObj() :-( + // this is OK for Draw but not for Calc and Writer + // cause here these objects have a default border + pObj = new SdrRectObj(rTextRect); + pOrgObj = pObj; + pObj->SetModel( pSdrModel ); + SfxItemSet aSet( pSdrModel->GetItemPool() ); + ApplyAttributes( rSt, aSet, rObjData ); + + const SfxPoolItem* pPoolItem=NULL; + SfxItemState eState = aSet.GetItemState( XATTR_FILLCOLOR, + sal_False, &pPoolItem ); + if( SFX_ITEM_DEFAULT == eState ) + aSet.Put( XFillColorItem( String(), + Color( mnDefaultColor ) ) ); + pObj->SetMergedItemSet(aSet); + } + + //Means that fBehindDocument is set + if (GetPropertyValue(DFF_Prop_fPrint) & 0x20) + pImpRec->bDrawHell = sal_True; + else + pImpRec->bDrawHell = sal_False; + if (GetPropertyValue(DFF_Prop_fPrint) & 0x02) + pImpRec->bHidden = sal_True; + pTextImpRec->bDrawHell = pImpRec->bDrawHell; + pTextImpRec->bHidden = pImpRec->bHidden; + pImpRec->nNextShapeId = GetPropertyValue( DFF_Prop_hspNext, 0 ); + pTextImpRec->nNextShapeId=pImpRec->nNextShapeId; + + if ( nTextId ) + { + pTextImpRec->aTextId.nTxBxS = (sal_uInt16)( nTextId >> 16 ); + pTextImpRec->aTextId.nSequence = (sal_uInt16)nTextId; + } + + pTextImpRec->nDxWrapDistLeft = GetPropertyValue( + DFF_Prop_dxWrapDistLeft, 114935L ) / 635L; + pTextImpRec->nDyWrapDistTop = GetPropertyValue( + DFF_Prop_dyWrapDistTop, 0 ) / 635L; + pTextImpRec->nDxWrapDistRight = GetPropertyValue( + DFF_Prop_dxWrapDistRight, 114935L ) / 635L; + pTextImpRec->nDyWrapDistBottom = GetPropertyValue( + DFF_Prop_dyWrapDistBottom, 0 ) / 635L; + // 16.16 fraction times total image width or height, as appropriate. + + if (SeekToContent(DFF_Prop_pWrapPolygonVertices, rSt)) + { + delete pTextImpRec->pWrapPolygon; + sal_uInt16 nNumElemVert, nNumElemMemVert, nElemSizeVert; + rSt >> nNumElemVert >> nNumElemMemVert >> nElemSizeVert; + if (nNumElemVert && ((nElemSizeVert == 8) || (nElemSizeVert == 4))) + { + pTextImpRec->pWrapPolygon = new Polygon(nNumElemVert); + for (sal_uInt16 i = 0; i < nNumElemVert; ++i) + { + sal_Int32 nX, nY; + if (nElemSizeVert == 8) + rSt >> nX >> nY; + else + { + sal_Int16 nSmallX, nSmallY; + rSt >> nSmallX >> nSmallY; + nX = nSmallX; + nY = nSmallY; + } + (*(pTextImpRec->pWrapPolygon))[i].X() = nX; + (*(pTextImpRec->pWrapPolygon))[i].Y() = nY; + } + } + } + + pImpRec->nCropFromTop = GetPropertyValue( + DFF_Prop_cropFromTop, 0 ); + pImpRec->nCropFromBottom = GetPropertyValue( + DFF_Prop_cropFromBottom, 0 ); + pImpRec->nCropFromLeft = GetPropertyValue( + DFF_Prop_cropFromLeft, 0 ); + pImpRec->nCropFromRight = GetPropertyValue( + DFF_Prop_cropFromRight, 0 ); + + pImpRec->bVFlip = (rObjData.nSpFlags & SP_FFLIPV) ? true : false; + pImpRec->bHFlip = (rObjData.nSpFlags & SP_FFLIPH) ? true : false; + + sal_uInt32 nLineFlags = GetPropertyValue( DFF_Prop_fNoLineDrawDash ); + pImpRec->eLineStyle = (nLineFlags & 8) + ? (MSO_LineStyle)GetPropertyValue( + DFF_Prop_lineStyle, + mso_lineSimple ) + : (MSO_LineStyle)USHRT_MAX; + pTextImpRec->eLineStyle = pImpRec->eLineStyle; + + if( pImpRec->nShapeId ) + { + // Import-Record-Liste ergaenzen + if( pOrgObj ) + { + pImpRec->pObj = pOrgObj; + rImportData.aRecords.Insert( pImpRec ); + } + + if( pTextObj && (pOrgObj != pTextObj) ) + { + // Modify ShapeId (must be unique) + pImpRec->nShapeId |= 0x8000000; + pTextImpRec->pObj = pTextObj; + rImportData.aRecords.Insert( pTextImpRec ); + } + + // Eintrag in Z-Order-Liste um Zeiger auf dieses Objekt ergaenzen + /*Only store objects which are not deep inside the tree*/ + if( ( rObjData.nCalledByGroup == 0 ) + || + ( (rObjData.nSpFlags & SP_FGROUP) + && (rObjData.nCalledByGroup < 2) ) + ) + StoreShapeOrder( pImpRec->nShapeId, + ( ( (sal_uLong)pImpRec->aTextId.nTxBxS ) << 16 ) + + pImpRec->aTextId.nSequence, pObj ); + } + else + delete pImpRec; + } + + return pObj; +}; + +void SvxMSDffManager::StoreShapeOrder(sal_uLong nId, + sal_uLong nTxBx, + SdrObject* pObject, + SwFlyFrmFmt* pFly, + short nHdFtSection) const +{ + sal_uInt16 nShpCnt = pShapeOrders->Count(); + for (sal_uInt16 nShapeNum=0; nShapeNum < nShpCnt; nShapeNum++) + { + SvxMSDffShapeOrder& rOrder + = *(SvxMSDffShapeOrder*)(pShapeOrders->GetObject( nShapeNum )); + + if( rOrder.nShapeId == nId ) + { + rOrder.nTxBxComp = nTxBx; + rOrder.pObj = pObject; + rOrder.pFly = pFly; + rOrder.nHdFtSection = nHdFtSection; + } + } +} + + +void SvxMSDffManager::ExchangeInShapeOrder( SdrObject* pOldObject, + sal_uLong nTxBx, + SwFlyFrmFmt* pFly, + SdrObject* pObject) const +{ + sal_uInt16 nShpCnt = pShapeOrders->Count(); + for (sal_uInt16 nShapeNum=0; nShapeNum < nShpCnt; nShapeNum++) + { + SvxMSDffShapeOrder& rOrder + = *(SvxMSDffShapeOrder*)(pShapeOrders->GetObject( nShapeNum )); + + if( rOrder.pObj == pOldObject ) + { + rOrder.pFly = pFly; + rOrder.pObj = pObject; + rOrder.nTxBxComp = nTxBx; + } + } +} + + +void SvxMSDffManager::RemoveFromShapeOrder( SdrObject* pObject ) const +{ + sal_uInt16 nShpCnt = pShapeOrders->Count(); + for (sal_uInt16 nShapeNum=0; nShapeNum < nShpCnt; nShapeNum++) + { + SvxMSDffShapeOrder& rOrder + = *(SvxMSDffShapeOrder*)(pShapeOrders->GetObject( nShapeNum )); + + if( rOrder.pObj == pObject ) + { + rOrder.pObj = 0; + rOrder.pFly = 0; + rOrder.nTxBxComp = 0; + } + } +} + + + + +//--------------------------------------------------------------------------- +// Hilfs Deklarationen +//--------------------------------------------------------------------------- + +/*struct SvxMSDffBLIPInfo -> in's Header-File +{ + sal_uInt16 nBLIPType; // Art des BLIP: z.B. 6 fuer PNG + sal_uLong nFilePos; // Offset des BLIP im Daten-Stream + sal_uLong nBLIPSize; // Anzahl Bytes, die der BLIP im Stream einnimmt + SvxMSDffBLIPInfo(sal_uInt16 nBType, sal_uLong nFPos, sal_uLong nBSize): + nBLIPType( nBType ), nFilePos( nFPos ), nBLIPSize( nBSize ){} +}; +*/ + +SV_IMPL_PTRARR( SvxMSDffBLIPInfos, SvxMSDffBLIPInfo_Ptr ); + +SV_IMPL_PTRARR( SvxMSDffShapeOrders, SvxMSDffShapeOrder_Ptr ); + +SV_IMPL_OP_PTRARR_SORT( SvxMSDffShapeInfos, SvxMSDffShapeInfo_Ptr ); + +SV_IMPL_OP_PTRARR_SORT( SvxMSDffShapeTxBxSort, SvxMSDffShapeOrder_Ptr ); + + +// Liste aller SvxMSDffImportRec fuer eine Gruppe +SV_IMPL_OP_PTRARR_SORT(MSDffImportRecords, MSDffImportRec_Ptr) + +//--------------------------------------------------------------------------- +// exportierte Klasse: oeffentliche Methoden +//--------------------------------------------------------------------------- + +SvxMSDffManager::SvxMSDffManager(SvStream& rStCtrl_, + const String& rBaseURL, + long nOffsDgg_, + SvStream* pStData_, + SdrModel* pSdrModel_,// s. unten: SetModel() + long nApplicationScale, + ColorData mnDefaultColor_, + sal_uLong nDefaultFontHeight_, + SvStream* pStData2_, + MSFilterTracer* pTracer ) + :DffPropertyReader( *this ), + pFormModel( NULL ), + pBLIPInfos( new SvxMSDffBLIPInfos ), + pShapeInfos( new SvxMSDffShapeInfos ), + pShapeOrders( new SvxMSDffShapeOrders ), + nDefaultFontHeight( nDefaultFontHeight_), + nOffsDgg( nOffsDgg_ ), + nBLIPCount( USHRT_MAX ), // mit Error initialisieren, da wir erst pruefen, + nShapeCount( USHRT_MAX ), // ob Kontroll-Stream korrekte Daten enthaellt + maBaseURL( rBaseURL ), + mpFidcls( NULL ), + rStCtrl( rStCtrl_ ), + pStData( pStData_ ), + pStData2( pStData2_ ), + nSvxMSDffSettings( 0 ), + nSvxMSDffOLEConvFlags( 0 ), + pEscherBlipCache( NULL ), + mnDefaultColor( mnDefaultColor_), + mpTracer( pTracer ), + mbTracing( sal_False ) +{ + if ( mpTracer ) + { + uno::Any aAny( mpTracer->GetProperty( rtl::OUString::createFromAscii( "On" ) ) ); + aAny >>= mbTracing; + } + SetModel( pSdrModel_, nApplicationScale ); + + // FilePos des/der Stream(s) merken + sal_uLong nOldPosCtrl = rStCtrl.Tell(); + sal_uLong nOldPosData = pStData ? pStData->Tell() : nOldPosCtrl; + + // Falls kein Datenstream angegeben, gehen wir davon aus, + // dass die BLIPs im Steuerstream stehen. + if( !pStData ) + pStData = &rStCtrl; + + SetDefaultPropSet( rStCtrl, nOffsDgg ); + + // Steuer Stream auslesen, im Erfolgsfall nBLIPCount setzen + GetCtrlData( nOffsDgg ); + + // Text-Box-Story-Ketten-Infos ueberpruefen + CheckTxBxStoryChain(); + + // alte FilePos des/der Stream(s) restaurieren + rStCtrl.Seek( nOldPosCtrl ); + if( &rStCtrl != pStData ) + pStData->Seek( nOldPosData ); +} + +SvxMSDffManager::SvxMSDffManager( SvStream& rStCtrl_, const String& rBaseURL, MSFilterTracer* pTracer ) + :DffPropertyReader( *this ), + pFormModel( NULL ), + pBLIPInfos( new SvxMSDffBLIPInfos ), + pShapeInfos( new SvxMSDffShapeInfos ), + pShapeOrders( new SvxMSDffShapeOrders ), + nDefaultFontHeight( 24 ), + nOffsDgg( 0 ), + nBLIPCount( USHRT_MAX ), // mit Error initialisieren, da wir erst pruefen, + nShapeCount( USHRT_MAX ), // ob Kontroll-Stream korrekte Daten enthaellt + maBaseURL( rBaseURL ), + mpFidcls( NULL ), + rStCtrl( rStCtrl_ ), + pStData( 0 ), + pStData2( 0 ), + nSvxMSDffSettings( 0 ), + nSvxMSDffOLEConvFlags( 0 ), + pEscherBlipCache( NULL ), + mnDefaultColor( COL_DEFAULT ), + mpTracer( pTracer ), + mbTracing( sal_False ) +{ + if ( mpTracer ) + { + uno::Any aAny( mpTracer->GetProperty( rtl::OUString::createFromAscii( "On" ) ) ); + aAny >>= mbTracing; + } + SetModel( NULL, 0 ); +} + +SvxMSDffManager::~SvxMSDffManager() +{ + if ( pEscherBlipCache ) + { + void* pPtr; + for ( pPtr = pEscherBlipCache->First(); pPtr; pPtr = pEscherBlipCache->Next() ) + delete (EscherBlipCacheEntry*)pPtr; + delete pEscherBlipCache; + } + delete pBLIPInfos; + delete pShapeInfos; + delete pShapeOrders; + delete pFormModel; + delete[] mpFidcls; +} + +void SvxMSDffManager::InitSvxMSDffManager( long nOffsDgg_, SvStream* pStData_, sal_uInt32 nOleConvFlags ) +{ + nOffsDgg = nOffsDgg_; + pStData = pStData_; + nSvxMSDffOLEConvFlags = nOleConvFlags; + + // FilePos des/der Stream(s) merken + sal_uLong nOldPosCtrl = rStCtrl.Tell(); + + SetDefaultPropSet( rStCtrl, nOffsDgg ); + + // insert fidcl cluster table + GetFidclData( nOffsDgg ); + + // Steuer Stream auslesen, im Erfolgsfall nBLIPCount setzen + GetCtrlData( nOffsDgg ); + + // Text-Box-Story-Ketten-Infos ueberpruefen + CheckTxBxStoryChain(); + + // alte FilePos des/der Stream(s) restaurieren + rStCtrl.Seek( nOldPosCtrl ); +} + +void SvxMSDffManager::SetDgContainer( SvStream& rSt ) +{ + sal_uInt32 nFilePos = rSt.Tell(); + DffRecordHeader aDgContHd; + rSt >> aDgContHd; + // insert this container only if there is also a DgAtom + if ( SeekToRec( rSt, DFF_msofbtDg, aDgContHd.GetRecEndFilePos() ) ) + { + DffRecordHeader aRecHd; + rSt >> aRecHd; + sal_uInt32 nDrawingId = aRecHd.nRecInstance; + maDgOffsetTable.Insert( nDrawingId, (void*)nFilePos ); + rSt.Seek( nFilePos ); + } +} + +void SvxMSDffManager::GetFidclData( long nOffsDggL ) +{ + if ( nOffsDggL ) + { + sal_uInt32 nDummy, nMerk = rStCtrl.Tell(); + rStCtrl.Seek( nOffsDggL ); + + DffRecordHeader aRecHd; + rStCtrl >> aRecHd; + + DffRecordHeader aDggAtomHd; + if ( SeekToRec( rStCtrl, DFF_msofbtDgg, aRecHd.GetRecEndFilePos(), &aDggAtomHd ) ) + { + aDggAtomHd.SeekToContent( rStCtrl ); + rStCtrl >> mnCurMaxShapeId + >> mnIdClusters + >> nDummy + >> mnDrawingsSaved; + + if ( mnIdClusters-- > 2 ) + { + if ( aDggAtomHd.nRecLen == ( mnIdClusters * sizeof( FIDCL ) + 16 ) ) + { + mpFidcls = new FIDCL[ mnIdClusters ]; + for ( sal_uInt32 i = 0; i < mnIdClusters; i++ ) + { + rStCtrl >> mpFidcls[ i ].dgid + >> mpFidcls[ i ].cspidCur; + } + } + } + } + rStCtrl.Seek( nMerk ); + } +} + +void SvxMSDffManager::CheckTxBxStoryChain() +{ + SvxMSDffShapeInfos* pOld = pShapeInfos; + sal_uInt16 nCnt = pOld->Count(); + pShapeInfos = new SvxMSDffShapeInfos( (nCnt < 255) + ? nCnt + : 255 ); + // altes Info-Array ueberarbeiten + // (ist sortiert nach nTxBxComp) + sal_uLong nChain = ULONG_MAX; + sal_uInt16 nObjMark = 0; + sal_Bool bSetReplaceFALSE = sal_False; + sal_uInt16 nObj; + for( nObj = 0; nObj < nCnt; ++nObj ) + { + SvxMSDffShapeInfo* pObj = pOld->GetObject( nObj ); + if( pObj->nTxBxComp ) + { + pObj->bLastBoxInChain = sal_False; + // Gruppenwechsel ? + // --> OD 2008-07-28 #156763# + // the text id also contains an internal drawing container id + // to distinguish between text id of drawing objects in different + // drawing containers. +// if( nChain != (pObj->nTxBxComp & 0xFFFF0000) ) + if( nChain != pObj->nTxBxComp ) + // <-- + { + // voriger war letzter seiner Gruppe + if( nObj ) + pOld->GetObject( nObj-1 )->bLastBoxInChain = sal_True; + // Merker und Hilfs-Flag zuruecksetzen + nObjMark = nObj; + // --> OD 2008-07-28 #156763# +// nChain = pObj->nTxBxComp & 0xFFFF0000; + nChain = pObj->nTxBxComp; + // <-- + bSetReplaceFALSE = !pObj->bReplaceByFly; + } + else + if( !pObj->bReplaceByFly ) + { + // Objekt, das NICHT durch Rahmen ersetzt werden darf ? + // Hilfs-Flag setzen + bSetReplaceFALSE = sal_True; + // ggfs Flag in Anfang der Gruppe austragen + for( sal_uInt16 nObj2 = nObjMark; nObj2 < nObj; ++nObj2 ) + pOld->GetObject( nObj2 )->bReplaceByFly = sal_False; + } + + if( bSetReplaceFALSE ) + { + pObj->bReplaceByFly = sal_False; + } + } + // alle Shape-Info-Objekte in pShapeInfos umkopieren + // (aber nach nShapeId sortieren) + pObj->bSortByShapeId = sal_True; + // --> OD 2008-07-28 #156763# + pObj->nTxBxComp = pObj->nTxBxComp & 0xFFFF0000; + // <-- + pShapeInfos->Insert( pObj ); + } + // voriger war letzter seiner Gruppe + if( nObj ) + pOld->GetObject( nObj-1 )->bLastBoxInChain = sal_True; + // urspruengliches Array freigeben, ohne Objekte zu zerstoeren + pOld->Remove((sal_uInt16)0, nCnt); + delete pOld; +} + + +/***************************************************************************** + + Einlesen der Shape-Infos im Ctor: + --------------------------------- + merken der Shape-Ids und zugehoerigen Blip-Nummern und TextBox-Infos + ========= ============ ============= + und merken des File-Offsets fuer jedes Blip + ============ +******************************************************************************/ +void SvxMSDffManager::GetCtrlData( long nOffsDgg_ ) +{ + // Start Offset unbedingt merken, falls wir nochmal aufsetzen muessen + long nOffsDggL = nOffsDgg_; + + // Kontroll Stream positionieren + rStCtrl.Seek( nOffsDggL ); + + sal_uInt8 nVer; + sal_uInt16 nInst; + sal_uInt16 nFbt; + sal_uInt32 nLength; + if( !this->ReadCommonRecordHeader( rStCtrl, nVer, nInst, nFbt, nLength ) ) return; + + sal_Bool bOk; + sal_uLong nPos = nOffsDggL + DFF_COMMON_RECORD_HEADER_SIZE; + + // Fall A: erst Drawing Group Container, dann n Mal Drawing Container + if( DFF_msofbtDggContainer == nFbt ) + { + GetDrawingGroupContainerData( rStCtrl, nLength ); + + rStCtrl.Seek( STREAM_SEEK_TO_END ); + sal_uInt32 nMaxStrPos = rStCtrl.Tell(); + + nPos += nLength; + // --> OD 2008-07-28 #156763# + unsigned long nDrawingContainerId = 1; + // <-- + do + { + rStCtrl.Seek( nPos ); + + bOk = ReadCommonRecordHeader( rStCtrl, nVer, nInst, nFbt, nLength ) && ( DFF_msofbtDgContainer == nFbt ); + + if( !bOk ) + { + nPos++; + rStCtrl.Seek( nPos ); + bOk = ReadCommonRecordHeader( rStCtrl, nVer, nInst, nFbt, nLength ) + && ( DFF_msofbtDgContainer == nFbt ); + } + if( bOk ) + { + // --> OD 2008-07-28 #156763# + GetDrawingContainerData( rStCtrl, nLength, nDrawingContainerId ); + // <-- + } + nPos += DFF_COMMON_RECORD_HEADER_SIZE + nLength; + // --> OD 2008-07-28 #156763# + ++nDrawingContainerId; + // <-- + } + while( nPos < nMaxStrPos && bOk ); + } +} + + +// ab hier: Drawing Group Container d.h. Dokument - weit gueltige Daten +// ======================= ======== +// +void SvxMSDffManager::GetDrawingGroupContainerData( SvStream& rSt, sal_uLong nLenDgg ) +{ + sal_uInt8 nVer; + sal_uInt16 nInst; + sal_uInt16 nFbt; + sal_uInt32 nLength; + + sal_uLong nLenBStoreCont = 0, nLenFBSE = 0, nRead = 0; + + // Nach einem BStore Container suchen + do + { + if(!this->ReadCommonRecordHeader( rSt, nVer, nInst, nFbt, nLength)) return; + nRead += DFF_COMMON_RECORD_HEADER_SIZE + nLength; + if( DFF_msofbtBstoreContainer == nFbt ) + { + nLenBStoreCont = nLength; break; + } + rSt.SeekRel( nLength ); + } + while( nRead < nLenDgg ); + + if( !nLenBStoreCont ) return; + + // Im BStore Container alle Header der Container und Atome auslesen und die + // relevanten Daten aller enthaltenen FBSEs in unserem Pointer Array ablegen. + // Dabei zaehlen wir die gefundenen FBSEs im Member nBLIPCount mit. + + const sal_uLong nSkipBLIPLen = 20; // bis zu nBLIPLen zu ueberspringende Bytes + const sal_uLong nSkipBLIPPos = 4; // dahinter bis zu nBLIPPos zu skippen + + sal_uInt32 nBLIPLen = 0, nBLIPPos = 0; + + nRead = 0; + do + { + if(!this->ReadCommonRecordHeader( rSt, nVer, nInst, nFbt, nLength)) return; + nRead += DFF_COMMON_RECORD_HEADER_SIZE + nLength; + if( DFF_msofbtBSE == nFbt ) + { + nLenFBSE = nLength; + // ist FBSE gross genug fuer unsere Daten + sal_Bool bOk = ( nSkipBLIPLen + 4 + nSkipBLIPPos + 4 <= nLenFBSE ); + + if( bOk ) + { + rSt.SeekRel( nSkipBLIPLen ); + rSt >> nBLIPLen; + rSt.SeekRel( nSkipBLIPPos ); + rSt >> nBLIPPos; + bOk = rSt.GetError() == 0; + + nLength -= nSkipBLIPLen+ 4 + nSkipBLIPPos + 4; + } + + if( bOk ) + { + // Besonderheit: + // Falls nBLIPLen kleiner ist als nLenFBSE UND nBLIPPos Null ist, + // nehmen wir an, dass das Bild IM FBSE drin steht! + if( (!nBLIPPos) && (nBLIPLen < nLenFBSE) ) + nBLIPPos = rSt.Tell() + 4; + + // Das hat ja fein geklappt! + // Wir merken uns, dass wir einen FBSE mehr im Pointer Array haben. + nBLIPPos = Calc_nBLIPPos(nBLIPPos, rSt.Tell()); + + if( USHRT_MAX == nBLIPCount ) + nBLIPCount = 1; + else + nBLIPCount++; + + // Jetzt die Infos fuer spaetere Zugriffe speichern + pBLIPInfos->Insert( new SvxMSDffBLIPInfo( nInst, nBLIPPos, nBLIPLen ), + pBLIPInfos->Count() ); + } + } + rSt.SeekRel( nLength ); + } + while( nRead < nLenBStoreCont ); +} + + +// ab hier: Drawing Container d.h. Seiten (Blatt, Dia) - weit gueltige Daten +// ================= ====== +// +void SvxMSDffManager::GetDrawingContainerData( SvStream& rSt, sal_uLong nLenDg, + const unsigned long nDrawingContainerId ) +{ + sal_uInt8 nVer;sal_uInt16 nInst;sal_uInt16 nFbt;sal_uInt32 nLength; + + sal_uLong nReadDg = 0; + + // Wir stehen in einem Drawing Container (je einer pro Seite) + // und muessen nun + // alle enthaltenen Shape Group Container abklappern + do + { + if(!this->ReadCommonRecordHeader( rSt, nVer, nInst, nFbt, nLength)) return; + nReadDg += DFF_COMMON_RECORD_HEADER_SIZE; + // Patriarch gefunden (der oberste Shape Group Container) ? + if( DFF_msofbtSpgrContainer == nFbt ) + { + if(!this->GetShapeGroupContainerData( rSt, nLength, sal_True, nDrawingContainerId )) return; + } + else + // blanker Shape Container ? (ausserhalb vom Shape Group Container) + if( DFF_msofbtSpContainer == nFbt ) + { + if(!this->GetShapeContainerData( rSt, nLength, ULONG_MAX, nDrawingContainerId )) return; + } + else + rSt.SeekRel( nLength ); + nReadDg += nLength; + } + while( nReadDg < nLenDg ); +} + +sal_Bool SvxMSDffManager::GetShapeGroupContainerData( SvStream& rSt, + sal_uLong nLenShapeGroupCont, + sal_Bool bPatriarch, + const unsigned long nDrawingContainerId ) +{ + sal_uInt8 nVer;sal_uInt16 nInst;sal_uInt16 nFbt;sal_uInt32 nLength; + long nStartShapeGroupCont = rSt.Tell(); + // Wir stehen in einem Shape Group Container (ggfs. mehrere pro Seite) + // und muessen nun + // alle enthaltenen Shape Container abklappern + sal_Bool bFirst = !bPatriarch; + sal_uLong nReadSpGrCont = 0; + do + { + if( !this->ReadCommonRecordHeader( rSt, nVer, nInst, nFbt, nLength ) ) + return sal_False; + nReadSpGrCont += DFF_COMMON_RECORD_HEADER_SIZE; + // Shape Container ? + if( DFF_msofbtSpContainer == nFbt ) + { + sal_uLong nGroupOffs = bFirst ? nStartShapeGroupCont - DFF_COMMON_RECORD_HEADER_SIZE : ULONG_MAX; + if ( !this->GetShapeContainerData( rSt, nLength, nGroupOffs, nDrawingContainerId ) ) + return sal_False; + bFirst = sal_False; + } + else + // eingeschachtelter Shape Group Container ? + if( DFF_msofbtSpgrContainer == nFbt ) + { + if ( !this->GetShapeGroupContainerData( rSt, nLength, sal_False, nDrawingContainerId ) ) + return sal_False; + } + else + rSt.SeekRel( nLength ); + nReadSpGrCont += nLength; + } + while( nReadSpGrCont < nLenShapeGroupCont ); + // den Stream wieder korrekt positionieren + rSt.Seek( nStartShapeGroupCont + nLenShapeGroupCont ); + return sal_True; +} + +sal_Bool SvxMSDffManager::GetShapeContainerData( SvStream& rSt, + sal_uLong nLenShapeCont, + sal_uLong nPosGroup, + const unsigned long nDrawingContainerId ) +{ + sal_uInt8 nVer;sal_uInt16 nInst;sal_uInt16 nFbt;sal_uInt32 nLength; + long nStartShapeCont = rSt.Tell(); + // Wir stehen in einem Shape Container (ggfs. mehrere pro Sh. Group) + // und muessen nun + // die Shape Id und File-Pos (fuer spaetere, erneute Zugriffe) + // und den ersten BStore Verweis (falls vorhanden) entnehmen + sal_uLong nLenShapePropTbl = 0; + sal_uLong nReadSpCont = 0; + + // File Offset des Shape-Containers bzw. der Gruppe(!) vermerken + // + sal_uLong nStartOffs = (ULONG_MAX > nPosGroup) ? + nPosGroup : nStartShapeCont - DFF_COMMON_RECORD_HEADER_SIZE; + SvxMSDffShapeInfo aInfo( nStartOffs ); + + // duerfte das Shape durch einen Rahmen ersetzt werden ? + // (vorausgesetzt, es zeigt sich, dass es eine TextBox ist, + // und der Text nicht gedreht ist) + sal_Bool bCanBeReplaced = (ULONG_MAX > nPosGroup) ? sal_False : sal_True; + + // wir wissen noch nicht, ob es eine TextBox ist + MSO_SPT eShapeType = mso_sptNil; + MSO_WrapMode eWrapMode = mso_wrapSquare; +// sal_Bool bIsTextBox = sal_False; + + // Shape analysieren + // + do + { + if(!this->ReadCommonRecordHeader( rSt, nVer, nInst, nFbt, nLength)) return sal_False; + nReadSpCont += DFF_COMMON_RECORD_HEADER_SIZE; + // FSP ? + if( ( DFF_msofbtSp == nFbt ) && ( 4 <= nLength ) ) + { + // Wir haben den FSP gefunden: Shape Typ und Id vermerken! + eShapeType = (MSO_SPT)nInst; + rSt >> aInfo.nShapeId; + rSt.SeekRel( nLength - 4 ); + nReadSpCont += nLength; + } + else if( DFF_msofbtOPT == nFbt ) // Shape Property Table ? + { + // Wir haben die Property Table gefunden: + // nach der Blip Property suchen! + sal_uLong nPropRead = 0; + sal_uInt16 nPropId; + sal_uInt32 nPropVal; + nLenShapePropTbl = nLength; +// sal_uInt32 nPropCount = nInst; + long nStartShapePropTbl = rSt.Tell(); +// sal_uInt32 nComplexDataFilePos = nStartShapePropTbl + (nPropCount * 6); + do + { + rSt >> nPropId + >> nPropVal; + nPropRead += 6; + + switch( nPropId ) + { + case DFF_Prop_txflTextFlow : + //Writer can now handle vertical textflows in its + //native frames, to only need to do this for the + //other two formats + + //Writer will handle all textflow except BtoT + if (GetSvxMSDffSettings() & + (SVXMSDFF_SETTINGS_IMPORT_PPT | + SVXMSDFF_SETTINGS_IMPORT_EXCEL)) + { + if( 0 != nPropVal ) + bCanBeReplaced = false; + } + else if ( + (nPropVal != mso_txflHorzN) && + (nPropVal != mso_txflTtoBA) + ) + { + bCanBeReplaced = false; + } + break; + case DFF_Prop_cdirFont : + //Writer can now handle right to left and left + //to right in its native frames, so only do + //this for the other two formats. + if (GetSvxMSDffSettings() & + (SVXMSDFF_SETTINGS_IMPORT_PPT | + SVXMSDFF_SETTINGS_IMPORT_EXCEL)) + { + if( 0 != nPropVal ) + bCanBeReplaced = sal_False; + } + break; + case DFF_Prop_Rotation : + if( 0 != nPropVal ) + bCanBeReplaced = sal_False; + break; + + case DFF_Prop_gtextFStrikethrough : + if( ( 0x20002000 & nPropVal ) == 0x20002000 ) + bCanBeReplaced = sal_False; + break; + + case DFF_Prop_fc3DLightFace : + if( ( 0x00080008 & nPropVal ) == 0x00080008 ) + bCanBeReplaced = sal_False; + break; + + case DFF_Prop_WrapText : + eWrapMode = (MSO_WrapMode)nPropVal; + break; + + default: + { + // Bit gesetzt und gueltig? + if( 0x4000 == ( nPropId & 0xC000 ) ) + { + // Blip Property gefunden: BStore Idx vermerken! + nPropRead = nLenShapePropTbl; + } + else if( 0x8000 & nPropId ) + { + // komplexe Prop gefunden: + // Laenge ist immer 6, nur die Laenge der nach der + // eigentlichen Prop-Table anhaengenden Extra-Daten + // ist unterschiedlich + nPropVal = 6; + } + } + break; + } + +/* +//JP 21.04.99: Bug 64510 +// alte Version, die unter OS/2 zu Compilerfehlern fuehrt und damit arge +// Performance einbussen hat. + + if( 0x4000 == ( nPropId & 0xC000 ) )// Bit gesetzt und gueltig? + { + // Blip Property gefunden: BStore Idx vermerken! + aInfo.nBStoreIdx = nPropVal; // Index im BStore Container + break; + } + else + if( ( ( (DFF_Prop_txflTextFlow == nPropId) + || (DFF_Prop_Rotation == nPropId) + || (DFF_Prop_cdirFont == nPropId) ) + && (0 != nPropVal) ) + + || ( (DFF_Prop_gtextFStrikethrough == nPropId) + && ( (0x20002000 & nPropVal) == 0x20002000) ) // also DFF_Prop_gtextFVertical + || ( (DFF_Prop_fc3DLightFace == nPropId) + && ( (0x00080008 & nPropVal) == 0x00080008) ) // also DFF_Prop_f3D + ) + { + bCanBeReplaced = sal_False; // Mist: gedrehter Text oder 3D-Objekt! + } + else + if( DFF_Prop_WrapText == nPropId ) + { + eWrapMode = (MSO_WrapMode)nPropVal; + } + //////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////// + // keine weitere Property-Auswertung: folge beim Shape-Import // + //////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////// + else + if( 0x8000 & nPropId ) + { + // komplexe Prop gefunden: Laenge lesen und ueberspringen + if(!SkipBytes( rSt, nPropVal )) return sal_False; + nPropRead += nPropVal; + } +*/ + } + while( nPropRead < nLenShapePropTbl ); + rSt.Seek( nStartShapePropTbl + nLenShapePropTbl ); + nReadSpCont += nLenShapePropTbl; + } + else if( ( DFF_msofbtClientTextbox == nFbt ) && ( 4 == nLength ) ) // Text-Box-Story-Eintrag gefunden + { + rSt >> aInfo.nTxBxComp; + // --> OD 2008-07-28 #156763# + // Add internal drawing container id to text id. + // Note: The text id uses the first two bytes, while the internal + // drawing container id used the second two bytes. + aInfo.nTxBxComp = ( aInfo.nTxBxComp & 0xFFFF0000 ) + + nDrawingContainerId; + DBG_ASSERT( (aInfo.nTxBxComp & 0x0000FFFF) == nDrawingContainerId, + "<SvxMSDffManager::GetShapeContainerData(..)> - internal drawing container Id could not be correctly merged into DFF_msofbtClientTextbox value." ); + // <-- + } + else + { + rSt.SeekRel( nLength ); + nReadSpCont += nLength; + } + } + while( nReadSpCont < nLenShapeCont ); + + // + // Jetzt ggfs. die Infos fuer spaetere Zugriffe auf das Shape speichern + // + if( aInfo.nShapeId ) + { + // fuer Textboxen ggfs. ersetzen durch Rahmen erlauben + if( bCanBeReplaced + && aInfo.nTxBxComp + && ( + ( eShapeType == mso_sptTextSimple ) + || ( eShapeType == mso_sptTextBox ) + || ( ( ( eShapeType == mso_sptRectangle ) + || ( eShapeType == mso_sptRoundRectangle ) + ) + ) ) ) + { + aInfo.bReplaceByFly = sal_True; + } + pShapeInfos->Insert( new SvxMSDffShapeInfo( aInfo ) ); + pShapeOrders->Insert( new SvxMSDffShapeOrder( aInfo.nShapeId ), + pShapeOrders->Count() ); + } + + // und den Stream wieder korrekt positionieren + rSt.Seek( nStartShapeCont + nLenShapeCont ); + return sal_True; +} + + + +/***************************************************************************** + + Zugriff auf ein Shape zur Laufzeit (ueber die Shape-Id) + ---------------------------------- +******************************************************************************/ +sal_Bool SvxMSDffManager::GetShape(sal_uLong nId, SdrObject*& rpShape, + SvxMSDffImportData& rData) +{ + SvxMSDffShapeInfo aTmpRec(0, nId); + aTmpRec.bSortByShapeId = sal_True; + + sal_uInt16 nFound; + if( pShapeInfos->Seek_Entry(&aTmpRec, &nFound) ) + { + SvxMSDffShapeInfo& rInfo = *pShapeInfos->GetObject( nFound ); + + // eventuell altes Errorflag loeschen + if( rStCtrl.GetError() ) + rStCtrl.ResetError(); + // FilePos des/der Stream(s) merken + sal_uLong nOldPosCtrl = rStCtrl.Tell(); + sal_uLong nOldPosData = pStData ? pStData->Tell() : nOldPosCtrl; + // das Shape im Steuer Stream anspringen + rStCtrl.Seek( rInfo.nFilePos ); + + // Falls missglueckt, den Fehlerstatus zuruecksetzen und Pech gehabt! + if( rStCtrl.GetError() ) + rStCtrl.ResetError(); + else + rpShape = ImportObj( rStCtrl, &rData, rData.aParentRect, rData.aParentRect ); + + // alte FilePos des/der Stream(s) restaurieren + rStCtrl.Seek( nOldPosCtrl ); + if( &rStCtrl != pStData ) + pStData->Seek( nOldPosData ); + return ( 0 != rpShape ); + } + return sal_False; +} + + + +/* Zugriff auf ein BLIP zur Laufzeit (bei bereits bekannter Blip-Nr) + --------------------------------- +******************************************************************************/ +sal_Bool SvxMSDffManager::GetBLIP( sal_uLong nIdx_, Graphic& rData, Rectangle* pVisArea ) const +{ + sal_Bool bOk = sal_False; // Ergebnisvariable initialisieren + if ( pStData ) + { + // check if a graphic for this blipId is already imported + if ( nIdx_ && pEscherBlipCache ) + { + EscherBlipCacheEntry* pEntry; + for ( pEntry = (EscherBlipCacheEntry*)pEscherBlipCache->First(); pEntry; + pEntry = (EscherBlipCacheEntry*)pEscherBlipCache->Next() ) + { + if ( pEntry->nBlip == nIdx_ ) + { /* if this entry is available, then it should be possible + to get the Graphic via GraphicObject */ + GraphicObject aGraphicObject( pEntry->aUniqueID ); + rData = aGraphicObject.GetGraphic(); + if ( rData.GetType() != GRAPHIC_NONE ) + bOk = sal_True; + else + delete (EscherBlipCacheEntry*)pEscherBlipCache->Remove(); + break; + } + } + } + if ( !bOk ) + { + sal_uInt16 nIdx = sal_uInt16( nIdx_ ); + if( !nIdx || (pBLIPInfos->Count() < nIdx) ) return sal_False; + + // eventuell alte(s) Errorflag(s) loeschen + if( rStCtrl.GetError() ) + rStCtrl.ResetError(); + if( ( &rStCtrl != pStData ) + && pStData->GetError() ) + pStData->ResetError(); + + // FilePos des/der Stream(s) merken + sal_uLong nOldPosCtrl = rStCtrl.Tell(); + sal_uLong nOldPosData = pStData ? pStData->Tell() : nOldPosCtrl; + + // passende Info-Struct aus unserem Pointer Array nehmen + SvxMSDffBLIPInfo& rInfo = *(*pBLIPInfos)[ nIdx-1 ]; + + // das BLIP Atom im Daten Stream anspringen + pStData->Seek( rInfo.nFilePos ); + // ggfs. Fehlerstatus zuruecksetzen + if( pStData->GetError() ) + pStData->ResetError(); + else + bOk = GetBLIPDirect( *pStData, rData, pVisArea ); + if( pStData2 && !bOk ) + { + // Fehler, aber zweite Chance: es gibt noch einen zweiten + // Datenstream, in dem die Grafik liegen koennte! + if( pStData2->GetError() ) + pStData2->ResetError(); + sal_uLong nOldPosData2 = pStData2->Tell(); + // das BLIP Atom im zweiten Daten Stream anspringen + pStData2->Seek( rInfo.nFilePos ); + // ggfs. Fehlerstatus zuruecksetzen + if( pStData2->GetError() ) + pStData2->ResetError(); + else + bOk = GetBLIPDirect( *pStData2, rData, pVisArea ); + // alte FilePos des zweiten Daten-Stream restaurieren + pStData2->Seek( nOldPosData2 ); + } + // alte FilePos des/der Stream(s) restaurieren + rStCtrl.Seek( nOldPosCtrl ); + if( &rStCtrl != pStData ) + pStData->Seek( nOldPosData ); + + if ( bOk ) + { + // create new BlipCacheEntry for this graphic + GraphicObject aGraphicObject( rData ); + if ( !pEscherBlipCache ) + const_cast <SvxMSDffManager*> (this)->pEscherBlipCache = new List(); + EscherBlipCacheEntry* pNewEntry = new EscherBlipCacheEntry( nIdx_, aGraphicObject.GetUniqueID() ); + pEscherBlipCache->Insert( pNewEntry, LIST_APPEND ); + } + } + } + return bOk; +} + +/* Zugriff auf ein BLIP zur Laufzeit (mit korrekt positioniertem Stream) + --------------------------------- +******************************************************************************/ +sal_Bool SvxMSDffManager::GetBLIPDirect( SvStream& rBLIPStream, Graphic& rData, Rectangle* pVisArea ) const +{ + sal_uLong nOldPos = rBLIPStream.Tell(); + + int nRes = GRFILTER_OPENERROR; // Fehlervariable initialisieren + + // nachschauen, ob es sich auch wirklich um ein BLIP handelt + sal_uInt32 nLength; + sal_uInt16 nInst, nFbt( 0 ); + sal_uInt8 nVer; + if( ReadCommonRecordHeader( rBLIPStream, nVer, nInst, nFbt, nLength) && ( 0xF018 <= nFbt ) && ( 0xF117 >= nFbt ) ) + { + Size aMtfSize100; + sal_Bool bMtfBLIP = sal_False; + sal_Bool bZCodecCompression = sal_False; + // Nun exakt auf den Beginn der eingebetteten Grafik positionieren + sal_uLong nSkip = ( nInst & 0x0001 ) ? 32 : 16; + + switch( nInst & 0xFFFE ) + { + case 0x216 : // Metafile header then compressed WMF + case 0x3D4 : // Metafile header then compressed EMF + case 0x542 : // Metafile hd. then compressed PICT + { + rBLIPStream.SeekRel( nSkip + 20 ); + + // read in size of metafile in EMUS + rBLIPStream >> aMtfSize100.Width() >> aMtfSize100.Height(); + + // scale to 1/100mm + aMtfSize100.Width() /= 360, aMtfSize100.Height() /= 360; + + if ( pVisArea ) // seem that we currently are skipping the visarea position + *pVisArea = Rectangle( Point(), aMtfSize100 ); + + // skip rest of header + nSkip = 6; + bMtfBLIP = bZCodecCompression = sal_True; + } + break; + case 0x46A : // One byte tag then JPEG (= JFIF) data + case 0x6E0 : // One byte tag then PNG data + case 0x7A8 : + nSkip += 1; // One byte tag then DIB data + break; + } + rBLIPStream.SeekRel( nSkip ); + + SvStream* pGrStream = &rBLIPStream; + SvMemoryStream* pOut = NULL; + if( bZCodecCompression ) + { + pOut = new SvMemoryStream( 0x8000, 0x4000 ); + ZCodec aZCodec( 0x8000, 0x8000 ); + aZCodec.BeginCompression(); + aZCodec.Decompress( rBLIPStream, *pOut ); + aZCodec.EndCompression(); + pOut->Seek( STREAM_SEEK_TO_BEGIN ); + pOut->SetResizeOffset( 0 ); // sj: #i102257# setting ResizeOffset of 0 prevents from seeking + // behind the stream end (allocating too much memory) + pGrStream = pOut; + } + +//#define DBG_EXTRACTGRAPHICS +#ifdef DBG_EXTRACTGRAPHICS + + static sal_Int32 nCount; + + String aFileName( String( RTL_CONSTASCII_STRINGPARAM( "dbggfx" ) ) ); + aFileName.Append( String::CreateFromInt32( nCount++ ) ); + switch( nInst &~ 1 ) + { + case 0x216 : aFileName.Append( String( RTL_CONSTASCII_STRINGPARAM( ".wmf" ) ) ); break; + case 0x3d4 : aFileName.Append( String( RTL_CONSTASCII_STRINGPARAM( ".emf" ) ) ); break; + case 0x542 : aFileName.Append( String( RTL_CONSTASCII_STRINGPARAM( ".pct" ) ) ); break; + case 0x46a : aFileName.Append( String( RTL_CONSTASCII_STRINGPARAM( ".jpg" ) ) ); break; + case 0x6e0 : aFileName.Append( String( RTL_CONSTASCII_STRINGPARAM( ".png" ) ) ); break; + case 0x7a8 : aFileName.Append( String( RTL_CONSTASCII_STRINGPARAM( ".bmp" ) ) ); break; + } + + String aURLStr; + + if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( Application::GetAppFileName(), aURLStr ) ) + { + INetURLObject aURL( aURLStr ); + + aURL.removeSegment(); + aURL.removeFinalSlash(); + aURL.Append( aFileName ); + + SvStream* pDbgOut = ::utl::UcbStreamHelper::CreateStream( aURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_TRUNC | STREAM_WRITE ); + + if( pDbgOut ) + { + if ( bZCodecCompression ) + { + pOut->Seek( STREAM_SEEK_TO_END ); + pDbgOut->Write( pOut->GetData(), pOut->Tell() ); + pOut->Seek( STREAM_SEEK_TO_BEGIN ); + } + else + { + sal_Int32 nDbgLen = nLength - nSkip; + if ( nDbgLen ) + { + sal_Char* pDat = new sal_Char[ nDbgLen ]; + pGrStream->Read( pDat, nDbgLen ); + pDbgOut->Write( pDat, nDbgLen ); + pGrStream->SeekRel( -nDbgLen ); + delete[] pDat; + } + } + + delete pDbgOut; + } + } +#endif + + if( ( nInst & 0xFFFE ) == 0x7A8 ) + { // DIBs direkt holen + Bitmap aNew; + if( aNew.Read( *pGrStream, sal_False ) ) + { + rData = Graphic( aNew ); + nRes = GRFILTER_OK; + } + } + else + { // und unsere feinen Filter darauf loslassen + GraphicFilter* pGF = GraphicFilter::GetGraphicFilter(); + String aEmptyStr; + nRes = pGF->ImportGraphic( rData, aEmptyStr, *pGrStream, GRFILTER_FORMAT_DONTKNOW ); + + // SJ: I40472, sometimes the aspect ratio (aMtfSize100) does not match and we get scaling problems, + // then it is better to use the prefsize that is stored within the metafile. Bug #72846# for what the + // scaling has been implemented does not happen anymore. + // + // For pict graphics we will furthermore scale the metafile, because font scaling leads to error if the + // dxarray is empty (this has been solved in wmf/emf but not for pict) + if( bMtfBLIP && ( GRFILTER_OK == nRes ) && ( rData.GetType() == GRAPHIC_GDIMETAFILE ) && ( ( nInst & 0xFFFE ) == 0x542 ) ) + { + if ( ( aMtfSize100.Width() >= 1000 ) && ( aMtfSize100.Height() >= 1000 ) ) + { // #75956#, scaling does not work properly, if the graphic is less than 1cm + GDIMetaFile aMtf( rData.GetGDIMetaFile() ); + const Size aOldSize( aMtf.GetPrefSize() ); + + if( aOldSize.Width() && ( aOldSize.Width() != aMtfSize100.Width() ) && + aOldSize.Height() && ( aOldSize.Height() != aMtfSize100.Height() ) ) + { + aMtf.Scale( (double) aMtfSize100.Width() / aOldSize.Width(), + (double) aMtfSize100.Height() / aOldSize.Height() ); + aMtf.SetPrefSize( aMtfSize100 ); + aMtf.SetPrefMapMode( MAP_100TH_MM ); + rData = aMtf; + } + } + } + } + // ggfs. Fehlerstatus zuruecksetzen + if ( ERRCODE_IO_PENDING == pGrStream->GetError() ) + pGrStream->ResetError(); + delete pOut; + } + rBLIPStream.Seek( nOldPos ); // alte FilePos des Streams restaurieren + + return ( GRFILTER_OK == nRes ); // Ergebniss melden +} + +/* static */ +sal_Bool SvxMSDffManager::ReadCommonRecordHeader(DffRecordHeader& rRec, SvStream& rIn) +{ + rRec.nFilePos = rIn.Tell(); + return SvxMSDffManager::ReadCommonRecordHeader( rIn,rRec.nRecVer, + rRec.nRecInstance, + rRec.nRecType, + rRec.nRecLen ); +} + + +/* auch static */ +sal_Bool SvxMSDffManager::ReadCommonRecordHeader( SvStream& rSt, + sal_uInt8& rVer, + sal_uInt16& rInst, + sal_uInt16& rFbt, + sal_uInt32& rLength ) +{ + sal_uInt16 nTmp; + rSt >> nTmp >> rFbt >> rLength; + rVer = sal::static_int_cast< sal_uInt8 >(nTmp & 15); + rInst = nTmp >> 4; + return rSt.GetError() == 0; +} + + + + +sal_Bool SvxMSDffManager::ProcessClientAnchor(SvStream& rStData, sal_uLong nDatLen, + char*& rpBuff, sal_uInt32& rBuffLen ) const +{ + if( nDatLen ) + { + rpBuff = new char[ nDatLen ]; + rBuffLen = nDatLen; + rStData.Read( rpBuff, nDatLen ); + } + return sal_True; +} + +sal_Bool SvxMSDffManager::ProcessClientData(SvStream& rStData, sal_uLong nDatLen, + char*& rpBuff, sal_uInt32& rBuffLen ) const +{ + if( nDatLen ) + { + rpBuff = new char[ nDatLen ]; + rBuffLen = nDatLen; + rStData.Read( rpBuff, nDatLen ); + } + return sal_True; +} + + +void SvxMSDffManager::ProcessClientAnchor2( SvStream& /* rSt */, DffRecordHeader& /* rHd */ , void* /* pData */, DffObjData& /* rObj */ ) +{ + return; // wird von SJ im Draw ueberladen +} + +sal_uLong SvxMSDffManager::Calc_nBLIPPos( sal_uLong nOrgVal, sal_uLong /* nStreamPos */ ) const +{ + return nOrgVal; +} + +sal_Bool SvxMSDffManager::GetOLEStorageName( long /* nOLEId */, String&, SvStorageRef&, uno::Reference < embed::XStorage >& ) const +{ + return sal_False; +} + +sal_Bool SvxMSDffManager::ShapeHasText( sal_uLong /* nShapeId */, sal_uLong /* nFilePos */ ) const +{ + return sal_True; +} + +// --> OD 2004-12-14 #i32596# - add new parameter <_nCalledByGroup> +SdrObject* SvxMSDffManager::ImportOLE( long nOLEId, + const Graphic& rGrf, + const Rectangle& rBoundRect, + const Rectangle& rVisArea, + const int /* _nCalledByGroup */, + sal_Int64 nAspect ) const +// <-- +{ + SdrObject* pRet = 0; + String sStorageName; + SvStorageRef xSrcStg; + ErrCode nError = ERRCODE_NONE; + uno::Reference < embed::XStorage > xDstStg; + if( GetOLEStorageName( nOLEId, sStorageName, xSrcStg, xDstStg )) + pRet = CreateSdrOLEFromStorage( sStorageName, xSrcStg, xDstStg, + rGrf, rBoundRect, rVisArea, pStData, nError, + nSvxMSDffOLEConvFlags, nAspect ); + return pRet; +} + +const GDIMetaFile* SvxMSDffManager::lcl_GetMetaFileFromGrf_Impl( const Graphic& rGrf, + GDIMetaFile& rMtf ) +{ + const GDIMetaFile* pMtf; + if( GRAPHIC_BITMAP == rGrf.GetType() ) + { + Point aPt; + const Size aSz(lcl_GetPrefSize(rGrf, MAP_100TH_MM)); + + VirtualDevice aVirtDev; + aVirtDev.EnableOutput( sal_False ); + MapMode aMM(MAP_100TH_MM); + aVirtDev.SetMapMode( aMM ); + + rMtf.Record( &aVirtDev ); + rGrf.Draw( &aVirtDev, aPt, aSz ); + rMtf.Stop(); + rMtf.SetPrefMapMode(aMM); + rMtf.SetPrefSize( aSz ); + + pMtf = &rMtf; + } + else + pMtf = &rGrf.GetGDIMetaFile(); + return pMtf; +} + +sal_Bool SvxMSDffManager::MakeContentStream( SotStorage * pStor, const GDIMetaFile & rMtf ) +{ + String aPersistStream( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( SVEXT_PERSIST_STREAM ) ) ); + SotStorageStreamRef xStm = pStor->OpenSotStream( aPersistStream ); + xStm->SetVersion( pStor->GetVersion() ); + xStm->SetBufferSize( 8192 ); + + sal_uInt16 nAspect = ASPECT_CONTENT; + sal_uLong nAdviseModes = 2; + + Impl_OlePres aEle( FORMAT_GDIMETAFILE ); + // Die Groesse in 1/100 mm umrechnen + // Falls eine nicht anwendbare MapUnit (Device abhaengig) verwendet wird, + // versucht SV einen BestMatchden richtigen Wert zu raten. + Size aSize = rMtf.GetPrefSize(); + MapMode aMMSrc = rMtf.GetPrefMapMode(); + MapMode aMMDst( MAP_100TH_MM ); + aSize = OutputDevice::LogicToLogic( aSize, aMMSrc, aMMDst ); + aEle.SetSize( aSize ); + aEle.SetAspect( nAspect ); + aEle.SetAdviseFlags( nAdviseModes ); + aEle.SetMtf( rMtf ); + aEle.Write( *xStm ); + + xStm->SetBufferSize( 0 ); + return xStm->GetError() == SVSTREAM_OK; +} + +struct ClsIDs { + sal_uInt32 nId; + const sal_Char* pSvrName; + const sal_Char* pDspName; +}; +static ClsIDs aClsIDs[] = { + + { 0x000212F0, "MSWordArt", "Microsoft Word Art" }, + { 0x000212F0, "MSWordArt.2", "Microsoft Word Art 2.0" }, + + // MS Apps + { 0x00030000, "ExcelWorksheet", "Microsoft Excel Worksheet" }, + { 0x00030001, "ExcelChart", "Microsoft Excel Chart" }, + { 0x00030002, "ExcelMacrosheet", "Microsoft Excel Macro" }, + { 0x00030003, "WordDocument", "Microsoft Word Document" }, + { 0x00030004, "MSPowerPoint", "Microsoft PowerPoint" }, + { 0x00030005, "MSPowerPointSho", "Microsoft PowerPoint Slide Show"}, + { 0x00030006, "MSGraph", "Microsoft Graph" }, + { 0x00030007, "MSDraw", "Microsoft Draw" }, + { 0x00030008, "Note-It", "Microsoft Note-It" }, + { 0x00030009, "WordArt", "Microsoft Word Art" }, + { 0x0003000a, "PBrush", "Microsoft PaintBrush Picture" }, + { 0x0003000b, "Equation", "Microsoft Equation Editor" }, + { 0x0003000c, "Package", "Package" }, + { 0x0003000d, "SoundRec", "Sound" }, + { 0x0003000e, "MPlayer", "Media Player" }, + // MS Demos + { 0x0003000f, "ServerDemo", "OLE 1.0 Server Demo" }, + { 0x00030010, "Srtest", "OLE 1.0 Test Demo" }, + { 0x00030011, "SrtInv", "OLE 1.0 Inv Demo" }, + { 0x00030012, "OleDemo", "OLE 1.0 Demo" }, + + // Coromandel / Dorai Swamy / 718-793-7963 + { 0x00030013, "CoromandelIntegra", "Coromandel Integra" }, + { 0x00030014, "CoromandelObjServer","Coromandel Object Server" }, + + // 3-d Visions Corp / Peter Hirsch / 310-325-1339 + { 0x00030015, "StanfordGraphics", "Stanford Graphics" }, + + // Deltapoint / Nigel Hearne / 408-648-4000 + { 0x00030016, "DGraphCHART", "DeltaPoint Graph Chart" }, + { 0x00030017, "DGraphDATA", "DeltaPoint Graph Data" }, + + // Corel / Richard V. Woodend / 613-728-8200 x1153 + { 0x00030018, "PhotoPaint", "Corel PhotoPaint" }, + { 0x00030019, "CShow", "Corel Show" }, + { 0x0003001a, "CorelChart", "Corel Chart" }, + { 0x0003001b, "CDraw", "Corel Draw" }, + + // Inset Systems / Mark Skiba / 203-740-2400 + { 0x0003001c, "HJWIN1.0", "Inset Systems" }, + + // Mark V Systems / Mark McGraw / 818-995-7671 + { 0x0003001d, "ObjMakerOLE", "MarkV Systems Object Maker" }, + + // IdentiTech / Mike Gilger / 407-951-9503 + { 0x0003001e, "FYI", "IdentiTech FYI" }, + { 0x0003001f, "FYIView", "IdentiTech FYI Viewer" }, + + // Inventa Corporation / Balaji Varadarajan / 408-987-0220 + { 0x00030020, "Stickynote", "Inventa Sticky Note" }, + + // ShapeWare Corp. / Lori Pearce / 206-467-6723 + { 0x00030021, "ShapewareVISIO10", "Shapeware Visio 1.0" }, + { 0x00030022, "ImportServer", "Spaheware Import Server" }, + + // test app SrTest + { 0x00030023, "SrvrTest", "OLE 1.0 Server Test" }, + + // test app ClTest. Doesn't really work as a server but is in reg db + { 0x00030025, "Cltest", "OLE 1.0 Client Test" }, + + // Microsoft ClipArt Gallery Sherry Larsen-Holmes + { 0x00030026, "MS_ClipArt_Gallery", "Microsoft ClipArt Gallery" }, + // Microsoft Project Cory Reina + { 0x00030027, "MSProject", "Microsoft Project" }, + + // Microsoft Works Chart + { 0x00030028, "MSWorksChart", "Microsoft Works Chart" }, + + // Microsoft Works Spreadsheet + { 0x00030029, "MSWorksSpreadsheet", "Microsoft Works Spreadsheet" }, + + // AFX apps - Dean McCrory + { 0x0003002A, "MinSvr", "AFX Mini Server" }, + { 0x0003002B, "HierarchyList", "AFX Hierarchy List" }, + { 0x0003002C, "BibRef", "AFX BibRef" }, + { 0x0003002D, "MinSvrMI", "AFX Mini Server MI" }, + { 0x0003002E, "TestServ", "AFX Test Server" }, + + // Ami Pro + { 0x0003002F, "AmiProDocument", "Ami Pro Document" }, + + // WordPerfect Presentations For Windows + { 0x00030030, "WPGraphics", "WordPerfect Presentation" }, + { 0x00030031, "WPCharts", "WordPerfect Chart" }, + + // MicroGrafx Charisma + { 0x00030032, "Charisma", "MicroGrafx Charisma" }, + { 0x00030033, "Charisma_30", "MicroGrafx Charisma 3.0" }, + { 0x00030034, "CharPres_30", "MicroGrafx Charisma 3.0 Pres" }, + // MicroGrafx Draw + { 0x00030035, "Draw", "MicroGrafx Draw" }, + // MicroGrafx Designer + { 0x00030036, "Designer_40", "MicroGrafx Designer 4.0" }, + + // STAR DIVISION +// { 0x000424CA, "StarMath", "StarMath 1.0" }, + { 0x00043AD2, "FontWork", "Star FontWork" }, +// { 0x000456EE, "StarMath2", "StarMath 2.0" }, + + { 0, "", "" } }; + + +sal_Bool SvxMSDffManager::ConvertToOle2( SvStream& rStm, sal_uInt32 nReadLen, + const GDIMetaFile * pMtf, const SotStorageRef& rDest ) +{ + sal_Bool bMtfRead = sal_False; + SotStorageStreamRef xOle10Stm = rDest->OpenSotStream( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "\1Ole10Native" ) ), + STREAM_WRITE| STREAM_SHARE_DENYALL ); + if( xOle10Stm->GetError() ) + return sal_False; + + sal_uInt32 nType; + sal_uInt32 nRecType; + sal_uInt32 nStrLen; + String aSvrName; + sal_uInt32 nDummy0; + sal_uInt32 nDummy1; + sal_uInt32 nDataLen; + sal_uInt8 * pData; + sal_uInt32 nBytesRead = 0; + do + { + rStm >> nType; + rStm >> nRecType; + rStm >> nStrLen; + if( nStrLen ) + { + if( 0x10000L > nStrLen ) + { + sal_Char * pBuf = new sal_Char[ nStrLen ]; + rStm.Read( pBuf, nStrLen ); + aSvrName.Assign( String( pBuf, (sal_uInt16) nStrLen-1, gsl_getSystemTextEncoding() ) ); + delete[] pBuf; + } + else + break; + } + rStm >> nDummy0; + rStm >> nDummy1; + rStm >> nDataLen; + + nBytesRead += 6 * sizeof( sal_uInt32 ) + nStrLen + nDataLen; + + if( !rStm.IsEof() && nReadLen > nBytesRead && nDataLen ) + { + if( xOle10Stm.Is() ) + { + pData = new sal_uInt8[ nDataLen ]; + if( !pData ) + return sal_False; + + rStm.Read( pData, nDataLen ); + + // write to ole10 stream + *xOle10Stm << nDataLen; + xOle10Stm->Write( pData, nDataLen ); + xOle10Stm = SotStorageStreamRef(); + + // set the compobj stream + ClsIDs* pIds; + for( pIds = aClsIDs; pIds->nId; pIds++ ) + { + if( COMPARE_EQUAL == aSvrName.CompareToAscii( pIds->pSvrName ) ) + break; + } +// SvGlobalName* pClsId = NULL; + String aShort, aFull; + if( pIds->nId ) + { + // gefunden! + sal_uLong nCbFmt = SotExchange::RegisterFormatName( aSvrName ); + rDest->SetClass( SvGlobalName( pIds->nId, 0, 0, 0xc0,0,0,0,0,0,0,0x46 ), nCbFmt, + String( pIds->pDspName, RTL_TEXTENCODING_ASCII_US ) ); + } + else + { + sal_uLong nCbFmt = SotExchange::RegisterFormatName( aSvrName ); + rDest->SetClass( SvGlobalName(), nCbFmt, aSvrName ); + } + + delete[] pData; + } + else if( nRecType == 5 && !pMtf ) + { + sal_uLong nPos = rStm.Tell(); + sal_uInt16 sz[4]; + rStm.Read( sz, 8 ); + //rStm.SeekRel( 8 ); + Graphic aGraphic; + if( ERRCODE_NONE == GraphicConverter::Import( rStm, aGraphic ) && aGraphic.GetType() ) + { + const GDIMetaFile& rMtf = aGraphic.GetGDIMetaFile(); + MakeContentStream( rDest, rMtf ); + bMtfRead = sal_True; + } + // set behind the data + rStm.Seek( nPos + nDataLen ); + } + else + rStm.SeekRel( nDataLen ); + } + } while( !rStm.IsEof() && nReadLen >= nBytesRead ); + + if( !bMtfRead && pMtf ) + { + MakeContentStream( rDest, *pMtf ); + return sal_True; + } + + return sal_False; +} + +const char* GetInternalServerName_Impl( const SvGlobalName& aGlobName ) +{ + if ( aGlobName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_60 ) + || aGlobName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 ) ) + return "swriter"; + else if ( aGlobName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_60 ) + || aGlobName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 ) ) + return "scalc"; + else if ( aGlobName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_60 ) + || aGlobName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 ) ) + return "simpress"; + else if ( aGlobName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_60 ) + || aGlobName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 ) ) + return "sdraw"; + else if ( aGlobName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_60 ) + || aGlobName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 ) ) + return "smath"; + else if ( aGlobName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_60 ) + || aGlobName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 ) ) + return "schart"; + return 0; +} + +::rtl::OUString GetFilterNameFromClassID_Impl( const SvGlobalName& aGlobName ) +{ + if ( aGlobName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_60 ) ) + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StarOffice XML (Writer)" ) ); + + if ( aGlobName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 ) ) + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "writer8" ) ); + + if ( aGlobName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_60 ) ) + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StarOffice XML (Calc)" ) ); + + if ( aGlobName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 ) ) + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "calc8" ) ); + + if ( aGlobName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_60 ) ) + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StarOffice XML (Impress)" ) ); + + if ( aGlobName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 ) ) + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "impress8" ) ); + + if ( aGlobName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_60 ) ) + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StarOffice XML (Draw)" ) ); + + if ( aGlobName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 ) ) + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "draw8" ) ); + + if ( aGlobName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_60 ) ) + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StarOffice XML (Math)" ) ); + + if ( aGlobName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 ) ) + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "math8" ) ); + + if ( aGlobName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_60 ) ) + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StarOffice XML (Chart)" ) ); + + if ( aGlobName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 ) ) + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "chart8" ) ); + + return ::rtl::OUString(); +} + +com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject > SvxMSDffManager::CheckForConvertToSOObj( sal_uInt32 nConvertFlags, + SotStorage& rSrcStg, const uno::Reference < embed::XStorage >& rDestStorage, + const Graphic& rGrf, + const Rectangle& rVisArea ) +{ + uno::Reference < embed::XEmbeddedObject > xObj; + SvGlobalName aStgNm = rSrcStg.GetClassName(); + const char* pName = GetInternalServerName_Impl( aStgNm ); + String sStarName; + if ( pName ) + sStarName = String::CreateFromAscii( pName ); + else if ( nConvertFlags ) + { + static struct _ObjImpType + { + sal_uInt32 nFlag; + const char* pFactoryNm; + // GlobalNameId + sal_uInt32 n1; + sal_uInt16 n2, n3; + sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15; + } aArr[] = { + { OLE_MATHTYPE_2_STARMATH, "smath", + 0x0002ce02L, 0x0000, 0x0000, + 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 }, + { OLE_MATHTYPE_2_STARMATH, "smath", + 0x00021700L, 0x0000, 0x0000, + 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 }, + { OLE_WINWORD_2_STARWRITER, "swriter", + 0x00020906L, 0x0000, 0x0000, + 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 }, + { OLE_EXCEL_2_STARCALC, "scalc", // Excel table + 0x00020810L, 0x0000, 0x0000, + 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 }, + { OLE_EXCEL_2_STARCALC, "scalc", // Excel chart + 0x00020820L, 0x0000, 0x0000, + 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 }, + // 114465: additional Excel OLE chart classId to above. + { OLE_EXCEL_2_STARCALC, "scalc", + 0x00020821L, 0x0000, 0x0000, + 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 }, + { OLE_POWERPOINT_2_STARIMPRESS, "simpress", // PowerPoint presentation + 0x64818d10L, 0x4f9b, 0x11cf, + 0x86,0xea,0x00,0xaa,0x00,0xb9,0x29,0xe8 }, + { OLE_POWERPOINT_2_STARIMPRESS, "simpress", // PowerPoint slide + 0x64818d11L, 0x4f9b, 0x11cf, + 0x86,0xea,0x00,0xaa,0x00,0xb9,0x29,0xe8 }, + { 0, 0, + 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 } + }; + + for( const _ObjImpType* pArr = aArr; pArr->nFlag; ++pArr ) + { + if( nConvertFlags & pArr->nFlag ) + { + SvGlobalName aTypeName( pArr->n1, pArr->n2, pArr->n3, + pArr->b8, pArr->b9, pArr->b10, pArr->b11, + pArr->b12, pArr->b13, pArr->b14, pArr->b15 ); + + if ( aStgNm == aTypeName ) + { + sStarName = String::CreateFromAscii( pArr->pFactoryNm ); + break; + } + } + } + } + + if ( sStarName.Len() ) + { + //TODO/MBA: check if (and when) storage and stream will be destroyed! + const SfxFilter* pFilter = 0; + SvMemoryStream* pStream = new SvMemoryStream; + if ( pName ) + { + // TODO/LATER: perhaps we need to retrieve VisArea and Metafile from the storage also + SotStorageStreamRef xStr = rSrcStg.OpenSotStream( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "package_stream" ) ), STREAM_STD_READ ); + *xStr >> *pStream; + } + else + { + SfxFilterMatcher aMatch( sStarName ); + SotStorageRef xStorage = new SotStorage( sal_False, *pStream ); + rSrcStg.CopyTo( xStorage ); + xStorage->Commit(); + xStorage.Clear(); + String aType = SfxFilter::GetTypeFromStorage( rSrcStg ); + if ( aType.Len() ) + pFilter = aMatch.GetFilter4EA( aType ); + } + + if ( pName || pFilter ) + { + //Reuse current ole name + String aDstStgName(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(MSO_OLE_Obj))); + aDstStgName += String::CreateFromInt32(nMSOleObjCntr); + + ::rtl::OUString aFilterName; + if ( pFilter ) + aFilterName = pFilter->GetName(); + else + aFilterName = GetFilterNameFromClassID_Impl( aStgNm ); + + uno::Sequence < beans::PropertyValue > aMedium( aFilterName.getLength() ? 3 : 2); + aMedium[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "InputStream" ) ); + uno::Reference < io::XInputStream > xStream = new ::utl::OSeekableInputStreamWrapper( *pStream ); + aMedium[0].Value <<= xStream; + aMedium[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ); + aMedium[1].Value <<= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:stream" ) ); + + if ( aFilterName.getLength() ) + { + aMedium[2].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" ) ); + aMedium[2].Value <<= aFilterName; + } + + ::rtl::OUString aName( aDstStgName ); + comphelper::EmbeddedObjectContainer aCnt( rDestStorage ); + xObj = aCnt.InsertEmbeddedObject( aMedium, aName ); + + if ( !xObj.is() ) + { + if( aFilterName.getLength() ) + { + // throw the filter parameter away as workaround + aMedium.realloc( 2 ); + xObj = aCnt.InsertEmbeddedObject( aMedium, aName ); + } + + if ( !xObj.is() ) + return xObj; + } + + // TODO/LATER: ViewAspect must be passed from outside! + sal_Int64 nViewAspect = embed::Aspects::MSOLE_CONTENT; + + // JP 26.10.2001: Bug 93374 / 91928 the writer + // objects need the correct visarea needs the + // correct visarea, but this is not true for + // PowerPoint (see bugdoc 94908b) + // SJ: 19.11.2001 bug 94908, also chart objects + // needs the correct visarea + + // If pName is set this is an own embedded object, it should have the correct size internally + // TODO/LATER: it might make sence in future to set the size stored in internal object + if( !pName && ( sStarName.EqualsAscii( "swriter" ) || sStarName.EqualsAscii( "scalc" ) ) ) + { + MapMode aMapMode( VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nViewAspect ) ) ); + Size aSz; + if ( rVisArea.IsEmpty() ) + aSz = lcl_GetPrefSize(rGrf, aMapMode ); + else + { + aSz = rVisArea.GetSize(); + aSz = OutputDevice::LogicToLogic( aSz, MapMode( MAP_100TH_MM ), aMapMode ); + } + + // don't modify the object + //TODO/LATER: remove those hacks, that needs to be done differently! + //xIPObj->EnableSetModified( sal_False ); + awt::Size aSize; + aSize.Width = aSz.Width(); + aSize.Height = aSz.Height(); + xObj->setVisualAreaSize( nViewAspect, aSize ); + //xIPObj->EnableSetModified( sal_True ); + } + else if ( sStarName.EqualsAscii( "smath" ) ) + { // SJ: force the object to recalc its visarea + //TODO/LATER: wait for PrinterChangeNotification + //xIPObj->OnDocumentPrinterChanged( NULL ); + } + } + } + + return xObj; +} + +// TODO/MBA: code review and testing! +SdrOle2Obj* SvxMSDffManager::CreateSdrOLEFromStorage( + const String& rStorageName, + SotStorageRef& rSrcStorage, + const uno::Reference < embed::XStorage >& xDestStorage, + const Graphic& rGrf, + const Rectangle& rBoundRect, + const Rectangle& rVisArea, + SvStream* pDataStrm, + ErrCode& rError, + sal_uInt32 nConvertFlags, + sal_Int64 nReccomendedAspect ) +{ + sal_Int64 nAspect = nReccomendedAspect; + SdrOle2Obj* pRet = 0; + if( rSrcStorage.Is() && xDestStorage.is() && rStorageName.Len() ) + { + comphelper::EmbeddedObjectContainer aCnt( xDestStorage ); + // Ist der 01Ole-Stream ueberhaupt vorhanden ? + // ( ist er z.B. bei FontWork nicht ) + // Wenn nicht -> Einbindung als Grafik + sal_Bool bValidStorage = sal_False; + String aDstStgName( String::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM(MSO_OLE_Obj))); + + aDstStgName += String::CreateFromInt32( ++nMSOleObjCntr ); + + { + SvStorageRef xObjStg = rSrcStorage->OpenSotStorage( rStorageName, + STREAM_READWRITE| STREAM_SHARE_DENYALL ); + if( xObjStg.Is() ) + { + { + sal_uInt8 aTestA[10]; // exist the \1CompObj-Stream ? + SvStorageStreamRef xSrcTst = xObjStg->OpenSotStream( + String(RTL_CONSTASCII_STRINGPARAM("\1CompObj"), + RTL_TEXTENCODING_MS_1252 )); + bValidStorage = xSrcTst.Is() && sizeof( aTestA ) == + xSrcTst->Read( aTestA, sizeof( aTestA ) ); + if( !bValidStorage ) + { + // or the \1Ole-Stream ? + xSrcTst = xObjStg->OpenSotStream( + String(RTL_CONSTASCII_STRINGPARAM("\1Ole"), + RTL_TEXTENCODING_MS_1252 )); + bValidStorage = xSrcTst.Is() && sizeof(aTestA) == + xSrcTst->Read(aTestA, sizeof(aTestA)); + } + } + + if( bValidStorage ) + { + if ( nAspect != embed::Aspects::MSOLE_ICON ) + { + // check whether the object is iconified one + // usually this information is already known, the only exception + // is a kind of embedded objects in Word documents + // TODO/LATER: should the caller be notified if the aspect changes in future? + + SvStorageStreamRef xObjInfoSrc = xObjStg->OpenSotStream( + String( RTL_CONSTASCII_STRINGPARAM( "\3ObjInfo" ) ), + STREAM_STD_READ | STREAM_NOCREATE ); + if ( xObjInfoSrc.Is() && !xObjInfoSrc->GetError() ) + { + sal_uInt8 nByte = 0; + *xObjInfoSrc >> nByte; + if ( ( nByte >> 4 ) & embed::Aspects::MSOLE_ICON ) + nAspect = embed::Aspects::MSOLE_ICON; + } + } + + uno::Reference < embed::XEmbeddedObject > xObj( CheckForConvertToSOObj( + nConvertFlags, *xObjStg, xDestStorage, rGrf, rVisArea )); + if ( xObj.is() ) + { + svt::EmbeddedObjectRef aObj( xObj, nAspect ); + + // TODO/LATER: need MediaType + aObj.SetGraphic( rGrf, ::rtl::OUString() ); + + // TODO/MBA: check setting of PersistName + pRet = new SdrOle2Obj( aObj, String(), rBoundRect, false); + // we have the Object, don't create another + bValidStorage = false; + } + } + } + } + + if( bValidStorage ) + { + // object is not an own object + SotStorageRef xObjStor = SotStorage::OpenOLEStorage( xDestStorage, aDstStgName, STREAM_READWRITE ); + + if ( xObjStor.Is() ) + { + SotStorageRef xSrcStor = rSrcStorage->OpenSotStorage( rStorageName, STREAM_READ ); + xSrcStor->CopyTo( xObjStor ); + + if( !xObjStor->GetError() ) + xObjStor->Commit(); + + if( xObjStor->GetError() ) + { + rError = xObjStor->GetError(); + bValidStorage = sal_False; + } + else if( !xObjStor.Is() ) + bValidStorage = sal_False; + } + } + else if( pDataStrm ) + { + sal_uInt32 nLen, nDummy; + *pDataStrm >> nLen >> nDummy; + if( SVSTREAM_OK != pDataStrm->GetError() || + // Id in BugDoc - exist there other Ids? + // The ConvertToOle2 - does not check for consistent + 0x30008 != nDummy ) + bValidStorage = sal_False; + else + { + // or is it an OLE-1 Stream in the DataStream? + SvStorageRef xObjStor = SotStorage::OpenOLEStorage( xDestStorage, aDstStgName ); + //TODO/MBA: remove metafile conversion from ConvertToOle2 + //when is this code used?! + GDIMetaFile aMtf; + bValidStorage = ConvertToOle2( *pDataStrm, nLen, &aMtf, xObjStor ); + xObjStor->Commit(); + } + } + + if( bValidStorage ) + { + uno::Reference < embed::XEmbeddedObject > xObj = aCnt.GetEmbeddedObject( aDstStgName ); + if( xObj.is() ) + { + // the visual area must be retrieved from the metafile (object doesn't know it so far) + + if ( nAspect != embed::Aspects::MSOLE_ICON ) + { + // working with visual area can switch the object to running state + awt::Size aAwtSz; + try + { + // the provided visual area should be used, if there is any + if ( rVisArea.IsEmpty() ) + { + MapUnit aMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) ); + Size aSz(lcl_GetPrefSize(rGrf, MapMode(aMapUnit))); + aAwtSz.Width = aSz.Width(); + aAwtSz.Height = aSz.Height(); + } + else + { + aAwtSz.Width = rVisArea.GetWidth(); + aAwtSz.Height = rVisArea.GetHeight(); + } + //xInplaceObj->EnableSetModified( sal_False ); + xObj->setVisualAreaSize( nAspect, aAwtSz ); + //xInplaceObj->EnableSetModified( sal_True );*/ + } + catch( uno::Exception& ) + { + OSL_ENSURE( sal_False, "Could not set visual area of the object!\n" ); + } + } + + svt::EmbeddedObjectRef aObj( xObj, nAspect ); + + // TODO/LATER: need MediaType + aObj.SetGraphic( rGrf, ::rtl::OUString() ); + + pRet = new SdrOle2Obj( aObj, aDstStgName, rBoundRect, false); + } + } + } + + return pRet; +} + +SdrObject* SvxMSDffManager::GetAutoForm( MSO_SPT eTyp ) const +{ + SdrObject* pRet = NULL; + + if(120 >= sal_uInt16(eTyp)) + { + pRet = new SdrRectObj(); + } + + DBG_ASSERT(pRet, "SvxMSDffManager::GetAutoForm -> UNKNOWN AUTOFORM"); + + return pRet; +} + +sal_Bool SvxMSDffManager::SetPropValue( const uno::Any& rAny, const uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet, + const String& rPropName, sal_Bool bTestPropertyAvailability ) +{ + sal_Bool bRetValue = sal_True; + if ( bTestPropertyAvailability ) + { + bRetValue = sal_False; + try + { + uno::Reference< beans::XPropertySetInfo > + aXPropSetInfo( rXPropSet->getPropertySetInfo() ); + if ( aXPropSetInfo.is() ) + bRetValue = aXPropSetInfo->hasPropertyByName( rPropName ); + } + catch( uno::Exception& ) + { + bRetValue = sal_False; + } + } + if ( bRetValue ) + { + try + { + rXPropSet->setPropertyValue( rPropName, rAny ); + bRetValue = sal_True; + } + catch( uno::Exception& ) + { + bRetValue = sal_False; + } + } + return bRetValue; +} + +SvxMSDffImportRec::SvxMSDffImportRec() + : pObj( 0 ), + pWrapPolygon(0), + pClientAnchorBuffer( 0 ), + nClientAnchorLen( 0 ), + pClientDataBuffer( 0 ), + nClientDataLen( 0 ), + nXAlign( 0 ), // position n cm from left + nXRelTo( 2 ), // relative to column + nYAlign( 0 ), // position n cm below + nYRelTo( 2 ), // relative to paragraph + nLayoutInTableCell( 0 ), // element is laid out in table cell + nTextRotationAngle( 0 ), + nDxTextLeft( 144 ), + nDyTextTop( 72 ), + nDxTextRight( 144 ), + nDyTextBottom( 72 ), + nDxWrapDistLeft( 0 ), + nDyWrapDistTop( 0 ), + nDxWrapDistRight( 0 ), + nDyWrapDistBottom(0 ), + nCropFromTop( 0 ), + nCropFromBottom( 0 ), + nCropFromLeft( 0 ), + nCropFromRight( 0 ), + aTextId( 0, 0 ), + nNextShapeId( 0 ), + nShapeId( 0 ), + eShapeType( mso_sptNil ) +{ + eLineStyle = mso_lineSimple; // GPF-Bug #66227# + bDrawHell = sal_False; + bHidden = sal_False; +// bInGroup = sal_False; + bReplaceByFly = sal_False; + bLastBoxInChain = sal_True; + bHasUDefProp = sal_False; // was the DFF_msofbtUDefProp record set? + bVFlip = sal_False; + bHFlip = sal_False; + bAutoWidth = sal_False; +} + +SvxMSDffImportRec::SvxMSDffImportRec(const SvxMSDffImportRec& rCopy) + : pObj( rCopy.pObj ), + nXAlign( rCopy.nXAlign ), + nXRelTo( rCopy.nXRelTo ), + nYAlign( rCopy.nYAlign ), + nYRelTo( rCopy.nYRelTo ), + nLayoutInTableCell( rCopy.nLayoutInTableCell ), + nTextRotationAngle( rCopy.nTextRotationAngle ), + nDxTextLeft( rCopy.nDxTextLeft ), + nDyTextTop( rCopy.nDyTextTop ), + nDxTextRight( rCopy.nDxTextRight ), + nDyTextBottom( rCopy.nDyTextBottom ), + nDxWrapDistLeft( rCopy.nDxWrapDistLeft ), + nDyWrapDistTop( rCopy.nDyWrapDistTop ), + nDxWrapDistRight( rCopy.nDxWrapDistRight ), + nDyWrapDistBottom(rCopy.nDyWrapDistBottom ), + nCropFromTop( rCopy.nCropFromTop ), + nCropFromBottom( rCopy.nCropFromBottom ), + nCropFromLeft( rCopy.nCropFromLeft ), + nCropFromRight( rCopy.nCropFromRight ), + aTextId( rCopy.aTextId ), + nNextShapeId( rCopy.nNextShapeId ), + nShapeId( rCopy.nShapeId ), + eShapeType( rCopy.eShapeType ) +{ + eLineStyle = rCopy.eLineStyle; // GPF-Bug #66227# + bDrawHell = rCopy.bDrawHell; + bHidden = rCopy.bHidden; +// bInGroup = rCopy.bInGroup; + bReplaceByFly = rCopy.bReplaceByFly; + bAutoWidth = rCopy.bAutoWidth; + bLastBoxInChain = rCopy.bLastBoxInChain; + bHasUDefProp = rCopy.bHasUDefProp; + bVFlip = rCopy.bVFlip; + bHFlip = rCopy.bHFlip; + nClientAnchorLen = rCopy.nClientAnchorLen; + if( rCopy.nClientAnchorLen ) + { + pClientAnchorBuffer = new char[ nClientAnchorLen ]; + memcpy( pClientAnchorBuffer, + rCopy.pClientAnchorBuffer, + nClientAnchorLen ); + } + else + pClientAnchorBuffer = 0; + + nClientDataLen = rCopy.nClientDataLen; + if( rCopy.nClientDataLen ) + { + pClientDataBuffer = new char[ nClientDataLen ]; + memcpy( pClientDataBuffer, + rCopy.pClientDataBuffer, + nClientDataLen ); + } + else + pClientDataBuffer = 0; + + if (rCopy.pWrapPolygon) + pWrapPolygon = new Polygon(*rCopy.pWrapPolygon); + else + pWrapPolygon = 0; +} + +SvxMSDffImportRec::~SvxMSDffImportRec() +{ + if (pClientAnchorBuffer) + delete[] pClientAnchorBuffer; + if (pClientDataBuffer) + delete[] pClientDataBuffer; + if (pWrapPolygon) + delete pWrapPolygon; +} + +/* vi:set tabstop=4 shiftwidth=4 expandtab: */ + +void SvxMSDffManager::insertShapeId( sal_Int32 nShapeId, SdrObject* pShape ) +{ + maShapeIdContainer[nShapeId] = pShape; +} + +void SvxMSDffManager::removeShapeId( SdrObject* pShape ) +{ + SvxMSDffShapeIdContainer::iterator aIter( maShapeIdContainer.begin() ); + const SvxMSDffShapeIdContainer::iterator aEnd( maShapeIdContainer.end() ); + while( aIter != aEnd ) + { + if( (*aIter).second == pShape ) + { + maShapeIdContainer.erase( aIter ); + break; + } + aIter++; + } +} + +SdrObject* SvxMSDffManager::getShapeForId( sal_Int32 nShapeId ) +{ + SvxMSDffShapeIdContainer::iterator aIter( maShapeIdContainer.find(nShapeId) ); + return aIter != maShapeIdContainer.end() ? (*aIter).second : 0; +} diff --git a/filter/source/msfilter/msfilter.component b/filter/source/msfilter/msfilter.component new file mode 100755 index 000000000000..64128aa1385b --- /dev/null +++ b/filter/source/msfilter/msfilter.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.vba.VBAMacroResolver"> + <service name="com.sun.star.script.vba.VBAMacroResolver"/> + </implementation> +</component> diff --git a/filter/source/msfilter/msfiltertracer.cxx b/filter/source/msfilter/msfiltertracer.cxx new file mode 100644 index 000000000000..a961693165ab --- /dev/null +++ b/filter/source/msfilter/msfiltertracer.cxx @@ -0,0 +1,251 @@ +/************************************************************************* + * + * 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_filter.hxx" +#include <filter/msfilter/msfiltertracer.hxx> +#include <vcl/svapp.hxx> +#include <tools/urlobj.hxx> +#include <com/sun/star/uno/Sequence.h> +#include <com/sun/star/util/logging/LogLevel.hpp> +#include <com/sun/star/util/SearchAlgorithms.hpp> +#include <com/sun/star/util/SearchFlags.hpp> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <svtools/FilterConfigItem.hxx> +#include <unotools/localfilehelper.hxx> +#include <unotools/streamwrap.hxx> +#include <unotools/ucbstreamhelper.hxx> + + +// -------------- +// - Namespaces - +// -------------- + +using namespace ::com::sun::star; + +MSFilterTracer::MSFilterTracer( const ::rtl::OUString& rConfigPath, uno::Sequence< beans::PropertyValue >* pConfigData ) : + mpCfgItem( new FilterConfigItem( rConfigPath, pConfigData ) ), + mpAttributeList( new SvXMLAttributeList() ), + mpStream( NULL ), + mbEnabled( sal_False ) // will be set to true in StartTracing() +{ + if ( mpCfgItem->ReadBool( rtl::OUString::createFromAscii( "On" ), sal_False ) ) + { + uno::Reference< lang::XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() ); + if ( xMgr.is() ) + { + /* the following methods try to read a property, if it is not available it will put the second + parameter as default into the property sequence of the FilterConfigItem. It means we ensure that + the property is available by trying to read it (the return value of the method is ignored) */ + ::rtl::OUString aEmptyString; + mpCfgItem->ReadInt32( rtl::OUString::createFromAscii( "LogLevel" ), util::logging::LogLevel::ALL ); + mpCfgItem->ReadString( rtl::OUString::createFromAscii( "ClassFilter" ), aEmptyString ); + mpCfgItem->ReadString( rtl::OUString::createFromAscii( "MethodFilter" ), aEmptyString ); + mpCfgItem->ReadString( rtl::OUString::createFromAscii( "MessageFilter" ), aEmptyString ); + util::SearchAlgorithms eSearchAlgorithm = (util::SearchAlgorithms) + mpCfgItem->ReadInt32( rtl::OUString::createFromAscii( "SearchAlgorithm" ), util::SearchAlgorithms_ABSOLUTE ); + + // creating the name of the log file + rtl::OUString aPath( mpCfgItem->ReadString( rtl::OUString::createFromAscii( "Path" ), aEmptyString ) ); + rtl::OUString aName( mpCfgItem->ReadString( rtl::OUString::createFromAscii( "Name" ), aEmptyString ) ); + rtl::OUString aDocumentURL( mpCfgItem->ReadString( rtl::OUString::createFromAscii( "DocumentURL" ), aEmptyString ) ); + INetURLObject aLogFile( aDocumentURL ); + if ( aLogFile.GetMainURL( INetURLObject::NO_DECODE ).getLength() ) + { + if ( aPath.getLength() ) + { + String aOldName( aLogFile.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::NO_DECODE ) ); + aLogFile = INetURLObject( aPath ); + aLogFile.insertName( aOldName ); + } + if ( aName.getLength() ) + aLogFile.setName( aName ); + } + else + { + if ( aPath.getLength() ) + aLogFile = INetURLObject( aPath ); + else + { + String aURLStr; + if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( Application::GetAppFileName(), aURLStr ) ) + { + aLogFile = INetURLObject(aURLStr); + aLogFile .removeSegment(); + aLogFile .removeFinalSlash(); + } + } + if ( !aName.getLength() ) + aName = rtl::OUString::createFromAscii( "tracer" ); + aLogFile.insertName( aName ); + } + aLogFile.setExtension( rtl::OUString::createFromAscii( "log" ) ); + + // creating the file stream + mpStream = ::utl::UcbStreamHelper::CreateStream( aLogFile.GetMainURL( INetURLObject::NO_DECODE ), STREAM_WRITE | STREAM_TRUNC | STREAM_SHARE_DENYNONE ); + if ( mpStream && !mpStream->GetError() ) + { + // creating a wrapper for our stream + utl::OOutputStreamWrapper* pHelper = new ::utl::OOutputStreamWrapper( *mpStream ); + uno::Reference< io::XOutputStream > xOutputStream( pHelper ); + + // instanciating the DocumentHandler, then setting the OutputStream + mxHandler = uno::Reference< xml::sax::XDocumentHandler >( xMgr->createInstance( rtl::OUString::createFromAscii( "com.sun.star.xml.sax.Writer" ) ), uno::UNO_QUERY ); + uno::Reference< io::XActiveDataSource > xDocSrc( mxHandler, uno::UNO_QUERY ); + xDocSrc->setOutputStream( xOutputStream ); + mxHandler->startDocument(); + mxHandler->ignorableWhitespace ( rtl::OUString::createFromAscii( " " ) ); + + // writing the "DocumentHandler" property, so the FilterTracer component + // will use it for the output + uno::Any aAny; + aAny <<= xDocSrc; + mpCfgItem->WriteAny( rtl::OUString::createFromAscii( "DocumentHandler" ), aAny ); + + SvXMLAttributeList* pAttrList = new SvXMLAttributeList; + pAttrList->AddAttribute( rtl::OUString::createFromAscii( "DocumentURL" ), aDocumentURL ); + uno::Reference < xml::sax::XAttributeList > xAttributeList(pAttrList); + mxHandler->startElement( rtl::OUString::createFromAscii( "Document" ), xAttributeList ); + } + + uno::Sequence< uno::Any > aArgument( 1 ); + uno::Sequence< beans::PropertyValue > aPropValues( mpCfgItem->GetFilterData() ); + aArgument[ 0 ] <<= aPropValues; + mxFilterTracer = xMgr->createInstanceWithArguments( rtl::OUString::createFromAscii( "com.sun.star.util.FilterTracer" ), aArgument ); + if ( mxFilterTracer.is() ) + { + mxTextSearch = uno::Reference< util::XTextSearch >( mxFilterTracer, uno::UNO_QUERY ); + mxLogger = uno::Reference< util::logging::XLogger >( mxFilterTracer, uno::UNO_QUERY ); + if ( mxTextSearch.is() ) + { + maSearchOptions.algorithmType = eSearchAlgorithm; + mxTextSearch->setOptions( maSearchOptions ); + } + } + } + } +} + +MSFilterTracer::~MSFilterTracer() +{ + mxLogger = NULL; + mxFilterTracer = NULL; + if ( mxHandler.is() ) + { + mxHandler->ignorableWhitespace ( rtl::OUString::createFromAscii( " " ) ); + mxHandler->endElement( rtl::OUString::createFromAscii( "Document" ) ); + mxHandler->ignorableWhitespace ( rtl::OUString::createFromAscii( " " ) ); + mxHandler->endDocument(); + mxHandler = NULL; + } + delete mpAttributeList; + delete mpCfgItem; + delete mpStream; +} + +void MSFilterTracer::StartTracing() +{ + mbEnabled = mpCfgItem->ReadBool( rtl::OUString::createFromAscii( "On" ), sal_False ); +} + +void MSFilterTracer::EndTracing() +{ + mbEnabled = sal_False; +} + +void MSFilterTracer::StartElement( const rtl::OUString& rName, uno::Reference< xml::sax::XAttributeList > xAttribs ) +{ + if ( mxHandler.is() ) + mxHandler->startElement( rName, xAttribs ); +} + +void MSFilterTracer::EndElement( const rtl::OUString& rName ) +{ + if ( mxHandler.is() ) + mxHandler->endElement( rName ); +} + +void MSFilterTracer::Trace( const rtl::OUString& rElement, const rtl::OUString& rMessage ) +{ + if ( mbEnabled && mxLogger.is() ) + { + sal_Bool bFilter = sal_False; + if ( rMessage.getLength() && mxTextSearch.is() ) + { + maSearchOptions.searchString = rMessage; + mxTextSearch->setOptions( maSearchOptions ); + util::SearchResult aSearchResult = mxTextSearch->searchForward( rMessage, 0, rMessage.getLength() ); + bFilter = aSearchResult.subRegExpressions != 0; + } + if ( !bFilter ) + { + uno::Reference < xml::sax::XAttributeList > xAttrList( new SvXMLAttributeList( *mpAttributeList ) ); + if ( mxHandler.is() ) + mxHandler->startElement( rElement, xAttrList ); + if ( rMessage.getLength() ) + { + rtl::OUString aEmpty; + mxLogger->logp( 0, aEmpty, aEmpty, rMessage ); + } + if ( mxHandler.is() ) + mxHandler->endElement( rElement ); + } + } +} + +void MSFilterTracer::AddAttribute( const ::rtl::OUString& sName , const ::rtl::OUString& sValue ) +{ + if ( mbEnabled ) + mpAttributeList->AddAttribute( sName, sValue ); +} +void MSFilterTracer::ClearAttributes() +{ + if ( mbEnabled ) + mpAttributeList->Clear(); +} + +void MSFilterTracer::RemoveAttribute( const ::rtl::OUString& sName ) +{ + if ( mbEnabled ) + mpAttributeList->RemoveAttribute( sName ); +} + +uno::Any MSFilterTracer::GetProperty( const rtl::OUString& rPropName, const uno::Any* pDefault ) const +{ + uno::Any aDefault; + if ( pDefault ) + aDefault = *pDefault; + return mpCfgItem->ReadAny( rPropName, aDefault ); +} + +void MSFilterTracer::SetProperty( const ::rtl::OUString& rPropName, const uno::Any& rProperty ) +{ + mpCfgItem->WriteAny( rPropName, rProperty ); +} + diff --git a/filter/source/msfilter/msocximex.cxx b/filter/source/msfilter/msocximex.cxx new file mode 100644 index 000000000000..e7b5eebb8b7f --- /dev/null +++ b/filter/source/msfilter/msocximex.cxx @@ -0,0 +1,5956 @@ +/************************************************************************* + * + * 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_filter.hxx" + +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */ +#include <com/sun/star/uno/Any.h> +#include <com/sun/star/text/VertOrientation.hpp> +#include <com/sun/star/text/XText.hpp> +#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HDL_ +#include <com/sun/star/lang/XServiceInfo.hpp> +#endif +#include <com/sun/star/text/TextContentAnchorType.hpp> +#include <com/sun/star/drawing/XShape.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/drawing/XDrawPage.hpp> +#include <com/sun/star/drawing/XShapes.hpp> +#include <com/sun/star/drawing/XControlShape.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/container/XIndexContainer.hpp> +#include <com/sun/star/drawing/XDrawPageSupplier.hpp> +#include <com/sun/star/form/XFormsSupplier.hpp> +#include <com/sun/star/form/XForm.hpp> +#include <com/sun/star/form/FormComponentType.hpp> +#include <com/sun/star/awt/FontWeight.hpp> +#include <com/sun/star/awt/FontSlant.hpp> +#include <com/sun/star/awt/FontUnderline.hpp> +#include <com/sun/star/awt/FontStrikeout.hpp> +#include <com/sun/star/awt/ScrollBarOrientation.hpp> +#include <com/sun/star/style/VerticalAlignment.hpp> +#include <comphelper/extract.hxx> +#include <com/sun/star/awt/XControlModel.hpp> +#include <com/sun/star/io/XInputStreamProvider.hpp> +#include <rtl/ustrbuf.hxx> +#include <vcl/svapp.hxx> +#include <sfx2/objsh.hxx> +#include <xmlscript/xmldlg_imexp.hxx> +#include <filter/msfilter/msocximex.hxx> +#include <osl/file.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <comphelper/processfactory.hxx> // shouldn't be needed +#include <com/sun/star/ucb/XSimpleFileAccess.hpp> +#include <algorithm> +#include <memory> + +#ifndef C2S +#define C2S(cChar) String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(cChar)) +#endif +#ifndef C2U +#define C2U(cChar) rtl::OUString::createFromAscii(cChar) +#endif + +using namespace ::com::sun::star; +using namespace ::rtl; +using namespace cppu; + + +#define WW8_ASCII2STR(s) String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(s)) + + +static char sWW8_form[] = "WW-Standard"; + + +struct SortOrderByTabPos +{ + bool operator()( const OCX_Control* a, const OCX_Control* b ) + { + return a->mnTabPos < b->mnTabPos; + } +}; + + +sal_uInt8 __READONLY_DATA OCX_Control::aObjInfo[4] = { 0x00, 0x12, 0x03, 0x00 }; + +long ReadAlign(SvStorageStream *pS, long nPos, int nAmount) +{ + if (long nAlign = nPos % nAmount) + { + + long nLen = nAmount - nAlign; + pS->SeekRel(nLen); + return nLen; + } + return 0; +} + + +// NP - Images in controls in OO2.0/SO8 exist as links, e.g. they are not part of the document so are +// referenced externally. On import from ms document try to save images for controls here. +// Images are stored in directory called temp in the user installation directory. Next version of OO/SO +// hopefully will address this issue and allow a choice e.g. images for controls to be stored as links +// or embeded in the document. + +// [out]location path to the stream to where the image is to be stored, +// if same name exists in folder then this function calcuates a new name +// [in] data raw bytes of image to be stored. +// [in] dataLen no. byte to be stored +// +// returns, true if successful + +bool storePictureInFileSystem( OUString& location, sal_uInt8* data, sal_uInt32 dataLen ) +{ + bool result = true; + OUString origPath = location; + try + { + uno::Reference<lang::XMultiServiceFactory > xMSF( ::comphelper::getProcessServiceFactory(), + uno::UNO_QUERY_THROW ); + uno::Reference< com::sun::star::ucb::XSimpleFileAccess> xSFA( xMSF->createInstance( + S2U("com.sun.star.ucb.SimpleFileAccess" ) ), + uno::UNO_QUERY_THROW ); + OUString ext; + sal_Int32 index = 0; + while ( xSFA->exists( location ) ) + { + ext = OUString::valueOf( ++index ); + location = origPath + ext; + } + + SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( location, STREAM_WRITE | STREAM_TRUNC ); + if ( pStream ) + { + pStream->Write(data, dataLen); + delete pStream; + } + else + { + result = false; + } + } + catch( uno::Exception& ) + { + result = false; + } + return result; +} + +// NP - Images in controls in OO2.0/SO8 exist as links, e.g. they are not part of the document so are +// referenced externally. On import from ms document try to save images from controls here so this +// at least a macro programmer has a chance to accessed them manually later. Next version of OO/SO +// hopefully will address this issue. +// Images will be stored in a top level folder in the document package, folder is named "MigratedImages" + +// [in] pDocSh* the document shell. +// [in] name name of stream image to stored in. +// [in] data raw bytes of image to be stored. +// [in] dataLen no. byte to be stored + +bool storePictureInDoc( SfxObjectShell* pDocSh, OUString& name, sal_uInt8* data, sal_uInt32 dataLen ) +{ + uno::Reference < embed::XStorage > xStor; + if (pDocSh) + { + xStor = pDocSh->GetStorage(); + if( xStor.is() ) + { + try + { + uno::Reference< embed::XStorage > xPictures = xStor->openStorageElement( + OUString( RTL_CONSTASCII_USTRINGPARAM( "MigratedImages" ) ), + embed::ElementModes::READWRITE ); + uno::Reference< beans::XPropertySet > xPropSet( xPictures, uno::UNO_QUERY ); + + // Set media type of folder MigratedImages to something ( that is unknown ) so that + // it will get copied to exported OO/SO format after SaveAs + if ( xPropSet.is() ) + { + OUString aMediaType = C2U("MigrationImages"); + uno::Any a; + a <<= aMediaType; + xPropSet->setPropertyValue( C2U("MediaType"), a ); + } + + uno::Reference< io::XStream > xObjReplStr = xPictures->openStreamElement( + name, + embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE ); + uno::Reference< io::XOutputStream > xOutStream( xObjReplStr->getOutputStream(), uno::UNO_QUERY_THROW ); + uno::Sequence< sal_Int8 > imageBytes( (sal_Int8*)data, dataLen ); + xOutStream->writeBytes( imageBytes ); + xOutStream->closeOutput(); + + uno::Reference< embed::XTransactedObject > xTransact( xPictures, uno::UNO_QUERY ); + if ( xTransact.is() ) + { + xTransact->commit(); + } + } + catch( uno::Exception& ) + { + return false; + } + + } + else + { + // no storage something wrong + return false; + } + } + else + { + //No doc shell + return false; + } + return true; +} + +long WriteAlign(SvStorageStream *pS, int nAmount) +{ + if (long nAlign = pS->Tell() % nAmount) + { + long nLen = nAmount - nAlign; + for (long i=0; i< nLen; ++i) + *pS << sal_uInt8(0x00); + return nLen; + } + return 0; +} +// string import/export ======================================================= +/** #117832# import of form control names +* control name is located in stream ("\3OCXNAME") +* a strings in "\3OCXNAME" stream seem to be terminated by 4 trailing bytes of 0's. +* ==== +* Note: If the string in the stream is overwritten by a shorter string +* some characters from the original string may remain, the new string however +* will still be terminated in the same way e.g. by 4 bytes with value 0. +*/ + +bool writeOCXNAME( const OUString& sOCXName, SvStorageStream* pStream ) +{ + const sal_Unicode* buffer = sOCXName.getStr(); + for ( sal_Int32 index=0; index < sOCXName.getLength(); index++ ) + { + sal_uInt16 ch = static_cast< sal_uInt16 >( buffer[ index ] ); + *pStream << ch; + } + // write + *pStream << sal_uInt32(0); + return ( SVSTREAM_OK == pStream->GetError() ); + +} + +bool readOCXNAME( OUString& sCName, SvStorageStream* pStream ) +{ + /* + * Read uniCode until no data or 0 encountered + */ + OUStringBuffer buf(40); + do + { + sal_uInt16 ch = 0; + *pStream >> ch; + sal_Unicode uni = static_cast< sal_Unicode >( ch ); + if ( uni == 0 ) + { + break; + } + buf.append( &uni, 1 ); + + } while ( !pStream->IsEof() ); + + sCName = buf.makeStringAndClear(); + return ( SVSTREAM_OK == pStream->GetError() ); +} + + +/* #110435# (DR, 2003-11-12) ** Import of Unicode strings in form controls ** + + Strings may be stored either as compressed or uncompressed Unicode + character array. There are no encoded byte strings anywhere. + + The string length field stores the length of the character array (not the + character count of the string) in the lower 31 bits, and the compression + state in the highest bit. + + A set bit means the character array is compressed. This means all Unicode + characters are <=0xFF. Therefore the high bytes of all characters are left + out, and the character array size is equal to the string length. + + A cleared bit means the character array is not compressed. The buffer + contains Little-Endian Unicode characters, and the resulting string length + is half the buffer size. + + TODO: This implementation of the new string import is a hack to keep + msocximex.hxx unchanged. A better implementation would replace the char* + members of all classes by something more reasonable. + */ + +namespace { + +const sal_uInt32 SVX_MSOCX_SIZEMASK = 0x7FFFFFFF; /// Mask for character buffer size. +const sal_uInt32 SVX_MSOCX_COMPRESSED = 0x80000000; /// 1 = compressed Unicode array. + + +/** Returns true, if the passed length field specifies a compressed character array. + */ +inline bool lclIsCompressed( sal_uInt32 nLenFld ) +{ + return (nLenFld & SVX_MSOCX_COMPRESSED) != 0; +} + + +/** Extracts and returns the memory size of the character buffer. + @return Character buffer size (may differ from resulting string length!). + */ +inline sal_uInt32 lclGetBufferSize( sal_uInt32 nLenFld ) +{ + return nLenFld & SVX_MSOCX_SIZEMASK; +} + + +// import --------------------------------------------------------------------- + +/** Reads the character array of a string in a form control. + + Creates a new character array containing the character data. + The length field must be read before and passed to this function. + Aligns stream position to multiple of 4 before. + + @param rStrm + The input stream. + + @param rpcCharArr + (out-param) Will point to the created character array, + or will be 0 if string is empty. The array is NOT null-terminated. + If the passed pointer points to an old existing array, it will be + deleted before. Caller must delete the returned array. + + @param nLenFld + The corresponding string length field read somewhere before. + */ +void lclReadCharArray( SvStorageStream& rStrm, char*& rpcCharArr, sal_uInt32 nLenFld, long nPos ) +{ + delete[] rpcCharArr; + rpcCharArr = 0; + sal_uInt32 nBufSize = lclGetBufferSize( nLenFld ); + DBG_ASSERT( nBufSize <= 0xFFFF, "lclReadCharArray - possible read error: char array is too big" ); + if( nBufSize && nBufSize <= 0xFFFF ) + { + rpcCharArr = new char[ nBufSize ]; + if( rpcCharArr ) + { + ReadAlign( &rStrm, nPos, 4 ); + rStrm.Read( rpcCharArr, nBufSize ); + } + } +} + + +/** Creates an OUString from a character array created with lclReadCharArray(). + + The passed parameters must match, that means the length field must be the + same used to create the passed character array. + + @param pcCharArr + The character array returned by lclReadCharArray(). May be compressed + or uncompressed, next parameter nLenFld will specify this. + + @param nLenFld + MUST be the same string length field that has been passed to + lclReadCharArray() to create the character array in previous parameter + pcCharArr. + + @return + An OUString containing the decoded string data. Will be empty if + pcCharArr is 0. + */ +OUString lclCreateOUString( const char* pcCharArr, sal_uInt32 nLenFld ) +{ + OUStringBuffer aBuffer; + sal_uInt32 nBufSize = lclGetBufferSize( nLenFld ); + if( lclIsCompressed( nLenFld ) ) + { + // buffer contains compressed Unicode, not encoded bytestring + sal_Int32 nStrLen = static_cast< sal_Int32 >( nBufSize ); + aBuffer.setLength( nStrLen ); + const char* pcCurrChar = pcCharArr; + for( sal_Int32 nChar = 0; nChar < nStrLen; ++nChar, ++pcCurrChar ) + /* *pcCurrChar may contain negative values and therefore MUST be + casted to unsigned char, before assigned to a sal_Unicode. */ + aBuffer.setCharAt( nChar, static_cast< unsigned char >( *pcCurrChar ) ); + } + else + { + // buffer contains Little-Endian Unicode + sal_Int32 nStrLen = static_cast< sal_Int32 >( nBufSize ) / 2; + aBuffer.setLength( nStrLen ); + const char* pcCurrChar = pcCharArr; + for( sal_Int32 nChar = 0; nChar < nStrLen; ++nChar ) + { + /* *pcCurrChar may contain negative values and therefore MUST be + casted to unsigned char, before assigned to a sal_Unicode. */ + sal_Unicode cChar = static_cast< unsigned char >( *pcCurrChar++ ); + cChar |= (static_cast< unsigned char >( *pcCurrChar++ ) << 8); + aBuffer.setCharAt( nChar, cChar ); + } + } + return aBuffer.makeStringAndClear(); +} + +// export --------------------------------------------------------------------- + +/** This class implements writing a character array from a Unicode string. + + Usage: + 1) Construct an instance, either directly with an OUString, or with an UNO + Any containing an OUString. + 2) Check with HasData(), if there is something to write. + 3) Write the string length field with WriteLenField() at the right place. + 4) Write the encoded character array with WriteCharArray(). + */ +class SvxOcxString +{ +public: + /** Constructs an empty string. String data may be set later by assignment. */ + inline explicit SvxOcxString() : mnLenFld( 0 ) {} + /** Constructs the string from the passed OUString. */ + inline explicit SvxOcxString( const OUString& rStr ) { Init( rStr ); } + /** Constructs the string from the passed UNO Any. */ + inline explicit SvxOcxString( const uno::Any& rAny ) { Init( rAny ); } + + /** Assigns the passed string to the object. */ + inline SvxOcxString& operator=( const OUString& rStr ) { Init( rStr ); return *this; } + /** Assigns the string in the passed UNO Any to the object. */ + inline SvxOcxString& operator=( const uno::Any& rAny ) { Init( rAny ); return *this; } + + /** Returns true, if the string contains at least one character to write. */ + inline bool HasData() const { return maString.getLength() > 0; } + + /** Writes the encoded 32-bit string length field. Aligns stream position to mult. of 4 before. */ + void WriteLenField( SvStorageStream& rStrm ) const; + /** Writes the encoded character array. Aligns stream position to mult. of 4 before. */ + void WriteCharArray( SvStorageStream& rStrm ) const; + +private: + inline void Init( const OUString& rStr ) { maString = rStr; Init(); } + void Init( const uno::Any& rAny ); + void Init(); + + OUString maString; /// The initial string data. + sal_uInt32 mnLenFld; /// The encoded string length field. +}; + +void SvxOcxString::Init( const uno::Any& rAny ) +{ + if( !(rAny >>= maString) ) + maString = OUString(); + Init(); +} + +void SvxOcxString::Init() +{ + mnLenFld = static_cast< sal_uInt32 >( maString.getLength() ); + bool bCompr = true; + // try to find a character >= 0x100 -> character array will be stored uncompressed then + if( const sal_Unicode* pChar = maString.getStr() ) + for( const sal_Unicode* pEnd = pChar + maString.getLength(); bCompr && (pChar < pEnd); ++pChar ) + bCompr = (*pChar < 0x100); + if( bCompr ) + mnLenFld |= SVX_MSOCX_COMPRESSED; + else + mnLenFld *= 2; +} + +void SvxOcxString::WriteLenField( SvStorageStream& rStrm ) const +{ + if( HasData() ) + { + WriteAlign( &rStrm, 4); + rStrm << mnLenFld; + } +} + +void SvxOcxString::WriteCharArray( SvStorageStream& rStrm ) const +{ + if( HasData() ) + { + const sal_Unicode* pChar = maString.getStr(); + const sal_Unicode* pEnd = pChar + maString.getLength(); + bool bCompr = lclIsCompressed( mnLenFld ); + + WriteAlign( &rStrm, 4); + for( ; pChar < pEnd; ++pChar ) + { + // write compressed Unicode (not encoded bytestring), or Little-Endian Unicode + rStrm << static_cast< sal_uInt8 >( *pChar ); + if( !bCompr ) + rStrm << static_cast< sal_uInt8 >( *pChar >> 8 ); + } + } +} + +const sal_uInt16 USERFORM = (sal_uInt16)0xFF; +const sal_uInt16 STDCONTAINER = (sal_uInt16)0xFE; + +const sal_uInt16 PAGE = (sal_uInt16)0x07; + +const sal_uInt16 IMAGE = (sal_uInt16)0x0C; +const sal_uInt16 FRAME = (sal_uInt16)0x0E; + +const sal_uInt16 SPINBUTTON = (sal_uInt16)0x10; +const sal_uInt16 CMDBUTTON = (sal_uInt16)0x11; +const sal_uInt16 TABSTRIP = (sal_uInt16)0x12; + +const sal_uInt16 LABEL = (sal_uInt16)0x15; + +const sal_uInt16 TEXTBOX = (sal_uInt16)0x17; +const sal_uInt16 LISTBOX = (sal_uInt16)0x18; +const sal_uInt16 COMBOBOX = (sal_uInt16)0x19; +const sal_uInt16 CHECKBOX = (sal_uInt16)0x1A; + +const sal_uInt16 OPTIONBUTTON = (sal_uInt16)0x1B; +const sal_uInt16 TOGGLEBUTTON = (sal_uInt16)0x1C; + +const sal_uInt16 SCROLLBAR = (sal_uInt16)0x2F; + +const sal_uInt16 MULTIPAGE = (sal_uInt16)0x39; +const sal_uInt16 PROGRESSBAR = (sal_uInt16)0x8000; + +typedef std::vector< ContainerRecord > ContainerRecordList; + +class ContainerRecReader +{ + public: + + virtual ~ContainerRecReader() {} + + virtual bool Read( OCX_ContainerControl* pContainerControl, SvStorageStream *pS) + { + *pS >> nNoRecords; + *pS >> nTotalLen; + + if ( isMultiPage ) + { + if ( !handleMultiPageHdr( pS ) ) + { + return false; + } + } + else + { + if ( !handleStandardHdr( pS ) ) + { + return false; + } + } + + records.clear(); + for (sal_uInt32 nRecord = 0; nRecord < nNoRecords; ++nRecord) + { + // DR #134146# redo loading of FrameChild data + + ContainerRecord rec; + + // record header + sal_uInt16 nId, nSize; + *pS >> nId >> nSize; + sal_Size nStartPos = pS->Tell(); + + // content flags + sal_uInt32 nContentFlags; + *pS >> nContentFlags; + + // length of control name + sal_uInt32 nNameLen = 0; + if( nContentFlags & 0x00000001 ) + *pS >> nNameLen; + // length of control tag + sal_uInt32 nTagLen = 0; + if( nContentFlags & 0x00000002 ) + *pS >> nTagLen; + // substorage id for frames + if( nContentFlags & 0x00000004 ) + *pS >> rec.nSubStorageId; + // help-context id + if( nContentFlags & 0x00000008 ) + pS->SeekRel( 4 ); + // option flags + if( nContentFlags & 0x00000010 ) + { + sal_uInt32 nBitFlags = 0; + *pS >> nBitFlags; + rec.bVisible = ( ( nBitFlags & 0x02 ) == 0x02 ); + } + // substream size + if( nContentFlags & 0x00000020 ) + *pS >> rec.nSubStreamLen; + // tabstop position + if( nContentFlags & 0x00000040 ) + *pS >> rec.nTabPos; + // control type + if( nContentFlags & 0x00000080 ) + *pS >> rec.nTypeIdent; + // length of infotip + sal_uInt32 nTipLen = 0; + if( nContentFlags & 0x00000800 ) + { + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + *pS >> nTipLen; + } + + sal_uInt32 nCntrlIdLen = 0; + if( nContentFlags & 0x00001000 ) + *pS >> nCntrlIdLen; + + // length of control source name + sal_uInt32 nCtrlSrcLen = 0; + if( nContentFlags & 0x00002000 ) + { + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + *pS >> nCtrlSrcLen; + } + + // length of row source name + sal_uInt32 nRowSrcLen = 0; + if( nContentFlags & 0x00004000 ) + { + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + *pS >> nRowSrcLen; + } + + // control name + sal_Char* pName = 0; + sal_uInt32 nNameBufSize = lclGetBufferSize( nNameLen ); + if( nNameBufSize > 0 ) + { + pName = new char[ nNameBufSize ]; + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + pS->Read( pName, nNameBufSize ); + } + // control tag + sal_uInt32 nTagBufSize = lclGetBufferSize( nTagLen ); + if( nTagBufSize > 0 ) + { + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + pS->SeekRel( nTagBufSize ); + } + + // control position + if( nContentFlags & 0x00000100 ) + { + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + *pS >> rec.nLeft >> rec.nTop; + } + + // control infotip + sal_uInt32 nTipBufSize = lclGetBufferSize( nTipLen ); + if( nTipBufSize > 0 ) + { + std::auto_ptr< sal_Char > pTipName; + pTipName.reset( new sal_Char[ nTipBufSize ] ); + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + pS->Read( pTipName.get(), nTipBufSize ); + rec.controlTip = lclCreateOUString( pTipName.get(), nTipLen ); + } + // control id + sal_uInt32 nCntrlIdSize = lclGetBufferSize( nCntrlIdLen ); + if( nCntrlIdSize > 0 ) + { + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + pS->SeekRel( nCntrlIdSize ); + } + // control source name + sal_uInt32 nCtrlSrcBufSize = lclGetBufferSize( nCtrlSrcLen ); + if( nCtrlSrcBufSize > 0 ) + { + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + pS->SeekRel( nCtrlSrcBufSize ); + } + // row source name + sal_uInt32 nRowSrcBufSize = lclGetBufferSize( nRowSrcLen ); + if( nRowSrcBufSize > 0 ) + { + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + pS->SeekRel( nRowSrcBufSize ); + } + + // seek to end of data + pS->Seek( nStartPos + nSize ); + + rec.cName = lclCreateOUString(pName, nNameLen); + delete[] pName; + + OCX_Control* pControl = NULL; + if( pContainerControl->createFromContainerRecord( rec, pControl ) && + pControl ) + { + // propagate doc shell from parent + pControl->pDocSh = pContainerControl->pDocSh; + pContainerControl->ProcessControl( pControl, pS, rec ); + } + else + { + DBG_ERROR("Terminating import, unexpected error"); + return false; + } + } + return true; + } + + protected: + ContainerRecReader() : isMultiPage(false){} + bool isMultiPage; + sal_uInt32 nNoRecords; + sal_uInt32 nTotalLen; + + private: + bool handleStandardHdr( SvStorageStream* pS ) + { + sal_uInt8 aUnknown11[4]; + pS->Read(aUnknown11, sizeof(aUnknown11)); + return true; + } + + bool handleMultiPageHdr( SvStorageStream* pS ) + { + sal_uInt32 nUnknown_32b; // unknown 32 bit structure, flags ? + sal_uInt16 nUnknown_16b; // unknown 16 bit structure + sal_uInt16 nMysteryLen; // lenght of unknown sub record + + *pS >> nUnknown_32b; + *pS >> nUnknown_16b; + *pS >> nMysteryLen; + + pS->SeekRel( nMysteryLen ); + return true; + } + ContainerRecordList records; +}; + +class StdContainerRecReader : public ContainerRecReader +{ + public: + StdContainerRecReader(){} +}; + +class MultiPageContainerRecReader : public ContainerRecReader +{ + public: + MultiPageContainerRecReader() + { + // NP ( 27-01-05 ) + // Strictly speaking this approach shouldn't be necessary. + // It should be possible to have a common routine read the + // container record array and by examining the flags present in + // the record to determine we expect to read or not. + // In this case for a MultPage control there is no Top or Left + // values in the control record array, however time contraints + // and associated risk prevent further investigation of this + // at the moment. + // similar situation exists for the start of the container record + // which in the case of the MultiPage is different from + // UserForm & Frame ( the other containers ) + + isMultiPage = true; // tell the base class skip + } +}; + +class ContainerRecordReaderFac +{ + public: + static ContainerRecReader* instance( sal_uInt32 containerType ) + { + switch( containerType ) + { + case PAGE: + case FRAME: + case USERFORM: + case STDCONTAINER: + return new StdContainerRecReader(); + case MULTIPAGE: + return new MultiPageContainerRecReader(); + default: + DBG_ERROR("Illegal container type for factory"); + return NULL; + } + } + private: + ContainerRecordReaderFac(); +}; + +} // namespace + +// ============================================================================ + +void RBGroup::add(OCX_Control* pRB) +{ + // The tab index for the group is calculated as + // the lowest tab index found in the list of RadioButtons + if ( pRB->mnTabPos < mRBGroupPos ) + { + mRBGroupPos = pRB->mnTabPos; + CtrlIterator aEnd = mpControls.end(); + for (CtrlIterator aIter = mpControls.begin(); aIter != aEnd; ++ aIter ) + { + (*aIter)->mnTabPos = mRBGroupPos; + } + } + mpControls.push_back( pRB ); +} + +struct SortGroupByTabPos +{ + bool operator()( const RBGroup* a, const RBGroup* b ) + { + return a->tabPos() < b->tabPos(); + } +}; + +RBGroupManager::RBGroupManager( String& defaultName ):mSDefaultName( defaultName ), + numRadioButtons(0) +{ + groupList.reserve( 8 ); // reserve far more than we expect +} + +RBGroupManager::~RBGroupManager() +{ + for ( GroupIterator gIter=groupList.begin(); gIter!=groupList.end(); ++gIter ) + { + delete( *gIter ); + } +} + +// Loose description of the method below ( I sure there is a better way to do +// this ) +// In order to "fake" MS grouping behavior for OptionButtons the OptionButtons +// in the same group need to have consecutive tab indices ( regardless of the +// imported tab indices of the RadioButtons ). Additionally if two +// groups of OptionButtons end up having all consecutive indices they +// will be treated as a single group by OpenOffice. In this case +// a dummy seperator control needs to be inserted between the groups. +// +// This method returns a new list "destinationList" containing the controls +// passed in "sourceList" and the OptionButtons contained in the various +// Groups maintained by this class. +// Controls are ordered in the destination list by tab index. +// Each RadioButtonGroup has a tab index associated with it. +// ( Tab index of a RadioGroup is determined as the tab index of the +// OptionButton control with the lowest tab index in the group ) + + +void RBGroupManager::addRadioButton( OCX_OptionButton* pRButton ) +{ + if ( pRButton ) + { + OUString groupName = mSDefaultName; + if ( pRButton->nGroupNameLen ) + { + groupName = + lclCreateOUString(pRButton->pGroupName, + pRButton->nGroupNameLen); + } + ++numRadioButtons; + RBGroupHash::iterator iter = rbGroups.find( groupName ); + if ( iter != rbGroups.end() ) + { + iter->second->controls().push_back( pRButton ); + } + else + { + RBGroup* newGroup = new RBGroup(pRButton->mnTabPos); + newGroup->controls().push_back( pRButton ); + rbGroups[ groupName ] = newGroup; + groupList.push_back( newGroup ); + } + + } +} + +CtrlList RBGroupManager::insertGroupsIntoControlList( const CtrlList& sourceList ) +{ + ::std::sort( groupList.begin(), groupList.end(), SortGroupByTabPos() ); + std::vector<OCX_Control*> destinationList; + if ( groupList.size() ) + { + destinationList.reserve( sourceList.size() + numRadioButtons ); + + GroupIterator groupEnd = groupList.end(); + CtrlIteratorConst sourceEnd = sourceList.end(); + + size_t prevGroupListSize = 0; + + CtrlIteratorConst containees = sourceList.begin(); + GroupIterator groupIter=groupList.begin(); + while ( containees != sourceEnd || + groupIter != groupEnd ) + { + bool addGroupSeperator = false; + if ( containees != sourceEnd ) + { + if ( groupIter != groupEnd ) + { + sal_Int16 groupTabPos = (*groupIter)->tabPos(); + if ( (*containees)->mnTabPos >= groupTabPos ) + { + if ( !(destinationList.size() >= prevGroupListSize )) + { + addGroupSeperator = true; + } + copyList( (*groupIter)->controls(), destinationList, addGroupSeperator ); + ++groupIter; + + prevGroupListSize = destinationList.size(); + } + } + destinationList.push_back(*containees); + ++containees; + } + else + { + if ( groupIter != groupEnd ) + { + if ( !(destinationList.size() > prevGroupListSize )) + { + addGroupSeperator = true; + } + copyList( (*groupIter)->controls(), destinationList, addGroupSeperator ); + ++groupIter; + prevGroupListSize = destinationList.size(); + } + } + } + } + else + { + destinationList = sourceList; + } + return destinationList; + +} + + +void RBGroupManager::addSeperator( std::vector< OCX_Control* >& dest ) +{ + OCX_Control* seperator = new OCX_CommandButton; + seperator->SetInDialog(true); + seperator->sName = C2S("GroupSeperator"); + dest.push_back( seperator ); +} + +void RBGroupManager::copyList( std::vector< OCX_Control* >& src, + std::vector< OCX_Control* >& dest, + bool addGroupSeperator ) +{ + if ( addGroupSeperator ) + { + addSeperator( dest ); + } + + for ( CtrlIterator rbIter = src.begin(); rbIter != src.end(); ++rbIter ) + { + dest.push_back( *rbIter ); + } +} + +class OCX_UserFormLabel : public OCX_Label +{ +public: + OCX_UserFormLabel(OCX_Control* pParent ) : OCX_Label( pParent ) + { + mnForeColor = 0x80000012L; + mnBackColor = 0x8000000FL; + } +}; + + +sal_uInt16 OCX_Control::nStandardId(0x0200); +sal_uInt16 OCX_FontData::nStandardId(0x0200); + +sal_uInt32 OCX_Control::pColor[25] = { +0xC0C0C0, 0x008080, 0x000080, 0x808080, 0xC0C0C0, 0xFFFFFF, 0x000000, +0x000000, 0x000000, 0xFFFFFF, 0xC0C0C0, 0xC0C0C0, 0x808080, 0x000080, +0xFFFFFF, 0xC0C0C0, 0x808080, 0x808080, 0x000000, 0xC0C0C0, 0xFFFFFF, +0x000000, 0xC0C0C0, 0x000000, 0xFFFFC0 }; + +void OCX_Control::FillSystemColors() +{ + // overwrite the predefined colors with available system colors + const StyleSettings& rSett = Application::GetSettings().GetStyleSettings(); + + pColor[ 0x00 ] = rSett.GetFaceColor().GetColor(); + pColor[ 0x01 ] = rSett.GetWorkspaceColor().GetColor(); + pColor[ 0x02 ] = rSett.GetActiveColor().GetColor(); + pColor[ 0x03 ] = rSett.GetDeactiveColor().GetColor(); + pColor[ 0x04 ] = rSett.GetMenuBarColor().GetColor(); + pColor[ 0x05 ] = rSett.GetWindowColor().GetColor(); + pColor[ 0x07 ] = rSett.GetMenuTextColor().GetColor(); + pColor[ 0x08 ] = rSett.GetWindowTextColor().GetColor(); + pColor[ 0x09 ] = rSett.GetActiveTextColor().GetColor(); + pColor[ 0x0A ] = rSett.GetActiveBorderColor().GetColor(); + pColor[ 0x0B ] = rSett.GetDeactiveBorderColor().GetColor(); + pColor[ 0x0C ] = rSett.GetWorkspaceColor().GetColor(); + pColor[ 0x0D ] = rSett.GetHighlightColor().GetColor(); + pColor[ 0x0E ] = rSett.GetHighlightTextColor().GetColor(); + pColor[ 0x0F ] = rSett.GetFaceColor().GetColor(); + pColor[ 0x10 ] = rSett.GetShadowColor().GetColor(); + pColor[ 0x12 ] = rSett.GetButtonTextColor().GetColor(); + pColor[ 0x13 ] = rSett.GetDeactiveTextColor().GetColor(); + pColor[ 0x14 ] = rSett.GetHighlightColor().GetColor(); + pColor[ 0x15 ] = rSett.GetDarkShadowColor().GetColor(); + pColor[ 0x16 ] = rSett.GetShadowColor().GetColor(); + pColor[ 0x17 ] = rSett.GetHelpTextColor().GetColor(); + pColor[ 0x18 ] = rSett.GetHelpColor().GetColor(); +} + +sal_uInt32 OCX_Control::ImportColor(sal_uInt32 nColor) const +{ + sal_uInt8 nUpper = (sal_uInt8)( nColor >> 24 ); + if (nUpper & 0x80) //Palette color, should be switch on bottom 24 bits + { + /*Might as well use my systems ones in the absence of any other ideas*/ + nColor = nColor&0x00FFFFFF; + DBG_ASSERT (nColor <= 24,"Unknown Palette Index"); + if (nColor > 24) + nColor = 0xFFFFFF; + else + nColor = pColor[nColor]; + } + else + { + //Stored in bgr! rather than rgb + nColor = SwapColor(nColor); + } + return nColor; +} + +sal_Int16 OCX_FontData::ImportAlign(sal_uInt8 _nJustification) const +{ + sal_Int16 nRet; + switch (_nJustification) + { + default: + case 1: + nRet = 0; + break; + case 2: + nRet = 2; + break; + case 3: + nRet = 1; + break; + } + return nRet; +} + +sal_uInt8 OCX_FontData::ExportAlign(sal_Int16 nAlign) const +{ + sal_Int8 nRet; + switch (nAlign) + { + default: + case 0: + nRet = 1; + break; + case 2: + nRet = 2; + break; + case 1: + nRet = 3; + break; + } + return nRet; +} + +sal_uInt32 OCX_Control::SwapColor(sal_uInt32 nColor) const +{ + sal_uInt8 + r(static_cast<sal_uInt8>(nColor&0xFF)), + g(static_cast<sal_uInt8>(((nColor)>>8)&0xFF)), + b(static_cast<sal_uInt8>((nColor>>16)&0xFF)); + nColor = (r<<16) + (g<<8) + b; + return nColor; +} + +sal_uInt32 OCX_Control::ExportColor(sal_uInt32 nColor) const +{ + sal_uInt8 nUpper = (sal_uInt8)( nColor >> 24 ); + if (nUpper & 0x80) //Palette color, should be switch on bottom 24 bits + { + /*Might as well use my systems ones in the absence of any other ideas*/ + nColor = nColor&0x00FFFFFF; + DBG_ASSERT (nColor <= 24,"Unknown Palette Index"); + if (nColor > 24) + nColor = 0xFFFFFF; + else + nColor = pColor[nColor]; + } + + //Stored in bgr! rather than rgb + nColor = SwapColor(nColor); + return nColor; +} + +sal_Bool OCX_Control::Import( + const uno::Reference< lang::XMultiServiceFactory > &rServiceFactory, + uno::Reference< form::XFormComponent > &rFComp, awt::Size &rSz) +{ + + if(msFormType.getLength() == 0) + return sal_False; + + rSz.Width = nWidth; + rSz.Height = nHeight; + + uno::Reference<uno::XInterface> xCreate = + rServiceFactory->createInstance(msFormType); + if (!xCreate.is()) + return sal_False; + + rFComp = uno::Reference<form::XFormComponent>(xCreate,uno::UNO_QUERY); + if (!rFComp.is()) + return sal_False; + uno::Reference<beans::XPropertySet> xPropSet(xCreate,uno::UNO_QUERY); + if (!xPropSet.is()) + return sal_False; + return Import(xPropSet); +} + +sal_Bool OCX_Control::Import(uno::Reference<container::XNameContainer> &rDialog + ) +{ + uno::Reference<lang::XMultiServiceFactory> + xFactory(rDialog, uno::UNO_QUERY); + + uno::Reference<uno::XInterface> xCreate = + xFactory->createInstance(msDialogType); + if (!xCreate.is()) + return sal_False; + + uno::Reference<awt::XControlModel> xModel(xCreate, uno::UNO_QUERY); + if (!xModel.is()) + return sal_False; + + /* #147900# sometimes insertion of a control fails due to existing name, + do not break entire form import then... */ + try + { + rDialog->insertByName(sName, uno::makeAny(xModel)); + } + catch( uno::Exception& ) + { + DBG_ERRORFILE( + ByteString( "OCX_Control::Import - cannot insert control \"" ). + Append( ByteString( sName, RTL_TEXTENCODING_UTF8 ) ). + Append( '"' ).GetBuffer() ); + } + + uno::Reference<beans::XPropertySet> xPropSet(xCreate, uno::UNO_QUERY); + if (!xPropSet.is()) + return sal_False; + + if (!Import(xPropSet)) + return sal_False; + + uno::Any aTmp; + aTmp <<= sal_Int32((mnLeft * 2) / 100); + xPropSet->setPropertyValue(WW8_ASCII2STR("PositionX"), aTmp); + aTmp <<= sal_Int32((mnTop * 2) / 100); + xPropSet->setPropertyValue(WW8_ASCII2STR("PositionY"), aTmp); + aTmp <<= sal_Int32((nWidth * 2) / 100); + xPropSet->setPropertyValue(WW8_ASCII2STR("Width"), aTmp); + aTmp <<= sal_Int32((nHeight * 2) / 100); + xPropSet->setPropertyValue(WW8_ASCII2STR("Height"), aTmp); + if ( msToolTip.Len() > 0 ) + xPropSet->setPropertyValue(WW8_ASCII2STR("HelpText"), uno::Any(OUString(msToolTip))); + + if ( mnStep ) + { + aTmp <<= mnStep; + xPropSet->setPropertyValue(WW8_ASCII2STR("Step"), aTmp); + } + + try + { + xPropSet->setPropertyValue(WW8_ASCII2STR("EnableVisible"), uno::makeAny( mbVisible ) ); + } + catch( uno::Exception& ) + { + } + return sal_True; +} + +sal_Int16 OCX_Control::ImportBorder(sal_uInt16 nSpecialEffect, + sal_uInt16 nBorderStyle) const +{ + if ((nSpecialEffect == 0) && (nBorderStyle == 0)) + return 0; //No Border + else if ((nSpecialEffect == 0) && (nBorderStyle == 1)) + return 2; //Flat Border + return 1; //3D Border +} + +sal_uInt8 OCX_Control::ExportBorder(sal_uInt16 nBorder,sal_uInt8 &rBorderStyle) + const +{ + sal_uInt8 nRet; + switch(nBorder) + { + case 0: + nRet = rBorderStyle = 0; + break; + default: + case 1: + nRet = 2; + rBorderStyle = 0; + break; + case 2: + nRet = 0; + rBorderStyle = 1; + break; + } + return nRet; +} + +sal_Int16 OCX_Control::ImportSpecEffect( sal_uInt8 nSpecialEffect ) const +{ + return (nSpecialEffect == 0) ? 2 : 1; +} + +sal_uInt8 OCX_Control::ExportSpecEffect( sal_Int16 nApiEffect ) const +{ + return (nApiEffect == 2) ? 0 : 2; +} + +sal_Bool OCX_Control::ReadFontData(SvStorageStream *pS) +{ + return aFontData.Read(pS); +} + + +const uno::Reference< drawing::XDrawPage >& + SvxMSConvertOCXControls::GetDrawPage() +{ + if( !xDrawPage.is() && pDocSh ) + { + uno::Reference< drawing::XDrawPageSupplier > xTxtDoc(pDocSh->GetModel(), + uno::UNO_QUERY); + DBG_ASSERT(xTxtDoc.is(),"XDrawPageSupplier nicht vom XModel erhalten"); + xDrawPage = xTxtDoc->getDrawPage(); + DBG_ASSERT( xDrawPage.is(), "XDrawPage nicht erhalten" ); + } + + return xDrawPage; +} + + +const uno::Reference< lang::XMultiServiceFactory >& + SvxMSConvertOCXControls::GetServiceFactory() +{ + if( !xServiceFactory.is() && pDocSh ) + { + xServiceFactory = uno::Reference< lang::XMultiServiceFactory > + (pDocSh->GetBaseModel(), uno::UNO_QUERY); + DBG_ASSERT( xServiceFactory.is(), + "XMultiServiceFactory nicht vom Model erhalten" ); + } + + return xServiceFactory; +} + +const uno::Reference< drawing::XShapes >& SvxMSConvertOCXControls::GetShapes() +{ + if( !xShapes.is() ) + { + GetDrawPage(); + if( xDrawPage.is() ) + { + + xShapes = uno::Reference< drawing::XShapes >(xDrawPage, + uno::UNO_QUERY); + DBG_ASSERT( xShapes.is(), "XShapes nicht vom XDrawPage erhalten" ); + } + } + return xShapes; +} + +const uno::Reference< container::XIndexContainer >& + SvxMSConvertOCXControls::GetFormComps() +{ + if( !xFormComps.is() ) + { + GetDrawPage(); + if( xDrawPage.is() ) + { + uno::Reference< form::XFormsSupplier > xFormsSupplier( xDrawPage, + uno::UNO_QUERY ); + DBG_ASSERT( xFormsSupplier.is(), + "XFormsSupplier nicht vom XDrawPage erhalten" ); + + uno::Reference< container::XNameContainer > xNameCont = + xFormsSupplier->getForms(); + + // Das Formular bekommt einen Namen wie "WW-Standard[n]" und + // wird in jedem Fall neu angelegt. + UniString sName( sWW8_form, RTL_TEXTENCODING_MS_1252 ); + sal_uInt16 n = 0; + + while( xNameCont->hasByName( sName ) ) + { + sName.AssignAscii( sWW8_form ); + sName += String::CreateFromInt32( ++n ); + } + + const uno::Reference< lang::XMultiServiceFactory > &rServiceFactory + = GetServiceFactory(); + if( !rServiceFactory.is() ) + return xFormComps; + + uno::Reference< uno::XInterface > xCreate = + rServiceFactory->createInstance(WW8_ASCII2STR( + "com.sun.star.form.component.Form")); + if( xCreate.is() ) + { + uno::Reference< beans::XPropertySet > xFormPropSet( xCreate, + uno::UNO_QUERY ); + + uno::Any aTmp(&sName,getCppuType((OUString *)0)); + xFormPropSet->setPropertyValue( WW8_ASCII2STR("Name"), aTmp ); + + uno::Reference< form::XForm > xForm( xCreate, uno::UNO_QUERY ); + DBG_ASSERT(xForm.is(), "keine Form?"); + + uno::Reference< container::XIndexContainer > xForms( xNameCont, + uno::UNO_QUERY ); + DBG_ASSERT( xForms.is(), "XForms nicht erhalten" ); + + aTmp.setValue( &xForm, + ::getCppuType((uno::Reference < form::XForm >*)0)); + xForms->insertByIndex( xForms->getCount(), aTmp ); + + xFormComps = uno::Reference< container::XIndexContainer > + (xCreate, uno::UNO_QUERY); + } + } + } + + return xFormComps; +} + +sal_Bool OCX_CommandButton::Import( com::sun::star::uno::Reference< + com::sun::star::beans::XPropertySet> &rPropSet) +{ + uno::Any aTmp(&sName,getCppuType((OUString *)0)); + rPropSet->setPropertyValue( WW8_ASCII2STR("Name"), aTmp ); + + aTmp <<= ImportColor(mnForeColor); + rPropSet->setPropertyValue( WW8_ASCII2STR("TextColor"), aTmp); + + // fake transparent push button by setting window background color + if( !fBackStyle ) + mnBackColor = 0x80000005; + aTmp <<= ImportColor(mnBackColor); + rPropSet->setPropertyValue( WW8_ASCII2STR("BackgroundColor"), aTmp); + + sal_Bool bTemp; + if ((!(fEnabled)) || (fLocked)) + bTemp = sal_False; + else + bTemp = sal_True; + aTmp = bool2any(bTemp); + + rPropSet->setPropertyValue( WW8_ASCII2STR("Enabled"), aTmp); + + bTemp = fWordWrap != 0; + aTmp = bool2any(bTemp); + rPropSet->setPropertyValue( WW8_ASCII2STR("MultiLine"), aTmp); + + if (pCaption) + { + aTmp <<= lclCreateOUString( pCaption, nCaptionLen ); + rPropSet->setPropertyValue( WW8_ASCII2STR("Label"), aTmp); + } + + aTmp = bool2any( mbTakeFocus ); + rPropSet->setPropertyValue( WW8_ASCII2STR( "FocusOnClick" ), aTmp ); + + aFontData.Import(rPropSet); + return sal_True; +} + +sal_Bool OCX_GroupBox::Export(SvStorageRef& /* rObj */, + const uno::Reference< beans::XPropertySet >& /* rPropSet */, + const awt::Size& /* rSize */ ) +{ + sal_Bool bRet=sal_True; + return bRet; +} + +sal_Bool OCX_GroupBox::WriteContents(SvStorageStreamRef& /* rObj */, + const uno::Reference< beans::XPropertySet >& /* rPropSet */, + const awt::Size& /* rSize */) +{ + sal_Bool bRet=sal_True; + return bRet; +} + +sal_Bool OCX_CommandButton::WriteContents(SvStorageStreamRef& rContents, + const uno::Reference< beans::XPropertySet >& rPropSet, + const awt::Size& rSize ) +{ + sal_Bool bRet=sal_True; + + sal_uInt32 nOldPos = rContents->Tell(); + rContents->SeekRel(8); + + uno::Any aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("TextColor")); + if (aTmp.hasValue()) + aTmp >>= mnForeColor; + *rContents << ExportColor(mnForeColor); + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("BackgroundColor")); + if (aTmp.hasValue()) + aTmp >>= mnBackColor; + *rContents << ExportColor(mnBackColor); + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("Enabled")); + fEnabled = any2bool(aTmp); + sal_uInt8 nTemp=0;//fEnabled; + if (fEnabled) + nTemp |= 0x02; + if (fBackStyle) + nTemp |= 0x08; + *rContents << nTemp; + *rContents << sal_uInt8(0x00); + + nTemp = 0; + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("MultiLine")); + fWordWrap = any2bool(aTmp); + if (fWordWrap) + nTemp |= 0x80; + *rContents << nTemp; + *rContents << sal_uInt8(0x00); + + SvxOcxString aCaption( rPropSet->getPropertyValue(WW8_ASCII2STR("Label")) ); + aCaption.WriteLenField( *rContents ); + aCaption.WriteCharArray( *rContents ); + + WriteAlign(rContents,4); + + *rContents << rSize.Width; + *rContents << rSize.Height; + + // "take focus on click" is directly in content flags, not in option field... + mbTakeFocus = any2bool( rPropSet->getPropertyValue( WW8_ASCII2STR( "FocusOnClick" ) ) ); + + nFixedAreaLen = static_cast<sal_uInt16>(rContents->Tell()-nOldPos-4); + + bRet = aFontData.Export(rContents,rPropSet); + + rContents->Seek(nOldPos); + *rContents << nStandardId; + *rContents << nFixedAreaLen; + + sal_uInt8 nTmp = 0x27; + if (aCaption.HasData()) + nTmp |= 0x08; + *rContents << nTmp; + nTmp = 0x00; + if( !mbTakeFocus ) // flag is set, if option is off + nTmp |= 0x02; + *rContents << nTmp; + *rContents << sal_uInt8(0x00); + *rContents << sal_uInt8(0x00); + + DBG_ASSERT((rContents.Is() && (SVSTREAM_OK==rContents->GetError())),"damn"); + return bRet; +} + + + +sal_Bool OCX_CommandButton::Export(SvStorageRef &rObj, + const uno::Reference< beans::XPropertySet > &rPropSet, + const awt::Size &rSize) +{ + static sal_uInt8 __READONLY_DATA aCompObj[] = { + 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0x32, 0x05, 0xD7, + 0x69, 0xCE, 0xCD, 0x11, 0xA7, 0x77, 0x00, 0xDD, + 0x01, 0x14, 0x3C, 0x57, 0x22, 0x00, 0x00, 0x00, + 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, + 0x74, 0x20, 0x46, 0x6F, 0x72, 0x6d, 0x73, 0x20, + 0x32, 0x2e, 0x30, 0x20, 0x43, 0x6F, 0x6D, 0x6D, + 0x61, 0x6E, 0x64, 0x42, 0x75, 0x74, 0x74, 0x6F, + 0x6E, 0x00, 0x10, 0x00, 0x00, 0x00, 0x45, 0x6D, + 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x20, 0x4F, + 0x62, 0x6A, 0x65, 0x63, 0x74, 0x00, 0x16, 0x00, + 0x00, 0x00, 0x46, 0x6F, 0x72, 0x6D, 0x73, 0x2E, + 0x43, 0x6F, 0x6D, 0x6D, 0x61, 0x6E, 0x64, 0x42, + 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x2E, 0x31, 0x00, + 0xF4, 0x39, 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor( rObj->OpenSotStream( C2S("\1CompObj"))); + xStor->Write(aCompObj,sizeof(aCompObj)); + DBG_ASSERT((xStor.Is() && (SVSTREAM_OK == xStor->GetError())),"damn"); + } + + { + SvStorageStreamRef xStor3( rObj->OpenSotStream( C2S("\3ObjInfo"))); + xStor3->Write(aObjInfo,sizeof(aObjInfo)); + DBG_ASSERT((xStor3.Is() && (SVSTREAM_OK == xStor3->GetError())),"damn"); + } + + static sal_uInt8 __READONLY_DATA aOCXNAME[] = { + 0x43, 0x00, 0x6F, 0x00, 0x6D, 0x00, 0x6D, 0x00, + 0x61, 0x00, 0x6E, 0x00, 0x64, 0x00, 0x42, 0x00, + 0x75, 0x00, 0x74, 0x00, 0x74, 0x00, 0x6F, 0x00, + 0x6E, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor2( rObj->OpenSotStream( C2S("\3OCXNAME"))); + xStor2->Write(aOCXNAME,sizeof(aOCXNAME)); + DBG_ASSERT((xStor2.Is() && (SVSTREAM_OK == xStor2->GetError())),"damn"); + } + + SvStorageStreamRef xContents( rObj->OpenSotStream( C2S("contents"))); + + return WriteContents(xContents,rPropSet,rSize); +} + +sal_Bool OCX_ImageButton::WriteContents(SvStorageStreamRef &rContents, + const uno::Reference< beans::XPropertySet > &rPropSet, + const awt::Size &rSize) +{ + sal_Bool bRet=sal_True; + + sal_uInt32 nOldPos = rContents->Tell(); + rContents->SeekRel(8); + + uno::Any aTmp=rPropSet->getPropertyValue(WW8_ASCII2STR("BackgroundColor")); + if (aTmp.hasValue()) + aTmp >>= mnBackColor; + *rContents << ExportColor(mnBackColor); + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("Enabled")); + fEnabled = any2bool(aTmp); + sal_uInt8 nTemp=0;//fEnabled; + if (fEnabled) + nTemp |= 0x02; + *rContents << nTemp; + *rContents << sal_uInt8(0x00); + *rContents << sal_uInt8(0x00); + *rContents << sal_uInt8(0x00); + + WriteAlign(rContents,4); + + *rContents << rSize.Width; + *rContents << rSize.Height; + + nFixedAreaLen = static_cast<sal_uInt16>(rContents->Tell()-nOldPos-4); + + bRet = aFontData.Export(rContents,rPropSet); + + rContents->Seek(nOldPos); + *rContents << nStandardId; + *rContents << nFixedAreaLen; + + sal_uInt8 nTmp = 0x26; + *rContents << nTmp; + *rContents << sal_uInt8(0x00); + *rContents << sal_uInt8(0x00); + *rContents << sal_uInt8(0x00); + + DBG_ASSERT((rContents.Is() && (SVSTREAM_OK==rContents->GetError())),"damn"); + return bRet; +} + + + +sal_Bool OCX_ImageButton::Export(SvStorageRef &rObj, + const uno::Reference< beans::XPropertySet > &rPropSet, + const awt::Size &rSize) +{ + static sal_uInt8 __READONLY_DATA aCompObj[] = { + 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0x32, 0x05, 0xD7, + 0x69, 0xCE, 0xCD, 0x11, 0xA7, 0x77, 0x00, 0xDD, + 0x01, 0x14, 0x3C, 0x57, 0x22, 0x00, 0x00, 0x00, + 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, + 0x74, 0x20, 0x46, 0x6F, 0x72, 0x6d, 0x73, 0x20, + 0x32, 0x2e, 0x30, 0x20, 0x43, 0x6F, 0x6D, 0x6D, + 0x61, 0x6E, 0x64, 0x42, 0x75, 0x74, 0x74, 0x6F, + 0x6E, 0x00, 0x10, 0x00, 0x00, 0x00, 0x45, 0x6D, + 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x20, 0x4F, + 0x62, 0x6A, 0x65, 0x63, 0x74, 0x00, 0x16, 0x00, + 0x00, 0x00, 0x46, 0x6F, 0x72, 0x6D, 0x73, 0x2E, + 0x43, 0x6F, 0x6D, 0x6D, 0x61, 0x6E, 0x64, 0x42, + 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x2E, 0x31, 0x00, + 0xF4, 0x39, 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor( rObj->OpenSotStream( C2S("\1CompObj"))); + xStor->Write(aCompObj,sizeof(aCompObj)); + DBG_ASSERT((xStor.Is() && (SVSTREAM_OK == xStor->GetError())),"damn"); + } + + { + SvStorageStreamRef xStor3( rObj->OpenSotStream( C2S("\3ObjInfo"))); + xStor3->Write(aObjInfo,sizeof(aObjInfo)); + DBG_ASSERT((xStor3.Is() && (SVSTREAM_OK == xStor3->GetError())),"damn"); + } + + static sal_uInt8 __READONLY_DATA aOCXNAME[] = { + 0x43, 0x00, 0x6F, 0x00, 0x6D, 0x00, 0x6D, 0x00, + 0x61, 0x00, 0x6E, 0x00, 0x64, 0x00, 0x42, 0x00, + 0x75, 0x00, 0x74, 0x00, 0x74, 0x00, 0x6F, 0x00, + 0x6E, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor2( rObj->OpenSotStream( C2S("\3OCXNAME"))); + xStor2->Write(aOCXNAME,sizeof(aOCXNAME)); + DBG_ASSERT((xStor2.Is() && (SVSTREAM_OK == xStor2->GetError())),"damn"); + } + + SvStorageStreamRef xContents( rObj->OpenSotStream( C2S("contents"))); + return WriteContents(xContents,rPropSet,rSize); +} + + +sal_Bool OCX_OptionButton::Import(com::sun::star::uno::Reference< + com::sun::star::beans::XPropertySet> &rPropSet) +{ + uno::Any aTmp(&sName,getCppuType((OUString *)0)); + rPropSet->setPropertyValue( WW8_ASCII2STR("Name"), aTmp ); + + // background color: fBackStyle==0 -> transparent + if( fBackStyle ) + aTmp <<= ImportColor(mnBackColor); + else + aTmp = uno::Any(); + rPropSet->setPropertyValue( WW8_ASCII2STR("BackgroundColor"), aTmp); + + sal_Bool bTemp; + if ((!(fEnabled)) || (fLocked)) + bTemp = sal_False; + else + bTemp = sal_True; + aTmp = bool2any(bTemp); + rPropSet->setPropertyValue( WW8_ASCII2STR("Enabled"), aTmp); + + bTemp = fWordWrap != 0; + aTmp = bool2any(bTemp); + rPropSet->setPropertyValue( WW8_ASCII2STR("MultiLine"), aTmp); + + aTmp <<= ImportColor(mnForeColor); + rPropSet->setPropertyValue( WW8_ASCII2STR("TextColor"), aTmp); + + aTmp <<= ImportSpecEffect( nSpecialEffect ); + rPropSet->setPropertyValue( WW8_ASCII2STR("VisualEffect"), aTmp); + + if (pValue && !bSetInDialog) + { + sal_Int16 nTmp = pValue[0]-0x30; + aTmp <<= nTmp; + rPropSet->setPropertyValue( WW8_ASCII2STR("DefaultState"), aTmp); + } + + if (pCaption) + { + aTmp <<= lclCreateOUString( pCaption, nCaptionLen ); + rPropSet->setPropertyValue( WW8_ASCII2STR("Label"), aTmp); + } + + // #i40279# always centered vertically + aTmp <<= ::com::sun::star::style::VerticalAlignment_MIDDLE; + rPropSet->setPropertyValue( WW8_ASCII2STR("VerticalAlign"), aTmp ); + + aFontData.Import(rPropSet); + return sal_True; +} + +sal_Bool OCX_OptionButton::WriteContents(SvStorageStreamRef &rContents, + const uno::Reference< beans::XPropertySet > &rPropSet, + const awt::Size &rSize) +{ + sal_Bool bRet=sal_True; + + sal_uInt32 nOldPos = rContents->Tell(); + rContents->SeekRel(12); + + pBlockFlags[0] = 0; + pBlockFlags[1] = 0x01; + pBlockFlags[2] = 0; + pBlockFlags[3] = 0x80; + pBlockFlags[4] = 0; + pBlockFlags[5] = 0; + pBlockFlags[6] = 0; + pBlockFlags[7] = 0; + + uno::Any aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("Enabled")); + fEnabled = any2bool(aTmp); + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("BackgroundColor")); + if (aTmp.hasValue()) + aTmp >>= mnBackColor; + else + fBackStyle = 0; + + sal_uInt8 nTemp=0;//=fEnabled; + if (fEnabled) + nTemp |= 0x02; + if (fBackStyle) + nTemp |= 0x08; + *rContents << nTemp; + pBlockFlags[0] |= 0x01; + *rContents << sal_uInt8(0x00); + nTemp = 0; + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("MultiLine")); + fWordWrap = any2bool(aTmp); + if (fWordWrap) + nTemp |= 0x80; + *rContents << nTemp; + *rContents << sal_uInt8(0x00); + + *rContents << ExportColor(mnBackColor); + pBlockFlags[0] |= 0x02; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("TextColor")); + if (aTmp.hasValue()) + aTmp >>= mnForeColor; + *rContents << ExportColor(mnForeColor); + pBlockFlags[0] |= 0x04; + + nStyle = 5; + *rContents << nStyle; + pBlockFlags[0] |= 0x40; + + WriteAlign(rContents,4); + nValueLen = 1|SVX_MSOCX_COMPRESSED; + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("DefaultState")); + sal_Int16 nDefault = sal_Int16(); + aTmp >>= nDefault; + *rContents << nValueLen; + pBlockFlags[2] |= 0x40; + + + SvxOcxString aCaption( rPropSet->getPropertyValue(WW8_ASCII2STR("Label")) ); + if (aCaption.HasData()) + pBlockFlags[2] |= 0x80; + aCaption.WriteLenField( *rContents ); + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("VisualEffect")); + if (aTmp.hasValue()) + { + sal_Int16 nApiSpecEffect = sal_Int16(); + aTmp >>= nApiSpecEffect; + nSpecialEffect = ExportSpecEffect( nApiSpecEffect ); + } + *rContents << nSpecialEffect; + pBlockFlags[3] |= 0x04; + + WriteAlign(rContents,4); + *rContents << rSize.Width; + *rContents << rSize.Height; + + nDefault += 0x30; + *rContents << sal_uInt8(nDefault); + *rContents << sal_uInt8(0x00); + + aCaption.WriteCharArray( *rContents ); + + WriteAlign(rContents,4); + nFixedAreaLen = static_cast<sal_uInt16>(rContents->Tell()-nOldPos-4); + bRet = aFontData.Export(rContents,rPropSet); + + rContents->Seek(nOldPos); + *rContents << nStandardId; + *rContents << nFixedAreaLen; + + *rContents << pBlockFlags[0]; + *rContents << pBlockFlags[1]; + *rContents << pBlockFlags[2]; + *rContents << pBlockFlags[3]; + *rContents << pBlockFlags[4]; + *rContents << pBlockFlags[5]; + *rContents << pBlockFlags[6]; + *rContents << pBlockFlags[7]; + + DBG_ASSERT((rContents.Is() && + (SVSTREAM_OK==rContents->GetError())),"damn"); + return bRet; +} + + + +sal_Bool OCX_OptionButton::Export(SvStorageRef &rObj, + const uno::Reference< beans::XPropertySet > &rPropSet, + const awt::Size &rSize) +{ + static sal_uInt8 __READONLY_DATA aCompObj[] = { + 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x50, 0x1D, 0xD2, 0x8B, + 0x42, 0xEC, 0xCE, 0x11, 0x9E, 0x0D, 0x00, 0xAA, + 0x00, 0x60, 0x02, 0xF3, 0x21, 0x00, 0x00, 0x00, + 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, + 0x74, 0x20, 0x46, 0x6F, 0x72, 0x6D, 0x73, 0x20, + 0x32, 0x2E, 0x30, 0x20, 0x4F, 0x70, 0x74, 0x69, + 0x6F, 0x6E, 0x42, 0x75, 0x74, 0x74, 0x6F, 0x6E, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x45, 0x6D, 0x62, + 0x65, 0x64, 0x64, 0x65, 0x64, 0x20, 0x4F, 0x62, + 0x6A, 0x65, 0x63, 0x74, 0x00, 0x15, 0x00, 0x00, + 0x00, 0x46, 0x6F, 0x72, 0x6D, 0x73, 0x2E, 0x4F, + 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x42, 0x75, 0x74, + 0x74, 0x6F, 0x6E, 0x2E, 0x31, 0x00, 0xF4, 0x39, + 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor( rObj->OpenSotStream( C2S("\1CompObj"))); + xStor->Write(aCompObj,sizeof(aCompObj)); + DBG_ASSERT((xStor.Is() && (SVSTREAM_OK == xStor->GetError())),"damn"); + } + + { + SvStorageStreamRef xStor3( rObj->OpenSotStream( C2S("\3ObjInfo"))); + xStor3->Write(aObjInfo,sizeof(aObjInfo)); + DBG_ASSERT((xStor3.Is() && (SVSTREAM_OK == xStor3->GetError())),"damn"); + } + + static sal_uInt8 __READONLY_DATA aOCXNAME[] = { + 0x4F, 0x00, 0x70, 0x00, 0x74, 0x00, 0x69, 0x00, + 0x6F, 0x00, 0x6E, 0x00, 0x42, 0x00, 0x75, 0x00, + 0x74, 0x00, 0x74, 0x00, 0x6F, 0x00, 0x6E, 0x00, + 0x31, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor2( rObj->OpenSotStream( C2S("\3OCXNAME"))); + xStor2->Write(aOCXNAME,sizeof(aOCXNAME)); + DBG_ASSERT((xStor2.Is() && (SVSTREAM_OK == xStor2->GetError())),"damn"); + } + + SvStorageStreamRef xContents( rObj->OpenSotStream( C2S("contents"))); + return WriteContents(xContents, rPropSet, rSize); +} + + +sal_Bool OCX_TextBox::Import(com::sun::star::uno::Reference< + com::sun::star::beans::XPropertySet> &rPropSet) +{ + uno::Any aTmp(&sName,getCppuType((OUString *)0)); + rPropSet->setPropertyValue( WW8_ASCII2STR("Name"), aTmp ); + + aTmp = bool2any( fEnabled != 0 ); + rPropSet->setPropertyValue( WW8_ASCII2STR("Enabled"), aTmp); + + aTmp = bool2any( fLocked != 0 ); + rPropSet->setPropertyValue( WW8_ASCII2STR("ReadOnly"), aTmp); + + aTmp = bool2any( fHideSelection != 0 ); + rPropSet->setPropertyValue( WW8_ASCII2STR( "HideInactiveSelection" ), aTmp); + + aTmp <<= ImportColor(mnForeColor); + rPropSet->setPropertyValue( WW8_ASCII2STR("TextColor"), aTmp); + + aTmp <<= ImportColor(mnBackColor); + rPropSet->setPropertyValue( WW8_ASCII2STR("BackgroundColor"), aTmp); + + aTmp <<= ImportBorder(nSpecialEffect,nBorderStyle); + rPropSet->setPropertyValue( WW8_ASCII2STR("Border"), aTmp); + + aTmp <<= ImportColor( nBorderColor ); + rPropSet->setPropertyValue( WW8_ASCII2STR("BorderColor"), aTmp); + + aTmp = bool2any( fMultiLine != 0 ); + rPropSet->setPropertyValue( WW8_ASCII2STR("MultiLine"), aTmp); + + sal_uInt16 nTmp = static_cast<sal_uInt16>(nMaxLength); + aTmp <<= nTmp; + rPropSet->setPropertyValue( WW8_ASCII2STR("MaxTextLen"), aTmp); + + + sal_Bool bTemp1,bTemp2; + uno::Any aBarsH,aBarsV; + switch(nScrollBars) + { + case 1: + bTemp1 = sal_True; + bTemp2 = sal_False; + break; + case 2: + bTemp1 = sal_False; + bTemp2 = sal_True; + break; + case 3: + bTemp1 = sal_True; + bTemp2 = sal_True; + break; + case 0: + default: + bTemp1 = sal_False; + bTemp2 = sal_False; + break; + } + + aBarsH = bool2any(bTemp1); + aBarsV = bool2any(bTemp2); + rPropSet->setPropertyValue( WW8_ASCII2STR("HScroll"), aBarsH); + rPropSet->setPropertyValue( WW8_ASCII2STR("VScroll"), aBarsV); + + nTmp = nPasswordChar; + aTmp <<= nTmp; + rPropSet->setPropertyValue( WW8_ASCII2STR("EchoChar"), aTmp); + + if (pValue) + { + aTmp <<= lclCreateOUString( pValue, nValueLen ); + // DefaultText seems to no longer be in UnoEditControlModel + if ( bSetInDialog ) + { + rPropSet->setPropertyValue( WW8_ASCII2STR("Text"), aTmp); + } + else + { + rPropSet->setPropertyValue( WW8_ASCII2STR("DefaultText"), aTmp); + } + } + + aFontData.Import(rPropSet); + return sal_True; +} + +sal_Bool OCX_TextBox::WriteContents(SvStorageStreamRef &rContents, + const uno::Reference< beans::XPropertySet > &rPropSet, + const awt::Size &rSize) +{ + sal_Bool bRet=sal_True; + sal_uInt32 nOldPos = rContents->Tell(); + rContents->SeekRel(12); + + pBlockFlags[0] = 0; + pBlockFlags[1] = 0x01; + pBlockFlags[2] = 0x00; + pBlockFlags[3] = 0x80; + pBlockFlags[4] = 0; + pBlockFlags[5] = 0; + pBlockFlags[6] = 0; + pBlockFlags[7] = 0; + + + sal_uInt8 nTemp=0x19; + uno::Any aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("Enabled")); + fEnabled = any2bool(aTmp); + if (fEnabled) + nTemp |= 0x02; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("ReadOnly")); + fLocked = any2bool(aTmp); + if (fLocked) + nTemp |= 0x04; + + *rContents << nTemp; + pBlockFlags[0] |= 0x01; + *rContents << sal_uInt8(0x48); + *rContents << sal_uInt8(0x80); + + fMultiLine = any2bool(rPropSet->getPropertyValue(WW8_ASCII2STR("MultiLine"))); + fHideSelection = any2bool(rPropSet->getPropertyValue(WW8_ASCII2STR("HideInactiveSelection"))); + nTemp = 0x0C; + if (fMultiLine) + nTemp |= 0x80; + if( fHideSelection ) + nTemp |= 0x20; + *rContents << nTemp; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("BackgroundColor")); + if (aTmp.hasValue()) + aTmp >>= mnBackColor; + *rContents << ExportColor(mnBackColor); + pBlockFlags[0] |= 0x02; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("TextColor")); + if (aTmp.hasValue()) + aTmp >>= mnForeColor; + *rContents << ExportColor(mnForeColor); + pBlockFlags[0] |= 0x04; + + aTmp = rPropSet->getPropertyValue( WW8_ASCII2STR("MaxTextLen")); + aTmp >>= nMaxLength; + *rContents << nMaxLength; + pBlockFlags[0] |= 0x08; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("Border")); + sal_Int16 nBorder = sal_Int16(); + aTmp >>= nBorder; + nSpecialEffect = ExportBorder(nBorder,nBorderStyle); + *rContents << nBorderStyle; + pBlockFlags[0] |= 0x10; + + aTmp = rPropSet->getPropertyValue( WW8_ASCII2STR("HScroll")); + sal_Bool bTemp1 = any2bool(aTmp); + aTmp = rPropSet->getPropertyValue( WW8_ASCII2STR("VScroll")); + sal_Bool bTemp2 = any2bool(aTmp); + if (!bTemp1 && !bTemp2) + nScrollBars =0; + else if (bTemp1 && bTemp2) + nScrollBars = 3; + else if (!bTemp1 && bTemp2) + nScrollBars = 2; + else + nScrollBars = 1; + *rContents << nScrollBars; + pBlockFlags[0] |= 0x20; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("EchoChar")); + sal_uInt16 nTmp = sal_uInt16(); + aTmp >>= nTmp; + nPasswordChar = static_cast<sal_uInt8>(nTmp); + *rContents << nPasswordChar; + pBlockFlags[1] |= 0x02; + + SvxOcxString aValue( rPropSet->getPropertyValue(WW8_ASCII2STR("DefaultText")) ); + aValue.WriteLenField( *rContents ); + if (aValue.HasData()) + pBlockFlags[2] |= 0x40; + + WriteAlign(rContents,4); + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("BorderColor")); + if (aTmp.hasValue()) + aTmp >>= nBorderColor; + *rContents << ExportColor(nBorderColor); + pBlockFlags[3] |= 0x02; + + *rContents << nSpecialEffect; + pBlockFlags[3] |= 0x04; + + WriteAlign(rContents,4); + *rContents << rSize.Width; + *rContents << rSize.Height; + + aValue.WriteCharArray( *rContents ); + + WriteAlign(rContents,4); + + nFixedAreaLen = static_cast<sal_uInt16>(rContents->Tell()-nOldPos-4); + + bRet = aFontData.Export(rContents,rPropSet); + + rContents->Seek(nOldPos); + *rContents << nStandardId; + *rContents << nFixedAreaLen; + + *rContents << pBlockFlags[0]; + *rContents << pBlockFlags[1]; + *rContents << pBlockFlags[2]; + *rContents << pBlockFlags[3]; + *rContents << pBlockFlags[4]; + *rContents << pBlockFlags[5]; + *rContents << pBlockFlags[6]; + *rContents << pBlockFlags[7]; + + DBG_ASSERT((rContents.Is() && + (SVSTREAM_OK == rContents->GetError())),"damn"); + return bRet; +} + + +sal_Bool OCX_TextBox::Export(SvStorageRef &rObj, + const uno::Reference< beans::XPropertySet > &rPropSet, + const awt::Size &rSize) +{ + static sal_uInt8 __READONLY_DATA aCompObj[] = { + 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x10, 0x1D, 0xD2, 0x8B, + 0x42, 0xEC, 0xCE, 0x11, 0x9E, 0x0D, 0x00, 0xAA, + 0x00, 0x60, 0x02, 0xF3, 0x1C, 0x00, 0x00, 0x00, + 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, + 0x74, 0x20, 0x46, 0x6F, 0x72, 0x6D, 0x73, 0x20, + 0x32, 0x2E, 0x30, 0x20, 0x54, 0x65, 0x78, 0x74, + 0x42, 0x6F, 0x78, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x45, 0x6D, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, + 0x20, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x46, 0x6F, 0x72, 0x6D, + 0x73, 0x2E, 0x54, 0x65, 0x78, 0x74, 0x42, 0x6F, + 0x78, 0x2E, 0x31, 0x00, 0xF4, 0x39, 0xB2, 0x71, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor( rObj->OpenSotStream( C2S("\1CompObj"))); + xStor->Write(aCompObj,sizeof(aCompObj)); + DBG_ASSERT((xStor.Is() && (SVSTREAM_OK == xStor->GetError())),"damn"); + } + + { + SvStorageStreamRef xStor3( rObj->OpenSotStream( C2S("\3ObjInfo"))); + xStor3->Write(aObjInfo,sizeof(aObjInfo)); + DBG_ASSERT((xStor3.Is() && (SVSTREAM_OK == xStor3->GetError())),"damn"); + } + + static sal_uInt8 __READONLY_DATA aOCXNAME[] = { + 0x54, 0x00, 0x65, 0x00, 0x78, 0x00, 0x74, 0x00, + 0x42, 0x00, 0x6F, 0x00, 0x78, 0x00, 0x31, 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor2( rObj->OpenSotStream( C2S("\3OCXNAME"))); + xStor2->Write(aOCXNAME,sizeof(aOCXNAME)); + DBG_ASSERT((xStor2.Is() && (SVSTREAM_OK == xStor2->GetError())),"damn"); + } + + SvStorageStreamRef xContents( rObj->OpenSotStream( C2S("contents"))); + return WriteContents(xContents, rPropSet, rSize); +} + +sal_Bool OCX_FieldControl::WriteContents(SvStorageStreamRef &rContents, + const uno::Reference< beans::XPropertySet > &rPropSet, + const awt::Size &rSize) +{ + sal_Bool bRet=sal_True; + sal_uInt32 nOldPos = rContents->Tell(); + rContents->SeekRel(12); + + pBlockFlags[0] = 0; + pBlockFlags[1] = 0x01; + pBlockFlags[2] = 0x00; + pBlockFlags[3] = 0x80; + pBlockFlags[4] = 0; + pBlockFlags[5] = 0; + pBlockFlags[6] = 0; + pBlockFlags[7] = 0; + + + sal_uInt8 nTemp=0x19; + uno::Any aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("Enabled")); + fEnabled = any2bool(aTmp); + if (fEnabled) + nTemp |= 0x02; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("ReadOnly")); + fLocked = any2bool(aTmp); + if (fLocked) + nTemp |= 0x04; + + *rContents << nTemp; + pBlockFlags[0] |= 0x01; + *rContents << sal_uInt8(0x48); + *rContents << sal_uInt8(0x80); + + nTemp = 0x2C; + *rContents << nTemp; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("BackgroundColor")); + if (aTmp.hasValue()) + aTmp >>= mnBackColor; + *rContents << ExportColor(mnBackColor); + pBlockFlags[0] |= 0x02; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("TextColor")); + if (aTmp.hasValue()) + aTmp >>= mnForeColor; + *rContents << ExportColor(mnForeColor); + pBlockFlags[0] |= 0x04; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("Border")); + sal_Int16 nBorder = sal_Int16(); + aTmp >>= nBorder; + nSpecialEffect = ExportBorder(nBorder,nBorderStyle); + *rContents << nBorderStyle; + pBlockFlags[0] |= 0x10; + +#if 0 //Each control has a different Value format, and how to convert each to text has to be found out + SvxOcxString aValue( rPropSet->getPropertyValue(WW8_ASCII2STR("DefaultText")) ); + aValue.WriteLenField( *rContents ); + if (aValue.HasData()) + pBlockFlags[2] |= 0x40; +#endif + + *rContents << nSpecialEffect; + pBlockFlags[3] |= 0x04; + + WriteAlign(rContents,4); + *rContents << rSize.Width; + *rContents << rSize.Height; + +#if 0 + aValue.WriteCharArray( *rContents ); +#endif + + WriteAlign(rContents,4); + + nFixedAreaLen = static_cast<sal_uInt16>(rContents->Tell()-nOldPos-4); + + bRet = aFontData.Export(rContents,rPropSet); + + rContents->Seek(nOldPos); + *rContents << nStandardId; + *rContents << nFixedAreaLen; + + *rContents << pBlockFlags[0]; + *rContents << pBlockFlags[1]; + *rContents << pBlockFlags[2]; + *rContents << pBlockFlags[3]; + *rContents << pBlockFlags[4]; + *rContents << pBlockFlags[5]; + *rContents << pBlockFlags[6]; + *rContents << pBlockFlags[7]; + + DBG_ASSERT((rContents.Is() && + (SVSTREAM_OK==rContents->GetError())),"damn"); + return bRet; +} + +sal_Bool OCX_FieldControl::Export(SvStorageRef &rObj, + const uno::Reference< beans::XPropertySet > &rPropSet, + const awt::Size &rSize) +{ + static sal_uInt8 __READONLY_DATA aCompObj[] = { + 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x10, 0x1D, 0xD2, 0x8B, + 0x42, 0xEC, 0xCE, 0x11, 0x9E, 0x0D, 0x00, 0xAA, + 0x00, 0x60, 0x02, 0xF3, 0x1C, 0x00, 0x00, 0x00, + 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, + 0x74, 0x20, 0x46, 0x6F, 0x72, 0x6D, 0x73, 0x20, + 0x32, 0x2E, 0x30, 0x20, 0x54, 0x65, 0x78, 0x74, + 0x42, 0x6F, 0x78, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x45, 0x6D, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, + 0x20, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x46, 0x6F, 0x72, 0x6D, + 0x73, 0x2E, 0x54, 0x65, 0x78, 0x74, 0x42, 0x6F, + 0x78, 0x2E, 0x31, 0x00, 0xF4, 0x39, 0xB2, 0x71, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor( rObj->OpenSotStream( C2S("\1CompObj"))); + xStor->Write(aCompObj,sizeof(aCompObj)); + DBG_ASSERT((xStor.Is() && (SVSTREAM_OK == xStor->GetError())),"damn"); + } + + { + SvStorageStreamRef xStor3( rObj->OpenSotStream( C2S("\3ObjInfo"))); + xStor3->Write(aObjInfo,sizeof(aObjInfo)); + DBG_ASSERT((xStor3.Is() && (SVSTREAM_OK == xStor3->GetError())),"damn"); + } + + static sal_uInt8 __READONLY_DATA aOCXNAME[] = { + 0x54, 0x00, 0x65, 0x00, 0x78, 0x00, 0x74, 0x00, + 0x42, 0x00, 0x6F, 0x00, 0x78, 0x00, 0x31, 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor2( rObj->OpenSotStream( C2S("\3OCXNAME"))); + xStor2->Write(aOCXNAME,sizeof(aOCXNAME)); + DBG_ASSERT((xStor2.Is() && (SVSTREAM_OK == xStor2->GetError())),"damn"); + } + + SvStorageStreamRef xContents( rObj->OpenSotStream( C2S("contents"))); + return WriteContents(xContents, rPropSet, rSize); +} + + + +sal_Bool OCX_ToggleButton::Import(com::sun::star::uno::Reference< + com::sun::star::beans::XPropertySet> &rPropSet) +{ + uno::Any aTmp(&sName,getCppuType((OUString *)0)); + rPropSet->setPropertyValue( WW8_ASCII2STR("Name"), aTmp ); + + aTmp = bool2any(true); + rPropSet->setPropertyValue( WW8_ASCII2STR("Toggle"), aTmp ); + + sal_Bool bTemp; + if ((!(fEnabled)) || (fLocked)) + bTemp = sal_False; + else + bTemp = sal_True; + aTmp = bool2any(bTemp); + rPropSet->setPropertyValue( WW8_ASCII2STR("Enabled"), aTmp); + + bTemp = fWordWrap != 0; + aTmp = bool2any(bTemp); + rPropSet->setPropertyValue( WW8_ASCII2STR("MultiLine"), aTmp); + + aTmp <<= ImportColor(mnForeColor); + rPropSet->setPropertyValue( WW8_ASCII2STR("TextColor"), aTmp); + + // fake transparent toggle button by setting window background color + if( !fBackStyle ) + mnBackColor = 0x80000005; + aTmp <<= ImportColor(mnBackColor); + rPropSet->setPropertyValue( WW8_ASCII2STR("BackgroundColor"), aTmp); + + if (pValue) + { + sal_Int16 nTmp=pValue[0]-0x30; + aTmp <<= nTmp == 1; + rPropSet->setPropertyValue( WW8_ASCII2STR("DefaultState"), aTmp); + } + + if (pCaption) + { + aTmp <<= lclCreateOUString( pCaption, nCaptionLen ); + rPropSet->setPropertyValue( WW8_ASCII2STR("Label"), aTmp); + } + + aFontData.Import(rPropSet); + return sal_True; +} + +sal_Bool OCX_ToggleButton::Export( + SvStorageRef &rObj, const uno::Reference< beans::XPropertySet> &rPropSet, + const awt::Size& rSize ) +{ + static sal_uInt8 __READONLY_DATA aCompObj[] = { + 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x60, 0x1D, 0xD2, 0x8B, + 0x42, 0xEC, 0xCE, 0x11, 0x9E, 0x0D, 0x00, 0xAA, + 0x00, 0x60, 0x02, 0xF3, 0x21, 0x00, 0x00, 0x00, + 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, + 0x74, 0x20, 0x46, 0x6F, 0x72, 0x6D, 0x73, 0x20, + 0x32, 0x2E, 0x30, 0x20, 0x54, 0x6F, 0x67, 0x67, + 0x6C, 0x65, 0x42, 0x75, 0x74, 0x74, 0x6F, 0x6E, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x45, 0x6D, 0x62, + 0x65, 0x64, 0x64, 0x65, 0x64, 0x20, 0x4F, 0x62, + 0x6A, 0x65, 0x63, 0x74, 0x00, 0x15, 0x00, 0x00, + 0x00, 0x46, 0x6F, 0x72, 0x6D, 0x73, 0x2E, 0x54, + 0x6F, 0x67, 0x67, 0x6C, 0x65, 0x42, 0x75, 0x74, + 0x74, 0x6F, 0x6E, 0x2E, 0x31, 0x00, 0xF4, 0x39, + 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor( rObj->OpenSotStream( C2S("\1CompObj"))); + xStor->Write(aCompObj,sizeof(aCompObj)); + DBG_ASSERT((xStor.Is() && (SVSTREAM_OK == xStor->GetError())),"damn"); + } + + { + SvStorageStreamRef xStor3( rObj->OpenSotStream( C2S("\3ObjInfo"))); + xStor3->Write(aObjInfo,sizeof(aObjInfo)); + DBG_ASSERT((xStor3.Is() && (SVSTREAM_OK == xStor3->GetError())),"damn"); + } + + static sal_uInt8 __READONLY_DATA aOCXNAME[] = { + 0x54, 0x00, 0x6F, 0x00, 0x67, 0x00, 0x67, 0x00, + 0x6C, 0x00, 0x65, 0x00, 0x42, 0x00, 0x75, 0x00, + 0x74, 0x00, 0x74, 0x00, 0x6F, 0x00, 0x6E, 0x00, + 0x31, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor2( rObj->OpenSotStream( C2S("\3OCXNAME"))); + xStor2->Write(aOCXNAME,sizeof(aOCXNAME)); + DBG_ASSERT((xStor2.Is() && (SVSTREAM_OK == xStor2->GetError())),"damn"); + } + + SvStorageStreamRef xContents( rObj->OpenSotStream( C2S("contents"))); + + return WriteContents(xContents,rPropSet,rSize); +} + +sal_Bool OCX_ToggleButton::WriteContents(SvStorageStreamRef &rContents, + const uno::Reference< beans::XPropertySet > &rPropSet, + const awt::Size &rSize) +{ + sal_Bool bRet=sal_True; + sal_uInt32 nOldPos = rContents->Tell(); + rContents->SeekRel(12); + + pBlockFlags[0] = 0; + pBlockFlags[1] = 0x01; + pBlockFlags[2] = 0; + pBlockFlags[3] = 0x80; + pBlockFlags[4] = 0; + pBlockFlags[5] = 0; + pBlockFlags[6] = 0; + pBlockFlags[7] = 0; + + uno::Any aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("Enabled")); + fEnabled = any2bool(aTmp); + + sal_uInt8 nTemp=fEnabled; + if (fEnabled) + nTemp = nTemp << 1; + if (fBackStyle) + nTemp |= 0x08; + *rContents << nTemp; + pBlockFlags[0] |= 0x01; + *rContents << sal_uInt8(0x00); + nTemp = 0; + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("MultiLine")); + fWordWrap = any2bool(aTmp); + if (fWordWrap) + nTemp |= 0x80; + *rContents << nTemp; + *rContents << sal_uInt8(0x00); + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("BackgroundColor")); + if (aTmp.hasValue()) + aTmp >>= mnBackColor; + *rContents << ExportColor(mnBackColor); + pBlockFlags[0] |= 0x02; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("TextColor")); + if (aTmp.hasValue()) + aTmp >>= mnForeColor; + *rContents << ExportColor(mnForeColor); + pBlockFlags[0] |= 0x04; + + nStyle = 6; + *rContents << nStyle; + pBlockFlags[0] |= 0x40; + + WriteAlign(rContents,4); + nValueLen = 1|SVX_MSOCX_COMPRESSED; + bool bDefault = false; + rPropSet->getPropertyValue(WW8_ASCII2STR("DefaultState")) >>= bDefault; + sal_uInt8 nDefault = static_cast< sal_uInt8 >( bDefault ? '1' : '0' ); + *rContents << nValueLen; + pBlockFlags[2] |= 0x40; + + SvxOcxString aCaption( rPropSet->getPropertyValue(WW8_ASCII2STR("Label")) ); + aCaption.WriteLenField( *rContents ); + if (aCaption.HasData()) + pBlockFlags[2] |= 0x80; + + WriteAlign(rContents,4); + *rContents << rSize.Width; + *rContents << rSize.Height; + + *rContents << nDefault; + *rContents << sal_uInt8(0x00); + + aCaption.WriteCharArray( *rContents ); + + WriteAlign(rContents,4); + nFixedAreaLen = static_cast<sal_uInt16>(rContents->Tell()-nOldPos-4); + bRet = aFontData.Export(rContents,rPropSet); + rContents->Seek(nOldPos); + *rContents << nStandardId; + *rContents << nFixedAreaLen; + + *rContents << pBlockFlags[0]; + *rContents << pBlockFlags[1]; + *rContents << pBlockFlags[2]; + *rContents << pBlockFlags[3]; + *rContents << pBlockFlags[4]; + *rContents << pBlockFlags[5]; + *rContents << pBlockFlags[6]; + *rContents << pBlockFlags[7]; + + DBG_ASSERT((rContents.Is() && + (SVSTREAM_OK==rContents->GetError())),"damn"); + return bRet; +} + +sal_Bool OCX_Label::Import(uno::Reference< beans::XPropertySet > &rPropSet) +{ + uno::Any aTmp(&sName,getCppuType((OUString *)0)); + rPropSet->setPropertyValue( WW8_ASCII2STR("Name"), aTmp ); + + sal_Bool bTemp; + if ((!(fEnabled)) || (fLocked)) + bTemp = sal_False; + else + bTemp = sal_True; + aTmp = bool2any(bTemp); + rPropSet->setPropertyValue( WW8_ASCII2STR("Enabled"), aTmp); + + aTmp <<= ImportColor(mnForeColor); + rPropSet->setPropertyValue( WW8_ASCII2STR("TextColor"), aTmp); + + // background color: fBackStyle==0 -> transparent + if( fBackStyle ) + { + aTmp <<= ImportColor(mnBackColor); + } + else + { + // try fake transparent by using parents backColor + if ( bSetInDialog && mpParent != NULL ) + { + aTmp <<= ImportColor( mpParent->mnBackColor ); + } + else + { + aTmp = uno::Any(); // use SO default + } + } + rPropSet->setPropertyValue( WW8_ASCII2STR("BackgroundColor"), aTmp); + + aTmp <<= ImportBorder(nSpecialEffect,nBorderStyle); + rPropSet->setPropertyValue( WW8_ASCII2STR("Border"), aTmp); + + aTmp <<= ImportColor( nBorderColor ); + rPropSet->setPropertyValue( WW8_ASCII2STR("BorderColor"), aTmp); + + bTemp=fWordWrap; + aTmp = bool2any(bTemp); + rPropSet->setPropertyValue( WW8_ASCII2STR("MultiLine"), aTmp); + + if (pCaption) + { + aTmp <<= lclCreateOUString( pCaption, nCaptionLen ); + rPropSet->setPropertyValue( WW8_ASCII2STR("Label"), aTmp); + } + + aFontData.Import(rPropSet); + return sal_True; +} + +sal_Bool OCX_ComboBox::Import(com::sun::star::uno::Reference< + com::sun::star::beans::XPropertySet> &rPropSet) +{ + + uno::Any aTmp(&sName,getCppuType((OUString *)0)); + rPropSet->setPropertyValue( WW8_ASCII2STR("Name"), aTmp ); + + aTmp = bool2any(fEnabled != 0); + rPropSet->setPropertyValue( WW8_ASCII2STR("Enabled"), aTmp); + + aTmp = bool2any(fLocked != 0); + rPropSet->setPropertyValue( WW8_ASCII2STR("ReadOnly"), aTmp); + + aTmp = bool2any( nDropButtonStyle != 0 ); + rPropSet->setPropertyValue( WW8_ASCII2STR("Dropdown"), aTmp); + + aTmp = bool2any( fHideSelection != 0 ); + rPropSet->setPropertyValue( WW8_ASCII2STR( "HideInactiveSelection" ), aTmp); + + aTmp <<= ImportColor(mnForeColor); + rPropSet->setPropertyValue( WW8_ASCII2STR("TextColor"), aTmp); + + if (pValue) + { + aTmp <<= lclCreateOUString( pValue, nValueLen ); + if ( bSetInDialog ) + { + rPropSet->setPropertyValue( WW8_ASCII2STR("Text"), aTmp); + } + else + { + rPropSet->setPropertyValue( WW8_ASCII2STR("DefaultText"), aTmp); + } + } + + aTmp <<= ImportColor(mnBackColor); + rPropSet->setPropertyValue( WW8_ASCII2STR("BackgroundColor"), aTmp); + + aTmp <<= ImportBorder(nSpecialEffect,nBorderStyle); + rPropSet->setPropertyValue( WW8_ASCII2STR("Border"), aTmp); + + aTmp <<= ImportColor( nBorderColor ); + rPropSet->setPropertyValue( WW8_ASCII2STR("BorderColor"), aTmp); + + sal_Int16 nTmp=static_cast<sal_Int16>(nMaxLength); + aTmp <<= nTmp; + rPropSet->setPropertyValue( WW8_ASCII2STR("MaxTextLen"), aTmp); + + aFontData.Import(rPropSet); + return sal_True; +} + +sal_Bool OCX_ComboBox::WriteContents(SvStorageStreamRef &rContents, + const uno::Reference< beans::XPropertySet > &rPropSet, + const awt::Size &rSize) +{ + sal_Bool bRet=sal_True; + sal_uInt32 nOldPos = rContents->Tell(); + rContents->SeekRel(12); + + pBlockFlags[0] = 0; + pBlockFlags[1] = 0x01; + pBlockFlags[2] = 0x00; + pBlockFlags[3] = 0x80; + pBlockFlags[4] = 0; + pBlockFlags[5] = 0; + pBlockFlags[6] = 0; + pBlockFlags[7] = 0; + + + sal_uInt8 nTemp=0x19;//fEnabled; + uno::Any aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("Enabled")); + fEnabled = any2bool(aTmp); + if (fEnabled) + nTemp |= 0x02; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("ReadOnly")); + fLocked = any2bool(aTmp); + if (fLocked) + nTemp |= 0x04; + + *rContents << nTemp; + pBlockFlags[0] |= 0x01; + *rContents << sal_uInt8(0x48); + *rContents << sal_uInt8(0x80); + + nTemp = 0x0C; + fHideSelection = any2bool(rPropSet->getPropertyValue(WW8_ASCII2STR("HideInactiveSelection"))); + if( fHideSelection ) + nTemp |= 0x20; + *rContents << nTemp; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("BackgroundColor")); + if (aTmp.hasValue()) + aTmp >>= mnBackColor; + *rContents << ExportColor(mnBackColor); + pBlockFlags[0] |= 0x02; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("TextColor")); + if (aTmp.hasValue()) + aTmp >>= mnForeColor; + *rContents << ExportColor(mnForeColor); + pBlockFlags[0] |= 0x04; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("Border")); + sal_Int16 nBorder = sal_Int16(); + aTmp >>= nBorder; + nSpecialEffect = ExportBorder(nBorder,nBorderStyle); + *rContents << nBorderStyle; + pBlockFlags[0] |= 0x10; + + nStyle = 3; + *rContents << nStyle; + pBlockFlags[0] |= 0x40; + + WriteAlign(rContents,2); + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("LineCount")); + aTmp >>= nListRows; + *rContents << nListRows; + pBlockFlags[1] |= 0x40; + + *rContents << sal_uInt8(1); //DefaultSelected One + pBlockFlags[2] |= 0x01; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("Dropdown")); + nDropButtonStyle = any2bool(aTmp); + if (nDropButtonStyle) + nDropButtonStyle=0x02; + *rContents << nDropButtonStyle; + pBlockFlags[2] |= 0x04; + + SvxOcxString aValue( rPropSet->getPropertyValue(WW8_ASCII2STR("Text")) ); + aValue.WriteLenField( *rContents ); + if (aValue.HasData()) + pBlockFlags[2] |= 0x40; + + WriteAlign(rContents,4); + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("BorderColor")); + if (aTmp.hasValue()) + aTmp >>= nBorderColor; + *rContents << ExportColor(nBorderColor); + pBlockFlags[3] |= 0x02; + + *rContents << nSpecialEffect; + pBlockFlags[3] |= 0x04; + + WriteAlign(rContents,4); + *rContents << rSize.Width; + *rContents << rSize.Height; + + aValue.WriteCharArray( *rContents ); + + WriteAlign(rContents,4); + + nFixedAreaLen = static_cast<sal_uInt16>(rContents->Tell()-nOldPos-4); + + bRet = aFontData.Export(rContents,rPropSet); + + rContents->Seek(nOldPos); + *rContents << nStandardId; + *rContents << nFixedAreaLen; + + *rContents << pBlockFlags[0]; + *rContents << pBlockFlags[1]; + *rContents << pBlockFlags[2]; + *rContents << pBlockFlags[3]; + *rContents << pBlockFlags[4]; + *rContents << pBlockFlags[5]; + *rContents << pBlockFlags[6]; + *rContents << pBlockFlags[7]; + + DBG_ASSERT((rContents.Is() && + (SVSTREAM_OK==rContents->GetError())),"damn"); + return bRet; +} + + +sal_Bool OCX_ComboBox::Export(SvStorageRef &rObj, + const uno::Reference< beans::XPropertySet > &rPropSet, + const awt::Size &rSize) +{ + static sal_uInt8 __READONLY_DATA aCompObj[] = { + 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x30, 0x1D, 0xD2, 0x8B, + 0x42, 0xEC, 0xCE, 0x11, 0x9E, 0x0D, 0x00, 0xAA, + 0x00, 0x60, 0x02, 0xF3, 0x1D, 0x00, 0x00, 0x00, + 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, + 0x74, 0x20, 0x46, 0x6F, 0x72, 0x6D, 0x73, 0x20, + 0x32, 0x2E, 0x30, 0x20, 0x43, 0x6F, 0x6D, 0x62, + 0x6F, 0x42, 0x6F, 0x78, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x45, 0x6D, 0x62, 0x65, 0x64, 0x64, 0x65, + 0x64, 0x20, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, + 0x00, 0x11, 0x00, 0x00, 0x00, 0x46, 0x6F, 0x72, + 0x6D, 0x73, 0x2E, 0x43, 0x6F, 0x6D, 0x62, 0x6F, + 0x42, 0x6F, 0x78, 0x2E, 0x31, 0x00, 0xF4, 0x39, + 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor( rObj->OpenSotStream( C2S("\1CompObj"))); + xStor->Write(aCompObj,sizeof(aCompObj)); + DBG_ASSERT((xStor.Is() && (SVSTREAM_OK == xStor->GetError())),"damn"); + } + + { + SvStorageStreamRef xStor3( rObj->OpenSotStream( C2S("\3ObjInfo"))); + xStor3->Write(aObjInfo,sizeof(aObjInfo)); + DBG_ASSERT((xStor3.Is() && (SVSTREAM_OK == xStor3->GetError())),"damn"); + } + + static sal_uInt8 __READONLY_DATA aOCXNAME[] = { + 0x43, 0x00, 0x6F, 0x00, 0x6D, 0x00, 0x62, 0x00, + 0x6F, 0x00, 0x42, 0x00, 0x6F, 0x00, 0x78, 0x00, + 0x31, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor2( rObj->OpenSotStream( C2S("\3OCXNAME"))); + xStor2->Write(aOCXNAME,sizeof(aOCXNAME)); + DBG_ASSERT((xStor2.Is() && (SVSTREAM_OK == xStor2->GetError())),"damn"); + } + + SvStorageStreamRef xContents( rObj->OpenSotStream( C2S("contents"))); + return WriteContents(xContents, rPropSet, rSize); +} + + + +sal_Bool OCX_ListBox::Import(com::sun::star::uno::Reference< + com::sun::star::beans::XPropertySet> &rPropSet) +{ + + uno::Any aTmp(&sName,getCppuType((OUString *)0)); + rPropSet->setPropertyValue( WW8_ASCII2STR("Name"), aTmp ); + + sal_Bool bTmp=fEnabled; + aTmp = bool2any(bTmp); + rPropSet->setPropertyValue( WW8_ASCII2STR("Enabled"), aTmp); + + bTmp=fLocked; + aTmp = bool2any(bTmp); + rPropSet->setPropertyValue( WW8_ASCII2STR("ReadOnly"), aTmp); + + aTmp <<= ImportColor(mnForeColor); + rPropSet->setPropertyValue( WW8_ASCII2STR("TextColor"), aTmp); + + sal_Bool bTemp = nMultiState; + aTmp = bool2any(bTemp); + rPropSet->setPropertyValue( WW8_ASCII2STR("MultiSelection"), aTmp); + +#if 0 //Don't delete this for now until I figure out if I can make this + if (pValue) + { + aTmp <<= lclCreateOUString( pValue, nValueLen ); + xPropSet->setPropertyValue( WW8_ASCII2STR("DefaultText"), aTmp); + } +#endif + + aTmp <<= ImportColor(mnBackColor); + rPropSet->setPropertyValue( WW8_ASCII2STR("BackgroundColor"), aTmp); + + aTmp <<= ImportBorder(nSpecialEffect,nBorderStyle); + rPropSet->setPropertyValue( WW8_ASCII2STR("Border"), aTmp); + + aTmp <<= ImportColor( nBorderColor ); + rPropSet->setPropertyValue( WW8_ASCII2STR("BorderColor"), aTmp); + + aFontData.Import(rPropSet); + return sal_True; +} + +sal_Bool OCX_ListBox::WriteContents(SvStorageStreamRef &rContents, + const uno::Reference< beans::XPropertySet > &rPropSet, + const awt::Size &rSize) +{ + sal_Bool bRet=sal_True; + sal_uInt32 nOldPos = rContents->Tell(); + rContents->SeekRel(12); + + pBlockFlags[0] = 0; + pBlockFlags[1] = 0x01; + pBlockFlags[2] = 0x01; + pBlockFlags[3] = 0x80; + pBlockFlags[4] = 0; + pBlockFlags[5] = 0; + pBlockFlags[6] = 0; + pBlockFlags[7] = 0; + + uno::Any aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("Enabled")); + fEnabled = any2bool(aTmp); + sal_uInt8 nTemp=fEnabled; + if (fEnabled) + nTemp = nTemp << 1; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("ReadOnly")); + fLocked = any2bool(aTmp); + if (fLocked) + nTemp |= 0x04; + + *rContents << nTemp; + pBlockFlags[0] |= 0x01; + *rContents << sal_uInt8(0x00); + *rContents << sal_uInt8(0x00); + *rContents << sal_uInt8(0x00); + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("BackgroundColor")); + if (aTmp.hasValue()) + aTmp >>= mnBackColor; + *rContents << ExportColor(mnBackColor); + pBlockFlags[0] |= 0x02; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("TextColor")); + if (aTmp.hasValue()) + aTmp >>= mnForeColor; + *rContents << ExportColor(mnForeColor); + pBlockFlags[0] |= 0x04; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("Border")); + sal_Int16 nBorder = sal_Int16(); + aTmp >>= nBorder; + nSpecialEffect = ExportBorder(nBorder,nBorderStyle); + WriteAlign(rContents,2); + *rContents << nBorderStyle; + pBlockFlags[0] |= 0x10; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("MultiSelection")); + nMultiState = any2bool(aTmp); + + if (nMultiState) + { + *rContents << nMultiState; + pBlockFlags[0] |= 0x20; + } + + nStyle = 2; + *rContents << nStyle; + pBlockFlags[0] |= 0x40; + + + WriteAlign(rContents,4); + +#if 0 + SvxOcxString aValue( rPropSet->getPropertyValue(WW8_ASCII2STR("DefaultText")) ); + aValue.WriteLenField( *rContents ); + if (aValue.HasData()) + pBlockFlags[2] |= 0x40; + + WriteAlign(rContents,4); +#endif + + WriteAlign(rContents,4); + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("BorderColor")); + if (aTmp.hasValue()) + aTmp >>= nBorderColor; + *rContents << ExportColor(nBorderColor); + pBlockFlags[3] |= 0x02; + + *rContents << nSpecialEffect; + pBlockFlags[3] |= 0x04; + + WriteAlign(rContents,4); + *rContents << rSize.Width; + *rContents << rSize.Height; + +#if 0 + aValue.WriteCharArray( *rContents ); +#endif + + WriteAlign(rContents,4); + + nFixedAreaLen = static_cast<sal_uInt16>(rContents->Tell()-nOldPos-4); + + bRet = aFontData.Export(rContents,rPropSet); + + rContents->Seek(nOldPos); + *rContents << nStandardId; + *rContents << nFixedAreaLen; + + *rContents << pBlockFlags[0]; + *rContents << pBlockFlags[1]; + *rContents << pBlockFlags[2]; + *rContents << pBlockFlags[3]; + *rContents << pBlockFlags[4]; + *rContents << pBlockFlags[5]; + *rContents << pBlockFlags[6]; + *rContents << pBlockFlags[7]; + + DBG_ASSERT((rContents.Is() && + (SVSTREAM_OK==rContents->GetError())),"damn"); + return bRet; +} + +sal_Bool OCX_ListBox::Export(SvStorageRef &rObj, + const uno::Reference< beans::XPropertySet > &rPropSet, + const awt::Size &rSize) +{ + static sal_uInt8 __READONLY_DATA aCompObj[] = { + 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x1D, 0xD2, 0x8B, + 0x42, 0xEC, 0xCE, 0x11, 0x9E, 0x0D, 0x00, 0xAA, + 0x00, 0x60, 0x02, 0xF3, 0x1C, 0x00, 0x00, 0x00, + 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, + 0x74, 0x20, 0x46, 0x6F, 0x72, 0x6D, 0x73, 0x20, + 0x32, 0x2E, 0x30, 0x20, 0x4C, 0x69, 0x73, 0x74, + 0x42, 0x6F, 0x78, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x45, 0x6D, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, + 0x20, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x46, 0x6F, 0x72, 0x6D, + 0x73, 0x2E, 0x4C, 0x69, 0x73, 0x74, 0x42, 0x6F, + 0x78, 0x2E, 0x31, 0x00, 0xF4, 0x39, 0xB2, 0x71, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor( rObj->OpenSotStream( C2S("\1CompObj"))); + xStor->Write(aCompObj,sizeof(aCompObj)); + DBG_ASSERT((xStor.Is() && (SVSTREAM_OK == xStor->GetError())),"damn"); + } + + { + SvStorageStreamRef xStor3( rObj->OpenSotStream( C2S("\3ObjInfo"))); + xStor3->Write(aObjInfo,sizeof(aObjInfo)); + DBG_ASSERT((xStor3.Is() && (SVSTREAM_OK == xStor3->GetError())),"damn"); + } + + static sal_uInt8 __READONLY_DATA aOCXNAME[] = { + 0x4C, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00, + 0x42, 0x00, 0x6F, 0x00, 0x78, 0x00, 0x31, 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor2( rObj->OpenSotStream( C2S("\3OCXNAME"))); + xStor2->Write(aOCXNAME,sizeof(aOCXNAME)); + DBG_ASSERT((xStor2.Is() && (SVSTREAM_OK == xStor2->GetError())),"damn"); + } + + SvStorageStreamRef xContents( rObj->OpenSotStream( C2S("contents"))); + return WriteContents(xContents, rPropSet, rSize); +} + +sal_Bool OCX_Control::Read(SvStorageStream *pS) +{ + sal_uInt16 nIdentifier, nFixedAreaLen; + *pS >> nIdentifier; + DBG_ASSERT(nStandardId==nIdentifier, + "A control that has a different identifier"); + *pS >> nFixedAreaLen; + pS->SeekRel(nFixedAreaLen); + return true; +} + +sal_Bool OCX_ModernControl::Read(SvStorageStream *pS) +{ + long nStart = pS->Tell(); + *pS >> nIdentifier; + DBG_ASSERT(nIdentifier==nStandardId, + "A control that has a different identifier"); + *pS >> nFixedAreaLen; + pS->Read(pBlockFlags,8); + + if (pBlockFlags[0] & 0x01) + { + sal_uInt8 nTemp; + *pS >> nTemp; + + fEnabled = (nTemp & 0x02) >> 1; + fLocked = (nTemp & 0x04) >> 2; + fBackStyle = (nTemp & 0x08) >> 3; + + *pS >> nTemp; + + fColumnHeads = (nTemp & 0x04) >> 2; + fIntegralHeight = (nTemp & 0x08) >> 3; + fMatchRequired = (nTemp & 0x10) >> 4; + fAlignment = (nTemp & 0x20) >> 5; + + *pS >> nTemp; + + fDragBehaviour = (nTemp & 0x08) >> 3; + fEnterKeyBehaviour = (nTemp & 0x10) >> 4; + fEnterFieldBehaviour = (nTemp & 0x20) >> 5; + fTabKeyBehaviour = (nTemp & 0x40) >> 6; + fWordWrap = (nTemp & 0x80) >> 7; + + *pS >> nTemp; + fSelectionMargin = (nTemp & 0x04) >> 2; + fAutoWordSelect = (nTemp & 0x08) >> 3; + fAutoSize = (nTemp & 0x10) >> 4; + fHideSelection = (nTemp & 0x20) >> 5; + fAutoTab = (nTemp & 0x40) >> 6; + fMultiLine = (nTemp & 0x80) >> 7; + + } + + /*If any of these are set they follow eachother in this order one after + another padded out to the next U32 boundary with 0's + U8 can abut each other U16 must start on a U16 boundary and are padded to + that with 0's. A standardish word alignment structure*/ + + if (pBlockFlags[0] & 0x02) + *pS >> mnBackColor; + if (pBlockFlags[0] & 0x04) + *pS >> mnForeColor; + if (pBlockFlags[0] & 0x08) + *pS >> nMaxLength; + + if (pBlockFlags[0] & 0x10) + *pS >> nBorderStyle; + if (pBlockFlags[0] & 0x20) + *pS >> nScrollBars; + if (pBlockFlags[0] & 0x40) + *pS >> nStyle;// (UI 0 == Data 3, UI 2 = Data 7) + if (pBlockFlags[0] & 0x80) + *pS >> nMousePointer; + + if (pBlockFlags[1] & 0x02) + *pS >> nPasswordChar; //HUH ??? always 0 ??? not sure maybe just padding + + if (pBlockFlags[1] & 0x04) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nListWidth; + } + + if (pBlockFlags[1] & 0x08) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nBoundColumn; + } + if (pBlockFlags[1] & 0x10) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nTextColumn; + } + if (pBlockFlags[1] & 0x20) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nColumnCount; + } + if (pBlockFlags[1] & 0x40) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nListRows; + } + if (pBlockFlags[1] & 0x80) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nUnknown8; //something to do with ColumnWidths + } + if (pBlockFlags[2] & 0x01) + *pS >> nMatchEntry; + if (pBlockFlags[2] & 0x02) + *pS >> nListStyle; + if (pBlockFlags[2] & 0x04) + *pS >> nShowDropButtonWhen; + if (pBlockFlags[2] & 0x10) + *pS >> nDropButtonStyle; + if (pBlockFlags[2] & 0x20) + *pS >> nMultiState; + + bool bValue = (pBlockFlags[2] & 0x40) != 0; + if (bValue) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nValueLen; + } + bool bCaption = (pBlockFlags[2] & 0x80) != 0; + if (bCaption) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nCaptionLen; + } + if (pBlockFlags[3] & 0x01) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nHorzPos; + *pS >> nVertPos; + } + if (pBlockFlags[3] & 0x02) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nBorderColor; + } + if (pBlockFlags[3] & 0x04) + { + ReadAlign(pS, pS->Tell() - nStart, 4); // NEW + *pS >> nSpecialEffect; + pS->SeekRel( 3 ); // special effect is 32bit, not 8bit + } + if (pBlockFlags[3] & 0x08) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nIcon; + DBG_ASSERT(nIcon == 0xFFFF, "Unexpected nIcon"); + } + if (pBlockFlags[3] & 0x10) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nPicture; + DBG_ASSERT(nPicture == 0xFFFF, "Unexpected nIcon"); + } + if (pBlockFlags[3] & 0x20) + *pS >> nAccelerator; + /* + if (pBlockFlags[3] & 0x80) + *pS >> nUnknown9; + */ + bool bGroupName = (pBlockFlags[4] & 0x01) != 0; + if (bGroupName) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nGroupNameLen; + } + + //End + + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nWidth; + *pS >> nHeight; + + if (bValue) + lclReadCharArray( *pS, pValue, nValueLen, pS->Tell() - nStart); + + if (bCaption) + lclReadCharArray( *pS, pCaption, nCaptionLen, pS->Tell() - nStart); + + if (bGroupName) + lclReadCharArray( *pS, pGroupName, nGroupNameLen, pS->Tell() - nStart); + + ReadAlign(pS, pS->Tell() - nStart, 4); + if (nIcon) + { + pS->Read(pIconHeader,20); + *pS >> nIconLen; + pIcon = new sal_uInt8[nIconLen]; + pS->Read(pIcon,nIconLen); + } + + if (nPicture) + { + pS->Read(pPictureHeader,20); + *pS >> nPictureLen; + pPicture = new sal_uInt8[nPictureLen]; + pS->Read(pPicture,nPictureLen); + } + + return sal_True; +} + + +sal_Bool OCX_CommandButton::Read(SvStorageStream *pS) +{ + long nStart = pS->Tell(); + *pS >> nIdentifier; + DBG_ASSERT(nStandardId==nIdentifier, + "A control that has a different identifier"); + *pS >> nFixedAreaLen; + pS->Read(pBlockFlags,4); + + + if (pBlockFlags[0] & 0x01) + *pS >> mnForeColor; + if (pBlockFlags[0] & 0x02) + *pS >> mnBackColor; + + if (pBlockFlags[0] & 0x04) + { + sal_uInt8 nTemp; + *pS >> nTemp; + fEnabled = (nTemp&0x02)>>1; + fLocked = (nTemp&0x04)>>2; + fBackStyle = (nTemp&0x08)>>3; + *pS >> nTemp; + *pS >> nTemp; + fWordWrap = (nTemp&0x80)>>7; + *pS >> nTemp; + fAutoSize = (nTemp&0x10)>>4; + } + + bool bCaption = (pBlockFlags[0] & 0x08) != 0; + if (bCaption) + { + *pS >> nCaptionLen; + } + if (pBlockFlags[0] & 0x10) /*Picture Position, a strange mechanism here*/ + { + *pS >> nVertPos; + *pS >> nHorzPos; + } + + if (pBlockFlags[0] & 0x40) /*MousePointer*/ + *pS >> nMousePointer; + + if (pBlockFlags[0] & 0x80) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nPicture; + } + + if (pBlockFlags[1] & 0x01) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nAccelerator; + } + + // "take focus on click" is directly in content flags, not in option field... + mbTakeFocus = (pBlockFlags[1] & 0x02) == 0; // option is on, if flag is not set + + if (pBlockFlags[1] & 0x04) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nIcon; + } + + if (bCaption) + lclReadCharArray( *pS, pCaption, nCaptionLen, pS->Tell() - nStart); + + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nWidth; + *pS >> nHeight; + + if (nIcon) + { + pS->Read(pIconHeader,20); + *pS >> nIconLen; + pIcon = new sal_uInt8[nIconLen]; + pS->Read(pIcon,nIconLen); + } + + if (nPicture) + { + pS->Read(pPictureHeader,20); + *pS >> nPictureLen; + pPicture = new sal_uInt8[nPictureLen]; + pS->Read(pPicture,nPictureLen); + } + + return sal_True; +} + +sal_Bool OCX_Label::Read(SvStorageStream *pS) +{ + long nStart = pS->Tell(); + *pS >> nIdentifier; + DBG_ASSERT(nStandardId==nIdentifier, + "A control that has a different identifier"); + *pS >> nFixedAreaLen; + pS->Read(pBlockFlags,4); + + + if (pBlockFlags[0] & 0x01) + *pS >> mnForeColor; + if (pBlockFlags[0] & 0x02) + *pS >> mnBackColor; + + + if (pBlockFlags[0] & 0x04) + { + sal_uInt8 nTemp; + *pS >> nTemp; + fEnabled = (nTemp&0x02)>>1; + fLocked = (nTemp&0x04)>>2; + fBackStyle = (nTemp&0x08)>>3; + *pS >> nTemp; + *pS >> nTemp; + fWordWrap = (nTemp&0x80)>>7; + *pS >> nTemp; + fAutoSize = (nTemp&0x10)>>4; + } + bool bCaption = (pBlockFlags[0] & 0x08) != 0; + if (bCaption) + *pS >> nCaptionLen; + + if (pBlockFlags[0] & 0x10) + { + *pS >> nVertPos; + *pS >> nHorzPos; + } + + if (pBlockFlags[0] & 0x40) + *pS >> nMousePointer; + + if (pBlockFlags[0] & 0x80) + { + ReadAlign(pS,pS->Tell() - nStart, 4); + *pS >> nBorderColor; + } + + if (pBlockFlags[1] & 0x01) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nBorderStyle; + } + + if (pBlockFlags[1] & 0x02) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nSpecialEffect; + } + + if (pBlockFlags[1] & 0x04) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nPicture; + } + + if (pBlockFlags[1] & 0x08) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nAccelerator; + } + + if (pBlockFlags[1] & 0x10) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nIcon; + } + + if (bCaption) + lclReadCharArray( *pS, pCaption, nCaptionLen, pS->Tell() - nStart); + + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nWidth; + *pS >> nHeight; + + if (nPicture) + { + pS->Read(pPictureHeader,20); + *pS >> nPictureLen; + pPicture = new sal_uInt8[nPictureLen]; + pS->Read(pPicture,nPictureLen); + } + if (nIcon) + { + pS->Read(pIconHeader,20); + *pS >> nIconLen; + pIcon = new sal_uInt8[nIconLen]; + pS->Read(pIcon,nIconLen); + } + + return sal_True; +} + +TypeName::TypeName(sal_Char *pName, sal_uInt32 nStoreId, sal_uInt32 nLen, sal_uInt16 nType, sal_Int32 nLeft, + sal_Int32 nTop) + : msName(lclCreateOUString(pName, nLen)), mnType(nType), mnLeft(nLeft), + mnTop(nTop),mnStoreId(nStoreId) +{ +} + +OCX_ContainerControl::OCX_ContainerControl( SotStorageRef& parent, + const ::rtl::OUString& storageName, + const ::rtl::OUString& sN, + const uno::Reference< container::XNameContainer > &rParent, + OCX_Control* pParent ) : + OCX_Control(sN, pParent), rbGroupMgr( sName ), mxParent(rParent), nNoRecords(0), nTotalLen(0), containerType( STDCONTAINER ) +{ + + mContainerStorage = parent->OpenSotStorage(storageName, + STREAM_READWRITE | + STREAM_NOCREATE | + STREAM_SHARE_DENYALL); + mContainerStream = mContainerStorage->OpenSotStream( + String(RTL_CONSTASCII_STRINGPARAM("f"), + RTL_TEXTENCODING_MS_1252), + STREAM_STD_READ | STREAM_NOCREATE); + mContainedControlsStream = mContainerStorage->OpenSotStream( String(RTL_CONSTASCII_STRINGPARAM("o"), + RTL_TEXTENCODING_MS_1252), + STREAM_STD_READ | STREAM_NOCREATE); +} +OCX_ContainerControl::~OCX_ContainerControl() +{ + CtrlIterator aEnd = mpControls.end(); + for (CtrlIterator aIter = mpControls.begin(); aIter != aEnd; ++ aIter ) + { + delete *aIter; + } +} + +// Really import should receive the parent e.g. a Userform, Frame or Multi Page +// and call import on its containees with itself ( up-called from +// the base class ) but... the reality is we have no containment model +// so we make sure rPropSet is always the parent Dialog + +sal_Bool OCX_ContainerControl::Import(uno::Reference<beans::XPropertySet>& /* rProps */ ) +{ + if ( !mxParent.is() ) + { + return sal_False; + } + CtrlIterator aEnd = mpControls.end(); +// int count = 0; + for (CtrlIterator aIter = mpControls.begin(); aIter != aEnd; ++ aIter ) + { + if ( !(*aIter)->Import( mxParent ) ) + { + return sal_False; + } + } + return sal_True; +} + +OUString OCX_ContainerControl::createSubStreamName( const sal_uInt32& subStorageId ) +{ + static OUString sI = OUString::createFromAscii("i"); + static OUString sZero = OUString::createFromAscii( "0" ); + OUStringBuffer buf( 6 ); + buf.append( sI ); + // for subStorage id < 10 stream name has leading '0' + // eg "i07" + if ( subStorageId < 10 ) + { + buf.append( sZero ); + } + buf.append( OUString::valueOf( (sal_Int32)subStorageId ) ); + return buf.makeStringAndClear(); +} + +bool OCX_ContainerControl::createFromContainerRecord( const ContainerRecord& record, OCX_Control*& pControl ) +{ + pControl = NULL; + switch ( record.nTypeIdent) + { + case CMDBUTTON: + pControl = new OCX_CommandButton; + break; + case LABEL: + pControl = new OCX_UserFormLabel(this); + break; + case TEXTBOX: + pControl = new OCX_TextBox; + break; + case LISTBOX: + pControl = new OCX_ListBox; + break; + case COMBOBOX: + pControl = new OCX_ComboBox; + break; + case CHECKBOX: + pControl = new OCX_CheckBox; + break; + case OPTIONBUTTON: + pControl = new OCX_OptionButton; + break; + case TOGGLEBUTTON: + pControl = new OCX_ToggleButton; + break; + case IMAGE: //Image + { + pControl = new OCX_Image; + break; + } + case PAGE: // Page + { + OUString sMSStore = createSubStreamName( record.nSubStorageId ); + pControl = new OCX_Page(mContainerStorage, sMSStore, + record.cName, mxParent, this); + break; + } + case MULTIPAGE: // MultiPage + { + OUString sMSStore = createSubStreamName( record.nSubStorageId ); + pControl = new OCX_MultiPage( mContainerStorage, sMSStore, + record.cName, mxParent, this); + break; + } + case FRAME: //Frame + { + OUString sFrameStore = createSubStreamName( record.nSubStorageId ); + pControl = new OCX_Frame(mContainerStorage, sFrameStore, + record.cName, mxParent, this); + + break; + } + case SPINBUTTON: //SpinButton + { + pControl = new OCX_SpinButton; + break; + } + case TABSTRIP: //TabStrip + { + pControl = new OCX_TabStrip; + break; + } + case SCROLLBAR: //ScrollBar + pControl = new OCX_ScrollBar; + break; + case PROGRESSBAR: //ProgressBar Active X control + pControl = new OCX_ProgressBar; + break; + default: + OSL_TRACE( "**** Unknown control 0x%x", record.nTypeIdent ); + DBG_ERROR( "Unknown control"); + return false; + } + pControl->sName = record.cName; + return true; +} + + +void addSeperator( std::vector< OCX_Control* >& dest ) +{ + OCX_Control* seperator = new OCX_CommandButton; + seperator->SetInDialog(true); + seperator->sName = C2S("GroupSeperator"); + dest.push_back( seperator ); +} + +void addRButtons( std::vector< OCX_Control* >& src, + std::vector< OCX_Control* >& dest, + bool addGroupSeperator ) +{ + if ( addGroupSeperator ) + { + addSeperator( dest ); + } + + for ( CtrlIterator rbIter = src.begin(); rbIter != src.end(); ++rbIter ) + { + dest.push_back( *rbIter ); + } +} + +void OCX_ContainerControl::ProcessControl(OCX_Control* pControl,SvStorageStream* /* pS */, ContainerRecord& rec ) +{ + SotStorageStreamRef oStream = mContainedControlsStream; + + // can insert into OO Dialog (e.g is this a supported dialog control)?? + if ( rec.nTypeIdent == SPINBUTTON || + rec.nTypeIdent == TABSTRIP) + { + // skip the record in the stream, discard the control + oStream->SeekRel( rec.nSubStreamLen ); + delete pControl; + } + else + { + // A container control needs to read the f stream in + // the folder ( substorage ) associated with this control + if ( rec.nTypeIdent == FRAME || + rec.nTypeIdent == MULTIPAGE|| + rec.nTypeIdent == PAGE ) + { + OCX_ContainerControl* pContainer = + static_cast< OCX_ContainerControl* >( pControl ); + oStream = pContainer->getContainerStream(); + } + + pControl->sName = rec.cName; + pControl->msToolTip = rec.controlTip; + // Position of controls is relative to the container + pControl->mnTop = rec.nTop + mnTop; + pControl->mnLeft = rec.nLeft + mnLeft; + // MS tabIndex, pretty useless in OpenOffice land + // as tab indexes in MS are relative to parent container. + // However we need this value in order to set + // OpenOffice tab indices in a sensible way to + // reflect the ms tabbing from orig MS UserForm, see below + pControl->mnTabPos = rec.nTabPos; + pControl->SetInDialog(true); + pControl->mbVisible = rec.bVisible; + if ( mnStep ) + { + // If the container has a step then it should be + // applied to all containees + pControl->mnStep = mnStep; + } + + // #117490# DR: container records provide size of substream, use it here... + + // remember initial position to set correct stream position + sal_uLong nStrmPos = oStream->Tell(); + // import control, may return with invalid stream position + pControl->FullRead(oStream); + // set stream to position behind substream of this control + oStream->Seek( nStrmPos + rec.nSubStreamLen ); + + //need to fake grouping behaviour for radio ( option ) buttons + if ( rec.nTypeIdent == OPTIONBUTTON ) + { + OCX_OptionButton* pRButton = + static_cast< OCX_OptionButton*>(pControl); + rbGroupMgr.addRadioButton( pRButton ); + } + else + { + mpControls.push_back( pControl ); + } + } +} + +sal_Bool OCX_ContainerControl::Read(SvStorageStream *pS) +{ + + if ( mpParent ) + { + mnBackColor = mpParent->mnBackColor; + } + + std::auto_ptr< ContainerRecReader > reader ( + ContainerRecordReaderFac::instance( containerType ) ); + + reader->Read( this, pS ); + // Need to honour the MS Tab Indexes. However MS tab indexes are + // relative to parent, this hack sorts the controls in each container + // based on the ms tab indexes. When import is called we create the + // controls in Open/Star office based on the order of the tab indexes, + // this ensures that the default tab index created by Star/Open office + // reflects the "flattened" ms tab order. + ::std::sort( mpControls.begin(), mpControls.end(), SortOrderByTabPos() ); + mpControls = rbGroupMgr.insertGroupsIntoControlList( mpControls ); + return true; +} + +OCX_MultiPage::OCX_MultiPage( SotStorageRef& parent, + const ::rtl::OUString& storageName, + const ::rtl::OUString& sN, + const uno::Reference< container::XNameContainer > &rDialog, + OCX_Control* pParent): + OCX_ContainerControl(parent, storageName, sN, rDialog, pParent ), fUnknown1(0), fEnabled(1), + fLocked(0), fBackStyle(1), fWordWrap(1), fAutoSize(0), nCaptionLen(0), + nVertPos(1), nHorzPos(7), nMousePointer(0), nBorderColor(0x80000012), + nKeepScrollBarsVisible(3), nCycle(0), nBorderStyle(0), nSpecialEffect(0), + nPicture(0), nPictureAlignment(2), nPictureSizeMode(0), + bPictureTiling(sal_False), nAccelerator(0), nIcon(0), pCaption(0), + nScrollWidth(0), nScrollHeight(0), nIconLen(0), pIcon(0), nPictureLen(0), + pPicture(0) +{ + msDialogType = C2U("NotSupported"); + mnForeColor = 0x80000012L, + mnBackColor = 0x8000000FL; + bSetInDialog = true;// UserForm control only + aFontData.SetHasAlign(sal_True); + containerType = MULTIPAGE; + mnCurrentPageStep = 0; +} + +void OCX_MultiPage::ProcessControl(OCX_Control* pControl, SvStorageStream* /* pS */, ContainerRecord& rec ) +{ + SotStorageStreamRef oStream = mContainedControlsStream; + + OCX_Page *pPage = NULL; + if ( rec.nTypeIdent == PAGE ) + pPage = static_cast< OCX_Page* >( pControl ); + if ( pPage != NULL ) + { + pPage->mnStep = ++mnCurrentPageStep; + + pPage->mnTop = mnTop;// move these to Page::import ? + pPage->mnLeft = mnLeft; + pPage->mnBackColor = mnBackColor; + + oStream = pPage->getContainerStream();; + // Position of controls is relative to pos of this MuliPage + // Control + pPage->FullRead( oStream ); + + mpControls.push_back( pPage ); + } + else + { + OSL_TRACE("!!!! Unsupported Control 0x%x ", rec.nTypeIdent); + DBG_ERROR("MultiPage error expected Page control"); + } + +} + +sal_Bool OCX_MultiPage::Read(SvStorageStream *pS) +{ + // Unlike the other containers e.g. UserForm & Frame + // the o stream is does not contain info for the contained controls + // ( e.g. the pages themselves ) but seems to be for the MultiPage + // itself - need to check this in more detail + + // For the moment skip read of the MultiPage specific properties + // not much point reading these as we can't display the multi page + // control or in fact any sort of tabbed layout, best we can do is + // import just the contained controls of the individual pages + // Note: the record skipped below ( does not contain the expected + // info on this control, that seems to be contained in the o stream, + // see comment above) + OCX_Control skip(C2S("Dummy")); + skip.Read( pS ); + mnCurrentPageStep = mnStep; //( set step of of pages relative to step + //of this MultiPage ( e.g. emulate containment ) + return OCX_ContainerControl::Read(pS); +} + + +sal_Bool OCX_MultiPage::Import(com::sun::star::uno::Reference< + com::sun::star::beans::XPropertySet> &rPropSet) +{ + // Calls import on contained controls + OCX_ContainerControl::Import( rPropSet ); + return sal_True; +} + +sal_Bool OCX_MultiPage::Import(com::sun::star::uno::Reference< + com::sun::star::container::XNameContainer> + &rDialog) +{ + uno::Reference<beans::XPropertySet> xPropSet( rDialog, uno::UNO_QUERY ); + + // Although MultiPage is not represeted by a "real" control we still + // need to propagate the backcolor of this logical parent + // ( the dialog or Frame or whatever ) to the children of this control. + // For example the controls contained in the Page of a + // MultiPage control use the parents backcolor ( e,g, + // Pages backcolor ) when trying to fake transparency + mnBackColor = mpParent->mnBackColor; + + if ( xPropSet.is() ) + { + // Calls import on contained pages + return OCX_ContainerControl::Import( xPropSet ); + } + OSL_TRACE("*** Major problem, no dialog to add controls to "); + DBG_ERROR(" Major problem, no dialog to add controls to "); + return false; +} + + + +OCX_Page::OCX_Page( SotStorageRef& parent, + const ::rtl::OUString& storageName, + const ::rtl::OUString& sN, + const uno::Reference< container::XNameContainer > &rDialog, + OCX_Control* pParent): + OCX_ContainerControl(parent, storageName, sN, rDialog, pParent ), + fUnknown1(0), fEnabled(1), fLocked(0), + fBackStyle(1), fWordWrap(1), fAutoSize(0), nCaptionLen(0), nVertPos(1), + nHorzPos(7), nMousePointer(0), nBorderColor(0x80000012), + nKeepScrollBarsVisible(3), nCycle(0), nBorderStyle(0), nSpecialEffect(0), + nPicture(0), nPictureAlignment(2), nPictureSizeMode(0), + bPictureTiling(sal_False), nAccelerator(0), nIcon(0), pCaption(0), + nScrollWidth(0), nScrollHeight(0), nIconLen(0), pIcon(0), nPictureLen(0), + pPicture(0) +{ + msDialogType = C2U("NotSupported"); + mnForeColor = 0x80000012, + mnBackColor = 0x8000000F, + bSetInDialog = true;// UserForm control only + aFontData.SetHasAlign(sal_True); +} + + +sal_Bool OCX_Page::Read(SvStorageStream *pS) +{ + long nStart = pS->Tell(); + *pS >> nIdentifier; + DBG_ASSERT(0x400==nIdentifier, + "A control that has a different identifier"); + *pS >> nFixedAreaLen; + pS->Read(pBlockFlags,4); + + pS->SeekRel( nFixedAreaLen - sizeof( pBlockFlags ) ); + + ReadAlign( pS, pS->Tell() - nStart, 4); + + if (pBlockFlags[2] & 0x10) + { + //Font Stuff.. + pS->SeekRel(0x1a); + sal_uInt8 nFontLen; + *pS >> nFontLen; + pS->SeekRel(nFontLen); + } + return OCX_ContainerControl::Read(pS); + +} + +sal_Bool OCX_Page::Import(com::sun::star::uno::Reference< + com::sun::star::container::XNameContainer> + &rDialog) +{ + + uno::Reference<beans::XPropertySet> xPropSet( rDialog, uno::UNO_QUERY ); + if ( xPropSet.is() ) + { + // apply Step to contained controls + CtrlIterator aEnd = mpControls.end(); + for (CtrlIterator aIter = mpControls.begin(); aIter != aEnd; ++ aIter ) + { + (*aIter)->mnStep = mnStep; + } + // Calls import on contained pages + return OCX_ContainerControl::Import( xPropSet ); + } + OSL_TRACE("*** Major problem, no dialog to add controls to "); + DBG_ERROR("*** Major problem, no dialog to add controls to "); + return sal_False; +} + +OCX_Frame::OCX_Frame( SotStorageRef& parent, + const ::rtl::OUString& storageName, + const ::rtl::OUString& sN, + const uno::Reference< container::XNameContainer > &rDialog, OCX_Control* pParent): + OCX_ContainerControl(parent, storageName, sN, rDialog, pParent ),fUnknown1(0),fEnabled(1), fLocked(0), + fBackStyle(1), fWordWrap(1), fAutoSize(0), nCaptionLen(0), nVertPos(1), + nHorzPos(7), nMousePointer(0), nBorderColor(0x80000012), + nKeepScrollBarsVisible(3), nCycle(0), nBorderStyle(0), nSpecialEffect(0), + nPicture(0), nPictureAlignment(2), nPictureSizeMode(0), + bPictureTiling(sal_False), nAccelerator(0), nIcon(0), pCaption(0), + nScrollWidth(0), nScrollHeight(0), nScrollLeft(0), nScrollTop(0), nIconLen(0), pIcon(0), nPictureLen(0), + pPicture(0) +{ + msDialogType = C2U("com.sun.star.awt.UnoControlGroupBoxModel"); + mnForeColor = 0x80000012; + mnBackColor = 0x8000000F; + bSetInDialog = true;// UserForm control only + aFontData.SetHasAlign(sal_True); +} + + +sal_Bool OCX_Frame::Read(SvStorageStream *pS) +{ + long nStart = pS->Tell(); + *pS >> nIdentifier; + DBG_ASSERT(0x400==nIdentifier, + "A control that has a different identifier"); + *pS >> nFixedAreaLen; + pS->Read(pBlockFlags,4); + + if (pBlockFlags[0] & 0x01) + { + DBG_ASSERT(!this, "ARSE"); + } + if (pBlockFlags[0] & 0x02) + *pS >> mnBackColor; + if (pBlockFlags[0] & 0x04) + *pS >> mnForeColor; + if (pBlockFlags[0] & 0x08) + *pS >> fUnknown1; + if (pBlockFlags[0] & 0x40) + { + sal_uInt8 nTemp; + *pS >> nTemp; + fEnabled = (nTemp&0x04)>>2; + fBackStyle = (nTemp&0x08)>>3; + *pS >> nTemp; + *pS >> nTemp; + fWordWrap = (nTemp&0x80)>>7; + *pS >> nTemp; + fAutoSize = (nTemp&0x10)>>4; + } + if (pBlockFlags[0] & 0x80) + { + *pS >> nBorderStyle; + } + + ReadAlign(pS, pS->Tell() - nStart, 4); + + if (pBlockFlags[1] & 0x01) + *pS >> nMousePointer; + if (pBlockFlags[1] & 0x02) + *pS >> nKeepScrollBarsVisible; + if (pBlockFlags[1] & 0x20) + *pS >> fUnknown1; // another unknown 32 bit ( or is 8 or 16 bit with padding ? ) + + if (pBlockFlags[1] & 0x80) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nIcon; + DBG_ASSERT(nIcon == 0xFFFF, "Unexpected nIcon"); + } + + bool bCaption = false; + + if (pBlockFlags[2] & 0x01) + *pS >> nCycle; + if (pBlockFlags[2] & 0x02) + *pS >> nSpecialEffect; + + if (pBlockFlags[2] & 0x04) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nBorderColor; + } + + if (pBlockFlags[2] & 0x08) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nCaptionLen; + bCaption = true; + } + + if (pBlockFlags[2] & 0x10) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + sal_uInt16 nNoIdea; + *pS >> nNoIdea; + DBG_ASSERT(nNoIdea == 0xFFFF, "Expected 0xFFFF, (related to font ?)"); + } + + if (pBlockFlags[2] & 0x20) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nPicture; + DBG_ASSERT(nPicture == 0xFFFF, "Unexpected nIcon"); + } + + if (pBlockFlags[2] & 0x80) + *pS >> nPictureAlignment; + + if (pBlockFlags[3] & 0x01) + bPictureTiling = true; + + if (pBlockFlags[3] & 0x02) + *pS >> nPictureSizeMode; + + if (pBlockFlags[3] & 0x04) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> fUnknown8; + } + + if (pBlockFlags[3] & 0x08) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> fUnknown9; + } + + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nWidth; + *pS >> nHeight; + *pS >> nScrollWidth; + *pS >> nScrollHeight; + + if (pBlockFlags[1] & 0x10) + { + *pS >> nScrollLeft; + *pS >> nScrollTop; + } + + if ( bCaption ) + { + lclReadCharArray( *pS, pCaption, nCaptionLen, pS->Tell() - nStart); + } + + OUString tempCaption = lclCreateOUString( pCaption, nCaptionLen ); + + if (nIcon) + { + pS->Read(pIconHeader,20); + *pS >> nIconLen; + pIcon = new sal_uInt8[nIconLen]; + pS->Read(pIcon,nIconLen); + } + + if (nPicture) + { + pS->Read(pPictureHeader,20); + *pS >> nPictureLen; + pPicture = new sal_uInt8[nPictureLen]; + pS->Read(pPicture,nPictureLen); + } + + ReadAlign( pS, pS->Tell() - nStart, 4); + + if (pBlockFlags[2] & 0x10) + { + //Font Stuff.. + pS->SeekRel(0x1a); + sal_uInt8 nFontLen; + *pS >> nFontLen; + pS->SeekRel(nFontLen); + } + + return OCX_ContainerControl::Read( pS ); +} + +sal_Bool OCX_Frame::Import(com::sun::star::uno::Reference< + com::sun::star::beans::XPropertySet> &rPropSet) +{ + uno::Any aTmp(&sName,getCppuType((OUString *)0)); + rPropSet->setPropertyValue( + OUString(RTL_CONSTASCII_USTRINGPARAM("Name")), aTmp); + if ( pCaption ) + { + aTmp <<= lclCreateOUString( pCaption, nCaptionLen ); + rPropSet->setPropertyValue( WW8_ASCII2STR("Label"), aTmp); + } + + // Calls import on contained controls + OCX_ContainerControl::Import( rPropSet ); + return sal_True; +} +OCX_UserForm::OCX_UserForm( SotStorageRef& parent, + const OUString& storageName, + const OUString& sN, + const ::uno::Reference< container::XNameContainer > &rDialog, + const ::uno::Reference< lang::XMultiServiceFactory >& rMsf): + OCX_ContainerControl(parent, storageName, sN, rDialog), + nChildrenA(0), fEnabled(1), fLocked(0), + fBackStyle(1), fWordWrap(1), fAutoSize(0), nCaptionLen(0), nVertPos(1), + nHorzPos(7), nMousePointer(0), nBorderColor(0x80000012), nChildrenB(0), + nKeepScrollBarsVisible(3), nCycle(0), nBorderStyle(0), nSpecialEffect(0), + nPicture(0), nPictureAlignment(2), nPictureSizeMode(0), + bPictureTiling(sal_False), nAccelerator(0), nIcon(0), pCaption(0), + nScrollWidth(0), nScrollHeight(0), nScrollLeft(0), nScrollTop(0), nIconLen(0), pIcon(0), nPictureLen(0), + pPicture(0) + { + mnForeColor = 0x80000012; + mnBackColor = 0x8000000F; + uno::Reference< beans::XPropertySet> xProps( rMsf, uno::UNO_QUERY); + if ( xProps.is() ) + { + xProps->getPropertyValue(C2S("DefaultContext")) >>= mxCtx; + } + aFontData.SetHasAlign(sal_True); + } +sal_Bool OCX_UserForm::Read(SvStorageStream *pS) +{ + long nStart = pS->Tell(); + *pS >> nIdentifier; + DBG_ASSERT(0x400==nIdentifier, + "A control that has a different identifier"); + *pS >> nFixedAreaLen; + pS->Read(pBlockFlags,4); + + if (pBlockFlags[0] & 0x01) + { + DBG_ASSERT(!this, "ARSE"); + } + if (pBlockFlags[0] & 0x02) + *pS >> mnBackColor; + if (pBlockFlags[0] & 0x04) + *pS >> mnForeColor; + if (pBlockFlags[0] & 0x08) + *pS >> nChildrenA; + if (pBlockFlags[0] & 0x40) + { + sal_uInt8 nTemp; + *pS >> nTemp; + fEnabled = (nTemp&0x04)>>2; + fBackStyle = (nTemp&0x08)>>3; + *pS >> nTemp; + *pS >> nTemp; + fWordWrap = (nTemp&0x80)>>7; + *pS >> nTemp; + fAutoSize = (nTemp&0x10)>>4; + } + if (pBlockFlags[0] & 0x80) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nBorderStyle; + } +#if 0 + sal_uInt16 nFixedOrAlign; + *pS >> nFixedOrAlign; +#endif + if (pBlockFlags[1] & 0x01) + *pS >> nMousePointer; + if (pBlockFlags[1] & 0x02) + *pS >> nKeepScrollBarsVisible; + if (pBlockFlags[1] & 0x20) + { + sal_uInt32 nUnknown32; + *pS >> nUnknown32; + } + if (pBlockFlags[1] & 0x80) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nIcon; + DBG_ASSERT(nIcon == 0xFFFF, "Unexpected nIcon"); + } + if (pBlockFlags[2] & 0x01) + *pS >> nCycle; + if (pBlockFlags[2] & 0x02) + *pS >> nSpecialEffect; + + if (pBlockFlags[2] & 0x04) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nBorderColor; + } + + if (pBlockFlags[2] & 0x10) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + sal_uInt16 nNoIdea; + *pS >> nNoIdea; + DBG_ASSERT(nNoIdea == 0xFFFF, "Expected 0xFFFF, (related to font ?)"); + } + + if (pBlockFlags[2] & 0x20) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nPicture; + DBG_ASSERT(nPicture == 0xFFFF, "Unexpected nIcon"); + } + + if (pBlockFlags[2] & 0x80) + *pS >> nPictureAlignment; + + if (pBlockFlags[3] & 0x01) + bPictureTiling = true; + + if (pBlockFlags[3] & 0x02) + *pS >> nPictureSizeMode; + + if (pBlockFlags[3] & 0x04) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nChildrenB; + } + + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nDrawBuffer; + + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nWidth; + *pS >> nHeight; + *pS >> nScrollWidth; + *pS >> nScrollHeight; + + if (pBlockFlags[1] & 0x10) + { + *pS >> nScrollLeft; + *pS >> nScrollTop; + } + + if (nIcon) + { + pS->Read(pIconHeader,20); + *pS >> nIconLen; + pIcon = new sal_uInt8[nIconLen]; + pS->Read(pIcon,nIconLen); + } + + if (nPicture) + { + pS->Read(pPictureHeader,20); + *pS >> nPictureLen; + pPicture = new sal_uInt8[nPictureLen]; + pS->Read(pPicture,nPictureLen); + } + + ReadAlign( pS, pS->Tell() - nStart, 4); + + if (pBlockFlags[2] & 0x10) + { + //Font Stuff.. + pS->SeekRel(0x1a); + sal_uInt8 nFontLen; + *pS >> nFontLen; + pS->SeekRel(nFontLen); + } + + sal_Int16 numTrailingRecs = 0; + *pS >> numTrailingRecs; + // seems to be no. of trailing records, + // before container record starts proper + // ( unknown what these trailing records are for) + if ( numTrailingRecs ) + { + for ( ; numTrailingRecs ; --numTrailingRecs ) + { + OCX_Control skip(C2S("dummy")) ; + skip.Read( pS ); + } + } + return OCX_ContainerControl::Read( pS ); +} + +sal_Bool OCX_UserForm::Import( + uno::Reference<container::XNameContainer> &rLib ) +{ + uno::Reference<beans::XPropertySet> + xDialogPropSet(mxParent, uno::UNO_QUERY); + uno::Any aTmp(&sName,getCppuType((OUString *)0)); + xDialogPropSet->setPropertyValue( + OUString(RTL_CONSTASCII_USTRINGPARAM("Name")), aTmp); + xDialogPropSet->setPropertyValue( + OUString(RTL_CONSTASCII_USTRINGPARAM("Title")), aTmp); + aTmp <<= ImportColor(mnBackColor); + xDialogPropSet->setPropertyValue( WW8_ASCII2STR("BackgroundColor"), aTmp); + + aTmp <<= sal_Int32((nWidth * 2) / 100); + xDialogPropSet->setPropertyValue(WW8_ASCII2STR("Width"), aTmp); + aTmp <<= sal_Int32((nHeight * 2) / 100); + xDialogPropSet->setPropertyValue(WW8_ASCII2STR("Height"), aTmp); + + uno::Reference<beans::XPropertySet> xPropSet( mxParent, uno::UNO_QUERY ); + OCX_ContainerControl::Import( xPropSet ); + + uno::Reference<io::XInputStreamProvider> xSource = + xmlscript::exportDialogModel(mxParent, mxCtx); + uno::Any aSourceAny(uno::makeAny(xSource)); + if (rLib->hasByName(sName)) + rLib->replaceByName(sName, aSourceAny); + else + rLib->insertByName(sName, aSourceAny); + return sal_True; +} + +sal_Bool OCX_Label::WriteContents(SvStorageStreamRef &rContents, + const uno::Reference< beans::XPropertySet > &rPropSet, + const awt::Size &rSize) +{ + sal_Bool bRet = sal_True; + sal_uInt32 nOldPos = rContents->Tell(); + rContents->SeekRel(8); + pBlockFlags[0] = 0x20; + pBlockFlags[1] = 0; + pBlockFlags[2] = 0; + pBlockFlags[3] = 0; + + uno::Any aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("TextColor")); + if (aTmp.hasValue()) + aTmp >>= mnForeColor; + *rContents << ExportColor(mnForeColor); + pBlockFlags[0] |= 0x01; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("BackgroundColor")); + if (aTmp.hasValue()) + aTmp >>= mnBackColor; + *rContents << ExportColor(mnBackColor); + pBlockFlags[0] |= 0x02; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("Enabled")); + fEnabled = any2bool(aTmp); + sal_uInt8 nTemp=fEnabled; + if (fEnabled) + nTemp = nTemp << 1; + *rContents << nTemp; + *rContents << sal_uInt8(0x00); + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("MultiLine")); + fWordWrap = any2bool(aTmp); + nTemp=fWordWrap; + nTemp = nTemp << 7; + *rContents << nTemp; + *rContents << sal_uInt8(0x00); + pBlockFlags[0] |= 0x04; + + SvxOcxString aCaption( rPropSet->getPropertyValue(WW8_ASCII2STR("Label")) ); + aCaption.WriteLenField( *rContents ); + if (aCaption.HasData()) + pBlockFlags[0] |= 0x08; + + WriteAlign(rContents,4); + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("BorderColor")); + if (aTmp.hasValue()) + aTmp >>= nBorderColor; + *rContents << ExportColor(nBorderColor); + pBlockFlags[0] |= 0x80; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("Border")); + sal_Int16 nBorder = sal_Int16(); + aTmp >>= nBorder; + sal_uInt8 nNewBorder; + nSpecialEffect = ExportBorder(nBorder,nNewBorder); + nBorderStyle = nNewBorder; + *rContents << nBorderStyle; + pBlockFlags[1] |= 0x01; + *rContents << nSpecialEffect; + pBlockFlags[1] |= 0x02; + + aCaption.WriteCharArray( *rContents ); + + WriteAlign(rContents,4); + *rContents << rSize.Width; + *rContents << rSize.Height; + nFixedAreaLen = static_cast<sal_uInt16>(rContents->Tell()-nOldPos-4); + + bRet = aFontData.Export(rContents,rPropSet); + + rContents->Seek(nOldPos); + *rContents << nStandardId; + *rContents << nFixedAreaLen; + + *rContents << pBlockFlags[0]; + *rContents << pBlockFlags[1]; + *rContents << pBlockFlags[2]; + *rContents << pBlockFlags[3]; + + DBG_ASSERT((rContents.Is() && + (SVSTREAM_OK==rContents->GetError())),"damn"); + return bRet; +} + + + +sal_Bool OCX_Label::Export(SvStorageRef &rObj, + const uno::Reference< beans::XPropertySet > &rPropSet, + const awt::Size &rSize) +{ + static sal_uInt8 __READONLY_DATA aCompObj[] = { + 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x23, 0x9E, 0x8C, 0x97, + 0xB0, 0xD4, 0xCE, 0x11, 0xBF, 0x2D, 0x00, 0xAA, + 0x00, 0x3F, 0x40, 0xD0, 0x1A, 0x00, 0x00, 0x00, + 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, + 0x74, 0x20, 0x46, 0x6F, 0x72, 0x6D, 0x73, 0x20, + 0x32, 0x2E, 0x30, 0x20, 0x4C, 0x61, 0x62, 0x65, + 0x6C, 0x00, 0x10, 0x00, 0x00, 0x00, 0x45, 0x6D, + 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x20, 0x4F, + 0x62, 0x6A, 0x65, 0x63, 0x74, 0x00, 0x0E, 0x00, + 0x00, 0x00, 0x46, 0x6F, 0x72, 0x6D, 0x73, 0x2E, + 0x4C, 0x61, 0x62, 0x65, 0x6C, 0x2E, 0x31, 0x00, + 0xF4, 0x39, 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor( rObj->OpenSotStream( C2S("\1CompObj"))); + xStor->Write(aCompObj,sizeof(aCompObj)); + DBG_ASSERT((xStor.Is() && (SVSTREAM_OK == xStor->GetError())),"damn"); + } + + { + SvStorageStreamRef xStor3( rObj->OpenSotStream( C2S("\3ObjInfo"))); + xStor3->Write(aObjInfo,sizeof(aObjInfo)); + DBG_ASSERT((xStor3.Is() && (SVSTREAM_OK == xStor3->GetError())),"damn"); + } + + static sal_uInt8 __READONLY_DATA aOCXNAME[] = { + 0x4C, 0x00, 0x61, 0x00, 0x62, 0x00, 0x65, 0x00, + 0x6C, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor2( rObj->OpenSotStream( C2S("\3OCXNAME"))); + xStor2->Write(aOCXNAME,sizeof(aOCXNAME)); + DBG_ASSERT((xStor2.Is() && (SVSTREAM_OK == xStor2->GetError())),"damn"); + } +/* + static sal_uInt8 __READONLY_DATA aTest[] = { + 0x00, 0x02, 0x20, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, + 0x06, 0x00, 0x00, 0x80, 0x4C, 0x61, 0x62, 0x65, + 0x6C, 0x31, 0x18, 0x00, 0xEC, 0x09, 0x00, 0x00, + 0x7B, 0x02, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, + 0x35, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x80, + 0xC3, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x54, 0x69, 0x6D, 0x65, 0x73, 0x20, 0x4E, 0x65, + 0x77, 0x20, 0x52, 0x6F, 0x6D, 0x61, 0x6E, 0x00, + }; +*/ + SvStorageStreamRef xContents( rObj->OpenSotStream( C2S("contents"))); + return WriteContents(xContents, rPropSet, rSize); +} + +typedef OCX_Control *(*FNCreate)(); + + +struct OCX_map +{ + FNCreate pCreate; + const char *sId; + sal_Int16 nId; + const char *sName; +}; + +OCX_map aOCXTab[] = +{ + // Command button MUST be at index 0 + {&OCX_CommandButton::Create,"D7053240-CE69-11CD-a777-00dd01143c57", + form::FormComponentType::COMMANDBUTTON,"CommandButton"}, + // Toggle button MUST be at index 1 + {&OCX_ToggleButton::Create,"8BD21D60-EC42-11CE-9e0d-00aa006002f3", + form::FormComponentType::COMMANDBUTTON,"ToggleButton"}, + {&OCX_Label::Create, "978C9E23-D4B0-11CE-bf2d-00aa003f40d0", + form::FormComponentType::FIXEDTEXT,"Label"}, + {&OCX_TextBox::Create,"8BD21D10-EC42-11CE-9e0d-00aa006002f3", + form::FormComponentType::TEXTFIELD,"TextBox"}, + {&OCX_ListBox::Create,"8BD21D20-EC42-11CE-9e0d-00aa006002f3", + form::FormComponentType::LISTBOX,"ListBox"}, + {&OCX_ComboBox::Create,"8BD21D30-EC42-11CE-9e0d-00aa006002f3", + form::FormComponentType::COMBOBOX,"ComboBox"}, + {&OCX_CheckBox::Create,"8BD21D40-EC42-11CE-9e0d-00aa006002f3", + form::FormComponentType::CHECKBOX,"CheckBox"}, + {&OCX_OptionButton::Create,"8BD21D50-EC42-11CE-9e0d-00aa006002f3", + form::FormComponentType::RADIOBUTTON,"OptionButton"}, + {&OCX_Image::Create,"4C599241-6926-101B-9992-00000b65c6f9", + form::FormComponentType::IMAGECONTROL,"Image"}, + {&OCX_FieldControl::Create,"8BD21D10-EC42-11CE-9e0d-00aa006002f3", + form::FormComponentType::DATEFIELD,"TextBox"}, + {&OCX_FieldControl::Create,"8BD21D10-EC42-11CE-9e0d-00aa006002f3", + form::FormComponentType::TIMEFIELD,"TextBox"}, + {&OCX_FieldControl::Create,"8BD21D10-EC42-11CE-9e0d-00aa006002f3", + form::FormComponentType::NUMERICFIELD,"TextBox"}, + {&OCX_FieldControl::Create,"8BD21D10-EC42-11CE-9e0d-00aa006002f3", + form::FormComponentType::CURRENCYFIELD,"TextBox"}, + {&OCX_FieldControl::Create,"8BD21D10-EC42-11CE-9e0d-00aa006002f3", + form::FormComponentType::PATTERNFIELD,"TextBox"}, +#if 0 + {&OCX_FieldControl::Create,"8BD21D10-EC42-11CE-9e0d-00aa006002f3", + form::FormComponentType::FORMULAFIELD,"TextBox"}, +#endif + {&OCX_ImageButton::Create,"D7053240-CE69-11CD-a777-00dd01143c57", + form::FormComponentType::IMAGEBUTTON,"CommandButton"}, + {&OCX_SpinButton::Create,"79176FB0-B7F2-11CE-97ef-00aa006d2776", + form::FormComponentType::SPINBUTTON,"SpinButton"}, + {&OCX_ScrollBar::Create,"DFD181E0-5E2F-11CE-a449-00aa004a803d", + form::FormComponentType::SCROLLBAR,"ScrollBar"}, + {&OCX_GroupBox::Create,"", + form::FormComponentType::GROUPBOX,""}, + {&OCX_ProgressBar::Create,"", + form::FormComponentType::CONTROL,""} +}; + +const int NO_OCX = sizeof( aOCXTab ) / sizeof( *aOCXTab ); + +SvxMSConvertOCXControls::SvxMSConvertOCXControls(SfxObjectShell *pDSh, SwPaM *pP) : + pDocSh(pDSh), pPaM(pP), nEdit(0), nCheckbox(0) +{ + DBG_ASSERT( pDocSh, "No DocShell, Cannot do Controls" ); + OCX_Control::FillSystemColors(); +} + +SvxMSConvertOCXControls::~SvxMSConvertOCXControls() +{ +} + +OCX_Control * SvxMSConvertOCXControls::OCX_Factory(const String &sName) +{ + for (int i=0;i<NO_OCX;i++) + { + if ( sName.EqualsIgnoreCaseAscii( aOCXTab[i].sId )) + return(aOCXTab[i].pCreate()); + } + return(NULL); +} + +OCX_Control * SvxMSConvertOCXControls::OCX_Factory( + const uno::Reference< awt::XControlModel > &rControlModel, + String &rId, String &rName) +{ + rName.Erase(); + rId.Erase(); + + uno::Reference< beans::XPropertySet > xPropSet( + rControlModel,uno::UNO_QUERY); + + uno::Any aTmp = xPropSet->getPropertyValue( + OUString::createFromAscii("ClassId")); + sal_Int16 nClassId = *(sal_Int16*) aTmp.getValue(); + +//Begin nasty hack + /* + There is a truly horrible thing with EditControls and FormattedField + Controls, they both pretend to have an EDITBOX ClassId for compability + reasons, at some stage in the future hopefully there will be a proper + FormulaField ClassId rather than this piggybacking two controls onto the + same ClassId, when this happens uncomment the FORMULAFIELD in the OCX_Tab + and delete this block, cmc. + + And also the nClassId for ImageControls is being reported as "CONTROL" + rather than IMAGECONTROL + */ + if (nClassId == form::FormComponentType::TEXTFIELD) + { + uno::Reference< lang::XServiceInfo > xInfo(rControlModel, + uno::UNO_QUERY); + if (xInfo-> + supportsService(OUString::createFromAscii( + "com.sun.star.form.component.FormattedField"))) + { + rId.AppendAscii("8BD21D10-EC42-11CE-9e0d-00aa006002f3"); + rName.AppendAscii("TextBox"); + return new OCX_FieldControl; + } + } + else if (nClassId == form::FormComponentType::CONTROL) + { + uno::Reference< lang::XServiceInfo > xInfo(rControlModel, + uno::UNO_QUERY); + if (xInfo-> + supportsService(OUString::createFromAscii( + "com.sun.star.form.component.ImageControl"))) + nClassId = form::FormComponentType::IMAGECONTROL; + } +//End nasty hack + + const OCX_map* pEntry = 0; + + // distinguish between push button and toggle button + if( nClassId == form::FormComponentType::COMMANDBUTTON ) + { + pEntry = any2bool(xPropSet->getPropertyValue(WW8_ASCII2STR("Toggle"))) ? + (aOCXTab + 1) : aOCXTab; + } + else + { + for( int i = 2; (i < NO_OCX) && !pEntry; ++i ) + if( nClassId == aOCXTab[ i ].nId ) + pEntry = aOCXTab + i; + } + + if( pEntry ) + { + rId.AppendAscii( pEntry->sId ); + rName.AppendAscii( pEntry->sName ); + return pEntry->pCreate(); + } + + return 0; +} + + +sal_Bool SvxMSConvertOCXControls::ReadOCXStream( SvStorageRef& rSrc1, + uno::Reference < drawing::XShape > *pShapeRef,sal_Bool bFloatingCtrl) +{ + + SvStorageStreamRef xCrash = rSrc1->OpenSotStream( WW8_ASCII2STR("contents") ); + sal_Bool bRet=sal_False; + + SvStorageStreamRef xSrc2 = rSrc1->OpenSotStream( WW8_ASCII2STR("\3OCXNAME") ); + SvStorageStream* pSt = xSrc2; + pSt->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); + + /* #117832# import control name */ + OUString controlName; + bool hasCName = readOCXNAME( controlName, pSt ); + + xSrc2 = rSrc1->OpenSotStream( WW8_ASCII2STR("contents") ); + pSt = xSrc2; + pSt->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); + + /*Get Class Id of this object, see if it is one of the types + *that this importer can handle, call the appropiate handler + to read that control, and call the appropiate handler to + insert that control + */ + + SvGlobalName aTest = rSrc1->GetClassName(); + OCX_Control *pObj = OCX_Factory(aTest.GetHexName()); + if (pObj) + { + pObj->pDocSh = pDocSh; + /* #117832# set imported control name */ + if ( hasCName ) + { + pObj->sName = controlName; + } + com::sun::star::awt::Size aSz; + uno::Reference< form::XFormComponent > xFComp; + const uno::Reference< lang::XMultiServiceFactory > & rServiceFactory = + GetServiceFactory(); + if(!rServiceFactory.is()) + return(sal_False); + bRet = pObj->FullRead(pSt); + if(bRet) + if (pObj->Import(rServiceFactory,xFComp,aSz)) + bRet = InsertControl( xFComp, aSz,pShapeRef,bFloatingCtrl); + delete pObj; + } + return bRet; +} + + +sal_Bool SvxMSConvertOCXControls::ReadOCXExcelKludgeStream( + SvStorageStreamRef& rSrc1, uno::Reference < drawing::XShape > * + pShapeRef,sal_Bool bFloatingCtrl) +{ + sal_Bool bRet=sal_False; + /*Get Class Id of this object, see if it is one of the types + *that this importer can handle, call the appropiate handler + to read that control, and call the appropiate handler to + insert that control + */ + /*The Excel Kludge is to concatenate a class id with a contents + * stream, and then concatenate all the controls together, + * This means that you should have the cnts stream wound to the + * correct location before passing the control stream in here*/ + SvStream *pSt = rSrc1; + pSt->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); + SvGlobalName aTest; + *pSt >> aTest; + OCX_Control *pObj = OCX_Factory(aTest.GetHexName()); + if (pObj) + { + + com::sun::star::awt::Size aSz; + uno::Reference< form::XFormComponent > xFComp; + const uno::Reference< lang::XMultiServiceFactory > & rServiceFactory = + GetServiceFactory(); + if(!rServiceFactory.is()) + return(sal_False); + bRet = pObj->FullRead(rSrc1); + if(bRet) + if (pObj->Import(rServiceFactory,xFComp,aSz)) + bRet = InsertControl( xFComp, aSz,pShapeRef,bFloatingCtrl); + delete pObj; + } + return bRet; +} + + +sal_Bool SvxMSConvertOCXControls::WriteOCXStream( SvStorageRef& rSrc1, + const uno::Reference< awt::XControlModel > &rControlModel, + const awt::Size &rSize, String &rName) +{ + sal_Bool bRet=sal_False; + + DBG_ASSERT( rControlModel.is(), "UNO-Control missing Model, panic!" ); + if( !rControlModel.is() ) + return sal_False; + +#if 0 + uno::Any aTmp = xPropSet->getPropertyValue( + OUString::createFromAscii("ClassId")); + sal_Int16 nClassId = *(sal_Int16*) aTmp.getValue(); +#endif + + String sId; + OCX_Control *pObj = OCX_Factory(rControlModel,sId,rName); + if (pObj != NULL) + { + uno::Reference<beans::XPropertySet> xPropSet(rControlModel, + uno::UNO_QUERY); + + /* #117832# - also enable export of control name */ + OUString sCName; + xPropSet->getPropertyValue(C2S("Name")) >>= sCName; + pObj->sName = sCName; + + SvGlobalName aName; + aName.MakeId(sId); + String sFullName(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM( + "Microsoft Forms 2.0 "))); + sFullName.Append(rName); + rSrc1->SetClass(aName,0x5C,sFullName); + // ^^^^, this pathetic 0x5c is the magic number + // which the lack of originally blocked the implementation of + // the controls export + // cmc + + bRet = pObj->Export(rSrc1,xPropSet,rSize); + SvStorageStreamRef xStor2( rSrc1->OpenSotStream( WW8_ASCII2STR("\3OCXNAME"))); + /* #117832# - also enable export of control name */ + writeOCXNAME( sCName, xStor2 ); + delete pObj; + } + return bRet; +} + + +//I think this should work for excel documents, create the "Ctls" stream +//and give it here as rContents, we'll append out streams ole id and +//contents here and that appears to be what Excel is doing +sal_Bool SvxMSConvertOCXControls::WriteOCXExcelKludgeStream( + SvStorageStreamRef& rContents, + const uno::Reference< awt::XControlModel > &rControlModel, + const awt::Size &rSize, String &rName) +{ + sal_Bool bRet=sal_False; + + DBG_ASSERT( rControlModel.is(), "UNO-Control missing Model, panic!" ); + if( !rControlModel.is() ) + return sal_False; + + String sId; + OCX_Control *pObj = OCX_Factory(rControlModel,sId,rName); + if (pObj != NULL) + { + uno::Reference<beans::XPropertySet> xPropSet(rControlModel, + uno::UNO_QUERY); + + SvGlobalName aName; + aName.MakeId(sId); + String sFullName(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM( + "Microsoft Forms 2.0 "))); + sFullName.Append(rName); + SvStream *pS=rContents; + *pS << aName; + bRet = pObj->WriteContents(rContents,xPropSet,rSize); + delete pObj; + // export needs correct stream position + rContents->Seek( STREAM_SEEK_TO_END ); + } + return bRet; +} + + + + + + + +sal_Bool OCX_CheckBox::Import(com::sun::star::uno::Reference< + com::sun::star::beans::XPropertySet> &rPropSet) +{ + uno::Any aTmp(&sName,getCppuType((OUString *)0)); + rPropSet->setPropertyValue( WW8_ASCII2STR("Name"), aTmp ); + + // background color: fBackStyle==0 -> transparent + if( fBackStyle ) + aTmp <<= ImportColor(mnBackColor); + else + aTmp = uno::Any(); + rPropSet->setPropertyValue( WW8_ASCII2STR("BackgroundColor"), aTmp); + + sal_Bool bTemp; + if ((!(fEnabled)) || (fLocked)) + bTemp = sal_False; + else + bTemp = sal_True; + aTmp = bool2any(bTemp); + rPropSet->setPropertyValue( WW8_ASCII2STR("Enabled"), aTmp); + + bTemp = fWordWrap != 0; + aTmp = bool2any(bTemp); + rPropSet->setPropertyValue( WW8_ASCII2STR("MultiLine"), aTmp); + + aTmp <<= ImportColor(mnForeColor); + rPropSet->setPropertyValue( WW8_ASCII2STR("TextColor"), aTmp); + + bTemp = nMultiState; + aTmp = bool2any(bTemp); + rPropSet->setPropertyValue( WW8_ASCII2STR("TriState"), aTmp); + + aTmp <<= ImportSpecEffect( nSpecialEffect ); + rPropSet->setPropertyValue( WW8_ASCII2STR("VisualEffect"), aTmp); + + if (pValue && !bSetInDialog) + { + sal_Int16 nTmp=pValue[0]-0x30; + aTmp <<= nTmp; + rPropSet->setPropertyValue( WW8_ASCII2STR("DefaultState"), aTmp); + } + + if (pCaption) + { + aTmp <<= lclCreateOUString( pCaption, nCaptionLen ); + rPropSet->setPropertyValue( WW8_ASCII2STR("Label"), aTmp); + } + + // #i40279# always centered vertically + aTmp <<= ::com::sun::star::style::VerticalAlignment_MIDDLE; + rPropSet->setPropertyValue( WW8_ASCII2STR("VerticalAlign"), aTmp ); + + aFontData.Import(rPropSet); + return(sal_True); +} + +sal_Bool OCX_CheckBox::WriteContents(SvStorageStreamRef &rContents, + const uno::Reference< beans::XPropertySet > &rPropSet, + const awt::Size &rSize) + +{ + sal_Bool bRet=sal_True; + sal_uInt32 nOldPos = rContents->Tell(); + rContents->SeekRel(12); + + pBlockFlags[0] = 0; + pBlockFlags[1] = 0x01; + pBlockFlags[2] = 0; + pBlockFlags[3] = 0x80; + pBlockFlags[4] = 0; + pBlockFlags[5] = 0; + pBlockFlags[6] = 0; + pBlockFlags[7] = 0; + + uno::Any aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("Enabled")); + fEnabled = any2bool(aTmp); + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("BackgroundColor")); + fBackStyle = aTmp.hasValue() ? 1 : 0; + if (fBackStyle) + aTmp >>= mnBackColor; + + sal_uInt8 nTemp=fEnabled; + if (fEnabled) + nTemp = nTemp << 1; + if (fBackStyle) + nTemp |= 0x08; + *rContents << nTemp; + pBlockFlags[0] |= 0x01; + *rContents << sal_uInt8(0x00); + nTemp = 0; + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("MultiLine")); + fWordWrap = any2bool(aTmp); + if (fWordWrap) + nTemp |= 0x80; + *rContents << nTemp; + *rContents << sal_uInt8(0x00); + + *rContents << ExportColor(mnBackColor); + pBlockFlags[0] |= 0x02; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("TextColor")); + if (aTmp.hasValue()) + aTmp >>= mnForeColor; + *rContents << ExportColor(mnForeColor); + pBlockFlags[0] |= 0x04; + + nStyle = 4; + *rContents << nStyle; + pBlockFlags[0] |= 0x40; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("TriState")); + nMultiState = any2bool(aTmp); + *rContents << nMultiState; + pBlockFlags[2] |= 0x20; + + WriteAlign(rContents,4); + nValueLen = 1|SVX_MSOCX_COMPRESSED; + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("DefaultState")); + sal_Int16 nDefault = sal_Int16(); + aTmp >>= nDefault; + *rContents << nValueLen; + pBlockFlags[2] |= 0x40; + + SvxOcxString aCaption( rPropSet->getPropertyValue(WW8_ASCII2STR("Label")) ); + aCaption.WriteLenField( *rContents ); + if (aCaption.HasData()) + pBlockFlags[2] |= 0x80; + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("VisualEffect")); + if (aTmp.hasValue()) + { + sal_Int16 nApiSpecEffect = sal_Int16(); + aTmp >>= nApiSpecEffect; + nSpecialEffect = ExportSpecEffect( nApiSpecEffect ); + } + WriteAlign(rContents,4); + *rContents << nSpecialEffect; + pBlockFlags[3] |= 0x04; + + WriteAlign(rContents,4); + *rContents << rSize.Width; + *rContents << rSize.Height; + + nDefault += 0x30; + *rContents << sal_uInt8(nDefault); + *rContents << sal_uInt8(0x00); + + aCaption.WriteCharArray( *rContents ); + + WriteAlign(rContents,4); + nFixedAreaLen = static_cast<sal_uInt16>(rContents->Tell()-nOldPos-4); + bRet = aFontData.Export(rContents,rPropSet); + rContents->Seek(nOldPos); + *rContents << nStandardId; + *rContents << nFixedAreaLen; + + *rContents << pBlockFlags[0]; + *rContents << pBlockFlags[1]; + *rContents << pBlockFlags[2]; + *rContents << pBlockFlags[3]; + *rContents << pBlockFlags[4]; + *rContents << pBlockFlags[5]; + *rContents << pBlockFlags[6]; + *rContents << pBlockFlags[7]; + + DBG_ASSERT((rContents.Is() && + (SVSTREAM_OK==rContents->GetError())),"damn"); + return bRet; +} + + +sal_Bool OCX_CheckBox::Export(SvStorageRef &rObj, + const uno::Reference< beans::XPropertySet > &rPropSet, + const awt::Size &rSize) + +{ + static sal_uInt8 __READONLY_DATA aCompObj[] = { + 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0x1D, 0xD2, 0x8B, + 0x42, 0xEC, 0xCE, 0x11, 0x9E, 0x0D, 0x00, 0xAA, + 0x00, 0x60, 0x02, 0xF3, 0x1D, 0x00, 0x00, 0x00, + 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, + 0x74, 0x20, 0x46, 0x6F, 0x72, 0x6D, 0x73, 0x20, + 0x32, 0x2E, 0x30, 0x20, 0x43, 0x68, 0x65, 0x63, + 0x6B, 0x42, 0x6F, 0x78, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x45, 0x6D, 0x62, 0x65, 0x64, 0x64, 0x65, + 0x64, 0x20, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, + 0x00, 0x11, 0x00, 0x00, 0x00, 0x46, 0x6F, 0x72, + 0x6D, 0x73, 0x2E, 0x43, 0x68, 0x65, 0x63, 0x6B, + 0x42, 0x6F, 0x78, 0x2E, 0x31, 0x00, 0xF4, 0x39, + 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor( rObj->OpenSotStream( C2S("\1CompObj"))); + xStor->Write(aCompObj,sizeof(aCompObj)); + DBG_ASSERT((xStor.Is() && (SVSTREAM_OK == xStor->GetError())),"damn"); + } + + { + SvStorageStreamRef xStor3( rObj->OpenSotStream( C2S("\3ObjInfo"))); + xStor3->Write(aObjInfo,sizeof(aObjInfo)); + DBG_ASSERT((xStor3.Is() && (SVSTREAM_OK == xStor3->GetError())),"damn"); + } + + static sal_uInt8 __READONLY_DATA aOCXNAME[] = { + 0x43, 0x00, 0x68, 0x00, 0x65, 0x00, 0x63, 0x00, + 0x6B, 0x00, 0x42, 0x00, 0x6F, 0x00, 0x78, 0x00, + 0x31, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + { + SvStorageStreamRef xStor2( rObj->OpenSotStream( C2S("\3OCXNAME"))); + xStor2->Write(aOCXNAME,sizeof(aOCXNAME)); + DBG_ASSERT((xStor2.Is() && (SVSTREAM_OK == xStor2->GetError())),"damn"); + } +/* + static sal_uInt8 __READONLY_DATA aTest[] = { + 0x00, 0x02, 0x34, 0x00, 0x46, 0x01, 0xC0, 0x80, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x80, 0x09, 0x00, 0x00, 0x80, + 0xE2, 0x0E, 0x00, 0x00, 0x95, 0x02, 0x00, 0x00, + 0x30, 0x69, 0x1D, 0x00, 0x43, 0x68, 0x65, 0x63, + 0x6B, 0x42, 0x6F, 0x78, 0x31, 0x20, 0x52, 0x6F, + 0x00, 0x02, 0x20, 0x00, 0x35, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x80, 0xC3, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x54, 0x69, 0x6D, 0x65, + 0x73, 0x20, 0x4E, 0x65, 0x77, 0x20, 0x52, 0x6F, + 0x6D, 0x61, 0x6E, 0x00, + }; +*/ + SvStorageStreamRef xContents( rObj->OpenSotStream( C2S("contents"))); + return WriteContents(xContents, rPropSet, rSize); +} + + +sal_Bool OCX_FontData::Read(SvStorageStream *pS) +{ + long nStart = pS->Tell(); + *pS >> nIdentifier; + *pS >> nFixedAreaLen; + pS->Read(pBlockFlags,4); + + bool bFontName = (pBlockFlags[0] & 0x01) != 0; + if (bFontName) + *pS >> nFontNameLen; + if (pBlockFlags[0] & 0x02) + { + sal_uInt8 nTmp; + *pS >> nTmp; + fBold = nTmp & 0x01; + fItalic = (nTmp & 0x02) >> 1; + fUnderline = (nTmp & 0x04) >> 2; + fStrike = (nTmp & 0x08) >> 3; + fUnknown1 = (nTmp & 0xF0) >> 4; + *pS >> nUnknown2; + *pS >> nUnknown3; + *pS >> nUnknown4; + } + if (pBlockFlags[0] & 0x04) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nFontSize; + } + else + nFontSize = 240; + if (pBlockFlags[0] & 0x10) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nLanguageID; + } + if (pBlockFlags[0] & 0x40) + { + *pS >> nJustification; + } + if (pBlockFlags[0] & 0x80) // font weight before font name + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nFontWeight; + } + + if (bFontName) + lclReadCharArray( *pS, pFontName, nFontNameLen, pS->Tell() - nStart); + + ReadAlign(pS, pS->Tell() - nStart, 4); + return(sal_True); +} + +void OCX_FontData::Import(uno::Reference< beans::XPropertySet > &rPropSet) +{ + uno::Any aTmp; + if (pFontName) + { + aTmp <<= lclCreateOUString( pFontName, nFontNameLen ); + rPropSet->setPropertyValue( WW8_ASCII2STR("FontName"), aTmp); + } + + if (bHasAlign) + { + sal_Int16 nAlign = ImportAlign(nJustification); + aTmp <<= nAlign; + rPropSet->setPropertyValue( WW8_ASCII2STR("Align"), aTmp); + } + + if (fBold) + { + aTmp <<= awt::FontWeight::BOLD; + rPropSet->setPropertyValue( WW8_ASCII2STR("FontWeight"), aTmp); + } + + if (fItalic) + { + aTmp <<= (sal_Int16)awt::FontSlant_ITALIC; + rPropSet->setPropertyValue( WW8_ASCII2STR("FontSlant"), aTmp); + } + + if (fUnderline) + { + aTmp <<= awt::FontUnderline::SINGLE; + rPropSet->setPropertyValue( WW8_ASCII2STR("FontUnderline"), aTmp); + } + + if (fStrike) + { + aTmp <<= awt::FontStrikeout::SINGLE; + rPropSet->setPropertyValue( WW8_ASCII2STR("FontStrikeout"), aTmp); + } + + // 2004-09-17: very strange way of storing font sizes... + // 1pt->30, 2pt->45, 3pt->60, 4pt->75, 5pt->105, 6pt->120, 7pt->135 + // 8pt->165, 9pt->180, 10pt->195, 11pt->225, ... + aTmp <<= sal_Int16( (nFontSize <= 30) ? 1 : ((nFontSize + 10) / 20) ); + rPropSet->setPropertyValue( WW8_ASCII2STR("FontHeight"), aTmp); +} + +sal_Bool OCX_FontData::Export(SvStorageStreamRef &rContent, + const uno::Reference< beans::XPropertySet > &rPropSet) +{ + sal_uInt8 nFlags=0x00; + sal_uInt32 nOldPos = rContent->Tell(); + rContent->SeekRel(8); + SvxOcxString aFontName; + uno::Any aTmp; + + if (bHasFont) + aFontName = rPropSet->getPropertyValue(WW8_ASCII2STR("FontName")); + if (!aFontName.HasData()) + aFontName = OUString( RTL_CONSTASCII_USTRINGPARAM( "Times New Roman" ) ); + aFontName.WriteLenField( *rContent ); + nFlags |= 0x01; + + if (bHasFont) + { + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("FontWeight")); + float nBold = 0; + aTmp >>= nBold; + + if (nBold >= 150) + { + nFlags |= 0x02; + sal_uInt8 nTmp=0x01; + *rContent << nTmp; + nTmp=0x00; + *rContent << nTmp; + *rContent << nTmp; + *rContent << nTmp; + } + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("FontHeight")); + float nFontHeight = 0; + aTmp >>= nFontHeight; + if (nFontHeight) + { + nFlags |= 0x04; + // 2004-09-17: very strange way of storing font sizes: + // 1pt->30, 2pt->45, 3pt->60, 4pt->75, 5pt->105, 6pt->120, 7pt->135 + // 8pt->165, 9pt->180, 10pt->195, 11pt->225, ... + nFontSize = (nFontHeight == 1) ? 30 : (static_cast<sal_uInt32>((nFontHeight*4+1)/3)*15); + *rContent << nFontSize; + } + + if (bHasAlign) + { + *rContent << sal_uInt16(0x0200); + nFlags |= 0x10; + + nFlags |= 0x20; // ? + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("Align")); + nFlags |= 0x40; + sal_Int16 nAlign(0); + if (aTmp.hasValue()) + aTmp >>= nAlign; + nJustification = ExportAlign(nAlign); + *rContent << nJustification; + } + } + + aFontName.WriteCharArray( *rContent ); + WriteAlign(rContent,4); + + sal_uInt16 nFixedAreaLn = static_cast<sal_uInt16>(rContent->Tell()-nOldPos-4); + rContent->Seek(nOldPos); + *rContent << nStandardId; + *rContent << nFixedAreaLn; + *rContent << nFlags; + *rContent << sal_uInt8(0x00); + *rContent << sal_uInt8(0x00); + *rContent << sal_uInt8(0x00); + + WriteAlign(rContent,4); + return sal_True; +} + +// Doesn't really read anything but just skips the +// record. +sal_Bool OCX_TabStrip::Read(SotStorageStream *pS) +{ + const long skipLen = 0x18; + *pS >> nIdentifier; + DBG_ASSERT(nStandardId==nIdentifier, + "A control that has a different identifier"); + *pS >> nFixedAreaLen; + + pS->Read(pBlockFlags, sizeof(pBlockFlags)); + pS->SeekRel(skipLen); + *pS >> nNumTabs; + // skip to end of control + pS->SeekRel(nFixedAreaLen - sizeof(pBlockFlags) - sizeof(nNumTabs) - skipLen ); + return sal_True; +} + +sal_Bool OCX_TabStrip::ReadFontData(SotStorageStream *pS) +{ + // Seems like there is a real font record followed by + // a number of blank records ( e.g. nFixedAreaLen = 0 ) + // The number of trailing blank records is equal to the number of tabs + OCX_Control::ReadFontData(pS); + for ( sal_uInt16 index = 0; index < nNumTabs; index++ ) + { + OCX_Control::Read(pS); // read trailing records + } + return sal_True; +} + +sal_Bool OCX_Image::Read(SotStorageStream *pS) +{ + if ( !bSetInDialog ) + { + // preserve the present behavior at the moment. + // only import image control for UserForms + return sal_False; + } + sal_uLong nStart = pS->Tell(); + *pS >> nIdentifier; + DBG_ASSERT(nStandardId==nIdentifier, + "A control that has a different identifier"); + *pS >> nFixedAreaLen; + + pS->Read(pBlockFlags, sizeof(pBlockFlags)); + + bool hasEmbeddedImage = false; + + if ( pBlockFlags[0] & 0x04 ) + { + bAutoSize = true; + } + if ( pBlockFlags[0] & 0x08 ) + { + *pS >> nBorderColor; + } + if ( pBlockFlags[0] & 0x10 ) + { + *pS >> mnBackColor; + } + if ( pBlockFlags[0] & 0x20 ) + { + *pS >> nBorderStyle; + } + if ( pBlockFlags[0] & 0x40 ) + { + *pS >> nMousePointer; + } + if ( pBlockFlags[0] & 0x80 ) + { + *pS >> nPictureSizeMode; + } + + if ( pBlockFlags[ 1 ] & 0x1 ) + { + *pS >> nSpecialEffect; + } + // investigate if valid also for formcontrols, although for controls + // images themselves seem to come through from escher ( as shape, think + // its probably a preview? ) + + // np a bit of a guess ( until proved incorrect ) + if ( pBlockFlags[ 1 ] & 0x4 ) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + hasEmbeddedImage = true; + sal_uInt16 unknown; + *pS >> unknown; + } + + + if ( pBlockFlags[ 1 ] & 0x8 ) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nPictureAlignment; + + } + if ( pBlockFlags[ 1 ] & 0x10 ) + { + bPictureTiling = true; + } + if ( pBlockFlags[1] & 0x20 ) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + sal_uInt8 nTemp; + *pS >> nTemp; + fEnabled = (nTemp&0x02)>>1; + fBackStyle = (nTemp&0x08)>>3; + // padding? + *pS >> nTemp; + *pS >> nTemp; + *pS >> nTemp; + } + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nWidth; + *pS >> nHeight; + + if ( hasEmbeddedImage ) + { + //image follows this block + //len of image is 0x14 relative to end of this block + pS->Seek( pS->Tell() + 0x14 ); + + sal_uInt32 nImageLen = 0; + *pS >> nImageLen; + + long imagePos = pS->Tell(); + + pS->Seek( imagePos ); + + sImageUrl = C2U("vnd.sun.star.expand:${$BRAND_BASE_DIR/program/") + C2U( SAL_CONFIGFILE( "bootstrap" ) ) + C2U("::UserInstallation}/user/temp/") + sName; + + sal_uInt8* pImage = new sal_uInt8[ nImageLen ]; + pS->Read(pImage, nImageLen); + bool result = storePictureInFileSystem( sImageUrl, pImage, nImageLen ); + OUString pictName = sImageUrl.copy( sImageUrl.lastIndexOf('/') + 1 ); + result = storePictureInDoc( pDocSh, pictName, pImage, nImageLen ); + delete [] pImage; + } + return sal_True; +} + +sal_Bool OCX_Image::Import( uno::Reference< beans::XPropertySet > &rPropSet ) +{ + uno::Any aTmp(&sName,getCppuType((OUString *)0)); + rPropSet->setPropertyValue( WW8_ASCII2STR("Name"), aTmp ); + + if( fBackStyle ) + aTmp <<= ImportColor(mnBackColor); + else + aTmp = uno::Any(); + rPropSet->setPropertyValue( WW8_ASCII2STR("BackgroundColor"), aTmp); + + sal_Bool bTemp; + if (fEnabled) + bTemp = sal_True; + else + bTemp = sal_False; + aTmp = bool2any(bTemp); + rPropSet->setPropertyValue( WW8_ASCII2STR("Enabled"), aTmp); + if ( sImageUrl.getLength() ) + { + aTmp <<= sImageUrl; + rPropSet->setPropertyValue( WW8_ASCII2STR("ImageURL"), aTmp); + } + return sal_True; +} + +sal_Bool OCX_Image::WriteContents(SvStorageStreamRef &rContents, + const uno::Reference< beans::XPropertySet > &rPropSet, + const awt::Size &rSize) +{ + sal_Bool bRet=sal_True; + sal_uInt32 nOldPos = rContents->Tell(); + rContents->SeekRel(8); + + pBlockFlags[0] = 0; + pBlockFlags[1] = 0x02; + pBlockFlags[2] = 0; + pBlockFlags[3] = 0; + + uno::Any aTmp = rPropSet->getPropertyValue( + WW8_ASCII2STR("BackgroundColor")); + if (aTmp.hasValue()) + aTmp >>= mnBackColor; + *rContents << ExportColor(mnBackColor); + pBlockFlags[0] |= 0x10; + + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("Border")); + sal_Int16 nBorder = sal_Int16(); + aTmp >>= nBorder; + nSpecialEffect = ExportBorder(nBorder,nBorderStyle); + *rContents << nBorderStyle; + pBlockFlags[0] |= 0x20; + + *rContents << nSpecialEffect; + pBlockFlags[1] |= 0x01; + + WriteAlign(rContents,4); + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("Enabled")); + fEnabled = any2bool(aTmp); + if (fEnabled) + { + sal_uInt8 nTemp = 0x19; + *rContents << nTemp; + pBlockFlags[1] |= 0x20; + *rContents << sal_uInt8(0x00); + *rContents << sal_uInt8(0x00); + *rContents << sal_uInt8(0x00); + } + + aTmp = rPropSet->getPropertyValue(WW8_ASCII2STR("ImageURL")); +// OUString *pStr = (OUString *)aTmp.getValue(); + /*Magically fetch that image and turn it into something that + *we can store in ms controls, wmf,png,jpg are almost certainly + *the options we have for export...*/ + + WriteAlign(rContents,4); + *rContents << rSize.Width; + *rContents << rSize.Height; + + WriteAlign(rContents,4); + nFixedAreaLen = static_cast<sal_uInt16>(rContents->Tell()-nOldPos-4); + + rContents->Seek(nOldPos); + *rContents << nStandardId; + *rContents << nFixedAreaLen; + + *rContents << pBlockFlags[0]; + *rContents << pBlockFlags[1]; + *rContents << pBlockFlags[2]; + *rContents << pBlockFlags[3]; + DBG_ASSERT((rContents.Is() && + (SVSTREAM_OK==rContents->GetError())),"damn"); + return bRet; +} + + +sal_Bool OCX_Image::Export(SvStorageRef &rObj, + const uno::Reference< beans::XPropertySet > &rPropSet, + const awt::Size &rSize) +{ + static sal_uInt8 __READONLY_DATA aCompObj[] = { + 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x92, 0x59, 0x4C, + 0x26, 0x69, 0x1B, 0x10, 0x99, 0x92, 0x00, 0x00, + 0x0B, 0x65, 0xC6, 0xF9, 0x1A, 0x00, 0x00, 0x00, + 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, + 0x74, 0x20, 0x46, 0x6F, 0x72, 0x6D, 0x73, 0x20, + 0x32, 0x2E, 0x30, 0x20, 0x49, 0x6D, 0x61, 0x67, + 0x65, 0x00, 0x10, 0x00, 0x00, 0x00, 0x45, 0x6D, + 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x20, 0x4F, + 0x62, 0x6A, 0x65, 0x63, 0x74, 0x00, 0x0E, 0x00, + 0x00, 0x00, 0x46, 0x6F, 0x72, 0x6D, 0x73, 0x2E, + 0x49, 0x6D, 0x61, 0x67, 0x65, 0x2E, 0x31, 0x00, + 0xF4, 0x39, 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor( rObj->OpenSotStream( C2S("\1CompObj"))); + xStor->Write(aCompObj,sizeof(aCompObj)); + DBG_ASSERT((xStor.Is() && (SVSTREAM_OK == xStor->GetError())),"damn"); + } + + { + SvStorageStreamRef xStor3( rObj->OpenSotStream( C2S("\3ObjInfo"))); + xStor3->Write(aObjInfo,sizeof(aObjInfo)); + DBG_ASSERT((xStor3.Is() && (SVSTREAM_OK == xStor3->GetError())),"damn"); + } + + static sal_uInt8 __READONLY_DATA aOCXNAME[] = { + 0x49, 0x00, 0x6D, 0x00, 0x61, 0x00, 0x67, 0x00, + 0x65, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor2( rObj->OpenSotStream( C2S("\3OCXNAME"))); + xStor2->Write(aOCXNAME,sizeof(aOCXNAME)); + DBG_ASSERT((xStor2.Is() && (SVSTREAM_OK == xStor2->GetError())),"damn"); + } + + SvStorageStreamRef xContents( rObj->OpenSotStream( C2S("contents"))); + return WriteContents(xContents, rPropSet, rSize); +} + +// ============================================================================ + +OCX_SpinButton::OCX_SpinButton() : + OCX_Control( OUString( RTL_CONSTASCII_USTRINGPARAM( "SpinButton" ) ) ), + mnBlockFlags( 0 ), + mnValue( 0 ), + mnMin( 0 ), + mnMax( 100 ), + mnSmallStep( 1 ), + mnPageStep( 1 ), + mnOrient( -1 ), + mnDelay( 50 ), + mbEnabled( true ), + mbLocked( false ), + mbPropThumb( true ) +{ + msFormType = C2U("com.sun.star.form.component.SpinButton"); + msDialogType = C2U("com.sun.star.awt.UnoControlSpinButtonModel"); + mnBackColor = 0x8000000F; + mnForeColor = 0x80000012; +} + +OCX_Control* OCX_SpinButton::Create() +{ + return new OCX_SpinButton; +} + +sal_Bool OCX_SpinButton::Read( SvStorageStream *pS ) +{ + if( !pS ) return sal_False; + + SvStream& rStrm = *pS; + sal_uInt16 nId, nSize; + sal_Int32 nIcon = 0; + + rStrm >> nId >> nSize >> mnBlockFlags; + + DBG_ASSERT( nStandardId == nId, "OCX_SpinButton::Read - unknown identifier" ); + + if( mnBlockFlags & 0x00000001 ) rStrm >> mnForeColor; + if( mnBlockFlags & 0x00000002 ) rStrm >> mnBackColor; + if( mnBlockFlags & 0x00000004 ) + { + sal_Int32 nFlags; + rStrm >> nFlags; + mbEnabled = (nFlags & 0x00000002) != 0; + mbLocked = (nFlags & 0x00000004) != 0; + } + if( mnBlockFlags & 0x00000010 ) rStrm.SeekRel( 4 ); // mouse pointer + if( mnBlockFlags & 0x00000020 ) rStrm >> mnMin; + if( mnBlockFlags & 0x00000040 ) rStrm >> mnMax; + if( mnBlockFlags & 0x00000080 ) rStrm >> mnValue; + if( mnBlockFlags & 0x00000100 ) rStrm.SeekRel( 4 ); // unknown + if( mnBlockFlags & 0x00000200 ) rStrm.SeekRel( 4 ); // unknown + if( mnBlockFlags & 0x00000400 ) rStrm.SeekRel( 4 ); // unknown + if( mnBlockFlags & 0x00000800 ) rStrm >> mnSmallStep; + if( mnBlockFlags & 0x00001000 ) rStrm >> mnPageStep; + if( mnBlockFlags & 0x00002000 ) rStrm >> mnOrient; + if( mnBlockFlags & 0x00004000 ) + { + sal_Int32 nThumb; + *pS >> nThumb; + mbPropThumb = nThumb != 0; + } + if( mnBlockFlags & 0x00008000 ) rStrm >> mnDelay; + if( mnBlockFlags & 0x00010000 ) rStrm >> nIcon; + if( mnBlockFlags & 0x00000008 ) rStrm >> nWidth >> nHeight; + + if( nIcon ) + { + sal_Int32 nIconSize; + pS->SeekRel( 20 ); + *pS >> nIconSize; + pS->SeekRel( nIconSize ); + } + + return sal_True; +} + +sal_Bool OCX_SpinButton::ReadFontData( SvStorageStream* /* pS */ ) +{ + // spin buttons and scroll bars do not support font data + return sal_True; +} + +sal_Bool OCX_SpinButton::Import(com::sun::star::uno::Reference< + com::sun::star::beans::XPropertySet> &rPropSet) +{ + if( (nWidth < 1) || (nHeight < 1) ) + return sal_False; + + uno::Any aTmp( &sName, getCppuType((OUString *)0) ); + rPropSet->setPropertyValue( WW8_ASCII2STR( "Name" ), aTmp ); + + aTmp <<= ImportColor( mnForeColor ); + rPropSet->setPropertyValue( WW8_ASCII2STR("SymbolColor"), aTmp); + + aTmp <<= ImportColor( mnBackColor ); + rPropSet->setPropertyValue( WW8_ASCII2STR("BackgroundColor"), aTmp); + + aTmp = bool2any( mbEnabled && !mbLocked ); + rPropSet->setPropertyValue( WW8_ASCII2STR("Enabled"), aTmp); + + aTmp <<= mnValue; + if ( bSetInDialog ) + { + rPropSet->setPropertyValue( WW8_ASCII2STR("SpinValue"), aTmp ); + } + else + { + rPropSet->setPropertyValue( WW8_ASCII2STR("DefaultSpinValue"), aTmp ); + } + + aTmp <<= mnMin; + rPropSet->setPropertyValue( WW8_ASCII2STR("SpinValueMin"), aTmp ); + + aTmp <<= mnMax; + rPropSet->setPropertyValue( WW8_ASCII2STR("SpinValueMax"), aTmp ); + + aTmp <<= mnSmallStep; + rPropSet->setPropertyValue( WW8_ASCII2STR("SpinIncrement"), aTmp ); + + namespace AwtScrollOrient = ::com::sun::star::awt::ScrollBarOrientation; + switch( mnOrient ) + { + case 0: aTmp <<= AwtScrollOrient::VERTICAL; break; + case 1: aTmp <<= AwtScrollOrient::HORIZONTAL; break; + default: aTmp <<= (nWidth < nHeight) ? AwtScrollOrient::VERTICAL : AwtScrollOrient::HORIZONTAL; + } + rPropSet->setPropertyValue( WW8_ASCII2STR("Orientation"), aTmp ); + + aTmp = bool2any( true ); + rPropSet->setPropertyValue( WW8_ASCII2STR("Repeat"), aTmp ); + + aTmp <<= mnDelay; + rPropSet->setPropertyValue( WW8_ASCII2STR("RepeatDelay"), aTmp ); + + aTmp <<= sal_Int16( 0 ); + rPropSet->setPropertyValue( WW8_ASCII2STR("Border"), aTmp); + + return sal_True; +} + +sal_Bool OCX_SpinButton::Export( + SvStorageRef &rObj, + const uno::Reference< beans::XPropertySet>& rPropSet, + const awt::Size& rSize ) +{ + static sal_uInt8 __READONLY_DATA aCompObj[] = + { + 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xB0, 0x6F, 0x17, 0x79, + 0xF2, 0xB7, 0xCE, 0x11, 0x97, 0xEF, 0x00, 0xAA, + 0x00, 0x6D, 0x27, 0x76, 0x1F, 0x00, 0x00, 0x00, + 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, + 0x74, 0x20, 0x46, 0x6F, 0x72, 0x6D, 0x73, 0x20, + 0x32, 0x2E, 0x30, 0x20, 0x53, 0x70, 0x69, 0x6E, + 0x42, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x45, 0x6D, 0x62, 0x65, 0x64, + 0x64, 0x65, 0x64, 0x20, 0x4F, 0x62, 0x6A, 0x65, + 0x63, 0x74, 0x00, 0x13, 0x00, 0x00, 0x00, 0x46, + 0x6E, 0x42, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x2E, + 0x31, 0x00, 0xF4, 0x39, 0xB2, 0x71, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor( rObj->OpenSotStream( C2S("\1CompObj"))); + xStor->Write(aCompObj,sizeof(aCompObj)); + DBG_ASSERT((xStor.Is() && (SVSTREAM_OK == xStor->GetError())),"damn"); + } + + { + SvStorageStreamRef xStor3( rObj->OpenSotStream( C2S("\3ObjInfo"))); + xStor3->Write(aObjInfo,sizeof(aObjInfo)); + DBG_ASSERT((xStor3.Is() && (SVSTREAM_OK == xStor3->GetError())),"damn"); + } + + static sal_uInt8 __READONLY_DATA aOCXNAME[] = + { + 0x53, 0x00, 0x70, 0x00, 0x69, 0x00, 0x6E, 0x00, + 0x42, 0x00, 0x75, 0x00, 0x74, 0x00, 0x74, 0x00, + 0x6F, 0x00, 0x6E, 0x00, 0x31, 0x00, 0x00, 0x00, + 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor2( rObj->OpenSotStream( C2S("\3OCXNAME"))); + xStor2->Write(aOCXNAME,sizeof(aOCXNAME)); + DBG_ASSERT((xStor2.Is() && (SVSTREAM_OK == xStor2->GetError())),"damn"); + } + + SvStorageStreamRef xContents( rObj->OpenSotStream( C2S("contents"))); + return WriteContents(xContents, rPropSet, rSize); +} + +sal_Bool OCX_SpinButton::WriteContents( + SvStorageStreamRef &rObj, + const uno::Reference< beans::XPropertySet> &rPropSet, + const awt::Size& rSize ) +{ + if( !rObj.Is() ) + return sal_False; + + mnBlockFlags = 0x00000008; + nWidth = rSize.Width; + nHeight = rSize.Height; + + GetInt32Property( mnForeColor, rPropSet, WW8_ASCII2STR( "SymbolColor" ), 0x00000001 ); + GetInt32Property( mnBackColor, rPropSet, WW8_ASCII2STR( "BackgroundColor" ), 0x00000002 ); + GetBoolProperty( mbEnabled, rPropSet, WW8_ASCII2STR( "Enabled" ), 0x00000304 ); + GetInt32Property( mnMin, rPropSet, WW8_ASCII2STR( "SpinValueMin" ), 0x00000020 ); + GetInt32Property( mnMax, rPropSet, WW8_ASCII2STR( "SpinValueMax" ), 0x00000040 ); + GetInt32Property( mnValue, rPropSet, WW8_ASCII2STR( "SpinValue" ), 0x00000080 ); + GetInt32Property( mnSmallStep, rPropSet, WW8_ASCII2STR( "SpinIncrement" ), 0x00000800 ); + GetInt32Property( mnDelay, rPropSet, WW8_ASCII2STR( "RepeatDelay" ), 0x00008000 ); + + namespace AwtScrollOrient = ::com::sun::star::awt::ScrollBarOrientation; + sal_Int16 nApiOrient = sal_Int16(); + if( rPropSet->getPropertyValue( WW8_ASCII2STR( "Orientation" ) ) >>= nApiOrient ) + UpdateInt32Property( mnOrient, (nApiOrient == AwtScrollOrient::VERTICAL) ? 0 : 1, 0x00002000 ); + + return WriteData( *rObj ); +} + +void OCX_SpinButton::UpdateInt32Property( + sal_Int32& rnCoreValue, sal_Int32 nNewValue, sal_Int32 nBlockFlag ) +{ + if( nNewValue != rnCoreValue ) + { + rnCoreValue = nNewValue; + mnBlockFlags |= nBlockFlag; + } +} + +void OCX_SpinButton::GetInt32Property( + sal_Int32& rnCoreValue, const uno::Reference< beans::XPropertySet>& rxPropSet, + const OUString& rPropName, sal_Int32 nBlockFlag ) +{ + sal_Int32 nNewValue = 0; + if( rxPropSet->getPropertyValue( rPropName ) >>= nNewValue ) + UpdateInt32Property( rnCoreValue, nNewValue, nBlockFlag ); +} + +void OCX_SpinButton::UpdateBoolProperty( + bool& rbCoreValue, bool bNewValue, sal_Int32 nBlockFlag ) +{ + if( bNewValue != rbCoreValue ) + { + rbCoreValue = bNewValue; + mnBlockFlags |= nBlockFlag; + } +} + +void OCX_SpinButton::GetBoolProperty( + bool& rbCoreValue, const uno::Reference< beans::XPropertySet>& rxPropSet, + const OUString& rPropName, sal_Int32 nBlockFlag ) +{ + UpdateBoolProperty( rbCoreValue, + any2bool( rxPropSet->getPropertyValue( rPropName ) ), nBlockFlag ); +} + +sal_Bool OCX_SpinButton::WriteData( SvStream& rStrm ) const +{ + sal_Bool bRet = sal_True; + sal_uLong nStartPos = rStrm.Tell(); + + rStrm << sal_Int32( 0 ) << mnBlockFlags; + + if( mnBlockFlags & 0x00000001 ) rStrm << ExportColor( mnForeColor ); + if( mnBlockFlags & 0x00000002 ) rStrm << ExportColor( mnBackColor ); + if( mnBlockFlags & 0x00000004 ) + { + sal_Int32 nFlags = 0x00000019; // always set + if( mbEnabled ) nFlags |= 0x00000002; + if( mbLocked ) nFlags |= 0x00000004; + rStrm << nFlags; + } + if( mnBlockFlags & 0x00000020 ) rStrm << mnMin; + if( mnBlockFlags & 0x00000040 ) rStrm << mnMax; + if( mnBlockFlags & 0x00000080 ) rStrm << mnValue; + if( mnBlockFlags & 0x00000100 ) rStrm << sal_Int32( 0 ); // unknown + if( mnBlockFlags & 0x00000200 ) rStrm << sal_Int32( 0 ); // unknown + if( mnBlockFlags & 0x00000400 ) rStrm << sal_Int32( 0 ); // unknown + if( mnBlockFlags & 0x00000800 ) rStrm << mnSmallStep; + if( mnBlockFlags & 0x00001000 ) rStrm << mnPageStep; + if( mnBlockFlags & 0x00002000 ) rStrm << mnOrient; + if( mnBlockFlags & 0x00004000 ) rStrm << sal_Int32( mbPropThumb ? 1 : 0 ); + if( mnBlockFlags & 0x00008000 ) rStrm << mnDelay; + if( mnBlockFlags & 0x00000008 ) rStrm << nWidth << nHeight; + + sal_uInt16 nSize = static_cast< sal_uInt16 >( rStrm.Tell() - nStartPos - 4 ); + rStrm.Seek( nStartPos ); + rStrm << nStandardId << nSize; + + DBG_ASSERT( rStrm.GetError() == SVSTREAM_OK, "OCX_SpinButton::WriteData - error in stream" ); + return bRet; +} + +// ============================================================================ + +OCX_ScrollBar::OCX_ScrollBar() +{ + sName = OUString( RTL_CONSTASCII_USTRINGPARAM( "ScrollBar" ) ); + mnMax = 32767; + msFormType = C2U("com.sun.star.form.component.ScrollBar"); + msDialogType = C2U("com.sun.star.awt.UnoControlScrollBarModel"); + +} + +OCX_Control* OCX_ScrollBar::Create() +{ + return new OCX_ScrollBar; +} + +sal_Bool OCX_ScrollBar::Import(com::sun::star::uno::Reference< + com::sun::star::beans::XPropertySet> &rPropSet) +{ + if( (nWidth < 1) || (nHeight < 1) ) + return sal_False; + + uno::Any aTmp( &sName, getCppuType((OUString *)0) ); + rPropSet->setPropertyValue( WW8_ASCII2STR( "Name" ), aTmp ); + + aTmp <<= ImportColor( mnForeColor ); + rPropSet->setPropertyValue( WW8_ASCII2STR("SymbolColor"), aTmp); + + aTmp <<= ImportColor( mnBackColor ); + rPropSet->setPropertyValue( WW8_ASCII2STR("BackgroundColor"), aTmp); + + aTmp = bool2any( mbEnabled && !mbLocked ); + rPropSet->setPropertyValue( WW8_ASCII2STR("Enabled"), aTmp); + + aTmp <<= mnValue; + if ( bSetInDialog ) + { + rPropSet->setPropertyValue( WW8_ASCII2STR("ScrollValue"), aTmp ); + } + else + { + rPropSet->setPropertyValue( WW8_ASCII2STR("DefaultScrollValue"), aTmp ); + } + + aTmp <<= mnMin; + rPropSet->setPropertyValue( WW8_ASCII2STR("ScrollValueMin"), aTmp ); + + aTmp <<= mnMax; + rPropSet->setPropertyValue( WW8_ASCII2STR("ScrollValueMax"), aTmp ); + + aTmp <<= mnSmallStep; + rPropSet->setPropertyValue( WW8_ASCII2STR("LineIncrement"), aTmp ); + + aTmp <<= mnPageStep; + rPropSet->setPropertyValue( WW8_ASCII2STR("BlockIncrement"), aTmp ); + if( mbPropThumb && (mnPageStep > 0) ) + rPropSet->setPropertyValue( WW8_ASCII2STR("VisibleSize"), aTmp ); + + namespace AwtScrollOrient = ::com::sun::star::awt::ScrollBarOrientation; + switch( mnOrient ) + { + case 0: aTmp <<= AwtScrollOrient::VERTICAL; break; + case 1: aTmp <<= AwtScrollOrient::HORIZONTAL; break; + default: aTmp <<= (nWidth < nHeight) ? AwtScrollOrient::VERTICAL : AwtScrollOrient::HORIZONTAL; + } + rPropSet->setPropertyValue( WW8_ASCII2STR("Orientation"), aTmp ); + + aTmp <<= mnDelay; + rPropSet->setPropertyValue( WW8_ASCII2STR("RepeatDelay"), aTmp ); + + aTmp <<= sal_Int16( 0 ); + rPropSet->setPropertyValue( WW8_ASCII2STR("Border"), aTmp); + + return sal_True; +} + +sal_Bool OCX_ScrollBar::Export( + SvStorageRef &rObj, + const uno::Reference< beans::XPropertySet>& rPropSet, + const awt::Size& rSize ) +{ + static sal_uInt8 __READONLY_DATA aCompObj[] = + { + 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x81, 0xD1, 0xDF, + 0x2F, 0x5E, 0xCE, 0x11, 0xA4, 0x49, 0x00, 0xAA, + 0x00, 0x4A, 0x80, 0x3D, 0x1E, 0x00, 0x00, 0x00, + 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, + 0x74, 0x20, 0x46, 0x6F, 0x72, 0x6D, 0x73, 0x20, + 0x32, 0x2E, 0x30, 0x20, 0x53, 0x63, 0x72, 0x6F, + 0x6C, 0x6C, 0x42, 0x61, 0x72, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x45, 0x6D, 0x62, 0x65, 0x64, 0x64, + 0x65, 0x64, 0x20, 0x4F, 0x62, 0x6A, 0x65, 0x63, + 0x74, 0x00, 0x12, 0x00, 0x00, 0x00, 0x46, 0x6F, + 0x72, 0x6D, 0x73, 0x2E, 0x53, 0x63, 0x72, 0x6F, + 0x6C, 0x6C, 0x42, 0x61, 0x72, 0x2E, 0x31, 0x00, + 0xF4, 0x39, 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor( rObj->OpenSotStream( C2S("\1CompObj"))); + xStor->Write(aCompObj,sizeof(aCompObj)); + DBG_ASSERT((xStor.Is() && (SVSTREAM_OK == xStor->GetError())),"damn"); + } + + { + SvStorageStreamRef xStor3( rObj->OpenSotStream( C2S("\3ObjInfo"))); + xStor3->Write(aObjInfo,sizeof(aObjInfo)); + DBG_ASSERT((xStor3.Is() && (SVSTREAM_OK == xStor3->GetError())),"damn"); + } + + static sal_uInt8 __READONLY_DATA aOCXNAME[] = + { + 0x53, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6F, 0x00, + 0x6C, 0x00, 0x6C, 0x00, 0x42, 0x00, 0x61, 0x00, + 0x72, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + { + SvStorageStreamRef xStor2( rObj->OpenSotStream( C2S("\3OCXNAME"))); + xStor2->Write(aOCXNAME,sizeof(aOCXNAME)); + DBG_ASSERT((xStor2.Is() && (SVSTREAM_OK == xStor2->GetError())),"damn"); + } + + SvStorageStreamRef xContents( rObj->OpenSotStream( C2S("contents"))); + return WriteContents(xContents, rPropSet, rSize); +} + +sal_Bool OCX_ScrollBar::WriteContents( + SvStorageStreamRef &rObj, + const uno::Reference< beans::XPropertySet> &rPropSet, + const awt::Size& rSize ) +{ + if( !rObj.Is() ) + return sal_False; + + mnBlockFlags = 0x00000008; + nWidth = rSize.Width; + nHeight = rSize.Height; + + GetInt32Property( mnForeColor, rPropSet, WW8_ASCII2STR( "SymbolColor" ), 0x00000001 ); + GetInt32Property( mnBackColor, rPropSet, WW8_ASCII2STR( "BackgroundColor" ), 0x00000002 ); + GetBoolProperty( mbEnabled, rPropSet, WW8_ASCII2STR( "Enabled" ), 0x00000304 ); + GetInt32Property( mnMin, rPropSet, WW8_ASCII2STR( "ScrollValueMin" ), 0x00000020 ); + GetInt32Property( mnMax, rPropSet, WW8_ASCII2STR( "ScrollValueMax" ), 0x00000040 ); + GetInt32Property( mnValue, rPropSet, WW8_ASCII2STR( "ScrollValue" ), 0x00000080 ); + GetInt32Property( mnSmallStep, rPropSet, WW8_ASCII2STR( "LineIncrement" ), 0x00000800 ); + GetInt32Property( mnPageStep, rPropSet, WW8_ASCII2STR( "BlockIncrement" ), 0x00001000 ); + GetInt32Property( mnDelay, rPropSet, WW8_ASCII2STR( "RepeatDelay" ), 0x00008000 ); + + namespace AwtScrollOrient = ::com::sun::star::awt::ScrollBarOrientation; + sal_Int16 nApiOrient = sal_Int16(); + if( rPropSet->getPropertyValue( WW8_ASCII2STR( "Orientation" ) ) >>= nApiOrient ) + UpdateInt32Property( mnOrient, (nApiOrient == AwtScrollOrient::VERTICAL) ? 0 : 1, 0x00002000 ); + + UpdateBoolProperty( mbPropThumb, true, 0x00004000 ); + + return WriteData( *rObj ); +} + +OCX_ProgressBar::OCX_ProgressBar() : + OCX_Control( OUString( RTL_CONSTASCII_USTRINGPARAM( "ProgressBar" ) ) ), + nMin( 0 ), + nMax( 0 ), + bFixedSingle(true), + bEnabled( true ), + b3d( true ) +{ + msDialogType = C2U("com.sun.star.awt.UnoControlProgressBarModel"); + bSetInDialog = true; +} + +sal_Bool OCX_ProgressBar::Read( SvStorageStream *pS ) +{ + pS->SeekRel( 8 ); + *pS >> nWidth >> nHeight; + pS->SeekRel( 12 ); + + float fMin, fMax; + *pS >> fMin >> fMax; + nMin = static_cast< sal_Int32 >( fMin ); + nMax = static_cast< sal_Int32 >( fMax ); + bool bVisible = true; + sal_uInt8 pUnknownFlags[4]; + pS->Read(pUnknownFlags,4); + + // complete guess, but we don't handle visible anyway + if ( ( pUnknownFlags[2] & 0x8 ) && ( pUnknownFlags[2] & 0x2 ) ) + bVisible = false; + + sal_uInt32 nFlags; + *pS >> nFlags; + + // seems these work out + bFixedSingle = (nFlags & 0x01) != 0; + bEnabled = (nFlags & 0x02) != 0; + b3d = (nFlags & 0x04) != 0; + + return true; +} + +OCX_Control* OCX_ProgressBar::Create() +{ + return new OCX_ProgressBar; +} + +sal_Bool OCX_ProgressBar::Import(uno::Reference< beans::XPropertySet > &rPropSet) +{ + uno::Any aTmp(&sName,getCppuType((OUString *)0)); + rPropSet->setPropertyValue( WW8_ASCII2STR("Name"), aTmp ); + aTmp <<= nMax; + rPropSet->setPropertyValue( WW8_ASCII2STR("ProgressValueMax"), aTmp ); + aTmp <<= nMin; + rPropSet->setPropertyValue( WW8_ASCII2STR("ProgressValueMin"), aTmp ); + + if ( !bEnabled ) + rPropSet->setPropertyValue( WW8_ASCII2STR("Enabled"), uno::makeAny( sal_False ) ); + return sal_True; +} +// ============================================================================ + +/* vi:set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/filter/source/msfilter/msoleexp.cxx b/filter/source/msfilter/msoleexp.cxx new file mode 100644 index 000000000000..bf00ddc966f1 --- /dev/null +++ b/filter/source/msfilter/msoleexp.cxx @@ -0,0 +1,364 @@ +/************************************************************************* + * + * 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_filter.hxx" +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/embed/XEmbedPersist.hpp> +#include <com/sun/star/embed/NoVisualAreaSizeException.hpp> +#include <com/sun/star/embed/EmbedStates.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/embed/Aspects.hpp> +#include <sot/clsids.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/docfac.hxx> +#include <sfx2/docfilt.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/fcontnr.hxx> +#include <sot/formats.hxx> +#include <comphelper/processfactory.hxx> +#include <unotools/streamwrap.hxx> +#include <comphelper/storagehelper.hxx> +#include <svtools/embedhlp.hxx> +#include <filter/msfilter/msdffimp.hxx> // extern sichtbare Header-Datei + +#include "filter/msfilter/msoleexp.hxx" + +#define CREATE_CONST_ASC(s) String::CreateFromAscii( \ + RTL_CONSTASCII_STRINGPARAM(s)) + +using namespace ::com::sun::star; + +SvGlobalName GetEmbeddedVersion( const SvGlobalName& aAppName ) +{ + if ( aAppName == SvGlobalName( SO3_SM_CLASSID_60 ) ) + return SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 ); + else if ( aAppName == SvGlobalName( SO3_SW_CLASSID_60 ) ) + return SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 ); + else if ( aAppName == SvGlobalName( SO3_SC_CLASSID_60 ) ) + return SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 ); + else if ( aAppName == SvGlobalName( SO3_SDRAW_CLASSID_60 ) ) + return SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 ); + else if ( aAppName == SvGlobalName( SO3_SIMPRESS_CLASSID_60 ) ) + return SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 ); + else if ( aAppName == SvGlobalName( SO3_SCH_CLASSID_60 ) ) + return SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 ); + + return SvGlobalName(); +} + +String GetStorageType( const SvGlobalName& aEmbName ) +{ + if ( aEmbName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 ) ) + return String::CreateFromAscii( "opendocument.MathDocument.1" ); + else if ( aEmbName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 ) ) + return String::CreateFromAscii( "opendocument.WriterDocument.1" ); + else if ( aEmbName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 ) ) + return String::CreateFromAscii( "opendocument.CalcDocument.1" ); + else if ( aEmbName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 ) ) + return String::CreateFromAscii( "opendocument.DrawDocument.1" ); + else if ( aEmbName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 ) ) + return String::CreateFromAscii( "opendocument.ImpressDocument.1" ); + else if ( aEmbName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 ) ) + return String::CreateFromAscii( "opendocument.ChartDocument.1" ); + + return String(); +} + +sal_Bool UseOldMSExport() +{ + uno::Reference< lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + + if ( xFactory.is() ) + { + uno::Reference< lang::XMultiServiceFactory > xProvider( xFactory->createInstance( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider"))), + uno::UNO_QUERY); + if ( xProvider.is() ) + { + try { + uno::Sequence< uno::Any > aArg( 1 ); + aArg[0] <<= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common/InternalMSExport") ); + uno::Reference< container::XNameAccess > xNameAccess( + xProvider->createInstanceWithArguments( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) ), + aArg ), + uno::UNO_QUERY ); + if ( xNameAccess.is() ) + { + uno::Any aResult = xNameAccess->getByName( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseOldExport" ) ) ); + + sal_Bool bResult = sal_Bool(); + if ( aResult >>= bResult ) + return bResult; + } + } + catch( uno::Exception& ) + { + } + } + } + + OSL_ENSURE( sal_False, "Could not get access to configuration entry!\n" ); + return sal_False; +} + +void SvxMSExportOLEObjects::ExportOLEObject( const com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject>& rObj, SotStorage& rDestStg ) +{ + svt::EmbeddedObjectRef aObj( rObj, embed::Aspects::MSOLE_CONTENT ); + ExportOLEObject( aObj, rDestStg ); +} + +void SvxMSExportOLEObjects::ExportOLEObject( svt::EmbeddedObjectRef& rObj, SvStorage& rDestStg ) +{ + SvGlobalName aOwnGlobalName; + SvGlobalName aObjName( rObj->getClassID() ); + const SfxFilter* pExpFilter = NULL; + { + static struct _ObjExpType { + sal_uInt32 nFlag; + const char* pFilterNm; + // GlobalNameId + struct _GlobalNameIds { + sal_uInt32 n1; + sal_uInt16 n2, n3; + sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15; + } + aGlNmIds[4]; + } aArr[] = { + { OLE_STARMATH_2_MATHTYPE, "MathType 3.x", + {{SO3_SM_CLASSID_60}, {SO3_SM_CLASSID_50}, + {SO3_SM_CLASSID_40}, {SO3_SM_CLASSID_30 }}}, + { OLE_STARWRITER_2_WINWORD, "MS Word 97", + {{SO3_SW_CLASSID_60}, {SO3_SW_CLASSID_50}, + {SO3_SW_CLASSID_40}, {SO3_SW_CLASSID_30 }}}, + { OLE_STARCALC_2_EXCEL, "MS Excel 97", + {{SO3_SC_CLASSID_60}, {SO3_SC_CLASSID_50}, + {SO3_SC_CLASSID_40}, {SO3_SC_CLASSID_30 }}}, + { OLE_STARIMPRESS_2_POWERPOINT, "MS PowerPoint 97", + {{SO3_SIMPRESS_CLASSID_60}, {SO3_SIMPRESS_CLASSID_50}, + {SO3_SIMPRESS_CLASSID_40}, {SO3_SIMPRESS_CLASSID_30 }}}, + { 0, "", + {{SO3_SCH_CLASSID_60}, {SO3_SCH_CLASSID_50}, + {SO3_SCH_CLASSID_40}, {SO3_SCH_CLASSID_30 }}}, + { 0, "", + {{SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50}, // SJ: !!!! SO3_SDRAW_CLASSID is only available up from + {SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50 }}}, // ver 5.0, it is purpose to have double entrys here. + + { 0xffff,0, + {{SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50}, + {SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50}}} + }; + + for( const _ObjExpType* pArr = aArr; !pExpFilter && ( pArr->nFlag != 0xffff ); ++pArr ) + { + for ( int n = 0; n < 4; ++n ) + { + const _ObjExpType::_GlobalNameIds& rId = pArr->aGlNmIds[ n ]; + SvGlobalName aGlbNm( rId.n1, rId.n2, rId.n3, + rId.b8, rId.b9, rId.b10, rId.b11, + rId.b12, rId.b13, rId.b14, rId.b15 ); + if( aObjName == aGlbNm ) + { + aOwnGlobalName = aGlbNm; + + // flags for checking if conversion is wanted at all (SaveOptions?!) + if( GetFlags() & pArr->nFlag ) + { + pExpFilter = SfxFilterMatcher().GetFilter4FilterName(String::CreateFromAscii(pArr->pFilterNm)); + break; + } + } + } + } + } + + if( pExpFilter ) // use this filter for the export + { + try + { + if ( rObj->getCurrentState() == embed::EmbedStates::LOADED ) + rObj->changeState( embed::EmbedStates::RUNNING ); + //TODO/LATER: is stream instead of outputstream a better choice?! + //TODO/LATER: a "StoreTo" method at embedded object would be nice + uno::Sequence < beans::PropertyValue > aSeq(2); + SvStream* pStream = new SvMemoryStream; + aSeq[0].Name = ::rtl::OUString::createFromAscii( "OutputStream" ); + ::uno::Reference < io::XOutputStream > xOut = new ::utl::OOutputStreamWrapper( *pStream ); + aSeq[0].Value <<= xOut; + aSeq[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" ) ); + aSeq[1].Value <<= ::rtl::OUString( pExpFilter->GetName() ); + uno::Reference < frame::XStorable > xStor( rObj->getComponent(), uno::UNO_QUERY ); + xStor->storeToURL( ::rtl::OUString::createFromAscii( "private:stream" ), aSeq ); + SotStorageRef xOLEStor = new SotStorage( pStream, sal_True ); + xOLEStor->CopyTo( &rDestStg ); + rDestStg.Commit(); + } + catch( uno::Exception& ) + { + // TODO/LATER: Error handling + DBG_ERROR( "The object could not be exported!" ); + } + } + else if( aOwnGlobalName != SvGlobalName() ) + { + // own format, maybe SO6 format or lower + SvGlobalName aEmbName = GetEmbeddedVersion( aOwnGlobalName ); + if ( aEmbName != SvGlobalName() && !UseOldMSExport() ) + { + // this is a SO6 embedded object, save in old binary format + rDestStg.SetVersion( SOFFICE_FILEFORMAT_31 ); + rDestStg.SetClass( aEmbName, + SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE, + GetStorageType( aEmbName ) ); + SotStorageStreamRef xExtStm = rDestStg.OpenSotStream( + String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "properties_stream" ) ), + STREAM_STD_READWRITE ); + + sal_Bool bExtentSuccess = sal_False; + if( !xExtStm->GetError() ) + { + // write extent + //TODO/MBA: check if writing a size is enough + if( rObj.GetObject().is() ) + { + // MSOLE objects don't need to be in running state for VisualArea access + awt::Size aSize; + try + { + // this is an own object, the content size must be stored in the + // extension stream + aSize = rObj->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); + } + catch( embed::NoVisualAreaSizeException& ) + { + OSL_ENSURE( sal_False, "Could not get visual area size!\n" ); + aSize.Width = 5000; + aSize.Height = 5000; + } + catch( uno::Exception& ) + { + OSL_ENSURE( sal_False, "Unexpected exception while getting visual area size!\n" ); + aSize.Width = 5000; + aSize.Height = 5000; + } + + //Rectangle aVisArea = xSfxIPObj->GetVisArea( ASPECT_CONTENT ); + sal_Int32 pRect[4]; + //pRect[0] = aVisArea.Left(); + //pRect[1] = aVisArea.Right(); + //pRect[2] = aVisArea.Top(); + //pRect[3] = aVisArea.Bottom(); + pRect[0] = 0; + pRect[1] = aSize.Width; + pRect[2] = 0; + pRect[3] = aSize.Height; + + sal_Int8 aWriteSet[16]; + for ( int ind = 0; ind < 4; ind++ ) + { + sal_Int32 nVal = pRect[ind]; + for ( int nByte = 0; nByte < 4; nByte++ ) + { + aWriteSet[ind*4+nByte] = (sal_Int8) nVal % 0x100; + nVal /= 0x100; + } + } + + bExtentSuccess = ( xExtStm->Write( aWriteSet, 16 ) == 16 ); + } + } + + if ( bExtentSuccess ) + { + SotStorageStreamRef xEmbStm = rDestStg.OpenSotStream( + String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "package_stream" ) ), + STREAM_STD_READWRITE ); + if( !xEmbStm->GetError() ) + { + try + { + if ( rObj->getCurrentState() == embed::EmbedStates::LOADED ) + rObj->changeState( embed::EmbedStates::RUNNING ); + //TODO/LATER: is stream instead of outputstream a better choice?! + //TODO/LATER: a "StoreTo" method at embedded object would be nice + uno::Sequence < beans::PropertyValue > aSeq(1); + aSeq[0].Name = ::rtl::OUString::createFromAscii( "OutputStream" ); + ::uno::Reference < io::XOutputStream > xOut = new ::utl::OOutputStreamWrapper( *xEmbStm ); + aSeq[0].Value <<= xOut; + uno::Reference < frame::XStorable > xStor( rObj->getComponent(), uno::UNO_QUERY ); + xStor->storeToURL( ::rtl::OUString::createFromAscii( "private:stream" ), aSeq ); + } + catch( uno::Exception& ) + { + // TODO/LATER: Error handling + DBG_ERROR( "The object could not be exported!" ); + } + } + } + } + else + { + DBG_ERROR("Own binary format inside own container document!"); + } + } + else + { + // alien objects + //TODO/LATER: a "StoreTo" method at embedded object would be nice + rDestStg.SetVersion( SOFFICE_FILEFORMAT_31 ); + uno::Reference < embed::XStorage > xStor = ::comphelper::OStorageHelper::GetTemporaryStorage(); + uno::Reference < embed::XEmbedPersist > xPers( rObj.GetObject(), uno::UNO_QUERY ); + if ( xPers.is() ) + { + uno::Sequence < beans::PropertyValue > aEmptySeq; + ::rtl::OUString aTempName(::rtl::OUString::createFromAscii("bla")); + try + { + xPers->storeToEntry( xStor, aTempName, aEmptySeq, aEmptySeq ); + } + catch ( uno::Exception& ) + {} + + SotStorageRef xOLEStor = SotStorage::OpenOLEStorage( xStor, aTempName, STREAM_STD_READ ); + xOLEStor->CopyTo( &rDestStg ); + rDestStg.Commit(); + } + } + + //We never need this stream: See #99809# and #i2179# + rDestStg.Remove(CREATE_CONST_ASC(SVEXT_PERSIST_STREAM)); +} + + + diff --git a/filter/source/msfilter/msvbahelper.cxx b/filter/source/msfilter/msvbahelper.cxx new file mode 100644 index 000000000000..02fa3d60e248 --- /dev/null +++ b/filter/source/msfilter/msvbahelper.cxx @@ -0,0 +1,541 @@ +/************************************************************************* + * + * 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_filter.hxx" + +#include <filter/msfilter/msvbahelper.hxx> +#include <basic/sbx.hxx> +#include <basic/sbstar.hxx> +#include <basic/basmgr.hxx> +#include <basic/sbmod.hxx> +#include <basic/sbmeth.hxx> +#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> +#include <com/sun/star/document/XDocumentProperties.hpp> +#include <com/sun/star/document/XDocumentInfoSupplier.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <tools/urlobj.hxx> +#include <osl/file.hxx> +#include <unotools/pathoptions.hxx> + +using namespace ::com::sun::star; + +namespace ooo { +namespace vba { + +const static rtl::OUString sUrlPart0 = rtl::OUString::createFromAscii( "vnd.sun.star.script:"); +const static rtl::OUString sUrlPart1 = rtl::OUString::createFromAscii( "?language=Basic&location=document"); + +String makeMacroURL( const String& sMacroName ) +{ + return sUrlPart0.concat( sMacroName ).concat( sUrlPart1 ) ; +} + +::rtl::OUString extractMacroName( const ::rtl::OUString& rMacroUrl ) +{ + if( (rMacroUrl.getLength() > sUrlPart0.getLength() + sUrlPart1.getLength()) && + rMacroUrl.match( sUrlPart0 ) && + rMacroUrl.match( sUrlPart1, rMacroUrl.getLength() - sUrlPart1.getLength() ) ) + { + return rMacroUrl.copy( sUrlPart0.getLength(), rMacroUrl.getLength() - sUrlPart0.getLength() - sUrlPart1.getLength() ); + } + return ::rtl::OUString(); +} + +::rtl::OUString trimMacroName( const ::rtl::OUString& rMacroName ) +{ + // the name may contain whitespaces and may be enclosed in apostrophs + ::rtl::OUString aMacroName = rMacroName.trim(); + sal_Int32 nMacroLen = aMacroName.getLength(); + if( (nMacroLen >= 2) && (aMacroName[ 0 ] == '\'') && (aMacroName[ nMacroLen - 1 ] == '\'') ) + aMacroName = aMacroName.copy( 1, nMacroLen - 2 ).trim(); + return aMacroName; +} + +SfxObjectShell* findShellForUrl( const rtl::OUString& sMacroURLOrPath ) +{ + SfxObjectShell* pFoundShell=NULL; + SfxObjectShell* pShell = SfxObjectShell::GetFirst(); + INetURLObject aObj; + aObj.SetURL( sMacroURLOrPath ); + bool bIsURL = aObj.GetProtocol() != INET_PROT_NOT_VALID; + rtl::OUString aURL; + if ( bIsURL ) + aURL = sMacroURLOrPath; + else + { + osl::FileBase::getFileURLFromSystemPath( sMacroURLOrPath, aURL ); + aObj.SetURL( aURL ); + } + OSL_TRACE("Trying to find shell for url %s", rtl::OUStringToOString( aURL, RTL_TEXTENCODING_UTF8 ).getStr() ); + while ( pShell ) + { + + uno::Reference< frame::XModel > xModel = pShell->GetModel(); + // are we searching for a template? if so we have to cater for the + // fact that in openoffice a document opened from a template is always + // a new document :/ + if ( xModel.is() ) + { + OSL_TRACE("shell 0x%x has model with url %s and we look for %s", pShell + , rtl::OUStringToOString( xModel->getURL(), RTL_TEXTENCODING_UTF8 ).getStr() + , rtl::OUStringToOString( aURL, RTL_TEXTENCODING_UTF8 ).getStr() + ); + ::rtl::OUString aName = xModel->getURL() ; + if (0 == aName.getLength()) + { + + const static rtl::OUString sTitle( RTL_CONSTASCII_USTRINGPARAM("Title" ) ); + uno::Reference< frame::XFrame > xFrame( xModel->getCurrentController()->getFrame(), uno::UNO_QUERY_THROW ); + uno::Reference< beans::XPropertySet > xProps( xFrame, uno::UNO_QUERY_THROW ); + xProps->getPropertyValue(sTitle) >>= aName; + sal_Int32 pos = 0; + aName = aName.getToken(0,'-',pos); + aName = aName.trim(); + if( sMacroURLOrPath.lastIndexOf( aName ) >= 0 ) + { + pFoundShell = pShell; + break; + } + } + + if ( sMacroURLOrPath.endsWithIgnoreAsciiCaseAsciiL( ".dot", 4 ) ) + { + uno::Reference< document::XDocumentInfoSupplier > xDocInfoSupp( xModel, uno::UNO_QUERY ); + if( xDocInfoSupp.is() ) + { + uno::Reference< document::XDocumentPropertiesSupplier > xDocPropSupp( xDocInfoSupp->getDocumentInfo(), uno::UNO_QUERY_THROW ); + uno::Reference< document::XDocumentProperties > xDocProps( xDocPropSupp->getDocumentProperties(), uno::UNO_QUERY_THROW ); + rtl::OUString sCurrName = xDocProps->getTemplateName(); + if( sMacroURLOrPath.lastIndexOf( sCurrName ) >= 0 ) + { + pFoundShell = pShell; + break; + } + } + } + else + { + // sometimes just the name of the document ( without the path + // is used + bool bDocNameNoPathMatch = false; + if ( aURL.getLength() && aURL.indexOf( '/' ) == -1 ) + { + sal_Int32 lastSlashIndex = xModel->getURL().lastIndexOf( '/' ); + if ( lastSlashIndex > -1 ) + { + bDocNameNoPathMatch = xModel->getURL().copy( lastSlashIndex + 1 ).equals( aURL ); + if ( !bDocNameNoPathMatch ) + { + rtl::OUString aTmpName = rtl::OUString::createFromAscii("'") + xModel->getURL().copy( lastSlashIndex + 1 ) + rtl::OUString::createFromAscii("'"); + bDocNameNoPathMatch = aTmpName.equals( aURL ); + } + } + } + + if ( aURL.equals( xModel->getURL() ) || bDocNameNoPathMatch ) + { + pFoundShell = pShell; + break; + } + } + } + pShell = SfxObjectShell::GetNext( *pShell ); + } + return pFoundShell; +} + +// sMod can be empty ( but we really need the library to search in ) +// if sMod is empty and a macro is found then sMod is updated +bool hasMacro( SfxObjectShell* pShell, const String& sLibrary, String& sMod, const String& sMacro ) +{ + bool bFound = false; + if ( sLibrary.Len() && sMacro.Len() ) + { + OSL_TRACE("** Searching for %s.%s in library %s" + ,rtl::OUStringToOString( sMod, RTL_TEXTENCODING_UTF8 ).getStr() + ,rtl::OUStringToOString( sMacro, RTL_TEXTENCODING_UTF8 ).getStr() + ,rtl::OUStringToOString( sLibrary, RTL_TEXTENCODING_UTF8 ).getStr() ); + BasicManager* pBasicMgr = pShell-> GetBasicManager(); + if ( pBasicMgr ) + { + StarBASIC* pBasic = pBasicMgr->GetLib( sLibrary ); + if ( !pBasic ) + { + sal_uInt16 nId = pBasicMgr->GetLibId( sLibrary ); + pBasicMgr->LoadLib( nId ); + pBasic = pBasicMgr->GetLib( sLibrary ); + } + if ( pBasic ) + { + if ( sMod.Len() ) // we wish to find the macro is a specific module + { + SbModule* pModule = pBasic->FindModule( sMod ); + if ( pModule ) + { + SbxArray* pMethods = pModule->GetMethods(); + if ( pMethods ) + { + SbMethod* pMethod = static_cast< SbMethod* >( pMethods->Find( sMacro, SbxCLASS_METHOD ) ); + if ( pMethod ) + bFound = true; + } + } + } + else if( SbMethod* pMethod = dynamic_cast< SbMethod* >( pBasic->Find( sMacro, SbxCLASS_METHOD ) ) ) + { + if( SbModule* pModule = pMethod->GetModule() ) + { + sMod = pModule->GetName(); + bFound = true; + } + } + } + } + } + return bFound; +} +void parseMacro( const rtl::OUString& sMacro, String& sContainer, String& sModule, String& sProcedure ) +{ + sal_Int32 nMacroDot = sMacro.lastIndexOf( '.' ); + + if ( nMacroDot != -1 ) + { + sProcedure = sMacro.copy( nMacroDot + 1 ); + + sal_Int32 nContainerDot = sMacro.lastIndexOf( '.', nMacroDot - 1 ); + if ( nContainerDot != -1 ) + { + sModule = sMacro.copy( nContainerDot + 1, nMacroDot - nContainerDot - 1 ); + sContainer = sMacro.copy( 0, nContainerDot ); + } + else + sModule = sMacro.copy( 0, nMacroDot ); + } + else + sProcedure = sMacro; +} + +MacroResolvedInfo resolveVBAMacro( SfxObjectShell* pShell, const rtl::OUString& MacroName, bool bSearchGlobalTemplates ) +{ + if( !pShell ) + return MacroResolvedInfo(); + + // the name may be enclosed in apostrophs + ::rtl::OUString aMacroName = trimMacroName( MacroName ); + + // parse the macro name + sal_Int32 nDocSepIndex = aMacroName.indexOf( '!' ); + if( nDocSepIndex > 0 ) + { + // macro specified by document name + // find document shell for document name and call ourselves + // recursively + + // assume for now that the document name is *this* document + String sDocUrlOrPath = aMacroName.copy( 0, nDocSepIndex ); + aMacroName = aMacroName.copy( nDocSepIndex + 1 ); + OSL_TRACE("doc search, current shell is 0x%x", pShell ); + SfxObjectShell* pFoundShell = 0; + if( bSearchGlobalTemplates ) + { + SvtPathOptions aPathOpt; + String aAddinPath = aPathOpt.GetAddinPath(); + if( rtl::OUString( sDocUrlOrPath ).indexOf( aAddinPath ) == 0 ) + pFoundShell = pShell; + } + if( !pFoundShell ) + pFoundShell = findShellForUrl( sDocUrlOrPath ); + OSL_TRACE("doc search, after find, found shell is 0x%x", pFoundShell ); + return resolveVBAMacro( pFoundShell, aMacroName ); + } + + // macro is contained in 'this' document ( or code imported from a template + // where that template is a global template or perhaps the template this + // document is created from ) + + MacroResolvedInfo aRes( pShell ); + + // macro format = Container.Module.Procedure + String sContainer, sModule, sProcedure; + parseMacro( aMacroName, sContainer, sModule, sProcedure ); + uno::Reference< container::XNameContainer > xPrjNameCache; + + // As long as service VBAProjectNameProvider isn't supported in the model, disable the createInstance call + // (the ServiceNotRegisteredException is wrongly caught in ScModelObj::createInstance) + //uno::Reference< lang::XMultiServiceFactory> xSF( pShell->GetModel(), uno::UNO_QUERY); + //if ( xSF.is() ) + // xPrjNameCache.set( xSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAProjectNameProvider" ) ) ), uno::UNO_QUERY ); + + std::vector< rtl::OUString > sSearchList; + + if ( sContainer.Len() > 0 ) + { + // get the Project associated with the Container + if ( xPrjNameCache.is() ) + { + if ( xPrjNameCache->hasByName( sContainer ) ) + { + rtl::OUString sProject; + xPrjNameCache->getByName( sContainer ) >>= sProject; + sContainer = sProject; + } + } + sSearchList.push_back( sContainer ); // First Lib to search + } + else + { + // Ok, if we have no Container specified then we need to search them in order, this document, template this document created from, global templates, + // get the name of Project/Library for 'this' document + rtl::OUString sThisProject; + BasicManager* pBasicMgr = pShell-> GetBasicManager(); + if ( pBasicMgr ) + { + if ( pBasicMgr->GetName().Len() ) + sThisProject = pBasicMgr->GetName(); + else // cater for the case where VBA is not enabled + sThisProject = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Standard") ); + } + sSearchList.push_back( sThisProject ); // First Lib to search + if ( xPrjNameCache.is() ) + { + // is this document created from a template? + uno::Reference< document::XDocumentInfoSupplier > xDocInfoSupp( pShell->GetModel(), uno::UNO_QUERY_THROW ); + uno::Reference< document::XDocumentPropertiesSupplier > xDocPropSupp( xDocInfoSupp->getDocumentInfo(), uno::UNO_QUERY_THROW ); + uno::Reference< document::XDocumentProperties > xDocProps( xDocPropSupp->getDocumentProperties(), uno::UNO_QUERY_THROW ); + + rtl::OUString sCreatedFrom = xDocProps->getTemplateURL(); + if ( sCreatedFrom.getLength() ) + { + INetURLObject aObj; + aObj.SetURL( sCreatedFrom ); + bool bIsURL = aObj.GetProtocol() != INET_PROT_NOT_VALID; + rtl::OUString aURL; + if ( bIsURL ) + aURL = sCreatedFrom; + else + { + osl::FileBase::getFileURLFromSystemPath( sCreatedFrom, aURL ); + aObj.SetURL( aURL ); + } + sCreatedFrom = aObj.GetLastName(); + } + + sal_Int32 nIndex = sCreatedFrom.lastIndexOf( '.' ); + if ( nIndex != -1 ) + sCreatedFrom = sCreatedFrom.copy( 0, nIndex ); + + rtl::OUString sPrj; + if ( sCreatedFrom.getLength() && xPrjNameCache->hasByName( sCreatedFrom ) ) + { + xPrjNameCache->getByName( sCreatedFrom ) >>= sPrj; + // Make sure we don't double up with this project + if ( !sPrj.equals( sThisProject ) ) + sSearchList.push_back( sPrj ); + } + + // get list of global template Names + uno::Sequence< rtl::OUString > sTemplateNames = xPrjNameCache->getElementNames(); + sal_Int32 nLen = sTemplateNames.getLength(); + for ( sal_Int32 index = 0; ( bSearchGlobalTemplates && index < nLen ); ++index ) + { + + if ( !sCreatedFrom.equals( sTemplateNames[ index ] ) ) + { + if ( xPrjNameCache->hasByName( sTemplateNames[ index ] ) ) + { + xPrjNameCache->getByName( sTemplateNames[ index ] ) >>= sPrj; + // Make sure we don't double up with this project + if ( !sPrj.equals( sThisProject ) ) + sSearchList.push_back( sPrj ); + } + } + + } + } + } + std::vector< rtl::OUString >::iterator it_end = sSearchList.end(); + for ( std::vector< rtl::OUString >::iterator it = sSearchList.begin(); !aRes.mbFound && (it != it_end); ++it ) + { + aRes.mbFound = hasMacro( pShell, *it, sModule, sProcedure ); + if ( aRes.mbFound ) + sContainer = *it; + } + aRes.msResolvedMacro = sProcedure.Insert( '.', 0 ).Insert( sModule, 0).Insert( '.', 0 ).Insert( sContainer, 0 ); + + return aRes; +} + +// Treat the args as possible inouts ( convertion at bottom of method ) +sal_Bool executeMacro( SfxObjectShell* pShell, const String& sMacroName, uno::Sequence< uno::Any >& aArgs, uno::Any& aRet, const uno::Any& /*aCaller*/) +{ + sal_Bool bRes = sal_False; + if ( !pShell ) + return bRes; + rtl::OUString sUrl = makeMacroURL( sMacroName ); + + uno::Sequence< sal_Int16 > aOutArgsIndex; + uno::Sequence< uno::Any > aOutArgs; + + try + { ErrCode nErr( ERRCODE_BASIC_INTERNAL_ERROR ); + if ( pShell ) + { + nErr = pShell->CallXScript( sUrl, + aArgs, aRet, aOutArgsIndex, aOutArgs, false ); + sal_Int32 nLen = aOutArgs.getLength(); + // convert any out params to seem like they were inouts + if ( nLen ) + { + for ( sal_Int32 index=0; index < nLen; ++index ) + { + sal_Int32 nOutIndex = aOutArgsIndex[ index ]; + aArgs[ nOutIndex ] = aOutArgs[ index ]; + } + } + } + bRes = ( nErr == ERRCODE_NONE ); + } + catch ( uno::Exception& ) + { + bRes = sal_False; + } + return bRes; +} + +// ============================================================================ + +uno::Sequence< ::rtl::OUString > VBAMacroResolver_getSupportedServiceNames() +{ + uno::Sequence< ::rtl::OUString > aServiceNames( 1 ); + aServiceNames[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.vba.VBAMacroResolver" ) ); + return aServiceNames; +} + +::rtl::OUString VBAMacroResolver_getImplementationName() +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.vba.VBAMacroResolver" ) ); +} + +uno::Reference< uno::XInterface > SAL_CALL VBAMacroResolver_createInstance( const uno::Reference< uno::XComponentContext >& ) throw (uno::Exception) +{ + return static_cast< ::cppu::OWeakObject* >( new VBAMacroResolver ); +} + +// ============================================================================ + +VBAMacroResolver::VBAMacroResolver() : + mpObjShell( 0 ) +{ +} + +VBAMacroResolver::~VBAMacroResolver() +{ +} + +// com.sun.star.lang.XServiceInfo interface ----------------------------------- + +::rtl::OUString SAL_CALL VBAMacroResolver::getImplementationName() throw (uno::RuntimeException) +{ + return VBAMacroResolver_getImplementationName(); +} + +sal_Bool SAL_CALL VBAMacroResolver::supportsService( const ::rtl::OUString& rService ) throw (uno::RuntimeException) +{ + uno::Sequence< ::rtl::OUString > aServices = VBAMacroResolver_getSupportedServiceNames(); + const ::rtl::OUString* pArray = aServices.getConstArray(); + const ::rtl::OUString* pArrayEnd = pArray + aServices.getLength(); + return ::std::find( pArray, pArrayEnd, rService ) != pArrayEnd; +} + +uno::Sequence< ::rtl::OUString > SAL_CALL VBAMacroResolver::getSupportedServiceNames() throw (uno::RuntimeException) +{ + return VBAMacroResolver_getSupportedServiceNames(); +} + +// com.sun.star.lang.XInitialization interface -------------------------------- + +void SAL_CALL VBAMacroResolver::initialize( const uno::Sequence< uno::Any >& rArgs ) throw (uno::Exception, uno::RuntimeException) +{ + OSL_ENSURE( rArgs.getLength() < 2, "VBAMacroResolver::initialize - missing arguments" ); + if( rArgs.getLength() < 2 ) + throw uno::RuntimeException(); + + // first argument: document model + mxModel.set( rArgs[ 0 ], uno::UNO_QUERY_THROW ); + uno::Reference< lang::XUnoTunnel > xUnoTunnel( mxModel, uno::UNO_QUERY_THROW ); + mpObjShell = reinterpret_cast< SfxObjectShell* >( xUnoTunnel->getSomething( SfxObjectShell::getUnoTunnelId() ) ); + if( !mpObjShell ) + throw uno::RuntimeException(); + + // second argument: VBA project name + if( !(rArgs[ 1 ] >>= maProjectName) || (maProjectName.getLength() == 0) ) + throw uno::RuntimeException(); +} + +// com.sun.star.script.vba.XVBAMacroResolver interface ------------------------ + +::rtl::OUString SAL_CALL VBAMacroResolver::resolveVBAMacroToScriptURL( const ::rtl::OUString& rVBAMacroName ) throw (lang::IllegalArgumentException, uno::RuntimeException) +{ + if( !mpObjShell ) + throw uno::RuntimeException(); + + // the name may be enclosed in apostrophs + ::rtl::OUString aMacroName = trimMacroName( rVBAMacroName ); + if( aMacroName.getLength() == 0 ) + throw lang::IllegalArgumentException(); + + // external references not supported here (syntax is "url!macroname" or "[url]!macroname" or "[url]macroname") + if( (aMacroName[ 0 ] == '[') || (aMacroName.indexOf( '!' ) >= 0) ) + throw lang::IllegalArgumentException(); + + // check if macro name starts with project name, replace with "Standard" + // TODO: adjust this when custom VBA project name is supported + sal_Int32 nDotPos = aMacroName.indexOf( '.' ); + if( (nDotPos == 0) || (nDotPos + 1 == aMacroName.getLength()) ) + throw lang::IllegalArgumentException(); + if( (nDotPos > 0) && aMacroName.matchIgnoreAsciiCase( maProjectName ) ) + aMacroName = aMacroName.copy( nDotPos + 1 ); + + // try to find the macro + MacroResolvedInfo aInfo = resolveVBAMacro( mpObjShell, aMacroName, false ); + if( !aInfo.mbFound ) + throw lang::IllegalArgumentException(); + + // build and return the script URL + return makeMacroURL( aInfo.msResolvedMacro ); +} + +::rtl::OUString SAL_CALL VBAMacroResolver::resolveScriptURLtoVBAMacro( const ::rtl::OUString& /*rScriptURL*/ ) throw (lang::IllegalArgumentException, uno::RuntimeException) +{ + OSL_ENSURE( false, "VBAMacroResolver::resolveScriptURLtoVBAMacro - not implemented" ); + throw uno::RuntimeException(); +} + +// ============================================================================ + +} // namespace vba +} // namespace ooo diff --git a/filter/source/msfilter/msvbasic.cxx b/filter/source/msfilter/msvbasic.cxx new file mode 100644 index 000000000000..1e148d2f1bcb --- /dev/null +++ b/filter/source/msfilter/msvbasic.cxx @@ -0,0 +1,639 @@ +/************************************************************************* + * + * 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_filter.hxx" + +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */ + +#include <string.h> // memset(), ... +#ifndef UNX +#include <io.h> // access() +#endif +#include <osl/endian.h> +#include <rtl/tencinfo.h> //rtl_getTextEncodingFromWindowsCodePage +#include "msvbasic.hxx" + +#include <com/sun/star/script/ModuleType.hpp> + +using namespace ::com::sun::star::script; + +/* +A few urls which may in the future be of some use +http://www.virusbtn.com/vb2000/Programme/papers/bontchev.pdf +*/ + +/* class VBA_Impl: + * The VBA class provides a set of methods to handle Visual Basic For + * Applications streams, the constructor is given the root ole2 stream + * of the document, Open reads the VBA project file and figures out + * the number of VBA streams, and the offset of the data within them. + * Decompress decompresses a particular numbered stream, NoStreams returns + * this number, and StreamName can give you the streams name. Decompress + * will call Output when it has a 4096 byte collection of data to output, + * and also with the final remainder of data if there is still some left + * at the end of compression. Output is virtual to allow custom handling + * of each chunk of decompressed data. So inherit from this to do something + * useful with the data. + * + * cmc + * */ +const int MINVBASTRING = 6; + +VBA_Impl::VBA_Impl(SvStorage &rIn, bool bCmmntd) + : aVBAStrings(0), + sComment(RTL_CONSTASCII_USTRINGPARAM("Rem ")), + xStor(&rIn), pOffsets(0), nOffsets(0), meCharSet(RTL_TEXTENCODING_MS_1252), + bCommented(bCmmntd), mbMac(false), nLines(0) +{ +} + +VBA_Impl::~VBA_Impl() +{ + delete [] pOffsets; + for (sal_uLong i=0;i<aVBAStrings.GetSize();++i) + delete aVBAStrings.Get(i); +} + +sal_uInt8 VBA_Impl::ReadPString(SvStorageStreamRef &xVBAProject, + bool bIsUnicode) +{ + sal_uInt16 nIdLen, nOut16; + sal_uInt8 nType = 0, nOut8; + String sReference; + + *xVBAProject >> nIdLen; + + if (nIdLen < MINVBASTRING) //Error recovery + xVBAProject->SeekRel(-2); //undo 2 byte len + else + { + for(sal_uInt16 i=0; i < nIdLen / (bIsUnicode ? 2 : 1); i++) + { + if (bIsUnicode) + *xVBAProject >> nOut16; + else + { + *xVBAProject >> nOut8; + nOut16 = nOut8; + } + sReference += nOut16; + if (i==2) + { + if ((nOut16 == 'G') || (nOut16 == 'H') || (nOut16 == 'C') || + nOut16 == 'D') + { + nType = static_cast<sal_uInt8>(nOut16); + } + if (nType == 0) + { + //Error recovery, 2byte len + 3 characters of used type + xVBAProject->SeekRel(-(2 + 3 * (bIsUnicode ? 2 : 1))); + break; + } + } + } + maReferences.push_back(sReference); + } + return nType; +} + +void VBA_Impl::Output( int nLen, const sal_uInt8*pData ) +{ + /* + Each StarBasic module is tragically limited to the maximum len of a + string and WordBasic is not, so each overlarge module must be split + */ + String sTemp((const sal_Char *)pData, (xub_StrLen)nLen, + meCharSet); + int nTmp = sTemp.GetTokenCount('\x0D'); + int nIndex = aVBAStrings.GetSize()-1; + if (aVBAStrings.Get(nIndex)->Len() + + nLen + ((nLines+nTmp) * sComment.Len()) >= STRING_MAXLEN) + { + //DBG_ASSERT(0,"New Module String\n"); + //we are too large for our boots, break out into another + //string + nLines=0; + nIndex++; + aVBAStrings.SetSize(nIndex+1); + aVBAStrings.Put(nIndex,new String); + } + *(aVBAStrings.Get(nIndex)) += sTemp; + nLines+=nTmp; +} + + +int VBA_Impl::ReadVBAProject(const SvStorageRef &rxVBAStorage) +{ + SvStorageStreamRef xVBAProject; + xVBAProject = rxVBAStorage->OpenSotStream( + String( RTL_CONSTASCII_USTRINGPARAM( "_VBA_PROJECT" ) ), + STREAM_STD_READ | STREAM_NOCREATE ); + + if( !xVBAProject.Is() || SVSTREAM_OK != xVBAProject->GetError() ) + { + DBG_WARNING("Not able to find vba project, cannot find macros"); + return 0; + } + + static const sal_uInt8 aKnownId[] = {0xCC, 0x61}; + sal_uInt8 aId[2]; + xVBAProject->Read( aId, sizeof(aId) ); + if (memcmp( aId, aKnownId, sizeof(aId))) + { + DBG_WARNING("unrecognized VBA macro project type"); + return 0; + } + + static const sal_uInt8 aOffice2007LE[] = { 0x88, 0x00, 0x00, 0x01, 0x00, 0xFF }; + static const sal_uInt8 aOffice2003LE_2[] = { 0x79, 0x00, 0x00, 0x01, 0x00, 0xFF }; + static const sal_uInt8 aOffice2003LE[] = { 0x76, 0x00, 0x00, 0x01, 0x00, 0xFF }; + static const sal_uInt8 aOfficeXPLE[] = { 0x73, 0x00, 0x00, 0x01, 0x00, 0xFF }; + static const sal_uInt8 aOfficeXPBE[] = { 0x63, 0x00, 0x00, 0x0E, 0x00, 0xFF }; + static const sal_uInt8 aOffice2000LE[] = { 0x6D, 0x00, 0x00, 0x01, 0x00, 0xFF }; + static const sal_uInt8 aOffice98BE[] = { 0x60, 0x00, 0x00, 0x0E, 0x00, 0xFF }; + static const sal_uInt8 aOffice97LE[] = { 0x5E, 0x00, 0x00, 0x01, 0x00, 0xFF }; + + sal_uInt8 aProduct[6]; + xVBAProject->Read( aProduct, sizeof(aProduct) ); + + bool bIsUnicode; + if (!(memcmp(aProduct, aOffice2007LE, sizeof(aProduct))) || + !(memcmp(aProduct, aOffice2003LE, sizeof(aProduct))) || + !(memcmp(aProduct, aOffice2003LE_2, sizeof(aProduct))) || + !(memcmp(aProduct, aOfficeXPLE, sizeof(aProduct))) || + !(memcmp(aProduct, aOffice2000LE, sizeof(aProduct))) || + !(memcmp(aProduct, aOffice97LE, sizeof(aProduct))) ) + { + xVBAProject->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); + bIsUnicode = true; + } + else if (!(memcmp(aProduct, aOfficeXPBE, sizeof(aProduct))) || + !(memcmp(aProduct, aOffice98BE, sizeof(aProduct))) ) + { + xVBAProject->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN ); + mbMac = true; + bIsUnicode = false; + } + else + { + switch (aProduct[3]) + { + case 0x1: + xVBAProject->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN); + bIsUnicode = true; + DBG_ASSERT(!this, "unrecognized VBA macro version, report to cmc. Guessing at unicode little endian"); + break; + case 0xe: + xVBAProject->SetNumberFormatInt(NUMBERFORMAT_INT_BIGENDIAN); + mbMac = true; + bIsUnicode = false; + DBG_ASSERT(!this, "unrecognized VBA macro version, report to cmc. Guessing at 8bit big endian"); + break; + default: + DBG_ASSERT(!this, "totally unrecognized VBA macro version, report to cmc"); + return 0; + } + } + + sal_uInt32 nLidA; //Language identifiers + sal_uInt32 nLidB; + sal_uInt16 nCharSet; + sal_uInt16 nLenA; + sal_uInt32 nUnknownB; + sal_uInt32 nUnknownC; + sal_uInt16 nLenB; + sal_uInt16 nLenC; + sal_uInt16 nLenD; + + *xVBAProject >> nLidA >> nLidB >> nCharSet >> nLenA >> nUnknownB; + *xVBAProject >> nUnknownC >> nLenB >> nLenC >> nLenD; + + meCharSet = rtl_getTextEncodingFromWindowsCodePage(nCharSet); + + DBG_ASSERT(meCharSet != RTL_TEXTENCODING_DONTKNOW, + "don't know what vba charset to use"); + if (meCharSet == RTL_TEXTENCODING_DONTKNOW) + meCharSet = RTL_TEXTENCODING_MS_1252; + + if (nLenD != 0x02) + { + DBG_WARNING("Warning VBA number is different, please report"); + return 0; + } + + /* + A sequence of string that are prepended with a len and then begin with G + or H, there are also those that begin with C or D. If a string begins with + C or D, it is really two strings, one right after the other. Each string + then has a 12 bytes suffix + + Recognizing the end of the sequence is done by finding a str len of < 6 + which does not appear to be the beginning of an object id. Admittedly this + isn't a great test, but nothing in the header appears to count the number + of strings, and nothing else seems to match. So it'll have to do, its + protected by a number of secondry tests to prove its a valid string, and + everything gives up if this isn't proven. + */ + bool bPredictsTrailingTwenty = false; + while (1) + { + sal_uInt8 nType = ReadPString(xVBAProject,bIsUnicode); + //Type C and D seem to come as pairs, so skip the following one + if (nType == 'C' || nType == 'D') + { + nType = ReadPString(xVBAProject,bIsUnicode); + DBG_ASSERT( nType == 'C' || nType == 'D', + "VBA: This must be a 'C' or 'D' string!" ); + if (nType != 'C' && nType != 'D') + return 0; + } + if (!nType) + break; + xVBAProject->SeekRel(10); + sal_uInt16 nPredictsTrailingTwenty; + *xVBAProject >> nPredictsTrailingTwenty; + if (nPredictsTrailingTwenty) + bPredictsTrailingTwenty = true; + if (bPredictsTrailingTwenty) + { + sal_uInt16 nTestIsNotString; + *xVBAProject >> nTestIsNotString; + if (nTestIsNotString < MINVBASTRING) + { + DBG_ASSERT(nTestIsNotString <= 1, + "Haven't seen a len like this in VBA, report to CMC"); + xVBAProject->SeekRel(18); + bPredictsTrailingTwenty = false; + } + else + xVBAProject->SeekRel(-2); + } + } + + sal_Int16 nInt16s; + *xVBAProject >> nInt16s; + DBG_ASSERT( nInt16s >= 0, "VBA: Bad no of records in VBA Project, panic!" ); + if (!nInt16s) + return 0; + + xVBAProject->SeekRel(2*nInt16s); + + sal_Int16 nInt32s; + *xVBAProject >> nInt32s; + DBG_ASSERT( nInt32s >= 0, "VBA: Bad no of records in VBA Project, panic!" ); + if (!nInt32s) + return 0; + xVBAProject->SeekRel(4*nInt32s); + + xVBAProject->SeekRel(2); + for(int k=0;k<3;k++) + { + sal_uInt16 nLen; + *xVBAProject >> nLen; + if (nLen != 0xFFFF) + xVBAProject->SeekRel(nLen); + } + xVBAProject->SeekRel(100); //Seems fixed len + + *xVBAProject >> nOffsets; + DBG_ASSERT( nOffsets != 0xFFFF, "VBA: Bad nOffsets, panic!!" ); + if ((nOffsets == 0xFFFF) || (nOffsets == 0)) + return 0; + pOffsets = new VBAOffset_Impl[ nOffsets ]; + + int i, j; + for( i=0; i < nOffsets; i++) + { + sal_uInt16 nLen; + *xVBAProject >> nLen; + + if (bIsUnicode) + { + sal_Unicode* pBuf = pOffsets[i].sName.AllocBuffer( nLen / 2 ); + xVBAProject->Read( (sal_Char*)pBuf, nLen ); + +#ifdef OSL_BIGENDIAN + for( j = 0; j < nLen / 2; ++j, ++pBuf ) + *pBuf = SWAPSHORT( *pBuf ); +#endif // ifdef OSL_BIGENDIAN + } + else + { + ByteString aByteStr; + sal_Char* pByteData = aByteStr.AllocBuffer( nLen ); + sal_Size nWasRead = xVBAProject->Read( pByteData, nLen ); + if( nWasRead != nLen ) + aByteStr.ReleaseBufferAccess(); + pOffsets[i].sName += String( aByteStr, meCharSet); + } + + *xVBAProject >> nLen; + xVBAProject->SeekRel( nLen ); + + //begin section, another problem area + *xVBAProject >> nLen; + if ( nLen == 0xFFFF) + { + xVBAProject->SeekRel(2); + *xVBAProject >> nLen; + xVBAProject->SeekRel( nLen ); + } + else + xVBAProject->SeekRel( nLen+2 ); + + *xVBAProject >> nLen; + DBG_ASSERT( nLen == 0xFFFF, "VBA: Bad field in VBA Project, panic!!" ); + if ( nLen != 0xFFFF) + return 0; + + xVBAProject->SeekRel(6); + sal_uInt16 nOctects; + *xVBAProject >> nOctects; + for(j=0;j<nOctects;j++) + xVBAProject->SeekRel(8); + + xVBAProject->SeekRel(5); + //end section + + *xVBAProject >> pOffsets[i].nOffset; + xVBAProject->SeekRel(2); + } + + return nOffsets; +} + + +/* #117718# For a given Module name return its type, + * Form, Class, Document, Normal or Unknown + * +*/ + +ModType VBA_Impl::GetModuleType( const UniString& rModuleName ) +{ + ModuleTypeHash::iterator iter = mhModHash.find( rModuleName ); + ModuleTypeHash::iterator iterEnd = mhModHash.end(); + if ( iter != iterEnd ) + { + return iter->second; + } + return ModuleType::UNKNOWN; +} + +bool VBA_Impl::Open( const String &rToplevel, const String &rSublevel ) +{ + /* beginning test for vba stuff */ + bool bRet = false; + SvStorageRef xMacros= xStor->OpenSotStorage( rToplevel, + STREAM_READWRITE | STREAM_NOCREATE | + STREAM_SHARE_DENYALL ); + if( !xMacros.Is() || SVSTREAM_OK != xMacros->GetError() ) + { + DBG_WARNING("No Macros Storage"); + } + else + { + xVBA = xMacros->OpenSotStorage( rSublevel, + STREAM_READWRITE | STREAM_NOCREATE | + STREAM_SHARE_DENYALL ); + if( !xVBA.Is() || SVSTREAM_OK != xVBA->GetError() ) + { + DBG_WARNING("No Visual Basic in Storage"); + } + else + { + if (ReadVBAProject(xVBA)) + bRet = true; + } + /* #117718# + * Information regarding the type of module is contained in the + * "PROJECT" stream, this stream consists of a number of ascii lines + * entries are of the form Key=Value, the ones that we are interested + * in have the keys; Class, BaseClass & Module indicating the module + * ( value ) is either a Class Module, Form Module or a plain VB Module. */ + SvStorageStreamRef xProject = xMacros->OpenSotStream( + String( RTL_CONSTASCII_USTRINGPARAM( "PROJECT" ) ) ); + SvStorageStream* pStp = xProject; + UniString tmp; + static const String sThisDoc( RTL_CONSTASCII_USTRINGPARAM( "ThisDocument" ) ); + static const String sModule( RTL_CONSTASCII_USTRINGPARAM( "Module" ) ); + static const String sClass( RTL_CONSTASCII_USTRINGPARAM( "Class" ) ); + static const String sBaseClass( RTL_CONSTASCII_USTRINGPARAM( "BaseClass" ) ); + static const String sDocument( RTL_CONSTASCII_USTRINGPARAM( "Document" ) ); + mhModHash[ sThisDoc ] = ModuleType::CLASS; + while ( pStp->ReadByteStringLine( tmp, meCharSet ) ) + { + xub_StrLen index = tmp.Search( '=' ); + if ( index != STRING_NOTFOUND ) + { + String key = tmp.Copy( 0, index ); + String value = tmp.Copy( index + 1 ); + if ( key == sClass ) + { + mhModHash[ value ] = ModuleType::CLASS; + OSL_TRACE("Module %s is of type Class", + ::rtl::OUStringToOString( value , + RTL_TEXTENCODING_ASCII_US ).pData->buffer ); + } + else if ( key == sBaseClass ) + { + mhModHash[ value ] = ModuleType::FORM; + OSL_TRACE("Module %s is of type Form", + ::rtl::OUStringToOString( value , + RTL_TEXTENCODING_ASCII_US ).pData->buffer ); + } + else if ( key == sDocument ) + { + /* #i37965# DR 2004-12-03: add "Document", used i.e. + in Excel for macros attached to sheet or document. */ + + // value is of form <name>/&H<identifier>, strip the identifier + value.Erase( value.Search( '/' ) ); + + mhModHash[ value ] = ModuleType::DOCUMENT; + OSL_TRACE("Module %s is of type Document VBA", + ::rtl::OUStringToOString( value , + RTL_TEXTENCODING_ASCII_US ).pData->buffer ); + } + else if ( key == sModule ) + { + mhModHash[ value ] = ModuleType::NORMAL; + OSL_TRACE("Module %s is of type Normal VBA", + ::rtl::OUStringToOString( value , + RTL_TEXTENCODING_ASCII_US ).pData->buffer ); + } + } + } + } + /* end test for vba stuff */ + return bRet; +} + +const StringArray &VBA_Impl::Decompress(sal_uInt16 nIndex, int *pOverflow) +{ + DBG_ASSERT( nIndex < nOffsets, "Index out of range" ); + SvStorageStreamRef xVBAStream; + aVBAStrings.SetSize(1); + aVBAStrings.Put(0,new String); + + xVBAStream = xVBA->OpenSotStream( pOffsets[nIndex].sName, + STREAM_STD_READ | STREAM_NOCREATE ); + if (pOverflow) + *pOverflow=0; + + if( !xVBAStream.Is() || SVSTREAM_OK != xVBAStream->GetError() ) + { + DBG_WARNING("Not able to open vb module "); + } + else + { + xVBAStream->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); + DecompressVBA( nIndex, xVBAStream ); + /* + * if len was too big for a single string set that variable ? + * if ((len > XX) && (pOverflow)) + *pOverflow=1; + */ + if (bCommented) + { + String sTempStringa; + if (mbMac) + sTempStringa = String( RTL_CONSTASCII_USTRINGPARAM( "\x0D" ) ); + else + sTempStringa = String( RTL_CONSTASCII_USTRINGPARAM( "\x0D\x0A" ) ); + String sTempStringb(sTempStringa); + sTempStringb+=sComment; + for(sal_uLong i=0;i<aVBAStrings.GetSize();i++) + { + aVBAStrings.Get(i)->SearchAndReplaceAll( + sTempStringa,sTempStringb); + aVBAStrings.Get(i)->Insert(sComment,0); + } + } + } + return aVBAStrings; +} + + +int VBA_Impl::DecompressVBA( int nIndex, SvStorageStreamRef &xVBAStream ) +{ + sal_uInt8 nLeadbyte; + sal_uInt16 nToken; + unsigned int nPos = 0; + int nLen, nDistance, nShift, nClean=1; + + xVBAStream->Seek( pOffsets[ nIndex ].nOffset + 3 ); + + while(xVBAStream->Read(&nLeadbyte,1)) + { + for(int nPosition=0x01;nPosition < 0x100;nPosition=nPosition<<1) + { + //we see if the leadbyte has flagged this location as a dataunit + //which is actually a token which must be looked up in the history + if (nLeadbyte & nPosition) + { + *xVBAStream >> nToken; + + if (nClean == 0) + nClean=1; + + //For some reason the division of the token into the length + //field of the data to be inserted, and the distance back into + //the history differs depending on how full the history is + int nPos2 = nPos % nWINDOWLEN; + if (nPos2 <= 0x10) + nShift = 12; + else if (nPos2 <= 0x20) + nShift = 11; + else if (nPos2 <= 0x40) + nShift = 10; + else if (nPos2 <= 0x80) + nShift = 9; + else if (nPos2 <= 0x100) + nShift = 8; + else if (nPos2 <= 0x200) + nShift = 7; + else if (nPos2 <= 0x400) + nShift = 6; + else if (nPos2 <= 0x800) + nShift = 5; + else + nShift = 4; + + int i; + nLen=0; + for(i=0;i<nShift;i++) + nLen |= nToken & (1<<i); + + nLen += 3; + + nDistance = nToken >> nShift; + + //read the len of data from the history, wrapping around the + //nWINDOWLEN boundary if necessary data read from the history + //is also copied into the recent part of the history as well. + for (i = 0; i < nLen; i++) + { + unsigned char c; + c = aHistory[(nPos-nDistance-1) % nWINDOWLEN]; + aHistory[nPos % nWINDOWLEN] = c; + nPos++; + } + } + else + { + // special boundary case code, not guarantueed to be correct + // seems to work though, there is something wrong with the + // compression scheme (or maybe a feature) where when the data + // ends on a nWINDOWLEN boundary and the excess bytes in the 8 + // dataunit list are discarded, and not interpreted as tokens + // or normal data. + if ((nPos != 0) && ((nPos % nWINDOWLEN) == 0) && (nClean)) + { + xVBAStream->SeekRel(2); + nClean=0; + Output(nWINDOWLEN, aHistory); + break; + } + //This is the normal case for when the data unit is not a + //token to be looked up, but instead some normal data which + //can be output, and placed in the history. + if (xVBAStream->Read(&aHistory[nPos % nWINDOWLEN],1)) + nPos++; + + if (nClean == 0) + nClean=1; + } + } + } + if (nPos % nWINDOWLEN) + Output(nPos % nWINDOWLEN,aHistory); + return(nPos); +} + +/* vi:set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/filter/source/msfilter/msvbasic.hxx b/filter/source/msfilter/msvbasic.hxx new file mode 100644 index 000000000000..171671e8cd5c --- /dev/null +++ b/filter/source/msfilter/msvbasic.hxx @@ -0,0 +1,120 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */ + +#ifndef _MSVBASIC_HXX +#define _MSVBASIC_HXX + +#include <tools/solar.h> +#include <tools/debug.hxx> +#include <sot/storage.hxx> +#include <tools/dynary.hxx> +#include <vector> +#include <map> + +/* class VBA: + * The VBA class provides a set of methods to handle Visual Basic For + * Applications streams, the constructor is given the root ole2 stream + * of the document, Open reads the VBA project file and figures out + * the number of VBA streams, and the offset of the data within them. + * Decompress decompresses a particular numbered stream, NoStreams returns + * this number, and StreamName can give you the streams name. Decompress + * will return a string with the decompressed data. The optional extra + * argument will be set if not NULL to 1 in the case of a string overflow, + * if I can figure out how to do that. + * + * Otherwise it is possible to inherit from VBA and implement a Output + * member which gets called with each 4096 output sized block. + * + * cmc + * */ + +DECLARE_DYNARRAY(StringArray,String *) + +// #117718# define internal types to distinguish between +// module types, form, class & normal +// #i37965# DR 2004-12-03: add "Document", used in Excel for macros attached to sheet + +// #117718# define map to hold types of module +// +typedef sal_Int32 ModType; +typedef ::std::map< UniString, + ModType > ModuleTypeHash; + +class VBA_Impl +{ +public: + VBA_Impl(SvStorage &rIn, bool bCmmntd = true); + ~VBA_Impl(); + //0 for failure, 1 for success + bool Open( const String &rToplevel, const String &rSublevel); + const StringArray & Decompress(sal_uInt16 nIndex, int *pOverflow=0); + sal_uInt16 GetNoStreams() const { return nOffsets; } + const String &GetStreamName(sal_uInt16 nIndex) const + { + DBG_ASSERT( nIndex < nOffsets, "Index out of range" ); + return pOffsets[ nIndex ].sName; + } + //I'm the method that would be made virtual to make this class + //useful elsewhere + void Output(int len, const sal_uInt8 *data); + // + // #117718# member map of module names to types of module + ModType GetModuleType( const UniString& rModuleName ); + std::vector<String> maReferences; +private: + struct VBAOffset_Impl + { + String sName; + sal_uInt32 nOffset; + }; + + // #117718# member map of module names to types of module + ModuleTypeHash mhModHash; + SvStorageRef xVBA; + StringArray aVBAStrings; + String sComment; + SvStorageRef xStor; + VBAOffset_Impl *pOffsets; + sal_uInt16 nOffsets; + enum Limits {nWINDOWLEN = 4096}; + sal_uInt8 aHistory[nWINDOWLEN]; + rtl_TextEncoding meCharSet; + bool bCommented; + bool mbMac; + int nLines; + + //0 for failure, anything else for success + int ReadVBAProject(const SvStorageRef &rxVBAStorage); + int DecompressVBA(int index, SvStorageStreamRef &rxVBAStream); + sal_uInt8 ReadPString(SvStorageStreamRef &xVBAProject, bool bIsUnicode); +}; + +#endif + +/* vi:set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/filter/source/msfilter/powerpoint/makefile.mk b/filter/source/msfilter/powerpoint/makefile.mk new file mode 100644 index 000000000000..0ad3d4202f1f --- /dev/null +++ b/filter/source/msfilter/powerpoint/makefile.mk @@ -0,0 +1,65 @@ +#************************************************************************* +# +# 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=filter +TARGET=PptImporter + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk + +# --- Files ------------------------------------- + +SLOFILES= $(SLO)$/pptimporter.obj \ + $(SLO)$/pptimporteruno.obj \ + $(SLO)$/ppttoxml.obj + +# --- Library ----------------------------------- + +SHL1TARGET=$(TARGET)$(DLLPOSTFIX) +SHL1STDLIBS=\ + $(SOTLIB) \ + $(TOOLSLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) + +SHL1DEPN= +SHL1IMPLIB= i$(SHL1TARGET) +SHL1LIBS= $(SLB)$/$(TARGET).lib +SHL1VERSIONMAP=$(SOLARENV)/src/component.map +SHL1DEF= $(MISC)$/$(SHL1TARGET).def + +DEF1NAME=$(SHL1TARGET) + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/filter/source/msfilter/powerpoint/pptcom.hxx b/filter/source/msfilter/powerpoint/pptcom.hxx new file mode 100644 index 000000000000..64dff7e54b30 --- /dev/null +++ b/filter/source/msfilter/powerpoint/pptcom.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 _PPTCOM_HXX +#define _PPTCOM_HXX + +#include <rtl/ustring.hxx> +#include <tools/debug.hxx> +#include <tools/stream.hxx> +#include <tools/string.hxx> +#include <tools/urlobj.hxx> +#include <tools/stack.hxx> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <xmloff/xmlexp.hxx> +#include <xmloff/nmspmap.hxx> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase4.hxx> +#include <com/sun/star/document/XFilter.hpp> +#include <com/sun/star/document/XImporter.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> + +// ----------------------------------------------------------------------------- + +#define NMSP_CPPU cppu +#define NMSP_RTL rtl +#define NMSP_UTL utl +#define NMSP_COMPHELPER comphelper +#define NMSP_UNO com::sun::star::uno +#define NMSP_BEANS com::sun::star::beans +#define NMSP_LANG com::sun::star::lang +#define NMSP_IO com::sun::star::io +#define NMSP_SAX com::sun::star::xml::sax +#define NMSP_PRES com::sun::star::presentation +#define NMSP_REGISTRY com::sun::star::registry +#define NMSP_DOCUMENT com::sun::star::document + + +#define REF( _def_Obj ) NMSP_UNO::Reference< _def_Obj > +#define SEQ( _def_Obj ) NMSP_UNO::Sequence< _def_Obj > +#define ANY NMSP_UNO::Any +#define B2UCONST( _def_pChar ) (NMSP_RTL::OUString(RTL_CONSTASCII_USTRINGPARAM(_def_pChar ))) +#define PPT_DTD_STRING B2UCONST( "<!DOCTYPE office:document-styles PUBLIC \"-//OpenOffice.org//DTD OfficeDocument 1.0//EN\" \"office.dtd\">" +#endif diff --git a/filter/source/msfilter/powerpoint/pptimporter.cxx b/filter/source/msfilter/powerpoint/pptimporter.cxx new file mode 100644 index 000000000000..960987700980 --- /dev/null +++ b/filter/source/msfilter/powerpoint/pptimporter.cxx @@ -0,0 +1,163 @@ +/************************************************************************* + * + * 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_filter.hxx" +#include "pptimporter.hxx" + +#ifdef DBG_DUMP_PPT_IMPORT +#ifndef _COM_SUN_STAR_IO_XACTIVEDATASOURCE_HDL_ +#include <com/sun/star/io/XActiveDataSource.hpp> +#endif +#include <unotools/streamwrap.hxx> +#include <comphelper/processfactory.hxx> +#endif + +#include <uno/mapping.hxx> + +// ----------------- +// - PptImporter - +// ----------------- + +NMSP_RTL::OUString PptImporter_getImplementationName() + throw( NMSP_UNO::RuntimeException ) +{ + return B2UCONST( "com.sun.star.presentation.PptImporter" ); +} +#define SERVICE_NAME "com.sun.star.document.ImportFilter" +sal_Bool SAL_CALL PptImporter_supportsService( const NMSP_RTL::OUString& ServiceName ) + throw( NMSP_UNO::RuntimeException ) +{ + return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SERVICE_NAME ) ); +} + +SEQ( NMSP_RTL::OUString ) SAL_CALL PptImporter_getSupportedServiceNames() + throw( NMSP_UNO::RuntimeException ) +{ + SEQ( NMSP_RTL::OUString ) aRet(1); + NMSP_RTL::OUString* pArray = aRet.getArray(); + pArray[0] = B2UCONST( SERVICE_NAME ); + return aRet; +} +#undef SERVICE_NAME + +// ----------------------------------------------------------------------------- + +PptImporter::PptImporter( const REF( NMSP_LANG::XMultiServiceFactory )& rxMgr ) : + xFact( rxMgr ) +{ + NMSP_RTL::OUString sService( B2UCONST( "com.sun.star.comp.Impress.XMLImporter" ) ); + try + { + xHdl = REF( NMSP_SAX::XDocumentHandler ) ( xFact->createInstance( sService ), NMSP_UNO::UNO_QUERY ); + xImporter = REF( NMSP_DOCUMENT::XImporter )( xHdl, NMSP_UNO::UNO_QUERY ); + } + catch( NMSP_UNO::Exception & ) + { + } +} + +// ----------------------------------------------------------------------------- + +PptImporter::~PptImporter() +{ +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL PptImporter::acquire() throw() +{ + OWeakObject::acquire(); +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL PptImporter::release() throw() +{ + OWeakObject::release(); +} + +// XFilter +sal_Bool SAL_CALL PptImporter::filter( const SEQ( NMSP_BEANS::PropertyValue )& aDescriptor ) + throw ( NMSP_UNO::RuntimeException ) +{ + + +#ifdef DBG_DUMP_PPT_IMPORT + + REF( NMSP_LANG::XMultiServiceFactory ) xServiceFactory( NMSP_COMPHELPER::getProcessServiceFactory() ); + REF( NMSP_UNO::XInterface ) xWriter( xServiceFactory->createInstance( B2UCONST( "com.sun.star.xml.sax.Writer" ) ) ); + SvFileStream aStrm( B2UCONST( "d:\\test2.xml" ), STREAM_READ | STREAM_WRITE | STREAM_TRUNC ); + REF( NMSP_IO::XOutputStream ) xOutStream( (::cppu::OWeakObject*) new NMSP_UTL::OOutputStreamWrapper( aStrm ), NMSP_UNO::UNO_QUERY ); + REF( NMSP_IO::XActiveDataSource ) xDataSource( xWriter , NMSP_UNO::UNO_QUERY ); + xDataSource->setOutputStream( xOutStream ); + aFilter.filter( aDescriptor, REF( NMSP_SAX::XDocumentHandler )( xWriter, NMSP_UNO::UNO_QUERY ) ); + +// REF( NMSP_BEANS::XPropertySet ) xPropSet( xServiceFactory->createInstance( B2UCONST( "com.sun.star.beans.PropertySet" ) ) ); +// Any aAny; +// aAny <<= (sal_Bool)sal_True; +// xPropSet->setPropertyValue( B2UCONST( "UsePrettyPrinting" ), aAny ); + +#endif + + return aFilter.filter( aDescriptor, xHdl ); +} +void SAL_CALL PptImporter::cancel() + throw ( NMSP_UNO::RuntimeException ) +{ + aFilter.cancel(); +} + +// XImporter +void SAL_CALL PptImporter::setTargetDocument( const REF( NMSP_LANG::XComponent )& xDoc ) + throw ( NMSP_LANG::IllegalArgumentException, NMSP_UNO::RuntimeException) +{ + xImporter->setTargetDocument( xDoc ); +} + +// XInitialization +void SAL_CALL PptImporter::initialize( const SEQ( NMSP_UNO::Any )& /* aArguments */ ) + throw ( NMSP_UNO::Exception, NMSP_UNO::RuntimeException ) +{ +} + +// XServiceInfo +NMSP_RTL::OUString SAL_CALL PptImporter::getImplementationName() + throw( NMSP_UNO::RuntimeException ) +{ + return PptImporter_getImplementationName(); +} +sal_Bool SAL_CALL PptImporter::supportsService( const NMSP_RTL::OUString& rServiceName ) + throw( NMSP_UNO::RuntimeException ) +{ + return PptImporter_supportsService( rServiceName ); +} +SEQ( NMSP_RTL::OUString ) SAL_CALL PptImporter::getSupportedServiceNames() + throw ( NMSP_UNO::RuntimeException ) +{ + return PptImporter_getSupportedServiceNames(); +} diff --git a/filter/source/msfilter/powerpoint/pptimporter.hxx b/filter/source/msfilter/powerpoint/pptimporter.hxx new file mode 100644 index 000000000000..6366d0fda054 --- /dev/null +++ b/filter/source/msfilter/powerpoint/pptimporter.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 _PPTIMPORTER_HXX +#define _PPTIMPORTER_HXX + +#include "pptcom.hxx" +#include "ppttoxml.hxx" + +// --------------- +// - PptImporter - +// --------------- + +class PptImporter : public NMSP_CPPU::WeakImplHelper4 +< + NMSP_DOCUMENT::XFilter, + NMSP_DOCUMENT::XImporter, + NMSP_LANG::XInitialization, + NMSP_LANG::XServiceInfo +> +{ + PptToXml aFilter; + REF( NMSP_SAX::XDocumentHandler ) xHdl; + REF( NMSP_LANG::XMultiServiceFactory ) xFact; + REF( NMSP_DOCUMENT::XImporter ) xImporter; + +public: + + PptImporter( const REF( NMSP_LANG::XMultiServiceFactory )& rxMgr ); + virtual ~PptImporter(); + + // XInterface + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + // XFilter + virtual sal_Bool SAL_CALL filter( const SEQ( NMSP_BEANS::PropertyValue )& aDescriptor ) + throw ( NMSP_UNO::RuntimeException ); + virtual void SAL_CALL cancel( ) + throw ( NMSP_UNO::RuntimeException ); + + // XImporter + virtual void SAL_CALL setTargetDocument( const REF(NMSP_LANG::XComponent)& xDoc ) + throw ( NMSP_LANG::IllegalArgumentException, NMSP_UNO::RuntimeException ); + + // XInitialization + virtual void SAL_CALL initialize( const SEQ( NMSP_UNO::Any )& aArguments ) + throw ( NMSP_UNO::Exception, NMSP_UNO::RuntimeException ); + + // XServiceInfo + virtual NMSP_RTL::OUString SAL_CALL getImplementationName() + throw ( NMSP_UNO::RuntimeException ); + virtual sal_Bool SAL_CALL supportsService( const NMSP_RTL::OUString& ServiceName ) + throw ( NMSP_UNO::RuntimeException ); + virtual SEQ( NMSP_RTL::OUString ) SAL_CALL getSupportedServiceNames() + throw ( NMSP_UNO::RuntimeException ); + +}; + +NMSP_RTL::OUString PptImporter_getImplementationName() + throw ( NMSP_UNO::RuntimeException ); +sal_Bool SAL_CALL PptImportert_supportsService( const NMSP_RTL::OUString& ServiceName ) + throw( NMSP_UNO::RuntimeException ); +SEQ( NMSP_RTL::OUString ) SAL_CALL PptImporter_getSupportedServiceNames() + throw( NMSP_UNO::RuntimeException ); + +#endif diff --git a/filter/source/msfilter/powerpoint/pptimporteruno.cxx b/filter/source/msfilter/powerpoint/pptimporteruno.cxx new file mode 100644 index 000000000000..325d360344cf --- /dev/null +++ b/filter/source/msfilter/powerpoint/pptimporteruno.cxx @@ -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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_filter.hxx" + +#include "pptimporter.hxx" + +#include <cppuhelper/factory.hxx> +#include <uno/mapping.hxx> + +// ------------------- +// - factory methods - +// ------------------- + +static REF( NMSP_UNO::XInterface ) SAL_CALL create_PptImporter( const REF( NMSP_LANG::XMultiServiceFactory )& rxFact ) +{ + return REF( NMSP_UNO::XInterface )( *new PptImporter( rxFact ) ); +} + +// ------------------------------------------ +// - component_getImplementationEnvironment - +// ------------------------------------------ + +extern "C" void SAL_CALL component_getImplementationEnvironment( const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +// ------------------------ +// - component_getFactory - +// ------------------------ + +extern "C" void* SAL_CALL component_getFactory( const sal_Char* pImplName, void* pServiceManager, void* /* pRegistryKey */ ) +{ + REF( NMSP_LANG::XSingleServiceFactory ) xFactory; + void* pRet = 0; + + if( rtl_str_compare( pImplName, "com.sun.star.presentation.PptImporter" ) == 0 ) + { + const NMSP_RTL::OUString aServiceName( B2UCONST( "com.sun.star.presentation.PptImporter" ) ); + + xFactory = REF( NMSP_LANG::XSingleServiceFactory )( NMSP_CPPU::createSingleFactory( + reinterpret_cast< NMSP_LANG::XMultiServiceFactory* >( pServiceManager ), + B2UCONST( "com.sun.star.presentation.PptImporter" ), + create_PptImporter, SEQ( NMSP_RTL::OUString )( &aServiceName, 1 ) ) ); + } + if( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} diff --git a/filter/source/msfilter/powerpoint/ppttoxml.cxx b/filter/source/msfilter/powerpoint/ppttoxml.cxx new file mode 100644 index 000000000000..d4ec2af93e7b --- /dev/null +++ b/filter/source/msfilter/powerpoint/ppttoxml.cxx @@ -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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_filter.hxx" + +#include "ppttoxml.hxx" +#include <sot/storage.hxx> + +PptToXml::PptToXml() +{ +} + +PptToXml::~PptToXml() +{ +} + +sal_Bool PptToXml::filter( const SEQ( NMSP_BEANS::PropertyValue )& aDescriptor, + REF( NMSP_SAX::XDocumentHandler ) xHandler ) +{ + xHdl = xHandler; + + sal_Bool bStatus = sal_False; + sal_Int32 i; + for( i = 0; i < aDescriptor.getLength(); i++ ) + { + NMSP_RTL::OUString strTemp; + aDescriptor[ i ].Value >>= strTemp; + +/* we will open the document by url, so the stream is not needed + if( aDescriptor[i].Name == B2UCONST( "InputStream" ) ) + { + REF( NMSP_IO::XInputStream ) rInputStream; + aDescriptor[ i].Value >>= rInputStream; + } + else +*/ + if ( aDescriptor[ i ].Name == B2UCONST( "URL" ) ) + { + NMSP_RTL::OUString sURL; + aDescriptor[ i ].Value >>= sURL; + SotStorageRef xStg( new SotStorage( sURL, STREAM_STD_READ, 0 ) ); + if ( xStg.Is() ) + { + SotStorageStreamRef xDocStream( xStg->OpenSotStream( B2UCONST( "PowerPoint Document" ), STREAM_STD_READ ) ); + if( xDocStream.Is() ) + { + xDocStream->SetVersion( xStg->GetVersion() ); + xDocStream->SetKey( xStg->GetKey() ); + +// xHdl->unknown( PPT_DTD_STRING ); + xHdl->startDocument(); + + + xHdl->endDocument(); + bStatus = sal_True; + } + } + } + } + return bStatus; +} + +void PptToXml::cancel() +{ + +} diff --git a/filter/source/msfilter/powerpoint/ppttoxml.hxx b/filter/source/msfilter/powerpoint/ppttoxml.hxx new file mode 100644 index 000000000000..b77f85b0109b --- /dev/null +++ b/filter/source/msfilter/powerpoint/ppttoxml.hxx @@ -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. + * + ************************************************************************/ + +#ifndef _PPTTOXML_HXX +#define _PPTTOXML_HXX + +#include "pptcom.hxx" + +// ------------ +// - PptToXml - +// ------------ + +class PptToXml +{ + REF( NMSP_SAX::XDocumentHandler ) xHdl; + + public: + + PptToXml(); + ~PptToXml(); + + sal_Bool filter( const SEQ( NMSP_BEANS::PropertyValue )& aDescriptor, + REF(NMSP_SAX::XDocumentHandler) xHandler ); + void cancel(); +}; + +#endif diff --git a/filter/source/msfilter/services.cxx b/filter/source/msfilter/services.cxx new file mode 100755 index 000000000000..09a303f72141 --- /dev/null +++ b/filter/source/msfilter/services.cxx @@ -0,0 +1,75 @@ +/************************************************************************* + * + * 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 <cppuhelper/implementationentry.hxx> + +using ::rtl::OUString; +using namespace ::com::sun::star::uno; + +// Declare static functions providing service information ===================== + +#define DECLARE_FUNCTIONS( className ) \ +extern OUString SAL_CALL className##_getImplementationName() throw(); \ +extern Sequence< OUString > SAL_CALL className##_getSupportedServiceNames() throw(); \ +extern Reference< XInterface > SAL_CALL className##_createInstance( \ + const Reference< XComponentContext >& rxContext ) throw (Exception) + +namespace ooo { namespace vba { DECLARE_FUNCTIONS( VBAMacroResolver ); } } + +#undef DECLARE_FUNCTIONS + +// ============================================================================ + +namespace { + +#define IMPLEMENTATION_ENTRY( className ) \ + { &className##_createInstance, &className##_getImplementationName, &className##_getSupportedServiceNames, ::cppu::createSingleComponentFactory, 0, 0 } + +static ::cppu::ImplementationEntry const spServices[] = +{ + IMPLEMENTATION_ENTRY( ::ooo::vba::VBAMacroResolver ), + { 0, 0, 0, 0, 0, 0 } +}; + +#undef IMPLEMENTATION_ENTRY + +} // namespace + +// ---------------------------------------------------------------------------- + +extern "C" SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment( + const sal_Char** ppEnvironmentTypeName, uno_Environment** /*ppEnvironment*/ ) +{ + *ppEnvironmentTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +extern "C" SAL_DLLPUBLIC_EXPORT void* SAL_CALL component_getFactory( const char* pImplName, void* pServiceManager, void* pRegistryKey ) +{ + return ::cppu::component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey, spServices ); +} + +// ============================================================================ diff --git a/filter/source/msfilter/svdfppt.cxx b/filter/source/msfilter/svdfppt.cxx new file mode 100644 index 000000000000..40a0a6b19e18 --- /dev/null +++ b/filter/source/msfilter/svdfppt.cxx @@ -0,0 +1,7823 @@ +/************************************************************************* + * + * 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_filter.hxx" +#include <osl/endian.h> +#include <vcl/svapp.hxx> +#include <unotools/tempfile.hxx> +#include <math.h> +#include <editeng/eeitem.hxx> +#include <sot/storage.hxx> +#include <sot/storinfo.hxx> +#include <sot/stg.hxx> +#include <com/sun/star/embed/Aspects.hpp> +#include <com/sun/star/office/XAnnotation.hpp> +#include <com/sun/star/office/XAnnotationAccess.hpp> +#include <com/sun/star/text/XText.hpp> +#include <com/sun/star/geometry/RealPoint2D.hpp> +#include <com/sun/star/util/DateTime.hpp> +#include <unotools/streamwrap.hxx> +#include <filter/msfilter/svdfppt.hxx> +#include <svx/xpoly.hxx> +#include <svx/svdtrans.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdogrp.hxx> +#include <svx/svdorect.hxx> +#include <svx/svdopage.hxx> +#include <svx/svdograf.hxx> +#include <svx/svdopath.hxx> +#include <svx/svdocirc.hxx> +#include <svx/svdocapt.hxx> +#include <svx/svdotable.hxx> +#include <editeng/outlobj.hxx> +#include <svx/svdattr.hxx> +#include "svx/xattr.hxx" +#include "svx/svditext.hxx" +#include <svx/svdetc.hxx> +#include <editeng/bulitem.hxx> +#include <svx/polysc3d.hxx> +#include <svx/extrud3d.hxx> +#include <svx/svdoashp.hxx> +#include <editeng/tstpitem.hxx> +#include <editeng/unoprnms.hxx> +#include <editeng/editids.hrc> + +#if defined(JOEENV) && defined(JOEDEBUG) +#include "impinccv.h" // etwas Testkram +#endif + +#if defined(DBG_EXTRACTOLEOBJECTS) || defined(DBG_EXTRACTFONTMETRICS) +#include <tools/urlobj.hxx> +#include <unotools/localfilehelper.hxx> +#endif + +#define ITEMVALUE(ItemSet,Id,Cast) ((const Cast&)(ItemSet).Get(Id)).GetValue() +#include <editeng/adjitem.hxx> +#include <editeng/escpitem.hxx> +#include <editeng/colritem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/crsditem.hxx> +#include <editeng/shdditem.hxx> +#include <editeng/charreliefitem.hxx> +#include <editeng/fontitem.hxx> +#include <svx/svdoutl.hxx> +#include <editeng/editeng.hxx> +#include <editeng/lspcitem.hxx> +#include <editeng/ulspitem.hxx> +#include <editeng/lrspitem.hxx> +#include <vcl/metric.hxx> +#include <vcl/bmpacc.hxx> +#include <svx/svditer.hxx> +#include <svx/svdoedge.hxx> +#include <svx/sxekitm.hxx> +#include <editeng/flditem.hxx> +#include <svtools/sychconv.hxx> +#include <tools/zcodec.hxx> +#include <filter/msfilter/svxmsbas.hxx> +#include <sfx2/objsh.hxx> +#include <editeng/brshitem.hxx> +#include <editeng/langitem.hxx> +#include <svx/svdoole2.hxx> +#include <svx/unoapi.hxx> +#include <toolkit/unohlp.hxx> +#include <com/sun/star/container/XIndexContainer.hpp> +#include <com/sun/star/drawing/XShapes.hpp> +#include <com/sun/star/drawing/XControlShape.hpp> +#include <com/sun/star/form/XFormComponent.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/drawing/XMasterPagesSupplier.hpp> +#include <com/sun/star/drawing/XDrawPageSupplier.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/drawing/TextVerticalAdjust.hpp> +#include <editeng/writingmodeitem.hxx> +#include <vcl/print.hxx> +#include <editeng/svxfont.hxx> +#include <editeng/frmdiritem.hxx> +#include <svx/sdtfchim.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <editeng/scripttypeitem.hxx> +#include "com/sun/star/awt/Gradient.hpp" +#include <com/sun/star/table/XMergeableCellRange.hpp> +#include <com/sun/star/table/BorderLine.hpp> +#include <vcl/virdev.hxx> +#include <algorithm> +#include <set> + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +// PPT ColorScheme Slots +#define PPT_COLSCHEME (0x08000000) +#define PPT_COLSCHEME_HINTERGRUND (0x08000000) +#define PPT_COLSCHEME_TEXT_UND_ZEILEN (0x08000001) +#define PPT_COLSCHEME_SCHATTEN (0x08000002) +#define PPT_COLSCHEME_TITELTEXT (0x08000003) +#define PPT_COLSCHEME_FUELLBEREICHE (0x08000004) +#define PPT_COLSCHEME_AKZENT (0x08000005) +#define PPT_COLSCHEME_A_UND_HYPERLINK (0x08000006) +#define PPT_COLSCHEME_A_H_GESICHERT (0x08000007) + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#define ANSI_CHARSET 0 +#define DEFAULT_CHARSET 1 +#define SYMBOL_CHARSET 2 +#define SHIFTJIS_CHARSET 128 +#define HANGEUL_CHARSET 129 +#define CHINESEBIG5_CHARSET 136 +#define OEM_CHARSET 255 + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/* Font Families */ +#define FF_DONTCARE 0x00 +#define FF_ROMAN 0x10 +#define FF_SWISS 0x20 +#define FF_MODERN 0x30 +#define FF_SCRIPT 0x40 +#define FF_DECORATIVE 0x50 + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#define DEFAULT_PITCH 0x00 +#define FIXED_PITCH 0x01 +#define VARIABLE_PITCH 0x02 + +using namespace ::com::sun::star ; +using namespace uno ; +using namespace beans ; +using namespace drawing ; +using namespace container ; +using namespace table ; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +PowerPointImportParam::PowerPointImportParam( SvStream& rDocStrm, sal_uInt32 nFlags, MSFilterTracer* pT ) : + rDocStream ( rDocStrm ), + nImportFlags ( nFlags ), + pTracer ( pT ) +{ +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SvStream& operator>>( SvStream& rIn, PptCurrentUserAtom& rAtom ) +{ + DffRecordHeader aHd; + rIn >> aHd; + if ( aHd.nRecType == PPT_PST_CurrentUserAtom ) + { + sal_uInt32 nLen; + sal_uInt16 nUserNameLen, nPad; + rIn >> nLen + >> rAtom.nMagic + >> rAtom.nCurrentUserEdit + >> nUserNameLen + >> rAtom.nDocFileVersion + >> rAtom.nMajorVersion + >> rAtom.nMinorVersion + >> nPad; + SvxMSDffManager::MSDFFReadZString( rIn, rAtom.aCurrentUser, nUserNameLen, sal_True ); + } + aHd.SeekToEndOfRecord( rIn ); + return rIn; +} + +void PptSlidePersistAtom::Clear() +{ + nReserved = nPsrReference = nFlags = nNumberTexts = nSlideId = 0; +} + +SvStream& operator>>( SvStream& rIn, PptSlidePersistAtom& rAtom ) +{ + DffRecordHeader aHd; + rIn >> aHd + >> rAtom.nPsrReference + >> rAtom.nFlags + >> rAtom.nNumberTexts + >> rAtom.nSlideId; +// >> rAtom.nReserved; + aHd.SeekToEndOfRecord( rIn ); + return rIn; +} + +SV_IMPL_PTRARR(_PptSlidePersistList,PptSlidePersistEntry*); + +sal_uInt16 PptSlidePersistList::FindPage(sal_uInt32 nId) const +{ + for ( sal_uInt16 i=0; i < Count(); i++ ) + { + if (operator[](i)->GetSlideId()==nId) return i; + } + return PPTSLIDEPERSIST_ENTRY_NOTFOUND; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SvStream& operator>>( SvStream& rIn, PptInteractiveInfoAtom& rAtom ) +{ + rIn >> rAtom.nSoundRef + >> rAtom.nExHyperlinkId + >> rAtom.nAction + >> rAtom.nOleVerb + >> rAtom.nJump + >> rAtom.nFlags + >> rAtom.nHyperlinkType + >> rAtom.nUnknown1 + >> rAtom.nUnknown2 + >> rAtom.nUnknown3; + return rIn; +} + +SvStream& operator>>( SvStream& rIn, PptExOleObjAtom& rAtom ) +{ + rIn >> rAtom.nAspect + >> rAtom.nDummy1 + >> rAtom.nId + >> rAtom.nDummy2 + >> rAtom.nPersistPtr + >> rAtom.nDummy4; + return rIn; +} + +Size PptDocumentAtom::GetPageSize(const Size& rSiz) const +{ + return rSiz; +/* + Size aRet; + switch ( eSlidesPageFormat ) + { + // Wenn man in Powerpoint als Seitenformat "Bildschirmgroesse" + // einstellt, dann zeigt dieser Dialog zwar 24x18cm an, die + // angezeigte Seite ist aber anders. Das sieht man, wenn man + // ein Rechteck seitenfuellend aufzieht und sich dessen Groesse + // ansieht. Die importierten Abmessungen sind auf jeden Fall + // die, die auch im Ppt-File stehen. Ich denke, das es sich + // hier eher um ein Bug in PowerPoint handelt, das im + // Seitenformat-Dialog bei "Bildschirmgroesse" falsche Masse + // angezeigt werden (vielleicht ja auch bildschirmabhaengig?). +// case PPTPF_SCREEN : aRet.Width()=4082; aRet.Height()=5443; break; + case PPTPF_USLETTER: aRet.Width()=4896; aRet.Height()=6336; break; + case PPTPF_A4 : aRet.Width()=4762; aRet.Height()=6735; break; +// case PPTPF_35MMDIA : aRet.Width()=4082; aRet.Height()=6123; break; +// case PPTPF_OVERHEAD: aRet.Width()=4082; aRet.Height()=5443; break; + } + if ( aRet.Width() ) + { + if ( rSiz.Width() > rSiz.Height() ) + { // Querformat + long nMerk = aRet.Width(); + aRet.Width() = aRet.Height(); + aRet.Height() = nMerk; + } + } + else // CustomFormat oder Unbekannt oder Screen,Dia,Overhead + aRet = rSiz; + return aRet; +*/ +} + +SvStream& operator>>(SvStream& rIn, PptDocumentAtom& rAtom) +{ +// Tatsaechliches Format: +// 00 aSlidePageSizeXY 8 +// 08 aNotesPageSizeXY 8 +// 16 aZoomRatio (OLE) 8 +// 24 nNotesMasterPersist 4 +// 28 nHandoutMasterPersist 4 +// 32 n1stPageNumber 2 +// 34 ePageFormat 2 +// 36 bEmbeddedTrueType 1 +// 37 bOmitTitlePlace 1 +// 38 bRightToLeft 1 +// 39 bShowComments 1 + + DffRecordHeader aHd; + sal_Int32 nSlideX,nSlideY, nNoticeX, nNoticeY, nDummy; + sal_uInt16 nSlidePageFormat; + sal_Int8 nEmbeddedTrueType, nTitlePlaceHoldersOmitted, nRightToLeft, nShowComments; + + rIn >> aHd + >> nSlideX >> nSlideY + >> nNoticeX >> nNoticeY + >> nDummy >> nDummy // ZoomRation ueberspringen + >> rAtom.nNotesMasterPersist + >> rAtom.nHandoutMasterPersist + >> rAtom.n1stPageNumber + >> nSlidePageFormat + >> nEmbeddedTrueType + >> nTitlePlaceHoldersOmitted + >> nRightToLeft + >> nShowComments; + rAtom.aSlidesPageSize.Width() = nSlideX; + rAtom.aSlidesPageSize.Height() = nSlideY; + rAtom.aNotesPageSize.Width() = nNoticeX; + rAtom.aNotesPageSize.Height() = nNoticeY; + rAtom.eSlidesPageFormat = (PptPageFormat)nSlidePageFormat; + rAtom.bEmbeddedTrueType = nEmbeddedTrueType; + rAtom.bTitlePlaceholdersOmitted = nTitlePlaceHoldersOmitted; + rAtom.bRightToLeft = nRightToLeft; + rAtom.bShowComments = nShowComments; + aHd.SeekToEndOfRecord( rIn ); + return rIn; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void PptSlideLayoutAtom::Clear() +{ + eLayout = 0; + for ( sal_uInt16 i = 0; i < 8; i++ ) + { + aPlaceholderId[ i ] = 0; + aPlacementId[ i ] = 0; + } +} + +SvStream& operator>>( SvStream& rIn, PptSlideLayoutAtom& rAtom ) +{ + rIn >> rAtom.eLayout; + rIn.Read( rAtom.aPlaceholderId, 8 ); + return rIn; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SvStream& operator>>( SvStream& rIn, PptSlideAtom& rAtom ) +{ + DffRecordHeader aHd; + rIn >> aHd + >> rAtom.aLayout + >> rAtom.nMasterId + >> rAtom.nNotesId + >> rAtom.nFlags; + aHd.SeekToEndOfRecord( rIn ); + return rIn; +} + +void PptSlideAtom::Clear() +{ + nMasterId = nNotesId = 0; + nFlags = 0; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SvStream& operator>>( SvStream& rIn, PptNotesAtom& rAtom ) +{ + DffRecordHeader aHd; + rIn >> aHd + >> rAtom.nSlideId + >> rAtom.nFlags; + aHd.SeekToEndOfRecord( rIn ); + return rIn; +} + +void PptNotesAtom::Clear() +{ + nSlideId = 0; + nFlags = 0; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void PptColorSchemeAtom::Clear() +{ + memset(&aData[0], 0, 32); +} + +Color PptColorSchemeAtom::GetColor( sal_uInt16 nNum ) const +{ + Color aRetval; + if ( nNum < 8 ) + { + nNum <<= 2; + aRetval.SetRed( aData[ nNum++ ] ); + aRetval.SetGreen( aData[ nNum++ ] ); + aRetval.SetBlue( aData[ nNum++ ] ); + } + return aRetval; +} + +SvStream& operator>>( SvStream& rIn, PptColorSchemeAtom& rAtom ) +{ + DffRecordHeader aHd; + rIn >> aHd; + rIn.Read( rAtom.aData, 32 ); + aHd.SeekToEndOfRecord( rIn ); + return rIn; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SvStream& operator>>( SvStream& rIn, PptFontEntityAtom& rAtom ) +{ + DffRecordHeader aHd; + rIn >> aHd; + sal_Unicode nTemp, cData[ 32 ]; + rIn.Read( cData, 64 ); + + sal_uInt8 lfCharset, lfPitchAndFamily; + + rIn >> lfCharset + >> rAtom.lfClipPrecision + >> rAtom.lfQuality + >> lfPitchAndFamily; + + switch( lfCharset ) + { + case SYMBOL_CHARSET : + rAtom.eCharSet = RTL_TEXTENCODING_SYMBOL; + break; + case ANSI_CHARSET : + rAtom.eCharSet = RTL_TEXTENCODING_MS_1252; + break; + +// case DEFAULT_CHARSET : +// case SHIFTJIS_CHARSET : +// case HANGEUL_CHARSET : +// case CHINESEBIG5_CHARSET : +// case OEM_CHARSET : + default : + rAtom.eCharSet = gsl_getSystemTextEncoding(); + } + switch ( lfPitchAndFamily & 0xf0 ) + { + case FF_ROMAN: + rAtom.eFamily = FAMILY_ROMAN; + break; + + case FF_SWISS: + rAtom.eFamily = FAMILY_SWISS; + break; + + case FF_MODERN: + rAtom.eFamily = FAMILY_MODERN; + break; + + case FF_SCRIPT: + rAtom.eFamily = FAMILY_SCRIPT; + break; + + case FF_DECORATIVE: + rAtom.eFamily = FAMILY_DECORATIVE; + break; + + default: + rAtom.eFamily = FAMILY_DONTKNOW; + break; + } + + switch ( lfPitchAndFamily & 0x0f ) + { + case FIXED_PITCH: + rAtom.ePitch = PITCH_FIXED; + break; + + case DEFAULT_PITCH: + case VARIABLE_PITCH: + default: + rAtom.ePitch = PITCH_VARIABLE; + break; + } + sal_uInt16 i; + for ( i = 0; i < 32; i++ ) + { + nTemp = cData[ i ]; + if ( !nTemp ) + break; +#ifdef OSL_BIGENDIAN + cData[ i ] = ( nTemp >> 8 ) | ( nTemp << 8 ); +#endif + } + rAtom.aName = String( cData, i ); + OutputDevice* pDev = (OutputDevice*)Application::GetDefaultDevice(); + rAtom.bAvailable = pDev->IsFontAvailable( rAtom.aName ); + aHd.SeekToEndOfRecord( rIn ); + return rIn; +} + +SV_DECL_PTRARR_DEL( PptFontEntityAtomList, PptFontEntityAtom*, 16, 16 ) +SV_IMPL_PTRARR( PptFontEntityAtomList, PptFontEntityAtom* ); + +class PptFontCollection: public PptFontEntityAtomList { +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SvStream& operator>>( SvStream& rIn, PptUserEditAtom& rAtom ) +{ + rIn >> rAtom.aHd + >> rAtom.nLastSlideID + >> rAtom.nVersion + >> rAtom.nOffsetLastEdit + >> rAtom.nOffsetPersistDirectory + >> rAtom.nDocumentRef + >> rAtom.nMaxPersistWritten + >> rAtom.eLastViewType; + rAtom.aHd.SeekToEndOfRecord(rIn); + return rIn; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void PptOEPlaceholderAtom::Clear() +{ + nPlacementId = 0; + nPlaceholderSize = nPlaceholderId = 0; +} + +SvStream& operator>>( SvStream& rIn, PptOEPlaceholderAtom& rAtom ) +{ + rIn >> rAtom.nPlacementId + >> rAtom.nPlaceholderId + >> rAtom.nPlaceholderSize; + return rIn; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +PptSlidePersistEntry::PptSlidePersistEntry() : + pStyleSheet ( NULL ), + pHeaderFooterEntry ( NULL ), + pSolverContainer ( NULL ), + nSlidePersistStartOffset( 0 ), + nSlidePersistEndOffset ( 0 ), + nBackgroundOffset ( 0 ), + nDrawingDgId ( 0xffffffff ), + pPresentationObjects ( NULL ), + pBObj ( NULL ), + bBObjIsTemporary ( sal_True ), + ePageKind ( PPT_MASTERPAGE ), + bNotesMaster ( sal_False ), + bHandoutMaster ( sal_False ), + bStarDrawFiller ( sal_False ) +{ + HeaderFooterOfs[ 0 ] = HeaderFooterOfs[ 1 ] = HeaderFooterOfs[ 2 ] = HeaderFooterOfs[ 3 ] = 0; +} + + +PptSlidePersistEntry::~PptSlidePersistEntry() +{ + delete pStyleSheet; + delete pSolverContainer; + delete[] pPresentationObjects; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrEscherImport::SdrEscherImport( PowerPointImportParam& rParam, const String& rBaseURL ) : + SvxMSDffManager ( rParam.rDocStream, rBaseURL, rParam.pTracer ), + pFonts ( NULL ), + nStreamLen ( 0 ), + nTextStylesIndex ( 0xffff ), + eCharSetSystem ( gsl_getSystemTextEncoding() ), + bWingdingsChecked ( sal_False ), + bWingdingsAvailable ( sal_False ), + bMonotypeSortsChecked ( sal_False ), + bMonotypeSortsAvailable ( sal_False ), + bTimesNewRomanChecked ( sal_False ), + bTimesNewRomanAvailable ( sal_False ), + rImportParam ( rParam ) +{ +} + +SdrEscherImport::~SdrEscherImport() +{ + void* pPtr; + for ( pPtr = aOleObjectList.First(); pPtr; pPtr = aOleObjectList.Next() ) + delete (PPTOleEntry*)pPtr; + delete pFonts; +} + +const PptSlideLayoutAtom* SdrEscherImport::GetSlideLayoutAtom() const +{ + return NULL; +} + +sal_Bool SdrEscherImport::ReadString( String& rStr ) const +{ + sal_Bool bRet = sal_False; + DffRecordHeader aStrHd; + rStCtrl >> aStrHd; + if (aStrHd.nRecType == PPT_PST_TextBytesAtom + || aStrHd.nRecType == PPT_PST_TextCharsAtom + || aStrHd.nRecType == PPT_PST_CString) + { + sal_Bool bUniCode = + (aStrHd.nRecType == PPT_PST_TextCharsAtom + || aStrHd.nRecType == PPT_PST_CString); + bRet=sal_True; + sal_uLong nBytes = aStrHd.nRecLen; + MSDFFReadZString( rStCtrl, rStr, nBytes, bUniCode ); + aStrHd.SeekToEndOfRecord( rStCtrl ); + } + else + aStrHd.SeekToBegOfRecord( rStCtrl ); + return bRet; +} + +FASTBOOL SdrEscherImport::GetColorFromPalette(sal_uInt16 /*nNum*/, Color& /*rColor*/) const +{ + return sal_False; +} + +sal_Bool SdrEscherImport::SeekToShape( SvStream& /*rSt*/, void* /*pClientData*/, sal_uInt32 /*nId*/) const +{ + return sal_False; +} + +PptFontEntityAtom* SdrEscherImport::GetFontEnityAtom( sal_uInt32 nNum ) const +{ + PptFontEntityAtom* pRetValue = NULL; + if ( pFonts && ( nNum < pFonts->Count() ) ) + pRetValue = (*pFonts)[ (sal_uInt16)nNum ]; + return pRetValue; +} + +CharSet SdrEscherImport::GetCharSet( sal_uInt32 nNum ) const +{ + CharSet eRetValue( eCharSetSystem ); + if ( pFonts && ( nNum < pFonts->Count() ) ) + eRetValue = (*pFonts)[ (sal_uInt16)nNum ]->eCharSet; + return eRetValue; +} + +sal_Bool SdrEscherImport::IsFontAvailable( sal_uInt32 nNum ) const +{ + sal_Bool bRetValue = sal_False; + if ( pFonts && ( nNum < pFonts->Count() ) ) + bRetValue = (*pFonts)[ (sal_uInt16)nNum ]->bAvailable; + return bRetValue; +} + +SdrObject* SdrEscherImport::ReadObjText( PPTTextObj* /*pTextObj*/, SdrObject* pObj, SdPage* /*pPage*/) const +{ + return pObj; +} + +void SdrEscherImport::ProcessClientAnchor2( SvStream& rSt, DffRecordHeader& rHd, void* /*pData*/, DffObjData& rObj ) +{ + sal_Int32 l, t, r, b; + if ( rHd.nRecLen == 16 ) + { + rSt >> l >> t >> r >> b; + } + else + { + sal_Int16 ls, ts, rs, bs; + rSt >> ts >> ls >> rs >> bs; // etwas seltsame Koordinatenreihenfolge ... + l = ls, t = ts, r = rs, b = bs; + } + Scale( l ); + Scale( t ); + Scale( r ); + Scale( b ); + rObj.aChildAnchor = Rectangle( l, t, r, b ); + rObj.bChildAnchor = sal_True; + return; +}; + +void SdrEscherImport::RecolorGraphic( SvStream& rSt, sal_uInt32 nRecLen, Graphic& rGraphic ) +{ + if ( rGraphic.GetType() == GRAPHIC_GDIMETAFILE ) + { + sal_uInt16 nX, nGlobalColorsCount, nFillColorsCount; + + rSt >> nX + >> nGlobalColorsCount + >> nFillColorsCount + >> nX + >> nX + >> nX; + + if ( ( nGlobalColorsCount <= 64 ) && ( nFillColorsCount <= 64 ) ) + { + if ( (sal_uInt32)( ( nGlobalColorsCount + nFillColorsCount ) * 44 + 12 ) == nRecLen ) + { + sal_uInt32 OriginalGlobalColors[ 64 ]; + sal_uInt32 NewGlobalColors[ 64 ]; + sal_uInt32 OriginalFillColors[ 64 ]; + sal_uInt32 NewFillColors[ 64 ]; + + sal_uInt32 i, j, nGlobalColorsChanged, nFillColorsChanged; + nGlobalColorsChanged = nFillColorsChanged = 0; + + sal_uInt32* pCurrentOriginal = OriginalGlobalColors; + sal_uInt32* pCurrentNew = NewGlobalColors; + sal_uInt32* pCount = &nGlobalColorsChanged; + i = nGlobalColorsCount; + + for ( j = 0; j < 2; j++ ) + { + for ( ; i > 0; i-- ) + { + sal_uInt32 nIndex, nPos = rSt.Tell(); + sal_uInt8 nDummy, nRed, nGreen, nBlue; + sal_uInt16 nChanged; + rSt >> nChanged; + if ( nChanged & 1 ) + { + sal_uInt32 nColor = 0; + rSt >> nDummy + >> nRed + >> nDummy + >> nGreen + >> nDummy + >> nBlue + >> nIndex; + + if ( nIndex < 8 ) + { + Color aColor = MSO_CLR_ToColor( nIndex << 24 ); + nRed = aColor.GetRed(); + nGreen = aColor.GetGreen(); + nBlue = aColor.GetBlue(); + } + nColor = nRed | ( nGreen << 8 ) | ( nBlue << 16 ); + *pCurrentNew++ = nColor; + rSt >> nDummy + >> nRed + >> nDummy + >> nGreen + >> nDummy + >> nBlue; + nColor = nRed | ( nGreen << 8 ) | ( nBlue << 16 ); + *pCurrentOriginal++ = nColor; + (*pCount)++; + } + rSt.Seek( nPos + 44 ); + } + pCurrentOriginal = OriginalFillColors; + pCurrentNew = NewFillColors; + pCount = &nFillColorsChanged; + i = nFillColorsCount; + } + if ( nGlobalColorsChanged || nFillColorsChanged ) + { + Color* pSearchColors = new Color[ nGlobalColorsChanged ]; + Color* pReplaceColors = new Color[ nGlobalColorsChanged ]; + + for ( j = 0; j < nGlobalColorsChanged; j++ ) + { + sal_uInt32 nSearch = OriginalGlobalColors[ j ]; + sal_uInt32 nReplace = NewGlobalColors[ j ]; + + pSearchColors[ j ].SetRed( (sal_uInt8)nSearch ); + pSearchColors[ j ].SetGreen( (sal_uInt8)( nSearch >> 8 ) ); + pSearchColors[ j ].SetBlue( (sal_uInt8)( nSearch >> 16 ) ); + + pReplaceColors[ j ].SetRed( (sal_uInt8)nReplace ); + pReplaceColors[ j ].SetGreen( (sal_uInt8)( nReplace >> 8 ) ); + pReplaceColors[ j ].SetBlue( (sal_uInt8)( nReplace >> 16 ) ); + } + GDIMetaFile aGdiMetaFile( rGraphic.GetGDIMetaFile() ); + aGdiMetaFile.ReplaceColors( pSearchColors, pReplaceColors, + nGlobalColorsChanged, NULL ); + rGraphic = aGdiMetaFile; + + delete[] pSearchColors; + delete[] pReplaceColors; + } + } + } + } +} + +/* ProcessObject is called from ImplSdPPTImport::ProcessObj to hanlde all application specific things, + such as the import of text, animation effects, header footer and placeholder. + + The parameter pOriginalObj is the object as it was imported by our general escher import, it must either + be deleted or it can be returned to be inserted into the sdr page. +*/ +SdrObject* SdrEscherImport::ProcessObj( SvStream& rSt, DffObjData& rObjData, void* pData, Rectangle& rTextRect, SdrObject* pOriginalObj ) +{ + if ( pOriginalObj && pOriginalObj->ISA( SdrObjCustomShape ) ) + pOriginalObj->SetMergedItem( SdrTextFixedCellHeightItem( sal_True ) ); + + // we are initializing our return value with the object that was imported by our escher import + SdrObject* pRet = pOriginalObj; + + ProcessData& rData = *((ProcessData*)pData); + PptSlidePersistEntry& rPersistEntry = rData.rPersistEntry; + + if ( ! ( rObjData.nSpFlags & SP_FGROUP ) ) // sj: #114758# ... + { + PptOEPlaceholderAtom aPlaceholderAtom; + sal_Int16 nHeaderFooterInstance = -1; + + if ( maShapeRecords.SeekToContent( rSt, DFF_msofbtClientData, SEEK_FROM_CURRENT_AND_RESTART ) ) + { + DffRecordHeader aClientDataHd; + while ( ( rSt.GetError() == 0 ) && ( rSt.Tell() < maShapeRecords.Current()->GetRecEndFilePos() ) ) + { + rSt >> aClientDataHd; + switch ( aClientDataHd.nRecType ) + { + // importing header/footer object from master page + case PPT_PST_OEPlaceholderAtom : + { + rSt >> aPlaceholderAtom; + if ( nHeaderFooterInstance == -1 ) + { + switch ( aPlaceholderAtom.nPlaceholderId ) + { + case PPT_PLACEHOLDER_MASTERSLIDENUMBER : nHeaderFooterInstance++; + case PPT_PLACEHOLDER_MASTERFOOTER : nHeaderFooterInstance++; + case PPT_PLACEHOLDER_MASTERHEADER : nHeaderFooterInstance++; + case PPT_PLACEHOLDER_MASTERDATE : nHeaderFooterInstance++; break; + } + if ( ! ( nHeaderFooterInstance & 0xfffc ) ) // is this a valid instance ( 0->3 ) + rPersistEntry.HeaderFooterOfs[ nHeaderFooterInstance ] = rObjData.rSpHd.GetRecBegFilePos(); + } + } + break; + + case PPT_PST_RecolorInfoAtom : + { + if ( pRet && ( pRet->ISA( SdrGrafObj ) && ((SdrGrafObj*)pRet)->HasGDIMetaFile() ) ) + { + Graphic aGraphic( ((SdrGrafObj*)pRet)->GetGraphic() ); + RecolorGraphic( rSt, aClientDataHd.nRecLen, aGraphic ); + ((SdrGrafObj*)pRet)->SetGraphic( aGraphic ); + } + } + break; + } + aClientDataHd.SeekToEndOfRecord( rSt ); + } + } + if ( ( aPlaceholderAtom.nPlaceholderId == PPT_PLACEHOLDER_NOTESSLIDEIMAGE ) && ( rPersistEntry.bNotesMaster == sal_False ) ) + { + sal_uInt16 nPageNum = pSdrModel->GetPageCount(); + if ( nPageNum > 0 ) + nPageNum--; + + // replacing the object which we will return with a SdrPageObj + SdrObject::Free( pRet ); + pRet = new SdrPageObj( rObjData.aBoundRect, pSdrModel->GetPage( nPageNum - 1 ) ); + } + else + { + // try to load some ppt text + PPTTextObj aTextObj( rSt, (SdrPowerPointImport&)*this, rPersistEntry, &rObjData ); + if ( ( aTextObj.Count() || aTextObj.GetOEPlaceHolderAtom() ) ) + { + sal_Bool bVerticalText = sal_False; + // and if the text object is not empty, it must be applied to pRet, the object we + // initially got from our escher import + sal_Int32 nTextRotationAngle = 0; + if ( IsProperty( DFF_Prop_txflTextFlow ) ) + { + MSO_TextFlow eTextFlow = (MSO_TextFlow)( GetPropertyValue( DFF_Prop_txflTextFlow ) & 0xFFFF ); + switch( eTextFlow ) + { + case mso_txflBtoT : // Bottom to Top non-@, unten -> oben + nTextRotationAngle += 9000; + break; + case mso_txflTtoBA : /* #68110# */ // Top to Bottom @-font, oben -> unten + case mso_txflTtoBN : // Top to Bottom non-@, oben -> unten + case mso_txflVertN : // Vertical, non-@, oben -> unten + bVerticalText = !bVerticalText; // nTextRotationAngle += 27000; + break; + // case mso_txflHorzN : // Horizontal non-@, normal + // case mso_txflHorzA : // Horizontal @-font, normal + default: break; + } + } + sal_Int32 nFontDirection = GetPropertyValue( DFF_Prop_cdirFont, mso_cdir0 ); + nTextRotationAngle -= nFontDirection * 9000; + if ( ( nFontDirection == 1 ) || ( nFontDirection == 3 ) ) // #104546# + { + bVerticalText = !bVerticalText; +/* + sal_Int32 nHalfWidth = ( rTextRect.GetWidth() + 1 ) >> 1; + sal_Int32 nHalfHeight = ( rTextRect.GetHeight() + 1 ) >> 1; + Point aTopLeft( rTextRect.Left() + nHalfWidth - nHalfHeight, + rTextRect.Top() + nHalfHeight - nHalfWidth ); + Size aNewSize( rTextRect.GetHeight(), rTextRect.GetWidth() ); + Rectangle aNewRect( aTopLeft, aNewSize ); + rTextRect = aNewRect; +*/ + } + aTextObj.SetVertical( bVerticalText ); + if ( pRet ) + { + sal_Bool bDeleteSource = aTextObj.GetOEPlaceHolderAtom() != 0; + if ( bDeleteSource && ( pRet->ISA( SdrGrafObj ) == sal_False ) // we are not allowed to get + && ( pRet->ISA( SdrObjGroup ) == sal_False ) // grouped placeholder objects + && ( pRet->ISA( SdrOle2Obj ) == sal_False ) ) + SdrObject::Free( pRet ); + } + sal_uInt32 nTextFlags = aTextObj.GetTextFlags(); + sal_Int32 nTextLeft = GetPropertyValue( DFF_Prop_dxTextLeft, 25 * 3600 ); // 0.25 cm (emu) + sal_Int32 nTextRight = GetPropertyValue( DFF_Prop_dxTextRight, 25 * 3600 ); // 0.25 cm (emu) + sal_Int32 nTextTop = GetPropertyValue( DFF_Prop_dyTextTop, 13 * 3600 ); // 0.13 cm (emu) + sal_Int32 nTextBottom = GetPropertyValue( DFF_Prop_dyTextBottom, 13 * 3600 ); + ScaleEmu( nTextLeft ); + ScaleEmu( nTextRight ); + ScaleEmu( nTextTop ); + ScaleEmu( nTextBottom ); + + sal_Int32 nMinFrameWidth = 0; + sal_Int32 nMinFrameHeight = 0; + sal_Bool bAutoGrowWidth, bAutoGrowHeight; + + SdrTextVertAdjust eTVA; + SdrTextHorzAdjust eTHA; + + nTextFlags &= PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT + | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK; + + if ( bVerticalText ) + { + eTVA = SDRTEXTVERTADJUST_BLOCK; + eTHA = SDRTEXTHORZADJUST_CENTER; + + // Textverankerung lesen + MSO_Anchor eTextAnchor = (MSO_Anchor)GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop ); + + switch( eTextAnchor ) + { + case mso_anchorTop: + case mso_anchorTopCentered: + case mso_anchorTopBaseline: + case mso_anchorTopCenteredBaseline: + eTHA = SDRTEXTHORZADJUST_RIGHT; + break; + + case mso_anchorMiddle : + case mso_anchorMiddleCentered: + eTHA = SDRTEXTHORZADJUST_CENTER; + break; + + case mso_anchorBottom: + case mso_anchorBottomCentered: + case mso_anchorBottomBaseline: + case mso_anchorBottomCenteredBaseline: + eTHA = SDRTEXTHORZADJUST_LEFT; + break; + } + // if there is a 100% use of following attributes, the textbox can been aligned also in vertical direction + switch ( eTextAnchor ) + { + case mso_anchorTopCentered : + case mso_anchorMiddleCentered : + case mso_anchorBottomCentered : + case mso_anchorTopCenteredBaseline: + case mso_anchorBottomCenteredBaseline: + { + // check if it is sensible to use the centered alignment + sal_uInt32 nMask = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT; + if ( ( nTextFlags & nMask ) != nMask ) // if the textobject has left and also right aligned pararagraphs + eTVA = SDRTEXTVERTADJUST_CENTER; // the text has to be displayed using the full width; + } + break; + + default : + { + if ( nTextFlags == PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT ) + eTVA = SDRTEXTVERTADJUST_TOP; + else if ( nTextFlags == PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT ) + eTVA = SDRTEXTVERTADJUST_BOTTOM; + } + break; + } + nMinFrameWidth = rTextRect.GetWidth() - ( nTextLeft + nTextRight ); + } + else + { + eTVA = SDRTEXTVERTADJUST_CENTER; + eTHA = SDRTEXTHORZADJUST_BLOCK; + + // Textverankerung lesen + MSO_Anchor eTextAnchor = (MSO_Anchor)GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop ); + + switch( eTextAnchor ) + { + case mso_anchorTop: + case mso_anchorTopCentered: + case mso_anchorTopBaseline: + case mso_anchorTopCenteredBaseline: + eTVA = SDRTEXTVERTADJUST_TOP; + break; + + case mso_anchorMiddle : + case mso_anchorMiddleCentered: + eTVA = SDRTEXTVERTADJUST_CENTER; + break; + + case mso_anchorBottom: + case mso_anchorBottomCentered: + case mso_anchorBottomBaseline: + case mso_anchorBottomCenteredBaseline: + eTVA = SDRTEXTVERTADJUST_BOTTOM; + break; + } + // if there is a 100% usage of following attributes, the textbox can be aligned also in horizontal direction + switch ( eTextAnchor ) + { + case mso_anchorTopCentered : + case mso_anchorMiddleCentered : + case mso_anchorBottomCentered : + case mso_anchorTopCenteredBaseline: + case mso_anchorBottomCenteredBaseline: + { + // check if it is sensible to use the centered alignment + sal_uInt32 nMask = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT; + if ( ( nTextFlags & nMask ) != nMask ) // if the textobject has left and also right aligned pararagraphs + eTHA = SDRTEXTHORZADJUST_CENTER; // the text has to be displayed using the full width; + } + break; + + default : + break; + } + nMinFrameHeight = rTextRect.GetHeight() - ( nTextTop + nTextBottom ); + } + + SdrObjKind eTextKind = OBJ_RECT; + if ( ( aPlaceholderAtom.nPlaceholderId == PPT_PLACEHOLDER_NOTESSLIDEIMAGE ) + || ( aPlaceholderAtom.nPlaceholderId == PPT_PLACEHOLDER_MASTERNOTESSLIDEIMAGE ) ) + { + aTextObj.SetInstance( 2 ); + eTextKind = OBJ_TITLETEXT; + } + else if ( ( aPlaceholderAtom.nPlaceholderId == PPT_PLACEHOLDER_MASTERNOTESBODYIMAGE ) + || ( aPlaceholderAtom.nPlaceholderId == PPT_PLACEHOLDER_NOTESBODY ) ) + { + aTextObj.SetInstance( 2 ); + eTextKind = OBJ_TEXT; + } + + sal_uInt32 nDestinationInstance = aTextObj.GetInstance(); + if ( ( rPersistEntry.ePageKind == PPT_MASTERPAGE ) ) + { + if ( !rPersistEntry.pPresentationObjects ) + { + rPersistEntry.pPresentationObjects = new sal_uInt32[ PPT_STYLESHEETENTRYS ]; + memset( rPersistEntry.pPresentationObjects, 0, PPT_STYLESHEETENTRYS * 4 ); + } + if ( !rPersistEntry.pPresentationObjects[ nDestinationInstance ] ) + rPersistEntry.pPresentationObjects[ nDestinationInstance ] = rObjData.rSpHd.GetRecBegFilePos(); + } + switch ( nDestinationInstance ) + { + case TSS_TYPE_PAGETITLE : + case TSS_TYPE_TITLE : + { + if ( GetSlideLayoutAtom()->eLayout == PPT_LAYOUT_TITLEMASTERSLIDE ) + nDestinationInstance = TSS_TYPE_TITLE; + else + nDestinationInstance = TSS_TYPE_PAGETITLE; + } + break; + case TSS_TYPE_BODY : + // case TSS_TYPE_SUBTITLE : + case TSS_TYPE_HALFBODY : + case TSS_TYPE_QUARTERBODY : + nDestinationInstance = TSS_TYPE_BODY; + break; + } + aTextObj.SetDestinationInstance( (sal_uInt16)nDestinationInstance ); + + switch ( aTextObj.GetInstance() ) + { + case TSS_TYPE_PAGETITLE : + case TSS_TYPE_TITLE : eTextKind = OBJ_TITLETEXT; break; + case TSS_TYPE_SUBTITLE : eTextKind = OBJ_TEXT; break; + case TSS_TYPE_BODY : + case TSS_TYPE_HALFBODY : + case TSS_TYPE_QUARTERBODY : eTextKind = OBJ_OUTLINETEXT; break; + } + if ( aTextObj.GetDestinationInstance() != TSS_TYPE_TEXT_IN_SHAPE ) + { + if ( !aTextObj.GetOEPlaceHolderAtom() || !aTextObj.GetOEPlaceHolderAtom()->nPlaceholderId ) + { + aTextObj.SetDestinationInstance( TSS_TYPE_TEXT_IN_SHAPE ); + eTextKind = OBJ_RECT; + } + } + SdrObject* pTObj = NULL; + sal_Bool bWordWrap = (MSO_WrapMode)GetPropertyValue( DFF_Prop_WrapText, mso_wrapSquare ) != mso_wrapNone; + sal_Bool bFitShapeToText = ( GetPropertyValue( DFF_Prop_FitTextToShape ) & 2 ) != 0; + + if ( pRet && pRet->ISA( SdrObjCustomShape ) && ( eTextKind == OBJ_RECT ) ) + { + bAutoGrowHeight = bFitShapeToText; + if ( bWordWrap ) + bAutoGrowWidth = sal_False; + else + bAutoGrowWidth = sal_True; + pTObj = pRet; + pRet = NULL; + } + else + { + if ( pRet && pRet->ISA( SdrObjCustomShape ) ) + { + SdrObject::Free( pRet ); + pRet = NULL; + } + pTObj = new SdrRectObj( eTextKind != OBJ_RECT ? eTextKind : OBJ_TEXT ); + pTObj->SetModel( pSdrModel ); + SfxItemSet aSet( pSdrModel->GetItemPool() ); + if ( !pRet ) + ((SdrEscherImport*)this)->ApplyAttributes( rSt, aSet, rObjData ); + pTObj->SetMergedItemSet( aSet ); + if ( pRet ) + { + pTObj->SetMergedItem( XLineStyleItem( XLINE_NONE ) ); + pTObj->SetMergedItem( XFillStyleItem( XFILL_NONE ) ); + } + if ( bVerticalText ) + { + bAutoGrowWidth = bFitShapeToText; // bFitShapeToText; can't be used, because we cut the text if it is too height, + bAutoGrowHeight = sal_False; + } + else + { + bAutoGrowWidth = sal_False; + bAutoGrowHeight = sal_True; // bFitShapeToText; can't be used, because we cut the text if it is too height, + } + } + pTObj->SetMergedItem( SvxFrameDirectionItem( bVerticalText ? FRMDIR_VERT_TOP_RIGHT : FRMDIR_HORI_LEFT_TOP, EE_PARA_WRITINGDIR ) ); + + if ( !pTObj->ISA( SdrObjCustomShape ) ) + { + pTObj->SetMergedItem( SdrTextAutoGrowWidthItem( bAutoGrowWidth ) ); + pTObj->SetMergedItem( SdrTextAutoGrowHeightItem( bAutoGrowHeight ) ); + } + else + { + pTObj->SetMergedItem( SdrTextWordWrapItem( bWordWrap ) ); + pTObj->SetMergedItem( SdrTextAutoGrowHeightItem( bFitShapeToText ) ); + } + + pTObj->SetMergedItem( SdrTextVertAdjustItem( eTVA ) ); + pTObj->SetMergedItem( SdrTextHorzAdjustItem( eTHA ) ); + + if ( nMinFrameHeight < 0 ) + nMinFrameHeight = 0; + if ( !pTObj->ISA( SdrObjCustomShape ) ) + pTObj->SetMergedItem( SdrTextMinFrameHeightItem( nMinFrameHeight ) ); + + if ( nMinFrameWidth < 0 ) + nMinFrameWidth = 0; + if ( !pTObj->ISA( SdrObjCustomShape ) ) + pTObj->SetMergedItem( SdrTextMinFrameWidthItem( nMinFrameWidth ) ); + + // Abstaende an den Raendern der Textbox setzen + pTObj->SetMergedItem( SdrTextLeftDistItem( nTextLeft ) ); + pTObj->SetMergedItem( SdrTextRightDistItem( nTextRight ) ); + pTObj->SetMergedItem( SdrTextUpperDistItem( nTextTop ) ); + pTObj->SetMergedItem( SdrTextLowerDistItem( nTextBottom ) ); + pTObj->SetMergedItem( SdrTextFixedCellHeightItem( sal_True ) ); + + if ( !pTObj->ISA( SdrObjCustomShape ) ) + pTObj->SetSnapRect( rTextRect ); + pTObj = ReadObjText( &aTextObj, pTObj, rData.pPage ); + if ( pTObj ) + { + /* check if our new snaprect makes trouble, + because we do not display the ADJUST_BLOCK + properly if the textsize is bigger than the + snaprect of the object. Then we will use + ADJUST_CENTER instead of ADJUST_BLOCK. + */ + if ( !pTObj->ISA( SdrObjCustomShape ) && !bFitShapeToText && !bWordWrap ) + { + SdrTextObj* pText = PTR_CAST( SdrTextObj, pTObj ); + if ( pText ) + { + if ( bVerticalText ) + { + if ( eTVA == SDRTEXTVERTADJUST_BLOCK ) + { + Size aTextSize( pText->GetTextSize() ); + aTextSize.Width() += nTextLeft + nTextRight; + aTextSize.Height() += nTextTop + nTextBottom; + if ( rTextRect.GetHeight() < aTextSize.Height() ) + pTObj->SetMergedItem( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_CENTER ) ); + } + } + else + { + if ( eTHA == SDRTEXTHORZADJUST_BLOCK ) + { + Size aTextSize( pText->GetTextSize() ); + aTextSize.Width() += nTextLeft + nTextRight; + aTextSize.Height() += nTextTop + nTextBottom; + if ( rTextRect.GetWidth() < aTextSize.Width() ) + pTObj->SetMergedItem( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_CENTER ) ); + } + } + } + } + // rotate text with shape ? + sal_Int32 nAngle = ( rObjData.nSpFlags & SP_FFLIPV ) ? -mnFix16Angle : mnFix16Angle; // #72116# vertical flip -> rotate by using the other way + nAngle += nTextRotationAngle; + + if ( pTObj->ISA( SdrObjCustomShape ) ) + { +/* + if ( nTextRotationAngle ) + { + double fTextRotateAngle = (double)nTextRotationAngle / 100.0; + SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)((SdrObjCustomShape*)pTObj)->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + const rtl::OUString sTextRotateAngle( RTL_CONSTASCII_USTRINGPARAM ( "TextRotateAngle" ) ); + PropertyValue aPropValue; + aPropValue.Name = sTextRotateAngle; + aPropValue.Value <<= fTextRotateAngle; + aGeometryItem.SetPropertyValue( aPropValue ); + ((SdrObjCustomShape*)pTObj)->SetMergedItem( aGeometryItem ); + } +*/ + } + else + { + if ( rObjData.nSpFlags & SP_FFLIPV ) + { + double a = 18000 * nPi180; + pTObj->Rotate( rTextRect.Center(), 18000, sin( a ), cos( a ) ); + } + if ( rObjData.nSpFlags & SP_FFLIPH ) + nAngle = 36000 - nAngle; + if ( nAngle ) + { + double a = nAngle * nPi180; + pTObj->NbcRotate( rObjData.aBoundRect.Center(), nAngle, sin( a ), cos( a ) ); + } + } + if ( pRet ) + { + SdrObject* pGroup = new SdrObjGroup; + pGroup->GetSubList()->NbcInsertObject( pRet ); + pGroup->GetSubList()->NbcInsertObject( pTObj ); + pRet = pGroup; + } + else + pRet = pTObj; + } + } + } + } + else + { + if ( maShapeRecords.SeekToContent( rSt, DFF_msofbtUDefProp, SEEK_FROM_CURRENT_AND_RESTART ) ) + { + maShapeRecords.Current()->SeekToBegOfRecord( rSt ); + DffPropertyReader aSecPropSet( *this ); + aSecPropSet.ReadPropSet( rSt, (ProcessData*)pData ); + sal_Int32 nTableProperties = aSecPropSet.GetPropertyValue( DFF_Prop_tableProperties, 0 ); + if ( nTableProperties & 3 ) + { + if ( aSecPropSet.SeekToContent( DFF_Prop_tableRowProperties, rSt ) ) + { + sal_Int16 i, nRowCount = 0; + rSt >> nRowCount >> i >> i; + if ( nRowCount ) + { + sal_uInt32* pTableArry = new sal_uInt32[ nRowCount + 2 ]; + pTableArry[ 0 ] = nTableProperties; + pTableArry[ 1 ] = nRowCount; + for ( i = 0; i < nRowCount; i++ ) + rSt >> pTableArry[ i + 2 ]; + rData.pTableRowProperties = pTableArry; + } + } + } + } + } + if ( pRet ) // sj: #i38501#, and and taking care of connections to group objects + { + if ( rObjData.nSpFlags & SP_FBACKGROUND ) + { + pRet->NbcSetSnapRect( Rectangle( Point(), ((SdrPage*)rData.pPage)->GetSize() ) ); // Groesse setzen + } + if ( rPersistEntry.pSolverContainer ) + { + for ( SvxMSDffConnectorRule* pPtr = (SvxMSDffConnectorRule*)rPersistEntry.pSolverContainer->aCList.First(); + pPtr; pPtr = (SvxMSDffConnectorRule*)rPersistEntry.pSolverContainer->aCList.Next() ) + { + if ( rObjData.nShapeId == pPtr->nShapeC ) + pPtr->pCObj = pRet; + else + { + SdrObject* pConnectObj = pRet; + if ( pOriginalObj && pRet->ISA( SdrObjGroup ) ) + { /* check if the original object from the escherimport is part of the group object, + if this is the case, we will use the original object to connect to */ + SdrObjListIter aIter( *pRet, IM_DEEPWITHGROUPS ); + while( aIter.IsMore() ) + { + SdrObject* pPartObj = aIter.Next(); + if ( pPartObj == pOriginalObj ) + { + pConnectObj = pPartObj; + break; + } + } + } + if ( rObjData.nShapeId == pPtr->nShapeA ) + { + pPtr->pAObj = pConnectObj; + pPtr->nSpFlagsA = rObjData.nSpFlags; + } + if ( rObjData.nShapeId == pPtr->nShapeB ) + { + pPtr->pBObj = pConnectObj; + pPtr->nSpFlagsB = rObjData.nSpFlags; + } + } + } + } + if ( rPersistEntry.ePageKind == PPT_MASTERPAGE ) + { // maybe the escher clusterlist is not correct, but we have to got the right page by using the + // spMaster property, so we are patching the table + if ( rPersistEntry.nDrawingDgId != 0xffffffff ) + { + sal_uInt32 nSec = ( rObjData.nShapeId >> 10 ) - 1; + if ( mpFidcls && ( nSec < mnIdClusters ) ) + mpFidcls[ nSec ].dgid = rPersistEntry.nDrawingDgId; // insert the correct drawing id; + } + } + if ( GetPropertyValue( DFF_Prop_fNoFillHitTest ) & 0x10 ) + { + if ( (MSO_FillType)GetPropertyValue( DFF_Prop_fillType, mso_fillSolid ) == mso_fillBackground ) + { + if ( !rData.pBackgroundColoredObjects ) + rData.pBackgroundColoredObjects = new List; + rData.pBackgroundColoredObjects->Insert( pRet, LIST_APPEND ); + } + } + } + return pRet; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void SdrEscherImport::CheckWingdings() const +{ + OutputDevice* pDev = (OutputDevice*)Application::GetDefaultDevice(); + ((SdrEscherImport*)this)->bWingdingsAvailable = pDev->IsFontAvailable( String( RTL_CONSTASCII_USTRINGPARAM( "WINGDINGS" ) ) ); + ((SdrEscherImport*)this)->bWingdingsChecked = sal_True; +} + +void SdrEscherImport::CheckMonotypeSorts() const +{ + OutputDevice* pDev = (OutputDevice*)Application::GetDefaultDevice(); + ((SdrEscherImport*)this)->bMonotypeSortsAvailable = pDev->IsFontAvailable( String( RTL_CONSTASCII_USTRINGPARAM( "MONOTYPE SORTS" ) ) ); + ((SdrEscherImport*)this)->bMonotypeSortsChecked = sal_True; +} + +void SdrEscherImport::CheckTimesNewRoman() const +{ + OutputDevice* pDev = (OutputDevice*)Application::GetDefaultDevice(); + ((SdrEscherImport*)this)->bTimesNewRomanAvailable = pDev->IsFontAvailable( String( RTL_CONSTASCII_USTRINGPARAM( "TIMES NEW ROMAN" ) ) ); + ((SdrEscherImport*)this)->bTimesNewRomanChecked = sal_True; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +SdrPowerPointImport::SdrPowerPointImport( PowerPointImportParam& rParam, const String& rBaseURL ) : + SdrEscherImport ( rParam, rBaseURL ), + bOk ( rStCtrl.GetErrorCode() == SVSTREAM_OK ), + pPersistPtr ( NULL ), + nPersistPtrAnz ( 0 ), + pDefaultSheet ( NULL ), + pMasterPages ( NULL ), + pSlidePages ( NULL ), + pNotePages ( NULL ), + nAktPageNum ( 0 ), + nDocStreamPos ( 0 ), + nPageColorsNum ( 0xFFFF ), + ePageColorsKind ( PPT_MASTERPAGE ), + eAktPageKind ( PPT_MASTERPAGE ) +{ + DffRecordHeader* pHd; + if ( bOk ) + { + rStCtrl.Seek( STREAM_SEEK_TO_END ); + nStreamLen = rStCtrl.Tell(); + + // try to allocate the UserEditAtom via CurrentUserAtom + sal_uInt32 nCurrentUserEdit = rParam.aCurrentUserAtom.nCurrentUserEdit; + if ( nCurrentUserEdit ) + { + rStCtrl.Seek( nCurrentUserEdit ); + rStCtrl >> aUserEditAtom; + } + if ( !aUserEditAtom.nOffsetPersistDirectory ) + { // if there is no UserEditAtom try to search the last one + + rStCtrl.Seek( 0 ); + DffRecordManager aPptRecManager; // contains all first level container and atoms + aPptRecManager.Consume( rStCtrl, sal_False, nStreamLen ); + for ( pHd = aPptRecManager.Last(); pHd; pHd = aPptRecManager.Prev() ) + { + if ( pHd->nRecType == PPT_PST_UserEditAtom ) + { + pHd->SeekToBegOfRecord( rStCtrl ); + rStCtrl >> aUserEditAtom; + break; + } + } + if ( !pHd ) + bOk = sal_False; + } + } + if ( rStCtrl.GetError() != 0 ) + bOk = sal_False; + + if ( bOk ) + { + nPersistPtrAnz = aUserEditAtom.nMaxPersistWritten + 1; + if ( ( nPersistPtrAnz >> 2 ) > nStreamLen ) // sj: at least nPersistPtrAnz is not allowed to be greater than filesize + bOk = sal_False; // (it should not be greater than the PPT_PST_PersistPtrIncrementalBlock, but + // we are reading this block later, so we do not have access yet) + + if ( bOk && ( nPersistPtrAnz < ( SAL_MAX_UINT32 / sizeof( sal_uInt32 ) ) ) ) + pPersistPtr = new (std::nothrow) sal_uInt32[ nPersistPtrAnz ]; + if ( !pPersistPtr ) + bOk = sal_False; + if ( bOk ) + { + memset( pPersistPtr, 0x00, nPersistPtrAnz * 4 ); + + // SJ: new search mechanism from bottom to top (Issue 21122) + PptUserEditAtom aCurrentEditAtom( aUserEditAtom ); + sal_uInt32 nCurrentEditAtomStrmPos = aCurrentEditAtom.aHd.GetRecEndFilePos(); + while( nCurrentEditAtomStrmPos ) + { + sal_uInt32 nPersistIncPos = aCurrentEditAtom.nOffsetPersistDirectory; + if ( nPersistIncPos ) + { + rStCtrl.Seek( nPersistIncPos ); + DffRecordHeader aPersistHd; + rStCtrl >> aPersistHd; + if ( aPersistHd.nRecType == PPT_PST_PersistPtrIncrementalBlock ) + { + sal_uLong nPibLen = aPersistHd.GetRecEndFilePos(); + while ( bOk && ( rStCtrl.GetError() == 0 ) && ( rStCtrl.Tell() < nPibLen ) ) + { + sal_uInt32 nOfs, nAnz; + rStCtrl >> nOfs; + nAnz = nOfs; + nOfs &= 0x000FFFFF; + nAnz >>= 20; + while ( bOk && ( rStCtrl.GetError() == 0 ) && ( nAnz > 0 ) && ( nOfs <= nPersistPtrAnz ) ) + { + sal_uInt32 nPt; + rStCtrl >> nPt; + if ( !pPersistPtr[ nOfs ] ) + { + pPersistPtr[ nOfs ] = nPt; + if ( pPersistPtr[ nOfs ] > nStreamLen ) + { + bOk = sal_False; + DBG_ERROR("SdrPowerPointImport::Ctor(): Ungueltiger Eintrag im Persist-Directory!"); + } + } + nAnz--; + nOfs++; + } + if ( bOk && nAnz > 0 ) + { + DBG_ERROR("SdrPowerPointImport::Ctor(): Nicht alle Persist-Directory Entraege gelesen!"); + bOk = sal_False; + } + } + } + } + nCurrentEditAtomStrmPos = aCurrentEditAtom.nOffsetLastEdit < nCurrentEditAtomStrmPos ? aCurrentEditAtom.nOffsetLastEdit : 0; + if ( nCurrentEditAtomStrmPos ) + { + rStCtrl.Seek( nCurrentEditAtomStrmPos ); + rStCtrl >> aCurrentEditAtom; + } + } + } + } + if ( rStCtrl.GetError() != 0 ) + bOk = sal_False; + if ( bOk ) + { // Document PersistEntry checken + nDocStreamPos = aUserEditAtom.nDocumentRef; + if ( nDocStreamPos > nPersistPtrAnz ) + { + DBG_ERROR("SdrPowerPointImport::Ctor(): aUserEditAtom.nDocumentRef ungueltig!"); + bOk = sal_False; + } + } + if ( bOk ) + { // Document FilePos checken + nDocStreamPos = pPersistPtr[ nDocStreamPos ]; + if ( nDocStreamPos >= nStreamLen ) + { + DBG_ERROR("SdrPowerPointImport::Ctor(): nDocStreamPos >= nStreamLen!"); + bOk = sal_False; + } + } + if ( bOk ) + { + rStCtrl.Seek( nDocStreamPos ); + aDocRecManager.Consume( rStCtrl ); + + DffRecordHeader aDocHd; + rStCtrl >> aDocHd; + // DocumentAtom lesen + DffRecordHeader aDocAtomHd; + rStCtrl >> aDocAtomHd; + if ( aDocHd.nRecType == PPT_PST_Document && aDocAtomHd.nRecType == PPT_PST_DocumentAtom ) + { + aDocAtomHd.SeekToBegOfRecord( rStCtrl ); + rStCtrl >> aDocAtom; + } + else + bOk = sal_False; + + if ( bOk ) + { + if ( !pFonts ) + ReadFontCollection(); + + // reading TxPF, TxSI + PPTTextCharacterStyleAtomInterpreter aTxCFStyle; // SJ: ToDo, this atom needs to be interpreted, it contains character default styles for standard objects (instance4) + PPTTextParagraphStyleAtomInterpreter aTxPFStyle; + PPTTextSpecInfoAtomInterpreter aTxSIStyle; // styles (default language setting ... ) + + DffRecordHeader* pEnvHd = aDocRecManager.GetRecordHeader( PPT_PST_Environment ); + if ( pEnvHd ) + { + pEnvHd->SeekToContent( rStCtrl ); + DffRecordHeader aTxPFStyleRecHd; + if ( SeekToRec( rStCtrl, PPT_PST_TxPFStyleAtom, pEnvHd->GetRecEndFilePos(), &aTxPFStyleRecHd ) ) + aTxPFStyle.Read( rStCtrl, aTxPFStyleRecHd ); + + pEnvHd->SeekToContent( rStCtrl ); + DffRecordHeader aTxSIStyleRecHd; + if ( SeekToRec( rStCtrl, PPT_PST_TxSIStyleAtom, pEnvHd->GetRecEndFilePos(), &aTxSIStyleRecHd ) ) + { + aTxSIStyle.Read( rStCtrl, aTxSIStyleRecHd, PPT_PST_TxSIStyleAtom ); +#ifdef DBG_UTIL + if ( !aTxSIStyle.bValid ) + { + if (!(rImportParam.nImportFlags & PPT_IMPORTFLAGS_NO_TEXT_ASSERT )) + { + DBG_ERROR( "SdrTextSpecInfoAtomInterpreter::Ctor(): parsing error, this document needs to be analysed (SJ)" ); + } + } +#endif + } + } + + // todo:: PPT_PST_TxPFStyleAtom + + // SlidePersists Lesen + pMasterPages=new PptSlidePersistList; + pSlidePages =new PptSlidePersistList; + pNotePages =new PptSlidePersistList; + + // now always creating the handout page, it will be the first in our masterpage list + PptSlidePersistEntry* pE = new PptSlidePersistEntry; + pE->aPersistAtom.nPsrReference = aDocAtom.nHandoutMasterPersist; + pE->bHandoutMaster = sal_True; + if ( !aDocAtom.nHandoutMasterPersist ) + pE->bStarDrawFiller = sal_True; // this is a dummy master page + pMasterPages->C40_INSERT( PptSlidePersistEntry, pE, 0 ); + + sal_uInt16 nPageListNum = 0; + DffRecordHeader* pSlideListWithTextHd = aDocRecManager.GetRecordHeader( PPT_PST_SlideListWithText ); + PptSlidePersistEntry* pPreviousPersist = NULL; + while ( pSlideListWithTextHd && ( nPageListNum < 3 ) ) + { + pSlideListWithTextHd->SeekToContent( rStCtrl ); + PptSlidePersistList* pPageList = GetPageList( PptPageKind( nPageListNum ) ); + sal_uInt32 nSlideListWithTextHdEndOffset = pSlideListWithTextHd->GetRecEndFilePos(); + while ( SeekToRec( rStCtrl, PPT_PST_SlidePersistAtom, nSlideListWithTextHdEndOffset ) ) + { + if ( pPreviousPersist ) + pPreviousPersist->nSlidePersistEndOffset = rStCtrl.Tell(); + PptSlidePersistEntry* pE2 = new PptSlidePersistEntry; + rStCtrl >> pE2->aPersistAtom; + pE2->nSlidePersistStartOffset = rStCtrl.Tell(); + pE2->ePageKind = PptPageKind( nPageListNum ); + pPageList->C40_INSERT( PptSlidePersistEntry, pE2, pPageList->Count() ); + pPreviousPersist = pE2; + } + if ( pPreviousPersist ) + pPreviousPersist->nSlidePersistEndOffset = nSlideListWithTextHdEndOffset; + pSlideListWithTextHd = aDocRecManager.GetRecordHeader( PPT_PST_SlideListWithText, SEEK_FROM_CURRENT ); + nPageListNum++; + } + + // we will ensure that there is at least one master page + if ( pMasterPages->Count() == 1 ) // -> there is only a handout page available + { + PptSlidePersistEntry* pE2 = new PptSlidePersistEntry; + pE2->bStarDrawFiller = sal_True; // this is a dummy master page + pMasterPages->C40_INSERT( PptSlidePersistEntry, pE2, 1 ); + } + + // now we will insert at least one notes master for each master page + sal_uInt16 nMasterPage; + sal_uInt16 nMasterPages = pMasterPages->Count() - 1; + for ( nMasterPage = 0; nMasterPage < nMasterPages; nMasterPage++ ) + { + PptSlidePersistEntry* pE2 = new PptSlidePersistEntry; + pE2->bNotesMaster = sal_True; + pE2->bStarDrawFiller = sal_True; // this is a dummy master page + if ( !nMasterPage && aDocAtom.nNotesMasterPersist ) + { // special treatment for the first notes master + pE2->aPersistAtom.nPsrReference = aDocAtom.nNotesMasterPersist; + pE2->bStarDrawFiller = sal_False; // this is a dummy master page + } + pMasterPages->C40_INSERT( PptSlidePersistEntry, pE2, ( nMasterPage + 1 ) << 1 ); + } + + // Zu jeder Page noch das SlideAtom bzw. NotesAtom lesen, soweit vorhanden + nPageListNum = 0; + for ( nPageListNum = 0; nPageListNum < 3; nPageListNum++ ) + { + PptSlidePersistList* pPageList = GetPageList( PptPageKind( nPageListNum ) ); + for ( sal_uInt16 nPageNum = 0; nPageNum < pPageList->Count(); nPageNum++ ) + { + PptSlidePersistEntry* pE2 = (*pPageList)[ nPageNum ]; + sal_uLong nPersist = pE2->aPersistAtom.nPsrReference; + if ( ( nPersist > 0 ) && ( nPersist < nPersistPtrAnz ) ) + { + sal_uLong nFPos = pPersistPtr[ nPersist ]; + if ( nFPos < nStreamLen ) + { + rStCtrl.Seek( nFPos ); + DffRecordHeader aSlideHd; + rStCtrl >> aSlideHd; + if ( SeekToRec( rStCtrl, PPT_PST_SlideAtom, aSlideHd.GetRecEndFilePos() ) ) + rStCtrl >> pE2->aSlideAtom; + else if ( SeekToRec( rStCtrl, PPT_PST_NotesAtom, aSlideHd.GetRecEndFilePos() ) ) + rStCtrl >> pE2->aNotesAtom; + aSlideHd.SeekToContent( rStCtrl ); + + DffRecordHeader aPPTDrawingHd; + if ( SeekToRec( rStCtrl, PPT_PST_PPDrawing, aSlideHd.GetRecEndFilePos(), &aPPTDrawingHd ) ) + { + DffRecordHeader aPPTDgContainer; + if ( SeekToRec( rStCtrl, DFF_msofbtDgContainer, aPPTDrawingHd.GetRecEndFilePos(), &aPPTDgContainer ) ) + { + if ( SeekToRec( rStCtrl, DFF_msofbtDg, aPPTDrawingHd.GetRecEndFilePos() ) ) + { + DffRecordHeader aDgRecordHeader; + rStCtrl >> aDgRecordHeader; + pE2->nDrawingDgId = aDgRecordHeader.nRecInstance; + aDgRecordHeader.SeekToEndOfRecord( rStCtrl ); + } + if ( SeekToRec( rStCtrl, DFF_msofbtSolverContainer, aPPTDgContainer.GetRecEndFilePos() ) ) + { + pE2->pSolverContainer = new SvxMSDffSolverContainer; + rStCtrl >> *( pE2->pSolverContainer ); + } + aPPTDgContainer.SeekToBegOfRecord( rStCtrl ); + SetDgContainer( rStCtrl ); // set this, so that the escherimport is knowing of our drawings + } + } + // office xp is supporting more than one stylesheet + if ( ( pE2->ePageKind == PPT_MASTERPAGE ) && ( pE2->aSlideAtom.nMasterId == 0 ) && ( pE2->bNotesMaster == 0 ) ) + { + PPTTextSpecInfo aTxSI( 0 ); + if ( aTxSIStyle.bValid && aTxSIStyle.aList.Count() ) + aTxSI = *( ( (PPTTextSpecInfo*)aTxSIStyle.aList.GetObject( 0 ) ) ); + + pE2->pStyleSheet = new PPTStyleSheet( aSlideHd, rStCtrl, *this, aTxCFStyle, aTxPFStyle, aTxSI ); + pDefaultSheet = pE2->pStyleSheet; + } + if ( SeekToRec( rStCtrl, PPT_PST_ColorSchemeAtom, aSlideHd.GetRecEndFilePos() ) ) + rStCtrl >> pE2->aColorScheme; + else + { + DBG_ERROR( "SdrPowerPointImport::Ctor(): could not get SlideColorScheme! (SJ)" ); + } + } + else + { + DBG_ERROR("SdrPowerPointImport::Ctor(): Persist-Eintrag fehlerhaft! (SJ)"); + } + } + } + } + DffRecordHeader* pHeadersFootersHd = aDocRecManager.GetRecordHeader( PPT_PST_HeadersFooters, SEEK_FROM_BEGINNING ); + if ( pHeadersFootersHd ) + { + HeaderFooterEntry aNormalMaster, aNotesMaster; + for ( ; pHeadersFootersHd; pHeadersFootersHd = aDocRecManager.GetRecordHeader( PPT_PST_HeadersFooters, SEEK_FROM_CURRENT ) ) + { + if ( pHeadersFootersHd->nRecInstance == 3 ) // normal master + ImportHeaderFooterContainer( *pHeadersFootersHd, aNormalMaster ); + else if ( pHeadersFootersHd->nRecInstance == 4 ) // notes master + ImportHeaderFooterContainer( *pHeadersFootersHd, aNotesMaster ); + } + for ( sal_uInt16 i = 0; i < pMasterPages->Count(); i++ ) + { + if ( (*pMasterPages)[ i ]->bNotesMaster ) + (*pMasterPages)[ i ]->pHeaderFooterEntry = new HeaderFooterEntry( aNotesMaster ); + else + (*pMasterPages)[ i ]->pHeaderFooterEntry = new HeaderFooterEntry( aNormalMaster ); + } + } + } + } + if ( ( rStCtrl.GetError() != 0 ) || ( pDefaultSheet == NULL ) ) + bOk = sal_False; + pPPTStyleSheet = pDefaultSheet; + rStCtrl.Seek( 0 ); +} + +SdrPowerPointImport::~SdrPowerPointImport() +{ + for ( void* pPtr = aHyperList.First(); pPtr; pPtr = aHyperList.Next() ) + delete (SdHyperlinkEntry*)pPtr; + delete pMasterPages; + delete pSlidePages; + delete pNotePages; + delete[] pPersistPtr; +} + +sal_Bool PPTConvertOCXControls::InsertControl( + const com::sun::star::uno::Reference< + com::sun::star::form::XFormComponent > &rFComp, + const com::sun::star::awt::Size& rSize, + com::sun::star::uno::Reference< + com::sun::star::drawing::XShape > *pShape, + sal_Bool /*bFloatingCtrl*/) +{ + sal_Bool bRetValue = sal_False; + try + { + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xShape; + + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer > & rFormComps = + GetFormComps(); + + ::com::sun::star::uno::Any aTmp( &rFComp, ::getCppuType((const ::com::sun::star::uno::Reference< + com::sun::star::form::XFormComponent >*)0) ); + + rFormComps->insertByIndex( rFormComps->getCount(), aTmp ); + + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & rServiceFactory = + GetServiceFactory(); + if( rServiceFactory.is() ) + { + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xCreate = rServiceFactory + ->createInstance(String( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.ControlShape" ) ) ); + if( xCreate.is() ) + { + xShape = ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >(xCreate, ::com::sun::star::uno::UNO_QUERY); + if ( xShape.is() ) + { + xShape->setSize(rSize); +// GetShapes()->add( xShape ); + // Das Control-Model am Control-Shape setzen + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XControlShape > xControlShape( xShape, + ::com::sun::star::uno::UNO_QUERY ); + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > xControlModel( rFComp, + ::com::sun::star::uno::UNO_QUERY ); + if ( xControlShape.is() && xControlModel.is() ) + { + xControlShape->setControl( xControlModel ); + if (pShape) + *pShape = xShape; + bRetValue = sal_True; + } + } + } + } + } + catch( ... ) + { + bRetValue = sal_False; + } + return bRetValue; +}; + +const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& PPTConvertOCXControls::GetDrawPage() +{ + if( !xDrawPage.is() && pDocSh ) + { + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > xModel( pDocSh->GetModel() ); + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPages > xDrawPages; + switch( ePageKind ) + { + case PPT_SLIDEPAGE : + case PPT_NOTEPAGE : + { + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPagesSupplier > + xDrawPagesSupplier( xModel, ::com::sun::star::uno::UNO_QUERY); + if ( xDrawPagesSupplier.is() ) + xDrawPages = xDrawPagesSupplier->getDrawPages(); + } + break; + + case PPT_MASTERPAGE : + { + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XMasterPagesSupplier > + xMasterPagesSupplier( xModel, ::com::sun::star::uno::UNO_QUERY); + if ( xMasterPagesSupplier.is() ) + xDrawPages = xMasterPagesSupplier->getMasterPages(); + } + break; + } + if ( xDrawPages.is() && xDrawPages->getCount() ) + { + xDrawPages->getCount(); + ::com::sun::star::uno::Any aAny( xDrawPages->getByIndex( xDrawPages->getCount() - 1 ) ); + aAny >>= xDrawPage; + } + } + return xDrawPage; +} + +sal_Bool SdrPowerPointOLEDecompress( SvStream& rOutput, SvStream& rInput, sal_uInt32 nInputSize ) +{ + sal_uInt32 nOldPos = rInput.Tell(); + char* pBuf = new char[ nInputSize ]; + rInput.Read( pBuf, nInputSize ); + ZCodec aZCodec( 0x8000, 0x8000 ); + aZCodec.BeginCompression(); + SvMemoryStream aSource( pBuf, nInputSize, STREAM_READ ); + aZCodec.Decompress( aSource, rOutput ); + const sal_Bool bSuccess(0L != aZCodec.EndCompression()); + delete[] pBuf; + rInput.Seek( nOldPos ); + return bSuccess; +} + +// --> OD 2004-12-14 #i32596# - add new parameter <_nCalledByGroup> +SdrObject* SdrPowerPointImport::ImportOLE( long nOLEId, + const Graphic& rGraf, + const Rectangle& rBoundRect, + const Rectangle& rVisArea, + const int /*_nCalledByGroup*/, + sal_Int64 /*nAspect*/ ) const +// <-- +{ + SdrObject* pRet = NULL; + + sal_uInt32 nOldPos = rStCtrl.Tell(); + + Graphic aGraphic( rGraf ); + + if ( ((SdrPowerPointImport*)this)->maShapeRecords.SeekToContent( rStCtrl, DFF_msofbtClientData, SEEK_FROM_CURRENT_AND_RESTART ) ) + { + DffRecordHeader aPlaceHd; + while ( ( rStCtrl.GetError() == 0 ) + && ( rStCtrl.Tell() < ((SdrPowerPointImport*)this)->maShapeRecords.Current()->GetRecEndFilePos() ) ) + { + rStCtrl >> aPlaceHd; + if ( aPlaceHd.nRecType == PPT_PST_RecolorInfoAtom ) + { + ((SdrPowerPointImport*)this)->RecolorGraphic( rStCtrl, aPlaceHd.nRecLen, aGraphic ); + break; + } + else + aPlaceHd.SeekToEndOfRecord( rStCtrl ); + } + } + + PPTOleEntry* pOe; + for ( pOe = (PPTOleEntry*)((SdrPowerPointImport*)this)->aOleObjectList.First(); pOe; + pOe = (PPTOleEntry*)((SdrPowerPointImport*)this)->aOleObjectList.Next() ) + { + if ( pOe->nId != (sal_uInt32)nOLEId ) + continue; + + rStCtrl.Seek( pOe->nRecHdOfs ); + + DffRecordHeader aHd; + rStCtrl >> aHd; + + sal_uInt32 nLen = aHd.nRecLen - 4; + if ( (sal_Int32)nLen > 0 ) + { + sal_Bool bSuccess = sal_False; + + rStCtrl.SeekRel( 4 ); + + ::utl::TempFile aTmpFile; + aTmpFile.EnableKillingFile( sal_True ); + + if ( aTmpFile.IsValid() ) + { + SvStream* pDest = ::utl::UcbStreamHelper::CreateStream( aTmpFile.GetURL(), STREAM_TRUNC | STREAM_WRITE ); + if ( pDest ) + bSuccess = SdrPowerPointOLEDecompress( *pDest, rStCtrl, nLen ); + delete pDest; + } + if ( bSuccess ) + { + SvStream* pDest = ::utl::UcbStreamHelper::CreateStream( aTmpFile.GetURL(), STREAM_READ ); + Storage* pObjStor = pDest ? new Storage( *pDest, sal_True ) : NULL; + if ( pObjStor ) + { + SotStorageRef xObjStor( new SotStorage( pObjStor ) ); + if ( xObjStor.Is() && !xObjStor->GetError() ) + { + if ( xObjStor->GetClassName() == SvGlobalName() ) + { + ClsId aId( pObjStor->GetClassId() ); + xObjStor->SetClass( SvGlobalName( aId.n1, aId.n2, aId.n3, aId.n4, aId.n5, aId.n6, aId.n7, aId.n8, aId.n9, aId.n10, aId.n11 ), + pObjStor->GetFormat(), pObjStor->GetUserName() ); + } + SotStorageStreamRef xSrcTst = xObjStor->OpenSotStream( String( RTL_CONSTASCII_USTRINGPARAM( "\1Ole" ) ) ); + if ( xSrcTst.Is() ) + { + sal_uInt8 aTestA[ 10 ]; + sal_Bool bGetItAsOle = ( sizeof( aTestA ) == xSrcTst->Read( aTestA, sizeof( aTestA ) ) ); + if ( !bGetItAsOle ) + { // maybe there is a contentsstream in here + xSrcTst = xObjStor->OpenSotStream( String( RTL_CONSTASCII_USTRINGPARAM( "Contents" ) ), STREAM_READWRITE | STREAM_NOCREATE ); + bGetItAsOle = ( xSrcTst.Is() && sizeof( aTestA ) == xSrcTst->Read( aTestA, sizeof( aTestA ) ) ); + } + if ( bGetItAsOle ) + { + ::rtl::OUString aNm; + // if ( nSvxMSDffOLEConvFlags ) + { + uno::Reference < embed::XStorage > xDestStorage( pOe->pShell->GetStorage() ); + uno::Reference < embed::XEmbeddedObject > xObj = + CheckForConvertToSOObj( nSvxMSDffOLEConvFlags, *xObjStor, xDestStorage, rGraf, rVisArea ); + if( xObj.is() ) + { + pOe->pShell->getEmbeddedObjectContainer().InsertEmbeddedObject( xObj, aNm ); + + svt::EmbeddedObjectRef aObj( xObj, pOe->nAspect ); + + // TODO/LATER: need MediaType for Graphic + aObj.SetGraphic( rGraf, ::rtl::OUString() ); + pRet = new SdrOle2Obj( aObj, aNm, rBoundRect, sal_False ); + } + } + if ( !pRet && ( pOe->nType == PPT_PST_ExControl ) ) + { + PPTConvertOCXControls aPPTConvertOCXControls( pOe->pShell, eAktPageKind ); + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xShape; + if ( aPPTConvertOCXControls.ReadOCXStream( xObjStor, &xShape, sal_False ) ) + pRet = GetSdrObjectFromXShape( xShape ); + } + if ( !pRet ) + { + aNm = pOe->pShell->getEmbeddedObjectContainer().CreateUniqueObjectName(); + ErrCode aErrCode = 0; + + // object is not an own object + SotStorageRef xTarget = SotStorage::OpenOLEStorage( pOe->pShell->GetStorage(), aNm, STREAM_READWRITE ); + if ( xObjStor.Is() && xTarget.Is() ) + { + xObjStor->CopyTo( xTarget ); + if( !xTarget->GetError() ) + xTarget->Commit(); + if( xTarget->GetError() ) + aErrCode = xTarget->GetError(); + } + xTarget.Clear(); + + uno::Reference < embed::XEmbeddedObject > xObj = + pOe->pShell->getEmbeddedObjectContainer().GetEmbeddedObject( aNm ); + if ( xObj.is() ) + { + if ( pOe->nAspect != embed::Aspects::MSOLE_ICON ) + { + //TODO/LATER: keep on hacking?! + // modifiziert wollen wir nicht werden + //xInplaceObj->EnableSetModified( sal_False ); + if ( rVisArea.IsEmpty() ) + { + MapUnit aMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( pOe->nAspect ) ); + Size aSize( OutputDevice::LogicToLogic( aGraphic.GetPrefSize(), + aGraphic.GetPrefMapMode(), MapMode( aMapUnit ) ) ); + + awt::Size aSz; + aSz.Width = aSize.Width(); + aSz.Height = aSize.Height(); + xObj->setVisualAreaSize( pOe->nAspect, aSz ); + } + else + { + awt::Size aSize( rVisArea.GetSize().Width(), rVisArea.GetSize().Height() ); + xObj->setVisualAreaSize( pOe->nAspect, aSize ); + } + //xInplaceObj->EnableSetModified( sal_True ); + } + + svt::EmbeddedObjectRef aObj( xObj, pOe->nAspect ); + + // TODO/LATER: need MediaType for Graphic + aObj.SetGraphic( aGraphic, ::rtl::OUString() ); + + pRet = new SdrOle2Obj( aObj, aNm, rBoundRect, sal_False ); + } + } + } + } + } + } + delete pDest; + } + } + } + rStCtrl.Seek( nOldPos ); + + return pRet; +} + +SvMemoryStream* SdrPowerPointImport::ImportExOleObjStg( sal_uInt32 nPersistPtr, sal_uInt32& nOleId ) const +{ + SvMemoryStream* pRet = NULL; + if ( nPersistPtr && ( nPersistPtr < nPersistPtrAnz ) ) + { + sal_uInt32 nOldPos, nOfs = pPersistPtr[ nPersistPtr ]; + nOldPos = rStCtrl.Tell(); + rStCtrl.Seek( nOfs ); + DffRecordHeader aHd; + rStCtrl >> aHd; + if ( aHd.nRecType == DFF_PST_ExOleObjStg ) + { + sal_uInt32 nLen = aHd.nRecLen - 4; + if ( (sal_Int32)nLen > 0 ) + { + rStCtrl >> nOleId; + pRet = new SvMemoryStream; + ZCodec aZCodec( 0x8000, 0x8000 ); + aZCodec.BeginCompression(); + aZCodec.Decompress( rStCtrl, *pRet ); + if ( !aZCodec.EndCompression() ) + delete pRet, pRet = NULL; + } + } + rStCtrl.Seek( nOldPos ); + } + return pRet; +} + +void SdrPowerPointImport::SeekOle( SfxObjectShell* pShell, sal_uInt32 nFilterOptions ) +{ + if ( pShell ) + { + DffRecordHeader* pHd; + + sal_uInt32 nOldPos = rStCtrl.Tell(); + if ( nFilterOptions & 1 ) + { + pHd = aDocRecManager.GetRecordHeader( PPT_PST_List, SEEK_FROM_BEGINNING ); + if ( pHd ) + { + // we try to locate the basic atom + pHd->SeekToContent( rStCtrl ); + if ( SeekToRec( rStCtrl, PPT_PST_VBAInfo, pHd->GetRecEndFilePos(), pHd ) ) + { + if ( SeekToRec( rStCtrl, PPT_PST_VBAInfoAtom, pHd->GetRecEndFilePos(), pHd ) ) + { + sal_uInt32 nPersistPtr, nIDoNotKnow1, nIDoNotKnow2; + rStCtrl >> nPersistPtr + >> nIDoNotKnow1 + >> nIDoNotKnow2; + + sal_uInt32 nOleId; + SvMemoryStream* pBas = ImportExOleObjStg( nPersistPtr, nOleId ); + if ( pBas ) + { + SotStorageRef xSource( new SotStorage( pBas, sal_True ) ); + SotStorageRef xDest( new SotStorage( new SvMemoryStream(), sal_True ) ); + if ( xSource.Is() && xDest.Is() ) + { + // is this a visual basic storage ? + SotStorageRef xSubStorage = xSource->OpenSotStorage( String( RTL_CONSTASCII_USTRINGPARAM( "VBA" ) ), + STREAM_READWRITE | STREAM_NOCREATE | STREAM_SHARE_DENYALL ); + if( xSubStorage.Is() && ( SVSTREAM_OK == xSubStorage->GetError() ) ) + { + SotStorageRef xMacros = xDest->OpenSotStorage( String( RTL_CONSTASCII_USTRINGPARAM( "MACROS" ) ) ); + if ( xMacros.Is() ) + { + SvStorageInfoList aList; + xSource->FillInfoList( &aList ); + sal_uInt32 i; + + sal_Bool bCopied = sal_True; + for ( i = 0; i < aList.Count(); i++ ) // copy all entrys + { + const SvStorageInfo& rInfo = aList[ i ]; + if ( !xSource->CopyTo( rInfo.GetName(), xMacros, rInfo.GetName() ) ) + bCopied = sal_False; + } + if ( i && bCopied ) + { + SvxImportMSVBasic aMSVBas( *pShell, *xDest, sal_True, sal_False ); + //int nSuccess = aMSVBas.Import( String( RTL_CONSTASCII_USTRINGPARAM( "MACROS" ) ), + // String( RTL_CONSTASCII_USTRINGPARAM( "VBA" ) ), TRUE, FALSE ); + + uno::Reference < embed::XStorage > xDoc( pShell->GetStorage() ); + if ( xDoc.is() ) + { + SotStorageRef xVBA = SotStorage::OpenOLEStorage( xDoc, String( RTL_CONSTASCII_USTRINGPARAM( "_MS_VBA_Macros" ) ) ); + if ( xVBA.Is() && ( xVBA->GetError() == SVSTREAM_OK ) ) + { + SotStorageRef xSubVBA = xVBA->OpenSotStorage( String( RTL_CONSTASCII_USTRINGPARAM( "_MS_VBA_Overhead" ) ) ); + if ( xSubVBA.Is() && ( xSubVBA->GetError() == SVSTREAM_OK ) ) + { + SotStorageStreamRef xOriginal = xSubVBA->OpenSotStream( String( RTL_CONSTASCII_USTRINGPARAM( "_MS_VBA_Overhead2" ) ) ); + if ( xOriginal.Is() && ( xOriginal->GetError() == SVSTREAM_OK ) ) + { + if ( nPersistPtr && ( nPersistPtr < nPersistPtrAnz ) ) + { + rStCtrl.Seek( pPersistPtr[ nPersistPtr ] ); + rStCtrl >> *pHd; + + *xOriginal << nIDoNotKnow1 + << nIDoNotKnow2; + + sal_uInt32 nSource, nToCopy, nBufSize; + nSource = rStCtrl.Tell(); + nToCopy = pHd->nRecLen; + sal_uInt8* pBuf = new sal_uInt8[ 0x40000 ]; // 256KB Buffer + if ( pBuf ) + { + while ( nToCopy ) + { + nBufSize = ( nToCopy >= 0x40000 ) ? 0x40000 : nToCopy; + rStCtrl.Read( pBuf, nBufSize ); + xOriginal->Write( pBuf, nBufSize ); + nToCopy -= nBufSize; + } + delete[] pBuf; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + pHd = aDocRecManager.GetRecordHeader( PPT_PST_ExObjList, SEEK_FROM_BEGINNING ); + if ( pHd ) + { + DffRecordManager* pExObjListManager = NULL; + DffRecordHeader* pExEmbed = NULL; + + pHd->SeekToBegOfRecord( rStCtrl ); + pExObjListManager = new DffRecordManager( rStCtrl ); + sal_uInt16 i, nRecType(PPT_PST_ExEmbed); + + for ( i = 0; i < 2; i++ ) + { + switch ( i ) + { + case 0 : nRecType = PPT_PST_ExEmbed; break; + case 1 : nRecType = PPT_PST_ExControl; break; + } + for ( pExEmbed = pExObjListManager->GetRecordHeader( nRecType, SEEK_FROM_BEGINNING ); + pExEmbed; pExEmbed = pExObjListManager->GetRecordHeader( nRecType, SEEK_FROM_CURRENT ) ) + { + pExEmbed->SeekToContent( rStCtrl ); + + DffRecordHeader aExOleAtHd; + if ( SeekToRec( rStCtrl, PPT_PST_ExOleObjAtom, pExEmbed->GetRecEndFilePos(), &aExOleAtHd ) ) + { + PptExOleObjAtom aAt; + rStCtrl >> aAt; + + if ( aAt.nPersistPtr && ( aAt.nPersistPtr < nPersistPtrAnz ) ) + { + sal_uInt32 nId; + rStCtrl.Seek( pPersistPtr[ aAt.nPersistPtr ] ); + DffRecordHeader aHd; + rStCtrl >> aHd; + if ( aHd.nRecType == DFF_PST_ExOleObjStg ) + { + rStCtrl >> nId; + aOleObjectList.Insert( + new PPTOleEntry( aAt.nId, aHd.nFilePos, pShell, nRecType, aAt.nAspect ) ); + } + } + } + } + } + delete pExObjListManager; + } + rStCtrl.Seek( nOldPos ); + } +} + +sal_Bool SdrPowerPointImport::ReadFontCollection() +{ + sal_Bool bRet = sal_False; + DffRecordHeader* pEnvHd = aDocRecManager.GetRecordHeader( PPT_PST_Environment ); + if ( pEnvHd ) + { + sal_uLong nFPosMerk = rStCtrl.Tell(); // FilePos merken fuer spaetere Restauration + pEnvHd->SeekToContent( rStCtrl ); + DffRecordHeader aListHd; + if ( SeekToRec( rStCtrl, PPT_PST_FontCollection, pEnvHd->GetRecEndFilePos(), &aListHd ) ) + { + sal_uInt16 nCount2 = 0; + VirtualDevice* pVDev = NULL; + while ( SeekToRec( rStCtrl, PPT_PST_FontEntityAtom, aListHd.GetRecEndFilePos() ) ) + { + bRet = sal_True; + if ( !pFonts ) + pFonts = new PptFontCollection; + PptFontEntityAtom* pFont = new PptFontEntityAtom; + rStCtrl >> *pFont; + + Font aFont; + aFont.SetCharSet( pFont->eCharSet ); + aFont.SetName( pFont->aName ); + aFont.SetFamily( pFont->eFamily ); + aFont.SetPitch( pFont->ePitch ); + aFont.SetHeight( 100 ); + + if ( mbTracing && !pFont->bAvailable ) + mpTracer->Trace( rtl::OUString::createFromAscii( "sd1000" ), pFont->aName ); + +#ifdef DBG_EXTRACTFONTMETRICS + + SvxFont aTmpFont( aFont ); + + if ( !pVDev ) + pVDev = new VirtualDevice; + aTmpFont.SetPhysFont( pVDev ); + FontMetric aMetric( pVDev->GetFontMetric() ); + sal_uInt16 nTxtHeight = (sal_uInt16)aMetric.GetAscent() + (sal_uInt16)aMetric.GetDescent(); + + String aFileURLStr; + if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( Application::GetAppFileName(), aFileURLStr ) ) + { + INetURLObject aURL( aFileURLStr ); + aURL.SetName( String( RTL_CONSTASCII_STRINGPARAM( "dbgfontmetrics.txt" ) ) ); + + SvStream* pDbgOut = ::utl::UcbStreamHelper::CreateStream( aURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_WRITE ); + if( pDbgOut ) + { + pDbgOut->Seek( STREAM_SEEK_TO_END ); + + Printer* pPrinter = NULL; + if ( pSdrModel->GetRefDevice() && pSdrModel->GetRefDevice()->GetOutDevType() == OUTDEV_PRINTER ) + pPrinter = (Printer*)pSdrModel->GetRefDevice(); + if ( pPrinter ) + { + Font aOldFont( pPrinter->GetFont() ); + aFont.SetKerning( sal_True ); + pPrinter->SetFont( aFont ); + aMetric = pPrinter->GetFontMetric(); + pPrinter->SetFont( aOldFont ); + } + + if ( ( pPrinter == NULL ) || ( aMetric.GetIntLeading() == 0 ) ) + { + VirtualDevice aVirDev( 1 ); + aVirDev.SetFont( aFont ); + aMetric = aVirDev.GetFontMetric(); + } + ByteString aFontName( aFont.GetName(), RTL_TEXTENCODING_UTF8 ); + ByteString aHeight( ByteString::CreateFromInt32( aMetric.GetLineHeight() ) ); + ByteString aAscent( ByteString::CreateFromInt32( aMetric.GetAscent() ) ); + ByteString aDescent( ByteString::CreateFromInt32( aMetric.GetDescent() ) ); + ByteString aLeading( ByteString::CreateFromInt32( aMetric.GetIntLeading() ) ); + ByteString aPhysHeight( ByteString::CreateFromInt32( nTxtHeight ) ); + + *pDbgOut << (sal_uInt8)0xa + << "FontName : " << aFontName.GetBuffer() << (sal_uInt8)0xa + << " Height: " << aHeight.GetBuffer() << (sal_uInt8)0xa + << " Ascent: " << aAscent.GetBuffer() << (sal_uInt8)0xa + << " Descent:" << aDescent.GetBuffer() << (sal_uInt8)0xa + << " Leading:" << aLeading.GetBuffer() << (sal_uInt8)0xa + << "PhysHeight :" << aPhysHeight.GetBuffer()<< (sal_uInt8)0xa; + } + delete pDbgOut; + } +#endif + // following block is necessary, because our old PowerPoint export did not set the + // correct charset + if ( pFont->aName.EqualsIgnoreCaseAscii( "Wingdings" ) || + pFont->aName.EqualsIgnoreCaseAscii( "Wingdings 2" ) || + pFont->aName.EqualsIgnoreCaseAscii( "Wingdings 3" ) || + pFont->aName.EqualsIgnoreCaseAscii( "Monotype Sorts" ) || + pFont->aName.EqualsIgnoreCaseAscii( "Monotype Sorts 2" ) || + pFont->aName.EqualsIgnoreCaseAscii( "Webdings" ) || + pFont->aName.EqualsIgnoreCaseAscii( "StarBats" ) || + pFont->aName.EqualsIgnoreCaseAscii( "StarMath" ) || + pFont->aName.EqualsIgnoreCaseAscii( "ZapfDingbats" ) ) + { + pFont->eCharSet = RTL_TEXTENCODING_SYMBOL; + }; + pFonts->C40_INSERT( PptFontEntityAtom, pFont, nCount2++ ); + } + delete pVDev; + } + rStCtrl.Seek( nFPosMerk ); // FilePos restaurieren + } + return bRet; +} + +PptSlidePersistList* SdrPowerPointImport::GetPageList(PptPageKind ePageKind) const +{ + if ( ePageKind == PPT_MASTERPAGE ) + return pMasterPages; + if ( ePageKind == PPT_SLIDEPAGE ) + return pSlidePages; + if ( ePageKind == PPT_NOTEPAGE ) + return pNotePages; + return NULL; +} + +SdrOutliner* SdrPowerPointImport::GetDrawOutliner( SdrTextObj* pSdrText ) const +{ + if ( !pSdrText ) + return NULL; + else + return &pSdrText->ImpGetDrawOutliner(); +} + + +SdrObject* SdrPowerPointImport::ReadObjText( PPTTextObj* pTextObj, SdrObject* pSdrObj, SdPage* pPage ) const +{ + SdrTextObj* pText = PTR_CAST( SdrTextObj, pSdrObj ); + if ( pText ) + { + if ( !ApplyTextObj( pTextObj, pText, pPage, NULL, NULL ) ) + pSdrObj = NULL; + } + return pSdrObj; +} + + +SdrObject* SdrPowerPointImport::ApplyTextObj( PPTTextObj* pTextObj, SdrTextObj* pSdrText, SdPage* /*pPage*/, + SfxStyleSheet* pSheet, SfxStyleSheet** ppStyleSheetAry ) const +{ + SdrTextObj* pText = pSdrText; + if ( pTextObj->Count() ) + { + sal_uInt32 nDestinationInstance = pTextObj->GetDestinationInstance() ; + SdrOutliner& rOutliner = pText->ImpGetDrawOutliner(); + if ( ( pText->GetObjInventor() == SdrInventor ) && ( pText->GetObjIdentifier() == OBJ_TITLETEXT ) ) // Outliner-Style fuer Titel-Textobjekt?!? (->von DL) + rOutliner.Init( OUTLINERMODE_TITLEOBJECT ); // Outliner reset + + sal_Bool bOldUpdateMode = rOutliner.GetUpdateMode(); + rOutliner.SetUpdateMode( sal_False ); + if ( pSheet ) + { + if ( rOutliner.GetStyleSheet( 0 ) != pSheet ) + rOutliner.SetStyleSheet( 0, pSheet ); + } + rOutliner.SetVertical( pTextObj->GetVertical() ); + sal_Int16 nLastStartNumbering = -1; + const PPTParagraphObj* pPreviousParagraph = NULL; + for ( PPTParagraphObj* pPara = pTextObj->First(); pPara; pPara = pTextObj->Next() ) + { + sal_uInt32 nTextSize = pPara->GetTextSize(); + if ( ! ( nTextSize & 0xffff0000 ) ) + { + PPTPortionObj* pPortion; + sal_Unicode* pParaText = new sal_Unicode[ nTextSize ]; + sal_uInt32 nCurrentIndex = 0; + for ( pPortion = pPara->First(); pPortion; pPortion = pPara->Next() ) + { + if ( pPortion->mpFieldItem ) + pParaText[ nCurrentIndex++ ] = ' '; + else + { + sal_uInt32 nCharacters = pPortion->Count(); + const sal_Unicode* pSource = pPortion->maString.GetBuffer(); + sal_Unicode* pDest = pParaText + nCurrentIndex; + + sal_uInt32 nFont; + pPortion->GetAttrib( PPT_CharAttr_Font, nFont, pTextObj->GetInstance() ); + PptFontEntityAtom* pFontEnityAtom = GetFontEnityAtom( nFont ); + if ( pFontEnityAtom && ( pFontEnityAtom->eCharSet == RTL_TEXTENCODING_SYMBOL ) ) + { + sal_uInt32 i; + sal_Unicode nUnicode; + for ( i = 0; i < nCharacters; i++ ) + { + nUnicode = pSource[ i ]; + if ( ! ( nUnicode & 0xff00 ) ) + nUnicode |= 0xf000; + pDest[ i ] = nUnicode; + } + } + else + memcpy( pDest, pSource, nCharacters << 1 ); + nCurrentIndex += nCharacters; + } + } + sal_uInt16 nParaIndex = (sal_uInt16)pTextObj->GetCurrentIndex(); + SfxStyleSheet* pS = ( ppStyleSheetAry ) ? ppStyleSheetAry[ pPara->pParaSet->mnDepth ] : pSheet; + + ESelection aSelection( nParaIndex, 0, nParaIndex, 0 ); + rOutliner.Insert( String(), nParaIndex, pPara->pParaSet->mnDepth ); + rOutliner.QuickInsertText( String( pParaText, (sal_uInt16)nCurrentIndex ), aSelection ); + rOutliner.SetParaAttribs( nParaIndex, rOutliner.GetEmptyItemSet() ); + if ( pS ) + rOutliner.SetStyleSheet( nParaIndex, pS ); + + for ( pPortion = pPara->First(); pPortion; pPortion = pPara->Next() ) + { + SfxItemSet aPortionAttribs( rOutliner.GetEmptyItemSet() ); + SvxFieldItem* pFieldItem = pPortion->GetTextField(); + if ( pFieldItem ) + { + rOutliner.QuickInsertField( *pFieldItem, ESelection( nParaIndex, aSelection.nEndPos, nParaIndex, aSelection.nEndPos + 1 ) ); + aSelection.nEndPos++; + delete pFieldItem; + } + else + { + const sal_Unicode *pF, *pPtr = pPortion->maString.GetBuffer(); + const sal_Unicode *pMax = pPtr + pPortion->maString.Len(); + sal_Int32 nLen; + for ( pF = pPtr; pPtr < pMax; pPtr++ ) + { + if ( *pPtr == 0xb ) + { + nLen = pPtr - pF; + if ( nLen ) + aSelection.nEndPos = + sal::static_int_cast< sal_uInt16 >( + aSelection.nEndPos + nLen ); + pF = pPtr + 1; + rOutliner.QuickInsertLineBreak( ESelection( nParaIndex, aSelection.nEndPos, nParaIndex, aSelection.nEndPos + 1 ) ); + aSelection.nEndPos++; + } + } + nLen = pPtr - pF; + if ( nLen ) + aSelection.nEndPos = sal::static_int_cast< sal_uInt16 >( + aSelection.nEndPos + nLen ); + } + pPortion->ApplyTo( aPortionAttribs, (SdrPowerPointImport&)*this, nDestinationInstance, pTextObj ); + rOutliner.QuickSetAttribs( aPortionAttribs, aSelection ); + aSelection.nStartPos = aSelection.nEndPos; + } + boost::optional< sal_Int16 > oStartNumbering; + SfxItemSet aParagraphAttribs( rOutliner.GetEmptyItemSet() ); + pPara->ApplyTo( aParagraphAttribs, oStartNumbering, (SdrPowerPointImport&)*this, nDestinationInstance, pPreviousParagraph ); + + sal_uInt32 nIsBullet2 = 0; //, nInstance = nDestinationInstance != 0xffffffff ? nDestinationInstance : pTextObj->GetInstance(); + pPara->GetAttrib( PPT_ParaAttr_BulletOn, nIsBullet2, nDestinationInstance ); + if ( !nIsBullet2 ) + aParagraphAttribs.Put( SfxBoolItem( EE_PARA_BULLETSTATE, sal_False ) ); + + if ( oStartNumbering ) + { + if ( *oStartNumbering != nLastStartNumbering ) + rOutliner.SetNumberingStartValue( nParaIndex, *oStartNumbering ); + else + rOutliner.SetNumberingStartValue( nParaIndex, -1 ); + nLastStartNumbering = *oStartNumbering; + } + else + { + nLastStartNumbering = -1; + rOutliner.SetNumberingStartValue( nParaIndex, nLastStartNumbering ); + } + + pPreviousParagraph = pPara; + if ( !aSelection.nStartPos ) // in PPT empty paragraphs never gets a bullet + { + aParagraphAttribs.Put( SfxBoolItem( EE_PARA_BULLETSTATE, sal_False ) ); +// rOutliner.SetDepth( rOutliner.GetParagraph( nParaIndex ), -1 ); + } + aSelection.nStartPos = 0; + rOutliner.QuickSetAttribs( aParagraphAttribs, aSelection ); + delete[] pParaText; + } + } + OutlinerParaObject* pNewText = rOutliner.CreateParaObject(); + rOutliner.Clear(); + rOutliner.SetUpdateMode( bOldUpdateMode ); + pText->SetOutlinerParaObject( pNewText ); + } + return pText; +} + +sal_Bool SdrPowerPointImport::SeekToDocument( DffRecordHeader* pRecHd ) const +{ + sal_Bool bRet; + sal_uLong nFPosMerk = rStCtrl.Tell(); // FilePos merken fuer ggf. spaetere Restauration + rStCtrl.Seek( nDocStreamPos ); + DffRecordHeader aDocHd; + rStCtrl >> aDocHd; + bRet = aDocHd.nRecType == PPT_PST_Document; + if ( bRet ) + { + if ( pRecHd ) + *pRecHd = aDocHd; + else + aDocHd.SeekToBegOfRecord( rStCtrl ); + } + if ( !bRet ) + rStCtrl.Seek( nFPosMerk ); // FilePos restaurieren + return bRet; +} + +sal_Bool SdrPowerPointImport::SeekToContentOfProgTag( sal_Int32 nVersion, SvStream& rSt, + const DffRecordHeader& rSourceHd, DffRecordHeader& rContentHd ) +{ + sal_Bool bRetValue = sal_False; + sal_uInt32 nOldPos = rSt.Tell(); + + DffRecordHeader aProgTagsHd, aProgTagBinaryDataHd; + rSourceHd.SeekToContent( rSt ); + sal_Bool bFound = rSourceHd.nRecType == PPT_PST_ProgTags; + if ( !bFound ) + bFound = SeekToRec( rSt, PPT_PST_ProgTags, rSourceHd.GetRecEndFilePos(), &aProgTagsHd ); + if ( bFound ) + { + while( SeekToRec( rSt, PPT_PST_ProgBinaryTag, aProgTagsHd.GetRecEndFilePos(), &aProgTagBinaryDataHd ) ) + { + rSt >> rContentHd; + if ( rContentHd.nRecType == PPT_PST_CString ) + { + sal_uInt16 n = 6; + sal_uInt32 i = rContentHd.nRecLen >> 1; + if ( i > n ) + { + String aPre, aSuf; + sal_Unicode *pTmp = aPre.AllocBuffer( n ); + while ( n-- ) + rSt >> *pTmp++; + n = (sal_uInt16)( i - 6 ); + pTmp = aSuf.AllocBuffer( n ); + while ( n-- ) + rSt >> *pTmp++; + sal_Int32 nV = aSuf.ToInt32(); + if ( ( nV == nVersion ) && ( aPre == String( RTL_CONSTASCII_USTRINGPARAM( "___PPT" ) ) ) ) + { + rContentHd.SeekToEndOfRecord( rSt ); + rSt >> rContentHd; + if ( rContentHd.nRecType == PPT_PST_BinaryTagData ) + { + bRetValue = sal_True; + break; + } + } + } + } + aProgTagBinaryDataHd.SeekToEndOfRecord( rSt ); + } + } + if ( !bRetValue ) + rSt.Seek( nOldPos ); + return bRetValue; +} + +sal_uInt32 SdrPowerPointImport::GetAktPageId() +{ + PptSlidePersistList* pList = GetPageList( eAktPageKind ); + if ( pList && nAktPageNum < pList->Count() ) + return (*pList)[ (sal_uInt16)nAktPageNum ]->aPersistAtom.nSlideId; + return 0; +} + +sal_Bool SdrPowerPointImport::SeekToAktPage( DffRecordHeader* pRecHd ) const +{ + sal_Bool bRet = sal_False; + PptSlidePersistList* pList = GetPageList( eAktPageKind ); + if ( pList && ( nAktPageNum < pList->Count() ) ) + { + sal_uLong nPersist = (*pList)[ (sal_uInt16)nAktPageNum ]->aPersistAtom.nPsrReference; + if ( nPersist > 0 && nPersist < nPersistPtrAnz ) + { + sal_uLong nFPos = 0; + nFPos = pPersistPtr[ nPersist ]; + if ( nFPos < nStreamLen ) + { + rStCtrl.Seek( nFPos ); + if ( pRecHd ) + rStCtrl >> *pRecHd; + bRet = sal_True; + } + } + } + return bRet; +} + +sal_uInt16 SdrPowerPointImport::GetPageCount( PptPageKind ePageKind ) const +{ + PptSlidePersistList* pList = GetPageList( ePageKind ); + if ( pList ) + return pList->Count(); + return 0; +} + +void SdrPowerPointImport::SetPageNum( sal_uInt16 nPageNum, PptPageKind eKind ) +{ + eAktPageKind = eKind; + nAktPageNum = nPageNum; + + pPPTStyleSheet = NULL; + + sal_Bool bHasMasterPage = sal_True; + sal_uInt16 nMasterIndex = 0; + + if ( eKind == PPT_MASTERPAGE ) + nMasterIndex = nPageNum; + else + { + if ( HasMasterPage( nPageNum, eKind ) ) + nMasterIndex = GetMasterPageIndex( nPageNum, eKind ); + else + bHasMasterPage = sal_False; + } + if ( bHasMasterPage ) + { + PptSlidePersistList* pPageList = GetPageList( PPT_MASTERPAGE ); + if ( pPageList && nMasterIndex < pPageList->Count() ) + { + PptSlidePersistEntry* pMasterPersist = (*pPageList)[ nMasterIndex ]; + if ( ( pMasterPersist->pStyleSheet == NULL ) && pMasterPersist->aSlideAtom.nMasterId ) + { + nMasterIndex = pMasterPages->FindPage( pMasterPersist->aSlideAtom.nMasterId ); + if ( nMasterIndex != PPTSLIDEPERSIST_ENTRY_NOTFOUND ) + pMasterPersist = (*pPageList)[ nMasterIndex ]; + } + pPPTStyleSheet = pMasterPersist->pStyleSheet; + } + } + if ( !pPPTStyleSheet ) + pPPTStyleSheet = pDefaultSheet; +} + +Size SdrPowerPointImport::GetPageSize() const +{ + Size aRet( IsNoteOrHandout( nAktPageNum, eAktPageKind ) ? aDocAtom.GetNotesPageSize() : aDocAtom.GetSlidesPageSize() ); + Scale( aRet ); + // PPT arbeitet nur mit Einheiten zu 576DPI. Um Ungenauigkeiten zu + // vermeiden runde ich die letzte Nachkommastelle metrisch weg. + if ( nMapMul > 2 * nMapDiv ) + { + MapUnit eMap = pSdrModel->GetScaleUnit(); + bool bInch = IsInch( eMap ); + long nInchMul = 1, nInchDiv = 1; + if ( bInch ) + { // Size temporaer (zum runden) in nach metric konvertieren + Fraction aFact(GetMapFactor(eMap,MAP_100TH_MM).X()); + nInchMul = aFact.GetNumerator(); + nInchDiv = aFact.GetDenominator(); + aRet.Width() = BigMulDiv( aRet.Width(), nInchMul, nInchDiv ); + aRet.Height() = BigMulDiv( aRet.Height(), nInchMul, nInchDiv ); + } + aRet.Width() += 5; aRet.Width() /= 10; aRet.Width()*=10; + aRet.Height() += 5; aRet.Height() /= 10; aRet.Height()*=10; + if ( bInch ) + { + aRet.Width() = BigMulDiv( aRet.Width(), nInchDiv, nInchMul ); + aRet.Height() = BigMulDiv( aRet.Height(), nInchDiv, nInchMul ); + } + } + return aRet; +} + +FASTBOOL SdrPowerPointImport::GetColorFromPalette( sal_uInt16 nNum, Color& rColor ) const +{ + if ( nPageColorsNum != nAktPageNum || ePageColorsKind != eAktPageKind ) + { + sal_uInt16 nSlideFlags = 0; + PptSlidePersistList* pPageList = GetPageList( eAktPageKind ); + if ( pPageList && ( nAktPageNum < pPageList->Count() ) ) + { + PptSlidePersistEntry* pE = (*pPageList)[ nAktPageNum ]; + if ( pE ) + nSlideFlags = pE->aSlideAtom.nFlags; + if ( ! ( nSlideFlags & 2 ) ) + ((SdrPowerPointImport*)this)->aPageColors = pE->aColorScheme; + } + if ( nSlideFlags & 2 ) // follow master colorscheme ? + { + PptSlidePersistList* pPageList2 = GetPageList( PPT_MASTERPAGE ); + if ( pPageList2 ) + { + PptSlidePersistEntry* pMasterPersist = NULL; + if ( eAktPageKind == PPT_MASTERPAGE ) + pMasterPersist = (*pPageList2)[ nAktPageNum ]; + else + { + if ( HasMasterPage( nAktPageNum, eAktPageKind ) ) + { + sal_uInt16 nMasterNum = GetMasterPageIndex( nAktPageNum, eAktPageKind ); + if ( nMasterNum < pPageList2->Count() ) + pMasterPersist = (*pPageList2)[ nMasterNum ]; + } + } + if ( pMasterPersist ) + { + while( ( pMasterPersist && pMasterPersist->aSlideAtom.nFlags & 2 ) // it is possible that a masterpage + && pMasterPersist->aSlideAtom.nMasterId ) // itself is following a master colorscheme + { + sal_uInt16 nNextMaster = pMasterPages->FindPage( pMasterPersist->aSlideAtom.nMasterId ); + if ( nNextMaster == PPTSLIDEPERSIST_ENTRY_NOTFOUND ) + break; + else + pMasterPersist = (*pPageList2)[ nNextMaster ]; + } + ((SdrPowerPointImport*)this)->aPageColors = pMasterPersist->aColorScheme; + } + } + } + // momentanes Farbschema eintragen + ((SdrPowerPointImport*)this)->nPageColorsNum = nAktPageNum; + ((SdrPowerPointImport*)this)->ePageColorsKind = eAktPageKind; + } + rColor = aPageColors.GetColor( nNum ); + return sal_True; +} + +sal_Bool SdrPowerPointImport::SeekToShape( SvStream& rSt, void* pClientData, sal_uInt32 nId ) const +{ + sal_Bool bRet = SvxMSDffManager::SeekToShape( rSt, pClientData, nId ); + if ( !bRet ) + { + ProcessData& rData = *( (ProcessData*)pClientData ); + PptSlidePersistEntry& rPersistEntry = rData.rPersistEntry; + if ( rPersistEntry.ePageKind == PPT_SLIDEPAGE ) + { + if ( HasMasterPage( nAktPageNum, eAktPageKind ) ) + { + sal_uInt16 nMasterNum = GetMasterPageIndex( nAktPageNum, eAktPageKind ); + PptSlidePersistList* pPageList = GetPageList( PPT_MASTERPAGE ); + if ( pPageList && ( nMasterNum < pPageList->Count() ) ) + { + PptSlidePersistEntry* pPersist = (*pPageList)[ nMasterNum ]; // get the masterpage's persistentry + if ( pPersist && pPersist->pPresentationObjects ) + { + sal_uInt32 nCurrent(0L); + DffRecordList* pCList = maShapeRecords.pCList; // we got a backup of the current position + if ( pCList ) + nCurrent = pCList->nCurrent; + if ( ((SdrEscherImport*)this )->maShapeRecords.SeekToContent( rSt, DFF_msofbtClientData, SEEK_FROM_CURRENT_AND_RESTART ) ) + { + sal_uInt32 nStreamPos = rSt.Tell(); + PPTTextObj aTextObj( rSt, (SdrPowerPointImport&)*this, rPersistEntry, NULL ); + if ( aTextObj.Count() || aTextObj.GetOEPlaceHolderAtom() ) + { + sal_uInt32 nShapePos = 0; + switch ( aTextObj.GetInstance() ) + { + case TSS_TYPE_TITLE : + nShapePos = pPersist->pPresentationObjects[ TSS_TYPE_PAGETITLE ]; + break; + case TSS_TYPE_PAGETITLE : + nShapePos = pPersist->pPresentationObjects[ TSS_TYPE_PAGETITLE ]; + break; + case TSS_TYPE_SUBTITLE : + case TSS_TYPE_HALFBODY : + case TSS_TYPE_QUARTERBODY : + case TSS_TYPE_BODY : + nShapePos = pPersist->pPresentationObjects[ TSS_TYPE_BODY ]; + break; +// case TSS_TYPE_NOTES : +// case TSS_TYPE_UNUSED : +// case TSS_TYPE_TEXT_IN_SHAPE : + } + if ( nShapePos ) + { + rSt.Seek( nShapePos ); + bRet = sal_True; + } + } + if ( !bRet ) + rSt.Seek( nStreamPos ); + } + if ( pCList ) // restoring + pCList->nCurrent = nCurrent; + ((SdrEscherImport*)this )->maShapeRecords.pCList = pCList; + } + } + } + } + } + return bRet; +} + +SdrPage* SdrPowerPointImport::MakeBlancPage( sal_Bool bMaster ) const +{ + SdrPage* pRet = pSdrModel->AllocPage( bMaster ); + pRet->SetSize( GetPageSize() ); + +/* + SJ (21.08.00) : since bug #77576# i decided not to set a border size. + + Size aPageSize( aDocAtom.GetSlidesPageSize() ); // PageSize in 576DPI-Units + long nHMarg = aPageSize.Width() - aDocAtom.aSlidesPageSize.Width(); + long nVMarg = aPageSize.Height() - aDocAtom.aSlidesPageSize.Height(); + if ( nHMarg > 0 ) + { + Scale( nHMarg ); + pRet->SetLftBorder( nHMarg / 2 ); + pRet->SetRgtBorder( nHMarg - nHMarg / 2 ); + } + if ( nVMarg > 0 ) + { + Scale( nVMarg ); + pRet->SetUppBorder( nVMarg / 2 ); + pRet->SetLwrBorder( nVMarg - nVMarg / 2 ); + } +*/ + return pRet; +} + +void ImportComment10( SvxMSDffManager& rMan, SvStream& rStCtrl, SdrPage* pPage, DffRecordHeader& rComment10Hd ) +{ + rtl::OUString sAuthor; + rtl::OUString sText; + rtl::OUString sInitials; + + sal_Int32 nIndex = 0; + util::DateTime aDateTime; + sal_Int32 nPosX = 0; + sal_Int32 nPosY = 0; + + while ( ( rStCtrl.GetError() == 0 ) && ( rStCtrl.Tell() < rComment10Hd.GetRecEndFilePos() ) ) + { + DffRecordHeader aCommentHd; + rStCtrl >> aCommentHd; + switch( aCommentHd.nRecType ) + { + case PPT_PST_CString : + { + String aString; + SvxMSDffManager::MSDFFReadZString( rStCtrl, aString, aCommentHd.nRecLen, sal_True ); + switch ( aCommentHd.nRecInstance ) + { + case 0 : sAuthor = aString; break; + case 1 : sText = aString; break; + case 2 : sInitials = aString; break; + } + } + break; + + case PPT_PST_CommentAtom10 : + { + rStCtrl >> nIndex + >> aDateTime.Year + >> aDateTime.Month + >> aDateTime.Day // DayOfWeek + >> aDateTime.Day + >> aDateTime.Hours + >> aDateTime.Minutes + >> aDateTime.Seconds + >> aDateTime.HundredthSeconds + >> nPosX + >> nPosY; + + aDateTime.HundredthSeconds /= 10; + } + break; + } + aCommentHd.SeekToEndOfRecord( rStCtrl ); + } + Point aPosition( nPosX, nPosY ); + rMan.Scale( aPosition ); + + try + { + uno::Reference< office::XAnnotationAccess > xAnnotationAccess( pPage->getUnoPage(), UNO_QUERY_THROW ); + uno::Reference< office::XAnnotation > xAnnotation( xAnnotationAccess->createAndInsertAnnotation() ); + xAnnotation->setPosition( geometry::RealPoint2D( aPosition.X() / 100.0, aPosition.Y() / 100.0 ) ); + xAnnotation->setAuthor( sAuthor ); + xAnnotation->setDateTime( aDateTime ); + uno::Reference< text::XText > xText( xAnnotation->getTextRange() ); + xText->setString( sText ); + } + catch( uno::Exception& ) + { + + } +} + + +// be sure not to import masterpages with this method +// be sure not to import masterpages with this method +void SdrPowerPointImport::ImportPage( SdrPage* pRet, const PptSlidePersistEntry* pMasterPersist ) +{ + sal_uInt32 nMerk = rStCtrl.Tell(); + PptSlidePersistList* pList = GetPageList( eAktPageKind ); + if ( ( !pList ) || ( pList->Count() <= nAktPageNum ) ) + return; + PptSlidePersistEntry& rSlidePersist = *(*pList)[ nAktPageNum ]; + if ( rSlidePersist.bStarDrawFiller ) + return; + + DffRecordHeader aPageHd; + if ( SeekToAktPage( &aPageHd ) ) + { + if ( mbTracing ) + mpTracer->AddAttribute( eAktPageKind == PPT_SLIDEPAGE + ? rtl::OUString::createFromAscii( "Page" ) + : rtl::OUString::createFromAscii( "NotesPage" ), + rtl::OUString::valueOf( (sal_Int32)nAktPageNum + 1 ) ); + + rSlidePersist.pHeaderFooterEntry = new HeaderFooterEntry( pMasterPersist ); + ProcessData aProcessData( rSlidePersist, (SdPage*)pRet ); + while ( ( rStCtrl.GetError() == 0 ) && ( rStCtrl.Tell() < aPageHd.GetRecEndFilePos() ) ) + { + DffRecordHeader aHd; + rStCtrl >> aHd; + switch ( aHd.nRecType ) + { + case PPT_PST_HeadersFooters : + { + ImportHeaderFooterContainer( aHd, *rSlidePersist.pHeaderFooterEntry ); + } + break; + + case PPT_PST_ProgTags : + { + DffRecordHeader aContentDataHd; + if ( SeekToContentOfProgTag( 10, rStCtrl, aHd, aContentDataHd ) ) + { + DffRecordHeader aComment10Hd; + while( ( rStCtrl.GetError() == 0 ) && SeekToRec( rStCtrl, PPT_PST_Comment10, aContentDataHd.GetRecEndFilePos(), &aComment10Hd ) ) + { + ImportComment10( *this, rStCtrl, pRet, aComment10Hd ); + aComment10Hd.SeekToEndOfRecord( rStCtrl ); + } + } + } + break; + + case PPT_PST_PPDrawing : + { + DffRecordHeader aPPDrawHd; + if ( SeekToRec( rStCtrl, DFF_msofbtDgContainer, aHd.GetRecEndFilePos(), &aPPDrawHd ) ) + { + sal_uInt32 nPPDrawOfs = rStCtrl.Tell(); + + // importing the background object before importing the page + while ( ( rStCtrl.GetError() == 0 ) && ( rStCtrl.Tell() < aPPDrawHd.GetRecEndFilePos() ) ) + { + DffRecordHeader aEscherObjListHd; + rStCtrl >> aEscherObjListHd; + switch ( aEscherObjListHd.nRecType ) + { + case DFF_msofbtSpContainer : + { + Rectangle aPageSize( Point(), pRet->GetSize() ); + if ( rSlidePersist.aSlideAtom.nFlags & 4 ) // follow master background ? + { + if ( HasMasterPage( nAktPageNum, eAktPageKind ) ) + { + sal_uInt16 nMasterNum = GetMasterPageIndex( nAktPageNum, eAktPageKind ); + PptSlidePersistList* pPageList = GetPageList( PPT_MASTERPAGE ); + PptSlidePersistEntry* pE = (*pPageList)[ nMasterNum ]; + while( ( pE->aSlideAtom.nFlags & 4 ) && pE->aSlideAtom.nMasterId ) + { + sal_uInt16 nNextMaster = pMasterPages->FindPage( pE->aSlideAtom.nMasterId ); + if ( nNextMaster == PPTSLIDEPERSIST_ENTRY_NOTFOUND ) + break; + else + pE = (*pPageList)[ nNextMaster ]; + } + if ( pE->nBackgroundOffset ) + { + // do not follow master colorscheme ? + sal_Bool bTemporary = ( rSlidePersist.aSlideAtom.nFlags & 2 ) != 0; + sal_uInt32 nPos = rStCtrl.Tell(); + rStCtrl.Seek( pE->nBackgroundOffset ); + rSlidePersist.pBObj = ImportObj( rStCtrl, (void*)&aProcessData, aPageSize, aPageSize ); + rSlidePersist.bBObjIsTemporary = bTemporary; + rStCtrl.Seek( nPos ); + } + } + } + else + { + DffRecordHeader aShapeHd; + rStCtrl >> aShapeHd; + if ( aShapeHd.nRecType == DFF_msofbtSp ) + { + sal_uInt32 nSpFlags; + rStCtrl >> nSpFlags >> nSpFlags; + if ( nSpFlags & SP_FBACKGROUND ) + { + aEscherObjListHd.SeekToBegOfRecord( rStCtrl ); + rSlidePersist.pBObj = ImportObj( rStCtrl, (void*)&aProcessData, aPageSize, aPageSize ); + rSlidePersist.bBObjIsTemporary = sal_False; + } + } + } + } + break; + } + if ( aEscherObjListHd.nRecType == DFF_msofbtSpContainer ) + break; + aEscherObjListHd.SeekToEndOfRecord( rStCtrl ); + } + + // now importing page + rStCtrl.Seek( nPPDrawOfs ); + while ( ( rStCtrl.GetError() == 0 ) && ( rStCtrl.Tell() < aPPDrawHd.GetRecEndFilePos() ) ) + { + DffRecordHeader aEscherObjListHd; + rStCtrl >> aEscherObjListHd; + switch ( aEscherObjListHd.nRecType ) + { + case DFF_msofbtSpgrContainer : + { + DffRecordHeader aShapeHd; + if ( SeekToRec( rStCtrl, DFF_msofbtSpContainer, aEscherObjListHd.GetRecEndFilePos(), &aShapeHd ) ) + { + aShapeHd.SeekToEndOfRecord( rStCtrl ); + while ( ( rStCtrl.GetError() == 0 ) && ( rStCtrl.Tell() < aEscherObjListHd.GetRecEndFilePos() ) ) + { + rStCtrl >> aShapeHd; + if ( ( aShapeHd.nRecType == DFF_msofbtSpContainer ) || ( aShapeHd.nRecType == DFF_msofbtSpgrContainer ) ) + { + Rectangle aEmpty; + aShapeHd.SeekToBegOfRecord( rStCtrl ); + sal_Int32 nShapeId; + aProcessData.pTableRowProperties = NULL; + SdrObject* pObj = ImportObj( rStCtrl, (void*)&aProcessData, aEmpty, aEmpty, 0, &nShapeId ); + if ( pObj ) + { + if ( aProcessData.pTableRowProperties ) + pObj = CreateTable( pObj, aProcessData.pTableRowProperties, aProcessData.rPersistEntry.pSolverContainer ); + + pRet->NbcInsertObject( pObj ); + + if( nShapeId ) + insertShapeId( nShapeId, pObj ); + } + } + aShapeHd.SeekToEndOfRecord( rStCtrl ); + } + } + } + break; + } + if ( aEscherObjListHd.nRecType == DFF_msofbtSpgrContainer ) + break; + aEscherObjListHd.SeekToEndOfRecord( rStCtrl ); + } + + /* There are a lot of Shapes who are dependent to + the current background color */ + if ( rSlidePersist.ePageKind == PPT_SLIDEPAGE ) + { + List* pList2 = aProcessData.pBackgroundColoredObjects; + if ( pList2 ) + { + if ( rSlidePersist.pBObj ) + { + void* pPtr; + const SfxPoolItem* pPoolItem = NULL; + const SfxItemSet& rObjectItemSet = rSlidePersist.pBObj->GetMergedItemSet(); + + //SfxItemState eState = rObjectItemSet.GetItemState( XATTR_FILLCOLOR, sal_False, &pPoolItem ); + if ( pPoolItem ) + { + SfxItemSet aNewSet(*rObjectItemSet.GetPool()); + aNewSet.Put(*pPoolItem); + aNewSet.Put(XFillStyleItem( XFILL_SOLID )); + + for ( pPtr = pList2->First(); pPtr; pPtr = pList2->Next() ) + { + ((SdrObject*)pPtr)->SetMergedItemSet(aNewSet); + } + } + } + } + } + if ( rSlidePersist.pBObj ) + { + // #i99386# transfer the attributes from the temporary BackgroundObject + // to the Page and delete it. Maybe rSlidePersist.bBObjIsTemporary is + // obsolete here, too. + pRet->getSdrPageProperties().ClearItem(); + pRet->getSdrPageProperties().PutItemSet(rSlidePersist.pBObj->GetMergedItemSet()); + SdrObject::Free( rSlidePersist.pBObj ); + } + } + } + break; + } + aHd.SeekToEndOfRecord( rStCtrl ); + } + if ( rSlidePersist.pSolverContainer ) + SolveSolver( *rSlidePersist.pSolverContainer ); + if ( mbTracing ) + mpTracer->RemoveAttribute( eAktPageKind == PPT_SLIDEPAGE + ? rtl::OUString::createFromAscii( "Page" ) + : rtl::OUString::createFromAscii( "NotesPage" ) ); + } + rStCtrl.Seek( nMerk ); +} + +const PptSlideLayoutAtom* SdrPowerPointImport::GetSlideLayoutAtom() const +{ + PptSlidePersistList* pPageList = GetPageList( eAktPageKind ); + if ( pPageList && nAktPageNum < pPageList->Count() ) + { + PptSlidePersistEntry* pE = (*pPageList)[ nAktPageNum ]; + if ( pE ) + return &pE->aSlideAtom.aLayout; + } + return NULL; +} + +sal_Bool SdrPowerPointImport::IsNoteOrHandout( sal_uInt16 nPageNum, PptPageKind /*ePageKind*/) const +{ + sal_Bool bNote = eAktPageKind == PPT_NOTEPAGE; + if ( eAktPageKind == PPT_MASTERPAGE ) + bNote = ( nPageNum & 1 ) == 0; + return bNote; +} + +sal_uInt32 SdrPowerPointImport::GetMasterPageId( sal_uInt16 nPageNum, PptPageKind ePageKind ) const +{ + PptSlidePersistList* pPageList = GetPageList( ePageKind ); + if ( pPageList && nPageNum < pPageList->Count() ) + return (*pPageList)[ nPageNum ]->aSlideAtom.nMasterId; + return 0; +} + +sal_uInt32 SdrPowerPointImport::GetNotesPageId( sal_uInt16 nPageNum ) const +{ + PptSlidePersistList* pPageList=GetPageList( PPT_SLIDEPAGE ); + if ( pPageList && nPageNum < pPageList->Count() ) + return (*pPageList)[ nPageNum ]->aSlideAtom.nNotesId; + return 0; +} + +sal_Bool SdrPowerPointImport::HasMasterPage( sal_uInt16 nPageNum, PptPageKind ePageKind ) const +{ + if ( ePageKind == PPT_NOTEPAGE ) + return aDocAtom.nNotesMasterPersist != 0; + if ( ePageKind == PPT_MASTERPAGE ) + return sal_False; + return GetMasterPageId( nPageNum, ePageKind ) != 0; +} + +sal_uInt16 SdrPowerPointImport::GetMasterPageIndex( sal_uInt16 nPageNum, PptPageKind ePageKind ) const +{ + sal_uInt16 nIdx = 0; + if ( ePageKind == PPT_NOTEPAGE ) + return 2; + sal_uInt32 nId = GetMasterPageId( nPageNum, ePageKind ); + if ( nId && pMasterPages ) + { + nIdx = pMasterPages->FindPage( nId ); + if ( nIdx == PPTSLIDEPERSIST_ENTRY_NOTFOUND ) + nIdx = 0; + } + return nIdx; +} + +SdrObject* SdrPowerPointImport::ImportPageBackgroundObject( const SdrPage& rPage, sal_uInt32& nBgFileOffset, sal_Bool bForce ) +{ + SdrObject* pRet = NULL; + sal_Bool bCreateObj = bForce; + SfxItemSet* pSet = NULL; + sal_uLong nFPosMerk = rStCtrl.Tell(); // FilePos merken fuer spaetere Restauration + DffRecordHeader aPageHd; + if ( SeekToAktPage( &aPageHd ) ) + { // und nun die Hintergrundattribute der Page suchen + sal_uLong nPageRecEnd = aPageHd.GetRecEndFilePos(); + DffRecordHeader aPPDrawHd; + if ( SeekToRec( rStCtrl, PPT_PST_PPDrawing, nPageRecEnd, &aPPDrawHd ) ) + { + sal_uLong nPPDrawEnd = aPPDrawHd.GetRecEndFilePos(); + DffRecordHeader aEscherF002Hd; + if ( SeekToRec( rStCtrl, DFF_msofbtDgContainer, nPPDrawEnd, &aEscherF002Hd ) ) + { + sal_uLong nEscherF002End = aEscherF002Hd.GetRecEndFilePos(); + DffRecordHeader aEscherObjectHd; + if ( SeekToRec( rStCtrl, DFF_msofbtSpContainer, nEscherF002End, &aEscherObjectHd ) ) + { + nBgFileOffset = aEscherObjectHd.GetRecBegFilePos(); + //sal_uLong nEscherObjectEnd = aEscherObjectHd.GetRecEndFilePos(); + //DffRecordHeader aEscherPropertiesHd; + if ( SeekToRec( rStCtrl, DFF_msofbtOPT,nEscherF002End ) ) + { + rStCtrl >> (DffPropertyReader&)*this; + mnFix16Angle = Fix16ToAngle( GetPropertyValue( DFF_Prop_Rotation, 0 ) ); + sal_uInt32 nColor = GetPropertyValue( DFF_Prop_fillColor, 0xffffff ); + pSet = new SfxItemSet( pSdrModel->GetItemPool() ); + DffObjData aObjData( aEscherObjectHd, Rectangle( 0, 0, 28000, 21000 ), 0 ); + ApplyAttributes( rStCtrl, *pSet, aObjData ); + Color aColor( MSO_CLR_ToColor( nColor ) ); + pSet->Put( XFillColorItem( String(), aColor ) ); + } + } + } + } + } + rStCtrl.Seek( nFPosMerk ); // FilePos restaurieren + if ( bCreateObj ) + { + if ( !pSet ) + { + pSet = new SfxItemSet( pSdrModel->GetItemPool() ); + pSet->Put( XFillStyleItem( XFILL_NONE ) ); + } + pSet->Put( XLineStyleItem( XLINE_NONE ) ); + Rectangle aRect( rPage.GetLftBorder(), rPage.GetUppBorder(), rPage.GetWdt()-rPage.GetRgtBorder(), rPage.GetHgt()-rPage.GetLwrBorder() ); + pRet = new SdrRectObj( aRect ); + pRet->SetModel( pSdrModel ); + + pRet->SetMergedItemSet(*pSet); + + pRet->SetMarkProtect( sal_True ); + pRet->SetMoveProtect( sal_True ); + pRet->SetResizeProtect( sal_True ); + } + delete pSet; + return pRet; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HeaderFooterEntry::HeaderFooterEntry( const PptSlidePersistEntry* pMPE ) : + pMasterPersist ( pMPE ), + nAtom ( 0 ) +{ + if ( pMPE ) + { + HeaderFooterEntry* pMHFE = pMPE->pHeaderFooterEntry; + if ( pMHFE ) + { + nAtom = pMPE->pHeaderFooterEntry->nAtom; + pPlaceholder[ 0 ] = pMHFE->pPlaceholder[ 0 ]; + pPlaceholder[ 1 ] = pMHFE->pPlaceholder[ 1 ]; + pPlaceholder[ 2 ] = pMHFE->pPlaceholder[ 2 ]; + pPlaceholder[ 3 ] = pMHFE->pPlaceholder[ 3 ]; + } + } +} + +HeaderFooterEntry::~HeaderFooterEntry() +{ +} + +sal_uInt32 HeaderFooterEntry::GetMaskForInstance( sal_uInt32 nInstance ) +{ + sal_uInt32 nRet = 0; + switch ( nInstance ) + { + case 0 : nRet = 0x07ffff; break; + case 1 : nRet = 0x100000; break; + case 2 : nRet = 0x200000; break; + case 3 : nRet = 0x080000; break; + } + return nRet; +} + +sal_uInt32 HeaderFooterEntry::IsToDisplay( sal_uInt32 nInstance ) +{ + sal_uInt32 nMask = 0; + switch ( nInstance ) + { + case 0 : nMask = 0x010000; break; + case 1 : nMask = 0x100000; break; + case 2 : nMask = 0x200000; break; + case 3 : nMask = 0x080000; break; + } + return ( nAtom & nMask ); +} + +// The following method checks if the slide is using a different colorscheme than +// its master, if this is the fact, then the HeaderFooter must probably be +// imported as real sdrobject. In this case, the return value is the offset to the +// master header footer object, so it can be re-loaded with a different color set +sal_uInt32 HeaderFooterEntry::NeedToImportInstance( const sal_uInt32 nInstance, const PptSlidePersistEntry& rSlidePersist ) +{ + sal_uInt32 nRet = 0; + if ( pMasterPersist ) + { + if ( !( rSlidePersist.aSlideAtom.nFlags & 2 ) ) + { // not following the master persist, so we have to check if the colors are changed + if ( memcmp( &rSlidePersist.aColorScheme, &pMasterPersist->aColorScheme, 32 ) ) + { + nRet = pMasterPersist->HeaderFooterOfs[ nInstance ]; + } + } + } + return nRet; +} + +void SdrEscherImport::ImportHeaderFooterContainer( DffRecordHeader& rHd, HeaderFooterEntry& rE ) +{ + rHd.SeekToContent( rStCtrl ); + while ( ( rStCtrl.GetError() == 0 ) && ( rStCtrl.Tell() < rHd.GetRecEndFilePos() ) ) + { + DffRecordHeader aHd; + rStCtrl >> aHd; + switch ( aHd.nRecType ) + { + case PPT_PST_HeadersFootersAtom : + rStCtrl >> rE.nAtom; + break; + + case PPT_PST_CString : + { + if ( aHd.nRecInstance < 4 ) + MSDFFReadZString( rStCtrl, rE.pPlaceholder[ aHd.nRecInstance ], aHd.nRecLen, sal_True ); + } + break; + } + aHd.SeekToEndOfRecord( rStCtrl ); + } +} + +//static sal_Unicode PPTExportMapper( sal_Unicode nUni, sal_Bool& bNeedsStarBats ) +//{ +// bNeedsStarBats = sal_False; +// +// sal_Unicode cLo, cReplace; +// cLo = cReplace = 0; +// switch ( nUni ) +// { +// case 132 : cLo = 175; break; +// case 147 : cLo = 174; break; +// // Currency +// case 0x00A2: cReplace = 224; break; +// case 0x00A4: cReplace = 225; break; +// case 0x00A5: cReplace = 226; break; +// case 0x20A1: cReplace = 228; break; +// case 0x20A2: cReplace = 229; break; +// case 0x20A3: cReplace = 230; break; +// case 0x20A4: cReplace = 231; break; +// case 0x20A7: cReplace = 227; break; +// case 0x20A8: cReplace = 234; break; +// case 0x20A9: cReplace = 232; break; +// case 0x20AB: cReplace = 233; break; +// case 0x20AC: cReplace = 128; break; +// // Punctuation and other +// case 0x201A: cReplace = 130; break; // SINGLE LOW-9 QUOTATION MARK +// case 0x0192: cReplace = 131; break; // LATIN SMALL LETTER F WITH HOOK +// case 0x201E: // DOUBLE LOW-9 QUOTATION MARK +// case 0x301F: // LOW DOUBLE PRIME QUOTATION MARK +// cReplace = 132; break; +// case 0x2026: cReplace = 133; break; // HORIZONTAL ELLIPSES +// case 0x2020: cReplace = 134; break; // DAGGER +// case 0x2021: cReplace = 135; break; // DOUBLE DAGGER +// case 0x02C6: cReplace = 136; break; // MODIFIER LETTER CIRCUMFLEX ACCENT +// case 0x2030: cReplace = 137; break; // PER MILLE SIGN +// case 0x0160: cReplace = 138; break; // LATIN CAPITAL LETTER S WITH CARON +// case 0x2039: cReplace = 139; break; // SINGLE LEFT-POINTING ANGLE QUOTATION MARK +// case 0x0152: cReplace = 140; break; // LATIN CAPITAL LIGATURE OE +// case 0x017D: cReplace = 142; break; // LATIN CAPITAL LETTER Z WITH CARON +// case 0x2018: // LEFT SINGLE QUOTATION MARK +// case 0x02BB: // MODIFIER LETTER TURNED COMMA +// cReplace = 145; break; +// case 0x2019: // RIGHT SINGLE QUOTATION MARK +// case 0x02BC: // MODIFIER LETTER APOSTROPHE +// cReplace = 146; break; +// case 0x201C: // LEFT DOUBLE QUOTATION MARK +// case 0x301D: // REVERSED DOUBLE PRIME QUOTATION MARK +// cReplace = 147; break; +// case 0x201D: // RIGHT DOUBLE QUOTATION MARK +// case 0x301E: // REVERSED DOUBLE PRIME QUOTATION MARK +// cReplace = 148; break; +// case 0x2022: cReplace = 149; break; // BULLET +// case 0x2013: cReplace = 150; break; // EN DASH +// case 0x2014: cReplace = 151; break; // EM DASH +// case 0x02DC: cReplace = 152; break; // SMALL TILDE +// case 0x2122: cReplace = 153; break; // TRADE MARK SIGN +// case 0x0161: cReplace = 154; break; // LATIN SMALL LETTER S WITH CARON +// case 0x203A: cReplace = 155; break; // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK +// case 0x0153: cReplace = 156; break; // LATIN SMALL LIGATURE OE +// case 0x017E: cReplace = 158; break; // LATIN SMALL LETTER Z WITH CARON +// case 0x0178: cReplace = 159; break; // LATIN CAPITAL LETTER Y WITH DIAERESIS +// case 0x00B6: cReplace = 222; break; // PILCROW SIGN / PARAGRAPH SIGN +// } +// if ( cReplace ) +// { +// bNeedsStarBats = sal_True; +// return cReplace; +// } +// else +// return cLo; +//} + +// no longer needed +sal_Unicode SdrPowerPointImport::PPTSubstitute( sal_uInt16 /*nFont*/, sal_Unicode /*nChar*/, + sal_uInt32& /*nMappedFontId*/, Font& /*rFont*/, char /*nDefault*/) const +{ + return 0; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +PPTBuGraEntry::PPTBuGraEntry( Graphic& rGraphic, sal_uInt32 nInst ) : + nInstance ( nInst ), + aBuGra ( rGraphic ) {} + +PPTExtParaLevel::PPTExtParaLevel() +: mnExtParagraphMask( 0 ) +, mnBuBlip( 0xffff ) +, mnHasAnm( 0 ) +, mnAnmScheme( 0 ) +, mpfPP10Ext( 0 ) +, mnExtCharacterMask( 0 ) +, mcfPP10Ext( 0 ) +, mbSet( sal_False ) +{} + +SvStream& operator>>( SvStream& rIn, PPTExtParaLevel& rLevel ) +{ + rLevel.mbSet = sal_True; + rIn >> rLevel.mnExtParagraphMask; + if ( rLevel.mnExtParagraphMask & 0x00800000 ) + rIn >> rLevel.mnBuBlip; + if ( rLevel.mnExtParagraphMask & 0x02000000 ) + rIn >> rLevel.mnHasAnm; + if ( rLevel.mnExtParagraphMask & 0x01000000 ) + rIn >> rLevel.mnAnmScheme; + if ( rLevel.mnExtParagraphMask & 0x04000000 ) + rIn >> rLevel.mpfPP10Ext; + rIn >> rLevel.mnExtCharacterMask; + if ( rLevel.mnExtCharacterMask & 0x100000 ) + rIn >> rLevel.mcfPP10Ext; + return rIn; +} + +sal_Bool PPTExtParaProv::GetGraphic( sal_uInt32 nInstance, Graphic& rGraph ) const +{ + sal_Bool bRetValue = sal_False; + PPTBuGraEntry* pPtr = NULL; + if ( nInstance < aBuGraList.Count() ) + { + pPtr = (PPTBuGraEntry*)aBuGraList.GetObject( nInstance ); + if ( pPtr->nInstance == nInstance ) + bRetValue = sal_True; + } + if ( !bRetValue ) + { + sal_uInt32 i; + for ( i = 0; i < aBuGraList.Count(); i++ ) + { + pPtr = (PPTBuGraEntry*)aBuGraList.GetObject( i ); + if ( pPtr->nInstance == nInstance ) + { + bRetValue = sal_True; + break; + } + } + } + if ( bRetValue ) + rGraph = pPtr->aBuGra; + return bRetValue; +} + +PPTExtParaProv::PPTExtParaProv( SdrPowerPointImport& rMan, SvStream& rSt, const DffRecordHeader* pHd ) : + bStyles ( sal_False ), + bGraphics ( sal_False ) +{ + sal_uInt32 nOldPos = rSt.Tell(); + + // here we have to get the graphical bullets... + + DffRecordHeader aHd; + DffRecordHeader aContentDataHd; + + const DffRecordHeader* pListHd = rMan.aDocRecManager.GetRecordHeader( PPT_PST_List, SEEK_FROM_BEGINNING ); + while( pListHd ) + { + pListHd->SeekToContent( rSt ); + if ( !rMan.SeekToContentOfProgTag( 9, rSt, *pListHd, aContentDataHd ) ) + break; + while ( ( rSt.GetError() == 0 ) && ( rSt.Tell() < aContentDataHd.GetRecEndFilePos() ) ) + { + rSt >> aHd; + switch ( aHd.nRecType ) + { + case PPT_PST_ExtendedBuGraContainer : + { + while ( ( rSt.GetError() == 0 ) && ( rSt.Tell() < aHd.GetRecEndFilePos() ) ) + { + sal_uInt16 nType; + DffRecordHeader aBuGraAtomHd; + rSt >> aBuGraAtomHd; + if ( aBuGraAtomHd.nRecType == PPT_PST_ExtendedBuGraAtom ) + { + rSt >> nType; + Graphic aGraphic; + if ( rMan.GetBLIPDirect( rSt, aGraphic, NULL ) ) + { + sal_uInt32 nInstance = aBuGraAtomHd.nRecInstance; + PPTBuGraEntry* pBuGra = new PPTBuGraEntry( aGraphic, nInstance ); + sal_uInt32 n = 0; + sal_uInt32 nBuGraCount = aBuGraList.Count(); + if ( nBuGraCount ) + { + if ( ( (PPTBuGraEntry*)aBuGraList.GetObject( nBuGraCount - 1 ) )->nInstance < nInstance ) + n = nBuGraCount; + else + { // maybe the instances are not sorted, we sort it + for ( n = 0; n < nBuGraCount; n++ ) + { // sorting fields ( hi >> lo ) + if ( ( (PPTBuGraEntry*)aBuGraList.GetObject( n ) )->nInstance < nInstance ) + break; + } + } + } + aBuGraList.Insert( pBuGra, (sal_uInt32)n ); + } +#ifdef DBG_UTIL + else DBG_ERROR( "PPTExParaProv::PPTExParaProv - bullet graphic is not valid (SJ)" ); +#endif + } +#ifdef DBG_UTIL + else DBG_ERROR( "PPTExParaProv::PPTExParaProv - unknown atom interpreting the PPT_PST_ExtendedBuGraContainer (SJ)" ); +#endif + aBuGraAtomHd.SeekToEndOfRecord( rSt ); + } + if ( aBuGraList.Count() ) + bGraphics = sal_True; + } + break; + + case PPT_PST_ExtendedPresRuleContainer : + aExtendedPresRules.Consume( rSt, sal_False, aHd.GetRecEndFilePos() ); + break; +#ifdef DBG_UTIL + default : + DBG_ERROR( "PPTExParaProv::PPTExParaProv - unknown atom reading ppt2000 num rules (SJ)" ); + case PPT_PST_MasterText : // first seen in: ms-tt02.ppt + case PPT_PST_SrKinsoku : + case PPT_PST_NewlyAddedAtom4016 : + case PPT_PST_NewlyAddedAtomByPPT2000_6010 : + case PPT_PST_NewlyAddedAtomByPPT2000_6011 : + case PPT_PST_NewlyAddedAtomByXP1037 : + case PPT_PST_NewlyAddedAtomByXP12004 : + case PPT_PST_NewlyAddedAtomByXP14001 : + break; +#endif + } + aHd.SeekToEndOfRecord( rSt ); + } + break; + } + + while( pHd ) + { // get the extended paragraph styles on mainmaster ( graphical bullets, num ruling ... ) + if ( !rMan.SeekToContentOfProgTag( 9, rSt, *pHd, aContentDataHd ) ) + break; + while ( ( rSt.GetError() == 0 ) && ( rSt.Tell() < aContentDataHd.GetRecEndFilePos() ) ) + { + rSt >> aHd; + switch ( aHd.nRecType ) + { + case PPT_PST_ExtendedParagraphMasterAtom : + { + if ( aHd.nRecInstance < PPT_STYLESHEETENTRYS ) + { + sal_uInt16 nDepth, i = 0; + rSt >> nDepth; + if ( i <= 5 ) + { + + while ( ( rSt.GetError() == 0 ) && ( rSt.Tell() < aHd.GetRecEndFilePos() ) && ( i < nDepth ) ) + { + bStyles = sal_True; + rSt >> aExtParaSheet[ aHd.nRecInstance ].aExtParaLevel[ i++ ]; + } +#ifdef DBG_UTIL + if ( rSt.Tell() != aHd.GetRecEndFilePos() ) + DBG_ERROR( "PPTExParaProv::PPTExParaProv - error reading PPT_PST_ExtendedParagraphMasterAtom (SJ)" ); +#endif + } +#ifdef DBG_UTIL + else DBG_ERROR( "PPTExParaProv::PPTExParaProv - depth is greater than 5 (SJ)" ); +#endif + } +#ifdef DBG_UTIL + else DBG_ERROR( "PPTExParaProv::PPTExParaProv - instance out of range (SJ)" ); +#endif + } + break; + default : + DBG_ERROR( "PPTExParaProv::PPTExParaProv - unknown atom, assuming PPT_PST_ExtendedParagraphMasterAtom (SJ)" ); + case PPT_PST_NewlyAddedAtomByXP11008 : + case PPT_PST_NewlyAddedAtomByXP11010 : + case PPT_PST_NewlyAddedAtomByXP12010 : + case PPT_PST_NewlyAddedAtomByXP12011 : + case 0xf144 : + break; + } + aHd.SeekToEndOfRecord( rSt ); + } + break; + } + rSt.Seek( nOldPos ); +} + +PPTExtParaProv::~PPTExtParaProv() +{ + void* pPtr; + for ( pPtr = aBuGraList.First(); pPtr; pPtr = aBuGraList.Next() ) + delete (PPTBuGraEntry*)pPtr; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +PPTNumberFormatCreator::PPTNumberFormatCreator( PPTExtParaProv* pParaProv ) : + pExtParaProv ( pParaProv ) +{ +} + +PPTNumberFormatCreator::~PPTNumberFormatCreator() +{ + delete pExtParaProv; +} + +sal_Bool PPTNumberFormatCreator::ImplGetExtNumberFormat( SdrPowerPointImport& rManager, + SvxNumberFormat& rNumberFormat, sal_uInt32 nLevel, sal_uInt32 nInstance, sal_uInt32 nDestinationInstance, + boost::optional< sal_Int16 >& rStartNumbering, sal_uInt32 nFontHeight, PPTParagraphObj* pPara ) +{ + sal_Bool bHardAttribute = ( nDestinationInstance == 0xffffffff ); + + sal_uInt32 nBuFlags = 0; + sal_uInt16 nHasAnm = 0; + sal_uInt32 nAnmScheme = 0x10003; + sal_uInt16 nBuBlip = 0xffff; + + const PPTExtParaProv* pParaProv = pExtParaProv; + if ( !pExtParaProv ) + pParaProv = ( pPara ) ? pPara->mrStyleSheet.pExtParaProv + : rManager.pPPTStyleSheet->pExtParaProv; + if ( pPara ) + { + nBuFlags = pPara->pParaSet->mnExtParagraphMask; + if ( nBuFlags ) + { + if ( nBuFlags & 0x00800000 ) + nBuBlip = pPara->pParaSet->mnBuBlip; + if ( nBuFlags & 0x01000000 ) + nAnmScheme = pPara->pParaSet->mnAnmScheme; + if ( nBuFlags & 0x02000000 ) + nHasAnm = pPara->pParaSet->mnHasAnm; + bHardAttribute = sal_True; + } + } + + if ( ( nBuFlags & 0x03800000 ) != 0x03800000 ) // merge style sheet + { // we have to read the master attributes + if ( pParaProv && ( nLevel < 5 ) ) + { + if ( pParaProv->bStyles ) + { + const PPTExtParaLevel& rLev = pParaProv->aExtParaSheet[ nInstance ].aExtParaLevel[ nLevel ]; + if ( rLev.mbSet ) + { + sal_uInt32 nMaBuFlags = rLev.mnExtParagraphMask; + + if ( (!( nBuFlags & 0x00800000)) && ( nMaBuFlags & 0x00800000 ) ) + { + if (!( nBuFlags & 0x02000000)) // if there is a BuStart without BuInstance, + nBuBlip = rLev.mnBuBlip; // then there is no graphical Bullet possible + } + if ( (!( nBuFlags & 0x01000000)) && ( nMaBuFlags & 0x01000000 ) ) + nAnmScheme = rLev.mnAnmScheme; + if ( (!( nBuFlags & 0x02000000)) && ( nMaBuFlags & 0x02000000 ) ) + nHasAnm = rLev.mnHasAnm; + nBuFlags |= nMaBuFlags; + } + } + } + } + if ( nBuBlip != 0xffff ) // set graphical bullet + { + Graphic aGraphic; + if ( pParaProv->GetGraphic( nBuBlip, aGraphic ) ) + { + SvxBrushItem aBrush( aGraphic, GPOS_MM, SID_ATTR_BRUSH ); + rNumberFormat.SetGraphicBrush( &aBrush ); + sal_uInt32 nHeight = (sal_uInt32)( (double)nFontHeight * 0.2540 * nBulletHeight + 0.5 ); + Size aPrefSize( aGraphic.GetPrefSize() ); + sal_uInt32 nWidth = ( nHeight * aPrefSize.Width() ) / aPrefSize.Height(); + rNumberFormat.SetGraphicSize( Size( nWidth, nHeight ) ); + rNumberFormat.SetNumberingType ( SVX_NUM_BITMAP ); + } + } + else if ( nHasAnm ) + { + switch( static_cast< sal_uInt16 >( nAnmScheme ) ) + { + default : + case 0 : + { + rNumberFormat.SetNumberingType( SVX_NUM_CHARS_LOWER_LETTER ); + rNumberFormat.SetSuffix( String( RTL_CONSTASCII_USTRINGPARAM( "." ) ) ); + } + break; + case 1 : + { + rNumberFormat.SetNumberingType( SVX_NUM_CHARS_UPPER_LETTER ); + rNumberFormat.SetSuffix( String( RTL_CONSTASCII_USTRINGPARAM( "." ) ) ); + } + break; + case 2 : + { + rNumberFormat.SetNumberingType( SVX_NUM_ARABIC ); + rNumberFormat.SetSuffix( String( RTL_CONSTASCII_USTRINGPARAM( ")" ) ) ); + } + break; + case 3 : + { + rNumberFormat.SetNumberingType( SVX_NUM_ARABIC ); + rNumberFormat.SetSuffix( String( RTL_CONSTASCII_USTRINGPARAM( "." ) ) ); + } + break; + case 4 : + { + rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_LOWER ); + rNumberFormat.SetSuffix( String( RTL_CONSTASCII_USTRINGPARAM( ")" ) ) ); + rNumberFormat.SetPrefix( String( RTL_CONSTASCII_USTRINGPARAM( "(" ) ) ); + } + break; + case 5 : + { + rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_LOWER ); + rNumberFormat.SetSuffix( String( RTL_CONSTASCII_USTRINGPARAM( ")" ) ) ); + } + break; + case 6 : + { + rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_LOWER ); + rNumberFormat.SetSuffix( String( RTL_CONSTASCII_USTRINGPARAM( "." ) ) ); + } + break; + case 7 : + { + rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_UPPER ); + rNumberFormat.SetSuffix( String( RTL_CONSTASCII_USTRINGPARAM( "." ) ) ); + } + break; + case 8 : + { + rNumberFormat.SetNumberingType( SVX_NUM_CHARS_LOWER_LETTER ); + rNumberFormat.SetSuffix( String( RTL_CONSTASCII_USTRINGPARAM( ")" ) ) ); + rNumberFormat.SetPrefix( String( RTL_CONSTASCII_USTRINGPARAM( "(" ) ) ); + } + break; + case 9 : + { + rNumberFormat.SetNumberingType( SVX_NUM_CHARS_LOWER_LETTER ); + rNumberFormat.SetSuffix( String( RTL_CONSTASCII_USTRINGPARAM( ")" ) ) ); + } + break; + case 10 : + { + rNumberFormat.SetNumberingType( SVX_NUM_CHARS_UPPER_LETTER ); + rNumberFormat.SetSuffix( String( RTL_CONSTASCII_USTRINGPARAM( ")" ) ) ); + rNumberFormat.SetPrefix( String( RTL_CONSTASCII_USTRINGPARAM( "(" ) ) ); + } + break; + case 11 : + { + rNumberFormat.SetNumberingType( SVX_NUM_CHARS_UPPER_LETTER ); + rNumberFormat.SetSuffix( String( RTL_CONSTASCII_USTRINGPARAM( ")" ) ) ); + } + break; + case 12 : + { + rNumberFormat.SetNumberingType( SVX_NUM_ARABIC ); + rNumberFormat.SetSuffix( String( RTL_CONSTASCII_USTRINGPARAM( ")" ) ) ); + rNumberFormat.SetPrefix( String( RTL_CONSTASCII_USTRINGPARAM( "(" ) ) ); + } + break; + case 13 : + { + rNumberFormat.SetNumberingType( SVX_NUM_ARABIC ); + } + break; + case 14 : + { + rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_UPPER ); + rNumberFormat.SetSuffix( String( RTL_CONSTASCII_USTRINGPARAM( ")" ) ) ); + rNumberFormat.SetPrefix( String( RTL_CONSTASCII_USTRINGPARAM( "(" ) ) ); + } + break; + case 15 : + { + rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_UPPER ); + rNumberFormat.SetSuffix( String( RTL_CONSTASCII_USTRINGPARAM( ")" ) ) ); + } + break; + } + rStartNumbering = boost::optional< sal_Int16 >( nAnmScheme >> 16 ); + } + return bHardAttribute; +} + +void PPTNumberFormatCreator::GetNumberFormat( SdrPowerPointImport& rManager, SvxNumberFormat& rNumberFormat, sal_uInt32 nLevel, const PPTParaLevel& rParaLevel, const PPTCharLevel& rCharLevel, sal_uInt32 nInstance ) +{ + nIsBullet = ( rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BulletOn ) ) != 0 ? 1 : 0; + nBulletChar = rParaLevel.mnBulletChar; + + sal_Bool bBuHardFont; + bBuHardFont = ( rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BuHardFont ) ) != 0; + if ( bBuHardFont ) + nBulletFont = rParaLevel.mnBulletFont; + else + nBulletFont = rCharLevel.mnFont; + nBulletHeight = rParaLevel.mnBulletHeight; + nBulletColor = rParaLevel.mnBulletColor; + nTextOfs = rParaLevel.mnTextOfs; + nBulletOfs = rParaLevel.mnBulletOfs; + + boost::optional< sal_Int16 > oStartNumbering; + ImplGetExtNumberFormat( rManager, rNumberFormat, nLevel, nInstance, 0xffffffff, oStartNumbering, rCharLevel.mnFontHeight, NULL ); + if ( ( rNumberFormat.GetNumberingType() != SVX_NUM_BITMAP ) && ( nBulletHeight > 0x7fff ) ) + nBulletHeight = rCharLevel.mnFontHeight ? ((-((sal_Int16)nBulletHeight)) * 100 ) / rCharLevel.mnFontHeight : 100; + ImplGetNumberFormat( rManager, rNumberFormat, nLevel ); + switch ( rNumberFormat.GetNumberingType() ) + { + case SVX_NUM_CHARS_UPPER_LETTER : + case SVX_NUM_CHARS_LOWER_LETTER : + case SVX_NUM_ROMAN_UPPER : + case SVX_NUM_ROMAN_LOWER : + case SVX_NUM_ARABIC : + case SVX_NUM_CHARS_UPPER_LETTER_N : + case SVX_NUM_CHARS_LOWER_LETTER_N : + { + sal_uInt32 nFont = rCharLevel.mnFont; + PptFontEntityAtom* pFontEnityAtom = rManager.GetFontEnityAtom( nFont ); + if ( pFontEnityAtom ) + { + Font aFont; + aFont.SetCharSet( pFontEnityAtom->eCharSet ); + aFont.SetName( pFontEnityAtom->aName ); + aFont.SetFamily( pFontEnityAtom->eFamily ); + aFont.SetPitch( pFontEnityAtom->ePitch ); + rNumberFormat.SetBulletFont( &aFont ); + } + } + break; + } +} + +sal_Bool PPTNumberFormatCreator::GetNumberFormat( SdrPowerPointImport& rManager, SvxNumberFormat& rNumberFormat, PPTParagraphObj* pParaObj, + sal_uInt32 nDestinationInstance, boost::optional< sal_Int16 >& rStartNumbering ) +{ + sal_uInt32 nHardCount = 0; + nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletOn, nIsBullet, nDestinationInstance ); + nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletChar, nBulletChar, nDestinationInstance ); + nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletFont, nBulletFont, nDestinationInstance ); + nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletHeight, nBulletHeight, nDestinationInstance ); + nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletColor, nBulletColor, nDestinationInstance ); + nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_TextOfs, nTextOfs, nDestinationInstance ); + nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletOfs, nBulletOfs, nDestinationInstance ); + + if ( nIsBullet ) + rNumberFormat.SetNumberingType( SVX_NUM_CHAR_SPECIAL ); + + sal_uInt32 nFontHeight = 24; + PPTPortionObj* pPtr = pParaObj->First(); + if ( pPtr ) + pPtr->GetAttrib( PPT_CharAttr_FontHeight, nFontHeight, nDestinationInstance ); + if ( nIsBullet ) + nHardCount += ImplGetExtNumberFormat( rManager, rNumberFormat, pParaObj->pParaSet->mnDepth, + pParaObj->mnInstance, nDestinationInstance, rStartNumbering, nFontHeight, pParaObj ); + + if ( rNumberFormat.GetNumberingType() != SVX_NUM_BITMAP ) + pParaObj->UpdateBulletRelSize( nBulletHeight ); + if ( nHardCount ) + ImplGetNumberFormat( rManager, rNumberFormat, pParaObj->pParaSet->mnDepth ); + + if ( nHardCount ) + { + switch ( rNumberFormat.GetNumberingType() ) + { + case SVX_NUM_CHARS_UPPER_LETTER : + case SVX_NUM_CHARS_LOWER_LETTER : + case SVX_NUM_ROMAN_UPPER : + case SVX_NUM_ROMAN_LOWER : + case SVX_NUM_ARABIC : + case SVX_NUM_CHARS_UPPER_LETTER_N : + case SVX_NUM_CHARS_LOWER_LETTER_N : + { + if ( pPtr ) + { + sal_uInt32 nFont; + pPtr->GetAttrib( PPT_CharAttr_Font, nFont, nDestinationInstance ); + PptFontEntityAtom* pFontEnityAtom = rManager.GetFontEnityAtom( nFont ); + if ( pFontEnityAtom ) + { + Font aFont; + aFont.SetCharSet( pFontEnityAtom->eCharSet ); + aFont.SetName( pFontEnityAtom->aName ); + aFont.SetFamily( pFontEnityAtom->eFamily ); + aFont.SetPitch( pFontEnityAtom->ePitch ); + rNumberFormat.SetBulletFont( &aFont ); + } + } + } + break; + } + } + return ( nHardCount ) ? sal_True : sal_False; +} + +void PPTNumberFormatCreator::ImplGetNumberFormat( SdrPowerPointImport& rManager, SvxNumberFormat& rNumberFormat, sal_uInt32 /*nLevel*/) +{ + Font aFont; + PptFontEntityAtom* pAtom = rManager.GetFontEnityAtom( nBulletFont ); + if ( pAtom ) + { + CharSet eCharSet( pAtom->eCharSet ); + aFont.SetName( pAtom->aName ); + aFont.SetCharSet( eCharSet ); + aFont.SetFamily( pAtom->eFamily ); + aFont.SetPitch( pAtom->ePitch ); + } + Color aCol( rManager.MSO_TEXT_CLR_ToColor( nBulletColor ) ); + aFont.SetColor( aCol ); + + sal_uInt16 nBuChar = (sal_uInt16)nBulletChar; + if ( aFont.GetCharSet() == RTL_TEXTENCODING_SYMBOL ) + { + nBuChar &= 0x00ff; + nBuChar |= 0xf000; + } + rNumberFormat.SetBulletFont( &aFont ); + rNumberFormat.SetBulletChar( nBuChar ); + rNumberFormat.SetBulletRelSize( (sal_uInt16)nBulletHeight ); + rNumberFormat.SetBulletColor( aCol ); + sal_uInt16 nAbsLSpace = (sal_uInt16)( ( (sal_uInt32)nTextOfs * 2540 ) / 576 ); + sal_uInt16 nFirstLineOffset = nAbsLSpace - (sal_uInt16)( ( (sal_uInt32)nBulletOfs * 2540 ) / 576 ); + rNumberFormat.SetAbsLSpace( nAbsLSpace ); + rNumberFormat.SetFirstLineOffset( -nFirstLineOffset ); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +PPTCharSheet::PPTCharSheet( sal_uInt32 nInstance ) +{ + sal_uInt32 nColor = PPT_COLSCHEME_TEXT_UND_ZEILEN; + sal_uInt16 nFontHeight(0); + switch ( nInstance ) + { + case TSS_TYPE_PAGETITLE : + case TSS_TYPE_TITLE : + { + nColor = PPT_COLSCHEME_TITELTEXT; + nFontHeight = 44; + } + break; + case TSS_TYPE_BODY : + case TSS_TYPE_SUBTITLE : + case TSS_TYPE_HALFBODY : + case TSS_TYPE_QUARTERBODY : + nFontHeight = 32; + break; + case TSS_TYPE_NOTES : + nFontHeight = 12; + break; + case TSS_TYPE_UNUSED : + case TSS_TYPE_TEXT_IN_SHAPE : + nFontHeight = 24; + break; + } + for ( sal_uInt32 nDepth = 0; nDepth < 5; nDepth++ ) + { + maCharLevel[ nDepth ].mnFlags = 0; + maCharLevel[ nDepth ].mnFont = 0; + maCharLevel[ nDepth ].mnAsianOrComplexFont = 0xffff; + maCharLevel[ nDepth ].mnFontHeight = nFontHeight; + maCharLevel[ nDepth ].mnFontColor = nColor; + maCharLevel[ nDepth ].mnFontColorInStyleSheet = Color( (sal_uInt8)nColor, (sal_uInt8)( nColor >> 8 ), (sal_uInt8)( nColor >> 16 ) ); + maCharLevel[ nDepth ].mnEscapement = 0; + } +} + +PPTCharSheet::PPTCharSheet( const PPTCharSheet& rAttr ) +{ + *this = rAttr; +} + +void PPTCharSheet::Read( SvStream& rIn, sal_Bool /*bMasterStyle*/, sal_uInt32 nLevel, sal_Bool /*bFirst*/) +{ + // Zeichenattribute + sal_uInt32 nCMask; + sal_uInt16 nVal16; + rIn >> nCMask; + + if ( nCMask & 0x0000FFFF ) + { + sal_uInt16 nBitAttr; + maCharLevel[ nLevel ].mnFlags &= ~( (sal_uInt16)nCMask ); + rIn >> nBitAttr; // Bit-Attribute (Fett, Unterstrichen, ...) + maCharLevel[ nLevel ].mnFlags |= nBitAttr; + } + if ( nCMask & ( 1 << PPT_CharAttr_Font ) ) // 0x00010000 + rIn >> maCharLevel[ nLevel ].mnFont; + if ( nCMask & ( 1 << PPT_CharAttr_AsianOrComplexFont ) ) // 0x00200000 + rIn >> maCharLevel[ nLevel ].mnAsianOrComplexFont; + if ( nCMask & ( 1 << PPT_CharAttr_ANSITypeface ) ) // 0x00400000 + rIn >> nVal16; + if ( nCMask & ( 1 << PPT_CharAttr_Symbol ) ) // 0x00800000 + rIn >> nVal16; + if ( nCMask & ( 1 << PPT_CharAttr_FontHeight ) ) // 0x00020000 + rIn >> maCharLevel[ nLevel ].mnFontHeight; + if ( nCMask & ( 1 << PPT_CharAttr_FontColor ) ) // 0x00040000 + { + rIn >> maCharLevel[ nLevel ].mnFontColor; + if( ! (maCharLevel[ nLevel ].mnFontColor & 0xff000000 ) ) + maCharLevel[ nLevel ].mnFontColor = PPT_COLSCHEME_HINTERGRUND; + } + if ( nCMask & ( 1 << PPT_CharAttr_Escapement ) ) // 0x00080000 + rIn >> maCharLevel[ nLevel ].mnEscapement; + if ( nCMask & 0x00100000 ) // 0x00100000 + rIn >> nVal16; + + nCMask >>= 24; + while( nCMask ) + { + if ( nCMask & 1 ) + { + DBG_ERROR( "PPTCharSheet::Read - unknown attribute, send me this document (SJ)" ); + rIn >> nVal16; + } + nCMask >>= 1; + } +} + +PPTParaSheet::PPTParaSheet( sal_uInt32 nInstance ) +{ + sal_uInt16 nBuFlags = 0; + sal_uInt32 nBulletColor = 0x8000000; + sal_uInt16 nUpperDist = 0; + + switch ( nInstance ) + { + case TSS_TYPE_PAGETITLE : + case TSS_TYPE_TITLE : + nBulletColor = PPT_COLSCHEME_TITELTEXT; + break; + case TSS_TYPE_BODY : + case TSS_TYPE_SUBTITLE : + case TSS_TYPE_HALFBODY : + case TSS_TYPE_QUARTERBODY : + { + nBuFlags = 1; + nUpperDist = 0x14; + } + break; + case TSS_TYPE_NOTES : + nUpperDist = 0x1e; + break; +/* + default : + case TSS_TYPE_UNUSED : + case TSS_TYPE_TEXT_IN_SHAPE : + break; +*/ + } + for ( sal_uInt32 i = 0; i < 5; i++ ) + { + maParaLevel[ i ].mnBuFlags = nBuFlags; + maParaLevel[ i ].mnBulletChar = 0x2022; + maParaLevel[ i ].mnBulletFont = 0; + maParaLevel[ i ].mnBulletHeight = 100; + maParaLevel[ i ].mnBulletColor = nBulletColor; + maParaLevel[ i ].mnAdjust = 0; + maParaLevel[ i ].mnLineFeed = 100; + maParaLevel[ i ].mnLowerDist = 0; + maParaLevel[ i ].mnUpperDist = nUpperDist; + maParaLevel[ i ].mnTextOfs = 0; + maParaLevel[ i ].mnBulletOfs = 0; + maParaLevel[ i ].mnDefaultTab = 0x240; + maParaLevel[ i ].mnAsianLineBreak = 0; + maParaLevel[ i ].mnBiDi = 0; + } +} + +PPTParaSheet::PPTParaSheet( const PPTParaSheet& rSheet ) +{ + *this = rSheet; +} + +void PPTParaSheet::Read( SdrPowerPointImport& +#ifdef DBG_UTIL + rManager +#endif + , SvStream& rIn, sal_Bool /*bMasterStyle*/, + sal_uInt32 nLevel, sal_Bool bFirst ) +{ + // Absatzattribute + sal_uInt16 nVal16, i, nMask16; + sal_uInt32 nVal32, nPMask; + rIn >> nPMask; + + nMask16 = (sal_uInt16)nPMask & 0xf; + if ( nMask16 ) + { + rIn >> nVal16; + maParaLevel[ nLevel ].mnBuFlags &=~ nMask16; + nVal16 &= nMask16; + maParaLevel[ nLevel ].mnBuFlags |= nVal16; + } + if ( nPMask & 0x0080 ) + rIn >> maParaLevel[ nLevel ].mnBulletChar; + if ( nPMask & 0x0010 ) + rIn >> maParaLevel[ nLevel ].mnBulletFont; + if ( nPMask & 0x0040 ) + { + rIn >> nVal16; + maParaLevel[ nLevel ].mnBulletHeight = nVal16; + } + if ( nPMask & 0x0020 ) + { + rIn >> nVal32; + maParaLevel[ nLevel ].mnBulletColor = nVal32; + } + if ( bFirst ) + { + if ( nPMask & 0xF00 ) + { // AbsJust! + rIn >> nVal16; + maParaLevel[ nLevel ].mnAdjust = nVal16 & 3; + } + if ( nPMask & 0x1000 ) + rIn >> maParaLevel[ nLevel ].mnLineFeed; + if ( nPMask & 0x2000 ) + rIn >> maParaLevel[ nLevel ].mnUpperDist; + if ( nPMask & 0x4000 ) + rIn >> maParaLevel[ nLevel ].mnLowerDist; + if ( nPMask & 0x8000 ) + rIn >> maParaLevel[ nLevel ].mnTextOfs; + if ( nPMask & 0x10000 ) + rIn >> maParaLevel[ nLevel ].mnBulletOfs; + if ( nPMask & 0x20000 ) + rIn >> maParaLevel[ nLevel ].mnDefaultTab; + if ( nPMask & 0x200000 ) + { + // number of tabulators + rIn >> nVal16; + for ( i = 0; i < nVal16; i++ ) + rIn >> nVal32; // reading the tabulators + } + if ( nPMask & 0x40000 ) + rIn >> nVal16; + if ( nPMask & 0x80000 ) + rIn >> maParaLevel[ nLevel ].mnAsianLineBreak; + if ( nPMask & 0x100000 ) + rIn >> maParaLevel[ nLevel ].mnBiDi; + } + else + { + if ( nPMask & 0x800 ) + { + rIn >> nVal16; + maParaLevel[ nLevel ].mnAdjust = nVal16 & 3; + } + if ( nPMask & 0x1000 ) + rIn >> maParaLevel[ nLevel ].mnLineFeed; + if ( nPMask & 0x2000 ) + rIn >> maParaLevel[ nLevel ].mnUpperDist; + if ( nPMask & 0x4000 ) + rIn >> maParaLevel[ nLevel ].mnLowerDist; + if ( nPMask & 0x8000 ) + rIn >> nVal16; + if ( nPMask & 0x100 ) + rIn >> maParaLevel[ nLevel ].mnTextOfs; + if ( nPMask & 0x200 ) + rIn >> nVal16; + if ( nPMask & 0x400 ) + rIn >> maParaLevel[ nLevel ].mnBulletOfs; + if ( nPMask & 0x10000 ) + rIn >> nVal16; + if ( nPMask & 0xe0000 ) + { + sal_uInt16 nFlagsToModifyMask = (sal_uInt16)( ( nPMask >> 17 ) & 7 ); + rIn >> nVal16; + // bits that are not involved to zero + nVal16 &= nFlagsToModifyMask; + // bits that are to change to zero + maParaLevel[ nLevel ].mnAsianLineBreak &=~nFlagsToModifyMask; + // now set the corresponding bits + maParaLevel[ nLevel ].mnAsianLineBreak |= nVal16; + } + if ( nPMask & 0x100000 ) + { + // number of tabulators + rIn >> nVal16; + for ( i = 0; i < nVal16; i++ ) + rIn >> nVal32; // reading the tabulators + } + if ( nPMask & 0x200000 ) + rIn >> maParaLevel[ nLevel ].mnBiDi; // #88602# + } + + nPMask >>= 22; + while( nPMask ) + { + if ( nPMask & 1 ) + { +#ifdef DBG_UTIL + if (!(rManager.rImportParam.nImportFlags & PPT_IMPORTFLAGS_NO_TEXT_ASSERT)) + { + DBG_ERROR( "PPTParaSheet::Read - unknown attribute, send me this document (SJ)" ); + } +#endif + rIn >> nVal16; + } + nPMask >>= 1; + } +} + +PPTStyleSheet::PPTStyleSheet( const DffRecordHeader& rSlideHd, SvStream& rIn, SdrPowerPointImport& rManager, + const PPTTextCharacterStyleAtomInterpreter& /*rTxCFStyle*/, const PPTTextParagraphStyleAtomInterpreter& rTxPFStyle, + const PPTTextSpecInfo& rTextSpecInfo ) : + + PPTNumberFormatCreator ( new PPTExtParaProv( rManager, rIn, &rSlideHd ) ), + maTxSI ( rTextSpecInfo ) +{ + sal_uInt32 i; + sal_uInt32 nOldFilePos = rIn.Tell(); + + // default stylesheets + mpCharSheet[ TSS_TYPE_PAGETITLE ] = new PPTCharSheet( TSS_TYPE_PAGETITLE ); + mpCharSheet[ TSS_TYPE_BODY ] = new PPTCharSheet( TSS_TYPE_BODY ); + mpCharSheet[ TSS_TYPE_NOTES ] = new PPTCharSheet( TSS_TYPE_NOTES ); + mpCharSheet[ TSS_TYPE_UNUSED ] = new PPTCharSheet( TSS_TYPE_UNUSED ); // this entry is not used by ppt + mpCharSheet[ TSS_TYPE_TEXT_IN_SHAPE ] = new PPTCharSheet( TSS_TYPE_TEXT_IN_SHAPE ); + mpParaSheet[ TSS_TYPE_PAGETITLE ] = new PPTParaSheet( TSS_TYPE_PAGETITLE ); + mpParaSheet[ TSS_TYPE_BODY ] = new PPTParaSheet( TSS_TYPE_BODY ); + mpParaSheet[ TSS_TYPE_NOTES ] = new PPTParaSheet( TSS_TYPE_NOTES ); + mpParaSheet[ TSS_TYPE_UNUSED ] = new PPTParaSheet( TSS_TYPE_UNUSED ); + mpParaSheet[ TSS_TYPE_TEXT_IN_SHAPE ] = new PPTParaSheet( TSS_TYPE_TEXT_IN_SHAPE ); + mpCharSheet[ TSS_TYPE_QUARTERBODY ] = mpCharSheet[ TSS_TYPE_HALFBODY ] = mpCharSheet[ TSS_TYPE_TITLE ] = mpCharSheet[ TSS_TYPE_SUBTITLE ] = NULL; + mpParaSheet[ TSS_TYPE_QUARTERBODY ] = mpParaSheet[ TSS_TYPE_HALFBODY ] = mpParaSheet[ TSS_TYPE_TITLE ] = mpParaSheet[ TSS_TYPE_SUBTITLE ] = NULL; + + /* SJ: try to locate the txMasterStyleAtom in the Environment + + it seems that the environment TextStyle is having a higher priority + than the TextStyle that can be found within the master page + */ + sal_Bool bFoundTxMasterStyleAtom04 = sal_False; + DffRecordHeader* pEnvHeader = rManager.aDocRecManager.GetRecordHeader( PPT_PST_Environment ); + if ( pEnvHeader ) + { + pEnvHeader->SeekToContent( rIn ); + DffRecordHeader aTxMasterStyleHd; + while ( rIn.Tell() < pEnvHeader->GetRecEndFilePos() ) + { + rIn >> aTxMasterStyleHd; + if ( aTxMasterStyleHd.nRecType == PPT_PST_TxMasterStyleAtom ) + { + sal_uInt16 nLevelAnz; + rIn >> nLevelAnz; + + sal_uInt16 nLev = 0; + sal_Bool bFirst = sal_True; + bFoundTxMasterStyleAtom04 = sal_True; + while ( rIn.GetError() == 0 && rIn.Tell() < aTxMasterStyleHd.GetRecEndFilePos() && nLev < nLevelAnz ) + { + if ( nLev ) + { + mpParaSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->maParaLevel[ nLev ] = mpParaSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->maParaLevel[ nLev - 1 ]; + mpCharSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->maCharLevel[ nLev ] = mpCharSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->maCharLevel[ nLev - 1 ]; + } + mpParaSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->Read( rManager, rIn, sal_True, nLev, bFirst ); + if ( !nLev ) + { + // set paragraph defaults for instance 4 (TSS_TYPE_TEXT_IN_SHAPE) + if ( rTxPFStyle.bValid ) + { + PPTParaLevel& rParaLevel = mpParaSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->maParaLevel[ 0 ]; + rParaLevel.mnAsianLineBreak = 0; + if ( rTxPFStyle.bForbiddenRules ) + rParaLevel.mnAsianLineBreak |= 1; + if ( !rTxPFStyle.bLatinTextWrap ) + rParaLevel.mnAsianLineBreak |= 2; + if ( rTxPFStyle.bHangingPunctuation ) + rParaLevel.mnAsianLineBreak |= 4; + } + } + mpCharSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->Read( rIn, sal_True, nLev, bFirst ); + bFirst = sal_False; + nLev++; + } + break; + } + else + aTxMasterStyleHd.SeekToEndOfRecord( rIn ); + } + } + + rSlideHd.SeekToContent( rIn ); + DffRecordHeader aTxMasterStyleHd; + while ( rIn.Tell() < rSlideHd.GetRecEndFilePos() ) + { + rIn >> aTxMasterStyleHd; + if ( aTxMasterStyleHd.nRecType == PPT_PST_TxMasterStyleAtom ) + break; + else + aTxMasterStyleHd.SeekToEndOfRecord( rIn ); + } + while ( ( aTxMasterStyleHd.nRecType == PPT_PST_TxMasterStyleAtom ) && ( rIn.Tell() < rSlideHd.GetRecEndFilePos() ) ) //TODO: aTxMasterStyleHd may be used without having been properly initialized + { + sal_uInt32 nInstance = aTxMasterStyleHd.nRecInstance; + if ( ( nInstance < PPT_STYLESHEETENTRYS ) && + ( ( nInstance != TSS_TYPE_TEXT_IN_SHAPE ) || ( bFoundTxMasterStyleAtom04 == sal_False ) ) ) + { + if ( nInstance > 4 ) + { + delete mpCharSheet[ nInstance ]; // be sure to delete the old one if this instance comes twice + delete mpParaSheet[ nInstance ]; + + switch ( nInstance ) + { + case TSS_TYPE_SUBTITLE : + { + mpCharSheet[ TSS_TYPE_SUBTITLE ] = new PPTCharSheet( *( mpCharSheet[ TSS_TYPE_BODY ] ) ); + mpParaSheet[ TSS_TYPE_SUBTITLE ] = new PPTParaSheet( *( mpParaSheet[ TSS_TYPE_BODY ] ) ); + } + break; + case TSS_TYPE_TITLE : + { + mpCharSheet[ TSS_TYPE_TITLE ] = new PPTCharSheet( *( mpCharSheet[ TSS_TYPE_PAGETITLE ] ) ); + mpParaSheet[ TSS_TYPE_TITLE ] = new PPTParaSheet( *( mpParaSheet[ TSS_TYPE_PAGETITLE ] ) ); + } + break; + case TSS_TYPE_HALFBODY : + { + mpCharSheet[ TSS_TYPE_HALFBODY ] = new PPTCharSheet( *( mpCharSheet[ TSS_TYPE_BODY ] ) ); + mpParaSheet[ TSS_TYPE_HALFBODY ] = new PPTParaSheet( *( mpParaSheet[ TSS_TYPE_BODY ] ) ); + } + break; + + case TSS_TYPE_QUARTERBODY : + { + mpCharSheet[ TSS_TYPE_QUARTERBODY ] = new PPTCharSheet( *( mpCharSheet[ TSS_TYPE_BODY ] ) ); + mpParaSheet[ TSS_TYPE_QUARTERBODY ] = new PPTParaSheet( *( mpParaSheet[ TSS_TYPE_BODY ] ) ); + } + break; + } + } + sal_uInt16 nLevelAnz; + rIn >> nLevelAnz; + if ( nLevelAnz > 5 ) + { + DBG_ERROR( "PPTStyleSheet::Ppt-TextStylesheet hat mehr als 5 Ebenen! (SJ)" ); + nLevelAnz = 5; + } + sal_uInt16 nLev = 0; + sal_Bool bFirst = sal_True; + + while ( rIn.GetError() == 0 && rIn.Tell() < aTxMasterStyleHd.GetRecEndFilePos() && nLev < nLevelAnz ) + { + if ( nLev && ( nInstance < 5 ) ) + { + mpParaSheet[ nInstance ]->maParaLevel[ nLev ] = mpParaSheet[ nInstance ]->maParaLevel[ nLev - 1 ]; + mpCharSheet[ nInstance ]->maCharLevel[ nLev ] = mpCharSheet[ nInstance ]->maCharLevel[ nLev - 1 ]; + } + + // Ausnahme: Vorlage 5, 6 (MasterTitle Titel und SubTitel) + if ( nInstance >= TSS_TYPE_SUBTITLE ) + { + bFirst = sal_False; + + sal_uInt16 nDontKnow; + rIn >> nDontKnow; + } + mpParaSheet[ nInstance ]->Read( rManager, rIn, sal_True, nLev, bFirst ); + mpCharSheet[ nInstance ]->Read( rIn, sal_True, nLev, bFirst ); + bFirst = sal_False; + nLev++; + } +#ifdef DBG_UTIL + if (!(rManager.rImportParam.nImportFlags & PPT_IMPORTFLAGS_NO_TEXT_ASSERT)) + { + if ( rIn.GetError() == 0 ) + { + ByteString aMsg; + if ( rIn.Tell() > aTxMasterStyleHd.GetRecEndFilePos() ) + { + aMsg += "\n "; + aMsg += "reading too many bytes:"; + aMsg += ByteString::CreateFromInt32( rIn.Tell() - aTxMasterStyleHd.GetRecEndFilePos() ); + } + if ( rIn.Tell() < aTxMasterStyleHd.GetRecEndFilePos() ) + { + aMsg += "\n "; + aMsg += "reading too less bytes:"; + aMsg += ByteString::CreateFromInt32( aTxMasterStyleHd.GetRecEndFilePos() - rIn.Tell() ); + } + if ( aMsg.Len() != 0 ) + { + aMsg.Insert( "]:", 0 ); + aMsg.Insert( "PptStyleSheet::operator>>[", 0 ); + DBG_ERROR(aMsg.GetBuffer()); + } + } + if ( rIn.Tell() != aTxMasterStyleHd.GetRecEndFilePos() ) + DBG_ASSERT(0, "SJ: Falsche Anzahl von Bytes gelesen beim Import der PPT-Formatvorlagen"); + } +#endif + } + aTxMasterStyleHd.SeekToEndOfRecord( rIn ); + rIn >> aTxMasterStyleHd; + } + if ( !mpCharSheet[ TSS_TYPE_SUBTITLE ] ) + { + mpCharSheet[ TSS_TYPE_SUBTITLE ] = new PPTCharSheet( *( mpCharSheet[ TSS_TYPE_BODY ] ) ); + mpParaSheet[ TSS_TYPE_SUBTITLE ] = new PPTParaSheet( *( mpParaSheet[ TSS_TYPE_BODY ] ) ); + } + if ( !mpCharSheet[ TSS_TYPE_TITLE ] ) + { + mpCharSheet[ TSS_TYPE_TITLE ] = new PPTCharSheet( *( mpCharSheet[ TSS_TYPE_PAGETITLE ] ) ); + mpParaSheet[ TSS_TYPE_TITLE ] = new PPTParaSheet( *( mpParaSheet[ TSS_TYPE_PAGETITLE ] ) ); + } + if ( !mpCharSheet[ TSS_TYPE_HALFBODY ] ) + { + mpCharSheet[ TSS_TYPE_HALFBODY ] = new PPTCharSheet( *( mpCharSheet[ TSS_TYPE_BODY ] ) ); + mpParaSheet[ TSS_TYPE_HALFBODY ] = new PPTParaSheet( *( mpParaSheet[ TSS_TYPE_BODY ] ) ); + } + if ( !mpCharSheet[ TSS_TYPE_QUARTERBODY ] ) + { + mpCharSheet[ TSS_TYPE_QUARTERBODY ] = new PPTCharSheet( *( mpCharSheet[ TSS_TYPE_BODY ] ) ); + mpParaSheet[ TSS_TYPE_QUARTERBODY ] = new PPTParaSheet( *( mpParaSheet[ TSS_TYPE_BODY ] ) ); + } + if ( !bFoundTxMasterStyleAtom04 ) + { // try to locate the txMasterStyleAtom in the Environment + DffRecordHeader* pEnvHeader2 = rManager.aDocRecManager.GetRecordHeader( PPT_PST_Environment ); + if ( pEnvHeader2 ) + { + pEnvHeader2->SeekToContent( rIn ); + DffRecordHeader aTxMasterStyleHd2; + while ( rIn.Tell() < pEnvHeader2->GetRecEndFilePos() ) + { + rIn >> aTxMasterStyleHd2; + if ( aTxMasterStyleHd2.nRecType == PPT_PST_TxMasterStyleAtom ) + { + sal_uInt16 nLevelAnz; + rIn >> nLevelAnz; + + sal_uInt16 nLev = 0; + sal_Bool bFirst = sal_True; + while ( rIn.GetError() == 0 && rIn.Tell() < aTxMasterStyleHd2.GetRecEndFilePos() && nLev < nLevelAnz ) + { + if ( nLev ) + { + mpParaSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->maParaLevel[ nLev ] = mpParaSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->maParaLevel[ nLev - 1 ]; + mpCharSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->maCharLevel[ nLev ] = mpCharSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->maCharLevel[ nLev - 1 ]; + } + mpParaSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->Read( rManager, rIn, sal_True, nLev, bFirst ); + if ( !nLev ) + { + // set paragraph defaults for instance 4 (TSS_TYPE_TEXT_IN_SHAPE) + if ( rTxPFStyle.bValid ) + { + PPTParaLevel& rParaLevel = mpParaSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->maParaLevel[ 0 ]; + rParaLevel.mnAsianLineBreak = 0; + if ( rTxPFStyle.bForbiddenRules ) + rParaLevel.mnAsianLineBreak |= 1; + if ( !rTxPFStyle.bLatinTextWrap ) + rParaLevel.mnAsianLineBreak |= 2; + if ( rTxPFStyle.bHangingPunctuation ) + rParaLevel.mnAsianLineBreak |= 4; + } + } + mpCharSheet[ TSS_TYPE_TEXT_IN_SHAPE ]->Read( rIn, sal_True, nLev, bFirst ); + bFirst = sal_False; + nLev++; + } + break; + } + else + aTxMasterStyleHd2.SeekToEndOfRecord( rIn ); + } + } + } + rIn.Seek( nOldFilePos ); + + // will will create the default numbulletitem for each instance + for ( i = 0; i < PPT_STYLESHEETENTRYS; i++ ) + { + sal_uInt16 nLevels, nDepth = 0; + SvxNumRuleType eNumRuleType; + + switch ( i ) + { + case TSS_TYPE_PAGETITLE : + case TSS_TYPE_TITLE : + nLevels = 1; + eNumRuleType = SVX_RULETYPE_NUMBERING; + break; + case TSS_TYPE_SUBTITLE : + nLevels = 10; + eNumRuleType = SVX_RULETYPE_NUMBERING; + break; + case TSS_TYPE_BODY : + case TSS_TYPE_HALFBODY : + case TSS_TYPE_QUARTERBODY : + nLevels = 10; + eNumRuleType = SVX_RULETYPE_PRESENTATION_NUMBERING; + break; + default : + case TSS_TYPE_NOTES : + case TSS_TYPE_UNUSED : + case TSS_TYPE_TEXT_IN_SHAPE : + nLevels = 10; + eNumRuleType = SVX_RULETYPE_NUMBERING; + break; + } + SvxNumRule aRule( NUM_BULLET_REL_SIZE | NUM_BULLET_COLOR | + NUM_CHAR_TEXT_DISTANCE | NUM_SYMBOL_ALIGNMENT, + nLevels, sal_False, eNumRuleType ); + for ( sal_uInt16 nCount = 0; nDepth < nLevels; nCount++ ) + { + const PPTParaLevel& rParaLevel = mpParaSheet[ i ]->maParaLevel[ nCount ]; + const PPTCharLevel& rCharLevel = mpCharSheet[ i ]->maCharLevel[ nCount ]; + SvxNumberFormat aNumberFormat( SVX_NUM_CHAR_SPECIAL ); + aNumberFormat.SetBulletChar( ' ' ); + GetNumberFormat( rManager, aNumberFormat, nCount, rParaLevel, rCharLevel, i ); + aRule.SetLevel( nDepth++, aNumberFormat ); + if ( nCount >= 4 ) + { + for ( ;nDepth < nLevels; nDepth++ ) + aRule.SetLevel( nDepth, aNumberFormat ); + if ( eNumRuleType == SVX_RULETYPE_PRESENTATION_NUMBERING ) + aRule.SetLevel( 0, aNumberFormat ); + } + } + mpNumBulletItem[ i ] = new SvxNumBulletItem( aRule, EE_PARA_NUMBULLET ); + } +} + +PPTStyleSheet::~PPTStyleSheet() +{ + for ( sal_uInt32 i = 0; i < PPT_STYLESHEETENTRYS; i++ ) + { + delete mpCharSheet[ i ]; + delete mpParaSheet[ i ]; + delete mpNumBulletItem[ i ]; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +PPTParaPropSet::PPTParaPropSet() : + pParaSet( new ImplPPTParaPropSet ) +{ + pParaSet->mnHasAnm = 1; +} + +PPTParaPropSet::PPTParaPropSet( PPTParaPropSet& rParaPropSet ) +{ + pParaSet = rParaPropSet.pParaSet; + pParaSet->mnRefCount++; + + mnOriginalTextPos = rParaPropSet.mnOriginalTextPos; +} + +PPTParaPropSet::~PPTParaPropSet() +{ + if ( ! ( --pParaSet->mnRefCount ) ) + delete pParaSet; +} + +PPTParaPropSet& PPTParaPropSet::operator=( PPTParaPropSet& rParaPropSet ) +{ + if ( this != &rParaPropSet ) + { + if ( ! ( --pParaSet->mnRefCount ) ) + delete pParaSet; + pParaSet = rParaPropSet.pParaSet; + pParaSet->mnRefCount++; + + mnOriginalTextPos = rParaPropSet.mnOriginalTextPos; + } + return *this; +} + +PPTCharPropSet::PPTCharPropSet( sal_uInt32 nParagraph ) : + mnParagraph ( nParagraph ), + mpFieldItem ( NULL ), + pCharSet ( new ImplPPTCharPropSet ) +{ + mnLanguage[ 0 ] = mnLanguage[ 1 ] = mnLanguage[ 2 ] = 0; +} + +PPTCharPropSet::PPTCharPropSet( PPTCharPropSet& rCharPropSet ) +{ + pCharSet = rCharPropSet.pCharSet; + pCharSet->mnRefCount++; + + mnParagraph = rCharPropSet.mnParagraph; + mnOriginalTextPos = rCharPropSet.mnOriginalTextPos; + maString = rCharPropSet.maString; + mpFieldItem = ( rCharPropSet.mpFieldItem ) ? new SvxFieldItem( *rCharPropSet.mpFieldItem ) : NULL; + mnLanguage[ 0 ] = rCharPropSet.mnLanguage[ 0 ]; + mnLanguage[ 1 ] = rCharPropSet.mnLanguage[ 1 ]; + mnLanguage[ 2 ] = rCharPropSet.mnLanguage[ 2 ]; +} + +PPTCharPropSet::PPTCharPropSet( PPTCharPropSet& rCharPropSet, sal_uInt32 nParagraph ) +{ + pCharSet = rCharPropSet.pCharSet; + pCharSet->mnRefCount++; + + mnParagraph = nParagraph; + mnOriginalTextPos = rCharPropSet.mnOriginalTextPos; + maString = rCharPropSet.maString; + mpFieldItem = ( rCharPropSet.mpFieldItem ) ? new SvxFieldItem( *rCharPropSet.mpFieldItem ) : NULL; + mnLanguage[ 0 ] = mnLanguage[ 1 ] = mnLanguage[ 2 ] = 0; +} + +PPTCharPropSet::~PPTCharPropSet() +{ + if ( ! ( --pCharSet->mnRefCount ) ) + delete pCharSet; + delete mpFieldItem; +} + +PPTCharPropSet& PPTCharPropSet::operator=( PPTCharPropSet& rCharPropSet ) +{ + if ( this != &rCharPropSet ) + { + if ( ! ( --pCharSet->mnRefCount ) ) + delete pCharSet; + pCharSet = rCharPropSet.pCharSet; + pCharSet->mnRefCount++; + + mnOriginalTextPos = rCharPropSet.mnOriginalTextPos; + mnParagraph = rCharPropSet.mnParagraph; + maString = rCharPropSet.maString; + mpFieldItem = ( rCharPropSet.mpFieldItem ) ? new SvxFieldItem( *rCharPropSet.mpFieldItem ) : NULL; + } + return *this; +} + +void PPTCharPropSet::ImplMakeUnique() +{ + if ( pCharSet->mnRefCount > 1 ) + { + ImplPPTCharPropSet& rOld = *pCharSet; + rOld.mnRefCount--; + pCharSet = new ImplPPTCharPropSet( rOld ); + pCharSet->mnRefCount = 1; + } +} + +void PPTCharPropSet::SetFont( sal_uInt16 nFont ) +{ + sal_uInt32 nMask = 1 << PPT_CharAttr_Font; + sal_uInt32 bDoNotMake = pCharSet->mnAttrSet & nMask; + + if ( bDoNotMake ) + bDoNotMake = nFont == pCharSet->mnFont; + + if ( !bDoNotMake ) + { + ImplMakeUnique(); + pCharSet->mnFont = nFont; + pCharSet->mnAttrSet |= nMask; + } +} + +void PPTCharPropSet::SetColor( sal_uInt32 nColor ) +{ + ImplMakeUnique(); + pCharSet->mnColor = nColor; + pCharSet->mnAttrSet |= 1 << PPT_CharAttr_FontColor; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +PPTRuler::PPTRuler() : + nRefCount ( 1 ), + nFlags ( 0 ), + pTab ( NULL ), + nTabCount ( 0 ) +{ +} + +PPTRuler::~PPTRuler() +{ + delete[] pTab; +}; + + +PPTTextRulerInterpreter::PPTTextRulerInterpreter() : + mpImplRuler ( new PPTRuler() ) +{ +} + +PPTTextRulerInterpreter::PPTTextRulerInterpreter( PPTTextRulerInterpreter& rRuler ) +{ + mpImplRuler = rRuler.mpImplRuler; + mpImplRuler->nRefCount++; +} + +PPTTextRulerInterpreter::PPTTextRulerInterpreter( sal_uInt32 nFileOfs, SdrPowerPointImport& rMan, DffRecordHeader& rHeader, SvStream& rIn ) : + mpImplRuler ( new PPTRuler() ) +{ + if ( nFileOfs != 0xffffffff ) + { + sal_uInt32 nOldPos = rIn.Tell(); + DffRecordHeader rHd; + if ( nFileOfs ) + { + rIn.Seek( nFileOfs ); + rIn >> rHd; + } + else + { + rHeader.SeekToContent( rIn ); + if ( rMan.SeekToRec( rIn, PPT_PST_TextRulerAtom, rHeader.GetRecEndFilePos(), &rHd ) ) + nFileOfs++; + } + if ( nFileOfs ) + { + sal_Int16 nTCount; + sal_Int32 i; + rIn >> mpImplRuler->nFlags; + if ( mpImplRuler->nFlags & 1 ) + rIn >> mpImplRuler->nDefaultTab; + if ( mpImplRuler->nFlags & 4 ) + { + rIn >> nTCount; + if ( nTCount ) + { + mpImplRuler->nTabCount = (sal_uInt16)nTCount; + mpImplRuler->pTab = new PPTTabEntry[ mpImplRuler->nTabCount ]; + for ( i = 0; i < nTCount; i++ ) + { + rIn >> mpImplRuler->pTab[ i ].nOffset + >> mpImplRuler->pTab[ i ].nStyle; + } + } + } + for ( i = 0; i < 5; i++ ) + { + if ( mpImplRuler->nFlags & ( 8 << i ) ) + rIn >> mpImplRuler->nTextOfs[ i ]; + if ( mpImplRuler->nFlags & ( 256 << i ) ) + rIn >> mpImplRuler->nBulletOfs[ i ]; + } + } + rIn.Seek( nOldPos ); + } +} + +sal_Bool PPTTextRulerInterpreter::GetDefaultTab( sal_uInt32 /*nLevel*/, sal_uInt16& nValue ) const +{ + if ( ! ( mpImplRuler->nFlags & 1 ) ) + return sal_False; + nValue = mpImplRuler->nDefaultTab; + return sal_True; +} + +sal_Bool PPTTextRulerInterpreter::GetTextOfs( sal_uInt32 nLevel, sal_uInt16& nValue ) const +{ + if ( ! ( ( nLevel < 5 ) && ( mpImplRuler->nFlags & ( 8 << nLevel ) ) ) ) + return sal_False; + nValue = mpImplRuler->nTextOfs[ nLevel ]; + return sal_True; +} + +sal_Bool PPTTextRulerInterpreter::GetBulletOfs( sal_uInt32 nLevel, sal_uInt16& nValue ) const +{ + if ( ! ( ( nLevel < 5 ) && ( mpImplRuler->nFlags & ( 256 << nLevel ) ) ) ) + return sal_False; + nValue = mpImplRuler->nBulletOfs[ nLevel ]; + return sal_True; +} + +PPTTextRulerInterpreter& PPTTextRulerInterpreter::operator=( PPTTextRulerInterpreter& rRuler ) +{ + if ( this != &rRuler ) + { + if ( ! ( --mpImplRuler->nRefCount ) ) + delete mpImplRuler; + mpImplRuler = rRuler.mpImplRuler; + mpImplRuler->nRefCount++; + } + return *this; +} + +PPTTextRulerInterpreter::~PPTTextRulerInterpreter() +{ + if ( ! ( --mpImplRuler->nRefCount ) ) + delete mpImplRuler; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +PPTTextCharacterStyleAtomInterpreter::PPTTextCharacterStyleAtomInterpreter() : + nFlags1 ( 0 ), + nFlags2 ( 0 ), + nFlags3 ( 0 ) +{ +} + +sal_Bool PPTTextCharacterStyleAtomInterpreter::Read( SvStream& rIn, const DffRecordHeader& rRecHd ) +{ + rRecHd.SeekToContent( rIn ); + + rIn >> nFlags1 + >> nFlags2 + >> nFlags3 + >> n1 + >> nFontHeight + >> nFontColor; + + return sal_True; +} + +PPTTextCharacterStyleAtomInterpreter::~PPTTextCharacterStyleAtomInterpreter() +{ +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +PPTTextParagraphStyleAtomInterpreter::PPTTextParagraphStyleAtomInterpreter() : + bValid ( sal_False ), + bForbiddenRules ( sal_False ), + bHangingPunctuation ( sal_False ), + bLatinTextWrap ( sal_False ) +{ +} + +sal_Bool PPTTextParagraphStyleAtomInterpreter::Read( SvStream& rIn, const DffRecordHeader& rRecHd ) +{ + bValid = sal_False; + rRecHd.SeekToContent( rIn ); + sal_uInt32 nDummy32, nFlags, nRecEndPos = rRecHd.GetRecEndFilePos(); + sal_uInt16 nDummy16; + + rIn >> nDummy16 + >> nFlags; + + if ( nFlags & 0xf && ( rIn.Tell() < nRecEndPos ) ) + rIn >> nDummy16; // BuFlags + if ( nFlags & 0x80 && ( rIn.Tell() < nRecEndPos ) ) + rIn >> nDummy16; // BuChar + if ( nFlags & 0x10 && ( rIn.Tell() < nRecEndPos ) ) + rIn >> nDummy16; // nBuFont; + if ( nFlags & 0x40 && ( rIn.Tell() < nRecEndPos ) ) + rIn >> nDummy16; // nBuHeight; + if ( nFlags & 0x0020 && ( rIn.Tell() < nRecEndPos ) ) + rIn >> nDummy32; // nBuColor; + if ( nFlags & 0x800 && ( rIn.Tell() < nRecEndPos ) ) + rIn >> nDummy16; // AbsJust! + if ( nFlags & 0x400 && ( rIn.Tell() < nRecEndPos ) ) + rIn >> nDummy16; + if ( nFlags & 0x200 && ( rIn.Tell() < nRecEndPos ) ) + rIn >> nDummy16; + if ( nFlags & 0x100 && ( rIn.Tell() < nRecEndPos ) ) + rIn >> nDummy16; + if ( nFlags & 0x1000 && ( rIn.Tell() < nRecEndPos ) ) + rIn >> nDummy16; // LineFeed + if ( nFlags & 0x2000 && ( rIn.Tell() < nRecEndPos ) ) + rIn >> nDummy16; // nUpperDist + if ( nFlags & 0x4000 && ( rIn.Tell() < nRecEndPos ) ) + rIn >> nDummy16; // nLowerDist + if ( nFlags & 0x8000 && ( rIn.Tell() < nRecEndPos ) ) + rIn >> nDummy16; + if ( nFlags & 0x10000 && ( rIn.Tell() < nRecEndPos ) ) + rIn >> nDummy16; + if ( nFlags & 0xe0000 && ( rIn.Tell() < nRecEndPos ) ) + { + rIn >> nDummy16; + if ( nFlags & 0x20000 ) + bForbiddenRules = ( nDummy16 & 1 ) == 1; + if ( nFlags & 0x40000 ) + bLatinTextWrap = ( nDummy16 & 2 ) == 0; + if ( nFlags & 0x80000 ) + bHangingPunctuation = ( nDummy16 & 4 ) == 4; + } + nFlags &=~ 0xfffff; + sal_uInt32 nMask = 0x100000; + while ( nFlags && nMask && ( rIn.Tell() < nRecEndPos ) ) + { + if ( nFlags & nMask ) + { + rIn >> nDummy16; + nFlags ^= nMask; + } + nMask <<= 1; + } + bValid = rIn.Tell() == nRecEndPos; + return bValid; +} + +PPTTextParagraphStyleAtomInterpreter::~PPTTextParagraphStyleAtomInterpreter() +{ + +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +PPTTextSpecInfo::PPTTextSpecInfo( sal_uInt32 _nCharIdx ) : + nCharIdx ( _nCharIdx ), + nDontKnow ( 1 ) +{ + nLanguage[ 0 ] = 0x400; + nLanguage[ 1 ] = 0; + nLanguage[ 2 ] = 0; +} + +PPTTextSpecInfo::~PPTTextSpecInfo() +{ +} + +PPTTextSpecInfoAtomInterpreter::PPTTextSpecInfoAtomInterpreter() : + bValid ( sal_False ) +{ +} + +sal_Bool PPTTextSpecInfoAtomInterpreter::Read( SvStream& rIn, const DffRecordHeader& rRecHd, + sal_uInt16 nRecordType, const PPTTextSpecInfo* pTextSpecDefault ) +{ + bValid = sal_False; + sal_uInt32 nCharIdx = 0; + rRecHd.SeekToContent( rIn ); + + while ( rIn.Tell() < rRecHd.GetRecEndFilePos() ) + { + sal_uInt32 nCharCount, + nFlags, i; + + if ( nRecordType == PPT_PST_TextSpecInfoAtom ) + { + rIn >> nCharCount; + nCharIdx += nCharCount; + } + rIn >> nFlags; + + PPTTextSpecInfo* pEntry = new PPTTextSpecInfo( nCharIdx ); + if ( pTextSpecDefault ) + { + pEntry->nDontKnow = pTextSpecDefault->nDontKnow; + pEntry->nLanguage[ 0 ] = pTextSpecDefault->nLanguage[ 0 ]; + pEntry->nLanguage[ 1 ] = pTextSpecDefault->nLanguage[ 1 ]; + pEntry->nLanguage[ 2 ] = pTextSpecDefault->nLanguage[ 2 ]; + } + for ( i = 1; nFlags && i ; i <<= 1 ) + { + sal_uInt16 nLang = 0; + switch( nFlags & i ) + { + case 0 : break; + case 1 : rIn >> pEntry->nDontKnow; break; + case 2 : rIn >> nLang; break; + case 4 : rIn >> nLang; break; + default : + { + rIn.SeekRel( 2 ); + } + } + if ( nLang ) + { + sal_uInt16 nScriptType = GetI18NScriptTypeOfLanguage( nLang ); + if ( nScriptType & SCRIPTTYPE_LATIN ) + pEntry->nLanguage[ 0 ] = nLang; + if ( nScriptType & SCRIPTTYPE_ASIAN ) + pEntry->nLanguage[ 1 ] = nLang; + if ( nScriptType & SCRIPTTYPE_COMPLEX ) + pEntry->nLanguage[ 2 ] = nLang; + } + nFlags &= ~i; + } + aList.Insert( pEntry, LIST_APPEND ); + } + bValid = rIn.Tell() == rRecHd.GetRecEndFilePos(); + return bValid; +} + +PPTTextSpecInfoAtomInterpreter::~PPTTextSpecInfoAtomInterpreter() +{ + void *pPtr; + for ( pPtr = aList.First(); pPtr; pPtr = aList.Next() ) + delete (PPTTextSpecInfo*)pPtr; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void StyleTextProp9::Read( SvStream& rIn ) +{ + rIn >> mnExtParagraphMask; + if ( mnExtParagraphMask & 0x800000 ) + rIn >> mnBuBlip; + if ( mnExtParagraphMask & 0x2000000 ) + rIn >> mnHasAnm; + if ( mnExtParagraphMask & 0x1000000 ) + rIn >> mnAnmScheme; + if ( mnExtParagraphMask & 0x4000000 ) + rIn >> mpfPP10Ext; + rIn >> mnExtCharacterMask; + if ( mnExtCharacterMask & 0x100000 ) + rIn >> mncfPP10Ext; + rIn >> mnSpecialInfoMask; + if ( mnSpecialInfoMask & 0x20 ) + rIn >> mnPP10Ext; + if ( mnSpecialInfoMask & 0x40 ) + rIn >> mfBidi; +} + +PPTStyleTextPropReader::PPTStyleTextPropReader( SvStream& rIn, SdrPowerPointImport& rMan, const DffRecordHeader& rTextHeader, + PPTTextRulerInterpreter& rRuler, const DffRecordHeader& rExtParaHd, sal_uInt32 nInstance ) +{ + Init(rIn, rMan, rTextHeader, rRuler, rExtParaHd, nInstance); +} + +void PPTStyleTextPropReader::ReadParaProps( SvStream& rIn, SdrPowerPointImport& rMan, const DffRecordHeader& rTextHeader, + const String& aString, PPTTextRulerInterpreter& rRuler, + sal_uInt32& nCharCount, sal_Bool& bTextPropAtom ) +{ + sal_uInt32 nMask = 0; //TODO: nMask initialized here to suppress warning for now, see corresponding TODO below + sal_uInt32 nCharAnzRead = 0; + sal_uInt16 nDummy16; + + sal_uInt16 nStringLen = aString.Len(); + + DffRecordHeader aTextHd2; + rTextHeader.SeekToContent( rIn ); + if ( rMan.SeekToRec( rIn, PPT_PST_StyleTextPropAtom, rTextHeader.GetRecEndFilePos(), &aTextHd2 ) ) + bTextPropAtom = sal_True; + while ( nCharAnzRead <= nStringLen ) + { + PPTParaPropSet aParaPropSet; + ImplPPTParaPropSet& aSet = *aParaPropSet.pParaSet; + if ( bTextPropAtom ) + { + rIn >> nCharCount + >> aParaPropSet.pParaSet->mnDepth; // Einruecktiefe + + aParaPropSet.pParaSet->mnDepth = // taking care of about using not more than 9 outliner levels + std::min(sal_uInt16(8), + aParaPropSet.pParaSet->mnDepth); + + nCharCount--; + + rIn >> nMask; + aSet.mnAttrSet = nMask & 0x207df7; + sal_uInt16 nBulFlg = 0; + if ( nMask & 0xF ) + rIn >> nBulFlg; // Bullet-HardAttr-Flags + aSet.mpArry[ PPT_ParaAttr_BulletOn ] = ( nBulFlg & 1 ) ? 1 : 0; + aSet.mpArry[ PPT_ParaAttr_BuHardFont ] = ( nBulFlg & 2 ) ? 1 : 0; + aSet.mpArry[ PPT_ParaAttr_BuHardColor ] = ( nBulFlg & 4 ) ? 1 : 0; + + if ( nMask & 0x0080 ) // buChar + rIn >> aSet.mpArry[ PPT_ParaAttr_BulletChar ]; + if ( nMask & 0x0010 ) // buTypeface + rIn >> aSet.mpArry[ PPT_ParaAttr_BulletFont ]; + if ( nMask & 0x0040 ) // buSize + { + rIn >> aSet.mpArry[ PPT_ParaAttr_BulletHeight ]; + if ( ! ( ( nMask & ( 1 << PPT_ParaAttr_BuHardHeight ) ) + && ( nBulFlg && ( 1 << PPT_ParaAttr_BuHardHeight ) ) ) ) + aSet.mnAttrSet ^= 0x40; + } + if ( nMask & 0x0020 ) // buColor + { + sal_uInt32 nVal32, nHiByte; + rIn >> nVal32; + nHiByte = nVal32 >> 24; + if ( nHiByte <= 8 ) + nVal32 = nHiByte | PPT_COLSCHEME; + aSet.mnBulletColor = nVal32; + } + if ( nMask & 0x0800 ) // pfAlignment + { + rIn >> nDummy16; + aSet.mpArry[ PPT_ParaAttr_Adjust ] = nDummy16 & 3; + } + if ( nMask & 0x1000 ) // pfLineSpacing + rIn >> aSet.mpArry[ PPT_ParaAttr_LineFeed ]; + if ( nMask & 0x2000 ) // pfSpaceBefore + rIn >> aSet.mpArry[ PPT_ParaAttr_UpperDist ]; + if ( nMask & 0x4000 ) // pfSpaceAfter + rIn >> aSet.mpArry[ PPT_ParaAttr_LowerDist ]; + if ( nMask & 0x100 ) // pfLeftMargin + rIn >> nDummy16; + if ( nMask & 0x400 ) // pfIndent + rIn >> nDummy16; + if ( nMask & 0x8000 ) // pfDefaultTabSize + rIn >> nDummy16; + if ( nMask & 0x100000 ) // pfTabStops + { + sal_uInt16 i, nDistance, nAlignment, nNumberOfTabStops = 0; + rIn >> nNumberOfTabStops; + for ( i = 0; i < nNumberOfTabStops; i++ ) + { + rIn >> nDistance + >> nAlignment; + } + } + if ( nMask & 0x10000 ) // pfBaseLine + rIn >> nDummy16; + if ( nMask & 0xe0000 ) // pfCharWrap, pfWordWrap, pfOverflow + { + rIn >> nDummy16; + if ( nMask & 0x20000 ) + aSet.mpArry[ PPT_ParaAttr_AsianLB_1 ] = nDummy16 & 1; + if ( nMask & 0x40000 ) + aSet.mpArry[ PPT_ParaAttr_AsianLB_2 ] = ( nDummy16 >> 1 ) & 1; + if ( nMask & 0x80000 ) + aSet.mpArry[ PPT_ParaAttr_AsianLB_3 ] = ( nDummy16 >> 2 ) & 1; + aSet.mnAttrSet |= ( ( nMask >> 17 ) & 7 ) << PPT_ParaAttr_AsianLB_1; + } + if ( nMask & 0x200000 ) // pfTextDirection + rIn >> aSet.mpArry[ PPT_ParaAttr_BiDi ]; + } + else + nCharCount = nStringLen; + + if ( rRuler.GetTextOfs( aParaPropSet.pParaSet->mnDepth, aSet.mpArry[ PPT_ParaAttr_TextOfs ] ) ) + aSet.mnAttrSet |= 1 << PPT_ParaAttr_TextOfs; + if ( rRuler.GetBulletOfs( aParaPropSet.pParaSet->mnDepth, aSet.mpArry[ PPT_ParaAttr_BulletOfs ] ) ) + aSet.mnAttrSet |= 1 << PPT_ParaAttr_BulletOfs; + if ( rRuler.GetDefaultTab( aParaPropSet.pParaSet->mnDepth, aSet.mpArry[ PPT_ParaAttr_DefaultTab ] ) ) + aSet.mnAttrSet |= 1 << PPT_ParaAttr_DefaultTab; + + if ( ( nCharCount > nStringLen ) || ( nStringLen < nCharAnzRead + nCharCount ) ) + { + bTextPropAtom = sal_False; + nCharCount = nStringLen - nCharAnzRead; + // please fix the right hand side of + // PPTParaPropSet& PPTParaPropSet::operator=(PPTParaPropSet&), + // it should be a const reference + PPTParaPropSet aTmpPPTParaPropSet; + aParaPropSet = aTmpPPTParaPropSet; + DBG_ERROR( "SJ:PPTStyleTextPropReader::could not get this PPT_PST_StyleTextPropAtom by reading the paragraph attributes" ); + } + PPTParaPropSet* pPara = new PPTParaPropSet( aParaPropSet ); + pPara->mnOriginalTextPos = nCharAnzRead; + aParaPropList.Insert( pPara, LIST_APPEND ); + if ( nCharCount ) + { + sal_uInt32 nCount; + const sal_Unicode* pDat = aString.GetBuffer() + nCharAnzRead; + for ( nCount = 0; nCount < nCharCount; nCount++ ) + { + if ( pDat[ nCount ] == 0xd ) + { + pPara = new PPTParaPropSet( aParaPropSet ); + pPara->mnOriginalTextPos = nCharAnzRead + nCount + 1; + aParaPropList.Insert( pPara, LIST_APPEND ); + } + } + } + nCharAnzRead += nCharCount + 1; + } +} + +void PPTStyleTextPropReader::ReadCharProps( SvStream& rIn, PPTCharPropSet& aCharPropSet, const String& aString, + sal_uInt32& nCharCount, sal_uInt32 nCharAnzRead, + sal_Bool& bTextPropAtom, sal_uInt32 nExtParaPos, + const std::vector< StyleTextProp9 >& aStyleTextProp9, + sal_uInt32& nExtParaFlags, sal_uInt16& nBuBlip, + sal_uInt16& nHasAnm, sal_uInt32& nAnmScheme ) +{ + sal_uInt32 nMask = 0; //TODO: nMask initialized here to suppress warning for now, see corresponding TODO below + sal_uInt16 nDummy16; + sal_Int32 nCharsToRead; + sal_uInt32 nExtParaNibble = 0; + + sal_uInt16 nStringLen = aString.Len(); + + rIn >> nDummy16; + nCharCount = nDummy16; + rIn >> nDummy16; + nCharsToRead = nStringLen - ( nCharAnzRead + nCharCount ); + if ( nCharsToRead < 0 ) + { + nCharCount = nStringLen - nCharAnzRead; + if ( nCharsToRead < -1 ) + { + bTextPropAtom = sal_False; + DBG_ERROR( "SJ:PPTStyleTextPropReader::could not get this PPT_PST_StyleTextPropAtom by reading the character attributes" ); + } + } + ImplPPTCharPropSet& aSet = *aCharPropSet.pCharSet; + + // character attributes + rIn >> nMask; + if ( (sal_uInt16)nMask ) + { + aSet.mnAttrSet |= (sal_uInt16)nMask; + rIn >> aSet.mnFlags; + } + if ( nMask & 0x10000 ) // cfTypeface + { + rIn >> aSet.mnFont; + aSet.mnAttrSet |= 1 << PPT_CharAttr_Font; + } + if ( nMask & 0x200000 ) // cfFEOldTypeface + { + rIn >> aSet.mnAsianOrComplexFont; + aSet.mnAttrSet |= 1 << PPT_CharAttr_AsianOrComplexFont; + } + if ( nMask & 0x400000 ) // cfANSITypeface + { + rIn >> aSet.mnANSITypeface; + aSet.mnAttrSet |= 1 << PPT_CharAttr_ANSITypeface; + } + if ( nMask & 0x800000 ) // cfSymbolTypeface + { + rIn >> aSet.mnSymbolFont; + aSet.mnAttrSet |= 1 << PPT_CharAttr_Symbol; + } + if ( nMask & 0x20000 ) // cfSize + { + rIn >> aSet.mnFontHeight; + aSet.mnAttrSet |= 1 << PPT_CharAttr_FontHeight; + } + if ( nMask & 0x40000 ) // cfColor + { + sal_uInt32 nVal; + rIn >> nVal; + if ( !( nVal & 0xff000000 ) ) + nVal = PPT_COLSCHEME_HINTERGRUND; + aSet.mnColor = nVal; + aSet.mnAttrSet |= 1 << PPT_CharAttr_FontColor; + } + if ( nMask & 0x80000 ) // cfPosition + { + rIn >> aSet.mnEscapement; + aSet.mnAttrSet |= 1 << PPT_CharAttr_Escapement; + } + if ( nExtParaPos ) + { + sal_uInt32 nExtBuInd = nMask & 0x3c00; + if ( nExtBuInd ) + nExtBuInd = ( aSet.mnFlags & 0x3c00 ) >> 10; + if ( nExtBuInd < aStyleTextProp9.size() ) + { + if ( nExtParaNibble && ( ( nExtBuInd + nExtParaNibble ) < aStyleTextProp9.size() ) ) + nExtBuInd += nExtParaNibble; + + nExtParaFlags = aStyleTextProp9[ nExtBuInd ].mnExtParagraphMask; + nBuBlip = aStyleTextProp9[ nExtBuInd ].mnBuBlip; + nHasAnm = aStyleTextProp9[ nExtBuInd ].mnHasAnm; + nAnmScheme = aStyleTextProp9[ nExtBuInd ].mnAnmScheme; + } + if ( ( nExtBuInd & 0xf ) == 0xf ) + nExtParaNibble += 16; + } +} + +void PPTStyleTextPropReader::Init( SvStream& rIn, SdrPowerPointImport& rMan, const DffRecordHeader& rTextHeader, + PPTTextRulerInterpreter& rRuler, const DffRecordHeader& rExtParaHd, sal_uInt32 nInstance ) +{ + sal_uInt32 nMerk = rIn.Tell(); + sal_uInt32 nExtParaPos = ( rExtParaHd.nRecType == PPT_PST_ExtendedParagraphAtom ) ? rExtParaHd.nFilePos + 8 : 0; + + std::vector< StyleTextProp9 > aStyleTextProp9; + if ( rExtParaHd.nRecType == PPT_PST_ExtendedParagraphAtom ) + { + rIn.Seek( rExtParaHd.nFilePos + 8 ); + while( ( rIn.GetError() == 0 ) && ( rIn.Tell() < rExtParaHd.GetRecEndFilePos() ) ) + { + aStyleTextProp9.resize( aStyleTextProp9.size() + 1 ); + aStyleTextProp9.back().Read( rIn ); + } + rIn.Seek( nMerk ); + } + + String aString; + DffRecordHeader aTextHd; + rIn >> aTextHd; + sal_uInt32 nMaxLen = aTextHd.nRecLen; + if ( nMaxLen >= 0xFFFF ) + nMaxLen = 0xFFFE; + + if( aTextHd.nRecType == PPT_PST_TextCharsAtom ) + { + sal_uInt32 i; + sal_Unicode nChar,*pBuf = new sal_Unicode[ ( nMaxLen >> 1 ) + 1 ]; + rIn.Read( pBuf, nMaxLen ); + nMaxLen >>= 1; + pBuf[ nMaxLen ] = 0; + sal_Unicode* pPtr = pBuf; +#ifdef OSL_BIGENDIAN + sal_Unicode nTemp; + for ( i = 0; i < nMaxLen; i++ ) + { + nTemp = *pPtr; + *pPtr++ = ( nTemp << 8 ) | ( nTemp >> 8 ); + } + pPtr = pBuf; +#endif + + for ( i = 0; i < nMaxLen; pPtr++, i++ ) + { + nChar = *pPtr; + if ( !nChar ) + break; + if ( ( nChar & 0xff00 ) == 0xf000 ) // in this special case we got a symbol + aSpecMarkerList.Insert( (void*)( i | PPT_SPEC_SYMBOL ), LIST_APPEND ); + else if ( nChar == 0xd ) + { + if ( nInstance == TSS_TYPE_PAGETITLE ) + *pPtr = 0xb; + else + aSpecMarkerList.Insert( (void*)( i | PPT_SPEC_NEWLINE ), LIST_APPEND ); + } + } + if ( i ) + aString = String( pBuf, (sal_uInt16)i ); + delete[] pBuf; + } + else if( aTextHd.nRecType == PPT_PST_TextBytesAtom ) + { + sal_Char *pBuf = new sal_Char[ nMaxLen + 1 ]; + pBuf[ nMaxLen ] = 0; + rIn.Read( pBuf, nMaxLen ); + sal_Char* pPtr = pBuf; + for (;;) + { + sal_Char cLo = *pPtr; + if ( cLo == 0 ) + break; + if ( cLo == 0xd ) + { + if ( nInstance == TSS_TYPE_PAGETITLE ) + *pPtr = 0xb; + else + aSpecMarkerList.Insert( (void*)( (pPtr - pBuf) | PPT_SPEC_NEWLINE ), LIST_APPEND ); + } + pPtr++; + } + xub_StrLen nLen = sal::static_int_cast< xub_StrLen >( pPtr - pBuf ); + if ( nLen ) + aString = String( pBuf, nLen, RTL_TEXTENCODING_MS_1252 ); + delete[] pBuf; + } + else + { + // no chars, but potentially char/para props? + sal_uInt32 nCharCount; + sal_Bool bTextPropAtom = sal_False; + ReadParaProps( rIn, rMan, rTextHeader, aString, rRuler, nCharCount, bTextPropAtom ); + + if ( bTextPropAtom ) + { + // yeah, StyleTextProp is there, read it all & push to + // aParaPropList + PPTCharPropSet aCharPropSet(0); + aCharPropSet.mnOriginalTextPos = 0; + + sal_uInt32 nCharAnzRead = 0; + sal_uInt32 nExtParaFlags = 0, nAnmScheme = 0; + sal_uInt16 nBuBlip = 0xffff, nHasAnm = 0; + ReadCharProps( rIn, aCharPropSet, aString, nCharCount, nCharAnzRead, + bTextPropAtom, nExtParaPos, aStyleTextProp9, nExtParaFlags, + nBuBlip, nHasAnm, nAnmScheme ); + + aCharPropList.Insert( + new PPTCharPropSet( aCharPropSet, 0 ), LIST_APPEND ); + } + } + + if ( aString.Len() ) + { + sal_uInt32 nCharCount; + sal_Bool bTextPropAtom = sal_False; + + ReadParaProps( rIn, rMan, rTextHeader, aString, rRuler, nCharCount, bTextPropAtom ); + + sal_Bool bEmptyParaPossible = sal_True; + sal_uInt32 nCharAnzRead = 0; + sal_uInt32 nCurrentPara = 0; + sal_uInt32 nCurrentSpecMarker = (sal_uInt32)(sal_uIntPtr)aSpecMarkerList.First(); + sal_uInt16 nStringLen = aString.Len(); + + while ( nCharAnzRead < nStringLen ) + { + sal_uInt32 nExtParaFlags = 0, nLatestParaUpdate = 0xffffffff, nAnmScheme = 0; + sal_uInt16 nBuBlip = 0xffff, nHasAnm = 0; + + PPTCharPropSet aCharPropSet( nCurrentPara ); + if ( bTextPropAtom ) + ReadCharProps( rIn, aCharPropSet, aString, nCharCount, nCharAnzRead, + bTextPropAtom, nExtParaPos, aStyleTextProp9, nExtParaFlags, + nBuBlip, nHasAnm, nAnmScheme ); + else + nCharCount = nStringLen; + + sal_uInt32 nLen; + while( nCharCount ) + { + if ( nExtParaPos && ( nLatestParaUpdate != nCurrentPara ) && ( nCurrentPara < aParaPropList.Count() ) ) + { + PPTParaPropSet* pPropSet = (PPTParaPropSet*)aParaPropList.GetObject( nCurrentPara ); + pPropSet->pParaSet->mnExtParagraphMask = nExtParaFlags; + if ( nExtParaFlags & 0x800000 ) + pPropSet->pParaSet->mnBuBlip = nBuBlip; + if ( nExtParaFlags & 0x01000000 ) + pPropSet->pParaSet->mnAnmScheme = nAnmScheme; + if ( nExtParaFlags & 0x02000000 ) + pPropSet->pParaSet->mnHasAnm = nHasAnm; + nLatestParaUpdate = nCurrentPara; + } + aCharPropSet.mnOriginalTextPos = nCharAnzRead; + if ( nCurrentSpecMarker && ( ( nCurrentSpecMarker & 0xffff ) < ( nCharAnzRead + nCharCount ) ) ) + { + if ( nCurrentSpecMarker & PPT_SPEC_NEWLINE ) + { + nLen = ( nCurrentSpecMarker & 0xffff ) - nCharAnzRead; + if ( nLen ) + aCharPropSet.maString = String( aString, (sal_uInt16)nCharAnzRead, (sal_uInt16)nLen ); + else if ( bEmptyParaPossible ) + aCharPropSet.maString = String(); + if ( nLen || bEmptyParaPossible ) + aCharPropList.Insert( new PPTCharPropSet( aCharPropSet, nCurrentPara ), LIST_APPEND ); + nCurrentPara++; + nLen++; + nCharAnzRead += nLen; + nCharCount -= nLen; + bEmptyParaPossible = sal_True; + } + else if ( nCurrentSpecMarker & PPT_SPEC_SYMBOL ) + { + if ( ( nCurrentSpecMarker & 0xffff ) != nCharAnzRead ) + { + nLen = ( nCurrentSpecMarker & 0xffff ) - nCharAnzRead; + aCharPropSet.maString = String( aString, (sal_uInt16)nCharAnzRead, (sal_uInt16)nLen ); + aCharPropList.Insert( new PPTCharPropSet( aCharPropSet, nCurrentPara ), LIST_APPEND ); + nCharCount -= nLen; + nCharAnzRead += nLen; + } + PPTCharPropSet* pCPropSet = new PPTCharPropSet( aCharPropSet, nCurrentPara ); + pCPropSet->maString = aString.GetChar( (sal_uInt16)nCharAnzRead ); + if ( aCharPropSet.pCharSet->mnAttrSet & ( 1 << PPT_CharAttr_Symbol ) ) + pCPropSet->SetFont( aCharPropSet.pCharSet->mnSymbolFont ); + aCharPropList.Insert( pCPropSet, LIST_APPEND ); + nCharCount--; + nCharAnzRead++; + bEmptyParaPossible = sal_False; + } + nCurrentSpecMarker = (sal_uInt32)(sal_uIntPtr)aSpecMarkerList.Next(); + } + else + { + aCharPropSet.maString = String( aString, (sal_uInt16)nCharAnzRead, (sal_uInt16)nCharCount ); + aCharPropList.Insert( new PPTCharPropSet( aCharPropSet, nCurrentPara ), LIST_APPEND ); + nCharAnzRead += nCharCount; + bEmptyParaPossible = sal_False; + break; + } + } + } + if ( aCharPropList.Count() && ( ((PPTCharPropSet*)aCharPropList.Last())->mnParagraph != nCurrentPara ) ) + { + PPTCharPropSet* pCharPropSet = new PPTCharPropSet( *(PPTCharPropSet*)aCharPropList.Last(), nCurrentPara ); + pCharPropSet->maString = String(); + pCharPropSet->mnOriginalTextPos = nStringLen - 1; + aCharPropList.Insert( pCharPropSet, LIST_APPEND ); + } + } + rIn.Seek( nMerk ); +} + +PPTStyleTextPropReader::~PPTStyleTextPropReader() +{ + void* pTmp; + for ( pTmp = aParaPropList.First(); pTmp; pTmp = aParaPropList.Next() ) + delete (PPTParaPropSet*)pTmp; + for ( pTmp = aCharPropList.First(); pTmp; pTmp = aCharPropList.Next() ) + delete (PPTCharPropSet*)pTmp; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct FieldEntry +{ + sal_uInt32 nFieldType; + sal_uInt32 nFieldStartPos; + sal_uInt32 nFieldEndPos; + String aFieldUrl; + + FieldEntry( sal_uInt32 nType, sal_uInt32 nStart, sal_uInt32 nEnd ) + { + nFieldType = nType; + nFieldStartPos = nStart; + nFieldEndPos = nEnd; + } + FieldEntry( FieldEntry& rFieldEntry ) + { + nFieldType = rFieldEntry.nFieldType; + nFieldStartPos = rFieldEntry.nFieldStartPos; + nFieldEndPos = rFieldEntry.nFieldEndPos; + aFieldUrl = rFieldEntry.aFieldUrl; + } +}; + + +PPTPortionObj::PPTPortionObj( const PPTStyleSheet& rStyleSheet, sal_uInt32 nInstance, sal_uInt32 nDepth ) : + PPTCharPropSet ( 0 ), + mrStyleSheet ( rStyleSheet ), + mnInstance ( nInstance ), + mnDepth ( ( nDepth > 4 ) ? 4 : nDepth ) +{ +} + +PPTPortionObj::PPTPortionObj( PPTCharPropSet& rCharPropSet, const PPTStyleSheet& rStyleSheet, sal_uInt32 nInstance, sal_uInt32 nDepth ) : + PPTCharPropSet ( rCharPropSet ), + mrStyleSheet ( rStyleSheet ), + mnInstance ( nInstance ), + mnDepth ( nDepth ) +{ +} + +PPTPortionObj::PPTPortionObj( PPTPortionObj& rPortionObj ) : + PPTCharPropSet ( rPortionObj ), + mrStyleSheet ( rPortionObj.mrStyleSheet ), + mnInstance ( rPortionObj.mnInstance ), + mnDepth ( rPortionObj.mnDepth ) +{ +} + +PPTPortionObj::~PPTPortionObj() +{ +} + +sal_Bool PPTPortionObj::HasTabulator() +{ + sal_Bool bRetValue = sal_False; + sal_Int32 nCount; + const sal_Unicode* pPtr = maString.GetBuffer(); + for ( nCount = 0; nCount < maString.Len(); nCount++ ) + { + if ( pPtr[ nCount ] == 0x9 ) + { + bRetValue = sal_True; + break; + } + + } + return bRetValue; +} + +sal_Bool PPTPortionObj::GetAttrib( sal_uInt32 nAttr, sal_uInt32& nRetValue, sal_uInt32 nDestinationInstance ) +{ + sal_uInt32 nMask = 1 << nAttr; + nRetValue = 0; + + sal_uInt32 bIsHardAttribute = ( ( pCharSet->mnAttrSet & nMask ) != 0 ) ? 1 : 0; + + if ( bIsHardAttribute ) + { + switch ( nAttr ) + { + case PPT_CharAttr_Bold : + case PPT_CharAttr_Italic : + case PPT_CharAttr_Underline : + case PPT_CharAttr_Shadow : + case PPT_CharAttr_Strikeout : + case PPT_CharAttr_Embossed : + nRetValue = ( pCharSet->mnFlags & nMask ) ? 1 : 0; + break; + case PPT_CharAttr_Font : + nRetValue = pCharSet->mnFont; + break; + case PPT_CharAttr_AsianOrComplexFont : + nRetValue = pCharSet->mnAsianOrComplexFont; + break; + case PPT_CharAttr_FontHeight : + nRetValue = pCharSet->mnFontHeight; + break; + case PPT_CharAttr_FontColor : + nRetValue = pCharSet->mnColor; + break; + case PPT_CharAttr_Escapement : + nRetValue = pCharSet->mnEscapement; + break; + default : + DBG_ERROR( "SJ:PPTPortionObj::GetAttrib ( hard attribute does not exist )" ); + } + } + else + { + const PPTCharLevel& rCharLevel = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[ mnDepth ]; + PPTCharLevel* pCharLevel = NULL; + if ( ( nDestinationInstance == 0xffffffff ) + || ( mnDepth && ( ( mnInstance == TSS_TYPE_SUBTITLE ) || ( mnInstance == TSS_TYPE_TEXT_IN_SHAPE ) ) ) ) + bIsHardAttribute = 1; + else if ( nDestinationInstance != mnInstance ) + pCharLevel = &mrStyleSheet.mpCharSheet[ nDestinationInstance ]->maCharLevel[ mnDepth ]; + switch( nAttr ) + { + case PPT_CharAttr_Bold : + case PPT_CharAttr_Italic : + case PPT_CharAttr_Underline : + case PPT_CharAttr_Shadow : + case PPT_CharAttr_Strikeout : + case PPT_CharAttr_Embossed : + { + nRetValue = ( rCharLevel.mnFlags & nMask ) ? 1 : 0; + if ( pCharLevel ) + { + sal_uInt32 nTmp = ( pCharLevel->mnFlags & nMask ) ? 1 : 0; + if ( nRetValue != nTmp ) + bIsHardAttribute = 1; + } + } + break; + case PPT_CharAttr_Font : + { + nRetValue = rCharLevel.mnFont; + if ( pCharLevel && ( nRetValue != pCharLevel->mnFont ) ) + bIsHardAttribute = 1; + } + break; + case PPT_CharAttr_AsianOrComplexFont : + { + nRetValue = rCharLevel.mnAsianOrComplexFont; + if ( pCharLevel && ( nRetValue != pCharLevel->mnAsianOrComplexFont ) ) + bIsHardAttribute = 1; + } + break; + case PPT_CharAttr_FontHeight : + { + nRetValue = rCharLevel.mnFontHeight; + if ( pCharLevel && ( nRetValue != pCharLevel->mnFontHeight ) ) + bIsHardAttribute = 1; + } + break; + case PPT_CharAttr_FontColor : + { + nRetValue = rCharLevel.mnFontColor; + if ( pCharLevel && ( nRetValue != pCharLevel->mnFontColor ) ) + bIsHardAttribute = 1; + } + break; + case PPT_CharAttr_Escapement : + { + nRetValue = rCharLevel.mnEscapement; + if ( pCharLevel && ( nRetValue != pCharLevel->mnEscapement ) ) + bIsHardAttribute = 1; + } + break; + default : + DBG_ERROR( "SJ:PPTPortionObj::GetAttrib ( attribute does not exist )" ); + } + } + return (sal_Bool)bIsHardAttribute; +} + +void PPTPortionObj::ApplyTo( SfxItemSet& rSet, SdrPowerPointImport& rManager, sal_uInt32 nDestinationInstance ) +{ + ApplyTo( rSet, rManager, nDestinationInstance, NULL ); +} + +void PPTPortionObj::ApplyTo( SfxItemSet& rSet, SdrPowerPointImport& rManager, sal_uInt32 nDestinationInstance, const PPTTextObj* pTextObj ) +{ + sal_uInt32 nVal; + if ( GetAttrib( PPT_CharAttr_Bold, nVal, nDestinationInstance ) ) + { + rSet.Put( SvxWeightItem( nVal != 0 ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT ) ); + rSet.Put( SvxWeightItem( nVal != 0 ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT_CJK ) ); + rSet.Put( SvxWeightItem( nVal != 0 ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT_CTL ) ); + } + if ( GetAttrib( PPT_CharAttr_Italic, nVal, nDestinationInstance ) ) + { + rSet.Put( SvxPostureItem( nVal != 0 ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC ) ); + rSet.Put( SvxPostureItem( nVal != 0 ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC_CJK ) ); + rSet.Put( SvxPostureItem( nVal != 0 ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC_CTL ) ); + } + if ( GetAttrib( PPT_CharAttr_Underline, nVal, nDestinationInstance ) ) + rSet.Put( SvxUnderlineItem( nVal != 0 ? UNDERLINE_SINGLE : UNDERLINE_NONE, EE_CHAR_UNDERLINE ) ); + + if ( GetAttrib( PPT_CharAttr_Shadow, nVal, nDestinationInstance ) ) + rSet.Put( SvxShadowedItem( nVal != 0, EE_CHAR_SHADOW ) ); + + if ( GetAttrib( PPT_CharAttr_Strikeout, nVal, nDestinationInstance ) ) + rSet.Put( SvxCrossedOutItem( nVal != 0 ? STRIKEOUT_SINGLE : STRIKEOUT_NONE, EE_CHAR_STRIKEOUT ) ); + + sal_uInt32 nAsianFontId = 0xffff; + if ( GetAttrib( PPT_CharAttr_AsianOrComplexFont, nAsianFontId, nDestinationInstance ) ) + { + if ( nAsianFontId != 0xffff ) + { + PptFontEntityAtom* pFontEnityAtom = rManager.GetFontEnityAtom( nAsianFontId ); + if ( pFontEnityAtom ) + { + rSet.Put( SvxFontItem( pFontEnityAtom->eFamily, pFontEnityAtom->aName, + String(), pFontEnityAtom->ePitch, pFontEnityAtom->eCharSet, EE_CHAR_FONTINFO_CJK ) ); + rSet.Put( SvxFontItem( pFontEnityAtom->eFamily, pFontEnityAtom->aName, + String(), pFontEnityAtom->ePitch, pFontEnityAtom->eCharSet, EE_CHAR_FONTINFO_CTL ) ); + } + } + } + if ( GetAttrib( PPT_CharAttr_Font, nVal, nDestinationInstance ) ) + { + PptFontEntityAtom* pFontEnityAtom = rManager.GetFontEnityAtom( nVal ); + if ( pFontEnityAtom ) + rSet.Put( SvxFontItem( pFontEnityAtom->eFamily, pFontEnityAtom->aName, String(), pFontEnityAtom->ePitch, pFontEnityAtom->eCharSet, EE_CHAR_FONTINFO ) ); + } + if ( GetAttrib( PPT_CharAttr_FontHeight, nVal, nDestinationInstance ) ) // Schriftgrad in Point + { + sal_uInt32 nHeight = rManager.ScalePoint( nVal ); + rSet.Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) ); + rSet.Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) ); + rSet.Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) ); + } + + if ( GetAttrib( PPT_CharAttr_Embossed, nVal, nDestinationInstance ) ) + rSet.Put( SvxCharReliefItem( nVal != 0 ? RELIEF_EMBOSSED : RELIEF_NONE, EE_CHAR_RELIEF ) ); + if ( nVal ) /* if Embossed is set, the font color depends to the fillstyle/color of the object, + if the object has no fillstyle, the font color depends to fillstyle of the background */ + { + Color aDefColor( COL_BLACK ); + MSO_FillType eFillType = mso_fillSolid; + if ( rManager.GetPropertyValue( DFF_Prop_fNoFillHitTest ) & 0x10 ) + eFillType = (MSO_FillType)rManager.GetPropertyValue( DFF_Prop_fillType, mso_fillSolid ); + else + eFillType = mso_fillBackground; + switch( eFillType ) + { + case mso_fillShade : + case mso_fillShadeCenter : + case mso_fillShadeShape : + case mso_fillShadeScale : + case mso_fillShadeTitle : + case mso_fillSolid : + aDefColor = rManager.MSO_CLR_ToColor( rManager.GetPropertyValue( DFF_Prop_fillColor ) ); + break; + case mso_fillPattern : + aDefColor = rManager.MSO_CLR_ToColor( rManager.GetPropertyValue( DFF_Prop_fillBackColor ) ); + break; + case mso_fillTexture : + { + Graphic aGraf; + if ( rManager.GetBLIP( rManager.GetPropertyValue( DFF_Prop_fillBlip ), aGraf, NULL ) ) + { + Bitmap aBmp( aGraf.GetBitmap() ); + Size aSize( aBmp.GetSizePixel() ); + if ( aSize.Width() && aSize.Height() ) + { + if ( aSize.Width () > 64 ) + aSize.Width () = 64; + if ( aSize.Height() > 64 ) + aSize.Height() = 64; + + sal_uLong nRt = 0, nGn = 0, nBl = 0; + BitmapReadAccess* pAcc = aBmp.AcquireReadAccess(); + if( pAcc ) + { + const long nWidth = aSize.Width(); + const long nHeight = aSize.Height(); + + if( pAcc->HasPalette() ) + { + for( long nY = 0L; nY < nHeight; nY++ ) + { + for( long nX = 0L; nX < nWidth; nX++ ) + { + const BitmapColor& rCol = pAcc->GetPaletteColor( (sal_uInt8) pAcc->GetPixel( nY, nX ) ); + nRt+=rCol.GetRed(); nGn+=rCol.GetGreen(); nBl+=rCol.GetBlue(); + } + } + } + else + { + for( long nY = 0L; nY < nHeight; nY++ ) + { + for( long nX = 0L; nX < nWidth; nX++ ) + { + const BitmapColor aCol( pAcc->GetPixel( nY, nX ) ); + nRt+=aCol.GetRed(); nGn+=aCol.GetGreen(); nBl+=aCol.GetBlue(); + } + } + } + aBmp.ReleaseAccess( pAcc ); + sal_uInt32 nC = ( aSize.Width() * aSize.Height() ); + nRt /= nC; + nGn /= nC; + nBl /= nC; + aDefColor = Color(sal_uInt8( nRt ), sal_uInt8( nGn ),sal_uInt8( nBl ) ); + } + } + } + } + break; + case mso_fillBackground : + { + if ( pTextObj ) // the textobject is needed + { + const SfxItemSet* pItemSet = pTextObj->GetBackground(); + if ( pItemSet ) + { + const SfxPoolItem* pFillStyleItem = NULL; + pItemSet->GetItemState( XATTR_FILLSTYLE, sal_False, &pFillStyleItem ); + if ( pFillStyleItem ) + { + XFillStyle eFillStyle = ((XFillStyleItem*)pFillStyleItem)->GetValue(); + switch( eFillStyle ) + { + case XFILL_SOLID : + { + const SfxPoolItem* pFillColorItem = NULL; + pItemSet->GetItemState( XATTR_FILLCOLOR, sal_False, &pFillColorItem ); + if ( pFillColorItem ) + aDefColor = ((XColorItem*)pFillColorItem)->GetColorValue(); + } + break; + case XFILL_GRADIENT : + { + const SfxPoolItem* pGradientItem = NULL; + pItemSet->GetItemState( XATTR_FILLGRADIENT, sal_False, &pGradientItem ); + if ( pGradientItem ) + aDefColor = ((XFillGradientItem*)pGradientItem)->GetGradientValue().GetStartColor(); + } + break; + case XFILL_HATCH : + case XFILL_BITMAP : + aDefColor = Color( COL_WHITE ); + break; + default: break; + } + } + } + } + } + break; +// case mso_fillPicture : + default: break; + } + rSet.Put( SvxColorItem( aDefColor, EE_CHAR_COLOR ) ); + } + else + { + if ( GetAttrib( PPT_CharAttr_FontColor, nVal, nDestinationInstance ) ) // Textfarbe (4Byte-Arg) + { + Color aCol( rManager.MSO_TEXT_CLR_ToColor( nVal ) ); + rSet.Put( SvxColorItem( aCol, EE_CHAR_COLOR ) ); + if ( nDestinationInstance == 0xffffffff ) + mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[ mnDepth ].mnFontColorInStyleSheet = aCol; + } + else if ( nVal & 0x0f000000 ) // this is not a hard attribute, but maybe the page has a different colerscheme, + { // so that in this case we must use a hard color attribute + Color aCol( rManager.MSO_TEXT_CLR_ToColor( nVal ) ); + Color& aColorInSheet = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[ mnDepth ].mnFontColorInStyleSheet; + if ( aColorInSheet != aCol ) + rSet.Put( SvxColorItem( aCol, EE_CHAR_COLOR ) ); + } + } + + if ( GetAttrib( PPT_CharAttr_Escapement, nVal, nDestinationInstance ) ) // Hoch/Tiefstellung in % + { + sal_uInt16 nEsc = 0; + sal_uInt8 nProp = 100; + + if ( nVal ) + { + nEsc = (sal_Int16)nVal; + nProp = DFLT_ESC_PROP; + } + SvxEscapementItem aItem( nEsc, nProp, EE_CHAR_ESCAPEMENT ); + rSet.Put( aItem ); + } + if ( mnLanguage[ 0 ] ) + rSet.Put( SvxLanguageItem( mnLanguage[ 0 ], EE_CHAR_LANGUAGE ) ); + if ( mnLanguage[ 1 ] ) + rSet.Put( SvxLanguageItem( mnLanguage[ 1 ], EE_CHAR_LANGUAGE_CJK ) ); + if ( mnLanguage[ 2 ] ) + rSet.Put( SvxLanguageItem( mnLanguage[ 2 ], EE_CHAR_LANGUAGE_CTL ) ); +} + +SvxFieldItem* PPTPortionObj::GetTextField() +{ + if ( mpFieldItem ) + return new SvxFieldItem( *mpFieldItem ); + return NULL; +} + +// ----------------------------------------------------------------------- + +PPTParagraphObj::PPTParagraphObj( const PPTStyleSheet& rStyleSheet, sal_uInt32 nInstance, sal_uInt16 nDepth ) : + PPTNumberFormatCreator ( NULL ), + mrStyleSheet ( rStyleSheet ), + mnInstance ( nInstance ), + mbTab ( sal_True ), // style sheets always have to get the right tabulator setting + mnPortionCount ( 0 ), + mpPortionList ( NULL ) +{ + if ( nDepth > 4 ) + nDepth = 4; + pParaSet->mnDepth = nDepth; +} + +PPTParagraphObj::PPTParagraphObj( PPTStyleTextPropReader& rPropReader, const PPTStyleSheet& rStyleSheet, + sal_uInt32 nInstance, PPTTextRulerInterpreter& rRuler ) : + PPTParaPropSet ( *( (PPTParaPropSet*)rPropReader.aParaPropList.GetCurObject() ) ), + PPTNumberFormatCreator ( NULL ), + PPTTextRulerInterpreter ( rRuler ), + mrStyleSheet ( rStyleSheet ), + mnInstance ( nInstance ), + mbTab ( sal_False ), + mnCurrentObject ( 0 ), + mnPortionCount ( 0 ), + mpPortionList ( NULL ) +{ + sal_uInt32 nCurPos = rPropReader.aCharPropList.GetCurPos(); + PPTCharPropSet* pCharPropSet = (PPTCharPropSet*)rPropReader.aCharPropList.GetCurObject(); + if ( pCharPropSet ) + { + sal_uInt32 nCurrentParagraph = pCharPropSet->mnParagraph; + for ( ; pCharPropSet && ( pCharPropSet->mnParagraph == nCurrentParagraph ); pCharPropSet = (PPTCharPropSet*)rPropReader.aCharPropList.Next() ) + mnPortionCount++; // counting number of portions that are part of this paragraph + pCharPropSet = (PPTCharPropSet*)rPropReader.aCharPropList.Seek( nCurPos ); + + mpPortionList = new PPTPortionObj*[ mnPortionCount ]; + for ( sal_uInt32 i = 0; i < mnPortionCount; i++ ) + { + if ( pCharPropSet ) + { + PPTPortionObj* pPPTPortion = new PPTPortionObj( *pCharPropSet, rStyleSheet, nInstance, pParaSet->mnDepth ); + mpPortionList[ i ] = pPPTPortion; + if ( !mbTab ) + mbTab = mpPortionList[ i ]->HasTabulator(); + } + else + { + DBG_ERROR( "SJ:PPTParagraphObj::It seems that there are missing some textportions" ); + mpPortionList[ i ] = NULL; + } + pCharPropSet = (PPTCharPropSet*)rPropReader.aCharPropList.Next(); + } + } +} + +PPTParagraphObj::~PPTParagraphObj() +{ + ImplClear(); +} + +void PPTParagraphObj::AppendPortion( PPTPortionObj& rPPTPortion ) +{ + sal_uInt32 i; + PPTPortionObj** mpOldPortionList = mpPortionList; + mpPortionList = new PPTPortionObj*[ ++mnPortionCount ]; + for ( i = 0; i < mnPortionCount - 1; i++ ) + mpPortionList[ i ] = mpOldPortionList[ i ]; + delete[] mpOldPortionList; + mpPortionList[ mnPortionCount - 1 ] = new PPTPortionObj( rPPTPortion ); + if ( !mbTab ) + mbTab = mpPortionList[ mnPortionCount - 1 ]->HasTabulator(); +} + +void PPTParagraphObj::UpdateBulletRelSize( sal_uInt32& nBulletRelSize ) const +{ + if ( nBulletRelSize > 0x7fff ) // a negative value is the absolute bullet height + { + sal_uInt16 nFontHeight = 0; + if ( mpPortionList ) + { + PPTPortionObj* pPortion = mpPortionList[ 0 ]; + if ( pPortion && ( pPortion->pCharSet->mnAttrSet & ( 1 << PPT_CharAttr_FontHeight ) ) ) + nFontHeight = pPortion->pCharSet->mnFontHeight; + } + // if we do not have a hard attributed fontheight, the fontheight is taken from the style + if ( !nFontHeight ) + nFontHeight = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[ pParaSet->mnDepth ].mnFontHeight; + nBulletRelSize = nFontHeight ? ((-((sal_Int16)nBulletRelSize)) * 100 ) / nFontHeight : 100; + } +} + +sal_Bool PPTParagraphObj::GetAttrib( sal_uInt32 nAttr, sal_uInt32& nRetValue, sal_uInt32 nDestinationInstance ) +{ + sal_uInt32 nMask = 1 << nAttr; + nRetValue = 0; + + if ( nAttr > 21 ) + { + DBG_ERROR( "SJ:PPTParagraphObj::GetAttrib - attribute does not exist" ); + return sal_False; + } + + sal_uInt32 bIsHardAttribute = ( ( pParaSet->mnAttrSet & nMask ) != 0 ) ? 1 : 0; + + if ( bIsHardAttribute ) + { + if ( nAttr == PPT_ParaAttr_BulletColor ) + { + sal_Bool bHardBulletColor; + if ( pParaSet->mnAttrSet & ( 1 << PPT_ParaAttr_BuHardColor ) ) + bHardBulletColor = pParaSet->mpArry[ PPT_ParaAttr_BuHardColor ] != 0; + else + bHardBulletColor = ( mrStyleSheet.mpParaSheet[ mnInstance ]->maParaLevel[ pParaSet->mnDepth ].mnBuFlags + & ( 1 << PPT_ParaAttr_BuHardColor ) ) != 0; + if ( bHardBulletColor ) + nRetValue = pParaSet->mnBulletColor; + else + { + nRetValue = PPT_COLSCHEME_TEXT_UND_ZEILEN; + if ( ( nDestinationInstance != 0xffffffff ) && mnPortionCount ) + { + PPTPortionObj* pPortion = mpPortionList[ 0 ]; + if ( pPortion ) + { + if ( pPortion->pCharSet->mnAttrSet & ( 1 << PPT_CharAttr_FontColor ) ) + nRetValue = pPortion->pCharSet->mnColor; + else + nRetValue = mrStyleSheet.mpCharSheet[ nDestinationInstance ]->maCharLevel[ pParaSet->mnDepth ].mnFontColor; + } + } + } + } + else if ( nAttr == PPT_ParaAttr_BulletFont ) + { + sal_Bool bHardBuFont; + if ( pParaSet->mnAttrSet & ( 1 << PPT_ParaAttr_BuHardFont ) ) + bHardBuFont = pParaSet->mpArry[ PPT_ParaAttr_BuHardFont ] != 0; + else + bHardBuFont = ( mrStyleSheet.mpParaSheet[ mnInstance ]->maParaLevel[ pParaSet->mnDepth ].mnBuFlags + & ( 1 << PPT_ParaAttr_BuHardFont ) ) != 0; + if ( bHardBuFont ) + nRetValue = pParaSet->mpArry[ PPT_ParaAttr_BulletFont ]; + else + { + // it is the font used which assigned to the first character of the following text + nRetValue = 0; + if ( ( nDestinationInstance != 0xffffffff ) && mnPortionCount ) + { + PPTPortionObj* pPortion = mpPortionList[ 0 ]; + if ( pPortion ) + { + if ( pPortion->pCharSet->mnAttrSet & ( 1 << PPT_CharAttr_Font ) ) + nRetValue = pPortion->pCharSet->mnFont; + else + nRetValue = mrStyleSheet.mpCharSheet[ nDestinationInstance ]->maCharLevel[ pParaSet->mnDepth ].mnFont; + } + } + } + } + else + nRetValue = pParaSet->mpArry[ nAttr ]; + } + else + { + const PPTParaLevel& rParaLevel = mrStyleSheet.mpParaSheet[ mnInstance ]->maParaLevel[ pParaSet->mnDepth ]; + + PPTParaLevel* pParaLevel = NULL; + if ( ( nDestinationInstance == 0xffffffff ) + || ( pParaSet->mnDepth && ( ( mnInstance == TSS_TYPE_SUBTITLE ) || ( mnInstance == TSS_TYPE_TEXT_IN_SHAPE ) ) ) ) + bIsHardAttribute = 1; + else if ( nDestinationInstance != mnInstance ) + pParaLevel = &mrStyleSheet.mpParaSheet[ nDestinationInstance ]->maParaLevel[ pParaSet->mnDepth ]; + switch ( nAttr ) + { + case PPT_ParaAttr_BulletOn : + { + nRetValue = rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BulletOn ); + if ( pParaLevel ) + { + if ( nRetValue != ( (sal_uInt32)pParaLevel->mnBuFlags & ( 1 << PPT_ParaAttr_BulletOn ) ) ) + bIsHardAttribute = 1; + } + } + break; + case PPT_ParaAttr_BuHardFont : + case PPT_ParaAttr_BuHardColor : + case PPT_ParaAttr_BuHardHeight : + DBG_ERROR( "SJ:PPTParagraphObj::GetAttrib - this attribute does not make sense" ); + break; + case PPT_ParaAttr_BulletChar : + { + nRetValue = rParaLevel.mnBulletChar; + if ( pParaLevel && ( nRetValue != pParaLevel->mnBulletChar ) ) + bIsHardAttribute = 1; + } + break; + case PPT_ParaAttr_BulletFont : + { + sal_Bool bHardBuFont; + if ( pParaSet->mnAttrSet & ( 1 << PPT_ParaAttr_BuHardFont ) ) + bHardBuFont = pParaSet->mpArry[ PPT_ParaAttr_BuHardFont ] != 0; + else + bHardBuFont = ( rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BuHardFont ) ) != 0; + if ( bHardBuFont ) + { + nRetValue = rParaLevel.mnBulletFont; + if ( pParaLevel && ( nRetValue != pParaLevel->mnBulletFont ) ) + bIsHardAttribute = 1; + } + else + { + if ( mnPortionCount ) + { + PPTPortionObj* pPortion = mpPortionList[ 0 ]; + if ( pPortion ) + bIsHardAttribute = pPortion->GetAttrib( PPT_CharAttr_Font, nRetValue, nDestinationInstance ); + } + else + { + nRetValue = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[ pParaSet->mnDepth ].mnFont; + bIsHardAttribute = 1; + } + } + } + break; + case PPT_ParaAttr_BulletHeight : + { + nRetValue = rParaLevel.mnBulletHeight; + if ( pParaLevel && ( nRetValue != pParaLevel->mnBulletHeight ) ) + bIsHardAttribute = 1; + } + break; + case PPT_ParaAttr_BulletColor : + { + sal_Bool bHardBulletColor; + if ( pParaSet->mnAttrSet & ( 1 << PPT_ParaAttr_BuHardColor ) ) + bHardBulletColor = pParaSet->mpArry[ PPT_ParaAttr_BuHardColor ] != 0; + else + bHardBulletColor = ( rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BuHardColor ) ) != 0; + if ( bHardBulletColor ) + { + nRetValue = rParaLevel.mnBulletColor; + if ( pParaLevel && ( nRetValue != pParaLevel->mnBulletColor ) ) + bIsHardAttribute = 1; + } + else + { + if ( mnPortionCount ) + { + PPTPortionObj* pPortion = mpPortionList[ 0 ]; + if ( pPortion ) + bIsHardAttribute = pPortion->GetAttrib( PPT_CharAttr_FontColor, nRetValue, nDestinationInstance ); + } + else + { + nRetValue = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[ pParaSet->mnDepth ].mnFontColor; + bIsHardAttribute = 1; + } + } + } + break; + case PPT_ParaAttr_Adjust : + { + nRetValue = rParaLevel.mnAdjust; + if ( pParaLevel && ( nRetValue != pParaLevel->mnAdjust ) ) + bIsHardAttribute = 1; + } + break; + case PPT_ParaAttr_LineFeed : + { + nRetValue = rParaLevel.mnLineFeed; + if ( pParaLevel && ( nRetValue != pParaLevel->mnLineFeed ) ) + bIsHardAttribute = 1; + } + break; + case PPT_ParaAttr_UpperDist : + { + nRetValue = rParaLevel.mnUpperDist; + if ( pParaLevel && ( nRetValue != pParaLevel->mnUpperDist ) ) + bIsHardAttribute = 1; + } + break; + case PPT_ParaAttr_LowerDist : + { + nRetValue = rParaLevel.mnLowerDist; + if ( pParaLevel && ( nRetValue != pParaLevel->mnLowerDist ) ) + bIsHardAttribute = 1; + } + break; + case PPT_ParaAttr_TextOfs : + { + nRetValue = rParaLevel.mnTextOfs; + if ( pParaLevel && ( nRetValue != pParaLevel->mnTextOfs ) ) + bIsHardAttribute = 1; + } + break; + case PPT_ParaAttr_BulletOfs : + { + nRetValue = rParaLevel.mnBulletOfs; + if ( pParaLevel && ( nRetValue != pParaLevel->mnBulletOfs ) ) + bIsHardAttribute = 1; + } + break; + case PPT_ParaAttr_DefaultTab : + { + nRetValue = rParaLevel.mnDefaultTab; + if ( pParaLevel && ( nRetValue != pParaLevel->mnBulletOfs ) ) + bIsHardAttribute = 1; + } + break; + case PPT_ParaAttr_AsianLB_1 : + { + nRetValue = rParaLevel.mnAsianLineBreak & 1; + if ( pParaLevel && ( nRetValue != ( (sal_uInt32)pParaLevel->mnAsianLineBreak & 1 ) ) ) + bIsHardAttribute = 1; + } + break; + case PPT_ParaAttr_AsianLB_2 : + { + nRetValue = ( rParaLevel.mnAsianLineBreak >> 1 ) & 1; + if ( pParaLevel && ( nRetValue != ( ( (sal_uInt32)pParaLevel->mnAsianLineBreak >> 1 ) & 1 ) ) ) + bIsHardAttribute = 1; + } + break; + case PPT_ParaAttr_AsianLB_3 : + { + nRetValue = ( rParaLevel.mnAsianLineBreak >> 2 ) & 1; + if ( pParaLevel && ( nRetValue != ( ( (sal_uInt32)pParaLevel->mnAsianLineBreak >> 2 ) & 1 ) ) ) + bIsHardAttribute = 1; + } + break; + case PPT_ParaAttr_BiDi : + { + nRetValue = rParaLevel.mnBiDi; + if ( pParaLevel && ( nRetValue != pParaLevel->mnBiDi ) ) + bIsHardAttribute = 1; + } + break; + } + } + return (sal_Bool)bIsHardAttribute; +} + +void PPTParagraphObj::ApplyTo( SfxItemSet& rSet, boost::optional< sal_Int16 >& rStartNumbering, SdrPowerPointImport& rManager, sal_uInt32 nDestinationInstance, const PPTParagraphObj* /*pPrev*/) +{ + sal_Int16 nVal2; + sal_uInt32 nVal, nUpperDist, nLowerDist; + sal_uInt32 nInstance = nDestinationInstance != 0xffffffff ? nDestinationInstance : mnInstance; + + if ( ( nDestinationInstance != 0xffffffff ) || ( pParaSet->mnDepth <= 1 ) ) + { + SvxNumBulletItem* pNumBulletItem = mrStyleSheet.mpNumBulletItem[ nInstance ]; + if ( pNumBulletItem ) + { + SvxNumberFormat aNumberFormat( SVX_NUM_NUMBER_NONE ); + if ( GetNumberFormat( rManager, aNumberFormat, this, nDestinationInstance, rStartNumbering ) ) + { + if ( aNumberFormat.GetNumberingType() == SVX_NUM_NUMBER_NONE ) + { + aNumberFormat.SetLSpace( 0 ); + aNumberFormat.SetAbsLSpace( 0 ); + aNumberFormat.SetFirstLineOffset( 0 ); + aNumberFormat.SetCharTextDistance( 0 ); + aNumberFormat.SetFirstLineIndent( 0 ); + aNumberFormat.SetIndentAt( 0 ); + } + SvxNumBulletItem aNewNumBulletItem( *pNumBulletItem ); + SvxNumRule* pRule = aNewNumBulletItem.GetNumRule(); + if ( pRule ) + { + pRule->SetLevel( pParaSet->mnDepth, aNumberFormat ); + sal_uInt16 i, n; + for ( i = 0; i < pRule->GetLevelCount(); i++ ) + { + if ( i != pParaSet->mnDepth ) + { + n = i > 4 ? 4 : i; + + SvxNumberFormat aNumberFormat2( pRule->GetLevel( i ) ); + const PPTParaLevel& rParaLevel = mrStyleSheet.mpParaSheet[ nInstance ]->maParaLevel[ n ]; + const PPTCharLevel& rCharLevel = mrStyleSheet.mpCharSheet[ nInstance ]->maCharLevel[ n ]; + sal_uInt32 nColor; + if ( rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BuHardColor ) ) + nColor = rParaLevel.mnBulletColor; + else + nColor = rCharLevel.mnFontColor; + aNumberFormat2.SetBulletColor( rManager.MSO_TEXT_CLR_ToColor( nColor ) ); + pRule->SetLevel( i, aNumberFormat2 ); + } + } + rSet.Put( aNewNumBulletItem ); + } + } + } + } + + sal_uInt32 nIsBullet2, _nTextOfs, _nBulletOfs, nHardAttribute = 0; + GetAttrib( PPT_ParaAttr_BulletOn, nIsBullet2, nDestinationInstance ); + nHardAttribute += GetAttrib( PPT_ParaAttr_TextOfs, _nTextOfs, nDestinationInstance ); + nHardAttribute += GetAttrib( PPT_ParaAttr_BulletOfs, _nBulletOfs, nDestinationInstance ); + if ( !nIsBullet2 ) + { + SvxLRSpaceItem aLRSpaceItem( EE_PARA_LRSPACE ); + sal_uInt16 nAbsLSpace = (sal_uInt16)( ( (sal_uInt32)_nTextOfs * 2540 ) / 576 ); + sal_uInt16 nFirstLineOffset = nAbsLSpace - (sal_uInt16)( ( (sal_uInt32)_nBulletOfs * 2540 ) / 576 ); + aLRSpaceItem.SetLeft( nAbsLSpace ); + aLRSpaceItem.SetTxtFirstLineOfstValue( -nFirstLineOffset ); + rSet.Put( aLRSpaceItem ); + } + else + { + SvxLRSpaceItem aLRSpaceItem( EE_PARA_LRSPACE ); + aLRSpaceItem.SetLeft( 0 ); + aLRSpaceItem.SetTxtFirstLineOfstValue( 0 ); + rSet.Put( aLRSpaceItem ); + } + if ( GetAttrib( PPT_ParaAttr_Adjust, nVal, nDestinationInstance ) ) + { + if ( nVal <= 3 ) + { // Absatzausrichtung + static SvxAdjust __READONLY_DATA aAdj[ 4 ] = { SVX_ADJUST_LEFT, SVX_ADJUST_CENTER, SVX_ADJUST_RIGHT, SVX_ADJUST_BLOCK }; + rSet.Put( SvxAdjustItem( aAdj[ nVal ], EE_PARA_JUST ) ); + } + } + + if ( GetAttrib( PPT_ParaAttr_AsianLB_1, nVal, nDestinationInstance ) ) + rSet.Put( SfxBoolItem( EE_PARA_FORBIDDENRULES, nVal != 0 ) ); + if ( GetAttrib( PPT_ParaAttr_AsianLB_3, nVal, nDestinationInstance ) ) + rSet.Put( SfxBoolItem( EE_PARA_HANGINGPUNCTUATION, nVal != 0 ) ); + + if ( GetAttrib( PPT_ParaAttr_BiDi, nVal, nDestinationInstance ) ) + rSet.Put( SvxFrameDirectionItem( nVal == 1 ? FRMDIR_HORI_RIGHT_TOP : FRMDIR_HORI_LEFT_TOP, EE_PARA_WRITINGDIR ) ); + + // LineSpacing + PPTPortionObj* pPortion = First(); + sal_Bool bIsHardAttribute = GetAttrib( PPT_ParaAttr_LineFeed, nVal, nDestinationInstance ); + nVal2 = (sal_Int16)nVal; + sal_uInt32 nFont = sal_uInt32(); + if ( pPortion && pPortion->GetAttrib( PPT_CharAttr_Font, nFont, nDestinationInstance ) ) + bIsHardAttribute = sal_True; + + if ( bIsHardAttribute ) + { + if ( pPortion && ( nVal2 > 200 ) ) + { + sal_uInt32 nFontHeight; + pPortion->GetAttrib( PPT_CharAttr_FontHeight, nFontHeight, nDestinationInstance ); + nVal2 = -(sal_Int16)( ( nFontHeight * nVal * 8 ) / 100 ); + } + rSet.Put( SdrTextFixedCellHeightItem( sal_True ), SDRATTR_TEXT_USEFIXEDCELLHEIGHT ); + SvxLineSpacingItem aItem( 200, EE_PARA_SBL ); + if ( nVal2 <= 0 ) + aItem.SetLineHeight( (sal_uInt16)( rManager.ScalePoint( -nVal2 ) / 8 ) ); + else + { + sal_uInt8 nPropLineSpace = (sal_uInt8)nVal2; + aItem.SetPropLineSpace( nPropLineSpace ); + aItem.GetLineSpaceRule() = SVX_LINE_SPACE_AUTO; + } + rSet.Put( aItem ); + } + + // Paragraph Spacing + sal_uInt32 nFontHeight = 0; + bIsHardAttribute = ( (sal_uInt32)GetAttrib( PPT_ParaAttr_UpperDist, nUpperDist, nDestinationInstance ) + + (sal_uInt32)GetAttrib( PPT_ParaAttr_LowerDist, nLowerDist, nDestinationInstance ) ) != 0; + if ( ( nUpperDist > 0 ) || ( nLowerDist > 0 ) ) + { + if ( mnPortionCount ) + { + mpPortionList[ mnPortionCount - 1 ]->GetAttrib( PPT_CharAttr_FontHeight, nFontHeight, nDestinationInstance ); + if ( ((sal_Int16)nUpperDist) > 0 ) + nUpperDist = - (sal_Int16)( ( nFontHeight * nUpperDist * 100 ) / 1000 ); + if ( ((sal_Int16)nLowerDist) > 0 ) + nLowerDist = - (sal_Int16)( ( nFontHeight * nLowerDist * 100 ) / 1000 ); + } + bIsHardAttribute = sal_True; + } + if ( bIsHardAttribute ) + { + SvxULSpaceItem aULSpaceItem( EE_PARA_ULSPACE ); + nVal2 = (sal_Int16)nUpperDist; + if ( nVal2 <= 0 ) + aULSpaceItem.SetUpper( (sal_uInt16)(((sal_uInt32) - nVal2 * 2540 ) / ( 72 * 8 ) ) ); + else + { + aULSpaceItem.SetUpperValue( 0 ); + aULSpaceItem.SetPropUpper( (sal_uInt16)nUpperDist == 100 ? 101 : (sal_uInt16)nUpperDist ); + } + nVal2 = (sal_Int16)nLowerDist; + if ( nVal2 <= 0 ) + aULSpaceItem.SetLower( (sal_uInt16)(((sal_uInt32) - nVal2 * 2540 ) / ( 72 * 8 ) ) ); + else + { + aULSpaceItem.SetLowerValue( 0 ); + aULSpaceItem.SetPropLower( (sal_uInt16)nLowerDist == 100 ? 101 : (sal_uInt16)nLowerDist ); + } + rSet.Put( aULSpaceItem ); + } + + if ( mbTab ) // makes it sense to apply tabsettings + { + sal_uInt32 i, nDefaultTab, nTab, nTextOfs2 = 0; + sal_uInt32 nLatestManTab = 0; + GetAttrib( PPT_ParaAttr_TextOfs, nTextOfs2, nDestinationInstance ); + GetAttrib( PPT_ParaAttr_BulletOfs, nTab, nDestinationInstance ); + GetAttrib( PPT_ParaAttr_BulletOn, i, nDestinationInstance ); + GetAttrib( PPT_ParaAttr_DefaultTab, nDefaultTab, nDestinationInstance ); + SvxTabStopItem aTabItem( 0, 0, SVX_TAB_ADJUST_DEFAULT, EE_PARA_TABS ); + if ( GetTabCount() ) + { + for ( i = 0; i < GetTabCount(); i++ ) + { + SvxTabAdjust eTabAdjust; + nTab = GetTabOffsetByIndex( (sal_uInt16)i ); + switch( GetTabStyleByIndex( (sal_uInt16)i ) ) + { + case 1 : eTabAdjust = SVX_TAB_ADJUST_CENTER; break; + case 2 : eTabAdjust = SVX_TAB_ADJUST_RIGHT; break; + case 3 : eTabAdjust = SVX_TAB_ADJUST_DECIMAL; break; + default : eTabAdjust = SVX_TAB_ADJUST_LEFT; + } + if ( nTab > nTextOfs2 ) + aTabItem.Insert( SvxTabStop( (sal_uInt16)( ( ( nTab - nTextOfs2 ) * 2540 ) / 576 ), eTabAdjust ) ); + } + nLatestManTab = nTab; + } + if ( nIsBullet2 == 0 ) + aTabItem.Insert( SvxTabStop( (sal_uInt16)0 ) ); + if ( nDefaultTab ) + { + nTab = ( nTextOfs2 > nLatestManTab ) ? nTextOfs2 : nLatestManTab; + nTab /= nDefaultTab; + nTab = nDefaultTab * ( 1 + nTab ); + for ( i = 0; ( i < 20 ) && ( nTab < 0x1b00 ); i++ ) + { + aTabItem.Insert( SvxTabStop( (sal_uInt16)( ( ( nTab - nTextOfs2 ) * 2540 ) / 576 ) ) ); + nTab += nDefaultTab; + } + } + rSet.Put( aTabItem ); + } +} + +sal_uInt32 PPTParagraphObj::GetTextSize() +{ + sal_uInt32 nCount, nRetValue = 0; + for ( sal_uInt32 i = 0; i < mnPortionCount; i++ ) + { + PPTPortionObj* pPortionObj = mpPortionList[ i ]; + nCount = pPortionObj->Count(); + if ( ( !nCount ) && pPortionObj->mpFieldItem ) + nCount++; + nRetValue += nCount; + } + return nRetValue; +} + +PPTPortionObj* PPTParagraphObj::First() +{ + mnCurrentObject = 0; + if ( !mnPortionCount ) + return NULL; + return mpPortionList[ 0 ]; +} + +PPTPortionObj* PPTParagraphObj::Next() +{ + sal_uInt32 i = mnCurrentObject + 1; + if ( i >= mnPortionCount ) + return NULL; + mnCurrentObject++; + return mpPortionList[ i ]; +} + +void PPTParagraphObj::ImplClear() +{ + for ( void* pPtr = First(); pPtr; pPtr = Next() ) + delete (PPTPortionObj*)pPtr; + delete[] mpPortionList; +} + +PPTFieldEntry::~PPTFieldEntry() +{ + delete pField1; + delete pField2; + delete pString; +}; + +void PPTFieldEntry::GetDateTime( const sal_uInt32 nVal, SvxDateFormat& eDateFormat, SvxTimeFormat& eTimeFormat ) +{ + eDateFormat = SVXDATEFORMAT_APPDEFAULT; + eTimeFormat = SVXTIMEFORMAT_APPDEFAULT; + // ID auswerten + switch( nVal ) + { + case 0: + case 6: + eDateFormat = SVXDATEFORMAT_A; + break; + case 1: + eDateFormat = SVXDATEFORMAT_F; + break; + case 2: + case 3: + eDateFormat = SVXDATEFORMAT_D; + break; + case 4: + case 5: + eDateFormat = SVXDATEFORMAT_C; + break; + case 7: + eDateFormat = SVXDATEFORMAT_A; + case 9: + eTimeFormat = SVXTIMEFORMAT_24_HM; + break; + case 8: + eDateFormat = SVXDATEFORMAT_A; + case 11: + eTimeFormat = SVXTIMEFORMAT_12_HM; + break; + case 10: + eTimeFormat = SVXTIMEFORMAT_24_HMS; + break; + case 12: + eTimeFormat = SVXTIMEFORMAT_12_HMS; + break; + } +} + +void PPTFieldEntry::SetDateTime( sal_uInt32 nVal ) +{ + SvxDateFormat eDateFormat; + SvxTimeFormat eTimeFormat; + GetDateTime( nVal, eDateFormat, eTimeFormat ); + if ( eDateFormat != SVXDATEFORMAT_APPDEFAULT ) + pField1 = new SvxFieldItem( SvxDateField( Date(), SVXDATETYPE_VAR, eDateFormat ), EE_FEATURE_FIELD ); + if ( eTimeFormat != SVXTIMEFORMAT_APPDEFAULT ) + { + SvxFieldItem* pFieldItem = new SvxFieldItem( SvxExtTimeField( Time(), SVXTIMETYPE_VAR, eTimeFormat ), EE_FEATURE_FIELD ); + if ( pField1 ) + pField2 = pFieldItem; + else + pField1 = pFieldItem; + } +} + +// ----------------------------------------------------------------------- + +PPTTextObj::PPTTextObj( SvStream& rIn, SdrPowerPointImport& rSdrPowerPointImport, PptSlidePersistEntry& rPersistEntry, DffObjData* pObjData ) : + mpImplTextObj ( new ImplPPTTextObj( rPersistEntry ) ) +{ + mpImplTextObj->mnRefCount = 1; + mpImplTextObj->mnShapeId = 0; + mpImplTextObj->mnShapeMaster = 0; + mpImplTextObj->mpPlaceHolderAtom = NULL; + mpImplTextObj->mnDestinationInstance = mpImplTextObj->mnInstance = 4; + mpImplTextObj->mnCurrentObject = 0; + mpImplTextObj->mnParagraphCount = 0; + mpImplTextObj->mpParagraphList = NULL; + mpImplTextObj->mnTextFlags = 0; + mpImplTextObj->meShapeType = ( pObjData && pObjData->bShapeType ) ? pObjData->eShapeType : mso_sptMin; + + DffRecordHeader aExtParaHd; + aExtParaHd.nRecType = 0; // set empty + + sal_uInt32 bStatus = sal_True; + + DffRecordHeader aShapeContainerHd; + rIn >> aShapeContainerHd; + + if ( ( pObjData == NULL ) || ( pObjData->bShapeType ) ) + { + PPTExtParaProv* pExtParaProv = rSdrPowerPointImport.pPPTStyleSheet->pExtParaProv; + if ( pObjData ) + { + mpImplTextObj->mnShapeId = pObjData->nShapeId; + if ( pObjData->nSpFlags & SP_FHAVEMASTER ) + mpImplTextObj->mnShapeMaster = rSdrPowerPointImport.GetPropertyValue( DFF_Prop_hspMaster, 0 ); + } + //////////////// + // ClientData // + //////////////// + if ( rSdrPowerPointImport.maShapeRecords.SeekToContent( rIn, DFF_msofbtClientData, SEEK_FROM_CURRENT_AND_RESTART ) ) + { + sal_uInt32 nOldPos = rIn.Tell(); + DffRecordHeader& aClientDataContainerHd = *rSdrPowerPointImport.maShapeRecords.Current(); + DffRecordHeader aPlaceHolderAtomHd; + if ( rSdrPowerPointImport.SeekToRec( rIn, PPT_PST_OEPlaceholderAtom, aClientDataContainerHd.GetRecEndFilePos(), &aPlaceHolderAtomHd ) ) + { + mpImplTextObj->mpPlaceHolderAtom = new PptOEPlaceholderAtom; + rIn >> *( mpImplTextObj->mpPlaceHolderAtom ); + } + rIn.Seek( nOldPos ); + DffRecordHeader aProgTagHd; + if ( rSdrPowerPointImport.SeekToContentOfProgTag( 9, rIn, aClientDataContainerHd, aProgTagHd ) ) + { + rIn >> aExtParaHd; + } + } + + /////////////////// + // ClientTextBox // + /////////////////// + if ( rSdrPowerPointImport.maShapeRecords.SeekToContent( rIn, DFF_msofbtClientTextbox, SEEK_FROM_CURRENT_AND_RESTART ) ) + { + DffRecordHeader aClientTextBoxHd( *rSdrPowerPointImport.maShapeRecords.Current() ); + sal_uInt32 nTextRulerAtomOfs = 0; // case of zero -> this atom may be found in aClientDataContainerHd; + // case of -1 -> ther is no atom of this kind + // else -> this is the fileofs where we can get it + + ////////////////////////////////////// + // checkout if this is a referenced // + // textobj, if so the we will patch // + // the ClientTextBoxHd for a // + // equivalent one // + ////////////////////////////////////// + DffRecordHeader aTextHd; + if ( rSdrPowerPointImport.SeekToRec( rIn, PPT_PST_OutlineTextRefAtom, aClientTextBoxHd.GetRecEndFilePos(), &aTextHd ) ) + { + sal_uInt32 nRefNum; + rIn >> nRefNum; + + if ( rSdrPowerPointImport.SeekToRec( rIn, PPT_PST_TextRulerAtom, aClientTextBoxHd.GetRecEndFilePos() ) ) + nTextRulerAtomOfs = rIn.Tell(); + else + nTextRulerAtomOfs = 0xffffffff; + + sal_uInt32 nInstance = 0; + switch( rSdrPowerPointImport.eAktPageKind ) + { + case PPT_NOTEPAGE : + nInstance++; + case PPT_MASTERPAGE : + nInstance++; + case PPT_SLIDEPAGE : + break; + default : + bStatus = sal_False; + } + if ( bStatus ) + { + sal_uInt32 nSlideId = rSdrPowerPointImport.GetAktPageId(); + if ( !nSlideId ) + bStatus = sal_False; + else + { + if ( !aExtParaHd.nRecType ) + { + sal_uInt32 nOldPos = rIn.Tell(); + // try to locate the referenced ExtendedParaHd + DffRecordHeader* pHd = pExtParaProv-> + aExtendedPresRules.GetRecordHeader( PPT_PST_ExtendedParagraphHeaderAtom, + SEEK_FROM_CURRENT_AND_RESTART ); + DffRecordHeader aPresRuleHd; + DffRecordHeader* pFirst = pHd; + + sal_uInt32 nTmpSlideId, nTmpRef; + while ( pHd ) + { + pHd->SeekToContent( rIn ); + rIn >> nTmpSlideId + >> nTmpRef; // this seems to be the instance + + if ( ( nTmpSlideId == nSlideId ) && ( pHd->nRecInstance == nRefNum ) ) + { + pHd->SeekToEndOfRecord( rIn ); + rIn >> aPresRuleHd; + if ( aPresRuleHd.nRecType == PPT_PST_ExtendedParagraphAtom ) + { + aExtParaHd = aPresRuleHd; + break; + } + } + pHd = pExtParaProv-> + aExtendedPresRules.GetRecordHeader( PPT_PST_ExtendedParagraphHeaderAtom, + SEEK_FROM_CURRENT_AND_RESTART ); + if ( pHd == pFirst ) + break; + } + rIn.Seek( nOldPos ); + } + // now pHd points to the right SlideListWithText Container + PptSlidePersistList* pPageList = rSdrPowerPointImport.GetPageList( rSdrPowerPointImport.eAktPageKind ); + PptSlidePersistEntry* pE = NULL; + if ( pPageList && ( rSdrPowerPointImport.nAktPageNum < pPageList->Count() ) ) + pE = (*pPageList)[ rSdrPowerPointImport.nAktPageNum ]; + if ( (!pE) || (!pE->nSlidePersistStartOffset) || ( pE->aPersistAtom.nSlideId != nSlideId ) ) + bStatus = sal_False; + else + { + rIn.Seek( pE->nSlidePersistStartOffset ); + // now we got the right page and are searching for the right + // TextHeaderAtom + while ( rIn.Tell() < pE->nSlidePersistEndOffset ) + { + rIn >> aClientTextBoxHd; + if ( aClientTextBoxHd.nRecType == PPT_PST_TextHeaderAtom ) + { + if ( aClientTextBoxHd.nRecInstance == nRefNum ) + { + aClientTextBoxHd.SeekToEndOfRecord( rIn ); + break; + } + } + aClientTextBoxHd.SeekToEndOfRecord( rIn ); + } + if ( rIn.Tell() > pE->nSlidePersistEndOffset ) + bStatus = sal_False; + else + { // patching the RecordHeader + aClientTextBoxHd.nFilePos -= DFF_COMMON_RECORD_HEADER_SIZE; + aClientTextBoxHd.nRecLen += DFF_COMMON_RECORD_HEADER_SIZE; + aClientTextBoxHd.nRecType = DFF_msofbtClientTextbox; + aClientTextBoxHd.nRecVer = DFF_PSFLAG_CONTAINER; + + // we have to calculate the correct record len + DffRecordHeader aTmpHd; + while ( rIn.Tell() < pE->nSlidePersistEndOffset ) + { + rIn >> aTmpHd; + if ( ( aTmpHd.nRecType == PPT_PST_SlidePersistAtom ) || ( aTmpHd.nRecType == PPT_PST_TextHeaderAtom ) ) + break; + aTmpHd.SeekToEndOfRecord( rIn ); + aClientTextBoxHd.nRecLen += aTmpHd.nRecLen + DFF_COMMON_RECORD_HEADER_SIZE; + } + aClientTextBoxHd.SeekToContent( rIn ); + } + } + } + } + } + + if ( bStatus ) + { + if ( rSdrPowerPointImport.SeekToRec( rIn, PPT_PST_TextHeaderAtom, aClientTextBoxHd.GetRecEndFilePos(), &aTextHd ) ) + { + // TextHeaderAtom is always the first Atom + sal_uInt16 nInstance; + rIn >> nInstance; // this number tells us the TxMasterStyleAtom Instance + if ( nInstance > 8 ) + nInstance = 4; + aTextHd.SeekToEndOfRecord( rIn ); + mpImplTextObj->mnInstance = nInstance; + + sal_uInt32 nFilePos = rIn.Tell(); + if ( rSdrPowerPointImport.SeekToRec2( PPT_PST_TextBytesAtom, + PPT_PST_TextCharsAtom, + aClientTextBoxHd.GetRecEndFilePos() ) + || rSdrPowerPointImport.SeekToRec( rIn, + PPT_PST_StyleTextPropAtom, + aClientTextBoxHd.GetRecEndFilePos() ) ) + { + PPTTextRulerInterpreter aTextRulerInterpreter( nTextRulerAtomOfs, rSdrPowerPointImport, + aClientTextBoxHd, rIn ); + + PPTStyleTextPropReader aStyleTextPropReader( rIn, rSdrPowerPointImport, aClientTextBoxHd, + aTextRulerInterpreter, aExtParaHd, nInstance ); + sal_uInt32 nParagraphs = mpImplTextObj->mnParagraphCount = aStyleTextPropReader.aParaPropList.Count(); + if ( nParagraphs ) + { + // the language settings will be merged into the list of PPTCharPropSet + DffRecordHeader aTextSpecInfoHd; + PPTTextSpecInfoAtomInterpreter aTextSpecInfoAtomInterpreter; + if ( rSdrPowerPointImport.SeekToRec( rIn, PPT_PST_TextSpecInfoAtom, + aClientTextBoxHd.GetRecEndFilePos(), &aTextSpecInfoHd ) ) + { + if ( aTextSpecInfoAtomInterpreter.Read( rIn, aTextSpecInfoHd, PPT_PST_TextSpecInfoAtom, + &(rSdrPowerPointImport.pPPTStyleSheet->maTxSI) ) ) + { + sal_uInt32 nI = 0; + PPTTextSpecInfo* pSpecInfo; + for ( pSpecInfo = (PPTTextSpecInfo*)aTextSpecInfoAtomInterpreter.aList.First(); + pSpecInfo; pSpecInfo =(PPTTextSpecInfo*)aTextSpecInfoAtomInterpreter.aList.Next() ) + { + sal_uInt32 nCharIdx = pSpecInfo->nCharIdx; + + // portions and text have to been splitted in some cases + for ( ; nI < aStyleTextPropReader.aCharPropList.Count(); ) + { + PPTCharPropSet* pSet = (PPTCharPropSet*)aStyleTextPropReader.aCharPropList.GetObject( nI ); + if ( pSet->mnOriginalTextPos < nCharIdx ) + { + pSet->mnLanguage[ 0 ] = pSpecInfo->nLanguage[ 0 ]; + pSet->mnLanguage[ 1 ] = pSpecInfo->nLanguage[ 1 ]; + pSet->mnLanguage[ 2 ] = pSpecInfo->nLanguage[ 2 ]; + // test if the current portion needs to be splitted + if ( pSet->maString.Len() > 1 ) + { + sal_Int32 nIndexOfNextPortion = pSet->maString.Len() + pSet->mnOriginalTextPos; + sal_Int32 nNewLen = nIndexOfNextPortion - nCharIdx; + sal_Int32 nOldLen = pSet->maString.Len() - nNewLen; + + if ( ( nNewLen > 0 ) && ( nOldLen > 0 ) ) + { + String aString( pSet->maString ); + PPTCharPropSet* pNew = new PPTCharPropSet( *pSet ); + pSet->maString = String( aString, 0, (sal_uInt16)nOldLen ); + pNew->maString = String( aString, (sal_uInt16)nOldLen, (sal_uInt16)nNewLen ); + pNew->mnOriginalTextPos += nOldLen; + aStyleTextPropReader.aCharPropList.Insert( pNew, nI + 1 ); + } + } + } + else + break; + nI++; + } + } + } +#ifdef DBG_UTIL + else + { + if (!(rSdrPowerPointImport.rImportParam.nImportFlags & PPT_IMPORTFLAGS_NO_TEXT_ASSERT)) + { + DBG_ERROR( "SdrTextSpecInfoAtomInterpreter::Ctor(): parsing error, this document needs to be analysed (SJ)" ); + } + } +#endif + } + // + // now will search for possible textextensions such as date/time fields + // or ParaTabStops and append them on this textobj + // + rIn.Seek( nFilePos ); + List* pFieldList = NULL; + while ( rIn.Tell() < aClientTextBoxHd.GetRecEndFilePos() ) + { + rIn >> aTextHd; + sal_uInt16 nVal = 0; + PPTFieldEntry* pEntry = NULL; + switch ( aTextHd.nRecType ) + { + case PPT_PST_DateTimeMCAtom : + { + pEntry = new PPTFieldEntry; + rIn >> pEntry->nPos + >> nVal + >> nVal; + pEntry->SetDateTime( nVal & 0xff ); + } + break; + + case PPT_PST_FooterMCAtom : + { + pEntry = new PPTFieldEntry; + rIn >> pEntry->nPos; + pEntry->pField1 = new SvxFieldItem( SvxFooterField(), EE_FEATURE_FIELD ); + } + break; + + case PPT_PST_HeaderMCAtom : + { + pEntry = new PPTFieldEntry; + rIn >> pEntry->nPos; + pEntry->pField1 = new SvxFieldItem( SvxHeaderField(), EE_FEATURE_FIELD ); + } + break; + + case PPT_PST_GenericDateMCAtom : + { + pEntry = new PPTFieldEntry; + rIn >> pEntry->nPos; + pEntry->pField1 = new SvxFieldItem( SvxDateTimeField(), EE_FEATURE_FIELD ); + if ( rPersistEntry.pHeaderFooterEntry ) // sj: #i34111# on master pages it is possible + { // that there is no HeaderFooterEntry available + if ( rPersistEntry.pHeaderFooterEntry->nAtom & 0x20000 ) // auto date time + pEntry->SetDateTime( rPersistEntry.pHeaderFooterEntry->nAtom & 0xff ); + else + pEntry->pString = new String( rPersistEntry.pHeaderFooterEntry->pPlaceholder[ nVal ] ); + } + } + break; + + case PPT_PST_SlideNumberMCAtom : + case PPT_PST_RTFDateTimeMCAtom : + { + pEntry = new PPTFieldEntry; + if ( aTextHd.nRecLen >= 4 ) + { + rIn >> pEntry->nPos + >> nVal; + + // ID auswerten + //SvxFieldItem* pFieldItem = NULL; + switch( aTextHd.nRecType ) + { + case PPT_PST_SlideNumberMCAtom: + pEntry->pField1 = new SvxFieldItem( SvxPageField(), EE_FEATURE_FIELD ); + break; + + case PPT_PST_RTFDateTimeMCAtom: + { + // Rude workaround for one specal case reported + // by a customer. (#i75203#) + + // Don't even attempt to handle the general use + // case for PPT_PST_RTFDateTimeMCAtom (a generic + // MS style date/time format string). Just handle + // the special case where the format string + // contains only one or several possibly empty + // quoted strings. I.e. something that doesn't + // expand to any date or time at all, but to a + // fixed string. How on earth somebody manages to + // produce such things in PPT slides I have no + // idea. + if (nVal == 0) + { + sal_Unicode n; + xub_StrLen nLen; + String aStr; + bool inquote = sal_False; + for (nLen = 0, n = 0; nLen < 64; nLen++) + { + rIn >> n; + + // Collect quoted characters into aStr + if ( n == '\'') + inquote = !inquote; + else if (!n) + { + // End of format string + pEntry->pString = new String( aStr ); + break; + } + else if (!inquote) + { + // Non-quoted character, i.e. a real + // format specifier. We don't handle + // those. Sorry. + break; + } + else + { + aStr += n; + } + } + } + if ( pEntry->pString == NULL ) + { + // Handle as previously + pEntry->pField1 = new SvxFieldItem( SvxDateField( Date(), SVXDATETYPE_FIX ), EE_FEATURE_FIELD ); + } + } + } + } + } + break; + + case PPT_PST_InteractiveInfo : + { + DffRecordHeader aHdInteractiveInfoAtom; + if ( rSdrPowerPointImport.SeekToRec( rIn, PPT_PST_InteractiveInfoAtom, aTextHd.GetRecEndFilePos(), &aHdInteractiveInfoAtom ) ) + { + PptInteractiveInfoAtom aInteractiveInfoAtom; + rIn >> aInteractiveInfoAtom; + for ( SdHyperlinkEntry* pHyperlink = (SdHyperlinkEntry*)rSdrPowerPointImport.aHyperList.First(); + pHyperlink; pHyperlink = (SdHyperlinkEntry*)rSdrPowerPointImport.aHyperList.Next() ) + { + if ( pHyperlink->nIndex == aInteractiveInfoAtom.nExHyperlinkId ) + { + aTextHd.SeekToEndOfRecord( rIn ); + rIn >> aTextHd; + if ( aTextHd.nRecType != PPT_PST_TxInteractiveInfoAtom ) + { + aTextHd.SeekToBegOfRecord( rIn ); + continue; + } + else + { + sal_uInt32 nStartPos, nEndPos; + rIn >> nStartPos + >> nEndPos; + if ( nEndPos ) + { + pEntry = new PPTFieldEntry; + pEntry->nPos = (sal_uInt16)nStartPos; + pEntry->nTextRangeEnd = (sal_uInt16)nEndPos; + String aTarget( pHyperlink->aTarget ); + if ( pHyperlink->aConvSubString.Len() ) + { + aTarget.Append( (sal_Unicode)'#' ); + aTarget.Append( pHyperlink->aConvSubString ); + } + pEntry->pField1 = new SvxFieldItem( SvxURLField( aTarget, String(), SVXURLFORMAT_REPR ), EE_FEATURE_FIELD ); + } + } + break; + } + } + } + } + break; + } + aTextHd.SeekToEndOfRecord( rIn ); + if ( pEntry ) + { + if ( !pFieldList ) + pFieldList = new List; + sal_uInt32 n; + for ( n = 0; n < pFieldList->Count(); n++ ) + { // sorting fields ( hi >> lo ) + if ( ( (PPTFieldEntry*)pFieldList->GetObject( n ) )->nPos < pEntry->nPos ) + break; + } + pFieldList->Insert( pEntry, (sal_uInt32)n ); + } + } + if ( pFieldList ) + { + PPTFieldEntry* pFE = (PPTFieldEntry*)pFieldList->First(); + List& aCharPropList = aStyleTextPropReader.aCharPropList; + + sal_Int32 i = nParagraphs - 1; + sal_Int32 n = aCharPropList.Count() - 1; + + // at this point we just have a list of textportions(aCharPropList) + // the next while loop tries to resolve the list of fields(pFieldList) + while( pFE && ( n >= 0 ) && ( i >= 0 ) ) + { + PPTCharPropSet* pSet = (PPTCharPropSet*)aCharPropList.GetObject( n ); + String aString( pSet->maString ); + sal_uInt32 nCount = aString.Len(); + sal_uInt32 nPos = pSet->mnOriginalTextPos + nCount; + while ( pFE && nCount-- ) + { + nPos--; + while ( pFE && ( pFE->nPos > nPos ) ) + pFE = (PPTFieldEntry*)pFieldList->Next(); + if ( !pFE ) + break; + + if ( pFE->nPos == nPos ) + { + if ( aString.GetChar( (sal_uInt16)nCount ) == 0x2a ) + { + sal_uInt32 nBehind = aString.Len() - ( nCount + 1 ); + pSet->maString = String(); + if ( nBehind ) + { + PPTCharPropSet* pNewCPS = new PPTCharPropSet( *pSet ); + pNewCPS->maString = String( aString, (sal_uInt16)nCount + 1, (sal_uInt16)nBehind ); + aCharPropList.Insert( pNewCPS, n + 1 ); + } + if ( pFE->pField2 ) + { + PPTCharPropSet* pNewCPS = new PPTCharPropSet( *pSet ); + pNewCPS->mpFieldItem = pFE->pField2, pFE->pField2 = NULL; + aCharPropList.Insert( pNewCPS, n + 1 ); + + pNewCPS = new PPTCharPropSet( *pSet ); + pNewCPS->maString = String( String( RTL_CONSTASCII_USTRINGPARAM( " " ) ) ); + aCharPropList.Insert( pNewCPS, n + 1 ); + } + if ( nCount ) + { + PPTCharPropSet* pNewCPS = new PPTCharPropSet( *pSet ); + pNewCPS->maString = String( aString, (sal_uInt16)0, (sal_uInt16)nCount ); + aCharPropList.Insert( pNewCPS, n++ ); + } + if ( pFE->pField1 ) + { + pSet->mpFieldItem = pFE->pField1, pFE->pField1 = NULL; + } + else if ( pFE->pString ) + pSet->maString = *pFE->pString; + } + else + { + if ( pFE->nTextRangeEnd ) // text range hyperlink + { + sal_uInt32 nHyperLen = pFE->nTextRangeEnd - nPos; + if ( nHyperLen ) + { + PPTCharPropSet* pBefCPS = NULL; + if ( nCount ) + { + pBefCPS = new PPTCharPropSet( *pSet ); + pSet->maString = String( pSet->maString, (sal_uInt16)nCount, (sal_uInt16)( pSet->maString.Len() - nCount ) ); + } + sal_uInt32 nIdx = n; + sal_Int32 nHyperLenLeft = nHyperLen; + + while ( ( aCharPropList.Count() > nIdx ) && nHyperLenLeft ) + { + // the textrange hyperlink can take more than 1 paragraph + // the solution here is to clone the hyperlink... + + PPTCharPropSet* pCurrent = (PPTCharPropSet*)aCharPropList.GetObject( nIdx ); + sal_Int32 nNextStringLen = pCurrent->maString.Len(); + + DBG_ASSERT( pFE->pField1, "missing field!" ); + if (!pFE->pField1) + break; + + const SvxURLField* pField = (const SvxURLField*)pFE->pField1->GetField(); + + if ( pCurrent->mpFieldItem ) + { + pCurrent->SetColor( PPT_COLSCHEME_A_UND_HYPERLINK ); + if ( pCurrent->mpFieldItem->GetField()->ISA( SvxURLField ) ) + break; + nHyperLenLeft--; + } + else if ( nNextStringLen ) + { + if ( nNextStringLen <= nHyperLenLeft ) + { + pCurrent->mpFieldItem = new SvxFieldItem( SvxURLField( pField->GetURL(), pCurrent->maString, SVXURLFORMAT_REPR ), EE_FEATURE_FIELD ); + nHyperLenLeft -= nNextStringLen; + + if ( nHyperLenLeft ) + { + // if the next portion is in a higher paragraph, + // the textrange is to decrease (because of the LineBreak character) + if ( aCharPropList.Count() > ( nIdx + 1 ) ) + { + PPTCharPropSet* pNext = (PPTCharPropSet*)aCharPropList.GetObject( nIdx + 1 ); + if ( pNext->mnParagraph > pCurrent->mnParagraph ) + nHyperLenLeft--; + } + } + } + else + { + PPTCharPropSet* pNewCPS = new PPTCharPropSet( *pCurrent ); + pNewCPS->maString = String( pCurrent->maString, (sal_uInt16)nHyperLenLeft, (sal_uInt16)( nNextStringLen - nHyperLenLeft ) ); + aCharPropList.Insert( pNewCPS, nIdx + 1 ); + String aRepresentation( pCurrent->maString, 0, (sal_uInt16)nHyperLenLeft ); + pCurrent->mpFieldItem = new SvxFieldItem( SvxURLField( pField->GetURL(), aRepresentation, SVXURLFORMAT_REPR ), EE_FEATURE_FIELD ); + nHyperLenLeft = 0; + } + pCurrent->maString = String(); + pCurrent->SetColor( PPT_COLSCHEME_A_UND_HYPERLINK ); + } + nIdx++; + } + delete pFE->pField1, pFE->pField1 = NULL; + + if ( pBefCPS ) + { + pBefCPS->maString = String( aString, (sal_uInt16)0, (sal_uInt16)nCount ); + aCharPropList.Insert( pBefCPS, n++ ); + + } + } + } + } + break; + } + } + n--; + } + for ( void* pPtr = pFieldList->First(); pPtr; pPtr = pFieldList->Next() ) + delete (PPTFieldEntry*)pPtr; + delete pFieldList; + } + mpImplTextObj->mpParagraphList = new PPTParagraphObj*[ nParagraphs ]; + aStyleTextPropReader.aCharPropList.First(); + sal_uInt32 nCount = 0; + for ( void* pPtr = aStyleTextPropReader.aParaPropList.First(); + pPtr; + pPtr = aStyleTextPropReader.aParaPropList.Next() ) + { + PPTParagraphObj* pPara = new PPTParagraphObj( aStyleTextPropReader, *rSdrPowerPointImport.pPPTStyleSheet, nInstance, aTextRulerInterpreter ); + mpImplTextObj->mpParagraphList[ nCount++ ] = pPara; + + sal_uInt32 nParaAdjust, nFlags = 0; + pPara->GetAttrib( PPT_ParaAttr_Adjust, nParaAdjust, GetInstance() ); + + switch ( nParaAdjust ) + { + case 0 : nFlags = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT; break; + case 1 : nFlags = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER; break; + case 2 : nFlags = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT; break; + case 3 : nFlags = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK; break; + } + mpImplTextObj->mnTextFlags |= nFlags; + } + } + } + } + } + } + } +} + +PPTTextObj::PPTTextObj( PPTTextObj& rTextObj ) +{ + mpImplTextObj = rTextObj.mpImplTextObj; + mpImplTextObj->mnRefCount++; +} + +PPTTextObj::~PPTTextObj() +{ + ImplClear(); +} + +PPTParagraphObj* PPTTextObj::First() +{ + mpImplTextObj->mnCurrentObject = 0; + if ( !mpImplTextObj->mnParagraphCount ) + return NULL; + return mpImplTextObj->mpParagraphList[ 0 ]; +} + +PPTParagraphObj* PPTTextObj::Next() +{ + sal_uInt32 i = mpImplTextObj->mnCurrentObject + 1; + if ( i >= mpImplTextObj->mnParagraphCount ) + return NULL; + mpImplTextObj->mnCurrentObject++; + return mpImplTextObj->mpParagraphList[ i ]; +} + +const SfxItemSet* PPTTextObj::GetBackground() const +{ + if ( mpImplTextObj->mrPersistEntry.pBObj ) + return &mpImplTextObj->mrPersistEntry.pBObj->GetMergedItemSet(); + else + return NULL; +} + +void PPTTextObj::ImplClear() +{ + if ( ! ( --mpImplTextObj->mnRefCount ) ) + { + for ( PPTParagraphObj* pPtr = First(); pPtr; pPtr = Next() ) + delete pPtr; + delete[] mpImplTextObj->mpParagraphList; + delete mpImplTextObj->mpPlaceHolderAtom; + delete mpImplTextObj; + } +} + +PPTTextObj& PPTTextObj::operator=( PPTTextObj& rTextObj ) +{ + if ( this != &rTextObj ) + { + ImplClear(); + mpImplTextObj = rTextObj.mpImplTextObj; + mpImplTextObj->mnRefCount++; + } + return *this; +} + +sal_Bool IsLine( const SdrObject* pObj ) +{ + return pObj->ISA( SdrPathObj ) && ((SdrPathObj*)pObj)->IsLine() && (((SdrPathObj*)pObj)->GetPointCount() == 2 ); +} + +sal_Bool GetCellPosition( const SdrObject* pObj, const std::set< sal_Int32 >& rRows, const std::set< sal_Int32 >& rColumns, + sal_Int32& nTableIndex, sal_Int32& nRow, sal_Int32& nRowCount, sal_Int32& nColumn, sal_Int32& nColumnCount ) +{ + Rectangle aSnapRect( pObj->GetSnapRect() ); + sal_Bool bCellObject = ( aSnapRect.GetWidth() > 1 ) && ( aSnapRect.GetHeight() > 1 ); + if ( bCellObject ) + { + std::set< sal_Int32 >::const_iterator aRowIter( rRows.find( aSnapRect.Top() ) ); + std::set< sal_Int32 >::const_iterator aColumnIter( rColumns.find( aSnapRect.Left() ) ); + if ( ( aRowIter == rRows.end() ) || ( aColumnIter == rColumns.end() ) ) + bCellObject = sal_False; + else + { + nRowCount = 1; + nRow = std::distance( rRows.begin(), aRowIter ); + while( ++aRowIter != rRows.end() ) + { + if ( *aRowIter >= aSnapRect.Bottom() ) + break; + nRowCount++; + } + nColumnCount = 1; + nColumn = std::distance( rColumns.begin(), aColumnIter ); + while( ++aColumnIter != rColumns.end() ) + { + if ( *aColumnIter >= aSnapRect.Right() ) + break; + nColumnCount++; + } + nTableIndex = nRow * rColumns.size() + nColumn; + } + } + return bCellObject; +} + +#define LinePositionLeft 0x01000000 +#define LinePositionTop 0x02000000 +#define LinePositionRight 0x04000000 +#define LinePositionBottom 0x08000000 +#define LinePositionTLBR 0x10000000 +#define LinePositionBLTR 0x20000000 + + +void GetRowPositions( const Rectangle& rSnapRect, const std::set< sal_Int32 >& rRows, + const std::set< sal_Int32 >& rColumns, std::vector< sal_Int32 >& rPositions, sal_Int32 nColumn, sal_Int32 nFlags ) +{ + std::set< sal_Int32 >::const_iterator aRow( rRows.find( rSnapRect.Top() ) ); + if ( aRow != rRows.end() ) + { + sal_Int32 nRow = std::distance( rRows.begin(), aRow ); + while( ( aRow != rRows.end() ) && ((*aRow) < rSnapRect.Bottom() ) ) + { + if ( nFlags & LinePositionLeft ) + rPositions.push_back( ( ( nRow * rColumns.size() ) + nColumn ) | LinePositionLeft ); + if ( nFlags & LinePositionRight ) + rPositions.push_back( ( ( nRow * rColumns.size() ) + ( nColumn - 1 ) ) | LinePositionRight ); + + nRow++; + aRow++; + } + } +} + + +void GetColumnPositions( const Rectangle& rSnapRect, const std::set< sal_Int32 >& /* rRows */, + const std::set< sal_Int32 >& rColumns, std::vector< sal_Int32 >& rPositions, sal_Int32 nRow, sal_Int32 nFlags ) +{ + std::set< sal_Int32 >::const_iterator aColumn( rColumns.find( rSnapRect.Left() ) ); + if ( aColumn != rColumns.end() ) + { + sal_Int32 nColumn = std::distance( rColumns.begin(), aColumn ); + while( ( aColumn != rColumns.end() ) && ((*aColumn) < rSnapRect.Right() ) ) + { + if ( nFlags & LinePositionTop ) + rPositions.push_back( ( ( nRow * rColumns.size() ) + nColumn ) | LinePositionTop ); + if ( nFlags & LinePositionBottom ) + rPositions.push_back( ( ( ( nRow - 1 ) * rColumns.size() ) + nColumn ) | LinePositionBottom ); + + nColumn++; + aColumn++; + } + } +} + +void GetLinePositions( const SdrObject* pObj, const std::set< sal_Int32 >& rRows, const std::set< sal_Int32 >& rColumns, + std::vector< sal_Int32 >& rPositions, const Rectangle& rGroupSnap ) +{ + Rectangle aSnapRect( pObj->GetSnapRect() ); + if ( aSnapRect.Left() == aSnapRect.Right() ) + { + std::set< sal_Int32 >::const_iterator aColumn( rColumns.find( aSnapRect.Left() ) ); + if ( ( aColumn != rColumns.end() ) || ( aSnapRect.Left() == rGroupSnap.Right() ) ) + { + sal_Int32 nColumn, nFlags; + if ( aColumn != rColumns.end() ) + { + nColumn = std::distance( rColumns.begin(), aColumn ); + nFlags = LinePositionLeft; + if ( aColumn != rColumns.begin() ) + nFlags |= LinePositionRight; + } + else + { + nColumn = rColumns.size(); + nFlags = LinePositionRight; + } + GetRowPositions( aSnapRect, rRows, rColumns, rPositions, nColumn, nFlags ); + } + } + else if ( aSnapRect.Top() == aSnapRect.Bottom() ) + { + std::set< sal_Int32 >::const_iterator aRow( rRows.find( aSnapRect.Top() ) ); + if ( ( aRow != rRows.end() ) || ( aSnapRect.Top() == rGroupSnap.Bottom() ) ) + { + sal_Int32 nRow, nFlags; + if ( aRow != rRows.end() ) + { + nRow = std::distance( rRows.begin(), aRow ); + nFlags = LinePositionTop; + if ( aRow != rRows.begin() ) + nFlags |= LinePositionBottom; + } + else + { + nRow = rRows.size(); + nFlags = LinePositionBottom; + } + GetColumnPositions( aSnapRect, rRows, rColumns, rPositions, nRow, nFlags ); + } + } + else + { + sal_uInt32 nPosition = 0; + Point aPt1( ((SdrPathObj*)pObj)->GetPoint( 0 ) ); + Point aPt2( ((SdrPathObj*)pObj)->GetPoint( 1 ) ); + if ( aPt1.X() < aPt2.X() ) + nPosition |= aPt1.Y() < aPt2.Y() ? LinePositionTLBR : LinePositionBLTR; + else + nPosition |= aPt1.Y() < aPt2.Y() ? LinePositionBLTR : LinePositionTLBR; + + std::set< sal_Int32 >::const_iterator aRow( rRows.find( aPt1.Y() < aPt2.Y() ? aPt1.Y() : aPt2.Y() ) ); + std::set< sal_Int32 >::const_iterator aColumn( rColumns.find( aPt1.X() < aPt2.X() ? aPt1.X() : aPt2.X() ) ); + if ( ( aRow != rRows.end() ) && ( aColumn != rColumns.end() ) ) + { + nPosition |= ( std::distance( rRows.begin(), aRow ) * rColumns.size() ) + std::distance( rColumns.begin(), aColumn ); + rPositions.push_back( nPosition ); + } + } +} + +void CreateTableRows( Reference< XTableRows > xTableRows, const std::set< sal_Int32 >& rRows, sal_Int32 nTableBottom ) +{ + if ( rRows.size() > 1 ) + xTableRows->insertByIndex( 0, rRows.size() - 1 ); + + std::set< sal_Int32 >::const_iterator aIter( rRows.begin() ); + sal_Int32 nLastPosition( *aIter ); + Reference< XIndexAccess > xIndexAccess( xTableRows, UNO_QUERY_THROW ); + for ( sal_Int32 n = 0; n < xIndexAccess->getCount(); n++ ) + { + sal_Int32 nHeight; + if ( ++aIter != rRows.end() ) + { + nHeight = *aIter - nLastPosition; + nLastPosition = *aIter; + } + else + nHeight = nTableBottom - nLastPosition; + + static const rtl::OUString sWidth( RTL_CONSTASCII_USTRINGPARAM ( "Height" ) ); + Reference< XPropertySet > xPropSet( xIndexAccess->getByIndex( n ), UNO_QUERY_THROW ); + xPropSet->setPropertyValue( sWidth, Any( nHeight ) ); + } +} + +void CreateTableColumns( Reference< XTableColumns > xTableColumns, const std::set< sal_Int32 >& rColumns, sal_Int32 nTableRight ) +{ + if ( rColumns.size() > 1 ) + xTableColumns->insertByIndex( 0, rColumns.size() - 1 ); + + std::set< sal_Int32 >::const_iterator aIter( rColumns.begin() ); + sal_Int32 nLastPosition( *aIter ); + Reference< XIndexAccess > xIndexAccess( xTableColumns, UNO_QUERY_THROW ); + for ( sal_Int32 n = 0; n < xIndexAccess->getCount(); n++ ) + { + sal_Int32 nWidth; + if ( ++aIter != rColumns.end() ) + { + nWidth = *aIter - nLastPosition; + nLastPosition = *aIter; + } + else + nWidth = nTableRight - nLastPosition; + + static const rtl::OUString sWidth( RTL_CONSTASCII_USTRINGPARAM ( "Width" ) ); + Reference< XPropertySet > xPropSet( xIndexAccess->getByIndex( n ), UNO_QUERY_THROW ); + xPropSet->setPropertyValue( sWidth, Any( nWidth ) ); + } +} + +void MergeCells( const Reference< XTable >& xTable, sal_Int32 nCol, sal_Int32 nRow, sal_Int32 nColSpan, sal_Int32 nRowSpan ) +{ + DBG_ASSERT( (nColSpan > 1) || (nRowSpan > 1), "nonsense parameter!!" ); + DBG_ASSERT( (nCol >= 0) && (nCol < xTable->getColumnCount()) && (nRow >= 0) && (nRow < xTable->getRowCount()), "die celle gibts nicht!!" ); + DBG_ASSERT( (nColSpan >= 1) && ((nCol + nColSpan - 1) < xTable->getColumnCount()), "nColSpan murks!" ); + DBG_ASSERT( (nRowSpan >= 1) && ((nRow + nRowSpan - 1) < xTable->getRowCount()), "nRowSpan murks!" ); + + if( xTable.is() ) try + { + Reference< XMergeableCellRange > xRange( xTable->createCursorByRange( xTable->getCellRangeByPosition( nCol, nRow,nCol + nColSpan - 1, nRow + nRowSpan - 1 ) ), UNO_QUERY_THROW ); + if( xRange->isMergeable() ) + xRange->merge(); + } + catch( Exception& ) + { + DBG_ASSERT( false, "exception caught!" ); + } +} + +void ApplyCellAttributes( const SdrObject* pObj, Reference< XCell >& xCell ) +{ + try + { + Reference< XPropertySet > xPropSet( xCell, UNO_QUERY_THROW ); + + const sal_Int32 nLeftDist(((const SdrTextLeftDistItem&)pObj->GetMergedItem(SDRATTR_TEXT_LEFTDIST)).GetValue()); + const sal_Int32 nRightDist(((const SdrTextRightDistItem&)pObj->GetMergedItem(SDRATTR_TEXT_RIGHTDIST)).GetValue()); + const sal_Int32 nUpperDist(((const SdrTextUpperDistItem&)pObj->GetMergedItem(SDRATTR_TEXT_UPPERDIST)).GetValue()); + const sal_Int32 nLowerDist(((const SdrTextLowerDistItem&)pObj->GetMergedItem(SDRATTR_TEXT_LOWERDIST)).GetValue()); + static const rtl::OUString sTopBorder( RTL_CONSTASCII_USTRINGPARAM( "TextUpperDistance" ) ); + static const rtl::OUString sBottomBorder( RTL_CONSTASCII_USTRINGPARAM( "TextLowerDistance" ) ); + static const rtl::OUString sLeftBorder( RTL_CONSTASCII_USTRINGPARAM( "TextLeftDistance" ) ); + static const rtl::OUString sRightBorder( RTL_CONSTASCII_USTRINGPARAM( "TextRightDistance" ) ); + xPropSet->setPropertyValue( sTopBorder, Any( nUpperDist ) ); + xPropSet->setPropertyValue( sRightBorder, Any( nRightDist ) ); + xPropSet->setPropertyValue( sLeftBorder, Any( nLeftDist ) ); + xPropSet->setPropertyValue( sBottomBorder, Any( nLowerDist ) ); + + static const rtl::OUString sTextVerticalAdjust( RTL_CONSTASCII_USTRINGPARAM( "TextVerticalAdjust" ) ); + const SdrTextVertAdjust eTextVertAdjust(((const SdrTextVertAdjustItem&)pObj->GetMergedItem(SDRATTR_TEXT_VERTADJUST)).GetValue()); + drawing::TextVerticalAdjust eVA( drawing::TextVerticalAdjust_TOP ); + if ( eTextVertAdjust == SDRTEXTVERTADJUST_CENTER ) + eVA = drawing::TextVerticalAdjust_CENTER; + else if ( eTextVertAdjust == SDRTEXTVERTADJUST_BOTTOM ) + eVA = drawing::TextVerticalAdjust_BOTTOM; + xPropSet->setPropertyValue( sTextVerticalAdjust, Any( eVA ) ); + + SfxItemSet aSet( pObj->GetMergedItemSet() ); + XFillStyle eFillStyle(((XFillStyleItem&)pObj->GetMergedItem( XATTR_FILLSTYLE )).GetValue()); + ::com::sun::star::drawing::FillStyle eFS( com::sun::star::drawing::FillStyle_NONE ); + switch( eFillStyle ) + { + case XFILL_SOLID : + { + static const rtl::OUString sFillColor( String( RTL_CONSTASCII_USTRINGPARAM( "FillColor" ) ) ); + eFS = com::sun::star::drawing::FillStyle_SOLID; + Color aFillColor( ((XFillColorItem&)pObj->GetMergedItem( XATTR_FILLCOLOR )).GetColorValue() ); + sal_Int32 nFillColor( aFillColor.GetColor() ); + xPropSet->setPropertyValue( sFillColor, Any( nFillColor ) ); + } + break; + case XFILL_GRADIENT : + { + eFS = com::sun::star::drawing::FillStyle_GRADIENT; + XGradient aXGradient(((const XFillGradientItem&)pObj->GetMergedItem(XATTR_FILLGRADIENT)).GetGradientValue()); + + com::sun::star::awt::Gradient aGradient; + aGradient.Style = (awt::GradientStyle) aXGradient.GetGradientStyle(); + aGradient.StartColor = (sal_Int32)aXGradient.GetStartColor().GetColor(); + aGradient.EndColor = (sal_Int32)aXGradient.GetEndColor().GetColor(); + aGradient.Angle = (short)aXGradient.GetAngle(); + aGradient.Border = aXGradient.GetBorder(); + aGradient.XOffset = aXGradient.GetXOffset(); + aGradient.YOffset = aXGradient.GetYOffset(); + aGradient.StartIntensity = aXGradient.GetStartIntens(); + aGradient.EndIntensity = aXGradient.GetEndIntens(); + aGradient.StepCount = aXGradient.GetSteps(); + + static const rtl::OUString sFillGradient( String( RTL_CONSTASCII_USTRINGPARAM( "FillGradient" ) ) ); + xPropSet->setPropertyValue( sFillGradient, Any( aGradient ) ); + } + break; + case XFILL_HATCH : + eFS = com::sun::star::drawing::FillStyle_HATCH; + break; + case XFILL_BITMAP : + { + eFS = com::sun::star::drawing::FillStyle_BITMAP; + + XFillBitmapItem aXFillBitmapItem((const XFillBitmapItem&)pObj->GetMergedItem( XATTR_FILLBITMAP )); + XOBitmap aLocalXOBitmap( aXFillBitmapItem.GetBitmapValue() ); + rtl::OUString aURL( RTL_CONSTASCII_USTRINGPARAM(UNO_NAME_GRAPHOBJ_URLPREFIX)); + aURL += rtl::OUString::createFromAscii( aLocalXOBitmap.GetGraphicObject().GetUniqueID().GetBuffer() ); + + static const rtl::OUString sFillBitmapURL( String( RTL_CONSTASCII_USTRINGPARAM( "FillBitmapURL" ) ) ); + xPropSet->setPropertyValue( sFillBitmapURL, Any( aURL ) ); + } + break; + case XFILL_NONE : + eFS = com::sun::star::drawing::FillStyle_NONE; + break; + + } + static const rtl::OUString sFillStyle( String( RTL_CONSTASCII_USTRINGPARAM( "FillStyle" ) ) ); + xPropSet->setPropertyValue( sFillStyle, Any( eFS ) ); + if ( eFillStyle != XFILL_NONE ) + { + sal_Int16 nFillTransparence( ( (const XFillTransparenceItem&)pObj->GetMergedItem( XATTR_FILLTRANSPARENCE ) ).GetValue() ); + if ( nFillTransparence != 100 ) + { + nFillTransparence *= 100; + static const rtl::OUString sFillTransparence( String( RTL_CONSTASCII_USTRINGPARAM( "FillTransparence" ) ) ); + xPropSet->setPropertyValue( sFillTransparence, Any( nFillTransparence ) ); + } + } + } + catch( Exception& ) + { + } +} + +void ApplyCellLineAttributes( const SdrObject* pLine, Reference< XTable >& xTable, const std::vector< sal_Int32 > vPositions, sal_Int32 nColumns ) +{ + try + { + SfxItemSet aSet( pLine->GetMergedItemSet() ); + XLineStyle eLineStyle(((XLineStyleItem&)pLine->GetMergedItem( XATTR_LINESTYLE )).GetValue()); + com::sun::star::table::BorderLine aBorderLine; + switch( eLineStyle ) + { + case XLINE_DASH : + case XLINE_SOLID : + { + Color aLineColor( ((XLineColorItem&)pLine->GetMergedItem( XATTR_LINECOLOR )).GetColorValue() ); + aBorderLine.Color = aLineColor.GetColor(); + aBorderLine.OuterLineWidth = static_cast< sal_Int16 >( ((const XLineWidthItem&)(pLine->GetMergedItem(XATTR_LINEWIDTH))).GetValue() / 4 ); + aBorderLine.InnerLineWidth = static_cast< sal_Int16 >( ((const XLineWidthItem&)(pLine->GetMergedItem(XATTR_LINEWIDTH))).GetValue() / 4 ); + aBorderLine.LineDistance = 0; + } + break; + case XLINE_NONE : + { + aBorderLine.OuterLineWidth = 0; + aBorderLine.InnerLineWidth = 0; + aBorderLine.LineDistance = 0; + } + break; + } + Reference< XCellRange > xCellRange( xTable, UNO_QUERY_THROW ); + std::vector< sal_Int32 >::const_iterator aIter( vPositions.begin() ); + while( aIter != vPositions.end() ) + { + static const rtl::OUString sTopBorder( String( RTL_CONSTASCII_USTRINGPARAM( "TopBorder" ) ) ); + static const rtl::OUString sBottomBorder( String( RTL_CONSTASCII_USTRINGPARAM( "BottomBorder" ) ) ); + static const rtl::OUString sLeftBorder( String( RTL_CONSTASCII_USTRINGPARAM( "LeftBorder" ) ) ); + static const rtl::OUString sRightBorder( String( RTL_CONSTASCII_USTRINGPARAM( "RightBorder" ) ) ); + static const rtl::OUString sDiagonalTLBR( RTL_CONSTASCII_USTRINGPARAM ( "DiagonalTLBR" ) ); + static const rtl::OUString sDiagonalBLTR( RTL_CONSTASCII_USTRINGPARAM ( "DiagonalBLTR" ) ); + + sal_Int32 nPosition = *aIter & 0xffffff; + sal_Int32 nFlags = *aIter &~0xffffff; + sal_Int32 nRow = nPosition / nColumns; + sal_Int32 nColumn = nPosition - ( nRow * nColumns ); + Reference< XCell > xCell( xCellRange->getCellByPosition( nColumn, nRow ) ); + Reference< XPropertySet > xPropSet( xCell, UNO_QUERY_THROW ); + + if ( nFlags & LinePositionLeft ) + xPropSet->setPropertyValue( sLeftBorder, Any( aBorderLine ) ); + if ( nFlags & LinePositionTop ) + xPropSet->setPropertyValue( sTopBorder, Any( aBorderLine ) ); + if ( nFlags & LinePositionRight ) + xPropSet->setPropertyValue( sRightBorder, Any( aBorderLine ) ); + if ( nFlags & LinePositionBottom ) + xPropSet->setPropertyValue( sBottomBorder, Any( aBorderLine ) ); + if ( nFlags & LinePositionTLBR ) + xPropSet->setPropertyValue( sDiagonalTLBR, Any( sal_True ) ); + if ( nFlags & LinePositionBLTR ) + xPropSet->setPropertyValue( sDiagonalBLTR, Any( sal_True ) ); + aIter++; + } + } + catch( Exception& ) + { + } +} + +SdrObject* SdrPowerPointImport::CreateTable( SdrObject* pGroup, sal_uInt32* pTableArry, SvxMSDffSolverContainer* pSolverContainer ) +{ + SdrObject* pRet = pGroup; + sal_uInt32 nRows = pTableArry[ 1 ]; + if ( nRows && pGroup->ISA( SdrObjGroup ) ) + { + SdrObjList* pSubList(((SdrObjGroup*)pGroup)->GetSubList()); + if ( pSubList ) + { + std::set< sal_Int32 > aRows; + std::set< sal_Int32 > aColumns; + + SdrObjListIter aGroupIter( *pSubList, IM_DEEPNOGROUPS, sal_False ); + while( aGroupIter.IsMore() ) + { + const SdrObject* pObj( aGroupIter.Next() ); + if ( !IsLine( pObj ) ) + { + Rectangle aSnapRect( pObj->GetSnapRect() ); + aRows.insert( aSnapRect.Top() ); + aColumns.insert( aSnapRect.Left() ); + } + } + ::sdr::table::SdrTableObj* pTable = new ::sdr::table::SdrTableObj( pSdrModel ); + pTable->uno_lock(); + Reference< XTable > xTable( pTable->getTable() ); + try + { + Reference< XColumnRowRange > xColumnRowRange( xTable, UNO_QUERY_THROW ); + + CreateTableRows( xColumnRowRange->getRows(), aRows, pGroup->GetSnapRect().Bottom() ); + CreateTableColumns( xColumnRowRange->getColumns(), aColumns, pGroup->GetSnapRect().Right() ); + + sal_Int32 nCellCount = aRows.size() * aColumns.size(); + sal_Int32 *pMergedCellIndexTable = new sal_Int32[ nCellCount ]; + for ( sal_Int32 i = 0; i < nCellCount; i++ ) + pMergedCellIndexTable[ i ] = i; + + aGroupIter.Reset(); + while( aGroupIter.IsMore() ) + { + SdrObject* pObj( aGroupIter.Next() ); + if ( !IsLine( pObj ) ) + { + Rectangle aSnapRect( pObj->GetSnapRect() ); + sal_Int32 nTableIndex = 0; + sal_Int32 nRow = 0; + sal_Int32 nRowCount = 0; + sal_Int32 nColumn = 0; + sal_Int32 nColumnCount = 0; + if ( GetCellPosition( pObj, aRows, aColumns, nTableIndex, nRow, nRowCount, nColumn, nColumnCount ) ) + { + Reference< XCellRange > xCellRange( xTable, UNO_QUERY_THROW ); + Reference< XCell > xCell( xCellRange->getCellByPosition( nColumn, nRow ) ); + + ApplyCellAttributes( pObj, xCell ); + + if ( ( nRowCount > 1 ) || ( nColumnCount > 1 ) ) // cell merging + { + MergeCells( xTable, nColumn, nRow, nColumnCount, nRowCount ); + for ( sal_Int32 nRowIter = 0; nRowIter < nRowCount; nRowIter++ ) + { + for ( sal_Int32 nColumnIter = 0; nColumnIter < nColumnCount; nColumnIter++ ) + { // now set the correct index for the merged cell + pMergedCellIndexTable[ ( ( nRow + nRowIter ) * aColumns.size() ) + nColumn + nColumnIter ] = nTableIndex; + } + } + } + + // applying text + OutlinerParaObject* pParaObject = pObj->GetOutlinerParaObject(); + if ( pParaObject ) + { + SdrText* pSdrText = pTable->getText( nTableIndex ); + if ( pSdrText ) + pSdrText->SetOutlinerParaObject(new OutlinerParaObject(*pParaObject) ); + } + } + } + } + aGroupIter.Reset(); + while( aGroupIter.IsMore() ) + { + SdrObject* pObj( aGroupIter.Next() ); + if ( IsLine( pObj ) ) + { + std::vector< sal_Int32 > vPositions; // containing cell indexes + cell position + GetLinePositions( pObj, aRows, aColumns, vPositions, pGroup->GetSnapRect() ); + + // correcting merged cell position + std::vector< sal_Int32 >::iterator aIter( vPositions.begin() ); + while( aIter != vPositions.end() ) + { + sal_Int32 nOldPosition = *aIter & 0xffff; + sal_Int32 nOldFlags = *aIter & 0xffff0000; + sal_Int32 nNewPosition = pMergedCellIndexTable[ nOldPosition ] | nOldFlags; + *aIter++ = nNewPosition; + } + ApplyCellLineAttributes( pObj, xTable, vPositions, aColumns.size() ); + } + } + delete[] pMergedCellIndexTable; + + // we are replacing the whole group object by a single table object, so + // possibly connections to the group object have to be removed. + if ( pSolverContainer ) + { + for ( SvxMSDffConnectorRule* pPtr = (SvxMSDffConnectorRule*)pSolverContainer->aCList.First(); + pPtr; pPtr = (SvxMSDffConnectorRule*)pSolverContainer->aCList.Next() ) + { + SdrObjListIter aIter( *pGroup, IM_DEEPWITHGROUPS ); + while( aIter.IsMore() ) + { + SdrObject* pPartObj = aIter.Next(); + if ( pPtr->pAObj == pPartObj ) + pPtr->pAObj = NULL; + if ( pPtr->pBObj == pPartObj ) + pPtr->pBObj = NULL; + } + } + } + pTable->uno_unlock(); + pTable->SetSnapRect( pGroup->GetSnapRect() ); + pRet = pTable; + + //Remove Objects from shape map + SdrObjListIter aIter( *pGroup, IM_DEEPWITHGROUPS ); + while( aIter.IsMore() ) + { + SdrObject* pPartObj = aIter.Next(); + removeShapeId( pPartObj ); + } + + SdrObject::Free( pGroup ); + } + catch( Exception& ) + { + pTable->uno_unlock(); + SdrObject* pObj = pTable; + SdrObject::Free( pObj ); + } + } + } + return pRet; +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + diff --git a/filter/source/msfilter/svxmsbas.cxx b/filter/source/msfilter/svxmsbas.cxx new file mode 100644 index 000000000000..f9ffb412f18b --- /dev/null +++ b/filter/source/msfilter/svxmsbas.cxx @@ -0,0 +1,496 @@ +/************************************************************************* + * + * 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_filter.hxx" + +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */ +#include <tools/debug.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/app.hxx> +#include <basic/basmgr.hxx> +#include <basic/sbmod.hxx> +#include <svx/svxerr.hxx> +#include <filter/msfilter/svxmsbas.hxx> +#include <msvbasic.hxx> +#include <filter/msfilter/msocximex.hxx> +#include <sot/storinfo.hxx> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/awt/XControlModel.hpp> +using namespace com::sun::star::beans; +using namespace com::sun::star::io; +using namespace com::sun::star::awt; +#include <comphelper/storagehelper.hxx> + +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/script/XLibraryContainer.hpp> +#include <com/sun/star/script/ModuleInfo.hpp> +#include <com/sun/star/script/ModuleType.hpp> +#include <com/sun/star/script/vba/XVBACompatibility.hpp> +#include <com/sun/star/script/vba/XVBAModuleInfo.hpp> + +using namespace com::sun::star::container; +using namespace com::sun::star::script; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star; + +using rtl::OUString; + +static ::rtl::OUString sVBAOption( RTL_CONSTASCII_USTRINGPARAM( "Option VBASupport 1\n" ) ); + +int SvxImportMSVBasic::Import( const String& rStorageName, + const String &rSubStorageName, + sal_Bool bAsComment, sal_Bool bStripped ) +{ + std::vector< String > codeNames; + return Import( rStorageName, rSubStorageName, codeNames, bAsComment, bStripped ); +} + +int SvxImportMSVBasic::Import( const String& rStorageName, + const String &rSubStorageName, + const std::vector< String >& codeNames, + sal_Bool bAsComment, sal_Bool bStripped ) +{ + int nRet = 0; + if( bImport && ImportCode_Impl( rStorageName, rSubStorageName, codeNames, + bAsComment, bStripped )) + nRet |= 1; + + if (bImport) + ImportForms_Impl(rStorageName, rSubStorageName); + + if( bCopy && CopyStorage_Impl( rStorageName, rSubStorageName )) + nRet |= 2; + + return nRet; +} + +bool SvxImportMSVBasic::ImportForms_Impl(const String& rStorageName, + const String& rSubStorageName) +{ + SvStorageRef xVBAStg(xRoot->OpenSotStorage(rStorageName, + STREAM_READWRITE | STREAM_NOCREATE | STREAM_SHARE_DENYALL)); + if (!xVBAStg.Is() || xVBAStg->GetError()) + return false; + + std::vector<String> aUserForms; + SvStorageInfoList aContents; + xVBAStg->FillInfoList(&aContents); + for (sal_uInt16 nI = 0; nI < aContents.Count(); ++nI) + { + SvStorageInfo& rInfo = aContents.GetObject(nI); + if (!rInfo.IsStream() && rInfo.GetName() != rSubStorageName) + aUserForms.push_back(rInfo.GetName()); + } + + if (aUserForms.empty()) + return false; + + bool bRet = true; + try + { + Reference<XMultiServiceFactory> xSF(comphelper::getProcessServiceFactory()); + + Reference<XComponentContext> xContext; + Reference<XPropertySet> xProps(xSF, UNO_QUERY); + xProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("DefaultContext")) ) >>= xContext; + + + Reference<XLibraryContainer> xLibContainer = rDocSh.GetDialogContainer(); + DBG_ASSERT( xLibContainer.is(), "No BasicContainer!" ); + + String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) ); + Reference<XNameContainer> xLib; + if (xLibContainer.is()) + { + if( !xLibContainer->hasByName(aLibName)) + xLibContainer->createLibrary(aLibName); + + Any aLibAny = xLibContainer->getByName( aLibName ); + aLibAny >>= xLib; + } + + if(xLib.is()) + { + typedef std::vector<String>::iterator myIter; + myIter aEnd = aUserForms.end(); + for (myIter aIter = aUserForms.begin(); aIter != aEnd; ++aIter) + { + SvStorageRef xForm (xVBAStg->OpenSotStorage(*aIter, + STREAM_READWRITE | STREAM_NOCREATE | STREAM_SHARE_DENYALL)); + + if (!xForm.Is() || xForm->GetError()) + continue; + + SvStorageStreamRef xFrame = xForm->OpenSotStream( + String( RTL_CONSTASCII_USTRINGPARAM( "\3VBFrame" ) ), + STREAM_STD_READ | STREAM_NOCREATE); + + if (!xFrame.Is() || xFrame->GetError()) + continue; + + SvStorageStreamRef xTypes = xForm->OpenSotStream( + String( 'f' ), STREAM_STD_READ | STREAM_NOCREATE); + + if (!xTypes.Is() || xTypes->GetError()) + continue; + + //<UserForm Name=""><VBFrame></VBFrame>" + String sData; + String sLine; + while(xFrame->ReadByteStringLine(sLine, RTL_TEXTENCODING_MS_1252)) + { + sData += sLine; + sData += '\n'; + } + sData.ConvertLineEnd(); + + Reference<container::XNameContainer> xDialog( + xSF->createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.awt.UnoControlDialogModel"))), uno::UNO_QUERY); + + OCX_UserForm aForm(xVBAStg, *aIter, *aIter, xDialog, xSF ); + aForm.pDocSh = &rDocSh; + sal_Bool bOk = aForm.Read(xTypes); + DBG_ASSERT(bOk, "Had unexpected content, not risking this module"); + if (bOk) + aForm.Import(xLib); + } + } + } + catch(...) + { + DBG_ERRORFILE( "SvxImportMSVBasic::ImportForms_Impl - any exception caught" ); + //bRet = false; + } + return bRet; +} + + +sal_Bool SvxImportMSVBasic::CopyStorage_Impl( const String& rStorageName, + const String& rSubStorageName) +{ + sal_Bool bValidStg = sal_False; + { + SvStorageRef xVBAStg( xRoot->OpenSotStorage( rStorageName, + STREAM_READWRITE | STREAM_NOCREATE | + STREAM_SHARE_DENYALL )); + if( xVBAStg.Is() && !xVBAStg->GetError() ) + { + SvStorageRef xVBASubStg( xVBAStg->OpenSotStorage( rSubStorageName, + STREAM_READWRITE | STREAM_NOCREATE | + STREAM_SHARE_DENYALL )); + if( xVBASubStg.Is() && !xVBASubStg->GetError() ) + { + // then we will copy these storages into the (temporary) storage of the document + bValidStg = sal_True; + } + } + } + + if( bValidStg ) + { + String aDstStgName( GetMSBasicStorageName() ); + SotStorageRef xDst = SotStorage::OpenOLEStorage( rDocSh.GetStorage(), aDstStgName, STREAM_READWRITE | STREAM_TRUNC ); + SotStorageRef xSrc = xRoot->OpenSotStorage( rStorageName, STREAM_STD_READ ); + + // TODO/LATER: should we commit the storage? + xSrc->CopyTo( xDst ); + xDst->Commit(); + ErrCode nError = xDst->GetError(); + if ( nError == ERRCODE_NONE ) + nError = xSrc->GetError(); + if ( nError != ERRCODE_NONE ) + xRoot->SetError( nError ); + else + bValidStg = sal_True; + } + + return bValidStg; +} + +sal_Bool SvxImportMSVBasic::ImportCode_Impl( const String& rStorageName, + const String &rSubStorageName, + const std::vector< String >& codeNames, + sal_Bool bAsComment, sal_Bool bStripped ) +{ + sal_Bool bRet = sal_False; + VBA_Impl aVBA( *xRoot, bAsComment ); + if( aVBA.Open(rStorageName,rSubStorageName) ) + { + Reference<XLibraryContainer> xLibContainer = rDocSh.GetBasicContainer(); + DBG_ASSERT( xLibContainer.is(), "No BasicContainer!" ); + + /* Set library container to VBA compatibility mode. This will create + the VBA Globals object and store it in the Basic manager of the + document. */ + if( !bAsComment ) try + { + Reference< vba::XVBACompatibility >( xLibContainer, UNO_QUERY_THROW )->setVBACompatibilityMode( sal_True ); + } + catch( Exception& ) + { + } + + sal_uInt16 nStreamCount = aVBA.GetNoStreams(); + Reference<XNameContainer> xLib; + String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) ); + if( xLibContainer.is() && nStreamCount ) + { + if( !xLibContainer->hasByName( aLibName ) ) + xLibContainer->createLibrary( aLibName ); + + Any aLibAny = xLibContainer->getByName( aLibName ); + aLibAny >>= xLib; + } + if( xLib.is() ) + { + Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, UNO_QUERY ); + Reference< container::XNameAccess > xVBACodeNamedObjectAccess; + if ( !bAsComment ) + { + Reference< XMultiServiceFactory> xSF(rDocSh.GetModel(), UNO_QUERY); + if ( xSF.is() ) + { + try + { + xVBACodeNamedObjectAccess.set( xSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAObjectModuleObjectProvider"))), UNO_QUERY ); + } + catch( Exception& ) { } + } + } + typedef std::hash_map< rtl::OUString, uno::Any, ::rtl::OUStringHash, +::std::equal_to< ::rtl::OUString > > NameModuleDataHash; + typedef std::hash_map< rtl::OUString, script::ModuleInfo, ::rtl::OUStringHash, +::std::equal_to< ::rtl::OUString > > NameModuleInfoHash; + + NameModuleDataHash moduleData; + NameModuleInfoHash moduleInfos; + + for( sal_uInt16 i=0; i<nStreamCount;i++) + { + StringArray aDecompressed = aVBA.Decompress(i); +#if 0 +/* DR 2005-08-11 #124850# Do not filter special characters from module name. + Just put the original module name and let the Basic interpreter deal with + it. Needed for roundtrip... + */ + ByteString sByteBasic(aVBA.GetStreamName(i), + RTL_TEXTENCODING_ASCII_US, + (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_UNDERLINE| + RTL_UNICODETOTEXT_FLAGS_INVALID_UNDERLINE | + RTL_UNICODETOTEXT_FLAGS_PRIVATE_MAPTO0 | + RTL_UNICODETOTEXT_FLAGS_NOCOMPOSITE) + ); + + const String sBasicModule(sByteBasic, + RTL_TEXTENCODING_ASCII_US); +#else + const String &sBasicModule = aVBA.GetStreamName( i); +#endif + /* #117718# expose information regarding type of Module + * Class, Form or plain 'ould VBA module with a REM statment + * at the top of the module. Mapping of Module Name + * to type is performed in VBA_Impl::Open() method, + * ( msvbasic.cxx ) by examining the PROJECT stream. + */ + + // using name from aVBA.GetStreamName + // because the encoding of the same returned + // is the same as the encoding for the names + // that are keys in the map used by GetModuleType method + const String &sOrigVBAModName = aVBA.GetStreamName( i ); + ModType mType = aVBA.GetModuleType( sOrigVBAModName ); + + rtl::OUString sClassRem( RTL_CONSTASCII_USTRINGPARAM( "Rem Attribute VBA_ModuleType=" ) ); + + rtl::OUString modeTypeComment; + + switch( mType ) + { + case ModuleType::CLASS: + modeTypeComment = sClassRem + + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VBAClassModule\n" ) ); + break; + case ModuleType::FORM: + modeTypeComment = sClassRem + + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VBAFormModule\n" ) ); + break; + case ModuleType::DOCUMENT: + modeTypeComment = sClassRem + + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VBADocumentModule\n" ) ); + break; + case ModuleType::NORMAL: + modeTypeComment = sClassRem + + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VBAModule\n" ) ); + break; + case ModuleType::UNKNOWN: + modeTypeComment = sClassRem + + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VBAUnknown\n" ) ); + break; + default: + DBG_ERRORFILE( "SvxImportMSVBasic::ImportCode_Impl - unknown module type" ); + break; + } + static ::rtl::OUString sClassOption( RTL_CONSTASCII_USTRINGPARAM( "Option ClassModule\n" ) ); + if ( !bAsComment ) + { + modeTypeComment += sVBAOption; + if ( mType == ModuleType::CLASS ) + modeTypeComment += sClassOption; + } + + String sModule(sBasicModule); //#i52606# no need to split Macros in 64KB blocks any more! + String sTemp; + if (bAsComment) + { + sTemp+=String(RTL_CONSTASCII_USTRINGPARAM( "Sub " )); + String sMunge(sModule); + //Streams can have spaces in them, but modulenames + //cannot ! + sMunge.SearchAndReplaceAll(' ','_'); + + sTemp += sMunge; + sTemp.AppendAscii("\n"); + }; + ::rtl::OUString aSource(sTemp); + + for(sal_uLong j=0;j<aDecompressed.GetSize();j++) + { + if (bStripped) + { + String *pStr = aDecompressed.Get(j); + bool bMac = true; + xub_StrLen nBegin = pStr->Search('\x0D'); + if ((STRING_NOTFOUND != nBegin) && (pStr->Len() > 1) && (pStr->GetChar(nBegin+1) == '\x0A')) + bMac = false; + + const char cLineEnd = bMac ? '\x0D' : '\x0A'; + const String sAttribute(String::CreateFromAscii( + bAsComment ? "Rem Attribute" : "Attribute")); + nBegin = 0; + while (STRING_NOTFOUND != (nBegin = pStr->Search(sAttribute, nBegin))) + { + if ((nBegin) && pStr->GetChar(nBegin-1) != cLineEnd) + { + // npower #i63766# Need to skip instances of Attribute + // that are NOT Attribute statements + nBegin = nBegin + sAttribute.Len(); + continue; + } + xub_StrLen nEnd = pStr->Search(cLineEnd ,nBegin); + // DR #i26521# catch STRING_NOTFOUND, will loop endless otherwise + if( nEnd == STRING_NOTFOUND ) + pStr->Erase(); + else + pStr->Erase(nBegin, (nEnd-nBegin)+1); + } + } + if( aDecompressed.Get(j)->Len() ) + { + aSource+=::rtl::OUString( *aDecompressed.Get(j) ); + } + + } + if (bAsComment) + { + aSource += rtl::OUString::createFromAscii("\nEnd Sub"); + } + ::rtl::OUString aModName( sModule ); + aSource = modeTypeComment + aSource; + + Any aSourceAny; + OSL_TRACE("erm %d", mType ); + aSourceAny <<= aSource; + if ( !bAsComment ) + { + OSL_TRACE("vba processing %d", mType ); + script::ModuleInfo sModuleInfo; + sModuleInfo.ModuleType = mType; + moduleInfos[ aModName ] = sModuleInfo; + } + moduleData[ aModName ] = aSourceAny; + } + // Hack for missing codenames ( only know to happen in excel but... ) + // only makes sense to do this if we are importing non-commented basic + if ( !bAsComment ) + { + for ( std::vector< String >::const_iterator it = codeNames.begin(); it != codeNames.end(); ++it ) + { + script::ModuleInfo sModuleInfo; + sModuleInfo.ModuleType = ModuleType::DOCUMENT; + moduleInfos[ *it ] = sModuleInfo; + moduleData[ *it ] = uno::makeAny( sVBAOption ); + } + } + NameModuleDataHash::iterator it_end = moduleData.end(); + for ( NameModuleDataHash::iterator it = moduleData.begin(); it != it_end; ++it ) + { + NameModuleInfoHash::iterator it_info = moduleInfos.find( it->first ); + if ( it_info != moduleInfos.end() ) + { + ModuleInfo& sModuleInfo = it_info->second; + if ( sModuleInfo.ModuleType == ModuleType::FORM ) + // hack, the module ( imo document basic should... + // know the XModel... ) but it doesn't + sModuleInfo.ModuleObject.set( rDocSh.GetModel(), UNO_QUERY ); + // document modules, we should be able to access + // the api objects at this time + else if ( sModuleInfo.ModuleType == ModuleType::DOCUMENT ) + { + if ( xVBACodeNamedObjectAccess.is() ) + { + try + { + sModuleInfo.ModuleObject.set( xVBACodeNamedObjectAccess->getByName( it->first ), uno::UNO_QUERY ); + OSL_TRACE("** Straight up creation of Module"); + } + catch(uno::Exception& e) + { + OSL_TRACE("Failed to get documument object for %s", rtl::OUStringToOString( it->first, RTL_TEXTENCODING_UTF8 ).getStr() ); + } + } + } + xVBAModuleInfo->insertModuleInfo( it->first, sModuleInfo ); + } + + if( xLib->hasByName( it->first ) ) + xLib->replaceByName( it->first, it->second ); + else + xLib->insertByName( it->first, it->second ); + } + bRet = true; + } + } + return bRet; +} + +/* vi:set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/filter/source/msfilter/svxmsbas2.cxx b/filter/source/msfilter/svxmsbas2.cxx new file mode 100644 index 000000000000..636c72ebbdbb --- /dev/null +++ b/filter/source/msfilter/svxmsbas2.cxx @@ -0,0 +1,85 @@ +/************************************************************************* + * + * 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_filter.hxx" + +#include <basic/basmgr.hxx> +#include <sfx2/objsh.hxx> +#include <svx/svxerr.hxx> +#include <filter/msfilter/svxmsbas.hxx> + +using namespace com::sun::star; + +sal_uLong SvxImportMSVBasic::SaveOrDelMSVBAStorage( sal_Bool bSaveInto, + const String& rStorageName ) +{ + sal_uLong nRet = ERRCODE_NONE; + uno::Reference < embed::XStorage > xSrcRoot( rDocSh.GetStorage() ); + String aDstStgName( GetMSBasicStorageName() ); + SotStorageRef xVBAStg( SotStorage::OpenOLEStorage( xSrcRoot, aDstStgName, + STREAM_READWRITE | STREAM_NOCREATE | STREAM_SHARE_DENYALL ) ); + if( xVBAStg.Is() && !xVBAStg->GetError() ) + { + xVBAStg = 0; + if( bSaveInto ) + { + BasicManager *pBasicMan = rDocSh.GetBasicManager(); + if( pBasicMan && pBasicMan->IsBasicModified() ) + nRet = ERRCODE_SVX_MODIFIED_VBASIC_STORAGE; + + SotStorageRef xSrc = SotStorage::OpenOLEStorage( xSrcRoot, aDstStgName, STREAM_STD_READ ); + SotStorageRef xDst = xRoot->OpenSotStorage( rStorageName, STREAM_READWRITE | STREAM_TRUNC ); + xSrc->CopyTo( xDst ); + xDst->Commit(); + ErrCode nError = xDst->GetError(); + if ( nError == ERRCODE_NONE ) + nError = xSrc->GetError(); + if ( nError != ERRCODE_NONE ) + xRoot->SetError( nError ); + } + } + + return nRet; +} + +// check if the MS-VBA-Storage exists in the RootStorage of the DocShell. +// If it exists, then return the WarningId for losing the information. +sal_uLong SvxImportMSVBasic::GetSaveWarningOfMSVBAStorage( SfxObjectShell &rDocSh) +{ + uno::Reference < embed::XStorage > xSrcRoot( rDocSh.GetStorage() ); + SvStorageRef xVBAStg( SotStorage::OpenOLEStorage( xSrcRoot, GetMSBasicStorageName(), + STREAM_READ | STREAM_NOCREATE | STREAM_SHARE_DENYALL )); + return ( xVBAStg.Is() && !xVBAStg->GetError() ) + ? ERRCODE_SVX_VBASIC_STORAGE_EXIST + : ERRCODE_NONE; +} + +String SvxImportMSVBasic::GetMSBasicStorageName() +{ + return String( RTL_CONSTASCII_USTRINGPARAM( "_MS_VBA_Macros" ) ); +} diff --git a/filter/source/msfilter/viscache.hxx b/filter/source/msfilter/viscache.hxx new file mode 100644 index 000000000000..83af84a8c1a9 --- /dev/null +++ b/filter/source/msfilter/viscache.hxx @@ -0,0 +1,82 @@ +/************************************************************************* + * + * 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 <tools/stream.hxx> +#include <vcl/gdimtf.hxx> +#include <vcl/bitmap.hxx> + +/************************************************************************ +|* Impl_CacheElement +|* Impl_Cache +|* +|* Beschreibung +*************************************************************************/ +class Impl_OlePres +{ + sal_uLong nFormat; + sal_uInt16 nAspect; + Bitmap * pBmp; + GDIMetaFile * pMtf; + + sal_uInt32 nAdvFlags; + sal_Int32 nJobLen; + sal_uInt8* pJob; + Size aSize; // Groesse in 100TH_MM +public: + Impl_OlePres( sal_uLong nF ) + : nFormat( nF ) + , pBmp( NULL ) + , pMtf( NULL ) + , nAdvFlags( 0x2 ) // in Dokument gefunden + , nJobLen( 0 ) + , pJob( NULL ) + {} + ~Impl_OlePres() + { + delete pJob; + delete pBmp; + delete pMtf; + } + void SetMtf( const GDIMetaFile & rMtf ) + { + if( pMtf ) + delete pMtf; + pMtf = new GDIMetaFile( rMtf ); + } + Bitmap *GetBitmap() const { return pBmp; } + GDIMetaFile *GetMetaFile() const { return pMtf; } + sal_uLong GetFormat() const { return nFormat; } + void SetAspect( sal_uInt16 nAsp ) { nAspect = nAsp; } + sal_uLong GetAdviseFlags() const { return nAdvFlags; } + void SetAdviseFlags( sal_uLong nAdv ) { nAdvFlags = nAdv; } + void SetSize( const Size & rSize ) { aSize = rSize; } + /// return sal_False => unknown format + sal_Bool Read( SvStream & rStm ); + void Write( SvStream & rStm ); +}; + + |