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