1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "oox/xls/workbooksettings.hxx" 29 30 #include <com/sun/star/sheet/XCalculatable.hpp> 31 #include <com/sun/star/util/Date.hpp> 32 #include <com/sun/star/util/XNumberFormatsSupplier.hpp> 33 #include <comphelper/mediadescriptor.hxx> 34 #include "oox/core/filterbase.hxx" 35 #include "oox/helper/attributelist.hxx" 36 #include "oox/helper/propertyset.hxx" 37 #include "oox/xls/biffinputstream.hxx" 38 #include "oox/xls/unitconverter.hxx" 39 40 namespace oox { 41 namespace xls { 42 43 // ============================================================================ 44 45 using namespace ::com::sun::star::beans; 46 using namespace ::com::sun::star::sheet; 47 using namespace ::com::sun::star::uno; 48 using namespace ::com::sun::star::util; 49 50 using ::comphelper::MediaDescriptor; 51 using ::oox::core::CodecHelper; 52 using ::rtl::OUString; 53 54 // ============================================================================ 55 56 namespace { 57 58 const sal_uInt32 BIFF12_WORKBOOKPR_DATE1904 = 0x00000001; 59 const sal_uInt32 BIFF12_WORKBOOKPR_STRIPEXT = 0x00000080; 60 61 const sal_uInt16 BIFF12_CALCPR_A1 = 0x0002; 62 const sal_uInt16 BIFF12_CALCPR_ITERATE = 0x0004; 63 const sal_uInt16 BIFF12_CALCPR_FULLPRECISION = 0x0008; 64 const sal_uInt16 BIFF12_CALCPR_CALCCOMPLETED = 0x0010; 65 const sal_uInt16 BIFF12_CALCPR_CALCONSAVE = 0x0020; 66 const sal_uInt16 BIFF12_CALCPR_CONCURRENT = 0x0040; 67 const sal_uInt16 BIFF12_CALCPR_MANUALPROC = 0x0080; 68 69 // no predefined constants for show objects mode 70 const sal_Int16 API_SHOWMODE_SHOW = 0; /// Show drawing objects. 71 const sal_Int16 API_SHOWMODE_HIDE = 1; /// Hide drawing objects. 72 const sal_Int16 API_SHOWMODE_PLACEHOLDER = 2; /// Show placeholders for drawing objects. 73 74 } // namespace 75 76 // ============================================================================ 77 78 FileSharingModel::FileSharingModel() : 79 mnPasswordHash( 0 ), 80 mbRecommendReadOnly( false ) 81 { 82 } 83 84 // ============================================================================ 85 86 WorkbookSettingsModel::WorkbookSettingsModel() : 87 mnShowObjectMode( XML_all ), 88 mnUpdateLinksMode( XML_userSet ), 89 mnDefaultThemeVer( -1 ), 90 mbDateMode1904( false ), 91 mbSaveExtLinkValues( true ) 92 { 93 } 94 95 void WorkbookSettingsModel::setBiffObjectMode( sal_uInt16 nObjMode ) 96 { 97 static const sal_Int32 spnObjModes[] = { XML_all, XML_placeholders, XML_none }; 98 mnShowObjectMode = STATIC_ARRAY_SELECT( spnObjModes, nObjMode, XML_all ); 99 } 100 101 // ============================================================================ 102 103 CalcSettingsModel::CalcSettingsModel() : 104 mfIterateDelta( 0.001 ), 105 mnCalcId( -1 ), 106 mnRefMode( XML_A1 ), 107 mnCalcMode( XML_auto ), 108 mnIterateCount( 100 ), 109 mnProcCount( -1 ), 110 mbCalcOnSave( true ), 111 mbCalcCompleted( true ), 112 mbFullPrecision( true ), 113 mbIterate( false ), 114 mbConcurrent( true ), 115 mbUseNlr( false ) 116 { 117 } 118 119 // ============================================================================ 120 121 WorkbookSettings::WorkbookSettings( const WorkbookHelper& rHelper ) : 122 WorkbookHelper( rHelper ) 123 { 124 } 125 126 void WorkbookSettings::importFileSharing( const AttributeList& rAttribs ) 127 { 128 maFileSharing.maUserName = rAttribs.getXString( XML_userName, OUString() ); 129 maFileSharing.mnPasswordHash = CodecHelper::getPasswordHash( rAttribs, XML_reservationPassword ); 130 maFileSharing.mbRecommendReadOnly = rAttribs.getBool( XML_readOnlyRecommended, false ); 131 } 132 133 void WorkbookSettings::importWorkbookPr( const AttributeList& rAttribs ) 134 { 135 maBookSettings.maCodeName = rAttribs.getString( XML_codeName, OUString() ); 136 maBookSettings.mnShowObjectMode = rAttribs.getToken( XML_showObjects, XML_all ); 137 maBookSettings.mnUpdateLinksMode = rAttribs.getToken( XML_updateLinks, XML_userSet ); 138 maBookSettings.mnDefaultThemeVer = rAttribs.getInteger( XML_defaultThemeVersion, -1 ); 139 maBookSettings.mbSaveExtLinkValues = rAttribs.getBool( XML_saveExternalLinkValues, true ); 140 setDateMode( rAttribs.getBool( XML_date1904, false ) ); 141 } 142 143 void WorkbookSettings::importCalcPr( const AttributeList& rAttribs ) 144 { 145 maCalcSettings.mfIterateDelta = rAttribs.getDouble( XML_iterateDelta, 0.0001 ); 146 maCalcSettings.mnCalcId = rAttribs.getInteger( XML_calcId, -1 ); 147 maCalcSettings.mnRefMode = rAttribs.getToken( XML_refMode, XML_A1 ); 148 maCalcSettings.mnCalcMode = rAttribs.getToken( XML_calcMode, XML_auto ); 149 maCalcSettings.mnIterateCount = rAttribs.getInteger( XML_iterateCount, 100 ); 150 maCalcSettings.mnProcCount = rAttribs.getInteger( XML_concurrentManualCount, -1 ); 151 maCalcSettings.mbCalcOnSave = rAttribs.getBool( XML_calcOnSave, true ); 152 maCalcSettings.mbCalcCompleted = rAttribs.getBool( XML_calcCompleted, true ); 153 maCalcSettings.mbFullPrecision = rAttribs.getBool( XML_fullPrecision, true ); 154 maCalcSettings.mbIterate = rAttribs.getBool( XML_iterate, false ); 155 maCalcSettings.mbConcurrent = rAttribs.getBool( XML_concurrentCalc, true ); 156 } 157 158 void WorkbookSettings::importFileSharing( SequenceInputStream& rStrm ) 159 { 160 maFileSharing.mbRecommendReadOnly = rStrm.readuInt16() != 0; 161 rStrm >> maFileSharing.mnPasswordHash >> maFileSharing.maUserName; 162 } 163 164 void WorkbookSettings::importWorkbookPr( SequenceInputStream& rStrm ) 165 { 166 sal_uInt32 nFlags; 167 rStrm >> nFlags >> maBookSettings.mnDefaultThemeVer >> maBookSettings.maCodeName; 168 maBookSettings.setBiffObjectMode( extractValue< sal_uInt16 >( nFlags, 13, 2 ) ); 169 // set flag means: strip external link values 170 maBookSettings.mbSaveExtLinkValues = !getFlag( nFlags, BIFF12_WORKBOOKPR_STRIPEXT ); 171 setDateMode( getFlag( nFlags, BIFF12_WORKBOOKPR_DATE1904 ) ); 172 } 173 174 void WorkbookSettings::importCalcPr( SequenceInputStream& rStrm ) 175 { 176 sal_Int32 nCalcMode, nProcCount; 177 sal_uInt16 nFlags; 178 rStrm >> maCalcSettings.mnCalcId >> nCalcMode >> maCalcSettings.mnIterateCount >> maCalcSettings.mfIterateDelta >> nProcCount >> nFlags; 179 180 static const sal_Int32 spnCalcModes[] = { XML_manual, XML_auto, XML_autoNoTable }; 181 maCalcSettings.mnRefMode = getFlagValue( nFlags, BIFF12_CALCPR_A1, XML_A1, XML_R1C1 ); 182 maCalcSettings.mnCalcMode = STATIC_ARRAY_SELECT( spnCalcModes, nCalcMode, XML_auto ); 183 maCalcSettings.mnProcCount = getFlagValue< sal_Int32 >( nFlags, BIFF12_CALCPR_MANUALPROC, nProcCount, -1 ); 184 maCalcSettings.mbCalcOnSave = getFlag( nFlags, BIFF12_CALCPR_CALCONSAVE ); 185 maCalcSettings.mbCalcCompleted = getFlag( nFlags, BIFF12_CALCPR_CALCCOMPLETED ); 186 maCalcSettings.mbFullPrecision = getFlag( nFlags, BIFF12_CALCPR_FULLPRECISION ); 187 maCalcSettings.mbIterate = getFlag( nFlags, BIFF12_CALCPR_ITERATE ); 188 maCalcSettings.mbConcurrent = getFlag( nFlags, BIFF12_CALCPR_CONCURRENT ); 189 } 190 191 void WorkbookSettings::setSaveExtLinkValues( bool bSaveExtLinks ) 192 { 193 maBookSettings.mbSaveExtLinkValues = bSaveExtLinks; 194 } 195 196 void WorkbookSettings::importBookBool( BiffInputStream& rStrm ) 197 { 198 // value of 0 means save external values, value of 1 means strip external values 199 maBookSettings.mbSaveExtLinkValues = rStrm.readuInt16() == 0; 200 } 201 202 void WorkbookSettings::importCalcCount( BiffInputStream& rStrm ) 203 { 204 maCalcSettings.mnIterateCount = rStrm.readuInt16(); 205 } 206 207 void WorkbookSettings::importCalcMode( BiffInputStream& rStrm ) 208 { 209 sal_Int16 nCalcMode = rStrm.readInt16() + 1; 210 static const sal_Int32 spnCalcModes[] = { XML_autoNoTable, XML_manual, XML_auto }; 211 maCalcSettings.mnCalcMode = STATIC_ARRAY_SELECT( spnCalcModes, nCalcMode, XML_auto ); 212 } 213 214 void WorkbookSettings::importCodeName( BiffInputStream& rStrm ) 215 { 216 maBookSettings.maCodeName = rStrm.readUniString(); 217 } 218 219 void WorkbookSettings::importDateMode( BiffInputStream& rStrm ) 220 { 221 setDateMode( rStrm.readuInt16() != 0 ); 222 } 223 224 void WorkbookSettings::importDelta( BiffInputStream& rStrm ) 225 { 226 rStrm >> maCalcSettings.mfIterateDelta; 227 } 228 229 void WorkbookSettings::importFileSharing( BiffInputStream& rStrm ) 230 { 231 maFileSharing.mbRecommendReadOnly = rStrm.readuInt16() != 0; 232 rStrm >> maFileSharing.mnPasswordHash; 233 if( getBiff() == BIFF8 ) 234 { 235 sal_uInt16 nStrLen = rStrm.readuInt16(); 236 // there is no string flags field if string is empty 237 if( nStrLen > 0 ) 238 maFileSharing.maUserName = rStrm.readUniStringBody( nStrLen ); 239 } 240 else 241 { 242 maFileSharing.maUserName = rStrm.readByteStringUC( false, getTextEncoding() ); 243 } 244 } 245 246 void WorkbookSettings::importHideObj( BiffInputStream& rStrm ) 247 { 248 maBookSettings.setBiffObjectMode( rStrm.readuInt16() ); 249 } 250 251 void WorkbookSettings::importIteration( BiffInputStream& rStrm ) 252 { 253 maCalcSettings.mbIterate = rStrm.readuInt16() != 0; 254 } 255 256 void WorkbookSettings::importPrecision( BiffInputStream& rStrm ) 257 { 258 maCalcSettings.mbFullPrecision = rStrm.readuInt16() != 0; 259 } 260 261 void WorkbookSettings::importRefMode( BiffInputStream& rStrm ) 262 { 263 maCalcSettings.mnRefMode = (rStrm.readuInt16() == 0) ? XML_R1C1 : XML_A1; 264 } 265 266 void WorkbookSettings::importSaveRecalc( BiffInputStream& rStrm ) 267 { 268 maCalcSettings.mbCalcOnSave = rStrm.readuInt16() != 0; 269 } 270 271 void WorkbookSettings::importUncalced( BiffInputStream& ) 272 { 273 // existence of this record indicates incomplete recalc 274 maCalcSettings.mbCalcCompleted = false; 275 } 276 277 void WorkbookSettings::importUsesElfs( BiffInputStream& rStrm ) 278 { 279 maCalcSettings.mbUseNlr = rStrm.readuInt16() != 0; 280 } 281 282 void WorkbookSettings::finalizeImport() 283 { 284 // default settings 285 PropertySet aPropSet( getDocument() ); 286 switch( getFilterType() ) 287 { 288 case FILTER_OOXML: 289 case FILTER_BIFF: 290 aPropSet.setProperty( PROP_IgnoreCase, true ); // always in Excel 291 aPropSet.setProperty( PROP_RegularExpressions, false ); // not supported in Excel 292 break; 293 case FILTER_UNKNOWN: 294 break; 295 } 296 297 // write protection 298 if( maFileSharing.mbRecommendReadOnly || (maFileSharing.mnPasswordHash != 0) ) try 299 { 300 getBaseFilter().getMediaDescriptor()[ CREATE_OUSTRING( "ReadOnly" ) ] <<= true; 301 302 Reference< XPropertySet > xDocumentSettings( getBaseFilter().getModelFactory()->createInstance( 303 CREATE_OUSTRING( "com.sun.star.document.Settings" ) ), UNO_QUERY_THROW ); 304 PropertySet aSettingsProp( xDocumentSettings ); 305 if( maFileSharing.mbRecommendReadOnly ) 306 aSettingsProp.setProperty( PROP_LoadReadonly, true ); 307 // if( maFileSharing.mnPasswordHash != 0 ) 308 // aSettingsProp.setProperty( PROP_ModifyPasswordHash, static_cast< sal_Int32 >( maFileSharing.mnPasswordHash ) ); 309 } 310 catch( Exception& ) 311 { 312 } 313 314 // calculation settings 315 Date aNullDate = getNullDate(); 316 317 aPropSet.setProperty( PROP_NullDate, aNullDate ); 318 aPropSet.setProperty( PROP_IsIterationEnabled, maCalcSettings.mbIterate ); 319 aPropSet.setProperty( PROP_IterationCount, maCalcSettings.mnIterateCount ); 320 aPropSet.setProperty( PROP_IterationEpsilon, maCalcSettings.mfIterateDelta ); 321 aPropSet.setProperty( PROP_CalcAsShown, !maCalcSettings.mbFullPrecision ); 322 aPropSet.setProperty( PROP_LookUpLabels, maCalcSettings.mbUseNlr ); 323 324 Reference< XNumberFormatsSupplier > xNumFmtsSupp( getDocument(), UNO_QUERY ); 325 if( xNumFmtsSupp.is() ) 326 { 327 PropertySet aNumFmtProp( xNumFmtsSupp->getNumberFormatSettings() ); 328 aNumFmtProp.setProperty( PROP_NullDate, aNullDate ); 329 } 330 331 Reference< XCalculatable > xCalculatable( getDocument(), UNO_QUERY ); 332 if( xCalculatable.is() ) 333 xCalculatable->enableAutomaticCalculation( (maCalcSettings.mnCalcMode == XML_auto) || (maCalcSettings.mnCalcMode == XML_autoNoTable) ); 334 335 // VBA code name 336 aPropSet.setProperty( PROP_CodeName, maBookSettings.maCodeName ); 337 } 338 339 sal_Int16 WorkbookSettings::getApiShowObjectMode() const 340 { 341 switch( maBookSettings.mnShowObjectMode ) 342 { 343 case XML_all: return API_SHOWMODE_SHOW; 344 case XML_none: return API_SHOWMODE_HIDE; 345 // #i80528# placeholders not supported anymore, but this is handled internally in Calc 346 case XML_placeholders: return API_SHOWMODE_PLACEHOLDER; 347 } 348 return API_SHOWMODE_SHOW; 349 } 350 351 Date WorkbookSettings::getNullDate() const 352 { 353 static const Date saDate1900( 30, 12, 1899 ), saDate1904( 1, 1, 1904 ); 354 return maBookSettings.mbDateMode1904 ? saDate1904 : saDate1900; 355 } 356 357 void WorkbookSettings::setDateMode( bool bDateMode1904 ) 358 { 359 maBookSettings.mbDateMode1904 = bDateMode1904; 360 getUnitConverter().finalizeNullDate( getNullDate() ); 361 } 362 363 // ============================================================================ 364 365 } // namespace xls 366 } // namespace oox 367