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/pagesettings.hxx" 29 30 #include <algorithm> 31 #include <set> 32 #include <com/sun/star/awt/Size.hpp> 33 #include <com/sun/star/container/XNamed.hpp> 34 #include <com/sun/star/sheet/XHeaderFooterContent.hpp> 35 #include <com/sun/star/style/GraphicLocation.hpp> 36 #include <com/sun/star/text/FilenameDisplayFormat.hpp> 37 #include <com/sun/star/text/XText.hpp> 38 #include <com/sun/star/text/XTextContent.hpp> 39 #include <com/sun/star/text/XTextCursor.hpp> 40 #include <rtl/strbuf.hxx> 41 #include <rtl/ustrbuf.hxx> 42 #include "oox/core/xmlfilterbase.hxx" 43 #include "oox/helper/attributelist.hxx" 44 #include "oox/helper/graphichelper.hxx" 45 #include "oox/helper/propertymap.hxx" 46 #include "oox/helper/propertyset.hxx" 47 #include "oox/xls/biffinputstream.hxx" 48 #include "oox/xls/excelhandlers.hxx" 49 #include "oox/xls/stylesbuffer.hxx" 50 #include "oox/xls/unitconverter.hxx" 51 52 namespace oox { 53 namespace xls { 54 55 // ============================================================================ 56 57 using namespace ::com::sun::star::awt; 58 using namespace ::com::sun::star::container; 59 using namespace ::com::sun::star::lang; 60 using namespace ::com::sun::star::sheet; 61 using namespace ::com::sun::star::style; 62 using namespace ::com::sun::star::text; 63 using namespace ::com::sun::star::uno; 64 65 using ::oox::core::Relations; 66 using ::rtl::OString; 67 using ::rtl::OStringBuffer; 68 using ::rtl::OUString; 69 using ::rtl::OUStringBuffer; 70 71 // ============================================================================ 72 73 namespace { 74 75 const double OOX_MARGIN_DEFAULT_LR = 0.748; /// Left/right default margin in inches. 76 const double OOX_MARGIN_DEFAULT_TB = 0.984; /// Top/bottom default margin in inches. 77 const double OOX_MARGIN_DEFAULT_HF = 0.512; /// Header/footer default margin in inches. 78 79 const sal_uInt16 BIFF12_PRINTOPT_HORCENTER = 0x0001; 80 const sal_uInt16 BIFF12_PRINTOPT_VERCENTER = 0x0002; 81 const sal_uInt16 BIFF12_PRINTOPT_PRINTHEADING = 0x0004; 82 const sal_uInt16 BIFF12_PRINTOPT_PRINTGRID = 0x0008; 83 84 const sal_uInt16 BIFF12_HEADERFOOTER_DIFFEVEN = 0x0001; 85 const sal_uInt16 BIFF12_HEADERFOOTER_DIFFFIRST = 0x0002; 86 const sal_uInt16 BIFF12_HEADERFOOTER_SCALEDOC = 0x0004; 87 const sal_uInt16 BIFF12_HEADERFOOTER_ALIGNMARGIN = 0x0008; 88 89 const sal_uInt16 BIFF12_PAGESETUP_INROWS = 0x0001; 90 const sal_uInt16 BIFF12_PAGESETUP_LANDSCAPE = 0x0002; 91 const sal_uInt16 BIFF12_PAGESETUP_INVALID = 0x0004; 92 const sal_uInt16 BIFF12_PAGESETUP_BLACKWHITE = 0x0008; 93 const sal_uInt16 BIFF12_PAGESETUP_DRAFTQUALITY = 0x0010; 94 const sal_uInt16 BIFF12_PAGESETUP_PRINTNOTES = 0x0020; 95 const sal_uInt16 BIFF12_PAGESETUP_DEFAULTORIENT = 0x0040; 96 const sal_uInt16 BIFF12_PAGESETUP_USEFIRSTPAGE = 0x0080; 97 const sal_uInt16 BIFF12_PAGESETUP_NOTES_END = 0x0100; // different to BIFF flag 98 99 const sal_uInt16 BIFF12_CHARTPAGESETUP_LANDSCAPE = 0x0001; 100 const sal_uInt16 BIFF12_CHARTPAGESETUP_INVALID = 0x0002; 101 const sal_uInt16 BIFF12_CHARTPAGESETUP_BLACKWHITE = 0x0004; 102 const sal_uInt16 BIFF12_CHARTPAGESETUP_DEFAULTORIENT= 0x0008; 103 const sal_uInt16 BIFF12_CHARTPAGESETUP_USEFIRSTPAGE = 0x0010; 104 const sal_uInt16 BIFF12_CHARTPAGESETUP_DRAFTQUALITY = 0x0020; 105 106 const sal_uInt16 BIFF_PAGESETUP_INROWS = 0x0001; 107 const sal_uInt16 BIFF_PAGESETUP_PORTRAIT = 0x0002; 108 const sal_uInt16 BIFF_PAGESETUP_INVALID = 0x0004; 109 const sal_uInt16 BIFF_PAGESETUP_BLACKWHITE = 0x0008; 110 const sal_uInt16 BIFF_PAGESETUP_DRAFTQUALITY = 0x0010; 111 const sal_uInt16 BIFF_PAGESETUP_PRINTNOTES = 0x0020; 112 const sal_uInt16 BIFF_PAGESETUP_DEFAULTORIENT = 0x0040; 113 const sal_uInt16 BIFF_PAGESETUP_USEFIRSTPAGE = 0x0080; 114 const sal_uInt16 BIFF_PAGESETUP_NOTES_END = 0x0200; 115 116 } // namespace 117 118 // ============================================================================ 119 120 PageSettingsModel::PageSettingsModel() : 121 mfLeftMargin( OOX_MARGIN_DEFAULT_LR ), 122 mfRightMargin( OOX_MARGIN_DEFAULT_LR ), 123 mfTopMargin( OOX_MARGIN_DEFAULT_TB ), 124 mfBottomMargin( OOX_MARGIN_DEFAULT_TB ), 125 mfHeaderMargin( OOX_MARGIN_DEFAULT_HF ), 126 mfFooterMargin( OOX_MARGIN_DEFAULT_HF ), 127 mnPaperSize( 1 ), 128 mnCopies( 1 ), 129 mnScale( 100 ), 130 mnFirstPage( 1 ), 131 mnFitToWidth( 1 ), 132 mnFitToHeight( 1 ), 133 mnHorPrintRes( 600 ), 134 mnVerPrintRes( 600 ), 135 mnOrientation( XML_default ), 136 mnPageOrder( XML_downThenOver ), 137 mnCellComments( XML_none ), 138 mnPrintErrors( XML_displayed ), 139 mbUseEvenHF( false ), 140 mbUseFirstHF( false ), 141 mbValidSettings( true ), 142 mbUseFirstPage( false ), 143 mbBlackWhite( false ), 144 mbDraftQuality( false ), 145 mbFitToPages( false ), 146 mbHorCenter( false ), 147 mbVerCenter( false ), 148 mbPrintGrid( false ), 149 mbPrintHeadings( false ) 150 { 151 } 152 153 void PageSettingsModel::setBiffPrintErrors( sal_uInt8 nPrintErrors ) 154 { 155 static const sal_Int32 spnErrorIds[] = { XML_displayed, XML_none, XML_dash, XML_NA }; 156 mnPrintErrors = STATIC_ARRAY_SELECT( spnErrorIds, nPrintErrors, XML_none ); 157 } 158 159 // ============================================================================ 160 161 PageSettings::PageSettings( const WorksheetHelper& rHelper ) : 162 WorksheetHelper( rHelper ) 163 { 164 } 165 166 void PageSettings::importPrintOptions( const AttributeList& rAttribs ) 167 { 168 maModel.mbHorCenter = rAttribs.getBool( XML_horizontalCentered, false ); 169 maModel.mbVerCenter = rAttribs.getBool( XML_verticalCentered, false ); 170 maModel.mbPrintGrid = rAttribs.getBool( XML_gridLines, false ); 171 maModel.mbPrintHeadings = rAttribs.getBool( XML_headings, false ); 172 } 173 174 void PageSettings::importPageMargins( const AttributeList& rAttribs ) 175 { 176 maModel.mfLeftMargin = rAttribs.getDouble( XML_left, OOX_MARGIN_DEFAULT_LR ); 177 maModel.mfRightMargin = rAttribs.getDouble( XML_right, OOX_MARGIN_DEFAULT_LR ); 178 maModel.mfTopMargin = rAttribs.getDouble( XML_top, OOX_MARGIN_DEFAULT_TB ); 179 maModel.mfBottomMargin = rAttribs.getDouble( XML_bottom, OOX_MARGIN_DEFAULT_TB ); 180 maModel.mfHeaderMargin = rAttribs.getDouble( XML_header, OOX_MARGIN_DEFAULT_HF ); 181 maModel.mfFooterMargin = rAttribs.getDouble( XML_footer, OOX_MARGIN_DEFAULT_HF ); 182 } 183 184 void PageSettings::importPageSetup( const Relations& rRelations, const AttributeList& rAttribs ) 185 { 186 maModel.maBinSettPath = rRelations.getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ); 187 maModel.mnPaperSize = rAttribs.getInteger( XML_paperSize, 1 ); 188 maModel.mnCopies = rAttribs.getInteger( XML_copies, 1 ); 189 maModel.mnScale = rAttribs.getInteger( XML_scale, 100 ); 190 maModel.mnFirstPage = rAttribs.getInteger( XML_firstPageNumber, 1 ); 191 maModel.mnFitToWidth = rAttribs.getInteger( XML_fitToWidth, 1 ); 192 maModel.mnFitToHeight = rAttribs.getInteger( XML_fitToHeight, 1 ); 193 maModel.mnHorPrintRes = rAttribs.getInteger( XML_horizontalDpi, 600 ); 194 maModel.mnVerPrintRes = rAttribs.getInteger( XML_verticalDpi, 600 ); 195 maModel.mnOrientation = rAttribs.getToken( XML_orientation, XML_default ); 196 maModel.mnPageOrder = rAttribs.getToken( XML_pageOrder, XML_downThenOver ); 197 maModel.mnCellComments = rAttribs.getToken( XML_cellComments, XML_none ); 198 maModel.mnPrintErrors = rAttribs.getToken( XML_errors, XML_displayed ); 199 maModel.mbValidSettings = rAttribs.getBool( XML_usePrinterDefaults, true ); 200 maModel.mbUseFirstPage = rAttribs.getBool( XML_useFirstPageNumber, false ); 201 maModel.mbBlackWhite = rAttribs.getBool( XML_blackAndWhite, false ); 202 maModel.mbDraftQuality = rAttribs.getBool( XML_draft, false ); 203 } 204 205 void PageSettings::importChartPageSetup( const Relations& rRelations, const AttributeList& rAttribs ) 206 { 207 maModel.maBinSettPath = rRelations.getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ); 208 maModel.mnPaperSize = rAttribs.getInteger( XML_paperSize, 1 ); 209 maModel.mnCopies = rAttribs.getInteger( XML_copies, 1 ); 210 maModel.mnFirstPage = rAttribs.getInteger( XML_firstPageNumber, 1 ); 211 maModel.mnHorPrintRes = rAttribs.getInteger( XML_horizontalDpi, 600 ); 212 maModel.mnVerPrintRes = rAttribs.getInteger( XML_verticalDpi, 600 ); 213 maModel.mnOrientation = rAttribs.getToken( XML_orientation, XML_default ); 214 maModel.mbValidSettings = rAttribs.getBool( XML_usePrinterDefaults, true ); 215 maModel.mbUseFirstPage = rAttribs.getBool( XML_useFirstPageNumber, false ); 216 maModel.mbBlackWhite = rAttribs.getBool( XML_blackAndWhite, false ); 217 maModel.mbDraftQuality = rAttribs.getBool( XML_draft, false ); 218 } 219 220 void PageSettings::importHeaderFooter( const AttributeList& rAttribs ) 221 { 222 maModel.mbUseEvenHF = rAttribs.getBool( XML_differentOddEven, false ); 223 maModel.mbUseFirstHF = rAttribs.getBool( XML_differentFirst, false ); 224 } 225 226 void PageSettings::importHeaderFooterCharacters( const OUString& rChars, sal_Int32 nElement ) 227 { 228 switch( nElement ) 229 { 230 case XLS_TOKEN( oddHeader ): maModel.maOddHeader += rChars; break; 231 case XLS_TOKEN( oddFooter ): maModel.maOddFooter += rChars; break; 232 case XLS_TOKEN( evenHeader ): maModel.maEvenHeader += rChars; break; 233 case XLS_TOKEN( evenFooter ): maModel.maEvenFooter += rChars; break; 234 case XLS_TOKEN( firstHeader ): maModel.maFirstHeader += rChars; break; 235 case XLS_TOKEN( firstFooter ): maModel.maFirstFooter += rChars; break; 236 } 237 } 238 239 void PageSettings::importPicture( const Relations& rRelations, const AttributeList& rAttribs ) 240 { 241 importPictureData( rRelations, rAttribs.getString( R_TOKEN( id ), OUString() ) ); 242 } 243 244 void PageSettings::importPageMargins( SequenceInputStream& rStrm ) 245 { 246 rStrm >> maModel.mfLeftMargin >> maModel.mfRightMargin 247 >> maModel.mfTopMargin >> maModel.mfBottomMargin 248 >> maModel.mfHeaderMargin >> maModel.mfFooterMargin; 249 } 250 251 void PageSettings::importPrintOptions( SequenceInputStream& rStrm ) 252 { 253 sal_uInt16 nFlags; 254 rStrm >> nFlags; 255 maModel.mbHorCenter = getFlag( nFlags, BIFF12_PRINTOPT_HORCENTER ); 256 maModel.mbVerCenter = getFlag( nFlags, BIFF12_PRINTOPT_VERCENTER ); 257 maModel.mbPrintGrid = getFlag( nFlags, BIFF12_PRINTOPT_PRINTGRID ); 258 maModel.mbPrintHeadings = getFlag( nFlags, BIFF12_PRINTOPT_PRINTHEADING ); 259 } 260 261 void PageSettings::importPageSetup( const Relations& rRelations, SequenceInputStream& rStrm ) 262 { 263 OUString aRelId; 264 sal_uInt16 nFlags; 265 rStrm >> maModel.mnPaperSize >> maModel.mnScale 266 >> maModel.mnHorPrintRes >> maModel.mnVerPrintRes 267 >> maModel.mnCopies >> maModel.mnFirstPage 268 >> maModel.mnFitToWidth >> maModel.mnFitToHeight 269 >> nFlags >> aRelId; 270 maModel.setBiffPrintErrors( extractValue< sal_uInt8 >( nFlags, 9, 2 ) ); 271 maModel.maBinSettPath = rRelations.getFragmentPathFromRelId( aRelId ); 272 maModel.mnOrientation = getFlagValue( nFlags, BIFF12_PAGESETUP_DEFAULTORIENT, XML_default, getFlagValue( nFlags, BIFF12_PAGESETUP_LANDSCAPE, XML_landscape, XML_portrait ) ); 273 maModel.mnPageOrder = getFlagValue( nFlags, BIFF12_PAGESETUP_INROWS, XML_overThenDown, XML_downThenOver ); 274 maModel.mnCellComments = getFlagValue( nFlags, BIFF12_PAGESETUP_PRINTNOTES, getFlagValue( nFlags, BIFF12_PAGESETUP_NOTES_END, XML_atEnd, XML_asDisplayed ), XML_none ); 275 maModel.mbValidSettings = !getFlag( nFlags, BIFF12_PAGESETUP_INVALID ); 276 maModel.mbUseFirstPage = getFlag( nFlags, BIFF12_PAGESETUP_USEFIRSTPAGE ); 277 maModel.mbBlackWhite = getFlag( nFlags, BIFF12_PAGESETUP_BLACKWHITE ); 278 maModel.mbDraftQuality = getFlag( nFlags, BIFF12_PAGESETUP_DRAFTQUALITY ); 279 } 280 281 void PageSettings::importChartPageSetup( const Relations& rRelations, SequenceInputStream& rStrm ) 282 { 283 OUString aRelId; 284 sal_uInt16 nFirstPage, nFlags; 285 rStrm >> maModel.mnPaperSize >> maModel.mnHorPrintRes >> maModel.mnVerPrintRes 286 >> maModel.mnCopies >> nFirstPage >> nFlags >> aRelId; 287 maModel.maBinSettPath = rRelations.getFragmentPathFromRelId( aRelId ); 288 maModel.mnFirstPage = nFirstPage; // 16-bit in CHARTPAGESETUP 289 maModel.mnOrientation = getFlagValue( nFlags, BIFF12_CHARTPAGESETUP_DEFAULTORIENT, XML_default, getFlagValue( nFlags, BIFF12_CHARTPAGESETUP_LANDSCAPE, XML_landscape, XML_portrait ) ); 290 maModel.mbValidSettings = !getFlag( nFlags, BIFF12_CHARTPAGESETUP_INVALID ); 291 maModel.mbUseFirstPage = getFlag( nFlags, BIFF12_CHARTPAGESETUP_USEFIRSTPAGE ); 292 maModel.mbBlackWhite = getFlag( nFlags, BIFF12_CHARTPAGESETUP_BLACKWHITE ); 293 maModel.mbDraftQuality = getFlag( nFlags, BIFF12_CHARTPAGESETUP_DRAFTQUALITY ); 294 } 295 296 void PageSettings::importHeaderFooter( SequenceInputStream& rStrm ) 297 { 298 sal_uInt16 nFlags; 299 rStrm >> nFlags 300 >> maModel.maOddHeader >> maModel.maOddFooter 301 >> maModel.maEvenHeader >> maModel.maEvenFooter 302 >> maModel.maFirstHeader >> maModel.maFirstFooter; 303 maModel.mbUseEvenHF = getFlag( nFlags, BIFF12_HEADERFOOTER_DIFFEVEN ); 304 maModel.mbUseFirstHF = getFlag( nFlags, BIFF12_HEADERFOOTER_DIFFFIRST ); 305 } 306 307 void PageSettings::importPicture( const Relations& rRelations, SequenceInputStream& rStrm ) 308 { 309 importPictureData( rRelations, BiffHelper::readString( rStrm ) ); 310 } 311 312 void PageSettings::importLeftMargin( BiffInputStream& rStrm ) 313 { 314 rStrm >> maModel.mfLeftMargin; 315 } 316 317 void PageSettings::importRightMargin( BiffInputStream& rStrm ) 318 { 319 rStrm >> maModel.mfRightMargin; 320 } 321 322 void PageSettings::importTopMargin( BiffInputStream& rStrm ) 323 { 324 rStrm >> maModel.mfTopMargin; 325 } 326 327 void PageSettings::importBottomMargin( BiffInputStream& rStrm ) 328 { 329 rStrm >> maModel.mfBottomMargin; 330 } 331 332 void PageSettings::importPageSetup( BiffInputStream& rStrm ) 333 { 334 sal_uInt16 nPaperSize, nScale, nFirstPage, nFitToWidth, nFitToHeight, nFlags; 335 rStrm >> nPaperSize >> nScale >> nFirstPage >> nFitToWidth >> nFitToHeight >> nFlags; 336 337 maModel.mnPaperSize = nPaperSize; // equal in BIFF and OOX 338 maModel.mnScale = nScale; 339 maModel.mnFirstPage = nFirstPage; 340 maModel.mnFitToWidth = nFitToWidth; 341 maModel.mnFitToHeight = nFitToHeight; 342 maModel.mnOrientation = getFlagValue( nFlags, BIFF_PAGESETUP_PORTRAIT, XML_portrait, XML_landscape ); 343 maModel.mnPageOrder = getFlagValue( nFlags, BIFF_PAGESETUP_INROWS, XML_overThenDown, XML_downThenOver ); 344 maModel.mbValidSettings = !getFlag( nFlags, BIFF_PAGESETUP_INVALID ); 345 maModel.mbUseFirstPage = true; 346 maModel.mbBlackWhite = getFlag( nFlags, BIFF_PAGESETUP_BLACKWHITE ); 347 348 if( getBiff() >= BIFF5 ) 349 { 350 sal_uInt16 nHorPrintRes, nVerPrintRes, nCopies; 351 rStrm >> nHorPrintRes >> nVerPrintRes >> maModel.mfHeaderMargin >> maModel.mfFooterMargin >> nCopies; 352 353 maModel.mnCopies = nCopies; 354 maModel.mnOrientation = getFlagValue( nFlags, BIFF_PAGESETUP_DEFAULTORIENT, XML_default, maModel.mnOrientation ); 355 maModel.mnHorPrintRes = nHorPrintRes; 356 maModel.mnVerPrintRes = nVerPrintRes; 357 maModel.mnCellComments = getFlagValue( nFlags, BIFF_PAGESETUP_PRINTNOTES, XML_asDisplayed, XML_none ); 358 maModel.mbUseFirstPage = getFlag( nFlags, BIFF_PAGESETUP_USEFIRSTPAGE ); 359 maModel.mbDraftQuality = getFlag( nFlags, BIFF_PAGESETUP_DRAFTQUALITY ); 360 361 if( getBiff() == BIFF8 ) 362 { 363 maModel.setBiffPrintErrors( extractValue< sal_uInt8 >( nFlags, 10, 2 ) ); 364 maModel.mnCellComments = getFlagValue( nFlags, BIFF_PAGESETUP_PRINTNOTES, getFlagValue( nFlags, BIFF_PAGESETUP_NOTES_END, XML_atEnd, XML_asDisplayed ), XML_none ); 365 } 366 } 367 } 368 369 void PageSettings::importHorCenter( BiffInputStream& rStrm ) 370 { 371 maModel.mbHorCenter = rStrm.readuInt16() != 0; 372 } 373 374 void PageSettings::importVerCenter( BiffInputStream& rStrm ) 375 { 376 maModel.mbVerCenter = rStrm.readuInt16() != 0; 377 } 378 379 void PageSettings::importPrintHeaders( BiffInputStream& rStrm ) 380 { 381 maModel.mbPrintHeadings = rStrm.readuInt16() != 0; 382 } 383 384 void PageSettings::importPrintGridLines( BiffInputStream& rStrm ) 385 { 386 maModel.mbPrintGrid = rStrm.readuInt16() != 0; 387 } 388 389 void PageSettings::importHeader( BiffInputStream& rStrm ) 390 { 391 if( rStrm.getRemaining() > 0 ) 392 maModel.maOddHeader = (getBiff() == BIFF8) ? rStrm.readUniString() : rStrm.readByteStringUC( false, getTextEncoding() ); 393 else 394 maModel.maOddHeader = OUString(); 395 } 396 397 void PageSettings::importFooter( BiffInputStream& rStrm ) 398 { 399 if( rStrm.getRemaining() > 0 ) 400 maModel.maOddFooter = (getBiff() == BIFF8) ? rStrm.readUniString() : rStrm.readByteStringUC( false, getTextEncoding() ); 401 else 402 maModel.maOddFooter = OUString(); 403 } 404 405 void PageSettings::importPicture( BiffInputStream& rStrm ) 406 { 407 StreamDataSequence aPictureData; 408 BiffHelper::importImgData( aPictureData, rStrm, getBiff() ); 409 maModel.maGraphicUrl = getBaseFilter().getGraphicHelper().importGraphicObject( aPictureData ); 410 } 411 412 void PageSettings::setFitToPagesMode( bool bFitToPages ) 413 { 414 maModel.mbFitToPages = bFitToPages; 415 } 416 417 void PageSettings::finalizeImport() 418 { 419 OUStringBuffer aStyleNameBuffer( CREATE_OUSTRING( "PageStyle_" ) ); 420 Reference< XNamed > xSheetName( getSheet(), UNO_QUERY ); 421 if( xSheetName.is() ) 422 aStyleNameBuffer.append( xSheetName->getName() ); 423 else 424 aStyleNameBuffer.append( static_cast< sal_Int32 >( getSheetIndex() + 1 ) ); 425 OUString aStyleName = aStyleNameBuffer.makeStringAndClear(); 426 427 Reference< XStyle > xStyle = createStyleObject( aStyleName, true ); 428 PropertySet aStyleProps( xStyle ); 429 getPageSettingsConverter().writePageSettingsProperties( aStyleProps, maModel, getSheetType() ); 430 431 PropertySet aSheetProps( getSheet() ); 432 aSheetProps.setProperty( PROP_PageStyle, aStyleName ); 433 } 434 435 void PageSettings::importPictureData( const Relations& rRelations, const OUString& rRelId ) 436 { 437 OUString aPicturePath = rRelations.getFragmentPathFromRelId( rRelId ); 438 if( aPicturePath.getLength() > 0 ) 439 maModel.maGraphicUrl = getBaseFilter().getGraphicHelper().importEmbeddedGraphicObject( aPicturePath ); 440 } 441 442 // ============================================================================ 443 // ============================================================================ 444 445 enum HFPortionId 446 { 447 HF_LEFT, 448 HF_CENTER, 449 HF_RIGHT, 450 HF_COUNT 451 }; 452 453 // ---------------------------------------------------------------------------- 454 455 struct HFPortionInfo 456 { 457 Reference< XText > mxText; /// XText interface of this portion. 458 Reference< XTextCursor > mxStart; /// Start position of current text range for formatting. 459 Reference< XTextCursor > mxEnd; /// End position of current text range for formatting. 460 double mfTotalHeight; /// Sum of heights of previous lines in points. 461 double mfCurrHeight; /// Height of the current text line in points. 462 463 bool initialize( const Reference< XText >& rxText ); 464 }; 465 466 bool HFPortionInfo::initialize( const Reference< XText >& rxText ) 467 { 468 mfTotalHeight = mfCurrHeight = 0.0; 469 mxText = rxText; 470 if( mxText.is() ) 471 { 472 mxStart = mxText->createTextCursor(); 473 mxEnd = mxText->createTextCursor(); 474 } 475 bool bRet = mxText.is() && mxStart.is() && mxEnd.is(); 476 OSL_ENSURE( bRet, "HFPortionInfo::initialize - missing interfaces" ); 477 return bRet; 478 } 479 480 // ============================================================================ 481 482 class HeaderFooterParser : public WorkbookHelper 483 { 484 public: 485 explicit HeaderFooterParser( const WorkbookHelper& rHelper ); 486 487 /** Parses the passed string and creates the header/footer contents. 488 @returns The total height of the converted header or footer in points. */ 489 double parse( 490 const Reference< XHeaderFooterContent >& rxContext, 491 const OUString& rData ); 492 493 private: 494 /** Returns the current edit engine text object. */ 495 inline HFPortionInfo& getPortion() { return maPortions[ meCurrPortion ]; } 496 /** Returns the start cursor of the current text range. */ 497 inline const Reference< XTextCursor >& getStartPos() { return getPortion().mxStart; } 498 /** Returns the end cursor of the current text range. */ 499 inline const Reference< XTextCursor >& getEndPos() { return getPortion().mxEnd; } 500 501 /** Returns the current line height of the specified portion. */ 502 double getCurrHeight( HFPortionId ePortion ) const; 503 /** Returns the current line height. */ 504 double getCurrHeight() const; 505 506 /** Updates the current line height of the specified portion, using the current font size. */ 507 void updateCurrHeight( HFPortionId ePortion ); 508 /** Updates the current line height, using the current font size. */ 509 void updateCurrHeight(); 510 511 /** Sets the font attributes at the current selection. */ 512 void setAttributes(); 513 /** Appends and clears internal string buffer. */ 514 void appendText(); 515 /** Appends a line break and adjusts internal text height data. */ 516 void appendLineBreak(); 517 518 /** Creates a text field from the passed service name. */ 519 Reference< XTextContent > createField( const OUString& rServiceName ) const; 520 /** Appends the passed text field. */ 521 void appendField( const Reference< XTextContent >& rxContent ); 522 523 /** Sets the passed font name if it is valid. */ 524 void convertFontName( const OUString& rStyle ); 525 /** Converts a font style given as string. */ 526 void convertFontStyle( const OUString& rStyle ); 527 /** Converts a font color given as string. */ 528 void convertFontColor( const OUString& rColor ); 529 530 /** Finalizes current portion: sets font attributes and updates text height data. */ 531 void finalizePortion(); 532 /** Changes current header/footer portion. */ 533 void setNewPortion( HFPortionId ePortion ); 534 535 private: 536 typedef ::std::vector< HFPortionInfo > HFPortionInfoVec; 537 typedef ::std::set< OString > OStringSet; 538 539 const OUString maPageNumberService; 540 const OUString maPageCountService; 541 const OUString maSheetNameService; 542 const OUString maFileNameService; 543 const OUString maDateTimeService; 544 const OStringSet maBoldNames; /// All names for bold font style in lowercase UTF-8. 545 const OStringSet maItalicNames; /// All names for italic font style in lowercase UTF-8. 546 HFPortionInfoVec maPortions; 547 HFPortionId meCurrPortion; /// Identifier of current H/F portion. 548 OUStringBuffer maBuffer; /// Text data to append to current text range. 549 FontModel maFontModel; /// Font attributes of current text range. 550 }; 551 552 // ---------------------------------------------------------------------------- 553 554 namespace { 555 556 // different names for bold font style (lowercase) 557 static const sal_Char* const sppcBoldNames[] = 558 { 559 "bold", 560 "fett", // German 'bold' 561 "demibold", 562 "halbfett", // German 'demibold' 563 "black", 564 "heavy" 565 }; 566 567 // different names for italic font style (lowercase) 568 static const sal_Char* const sppcItalicNames[] = 569 { 570 "italic", 571 "kursiv", // German 'italic' 572 "oblique", 573 "schr\303\204g", // German 'oblique' with uppercase A umlaut 574 "schr\303\244g" // German 'oblique' with lowercase A umlaut 575 }; 576 577 } // namespace 578 579 // ---------------------------------------------------------------------------- 580 581 HeaderFooterParser::HeaderFooterParser( const WorkbookHelper& rHelper ) : 582 WorkbookHelper( rHelper ), 583 maPageNumberService( CREATE_OUSTRING( "com.sun.star.text.TextField.PageNumber" ) ), 584 maPageCountService( CREATE_OUSTRING( "com.sun.star.text.TextField.PageCount" ) ), 585 maSheetNameService( CREATE_OUSTRING( "com.sun.star.text.TextField.SheetName" ) ), 586 maFileNameService( CREATE_OUSTRING( "com.sun.star.text.TextField.FileName" ) ), 587 maDateTimeService( CREATE_OUSTRING( "com.sun.star.text.TextField.DateTime" ) ), 588 maBoldNames( sppcBoldNames, STATIC_ARRAY_END( sppcBoldNames ) ), 589 maItalicNames( sppcItalicNames, STATIC_ARRAY_END( sppcItalicNames ) ), 590 maPortions( static_cast< size_t >( HF_COUNT ) ), 591 meCurrPortion( HF_CENTER ) 592 { 593 } 594 595 double HeaderFooterParser::parse( const Reference< XHeaderFooterContent >& rxContext, const OUString& rData ) 596 { 597 if( !rxContext.is() || (rData.getLength() == 0) || 598 !maPortions[ HF_LEFT ].initialize( rxContext->getLeftText() ) || 599 !maPortions[ HF_CENTER ].initialize( rxContext->getCenterText() ) || 600 !maPortions[ HF_RIGHT ].initialize( rxContext->getRightText() ) ) 601 return 0.0; 602 603 meCurrPortion = HF_CENTER; 604 maBuffer.setLength( 0 ); 605 maFontModel = getStyles().getDefaultFontModel(); 606 OUStringBuffer aFontName; // current font name 607 OUStringBuffer aFontStyle; // current font style 608 sal_Int32 nFontHeight = 0; // current font height 609 610 /** State of the parser. */ 611 enum 612 { 613 STATE_TEXT, /// Literal text data. 614 STATE_TOKEN, /// Control token following a '&' character. 615 STATE_FONTNAME, /// Font name ('&' is followed by '"', reads until next '"' or ','). 616 STATE_FONTSTYLE, /// Font style name (font part after ',', reads until next '"'). 617 STATE_FONTHEIGHT /// Font height ('&' is followed by num. digits, reads until non-digit). 618 } 619 eState = STATE_TEXT; 620 621 const sal_Unicode* pcChar = rData.getStr(); 622 const sal_Unicode* pcEnd = pcChar + rData.getLength(); 623 for( ; (pcChar != pcEnd) && (*pcChar != 0); ++pcChar ) 624 { 625 sal_Unicode cChar = *pcChar; 626 switch( eState ) 627 { 628 case STATE_TEXT: 629 { 630 switch( cChar ) 631 { 632 case '&': // new token 633 appendText(); 634 eState = STATE_TOKEN; 635 break; 636 case '\n': // line break 637 appendText(); 638 appendLineBreak(); 639 break; 640 default: 641 maBuffer.append( cChar ); 642 } 643 } 644 break; 645 646 case STATE_TOKEN: 647 { 648 // default: back to text mode, may be changed in specific cases 649 eState = STATE_TEXT; 650 // ignore case of token codes 651 if( ('a' <= cChar) && (cChar <= 'z') ) 652 (cChar -= 'a') += 'A'; 653 switch( cChar ) 654 { 655 case '&': maBuffer.append( cChar ); break; // the '&' character 656 657 case 'L': setNewPortion( HF_LEFT ); break; // left portion 658 case 'C': setNewPortion( HF_CENTER ); break; // center portion 659 case 'R': setNewPortion( HF_RIGHT ); break; // right portion 660 661 case 'P': // page number 662 appendField( createField( maPageNumberService ) ); 663 break; 664 case 'N': // total page count 665 appendField( createField( maPageCountService ) ); 666 break; 667 case 'A': // current sheet name 668 appendField( createField( maSheetNameService ) ); 669 break; 670 671 case 'F': // file name 672 { 673 Reference< XTextContent > xContent = createField( maFileNameService ); 674 PropertySet aPropSet( xContent ); 675 aPropSet.setProperty( PROP_FileFormat, ::com::sun::star::text::FilenameDisplayFormat::NAME_AND_EXT ); 676 appendField( xContent ); 677 } 678 break; 679 case 'Z': // file path (without file name), OOXML, BIFF12, and BIFF8 only 680 if( (getFilterType() == FILTER_OOXML) || ((getFilterType() == FILTER_BIFF) && (getBiff() == BIFF8)) ) 681 { 682 Reference< XTextContent > xContent = createField( maFileNameService ); 683 PropertySet aPropSet( xContent ); 684 // FilenameDisplayFormat::PATH not supported by Calc 685 aPropSet.setProperty( PROP_FileFormat, ::com::sun::star::text::FilenameDisplayFormat::FULL ); 686 appendField( xContent ); 687 /* path only is not supported -- if we find a '&Z&F' 688 combination for path/name, skip the '&F' part */ 689 if( (pcChar + 2 < pcEnd) && (pcChar[ 1 ] == '&') && ((pcChar[ 2 ] == 'f') || (pcChar[ 2 ] == 'F')) ) 690 pcChar += 2; 691 } 692 break; 693 case 'D': // date 694 { 695 Reference< XTextContent > xContent = createField( maDateTimeService ); 696 PropertySet aPropSet( xContent ); 697 aPropSet.setProperty( PROP_IsDate, true ); 698 appendField( xContent ); 699 } 700 break; 701 case 'T': // time 702 { 703 Reference< XTextContent > xContent = createField( maDateTimeService ); 704 PropertySet aPropSet( xContent ); 705 aPropSet.setProperty( PROP_IsDate, false ); 706 appendField( xContent ); 707 } 708 break; 709 710 case 'B': // bold 711 setAttributes(); 712 maFontModel.mbBold = !maFontModel.mbBold; 713 break; 714 case 'I': // italic 715 setAttributes(); 716 maFontModel.mbItalic = !maFontModel.mbItalic; 717 break; 718 case 'U': // underline 719 setAttributes(); 720 maFontModel.mnUnderline = (maFontModel.mnUnderline == XML_single) ? XML_none : XML_single; 721 break; 722 case 'E': // double underline 723 setAttributes(); 724 maFontModel.mnUnderline = (maFontModel.mnUnderline == XML_double) ? XML_none : XML_double; 725 break; 726 case 'S': // strikeout 727 setAttributes(); 728 maFontModel.mbStrikeout = !maFontModel.mbStrikeout; 729 break; 730 case 'X': // superscript 731 setAttributes(); 732 maFontModel.mnEscapement = (maFontModel.mnEscapement == XML_superscript) ? XML_baseline : XML_superscript; 733 break; 734 case 'Y': // subsrcipt 735 setAttributes(); 736 maFontModel.mnEscapement = (maFontModel.mnEscapement == XML_subscript) ? XML_baseline : XML_subscript; 737 break; 738 case 'O': // outlined 739 setAttributes(); 740 maFontModel.mbOutline = !maFontModel.mbOutline; 741 break; 742 case 'H': // shadow 743 setAttributes(); 744 maFontModel.mbShadow = !maFontModel.mbShadow; 745 break; 746 747 case 'K': // text color (not in BIFF) 748 if( (getFilterType() == FILTER_OOXML) && (pcChar + 6 < pcEnd) ) 749 { 750 setAttributes(); 751 // eat the following 6 characters 752 convertFontColor( OUString( pcChar + 1, 6 ) ); 753 pcChar += 6; 754 } 755 break; 756 757 case '\"': // font name 758 aFontName.setLength( 0 ); 759 aFontStyle.setLength( 0 ); 760 eState = STATE_FONTNAME; 761 break; 762 default: 763 if( ('0' <= cChar) && (cChar <= '9') ) // font size 764 { 765 nFontHeight = cChar - '0'; 766 eState = STATE_FONTHEIGHT; 767 } 768 } 769 } 770 break; 771 772 case STATE_FONTNAME: 773 { 774 switch( cChar ) 775 { 776 case '\"': 777 setAttributes(); 778 convertFontName( aFontName.makeStringAndClear() ); 779 eState = STATE_TEXT; 780 break; 781 case ',': 782 eState = STATE_FONTSTYLE; 783 break; 784 default: 785 aFontName.append( cChar ); 786 } 787 } 788 break; 789 790 case STATE_FONTSTYLE: 791 { 792 switch( cChar ) 793 { 794 case '\"': 795 setAttributes(); 796 convertFontName( aFontName.makeStringAndClear() ); 797 convertFontStyle( aFontStyle.makeStringAndClear() ); 798 eState = STATE_TEXT; 799 break; 800 default: 801 aFontStyle.append( cChar ); 802 } 803 } 804 break; 805 806 case STATE_FONTHEIGHT: 807 { 808 if( ('0' <= cChar) && (cChar <= '9') ) 809 { 810 if( nFontHeight >= 0 ) 811 { 812 nFontHeight *= 10; 813 nFontHeight += (cChar - '0'); 814 if( nFontHeight > 1000 ) 815 nFontHeight = -1; 816 } 817 } 818 else 819 { 820 if( nFontHeight > 0 ) 821 { 822 setAttributes(); 823 maFontModel.mfHeight = nFontHeight; 824 } 825 --pcChar; 826 eState = STATE_TEXT; 827 } 828 } 829 break; 830 } 831 } 832 833 // finalize 834 finalizePortion(); 835 maPortions[ HF_LEFT ].mfTotalHeight += getCurrHeight( HF_LEFT ); 836 maPortions[ HF_CENTER ].mfTotalHeight += getCurrHeight( HF_CENTER ); 837 maPortions[ HF_RIGHT ].mfTotalHeight += getCurrHeight( HF_RIGHT ); 838 839 return ::std::max( maPortions[ HF_LEFT ].mfTotalHeight, 840 ::std::max( maPortions[ HF_CENTER ].mfTotalHeight, maPortions[ HF_RIGHT ].mfTotalHeight ) ); 841 } 842 843 // private -------------------------------------------------------------------- 844 845 double HeaderFooterParser::getCurrHeight( HFPortionId ePortion ) const 846 { 847 double fMaxHt = maPortions[ ePortion ].mfCurrHeight; 848 return (fMaxHt == 0.0) ? maFontModel.mfHeight : fMaxHt; 849 } 850 851 double HeaderFooterParser::getCurrHeight() const 852 { 853 return getCurrHeight( meCurrPortion ); 854 } 855 856 void HeaderFooterParser::updateCurrHeight( HFPortionId ePortion ) 857 { 858 double& rfMaxHt = maPortions[ ePortion ].mfCurrHeight; 859 rfMaxHt = ::std::max( rfMaxHt, maFontModel.mfHeight ); 860 } 861 862 void HeaderFooterParser::updateCurrHeight() 863 { 864 updateCurrHeight( meCurrPortion ); 865 } 866 867 void HeaderFooterParser::setAttributes() 868 { 869 Reference< XTextRange > xRange( getStartPos(), UNO_QUERY ); 870 getEndPos()->gotoRange( xRange, sal_False ); 871 getEndPos()->gotoEnd( sal_True ); 872 if( !getEndPos()->isCollapsed() ) 873 { 874 Font aFont( *this, maFontModel ); 875 aFont.finalizeImport(); 876 PropertySet aPropSet( getEndPos() ); 877 aFont.writeToPropertySet( aPropSet, FONT_PROPTYPE_TEXT ); 878 getStartPos()->gotoEnd( sal_False ); 879 getEndPos()->gotoEnd( sal_False ); 880 } 881 } 882 883 void HeaderFooterParser::appendText() 884 { 885 if( maBuffer.getLength() > 0 ) 886 { 887 getEndPos()->gotoEnd( sal_False ); 888 getEndPos()->setString( maBuffer.makeStringAndClear() ); 889 updateCurrHeight(); 890 } 891 } 892 893 void HeaderFooterParser::appendLineBreak() 894 { 895 getEndPos()->gotoEnd( sal_False ); 896 getEndPos()->setString( OUString( sal_Unicode( '\n' ) ) ); 897 getPortion().mfTotalHeight += getCurrHeight(); 898 getPortion().mfCurrHeight = 0; 899 } 900 901 Reference< XTextContent > HeaderFooterParser::createField( const OUString& rServiceName ) const 902 { 903 Reference< XTextContent > xContent; 904 try 905 { 906 xContent.set( getBaseFilter().getModelFactory()->createInstance( rServiceName ), UNO_QUERY_THROW ); 907 } 908 catch( Exception& ) 909 { 910 OSL_ENSURE( false, 911 OStringBuffer( "HeaderFooterParser::createField - error while creating text field \"" ). 912 append( OUStringToOString( rServiceName, RTL_TEXTENCODING_ASCII_US ) ). 913 append( '"' ).getStr() ); 914 } 915 return xContent; 916 } 917 918 void HeaderFooterParser::appendField( const Reference< XTextContent >& rxContent ) 919 { 920 getEndPos()->gotoEnd( sal_False ); 921 try 922 { 923 Reference< XTextRange > xRange( getEndPos(), UNO_QUERY_THROW ); 924 getPortion().mxText->insertTextContent( xRange, rxContent, sal_False ); 925 updateCurrHeight(); 926 } 927 catch( Exception& ) 928 { 929 } 930 } 931 932 void HeaderFooterParser::convertFontName( const OUString& rName ) 933 { 934 if( rName.getLength() > 0 ) 935 { 936 // single dash is document default font 937 if( (rName.getLength() == 1) && (rName[ 0 ] == '-') ) 938 maFontModel.maName = getStyles().getDefaultFontModel().maName; 939 else 940 maFontModel.maName = rName; 941 } 942 } 943 944 void HeaderFooterParser::convertFontStyle( const OUString& rStyle ) 945 { 946 maFontModel.mbBold = maFontModel.mbItalic = false; 947 sal_Int32 nPos = 0; 948 sal_Int32 nLen = rStyle.getLength(); 949 while( (0 <= nPos) && (nPos < nLen) ) 950 { 951 OString aToken = OUStringToOString( rStyle.getToken( 0, ' ', nPos ), RTL_TEXTENCODING_UTF8 ).toAsciiLowerCase(); 952 if( aToken.getLength() > 0 ) 953 { 954 if( maBoldNames.count( aToken ) > 0 ) 955 maFontModel.mbBold = true; 956 else if( maItalicNames.count( aToken ) > 0 ) 957 maFontModel.mbItalic = true; 958 } 959 } 960 } 961 962 void HeaderFooterParser::convertFontColor( const OUString& rColor ) 963 { 964 OSL_ENSURE( rColor.getLength() == 6, "HeaderFooterParser::convertFontColor - invalid font color code" ); 965 if( (rColor[ 2 ] == '+') || (rColor[ 2 ] == '-') ) 966 // theme color: TTSNNN (TT = decimal theme index, S = +/-, NNN = decimal tint/shade in percent) 967 maFontModel.maColor.setTheme( 968 rColor.copy( 0, 2 ).toInt32(), 969 static_cast< double >( rColor.copy( 2 ).toInt32() ) / 100.0 ); 970 else 971 // RGB color: RRGGBB 972 maFontModel.maColor.setRgb( rColor.toInt32( 16 ) ); 973 } 974 975 void HeaderFooterParser::finalizePortion() 976 { 977 appendText(); 978 setAttributes(); 979 } 980 981 void HeaderFooterParser::setNewPortion( HFPortionId ePortion ) 982 { 983 if( ePortion != meCurrPortion ) 984 { 985 finalizePortion(); 986 meCurrPortion = ePortion; 987 maFontModel = getStyles().getDefaultFontModel(); 988 } 989 } 990 991 // ============================================================================ 992 993 namespace { 994 995 /** Paper size in 1/100 millimeters. */ 996 struct ApiPaperSize 997 { 998 sal_Int32 mnWidth; 999 sal_Int32 mnHeight; 1000 }; 1001 1002 #define IN2MM100( v ) static_cast< sal_Int32 >( (v) * 2540.0 + 0.5 ) 1003 #define MM2MM100( v ) static_cast< sal_Int32 >( (v) * 100.0 + 0.5 ) 1004 1005 static const ApiPaperSize spPaperSizeTable[] = 1006 { 1007 { 0, 0 }, // 0 - (undefined) 1008 { IN2MM100( 8.5 ), IN2MM100( 11 ) }, // 1 - Letter paper 1009 { IN2MM100( 8.5 ), IN2MM100( 11 ) }, // 2 - Letter small paper 1010 { IN2MM100( 11 ), IN2MM100( 17 ) }, // 3 - Tabloid paper 1011 { IN2MM100( 17 ), IN2MM100( 11 ) }, // 4 - Ledger paper 1012 { IN2MM100( 8.5 ), IN2MM100( 14 ) }, // 5 - Legal paper 1013 { IN2MM100( 5.5 ), IN2MM100( 8.5 ) }, // 6 - Statement paper 1014 { IN2MM100( 7.25 ), IN2MM100( 10.5 ) }, // 7 - Executive paper 1015 { MM2MM100( 297 ), MM2MM100( 420 ) }, // 8 - A3 paper 1016 { MM2MM100( 210 ), MM2MM100( 297 ) }, // 9 - A4 paper 1017 { MM2MM100( 210 ), MM2MM100( 297 ) }, // 10 - A4 small paper 1018 { MM2MM100( 148 ), MM2MM100( 210 ) }, // 11 - A5 paper 1019 { MM2MM100( 250 ), MM2MM100( 353 ) }, // 12 - B4 paper 1020 { MM2MM100( 176 ), MM2MM100( 250 ) }, // 13 - B5 paper 1021 { IN2MM100( 8.5 ), IN2MM100( 13 ) }, // 14 - Folio paper 1022 { MM2MM100( 215 ), MM2MM100( 275 ) }, // 15 - Quarto paper 1023 { IN2MM100( 10 ), IN2MM100( 14 ) }, // 16 - Standard paper 1024 { IN2MM100( 11 ), IN2MM100( 17 ) }, // 17 - Standard paper 1025 { IN2MM100( 8.5 ), IN2MM100( 11 ) }, // 18 - Note paper 1026 { IN2MM100( 3.875 ), IN2MM100( 8.875 ) }, // 19 - #9 envelope 1027 { IN2MM100( 4.125 ), IN2MM100( 9.5 ) }, // 20 - #10 envelope 1028 { IN2MM100( 4.5 ), IN2MM100( 10.375 ) }, // 21 - #11 envelope 1029 { IN2MM100( 4.75 ), IN2MM100( 11 ) }, // 22 - #12 envelope 1030 { IN2MM100( 5 ), IN2MM100( 11.5 ) }, // 23 - #14 envelope 1031 { IN2MM100( 17 ), IN2MM100( 22 ) }, // 24 - C paper 1032 { IN2MM100( 22 ), IN2MM100( 34 ) }, // 25 - D paper 1033 { IN2MM100( 34 ), IN2MM100( 44 ) }, // 26 - E paper 1034 { MM2MM100( 110 ), MM2MM100( 220 ) }, // 27 - DL envelope 1035 { MM2MM100( 162 ), MM2MM100( 229 ) }, // 28 - C5 envelope 1036 { MM2MM100( 324 ), MM2MM100( 458 ) }, // 29 - C3 envelope 1037 { MM2MM100( 229 ), MM2MM100( 324 ) }, // 30 - C4 envelope 1038 { MM2MM100( 114 ), MM2MM100( 162 ) }, // 31 - C6 envelope 1039 { MM2MM100( 114 ), MM2MM100( 229 ) }, // 32 - C65 envelope 1040 { MM2MM100( 250 ), MM2MM100( 353 ) }, // 33 - B4 envelope 1041 { MM2MM100( 176 ), MM2MM100( 250 ) }, // 34 - B5 envelope 1042 { MM2MM100( 176 ), MM2MM100( 125 ) }, // 35 - B6 envelope 1043 { MM2MM100( 110 ), MM2MM100( 230 ) }, // 36 - Italy envelope 1044 { IN2MM100( 3.875 ), IN2MM100( 7.5 ) }, // 37 - Monarch envelope 1045 { IN2MM100( 3.625 ), IN2MM100( 6.5 ) }, // 38 - 6 3/4 envelope 1046 { IN2MM100( 14.875 ), IN2MM100( 11 ) }, // 39 - US standard fanfold 1047 { IN2MM100( 8.5 ), IN2MM100( 12 ) }, // 40 - German standard fanfold 1048 { IN2MM100( 8.5 ), IN2MM100( 13 ) }, // 41 - German legal fanfold 1049 { MM2MM100( 250 ), MM2MM100( 353 ) }, // 42 - ISO B4 1050 { MM2MM100( 200 ), MM2MM100( 148 ) }, // 43 - Japanese double postcard 1051 { IN2MM100( 9 ), IN2MM100( 11 ) }, // 44 - Standard paper 1052 { IN2MM100( 10 ), IN2MM100( 11 ) }, // 45 - Standard paper 1053 { IN2MM100( 15 ), IN2MM100( 11 ) }, // 46 - Standard paper 1054 { MM2MM100( 220 ), MM2MM100( 220 ) }, // 47 - Invite envelope 1055 { 0, 0 }, // 48 - (undefined) 1056 { 0, 0 }, // 49 - (undefined) 1057 { IN2MM100( 9.275 ), IN2MM100( 12 ) }, // 50 - Letter extra paper 1058 { IN2MM100( 9.275 ), IN2MM100( 15 ) }, // 51 - Legal extra paper 1059 { IN2MM100( 11.69 ), IN2MM100( 18 ) }, // 52 - Tabloid extra paper 1060 { MM2MM100( 236 ), MM2MM100( 322 ) }, // 53 - A4 extra paper 1061 { IN2MM100( 8.275 ), IN2MM100( 11 ) }, // 54 - Letter transverse paper 1062 { MM2MM100( 210 ), MM2MM100( 297 ) }, // 55 - A4 transverse paper 1063 { IN2MM100( 9.275 ), IN2MM100( 12 ) }, // 56 - Letter extra transverse paper 1064 { MM2MM100( 227 ), MM2MM100( 356 ) }, // 57 - SuperA/SuperA/A4 paper 1065 { MM2MM100( 305 ), MM2MM100( 487 ) }, // 58 - SuperB/SuperB/A3 paper 1066 { IN2MM100( 8.5 ), IN2MM100( 12.69 ) }, // 59 - Letter plus paper 1067 { MM2MM100( 210 ), MM2MM100( 330 ) }, // 60 - A4 plus paper 1068 { MM2MM100( 148 ), MM2MM100( 210 ) }, // 61 - A5 transverse paper 1069 { MM2MM100( 182 ), MM2MM100( 257 ) }, // 62 - JIS B5 transverse paper 1070 { MM2MM100( 322 ), MM2MM100( 445 ) }, // 63 - A3 extra paper 1071 { MM2MM100( 174 ), MM2MM100( 235 ) }, // 64 - A5 extra paper 1072 { MM2MM100( 201 ), MM2MM100( 276 ) }, // 65 - ISO B5 extra paper 1073 { MM2MM100( 420 ), MM2MM100( 594 ) }, // 66 - A2 paper 1074 { MM2MM100( 297 ), MM2MM100( 420 ) }, // 67 - A3 transverse paper 1075 { MM2MM100( 322 ), MM2MM100( 445 ) } // 68 - A3 extra transverse paper 1076 }; 1077 1078 } // namespace 1079 1080 // ---------------------------------------------------------------------------- 1081 1082 PageSettingsConverter::HFHelperData::HFHelperData( sal_Int32 nLeftPropId, sal_Int32 nRightPropId ) : 1083 mnLeftPropId( nLeftPropId ), 1084 mnRightPropId( nRightPropId ), 1085 mnHeight( 0 ), 1086 mnBodyDist( 0 ), 1087 mbHasContent( false ), 1088 mbShareOddEven( false ), 1089 mbDynamicHeight( false ) 1090 { 1091 } 1092 1093 // ---------------------------------------------------------------------------- 1094 1095 PageSettingsConverter::PageSettingsConverter( const WorkbookHelper& rHelper ) : 1096 WorkbookHelper( rHelper ), 1097 mxHFParser( new HeaderFooterParser( rHelper ) ), 1098 maHeaderData( PROP_LeftPageHeaderContent, PROP_RightPageHeaderContent ), 1099 maFooterData( PROP_LeftPageFooterContent, PROP_RightPageFooterContent ) 1100 { 1101 } 1102 1103 PageSettingsConverter::~PageSettingsConverter() 1104 { 1105 } 1106 1107 void PageSettingsConverter::writePageSettingsProperties( 1108 PropertySet& rPropSet, const PageSettingsModel& rModel, WorksheetType eSheetType ) 1109 { 1110 // special handling for chart sheets 1111 bool bChartSheet = eSheetType == SHEETTYPE_CHARTSHEET; 1112 1113 // printout scaling 1114 if( bChartSheet ) 1115 { 1116 // always fit chart sheet to 1 page 1117 rPropSet.setProperty< sal_Int16 >( PROP_ScaleToPages, 1 ); 1118 } 1119 else if( rModel.mbFitToPages ) 1120 { 1121 // fit to number of pages 1122 rPropSet.setProperty( PROP_ScaleToPagesX, getLimitedValue< sal_Int16, sal_Int32 >( rModel.mnFitToWidth, 0, 1000 ) ); 1123 rPropSet.setProperty( PROP_ScaleToPagesY, getLimitedValue< sal_Int16, sal_Int32 >( rModel.mnFitToHeight, 0, 1000 ) ); 1124 } 1125 else 1126 { 1127 // scale may be 0 which indicates uninitialized 1128 sal_Int16 nScale = (rModel.mbValidSettings && (rModel.mnScale > 0)) ? getLimitedValue< sal_Int16, sal_Int32 >( rModel.mnScale, 10, 400 ) : 100; 1129 rPropSet.setProperty( PROP_PageScale, nScale ); 1130 } 1131 1132 // paper orientation 1133 bool bLandscape = rModel.mnOrientation == XML_landscape; 1134 // default orientation for current sheet type (chart sheets default to landscape) 1135 if( !rModel.mbValidSettings || (rModel.mnOrientation == XML_default) ) 1136 bLandscape = bChartSheet; 1137 1138 // paper size 1139 if( rModel.mbValidSettings && (0 < rModel.mnPaperSize) && (rModel.mnPaperSize < static_cast< sal_Int32 >( STATIC_ARRAY_SIZE( spPaperSizeTable ) )) ) 1140 { 1141 const ApiPaperSize& rPaperSize = spPaperSizeTable[ rModel.mnPaperSize ]; 1142 Size aSize( rPaperSize.mnWidth, rPaperSize.mnHeight ); 1143 if( bLandscape ) 1144 ::std::swap( aSize.Width, aSize.Height ); 1145 rPropSet.setProperty( PROP_Size, aSize ); 1146 } 1147 1148 // header/footer 1149 convertHeaderFooterData( rPropSet, maHeaderData, rModel.maOddHeader, rModel.maEvenHeader, rModel.mbUseEvenHF, rModel.mfTopMargin, rModel.mfHeaderMargin ); 1150 convertHeaderFooterData( rPropSet, maFooterData, rModel.maOddFooter, rModel.maEvenFooter, rModel.mbUseEvenHF, rModel.mfBottomMargin, rModel.mfFooterMargin ); 1151 1152 // write all properties to property set 1153 const UnitConverter& rUnitConv = getUnitConverter(); 1154 PropertyMap aPropMap; 1155 aPropMap[ PROP_IsLandscape ] <<= bLandscape; 1156 aPropMap[ PROP_FirstPageNumber ] <<= getLimitedValue< sal_Int16, sal_Int32 >( rModel.mbUseFirstPage ? rModel.mnFirstPage : 0, 0, 9999 ); 1157 aPropMap[ PROP_PrintDownFirst ] <<= (rModel.mnPageOrder == XML_downThenOver); 1158 aPropMap[ PROP_PrintAnnotations ] <<= (rModel.mnCellComments == XML_asDisplayed); 1159 aPropMap[ PROP_CenterHorizontally ] <<= rModel.mbHorCenter; 1160 aPropMap[ PROP_CenterVertically ] <<= rModel.mbVerCenter; 1161 aPropMap[ PROP_PrintGrid ] <<= (!bChartSheet && rModel.mbPrintGrid); // no gridlines in chart sheets 1162 aPropMap[ PROP_PrintHeaders ] <<= (!bChartSheet && rModel.mbPrintHeadings); // no column/row headings in chart sheets 1163 aPropMap[ PROP_LeftMargin ] <<= rUnitConv.scaleToMm100( rModel.mfLeftMargin, UNIT_INCH ); 1164 aPropMap[ PROP_RightMargin ] <<= rUnitConv.scaleToMm100( rModel.mfRightMargin, UNIT_INCH ); 1165 // #i23296# In Calc, "TopMargin" property is distance to top of header if enabled 1166 aPropMap[ PROP_TopMargin ] <<= rUnitConv.scaleToMm100( maHeaderData.mbHasContent ? rModel.mfHeaderMargin : rModel.mfTopMargin, UNIT_INCH ); 1167 // #i23296# In Calc, "BottomMargin" property is distance to bottom of footer if enabled 1168 aPropMap[ PROP_BottomMargin ] <<= rUnitConv.scaleToMm100( maFooterData.mbHasContent ? rModel.mfFooterMargin : rModel.mfBottomMargin, UNIT_INCH ); 1169 aPropMap[ PROP_HeaderIsOn ] <<= maHeaderData.mbHasContent; 1170 aPropMap[ PROP_HeaderIsShared ] <<= maHeaderData.mbShareOddEven; 1171 aPropMap[ PROP_HeaderIsDynamicHeight ] <<= maHeaderData.mbDynamicHeight; 1172 aPropMap[ PROP_HeaderHeight ] <<= maHeaderData.mnHeight; 1173 aPropMap[ PROP_HeaderBodyDistance ] <<= maHeaderData.mnBodyDist; 1174 aPropMap[ PROP_FooterIsOn ] <<= maFooterData.mbHasContent; 1175 aPropMap[ PROP_FooterIsShared ] <<= maFooterData.mbShareOddEven; 1176 aPropMap[ PROP_FooterIsDynamicHeight ] <<= maFooterData.mbDynamicHeight; 1177 aPropMap[ PROP_FooterHeight ] <<= maFooterData.mnHeight; 1178 aPropMap[ PROP_FooterBodyDistance ] <<= maFooterData.mnBodyDist; 1179 // background image 1180 if( rModel.maGraphicUrl.getLength() > 0 ) 1181 { 1182 aPropMap[ PROP_BackGraphicURL ] <<= rModel.maGraphicUrl; 1183 aPropMap[ PROP_BackGraphicLocation ] <<= ::com::sun::star::style::GraphicLocation_TILED; 1184 } 1185 1186 rPropSet.setProperties( aPropMap ); 1187 } 1188 1189 void PageSettingsConverter::convertHeaderFooterData( 1190 PropertySet& rPropSet, HFHelperData& orHFData, 1191 const OUString rOddContent, const OUString rEvenContent, bool bUseEvenContent, 1192 double fPageMargin, double fContentMargin ) 1193 { 1194 bool bHasOddContent = rOddContent.getLength() > 0; 1195 bool bHasEvenContent = bUseEvenContent && (rEvenContent.getLength() > 0); 1196 1197 sal_Int32 nOddHeight = bHasOddContent ? writeHeaderFooter( rPropSet, orHFData.mnRightPropId, rOddContent ) : 0; 1198 sal_Int32 nEvenHeight = bHasEvenContent ? writeHeaderFooter( rPropSet, orHFData.mnLeftPropId, rEvenContent ) : 0; 1199 1200 orHFData.mnHeight = 750; 1201 orHFData.mnBodyDist = 250; 1202 orHFData.mbHasContent = bHasOddContent || bHasEvenContent; 1203 orHFData.mbShareOddEven = !bUseEvenContent; 1204 orHFData.mbDynamicHeight = true; 1205 1206 if( orHFData.mbHasContent ) 1207 { 1208 // use maximum height of odd/even header/footer 1209 orHFData.mnHeight = ::std::max( nOddHeight, nEvenHeight ); 1210 /* Calc contains distance between bottom of header and top of page 1211 body in "HeaderBodyDistance" property, and distance between bottom 1212 of page body and top of footer in "FooterBodyDistance" property */ 1213 orHFData.mnBodyDist = getUnitConverter().scaleToMm100( fPageMargin - fContentMargin, UNIT_INCH ) - orHFData.mnHeight; 1214 /* #i23296# Distance less than 0 means, header or footer overlays page 1215 body. As this is not possible in Calc, set fixed header or footer 1216 height (crop header/footer) to get correct top position of page body. */ 1217 orHFData.mbDynamicHeight = orHFData.mnBodyDist >= 0; 1218 /* "HeaderHeight" property is in fact distance from top of header to 1219 top of page body (including "HeaderBodyDistance"). 1220 "FooterHeight" property is in fact distance from bottom of page 1221 body to bottom of footer (including "FooterBodyDistance"). */ 1222 orHFData.mnHeight += orHFData.mnBodyDist; 1223 // negative body distance not allowed 1224 orHFData.mnBodyDist = ::std::max< sal_Int32 >( orHFData.mnBodyDist, 0 ); 1225 } 1226 } 1227 1228 sal_Int32 PageSettingsConverter::writeHeaderFooter( 1229 PropertySet& rPropSet, sal_Int32 nPropId, const OUString& rContent ) 1230 { 1231 OSL_ENSURE( rContent.getLength() > 0, "PageSettingsConverter::writeHeaderFooter - empty h/f string found" ); 1232 sal_Int32 nHeight = 0; 1233 if( rContent.getLength() > 0 ) 1234 { 1235 Reference< XHeaderFooterContent > xHFContent( rPropSet.getAnyProperty( nPropId ), UNO_QUERY ); 1236 if( xHFContent.is() ) 1237 { 1238 double fTotalHeight = mxHFParser->parse( xHFContent, rContent ); 1239 rPropSet.setProperty( nPropId, xHFContent ); 1240 nHeight = getUnitConverter().scaleToMm100( fTotalHeight, UNIT_POINT ); 1241 } 1242 } 1243 return nHeight; 1244 } 1245 1246 // ============================================================================ 1247 1248 } // namespace xls 1249 } // namespace oox 1250