From 3381981e76873304b171f7df900561dac681d2af Mon Sep 17 00:00:00 2001 From: RĂ¼diger Timm Date: Thu, 17 Jan 2008 07:06:10 +0000 Subject: #i10000# Bring module to HEAD. --- oox/source/core/binarycodec.cxx | 388 ++ oox/source/core/binaryfilterbase.cxx | 74 + oox/source/core/facreg.cxx | 157 + oox/source/core/filterbase.cxx | 247 + oox/source/core/filterdetect.cxx | 404 ++ oox/source/core/fragmenthandler.cxx | 149 + oox/source/core/makefile.mk | 69 + oox/source/core/recordparser.cxx | 362 ++ oox/source/core/relations.cxx | 139 + oox/source/core/relationshandler.cxx | 106 + oox/source/core/skipcontext.cxx | 50 + oox/source/core/xmlfilterbase.cxx | 300 ++ oox/source/drawingml/clrscheme.cxx | 104 + oox/source/drawingml/clrschemecontext.cxx | 137 + oox/source/drawingml/color.cxx | 64 + oox/source/drawingml/colorchoicecontext.cxx | 146 + oox/source/drawingml/connectorshapecontext.cxx | 89 + oox/source/drawingml/customshapegeometry.cxx | 1071 ++++ oox/source/drawingml/customshapeproperties.cxx | 156 + oox/source/drawingml/diagram/datamodelcontext.cxx | 336 ++ oox/source/drawingml/diagram/diagram.cxx | 130 + .../drawingml/diagram/diagramdefinitioncontext.cxx | 124 + .../drawingml/diagram/diagramdefinitioncontext.hxx | 60 + .../drawingml/diagram/diagramfragmenthandler.cxx | 233 + .../drawingml/diagram/diagramlayoutatoms.cxx | 149 + oox/source/drawingml/diagram/layoutnodecontext.cxx | 368 ++ oox/source/drawingml/diagram/layoutnodecontext.hxx | 61 + oox/source/drawingml/diagram/makefile.mk | 61 + oox/source/drawingml/drawingmltypes.cxx | 433 ++ oox/source/drawingml/embeddedwavaudiofile.cxx | 64 + oox/source/drawingml/fillproperties.cxx | 117 + .../drawingml/fillpropertiesgroupcontext.cxx | 457 ++ oox/source/drawingml/graphicshapecontext.cxx | 335 ++ oox/source/drawingml/hyperlinkcontext.cxx | 121 + oox/source/drawingml/hyperlinkcontext.hxx | 67 + oox/source/drawingml/lineproperties.cxx | 349 ++ oox/source/drawingml/linepropertiescontext.cxx | 157 + oox/source/drawingml/makefile.mk | 96 + oox/source/drawingml/objectdefaultcontext.cxx | 81 + oox/source/drawingml/shape.cxx | 489 ++ oox/source/drawingml/shapecontext.cxx | 130 + oox/source/drawingml/shapegroupcontext.cxx | 125 + oox/source/drawingml/shapepropertiescontext.cxx | 140 + oox/source/drawingml/shapestylecontext.cxx | 148 + oox/source/drawingml/spdefcontext.cxx | 83 + oox/source/drawingml/textbody.cxx | 86 + oox/source/drawingml/textbodycontext.cxx | 224 + oox/source/drawingml/textbodypropertiescontext.cxx | 161 + oox/source/drawingml/textcharacterproperties.cxx | 135 + .../drawingml/textcharacterpropertiescontext.cxx | 282 + oox/source/drawingml/textfield.cxx | 196 + oox/source/drawingml/textfieldcontext.cxx | 107 + oox/source/drawingml/textliststyle.cxx | 78 + oox/source/drawingml/textliststylecontext.cxx | 120 + oox/source/drawingml/textparagraph.cxx | 127 + oox/source/drawingml/textparagraphproperties.cxx | 419 ++ .../drawingml/textparagraphpropertiescontext.cxx | 306 ++ oox/source/drawingml/textrun.cxx | 120 + oox/source/drawingml/textspacingcontext.cxx | 87 + oox/source/drawingml/textspacingcontext.hxx | 69 + oox/source/drawingml/texttabstoplistcontext.cxx | 106 + oox/source/drawingml/texttabstoplistcontext.hxx | 69 + oox/source/drawingml/theme.cxx | 55 + oox/source/drawingml/themeelementscontext.cxx | 234 + oox/source/drawingml/themefragmenthandler.cxx | 108 + oox/source/dump/biffdumper.cxx | 3195 +++++++++++ oox/source/dump/biffdumperconfig.dat | 1782 +++++++ oox/source/dump/dffdumper.cxx | 212 + oox/source/dump/dumperbase.cxx | 2775 ++++++++++ oox/source/dump/dumperconfig.dat | 436 ++ oox/source/dump/makefile.mk | 60 + oox/source/dump/olestoragedumper.cxx | 449 ++ oox/source/dump/xlsbdumper.cxx | 1920 +++++++ oox/source/dump/xlsbdumperconfig.dat | 655 +++ oox/source/helper/attributelist.cxx | 111 + oox/source/helper/binaryinputstream.cxx | 113 + oox/source/helper/binaryoutputstream.cxx | 121 + oox/source/helper/binarystreambase.cxx | 91 + oox/source/helper/containerhelper.cxx | 173 + oox/source/helper/makefile.mk | 68 + oox/source/helper/olestorage.cxx | 186 + oox/source/helper/progressbar.cxx | 193 + oox/source/helper/propertymap.cxx | 286 + oox/source/helper/propertysequence.cxx | 164 + oox/source/helper/propertyset.cxx | 157 + oox/source/helper/recordinputstream.cxx | 104 + oox/source/helper/storagebase.cxx | 201 + oox/source/helper/zipstorage.cxx | 174 + oox/source/ppt/animationspersist.cxx | 210 + oox/source/ppt/animationtypes.cxx | 82 + oox/source/ppt/animationtypes.hxx | 55 + oox/source/ppt/animvariantcontext.cxx | 132 + oox/source/ppt/animvariantcontext.hxx | 69 + oox/source/ppt/backgroundproperties.cxx | 79 + oox/source/ppt/buildlistcontext.cxx | 121 + oox/source/ppt/buildlistcontext.hxx | 72 + oox/source/ppt/commonbehaviorcontext.cxx | 188 + oox/source/ppt/commonbehaviorcontext.hxx | 90 + oox/source/ppt/commontimenodecontext.cxx | 717 +++ oox/source/ppt/commontimenodecontext.hxx | 70 + oox/source/ppt/conditioncontext.cxx | 222 + oox/source/ppt/conditioncontext.hxx | 92 + oox/source/ppt/customshowlistcontext.cxx | 129 + oox/source/ppt/customshowlistcontext.hxx | 71 + oox/source/ppt/layoutfragmenthandler.cxx | 92 + oox/source/ppt/makefile.mk | 83 + oox/source/ppt/pptfilterhelpers.cxx | 148 + oox/source/ppt/pptfilterhelpers.hxx | 112 + oox/source/ppt/pptimport.cxx | 135 + oox/source/ppt/pptshape.cxx | 179 + oox/source/ppt/pptshapecontext.cxx | 209 + oox/source/ppt/pptshapegroupcontext.cxx | 123 + oox/source/ppt/pptshapepropertiescontext.cxx | 94 + oox/source/ppt/presentationfragmenthandler.cxx | 301 ++ oox/source/ppt/slidefragmenthandler.cxx | 193 + oox/source/ppt/slidemastertextstylescontext.cxx | 94 + oox/source/ppt/slidepersist.cxx | 320 ++ oox/source/ppt/slidetimingcontext.cxx | 113 + oox/source/ppt/slidetransition.cxx | 393 ++ oox/source/ppt/slidetransitioncontext.cxx | 213 + oox/source/ppt/soundactioncontext.cxx | 144 + oox/source/ppt/timeanimvaluecontext.cxx | 113 + oox/source/ppt/timeanimvaluecontext.hxx | 72 + oox/source/ppt/timenode.cxx | 635 +++ oox/source/ppt/timenodelistcontext.cxx | 1181 +++++ oox/source/ppt/timetargetelementcontext.cxx | 185 + oox/source/ppt/timetargetelementcontext.hxx | 65 + oox/source/shape/FastTokenHandlerService.cxx | 119 + oox/source/shape/FastTokenHandlerService.hxx | 89 + oox/source/shape/ShapeContextHandler.cxx | 245 + oox/source/shape/ShapeContextHandler.hxx | 160 + oox/source/shape/ShapeFilterBase.cxx | 69 + oox/source/shape/ShapeFilterBase.hxx | 80 + oox/source/shape/makefile.mk | 58 + oox/source/token/gentoken.pl | 55 + oox/source/token/makefile.mk | 66 + oox/source/token/parsexsd.pl | 48 + oox/source/token/tokenmap.cxx | 105 + oox/source/token/tokens.txt | 5569 ++++++++++++++++++++ oox/source/vml/makefile.mk | 58 + oox/source/vml/vmldrawing.cxx | 101 + oox/source/vml/vmldrawingfragmenthandler.cxx | 226 + oox/source/vml/vmlshape.cxx | 72 + oox/source/xls/addressconverter.cxx | 772 +++ oox/source/xls/autofiltercontext.cxx | 770 +++ oox/source/xls/biffcodec.cxx | 211 + oox/source/xls/biffdetector.cxx | 241 + oox/source/xls/bifffragmenthandler.cxx | 169 + oox/source/xls/biffhelper.cxx | 296 ++ oox/source/xls/biffinputstream.cxx | 646 +++ oox/source/xls/biffoutputstream.cxx | 191 + oox/source/xls/condformatbuffer.cxx | 782 +++ oox/source/xls/condformatcontext.cxx | 114 + oox/source/xls/connectionsfragment.cxx | 127 + oox/source/xls/defnamesbuffer.cxx | 674 +++ oox/source/xls/excelfilter.cxx | 284 + oox/source/xls/externallinkbuffer.cxx | 857 +++ oox/source/xls/externallinkfragment.cxx | 392 ++ oox/source/xls/formulabase.cxx | 1459 +++++ oox/source/xls/formulaparser.cxx | 2595 +++++++++ oox/source/xls/headerfooterparser.cxx | 643 +++ oox/source/xls/makefile.mk | 106 + oox/source/xls/numberformatsbuffer.cxx | 2124 ++++++++ oox/source/xls/pagesettings.cxx | 641 +++ oox/source/xls/pivotcachefragment.cxx | 160 + oox/source/xls/pivottablebuffer.cxx | 275 + oox/source/xls/pivottablefragment.cxx | 194 + oox/source/xls/querytablefragment.cxx | 82 + oox/source/xls/richstring.cxx | 605 +++ oox/source/xls/richstringcontext.cxx | 118 + oox/source/xls/sharedformulabuffer.cxx | 220 + oox/source/xls/sharedstringsbuffer.cxx | 91 + oox/source/xls/sharedstringsfragment.cxx | 110 + oox/source/xls/sheetcellrangemap.cxx | 172 + oox/source/xls/sheetdatacontext.cxx | 1160 ++++ oox/source/xls/stylesbuffer.cxx | 3214 +++++++++++ oox/source/xls/stylesfragment.cxx | 316 ++ oox/source/xls/stylespropertyhelper.cxx | 386 ++ oox/source/xls/tablebuffer.cxx | 172 + oox/source/xls/tablefragment.cxx | 92 + oox/source/xls/themebuffer.cxx | 170 + oox/source/xls/unitconverter.cxx | 209 + oox/source/xls/validationpropertyhelper.cxx | 174 + oox/source/xls/viewsettings.cxx | 789 +++ oox/source/xls/webquerybuffer.cxx | 207 + oox/source/xls/workbookfragment.cxx | 756 +++ oox/source/xls/workbookhelper.cxx | 876 +++ oox/source/xls/workbooksettings.cxx | 297 ++ oox/source/xls/worksheetbuffer.cxx | 333 ++ oox/source/xls/worksheetfragment.cxx | 1068 ++++ oox/source/xls/worksheethelper.cxx | 1652 ++++++ oox/source/xls/worksheetsettings.cxx | 270 + 192 files changed, 68819 insertions(+) create mode 100644 oox/source/core/binarycodec.cxx create mode 100644 oox/source/core/binaryfilterbase.cxx create mode 100644 oox/source/core/facreg.cxx create mode 100644 oox/source/core/filterbase.cxx create mode 100644 oox/source/core/filterdetect.cxx create mode 100644 oox/source/core/fragmenthandler.cxx create mode 100644 oox/source/core/makefile.mk create mode 100644 oox/source/core/recordparser.cxx create mode 100644 oox/source/core/relations.cxx create mode 100644 oox/source/core/relationshandler.cxx create mode 100644 oox/source/core/skipcontext.cxx create mode 100644 oox/source/core/xmlfilterbase.cxx create mode 100644 oox/source/drawingml/clrscheme.cxx create mode 100644 oox/source/drawingml/clrschemecontext.cxx create mode 100644 oox/source/drawingml/color.cxx create mode 100644 oox/source/drawingml/colorchoicecontext.cxx create mode 100644 oox/source/drawingml/connectorshapecontext.cxx create mode 100644 oox/source/drawingml/customshapegeometry.cxx create mode 100644 oox/source/drawingml/customshapeproperties.cxx create mode 100644 oox/source/drawingml/diagram/datamodelcontext.cxx create mode 100644 oox/source/drawingml/diagram/diagram.cxx create mode 100644 oox/source/drawingml/diagram/diagramdefinitioncontext.cxx create mode 100644 oox/source/drawingml/diagram/diagramdefinitioncontext.hxx create mode 100644 oox/source/drawingml/diagram/diagramfragmenthandler.cxx create mode 100644 oox/source/drawingml/diagram/diagramlayoutatoms.cxx create mode 100644 oox/source/drawingml/diagram/layoutnodecontext.cxx create mode 100644 oox/source/drawingml/diagram/layoutnodecontext.hxx create mode 100644 oox/source/drawingml/diagram/makefile.mk create mode 100644 oox/source/drawingml/drawingmltypes.cxx create mode 100644 oox/source/drawingml/embeddedwavaudiofile.cxx create mode 100644 oox/source/drawingml/fillproperties.cxx create mode 100644 oox/source/drawingml/fillpropertiesgroupcontext.cxx create mode 100644 oox/source/drawingml/graphicshapecontext.cxx create mode 100644 oox/source/drawingml/hyperlinkcontext.cxx create mode 100644 oox/source/drawingml/hyperlinkcontext.hxx create mode 100644 oox/source/drawingml/lineproperties.cxx create mode 100644 oox/source/drawingml/linepropertiescontext.cxx create mode 100644 oox/source/drawingml/makefile.mk create mode 100644 oox/source/drawingml/objectdefaultcontext.cxx create mode 100644 oox/source/drawingml/shape.cxx create mode 100644 oox/source/drawingml/shapecontext.cxx create mode 100644 oox/source/drawingml/shapegroupcontext.cxx create mode 100644 oox/source/drawingml/shapepropertiescontext.cxx create mode 100644 oox/source/drawingml/shapestylecontext.cxx create mode 100644 oox/source/drawingml/spdefcontext.cxx create mode 100644 oox/source/drawingml/textbody.cxx create mode 100644 oox/source/drawingml/textbodycontext.cxx create mode 100644 oox/source/drawingml/textbodypropertiescontext.cxx create mode 100644 oox/source/drawingml/textcharacterproperties.cxx create mode 100644 oox/source/drawingml/textcharacterpropertiescontext.cxx create mode 100644 oox/source/drawingml/textfield.cxx create mode 100644 oox/source/drawingml/textfieldcontext.cxx create mode 100644 oox/source/drawingml/textliststyle.cxx create mode 100644 oox/source/drawingml/textliststylecontext.cxx create mode 100644 oox/source/drawingml/textparagraph.cxx create mode 100644 oox/source/drawingml/textparagraphproperties.cxx create mode 100644 oox/source/drawingml/textparagraphpropertiescontext.cxx create mode 100644 oox/source/drawingml/textrun.cxx create mode 100644 oox/source/drawingml/textspacingcontext.cxx create mode 100644 oox/source/drawingml/textspacingcontext.hxx create mode 100644 oox/source/drawingml/texttabstoplistcontext.cxx create mode 100644 oox/source/drawingml/texttabstoplistcontext.hxx create mode 100644 oox/source/drawingml/theme.cxx create mode 100644 oox/source/drawingml/themeelementscontext.cxx create mode 100644 oox/source/drawingml/themefragmenthandler.cxx create mode 100644 oox/source/dump/biffdumper.cxx create mode 100644 oox/source/dump/biffdumperconfig.dat create mode 100644 oox/source/dump/dffdumper.cxx create mode 100644 oox/source/dump/dumperbase.cxx create mode 100644 oox/source/dump/dumperconfig.dat create mode 100644 oox/source/dump/makefile.mk create mode 100644 oox/source/dump/olestoragedumper.cxx create mode 100644 oox/source/dump/xlsbdumper.cxx create mode 100644 oox/source/dump/xlsbdumperconfig.dat create mode 100644 oox/source/helper/attributelist.cxx create mode 100644 oox/source/helper/binaryinputstream.cxx create mode 100644 oox/source/helper/binaryoutputstream.cxx create mode 100644 oox/source/helper/binarystreambase.cxx create mode 100644 oox/source/helper/containerhelper.cxx create mode 100644 oox/source/helper/makefile.mk create mode 100644 oox/source/helper/olestorage.cxx create mode 100644 oox/source/helper/progressbar.cxx create mode 100644 oox/source/helper/propertymap.cxx create mode 100644 oox/source/helper/propertysequence.cxx create mode 100644 oox/source/helper/propertyset.cxx create mode 100644 oox/source/helper/recordinputstream.cxx create mode 100644 oox/source/helper/storagebase.cxx create mode 100644 oox/source/helper/zipstorage.cxx create mode 100644 oox/source/ppt/animationspersist.cxx create mode 100644 oox/source/ppt/animationtypes.cxx create mode 100644 oox/source/ppt/animationtypes.hxx create mode 100644 oox/source/ppt/animvariantcontext.cxx create mode 100644 oox/source/ppt/animvariantcontext.hxx create mode 100644 oox/source/ppt/backgroundproperties.cxx create mode 100644 oox/source/ppt/buildlistcontext.cxx create mode 100644 oox/source/ppt/buildlistcontext.hxx create mode 100644 oox/source/ppt/commonbehaviorcontext.cxx create mode 100644 oox/source/ppt/commonbehaviorcontext.hxx create mode 100644 oox/source/ppt/commontimenodecontext.cxx create mode 100644 oox/source/ppt/commontimenodecontext.hxx create mode 100644 oox/source/ppt/conditioncontext.cxx create mode 100644 oox/source/ppt/conditioncontext.hxx create mode 100644 oox/source/ppt/customshowlistcontext.cxx create mode 100644 oox/source/ppt/customshowlistcontext.hxx create mode 100644 oox/source/ppt/layoutfragmenthandler.cxx create mode 100644 oox/source/ppt/makefile.mk create mode 100644 oox/source/ppt/pptfilterhelpers.cxx create mode 100644 oox/source/ppt/pptfilterhelpers.hxx create mode 100644 oox/source/ppt/pptimport.cxx create mode 100644 oox/source/ppt/pptshape.cxx create mode 100644 oox/source/ppt/pptshapecontext.cxx create mode 100644 oox/source/ppt/pptshapegroupcontext.cxx create mode 100644 oox/source/ppt/pptshapepropertiescontext.cxx create mode 100644 oox/source/ppt/presentationfragmenthandler.cxx create mode 100644 oox/source/ppt/slidefragmenthandler.cxx create mode 100644 oox/source/ppt/slidemastertextstylescontext.cxx create mode 100644 oox/source/ppt/slidepersist.cxx create mode 100644 oox/source/ppt/slidetimingcontext.cxx create mode 100644 oox/source/ppt/slidetransition.cxx create mode 100644 oox/source/ppt/slidetransitioncontext.cxx create mode 100644 oox/source/ppt/soundactioncontext.cxx create mode 100644 oox/source/ppt/timeanimvaluecontext.cxx create mode 100644 oox/source/ppt/timeanimvaluecontext.hxx create mode 100644 oox/source/ppt/timenode.cxx create mode 100644 oox/source/ppt/timenodelistcontext.cxx create mode 100644 oox/source/ppt/timetargetelementcontext.cxx create mode 100644 oox/source/ppt/timetargetelementcontext.hxx create mode 100644 oox/source/shape/FastTokenHandlerService.cxx create mode 100644 oox/source/shape/FastTokenHandlerService.hxx create mode 100644 oox/source/shape/ShapeContextHandler.cxx create mode 100644 oox/source/shape/ShapeContextHandler.hxx create mode 100644 oox/source/shape/ShapeFilterBase.cxx create mode 100644 oox/source/shape/ShapeFilterBase.hxx create mode 100644 oox/source/shape/makefile.mk create mode 100644 oox/source/token/gentoken.pl create mode 100644 oox/source/token/makefile.mk create mode 100644 oox/source/token/parsexsd.pl create mode 100644 oox/source/token/tokenmap.cxx create mode 100644 oox/source/token/tokens.txt create mode 100644 oox/source/vml/makefile.mk create mode 100644 oox/source/vml/vmldrawing.cxx create mode 100644 oox/source/vml/vmldrawingfragmenthandler.cxx create mode 100644 oox/source/vml/vmlshape.cxx create mode 100644 oox/source/xls/addressconverter.cxx create mode 100644 oox/source/xls/autofiltercontext.cxx create mode 100644 oox/source/xls/biffcodec.cxx create mode 100644 oox/source/xls/biffdetector.cxx create mode 100644 oox/source/xls/bifffragmenthandler.cxx create mode 100644 oox/source/xls/biffhelper.cxx create mode 100644 oox/source/xls/biffinputstream.cxx create mode 100644 oox/source/xls/biffoutputstream.cxx create mode 100644 oox/source/xls/condformatbuffer.cxx create mode 100644 oox/source/xls/condformatcontext.cxx create mode 100644 oox/source/xls/connectionsfragment.cxx create mode 100644 oox/source/xls/defnamesbuffer.cxx create mode 100644 oox/source/xls/excelfilter.cxx create mode 100644 oox/source/xls/externallinkbuffer.cxx create mode 100644 oox/source/xls/externallinkfragment.cxx create mode 100644 oox/source/xls/formulabase.cxx create mode 100644 oox/source/xls/formulaparser.cxx create mode 100644 oox/source/xls/headerfooterparser.cxx create mode 100644 oox/source/xls/makefile.mk create mode 100644 oox/source/xls/numberformatsbuffer.cxx create mode 100644 oox/source/xls/pagesettings.cxx create mode 100644 oox/source/xls/pivotcachefragment.cxx create mode 100644 oox/source/xls/pivottablebuffer.cxx create mode 100644 oox/source/xls/pivottablefragment.cxx create mode 100644 oox/source/xls/querytablefragment.cxx create mode 100644 oox/source/xls/richstring.cxx create mode 100644 oox/source/xls/richstringcontext.cxx create mode 100644 oox/source/xls/sharedformulabuffer.cxx create mode 100644 oox/source/xls/sharedstringsbuffer.cxx create mode 100644 oox/source/xls/sharedstringsfragment.cxx create mode 100644 oox/source/xls/sheetcellrangemap.cxx create mode 100644 oox/source/xls/sheetdatacontext.cxx create mode 100644 oox/source/xls/stylesbuffer.cxx create mode 100644 oox/source/xls/stylesfragment.cxx create mode 100644 oox/source/xls/stylespropertyhelper.cxx create mode 100644 oox/source/xls/tablebuffer.cxx create mode 100644 oox/source/xls/tablefragment.cxx create mode 100644 oox/source/xls/themebuffer.cxx create mode 100644 oox/source/xls/unitconverter.cxx create mode 100644 oox/source/xls/validationpropertyhelper.cxx create mode 100644 oox/source/xls/viewsettings.cxx create mode 100644 oox/source/xls/webquerybuffer.cxx create mode 100644 oox/source/xls/workbookfragment.cxx create mode 100644 oox/source/xls/workbookhelper.cxx create mode 100644 oox/source/xls/workbooksettings.cxx create mode 100644 oox/source/xls/worksheetbuffer.cxx create mode 100644 oox/source/xls/worksheetfragment.cxx create mode 100644 oox/source/xls/worksheethelper.cxx create mode 100644 oox/source/xls/worksheetsettings.cxx (limited to 'oox/source') diff --git a/oox/source/core/binarycodec.cxx b/oox/source/core/binarycodec.cxx new file mode 100644 index 000000000000..746a555f082d --- /dev/null +++ b/oox/source/core/binarycodec.cxx @@ -0,0 +1,388 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: binarycodec.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:50 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/core/binarycodec.hxx" +#include +#include + +namespace oox { +namespace core { + +// ============================================================================ + +namespace { + +/** Rotates rnValue left by nBits bits. */ +template< typename Type > +inline void lclRotateLeft( Type& rnValue, size_t nBits ) +{ + OSL_ENSURE( nBits < sizeof( Type ) * 8, "lclRotateLeft - rotation count overflow" ); + rnValue = static_cast< Type >( (rnValue << nBits) | (rnValue >> (sizeof( Type ) * 8 - nBits)) ); +} + +/** Rotates the lower nWidth bits of rnValue left by nBits bits. */ +template< typename Type > +inline void lclRotateLeft( Type& rnValue, size_t nBits, size_t nWidth ) +{ + OSL_ENSURE( (nBits < nWidth) && (nWidth < sizeof( Type ) * 8), "lclRotateLeft - rotation count overflow" ); + Type nMask = static_cast< Type >( (1UL << nWidth) - 1 ); + rnValue = static_cast< Type >( + ((rnValue << nBits) | ((rnValue & nMask) >> (nWidth - nBits))) & nMask ); +} + +sal_Int32 lclGetLen( const sal_uInt8* pnPassData, sal_Int32 nBufferSize ) +{ + sal_Int32 nLen = 0; + while( (nLen < nBufferSize) && pnPassData[ nLen ] ) ++nLen; + return nLen; +} + +sal_uInt16 lclGetKey( const sal_uInt8* pnPassData, sal_Int32 nBufferSize ) +{ + sal_Int32 nLen = lclGetLen( pnPassData, nBufferSize ); + if( nLen <= 0 ) return 0; + + sal_uInt16 nKey = 0; + sal_uInt16 nKeyBase = 0x8000; + sal_uInt16 nKeyEnd = 0xFFFF; + const sal_uInt8* pnChar = pnPassData + nLen - 1; + for( sal_Int32 nIndex = 0; nIndex < nLen; ++nIndex, --pnChar ) + { + sal_uInt8 cChar = *pnChar & 0x7F; + for( size_t nBit = 0; nBit < 8; ++nBit ) + { + lclRotateLeft( nKeyBase, 1 ); + if( nKeyBase & 1 ) nKeyBase ^= 0x1020; + if( cChar & 1 ) nKey ^= nKeyBase; + cChar >>= 1; + lclRotateLeft( nKeyEnd, 1 ); + if( nKeyEnd & 1 ) nKeyEnd ^= 0x1020; + } + } + return nKey ^ nKeyEnd; +} + +sal_uInt16 lclGetHash( const sal_uInt8* pnPassData, sal_Int32 nBufferSize ) +{ + sal_Int32 nLen = lclGetLen( pnPassData, nBufferSize ); + + sal_uInt16 nHash = static_cast< sal_uInt16 >( nLen ); + if( nLen > 0 ) + nHash ^= 0xCE4B; + + const sal_uInt8* pnChar = pnPassData; + for( sal_Int32 nIndex = 0; nIndex < nLen; ++nIndex, ++pnChar ) + { + sal_uInt16 cChar = *pnChar; + size_t nRot = static_cast< size_t >( (nIndex + 1) % 15 ); + lclRotateLeft( cChar, nRot, 15 ); + nHash ^= cChar; + } + return nHash; +} + +} // namespace + +// ============================================================================ + +BinaryCodec_XOR::BinaryCodec_XOR( CodecType eCodecType ) : + meCodecType( eCodecType ), + mnOffset( 0 ), + mnBaseKey( 0 ), + mnHash( 0 ) +{ + (void)memset( mpnKey, 0, sizeof( mpnKey ) ); +} + +BinaryCodec_XOR::~BinaryCodec_XOR() +{ + (void)memset( mpnKey, 0, sizeof( mpnKey ) ); + mnBaseKey = mnHash = 0; +} + +void BinaryCodec_XOR::initKey( const sal_uInt8 pnPassData[ 16 ] ) +{ + // calculate base key and hash from passed password + mnBaseKey = lclGetKey( pnPassData, 16 ); + mnHash = lclGetHash( pnPassData, 16 ); + + static const sal_uInt8 spnFillChars[] = + { + 0xBB, 0xFF, 0xFF, 0xBA, + 0xFF, 0xFF, 0xB9, 0x80, + 0x00, 0xBE, 0x0F, 0x00, + 0xBF, 0x0F, 0x00 + }; + + (void)memcpy( mpnKey, pnPassData, 16 ); + sal_Int32 nIndex; + sal_Int32 nLen = lclGetLen( pnPassData, 16 ); + const sal_uInt8* pnFillChar = spnFillChars; + for( nIndex = nLen; nIndex < static_cast< sal_Int32 >( sizeof( mpnKey ) ); ++nIndex, ++pnFillChar ) + mpnKey[ nIndex ] = *pnFillChar; + + // rotation of key values is application dependent + size_t nRotateSize = 0; + switch( meCodecType ) + { + case CODEC_WORD: nRotateSize = 7; break; + case CODEC_EXCEL: nRotateSize = 2; break; + // compiler will warn, if new codec type is introduced and not handled here + } + + // use little-endian base key to create key array + sal_uInt8 pnBaseKeyLE[ 2 ]; + pnBaseKeyLE[ 0 ] = static_cast< sal_uInt8 >( mnBaseKey ); + pnBaseKeyLE[ 1 ] = static_cast< sal_uInt8 >( mnBaseKey >> 8 ); + sal_uInt8* pnKeyChar = mpnKey; + for( nIndex = 0; nIndex < static_cast< sal_Int32 >( sizeof( mpnKey ) ); ++nIndex, ++pnKeyChar ) + { + *pnKeyChar ^= pnBaseKeyLE[ nIndex & 1 ]; + lclRotateLeft( *pnKeyChar, nRotateSize ); + } +} + +bool BinaryCodec_XOR::verifyKey( sal_uInt16 nKey, sal_uInt16 nHash ) const +{ + return (nKey == mnBaseKey) && (nHash == mnHash); +} + +void BinaryCodec_XOR::startBlock() +{ + mnOffset = 0; +} + +bool BinaryCodec_XOR::decode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcData, sal_Int32 nBytes ) +{ + const sal_uInt8* pnCurrKey = mpnKey + mnOffset; + const sal_uInt8* pnKeyLast = mpnKey + 0x0F; + + // switch/case outside of the for loop (performance) + const sal_uInt8* pnSrcDataEnd = pnSrcData + nBytes; + switch( meCodecType ) + { + case CODEC_WORD: + { + for( ; pnSrcData < pnSrcDataEnd; ++pnSrcData, ++pnDestData ) + { + sal_uInt8 nData = *pnSrcData ^ *pnCurrKey; + if( (*pnSrcData != 0) && (nData != 0) ) + *pnDestData = nData; + if( pnCurrKey < pnKeyLast ) ++pnCurrKey; else pnCurrKey = mpnKey; + } + } + break; + case CODEC_EXCEL: + { + for( ; pnSrcData < pnSrcDataEnd; ++pnSrcData, ++pnDestData ) + { + *pnDestData = *pnSrcData; + lclRotateLeft( *pnDestData, 3 ); + *pnDestData ^= *pnCurrKey; + if( pnCurrKey < pnKeyLast ) ++pnCurrKey; else pnCurrKey = mpnKey; + } + } + break; + // compiler will warn, if new codec type is introduced and not handled here + } + + // update offset and leave + return skip( nBytes ); +} + +bool BinaryCodec_XOR::skip( sal_Int32 nBytes ) +{ + mnOffset = static_cast< sal_Int32 >( (mnOffset + nBytes) & 0x0F ); + return true; +} + +sal_uInt16 BinaryCodec_XOR::getHash( const sal_uInt8* pnPassData, sal_Int32 nSize ) +{ + return lclGetHash( pnPassData, nSize ); +} + +// ============================================================================ + +BinaryCodec_RCF::BinaryCodec_RCF() +{ + mhCipher = rtl_cipher_create( rtl_Cipher_AlgorithmARCFOUR, rtl_Cipher_ModeStream ); + OSL_ENSURE( mhCipher != 0, "BinaryCodec_RCF::BinaryCodec_RCF - cannot create cipher" ); + + mhDigest = rtl_digest_create( rtl_Digest_AlgorithmMD5 ); + OSL_ENSURE( mhDigest != 0, "BinaryCodec_RCF::BinaryCodec_RCF - cannot create digest" ); + + (void)memset( mpnDigestValue, 0, sizeof( mpnDigestValue ) ); +} + +BinaryCodec_RCF::~BinaryCodec_RCF() +{ + (void)memset( mpnDigestValue, 0, sizeof( mpnDigestValue ) ); + rtl_digest_destroy( mhDigest ); + rtl_cipher_destroy( mhCipher ); +} + +void BinaryCodec_RCF::initKey( const sal_uInt16 pnPassData[ 16 ], const sal_uInt8 pnUnique[ 16 ] ) +{ + // create little-endian key data array from password data + sal_uInt8 pnKeyData[ 64 ]; + (void)memset( pnKeyData, 0, sizeof( pnKeyData ) ); + + const sal_uInt16* pnCurrPass = pnPassData; + const sal_uInt16* pnPassEnd = pnPassData + 16; + sal_uInt8* pnCurrKey = pnKeyData; + size_t nPassSize = 0; + for( ; (pnCurrPass < pnPassEnd) && (*pnCurrPass != 0); ++pnCurrPass, ++nPassSize ) + { + *pnCurrKey++ = static_cast< sal_uInt8 >( *pnCurrPass ); + *pnCurrKey++ = static_cast< sal_uInt8 >( *pnCurrPass >> 8 ); + } + pnKeyData[ 2 * nPassSize ] = 0x80; + pnKeyData[ 56 ] = static_cast< sal_uInt8 >( nPassSize << 4 ); + + // fill raw digest of key data into key data + (void)rtl_digest_updateMD5( mhDigest, pnKeyData, sizeof( pnKeyData ) ); + (void)rtl_digest_rawMD5( mhDigest, pnKeyData, RTL_DIGEST_LENGTH_MD5 ); + + // update digest with key data and passed unique data + for( size_t nIndex = 0; nIndex < 16; ++nIndex ) + { + rtl_digest_updateMD5( mhDigest, pnKeyData, 5 ); + rtl_digest_updateMD5( mhDigest, pnUnique, 16 ); + } + + // update digest with padding + pnKeyData[ 16 ] = 0x80; + (void)memset( pnKeyData + 17, 0, sizeof( pnKeyData ) - 17 ); + pnKeyData[ 56 ] = 0x80; + pnKeyData[ 57 ] = 0x0A; + rtl_digest_updateMD5( mhDigest, pnKeyData + 16, sizeof( pnKeyData ) - 16 ); + + // fill raw digest of above updates into digest value + rtl_digest_rawMD5( mhDigest, mpnDigestValue, sizeof( mpnDigestValue ) ); + + // erase key data array and leave + (void)memset( pnKeyData, 0, sizeof( pnKeyData ) ); +} + +bool BinaryCodec_RCF::verifyKey( const sal_uInt8 pnSaltData[ 16 ], const sal_uInt8 pnSaltDigest[ 16 ] ) +{ + if( !startBlock( 0 ) ) + return false; + + sal_uInt8 pnDigest[ RTL_DIGEST_LENGTH_MD5 ]; + sal_uInt8 pnBuffer[ 64 ]; + + // decode salt data into buffer + rtl_cipher_decode( mhCipher, pnSaltData, 16, pnBuffer, sizeof( pnBuffer ) ); + + pnBuffer[ 16 ] = 0x80; + (void)memset( pnBuffer + 17, 0, sizeof( pnBuffer ) - 17 ); + pnBuffer[ 56 ] = 0x80; + + // fill raw digest of buffer into digest + rtl_digest_updateMD5( mhDigest, pnBuffer, sizeof( pnBuffer ) ); + rtl_digest_rawMD5( mhDigest, pnDigest, sizeof( pnDigest ) ); + + // decode original salt digest into buffer + rtl_cipher_decode( mhCipher, pnSaltDigest, 16, pnBuffer, sizeof( pnBuffer ) ); + + // compare buffer with computed digest + bool bResult = memcmp( pnBuffer, pnDigest, sizeof( pnDigest ) ) == 0; + + // erase buffer and digest arrays and leave + (void)memset( pnBuffer, 0, sizeof( pnBuffer ) ); + (void)memset( pnDigest, 0, sizeof( pnDigest ) ); + return bResult; +} + +bool BinaryCodec_RCF::startBlock( sal_Int32 nCounter ) +{ + // initialize key data array + sal_uInt8 pnKeyData[ 64 ]; + (void)memset( pnKeyData, 0, sizeof( pnKeyData ) ); + + // fill 40 bit of digest value into [0..4] + (void)memcpy( pnKeyData, mpnDigestValue, 5 ); + + // fill little-endian counter into [5..8], static_cast masks out unneeded bits + pnKeyData[ 5 ] = static_cast< sal_uInt8 >( nCounter ); + pnKeyData[ 6 ] = static_cast< sal_uInt8 >( nCounter >> 8 ); + pnKeyData[ 7 ] = static_cast< sal_uInt8 >( nCounter >> 16 ); + pnKeyData[ 8 ] = static_cast< sal_uInt8 >( nCounter >> 24 ); + + pnKeyData[ 9 ] = 0x80; + pnKeyData[ 56 ] = 0x48; + + // fill raw digest of key data into key data + (void)rtl_digest_updateMD5( mhDigest, pnKeyData, sizeof( pnKeyData ) ); + (void)rtl_digest_rawMD5( mhDigest, pnKeyData, RTL_DIGEST_LENGTH_MD5 ); + + // initialize cipher with key data (for decoding) + rtlCipherError eResult = + rtl_cipher_init( mhCipher, rtl_Cipher_DirectionDecode, pnKeyData, RTL_DIGEST_LENGTH_MD5, 0, 0 ); + + // rrase key data array and leave + (void)memset( pnKeyData, 0, sizeof( pnKeyData ) ); + return eResult == rtl_Cipher_E_None; +} + +bool BinaryCodec_RCF::decode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcData, sal_Int32 nBytes ) +{ + rtlCipherError eResult = rtl_cipher_decode( mhCipher, + pnSrcData, static_cast< sal_Size >( nBytes ), + pnDestData, static_cast< sal_Size >( nBytes ) ); + return eResult == rtl_Cipher_E_None; +} + +bool BinaryCodec_RCF::skip( sal_Int32 nBytes ) +{ + // decode dummy data in memory to update internal state of RC4 cipher + sal_uInt8 pnDummy[ 1024 ]; + sal_Int32 nBytesLeft = nBytes; + bool bResult = true; + while( bResult && (nBytesLeft > 0) ) + { + sal_Int32 nBlockLen = ::std::min( nBytesLeft, static_cast< sal_Int32 >( sizeof( pnDummy ) ) ); + bResult = decode( pnDummy, pnDummy, nBlockLen ); + nBytesLeft -= nBlockLen; + } + return bResult; +} + +// ============================================================================ + +} // namespace core +} // namespace oox + diff --git a/oox/source/core/binaryfilterbase.cxx b/oox/source/core/binaryfilterbase.cxx new file mode 100644 index 000000000000..29348c5468f6 --- /dev/null +++ b/oox/source/core/binaryfilterbase.cxx @@ -0,0 +1,74 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: binaryfilterbase.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:50 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/core/binaryfilterbase.hxx" +#include "oox/helper/olestorage.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::io::XInputStream; +using ::com::sun::star::io::XOutputStream; + +namespace oox { +namespace core { + +// ============================================================================ + +BinaryFilterBase::BinaryFilterBase( const Reference< XMultiServiceFactory >& rxFactory ) : + FilterBase( rxFactory ) +{ +} + +BinaryFilterBase::~BinaryFilterBase() +{ +} + +StorageRef BinaryFilterBase::implCreateStorage( + Reference< XInputStream >& rxInStream, Reference< XOutputStream >& rxOutStream ) const +{ + StorageRef xStorage; + if( rxInStream.is() ) + xStorage.reset( new OleStorage( getServiceFactory(), rxInStream, true ) ); + else if( rxOutStream.is() ) + xStorage.reset( new OleStorage( getServiceFactory(), rxOutStream, true ) ); + return xStorage; +} + +// ============================================================================ + +} // namespace core +} // namespace oox + diff --git a/oox/source/core/facreg.cxx b/oox/source/core/facreg.cxx new file mode 100644 index 000000000000..e8bbb147a480 --- /dev/null +++ b/oox/source/core/facreg.cxx @@ -0,0 +1,157 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: facreg.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:50 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/dllapi.h" + +#include + +#include + +#include +#include + +#include +#include + +using namespace rtl; +using namespace com::sun::star; + +#define SERVICE( className ) \ +extern OUString SAL_CALL className##_getImplementationName() throw(); \ +extern uno::Sequence< OUString > SAL_CALL className##_getSupportedServiceNames() throw();\ +extern uno::Reference< uno::XInterface > SAL_CALL className##_createInstance( \ + const uno::Reference< lang::XMultiServiceFactory > & rSMgr ) \ + throw( uno::Exception ) + +namespace oox { + namespace core { SERVICE( FilterDetect ); } + namespace ppt { SERVICE( PowerPointImport ); } + namespace xls { SERVICE( BiffDetector ); } + namespace xls { SERVICE( ExcelFilter ); } + namespace xls { SERVICE( ExcelBiffFilter ); } + namespace shape { SERVICE( ShapeContextHandler ); } + namespace shape { SERVICE( FastTokenHandlerService ); } +} + +// +#ifdef __cplusplus +extern "C" +{ +#endif + +OOX_DLLPUBLIC void SAL_CALL component_getImplementationEnvironment( const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +void SAL_CALL writeInfo( registry::XRegistryKey * pRegistryKey, const OUString& rImplementationName, const uno::Sequence< OUString >& rServices ) +{ + uno::Reference< registry::XRegistryKey > xNewKey( + pRegistryKey->createKey( + OUString( sal_Unicode( '/' ) ) + rImplementationName + OUString(RTL_CONSTASCII_USTRINGPARAM( "/UNO/SERVICES") ) ) ); + + for( sal_Int32 i = 0; i < rServices.getLength(); i++ ) + xNewKey->createKey( rServices.getConstArray()[i]); +} + +#define WRITEINFO(className)\ + writeInfo( pKey, className##_getImplementationName(), className##_getSupportedServiceNames() ) + +OOX_DLLPUBLIC sal_Bool SAL_CALL component_writeInfo( void * , void * pRegistryKey ) +{ + if( pRegistryKey ) + { + try + { + registry::XRegistryKey *pKey = reinterpret_cast< registry::XRegistryKey * >( pRegistryKey ); + + WRITEINFO( ::oox::core::FilterDetect ); + WRITEINFO( ::oox::ppt::PowerPointImport ); + WRITEINFO( ::oox::xls::BiffDetector ); + WRITEINFO( ::oox::xls::ExcelFilter ); + WRITEINFO( ::oox::xls::ExcelBiffFilter ); + WRITEINFO( ::oox::shape::ShapeContextHandler ); + WRITEINFO( ::oox::shape::FastTokenHandlerService ); + } + catch (registry::InvalidRegistryException &) + { + OSL_ENSURE( sal_False, "### InvalidRegistryException!" ); + } + } + return sal_True; +} + +#define SINGLEFACTORY(classname)\ + if( classname##_getImplementationName().equalsAsciiL( pImplName, nImplNameLen ) )\ + {\ + xFactory = ::cppu::createSingleFactory( xMSF,\ + classname##_getImplementationName(),\ + classname##_createInstance,\ + classname##_getSupportedServiceNames() );\ + } + +OOX_DLLPUBLIC void * SAL_CALL component_getFactory( const sal_Char * pImplName, void * pServiceManager, void * ) +{ + void * pRet = 0; + if( pServiceManager ) + { + uno::Reference< lang::XMultiServiceFactory > xMSF( reinterpret_cast< lang::XMultiServiceFactory * >( pServiceManager ) ); + + uno::Reference< lang::XSingleServiceFactory > xFactory; + + const sal_Int32 nImplNameLen = strlen( pImplName ); + + // impress oasis import + SINGLEFACTORY( ::oox::core::FilterDetect ) + else SINGLEFACTORY( oox::ppt::PowerPointImport ) + else SINGLEFACTORY( ::oox::xls::BiffDetector ) + else SINGLEFACTORY( ::oox::xls::ExcelFilter ) + else SINGLEFACTORY( ::oox::xls::ExcelBiffFilter ) + else SINGLEFACTORY( ::oox::shape::ShapeContextHandler) + else SINGLEFACTORY( ::oox::shape::FastTokenHandlerService) + + if( xFactory.is()) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } + return pRet; +} + +#ifdef __cplusplus +} +#endif + diff --git a/oox/source/core/filterbase.cxx b/oox/source/core/filterbase.cxx new file mode 100644 index 000000000000..fa0408203446 --- /dev/null +++ b/oox/source/core/filterbase.cxx @@ -0,0 +1,247 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: filterbase.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:50 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/core/filterbase.hxx" +#include +#include +#include +#include + +using ::rtl::OUString; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::lang::IllegalArgumentException; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::lang::XComponent; +using ::com::sun::star::beans::PropertyValue; +using ::com::sun::star::frame::XModel; +using ::com::sun::star::io::XInputStream; +using ::com::sun::star::io::XOutputStream; +using ::com::sun::star::task::XStatusIndicator; +using ::com::sun::star::task::XInteractionHandler; +using ::comphelper::MediaDescriptor; + +namespace oox { +namespace core { + +// ============================================================================ + +struct FilterBaseImpl +{ + MediaDescriptor maDescriptor; + OUString maFileUrl; + StorageRef mxStorage; + + Reference< XMultiServiceFactory > mxFactory; + Reference< XModel > mxModel; + Reference< XInputStream > mxInStream; + Reference< XOutputStream > mxOutStream; + Reference< XStatusIndicator > mxStatusIndicator; + Reference< XInteractionHandler > mxInteractionHandler; + + explicit FilterBaseImpl( const Reference< XMultiServiceFactory >& rxFactory ); + void setMediaDescriptor( const Sequence< PropertyValue >& rDescriptor ); +}; + +// ---------------------------------------------------------------------------- + +FilterBaseImpl::FilterBaseImpl( const Reference< XMultiServiceFactory >& rxFactory ) : + mxFactory( rxFactory ) +{ +} + +void FilterBaseImpl::setMediaDescriptor( const Sequence< PropertyValue >& rDescriptor ) +{ + maDescriptor = rDescriptor; + maDescriptor.addInputStream(); + + maFileUrl = maDescriptor.getUnpackedValueOrDefault( MediaDescriptor::PROP_URL(), maFileUrl ); + mxInStream = maDescriptor.getUnpackedValueOrDefault( MediaDescriptor::PROP_INPUTSTREAM(), mxInStream ); + mxOutStream = maDescriptor.getUnpackedValueOrDefault( MediaDescriptor::PROP_OUTPUTSTREAM(), mxOutStream ); + mxStatusIndicator = maDescriptor.getUnpackedValueOrDefault( MediaDescriptor::PROP_STATUSINDICATOR(), mxStatusIndicator ); + mxInteractionHandler = maDescriptor.getUnpackedValueOrDefault( MediaDescriptor::PROP_INTERACTIONHANDLER(), mxInteractionHandler ); +} + +// ============================================================================ + +FilterBase::FilterBase( const Reference< XMultiServiceFactory >& rxFactory ) : + mxImpl( new FilterBaseImpl( rxFactory ) ) +{ +} + +FilterBase::~FilterBase() +{ +} + +bool FilterBase::isImportFilter() const +{ + return mxImpl->mxInStream.is(); +} + +bool FilterBase::isExportFilter() const +{ + return mxImpl->mxOutStream.is(); +} + +// ---------------------------------------------------------------------------- + +const Reference< XMultiServiceFactory >& FilterBase::getServiceFactory() const +{ + return mxImpl->mxFactory; +} + +const Reference< XModel >& FilterBase::getModel() const +{ + return mxImpl->mxModel; +} + +const Reference< XStatusIndicator >& FilterBase::getStatusIndicator() const +{ + return mxImpl->mxStatusIndicator; +} + +const Reference< XInteractionHandler >& FilterBase::getInteractionHandler() const +{ + return mxImpl->mxInteractionHandler; +} + +const OUString& FilterBase::getFileUrl() const +{ + return mxImpl->maFileUrl; +} + +OUString FilterBase::getAbsoluteUrl( const OUString& rUrl ) const +{ + return rUrl; +} + +StorageRef FilterBase::getStorage() const +{ + return mxImpl->mxStorage; +} + +StorageRef FilterBase::openSubStorage( const OUString& rStorageName, bool bCreate ) +{ + return mxImpl->mxStorage->openSubStorage( rStorageName, bCreate ); +} + +Reference< XInputStream > FilterBase::openInputStream( const OUString& rStreamName ) +{ + return mxImpl->mxStorage->openInputStream( rStreamName ); +} + +Reference< XOutputStream > FilterBase::openOutputStream( const OUString& rStreamName ) +{ + return mxImpl->mxStorage->openOutputStream( rStreamName ); +} + +// com.sun.star.lang.XServiceInfo interface ----------------------------------- + +OUString SAL_CALL FilterBase::getImplementationName() throw( RuntimeException ) +{ + return implGetImplementationName(); +} + +sal_Bool SAL_CALL FilterBase::supportsService( const OUString& rServiceName ) throw( RuntimeException ) +{ + return + (rServiceName == CREATE_OUSTRING( "com.sun.star.document.ImportFilter" )) || + (rServiceName == CREATE_OUSTRING( "com.sun.star.document.ExportFilter" )); +} + +Sequence< OUString > SAL_CALL FilterBase::getSupportedServiceNames() throw( RuntimeException ) +{ + Sequence< OUString > aServiceNames( 2 ); + aServiceNames[ 0 ] = CREATE_OUSTRING( "com.sun.star.document.ImportFilter" ); + aServiceNames[ 1 ] = CREATE_OUSTRING( "com.sun.star.document.ExportFilter" ); + return aServiceNames; +} + +// com.sun.star.lang.XInitialization interface -------------------------------- + +void SAL_CALL FilterBase::initialize( const Sequence< Any >& /*rArgs*/ ) throw( Exception, RuntimeException ) +{ +} + +// com.sun.star.document.XImporter interface ---------------------------------- + +void SAL_CALL FilterBase::setTargetDocument( const Reference< XComponent >& rxDocument ) throw( IllegalArgumentException, RuntimeException ) +{ + mxImpl->mxModel.set( rxDocument, UNO_QUERY ); + if( !mxImpl->mxModel.is() ) + throw IllegalArgumentException(); +} + +// com.sun.star.document.XExporter interface ---------------------------------- + +void SAL_CALL FilterBase::setSourceDocument( const Reference< XComponent >& rxDocument ) throw( IllegalArgumentException, RuntimeException ) +{ + mxImpl->mxModel.set( rxDocument, UNO_QUERY ); + if( !mxImpl->mxModel.is() ) + throw IllegalArgumentException(); +} + +// com.sun.star.document.XFilter interface ------------------------------------ + +sal_Bool SAL_CALL FilterBase::filter( const Sequence< PropertyValue >& rDescriptor ) throw( RuntimeException ) +{ + sal_Bool bRet = sal_False; + mxImpl->setMediaDescriptor( rDescriptor ); + mxImpl->mxStorage = implCreateStorage( mxImpl->mxInStream, mxImpl->mxOutStream ); + if( mxImpl->mxModel.is() && mxImpl->mxStorage.get() ) + { + mxImpl->mxModel->lockControllers(); + if( mxImpl->mxInStream.is() ) + bRet = importDocument(); + else if( mxImpl->mxOutStream.is() ) + bRet = exportDocument(); + mxImpl->mxModel->unlockControllers(); + } + return bRet; +} + +void SAL_CALL FilterBase::cancel() throw( RuntimeException ) +{ +} + +// ============================================================================ + +} // namespace core +} // namespace oox + diff --git a/oox/source/core/filterdetect.cxx b/oox/source/core/filterdetect.cxx new file mode 100644 index 000000000000..76d82875ee23 --- /dev/null +++ b/oox/source/core/filterdetect.cxx @@ -0,0 +1,404 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: filterdetect.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:50 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "oox/helper/attributelist.hxx" +#include "oox/helper/helper.hxx" +#include "oox/core/fasttokenhandler.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +#include + +using ::rtl::OUString; +using ::rtl::OString; +using ::comphelper::MediaDescriptor; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::embed; +using namespace ::com::sun::star::xml::sax; + +namespace oox { +namespace core { + +// ============================================================================ + +/** Document handler specifically designed for detecting OOXML file formats. + + It takes a reference to the filter string object via its constructor, and + puts the name of the detected filter to it if it successfully finds one. + */ +class FilterDetectDocHandler : public ::cppu::WeakImplHelper1< XFastDocumentHandler > +{ +public: + explicit FilterDetectDocHandler( OUString& rFilter ); + virtual ~FilterDetectDocHandler(); + + // XFastDocumentHandler + virtual void SAL_CALL startDocument() throw (SAXException, RuntimeException); + virtual void SAL_CALL endDocument() throw (SAXException, RuntimeException); + virtual void SAL_CALL setDocumentLocator( const Reference< XLocator >& xLocator ) throw (SAXException, RuntimeException); + + // XFastContextHandler + virtual void SAL_CALL startFastElement( sal_Int32 nElement, const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException); + virtual void SAL_CALL startUnknownElement( const OUString& Namespace, const OUString& Name, const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException); + virtual void SAL_CALL endFastElement( sal_Int32 Element ) throw (SAXException, RuntimeException); + virtual void SAL_CALL endUnknownElement( const OUString& Namespace, const OUString& Name ) throw (SAXException, RuntimeException); + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 Element, const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException); + virtual Reference< XFastContextHandler > SAL_CALL createUnknownChildContext( const OUString& Namespace, const OUString& Name, const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException); + virtual void SAL_CALL characters( const OUString& aChars ) throw (SAXException, RuntimeException); + virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces ) throw (SAXException, RuntimeException); + virtual void SAL_CALL processingInstruction( const OUString& aTarget, const OUString& aData ) throw (SAXException, RuntimeException); + +private: + void parseRelationship( const AttributeList& rAttribs ); + + OUString getFilterNameFromContentType( const OUString& rContentType ) const; + void parseContentTypesDefault( const AttributeList& rAttribs ); + void parseContentTypesOverride( const AttributeList& rAttribs ); + +private: + typedef ::std::vector< sal_Int32 > ContextVector; + + OUString& mrFilter; + ContextVector maContextStack; + const OUString maWordFilterName; + const OUString maExcelFilterName; + const OUString maExcelBinFilterName; + const OUString maPowerPointFilterName; + OUString maTargetPath; +}; + +// ============================================================================ + +FilterDetectDocHandler::FilterDetectDocHandler( OUString& rFilter ) : + mrFilter( rFilter ), + maWordFilterName( CREATE_OUSTRING( "MS Word 2007 XML" ) ), + maExcelFilterName( CREATE_OUSTRING( "MS Excel 2007 XML" ) ), + maExcelBinFilterName( CREATE_OUSTRING( "MS Excel 2007 Binary" ) ), + maPowerPointFilterName( CREATE_OUSTRING( "MS PowerPoint 2007 XML" ) ) +{ + maContextStack.reserve( 2 ); +} + +FilterDetectDocHandler::~FilterDetectDocHandler() +{ +} + +void SAL_CALL FilterDetectDocHandler::startDocument() + throw (SAXException, RuntimeException) +{ +} + +void SAL_CALL FilterDetectDocHandler::endDocument() + throw (SAXException, RuntimeException) +{ +} + +void SAL_CALL FilterDetectDocHandler::setDocumentLocator( const Reference& /*xLocator*/ ) + throw (SAXException, RuntimeException) +{ +} + +// =========================================================================== + +void SAL_CALL FilterDetectDocHandler::startFastElement( + sal_Int32 nElement, const Reference< XFastAttributeList >& rAttribs ) + throw (SAXException,RuntimeException) +{ + AttributeList aAttribs( rAttribs ); + switch ( nElement ) + { + // cases for _rels/.rels + case NMSP_PACKAGE_RELATIONSHIPS|XML_Relationships: + break; + case NMSP_PACKAGE_RELATIONSHIPS|XML_Relationship: + if( !maContextStack.empty() && (maContextStack.back() == (NMSP_PACKAGE_RELATIONSHIPS|XML_Relationships)) ) + parseRelationship( aAttribs ); + break; + + // cases for [Content_Types].xml + case NMSP_CONTENT_TYPES|XML_Types: + break; + case NMSP_CONTENT_TYPES|XML_Default: + if( !maContextStack.empty() && (maContextStack.back() == (NMSP_CONTENT_TYPES|XML_Types)) ) + parseContentTypesDefault( aAttribs ); + break; + case NMSP_CONTENT_TYPES|XML_Override: + if( !maContextStack.empty() && (maContextStack.back() == (NMSP_CONTENT_TYPES|XML_Types)) ) + parseContentTypesOverride( aAttribs ); + break; + } + maContextStack.push_back( nElement ); +} + +void SAL_CALL FilterDetectDocHandler::startUnknownElement( + const OUString& /*Namespace*/, const OUString& /*Name*/, const Reference& /*Attribs*/ ) + throw (SAXException, RuntimeException) +{ +} + +void SAL_CALL FilterDetectDocHandler::endFastElement( sal_Int32 /*nElement*/ ) + throw (SAXException, RuntimeException) +{ + maContextStack.pop_back(); +} + +void SAL_CALL FilterDetectDocHandler::endUnknownElement( + const OUString& /*Namespace*/, const OUString& /*Name*/ ) throw (SAXException, RuntimeException) +{ +} + +Reference SAL_CALL FilterDetectDocHandler::createFastChildContext( + sal_Int32 /*Element*/, const Reference& /*Attribs*/ ) + throw (SAXException, RuntimeException) +{ + return this; +} + +Reference SAL_CALL FilterDetectDocHandler::createUnknownChildContext( + const OUString& /*Namespace*/, const OUString& /*Name*/, const Reference& /*Attribs*/) + throw (SAXException, RuntimeException) +{ + return this; +} + +void SAL_CALL FilterDetectDocHandler::characters( const OUString& /*aChars*/ ) + throw (SAXException, RuntimeException) +{ +} + +void SAL_CALL FilterDetectDocHandler::ignorableWhitespace( const OUString& /*aWhitespaces*/ ) + throw (SAXException, RuntimeException) +{ +} + +void SAL_CALL FilterDetectDocHandler::processingInstruction( + const OUString& /*aTarget*/, const OUString& /*aData*/ ) + throw (SAXException, RuntimeException) +{ +} + +// ============================================================================ + +void FilterDetectDocHandler::parseRelationship( const AttributeList& rAttribs ) +{ + OUString aType = rAttribs.getString( XML_Type ); + if( aType.equalsAscii( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" ) ) + maTargetPath = OUString( sal_Unicode( '/' ) ) + rAttribs.getString( XML_Target ); +} + +OUString FilterDetectDocHandler::getFilterNameFromContentType( const OUString& rContentType ) const +{ + if( rContentType.equalsAscii( "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml" ) ) + return maWordFilterName; + if( rContentType.equalsAscii( "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml" ) ) + return maExcelFilterName; + if( rContentType.equalsAscii( "application/vnd.ms-excel.sheet.binary.macroEnabled.main" ) ) + return maExcelBinFilterName; + if( rContentType.equalsAscii( "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml" ) ) + return maPowerPointFilterName; + return OUString(); +} + +void FilterDetectDocHandler::parseContentTypesDefault( const AttributeList& rAttribs ) +{ + // only if no overridden part name found + if( mrFilter.getLength() == 0 ) + { + // check if target path ends with extension + OUString aExtension = rAttribs.getString( XML_Extension ); + sal_Int32 nExtPos = maTargetPath.getLength() - aExtension.getLength(); + if( (nExtPos > 0) && (maTargetPath[ nExtPos - 1 ] == '.') && maTargetPath.match( aExtension, nExtPos ) ) + mrFilter = getFilterNameFromContentType( rAttribs.getString( XML_ContentType ) ); + } +} + +void FilterDetectDocHandler::parseContentTypesOverride( const AttributeList& rAttribs ) +{ + if( rAttribs.getString( XML_PartName ).equals( maTargetPath ) ) + mrFilter = getFilterNameFromContentType( rAttribs.getString( XML_ContentType ) ); +} + +// ============================================================================ + +class FilterDetect : public ::cppu::WeakImplHelper2< XExtendedFilterDetection, XServiceInfo > +{ +public: + explicit FilterDetect( const Reference< XMultiServiceFactory >& xFactory ); + virtual ~FilterDetect(); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() throw( RuntimeException ); + virtual sal_Bool SAL_CALL supportsService( const OUString& rServiceName ) throw( RuntimeException ); + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw( RuntimeException ); + + // XExtendedFilterDetect + virtual OUString SAL_CALL detect( Sequence< PropertyValue >& lDescriptor ) throw( RuntimeException ); + +private: + Reference< XMultiServiceFactory > mxFactory; +}; + +// ---------------------------------------------------------------------------- + +/* Helper for XServiceInfo */ +Sequence< OUString > FilterDetect_getSupportedServiceNames() +{ + Sequence< OUString > aServiceNames( 1 ); + aServiceNames[ 0 ] = CREATE_OUSTRING( "com.sun.star.frame.ExtendedTypeDetection" ); + return aServiceNames; +} + +/* Helper for XServiceInfo */ +OUString FilterDetect_getImplementationName() +{ + return CREATE_OUSTRING( "com.sun.star.comp.oox.FormatDetector" ); +} + +/* Helper for registry */ +Reference< XInterface > SAL_CALL FilterDetect_createInstance( const Reference< XMultiServiceFactory >& xServiceManager ) throw( Exception ) +{ + return Reference< XInterface >( *new FilterDetect( xServiceManager ) ); +} + +FilterDetect::FilterDetect( const Reference< XMultiServiceFactory >& xFactory ) : + mxFactory( xFactory ) +{ +} + +FilterDetect::~FilterDetect() +{ +} + +// com.sun.star.document.XExtendedFilterDetect interface ---------------------- + +OUString SAL_CALL FilterDetect::detect( Sequence< PropertyValue >& lDescriptor ) throw( RuntimeException ) +{ + OUString aFilter; + + Reference< XFastDocumentHandler > xHandler( new FilterDetectDocHandler(aFilter) ); + Reference< XFastTokenHandler > xTokenHandler( new ::oox::FastTokenHandler ); + + try + { + Reference< XFastParser > xParser( ::comphelper::getProcessServiceFactory()->createInstance( + CREATE_OUSTRING( "com.sun.star.xml.sax.FastParser" ) ), UNO_QUERY_THROW ); + + xParser->setFastDocumentHandler( xHandler ); + xParser->setTokenHandler( xTokenHandler ); + + xParser->registerNamespace( CREATE_OUSTRING( "http://schemas.openxmlformats.org/package/2006/relationships" ), + NMSP_PACKAGE_RELATIONSHIPS ); + xParser->registerNamespace( CREATE_OUSTRING( "http://schemas.openxmlformats.org/officeDocument/2006/relationships" ), + NMSP_RELATIONSHIPS ); + xParser->registerNamespace( CREATE_OUSTRING( "http://schemas.openxmlformats.org/package/2006/content-types" ), + NMSP_CONTENT_TYPES ); + + MediaDescriptor aDescriptor( lDescriptor ); + aDescriptor.addInputStream(); + Reference< XInputStream > xInputStream( + aDescriptor[MediaDescriptor::PROP_INPUTSTREAM()], UNO_QUERY_THROW ); + + Reference< XStorage > xStorage( ::comphelper::OStorageHelper::GetStorageFromInputStream( xInputStream, mxFactory ), + UNO_QUERY_THROW ); + + // Parse _rels/.rels to get the target path. + Reference< XStorage > xRels( xStorage->openStorageElement( CREATE_OUSTRING("_rels"), ElementModes::READ ) ); + Reference< XInputStream > xStream( xRels->openStreamElement( CREATE_OUSTRING(".rels"), ElementModes::READ ), + UNO_QUERY_THROW ); + + InputSource aParserInput; + aParserInput.sSystemId = CREATE_OUSTRING("_rels/.rels"); + aParserInput.aInputStream = xStream; + xParser->parseStream( aParserInput ); + + // Parse [Content_Types].xml to determine the content type of the part at the target path. + OUString aContentTypeName = CREATE_OUSTRING("[Content_Types].xml"); + xStream.set( xStorage->openStreamElement( aContentTypeName, ElementModes::READ ), UNO_QUERY_THROW ); + + aParserInput.sSystemId = aContentTypeName; + aParserInput.aInputStream = xStream; + xParser->parseStream( aParserInput ); + } + catch ( const Exception& ) + { + } + + return aFilter; +} + +// com.sun.star.lang.XServiceInfo interface ----------------------------------- + +OUString SAL_CALL FilterDetect::getImplementationName() throw( RuntimeException ) +{ + return FilterDetect_getImplementationName(); +} + +sal_Bool SAL_CALL FilterDetect::supportsService( const OUString& rServiceName ) throw( RuntimeException ) +{ + const Sequence< OUString > aServices = FilterDetect_getSupportedServiceNames(); + const OUString* pArray = aServices.getConstArray(); + const OUString* pArrayEnd = pArray + aServices.getLength(); + return ::std::find( pArray, pArrayEnd, rServiceName ) != pArrayEnd; +} + +Sequence< OUString > SAL_CALL FilterDetect::getSupportedServiceNames() throw( RuntimeException ) +{ + return FilterDetect_getSupportedServiceNames(); +} + +// ============================================================================ + +} // namespace core +} // namespace oox + diff --git a/oox/source/core/fragmenthandler.cxx b/oox/source/core/fragmenthandler.cxx new file mode 100644 index 000000000000..38b22186165c --- /dev/null +++ b/oox/source/core/fragmenthandler.cxx @@ -0,0 +1,149 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: fragmenthandler.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:50 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/core/fragmenthandler.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::io; + +namespace oox { +namespace core { + +// ============================================================================ + +FragmentHandler::FragmentHandler( const XmlFilterRef& rxFilter, const OUString& rFragmentPath ) : + mxFilter( rxFilter ), + mxRelations( rxFilter->importRelations( rFragmentPath ) ), + maFragmentPath( rFragmentPath ), + mpParser( 0 ) +{ +} + +FragmentHandler::FragmentHandler( const XmlFilterRef& rxFilter, const OUString& rFragmentPath, RelationsRef xRelations ) : + mxFilter( rxFilter ), + mxRelations( xRelations ), + maFragmentPath( rFragmentPath ), + mpParser( 0 ) +{ +} + +OUString FragmentHandler::getFragmentPathFromTarget( const OUString& rTarget ) const +{ + return Relations::getFragmentPathFromTarget( maFragmentPath, rTarget ); +} + +OUString FragmentHandler::getFragmentPathFromRelId( const OUString& rRelId ) const +{ + return mxRelations->getFragmentPathFromRelId( maFragmentPath, rRelId ); +} + +OUString FragmentHandler::getFragmentPathFromType( const OUString& rType ) const +{ + return mxRelations->getFragmentPathFromType( maFragmentPath, rType ); +} + +void FragmentHandler::setRecordParser( RecordParser& rParser ) +{ + mpParser = &rParser; +} + +RecordParser& FragmentHandler::getRecordParser() +{ + OSL_ENSURE( mpParser, "FragmentHandler::getRecordParser - not in binary import mode" ); + return *mpParser; +} + +// com.sun.star.xml.sax.XFastDocumentHandler interface ------------------------ + +void FragmentHandler::startDocument( ) throw (SAXException, RuntimeException) +{ +} + +void FragmentHandler::endDocument( ) throw (SAXException, RuntimeException) +{ +} + +void FragmentHandler::setDocumentLocator( const Reference< XLocator >& xLocator ) throw (SAXException, RuntimeException) +{ + mxLocator = xLocator; +} + +// com.sun.star.xml.sax.XFastContextHandler interface ------------------------- + +void FragmentHandler::startFastElement( ::sal_Int32, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +{ +} + +void FragmentHandler::startUnknownElement( const OUString&, const OUString&, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +{ +} + +void FragmentHandler::endFastElement( ::sal_Int32 ) throw (SAXException, RuntimeException) +{ +} + +void FragmentHandler::endUnknownElement( const OUString&, const OUString& ) throw (SAXException, RuntimeException) +{ +} + +Reference< XFastContextHandler > FragmentHandler::createFastChildContext( ::sal_Int32, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +{ + return Reference< XFastContextHandler >(); +} + +Reference< XFastContextHandler > FragmentHandler::createUnknownChildContext( const OUString&, const OUString&, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +{ + return Reference< XFastContextHandler >(); +} + +void FragmentHandler::characters( const OUString& ) throw (SAXException, RuntimeException) +{ +} + +void FragmentHandler::ignorableWhitespace( const OUString& ) throw (SAXException, RuntimeException) +{ +} + +void FragmentHandler::processingInstruction( const OUString&, const OUString& ) throw (SAXException, RuntimeException) +{ +} + +// ============================================================================ + +} // namespace core +} // namespace oox + diff --git a/oox/source/core/makefile.mk b/oox/source/core/makefile.mk new file mode 100644 index 000000000000..6bfff2d36b8a --- /dev/null +++ b/oox/source/core/makefile.mk @@ -0,0 +1,69 @@ +#************************************************************************* +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.2 $ +# +# last change: $Author: rt $ $Date: 2008-01-17 08:05:50 $ +# +# The Contents of this file are made available subject to +# the terms of GNU Lesser General Public License Version 2.1. +# +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2005 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=oox +TARGET=core +AUTOSEG=true + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/binarycodec.obj \ + $(SLO)$/binaryfilterbase.obj \ + $(SLO)$/context.obj \ + $(SLO)$/facreg.obj \ + $(SLO)$/filterbase.obj \ + $(SLO)$/filterdetect.obj \ + $(SLO)$/fragmenthandler.obj \ + $(SLO)$/recordcontext.obj \ + $(SLO)$/recordinfoprovider.obj \ + $(SLO)$/recordparser.obj \ + $(SLO)$/relations.obj \ + $(SLO)$/relationshandler.obj \ + $(SLO)$/skipcontext.obj \ + $(SLO)$/xmlfilterbase.obj + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk diff --git a/oox/source/core/recordparser.cxx b/oox/source/core/recordparser.cxx new file mode 100644 index 000000000000..185161f9eb4b --- /dev/null +++ b/oox/source/core/recordparser.cxx @@ -0,0 +1,362 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: recordparser.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:50 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/core/recordparser.hxx" +#include +#include +#include +#include "oox/helper/recordinputstream.hxx" +#include "oox/core/fragmenthandler.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::lang::DisposedException; +using ::com::sun::star::io::XInputStream; +using ::com::sun::star::io::IOException; +using ::com::sun::star::xml::sax::SAXException; +using ::com::sun::star::xml::sax::XLocator; + +namespace oox { +namespace core { + +// ============================================================================ + +namespace prv { + +class Locator : public ::cppu::WeakImplHelper1< XLocator > +{ +public: + inline explicit Locator( RecordParser* pParser ) : mpParser( pParser ) {} + + void dispose(); + void checkDispose() throw( RuntimeException ); + + // com.sun.star.sax.XLocator interface + + virtual sal_Int32 SAL_CALL getColumnNumber() throw( RuntimeException ); + virtual sal_Int32 SAL_CALL getLineNumber() throw( RuntimeException ); + virtual OUString SAL_CALL getPublicId() throw( RuntimeException ); + virtual OUString SAL_CALL getSystemId() throw( RuntimeException ); + +private: + RecordParser* mpParser; +}; + +// ---------------------------------------------------------------------------- + +void Locator::dispose() +{ + mpParser = 0; +} + +void Locator::checkDispose() throw( RuntimeException ) +{ + if( !mpParser ) + throw DisposedException(); +} + +sal_Int32 SAL_CALL Locator::getColumnNumber() throw( RuntimeException ) +{ + return -1; +} + +sal_Int32 SAL_CALL Locator::getLineNumber() throw( RuntimeException ) +{ + return -1; +} + +OUString SAL_CALL Locator::getPublicId() throw( RuntimeException ) +{ + checkDispose(); + return mpParser->getInputSource().maPublicId; +} + +OUString SAL_CALL Locator::getSystemId() throw( RuntimeException ) +{ + checkDispose(); + return mpParser->getInputSource().maSystemId; +} + +// ============================================================================ + +class ContextStack +{ +public: + explicit ContextStack( FragmentHandlerRef xHandler ); + + inline bool empty() const { return maStack.empty(); } + + sal_Int32 getCurrentRecId() const; + bool hasCurrentEndRecId() const; + RecordContextRef getCurrentContext() const; + + void pushContext( const RecordInfo& rRec, const RecordContextRef& rxContext ); + void popContext(); + +private: + typedef ::std::pair< RecordInfo, RecordContextRef > ContextInfo; + typedef ::std::vector< ContextInfo > ContextInfoVec; + + FragmentHandlerRef mxHandler; + ContextInfoVec maStack; +}; + +// ---------------------------------------------------------------------------- + +ContextStack::ContextStack( FragmentHandlerRef xHandler ) : + mxHandler( xHandler ) +{ +} + +sal_Int32 ContextStack::getCurrentRecId() const +{ + return maStack.empty() ? -1 : maStack.back().first.mnStartRecId; +} + +bool ContextStack::hasCurrentEndRecId() const +{ + return !maStack.empty() && (maStack.back().first.mnEndRecId >= 0); +} + +RecordContextRef ContextStack::getCurrentContext() const +{ + if( !maStack.empty() ) + return maStack.back().second; + return mxHandler.get(); +} + +void ContextStack::pushContext( const RecordInfo& rRecInfo, const RecordContextRef& rxContext ) +{ + OSL_ENSURE( (rRecInfo.mnEndRecId >= 0) || maStack.empty() || hasCurrentEndRecId(), + "ContextStack::pushContext - nested incomplete context record identifiers" ); + maStack.push_back( ContextInfo( rRecInfo, rxContext ) ); +} + +void ContextStack::popContext() +{ + OSL_ENSURE( !maStack.empty(), "ContextStack::popContext - no context on stack" ); + if( !maStack.empty() ) + { + ContextInfo& rContextInfo = maStack.back(); + if( rContextInfo.second.is() ) + rContextInfo.second->endRecord( rContextInfo.first.mnStartRecId ); + maStack.pop_back(); + } +} + +} // namespace prv + +// ============================================================================ + +namespace { + +/** Reads a byte from the passed stream, returns true on success. */ +inline bool lclReadByte( sal_uInt8& ornByte, BinaryInputStream& rStrm ) +{ + return rStrm.read( &ornByte, 1 ) == 1; +} + +/** Reads a compressed signed 32-bit integer from the passed stream. */ +bool lclReadCompressedInt( sal_Int32& ornValue, BinaryInputStream& rStrm ) +{ + ornValue = 0; + sal_uInt8 nByte; + if( !lclReadByte( nByte, rStrm ) ) return false; + ornValue = nByte & 0x7F; + if( (nByte & 0x80) == 0 ) return true; + if( !lclReadByte( nByte, rStrm ) ) return false; + ornValue |= sal_Int32( nByte & 0x7F ) << 7; + if( (nByte & 0x80) == 0 ) return true; + if( !lclReadByte( nByte, rStrm ) ) return false; + ornValue |= sal_Int32( nByte & 0x7F ) << 14; + if( (nByte & 0x80) == 0 ) return true; + if( !lclReadByte( nByte, rStrm ) ) return false; + ornValue |= sal_Int32( nByte & 0x7F ) << 21; + return true; +} + +bool lclReadRecordHeader( sal_Int32& ornRecId, sal_Int32& ornRecSize, BinaryInputStream& rStrm ) +{ + return + lclReadCompressedInt( ornRecId, rStrm ) && (ornRecId >= 0) && + lclReadCompressedInt( ornRecSize, rStrm ) && (ornRecSize >= 0); +} + +bool lclReadNextRecord( sal_Int32& ornRecId, RecordDataSequence& orData, BinaryInputStream& rStrm ) +{ + sal_Int32 nRecSize = 0; + bool bValid = lclReadRecordHeader( ornRecId, nRecSize, rStrm ); + if( bValid ) + { + orData.realloc( nRecSize ); + bValid = (nRecSize == 0) || (rStrm.read( orData, nRecSize ) == nRecSize); + } + return bValid; +} + +} // namespace + +// ============================================================================ + +RecordParser::RecordParser() +{ + mxLocator.set( new prv::Locator( this ) ); +} + +RecordParser::~RecordParser() +{ + if( mxLocator.is() ) + mxLocator->dispose(); +} + +void RecordParser::setFragmentHandler( const ::rtl::Reference< FragmentHandler >& rxHandler ) +{ + mxHandler = rxHandler; +} + +void RecordParser::setRecordInfoProvider( const RecordInfoProviderRef& rxProvider ) +{ + mxRecInfoProvider = rxProvider; +} + +void RecordParser::parseStream( const RecordInputSource& rInputSource ) throw( SAXException, IOException, RuntimeException ) +{ + maSource = rInputSource; + + if( !maSource.mxInStream || !maSource.mxInStream->is() ) + throw IOException(); + if( !mxHandler.is() ) + throw SAXException(); + if( !mxRecInfoProvider ) + throw RuntimeException(); + + // start the document + Reference< XLocator > xLocator( mxLocator.get() ); + mxHandler->setDocumentLocator( xLocator ); + mxHandler->startDocument(); + + // parse the stream + mxStack.reset( new prv::ContextStack( mxHandler ) ); + sal_Int32 nRecId = 0; + RecordDataSequence aRecData; + while( lclReadNextRecord( nRecId, aRecData, *maSource.mxInStream ) ) + { + // create record stream object from imported record data + RecordInputStream aRecStrm( aRecData ); + // try to leave a context, there may be other incomplete contexts on the stack + if( const RecordInfo* pEndRecInfo = mxRecInfoProvider->getEndRecordInfo( nRecId ) ) + { + (void)pEndRecInfo; // shut warning up in non-debug + // finalize contexts without record identifier for context end + while( !mxStack->empty() && !mxStack->hasCurrentEndRecId() ) + mxStack->popContext(); + // finalize the current context and pop context info from stack + OSL_ENSURE( mxStack->getCurrentRecId() == pEndRecInfo->mnStartRecId, "RecordParser::parseStream - context records mismatch" ); + (void)pEndRecInfo; // suppress compiler warning for unused variable + RecordContextRef xCurrContext = mxStack->getCurrentContext(); + if( xCurrContext.is() ) + { + // context end record may contain some data, handle it as simple record + aRecStrm.seek( 0 ); + xCurrContext->startRecord( nRecId, aRecStrm ); + xCurrContext->endRecord( nRecId ); + } + mxStack->popContext(); + } + else + { + // end context with incomplete record id, if the same id comes again + if( (mxStack->getCurrentRecId() == nRecId) && !mxStack->hasCurrentEndRecId() ) + mxStack->popContext(); + // try to start a new context + RecordContextRef xCurrContext = mxStack->getCurrentContext(); + if( xCurrContext.is() ) + { + aRecStrm.seek( 0 ); + xCurrContext = xCurrContext->createRecordContext( nRecId, aRecStrm ); + } + // track all context identifiers on the stack (do not push simple records) + const RecordInfo* pStartRecInfo = mxRecInfoProvider->getStartRecordInfo( nRecId ); + if( pStartRecInfo ) + mxStack->pushContext( *pStartRecInfo, xCurrContext ); + // import the record + if( xCurrContext.is() ) + { + // import the record + aRecStrm.seek( 0 ); + xCurrContext->startRecord( nRecId, aRecStrm ); + // end simple records (context records are finished in ContextStack::popContext) + if( !pStartRecInfo ) + xCurrContext->endRecord( nRecId ); + } + } + } + // close remaining contexts (missing context end records or stream error) + while( !mxStack->empty() ) + mxStack->popContext(); + mxStack.reset(); + + // finish document + mxHandler->endDocument(); + + maSource = RecordInputSource(); +} + +void RecordParser::pushContext( sal_Int32 nRecId, const RecordContextRef& rxContext ) +{ + const RecordInfo* pRecInfo = mxRecInfoProvider->getStartRecordInfo( nRecId ); + OSL_ENSURE( pRecInfo, "RecordParser::pushContext - invalid record identifier" ); + OSL_ENSURE( (pRecInfo->mnEndRecId >= 0) || mxStack->empty() || mxStack->hasCurrentEndRecId(), + "RecordParser::pushContext - nested incomplete context record identifiers" ); + mxStack->pushContext( *pRecInfo, rxContext ); + if( rxContext.is() ) + { + RecordDataSequence aEmptyData; + RecordInputStream aRecStrm( aEmptyData ); + rxContext->startRecord( nRecId, aRecStrm ); + } +} + +void RecordParser::popContext() +{ + mxStack->popContext(); +} + +// ============================================================================ + +} // namespace core +} // namespace oox + diff --git a/oox/source/core/relations.cxx b/oox/source/core/relations.cxx new file mode 100644 index 000000000000..6e3aa9cf67bc --- /dev/null +++ b/oox/source/core/relations.cxx @@ -0,0 +1,139 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: relations.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/core/relations.hxx" +#include "oox/helper/helper.hxx" + +using ::rtl::OUString; + +namespace oox { +namespace core { + +// ============================================================================ + +const Relation* Relations::getRelationFromRelId( const OUString& rId ) const +{ + const_iterator aIt = find( rId ); + return (aIt == end()) ? 0 : &aIt->second; +} + +const Relation* Relations::getRelationFromType( const OUString& rType ) const +{ + for( const_iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt ) + if( aIt->second.maType == rType ) + return &aIt->second; + return 0; +} + +RelationsRef Relations::getRelationsFromType( const OUString& rType ) const +{ + RelationsRef xRelations( new Relations ); + for( const_iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt ) + if( aIt->second.maType == rType ) + (*xRelations)[ aIt->first ] = aIt->second; + return xRelations; +} + +OUString Relations::getTargetFromRelId( const OUString& rRelId ) const +{ + if( const Relation* pRelation = getRelationFromRelId( rRelId ) ) + return pRelation->maTarget; + return OUString(); +} + +OUString Relations::getTargetFromType( const OUString& rType ) const +{ + if( const Relation* pRelation = getRelationFromType( rType ) ) + return pRelation->maTarget; + return OUString(); +} + +OUString Relations::getFragmentPathFromTarget( const OUString& rParentFragment, const OUString& rTarget ) +{ + const sal_Unicode cDirSep = '/'; + + // no target, no fragment path + if( rTarget.getLength() == 0 ) + return OUString(); + + // absolute target, or empty fragment path -> return target + if( (rTarget[ 0 ] == cDirSep) || (rParentFragment.getLength() == 0) ) + return rTarget; + + sal_Int32 nLastSepPos = rParentFragment.lastIndexOf( cDirSep ); + OUString aPath = (nLastSepPos < 0) ? rParentFragment : rParentFragment.copy( 0, nLastSepPos ); + + const OUString sBack = CREATE_OUSTRING( "../" ); + + // First, count the number of "../"'s found in relative path string. + sal_Int32 nCount = 0, nPos = 0; + while ( true ) + { + nPos = rTarget.indexOf(sBack, nCount*3); + if ( nPos != nCount*3 ) + break; + ++nCount; + } + + // Now, reduce the base path's directory level by the count. + for ( sal_Int32 i = 0; i < nCount; ++i ) + { + sal_Int32 pos = aPath.lastIndexOf(cDirSep); + if ( pos < 0 ) + // This is unexpected. Bail out. + return rTarget; + aPath = aPath.copy( 0, pos ); + } + + aPath += OUString( cDirSep ); + aPath += rTarget.copy( nCount*3 ); + return aPath; +} + +OUString Relations::getFragmentPathFromRelId( const OUString& rParentFragment, const OUString& rRelId ) const +{ + return getFragmentPathFromTarget( rParentFragment, getTargetFromRelId( rRelId ) ); +} + +OUString Relations::getFragmentPathFromType( const OUString& rParentFragment, const OUString& rType ) const +{ + return getFragmentPathFromTarget( rParentFragment, getTargetFromType( rType ) ); +} + +// ============================================================================ + +} // namespace core +} // namespace oox + diff --git a/oox/source/core/relationshandler.cxx b/oox/source/core/relationshandler.cxx new file mode 100644 index 000000000000..3924605a0dc9 --- /dev/null +++ b/oox/source/core/relationshandler.cxx @@ -0,0 +1,106 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: relationshandler.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/core/relationshandler.hxx" +#include +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { +namespace core { + +// ============================================================================ + +namespace { + +/* Build path to relations file from passed path, e.g.: + 'path/path/file.xml' -> 'path/path/_rels/file.xml.rels' + 'file.xml' -> '_rels/file.xml.rels' + '' -> '_rels/.rels' + */ +OUString lclGetRelationsPath( const OUString& rFragmentPath ) +{ + sal_Int32 nPathLen = ::std::max< sal_Int32 >( rFragmentPath.lastIndexOf( '/' ) + 1, 0 ); + return + OUStringBuffer( rFragmentPath.copy( 0, nPathLen ) ). // file path including slash + appendAscii( "_rels/" ). // additional '_rels/' path + append( rFragmentPath.copy( nPathLen ) ). // file name after path + appendAscii( ".rels" ). // '.rels' suffix + makeStringAndClear(); +} + +} // namespace + +// ============================================================================ + +RelationsFragmentHandler::RelationsFragmentHandler( const XmlFilterRef& rxFilter, const OUString& rFragmentPath, RelationsRef xRelations ) : + FragmentHandler( rxFilter, lclGetRelationsPath( rFragmentPath ), xRelations ), + mrRelations( *xRelations ) +{ +} + +Reference< XFastContextHandler > RelationsFragmentHandler::createFastChildContext( + sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + switch( nElement ) + { + case NMSP_PACKAGE_RELATIONSHIPS|XML_Relationship: + { + Relation aRelation; + aRelation.maId = rxAttribs->getOptionalValue( XML_Id ); + aRelation.maType = rxAttribs->getOptionalValue( XML_Type ); + aRelation.maTarget = rxAttribs->getOptionalValue( XML_Target ); + if( (aRelation.maId.getLength() > 0) && (aRelation.maType.getLength() > 0) && (aRelation.maTarget.getLength() > 0) ) + mrRelations[ aRelation.maId ] = aRelation; + } + break; + case NMSP_PACKAGE_RELATIONSHIPS|XML_Relationships: + xRet.set( this ); + break; + } + return xRet; +} + +// ============================================================================ + +} // namespace core +} // namespace oox + diff --git a/oox/source/core/skipcontext.cxx b/oox/source/core/skipcontext.cxx new file mode 100644 index 000000000000..d79186cf6fcf --- /dev/null +++ b/oox/source/core/skipcontext.cxx @@ -0,0 +1,50 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: skipcontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/core/context.hxx" +#include "oox/core/skipcontext.hxx" + + + +namespace oox { namespace core { + + SkipContext::SkipContext( const FragmentHandlerRef& xHandler ) + : Context( xHandler ) + { + OSL_TRACE( "OOX: Skipping Context" ); + } + + +} } diff --git a/oox/source/core/xmlfilterbase.cxx b/oox/source/core/xmlfilterbase.cxx new file mode 100644 index 000000000000..48f93cddec67 --- /dev/null +++ b/oox/source/core/xmlfilterbase.cxx @@ -0,0 +1,300 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: xmlfilterbase.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/core/xmlfilterbase.hxx" +#include +#include +#include +#include +#include +#include +#include +#include "oox/helper/containerhelper.hxx" +#include "oox/helper/zipstorage.hxx" +#include "oox/core/fasttokenhandler.hxx" +#include "oox/core/fragmenthandler.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/core/recordparser.hxx" +#include "oox/core/relationshandler.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::embed::XStorage; +using ::com::sun::star::embed::XTransactedObject; +using ::com::sun::star::io::XInputStream; +using ::com::sun::star::io::XOutputStream; +using ::com::sun::star::container::XNameContainer; +using ::com::sun::star::document::XDocumentSubStorageSupplier; +using ::com::sun::star::xml::sax::XFastParser; +using ::com::sun::star::xml::sax::XFastTokenHandler; +using ::com::sun::star::xml::sax::XFastDocumentHandler; +using ::com::sun::star::xml::sax::InputSource; +using ::com::sun::star::xml::sax::SAXException; + +namespace oox { +namespace core { + +// ============================================================================ + +struct XmlFilterBaseImpl +{ + typedef RefMap< OUString, Relations > RelationsMap; + + OUString maBinSuffix; + Reference< XFastTokenHandler > + mxTokenHandler; + RelationsMap maRelationsMap; + ::std::set< OUString > maPictureSet; /// Already copied picture stream names. + Reference< XStorage > mxPictureStorage; /// Target model picture storage. + Reference< XNameContainer > mxMarkerTable; /// Table to create new arrow names. + + explicit XmlFilterBaseImpl(); +}; + +// ---------------------------------------------------------------------------- + +XmlFilterBaseImpl::XmlFilterBaseImpl() : + maBinSuffix( CREATE_OUSTRING( ".bin" ) ), + mxTokenHandler( new FastTokenHandler ) +{ +} + +// ============================================================================ + +XmlFilterBase::XmlFilterBase( const Reference< XMultiServiceFactory >& rxFactory ) : + FilterBase( rxFactory ), + mxImpl( new XmlFilterBaseImpl ) +{ +} + +XmlFilterBase::~XmlFilterBase() +{ +} + +RecordInfoProviderRef XmlFilterBase::getRecordInfoProvider() +{ + // default: no support for binary streams + return RecordInfoProviderRef(); +} + +// ---------------------------------------------------------------------------- + +OUString XmlFilterBase::getFragmentPathFromType( const OUString& rType ) +{ + return importRelations( OUString() )->getTargetFromType( rType ); +} + +bool XmlFilterBase::importFragment( const ::rtl::Reference< FragmentHandler >& rxHandler ) +{ + OSL_ENSURE( rxHandler.is(), "XmlFilterBase::importFragment - missing fragment handler" ); + if( !rxHandler.is() ) + return false; + + // fragment handler must contain path to fragment stream + OUString aFragmentPath = rxHandler->getFragmentPath(); + OSL_ENSURE( aFragmentPath.getLength() > 0, "XmlFilterBase::importFragment - missing fragment path" ); + if( aFragmentPath.getLength() == 0 ) + return false; + + // try to open the fragment stream (this may fail - do not assert) + Reference< XInputStream > xInStrm = openInputStream( aFragmentPath ); + if( !xInStrm.is() ) + return false; + + // try to import binary streams (fragment extension must be '.bin') + sal_Int32 nBinSuffixPos = aFragmentPath.getLength() - mxImpl->maBinSuffix.getLength(); + if( (nBinSuffixPos >= 0) && aFragmentPath.match( mxImpl->maBinSuffix, nBinSuffixPos ) ) + { + try + { + // create the record parser + RecordParser aParser; + aParser.setFragmentHandler( rxHandler ); + aParser.setRecordInfoProvider( getRecordInfoProvider() ); + rxHandler->setRecordParser( aParser ); + + // create the input source and parse the stream + RecordInputSource aSource; + aSource.mxInStream.reset( new BinaryInputStream( xInStrm, true ) ); + aSource.maSystemId = aFragmentPath; + aParser.parseStream( aSource ); + return true; + } + catch( Exception& ) + { + } + return false; + } + + // get the XFastDocumentHandler interface from the fragment handler + Reference< XFastDocumentHandler > xDocHandler( rxHandler.get() ); + if( !xDocHandler.is() ) + return false; + + // try to import XML stream + try + { + // create the fast parser + Reference< XFastParser > xParser( getServiceFactory()->createInstance( + CREATE_OUSTRING( "com.sun.star.xml.sax.FastParser" ) ), UNO_QUERY_THROW ); + xParser->setFastDocumentHandler( xDocHandler ); + xParser->setTokenHandler( mxImpl->mxTokenHandler ); + + // register XML namespaces + xParser->registerNamespace( CREATE_OUSTRING( "http://schemas.openxmlformats.org/spreadsheetml/2006/main"), NMSP_EXCEL ); + xParser->registerNamespace( CREATE_OUSTRING( "urn:schemas-microsoft-com:office:office" ), NMSP_OFFICE ); + xParser->registerNamespace( CREATE_OUSTRING( "http://schemas.openxmlformats.org/presentationml/2006/main"), NMSP_PPT ); + xParser->registerNamespace( CREATE_OUSTRING( "urn:schemas-microsoft-com:office:word" ), NMSP_WORD ); + xParser->registerNamespace( CREATE_OUSTRING( "urn:schemas-microsoft-com:vml" ), NMSP_VML ); + xParser->registerNamespace( CREATE_OUSTRING( "http://schemas.openxmlformats.org/drawingml/2006/main" ), NMSP_DRAWINGML ); + xParser->registerNamespace( CREATE_OUSTRING( "http://schemas.openxmlformats.org/package/2006/relationships" ), NMSP_PACKAGE_RELATIONSHIPS ); + xParser->registerNamespace( CREATE_OUSTRING( "http://schemas.openxmlformats.org/officeDocument/2006/relationships" ), NMSP_RELATIONSHIPS ); + xParser->registerNamespace( CREATE_OUSTRING( "http://www.w3.org/XML/1998/namespace" ), NMSP_XML ); + xParser->registerNamespace( CREATE_OUSTRING( "urn:schemas-microsoft-com:office:powerpoint" ), NMSP_POWERPOINT ); + xParser->registerNamespace( CREATE_OUSTRING( "urn:schemas-microsoft-com:office:activation" ), NMSP_ACTIVATION ); + xParser->registerNamespace( CREATE_OUSTRING( "http://schemas.openxmlformats.org/drawingml/2006/diagram" ), NMSP_DIAGRAM ); + + // create the input source and parse the stream + InputSource aSource; + aSource.aInputStream = xInStrm; + aSource.sSystemId = aFragmentPath; + xParser->parseStream( aSource ); + return true; + } + catch( Exception& ) + { + } + return false; +} + +RelationsRef XmlFilterBase::importRelations( const OUString& rFragmentPath ) +{ + // try to find cached relations + RelationsRef& rxRelations = mxImpl->maRelationsMap[ rFragmentPath ]; + if( !rxRelations ) + { + // import and cache relations + rxRelations.reset( new Relations ); + importFragment( new RelationsFragmentHandler( this, rFragmentPath, rxRelations ) ); + } + return rxRelations; +} + +OUString XmlFilterBase::copyPictureStream( const OUString& rPicturePath ) +{ + // split source path into source storage path and stream name + sal_Int32 nIndex = rPicturePath.lastIndexOf( sal_Unicode( '/' ) ); + OUString sPictureName; + OUString sSourceStorageName; + if( nIndex < 0 ) + { + // root stream + sPictureName = rPicturePath; + } + else + { + // sub stream + sPictureName = rPicturePath.copy( nIndex + 1 ); + sSourceStorageName = rPicturePath.copy( 0, nIndex ); + } + + // check if we already copied this one! + if( mxImpl->maPictureSet.find( rPicturePath ) == mxImpl->maPictureSet.end() ) try + { + // ok, not yet, copy stream to documents picture storage + + // first get the picture storage from our target model + if( !mxImpl->mxPictureStorage.is() ) + { + static const OUString sPictures = CREATE_OUSTRING( "Pictures" ); + Reference< XDocumentSubStorageSupplier > xDSSS( getModel(), UNO_QUERY_THROW ); + mxImpl->mxPictureStorage.set( xDSSS->getDocumentSubStorage( + sPictures, ::com::sun::star::embed::ElementModes::WRITE ), UNO_QUERY_THROW ); + } + + StorageRef xSourceStorage = openSubStorage( sSourceStorageName, false ); + if( xSourceStorage.get() ) + { + Reference< XStorage > xSourceXStorage = xSourceStorage->getXStorage(); + if( xSourceXStorage.is() ) + { + xSourceXStorage->copyElementTo( sPictureName, mxImpl->mxPictureStorage, sPictureName ); + Reference< XTransactedObject > xTO( mxImpl->mxPictureStorage, UNO_QUERY_THROW ); + xTO->commit(); + } + } + } + catch( Exception& ) + { + } + + static const OUString sUrlPrefix = CREATE_OUSTRING( "vnd.sun.star.Package:Pictures/" ); + return sUrlPrefix + sPictureName; +} + +Reference< XNameContainer >& XmlFilterBase::getMarkerTable() const +{ + if( !mxImpl->mxMarkerTable.is() ) try + { + mxImpl->mxMarkerTable.set( getServiceFactory()->createInstance( + CREATE_OUSTRING( "com.sun.star.drawing.MarkerTable" ) ), UNO_QUERY_THROW ); + } + catch( Exception& ) + { + } + return mxImpl->mxMarkerTable; +} + +StorageRef XmlFilterBase::implCreateStorage( + Reference< XInputStream >& rxInStream, Reference< XOutputStream >& rxOutStream ) const +{ + StorageRef xStorage; + if( rxInStream.is() ) + xStorage.reset( new ZipStorage( getServiceFactory(), rxInStream ) ); + else if( rxOutStream.is() ) + xStorage.reset( new ZipStorage( getServiceFactory(), rxOutStream ) ); + return xStorage; +} + +// ============================================================================ + +} // namespace core +} // namespace oox + diff --git a/oox/source/drawingml/clrscheme.cxx b/oox/source/drawingml/clrscheme.cxx new file mode 100644 index 000000000000..50c0ea07d417 --- /dev/null +++ b/oox/source/drawingml/clrscheme.cxx @@ -0,0 +1,104 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: clrscheme.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/clrscheme.hxx" +#include "tokens.hxx" + +namespace oox { namespace drawingml { + +sal_Bool ClrMap::getColorMap( sal_Int32& nClrToken ) +{ + sal_Int32 nMapped = 0; + std::map < sal_Int32, sal_Int32 >::const_iterator aIter( maClrMap.find( nClrToken ) ); + if ( aIter != maClrMap.end() ) + nMapped = (*aIter).second; + if ( nMapped ) + { + nClrToken = nMapped; + return sal_True; + } + else + return sal_False; +} + +void ClrMap::setColorMap( sal_Int32 nClrToken, sal_Int32 nMappedClrToken ) +{ + maClrMap[ nClrToken ] = nMappedClrToken; +} + +//----------------------------------------------------------------------------------------- + +ClrScheme::ClrScheme() +{ +} +ClrScheme::~ClrScheme() +{ +} + +sal_Bool ClrScheme::getColor( sal_Int32 nSchemeClrToken, sal_Int32& rColor ) const +{ + switch( nSchemeClrToken ) + { + case XML_bg1 : nSchemeClrToken = XML_dk1; break; + case XML_bg2 : nSchemeClrToken = XML_dk2; break; + case XML_tx1 : nSchemeClrToken = XML_lt1; break; + case XML_tx2 : nSchemeClrToken = XML_lt2; break; + } + std::map < sal_Int32, sal_Int32 >::const_iterator aIter( maClrScheme.find( nSchemeClrToken ) ); + if ( aIter != maClrScheme.end() ) + rColor = (*aIter).second; + return aIter != maClrScheme.end(); +} + +void ClrScheme::setColor( sal_Int32 nSchemeClrToken, sal_Int32 nColor ) +{ + maClrScheme[ nSchemeClrToken ] = nColor; +} + +// static +bool ClrScheme::getSystemColor( const sal_Int32 nSysClrToken, sal_Int32& rColor ) +{ + //! TODO: get colors from system + switch( nSysClrToken ) + { + case XML_window: rColor = 0xFFFFFF; break; + case XML_windowText: rColor = 0x000000; break; + //! TODO: more colors to follow... (chapter 5.1.12.58) + default: return false; + } + return true; +} + +} } diff --git a/oox/source/drawingml/clrschemecontext.cxx b/oox/source/drawingml/clrschemecontext.cxx new file mode 100644 index 000000000000..a6a5373d772a --- /dev/null +++ b/oox/source/drawingml/clrschemecontext.cxx @@ -0,0 +1,137 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: clrschemecontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/clrschemecontext.hxx" +#include "oox/drawingml/colorchoicecontext.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +static void setClrMap( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttributes, + oox::drawingml::ClrMap& rClrMap, sal_Int32 nToken ) +{ + if ( xAttributes->hasAttribute( nToken ) ) + { + sal_Int32 nMappedToken = xAttributes->getOptionalValueToken( nToken, 0 ); + rClrMap.setColorMap( nToken, nMappedToken ); + } +} + +clrMapContext::clrMapContext( const FragmentHandlerRef& xHandler, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttributes, oox::drawingml::ClrMap& rClrMap ) +: Context( xHandler ) +{ + setClrMap( xAttributes, rClrMap, XML_bg1 ); + setClrMap( xAttributes, rClrMap, XML_tx1 ); + setClrMap( xAttributes, rClrMap, XML_bg2 ); + setClrMap( xAttributes, rClrMap, XML_tx2 ); + setClrMap( xAttributes, rClrMap, XML_accent1 ); + setClrMap( xAttributes, rClrMap, XML_accent2 ); + setClrMap( xAttributes, rClrMap, XML_accent3 ); + setClrMap( xAttributes, rClrMap, XML_accent4 ); + setClrMap( xAttributes, rClrMap, XML_accent5 ); + setClrMap( xAttributes, rClrMap, XML_accent6 ); + setClrMap( xAttributes, rClrMap, XML_hlink ); + setClrMap( xAttributes, rClrMap, XML_folHlink ); +} + +Reference< XFastContextHandler > clrMapContext::createFastChildContext( sal_Int32 /* aElementToken */, const Reference< XFastAttributeList >& /* xAttribs */ ) + throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + return xRet; +} + +clrSchemeContext::clrSchemeContext( const ::oox::core::FragmentHandlerRef& xHandler, const oox::drawingml::ClrSchemePtr pClrSchemePtr ) +: Context( xHandler ) +, mpClrSchemePtr( pClrSchemePtr ) +{ +} + +void clrSchemeContext::startFastElement( sal_Int32 /* aElementToken */, const Reference< XFastAttributeList >& /* xAttribs */ ) throw (SAXException, RuntimeException) +{ +} + +void clrSchemeContext::endFastElement( sal_Int32 aElementToken ) throw (SAXException, RuntimeException) +{ + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_dk1: + case NMSP_DRAWINGML|XML_lt1: + case NMSP_DRAWINGML|XML_dk2: + case NMSP_DRAWINGML|XML_lt2: + case NMSP_DRAWINGML|XML_accent1: + case NMSP_DRAWINGML|XML_accent2: + case NMSP_DRAWINGML|XML_accent3: + case NMSP_DRAWINGML|XML_accent4: + case NMSP_DRAWINGML|XML_accent5: + case NMSP_DRAWINGML|XML_accent6: + case NMSP_DRAWINGML|XML_hlink: + case NMSP_DRAWINGML|XML_folHlink: + { + mpClrSchemePtr->setColor( aElementToken & 0xffff, maColor.getColor( *getHandler()->getFilter().get() ) ); + break; + } + } +} + +Reference< XFastContextHandler > clrSchemeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& /* xAttribs */ ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_scrgbClr: // CT_ScRgbColor + case NMSP_DRAWINGML|XML_srgbClr: // CT_SRgbColor + case NMSP_DRAWINGML|XML_hslClr: // CT_HslColor + case NMSP_DRAWINGML|XML_sysClr: // CT_SystemColor +// case NMSP_DRAWINGML|XML_schemeClr: // CT_SchemeColor + case NMSP_DRAWINGML|XML_prstClr: // CT_PresetColor + { + xRet.set( new colorChoiceContext( getHandler(), maColor ) ); + break; + } + } + if( !xRet.is() ) + xRet.set( this ); + + return xRet; +} + +} } diff --git a/oox/source/drawingml/color.cxx b/oox/source/drawingml/color.cxx new file mode 100644 index 000000000000..9b27916d83ca --- /dev/null +++ b/oox/source/drawingml/color.cxx @@ -0,0 +1,64 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: color.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/color.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using namespace ::oox::core; + +namespace oox { namespace drawingml { + +Color::Color() +: mnColor( 0 ) +, mnAlpha( 0 ) +, mbUsed( sal_False ) +, mbSchemeColor( sal_False ) +, mbAlphaColor( sal_False ) +{ +} +Color::~Color() +{ +} +sal_Int32 Color::getColor( const oox::core::XmlFilterBase& rFilterBase ) const +{ + return mbSchemeColor ? rFilterBase.getSchemeClr( mnColor ) : mnColor; +} +sal_Int32 Color::getAlpha() const +{ + return mnAlpha; +} + +} } diff --git a/oox/source/drawingml/colorchoicecontext.cxx b/oox/source/drawingml/colorchoicecontext.cxx new file mode 100644 index 000000000000..6f5572fcaefa --- /dev/null +++ b/oox/source/drawingml/colorchoicecontext.cxx @@ -0,0 +1,146 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: colorchoicecontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/colorchoicecontext.hxx" +#include "oox/drawingml/clrscheme.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +colorChoiceContext::colorChoiceContext( const ::oox::core::FragmentHandlerRef& xHandler, ::oox::drawingml::Color& rColor ) +: Context( xHandler ) +, mrColor( rColor ) +{ +} + +void colorChoiceContext::startFastElement( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) +{ + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_scrgbClr: // CT_ScRgbColor + { + sal_Int32 r = ((xAttribs->getOptionalValue( XML_r ).toInt32() * 256) / 1000) & 0xff; + sal_Int32 g = ((xAttribs->getOptionalValue( XML_g ).toInt32() * 256) / 1000) & 0xff; + sal_Int32 b = ((xAttribs->getOptionalValue( XML_b ).toInt32() * 256) / 1000) & 0xff; + mrColor.mnColor = (r << 16) | (g << 8) | b; + mrColor.mbUsed = sal_True; + break; + } + case NMSP_DRAWINGML|XML_srgbClr: // CT_SRgbColor + { + mrColor.mnColor = xAttribs->getOptionalValue( XML_val ).toInt32( 16 ); + mrColor.mbUsed = sal_True; + break; + } + case NMSP_DRAWINGML|XML_hslClr: // CT_HslColor + // todo + break; + case NMSP_DRAWINGML|XML_sysClr: // CT_SystemColor + sal_Int32 nColor; + if( !ClrScheme::getSystemColor( xAttribs->getOptionalValueToken( XML_val, XML_TOKEN_INVALID ), nColor ) ) + nColor = xAttribs->getOptionalValue( XML_lastClr ).toInt32( 16 ); + mrColor.mnColor = nColor; + mrColor.mbUsed = sal_True; + break; + case NMSP_DRAWINGML|XML_schemeClr: // CT_SchemeColor + { + mrColor.mnColor = xAttribs->getOptionalValueToken( XML_val, XML_nothing ); + mrColor.mbUsed = sal_True; + mrColor.mbSchemeColor = sal_True; + break; + } + case NMSP_DRAWINGML|XML_prstClr: // CT_PresetColor + // todo + break; + + } +} + +Reference< XFastContextHandler > colorChoiceContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& rxAttribs ) throw (SAXException, RuntimeException) +{ + // colorTransformGroup + + // color should be available as rgb in member mnColor already, now modify it depending on + // the transformation elements + + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_tint: // CT_PositiveFixedPercentage + case NMSP_DRAWINGML|XML_shade: // CT_PositiveFixedPercentage + case NMSP_DRAWINGML|XML_comp: // CT_ComplementTransform + case NMSP_DRAWINGML|XML_inv: // CT_InverseTransform + case NMSP_DRAWINGML|XML_gray: // CT_GrayscaleTransform + break; + case NMSP_DRAWINGML|XML_alpha: // CT_PositiveFixedPercentage + { + mrColor.mbUsed = sal_True; + mrColor.mbAlphaColor = sal_True; + mrColor.mnAlpha = GetPercent( rxAttribs->getOptionalValue( XML_val ) ); + } + break; + case NMSP_DRAWINGML|XML_alphaOff: // CT_FixedPercentage + case NMSP_DRAWINGML|XML_alphaMod: // CT_PositivePercentage + case NMSP_DRAWINGML|XML_hue: // CT_PositiveFixedAngle + case NMSP_DRAWINGML|XML_hueOff: // CT_Angle + case NMSP_DRAWINGML|XML_hueMod: // CT_PositivePercentage + case NMSP_DRAWINGML|XML_sat: // CT_Percentage + case NMSP_DRAWINGML|XML_satOff: // CT_Percentage + case NMSP_DRAWINGML|XML_satMod: // CT_Percentage + case NMSP_DRAWINGML|XML_lum: // CT_Percentage + case NMSP_DRAWINGML|XML_lumOff: // CT_Percentage + case NMSP_DRAWINGML|XML_lumMod: // CT_Percentage + case NMSP_DRAWINGML|XML_red: // CT_Percentage + case NMSP_DRAWINGML|XML_redOff: // CT_Percentage + case NMSP_DRAWINGML|XML_redMod: // CT_Percentage + case NMSP_DRAWINGML|XML_green: // CT_Percentage + case NMSP_DRAWINGML|XML_greenOff: // CT_Percentage + case NMSP_DRAWINGML|XML_greenMod: // CT_Percentage + case NMSP_DRAWINGML|XML_blue: // CT_Percentage + case NMSP_DRAWINGML|XML_blueOff: // CT_Percentage + case NMSP_DRAWINGML|XML_blueMod: // CT_Percentage + break; + } + return this; +} + + +} } diff --git a/oox/source/drawingml/connectorshapecontext.cxx b/oox/source/drawingml/connectorshapecontext.cxx new file mode 100644 index 000000000000..447065f56cd9 --- /dev/null +++ b/oox/source/drawingml/connectorshapecontext.cxx @@ -0,0 +1,89 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: connectorshapecontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include +#include +#include + +#include "oox/drawingml/connectorshapecontext.hxx" +#include "oox/drawingml/graphicshapecontext.hxx" +#include "oox/drawingml/lineproperties.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/drawingml/customshapegeometry.hxx" +#include "oox/drawingml/textbodycontext.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using rtl::OUString; +using namespace oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +ConnectorShapeContext::ConnectorShapeContext( const FragmentHandlerRef& xHandler, + sal_Int32 /* aElementToken */, ShapePtr pMasterShapePtr, ShapePtr pGroupShapePtr ) +: ShapeContext( xHandler, pMasterShapePtr, pGroupShapePtr ) +{ +} + +ConnectorShapeContext::~ConnectorShapeContext() +{ +} + +Reference< XFastContextHandler > ConnectorShapeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElementToken &(~NMSP_MASK) ) + { + case XML_nvCxnSpPr : + break; + + default: + xRet = ShapeContext::createFastChildContext( aElementToken, xAttribs ); + } + if( !xRet.is() ) + xRet.set( this ); + + + return xRet; +} + +} } diff --git a/oox/source/drawingml/customshapegeometry.cxx b/oox/source/drawingml/customshapegeometry.cxx new file mode 100644 index 000000000000..3eeeabd77e0e --- /dev/null +++ b/oox/source/drawingml/customshapegeometry.cxx @@ -0,0 +1,1071 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: customshapegeometry.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include + +#include "oox/helper/propertymap.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/drawingml/customshapegeometry.hxx" +#include "tokens.hxx" +#ifndef _UTL_STLTYPES_HXX_ +#include +#endif +#include + +using ::rtl::OUString; +using ::com::sun::star::beans::NamedValue; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +enum FormularCommand +{ + FC_MULDIV = 0, + FC_PLUSMINUS, + FC_PLUSDIV, + FC_IFELSE, + FC_ABS, + FC_AT2, + FC_CAT2, + FC_COS, + FC_MAX, + FC_MIN, + FC_MOD, + FC_PIN, + FC_SAT2, + FC_SIN, + FC_SQRT, + FC_TAN, + FC_VAL, + FC_LAST +}; +struct FormularCommandNameTable +{ + const char* pS; + FormularCommand pE; +}; +static FormularCommandNameTable pFormularCommandNameTable[] = +{ + { "*/", FC_MULDIV }, + { "+-", FC_PLUSMINUS }, + { "+/", FC_PLUSDIV }, + { "ifelse", FC_IFELSE }, + { "abs", FC_ABS }, + { "at2", FC_AT2 }, + { "cat2", FC_CAT2 }, + { "cos", FC_COS }, + { "max", FC_MAX }, + { "min", FC_MIN }, + { "mod", FC_MOD }, + { "pin", FC_PIN }, + { "sat2", FC_SAT2 }, + { "sin", FC_SIN }, + { "sqrt", FC_SQRT }, + { "tan", FC_TAN }, + { "val", FC_VAL } + +}; +typedef std::hash_map< rtl::OUString, FormularCommand, comphelper::UStringHash, comphelper::UStringEqual > FormulaCommandHMap; + +static const FormulaCommandHMap* pCommandHashMap; + +// --------------------------------------------------------------------- +// CT_GeomGuideList +class AdjustmentValueContext : public ::oox::core::Context +{ +public: + AdjustmentValueContext( const ::oox::core::FragmentHandlerRef& xHandler, CustomShapeProperties& rCustomShapeProperties ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + +protected: + ::oox::drawingml::CustomShapeProperties& mrCustomShapeProperties; +}; + +AdjustmentValueContext::AdjustmentValueContext( const FragmentHandlerRef& xHandler, CustomShapeProperties& rCustomShapeProperties ) +: Context( xHandler ) +, mrCustomShapeProperties( rCustomShapeProperties ) +{ +} + +static rtl::OUString convertToOOEquation( const rtl::OUString& rSource ) +{ + if ( !pCommandHashMap ) + { + FormulaCommandHMap* pHM = new FormulaCommandHMap(); + for( sal_Int32 i = 0; i < FC_LAST; i++ ) + (*pHM)[ OUString::createFromAscii( pFormularCommandNameTable[ i ].pS ) ] = pFormularCommandNameTable[ i ].pE; + pCommandHashMap = pHM; + } + + std::vector< rtl::OUString > aTokens; + sal_Int32 nIndex = 0; + do + { + rtl::OUString aToken( rSource.getToken( 0, ' ', nIndex ) ); + if ( aToken.getLength() ) + aTokens.push_back( aToken ); + } + while ( nIndex >= 0 ); + + rtl::OUString aEquation; + if ( aTokens.size() ) + { + const FormulaCommandHMap::const_iterator aIter( pCommandHashMap->find( aTokens[ 0 ] ) ); + if ( aIter != pCommandHashMap->end() ) + { + switch( aIter->second ) + { + case FC_MULDIV : + case FC_PLUSMINUS : + case FC_PLUSDIV : + case FC_IFELSE : + case FC_ABS : + case FC_AT2 : + case FC_CAT2 : + case FC_COS : + case FC_MAX : + case FC_MIN : + case FC_MOD : + case FC_PIN : + case FC_SAT2 : + case FC_SIN : + case FC_SQRT : + case FC_TAN : + case FC_VAL : + default : + break; + } + } + } + return aEquation; +} + +Reference< XFastContextHandler > AdjustmentValueContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + if ( aElementToken == ( NMSP_DRAWINGML | XML_gd ) ) // CT_GeomGuide + { + CustomShapeGuide aGuide; + aGuide.maName = xAttribs->getOptionalValue( XML_name ); + aGuide.maFormula = convertToOOEquation( xAttribs->getOptionalValue( XML_fmla ) ); + std::vector< CustomShapeGuide >& rAdjustmentValues( mrCustomShapeProperties.getAdjustmentValues() ); + rAdjustmentValues.push_back( aGuide ); + } + return this; +} + +// --------------------------------------------------------------------- + +static OUString GetShapeType( sal_Int32 nType ) +{ + OUString sType; + switch( nType ) + { + case XML_lineInv: // TODO + case XML_line: { + static const OUString sLine = CREATE_OUSTRING( "mso-spt20" ); + sType = sLine; + } break; + case XML_triangle: { + static const OUString sTriangle = CREATE_OUSTRING( "isosceles-triangle" ); + sType = sTriangle; + } break; + case XML_rtTriangle: { + static const OUString sRtTriangle = CREATE_OUSTRING( "right-triangle" ); + sType = sRtTriangle; + } break; + case XML_rect: { + static const OUString sRectangle = CREATE_OUSTRING( "rectangle" ); + sType = sRectangle; + } break; + case XML_diamond: { + static const OUString sDiamond = CREATE_OUSTRING( "diamond" ); + sType = sDiamond; + } break; + case XML_parallelogram: { + static const OUString sParallelogram = CREATE_OUSTRING( "parallelogram" ); + sType = sParallelogram; + } break; + case XML_nonIsoscelesTrapezoid: // TODO + case XML_trapezoid: { + static const OUString sTrapezoid = CREATE_OUSTRING( "trapezoid" ); + sType = sTrapezoid; + } break; + case XML_pentagon: { + static const OUString sPentagon = CREATE_OUSTRING( "pentagon" ); + sType = sPentagon; + } break; + case XML_heptagon: // TODO + case XML_hexagon: { + static const OUString sHexagon = CREATE_OUSTRING( "hexagon" ); + sType = sHexagon; + } break; + case XML_decagon: // TODO + case XML_dodecagon: // TODO + case XML_octagon: { + static const OUString sOctagon = CREATE_OUSTRING( "octagon" ); + sType = sOctagon; + } break; + case XML_star4: { + static const OUString sStar4 = CREATE_OUSTRING( "star4" ); + sType = sStar4; + } break; + case XML_star6: // TODO + case XML_star7: // TODO + case XML_star5: { + static const OUString sStar5 = CREATE_OUSTRING( "star5" ); + sType = sStar5; + } break; + case XML_star10: // TODO + case XML_star12: // TODO + case XML_star16: // TODO + case XML_star8: { + static const OUString sStar8 = CREATE_OUSTRING( "star8" ); + sType = sStar8; + } break; + case XML_star32: // TODO + case XML_star24: { + static const OUString sStar24 = CREATE_OUSTRING( "star24" ); + sType = sStar24; + } break; + case XML_round1Rect: // TODO + case XML_round2SameRect: // TODO + case XML_round2DiagRect: // TODO + case XML_snipRoundRect: // TODO + case XML_snip1Rect: // TODO + case XML_snip2SameRect: // TODO + case XML_snip2DiagRect: // TODO + case XML_roundRect: { + static const OUString sRoundRect = CREATE_OUSTRING( "round-rectangle" ); + sType = sRoundRect; + } break; + case XML_plaque: { + static const OUString sPlaque = CREATE_OUSTRING( "mso-spt21" ); + sType = sPlaque; + } break; + case XML_teardrop: // TODO + case XML_ellipse: { + static const OUString sEllipse = CREATE_OUSTRING( "ellipse" ); + sType = sEllipse; + } break; + case XML_homePlate: { + static const OUString sHomePlate = CREATE_OUSTRING( "pentagon-right" ); + sType = sHomePlate; + } break; + case XML_chevron: { + static const OUString sChevron = CREATE_OUSTRING( "chevron" ); + sType = sChevron; + } break; + case XML_pieWedge: // TODO + case XML_pie: // TODO + case XML_blockArc: { + static const OUString sBlockArc = CREATE_OUSTRING( "block-arc" ); + sType = sBlockArc; + } break; + case XML_donut: { + static const OUString sDonut = CREATE_OUSTRING( "ring" ); + sType = sDonut; + } break; + case XML_noSmoking: { + static const OUString sNoSmoking = CREATE_OUSTRING( "forbidden" ); + sType = sNoSmoking; + } break; + case XML_rightArrow: { + static const OUString sRightArrow = CREATE_OUSTRING( "right-arrow" ); + sType = sRightArrow; + } break; + case XML_leftArrow: { + static const OUString sLeftArrow = CREATE_OUSTRING( "left-arrow" ); + sType = sLeftArrow; + } break; + case XML_upArrow: { + static const OUString sUpArrow = CREATE_OUSTRING( "up-arrow" ); + sType = sUpArrow; + } break; + case XML_downArrow: { + static const OUString sDownArrow = CREATE_OUSTRING( "down-arrow" ); + sType = sDownArrow; + } break; + case XML_stripedRightArrow: { + static const OUString sStripedRightArrow = CREATE_OUSTRING( "striped-right-arrow" ); + sType = sStripedRightArrow; + } break; + case XML_notchedRightArrow: { + static const OUString sNotchedRightArrow = CREATE_OUSTRING( "notched-right-arrow" ); + sType = sNotchedRightArrow; + } break; + case XML_bentUpArrow: { + static const OUString sBentUpArrow = CREATE_OUSTRING( "mso-spt90" ); + sType = sBentUpArrow; + } break; + case XML_leftRightArrow: { + static const OUString sLeftRightArrow = CREATE_OUSTRING( "left-right-arrow" ); + sType = sLeftRightArrow; + } break; + case XML_upDownArrow: { + static const OUString sUpDownArrow = CREATE_OUSTRING( "up-down-arrow" ); + sType = sUpDownArrow; + } break; + case XML_leftUpArrow: { + static const OUString sLeftUpArrow = CREATE_OUSTRING( "mso-spt89" ); + sType = sLeftUpArrow; + } break; + case XML_leftRightUpArrow: { + static const OUString sLeftRightUpArrow = CREATE_OUSTRING( "mso-spt182" ); + sType = sLeftRightUpArrow; + } break; + case XML_quadArrow: { + static const OUString sQuadArrow = CREATE_OUSTRING( "quad-arrow" ); + sType = sQuadArrow; + } break; + case XML_leftArrowCallout: { + static const OUString sLeftArrowCallout = CREATE_OUSTRING( "left-arrow-callout" ); + sType = sLeftArrowCallout; + } break; + case XML_rightArrowCallout: { + static const OUString sRightArrowCallout = CREATE_OUSTRING( "right-arrow-callout" ); + sType = sRightArrowCallout; + } break; + case XML_upArrowCallout: { + static const OUString sUpArrowCallout = CREATE_OUSTRING( "up-arrow-callout" ); + sType = sUpArrowCallout; + } break; + case XML_downArrowCallout: { + static const OUString sDownArrowCallout = CREATE_OUSTRING( "down-arrow-callout" ); + sType = sDownArrowCallout; + } break; + case XML_leftRightArrowCallout: { + static const OUString sLeftRightArrowCallout = CREATE_OUSTRING( "left-right-arrow-callout" ); + sType = sLeftRightArrowCallout; + } break; + case XML_upDownArrowCallout: { + static const OUString sUpDownArrowCallout = CREATE_OUSTRING( "up-down-arrow-callout" ); + sType = sUpDownArrowCallout; + } break; + case XML_quadArrowCallout: { + static const OUString sQuadArrowCallout = CREATE_OUSTRING( "quad-arrow-callout" ); + sType = sQuadArrowCallout; + } break; + case XML_bentArrow: { + static const OUString sBentArrow = CREATE_OUSTRING( "mso-spt91" ); + sType = sBentArrow; + } break; + case XML_uturnArrow: { + static const OUString sUTurnArrow = CREATE_OUSTRING( "mso-spt101" ); + sType = sUTurnArrow; + } break; + case XML_leftCircularArrow: // TODO + case XML_leftRightCircularArrow: // TODO + case XML_circularArrow: { + static const OUString sCircularArrow = CREATE_OUSTRING( "circular-arrow" ); + sType = sCircularArrow; + } break; + case XML_curvedRightArrow: { + static const OUString sCurvedRightArrow = CREATE_OUSTRING( "mso-spt102" ); + sType = sCurvedRightArrow; + } break; + case XML_curvedLeftArrow: { + static const OUString sCurvedLeftArrow = CREATE_OUSTRING( "mso-spt103" ); + sType = sCurvedLeftArrow; + } break; + case XML_curvedUpArrow: { + static const OUString sCurvedUpArrow = CREATE_OUSTRING( "mso-spt104" ); + sType = sCurvedUpArrow; + } break; + case XML_swooshArrow: // TODO + case XML_curvedDownArrow: { + static const OUString sCurvedDownArrow = CREATE_OUSTRING( "mso-spt105" ); + sType = sCurvedDownArrow; + } break; + case XML_cube: { + static const OUString sCube = CREATE_OUSTRING( "cube" ); + sType = sCube; + } break; + case XML_can: { + static const OUString sCan = CREATE_OUSTRING( "can" ); + sType = sCan; + } break; + case XML_lightningBolt: { + static const OUString sLightningBolt = CREATE_OUSTRING( "lightning" ); + sType = sLightningBolt; + } break; + case XML_heart: { + static const OUString sHeart = CREATE_OUSTRING( "heart" ); + sType = sHeart; + } break; + case XML_sun: { + static const OUString sSun = CREATE_OUSTRING( "sun" ); + sType = sSun; + } break; + case XML_moon: { + static const OUString sMoon = CREATE_OUSTRING( "moon" ); + sType = sMoon; + } break; + case XML_smileyFace: { + static const OUString sSmileyFace = CREATE_OUSTRING( "smiley" ); + sType = sSmileyFace; + } break; + case XML_irregularSeal1: { + static const OUString sIrregularSeal1 = CREATE_OUSTRING( "mso-spt71" ); + sType = sIrregularSeal1; + } break; + case XML_irregularSeal2: { + static const OUString sIrregularSeal2 = CREATE_OUSTRING( "bang" ); + sType = sIrregularSeal2; + } break; + case XML_foldedCorner: { + static const OUString sFoldedCorner = CREATE_OUSTRING( "paper" ); + sType = sFoldedCorner; + } break; + case XML_bevel: { + static const OUString sBevel = CREATE_OUSTRING( "quad-bevel" ); + sType = sBevel; + } break; + case XML_halfFrame: // TODO + case XML_corner: // TODO + case XML_diagStripe: // TODO + case XML_chord: // TODO + case XML_frame: { + static const OUString sFrame = CREATE_OUSTRING( "mso-spt75" ); + sType = sFrame; + } break; + case XML_arc: { + static const OUString sArc = CREATE_OUSTRING( "mso-spt19" ); + sType = sArc; + } break; + case XML_leftBracket: { + static const OUString sLeftBracket = CREATE_OUSTRING( "left-bracket" ); + sType = sLeftBracket; + } break; + case XML_rightBracket: { + static const OUString sRightBracket = CREATE_OUSTRING( "right-bracket" ); + sType = sRightBracket; + } break; + case XML_leftBrace: { + static const OUString sLeftBrace = CREATE_OUSTRING( "left-brace" ); + sType = sLeftBrace; + } break; + case XML_rightBrace: { + static const OUString sRightBrace = CREATE_OUSTRING( "right-brace" ); + sType = sRightBrace; + } break; + case XML_bracketPair: { + static const OUString sBracketPair = CREATE_OUSTRING( "bracket-pair" ); + sType = sBracketPair; + } break; + case XML_bracePair: { + static const OUString sBracePair = CREATE_OUSTRING( "brace-pair" ); + sType = sBracePair; + } break; + case XML_straightConnector1: { + static const OUString sStraightConnector1 = CREATE_OUSTRING( "mso-spt32" ); + sType = sStraightConnector1; + } break; + case XML_bentConnector2: { + static const OUString sBentConnector2 = CREATE_OUSTRING( "mso-spt33" ); + sType = sBentConnector2; + } break; + case XML_bentConnector3: { + static const OUString sBentConnector3 = CREATE_OUSTRING( "mso-spt34" ); + sType = sBentConnector3; + } break; + case XML_bentConnector4: { + static const OUString sBentConnector4 = CREATE_OUSTRING( "mso-spt35" ); + sType = sBentConnector4; + } break; + case XML_bentConnector5: { + static const OUString sBentConnector5 = CREATE_OUSTRING( "mso-spt36" ); + sType = sBentConnector5; + } break; + case XML_curvedConnector2: { + static const OUString sCurvedConnector2 = CREATE_OUSTRING( "mso-spt37" ); + sType = sCurvedConnector2; + } break; + case XML_curvedConnector3: { + static const OUString sCurvedConnector3 = CREATE_OUSTRING( "mso-spt38" ); + sType = sCurvedConnector3; + } break; + case XML_curvedConnector4: { + static const OUString sCurvedConnector4 = CREATE_OUSTRING( "mso-spt39" ); + sType = sCurvedConnector4; + } break; + case XML_curvedConnector5: { + static const OUString sCurvedConnector5 = CREATE_OUSTRING( "mso-spt40" ); + sType = sCurvedConnector5; + } break; + case XML_callout1: { + static const OUString sCallout1 = CREATE_OUSTRING( "mso-spt41" ); + sType = sCallout1; + } break; + case XML_callout2: { + static const OUString sCallout2 = CREATE_OUSTRING( "mso-spt42" ); + sType = sCallout2; + } break; + case XML_callout3: { + static const OUString sCallout3 = CREATE_OUSTRING( "mso-spt43" ); + sType = sCallout3; + } break; + case XML_accentCallout1: { + static const OUString sAccentCallout1 = CREATE_OUSTRING( "mso-spt44" ); + sType = sAccentCallout1; + } break; + case XML_accentCallout2: { + static const OUString sAccentCallout2 = CREATE_OUSTRING( "mso-spt45" ); + sType = sAccentCallout2; + } break; + case XML_accentCallout3: { + static const OUString sAccentCallout3 = CREATE_OUSTRING( "mso-spt46" ); + sType = sAccentCallout3; + } break; + case XML_borderCallout1: { + static const OUString sBorderCallout1 = CREATE_OUSTRING( "line-callout-1" ); + sType = sBorderCallout1; + } break; + case XML_borderCallout2: { + static const OUString sBorderCallout2 = CREATE_OUSTRING( "line-callout-2" ); + sType = sBorderCallout2; + } break; + case XML_borderCallout3: { + static const OUString sBorderCallout3 = CREATE_OUSTRING( "mso-spt49" ); + sType = sBorderCallout3; + } break; + case XML_accentBorderCallout1: { + static const OUString sAccentBorderCallout1 = CREATE_OUSTRING( "mso-spt50" ); + sType = sAccentBorderCallout1; + } break; + case XML_accentBorderCallout2: { + static const OUString sAccentBorderCallout2 = CREATE_OUSTRING( "mso-spt51" ); + sType = sAccentBorderCallout2; + } break; + case XML_accentBorderCallout3: { + static const OUString sAccentBorderCallout3 = CREATE_OUSTRING( "mso-spt52" ); + sType = sAccentBorderCallout3; + } break; + case XML_wedgeRectCallout: { + static const OUString sWedgeRectCallout = CREATE_OUSTRING( "rectangular-callout" ); + sType = sWedgeRectCallout; + } break; + case XML_wedgeRoundRectCallout: { + static const OUString sWedgeRoundRectCallout = CREATE_OUSTRING( "round-rectangular-callout" ); + sType = sWedgeRoundRectCallout; + } break; + case XML_wedgeEllipseCallout: { + static const OUString sWedgeEllipseCallout = CREATE_OUSTRING( "round-callout" ); + sType = sWedgeEllipseCallout; + } break; + case XML_cloud: // TODO + case XML_cloudCallout: { + static const OUString sCloudCallout = CREATE_OUSTRING( "cloud-callout" ); + sType = sCloudCallout; + } break; + case XML_ribbon: { + static const OUString sRibbon = CREATE_OUSTRING( "mso-spt53" ); + sType = sRibbon; + } break; + case XML_ribbon2: { + static const OUString sRibbon2 = CREATE_OUSTRING( "mso-spt54" ); + sType = sRibbon2; + } break; + case XML_ellipseRibbon: { + static const OUString sEllipseRibbon = CREATE_OUSTRING( "mso-spt107" ); + sType = sEllipseRibbon; + } break; + case XML_leftRightRibbon: // TODO + case XML_ellipseRibbon2: { + static const OUString sEllipseRibbon2 = CREATE_OUSTRING( "mso-spt108" ); + sType = sEllipseRibbon2; + } break; + case XML_verticalScroll: { + static const OUString sVerticalScroll = CREATE_OUSTRING( "vertical-scroll" ); + sType = sVerticalScroll; + } break; + case XML_horizontalScroll: { + static const OUString sHorizontalScroll = CREATE_OUSTRING( "horizontal-scroll" ); + sType = sHorizontalScroll; + } break; + case XML_wave: { + static const OUString sWave = CREATE_OUSTRING( "mso-spt64" ); + sType = sWave; + } break; + case XML_doubleWave: { + static const OUString sDoubleWave = CREATE_OUSTRING( "mso-spt188" ); + sType = sDoubleWave; + } break; + case XML_plus: { + static const OUString sPlus = CREATE_OUSTRING( "cross" ); + sType = sPlus; + } break; + case XML_flowChartProcess: { + static const OUString sFlowChartProcess = CREATE_OUSTRING( "flowchart-process" ); + sType = sFlowChartProcess; + } break; + case XML_flowChartDecision: { + static const OUString sFlowChartDecision = CREATE_OUSTRING( "flowchart-decision" ); + sType = sFlowChartDecision; + } break; + case XML_flowChartInputOutput: { + static const OUString sFlowChartInputOutput = CREATE_OUSTRING( "flowchart-data" ); + sType = sFlowChartInputOutput; + } break; + case XML_flowChartPredefinedProcess: { + static const OUString sFlowChartPredefinedProcess = CREATE_OUSTRING( "flowchart-predefined-process" ); + sType = sFlowChartPredefinedProcess; + } break; + case XML_flowChartInternalStorage: { + static const OUString sFlowChartInternalStorage = CREATE_OUSTRING( "flowchart-internal-storage" ); + sType = sFlowChartInternalStorage; + } break; + case XML_flowChartDocument: { + static const OUString sFlowChartDocument = CREATE_OUSTRING( "flowchart-document" ); + sType = sFlowChartDocument; + } break; + case XML_flowChartMultidocument: { + static const OUString sFlowChartMultidocument = CREATE_OUSTRING( "flowchart-multidocument" ); + sType = sFlowChartMultidocument; + } break; + case XML_flowChartTerminator: { + static const OUString sFlowChartTerminator = CREATE_OUSTRING( "flowchart-terminator" ); + sType = sFlowChartTerminator; + } break; + case XML_flowChartPreparation : { + static const OUString sFlowChartPreparation = CREATE_OUSTRING( "flowchart-preparation" ); + sType = sFlowChartPreparation; + } break; + case XML_flowChartManualInput: { + static const OUString sFlowChartManualInput = CREATE_OUSTRING( "flowchart-manual-input" ); + sType = sFlowChartManualInput; + } break; + case XML_flowChartManualOperation: { + static const OUString sFlowChartManualOperation = CREATE_OUSTRING( "flowchart-manual-operation" ); + sType = sFlowChartManualOperation; + } break; + case XML_flowChartConnector: { + static const OUString sFlowChartConnector = CREATE_OUSTRING( "flowchart-connector" ); + sType = sFlowChartConnector; + } break; + case XML_flowChartPunchedCard: { + static const OUString sFlowChartPunchedCard = CREATE_OUSTRING( "flowchart-card" ); + sType = sFlowChartPunchedCard; + } break; + case XML_flowChartPunchedTape: { + static const OUString sFlowChartPunchedTape = CREATE_OUSTRING( "flowchart-punched-tape" ); + sType = sFlowChartPunchedTape; + } break; + case XML_flowChartSummingJunction: { + static const OUString sFlowChartSummingJunction = CREATE_OUSTRING( "flowchart-summing-junction" ); + sType = sFlowChartSummingJunction; + } break; + case XML_flowChartOr: { + static const OUString sFlowChartOr = CREATE_OUSTRING( "flowchart-or" ); + sType = sFlowChartOr; + } break; + case XML_flowChartCollate: { + static const OUString sFlowChartCollate = CREATE_OUSTRING( "flowchart-collate" ); + sType = sFlowChartCollate; + } break; + case XML_flowChartSort: { + static const OUString sFlowChartSort = CREATE_OUSTRING( "flowchart-sort" ); + sType = sFlowChartSort; + } break; + case XML_flowChartExtract: { + static const OUString sFlowChartExtract = CREATE_OUSTRING( "flowchart-extract" ); + sType = sFlowChartExtract; + } break; + case XML_flowChartMerge: { + static const OUString sFlowChartMerge = CREATE_OUSTRING( "flowchart-merge" ); + sType = sFlowChartMerge; + } break; + case XML_flowChartOfflineStorage: { + static const OUString sFlowChartOfflineStorage = CREATE_OUSTRING( "mso-spt129" ); + sType = sFlowChartOfflineStorage; + } break; + case XML_flowChartOnlineStorage: { + static const OUString sFlowChartOnlineStorage = CREATE_OUSTRING( "flowchart-stored-data" ); + sType = sFlowChartOnlineStorage; + } break; + case XML_flowChartMagneticTape: { + static const OUString sFlowChartMagneticTape = CREATE_OUSTRING( "flowchart-sequential-access" ); + sType = sFlowChartMagneticTape; + } break; + case XML_flowChartMagneticDisk: { + static const OUString sFlowChartMagneticDisk = CREATE_OUSTRING( "flowchart-magnetic-disk" ); + sType = sFlowChartMagneticDisk; + } break; + case XML_flowChartMagneticDrum: { + static const OUString sFlowChartMagneticDrum = CREATE_OUSTRING( "flowchart-direct-access-storage" ); + sType = sFlowChartMagneticDrum; + } break; + case XML_flowChartDisplay: { + static const OUString sFlowChartDisplay = CREATE_OUSTRING( "flowchart-display" ); + sType = sFlowChartDisplay; + } break; + case XML_flowChartDelay: { + static const OUString sFlowChartDelay = CREATE_OUSTRING( "flowchart-delay" ); + sType = sFlowChartDelay; + } break; + case XML_flowChartAlternateProcess: { + static const OUString sFlowChartAlternateProcess = CREATE_OUSTRING( "flowchart-alternate-process" ); + sType = sFlowChartAlternateProcess; + } break; + case XML_flowChartOffpageConnector: { + static const OUString sFlowChartOffpageConnector = CREATE_OUSTRING( "flowchart-off-page-connector" ); + sType = sFlowChartOffpageConnector; + } break; + case XML_actionButtonBlank: { + static const OUString sActionButtonBlank = CREATE_OUSTRING( "mso-spt189" ); + sType = sActionButtonBlank; + } break; + case XML_actionButtonHome: { + static const OUString sActionButtonHome = CREATE_OUSTRING( "mso-spt190" ); + sType = sActionButtonHome; + } break; + case XML_actionButtonHelp: { + static const OUString sActionButtonHelp = CREATE_OUSTRING( "mso-spt191" ); + sType = sActionButtonHelp; + } break; + case XML_actionButtonInformation: { + static const OUString sActionButtonInformation = CREATE_OUSTRING( "mso-spt192" ); + sType = sActionButtonInformation; + } break; + case XML_actionButtonForwardNext: { + static const OUString sActionButtonForwardNext = CREATE_OUSTRING( "mso-spt193" ); + sType = sActionButtonForwardNext; + } break; + case XML_actionButtonBackPrevious: { + static const OUString sActionButtonBackPrevious = CREATE_OUSTRING( "mso-spt194" ); + sType = sActionButtonBackPrevious; + } break; + case XML_actionButtonEnd: { + static const OUString sActionButtonEnd = CREATE_OUSTRING( "mso-spt195" ); + sType = sActionButtonEnd; + } break; + case XML_actionButtonBeginning: { + static const OUString sActionButtonBeginning = CREATE_OUSTRING( "mso-spt196" ); + sType = sActionButtonBeginning; + } break; + case XML_actionButtonReturn: { + static const OUString sActionButtonReturn = CREATE_OUSTRING( "mso-spt197" ); + sType = sActionButtonReturn; + } break; + case XML_actionButtonDocument: { + static const OUString sActionButtonDocument = CREATE_OUSTRING( "mso-spt198" ); + sType = sActionButtonDocument; + } break; + case XML_actionButtonSound: { + static const OUString sActionButtonSound = CREATE_OUSTRING( "mso-spt199" ); + sType = sActionButtonSound; + } break; + case XML_actionButtonMovie: { + static const OUString sActionButtonMovie = CREATE_OUSTRING( "mso-spt200" ); + sType = sActionButtonMovie; + } break; + case XML_gear6: // TODO + case XML_gear9: // TODO + case XML_funnel: // TODO + case XML_mathPlus: // TODO + case XML_mathMinus: // TODO + case XML_mathMultiply: // TODO + case XML_mathDivide: // TODO + case XML_mathEqual: // TODO + case XML_mathNotEqual: // TODO + case XML_cornerTabs: // TODO + case XML_squareTabs: // TODO + case XML_plaqueTabs: // TODO + case XML_chartX: // TODO + case XML_chartStar: // TODO + case XML_chartPlus: { // TODO + static const OUString sRectangle = CREATE_OUSTRING( "rectangle" ); + sType = sRectangle; + } break; + default: + break; + } + return sType; +} + +static OUString GetTextShapeType( sal_Int32 nType ) +{ + OUString sType; + switch( nType ) + { + case XML_textNoShape: // TODO + case XML_textPlain: { + static const OUString sTextPlain = CREATE_OUSTRING( "fontwork-plain-text" ); + sType = sTextPlain; + } break; + case XML_textStop: { + static const OUString sTextStop = CREATE_OUSTRING( "fontwork-stop" ); + sType = sTextStop; + } break; + case XML_textTriangle: { + static const OUString sTextTriangle = CREATE_OUSTRING( "fontwork-triangle-up" ); + sType = sTextTriangle; + } break; + case XML_textTriangleInverted: { + static const OUString sTextTriangleInverted = CREATE_OUSTRING( "fontwork-triangle-down" ); + sType = sTextTriangleInverted; + } break; + case XML_textChevron: { + static const OUString sTextChevron = CREATE_OUSTRING( "fontwork-chevron-up" ); + sType = sTextChevron; + } break; + case XML_textChevronInverted: { + static const OUString sTextChevronInverted = CREATE_OUSTRING( "fontwork-chevron-down" ); + sType = sTextChevronInverted; + } break; + case XML_textRingInside: { + static const OUString sTextRingInside = CREATE_OUSTRING( "mso-spt142" ); + sType = sTextRingInside; + } break; + case XML_textRingOutside: { + static const OUString sTextRingOutside = CREATE_OUSTRING( "mso-spt143" ); + sType = sTextRingOutside; + } break; + case XML_textArchUp: { + static const OUString sTextArchUp = CREATE_OUSTRING( "fontwork-arch-up-curve" ); + sType = sTextArchUp; + } break; + case XML_textArchDown: { + static const OUString sTextArchDown = CREATE_OUSTRING( "fontwork-arch-down-curve" ); + sType = sTextArchDown; + } break; + case XML_textCircle: { + static const OUString sTextCircle = CREATE_OUSTRING( "fontwork-circle-curve" ); + sType = sTextCircle; + } break; + case XML_textButton: { + static const OUString sTextButton = CREATE_OUSTRING( "fontwork-open-circle-curve" ); + sType = sTextButton; + } break; + case XML_textArchUpPour: { + static const OUString sTextArchUpPour = CREATE_OUSTRING( "fontwork-arch-up-pour" ); + sType = sTextArchUpPour; + } break; + case XML_textArchDownPour: { + static const OUString sTextArchDownPour = CREATE_OUSTRING( "fontwork-arch-down-pour" ); + sType = sTextArchDownPour; + } break; + case XML_textCirclePour: { + static const OUString sTextCirclePour = CREATE_OUSTRING( "fontwork-circle-pour" ); + sType = sTextCirclePour; + } break; + case XML_textButtonPour: { + static const OUString sTextButtonPour = CREATE_OUSTRING( "fontwork-open-circle-pour" ); + sType = sTextButtonPour; + } break; + case XML_textCurveUp: { + static const OUString sTextCurveUp = CREATE_OUSTRING( "fontwork-curve-up" ); + sType = sTextCurveUp; + } break; + case XML_textCurveDown: { + static const OUString sTextCurveDown = CREATE_OUSTRING( "fontwork-curve-down" ); + sType = sTextCurveDown; + } break; + case XML_textCanUp: { + static const OUString sTextCanUp = CREATE_OUSTRING( "mso-spt174" ); + sType = sTextCanUp; + } break; + case XML_textCanDown: { + static const OUString sTextCanDown = CREATE_OUSTRING( "mso-spt175" ); + sType = sTextCanDown; + } break; + case XML_textWave1: { + static const OUString sTextWave1 = CREATE_OUSTRING( "fontwork-wave" ); + sType = sTextWave1; + } break; + case XML_textWave2: { + static const OUString sTextWave2 = CREATE_OUSTRING( "mso-spt157" ); + sType = sTextWave2; + } break; + case XML_textDoubleWave1: { + static const OUString sTextDoubleWave1 = CREATE_OUSTRING( "mso-spt158" ); + sType = sTextDoubleWave1; + } break; + case XML_textWave4: { + static const OUString sTextWave4 = CREATE_OUSTRING( "mso-spt159" ); + sType = sTextWave4; + } break; + case XML_textInflate: { + static const OUString sTextInflate = CREATE_OUSTRING( "fontwork-inflate" ); + sType = sTextInflate; + } break; + case XML_textDeflate: { + static const OUString sTextDeflate = CREATE_OUSTRING( "mso-spt161" ); + sType = sTextDeflate; + } break; + case XML_textInflateBottom: { + static const OUString sTextInflateBottom = CREATE_OUSTRING( "mso-spt162" ); + sType = sTextInflateBottom; + } break; + case XML_textDeflateBottom: { + static const OUString sTextDeflateBottom = CREATE_OUSTRING( "mso-spt163" ); + sType = sTextDeflateBottom; + } break; + case XML_textInflateTop: { + static const OUString sTextInflateTop = CREATE_OUSTRING( "mso-spt164" ); + sType = sTextInflateTop; + } break; + case XML_textDeflateTop: { + static const OUString sTextDeflateTop = CREATE_OUSTRING( "mso-spt165" ); + sType = sTextDeflateTop; + } break; + case XML_textDeflateInflate: { + static const OUString sTextDeflateInflate = CREATE_OUSTRING( "mso-spt166" ); + sType = sTextDeflateInflate; + } break; + case XML_textDeflateInflateDeflate: { + static const OUString sTextDeflateInflateDeflate = CREATE_OUSTRING( "mso-spt167" ); + sType = sTextDeflateInflateDeflate; + } break; + case XML_textFadeRight: { + static const OUString sTextFadeRight = CREATE_OUSTRING( "fontwork-fade-right" ); + sType = sTextFadeRight; + } break; + case XML_textFadeLeft: { + static const OUString sTextFadeLeft = CREATE_OUSTRING( "fontwork-fade-left" ); + sType = sTextFadeLeft; + } break; + case XML_textFadeUp: { + static const OUString sTextFadeUp = CREATE_OUSTRING( "fontwork-fade-up" ); + sType = sTextFadeUp; + } break; + case XML_textFadeDown: { + static const OUString sTextFadeDown = CREATE_OUSTRING( "fontwork-fade-down" ); + sType = sTextFadeDown; + } break; + case XML_textSlantUp: { + static const OUString sTextSlantUp = CREATE_OUSTRING( "fontwork-slant-up" ); + sType = sTextSlantUp; + } break; + case XML_textSlantDown: { + static const OUString sTextSlantDown = CREATE_OUSTRING( "fontwork-slant-down" ); + sType = sTextSlantDown; + } break; + case XML_textCascadeUp: { + static const OUString sTextCascadeUp = CREATE_OUSTRING( "fontwork-fade-up-and-right" ); + sType = sTextCascadeUp; + } break; + case XML_textCascadeDown: { + static const OUString sTextCascadeDown = CREATE_OUSTRING( "fontwork-fade-up-and-left" ); + sType = sTextCascadeDown; + } break; + default: + break; + } + return sType; +} + +// --------------------------------------------------------------------- +// CT_CustomGeometry2D +CustomShapeGeometryContext::CustomShapeGeometryContext( const FragmentHandlerRef& xHandler, const Reference< XFastAttributeList >& /* xAttribs */, CustomShapeProperties& rCustomShapeProperties ) +: Context( xHandler ) +, mrCustomShapeProperties( rCustomShapeProperties ) +{ +} + +Reference< XFastContextHandler > CustomShapeGeometryContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +{ + switch( aElementToken ) + { + // todo + case NMSP_DRAWINGML|XML_avLst: // CT_GeomGuideList adjust value list + case NMSP_DRAWINGML|XML_gdLst: // CT_GeomGuideList guide list + case NMSP_DRAWINGML|XML_ahLst: // CT_AdjustHandleList adjust handle list + case NMSP_DRAWINGML|XML_cxnLst: // CT_ConnectionSiteList connection site list + case NMSP_DRAWINGML|XML_rect: // CT_GeomRectList geometry rect list + case NMSP_DRAWINGML|XML_pathLst: // CT_Path2DList 2d path list + break; + } + + Reference< XFastContextHandler > xEmpty; + return xEmpty; +} + +// --------------------------------------------------------------------- +// CT_PresetGeometry2D +PresetShapeGeometryContext::PresetShapeGeometryContext( const FragmentHandlerRef& xHandler, const Reference< XFastAttributeList >& xAttribs, CustomShapeProperties& rCustomShapeProperties ) +: Context( xHandler ) +, mrCustomShapeProperties( rCustomShapeProperties ) +{ + OUString sShapeType; + sal_Int32 nShapeType = xAttribs->getOptionalValueToken( XML_prst, FastToken::DONTKNOW ); + if ( nShapeType != FastToken::DONTKNOW ) + sShapeType = GetShapeType( nShapeType ); + OSL_ENSURE( sShapeType.getLength(), "oox::drawingml::CustomShapeCustomGeometryContext::CustomShapeCustomGeometryContext(), unknown shape type" ); + mrCustomShapeProperties.setShapePresetType( sShapeType ); +} + +Reference< XFastContextHandler > PresetShapeGeometryContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +{ + if ( aElementToken == ( NMSP_DRAWINGML | XML_avLst ) ) + return new AdjustmentValueContext( getHandler(), mrCustomShapeProperties ); + else + return this; +} + +// --------------------------------------------------------------------- +// CT_PresetTextShape +PresetTextShapeContext::PresetTextShapeContext( const FragmentHandlerRef& xHandler, const Reference< XFastAttributeList >& xAttribs, CustomShapeProperties& rCustomShapeProperties ) +: Context( xHandler ) +, mrCustomShapeProperties( rCustomShapeProperties ) +{ + OUString sShapeType; + sal_Int32 nShapeType = xAttribs->getOptionalValueToken( XML_prst, FastToken::DONTKNOW ); + if ( nShapeType != FastToken::DONTKNOW ) + sShapeType = GetTextShapeType( nShapeType ); + OSL_ENSURE( sShapeType.getLength(), "oox::drawingml::CustomShapeCustomGeometryContext::CustomShapeCustomGeometryContext(), unknown shape type" ); + mrCustomShapeProperties.setShapePresetType( sShapeType ); +} + +Reference< XFastContextHandler > PresetTextShapeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +{ + switch( aElementToken ) + { + // todo + case NMSP_DRAWINGML|XML_avLst: // CT_GeomGuideList adjust value list + case NMSP_DRAWINGML|XML_gdLst: // CT_GeomGuideList guide list + case NMSP_DRAWINGML|XML_ahLst: // CT_AdjustHandleList adjust handle list + case NMSP_DRAWINGML|XML_cxnLst: // CT_ConnectionSiteList connection site list + case NMSP_DRAWINGML|XML_rect: // CT_GeomRectList geometry rect list + case NMSP_DRAWINGML|XML_pathLst: // CT_Path2DList 2d path list + break; + } + + Reference< XFastContextHandler > xEmpty; + return xEmpty; +} + +} } diff --git a/oox/source/drawingml/customshapeproperties.cxx b/oox/source/drawingml/customshapeproperties.cxx new file mode 100644 index 000000000000..255a986e7336 --- /dev/null +++ b/oox/source/drawingml/customshapeproperties.cxx @@ -0,0 +1,156 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: customshapeproperties.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include +#include "oox/drawingml/customshapeproperties.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" +#ifndef _SOLAR_H +#include +#endif +#include +#include +#include + +using rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::graphic; + +namespace oox { namespace drawingml { + +CustomShapeProperties::CustomShapeProperties() +{ +} +CustomShapeProperties::~CustomShapeProperties() +{ +} + +void CustomShapeProperties::apply( const CustomShapePropertiesPtr& /* rSourceCustomShapeProperties */ ) +{ + // not sure if this needs to be implemented +} + +void CustomShapeProperties::pushToPropSet( const ::oox::core::XmlFilterBase& /* rFilterBase */, + const Reference < XPropertySet >& xPropSet ) const +{ + const OUString sType = CREATE_OUSTRING( "Type" ); + if ( maShapePresetType.getLength() ) + { + + // XEnhancedCustomShapeDefaulter TODO +// const uno::Reference < drawing::XShape > xShape( xPropSet, UNO_QUERY ) ; // REMOVE THIS +// SdrObjCustomShape* pCustoObj = const_cast< SdrObjCustomShape* >( dynamic_cast< SdrObjCustomShape* >( GetSdrObjectFromXShape( xShape ) ) ) ; // REMOVE THIS +// if ( pCustoObj ) // REMOVE THIS +// pCustoObj->MergeDefaultAttributes( &sType ); // REMOVE THIS + + const rtl::OUString sCustomShapeGeometry( RTL_CONSTASCII_USTRINGPARAM( "CustomShapeGeometry" ) ); + uno::Any aGeoPropSet = xPropSet->getPropertyValue( sCustomShapeGeometry ); + uno::Sequence< beans::PropertyValue > aGeoPropSeq; + if ( aGeoPropSet >>= aGeoPropSeq ) + { + sal_Int32 i, nCount = aGeoPropSeq.getLength(); + for ( i = 0; i < nCount; i++ ) + { + const rtl::OUString sAdjustmentValues( RTL_CONSTASCII_USTRINGPARAM( "AdjustmentValues" ) ); + if ( aGeoPropSeq[ i ].Name.equals( sAdjustmentValues ) ) + { + uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq; + if ( aGeoPropSeq[ i ].Value >>= aAdjustmentSeq ) + { + sal_uInt32 j, nHighest = 0; + for( j = 0; j < maAdjustmentValues.size(); j++ ) + { + const rtl::OUString& rS( maAdjustmentValues[ j ].maName ); + if ( rS.getLength() > 3 ) + { + sal_uInt32 nVal = rS.copy( 3 ).toInt32(); + if ( ( nVal < 10 ) && ( nVal > nHighest ) ) + nHighest = nVal; + } + } + if ( nHighest > static_cast< sal_uInt32 >( aAdjustmentSeq.getLength() ) ) + aAdjustmentSeq.realloc( nHighest ); + + for ( j = 0; j < maAdjustmentValues.size(); j++ ) + { + sal_uInt32 nVal = maAdjustmentValues[ j ].maName.copy( 3 ).toInt32(); + if ( nVal-- ) + { + double fNewAdj = getValue( maAdjustmentValues, nVal ); + aAdjustmentSeq[ nVal ].State = beans::PropertyState_DIRECT_VALUE; + aAdjustmentSeq[ nVal ].Value <<= fNewAdj; + } + } + aGeoPropSeq[ i ].Value <<= aAdjustmentSeq; + xPropSet->setPropertyValue( sCustomShapeGeometry, Any( aGeoPropSeq ) ); + } + } + else if ( aGeoPropSeq[ i ].Name.equals( sType ) ) + { + aGeoPropSeq[ i ].Value <<= maShapePresetType; + } + } + } + } + else + { + PropertyMap aPropertyMap; + OUString sShapeType( CREATE_OUSTRING( "non-primitive" ) ); + aPropertyMap[ sType ] <<= sShapeType; + + + // converting the vector to a sequence + Sequence< PropertyValue > aSeq; + aPropertyMap.makeSequence( aSeq ); + static const rtl::OUString sCustomShapeGeometry( RTL_CONSTASCII_USTRINGPARAM( "CustomShapeGeometry" ) ); + xPropSet->setPropertyValue( sCustomShapeGeometry, Any( aSeq ) ); + } +} + +double CustomShapeProperties::getValue( const std::vector< CustomShapeGuide >& rGuideList, sal_uInt32 nIndex ) const +{ + double fRet = 0.0; + if ( nIndex < rGuideList.size() ) + { + + } + return fRet; +} + +} } diff --git a/oox/source/drawingml/diagram/datamodelcontext.cxx b/oox/source/drawingml/diagram/datamodelcontext.cxx new file mode 100644 index 000000000000..d7502ea4781a --- /dev/null +++ b/oox/source/drawingml/diagram/datamodelcontext.cxx @@ -0,0 +1,336 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: datamodelcontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:57 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/diagram/datamodelcontext.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/core/skipcontext.hxx" +#include "oox/drawingml/fillpropertiesgroupcontext.hxx" +#include "oox/drawingml/shapepropertiescontext.hxx" +#include "oox/drawingml/textbodycontext.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +namespace oox { namespace drawingml { + + + +// CL_Cxn +class CxnContext + : public Context +{ +public: + CxnContext( const FragmentHandlerRef& xParent, + const Reference< XFastAttributeList >& xAttribs, + const dgm::ConnectionPtr & pConnection ) + : Context( xParent ) + , mpConnection( pConnection ) + { + pConnection->msModelId = xAttribs->getOptionalValue( XML_modelId ); + pConnection->msSourceId = xAttribs->getOptionalValue( XML_srcId ); + pConnection->msDestId = xAttribs->getOptionalValue( XML_destId ); + pConnection->msPresId = xAttribs->getOptionalValue( XML_presId ); + pConnection->msSibTransId = xAttribs->getOptionalValue( XML_sibTransId ); + AttributeList attribs( xAttribs ); + pConnection->mnSourceOrder = attribs.getInteger( XML_srcOrd, 0 ); + pConnection->mnDestOrder = attribs.getInteger( XML_destOrd, 0 ); + } + + virtual Reference< XFastContextHandler > SAL_CALL + createFastChildContext( sal_Int32 aElementToken, + const Reference< XFastAttributeList >& /*xAttribs*/ ) + throw (SAXException, RuntimeException) + { + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case NMSP_DIAGRAM|XML_extLst: + xRet.set( new SkipContext( getHandler() ) ); + break; + default: + break; + } + if( !xRet.is() ) + xRet.set( this ); + return xRet; + } +private: + dgm::ConnectionPtr mpConnection; +}; + + +// CT_CxnList +class CxnListContext + : public Context +{ +public: + CxnListContext( const FragmentHandlerRef& xParent, dgm::Connections & aConnections ) + : Context( xParent ) + , maConnections( aConnections ) + { + } + virtual Reference< XFastContextHandler > SAL_CALL + createFastChildContext( sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) + { + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case NMSP_DIAGRAM|XML_cxn: + { + dgm::ConnectionPtr pConnection( new dgm::Connection() ); + maConnections.push_back( pConnection ); + xRet.set( new CxnContext( getHandler( ), xAttribs, pConnection ) ); + break; + } + default: + break; + } + if( !xRet.is() ) + xRet.set( this ); + return xRet; + } + +private: + dgm::Connections & maConnections; +}; + + + +// CL_Pt +class PtContext + : public Context +{ +public: + PtContext( const FragmentHandlerRef& xParent, + const Reference< XFastAttributeList >& xAttribs, + const dgm::PointPtr & pPoint) + : Context( xParent ) + , mpPoint( pPoint ) + { + // both can be either an int or a uuid + mpPoint->setCnxId( xAttribs->getOptionalValue( XML_cxnId ) ); + mpPoint->setModelId( xAttribs->getOptionalValue( XML_modelId ) ); + // + mpPoint->setType( xAttribs->getOptionalValueToken( XML_type, 0 ) ); + } + + virtual Reference< XFastContextHandler > SAL_CALL + createFastChildContext( sal_Int32 aElementToken, + const Reference< XFastAttributeList >& /*xAttribs*/ ) + throw (SAXException, RuntimeException) + { + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case NMSP_DIAGRAM|XML_extLst: + xRet.set( new SkipContext( getHandler() ) ); + break; + case NMSP_DIAGRAM|XML_prSet: + // TODO + // CT_ElemPropSet + break; + case NMSP_DIAGRAM|XML_spPr: + xRet = new ShapePropertiesContext( this, *(mpPoint->getShape().get()) ); + break; + case NMSP_DIAGRAM|XML_t: + xRet = new TextBodyContext( getHandler(), *(mpPoint->getShape().get()) ); + break; + default: + break; + } + if( !xRet.is() ) + xRet.set( this ); + return xRet; + } + +private: + dgm::PointPtr mpPoint; +}; + + + +// CT_PtList +class PtListContext + : public Context +{ +public: + PtListContext( const FragmentHandlerRef& xParent, dgm::Points & aPoints) + : Context( xParent ) + , maPoints( aPoints ) + { + } + virtual Reference< XFastContextHandler > SAL_CALL + createFastChildContext( sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) + { + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case NMSP_DIAGRAM|XML_pt: + { + // CT_Pt + dgm::PointPtr pPoint( new dgm::Point() ); + maPoints.push_back( pPoint ); + xRet.set( new PtContext( getHandler( ), xAttribs, pPoint ) ); + break; + } + default: + break; + } + if( !xRet.is() ) + xRet.set( this ); + return xRet; + } + +private: + dgm::Points & maPoints; +}; + +// CT_BackgroundFormatting +class BackgroundFormattingContext + : public Context +{ +public: + BackgroundFormattingContext( const FragmentHandlerRef& xParent, DiagramDataPtr & pModel ) + : Context( xParent ) + , mpDataModel( pModel ) + { + OSL_ENSURE( pModel, "the data model MUST NOT be NULL" ); + } + + virtual Reference< XFastContextHandler > SAL_CALL + createFastChildContext( sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) + { + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_blipFill: + case NMSP_DRAWINGML|XML_gradFill: + case NMSP_DRAWINGML|XML_grpFill: + case NMSP_DRAWINGML|XML_noFill: + case NMSP_DRAWINGML|XML_pattFill: + case NMSP_DRAWINGML|XML_solidFill: + // EG_FillProperties + xRet.set( FillPropertiesGroupContext::StaticCreateContext( getHandler( ), + aElementToken, + xAttribs, + *(mpDataModel->getFillProperties().get()) ) ); + break; + case NMSP_DRAWINGML|XML_effectDag: + case NMSP_DRAWINGML|XML_effectLst: + // TODO + // EG_EffectProperties + break; + default: + break; + } + if( !xRet.is() ) + xRet.set( this ); + return xRet; + } +private: + DiagramDataPtr mpDataModel; +}; + + + +DataModelContext::DataModelContext( const FragmentHandlerRef& xHandler, + const DiagramDataPtr & pDataModel ) + : Context( xHandler ) + , mpDataModel( pDataModel ) +{ + OSL_ENSURE( pDataModel, "Data Model must not be NULL" ); +} + + +DataModelContext::~DataModelContext() +{ + // some debug + mpDataModel->dump(); +} + + +Reference< XFastContextHandler > SAL_CALL +DataModelContext::createFastChildContext( ::sal_Int32 aElement, + const Reference< XFastAttributeList >& /*xAttribs*/ ) + throw ( SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElement ) + { + case NMSP_DIAGRAM|XML_cxnLst: + // CT_CxnList + xRet.set( new CxnListContext( getHandler( ), mpDataModel->getConnections() ) ); + break; + case NMSP_DIAGRAM|XML_ptLst: + // CT_PtList + xRet.set( new PtListContext( getHandler( ), mpDataModel->getPoints() ) ); + break; + case NMSP_DIAGRAM|XML_bg: + // CT_BackgroundFormatting + xRet.set( new BackgroundFormattingContext( getHandler(), mpDataModel ) ); + break; + case NMSP_DIAGRAM|XML_whole: + // CT_WholeE2oFormatting + // TODO + xRet.set( new SkipContext( getHandler() ) ); + break; + case NMSP_DIAGRAM|XML_extLst: + xRet.set( new SkipContext( getHandler() ) ); + break; + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; +} + +} } diff --git a/oox/source/drawingml/diagram/diagram.cxx b/oox/source/drawingml/diagram/diagram.cxx new file mode 100644 index 000000000000..04394b331f4b --- /dev/null +++ b/oox/source/drawingml/diagram/diagram.cxx @@ -0,0 +1,130 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: diagram.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:57 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + + +#include +#include + +#include "oox/drawingml/diagram/diagram.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + + +namespace oox { namespace drawingml { + +namespace dgm { + + +void Connection::dump() +{ + OSL_TRACE("dgm: cnx modelId %s, srcId %s, dstId %s", + OUSTRING_TO_CSTR( msModelId ), + OUSTRING_TO_CSTR( msSourceId ), + OUSTRING_TO_CSTR( msDestId ) ); +} + +Point::Point() + : mpShape( new Shape( "com.sun.star.drawing.GroupShape" ) ) + , mnType( 0 ) +{ +} + +void Point::dump() +{ + OSL_TRACE( "dgm: pt cnxId %s, modelId %s", + OUSTRING_TO_CSTR( msCnxId ), + OUSTRING_TO_CSTR( msModelId ) ); +} + + +} + + +DiagramData::DiagramData() + : mpFillProperties( new FillProperties( ) ) +{ +} + +void DiagramData::dump() +{ + OSL_TRACE("Dgm: DiagramData # of cnx: %d", maConnections.size() ); + std::for_each( maConnections.begin(), maConnections.end(), + boost::bind( &dgm::Connection::dump, _1 ) ); + OSL_TRACE("Dgm: DiagramData # of pt: %d", maPoints.size() ); + std::for_each( maPoints.begin(), maPoints.end(), + boost::bind( &dgm::Point::dump, _1 ) ); +} + + +void Diagram::setData( const DiagramDataPtr & pData) +{ + mpData = pData; +} + + +void Diagram::setLayout( const DiagramLayoutPtr & pLayout) +{ + mpLayout = pLayout; +} + +void Diagram::setQStyles( const DiagramQStylesPtr & pStyles) +{ + mpQStyles = pStyles; +} + + +void Diagram::setColors( const DiagramColorsPtr & pColors) +{ + mpColors = pColors; +} + + +void Diagram::addTo( const ShapePtr & pShape ) +{ + dgm::Points & aPoints( mpData->getPoints( ) ); + std::for_each( aPoints.begin(), aPoints.end(), + boost::bind( &Shape::addChild, boost::ref( pShape ), + boost::bind( &dgm::Point::getShape, _1 ) ) ); + + OSL_TRACE( "Dgm: addTo() # of childs %d", pShape->getChilds().size() ); + for( std::vector< ShapePtr >::iterator iter = pShape->getChilds().begin(); + iter != pShape->getChilds().end(); ++iter) + { + OSL_TRACE( "Dgm: shape name %s", OUSTRING_TO_CSTR( (*iter)->getName() ) ); + } +} + + +} } diff --git a/oox/source/drawingml/diagram/diagramdefinitioncontext.cxx b/oox/source/drawingml/diagram/diagramdefinitioncontext.cxx new file mode 100644 index 000000000000..d8d246efa3c2 --- /dev/null +++ b/oox/source/drawingml/diagram/diagramdefinitioncontext.cxx @@ -0,0 +1,124 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: diagramdefinitioncontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:57 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/core/skipcontext.hxx" +#include "layoutnodecontext.hxx" +#include "diagramdefinitioncontext.hxx" +#include "oox/drawingml/diagram/datamodelcontext.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using ::rtl::OUString; + +namespace oox { namespace drawingml { + + +// CT_DiagramDefinition +DiagramDefinitionContext::DiagramDefinitionContext( const FragmentHandlerRef& xHandler, + const Reference< XFastAttributeList >& xAttributes, + const DiagramLayoutPtr &pLayout ) + : Context( xHandler ) + , mpLayout( pLayout ) +{ + OSL_TRACE( "OOX: DiagramDefinitionContext::DiagramDefinitionContext()" ); + mpLayout->setDefStyle( xAttributes->getOptionalValue( XML_defStyle ) ); + OUString sValue = xAttributes->getOptionalValue( XML_minVer ); + if( sValue.getLength() == 0 ) + { + sValue = CREATE_OUSTRING( "http://schemas.openxmlformats.org/drawingml/2006/diagram" ); + } + mpLayout->setMinVer( sValue ); + mpLayout->setUniqueId( xAttributes->getOptionalValue( XML_uniqueId ) ); +} + + +DiagramDefinitionContext::~DiagramDefinitionContext() +{ + mpLayout->getNode()->dump(0); +} + +void SAL_CALL DiagramDefinitionContext::endFastElement( ::sal_Int32 ) + throw (SAXException, RuntimeException) +{ + +} + + +Reference< XFastContextHandler > SAL_CALL +DiagramDefinitionContext::createFastChildContext( ::sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElement ) + { + case NMSP_DIAGRAM|XML_title: + mpLayout->setTitle( xAttribs->getOptionalValue( XML_val ) ); + break; + case NMSP_DIAGRAM|XML_desc: + mpLayout->setDesc( xAttribs->getOptionalValue( XML_val ) ); + break; + case NMSP_DIAGRAM|XML_layoutNode: + mpLayout->getNode().reset( new LayoutNode() ); + xRet.set( new LayoutNodeContext( getHandler(), xAttribs, mpLayout->getNode() ) ); + break; + case NMSP_DIAGRAM|XML_clrData: + // TODO, does not matter for the UI. skip. + xRet.set( new SkipContext( getHandler() ) ); + break; + case NMSP_DIAGRAM|XML_sampData: + mpLayout->getSampData().reset( new DiagramData ); + xRet.set( new DataModelContext( getHandler(), mpLayout->getSampData() ) ); + break; + case NMSP_DIAGRAM|XML_styleData: + mpLayout->getStyleData().reset( new DiagramData ); + xRet.set( new DataModelContext( getHandler(), mpLayout->getStyleData() ) ); + break; + case NMSP_DIAGRAM|XML_cat: + case NMSP_DIAGRAM|XML_catLst: + // TODO, does not matter for the UI + default: + break; + } + if( !xRet.is() ) + xRet.set(this); + + return xRet; +} + + +} } diff --git a/oox/source/drawingml/diagram/diagramdefinitioncontext.hxx b/oox/source/drawingml/diagram/diagramdefinitioncontext.hxx new file mode 100644 index 000000000000..7931f5357e45 --- /dev/null +++ b/oox/source/drawingml/diagram/diagramdefinitioncontext.hxx @@ -0,0 +1,60 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: diagramdefinitioncontext.hxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:57 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef OOX_DRAWINGML_DIAGRAMDEFINITIONCONTEXT_HXX +#define OOX_DRAWINGML_DIAGRAMDEFINITIONCONTEXT_HXX + +#include "oox/core/fragmenthandler.hxx" +#include "oox/core/context.hxx" +#include "oox/drawingml/diagram/diagram.hxx" + +namespace oox { namespace drawingml { + +class DiagramDefinitionContext : public ::oox::core::Context +{ +public: + DiagramDefinitionContext( const ::oox::core::FragmentHandlerRef& xHandler, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttributes, const DiagramLayoutPtr &pLayout ); + virtual ~DiagramDefinitionContext(); + + virtual void SAL_CALL endFastElement( ::sal_Int32 Element ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 Element, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + +private: + DiagramLayoutPtr mpLayout; +}; + +} } + +#endif diff --git a/oox/source/drawingml/diagram/diagramfragmenthandler.cxx b/oox/source/drawingml/diagram/diagramfragmenthandler.cxx new file mode 100644 index 000000000000..1a9646323794 --- /dev/null +++ b/oox/source/drawingml/diagram/diagramfragmenthandler.cxx @@ -0,0 +1,233 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: diagramfragmenthandler.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:58 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include + +#include "oox/drawingml/diagram/diagramfragmenthandler.hxx" +#include "oox/drawingml/diagram/datamodelcontext.hxx" +#include "oox/core/namespaces.hxx" +#include "diagramdefinitioncontext.hxx" + + +using namespace ::oox::core; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +namespace oox { namespace drawingml { + +DiagramDataFragmentHandler::DiagramDataFragmentHandler( const XmlFilterRef& xFilter, + const OUString& rFragmentPath, + const DiagramDataPtr pDataPtr ) + throw( ) + : FragmentHandler( xFilter, rFragmentPath ) + , mpDataPtr( pDataPtr ) +{ +} + +DiagramDataFragmentHandler::~DiagramDataFragmentHandler( ) throw () +{ + +} + +void SAL_CALL DiagramDataFragmentHandler::endDocument() + throw (SAXException, RuntimeException) +{ + +} + + +Reference< XFastContextHandler > SAL_CALL +DiagramDataFragmentHandler::createFastChildContext( ::sal_Int32 aElement, + const Reference< XFastAttributeList >& ) + throw ( SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElement ) + { + case NMSP_DIAGRAM|XML_dataModel: + xRet.set( new DataModelContext( this, mpDataPtr ) ); + break; + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; +} + +/////////////////// + +DiagramLayoutFragmentHandler::DiagramLayoutFragmentHandler( const XmlFilterRef& xFilter, + const OUString& rFragmentPath, + const DiagramLayoutPtr pDataPtr ) + throw( ) + : FragmentHandler( xFilter, rFragmentPath ) + , mpDataPtr( pDataPtr ) +{ +} + +DiagramLayoutFragmentHandler::~DiagramLayoutFragmentHandler( ) throw () +{ + +} + +void SAL_CALL DiagramLayoutFragmentHandler::endDocument() + throw (SAXException, RuntimeException) +{ + +} + + +Reference< XFastContextHandler > SAL_CALL +DiagramLayoutFragmentHandler::createFastChildContext( ::sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs ) + throw ( SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElement ) + { + case NMSP_DIAGRAM|XML_layoutDef: + xRet.set( new DiagramDefinitionContext( this, xAttribs, + mpDataPtr ) ); + break; + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; +} + +/////////////////////// + +DiagramQStylesFragmentHandler::DiagramQStylesFragmentHandler( const XmlFilterRef& xFilter, + const OUString& rFragmentPath, + const DiagramQStylesPtr pDataPtr ) + throw( ) + : FragmentHandler( xFilter, rFragmentPath ) + , mpDataPtr( pDataPtr ) +{ +} + +DiagramQStylesFragmentHandler::~DiagramQStylesFragmentHandler( ) throw () +{ + +} + +void SAL_CALL DiagramQStylesFragmentHandler::endDocument() + throw (SAXException, RuntimeException) +{ + +} + + +Reference< XFastContextHandler > SAL_CALL +DiagramQStylesFragmentHandler::createFastChildContext( ::sal_Int32 aElement, + const Reference< XFastAttributeList >& ) + throw ( SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElement ) + { + case NMSP_DIAGRAM|XML_styleDef: + // TODO + break; + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; +} + +///////////////////// + +DiagramColorsFragmentHandler::DiagramColorsFragmentHandler( const XmlFilterRef& xFilter, + const OUString& rFragmentPath, + const DiagramColorsPtr pDataPtr ) + throw( ) + : FragmentHandler( xFilter, rFragmentPath ) + , mpDataPtr( pDataPtr ) +{ +} + +DiagramColorsFragmentHandler::~DiagramColorsFragmentHandler( ) throw () +{ + +} + +void SAL_CALL DiagramColorsFragmentHandler::endDocument() + throw (SAXException, RuntimeException) +{ + +} + + +Reference< XFastContextHandler > SAL_CALL +DiagramColorsFragmentHandler::createFastChildContext( ::sal_Int32 aElement, + const Reference< XFastAttributeList >& ) + throw ( SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElement ) + { + case NMSP_DIAGRAM|XML_colorsDef: + // TODO + break; + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; +} + + + + +} } diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx new file mode 100644 index 000000000000..81d7631befc2 --- /dev/null +++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx @@ -0,0 +1,149 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: diagramlayoutatoms.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:58 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/diagram/diagramlayoutatoms.hxx" + +#include +#include + +#include "oox/helper/attributelist.hxx" +#include "layoutnodecontext.hxx" + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::oox::core; + +namespace oox { namespace drawingml { + + +IteratorAttr::IteratorAttr( ) + : mnAxis( 0 ) + , mnCnt( 0 ) + , mbHideLastTrans( false ) + , mnPtType( 0 ) + , mnSt( 0 ) + , mnStep( 1 ) +{ +} + +void IteratorAttr::loadFromXAttr( const Reference< XFastAttributeList >& xAttr ) +{ + AttributeList attr( xAttr ); + mnAxis = xAttr->getOptionalValueToken( XML_axis, 0 ); + mnCnt = attr.getInteger( XML_cnt, 0 ); + mbHideLastTrans = attr.getBool( XML_hideLastTrans, false ); + mnPtType = xAttr->getOptionalValueToken( XML_ptType, 0 ); + mnSt = attr.getInteger( XML_st, 0 ); + mnStep = attr.getInteger( XML_step, 1 ); +} + + + +ConditionAttr::ConditionAttr() + : mnFunc( 0 ) + , mnArg( 0 ) + , mnOp( 0 ) +{ + +} + + +void ConditionAttr::loadFromXAttr( const Reference< XFastAttributeList >& xAttr ) +{ + mnFunc = xAttr->getOptionalValueToken( XML_func, 0 ); + // mnArg will be -1 for "none" or any other unknown value + mnArg = LayoutNodeContext::tagToVarIdx( xAttr->getOptionalValueToken( XML_arg, XML_none ) ); + mnOp = xAttr->getOptionalValueToken( XML_op, 0 ); + msVal = xAttr->getOptionalValue( XML_val ); +} + + +void LayoutAtom::dump(int level) +{ + OSL_TRACE( "level = %d - %s of type %s", level, + OUSTRING_TO_CSTR( msName ), + typeid(*this).name() ); + std::for_each( mpChildNodes.begin(), mpChildNodes.end(), + boost::bind( &LayoutAtom::dump, _1, level + 1 ) ); +} + + +void ForEachAtom::processAtom() +{ + // TODO there is likely some conditions + std::for_each( mpChildNodes.begin(), mpChildNodes.end(), + boost::bind( &LayoutAtom::processAtom, _1 ) ); +} + +/** call ConditionAtom::test() if pAtom is one + * if it is not a ConditionAtom, then return false. + */ +static bool _test_atom( const LayoutAtomPtr & pAtom) +{ + try { + bool bResult = false; + const ConditionAtomPtr pCond = boost::dynamic_pointer_cast< ConditionAtom >(pAtom); + if( pCond ) + { + bResult = pCond->test(); + } + return bResult; + } + catch(...) + { + } + return false; +} + +void ChooseAtom::processAtom() +{ + std::vector< LayoutAtomPtr >::iterator + iter = std::find_if( mpChildNodes.begin(), mpChildNodes.end(), + boost::bind( &_test_atom, _1 ) ); + if( iter != mpChildNodes.end() ) + { + // TODO do something + (*iter)->processAtom(); + } +} + +bool ConditionAtom::test() +{ + // TODO + return false; +} + + +} } diff --git a/oox/source/drawingml/diagram/layoutnodecontext.cxx b/oox/source/drawingml/diagram/layoutnodecontext.cxx new file mode 100644 index 000000000000..eb070fba70f3 --- /dev/null +++ b/oox/source/drawingml/diagram/layoutnodecontext.cxx @@ -0,0 +1,368 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: layoutnodecontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:58 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "layoutnodecontext.hxx" + +#include "oox/helper/attributelist.hxx" +#include "oox/core/skipcontext.hxx" +#include "oox/drawingml/diagram/diagram.hxx" +#include "oox/drawingml/shapecontext.hxx" +#include "diagramdefinitioncontext.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using ::rtl::OUString; + +namespace oox { namespace drawingml { + +class IfContext + : public LayoutNodeContext +{ +public: + IfContext( const FragmentHandlerRef& xHandler, + const Reference< XFastAttributeList >& xAttribs, + const LayoutAtomPtr & pNode ) + : LayoutNodeContext( xHandler, xAttribs, pNode ) + { + ConditionAtomPtr pAtom( boost::dynamic_pointer_cast< ConditionAtom >(pNode) ); + OSL_ENSURE( pAtom, "Must pass a ConditionAtom" ); + + pAtom->iterator().loadFromXAttr( xAttribs ); + pAtom->cond().loadFromXAttr( xAttribs ); + } +}; + + + +class AlgorithmContext + : public Context +{ +public: + AlgorithmContext( const FragmentHandlerRef& xHandler, const Reference< XFastAttributeList >& xAttribs, const LayoutAtomPtr & pNode ) + : Context( xHandler ) + , mnRevision( 0 ) + , mnType( 0 ) + , mpNode( pNode ) + { + AttributeList aAttribs( xAttribs ); + mnRevision = aAttribs.getInteger( XML_rev, 0 ); + mnType = xAttribs->getOptionalValueToken( XML_type, 0 ); + } + +private: + sal_Int32 mnRevision; + sal_Int32 mnType; + LayoutAtomPtr mpNode; +}; + + +class ChooseContext + : public Context +{ +public: + ChooseContext( const FragmentHandlerRef& xHandler, const Reference< XFastAttributeList >& xAttribs, const LayoutAtomPtr & pNode ) + : Context( xHandler ) + , mbHasElse( false ) + , mpNode( pNode ) + { + msName = xAttribs->getOptionalValue( XML_name ); + } + + virtual Reference< XFastContextHandler > SAL_CALL + createFastChildContext( ::sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) + { + Reference< XFastContextHandler > xRet; + + switch( aElement ) + { + case XML_if: + { + // CT_When + LayoutAtomPtr pAtom( new ConditionAtom( false ) ); + mpNode->addChild( pAtom ); + xRet.set( new IfContext( getHandler(), xAttribs, pAtom ) ); + break; + } + case XML_else: + // CT_Otherwise + if( !mbHasElse ) + { + LayoutAtomPtr pAtom( new ConditionAtom( true ) ); + mpNode->addChild( pAtom ); + xRet.set( new IfContext( getHandler(), xAttribs, pAtom ) ); + mbHasElse = true; + } + else + { + OSL_TRACE( "ignoring second else clause" ); + } + break; + default: + break; + } + + if( !xRet.is() ) + xRet.set(this); + + return xRet; + } +private: + bool mbHasElse; + OUString msName; + LayoutAtomPtr mpNode; +}; + + + + +class ForEachContext + : public LayoutNodeContext +{ +public: + ForEachContext( const FragmentHandlerRef& xHandler, const Reference< XFastAttributeList >& xAttribs, const LayoutAtomPtr & pNode ) + : LayoutNodeContext( xHandler, xAttribs, pNode ) + { + ForEachAtomPtr pAtom( boost::dynamic_pointer_cast< ForEachAtom >(pNode) ); + OSL_ENSURE( pAtom, "Must pass a ForEachAtom" ); + xAttribs->getOptionalValue( XML_ref ); + + pAtom->iterator().loadFromXAttr( xAttribs ); + } +}; + + +// CT_LayoutVariablePropertySet +class LayoutVariablePropertySetContext + : public Context +{ +public: + LayoutVariablePropertySetContext( const FragmentHandlerRef& xHandler, + LayoutNode::VarMap & aVar ) + : Context( xHandler ) + , mVariables( aVar ) + { + } + + virtual ~LayoutVariablePropertySetContext() + { + } + + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) + { + Reference< XFastContextHandler > xRet; + + sal_Int32 nIdx = LayoutNodeContext::tagToVarIdx( aElement & ( ~NMSP_MASK ) ); + if( nIdx != -1 ) + { + mVariables[ nIdx ] = makeAny( xAttribs->getOptionalValue( XML_val ) ); + } + if( !xRet.is() ) + xRet.set(this); + + return xRet; + } +private: + LayoutNode::VarMap & mVariables; +}; + + +// CT_LayoutNode +LayoutNodeContext::LayoutNodeContext( const FragmentHandlerRef& xHandler, + const Reference< XFastAttributeList >& xAttribs, + const LayoutAtomPtr &pNode ) + : Context( xHandler ) + , mpNode( pNode ) +{ + OSL_ENSURE( pNode, "Node must NOT be NULL" ); + mpNode->setName( xAttribs->getOptionalValue( XML_name ) ); + // TODO shall we even bother? + // b or t +// sal_Int32 nChOrder = xAttributes->getOptionalValueToken( XML_chOrder, XML_b ); +// OUString sMoveWith = xAttributes->getOptionalValue( XML_moveWith ); +// OUString sStyleLbl = xAttributes->getOptionalValue( XML_styleLbl ); +} + + +LayoutNodeContext::~LayoutNodeContext() +{ +} + +void SAL_CALL LayoutNodeContext::endFastElement( ::sal_Int32 ) + throw (SAXException, RuntimeException) +{ + +} + +/** convert the XML tag to a variable index in the array + * @param aTag the tag, wihout namespace + * @return the variable index. -1 is an error + */ +sal_Int32 LayoutNodeContext::tagToVarIdx( sal_Int32 aTag ) +{ + sal_Int32 nIdx = -1; + switch( aTag ) + { + case NMSP_DIAGRAM|XML_animLvl: + nIdx = LayoutNode::VAR_animLvl; + break; + case NMSP_DIAGRAM|XML_animOne: + nIdx = LayoutNode::VAR_animOne; + break; + case NMSP_DIAGRAM|XML_bulletEnabled: + nIdx = LayoutNode::VAR_bulletEnabled; + break; + case NMSP_DIAGRAM|XML_chMax: + nIdx = LayoutNode::VAR_chMax; + break; + case NMSP_DIAGRAM|XML_chPref: + nIdx = LayoutNode::VAR_chPref; + break; + case NMSP_DIAGRAM|XML_dir: + nIdx = LayoutNode::VAR_dir; + break; + case NMSP_DIAGRAM|XML_hierBranch: + nIdx = LayoutNode::VAR_hierBranch; + break; + case NMSP_DIAGRAM|XML_orgChart: + nIdx = LayoutNode::VAR_orgChart; + break; + case NMSP_DIAGRAM|XML_resizeHandles: + nIdx = LayoutNode::VAR_resizeHandles; + break; + default: + break; + } + return nIdx; +} + + +Reference< XFastContextHandler > SAL_CALL +LayoutNodeContext::createFastChildContext( ::sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElement ) + { + case NMSP_DIAGRAM|XML_layoutNode: + { + LayoutNodePtr pNode( new LayoutNode() ); + mpNode->addChild( pNode ); + xRet.set( new LayoutNodeContext( getHandler(), xAttribs, pNode ) ); + break; + } + case NMSP_DIAGRAM|XML_shape: + { + ShapePtr pShape( new Shape() ); + xRet.set( new ShapeContext( getHandler(), ShapePtr( ( Shape* )NULL ), pShape ) ); + break; + } + case NMSP_DIAGRAM|XML_extLst: + xRet.set( new SkipContext( getHandler() ) ); + break; + case NMSP_DIAGRAM|XML_alg: + { + // CT_Algorithm + LayoutAtomPtr pAtom( new AlgAtom ); + mpNode->addChild( pAtom ); + xRet.set( new AlgorithmContext( getHandler(), xAttribs, pAtom ) ); + break; + } + case NMSP_DIAGRAM|XML_choose: + { + // CT_Choose + LayoutAtomPtr pAtom( new ChooseAtom ); + mpNode->addChild( pAtom ); + xRet.set( new ChooseContext( getHandler(), xAttribs, pAtom ) ); + break; + } + case NMSP_DIAGRAM|XML_forEach: + { + // CT_ForEach + LayoutAtomPtr pAtom( new ForEachAtom ); + mpNode->addChild( pAtom ); + xRet.set( new ForEachContext( getHandler(), xAttribs, pAtom ) ); + break; + } + case NMSP_DIAGRAM|XML_constrLst: + // CT_Constraints + // TODO + break; + case NMSP_DIAGRAM|XML_presOf: + { + // CT_PresentationOf + // TODO + xAttribs->getOptionalValue( XML_axis ); + xAttribs->getOptionalValue( XML_cnt ); + xAttribs->getOptionalValue( XML_hideLastTrans ); + xAttribs->getOptionalValue( XML_ptType ); + xAttribs->getOptionalValue( XML_st ); + xAttribs->getOptionalValue( XML_step ); + break; + } + case NMSP_DIAGRAM|XML_ruleLst: + // CT_Rules + // TODO + break; + case NMSP_DIAGRAM|XML_varLst: + { + LayoutNodePtr pNode( boost::dynamic_pointer_cast< LayoutNode >( mpNode ) ); + if( pNode ) + { + xRet.set( new LayoutVariablePropertySetContext( getHandler(), + pNode->variables() ) ); + } + else + { + OSL_TRACE( "OOX: encountered a varLst in a non layoutNode context" ); + } + break; + } + default: + break; + } + if( !xRet.is() ) + xRet.set(this); + + return xRet; +} + + +} } diff --git a/oox/source/drawingml/diagram/layoutnodecontext.hxx b/oox/source/drawingml/diagram/layoutnodecontext.hxx new file mode 100644 index 000000000000..90ad860a98f5 --- /dev/null +++ b/oox/source/drawingml/diagram/layoutnodecontext.hxx @@ -0,0 +1,61 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: layoutnodecontext.hxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:58 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef OOX_DRAWINGML_LAYOUTNODECONTEXT_HXX +#define OOX_DRAWINGML_LAYOUTNODECONTEXT_HXX + +#include "oox/core/fragmenthandler.hxx" +#include "oox/core/context.hxx" +#include "oox/drawingml/diagram/diagram.hxx" + +namespace oox { namespace drawingml { + +class LayoutNodeContext : public ::oox::core::Context +{ +public: + LayoutNodeContext( const ::oox::core::FragmentHandlerRef& xHandler, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttributes, const LayoutAtomPtr &pNode ); + virtual ~LayoutNodeContext(); + + virtual void SAL_CALL endFastElement( ::sal_Int32 Element ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 Element, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + + static ::sal_Int32 tagToVarIdx( ::sal_Int32 aTag ); +private: + LayoutAtomPtr mpNode; +}; + +} } + +#endif diff --git a/oox/source/drawingml/diagram/makefile.mk b/oox/source/drawingml/diagram/makefile.mk new file mode 100644 index 000000000000..d2a1bf63d5d8 --- /dev/null +++ b/oox/source/drawingml/diagram/makefile.mk @@ -0,0 +1,61 @@ +#************************************************************************* +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.2 $ +# +# last change: $Author: rt $ $Date: 2008-01-17 08:05:58 $ +# +# The Contents of this file are made available subject to +# the terms of GNU Lesser General Public License Version 2.1. +# +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2005 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=oox +TARGET=diagram +AUTOSEG=true + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/diagram.obj \ + $(SLO)$/diagramfragmenthandler.obj \ + $(SLO)$/diagramdefinitioncontext.obj \ + $(SLO)$/diagramlayoutatoms.obj \ + $(SLO)$/datamodelcontext.obj \ + $(SLO)$/layoutnodecontext.obj + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk diff --git a/oox/source/drawingml/drawingmltypes.cxx b/oox/source/drawingml/drawingmltypes.cxx new file mode 100644 index 000000000000..7d5f15c899ec --- /dev/null +++ b/oox/source/drawingml/drawingmltypes.cxx @@ -0,0 +1,433 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: drawingmltypes.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/drawingmltypes.hxx" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "oox/helper/attributelist.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/drawingml/shape.hxx" +#include "tokens.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::style; +using namespace ::oox::core; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +// -------------------------------------------------------------------- + +/** converts an emu string into 1/100th mmm but constrain as per ST_TextMargin + * see 5.1.12.73 + */ +sal_Int32 GetTextMargin( const ::rtl::OUString& sValue ) +{ + sal_Int32 nRet = 0; + if( !::sax::Converter::convertNumber( nRet, sValue ) ) + nRet = 0; + else if( nRet < 0 ) + nRet = 0; + else if( nRet > 51206400 ) + nRet = 51206400; + + nRet /= 360; + return nRet; +} + +/** converts an emu string into 1/100th mmm */ +sal_Int32 GetCoordinate( const ::rtl::OUString& sValue ) +{ + sal_Int32 nRet = 0; + if( !::sax::Converter::convertNumber( nRet, sValue ) ) + nRet = 0; + + nRet /= 360; + return nRet; +} + +/** converts a ST_Percentage % string into 1/1000th of % */ +sal_Int32 GetPercent( const ::rtl::OUString& sValue ) +{ + sal_Int32 nRet = 0; + if( !::sax::Converter::convertNumber( nRet, sValue ) ) + nRet = 0; + + return nRet; +} + +double GetPositiveFixedPercentage( const ::rtl::OUString& sValue ) +{ + double fPercent = sValue.toFloat() / 100000.; + return fPercent; +} + +// -------------------------------------------------------------------- + +/** converts the attributes from an CT_Point2D into an awt Point with 1/100thmm */ +::com::sun::star::awt::Point GetPoint2D( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs ) +{ + return ::com::sun::star::awt::Point( GetCoordinate( xAttribs->getOptionalValue( XML_x ) ), GetCoordinate( xAttribs->getOptionalValue( XML_y ) ) ); +} + +/** converts the attributes from an CT_TLPoint into an awt Point with 1/1000% */ +::com::sun::star::awt::Point GetPointPercent( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs ) +{ + return ::com::sun::star::awt::Point( GetPercent( xAttribs->getOptionalValue( XML_x ) ), GetCoordinate( xAttribs->getOptionalValue( XML_y ) ) ); +} + +// -------------------------------------------------------------------- + +/** converts the ST_TextFontSize to point */ +float GetTextSize( const ::rtl::OUString& sValue ) +{ + float fRet = 0; + sal_Int32 nRet; + if( ::sax::Converter::convertNumber( nRet, sValue ) ) + fRet = static_cast< float >( static_cast< double >( nRet ) / 100.0 ); + return fRet; +} + + +/** converts the ST_TextSpacingPoint to 1/100mm */ +sal_Int32 GetTextSpacingPoint( const ::rtl::OUString& sValue ) +{ + sal_Int32 nRet; + if( ::sax::Converter::convertNumber( nRet, sValue ) ) + nRet = ( nRet * 254 + 360 ) / 720; + return nRet; +} + + +sal_Int16 GetFontUnderline( ::sal_Int32 nToken ) +{ + sal_Int16 nEnum; + switch( nToken ) + { + case XML_none: + nEnum = FontUnderline::NONE; + break; + case XML_dash: + nEnum = FontUnderline::DASH; + break; + case XML_dashHeavy: + nEnum = FontUnderline::BOLDDASH; + break; + case XML_dashLong: + nEnum = FontUnderline::LONGDASH; + break; + case XML_dashLongHeavy: + nEnum = FontUnderline::BOLDLONGDASH; + break; + case XML_dbl: + nEnum = FontUnderline::DOUBLE; + break; + case XML_dotDash: + nEnum = FontUnderline::DASHDOT; + break; + case XML_dotDashHeavy: + nEnum = FontUnderline::BOLDDASHDOT; + break; + case XML_dotDotDash: + nEnum = FontUnderline::DASHDOTDOT; + break; + case XML_dotDotDashHeavy: + nEnum = FontUnderline::BOLDDASHDOTDOT; + break; + case XML_dotted: + nEnum = FontUnderline::DOTTED; + break; + case XML_dottedHeavy: + nEnum = FontUnderline::BOLDDOTTED; + break; + case XML_heavy: + nEnum = FontUnderline::BOLD; + break; + case XML_sng: + nEnum = FontUnderline::SINGLE; + break; + case XML_wavy: + nEnum = FontUnderline::WAVE; + break; + case XML_wavyDbl: + nEnum = FontUnderline::DOUBLEWAVE; + break; + case XML_wavyHeavy: + nEnum = FontUnderline::BOLDWAVE; + break; + case XML_words: + // TODO + default: + nEnum = FontUnderline::DONTKNOW; + break; + } + return nEnum; +} + +sal_Int16 GetFontStrikeout( sal_Int32 nToken ) +{ + sal_Int16 nEnum; + switch( nToken ) + { + case XML_dblStrike: + nEnum = FontStrikeout::DOUBLE; + break; + case XML_noStrike: + nEnum = FontStrikeout::NONE; + break; + case XML_sngStrike: + nEnum = FontStrikeout::SINGLE; + break; + default: + nEnum = FontStrikeout::DONTKNOW; + break; + } + return nEnum; +} + +sal_Int16 GetCaseMap( sal_Int32 nToken ) +{ + sal_Int16 nEnum; + switch( nToken ) + { + case XML_all: + nEnum = CaseMap::UPPERCASE; + break; + case XML_small: + nEnum = CaseMap::SMALLCAPS; + break; + case XML_none: + // fall through + default: + nEnum = CaseMap::NONE; + break; + } + return nEnum; +} + +// BEGIN stolen from sd/source/filter/eppt/epptso.cxx +/* Font Families */ +#define FF_DONTCARE 0x00 +#define FF_ROMAN 0x10 +#define FF_SWISS 0x20 +#define FF_MODERN 0x30 +#define FF_SCRIPT 0x40 +#define FF_DECORATIVE 0x50 + +/* Font pitches */ +#define DEFAULT_PITCH 0x00 +#define FIXED_PITCH 0x01 +#define VARIABLE_PITCH 0x02 + +// END + +void GetFontPitch( sal_Int32 nOoxValue, sal_Int16 & nPitch, sal_Int16 & nFamily ) +{ + sal_Int32 oFamily = ( nOoxValue & 0xf0 ); + sal_Int32 oPitch = ( nOoxValue & 0x0f ); + switch( oFamily ) + { + case FF_ROMAN: + nFamily = FontFamily::ROMAN; + break; + case FF_SWISS: + nFamily = FontFamily::SWISS; + break; + case FF_MODERN: + nFamily = FontFamily::MODERN; + break; + case FF_SCRIPT: + nFamily = FontFamily::SCRIPT; + break; + case FF_DECORATIVE: + nFamily = FontFamily::DECORATIVE; + break; + default: + nFamily = FontFamily::DONTKNOW; + break; + } + switch( oPitch ) + { + case FIXED_PITCH: + nPitch = FontPitch::FIXED; + break; + case VARIABLE_PITCH: + nPitch = FontPitch::VARIABLE; + break; + case DEFAULT_PITCH: + default: + nPitch = FontPitch::DONTKNOW; + break; + } +} + +/** converts a paragraph align to a ParaAdjust */ +sal_Int16 GetParaAdjust( sal_Int32 nAlign ) +{ + sal_Int16 nEnum; + switch( nAlign ) + { + case XML_ctr: + nEnum = ParagraphAdjust_CENTER; + break; + case XML_just: + case XML_justLow: + nEnum = ParagraphAdjust_BLOCK; + break; + case XML_r: + nEnum = ParagraphAdjust_RIGHT; + break; + case XML_thaiDist: + case XML_dist: + nEnum = ParagraphAdjust_STRETCH; + break; + case XML_l: + default: + nEnum = ParagraphAdjust_LEFT; + break; + } + return nEnum; +} + + +TabAlign GetTabAlign( sal_Int32 aToken ) +{ + TabAlign nEnum; + switch( aToken ) + { + case XML_ctr: + nEnum = TabAlign_CENTER; + break; + case XML_dec: + nEnum = TabAlign_DECIMAL; + break; + case XML_l: + nEnum = TabAlign_LEFT; + break; + case XML_r: + nEnum = TabAlign_RIGHT; + break; + default: + nEnum = TabAlign_DEFAULT; + break; + } + return nEnum; +} + +// -------------------------------------------------------------------- + +/** converts the attributes from a CT_RelativeRect to an IntegerRectangle2D */ +com::sun::star::geometry::IntegerRectangle2D GetRelativeRect( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs ) +{ + com::sun::star::geometry::IntegerRectangle2D r; + + r.X1 = xAttribs->getOptionalValue( XML_l ).toInt32(); + r.Y1 = xAttribs->getOptionalValue( XML_t ).toInt32(); + r.X2 = xAttribs->getOptionalValue( XML_r ).toInt32(); + r.Y2 = xAttribs->getOptionalValue( XML_b ).toInt32(); + + return r; +} + +// -------------------------------------------------------------------- + +/** converts the attributes from an CT_Size2D into an awt Size with 1/100thmm */ +::com::sun::star::awt::Size GetSize2D( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs ) +{ + return ::com::sun::star::awt::Size( GetCoordinate( xAttribs->getOptionalValue( XML_cx ) ), GetCoordinate( xAttribs->getOptionalValue( XML_cy ) ) ); +} + + + + +IndexRange GetIndexRange( const Reference< XFastAttributeList >& xAttributes ) +{ + IndexRange range; + range.start = xAttributes->getOptionalValue( XML_st ).toInt32(); + range.end = xAttributes->getOptionalValue( XML_end ).toInt32(); + return range; +} + + +// -------------------------------------------------------------------- + +/** context to import a CT_Transform2D */ +Transform2DContext::Transform2DContext( const FragmentHandlerRef& xHandler, const Reference< XFastAttributeList >& xAttribs, ::oox::drawingml::Shape& rShape ) throw() +: Context( xHandler ) +, mrShape( rShape ) +{ + AttributeList aAttributeList( xAttribs ); + mrShape.setRotation( aAttributeList.getInteger( XML_rot, 0 ) ); // 60000ths of a degree Positive angles are clockwise; negative angles are counter-clockwise + mrShape.setFlip( aAttributeList.getBool( XML_flipH, sal_False ), aAttributeList.getBool( XML_flipV, sal_False ) ); +} + +void Transform2DContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) +{ +} + +Reference< XFastContextHandler > Transform2DContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_off: // horz/vert translation + mrShape.setPosition( Point( xAttribs->getOptionalValue( XML_x ).toInt32(), xAttribs->getOptionalValue( XML_y ).toInt32() ) ); + break; + case NMSP_DRAWINGML|XML_ext: // horz/vert size + mrShape.setSize( Size( xAttribs->getOptionalValue( XML_cx ).toInt32(), xAttribs->getOptionalValue( XML_cy ).toInt32() ) ); + break; +/* todo: what to do? + case NMSP_DRAWINGML|XML_chOff: // horz/vert translation of children + case NMSP_DRAWINGML|XML_chExt: // horz/vert size of children + break; +*/ + } + + Reference< XFastContextHandler > xEmpty; + return xEmpty; +} + + +} } diff --git a/oox/source/drawingml/embeddedwavaudiofile.cxx b/oox/source/drawingml/embeddedwavaudiofile.cxx new file mode 100644 index 000000000000..e9631b91c0dd --- /dev/null +++ b/oox/source/drawingml/embeddedwavaudiofile.cxx @@ -0,0 +1,64 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: embeddedwavaudiofile.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/embeddedwavaudiofile.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/core/namespaces.hxx" + +#include "tokens.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + + +namespace oox { namespace drawingml { + + + // CT_EmbeddedWAVAudioFile + void getEmbeddedWAVAudioFile( const FragmentHandlerRef &xHandler, const Reference< XFastAttributeList >& xAttribs, + EmbeddedWAVAudioFile & aAudio ) + { + AttributeList attribs(xAttribs); + + OUString sId = xAttribs->getOptionalValue( NMSP_RELATIONSHIPS|XML_embed ); + aAudio.msLink = xHandler->getRelations().getTargetFromRelId( sId ); + aAudio.mbBuiltIn = attribs.getBool( XML_builtIn, false ); + aAudio.msName = xAttribs->getOptionalValue( XML_name ); + } + + +} } diff --git a/oox/source/drawingml/fillproperties.cxx b/oox/source/drawingml/fillproperties.cxx new file mode 100644 index 000000000000..562eb35f22aa --- /dev/null +++ b/oox/source/drawingml/fillproperties.cxx @@ -0,0 +1,117 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: fillproperties.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include +#include "oox/drawingml/fillproperties.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" +#include +#include +#include + +using rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::graphic; + +namespace oox { namespace drawingml { + +FillProperties::FillProperties( sal_Int32 nContext ) +: mnContext( nContext ) +, maFillColor( new Color() ) +{ +} +FillProperties::~FillProperties() +{ +} + +void FillProperties::apply( const FillPropertiesPtr& rSourceFillProperties ) +{ + maFillProperties.insert( rSourceFillProperties->maFillProperties.begin(), rSourceFillProperties->maFillProperties.end() ); + if ( rSourceFillProperties->maFillColor->isUsed() ) + maFillColor = rSourceFillProperties->maFillColor; +} + +void FillProperties::pushToPropSet( const ::oox::core::XmlFilterBase& rFilterBase, + const Reference < XPropertySet >& xPropSet ) const +{ + PropertySet aPropSet( xPropSet ); + Sequence< OUString > aNames; + Sequence< Any > aValues; + + maFillProperties.makeSequence( aNames, aValues ); + aPropSet.setProperties( aNames, aValues ); + if ( maFillColor->isUsed() ) + { + const rtl::OUString sFillColor( OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "FillColor" ) ) ); + xPropSet->setPropertyValue( sFillColor, Any( maFillColor->getColor( rFilterBase ) ) ); + } + createTransformedGraphic( rFilterBase, xPropSet ); +} + +void FillProperties::createTransformedGraphic( const oox::core::XmlFilterBase& rFilterBase, const Reference < XPropertySet >& xPropSet ) const +{ + if( mxGraphic.is() ) + { + if ( mnContext == XML_pic ) + { + Reference< XGraphic > xGraphic( mxGraphic ); + if ( maColorChangeFrom.get() && maColorChangeTo.get() ) + { + sal_Int32 nClrChangeFrom = maColorChangeFrom->getColor( rFilterBase ); + sal_Int32 nClrChangeTo = maColorChangeTo->getColor( rFilterBase ); + sal_Int32 nAlphaTo = maColorChangeTo->getAlpha(); + if ( ( nClrChangeFrom != nClrChangeTo ) || ( maColorChangeTo->hasAlpha() && ( nAlphaTo != 1000000 ) ) ) + { + Reference< XGraphicTransformer > xTransformer( xGraphic, UNO_QUERY ); + if ( xTransformer.is() ) + xGraphic = xTransformer->colorChange( xGraphic, nClrChangeFrom, 9, nClrChangeTo, static_cast< sal_Int8 >( ( nAlphaTo / 39062 ) ) ); + } + } + static const OUString sGraphic( CREATE_OUSTRING( "Graphic" ) ); + xPropSet->setPropertyValue( sGraphic, Any( xGraphic ) ); + } + else if ( mnContext == XML_spPr ) + { + static const OUString sFillBitmap( CREATE_OUSTRING( "FillBitmap" ) ); + xPropSet->setPropertyValue( sFillBitmap, Any( mxGraphic ) ); + } + } +} + +} } diff --git a/oox/source/drawingml/fillpropertiesgroupcontext.cxx b/oox/source/drawingml/fillpropertiesgroupcontext.cxx new file mode 100644 index 000000000000..351391c7aca7 --- /dev/null +++ b/oox/source/drawingml/fillpropertiesgroupcontext.cxx @@ -0,0 +1,457 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: fillpropertiesgroupcontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/fillpropertiesgroupcontext.hxx" + +#include "comphelper/anytostring.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "oox/drawingml/colorchoicecontext.hxx" +#include +#include "oox/helper/propertymap.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using ::rtl::OUString; +using ::com::sun::star::beans::NamedValue; +using namespace ::oox::core; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::graphic; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +// --------------------------------------------------------------------- + +class NoFillContext : public FillPropertiesGroupContext +{ +public: + NoFillContext( const oox::core::FragmentHandlerRef& xHandler, ::oox::drawingml::FillProperties& rFillProperties ) throw(); +}; + +// --------------------------------------------------------------------- + +class SolidColorFillPropertiesContext : public FillPropertiesGroupContext +{ +public: + SolidColorFillPropertiesContext( const oox::core::FragmentHandlerRef& xHandler, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttributes, ::oox::drawingml::FillProperties& rFillProperties ) throw(); + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException); +}; + +// --------------------------------------------------------------------- + +class GradFillPropertiesContext : public FillPropertiesGroupContext +{ +public: + GradFillPropertiesContext( const oox::core::FragmentHandlerRef& xHandler, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttributes, ::oox::drawingml::FillProperties& rFillProperties ) throw(); + + virtual void SAL_CALL endFastElement( sal_Int32 aElementToken ) throw (SAXException, RuntimeException); + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException); +}; + +// --------------------------------------------------------------------- + +class PattFillPropertiesContext : public FillPropertiesGroupContext +{ +public: + PattFillPropertiesContext( const oox::core::FragmentHandlerRef& xHandler, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttributes, ::oox::drawingml::FillProperties& rFillProperties ) throw(); + + virtual void SAL_CALL startFastElement( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException); + virtual void SAL_CALL endFastElement( sal_Int32 aElementToken ) throw (SAXException, RuntimeException); + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException); +}; + +// --------------------------------------------------------------------- + +class GrpFillPropertiesContext : public FillPropertiesGroupContext +{ +public: + GrpFillPropertiesContext( const oox::core::FragmentHandlerRef& xHandler, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttributes, ::oox::drawingml::FillProperties& rFillProperties ) throw(); + + virtual void SAL_CALL startFastElement( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException); + virtual void SAL_CALL endFastElement( sal_Int32 aElementToken ) throw (SAXException, RuntimeException); + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException); +}; + +// --------------------------------------------------------------------- + +class clrChangeContext : public ::oox::core::Context +{ + oox::drawingml::ColorPtr& mraClrFrom; + oox::drawingml::ColorPtr& mraClrTo; + sal_Bool mbUseAlpha; +public: + clrChangeContext( const oox::core::FragmentHandlerRef& xHandler, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttributes, + oox::drawingml::ColorPtr& raClrFrom, oox::drawingml::ColorPtr& raClrTo ) throw(); + ~clrChangeContext(); + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException); +}; + +// --------------------------------------------------------------------- + +FillPropertiesGroupContext::FillPropertiesGroupContext( const FragmentHandlerRef& xHandler, ::com::sun::star::drawing::FillStyle eFillStyle, oox::drawingml::FillProperties& rFillProperties ) throw() +: ::oox::core::Context( xHandler ) +, mrFillProperties( rFillProperties ) +{ + static const OUString sFillStyle = CREATE_OUSTRING( "FillStyle" ); + mrFillProperties.getFillPropertyMap()[ sFillStyle ] <<= eFillStyle; +} + +// --------------------------------------------------------------------- + +Reference< XFastContextHandler > FillPropertiesGroupContext::StaticCreateContext( const FragmentHandlerRef& xHandler, sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs, ::oox::drawingml::FillProperties& rFillProperties ) + throw ( SAXException, RuntimeException ) +{ + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_noFill: + xRet.set( new NoFillContext( xHandler, rFillProperties ) ); + break; + case NMSP_DRAWINGML|XML_solidFill: + xRet.set( new SolidColorFillPropertiesContext( xHandler, xAttribs, rFillProperties ) ); + break; + case NMSP_DRAWINGML|XML_gradFill: + xRet.set( new GradFillPropertiesContext( xHandler, xAttribs, rFillProperties ) ); + break; + case NMSP_DRAWINGML|XML_blipFill: + xRet.set( new BlipFillPropertiesContext( xHandler, xAttribs, rFillProperties ) ); + break; + case NMSP_DRAWINGML|XML_pattFill: + xRet.set( new PattFillPropertiesContext( xHandler, xAttribs, rFillProperties ) ); + break; + case NMSP_DRAWINGML|XML_grpFill: + xRet.set( new GrpFillPropertiesContext( xHandler, xAttribs, rFillProperties ) ); + break; + } + return xRet; +} + +// --------------------------------------------------------------------- + +NoFillContext::NoFillContext( const FragmentHandlerRef& xHandler, oox::drawingml::FillProperties& rFillProperties ) throw() +: FillPropertiesGroupContext( xHandler, FillStyle_NONE, rFillProperties ) +{ +} + +// --------------------------------------------------------------------- + +SolidColorFillPropertiesContext::SolidColorFillPropertiesContext( const FragmentHandlerRef& xHandler, const Reference< XFastAttributeList >&, ::oox::drawingml::FillProperties& rFillProperties ) throw() +: FillPropertiesGroupContext( xHandler, FillStyle_SOLID, rFillProperties ) +{ +} +Reference< XFastContextHandler > SolidColorFillPropertiesContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +{ + // colorTransformGroup + + // color should be available as rgb in member mnColor already, now modify it depending on + // the transformation elements + + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + + case NMSP_DRAWINGML|XML_scrgbClr: // CT_ScRgbColor + case NMSP_DRAWINGML|XML_srgbClr: // CT_SRgbColor + case NMSP_DRAWINGML|XML_hslClr: // CT_HslColor + case NMSP_DRAWINGML|XML_sysClr: // CT_SystemColor + case NMSP_DRAWINGML|XML_schemeClr: // CT_SchemeColor + case NMSP_DRAWINGML|XML_prstClr: // CT_PresetColor + { + xRet.set( new colorChoiceContext( getHandler(), *(mrFillProperties.getFillColor().get()) ) ); + break; + } + case NMSP_DRAWINGML|XML_tint: // CT_PositiveFixedPercentage + case NMSP_DRAWINGML|XML_shade: // CT_PositiveFixedPercentage + case NMSP_DRAWINGML|XML_comp: // CT_ComplementTransform + case NMSP_DRAWINGML|XML_inv: // CT_InverseTransform + case NMSP_DRAWINGML|XML_gray: // CT_GrayscaleTransform + case NMSP_DRAWINGML|XML_alpha: // CT_PositiveFixedPercentage + case NMSP_DRAWINGML|XML_alphaOff: // CT_FixedPercentage + case NMSP_DRAWINGML|XML_alphaMod: // CT_PositivePercentage + case NMSP_DRAWINGML|XML_hue: // CT_PositiveFixedAngle + case NMSP_DRAWINGML|XML_hueOff: // CT_Angle + case NMSP_DRAWINGML|XML_hueMod: // CT_PositivePercentage + case NMSP_DRAWINGML|XML_sat: // CT_Percentage + case NMSP_DRAWINGML|XML_satOff: // CT_Percentage + case NMSP_DRAWINGML|XML_satMod: // CT_Percentage + case NMSP_DRAWINGML|XML_lum: // CT_Percentage + case NMSP_DRAWINGML|XML_lumOff: // CT_Percentage + case NMSP_DRAWINGML|XML_lumMod: // CT_Percentage + case NMSP_DRAWINGML|XML_red: // CT_Percentage + case NMSP_DRAWINGML|XML_redOff: // CT_Percentage + case NMSP_DRAWINGML|XML_redMod: // CT_Percentage + case NMSP_DRAWINGML|XML_green: // CT_Percentage + case NMSP_DRAWINGML|XML_greenOff: // CT_Percentage + case NMSP_DRAWINGML|XML_greenMod: // CT_Percentage + case NMSP_DRAWINGML|XML_blue: // CT_Percentage + case NMSP_DRAWINGML|XML_blueOff: // CT_Percentage + case NMSP_DRAWINGML|XML_blueMod: // CT_Percentage + break; + } + if( !xRet.is() ) + xRet.set( this ); + return xRet; +} + +// --------------------------------------------------------------------- + +GradFillPropertiesContext::GradFillPropertiesContext( const FragmentHandlerRef& xHandler, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >&, ::oox::drawingml::FillProperties& rFillProperties ) throw() +: FillPropertiesGroupContext( xHandler, FillStyle_GRADIENT, rFillProperties ) +{ +} + +void GradFillPropertiesContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) +{ +} + +Reference< XFastContextHandler > GradFillPropertiesContext::createFastChildContext( sal_Int32, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +{ + return this; +} + +// --------------------------------------------------------------------- +// CT_BlipFill +// --------------------------------------------------------------------- + +BlipFillPropertiesContext::BlipFillPropertiesContext( const FragmentHandlerRef& xHandler, const Reference< XFastAttributeList >&, + ::oox::drawingml::FillProperties& rFillProperties ) + throw() +: FillPropertiesGroupContext( xHandler, FillStyle_BITMAP, rFillProperties ) +, meBitmapMode( BitmapMode_REPEAT ) +, mnWidth( 0 ) +, mnHeight( 0 ) +{ + /* todo + if( xAttribs->hasAttribute( XML_dpi ) ) + { + xsd:unsignedInt + DPI (dots per inch) used to calculate the size of the blip. If not present or zero, + the DPI in the blip is used. + + } + if( xAttribs->hasAttribute( XML_rotWithShape ) ) + { + xsd:boolean + fill should rotate with the shape + } + */ +} + +void BlipFillPropertiesContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) +{ + if( msEmbed.getLength() ) + { + const OUString aFragmentPath = getHandler()->getFragmentPathFromRelId( msEmbed ); + if( aFragmentPath.getLength() > 0 ) try + { + // get the input stream for the fill bitmap + XmlFilterRef xFilter = getHandler()->getFilter(); + Reference< XInputStream > xInputStream( xFilter->openInputStream( aFragmentPath ), UNO_QUERY_THROW ); + + // load the fill bitmap into an XGraphic with the GraphicProvider + static const OUString sGraphicProvider = CREATE_OUSTRING( "com.sun.star.graphic.GraphicProvider" ); + Reference< XMultiServiceFactory > xMSFT( xFilter->getServiceFactory(), UNO_QUERY_THROW ); + Reference< XGraphicProvider > xGraphicProvider( xMSFT->createInstance( sGraphicProvider ), UNO_QUERY_THROW ); + + static const OUString sInputStream = CREATE_OUSTRING( "InputStream" ); + PropertyValues aMediaProperties(1); + aMediaProperties[0].Name = sInputStream; + aMediaProperties[0].Value <<= xInputStream; + + Reference< XGraphic > xGraphic( xGraphicProvider->queryGraphic(aMediaProperties ) ); + mrFillProperties.mxGraphic = xGraphic; + } + catch( Exception& ) + { + OSL_ENSURE( false, + (rtl::OString("oox::drawingml::BlipFillPropertiesContext::EndElement(), " + "exception caught: ") + + rtl::OUStringToOString( + comphelper::anyToString( cppu::getCaughtException() ), + RTL_TEXTENCODING_UTF8 )).getStr() ); + + } + + static const OUString sFillBitmapMode = CREATE_OUSTRING( "FillBitmapMode" ); + mrFillProperties.getFillPropertyMap()[ sFillBitmapMode ] <<= meBitmapMode; + } +} + +Reference< XFastContextHandler > BlipFillPropertiesContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_blip: // CT_Blip +// mnWidth = xAttribs.getInt32( XML_w ); +// mnHeight = xAttribs.getInt32( XML_h ); + msEmbed = xAttribs->getOptionalValue(NMSP_RELATIONSHIPS|XML_embed); // relationship identifer for embedded blobs + msLink = xAttribs->getOptionalValue(NMSP_RELATIONSHIPS|XML_link); // relationship identifer for linked blobs + break; + case NMSP_DRAWINGML|XML_alphaBiLevel: + case NMSP_DRAWINGML|XML_alphaCeiling: + case NMSP_DRAWINGML|XML_alphaFloor: + case NMSP_DRAWINGML|XML_alphaInv: + case NMSP_DRAWINGML|XML_alphaMod: + case NMSP_DRAWINGML|XML_alphaModFix: + case NMSP_DRAWINGML|XML_alphaRepl: + case NMSP_DRAWINGML|XML_biLevel: + case NMSP_DRAWINGML|XML_blur: + break; + case NMSP_DRAWINGML|XML_clrChange: + { + xRet = new clrChangeContext( getHandler(), xAttribs, mrFillProperties.getColorChangeFrom(), mrFillProperties.getColorChangeTo() ); + } + break; + case NMSP_DRAWINGML|XML_clrRepl: + case NMSP_DRAWINGML|XML_duotone: + case NMSP_DRAWINGML|XML_extLst: + case NMSP_DRAWINGML|XML_fillOverlay: + case NMSP_DRAWINGML|XML_grayscl: + case NMSP_DRAWINGML|XML_hsl: + case NMSP_DRAWINGML|XML_lum: + case NMSP_DRAWINGML|XML_tint: + break; + + case NMSP_DRAWINGML|XML_srcRect: // CT_RelativeRect +// todo maSrcRect = GetRelativeRect( xAttribs ); + break; + case NMSP_DRAWINGML|XML_tile: // CT_TileInfo + meBitmapMode = BitmapMode_REPEAT; +/* todo + mnTileX = GetCoordinate( xAttribs[ XML_tx ] ); // additional horizontal offset after alignment + mnTileY = GetCoordinate( xAttribs[ XML_ty ] ); // additional vertical offset after alignment + mnSX = xAttribs.getInt32( XML_sx, 100000 ); // amount to horizontally scale the srcRect + mnSX = xAttribs.getInt32( XML_sy, 100000 ); // amount to vertically scale the srcRect + mnFlip = xAttribs->getOptionalValueToken( XML_flip ); // ST_TileFlipMode how to flip the tile when it repeats + mnAlign = xAttribs->getOptionalValueToken( XML_algn ); // ST_RectAlignment where to align the first tile with respect to the shape; alignment happens after the scaling, but before the additional offset. +*/ + break; + case NMSP_DRAWINGML|XML_stretch: // CT_StretchInfo + meBitmapMode = BitmapMode_STRETCH; + break; + case NMSP_DRAWINGML|XML_fillRect: +// todo maFillRect = GetRelativeRect( xAttribs ); + break; + } + if ( !xRet.is() ) + xRet.set( this ); + return xRet; +} + +// --------------------------------------------------------------------- + +PattFillPropertiesContext::PattFillPropertiesContext( const FragmentHandlerRef& xHandler, const Reference< XFastAttributeList >&, ::oox::drawingml::FillProperties& rFillProperties ) throw() +: FillPropertiesGroupContext( xHandler, FillStyle_HATCH, rFillProperties ) +{ +} + +void PattFillPropertiesContext::startFastElement( sal_Int32, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +{ +} + +void PattFillPropertiesContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) +{ +} + +Reference< XFastContextHandler > PattFillPropertiesContext::createFastChildContext( sal_Int32, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +{ + return this; +} + +// --------------------------------------------------------------------- + +GrpFillPropertiesContext::GrpFillPropertiesContext( const FragmentHandlerRef& xHandler,const Reference< XFastAttributeList >&, ::oox::drawingml::FillProperties& rFillProperties ) throw() +: FillPropertiesGroupContext( xHandler, FillStyle_NONE, rFillProperties ) +{ +} + +void GrpFillPropertiesContext::startFastElement( sal_Int32, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +{ +} + +void GrpFillPropertiesContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) +{ +} + +Reference< XFastContextHandler > GrpFillPropertiesContext::createFastChildContext( sal_Int32, const Reference< XFastAttributeList >& ) + throw (SAXException, RuntimeException) +{ + return this; +} + + +// --------------------------------------------------------------------- + +clrChangeContext::clrChangeContext( const FragmentHandlerRef& xHandler,const Reference< XFastAttributeList >& xAttributes, + ColorPtr& raClrFrom, ColorPtr& raClrTo ) throw() +: Context( xHandler ) +, mraClrFrom( raClrFrom ) +, mraClrTo( raClrTo ) +, mbUseAlpha( xAttributes->getOptionalValueToken( XML_useA, XML_true ) == XML_true ? sal_True : sal_False ) +{ + mraClrFrom = ColorPtr( new Color() ); + mraClrTo = ColorPtr( new Color() ); +} +clrChangeContext::~clrChangeContext() +{ + if ( !mbUseAlpha ) + mraClrTo->mbAlphaColor = sal_False; +} +Reference< XFastContextHandler > clrChangeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& ) + throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_clrFrom: // CT_Color + xRet.set( new colorChoiceContext( getHandler(), *mraClrFrom.get() ) ); + break; + case NMSP_DRAWINGML|XML_clrTo: // CT_Color + xRet.set( new colorChoiceContext( getHandler(), *mraClrTo.get() ) ); + break; + default: + break; + } + return xRet; +} + +} } diff --git a/oox/source/drawingml/graphicshapecontext.cxx b/oox/source/drawingml/graphicshapecontext.cxx new file mode 100644 index 000000000000..c9e9de409d88 --- /dev/null +++ b/oox/source/drawingml/graphicshapecontext.cxx @@ -0,0 +1,335 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: graphicshapecontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include + +#include "oox/drawingml/fillpropertiesgroupcontext.hxx" +#include "oox/drawingml/graphicshapecontext.hxx" +#include "oox/drawingml/diagram/diagramfragmenthandler.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "tokens.hxx" +#ifndef _COMPHELPER_PROCESSFACTORY_HXX_ +#include +#endif +#include "com/sun/star/container/XNameAccess.hpp" +#include "com/sun/star/io/XStream.hpp" +#include "com/sun/star/beans/XPropertySet.hpp" +#include "com/sun/star/document/XEmbeddedObjectResolver.hpp" +#include + +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::oox::core; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +// ==================================================================== +// CT_Picture +GraphicShapeContext::GraphicShapeContext( const FragmentHandlerRef& xHandler, ShapePtr pMasterShapePtr, ShapePtr pShapePtr ) +: ShapeContext( xHandler, pMasterShapePtr, pShapePtr ) +{ +} + +Reference< XFastContextHandler > GraphicShapeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElementToken &(~NMSP_MASK) ) + { + // CT_ShapeProperties + case XML_xfrm: + xRet.set( new Transform2DContext( getHandler(), xAttribs, *(mpShapePtr.get()) ) ); + break; + case XML_blipFill: + xRet.set( new BlipFillPropertiesContext( getHandler(), xAttribs, *(mpShapePtr->getGraphicProperties().get()) ) ); + break; + } + if( !xRet.is() ) + xRet.set( ShapeContext::createFastChildContext( aElementToken, xAttribs ) ); + + return xRet; +} + +// ==================================================================== +// CT_GraphicalObjectFrameContext +GraphicalObjectFrameContext::GraphicalObjectFrameContext( const FragmentHandlerRef& xHandler, ShapePtr pMasterShapePtr, ShapePtr pShapePtr ) +: ShapeContext( xHandler, pMasterShapePtr, pShapePtr ) +{ +} + +Reference< XFastContextHandler > GraphicalObjectFrameContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElementToken &(~NMSP_MASK) ) + { + // CT_ShapeProperties + case XML_nvGraphicFramePr: // CT_GraphicalObjectFrameNonVisual + break; + case XML_xfrm: // CT_Transform2D + xRet.set( new Transform2DContext( getHandler(), xAttribs, *(mpShapePtr.get()) ) ); + break; + case XML_graphic: // CT_GraphicalObject + xRet.set( this ); + break; + + case XML_graphicData : // CT_GraphicalObjectData + { + rtl::OUString sUri( xAttribs->getOptionalValue( XML_uri ) ); + if ( sUri.compareToAscii( "http://schemas.openxmlformats.org/presentationml/2006/ole" ) == 0 ) + xRet.set( new PresentationOle2006Context( mxHandler, mpShapePtr ) ); + else if ( sUri.compareToAscii( "http://schemas.openxmlformats.org/drawingml/2006/diagram" ) == 0 ) + xRet.set( new DiagramGraphicDataContext( mxHandler, mpShapePtr ) ); + else if ( sUri.compareToAscii( "http://schemas.openxmlformats.org/drawingml/2006/table" ) == 0 ) + // TODO deal with tables too. + xRet.set( this ); + else + { + OSL_TRACE( "OOX: Ignore graphicsData of %s", OUSTRING_TO_CSTR( sUri ) ); + return xRet; + } + } + break; + } + if( !xRet.is() ) + xRet.set( ShapeContext::createFastChildContext( aElementToken, xAttribs ) ); + + return xRet; +} + +// ==================================================================== + +PresentationOle2006Context::PresentationOle2006Context( const FragmentHandlerRef& xHandler, ShapePtr pShapePtr ) +: ShapeContext( xHandler, ShapePtr(), pShapePtr ) +{ +} + +PresentationOle2006Context::~PresentationOle2006Context() +{ + XmlFilterRef xFilter = getHandler()->getFilter(); + const OUString aFragmentPath = getHandler()->getFragmentPathFromRelId( msId ); + if( aFragmentPath.getLength() > 0 ) + { + Reference< ::com::sun::star::io::XInputStream > xInputStream( xFilter->openInputStream( aFragmentPath ), UNO_QUERY_THROW ); + + Sequence< sal_Int8 > aData; + xInputStream->readBytes( aData, 0x7fffffff ); + uno::Reference< lang::XMultiServiceFactory > xMSF( xFilter->getModel(), UNO_QUERY ); + Reference< com::sun::star::document::XEmbeddedObjectResolver > xEmbeddedResolver( xMSF->createInstance( OUString::createFromAscii( "com.sun.star.document.ImportEmbeddedObjectResolver" ) ), UNO_QUERY ); + + if ( xEmbeddedResolver.is() ) + { + Reference< com::sun::star::container::XNameAccess > xNA( xEmbeddedResolver, UNO_QUERY ); + if( xNA.is() ) + { + Reference < XOutputStream > xOLEStream; + OUString aURL = CREATE_OUSTRING( "Obj12345678" ); + Any aAny( xNA->getByName( aURL ) ); + aAny >>= xOLEStream; + if ( xOLEStream.is() ) + { + xOLEStream->writeBytes( aData ); + xOLEStream->closeOutput(); + + const OUString sProtocol = CREATE_OUSTRING( "vnd.sun.star.EmbeddedObject:" ); + rtl::OUString aPersistName( xEmbeddedResolver->resolveEmbeddedObjectURL( aURL ) ); + aPersistName = aPersistName.copy( sProtocol.getLength() ); + + static const OUString sPersistName = CREATE_OUSTRING( "PersistName" ); + mpShapePtr->getShapeProperties()[ sPersistName ] <<= aPersistName; + } + } + Reference< XComponent > xComp( xEmbeddedResolver, UNO_QUERY ); + xComp->dispose(); + } + } + + // taking care of the representation graphic + if ( msSpid.getLength() ) + { + oox::vml::DrawingPtr pDrawingPtr = xFilter->getDrawings(); + if ( pDrawingPtr.get() ) + { + rtl::OUString aGraphicURL( pDrawingPtr->getGraphicUrlById( msSpid ) ); + if ( aGraphicURL.getLength() ) + { + try + { + uno::Reference< lang::XMultiServiceFactory > xMSF( ::comphelper::getProcessServiceFactory() ); + Reference< io::XInputStream > xInputStream( xFilter->openInputStream( aGraphicURL ), UNO_QUERY_THROW ); + Reference< graphic::XGraphicProvider > xGraphicProvider( xMSF->createInstance( OUString::createFromAscii( "com.sun.star.graphic.GraphicProvider" ) ), UNO_QUERY_THROW ); + if ( xInputStream.is() && xGraphicProvider.is() ) + { + Sequence< PropertyValue > aArgs( 1 ); + const OUString sInputStream = CREATE_OUSTRING( "InputStream" ); + aArgs[ 0 ].Name = sInputStream; + aArgs[ 0 ].Value <<= xInputStream; + Reference< graphic::XGraphic > xGraphic = xGraphicProvider->queryGraphic( aArgs ); + if ( xGraphic.is() ) + { + static const OUString sEmptyGraphicURL; + static const OUString sGraphicURL = CREATE_OUSTRING( "GraphicURL" ); + mpShapePtr->getShapeProperties()[ sGraphicURL ] <<= sEmptyGraphicURL; + + static const OUString sThumbnailGraphic = CREATE_OUSTRING( "Graphic" ); + mpShapePtr->getShapeProperties()[ sThumbnailGraphic ] <<= xGraphic; + } + } + } + catch( Exception& ) + { + } + } + } + } +} + +Reference< XFastContextHandler > PresentationOle2006Context::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElementToken &(~NMSP_MASK) ) + { + case XML_oleObj: + { + msSpid = xAttribs->getOptionalValue( XML_spid ); + msName = xAttribs->getOptionalValue( XML_name ); + msId = xAttribs->getOptionalValue( NMSP_RELATIONSHIPS|XML_id ); + mnWidth = GetCoordinate( xAttribs->getOptionalValue( XML_imgW ) ); + mnHeight = GetCoordinate( xAttribs->getOptionalValue( XML_imgH ) ); + msProgId = xAttribs->getOptionalValue( XML_progId ); + } + break; + + case XML_embed: + { + mnFollowColorSchemeToken = xAttribs->getOptionalValueToken( XML_followColorScheme, XML_full ); + } + break; + } + if( !xRet.is() ) + xRet.set( ShapeContext::createFastChildContext( aElementToken, xAttribs ) ); + + return xRet; +} + +DiagramGraphicDataContext::DiagramGraphicDataContext( const ::oox::core::FragmentHandlerRef& xHandler, ShapePtr pShapePtr ) +: ShapeContext( xHandler, ShapePtr(), pShapePtr ) +{ +} + + + +DiagramGraphicDataContext::~DiagramGraphicDataContext() +{ + +} + +DiagramPtr DiagramGraphicDataContext::loadDiagram() +{ + DiagramPtr pDiagram( new Diagram() ); + const oox::core::XmlFilterRef& xFilter( getHandler()->getFilter() ); + + // data + OUString sDmPath = getHandler()->getFragmentPathFromRelId( msDm ); + if( sDmPath.getLength() > 0 ) + { + DiagramDataPtr pData( new DiagramData() ); + pDiagram->setData( pData ); + xFilter->importFragment( new DiagramDataFragmentHandler( xFilter, sDmPath, pData ) ); + } + // layout + OUString sLoPath = getHandler()->getFragmentPathFromRelId( msLo ); + if( sLoPath.getLength() > 0 ) + { + DiagramLayoutPtr pLayout( new DiagramLayout() ); + pDiagram->setLayout( pLayout ); + xFilter->importFragment( new DiagramLayoutFragmentHandler( xFilter, sLoPath, pLayout ) ); + } + // style + OUString sQsPath = getHandler()->getFragmentPathFromRelId( msQs ); + if( sQsPath.getLength() > 0 ) + { + DiagramQStylesPtr pStyles( new DiagramQStyles() ); + pDiagram->setQStyles( pStyles ); + xFilter->importFragment( new DiagramQStylesFragmentHandler( xFilter, sQsPath, pStyles ) ); + } + // colors + OUString sCsPath = getHandler()->getFragmentPathFromRelId( msCs ); + if( sCsPath.getLength() > 0 ) + { + DiagramColorsPtr pColors( new DiagramColors() ); + pDiagram->setColors( pColors ); + xFilter->importFragment( new DiagramColorsFragmentHandler( xFilter, sCsPath, pColors ) ) ; + } + + return pDiagram; +} + + +Reference< XFastContextHandler > DiagramGraphicDataContext::createFastChildContext( ::sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case NMSP_DIAGRAM|XML_relIds: + { + msDm = xAttribs->getOptionalValue( NMSP_RELATIONSHIPS|XML_dm ); + msLo = xAttribs->getOptionalValue( NMSP_RELATIONSHIPS|XML_lo ); + msQs = xAttribs->getOptionalValue( NMSP_RELATIONSHIPS|XML_qs ); + msCs = xAttribs->getOptionalValue( NMSP_RELATIONSHIPS|XML_cs ); + DiagramPtr pDiagram = loadDiagram(); + pDiagram->addTo( mpShapePtr ); + break; + } + default: + break; + } + + if( !xRet.is() ) + xRet.set( ShapeContext::createFastChildContext( aElementToken, xAttribs ) ); + + return xRet; +} + +} } diff --git a/oox/source/drawingml/hyperlinkcontext.cxx b/oox/source/drawingml/hyperlinkcontext.cxx new file mode 100644 index 000000000000..d4c75b83663f --- /dev/null +++ b/oox/source/drawingml/hyperlinkcontext.cxx @@ -0,0 +1,121 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: hyperlinkcontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "hyperlinkcontext.hxx" + +#include + +#include + +#include "oox/helper/propertymap.hxx" +#include "oox/core/relations.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/core/skipcontext.hxx" +#include "oox/drawingml/embeddedwavaudiofile.hxx" +#include "tokens.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + + + HyperLinkContext::HyperLinkContext( const FragmentHandlerRef& xParent, + const Reference< XFastAttributeList >& xAttributes, + PropertyMap& aProperties) + : Context( xParent ) + , maProperties(aProperties) + { + OUString aRelId = xAttributes->getOptionalValue( NMSP_RELATIONSHIPS|XML_id ); + OSL_TRACE("OOX: URI rId %s", ::rtl::OUStringToOString (aRelId, RTL_TEXTENCODING_UTF8).pData->buffer); + const OUString& sHref = getHandler()->getRelations().getTargetFromRelId( aRelId ); + if( sHref.getLength() > 0 ) + { + OSL_TRACE("OOX: URI href %s", ::rtl::OUStringToOString (sHref, RTL_TEXTENCODING_UTF8).pData->buffer); + const OUString sURL( CREATE_OUSTRING( "URL" ) ); + maProperties[ sURL ] <<= getHandler()->getFilter()->getAbsoluteUrl( sHref ); + OUString sTooltip = xAttributes->getOptionalValue( NMSP_RELATIONSHIPS|XML_tooltip ); + const OUString sRepresentation( CREATE_OUSTRING( "Representation" ) ); + maProperties[ sRepresentation ] <<= sTooltip; + + OUString sFrame = xAttributes->getOptionalValue( NMSP_RELATIONSHIPS|XML_tgtFrame ); + if( sFrame.getLength() ) + { + const OUString sTargetFrame( CREATE_OUSTRING( "TargetFrame" ) ); + maProperties[ sTargetFrame ] <<= sFrame; + } + +// sValue = OUString( RTL_CONSTASCII_USTRINGPARAM( "" ) ); +// const rtl::OUString sUnvisitedCharStyleName( CREATE_OUSTRING( "UnvisitedCharStyleName" ) ); +// maProperties[ sUnvisitedCharStyleName ] <<= sValue; +// const rtl::OUString sVisitedCharStyleName( CREATE_OUSTRING( "VisitedCharStyleName" ) ); +// maProperties[ sVisitedCharStyleName ] <<= sValue; + + } + // TODO unhandled + // XML_invalidUrl + // XML_history + // XML_highlightClick + // XML_endSnd + // XML_action + } + + HyperLinkContext::~HyperLinkContext() + { + } + + Reference< XFastContextHandler > HyperLinkContext::createFastChildContext( ::sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) + { + Reference< XFastContextHandler > xRet; + switch( aElement ) + { + case NMSP_DRAWINGML|XML_extLst: + xRet.set( new SkipContext( getHandler() ) ); + break; + case NMSP_DRAWINGML|XML_snd: + EmbeddedWAVAudioFile aAudio; + getEmbeddedWAVAudioFile( getHandler(), xAttribs, aAudio ); + break; + } + if ( !xRet.is() ) + xRet.set( this ); + return xRet; + } + +} } diff --git a/oox/source/drawingml/hyperlinkcontext.hxx b/oox/source/drawingml/hyperlinkcontext.hxx new file mode 100644 index 000000000000..f35261aaad54 --- /dev/null +++ b/oox/source/drawingml/hyperlinkcontext.hxx @@ -0,0 +1,67 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: hyperlinkcontext.hxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef OOX_DRAWINGML_HYPERLINKCONTEXT_HXX +#define OOX_DRAWINGML_HYPERLINKCONTEXT_HXX + +#include + +#include "oox/core/context.hxx" +#include "oox/core/fragmenthandler.hxx" + +namespace oox { class PropertyMap; } + +namespace oox { namespace drawingml { + + class HyperLinkContext : public ::oox::core::Context + { + public: + HyperLinkContext( const ::oox::core::FragmentHandlerRef& xParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs, + PropertyMap& aProperties); + ~HyperLinkContext(); + +// virtual void SAL_CALL endFastElement( ::sal_Int32 Element ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 Element, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + + protected: + PropertyMap& maProperties; + }; + + +} } + + +#endif diff --git a/oox/source/drawingml/lineproperties.cxx b/oox/source/drawingml/lineproperties.cxx new file mode 100644 index 000000000000..ed4261f7154b --- /dev/null +++ b/oox/source/drawingml/lineproperties.cxx @@ -0,0 +1,349 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: lineproperties.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/lineproperties.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" +#include +#include +#include +#include "oox/helper/propertyset.hxx" +#include +#include +#include +#include +#include + +using rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; + +namespace oox { namespace drawingml { + +LineProperties::LineProperties() +: maLineColor( new Color() ) +{ +} +LineProperties::~LineProperties() +{ +} + +void LineProperties::apply( const LinePropertiesPtr& rSourceLineProperties ) +{ + maLineProperties.insert( rSourceLineProperties->maLineProperties.begin(), rSourceLineProperties->maLineProperties.end() ); + if ( rSourceLineProperties->maLineColor->isUsed() ) + maLineColor = rSourceLineProperties->maLineColor; + if ( rSourceLineProperties->moLineWidth ) + moLineWidth = rSourceLineProperties->moLineWidth; + if ( rSourceLineProperties->moStartArrow ) + moStartArrow = rSourceLineProperties->moStartArrow; + if ( rSourceLineProperties->moStartArrowWidth ) + moStartArrowWidth = rSourceLineProperties->moStartArrowWidth; + if ( rSourceLineProperties->moStartArrowLength ) + moStartArrowLength = rSourceLineProperties->moStartArrowLength; + if ( rSourceLineProperties->moEndArrow ) + moEndArrow = rSourceLineProperties->moEndArrow; + if ( rSourceLineProperties->moEndArrowWidth ) + moEndArrowWidth = rSourceLineProperties->moEndArrowWidth; + if ( rSourceLineProperties->moEndArrowLength ) + moEndArrowLength = rSourceLineProperties->moEndArrowLength; + if ( rSourceLineProperties->moPresetDash ) + moPresetDash = rSourceLineProperties->moPresetDash; + if ( rSourceLineProperties->moLineCap ) + moLineCap = rSourceLineProperties->moLineCap; +} + +static com::sun::star::drawing::PolyPolygonBezierCoords GetLineArrow( const sal_Int32 nLineWidth, const sal_Int32 nLineEndToken, + const sal_Int32 nArrowWidthToken, const sal_Int32 nArrowLengthToken, sal_Int32& rnArrowWidth, sal_Bool& rbArrowCenter, rtl::OUString& rsArrowName ) +{ + uno::Sequence< awt::Point > aPoly; + + double fLineWidth = nLineWidth < 70 ? 70.0 : nLineWidth; + double fLenghtMul, fWidthMul; + sal_Int32 nLineNumber; + switch( nArrowLengthToken ) + { + default : + case XML_med: fLenghtMul = 3.0; nLineNumber = 2; break; + case XML_sm : fLenghtMul = 2.0; nLineNumber = 1; break; + case XML_lg : fLenghtMul = 5.0; nLineNumber = 3; break; + } + switch( nArrowWidthToken ) + { + default : + case XML_med: fWidthMul = 3.0; nLineNumber += 3; break; + case XML_sm : fWidthMul = 2.0; break; + case XML_lg : fWidthMul = 5.0; nLineNumber += 6; break; + } + rbArrowCenter = sal_False; + switch ( nLineEndToken ) + { + case XML_triangle : + { + aPoly.realloc( 4 ); + aPoly[ 0 ] = awt::Point( static_cast< sal_Int32 >( fWidthMul * fLineWidth * 0.50 ), 0 ); + aPoly[ 1 ] = awt::Point( static_cast< sal_Int32 >( fWidthMul * fLineWidth ), static_cast< sal_Int32 >( fLenghtMul * fLineWidth ) ); + aPoly[ 2 ] = awt::Point( 0, static_cast< sal_Int32 >( fLenghtMul * fLineWidth ) ); + aPoly[ 3 ] = awt::Point( static_cast< sal_Int32 >( fWidthMul * fLineWidth * 0.50 ), 0 ); + static const OUString sArrowEnd( RTL_CONSTASCII_USTRINGPARAM( "msArrowEnd " ) ); + rsArrowName = sArrowEnd; + } + break; + + case XML_arrow : + { + switch( nArrowLengthToken ) + { + default : + case XML_med: fLenghtMul = 4.5; break; + case XML_sm : fLenghtMul = 3.5; break; + case XML_lg : fLenghtMul = 6.0; break; + } + switch( nArrowWidthToken ) + { + default : + case XML_med: fWidthMul = 4.5; break; + case XML_sm : fWidthMul = 3.5; break; + case XML_lg : fWidthMul = 6.0; break; + } + aPoly.realloc( 7 ); + aPoly[ 0 ] = awt::Point( static_cast< sal_Int32 >( fWidthMul * fLineWidth * 0.50 ), 0 ); + aPoly[ 1 ] = awt::Point( static_cast< sal_Int32 >( fWidthMul * fLineWidth ), static_cast< sal_Int32 >( fLenghtMul * fLineWidth * 0.91 ) ); + aPoly[ 2 ] = awt::Point( static_cast< sal_Int32 >( fWidthMul * fLineWidth * 0.85 ), static_cast< sal_Int32 >( fLenghtMul * fLineWidth ) ); + aPoly[ 3 ] = awt::Point( static_cast< sal_Int32 >( fWidthMul * fLineWidth * 0.50 ), static_cast< sal_Int32 >( fLenghtMul * fLineWidth * 0.36 ) ); + aPoly[ 4 ] = awt::Point( static_cast< sal_Int32 >( fWidthMul * fLineWidth * 0.15 ), static_cast< sal_Int32 >( fLenghtMul * fLineWidth ) ); + aPoly[ 5 ] = awt::Point( 0, static_cast< sal_Int32 >( fLenghtMul * fLineWidth * 0.91 ) ); + aPoly[ 6 ] = awt::Point( static_cast< sal_Int32 >( fWidthMul * fLineWidth * 0.50 ), 0 ); + static const OUString sArrowOpenEnd( RTL_CONSTASCII_USTRINGPARAM( "msArrowOpenEnd " ) ); + rsArrowName = sArrowOpenEnd; + } + break; + case XML_stealth : + { + aPoly.realloc( 5 ); + aPoly[ 0 ] = awt::Point( static_cast< sal_Int32 >( fWidthMul * fLineWidth * 0.50 ), 0 ); + aPoly[ 1 ] = awt::Point( static_cast< sal_Int32 >( fWidthMul * fLineWidth ), static_cast< sal_Int32 >( fLenghtMul * fLineWidth ) ); + aPoly[ 2 ] = awt::Point( static_cast< sal_Int32 >( fWidthMul * fLineWidth * 0.50 ), static_cast< sal_Int32 >( fLenghtMul * fLineWidth * 0.60 ) ); + aPoly[ 3 ] = awt::Point( 0, static_cast< sal_Int32 >( fLenghtMul * fLineWidth ) ); + aPoly[ 4 ] = awt::Point( static_cast< sal_Int32 >( fWidthMul * fLineWidth * 0.50 ), 0 ); + static const OUString sArrowStealthEnd( RTL_CONSTASCII_USTRINGPARAM( "msArrowStealthEnd " ) ); + rsArrowName = sArrowStealthEnd; + } + break; + case XML_diamond : + { + aPoly.realloc( 5 ); + aPoly[ 0 ] = awt::Point( static_cast< sal_Int32 >( fWidthMul * fLineWidth * 0.50 ), 0 ); + aPoly[ 1 ] = awt::Point( static_cast< sal_Int32 >( fWidthMul * fLineWidth ), static_cast< sal_Int32 >( fLenghtMul * fLineWidth * 0.50 ) ); + aPoly[ 2 ] = awt::Point( static_cast< sal_Int32 >( fWidthMul * fLineWidth * 0.50 ), static_cast< sal_Int32 >( fLenghtMul * fLineWidth ) ); + aPoly[ 3 ] = awt::Point( 0, static_cast< sal_Int32 >( fLenghtMul * fLineWidth * 0.50 ) ); + aPoly[ 4 ] = awt::Point( static_cast< sal_Int32 >( fWidthMul * fLineWidth * 0.50 ), 0 ); + static const OUString sArrowDiamondEnd( RTL_CONSTASCII_USTRINGPARAM( "msArrowDiamondEnd " ) ); + rsArrowName = sArrowDiamondEnd; + rbArrowCenter = sal_True; + } + break; + case XML_oval : + { + aPoly.realloc( 5 ); + aPoly[ 0 ] = awt::Point( static_cast< sal_Int32 >( fWidthMul * fLineWidth * 0.50 ), 0 ); + aPoly[ 1 ] = awt::Point( static_cast< sal_Int32 >( fWidthMul * fLineWidth ), static_cast< sal_Int32 >( fLenghtMul * fLineWidth * 0.50 ) ); + aPoly[ 2 ] = awt::Point( static_cast< sal_Int32 >( fWidthMul * fLineWidth * 0.50 ), static_cast< sal_Int32 >( fLenghtMul * fLineWidth ) ); + aPoly[ 3 ] = awt::Point( 0, static_cast< sal_Int32 >( fLenghtMul * fLineWidth * 0.50 ) ); + aPoly[ 4 ] = awt::Point( static_cast< sal_Int32 >( fWidthMul * fLineWidth * 0.50 ), 0 ); + static const OUString sArrowOvalEnd( RTL_CONSTASCII_USTRINGPARAM( "msArrowOvalEnd " ) ); + rsArrowName = sArrowOvalEnd; + rbArrowCenter = sal_True; + } + break; + default: break; + } + rsArrowName += rtl::OUString::valueOf( nLineNumber ); + rnArrowWidth = static_cast< sal_Int32 >( fLineWidth * fWidthMul ); + + com::sun::star::drawing::PolyPolygonBezierCoords aPolyPolyBezier; + aPolyPolyBezier.Coordinates.realloc( 1 ); + aPolyPolyBezier.Flags.realloc( 1 ); + ::com::sun::star::drawing::PointSequence* pOuterSequence = aPolyPolyBezier.Coordinates.getArray(); + ::com::sun::star::drawing::FlagSequence* pOuterFlags = aPolyPolyBezier.Flags.getArray(); + pOuterSequence[ 0 ] = aPoly; + pOuterFlags[ 0 ] = ::com::sun::star::drawing::PolygonFlags( aPoly.getLength() ); + return aPolyPolyBezier; +} + +void setArrow( const ::oox::core::XmlFilterBase& rFilterBase, rtl::OUString& rName, com::sun::star::drawing::PolyPolygonBezierCoords& rPoly ) +{ + uno::Reference< container::XNameContainer >& xMarker( rFilterBase.getMarkerTable() ); + try + { + if( xMarker.is() ) + { + if( xMarker->hasByName( rName ) ) + xMarker->replaceByName( rName, Any( rPoly ) ); + else + xMarker->insertByName( rName, Any( rPoly ) ); + } + } + catch( container::ElementExistException& ) + {} +} + +void LineProperties::pushToPropSet( const ::oox::core::XmlFilterBase& rFilterBase, + const Reference < XPropertySet >& xPropSet ) const +{ + PropertySet aPropSet( xPropSet ); + Sequence< OUString > aNames; + Sequence< Any > aValues; + + maLineProperties.makeSequence( aNames, aValues ); + aPropSet.setProperties( aNames, aValues ); + if ( maLineColor->isUsed() ) + { + const rtl::OUString sLineColor( OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "LineColor" ) ) ); + xPropSet->setPropertyValue( sLineColor, Any( maLineColor->getColor( rFilterBase ) ) ); + } + if ( moLineWidth ) + { + const rtl::OUString sLineWidth( OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "LineWidth" ) ) ); + xPropSet->setPropertyValue( sLineWidth, Any( *moLineWidth ) ); + } + if ( moStartArrow && ( *moStartArrow != XML_none ) ) + { + sal_Int32 nArrowWidth; + sal_Bool bArrowCenter; + rtl::OUString aArrowName; + com::sun::star::drawing::PolyPolygonBezierCoords aPoly( GetLineArrow( moLineWidth ? *moLineWidth : 70, *moStartArrow, + moStartArrowWidth ? *moStartArrowWidth : XML_med, moStartArrowLength ? *moStartArrowLength : XML_med, nArrowWidth, bArrowCenter, aArrowName ) ); + const rtl::OUString sLineStart( OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "LineStart" ) ) ); + const rtl::OUString sLineStartName( OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "LineStartName" ) ) ); + const rtl::OUString sLineStartCenter( OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "LineStartCenter" ) ) ); + const rtl::OUString sLineStartWidth( OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "LineStartWidth" ) ) ); +// xPropSet->setPropertyValue( sLineStart, Any( aPoly ) ); + setArrow( rFilterBase, aArrowName, aPoly ); + xPropSet->setPropertyValue( sLineStartName, Any( aArrowName ) ); + xPropSet->setPropertyValue( sLineStartCenter, Any( bArrowCenter ) ); + xPropSet->setPropertyValue( sLineStartWidth, Any( nArrowWidth ) ); + } + if ( moEndArrow && ( *moEndArrow != XML_none ) ) + { + sal_Int32 nArrowWidth; + sal_Bool bArrowCenter; + rtl::OUString aArrowName; + com::sun::star::drawing::PolyPolygonBezierCoords aPoly( GetLineArrow( moLineWidth ? *moLineWidth : 70, *moEndArrow, + moEndArrowWidth ? *moEndArrowWidth : XML_med, moEndArrowLength ? *moEndArrowLength : XML_med, nArrowWidth, bArrowCenter, aArrowName ) ); + const rtl::OUString sLineEnd( OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "LineEnd" ) ) ); + const rtl::OUString sLineEndName( OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "LineEndName" ) ) ); + const rtl::OUString sLineEndCenter( OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "LineEndCenter" ) ) ); + const rtl::OUString sLineEndWidth( OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "LineEndWidth" ) ) ); +// xPropSet->setPropertyValue( sLineEnd, Any( aPoly ) ); + setArrow( rFilterBase, aArrowName, aPoly ); + xPropSet->setPropertyValue( sLineEndName, Any( aArrowName ) ); + xPropSet->setPropertyValue( sLineEndCenter, Any( bArrowCenter ) ); + xPropSet->setPropertyValue( sLineEndWidth, Any( nArrowWidth ) ); + } + if ( moPresetDash ) // ST_PresetLineDashVal + { + const rtl::OUString sLineStyle( OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "LineStyle" ) ) ); + if ( *moPresetDash == XML_solid ) + xPropSet->setPropertyValue( sLineStyle, Any( drawing::LineStyle_SOLID ) ); + else + { + sal_Int32 nLineWidth = moLineWidth ? *moLineWidth : 288; + drawing::LineDash aLineDash; + aLineDash.Style = drawing::DashStyle_ROUNDRELATIVE; + if ( moLineCap ) + { + switch( *moLineCap ) + { + default: + case XML_rnd: // Rounded ends. Semi-circle protrudes by half line width. + aLineDash.Style = drawing::DashStyle_ROUNDRELATIVE; + break; + case XML_sq: // Square protrudes by half line width. + aLineDash.Style = drawing::DashStyle_RECTRELATIVE; + break; + case XML_flat: // Line ends at end point. + aLineDash.Style = drawing::DashStyle_RECT; + break; + } + } + aLineDash.Dots = 1; + aLineDash.DotLen = nLineWidth; + aLineDash.Dashes = 0; + aLineDash.DashLen = ( 8 * nLineWidth ); + aLineDash.Distance = ( 3 * nLineWidth ); + + switch( *moPresetDash ) + { + default : + case XML_dash : + case XML_sysDash : + aLineDash.DashLen = ( 4 * nLineWidth ); // !!PASSTHROUGH INTENDED + case XML_lgDash : + { + aLineDash.Dots = 0; + aLineDash.Dashes = 1; + } + break; + case XML_dashDot : + case XML_sysDashDot : + aLineDash.DashLen = ( 4 * nLineWidth ); // !!PASSTHROUGH INTENDED + case XML_lgDashDot : + aLineDash.Dashes = 1; + break; + case XML_sysDashDotDot : + aLineDash.DashLen = ( 4 * nLineWidth ); // !!PASSTHROUGH INTENDED + case XML_lgDashDotDot : + { + aLineDash.Dots = 2; + aLineDash.Dashes = 1; + } + break; + case XML_dot : + case XML_sysDot : + aLineDash.Distance = aLineDash.DotLen; + break; + } + const rtl::OUString sLineDash( OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "LineDash" ) ) ); + xPropSet->setPropertyValue( sLineStyle, Any( drawing::LineStyle_DASH ) ); + xPropSet->setPropertyValue( sLineDash, Any( aLineDash ) ); + } + } +} + +} } diff --git a/oox/source/drawingml/linepropertiescontext.cxx b/oox/source/drawingml/linepropertiescontext.cxx new file mode 100644 index 000000000000..5f21b0aa7109 --- /dev/null +++ b/oox/source/drawingml/linepropertiescontext.cxx @@ -0,0 +1,157 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: linepropertiescontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/linepropertiescontext.hxx" + +#include +#include +#include "oox/helper/propertymap.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/drawingml/colorchoicecontext.hxx" +#include "oox/drawingml/drawingmltypes.hxx" + +#include "tokens.hxx" + +using ::rtl::OUString; +using ::com::sun::star::beans::NamedValue; +using namespace ::oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +// CT_LineProperties + +namespace oox { namespace drawingml { +// --------------------------------------------------------------------- + +LinePropertiesContext::LinePropertiesContext( const FragmentHandlerRef& xHandler, const Reference< XFastAttributeList >& xAttribs, + oox::drawingml::LineProperties& rLineProperties ) throw() +: Context( xHandler ) +, mrLineProperties( rLineProperties ) +{ + // ST_LineWidth + if( xAttribs->hasAttribute( XML_w ) ) + mrLineProperties.getLineWidth() = boost::optional< sal_Int32 >( GetCoordinate( xAttribs->getOptionalValue( XML_w ) ) ); + + // "ST_LineCap" + if( xAttribs->hasAttribute( XML_cap ) ) + mrLineProperties.getLineCap() = boost::optional< sal_Int32 >( xAttribs->getOptionalValueToken( XML_cap, 0 ) ); + + // if ( xAttribs->hasAttribute( XML_cmpd ) ) ST_CompoundLine + // if ( xAttribs->hasAttribute( XML_algn ) ) ST_PenAlignment +} + +LinePropertiesContext::~LinePropertiesContext() +{ +} + +Reference< XFastContextHandler > LinePropertiesContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + const rtl::OUString sLineStyle( RTL_CONSTASCII_USTRINGPARAM( "LineStyle" ) ); + switch( aElementToken ) + { + // LineFillPropertiesGroup, line fillings currently unsuported + case NMSP_DRAWINGML|XML_noFill: + mrLineProperties.getLinePropertyMap()[ sLineStyle ] <<= LineStyle_NONE; + break; + case NMSP_DRAWINGML|XML_solidFill: + { + mrLineProperties.getLinePropertyMap()[ sLineStyle ] <<= LineStyle_SOLID; + xRet = new colorChoiceContext( getHandler(), *mrLineProperties.getLineColor().get() ); + } + break; + case NMSP_DRAWINGML|XML_gradFill: + case NMSP_DRAWINGML|XML_pattFill: + mrLineProperties.getLinePropertyMap()[ sLineStyle ] <<= LineStyle_SOLID; + break; + + // LineDashPropertiesGroup + case NMSP_DRAWINGML|XML_prstDash: // CT_PresetLineDashProperties + mrLineProperties.getPresetDash() = boost::optional< sal_Int32 >( xAttribs->getOptionalValueToken( XML_val, XML_solid ) ); + break; + case NMSP_DRAWINGML|XML_custDash: // CT_DashStopList + break; + + // LineJoinPropertiesGroup + case NMSP_DRAWINGML|XML_round: + case NMSP_DRAWINGML|XML_bevel: + case NMSP_DRAWINGML|XML_miter: + { + LineJoint eJoint = (aElementToken == (NMSP_DRAWINGML|XML_round)) ? LineJoint_ROUND : + (aElementToken == (NMSP_DRAWINGML|XML_bevel)) ? LineJoint_BEVEL : + LineJoint_MITER; + static const OUString sLineJoint( RTL_CONSTASCII_USTRINGPARAM( "LineJoint" ) ); + mrLineProperties.getLinePropertyMap()[ sLineJoint ] <<= eJoint; + } + break; + + case NMSP_DRAWINGML|XML_headEnd: // CT_LineEndProperties + case NMSP_DRAWINGML|XML_tailEnd: // CT_LineEndProperties + { // ST_LineEndType + if( xAttribs->hasAttribute( XML_type ) ) + { + sal_Int32 nType = xAttribs->getOptionalValueToken( XML_type, 0 ); + if ( aElementToken == ( NMSP_DRAWINGML|XML_tailEnd ) ) + mrLineProperties.getStartArrow() = boost::optional< sal_Int32 >( nType ); + else + mrLineProperties.getEndArrow() = boost::optional< sal_Int32 >( nType ); + } + if ( xAttribs->hasAttribute( XML_w ) ) + { + sal_Int32 nW = xAttribs->getOptionalValueToken( XML_w, 0 ); + if ( aElementToken == ( NMSP_DRAWINGML|XML_tailEnd ) ) + mrLineProperties.getStartArrowWidth() = boost::optional< sal_Int32 >( nW ); + else + mrLineProperties.getEndArrowWidth() = boost::optional< sal_Int32 >( nW ); + } + if ( xAttribs->hasAttribute( XML_len ) ) + { + sal_Int32 nLen = xAttribs->getOptionalValueToken( XML_len, 0 ); + if ( aElementToken == ( NMSP_DRAWINGML|XML_tailEnd ) ) + mrLineProperties.getStartArrowLength() = boost::optional< sal_Int32 >( nLen ); + else + mrLineProperties.getEndArrowLength() = boost::optional< sal_Int32 >( nLen ); + } + } + break; + } + if ( !xRet.is() ) + xRet.set( this ); + return xRet; +} + +} } diff --git a/oox/source/drawingml/makefile.mk b/oox/source/drawingml/makefile.mk new file mode 100644 index 000000000000..4df20df79252 --- /dev/null +++ b/oox/source/drawingml/makefile.mk @@ -0,0 +1,96 @@ +#************************************************************************* +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.2 $ +# +# last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ +# +# The Contents of this file are made available subject to +# the terms of GNU Lesser General Public License Version 2.1. +# +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2005 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=oox +TARGET=drawingml +AUTOSEG=true + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/shapecontext.obj\ + $(SLO)$/shapegroupcontext.obj\ + $(SLO)$/fillproperties.obj\ + $(SLO)$/fillpropertiesgroupcontext.obj\ + $(SLO)$/lineproperties.obj\ + $(SLO)$/linepropertiescontext.obj\ + $(SLO)$/drawingmltypes.obj\ + $(SLO)$/customshapegeometry.obj\ + $(SLO)$/connectorshapecontext.obj\ + $(SLO)$/graphicshapecontext.obj\ + $(SLO)$/textbodycontext.obj\ + $(SLO)$/textbodypropertiescontext.obj\ + $(SLO)$/themefragmenthandler.obj\ + $(SLO)$/objectdefaultcontext.obj\ + $(SLO)$/themeelementscontext.obj\ + $(SLO)$/spdefcontext.obj\ + $(SLO)$/colorchoicecontext.obj\ + $(SLO)$/clrschemecontext.obj\ + $(SLO)$/clrscheme.obj\ + $(SLO)$/color.obj\ + $(SLO)$/shape.obj\ + $(SLO)$/shapestylecontext.obj\ + $(SLO)$/shapepropertiescontext.obj\ + $(SLO)$/textparagraphproperties.obj\ + $(SLO)$/textparagraphpropertiescontext.obj\ + $(SLO)$/textcharacterproperties.obj\ + $(SLO)$/textcharacterpropertiescontext.obj\ + $(SLO)$/theme.obj\ + $(SLO)$/textliststylecontext.obj\ + $(SLO)$/textrun.obj\ + $(SLO)$/textbody.obj\ + $(SLO)$/textparagraph.obj\ + $(SLO)$/textfontcontext.obj\ + $(SLO)$/textspacingcontext.obj\ + $(SLO)$/texttabstoplistcontext.obj\ + $(SLO)$/textliststyle.obj \ + $(SLO)$/textfieldcontext.obj\ + $(SLO)$/textfield.obj\ + $(SLO)$/hyperlinkcontext.obj\ + $(SLO)$/embeddedwavaudiofile.obj\ + $(SLO)$/customshapeproperties.obj + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk diff --git a/oox/source/drawingml/objectdefaultcontext.cxx b/oox/source/drawingml/objectdefaultcontext.cxx new file mode 100644 index 000000000000..4e76cf1fb633 --- /dev/null +++ b/oox/source/drawingml/objectdefaultcontext.cxx @@ -0,0 +1,81 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: objectdefaultcontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/objectdefaultcontext.hxx" +#include "oox/drawingml/spdefcontext.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +objectDefaultContext::objectDefaultContext( const ::oox::core::FragmentHandlerRef& xHandler, Theme& rTheme ) +: Context( xHandler ) +, mrTheme( rTheme ) +{ +} + +Reference< XFastContextHandler > objectDefaultContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& /* xAttribs */ ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_spDef: + { + xRet.set( new spDefContext( getHandler(), *(mrTheme.getspDef().get()) ) ); + break; + } + case NMSP_DRAWINGML|XML_lnDef: + { + xRet.set( new spDefContext( getHandler(), *(mrTheme.getlnDef().get()) ) ); + break; + } + case NMSP_DRAWINGML|XML_txDef: + { + xRet.set( new spDefContext( getHandler(), *(mrTheme.gettxDef().get()) ) ); + break; + } + } + if( !xRet.is() ) + xRet.set( this ); + + return xRet; +} + +} } diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx new file mode 100644 index 000000000000..dabd5a359e7e --- /dev/null +++ b/oox/source/drawingml/shape.cxx @@ -0,0 +1,489 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: shape.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/shape.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +#include // for the F_PI180 define +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::drawing; + +namespace oox { namespace drawingml { + +Shape::Shape( const sal_Char* pServiceName ) +: mpLinePropertiesPtr( new LineProperties() ) +, mpFillPropertiesPtr( new FillProperties( XML_spPr ) ) +, mpGraphicPropertiesPtr( new FillProperties( XML_pic ) ) +, mpCustomShapePropertiesPtr( new CustomShapeProperties() ) +, mpMasterTextListStyle( new TextListStyle() ) +, mnSubType( 0 ) +, mnIndex( 0 ) +, mnRotation( 0 ) +, mbFlipH( false ) +, mbFlipV( false ) +{ + if ( pServiceName ) + msServiceName = OUString::createFromAscii( pServiceName ); + setDefaults(); +} +Shape::~Shape() +{ +} + +void Shape::setDefaults() +{ + const OUString sTextAutoGrowHeight( RTL_CONSTASCII_USTRINGPARAM( "TextAutoGrowHeight" ) ); + const OUString sTextWordWrap( RTL_CONSTASCII_USTRINGPARAM( "TextWordWrap" ) ); + const OUString sTextLeftDistance( RTL_CONSTASCII_USTRINGPARAM( "TextLeftDistance" ) ); + const OUString sTextUpperDistance( RTL_CONSTASCII_USTRINGPARAM( "TextUpperDistance" ) ); + const OUString sTextRightDistance( RTL_CONSTASCII_USTRINGPARAM( "TextRightDistance" ) ); + const OUString sTextLowerDistance( RTL_CONSTASCII_USTRINGPARAM( "TextLowerDistance" ) ); + maShapeProperties[ sTextAutoGrowHeight ] <<= sal_False; + maShapeProperties[ sTextWordWrap ] <<= sal_True; + maShapeProperties[ sTextLeftDistance ] <<= static_cast< sal_Int32 >( 250 ); + maShapeProperties[ sTextUpperDistance ] <<= static_cast< sal_Int32 >( 125 ); + maShapeProperties[ sTextRightDistance ] <<= static_cast< sal_Int32 >( 250 ); + maShapeProperties[ sTextLowerDistance ] <<= static_cast< sal_Int32 >( 125 ); +} + +void Shape::setServiceName( const sal_Char* pServiceName ) +{ + if ( pServiceName ) + msServiceName = OUString::createFromAscii( pServiceName ); +} + + +void Shape::addShape( const oox::core::XmlFilterBase& rFilterBase, const Reference< XModel > &rxModel, const oox::drawingml::ThemePtr pThemePtr, + std::map< ::rtl::OUString, ShapePtr > & aShapeMap, const Reference< XShapes >& rxShapes, const awt::Rectangle* pShapeRect ) +{ + try + { + rtl::OUString sServiceName( msServiceName ); + if( sServiceName.getLength() ) + { + Reference< XShape > xShape( createAndInsert( rFilterBase, sServiceName, rxModel, pThemePtr, rxShapes, pShapeRect ) ); + + if( msId.getLength() ) + { + aShapeMap[ msId ] = shared_from_this(); + } + + // if this is a group shape, we have to add also each child shape + Reference< XShapes > xShapes( xShape, UNO_QUERY ); + if ( xShapes.is() ) + addChilds( rFilterBase, *this, rxModel, pThemePtr, aShapeMap, xShapes, pShapeRect ? *pShapeRect : awt::Rectangle( maPosition.X, maPosition.Y, maSize.Width, maSize.Height ) ); + } + } + catch( const Exception& ) + { + } +} + +void Shape::applyShapeReference( const oox::drawingml::Shape& rReferencedShape ) +{ + mpTextBody = TextBodyPtr( new TextBody( *rReferencedShape.mpTextBody.get() ) ); + maShapeProperties = rReferencedShape.maShapeProperties; + mpLinePropertiesPtr = LinePropertiesPtr( new LineProperties( *rReferencedShape.mpLinePropertiesPtr.get() ) ); + mpFillPropertiesPtr = FillPropertiesPtr( new FillProperties( *rReferencedShape.mpFillPropertiesPtr.get() ) ); + mpCustomShapePropertiesPtr = CustomShapePropertiesPtr( new CustomShapeProperties( *rReferencedShape.mpCustomShapePropertiesPtr.get() ) ); + mpMasterTextListStyle = TextListStylePtr( new TextListStyle( *rReferencedShape.mpMasterTextListStyle.get() ) ); + maShapeStylesColorMap = rReferencedShape.maShapeStylesColorMap; + maShapeStylesIndexMap = rReferencedShape.maShapeStylesIndexMap; + maSize = rReferencedShape.maSize; + maPosition = rReferencedShape.maPosition; + mnRotation = rReferencedShape.mnRotation; + mbFlipH = rReferencedShape.mbFlipH; + mbFlipV = rReferencedShape.mbFlipV; +} + +// for group shapes, the following method is also adding each child +void Shape::addChilds( const oox::core::XmlFilterBase& rFilterBase, Shape& rMaster, const Reference< XModel > &rxModel, const oox::drawingml::ThemePtr pThemePtr, + std::map< ::rtl::OUString, ShapePtr > & aShapeMap, const Reference< XShapes >& rxShapes, const awt::Rectangle& rClientRect ) +{ + // first the global child union needs to be calculated + sal_Int32 nGlobalLeft = SAL_MAX_INT32; + sal_Int32 nGlobalRight = SAL_MIN_INT32; + sal_Int32 nGlobalTop = SAL_MAX_INT32; + sal_Int32 nGlobalBottom= SAL_MIN_INT32; + std::vector< ShapePtr >::iterator aIter( rMaster.maChilds.begin() ); + while( aIter != rMaster.maChilds.end() ) + { + sal_Int32 l = (*aIter)->maPosition.X; + sal_Int32 t = (*aIter)->maPosition.Y; + sal_Int32 r = l + (*aIter)->maSize.Width; + sal_Int32 b = t + (*aIter)->maSize.Height; + if ( nGlobalLeft > l ) + nGlobalLeft = l; + if ( nGlobalRight < r ) + nGlobalRight = r; + if ( nGlobalTop > t ) + nGlobalTop = t; + if ( nGlobalBottom < b ) + nGlobalBottom = b; + aIter++; + } + aIter = rMaster.maChilds.begin(); + while( aIter != rMaster.maChilds.end() ) + { + Rectangle aShapeRect; + Rectangle* pShapeRect = 0; + if ( ( nGlobalLeft != SAL_MAX_INT32 ) && ( nGlobalRight != SAL_MIN_INT32 ) && ( nGlobalTop != SAL_MAX_INT32 ) && ( nGlobalBottom != SAL_MIN_INT32 ) ) + { + sal_Int32 nGlobalWidth = nGlobalRight - nGlobalLeft; + sal_Int32 nGlobalHeight = nGlobalBottom - nGlobalTop; + if ( nGlobalWidth && nGlobalHeight ) + { + double fWidth = (*aIter)->maSize.Width; + double fHeight= (*aIter)->maSize.Height; + double fXScale = (double)rClientRect.Width / (double)nGlobalWidth; + double fYScale = (double)rClientRect.Height / (double)nGlobalHeight; + aShapeRect.X = static_cast< sal_Int32 >( ( ( (*aIter)->maPosition.X - nGlobalLeft ) * fXScale ) + rClientRect.X ); + aShapeRect.Y = static_cast< sal_Int32 >( ( ( (*aIter)->maPosition.Y - nGlobalTop ) * fYScale ) + rClientRect.Y ); + fWidth *= fXScale; + fHeight *= fYScale; + aShapeRect.Width = static_cast< sal_Int32 >( fWidth ); + aShapeRect.Height = static_cast< sal_Int32 >( fHeight ); + pShapeRect = &aShapeRect; + } + } + (*aIter++)->addShape( rFilterBase, rxModel, pThemePtr, aShapeMap, rxShapes, pShapeRect ); + } +} + +void applyPropertyMap( uno::Reference< drawing::XShape >& rxShape, PropertyMap& rPropertyMap ) +{ + if( !rPropertyMap.empty() ) + { + Reference< XMultiPropertySet > xMSet( rxShape, UNO_QUERY ); + if( xMSet.is() ) + { + try + { + Sequence< OUString > aNames; + Sequence< Any > aValues; + rPropertyMap.makeSequence( aNames, aValues ); + xMSet->setPropertyValues( aNames, aValues); + } + catch( Exception& ) + { + } + } + else + { + uno::Reference< beans::XPropertySet > xSet( rxShape, uno::UNO_QUERY_THROW ); + uno::Reference< beans::XPropertySetInfo > xInfo( xSet->getPropertySetInfo() ); + + for( PropertyMap::const_iterator aIter( rPropertyMap.begin() ); aIter != rPropertyMap.end(); aIter++ ) + { + if ( xInfo->hasPropertyByName( (*aIter).first ) ) + xSet->setPropertyValue( (*aIter).first, (*aIter).second ); + } + } + } +} + + + +Reference< XShape > Shape::createAndInsert( const oox::core::XmlFilterBase& rFilterBase, const rtl::OUString& rServiceName, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > &rxModel, + const oox::drawingml::ThemePtr pThemePtr, const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes, + const awt::Rectangle* pShapeRect ) +{ + basegfx::B2DHomMatrix aTransformation; + + awt::Size aSize( pShapeRect ? awt::Size( pShapeRect->Width, pShapeRect->Height ) : maSize ); + awt::Point aPosition( pShapeRect ? awt::Point( pShapeRect->X, pShapeRect->Y ) : maPosition ); + if( aSize.Width != 1 || aSize.Height != 1) + { + // take care there are no zeros used by error + aTransformation.scale( + aSize.Width ? aSize.Width / 360.0 : 1.0, + aSize.Height ? aSize.Height / 360.0 : 1.0 ); + } + + if( mbFlipH || mbFlipV || mnRotation != 0) + { + // calculate object's center + basegfx::B2DPoint aCenter(0.5, 0.5); + aCenter *= aTransformation; + + // center object at origin + aTransformation.translate( -aCenter.getX(), -aCenter.getY() ); + + if( mbFlipH || mbFlipV) + { + // mirror around object's center + aTransformation.scale( mbFlipH ? -1.0 : 1.0, mbFlipV ? -1.0 : 1.0 ); + } + + if( mnRotation != 0 ) + { + // rotate around object's center + aTransformation.rotate( -F_PI180 * ( (double)mnRotation / 60000.0 ) ); + } + + // move object back from center + aTransformation.translate( aCenter.getX(), aCenter.getY() ); + } + + if( aPosition.X != 0 || aPosition.Y != 0) + { + // if global position is used, add it to transformation + aTransformation.translate( aPosition.X / 360.0, aPosition.Y / 360.0 ); + } + + // special for lineshape + if ( rServiceName == OUString::createFromAscii( "com.sun.star.drawing.LineShape" ) ) + { + ::basegfx::B2DPolygon aPoly; + aPoly.insert( 0, ::basegfx::B2DPoint( 0, 0 ) ); + aPoly.insert( 1, ::basegfx::B2DPoint( maSize.Width ? 1 : 0, maSize.Height ? 1 : 0 ) ); + aPoly.transform( aTransformation ); + + // now creating the corresponding PolyPolygon + sal_Int32 i, nNumPoints = aPoly.count(); + uno::Sequence< awt::Point > aPointSequence( nNumPoints ); + awt::Point* pPoints = aPointSequence.getArray(); + for( i = 0; i < nNumPoints; ++i ) + { + const ::basegfx::B2DPoint aPoint( aPoly.getB2DPoint( i ) ); + pPoints[ i ] = awt::Point( static_cast< sal_Int32 >( aPoint.getX() ), static_cast< sal_Int32 >( aPoint.getY() ) ); + } + uno::Sequence< uno::Sequence< awt::Point > > aPolyPolySequence( 1 ); + aPolyPolySequence.getArray()[ 0 ] = aPointSequence; + + static const OUString sPolyPolygon(RTL_CONSTASCII_USTRINGPARAM("PolyPolygon")); + maShapeProperties[ sPolyPolygon ] <<= aPolyPolySequence; + } + else if ( rServiceName == OUString::createFromAscii( "com.sun.star.drawing.ConnectorShape" ) ) + { + ::basegfx::B2DPolygon aPoly; + aPoly.insert( 0, ::basegfx::B2DPoint( 0, 0 ) ); + aPoly.insert( 1, ::basegfx::B2DPoint( maSize.Width ? 1 : 0, maSize.Height ? 1 : 0 ) ); + aPoly.transform( aTransformation ); + + basegfx::B2DPoint aStartPosition( aPoly.getB2DPoint( 0 ) ); + basegfx::B2DPoint aEndPosition( aPoly.getB2DPoint( 1 ) ); + awt::Point aAWTStartPosition( static_cast< sal_Int32 >( aStartPosition.getX() ), static_cast< sal_Int32 >( aStartPosition.getY() ) ); + awt::Point aAWTEndPosition( static_cast< sal_Int32 >( aEndPosition.getX() ), static_cast< sal_Int32 >( aEndPosition.getY() ) ); + + static const OUString sStartPosition(RTL_CONSTASCII_USTRINGPARAM("StartPosition")); + maShapeProperties[ sStartPosition ] <<= aAWTStartPosition; + static const OUString sEndPosition(RTL_CONSTASCII_USTRINGPARAM("EndPosition")); + maShapeProperties[ sEndPosition ] <<= aAWTEndPosition; + } + else + { + // now set transformation for this object + HomogenMatrix3 aMatrix; + + aMatrix.Line1.Column1 = aTransformation.get(0,0); + aMatrix.Line1.Column2 = aTransformation.get(0,1); + aMatrix.Line1.Column3 = aTransformation.get(0,2); + + aMatrix.Line2.Column1 = aTransformation.get(1,0); + aMatrix.Line2.Column2 = aTransformation.get(1,1); + aMatrix.Line2.Column3 = aTransformation.get(1,2); + + aMatrix.Line3.Column1 = aTransformation.get(2,0); + aMatrix.Line3.Column2 = aTransformation.get(2,1); + aMatrix.Line3.Column3 = aTransformation.get(2,2); + + static const OUString sTransformation(RTL_CONSTASCII_USTRINGPARAM("Transformation")); + maShapeProperties[ sTransformation ] <<= aMatrix; + } + Reference< lang::XMultiServiceFactory > xServiceFact( rxModel, UNO_QUERY_THROW ); + Reference< drawing::XShape > xShape( xServiceFact->createInstance( rServiceName ), UNO_QUERY_THROW ); + Reference< XPropertySet > xSet( xShape, UNO_QUERY_THROW ); + if( xShape.is() && xSet.is() ) + { + if( msName.getLength() ) + { + Reference< container::XNamed > xNamed( xShape, UNO_QUERY ); + if( xNamed.is() ) + xNamed->setName( msName ); + } + rxShapes->add( xShape ); + mxShape = xShape; + + setShapeStyles( pThemePtr, rFilterBase ); + + // applying properties + if ( rServiceName == OUString::createFromAscii( "com.sun.star.drawing.GraphicObjectShape" ) ) + mpGraphicPropertiesPtr->pushToPropSet( rFilterBase, xSet ); + mpFillPropertiesPtr->pushToPropSet( rFilterBase, xSet ); + mpLinePropertiesPtr->pushToPropSet( rFilterBase, xSet ); + + // applying autogrowheight property before setting shape size, because + // the shape size might be changed if currently autogrowheight is true + // we must also check that the PropertySet supports the property. + Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() ); + static const rtl::OUString sTextAutoGrowHeight( RTL_CONSTASCII_USTRINGPARAM( "TextAutoGrowHeight" ) ); + if( xSetInfo->hasPropertyByName( sTextAutoGrowHeight ) ) + { + const Any* pAutoGrowHeight = maShapeProperties.getPropertyValue( sTextAutoGrowHeight ); + if ( pAutoGrowHeight ) + xSet->setPropertyValue( sTextAutoGrowHeight, Any( sal_False ) ); + } + + applyPropertyMap( xShape, maShapeProperties ); + + if( rServiceName == OUString::createFromAscii( "com.sun.star.drawing.CustomShape" ) ) + mpCustomShapePropertiesPtr->pushToPropSet( rFilterBase, xSet ); + + // in some cases, we don't have any text body. + if( getTextBody() ) + { + Reference < XText > xText( xShape, UNO_QUERY ); + if ( xText.is() ) // not every shape is supporting an XText interface (e.g. GroupShape) + { + Reference < XTextCursor > xAt = xText->createTextCursor(); + getTextBody()->insertAt( rFilterBase, xText, xAt, rxModel, mpMasterTextListStyle ); + } + } + } + return xShape; +} + +// the properties of rSource which are not part of rDest are being put into rDest +void addMissingProperties( const PropertyMap& rSource, PropertyMap& rDest ) +{ + PropertyMap::const_iterator aSourceIter( rSource.begin() ); + while( aSourceIter != rSource.end() ) + { + if ( rDest.find( (*aSourceIter ).first ) == rDest.end() ) + rDest[ (*aSourceIter).first ] <<= (*aSourceIter).second; + aSourceIter++; + } +} + +// merging styles, if a shape property is not set, we have to set the shape style property +void Shape::setShapeStyles( const oox::drawingml::ThemePtr pThemePtr, const oox::core::XmlFilterBase& rFilterBase ) +{ + std::map< ShapeStyle, ColorPtr >::const_iterator aShapeStylesColorIter( getShapeStylesColor().begin() ); + std::map< ShapeStyle, rtl::OUString >::const_iterator aShapeStylesIndexIter( getShapeStylesIndex().begin() ); + while( aShapeStylesColorIter != getShapeStylesColor().end() ) + { + switch( (*aShapeStylesColorIter).first ) + { + case oox::drawingml::SHAPESTYLE_ln : + { + if ( !mpLinePropertiesPtr->getLineColor()->isUsed() ) + mpLinePropertiesPtr->getLineColor() = (*aShapeStylesColorIter).second; + } + break; + case oox::drawingml::SHAPESTYLE_fill : + { + if ( !mpFillPropertiesPtr->getFillColor()->isUsed() ) + mpFillPropertiesPtr->getFillColor() = (*aShapeStylesColorIter).second; + } + case oox::drawingml::SHAPESTYLE_effect : + break; + case oox::drawingml::SHAPESTYLE_font : + { + const rtl::OUString sCharColor( OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "CharColor" ) ) ); + if ( maShapeProperties.find( sCharColor ) == maShapeProperties.end() ) + maShapeProperties[ sCharColor ] <<= ((*aShapeStylesColorIter).second)->getColor( rFilterBase ); + } + break; + } + aShapeStylesColorIter++; + } + while( aShapeStylesIndexIter != getShapeStylesIndex().end() ) + { + const rtl::OUString sIndex( (*aShapeStylesIndexIter).second ); + sal_uInt32 nIndex( sIndex.toInt32() ); + if ( nIndex-- ) + { + switch( (*aShapeStylesIndexIter).first ) + { + case oox::drawingml::SHAPESTYLE_ln : + { + const std::vector< oox::drawingml::LinePropertiesPtr >& rThemeLineStyleList( pThemePtr->getLineStyleList() ); + if ( rThemeLineStyleList.size() > nIndex ) + mpLinePropertiesPtr->apply( rThemeLineStyleList[ nIndex ] ); + } + break; + case oox::drawingml::SHAPESTYLE_fill : + { + const std::vector< oox::drawingml::FillPropertiesPtr >& rThemeFillStyleList( pThemePtr->getFillStyleList() ); + if ( rThemeFillStyleList.size() > nIndex ) + mpFillPropertiesPtr->apply( rThemeFillStyleList[ nIndex ] ); + } + break; + case oox::drawingml::SHAPESTYLE_effect : + case oox::drawingml::SHAPESTYLE_font : + break; + } + } + aShapeStylesIndexIter++; + } +} + +void Shape::setTextBody(const TextBodyPtr & pTextBody) +{ + mpTextBody = pTextBody; +} + + +TextBodyPtr Shape::getTextBody() +{ + return mpTextBody; +} + +void Shape::setMasterTextListStyle( const TextListStylePtr& pMasterTextListStyle ) +{ + mpMasterTextListStyle = pMasterTextListStyle; +} + + +} } diff --git a/oox/source/drawingml/shapecontext.cxx b/oox/source/drawingml/shapecontext.cxx new file mode 100644 index 000000000000..5ac0ffc255bf --- /dev/null +++ b/oox/source/drawingml/shapecontext.cxx @@ -0,0 +1,130 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: shapecontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include +#include +#include +#include +#include + +#include "oox/drawingml/shapecontext.hxx" +#include "oox/drawingml/shapestylecontext.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/drawingml/fillpropertiesgroupcontext.hxx" +#include "oox/drawingml/lineproperties.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/drawingml/customshapegeometry.hxx" +#include "oox/drawingml/textbodycontext.hxx" +#include "tokens.hxx" + +using rtl::OUString; +using namespace oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +// CT_Shape +ShapeContext::ShapeContext( const FragmentHandlerRef& xHandler, ShapePtr pMasterShapePtr, ShapePtr pShapePtr ) +: Context( xHandler ) +, mpMasterShapePtr( pMasterShapePtr ) +, mpShapePtr( pShapePtr ) +{ +} + +ShapeContext::~ShapeContext() +{ + if ( mpMasterShapePtr.get() && mpShapePtr.get() ) + mpMasterShapePtr->addChild( mpShapePtr ); +} + +ShapePtr ShapeContext::getShape() +{ + return mpShapePtr; +} + +void ShapeContext::endFastElement( sal_Int32 /* aElementToken */ ) throw( SAXException, RuntimeException ) +{ +} + +Reference< XFastContextHandler > ShapeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElementToken &(~NMSP_MASK) ) + { + // nvSpPr CT_ShapeNonVisual begin +// case XML_drElemPr: +// break; + case XML_cNvPr: + mpShapePtr->setId( xAttribs->getOptionalValue( XML_id ) ); + mpShapePtr->setName( xAttribs->getOptionalValue( XML_name ) ); + break; + case XML_ph: + mpShapePtr->setSubType( xAttribs->getOptionalValueToken( XML_type, XML_obj ) ); + mpShapePtr->setIndex( xAttribs->getOptionalValue( XML_idx ).toInt32() ); + break; + // nvSpPr CT_ShapeNonVisual end + + case XML_spPr: + xRet = new ShapePropertiesContext( this, *(mpShapePtr.get()) ); + break; + + case XML_style: + xRet = new ShapeStyleContext( this, *(mpShapePtr.get()) ); + break; + + case XML_txBody: + { + xRet = new TextBodyContext( getHandler(), *(mpShapePtr.get()) ); + break; + } + } + + if( !xRet.is() ) + { + uno::Reference xTmp(this); + xRet.set( xTmp ); + } + + return xRet; +} + + +} } diff --git a/oox/source/drawingml/shapegroupcontext.cxx b/oox/source/drawingml/shapegroupcontext.cxx new file mode 100644 index 000000000000..7e6c7dd0c6ee --- /dev/null +++ b/oox/source/drawingml/shapegroupcontext.cxx @@ -0,0 +1,125 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: shapegroupcontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include +#include +#include + +#include "oox/drawingml/shapegroupcontext.hxx" +#include "oox/drawingml/connectorshapecontext.hxx" +#include "oox/drawingml/graphicshapecontext.hxx" +#include "oox/drawingml/lineproperties.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/drawingml/customshapegeometry.hxx" +#include "oox/drawingml/textbodycontext.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using rtl::OUString; +using namespace oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +ShapeGroupContext::ShapeGroupContext( const FragmentHandlerRef& xHandler, + sal_Int32 /* aElementToken */, ShapePtr pMasterShapePtr, ShapePtr pGroupShapePtr ) +: Context( xHandler ) +, mpGroupShapePtr( pGroupShapePtr ) +, mpMasterShapePtr( pMasterShapePtr ) +{ +} + +ShapeGroupContext::~ShapeGroupContext() +{ + if ( mpMasterShapePtr.get() && mpGroupShapePtr.get() ) + mpMasterShapePtr->addChild( mpGroupShapePtr ); +} + +Reference< XFastContextHandler > ShapeGroupContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElementToken &(~NMSP_MASK) ) + { + case XML_cNvPr: + mpGroupShapePtr->setId( xAttribs->getOptionalValue( XML_id ) ); + mpGroupShapePtr->setName( xAttribs->getOptionalValue( XML_name ) ); + break; + case XML_ph: + mpGroupShapePtr->setSubType( xAttribs->getOptionalValueToken( XML_type, FastToken::DONTKNOW ) ); + mpGroupShapePtr->setIndex( xAttribs->getOptionalValue( XML_idx ).toInt32() ); + break; + // nvSpPr CT_ShapeNonVisual end + + case XML_grpSpPr: + xRet = new ShapePropertiesContext( this, *(mpGroupShapePtr.get()) ); + break; + case XML_spPr: + xRet = new ShapePropertiesContext( this, *(mpGroupShapePtr.get()) ); + break; +/* + case XML_style: + xRet = new ShapeStyleContext( getParser() ); + break; +*/ + case XML_cxnSp: // connector shape + xRet.set( new ConnectorShapeContext( getHandler(), aElementToken, mpGroupShapePtr, ShapePtr( new Shape( "com.sun.star.drawing.ConnectorShape" ) ) ) ); + break; + case XML_grpSp: // group shape + xRet.set( new ShapeGroupContext( getHandler(), aElementToken, mpGroupShapePtr, ShapePtr( new Shape( "com.sun.star.drawing.GroupShape" ) ) ) ); + break; + case XML_sp: // shape + xRet.set( new ShapeContext( getHandler(), mpGroupShapePtr, ShapePtr( new Shape( "com.sun.star.drawing.CustomShape" ) ) ) ); + break; + case XML_pic: // CT_Picture + xRet.set( new GraphicShapeContext( getHandler(), mpGroupShapePtr, ShapePtr( new Shape( "com.sun.star.drawing.GraphicObjectShape" ) ) ) ); + break; + case XML_graphicFrame: // CT_GraphicalObjectFrame + xRet.set( new GraphicalObjectFrameContext( getHandler(), mpGroupShapePtr, ShapePtr( new Shape( "com.sun.star.drawing.OLE2Shape" ) ) ) ); + break; + } + if( !xRet.is() ) + xRet.set( this ); + + + return xRet; +} + +} } diff --git a/oox/source/drawingml/shapepropertiescontext.cxx b/oox/source/drawingml/shapepropertiescontext.cxx new file mode 100644 index 000000000000..a4c6ad5c98c8 --- /dev/null +++ b/oox/source/drawingml/shapepropertiescontext.cxx @@ -0,0 +1,140 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: shapepropertiescontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef _TOOLS_DEBUG_HXX +#include +#endif + +#include +#include +#include +#include +#include + +#include "oox/drawingml/shapepropertiescontext.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/drawingml/linepropertiescontext.hxx" +#include "oox/drawingml/fillpropertiesgroupcontext.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/drawingml/customshapegeometry.hxx" +#include "tokens.hxx" + +using rtl::OUString; +using namespace oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +// ==================================================================== + +// CT_ShapeProperties +ShapePropertiesContext::ShapePropertiesContext( const ContextRef& xParent, ::oox::drawingml::Shape& rShape ) +: Context( xParent->getHandler() ) +, mxParent( xParent ) +, mrShape( rShape ) +{ +} + +// -------------------------------------------------------------------- + +void ShapePropertiesContext::endFastElement( sal_Int32 aElementToken ) throw( SAXException, RuntimeException ) +{ + mxParent->endFastElement( aElementToken ); +} + +// -------------------------------------------------------------------- + +Reference< XFastContextHandler > ShapePropertiesContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + // CT_Transform2D + case NMSP_DRAWINGML|XML_xfrm: + xRet.set( new Transform2DContext( getHandler(), xAttribs, mrShape ) ); + break; + + // GeometryGroup + case NMSP_DRAWINGML|XML_custGeom: // custom geometry "CT_CustomGeometry2D" + xRet.set( new CustomShapeGeometryContext( getHandler(), xAttribs, *(mrShape.getCustomShapeProperties()) ) ); + break; + + + case NMSP_DRAWINGML|XML_prstGeom: // preset geometry "CT_PresetGeometry2D" + { + sal_Int32 nToken = xAttribs->getOptionalValueToken( XML_prst, 0 ); + if ( nToken == XML_line ) + { + static const OUString sLineShape( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.LineShape" ) ); + mrShape.getServiceName() = sLineShape; + } + xRet.set( new PresetShapeGeometryContext( getHandler(), xAttribs, *(mrShape.getCustomShapeProperties()) ) ); + } + break; + + case NMSP_DRAWINGML|XML_prstTxWarp: + xRet.set( new PresetTextShapeContext( getHandler(), xAttribs, *(mrShape.getCustomShapeProperties()) ) ); + break; + + // CT_LineProperties + case NMSP_DRAWINGML|XML_ln: + xRet.set( new LinePropertiesContext( getHandler(), xAttribs, *(mrShape.getLineProperties().get()) ) ); + break; + + // EffectPropertiesGroup + // todo not supported by core + case NMSP_DRAWINGML|XML_effectLst: // CT_EffectList + case NMSP_DRAWINGML|XML_effectDag: // CT_EffectContainer + break; + + // todo + case NMSP_DRAWINGML|XML_scene3d: // CT_Scene3D + case NMSP_DRAWINGML|XML_sp3d: // CT_Shape3D + break; + } + + // FillPropertiesGroupContext + if( !xRet.is() ) + xRet.set( FillPropertiesGroupContext::StaticCreateContext( getHandler(), aElementToken, xAttribs, *(mrShape.getFillProperties().get()) ) ); + + return xRet; +} + +} } diff --git a/oox/source/drawingml/shapestylecontext.cxx b/oox/source/drawingml/shapestylecontext.cxx new file mode 100644 index 000000000000..bf58ecde8f4a --- /dev/null +++ b/oox/source/drawingml/shapestylecontext.cxx @@ -0,0 +1,148 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: shapestylecontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/shapestylecontext.hxx" + +#include "oox/helper/attributelist.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/drawingml/colorchoicecontext.hxx" +#include "tokens.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +// ------------------------- +// CT_StyleMatrixReference +// ------------------------- +class StyleMatrixReferenceContext : public ::oox::core::Context +{ +public: + StyleMatrixReferenceContext( const ::oox::core::ContextRef& rxParent, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs, + const oox::drawingml::ShapeStyle eShapeStyle, oox::drawingml::Shape& rShape ); + ~StyleMatrixReferenceContext(); + + virtual void SAL_CALL endFastElement( ::sal_Int32 Element ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 Element, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + +protected: + ::oox::drawingml::Shape& mrShape; + ::oox::drawingml::ShapeStyle meShapeStyle; + ::oox::drawingml::ColorPtr maColor; +}; + +StyleMatrixReferenceContext::StyleMatrixReferenceContext( const ::oox::core::ContextRef& rxParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& rxAttribs, + const oox::drawingml::ShapeStyle eShapeStyle, oox::drawingml::Shape& rShape ) +: Context( rxParent->getHandler() ) +, mrShape( rShape ) +, meShapeStyle( eShapeStyle ) +, maColor( new Color() ) +{ + mrShape.getShapeStylesIndex()[ meShapeStyle ] = rxAttribs->getOptionalValue( XML_idx ); +} + +StyleMatrixReferenceContext::~StyleMatrixReferenceContext() +{ + +} + +// -------------------------------------------------------------------- + +void StyleMatrixReferenceContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) +{ + mrShape.getShapeStylesColor()[ meShapeStyle ] = maColor; +} + +// -------------------------------------------------------------------- + +Reference< XFastContextHandler > StyleMatrixReferenceContext::createFastChildContext( sal_Int32 /* aElementToken */, const Reference< XFastAttributeList >& /* rxAttributes */ ) throw (SAXException, RuntimeException) +{ + return new colorChoiceContext( getHandler(), *maColor.get() ); +} + +// --------------- +// CT_ShapeStyle +// --------------- +ShapeStyleContext::ShapeStyleContext( const ::oox::core::ContextRef& rxParent, oox::drawingml::Shape& rShape ) +: Context( rxParent->getHandler() ) +, mrShape( rShape ) +{ +} + +ShapeStyleContext::~ShapeStyleContext() +{ +} + +// -------------------------------------------------------------------- + +void ShapeStyleContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) +{ +} + +// -------------------------------------------------------------------- + +Reference< XFastContextHandler > ShapeStyleContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& rxAttributes ) + throw ( SAXException, RuntimeException ) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_lnRef : // CT_StyleMatrixReference + xRet.set( new StyleMatrixReferenceContext( this, rxAttributes, oox::drawingml::SHAPESTYLE_ln, mrShape ) ); + break; + case NMSP_DRAWINGML|XML_fillRef : // CT_StyleMatrixReference + xRet.set( new StyleMatrixReferenceContext( this, rxAttributes, oox::drawingml::SHAPESTYLE_fill, mrShape ) ); + break; + case NMSP_DRAWINGML|XML_effectRef : // CT_StyleMatrixReference + xRet.set( new StyleMatrixReferenceContext( this, rxAttributes, oox::drawingml::SHAPESTYLE_effect, mrShape ) ); + break; + case NMSP_DRAWINGML|XML_fontRef : // CT_FontReference + xRet.set( new StyleMatrixReferenceContext( this, rxAttributes, oox::drawingml::SHAPESTYLE_font, mrShape ) ); + break; + } + if ( !xRet.is() ) + xRet.set( this ); + return xRet; +} + +// -------------------------------------------------------------------- + +} } + diff --git a/oox/source/drawingml/spdefcontext.cxx b/oox/source/drawingml/spdefcontext.cxx new file mode 100644 index 000000000000..55530b3ffefb --- /dev/null +++ b/oox/source/drawingml/spdefcontext.cxx @@ -0,0 +1,83 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: spdefcontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:51 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/spdefcontext.hxx" +#include "oox/drawingml/shapepropertiescontext.hxx" +#include "oox/drawingml/textbodypropertiescontext.hxx" +#include "oox/drawingml/textliststylecontext.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +spDefContext::spDefContext( const ::oox::core::FragmentHandlerRef& xHandler, oox::drawingml::Shape& rDefaultObject ) +: Context( xHandler ) +, mrDefaultObject( rDefaultObject ) +{ +} + +Reference< XFastContextHandler > spDefContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_spPr: + { + xRet = new ShapePropertiesContext( this, mrDefaultObject ); + break; + } + case NMSP_DRAWINGML|XML_bodyPr: + { + xRet = new TextBodyPropertiesContext( this, xAttribs, mrDefaultObject ); + break; + } + case NMSP_DRAWINGML|XML_lstStyle: + xRet.set( new TextListStyleContext( getHandler(), *(mrDefaultObject.getMasterTextListStyle().get()) ) ); + break; + case NMSP_DRAWINGML|XML_style: + break; + } + if( !xRet.is() ) + xRet.set( this ); + + return xRet; +} + +} } diff --git a/oox/source/drawingml/textbody.cxx b/oox/source/drawingml/textbody.cxx new file mode 100644 index 000000000000..13afccddac2f --- /dev/null +++ b/oox/source/drawingml/textbody.cxx @@ -0,0 +1,86 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: textbody.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:52 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include +#include + +#include "oox/drawingml/textbody.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::frame; + +namespace oox { namespace drawingml { + + + TextBody::TextBody() + : mpTextListStyle( new TextListStyle() ) + { + } + + TextBody::~TextBody() + { + } + + + + void TextBody::insertAt( const ::oox::core::XmlFilterBase& rFilterBase, const Reference < XText > & xText, const Reference < XTextCursor > & xAt, + const Reference < XModel > &xModel, const TextListStylePtr& pMasterTextListStylePtr ) + { + TextListStylePtr aCombinedTextStyle( new TextListStyle( *(pMasterTextListStylePtr.get()) ) ); + aCombinedTextStyle->apply( mpTextListStyle ); + + std::vector< TextParagraphPtr >::iterator begin( maParagraphs.begin() ); + std::vector< TextParagraphPtr >::iterator end( maParagraphs.end() ); + // apparently if there is no paragraph, it crashes. this is sort of the + // expected behavior. + while( begin != end ) + { + (*begin)->insertAt( rFilterBase, xText, xAt, xModel, aCombinedTextStyle, begin == maParagraphs.begin() ); + begin++; +/* + std::for_each( begin, end, + boost::bind( &TextParagraph::insertAt, _1, + rFilterBase, xText, xAt, xModel, aCombinedTextStyle, + // determine whether it is the first paragraph of not + boost::bind( std::equal_to(), _1, + *maParagraphs.begin() ) ) ); +*/ + } + } + + +} } diff --git a/oox/source/drawingml/textbodycontext.cxx b/oox/source/drawingml/textbodycontext.cxx new file mode 100644 index 000000000000..0636ece28713 --- /dev/null +++ b/oox/source/drawingml/textbodycontext.cxx @@ -0,0 +1,224 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: textbodycontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:52 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/textbodypropertiescontext.hxx" +#include "oox/drawingml/textbodycontext.hxx" +#include "oox/drawingml/textparagraphpropertiescontext.hxx" +#include "oox/drawingml/textcharacterpropertiescontext.hxx" +#include "oox/drawingml/textliststylecontext.hxx" +#include "oox/drawingml/textfieldcontext.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +// -------------------------------------------------------------------- + +// CT_TextParagraph +class TextParagraphContext : public Context +{ +public: + TextParagraphContext( const FragmentHandlerRef& xHandler, TextParagraph& rPara ); + + virtual void SAL_CALL endFastElement( sal_Int32 aElementToken ) throw (SAXException, RuntimeException); + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException); + +protected: + TextParagraph& mrParagraph; +}; + +// -------------------------------------------------------------------- +TextParagraphContext::TextParagraphContext( const FragmentHandlerRef& xHandler, TextParagraph& rPara ) +: Context( xHandler ) +, mrParagraph( rPara ) +{ +} + +// -------------------------------------------------------------------- +void TextParagraphContext::endFastElement( sal_Int32 aElementToken ) throw (SAXException, RuntimeException) +{ + if( aElementToken == (NMSP_DRAWINGML|XML_p) ) + { + } +} + +// -------------------------------------------------------------------- + +Reference< XFastContextHandler > TextParagraphContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + // EG_TextRun + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_r: // "CT_RegularTextRun" Regular Text Run. + { + TextRunPtr pRun( new TextRun() ); + mrParagraph.addRun( pRun ); + xRet.set( new RegularTextRunContext( getHandler(), pRun ) ); + break; + } + case NMSP_DRAWINGML|XML_br: // "CT_TextLineBreak" Soft return line break (vertical tab). + { + TextRunPtr pRun( new TextRun() ); + pRun->setLineBreak(); + mrParagraph.addRun( pRun ); + xRet.set( new RegularTextRunContext( getHandler(), pRun ) ); + break; + } + case NMSP_DRAWINGML|XML_fld: // "CT_TextField" Text Field. + { + TextFieldPtr pField( new TextField() ); + mrParagraph.addRun( pField ); + xRet.set( new TextFieldContext( this, xAttribs, pField ) ); + break; + } + case NMSP_DRAWINGML|XML_pPr: + xRet.set( new TextParagraphPropertiesContext( this, xAttribs, *(mrParagraph.getProperties().get()) ) ); + break; + case NMSP_DRAWINGML|XML_endParaRPr: + xRet.set( new TextParagraphPropertiesContext( this, xAttribs, *(mrParagraph.getEndProperties().get()) ) ); + break; + } + + return xRet; +} +// -------------------------------------------------------------------- + +RegularTextRunContext::RegularTextRunContext( const FragmentHandlerRef& xHandler, oox::drawingml::TextRunPtr pRunPtr ) +: Context( xHandler ) +, mpRunPtr( pRunPtr ) +, mbIsInText( false ) +{ +} + +// -------------------------------------------------------------------- + +void RegularTextRunContext::endFastElement( sal_Int32 aElementToken ) throw (SAXException, RuntimeException) +{ + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_t: + { + mbIsInText = false; + break; + } + case NMSP_DRAWINGML|XML_r: + { + break; + } + + } +} + +// -------------------------------------------------------------------- + +void RegularTextRunContext::characters( const OUString& aChars ) throw (SAXException, RuntimeException) +{ + if( mbIsInText ) + { + mpRunPtr->text() += aChars; + } +} + +// -------------------------------------------------------------------- + +Reference< XFastContextHandler > RegularTextRunContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet( this ); + + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_rPr: // "CT_TextCharPropertyBag" The text char properties of this text run. + xRet.set( new TextCharacterPropertiesContext( this, xAttribs, *(mpRunPtr->getTextCharacterProperties().get()) ) ); + break; + case NMSP_DRAWINGML|XML_t: // "xsd:string" minOccurs="1" The actual text string. + mbIsInText = true; + break; + } + + return xRet; +} + +// -------------------------------------------------------------------- + +TextBodyContext::TextBodyContext( const ::oox::core::FragmentHandlerRef& xHandler, oox::drawingml::Shape& rShape ) +: Context( xHandler ) +, mrShape( rShape ) +, mpBodyPtr( new TextBody() ) +{ + rShape.setTextBody( mpBodyPtr ); +} + +// -------------------------------------------------------------------- + +void TextBodyContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) +{ +} + +// -------------------------------------------------------------------- + +Reference< XFastContextHandler > TextBodyContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_bodyPr: // CT_TextBodyPropertyBag + xRet.set( new TextBodyPropertiesContext( this, xAttribs, mrShape ) ); + break; + case NMSP_DRAWINGML|XML_lstStyle: // CT_TextListStyle + xRet.set( new TextListStyleContext( getHandler(), *(mpBodyPtr->getTextListStyle().get()) ) ); + break; + case NMSP_DRAWINGML|XML_p: // CT_TextParagraph + TextParagraphPtr pPara( new TextParagraph() ); + mpBodyPtr->addParagraph( pPara ); + xRet.set( new TextParagraphContext( getHandler(), *(pPara.get()) ) ); + break; + } + + return xRet; +} + +// -------------------------------------------------------------------- + +} } + diff --git a/oox/source/drawingml/textbodypropertiescontext.cxx b/oox/source/drawingml/textbodypropertiescontext.cxx new file mode 100644 index 000000000000..31b0aca30f7c --- /dev/null +++ b/oox/source/drawingml/textbodypropertiescontext.cxx @@ -0,0 +1,161 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: textbodypropertiescontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:52 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/textbodypropertiescontext.hxx" + +#include +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +// -------------------------------------------------------------------- + +// CT_TextBodyProperties +TextBodyPropertiesContext::TextBodyPropertiesContext( const ::oox::core::ContextRef& xParent, + const Reference< XFastAttributeList >& xAttributes, Shape& rShape ) +: Context( xParent->getHandler() ) +, mrShape( rShape ) +{ + AttributeList attribs(xAttributes); + + // ST_TextWrappingType + sal_Int32 nWrappingType = xAttributes->getOptionalValueToken( XML_wrap, XML_square ); + const OUString sTextWordWrap( RTL_CONSTASCII_USTRINGPARAM( "TextWordWrap" ) ); + mrShape.getShapeProperties()[ sTextWordWrap ] <<= (nWrappingType == XML_square); + + // ST_Coordinate + const OUString sTextLeftDistance( RTL_CONSTASCII_USTRINGPARAM( "TextLeftDistance" ) ); + const OUString sTextUpperDistance( RTL_CONSTASCII_USTRINGPARAM( "TextUpperDistance" ) ); + const OUString sTextRightDistance( RTL_CONSTASCII_USTRINGPARAM( "TextRightDistance" ) ); + const OUString sTextLowerDistance( RTL_CONSTASCII_USTRINGPARAM( "TextLowerDistance" ) ); + OUString sValue; + sValue = xAttributes->getOptionalValue( XML_lIns ); + sal_Int32 nLeftInset = ( sValue.getLength() != 0 ? GetCoordinate( sValue ) : 91440 / 360 ); + mrShape.getShapeProperties()[ sTextLeftDistance ] <<= static_cast< sal_Int32 >( nLeftInset ); + + sValue = xAttributes->getOptionalValue( XML_tIns ); + sal_Int32 nTopInset = ( sValue.getLength() != 0 ? GetCoordinate( sValue ) : 91440 / 360 ); + mrShape.getShapeProperties()[ sTextUpperDistance ] <<= static_cast< sal_Int32 >( nTopInset ); + + sValue = xAttributes->getOptionalValue( XML_rIns ); + sal_Int32 nRightInset = ( sValue.getLength() != 0 ? GetCoordinate( sValue ) : 91440 / 360 ); + mrShape.getShapeProperties()[ sTextRightDistance ] <<= static_cast< sal_Int32 >( nRightInset ); + + sValue = xAttributes->getOptionalValue( XML_bIns ); + sal_Int32 nBottonInset = ( sValue.getLength() != 0 ? GetCoordinate( sValue ) : 45720 / 360 );; + mrShape.getShapeProperties()[ sTextLowerDistance ] <<= static_cast< sal_Int32 >( nBottonInset ); + + + // ST_TextAnchoringType +// sal_Int32 nAnchoringType = xAttributes->getOptionalValueToken( XML_anchor, XML_t ); + +// bool bAnchorCenter = attribs.getBool( XML_anchorCtr, false ); + +// bool bCompatLineSpacing = attribs.getBool( XML_compatLnSpc, false ); +// bool bForceAA = attribs.getBool( XML_forceAA, false ); +// bool bFromWordArt = attribs.getBool( XML_fromWordArt, false ); + + // ST_TextHorzOverflowType +// sal_Int32 nHorzOverflow = xAttributes->getOptionalValueToken( XML_horzOverflow, XML_overflow ); + // ST_TextVertOverflowType +// sal_Int32 nVertOverflow = xAttributes->getOptionalValueToken( XML_vertOverflow, XML_overflow ); + + // ST_TextColumnCount +// sal_Int32 nNumCol = attribs.getInteger( XML_numCol, 1 ); + + // ST_Angle +// sal_Int32 nRot = attribs.getInteger( XML_rot, 0 ); +// bool bRtlCol = attribs.getBool( XML_rtlCol, false ); + // ST_PositiveCoordinate +// sal_Int32 nSpcCol = attribs.getInteger( XML_spcCol, 0 ); +// bool bSpcFirstLastPara = attribs.getBool( XML_spcFirstLastPara, 0 ); +// bool bUpRight = attribs.getBool( XML_upright, 0 ); + // ST_TextVerticalType +// sal_Int32 nVert = xAttributes->getOptionalValueToken( XML_vert, XML_horz ); +} + +// -------------------------------------------------------------------- + +void TextBodyPropertiesContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) +{ +} + +// -------------------------------------------------------------------- + +Reference< XFastContextHandler > TextBodyPropertiesContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& /*xAttributes*/) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + const OUString sTextAutoGrowHeight( RTL_CONSTASCII_USTRINGPARAM( "TextAutoGrowHeight" ) ); + switch( aElementToken ) + { + // Sequence + case NMSP_DRAWINGML|XML_prstTxWarp: // CT_PresetTextShape + case NMSP_DRAWINGML|XML_prot: // CT_TextProtectionProperty + break; + + // EG_TextAutofit + case NMSP_DRAWINGML|XML_noAutofit: + mrShape.getShapeProperties()[ sTextAutoGrowHeight ] <<= sal_False; // CT_TextNoAutofit + break; + case NMSP_DRAWINGML|XML_normAutofit: // CT_TextNormalAutofit + case NMSP_DRAWINGML|XML_spAutoFit: + mrShape.getShapeProperties()[ sTextAutoGrowHeight ] <<= sal_True; + break; + + case NMSP_DRAWINGML|XML_scene3d: // CT_Scene3D + + // EG_Text3D + case NMSP_DRAWINGML|XML_sp3d: // CT_Shape3D + case NMSP_DRAWINGML|XML_flatTx: // CT_FlatText + + break; + } + + return xRet; +} + +// -------------------------------------------------------------------- + +} } + diff --git a/oox/source/drawingml/textcharacterproperties.cxx b/oox/source/drawingml/textcharacterproperties.cxx new file mode 100644 index 000000000000..999f1e6dccb4 --- /dev/null +++ b/oox/source/drawingml/textcharacterproperties.cxx @@ -0,0 +1,135 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: textcharacterproperties.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:52 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/textcharacterproperties.hxx" + +#include "oox/helper/propertyset.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; + +namespace oox { namespace drawingml { + +TextCharacterProperties::TextCharacterProperties() +: maCharColorPtr( new Color() ) +, maUnderlineColorPtr( new Color() ) +, maHighlightColorPtr( new Color() ) +{ +} +TextCharacterProperties::~TextCharacterProperties() +{ +} +void TextCharacterProperties::apply( const TextCharacterPropertiesPtr& rSourceTextCharacterPropertiesPtr ) +{ + maTextCharacterPropertyMap.insert( rSourceTextCharacterPropertiesPtr->maTextCharacterPropertyMap.begin(), rSourceTextCharacterPropertiesPtr->maTextCharacterPropertyMap.end() ); + maHyperlinkPropertyMap.insert( rSourceTextCharacterPropertiesPtr->maHyperlinkPropertyMap.begin(), rSourceTextCharacterPropertiesPtr->maHyperlinkPropertyMap.end() ); + ColorPtr rSourceCharColor( rSourceTextCharacterPropertiesPtr->getCharColor() ); + if ( rSourceCharColor->isUsed() ) + maCharColorPtr = rSourceCharColor; + ColorPtr rSourceHighlightColor( rSourceTextCharacterPropertiesPtr->getHighlightColor() ); + if ( rSourceHighlightColor->isUsed() ) + maHighlightColorPtr = rSourceHighlightColor; + ColorPtr rSourceUnderlineColor( rSourceTextCharacterPropertiesPtr->getUnderlineColor() ); + if ( rSourceUnderlineColor->isUsed() ) + maUnderlineColorPtr = rSourceUnderlineColor; + Any& rHasUnderline = rSourceTextCharacterPropertiesPtr->getHasUnderline(); + if ( rHasUnderline.hasValue() ) + maHasUnderline = rHasUnderline; + Any& rUnderlineLineFollowText = rSourceTextCharacterPropertiesPtr->getUnderlineLineFollowText(); + if ( rUnderlineLineFollowText.hasValue() ) + maUnderlineLineFollowText = rUnderlineLineFollowText; + Any& rUnderlineFillFollowText = rSourceTextCharacterPropertiesPtr->getUnderlineFillFollowText(); + if ( rUnderlineFillFollowText.hasValue() ) + maUnderlineFillFollowText = rUnderlineFillFollowText; +} +void TextCharacterProperties::pushToPropSet( const ::oox::core::XmlFilterBase& rFilterBase, const Reference < XPropertySet > & xPropSet ) const +{ + PropertySet aPropSet( xPropSet ); + Sequence< OUString > aNames; + Sequence< Any > aValues; + +// maTextCharacterPropertyMap.dump_debug("TextCharacter props"); + maTextCharacterPropertyMap.makeSequence( aNames, aValues ); + aPropSet.setProperties( aNames, aValues ); + if ( maCharColorPtr->isUsed() ) + { + const rtl::OUString sCharColor( CREATE_OUSTRING( "CharColor" ) ); + aPropSet.setProperty( sCharColor, maCharColorPtr->getColor( rFilterBase ) ); + + } + + sal_Bool bHasUnderline = sal_False; + sal_Bool bUnderlineFillFollowText = sal_False; + maHasUnderline >>= bHasUnderline; + maUnderlineFillFollowText >>= bUnderlineFillFollowText; + if( bHasUnderline ) + { + if( maUnderlineColorPtr.get() && !bUnderlineFillFollowText ) + { + const rtl::OUString sCharUnderlineColor( CREATE_OUSTRING( "CharUnderlineColor" ) ); + aPropSet.setProperty( sCharUnderlineColor, maUnderlineColorPtr->getColor( rFilterBase ) ); + const rtl::OUString sCharUnderlineHasColor( CREATE_OUSTRING( "CharUnderlineHasColor" ) ); + aPropSet.setProperty( sCharUnderlineHasColor, Any( sal_True ) ); + } + } +} + +void TextCharacterProperties::pushToUrlFieldPropSet( const Reference < XPropertySet > & xPropSet ) const +{ + PropertySet aPropSet( xPropSet ); + Sequence< OUString > aNames; + Sequence< Any > aValues; + + maHyperlinkPropertyMap.makeSequence( aNames, aValues ); + aPropSet.setProperties( aNames, aValues ); +} + +float TextCharacterProperties::getCharacterSize( float fDefault ) const +{ + const rtl::OUString sCharHeight( CREATE_OUSTRING( "CharHeight" ) ); + float fCharHeight; + const Any* pAny = maTextCharacterPropertyMap.getPropertyValue( sCharHeight ); + if ( pAny && ( *pAny >>= fCharHeight ) ) + return fCharHeight; + else + return fDefault; +} + +} } diff --git a/oox/source/drawingml/textcharacterpropertiescontext.cxx b/oox/source/drawingml/textcharacterpropertiescontext.cxx new file mode 100644 index 000000000000..21ef91063726 --- /dev/null +++ b/oox/source/drawingml/textcharacterpropertiescontext.cxx @@ -0,0 +1,282 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: textcharacterpropertiescontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:52 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/textcharacterpropertiescontext.hxx" + +#include +#include +#include +#include +#include + +#include "oox/helper/attributelist.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/drawingml/colorchoicecontext.hxx" +#include "oox/drawingml/lineproperties.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/core/relations.hxx" +#include "textfontcontext.hxx" +#include "hyperlinkcontext.hxx" +#include "tokens.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::awt; + +namespace oox { namespace drawingml { + +// -------------------------------------------------------------------- + +// CT_TextCharacterProperties +TextCharacterPropertiesContext::TextCharacterPropertiesContext( const ::oox::core::ContextRef& xParent, + const Reference< XFastAttributeList >& rXAttributes, + oox::drawingml::TextCharacterProperties& rTextCharacterProperties ) +: Context( xParent->getHandler() ) +, mrTextCharacterProperties( rTextCharacterProperties ) +{ + AttributeList attribs( rXAttributes ); + PropertyMap& rPropertyMap( mrTextCharacterProperties.getTextCharacterPropertyMap() ); + + rtl::OUString aVal( rXAttributes->getOptionalValue( XML_sz ) ); + if ( aVal.getLength() ) + { + float fTextSize = GetTextSize( aVal ); + const rtl::OUString sCharHeight( CREATE_OUSTRING( "CharHeight" ) ); + const rtl::OUString sCharHeightAsian( CREATE_OUSTRING( "CharHeightAsian" ) ); + const rtl::OUString sCharHeightComplex( CREATE_OUSTRING( "CharHeightComplex" ) ); + rPropertyMap[ sCharHeight ] <<= fTextSize; + rPropertyMap[ sCharHeightAsian ] <<= fTextSize; + rPropertyMap[ sCharHeightComplex ] <<= fTextSize; + } + + bool bIsBold = attribs.getBool( XML_b, false ); + const rtl::OUString sCharWeight( CREATE_OUSTRING( "CharWeight" ) ); + const rtl::OUString sCharWeightAsian( CREATE_OUSTRING( "CharWeightAsian" ) ); + const rtl::OUString sCharWeightComplex( CREATE_OUSTRING( "CharWeightComplex" ) ); + rPropertyMap[ sCharWeight ] <<= ( bIsBold ? FontWeight::BOLD : FontWeight::NORMAL ); + rPropertyMap[ sCharWeightAsian ] <<= ( bIsBold ? FontWeight::BOLD : FontWeight::NORMAL ); + rPropertyMap[ sCharWeightComplex ] <<= ( bIsBold ? FontWeight::BOLD : FontWeight::NORMAL ); + + bool bIsItalic = attribs.getBool( XML_i, false ); + const rtl::OUString sCharFontPosture( CREATE_OUSTRING( "CharPosture" ) ); + const rtl::OUString sCharFontPostureAsian( CREATE_OUSTRING( "CharPostureAsian" ) ); + const rtl::OUString sCharFontPostureComplex( CREATE_OUSTRING( "CharPostureComplex" ) ); + rPropertyMap[ sCharFontPosture ] <<= ( bIsItalic ? FontSlant_ITALIC : FontSlant_NONE ); + rPropertyMap[ sCharFontPostureAsian ] <<= ( bIsItalic ? FontSlant_ITALIC : FontSlant_NONE ); + rPropertyMap[ sCharFontPostureComplex ] <<= ( bIsItalic ? FontSlant_ITALIC : FontSlant_NONE ); + + sal_Int32 nFontUnderline( rXAttributes->getOptionalValueToken( XML_u, 0 ) ); + if ( nFontUnderline ) + { + const rtl::OUString sCharUnderline( CREATE_OUSTRING( "CharUnderline" ) ); + rPropertyMap[ sCharUnderline ] <<= GetFontUnderline( nFontUnderline ); + mrTextCharacterProperties.getHasUnderline() <<= sal_True; + } + + const rtl::OUString sCharStrikeout( CREATE_OUSTRING( "CharStrikeout" ) ); + rPropertyMap[ sCharStrikeout ] <<= GetFontStrikeout( rXAttributes->getOptionalValueToken( XML_strike, XML_noStrike ) ); + + // ST_TextCapsType + const rtl::OUString sCharCaseMap( CREATE_OUSTRING( "CharCaseMap" ) ); + rPropertyMap[ sCharCaseMap ] <<= GetCaseMap( rXAttributes->getOptionalValueToken( XML_cap, XML_none ) ); + + + OUString sLang = rXAttributes->getOptionalValue( XML_lang ); + if( sLang.getLength( ) ) + { + const rtl::OUString sCharLocale( CREATE_OUSTRING( "CharLocale" ) ); + const rtl::OUString sCharLocaleAsian( CREATE_OUSTRING( "CharLocaleAsian" ) ); + const rtl::OUString sCharLocaleComplex( CREATE_OUSTRING( "CharLocaleComplex" ) ); + + com::sun::star::lang::Locale aLocale; + OUString aString( sLang ); + sal_Int32 nSepPos = aString.indexOf( (sal_Unicode)'-', 0 ); + if ( nSepPos != -1 ) + { + aLocale.Language = aString.copy( 0, nSepPos ); + aLocale.Country = aString.copy( nSepPos+1 ); + } + else + { + aLocale.Language = aString; + } + + rPropertyMap[ sCharLocale ] <<= aLocale; + rPropertyMap[ sCharLocaleAsian ] <<= aLocale; + rPropertyMap[ sCharLocaleComplex ] <<= aLocale; + } + + +// TODO +/* todo: we need to be able to iterate over the XFastAttributes + + // ST_TextNonNegativePoint + const rtl::OUString sCharKerning( CREATE_OUSTRING( "CharKerning" ) ); + //case NMSP_DRAWINGML|XML_kern: + + // ST_TextLanguageID + OUString sAltLang = rXAttributes->getOptionalValue( XML_altLang ); + + case NMSP_DRAWINGML|XML_kumimoji: // xsd:boolean + break; + case NMSP_DRAWINGML|XML_spc: // ST_TextPoint + case NMSP_DRAWINGML|XML_normalizeH: // xsd:boolean + case NMSP_DRAWINGML|XML_baseline: // ST_Percentage + case NMSP_DRAWINGML|XML_noProof: // xsd:boolean + case NMSP_DRAWINGML|XML_dirty: // xsd:boolean + case NMSP_DRAWINGML|XML_err: // xsd:boolean + case NMSP_DRAWINGML|XML_smtClean: // xsd:boolean + case NMSP_DRAWINGML|XML_smtId: // xsd:unsignedInt + break; +*/ + +} + +TextCharacterPropertiesContext::~TextCharacterPropertiesContext() +{ + PropertyMap& rPropertyMap( mrTextCharacterProperties.getTextCharacterPropertyMap() ); + + sal_Int16 nPitch, nFamily; + + if( maLatinFont.is() ) + { + const rtl::OUString sCharFontName( CREATE_OUSTRING( "CharFontName" ) ); + const rtl::OUString sCharFontPitch( CREATE_OUSTRING( "CharFontPitch" ) ); + const rtl::OUString sCharFontFamily( CREATE_OUSTRING( "CharFontFamily" ) ); + GetFontPitch( maLatinFont.mnPitch, nPitch, nFamily); + rPropertyMap[ sCharFontName ] <<= maLatinFont.msTypeface; + rPropertyMap[ sCharFontPitch ] <<= nPitch; + rPropertyMap[ sCharFontFamily ] <<= nFamily; + } + if( maAsianFont.is() ) + { + const rtl::OUString sCharFontNameAsian( CREATE_OUSTRING( "CharFontNameAsian" ) ); + const rtl::OUString sCharFontPitchAsian( CREATE_OUSTRING( "CharFontPitchAsian" ) ); + const rtl::OUString sCharFontFamilyAsian( CREATE_OUSTRING( "CharFontFamilyAsian" ) ); + GetFontPitch( maAsianFont.mnPitch, nPitch, nFamily); + rPropertyMap[ sCharFontNameAsian ] <<= maAsianFont.msTypeface; + rPropertyMap[ sCharFontPitchAsian ] <<= nFamily; + rPropertyMap[ sCharFontFamilyAsian ] <<= nPitch; + } + if( maComplexFont.is() ) + { + const rtl::OUString sCharFontNameComplex( CREATE_OUSTRING( "CharFontNameComplex" ) ); + const rtl::OUString sCharFontPitchComplex( CREATE_OUSTRING( "CharFontPitchComplex" ) ); + const rtl::OUString sCharFontFamilyComplex( CREATE_OUSTRING( "CharFontFamilyComplex" ) ); + GetFontPitch( maComplexFont.mnPitch, nPitch, nFamily ); + rPropertyMap[ sCharFontNameComplex ] <<= maComplexFont.msTypeface; + rPropertyMap[ sCharFontPitchComplex ] <<= nPitch; + rPropertyMap[ sCharFontFamilyComplex ] <<= nFamily; + } +} + +// -------------------------------------------------------------------- + +void TextCharacterPropertiesContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) +{ +} + +// -------------------------------------------------------------------- + +Reference< XFastContextHandler > TextCharacterPropertiesContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttributes ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + // not supported..... + case NMSP_DRAWINGML|XML_ln: // CT_LineProperties +// TODO unsupported yet +// xRet.set( new LinePropertiesContext( getHandler(), xAttributes, maTextOutlineProperties ) ); + break; + // EG_FillProperties + case NMSP_DRAWINGML|XML_solidFill: + xRet.set( new colorChoiceContext( getHandler(), *(mrTextCharacterProperties.getCharColor().get()) ) ); + break; + // EG_EffectProperties + case NMSP_DRAWINGML|XML_effectDag: + // CT_EffectContainer 5.1.10.25 + case NMSP_DRAWINGML|XML_effectLst: + // CT_EffectList 5.1.10.26 + break; + + case NMSP_DRAWINGML|XML_highlight: //CT_Color + xRet.set( new colorChoiceContext( getHandler(), *(mrTextCharacterProperties.getHighlightColor().get()) ) ); + break; + + // EG_TextUnderlineLine + case NMSP_DRAWINGML|XML_uLnTx: // CT_TextUnderlineLineFollowText + mrTextCharacterProperties.getUnderlineLineFollowText() <<= sal_True; + break; + case NMSP_DRAWINGML|XML_uLn: // CT_LineProperties +// TODO unsupported yet +// xRet.set( new LinePropertiesContext( getHandler(), xAttributes, maUnderlineProperties ) ); + break; + + // EG_TextUnderlineFill + case NMSP_DRAWINGML|XML_uFillTx: // CT_TextUnderlineFillFollowText + mrTextCharacterProperties.getUnderlineFillFollowText() <<= sal_True; + break; + case NMSP_DRAWINGML|XML_uFill: // CT_TextUnderlineFillGroupWrapper->EG_FillProperties (not supported) + xRet.set( new colorChoiceContext( getHandler(), *(mrTextCharacterProperties.getUnderlineColor().get()) ) ); + break; + + case NMSP_DRAWINGML|XML_ea: // CT_TextFont + xRet.set( new TextFontContext( getHandler(), aElementToken, xAttributes, maAsianFont ) ); + break; + case NMSP_DRAWINGML|XML_cs: // CT_TextFont + xRet.set( new TextFontContext( getHandler(), aElementToken, xAttributes, maComplexFont ) ); + break; + case NMSP_DRAWINGML|XML_sym: // CT_TextFont + xRet.set( new TextFontContext( getHandler(), aElementToken, xAttributes, maSymbolFont ) ); + break; + case NMSP_DRAWINGML|XML_latin: // CT_TextFont + xRet.set( new TextFontContext( getHandler(), aElementToken, xAttributes, maLatinFont ) ); + break; + case NMSP_DRAWINGML|XML_hlinkClick: // CT_Hyperlink + case NMSP_DRAWINGML|XML_hlinkMouseOver: // CT_Hyperlink + xRet.set( new HyperLinkContext( getHandler(), xAttributes, mrTextCharacterProperties.getHyperlinkPropertyMap() ) ); + break; + } + if ( !xRet.is() ) + xRet.set( this ); + return xRet; +} + +// -------------------------------------------------------------------- + +} } + diff --git a/oox/source/drawingml/textfield.cxx b/oox/source/drawingml/textfield.cxx new file mode 100644 index 000000000000..7ae2ba947dd7 --- /dev/null +++ b/oox/source/drawingml/textfield.cxx @@ -0,0 +1,196 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: textfield.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:52 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/textfield.hxx" + +#include + +#include +#include +#include +#include +#include + +#include "oox/helper/helper.hxx" +#include "oox/drawingml/textparagraphproperties.hxx" + +using ::rtl::OString; +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; + +namespace oox { namespace drawingml { + + TextField::TextField() + : mpTextParagraphPropertiesPtr( new TextParagraphProperties()) + { + } + + + /** intsanciate the textfields. Because of semantics difference between + * OpenXML and OpenOffice, some OpenXML field might cause two fields to be created. + * @param aFields the created fields. The list is empty if no field has been created. + * @param xModel the model + * @param sType the OpenXML field type. + */ + static void createTextFields( std::list< Reference< XTextField > > & aFields, + const Reference< XModel > & xModel, const OUString & sType ) + { + Reference< XInterface > xIface; + Reference< XMultiServiceFactory > xFactory( xModel, UNO_QUERY_THROW ); + + if( sType.compareToAscii( "datetime", 8 ) == 0) + { + OString s = ::rtl::OUStringToOString( sType, RTL_TEXTENCODING_UTF8); + OString p( s.pData->buffer + 8 ); + try + { + bool bIsDate = true; + int idx = p.toInt32(); +// OSL_TRACE( "OOX: p = %s, %d", p.pData->buffer, idx ); + xIface = xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.text.TextField.DateTime" ) ); + aFields.push_back( Reference< XTextField > ( xIface, UNO_QUERY ) ); + Reference< XPropertySet > xProps( xIface, UNO_QUERY_THROW ); + + // here we should format the field properly. waiting after #i81091. + switch( idx ) + { + case 1: // Date dd/mm/yyyy + // this is the default format... + break; + case 2: // Date Day, Month dd, yyyy + break; + case 3: // Date dd Month yyyy + break; + case 4: // Date Month dd, yyyy + break; + case 5: // Date dd-Mon-yy + break; + case 6: // Date Month yy + break; + case 7: // Date Mon-yy + break; + case 8: // DateTime dd/mm/yyyy H:MM PM + createTextFields( aFields, xModel, CREATE_OUSTRING( "datetime12" ) ); + break; + case 9: // DateTime dd/mm/yy H:MM:SS PM + createTextFields( aFields, xModel, CREATE_OUSTRING( "datetime13" ) ); + break; + case 10: // Time H:MM + bIsDate = false; + break; + case 11: // Time H:MM:SS + bIsDate = false; + // this is the default format + break; + case 12: // Time H:MM PM + bIsDate = false; + break; + case 13: // Time H:MM:SS PM + bIsDate = false; + break; + } + xProps->setPropertyValue( CREATE_OUSTRING( "IsDate" ), makeAny( bIsDate ) ); + xProps->setPropertyValue( CREATE_OUSTRING( "IsFixed" ), makeAny( false ) ); + } + catch(Exception & e) + { + OSL_TRACE( "Exception %s", OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); + } + } + else if ( sType.compareToAscii( "slidenum" ) == 0 ) + { + xIface = xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.text.TextField.PageNumber" ) ); + aFields.push_back( Reference< XTextField > ( xIface, UNO_QUERY ) ); + } + } + + void TextField::insertAt( const ::oox::core::XmlFilterBase& rFilterBase, const Reference < XText > & xText, + const Reference < XTextCursor > &xAt, + const Reference< XModel > &xModel, + const TextCharacterPropertiesPtr& rTextCharacterStyle ) + { + try { + + PropertyMap aioBulletList; + Reference< XTextRange > xStart( xAt, UNO_QUERY ); + Reference< XPropertySet > xProps( xStart, UNO_QUERY); + mpTextParagraphPropertiesPtr->pushToPropSet( rFilterBase, xProps, aioBulletList, sal_True ); + + if ( rTextCharacterStyle.get() ) + rTextCharacterStyle->pushToPropSet( rFilterBase, xProps ); + + maTextCharacterPropertiesPtr->pushToPropSet( rFilterBase, xProps ); + + std::list< Reference< XTextField > > fields; + createTextFields( fields, xModel, msType ); + if( !fields.empty() ) + { + bool bFirst = true; + for( std::list< Reference< XTextField > >::iterator iter = fields.begin(); + iter != fields.end(); ++iter ) + { + if( iter->is() ) + { + Reference< XTextContent > xContent( *iter, UNO_QUERY); + if( bFirst) + { + bFirst = false; + } + else + { + xText->insertString( xStart, CREATE_OUSTRING( " " ), sal_False ); + } + xText->insertTextContent( xStart, xContent, sal_False ); + } + } + } + else + { + xText->insertString( xStart, text(), sal_False ); + } + } + catch( const Exception& ) + { + OSL_TRACE("OOX: TextField::insertAt() exception"); + } + } + + +} } diff --git a/oox/source/drawingml/textfieldcontext.cxx b/oox/source/drawingml/textfieldcontext.cxx new file mode 100644 index 000000000000..00845ee76862 --- /dev/null +++ b/oox/source/drawingml/textfieldcontext.cxx @@ -0,0 +1,107 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: textfieldcontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:52 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include + +#include "oox/drawingml/textparagraphpropertiescontext.hxx" +#include "oox/drawingml/textcharacterpropertiescontext.hxx" +#include "oox/drawingml/textfieldcontext.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + + TextFieldContext::TextFieldContext( const ContextRef& xParent, + const Reference< XFastAttributeList >& rXAttributes, + const TextFieldPtr & pTextField) + : Context( xParent->getHandler() ) + , mpTextField( pTextField ) + , mbIsInText( false ) + { + try { + pTextField->setUuid( rXAttributes->getValue( XML_id ) ); + } + catch(...) + { + + } + pTextField->setType( rXAttributes->getOptionalValue( XML_type ) ); + } + + void TextFieldContext::endFastElement( sal_Int32 aElementToken ) throw (SAXException, RuntimeException) + { + if( aElementToken == (NMSP_DRAWINGML|XML_t) ) + { + mbIsInText = false; + } + } + + void TextFieldContext::characters( const OUString& aChars ) throw (SAXException, RuntimeException) + { + if( mbIsInText ) + { + mpTextField->text() += aChars; + } + } + + Reference< XFastContextHandler > TextFieldContext::createFastChildContext( sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) + { + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_rPr: + xRet.set( new TextCharacterPropertiesContext( this, xAttribs, *(mpTextField->getTextCharacterProperties().get()) ) ); + break; + case NMSP_DRAWINGML|XML_pPr: + xRet.set( new TextParagraphPropertiesContext( this, xAttribs, *(mpTextField->getTextParagraphProperties().get()) ) ); + break; + case NMSP_DRAWINGML|XML_t: + mbIsInText = true; + break; + } + if ( !xRet.is() ) + xRet.set( this ); + return xRet; + } + + +} } diff --git a/oox/source/drawingml/textliststyle.cxx b/oox/source/drawingml/textliststyle.cxx new file mode 100644 index 000000000000..fec174159497 --- /dev/null +++ b/oox/source/drawingml/textliststyle.cxx @@ -0,0 +1,78 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: textliststyle.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:52 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/textliststyle.hxx" + +namespace oox { namespace drawingml { + +TextListStyle::TextListStyle() + : maListStyle() + , maAggregationListStyle() +{ + int i; + for ( i = 0; i < 9; i++ ) + maListStyle.push_back( TextParagraphPropertiesPtr( new TextParagraphProperties() ) ); + for ( i = 0; i < 9; i++ ) + maAggregationListStyle.push_back( TextParagraphPropertiesPtr( new TextParagraphProperties() ) ); +} +TextListStyle::~TextListStyle() +{ +} + +void applyStyleList( const std::vector< ::oox::drawingml::TextParagraphPropertiesPtr >& rSourceListStyle, + std::vector< ::oox::drawingml::TextParagraphPropertiesPtr >& rDestListStyle ) +{ + std::vector< ::oox::drawingml::TextParagraphPropertiesPtr >::const_iterator aSourceListStyleIter( rSourceListStyle.begin() ); + std::vector< ::oox::drawingml::TextParagraphPropertiesPtr >::iterator aDestListStyleIter( rDestListStyle.begin() ); + while( aSourceListStyleIter != rSourceListStyle.end() ) + { + if ( aDestListStyleIter != rDestListStyle.end() ) + { + (*aDestListStyleIter)->apply( *aSourceListStyleIter ); + aDestListStyleIter++; + } + else + rDestListStyle.push_back( TextParagraphPropertiesPtr( new oox::drawingml::TextParagraphProperties( *(*aSourceListStyleIter).get() ) ) ); + aSourceListStyleIter++; + } +} + +void TextListStyle::apply( const TextListStylePtr& rTextListStylePtr ) +{ + applyStyleList( rTextListStylePtr->getAggregationListStyle(), getAggregationListStyle() ); + applyStyleList( rTextListStylePtr->getListStyle(), getListStyle() ); +} + +} } diff --git a/oox/source/drawingml/textliststylecontext.cxx b/oox/source/drawingml/textliststylecontext.cxx new file mode 100644 index 000000000000..1e8b33b0fbd1 --- /dev/null +++ b/oox/source/drawingml/textliststylecontext.cxx @@ -0,0 +1,120 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: textliststylecontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:52 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/textliststylecontext.hxx" +#include "oox/drawingml/textparagraphpropertiescontext.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/helper/attributelist.hxx" +#include "tokens.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +// -------------------------------------------------------------------- + +// CT_TextListStyle +TextListStyleContext::TextListStyleContext( const ::oox::core::FragmentHandlerRef& xHandler, oox::drawingml::TextListStyle& rTextListStyle ) +: Context( xHandler ) +, mrTextListStyle( rTextListStyle ) +{ +} + +TextListStyleContext::~TextListStyleContext() +{ +} + +// -------------------------------------------------------------------- + +void TextListStyleContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) +{ +} + +// -------------------------------------------------------------------- + +Reference< XFastContextHandler > TextListStyleContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& rxAttributes ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_defPPr: // CT_TextParagraphProperties + xRet.set( new TextParagraphPropertiesContext( this, rxAttributes, *(mrTextListStyle.getListStyle()[ 0 ].get()) ) ); + break; + case NMSP_DRAWINGML|XML_outline1pPr: + xRet.set( new TextParagraphPropertiesContext( this, rxAttributes, *(mrTextListStyle.getAggregationListStyle()[ 0 ].get()) ) ); + break; + case NMSP_DRAWINGML|XML_outline2pPr: + xRet.set( new TextParagraphPropertiesContext( this, rxAttributes, *(mrTextListStyle.getAggregationListStyle()[ 1 ].get()) ) ); + break; + case NMSP_DRAWINGML|XML_lvl1pPr: + xRet.set( new TextParagraphPropertiesContext( this, rxAttributes, *(mrTextListStyle.getListStyle()[ 0 ].get()) ) ); + break; + case NMSP_DRAWINGML|XML_lvl2pPr: + xRet.set( new TextParagraphPropertiesContext( this, rxAttributes, *(mrTextListStyle.getListStyle()[ 1 ].get()) ) ); + break; + case NMSP_DRAWINGML|XML_lvl3pPr: + xRet.set( new TextParagraphPropertiesContext( this, rxAttributes, *(mrTextListStyle.getListStyle()[ 2 ].get()) ) ); + break; + case NMSP_DRAWINGML|XML_lvl4pPr: + xRet.set( new TextParagraphPropertiesContext( this, rxAttributes, *(mrTextListStyle.getListStyle()[ 3 ].get()) ) ); + break; + case NMSP_DRAWINGML|XML_lvl5pPr: + xRet.set( new TextParagraphPropertiesContext( this, rxAttributes, *(mrTextListStyle.getListStyle()[ 4 ].get()) ) ); + break; + case NMSP_DRAWINGML|XML_lvl6pPr: + xRet.set( new TextParagraphPropertiesContext( this, rxAttributes, *(mrTextListStyle.getListStyle()[ 5 ].get()) ) ); + break; + case NMSP_DRAWINGML|XML_lvl7pPr: + xRet.set( new TextParagraphPropertiesContext( this, rxAttributes, *(mrTextListStyle.getListStyle()[ 6 ].get()) ) ); + break; + case NMSP_DRAWINGML|XML_lvl8pPr: + xRet.set( new TextParagraphPropertiesContext( this, rxAttributes, *(mrTextListStyle.getListStyle()[ 7 ].get()) ) ); + break; + case NMSP_DRAWINGML|XML_lvl9pPr: + xRet.set( new TextParagraphPropertiesContext( this, rxAttributes, *(mrTextListStyle.getListStyle()[ 8 ].get()) ) ); + break; + } + if ( !xRet.is() ) + xRet.set( this ); + return xRet; +} + +// -------------------------------------------------------------------- + +} } + diff --git a/oox/source/drawingml/textparagraph.cxx b/oox/source/drawingml/textparagraph.cxx new file mode 100644 index 000000000000..e078e899282d --- /dev/null +++ b/oox/source/drawingml/textparagraph.cxx @@ -0,0 +1,127 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: textparagraph.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:52 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + + +#include +#include + +#include +#include +#include +#include +#include + +#include "oox/drawingml/textparagraph.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; + +namespace oox { namespace drawingml { + + TextParagraph::TextParagraph() + : mpProperties( new TextParagraphProperties( ) ) + , mpEndProperties( new TextParagraphProperties( ) ) + { + } + + + TextParagraph::~TextParagraph() + { + } + + + void TextParagraph::insertAt( const ::oox::core::XmlFilterBase& rFilterBase, const Reference < XText > &xText, const Reference < XTextCursor > &xAt, const Reference < XModel > &xModel, + const TextListStylePtr& rTextStyleList, bool bFirst) + { + try { + sal_Int32 nParagraphSize = 0; + Reference< XTextRange > xStart( xAt, UNO_QUERY ); + + sal_Int16 nLevel = mpProperties->getLevel(); + std::vector< ::oox::drawingml::TextParagraphPropertiesPtr >& rListStyle = rTextStyleList->getListStyle(); + if ( nLevel >= static_cast< sal_Int16 >( rListStyle.size() ) ) + nLevel = 0; + TextParagraphPropertiesPtr pTextParagraphStyle; + TextCharacterPropertiesPtr pTextCharacterStyle; + if ( rListStyle.size() ) + pTextParagraphStyle = rListStyle[ nLevel ]; + if ( pTextParagraphStyle.get() ) + pTextCharacterStyle = pTextParagraphStyle->getTextCharacterProperties(); + + if( !bFirst ) + { + xText->insertControlCharacter( xStart, ControlCharacter::APPEND_PARAGRAPH, sal_False ); + xAt->gotoEnd(true); + } + + std::vector< TextRunPtr >::iterator begin( maRuns.begin() ); + while( begin != maRuns.end() ) + { + (*begin)->insertAt( rFilterBase, xText, xAt, xModel, pTextCharacterStyle ); + nParagraphSize += (*begin++)->text().getLength(); + } + xAt->gotoEnd(true); + + PropertyMap aioBulletList; + Reference< XPropertySet > xProps( xStart, UNO_QUERY); + if ( pTextParagraphStyle.get() ) + pTextParagraphStyle->pushToPropSet( rFilterBase, xProps, aioBulletList, sal_False ); + + mpProperties->pushToPropSet( rFilterBase, xProps, aioBulletList, sal_True ); + + // empty paragraphs do not have bullets in ppt + if ( !nParagraphSize ) + { + const rtl::OUString sIsNumbering( CREATE_OUSTRING( "IsNumbering" ) ); + xProps->setPropertyValue( sIsNumbering, Any( sal_False ) ); + } + +// FIXME this is causing a lot of dispruption (ie does not work). I wonder what to do -- Hub +// Reference< XTextRange > xEnd( xAt, UNO_QUERY ); +// Reference< XPropertySet > xProps2( xEnd, UNO_QUERY ); +// mpEndProperties->pushToPropSet( xProps2 ); + } + catch( Exception & ) + { + OSL_TRACE("OOX: exception in TextParagraph::insertAt"); + } + } + + +} } + diff --git a/oox/source/drawingml/textparagraphproperties.cxx b/oox/source/drawingml/textparagraphproperties.cxx new file mode 100644 index 000000000000..e29cbf823aa2 --- /dev/null +++ b/oox/source/drawingml/textparagraphproperties.cxx @@ -0,0 +1,419 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: textparagraphproperties.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:52 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/textparagraphproperties.hxx" + +#include +#include +#include +#include + +#include "oox/helper/propertyset.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "tokens.hxx" + +using rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::style; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::container; +using ::com::sun::star::awt::FontDescriptor; + +namespace oox { namespace drawingml { + +BulletList::BulletList( ) +: maBulletColorPtr( new Color() ) +{ +} + +bool BulletList::is() const +{ + return mnNumberingType.hasValue(); +} + +void BulletList::setBulletChar( const ::rtl::OUString & sChar ) +{ + mnNumberingType <<= NumberingType::CHAR_SPECIAL; + msBulletChar <<= sChar; +} + +void BulletList::setNone( ) +{ + mnNumberingType <<= NumberingType::NUMBER_NONE; +} + +void BulletList::setSuffixParenBoth() +{ + msNumberingSuffix <<= CREATE_OUSTRING( ")" ); + msNumberingPrefix <<= CREATE_OUSTRING( "(" ); +} + +void BulletList::setSuffixParenRight() +{ + msNumberingSuffix <<= CREATE_OUSTRING( ")" ); + msNumberingPrefix <<= OUString(); +} + +void BulletList::setSuffixPeriod() +{ + msNumberingSuffix <<= CREATE_OUSTRING( "." ); + msNumberingPrefix <<= OUString(); +} + +void BulletList::setSuffixNone() +{ + msNumberingSuffix <<= OUString(); + msNumberingPrefix <<= OUString(); +} + +void BulletList::setSuffixMinusRight() +{ + msNumberingSuffix <<= CREATE_OUSTRING( "-" ); + msNumberingPrefix <<= OUString(); +} + +void BulletList::setType( sal_Int32 nType ) +{ +// OSL_TRACE( "OOX: set list numbering type %d", nType); + switch( nType ) + { + case XML_alphaLcParenBoth: + mnNumberingType <<= NumberingType::CHARS_LOWER_LETTER; + setSuffixParenBoth(); + break; + case XML_alphaLcParenR: + mnNumberingType <<= NumberingType::CHARS_LOWER_LETTER; + setSuffixParenRight(); + break; + case XML_alphaLcPeriod: + mnNumberingType <<= NumberingType::CHARS_LOWER_LETTER; + setSuffixPeriod(); + break; + case XML_alphaUcParenBoth: + mnNumberingType <<= NumberingType::CHARS_UPPER_LETTER; + setSuffixParenBoth(); + break; + case XML_alphaUcParenR: + mnNumberingType <<= NumberingType::CHARS_UPPER_LETTER; + setSuffixParenRight(); + break; + case XML_alphaUcPeriod: + mnNumberingType <<= NumberingType::CHARS_UPPER_LETTER; + setSuffixPeriod(); + break; + case XML_arabic1Minus: + case XML_arabic2Minus: + case XML_arabicDbPeriod: + case XML_arabicDbPlain: + // TODO + break; + case XML_arabicParenBoth: + mnNumberingType <<= NumberingType::ARABIC; + setSuffixParenBoth(); + break; + case XML_arabicParenR: + mnNumberingType <<= NumberingType::ARABIC; + setSuffixParenRight(); + break; + case XML_arabicPeriod: + mnNumberingType <<= NumberingType::ARABIC; + setSuffixPeriod(); + break; + case XML_arabicPlain: + mnNumberingType <<= NumberingType::ARABIC; + setSuffixNone(); + break; + case XML_circleNumDbPlain: + case XML_circleNumWdBlackPlain: + case XML_circleNumWdWhitePlain: + mnNumberingType <<= NumberingType::CIRCLE_NUMBER; + break; + case XML_ea1ChsPeriod: + mnNumberingType <<= NumberingType::NUMBER_UPPER_ZH; + setSuffixPeriod(); + break; + case XML_ea1ChsPlain: + mnNumberingType <<= NumberingType::NUMBER_UPPER_ZH; + setSuffixNone(); + break; + case XML_ea1ChtPeriod: + mnNumberingType <<= NumberingType::NUMBER_UPPER_ZH_TW; + setSuffixPeriod(); + break; + case XML_ea1ChtPlain: + mnNumberingType <<= NumberingType::NUMBER_UPPER_ZH_TW; + setSuffixNone(); + break; + case XML_ea1JpnChsDbPeriod: + case XML_ea1JpnKorPeriod: + case XML_ea1JpnKorPlain: + break; + case XML_hebrew2Minus: + mnNumberingType <<= NumberingType::CHARS_HEBREW; + setSuffixMinusRight(); + break; + case XML_hindiAlpha1Period: + case XML_hindiAlphaPeriod: + case XML_hindiNumParenR: + case XML_hindiNumPeriod: + // TODO + break; + case XML_romanLcParenBoth: + mnNumberingType <<= NumberingType::ROMAN_LOWER; + setSuffixParenBoth(); + break; + case XML_romanLcParenR: + mnNumberingType <<= NumberingType::ROMAN_LOWER; + setSuffixParenRight(); + break; + case XML_romanLcPeriod: + mnNumberingType <<= NumberingType::ROMAN_LOWER; + setSuffixPeriod(); + break; + case XML_romanUcParenBoth: + mnNumberingType <<= NumberingType::ROMAN_UPPER; + setSuffixParenBoth(); + break; + case XML_romanUcParenR: + mnNumberingType <<= NumberingType::ROMAN_UPPER; + setSuffixParenRight(); + break; + case XML_romanUcPeriod: + mnNumberingType <<= NumberingType::ROMAN_UPPER; + setSuffixPeriod(); + break; + case XML_thaiAlphaParenBoth: + case XML_thaiNumParenBoth: + mnNumberingType <<= NumberingType::CHARS_THAI; + setSuffixParenBoth(); + break; + case XML_thaiAlphaParenR: + case XML_thaiNumParenR: + mnNumberingType <<= NumberingType::CHARS_THAI; + setSuffixParenRight(); + break; + case XML_thaiAlphaPeriod: + case XML_thaiNumPeriod: + mnNumberingType <<= NumberingType::CHARS_THAI; + setSuffixPeriod(); + break; + } +} + +void BulletList::setBulletSize(sal_Int16 nSize) +{ + mnSize <<= nSize; +} + + +void BulletList::setFontSize(sal_Int16 nSize) +{ + mnFontSize <<= nSize; +} + +void BulletList::apply( const BulletList& rSource ) +{ + if ( rSource.maBulletColorPtr->isUsed() ) + maBulletColorPtr = rSource.maBulletColorPtr; + if ( rSource.mbBulletColorFollowText.hasValue() ) + mbBulletColorFollowText = rSource.mbBulletColorFollowText; + if ( rSource.mbBulletFontFollowText.hasValue() ) + mbBulletFontFollowText = rSource.mbBulletFontFollowText; + if ( rSource.maBulletFont.is() ) + maBulletFont = rSource.maBulletFont; + if ( rSource.msBulletChar.hasValue() ) + msBulletChar = rSource.msBulletChar; + if ( rSource.mnStartAt.hasValue() ) + mnStartAt = rSource.mnStartAt; + if ( rSource.mnNumberingType.hasValue() ) + mnNumberingType = rSource.mnNumberingType; + if ( rSource.msNumberingPrefix.hasValue() ) + msNumberingPrefix = rSource.msNumberingPrefix; + if ( rSource.msNumberingSuffix.hasValue() ) + msNumberingSuffix = rSource.msNumberingSuffix; + if ( rSource.mnSize.hasValue() ) + mnSize = rSource.mnSize; + if ( rSource.mnFontSize.hasValue() ) + mnFontSize = rSource.mnFontSize; + if ( rSource.maStyleName.hasValue() ) + maStyleName = rSource.maStyleName; +} + +void BulletList::pushToPropMap( const ::oox::core::XmlFilterBase& rFilterBase, PropertyMap& rPropMap ) const +{ + if( msNumberingPrefix.hasValue() ) + { +// OSL_TRACE( "OOX: numb prefix found"); + const rtl::OUString sPrefix( CREATE_OUSTRING( "Prefix" ) ); + rPropMap[ sPrefix ] = msNumberingPrefix; + } + if( msNumberingSuffix.hasValue() ) + { +// OSL_TRACE( "OOX: numb suffix found"); + const rtl::OUString sSuffix( CREATE_OUSTRING( "Suffix" ) ); + rPropMap[ sSuffix ] = msNumberingSuffix; + } + if( mnStartAt.hasValue() ) + { + const rtl::OUString sStartWith( CREATE_OUSTRING( "StartWith" ) ); + rPropMap[ sStartWith ] = mnStartAt; + } + const rtl::OUString sAdjust( CREATE_OUSTRING( "Adjust" ) ); + rPropMap[ sAdjust ] <<= HoriOrientation::LEFT; + + if( mnNumberingType.hasValue() ) + { + const rtl::OUString sNumberingType( CREATE_OUSTRING( "NumberingType" ) ); + rPropMap[ sNumberingType ] = mnNumberingType; + } + if( maBulletFont.is() ) + { + FontDescriptor aFontDesc; + sal_Int16 nFontSize = 0; + if( mnFontSize >>= nFontSize ) + aFontDesc.Height = nFontSize; + + // TODO move the to the TextFont struct. + sal_Int16 nPitch, nFamily; + aFontDesc.Name = maBulletFont.msTypeface; + GetFontPitch( maBulletFont.mnPitch, nPitch, nFamily); + aFontDesc.Pitch = nPitch; + aFontDesc.Family = nFamily; + const rtl::OUString sBulletFont( CREATE_OUSTRING( "BulletFont" ) ); + rPropMap[ sBulletFont ] <<= aFontDesc; + const rtl::OUString sBulletFontName( CREATE_OUSTRING( "BulletFontName" ) ); + rPropMap[ sBulletFontName ] <<= maBulletFont.msTypeface; + } + if ( msBulletChar.hasValue() ) + { + const rtl::OUString sBulletChar( CREATE_OUSTRING( "BulletChar" ) ); + rPropMap[ sBulletChar ] = msBulletChar; + } + if( mnSize.hasValue() ) + { + const rtl::OUString sBulletRelSize( CREATE_OUSTRING( "BulletRelSize" ) ); + rPropMap[ sBulletRelSize ] = mnSize; + } + if ( maStyleName.hasValue() ) + { + const OUString sCharStyleName( CREATE_OUSTRING( "CharStyleName" ) ); + rPropMap[ sCharStyleName ] <<= maStyleName; + } + if ( maBulletColorPtr->isUsed() ) + { + const rtl::OUString sBulletColor( CREATE_OUSTRING( "BulletColor" ) ); + rPropMap[ sBulletColor ] <<= maBulletColorPtr->getColor( rFilterBase ); + } +} + +TextParagraphProperties::TextParagraphProperties() +: maTextCharacterPropertiesPtr( new TextCharacterProperties() ) +, mnLevel( 0 ) +{ +} +TextParagraphProperties::~TextParagraphProperties() +{ +} +void TextParagraphProperties::apply( const TextParagraphPropertiesPtr& rSourceTextParagraphProperties ) +{ + maTextParagraphPropertyMap.insert( rSourceTextParagraphProperties->maTextParagraphPropertyMap.begin(), rSourceTextParagraphProperties->maTextParagraphPropertyMap.end() ); + maBulletList.apply( rSourceTextParagraphProperties->maBulletList ); + maTextCharacterPropertiesPtr->apply( rSourceTextParagraphProperties->maTextCharacterPropertiesPtr ); + if ( rSourceTextParagraphProperties->maParaTopMargin.bHasValue ) + maParaTopMargin = rSourceTextParagraphProperties->maParaTopMargin; + if ( rSourceTextParagraphProperties->maParaBottomMargin.bHasValue ) + maParaBottomMargin = rSourceTextParagraphProperties->maParaBottomMargin; +} +void TextParagraphProperties::pushToPropSet( const ::oox::core::XmlFilterBase& rFilterBase, + const Reference < XPropertySet >& xPropSet, PropertyMap& rioBulletMap, sal_Bool bApplyBulletMap ) const +{ + PropertySet aPropSet( xPropSet ); + Sequence< OUString > aNames; + Sequence< Any > aValues; + +// maTextParagraphPropertyMap.dump_debug("TextParagraph paragraph props"); + maTextParagraphPropertyMap.makeSequence( aNames, aValues ); + aPropSet.setProperties( aNames, aValues ); + + maTextCharacterPropertiesPtr->pushToPropSet( rFilterBase, aPropSet.getXPropertySet() ); + maBulletList.pushToPropMap( rFilterBase, rioBulletMap ); + + if ( maParaTopMargin.bHasValue ) + { + const OUString sParaTopMargin( CREATE_OUSTRING( "ParaTopMargin" ) ); + //OSL_TRACE( "OOX: ParaTopMargin unit = %d, value = %d", maParaTopMargin.nUnit, maParaTopMargin.nValue ); + xPropSet->setPropertyValue( sParaTopMargin, Any( maParaTopMargin.toMargin( getCharacterSize( 18 ) ) ) ); + } + if ( maParaBottomMargin.bHasValue ) + { + const OUString sParaBottomMargin( CREATE_OUSTRING( "ParaBottomMargin" ) ); + //OSL_TRACE( "OOX: ParaBottomMargin unit = %d, value = %d", maParaBottomMargin.nUnit, maParaBottomMargin.nValue ); + xPropSet->setPropertyValue( sParaBottomMargin, Any( maParaBottomMargin.toMargin( getCharacterSize( 18 ) ) ) ); + } + if ( bApplyBulletMap ) + { + Any aValue; + Reference< XIndexReplace > xNumRule; + const rtl::OUString sNumberingRules( OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "NumberingRules" ) ) ); + aValue = xPropSet->getPropertyValue( sNumberingRules ); + aValue >>= xNumRule; + + OSL_ENSURE( xNumRule.is(), "can't get Numbering rules"); + if( xNumRule.is() ) + { +// OSL_TRACE("OOX: BulletList for level %d", getLevel()); +// pProps->getBulletListPropertyMap().dump_debug(); + Sequence< PropertyValue > aBulletPropSeq; + rioBulletMap.makeSequence( aBulletPropSeq ); + if( aBulletPropSeq.hasElements() ) + { +// OSL_TRACE("OOX: bullet props inserted at level %d", getLevel()); + xNumRule->replaceByIndex( getLevel(), makeAny( aBulletPropSeq ) ); + } + xPropSet->setPropertyValue( sNumberingRules, makeAny( xNumRule ) ); + } + } +} +float TextParagraphProperties::getCharacterSize( float fValue ) const +{ + if ( maTextCharacterPropertiesPtr.get() ) + fValue = maTextCharacterPropertiesPtr->getCharacterSize( fValue ); + return fValue; +} + +} } diff --git a/oox/source/drawingml/textparagraphpropertiescontext.cxx b/oox/source/drawingml/textparagraphpropertiescontext.cxx new file mode 100644 index 000000000000..65bd19d22ea7 --- /dev/null +++ b/oox/source/drawingml/textparagraphpropertiescontext.cxx @@ -0,0 +1,306 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: textparagraphpropertiescontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:52 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/textparagraphpropertiescontext.hxx" + +#include +#include + +#include "oox/drawingml/colorchoicecontext.hxx" +#include "oox/drawingml/textcharacterpropertiescontext.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/core/namespaces.hxx" +#include "textspacingcontext.hxx" +#include "textfontcontext.hxx" +#include "texttabstoplistcontext.hxx" +#include "tokens.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using ::com::sun::star::awt::FontDescriptor; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::style; +using namespace ::com::sun::star::text; + +namespace oox { namespace drawingml { + +// CT_TextParagraphProperties +TextParagraphPropertiesContext::TextParagraphPropertiesContext( const ::oox::core::ContextRef& xParent, + const Reference< XFastAttributeList >& xAttribs, + oox::drawingml::TextParagraphProperties& rTextParagraphProperties ) +: Context( xParent->getHandler() ) +, mrTextParagraphProperties( rTextParagraphProperties ) +, mrSpaceBefore( rTextParagraphProperties.getParaTopMargin() ) +, mrSpaceAfter( rTextParagraphProperties.getParaBottomMargin() ) +, mrBulletList( rTextParagraphProperties.getBulletList() ) +{ + OUString sValue; + AttributeList attribs( xAttribs ); + + PropertyMap& rPropertyMap( mrTextParagraphProperties.getTextParagraphPropertyMap() ); + + // ST_TextAlignType + if ( xAttribs->hasAttribute( XML_algn ) ) + { + sal_Int32 nAlign = xAttribs->getOptionalValueToken( XML_algn, XML_l ); + const OUString sParaAdjust( CREATE_OUSTRING( "ParaAdjust" ) ); + rPropertyMap[ sParaAdjust ] <<= GetParaAdjust( nAlign ); + } +// OSL_TRACE( "OOX: para adjust %d", GetParaAdjust( nAlign )); + // TODO see to do the same with RubyAdjust + + // ST_Coordinate32 +// sValue = xAttribs->getOptionalValue( XML_defTabSz ); SJ: we need to be able to set the default tab size for each text object, +// this is possible at the moment only for the whole document. +// sal_Int32 nDefTabSize = ( sValue.getLength() == 0 ? 0 : GetCoordinate( sValue ) ); + // TODO + +// bool bEaLineBrk = attribs.getBool( XML_eaLnBrk, true ); + if ( xAttribs->hasAttribute( XML_latinLnBrk ) ) + { + bool bLatinLineBrk = attribs.getBool( XML_latinLnBrk, true ); + const OUString sParaIsHyphenation( CREATE_OUSTRING( "ParaIsHyphenation" ) ); + rPropertyMap[ sParaIsHyphenation ] <<= bLatinLineBrk; + } + // TODO see what to do with Asian hyphenation + + // ST_TextFontAlignType + // TODO +// sal_Int32 nFontAlign = xAttribs->getOptionalValueToken( XML_fontAlgn, XML_base ); + + if ( xAttribs->hasAttribute( XML_hangingPunct ) ) + { + bool bHangingPunct = attribs.getBool( XML_hangingPunct, false ); + const OUString sParaIsHangingPunctuation( CREATE_OUSTRING( "ParaIsHangingPunctuation" ) ); + rPropertyMap[ sParaIsHangingPunctuation ] <<= bHangingPunct; + } + + // ST_Coordinate + if ( xAttribs->hasAttribute( XML_indent ) ) + { + sValue = xAttribs->getOptionalValue( XML_indent ); + const OUString sParaFirstLineIndent( CREATE_OUSTRING( "ParaFirstLineIndent" ) ); + rPropertyMap[ sParaFirstLineIndent ] <<= ( sValue.getLength() == 0 ? 0 : GetCoordinate( sValue ) ); + } + + // ST_TextIndentLevelType + // -1 is an invalid value and denote the lack of level + sal_Int32 nLevel = attribs.getInteger( XML_lvl, 0 ); + if( nLevel > 8 || nLevel < 0 ) + { + nLevel = 0; + } + + mrTextParagraphProperties.setLevel( static_cast< sal_Int16 >( nLevel ) ); + + char name[] = "Outline X"; + name[8] = static_cast( '1' + nLevel ); + const OUString sStyleNameValue( rtl::OUString::createFromAscii( name ) ); + mrBulletList.setStyleName( sStyleNameValue ); + + // ST_TextMargin + // ParaLeftMargin + if ( xAttribs->hasAttribute( XML_marL ) ) + { + sValue = xAttribs->getOptionalValue( XML_marL ); + sal_Int32 nMarL = ( sValue.getLength() == 0 ? 0 : GetCoordinate( sValue ) ); + const OUString sParaLeftMargin( CREATE_OUSTRING( "ParaLeftMargin" ) ); + rPropertyMap[ sParaLeftMargin ] <<= nMarL; + } + + // ParaRightMargin + if ( xAttribs->hasAttribute( XML_marR ) ) + { + sValue = xAttribs->getOptionalValue( XML_marR ); + sal_Int32 nMarR = ( sValue.getLength() == 0 ? 0 : GetCoordinate( sValue ) ); + const OUString sParaRightMargin( CREATE_OUSTRING( "ParaRightMargin" ) ); + rPropertyMap[ sParaRightMargin ] <<= nMarR; + } + + if ( xAttribs->hasAttribute( XML_rtl ) ) + { + bool bRtl = attribs.getBool( XML_rtl, false ); + const OUString sTextWritingMode( CREATE_OUSTRING( "TextWritingMode" ) ); + rPropertyMap[ sTextWritingMode ] <<= ( bRtl ? WritingMode_RL_TB : WritingMode_LR_TB ); + } +} + + + +TextParagraphPropertiesContext::~TextParagraphPropertiesContext() +{ + PropertyMap& rPropertyMap( mrTextParagraphProperties.getTextParagraphPropertyMap() ); + if ( maLineSpacing.bHasValue ) + { + const OUString sParaLineSpacing( CREATE_OUSTRING( "ParaLineSpacing" ) ); + //OSL_TRACE( "OOX: ParaLineSpacing unit = %d, value = %d", maLineSpacing.nUnit, maLineSpacing.nValue ); + rPropertyMap[ sParaLineSpacing ] <<= maLineSpacing.toLineSpacing(); + } + ::std::list< TabStop >::size_type nTabCount = maTabList.size(); + if( nTabCount != 0 ) + { + Sequence< TabStop > aSeq( nTabCount ); + TabStop * aArray = aSeq.getArray(); + OSL_ENSURE( aArray != NULL, "sequence array is NULL" ); + ::std::copy( maTabList.begin(), maTabList.end(), aArray ); + const OUString sParaTabStops( CREATE_OUSTRING( "ParaTabStops" ) ); + rPropertyMap[ sParaTabStops ] <<= aSeq; + } + if( mrBulletList.is() ) + { + const rtl::OUString sIsNumbering( CREATE_OUSTRING( "IsNumbering" ) ); + rPropertyMap[ sIsNumbering ] <<= sal_True; + } + sal_Int16 nLevel = mrTextParagraphProperties.getLevel(); +// OSL_TRACE("OOX: numbering level = %d", nLevel ); + const OUString sNumberingLevel( CREATE_OUSTRING( "NumberingLevel" ) ); + rPropertyMap[ sNumberingLevel ] <<= (sal_Int16)nLevel; + sal_Bool bTmp = sal_True; + const OUString sNumberingIsNumber( CREATE_OUSTRING( "NumberingIsNumber" ) ); + rPropertyMap[ sNumberingIsNumber ] <<= bTmp; +} + +// -------------------------------------------------------------------- + +void TextParagraphPropertiesContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) +{ +} + + + +// -------------------------------------------------------------------- + +Reference< XFastContextHandler > TextParagraphPropertiesContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& rXAttributes ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_lnSpc: // CT_TextSpacing + xRet.set( new TextSpacingContext( getHandler(), maLineSpacing ) ); + break; + case NMSP_DRAWINGML|XML_spcBef: // CT_TextSpacing + xRet.set( new TextSpacingContext( getHandler(), mrSpaceBefore ) ); + break; + case NMSP_DRAWINGML|XML_spcAft: // CT_TextSpacing + xRet.set( new TextSpacingContext( getHandler(), mrSpaceAfter ) ); + break; + + // EG_TextBulletColor + case NMSP_DRAWINGML|XML_buClrTx: // CT_TextBulletColorFollowText ??? + mrBulletList.mbBulletColorFollowText <<= sal_True; + break; + case NMSP_DRAWINGML|XML_buClr: // CT_Color + xRet.set( new colorChoiceContext( getHandler(), *mrBulletList.maBulletColorPtr.get() ) ); + break; + + // EG_TextBulletSize + case NMSP_DRAWINGML|XML_buSzTx: // CT_TextBulletSizeFollowText + mrBulletList.setBulletSize(100); + break; + case NMSP_DRAWINGML|XML_buSzPct: // CT_TextBulletSizePercent + mrBulletList.setBulletSize( static_cast( GetPercent( rXAttributes->getOptionalValue( XML_val ) ) / 1000 ) ); + break; + case NMSP_DRAWINGML|XML_buSzPts: // CT_TextBulletSizePoint + mrBulletList.setBulletSize(0); + mrBulletList.setFontSize( static_cast(GetTextSize( rXAttributes->getOptionalValue( XML_val ) ) ) ); + break; + + // EG_TextBulletTypeface + case NMSP_DRAWINGML|XML_buFontTx: // CT_TextBulletTypefaceFollowText + mrBulletList.mbBulletFontFollowText <<= sal_True; + break; + case NMSP_DRAWINGML|XML_buFont: // CT_TextFont + xRet.set( new TextFontContext( getHandler(), aElementToken, rXAttributes, + mrBulletList.maBulletFont ) ); + break; + + // EG_TextBullet + case NMSP_DRAWINGML|XML_buNone: // CT_TextNoBullet + mrBulletList.setNone(); + break; + case NMSP_DRAWINGML|XML_buAutoNum: // CT_TextAutonumberBullet + { + AttributeList attribs( rXAttributes ); + try { + sal_Int32 nType = rXAttributes->getValueToken( XML_type ); + sal_Int32 nStartAt = attribs.getInteger( XML_startAt, 1 ); + if( nStartAt > 32767 ) + { + nStartAt = 32767; + } + else if( nStartAt < 1 ) + { + nStartAt = 1; + } + mrBulletList.setStartAt( nStartAt ); + mrBulletList.setType( nType ); + } + catch(SAXException& /* e */ ) + { + OSL_TRACE("OOX: SAXException in XML_buAutoNum"); + } + break; + } + case NMSP_DRAWINGML|XML_buChar: // CT_TextCharBullet + try { + mrBulletList.setBulletChar( rXAttributes->getValue( XML_char ) ); + } + catch(SAXException& /* e */) + { + OSL_TRACE("OOX: SAXException in XML_buChar"); + } + break; + case NMSP_DRAWINGML|XML_buBlip: // CT_TextBlipBullet + // TODO + break; + + case NMSP_DRAWINGML|XML_tabLst: // CT_TextTabStopList + xRet.set( new TextTabStopListContext( this, maTabList ) ); + break; + case NMSP_DRAWINGML|XML_defRPr: // CT_TextCharacterProperties + xRet.set( new TextCharacterPropertiesContext( this, rXAttributes, *(mrTextParagraphProperties.getTextCharacterProperties().get()) ) ); + break; + } + if ( !xRet.is() ) + xRet.set( this ); + return xRet; +} + +// -------------------------------------------------------------------- + +} } + diff --git a/oox/source/drawingml/textrun.cxx b/oox/source/drawingml/textrun.cxx new file mode 100644 index 000000000000..ed3b362014b7 --- /dev/null +++ b/oox/source/drawingml/textrun.cxx @@ -0,0 +1,120 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: textrun.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:52 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/textrun.hxx" + +#include + +#include +#include +#include +#include + +#include "oox/helper/helper.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; + +namespace oox { namespace drawingml { + + TextRun::TextRun() + : mbIsLineBreak( false ) + , maTextCharacterPropertiesPtr( new TextCharacterProperties() ) + { + } + + + TextRun::~TextRun() + { + } + + void TextRun::insertAt( const ::oox::core::XmlFilterBase& rFilterBase, const Reference < XText > & xText, const Reference < XTextCursor > &xAt, + const Reference < XModel > & xModel, const TextCharacterPropertiesPtr& rTextCharacterStyle ) + { + try { + Reference< XTextRange > xStart( xAt, UNO_QUERY ); + + Reference< XPropertySet > xProps( xStart, UNO_QUERY); + if ( rTextCharacterStyle.get() ) + rTextCharacterStyle->pushToPropSet( rFilterBase, xProps ); + + maTextCharacterPropertiesPtr->pushToPropSet( rFilterBase, xProps ); + + if( maTextCharacterPropertiesPtr->getHyperlinkPropertyMap().empty() ) + { + if( mbIsLineBreak ) + { + OSL_TRACE( "OOX: TextRun::insertAt() insert line break" ); + xText->insertControlCharacter( xStart, ControlCharacter::LINE_BREAK, sal_False ); + } + else + { + xText->insertString( xStart, text(), sal_False ); + } + } + else + { + OSL_TRACE( "OOX: URL field" ); + Reference< XMultiServiceFactory > xFactory( xModel, UNO_QUERY ); + Reference< XTextField > xField( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.text.TextField.URL" ) ), UNO_QUERY ); + if( xField.is() ) + { + const rtl::OUString sRepresentation( OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "Representation" ) ) ); + maTextCharacterPropertiesPtr->getHyperlinkPropertyMap()[ sRepresentation ] <<= text(); + + Reference< XPropertySet > xFieldProps( xField, UNO_QUERY); + maTextCharacterPropertiesPtr->pushToUrlFieldPropSet( xFieldProps ); + Reference< XTextContent > xContent( xField, UNO_QUERY); + xText->insertTextContent( xStart, xContent, sal_False ); + } + else + { + OSL_TRACE( "OOX: URL field couldn't be created" ); + xText->insertString( xStart, text(), sal_False ); + } + } + } + catch( const Exception& ) + { + OSL_TRACE("OOX: TextRun::insertAt() exception"); + } + } + + +} } diff --git a/oox/source/drawingml/textspacingcontext.cxx b/oox/source/drawingml/textspacingcontext.cxx new file mode 100644 index 000000000000..e222a8d27a8d --- /dev/null +++ b/oox/source/drawingml/textspacingcontext.cxx @@ -0,0 +1,87 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: textspacingcontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:52 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/drawingml/textspacing.hxx" +#include "oox/core/namespaces.hxx" +#include "textspacingcontext.hxx" +#include "tokens.hxx" + + +using namespace ::oox::core; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::uno; + + +namespace oox { namespace drawingml { + + TextSpacingContext::TextSpacingContext( const FragmentHandlerRef& xHandler, + TextSpacing & aSpacing ) + : Context( xHandler ) + , maSpacing( aSpacing ) + { + maSpacing.bHasValue = sal_True; + } + + void TextSpacingContext::endFastElement( sal_Int32 /*nElement*/ ) + throw ( SAXException, RuntimeException ) + { + } + + Reference< XFastContextHandler > TextSpacingContext::createFastChildContext( ::sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs ) + throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + switch( aElement ) + { + case NMSP_DRAWINGML|XML_spcPct: + maSpacing.nUnit = TextSpacing::PERCENT; + maSpacing.nValue = GetPercent( xAttribs->getValue( XML_val ) ); + break; + case NMSP_DRAWINGML|XML_spcPts: + maSpacing.nUnit = TextSpacing::POINTS; + maSpacing.nValue = GetTextSpacingPoint( xAttribs->getValue( XML_val ) ); + break; + default: + break; + } + if ( !xRet.is() ) + xRet.set( this ); + return xRet; + } + + +} } diff --git a/oox/source/drawingml/textspacingcontext.hxx b/oox/source/drawingml/textspacingcontext.hxx new file mode 100644 index 000000000000..615e0541dbdb --- /dev/null +++ b/oox/source/drawingml/textspacingcontext.hxx @@ -0,0 +1,69 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: textspacingcontext.hxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:52 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + + + +#ifndef OOX_DRAWINGML_TEXTSPACINGCONTEXT_HXX +#define OOX_DRAWINGML_TEXTSPACINGCONTEXT_HXX + +#include + +#include "oox/core/context.hxx" + +namespace oox { namespace drawingml { + +class TextSpacing; + +class TextSpacingContext : public ::oox::core::Context +{ +public: + TextSpacingContext( const ::oox::core::FragmentHandlerRef& xHandler, TextSpacing & aSpacing ); + + virtual void SAL_CALL endFastElement( ::sal_Int32 Element ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 Element, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + +private: + TextSpacing& maSpacing; +}; + + +} } + + + + +#endif + + diff --git a/oox/source/drawingml/texttabstoplistcontext.cxx b/oox/source/drawingml/texttabstoplistcontext.cxx new file mode 100644 index 000000000000..54f6bed012b8 --- /dev/null +++ b/oox/source/drawingml/texttabstoplistcontext.cxx @@ -0,0 +1,106 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: texttabstoplistcontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:52 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include +#include + +#include + +#include "oox/core/namespaces.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "texttabstoplistcontext.hxx" +#include "tokens.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::style; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + + TextTabStopListContext::TextTabStopListContext( const ContextRef& xParent, + std::list< TabStop > & aTabList ) + : Context( *xParent ) + , maTabList( aTabList ) + { + } + + TextTabStopListContext::~TextTabStopListContext() + { + } + + void SAL_CALL TextTabStopListContext::endFastElement( ::sal_Int32 /*Element*/ ) + throw ( SAXException, RuntimeException) + { + } + + + Reference< ::XFastContextHandler > TextTabStopListContext::createFastChildContext( ::sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) + { + Reference< XFastContextHandler > xRet; + switch( aElement ) + { + case NMSP_DRAWINGML|XML_tab: + { + OUString sValue; + TabStop aTabStop; + sValue = xAttribs->getOptionalValue( XML_pos ); + if( sValue.getLength() ) + { + aTabStop.Position = GetCoordinate( sValue ); + } + sal_Int32 aToken = xAttribs->getOptionalValueToken( XML_algn, 0 ); + if( aToken != 0 ) + { + aTabStop.Alignment = GetTabAlign( aToken ); + } + maTabList.push_back(aTabStop); + break; + } + default: + break; + } + if ( !xRet.is() ) + xRet.set( this ); + return xRet; + } + + +} } + + diff --git a/oox/source/drawingml/texttabstoplistcontext.hxx b/oox/source/drawingml/texttabstoplistcontext.hxx new file mode 100644 index 000000000000..e0faed8f0f88 --- /dev/null +++ b/oox/source/drawingml/texttabstoplistcontext.hxx @@ -0,0 +1,69 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: texttabstoplistcontext.hxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:52 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef OOX_DRAWINGML_TEXTTABSTOPLISTCONTEXT_HXX +#define OOX_DRAWINGML_TEXTTABSTOPLISTCONTEXT_HXX + +#include + +#include + + +#ifndef OOX_CORE_CONTEXT_HXX +#include "oox/core/context.hxx" +#endif + +namespace oox { namespace drawingml { + + class TextTabStopListContext : public ::oox::core::Context + { + public: + TextTabStopListContext( const ::oox::core::ContextRef& xParent, + ::std::list< ::com::sun::star::style::TabStop > & aTabList ); + ~TextTabStopListContext(); + + virtual void SAL_CALL endFastElement( ::sal_Int32 Element ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 Element, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + +protected: + ::std::list< ::com::sun::star::style::TabStop > & maTabList; + }; + + +} } + + +#endif + diff --git a/oox/source/drawingml/theme.cxx b/oox/source/drawingml/theme.cxx new file mode 100644 index 000000000000..c9b776b941c6 --- /dev/null +++ b/oox/source/drawingml/theme.cxx @@ -0,0 +1,55 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: theme.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:52 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/shape.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using namespace ::oox::core; + +namespace oox { namespace drawingml { + +Theme::Theme() +: mpClrSchemePtr( new ClrScheme ) +, mpspDefPtr( new Shape ) +, mplnDefPtr( new Shape ) +, mptxDefPtr( new Shape ) +{ +} +Theme::~Theme() +{ +} + +} } diff --git a/oox/source/drawingml/themeelementscontext.cxx b/oox/source/drawingml/themeelementscontext.cxx new file mode 100644 index 000000000000..503e6d4e9514 --- /dev/null +++ b/oox/source/drawingml/themeelementscontext.cxx @@ -0,0 +1,234 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: themeelementscontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:52 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/themeelementscontext.hxx" +#include "oox/drawingml/clrschemecontext.hxx" +#include "oox/drawingml/linepropertiescontext.hxx" +#include "oox/drawingml/fillpropertiesgroupcontext.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +class fillStyleListContext : public ::oox::core::Context +{ + std::vector< oox::drawingml::FillPropertiesPtr >& mrFillStyleList; +public: + fillStyleListContext( const ::oox::core::FragmentHandlerRef& xHandler, std::vector< oox::drawingml::FillPropertiesPtr >& rFillStyleList ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 Element, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); +}; +fillStyleListContext::fillStyleListContext( const FragmentHandlerRef& xHandler, std::vector< oox::drawingml::FillPropertiesPtr >& rFillStyleList ) +: oox::core::Context( xHandler ) +, mrFillStyleList( rFillStyleList ) +{ +} +Reference< XFastContextHandler > fillStyleListContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_noFill: + case NMSP_DRAWINGML|XML_solidFill: + case NMSP_DRAWINGML|XML_gradFill: + case NMSP_DRAWINGML|XML_blipFill: + case NMSP_DRAWINGML|XML_pattFill: + case NMSP_DRAWINGML|XML_grpFill: + { + mrFillStyleList.push_back( FillPropertiesPtr( new oox::drawingml::FillProperties ) ); + FillPropertiesGroupContext::StaticCreateContext( getHandler(), aElementToken, xAttribs, *(mrFillStyleList.back().get()) ); + } + break; + } + if( !xRet.is() ) + xRet.set( this ); + return xRet; +} + +// --------------------------------------------------------------------- + +class lineStyleListContext : public ::oox::core::Context +{ + std::vector< oox::drawingml::LinePropertiesPtr >& mrLineStyleList; +public: + lineStyleListContext( const ::oox::core::FragmentHandlerRef& xHandler, std::vector< oox::drawingml::LinePropertiesPtr >& rLineStyleList ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( + ::sal_Int32 Element, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs ) + throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); +}; +lineStyleListContext::lineStyleListContext( const FragmentHandlerRef& xHandler, std::vector< oox::drawingml::LinePropertiesPtr >& rLineStyleList ) +: oox::core::Context( xHandler ) +, mrLineStyleList( rLineStyleList ) +{ +} +Reference< XFastContextHandler > lineStyleListContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_ln: + { + mrLineStyleList.push_back( LinePropertiesPtr( new oox::drawingml::LineProperties ) ); + xRet.set( new LinePropertiesContext( getHandler(), xAttribs, *(mrLineStyleList.back().get()) ) ); + } + break; + } + if( !xRet.is() ) + xRet.set( this ); + return xRet; +} + +// --------------------------------------------------------------------- + +class effectStyleListContext : public ::oox::core::Context +{ + std::vector< PropertyMap >& mrEffectStyleList; +public: + effectStyleListContext( const ::oox::core::FragmentHandlerRef& xHandler, std::vector< PropertyMap >& rEffectStyleList ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 Element, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); +}; +effectStyleListContext::effectStyleListContext( const FragmentHandlerRef& xHandler, std::vector< PropertyMap >& rEffectStyleList ) +: oox::core::Context( xHandler ) +, mrEffectStyleList( rEffectStyleList ) +{ +} +Reference< XFastContextHandler > effectStyleListContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& /* xAttribs */ ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_effectStyle: + { + mrEffectStyleList.push_back( PropertyMap() ); + // todo: last effect list entry needs to be filled/ + break; + } + } + if( !xRet.is() ) + xRet.set( this ); + return xRet; +} + +// --------------------------------------------------------------------- + +class bgFillStyleListContext : public ::oox::core::Context +{ + std::vector< oox::drawingml::FillPropertiesPtr >& mrBgFillStyleList; +public: + bgFillStyleListContext( const ::oox::core::FragmentHandlerRef& xHandler, std::vector< oox::drawingml::FillPropertiesPtr >& rBgFillStyleList ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 Element, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); +}; +bgFillStyleListContext::bgFillStyleListContext( const FragmentHandlerRef& xHandler, std::vector< oox::drawingml::FillPropertiesPtr >& rBgFillStyleList ) +: oox::core::Context( xHandler ) +, mrBgFillStyleList( rBgFillStyleList ) +{ +} +Reference< XFastContextHandler > bgFillStyleListContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_noFill: + case NMSP_DRAWINGML|XML_solidFill: + case NMSP_DRAWINGML|XML_gradFill: + case NMSP_DRAWINGML|XML_blipFill: + case NMSP_DRAWINGML|XML_pattFill: + case NMSP_DRAWINGML|XML_grpFill: + { + mrBgFillStyleList.push_back( FillPropertiesPtr( new oox::drawingml::FillProperties ) ); + FillPropertiesGroupContext::StaticCreateContext( getHandler(), aElementToken, xAttribs, *(mrBgFillStyleList.back().get()) ); + } + break; + } + if( !xRet.is() ) + xRet.set( this ); + return xRet; +} + +// --------------------------------------------------------------------- + +themeElementsContext::themeElementsContext( const ::oox::core::FragmentHandlerRef& xHandler, ::oox::drawingml::Theme& rTheme ) +: Context( xHandler ) +, mrTheme( rTheme ) +{ +} + +Reference< XFastContextHandler > themeElementsContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + // CT_BaseStyles + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_clrScheme: // CT_ColorScheme + { + xRet.set( new clrSchemeContext( getHandler(), mrTheme.getClrScheme() ) ); + break; + } + + case NMSP_DRAWINGML|XML_fontScheme: // CT_FontScheme + break; + + case NMSP_DRAWINGML|XML_fmtScheme: // CT_StyleMatrix + mrTheme.getStyleName() = xAttribs->getOptionalValue( XML_name ); + break; + + case NMSP_DRAWINGML|XML_fillStyleLst: // CT_FillStyleList + xRet.set( new fillStyleListContext( getHandler(), mrTheme.getFillStyleList() ) ); + break; + case NMSP_DRAWINGML|XML_lineStyleLst: // CT_LineStyleList + xRet.set( new lineStyleListContext( getHandler(), mrTheme.getLineStyleList() ) ); + break; + case NMSP_DRAWINGML|XML_effectStyleLst: // CT_EffectStyleList + xRet.set( new effectStyleListContext( getHandler(), mrTheme.getEffectStyleList() ) ); + break; + case NMSP_DRAWINGML|XML_bgFillStyleLst: // CT_BackgroundFillStyleList + xRet.set( new bgFillStyleListContext( getHandler(), mrTheme.getBgFillStyleList() ) ); + break; + + case NMSP_DRAWINGML|XML_extLst: // CT_OfficeArtExtensionList + break; + } + if( !xRet.is() ) + xRet.set( this ); + return xRet; +} + +} } diff --git a/oox/source/drawingml/themefragmenthandler.cxx b/oox/source/drawingml/themefragmenthandler.cxx new file mode 100644 index 000000000000..bebda788d729 --- /dev/null +++ b/oox/source/drawingml/themefragmenthandler.cxx @@ -0,0 +1,108 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: themefragmenthandler.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:52 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "comphelper/anytostring.hxx" +#include "cppuhelper/exc_hlp.hxx" + +#include +#include + +#include "oox/drawingml/themefragmenthandler.hxx" +#include "oox/drawingml/objectdefaultcontext.hxx" +#include "oox/drawingml/themeelementscontext.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::oox::core; +using namespace ::oox::drawingml; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::container; + +namespace oox { namespace drawingml { + +ThemeFragmentHandler::ThemeFragmentHandler( const XmlFilterRef& xFilter, const OUString& rFragmentPath, Theme& rTheme ) + throw() +: FragmentHandler( xFilter, rFragmentPath ) +, mrTheme( rTheme ) +{ +} +ThemeFragmentHandler::~ThemeFragmentHandler() + throw() +{ + +} +Reference< XFastContextHandler > ThemeFragmentHandler::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& /*xAttribs */ ) + throw (SAXException, RuntimeException) +{ + // CT_OfficeStyleSheet + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case NMSP_DRAWINGML|XML_themeElements: // CT_BaseStyles + { + xRet.set( new themeElementsContext( this, mrTheme ) ); + break; + } + case NMSP_DRAWINGML|XML_objectDefaults: // CT_ObjectStyleDefaults + { + xRet.set( new objectDefaultContext( this, mrTheme ) ); + break; + } + case NMSP_DRAWINGML|XML_extraClrSchemeLst: // CT_ColorSchemeList + break; + case NMSP_DRAWINGML|XML_custClrLst: // CustomColorList + break; + case NMSP_DRAWINGML|XML_ext: // CT_OfficeArtExtension + break; + } + if( !xRet.is() ) + xRet.set( this ); + return xRet; +} +void SAL_CALL ThemeFragmentHandler::endDocument() + throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException) +{ +} + +//-------------------------------------------------------------------------------------------------------------- + + + +} } + diff --git a/oox/source/dump/biffdumper.cxx b/oox/source/dump/biffdumper.cxx new file mode 100644 index 000000000000..92a892a6274a --- /dev/null +++ b/oox/source/dump/biffdumper.cxx @@ -0,0 +1,3195 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: biffdumper.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:58 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/dump/biffdumper.hxx" + +#include +#include +#include +#include +#include +#include "oox/core/filterbase.hxx" +#include "oox/xls/biffdetector.hxx" +#include "oox/xls/biffinputstream.hxx" +#include "oox/xls/formulabase.hxx" +#include "oox/xls/richstring.hxx" + +#if OOX_INCLUDE_DUMPER + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::rtl::OString; +using ::rtl::OStringBuffer; +using ::rtl::OStringToOUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::util::DateTime; +using ::com::sun::star::sheet::XSpreadsheetDocument; +using ::oox::core::FilterBase; + +using namespace ::oox::xls; + +namespace oox { +namespace dump { +namespace biff { + +namespace { + +// constants ------------------------------------------------------------------ + +const sal_uInt16 BIFF_FONTFLAG_BOLD = 0x0001; +const sal_uInt16 BIFF_FONTFLAG_ITALIC = 0x0002; + +const sal_uInt32 BIFF_HYPERLINK_TARGET = 0x00000001; /// File name or URL. +const sal_uInt32 BIFF_HYPERLINK_ABS = 0x00000002; /// Absolute path. +const sal_uInt32 BIFF_HYPERLINK_DISPLAY = 0x00000014; /// Display string. +const sal_uInt32 BIFF_HYPERLINK_LOC = 0x00000008; /// Target location. +const sal_uInt32 BIFF_HYPERLINK_FRAME = 0x00000080; /// Target frame. +const sal_uInt32 BIFF_HYPERLINK_UNC = 0x00000100; /// UNC path. + +const sal_uInt16 BIFF_OBJPIO_MANUALSIZE = 0x0001; +const sal_uInt16 BIFF_OBJPIO_LINKED = 0x0002; +const sal_uInt16 BIFF_OBJPIO_SYMBOL = 0x0008; +const sal_uInt16 BIFF_OBJPIO_CONTROL = 0x0010; /// Form control. +const sal_uInt16 BIFF_OBJPIO_CTLSSTREAM = 0x0020; /// Data in Ctls stream. +const sal_uInt16 BIFF_OBJPIO_AUTOLOAD = 0x0200; + +const sal_uInt16 BIFF_OBJCMO_GROUP = 0x0000; +const sal_uInt16 BIFF_OBJCMO_LINE = 0x0001; +const sal_uInt16 BIFF_OBJCMO_RECTANGLE = 0x0002; +const sal_uInt16 BIFF_OBJCMO_ELLIPSE = 0x0003; +const sal_uInt16 BIFF_OBJCMO_ARC = 0x0004; +const sal_uInt16 BIFF_OBJCMO_CHART = 0x0005; +const sal_uInt16 BIFF_OBJCMO_TEXT = 0x0006; +const sal_uInt16 BIFF_OBJCMO_BUTTON = 0x0007; +const sal_uInt16 BIFF_OBJCMO_PICTURE = 0x0008; +const sal_uInt16 BIFF_OBJCMO_POLYGON = 0x0009; +const sal_uInt16 BIFF_OBJCMO_CHECKBOX = 0x000B; +const sal_uInt16 BIFF_OBJCMO_OPTIONBUTTON = 0x000C; +const sal_uInt16 BIFF_OBJCMO_EDIT = 0x000D; +const sal_uInt16 BIFF_OBJCMO_LABEL = 0x000E; +const sal_uInt16 BIFF_OBJCMO_DIALOG = 0x000F; +const sal_uInt16 BIFF_OBJCMO_SPIN = 0x0010; +const sal_uInt16 BIFF_OBJCMO_SCROLLBAR = 0x0011; +const sal_uInt16 BIFF_OBJCMO_LISTBOX = 0x0012; +const sal_uInt16 BIFF_OBJCMO_GROUPBOX = 0x0013; +const sal_uInt16 BIFF_OBJCMO_COMBOBOX = 0x0014; +const sal_uInt16 BIFF_OBJCMO_NOTE = 0x0019; +const sal_uInt16 BIFF_OBJCMO_DRAWING = 0x001E; + +const sal_uInt16 BIFF_STYLE_BUILTIN = 0x8000; + +const sal_uInt16 BIFF_PT_NOSTRING = 0xFFFF; + +} // namespace + +// ============================================================================ +// ============================================================================ + +class BiffStreamInput : public Input +{ +public: + inline explicit BiffStreamInput( BiffInputStream& rStrm ) : mrStrm( rStrm ) {} + virtual ~BiffStreamInput(); + + virtual sal_Int64 getSize() const; + virtual sal_Int64 tell() const; + virtual void seek( sal_Int64 nPos ); + virtual void skip( sal_Int32 nBytes ); + virtual sal_Int32 read( void* pBuffer, sal_Int32 nBytes ); + + virtual BiffStreamInput& operator>>( sal_Int8& rnData ); + virtual BiffStreamInput& operator>>( sal_uInt8& rnData ); + virtual BiffStreamInput& operator>>( sal_Int16& rnData ); + virtual BiffStreamInput& operator>>( sal_uInt16& rnData ); + virtual BiffStreamInput& operator>>( sal_Int32& rnData ); + virtual BiffStreamInput& operator>>( sal_uInt32& rnData ); + virtual BiffStreamInput& operator>>( float& rfData ); + virtual BiffStreamInput& operator>>( double& rfData ); + +private: + BiffInputStream& mrStrm; +}; + +// ---------------------------------------------------------------------------- + +BiffStreamInput::~BiffStreamInput() +{ +} + +sal_Int64 BiffStreamInput::getSize() const +{ + return mrStrm.getRecSize(); +} + +sal_Int64 BiffStreamInput::tell() const +{ + return mrStrm.getRecPos(); +} + +void BiffStreamInput::seek( sal_Int64 nPos ) +{ + mrStrm.seek( static_cast< sal_uInt32 >( nPos ) ); +} + +void BiffStreamInput::skip( sal_Int32 nBytes ) +{ + mrStrm.skip( static_cast< sal_uInt32 >( nBytes ) ); +} + +sal_Int32 BiffStreamInput::read( void* pBuffer, sal_Int32 nSize ) +{ + return static_cast< sal_Int32 >( mrStrm.read( pBuffer, static_cast< sal_uInt32 >( nSize ) ) ); +} + +BiffStreamInput& BiffStreamInput::operator>>( sal_Int8& rnData ) { mrStrm >> rnData; return *this; } +BiffStreamInput& BiffStreamInput::operator>>( sal_uInt8& rnData ) { mrStrm >> rnData; return *this; } +BiffStreamInput& BiffStreamInput::operator>>( sal_Int16& rnData ) { mrStrm >> rnData; return *this; } +BiffStreamInput& BiffStreamInput::operator>>( sal_uInt16& rnData ) { mrStrm >> rnData; return *this; } +BiffStreamInput& BiffStreamInput::operator>>( sal_Int32& rnData ) { mrStrm >> rnData; return *this; } +BiffStreamInput& BiffStreamInput::operator>>( sal_uInt32& rnData ) { mrStrm >> rnData; return *this; } +BiffStreamInput& BiffStreamInput::operator>>( float& rfData ) { mrStrm >> rfData; return *this; } +BiffStreamInput& BiffStreamInput::operator>>( double& rfData ) { mrStrm >> rfData; return *this; } + +// ============================================================================ +// ============================================================================ + +BiffConfig::BiffConfig( const Config& rParent, BiffType eBiff ) : + meBiff( eBiff ) +{ + Config::construct( rParent ); +} + +bool BiffConfig::implIsValid() const +{ + return (meBiff != BIFF_UNKNOWN) && Config::implIsValid(); +} + +NameListRef BiffConfig::implGetNameList( const OUString& rKey ) const +{ + NameListRef xList = Config::implGetNameList( rKey ); + if( !xList ) + { + OUString aBaseKey = rKey + CREATE_OUSTRING( "-BIFF" ); + switch( meBiff ) + { + // fall-through intended! + case BIFF8: if( !xList ) xList = Config::implGetNameList( aBaseKey + OUString( sal_Unicode( '8' ) ) ); + case BIFF5: if( !xList ) xList = Config::implGetNameList( aBaseKey + OUString( sal_Unicode( '5' ) ) ); + case BIFF4: if( !xList ) xList = Config::implGetNameList( aBaseKey + OUString( sal_Unicode( '4' ) ) ); + case BIFF3: if( !xList ) xList = Config::implGetNameList( aBaseKey + OUString( sal_Unicode( '3' ) ) ); + case BIFF2: if( !xList ) xList = Config::implGetNameList( aBaseKey + OUString( sal_Unicode( '2' ) ) ); + case BIFF_UNKNOWN: break; + } + } + return xList; +} + +// ============================================================================ + +BiffSharedData::BiffSharedData( BiffType eBiff ) : + meBiff( eBiff ), + meTextEnc( osl_getThreadTextEncoding() ) +{ +} + +BiffSharedData::~BiffSharedData() +{ +} + +void BiffSharedData::setTextEncoding( rtl_TextEncoding eTextEnc ) +{ + if( eTextEnc != RTL_TEXTENCODING_DONTKNOW ) + meTextEnc = eTextEnc; +} + +sal_uInt16 BiffSharedData::getFontCount() const +{ + return static_cast< sal_uInt16 >( maFontEncs.size() ); +} + +rtl_TextEncoding BiffSharedData::getFontEncoding( sal_uInt16 nFontId ) const +{ + return (nFontId < getFontCount()) ? maFontEncs[ nFontId ] : meTextEnc; +} + +void BiffSharedData::appendFontEncoding( rtl_TextEncoding eFontEnc ) +{ + maFontEncs.push_back( (eFontEnc == RTL_TEXTENCODING_DONTKNOW) ? meTextEnc : eFontEnc ); + if( maFontEncs.size() == 4 ) + maFontEncs.push_back( meTextEnc ); +} + +sal_uInt16 BiffSharedData::getXfCount() const +{ + return static_cast< sal_uInt16 >( maXfFontIds.size() ); +} + +rtl_TextEncoding BiffSharedData::getXfEncoding( sal_uInt16 nXfId ) const +{ + sal_uInt16 nFontId = (nXfId < getXfCount()) ? maXfFontIds[ nXfId ] : 0; + return getFontEncoding( nFontId ); +} + +void BiffSharedData::appendXfFontId( sal_uInt16 nFontId ) +{ + maXfFontIds.push_back( nFontId ); +} + +bool BiffSharedData::implIsValid() const +{ + return meBiff != BIFF_UNKNOWN; +} + +// ============================================================================ + +BiffObjectBase::BiffObjectBase() +{ +} + +BiffObjectBase::~BiffObjectBase() +{ +} + +void BiffObjectBase::construct( const ObjectBase& rParent, const OUString& rOutFileName, BinaryInputStreamRef xStrm, BiffType eBiff ) +{ + if( eBiff != BIFF_UNKNOWN ) + { + InputStreamObject::construct( rParent, rOutFileName, xStrm ); + if( InputStreamObject::implIsValid() ) + { + mxBiffData.reset( new BiffSharedData( eBiff ) ); + mxStrm.reset( new BiffInputStream( getStream() ) ); + reconstructConfig(); + reconstructInput(); + } + if( BiffObjectBase::implIsValid() ) + { + const Config& rCfg = cfg(); + mxErrCodes = rCfg.getNameList( "ERRORCODES" ); + mxConstType = rCfg.getNameList( "CONSTVALUE-TYPE" ); + mxResultType = rCfg.getNameList( "FORMULA-RESULTTYPE" ); + } + } +} + +void BiffObjectBase::construct( const BiffObjectBase& rParent ) +{ + *this = rParent; +} + +bool BiffObjectBase::implIsValid() const +{ + return isValid( mxBiffCfg ) && isValid( mxBiffData ) && mxStrm.get() && InputStreamObject::implIsValid(); +} + +ConfigRef BiffObjectBase::implReconstructConfig() +{ + mxBiffCfg.reset( new BiffConfig( cfg(), getBiff() ) ); + return mxBiffCfg; +} + +InputRef BiffObjectBase::implReconstructInput() +{ + InputRef xIn; + if( mxStrm.get() ) + xIn.reset( new BiffStreamInput( *mxStrm ) ); + return xIn; +} + +OUString BiffObjectBase::getErrorName( sal_uInt8 nErrCode ) const +{ + return cfg().getName( mxErrCodes, nErrCode ); +} + +// ---------------------------------------------------------------------------- + +sal_Int32 BiffObjectBase::readCol( bool bCol16Bit ) +{ + return bCol16Bit ? mxStrm->readuInt16() : mxStrm->readuInt8(); +} + +sal_Int32 BiffObjectBase::readRow( bool bRow32Bit ) +{ + return bRow32Bit ? mxStrm->readInt32() : mxStrm->readuInt16(); +} + +void BiffObjectBase::readAddress( Address& orAddress, bool bCol16Bit, bool bRow32Bit ) +{ + orAddress.mnRow = readRow( bRow32Bit ); + orAddress.mnCol = readCol( bCol16Bit ); +} + +void BiffObjectBase::readRange( Range& orRange, bool bCol16Bit, bool bRow32Bit ) +{ + orRange.maFirst.mnRow = readRow( bRow32Bit ); + orRange.maLast.mnRow = readRow( bRow32Bit ); + orRange.maFirst.mnCol = readCol( bCol16Bit ); + orRange.maLast.mnCol = readCol( bCol16Bit ); +} + +void BiffObjectBase::readRangeList( RangeList& orRanges, bool bCol16Bit, bool bRow32Bit ) +{ + sal_uInt16 nCount; + *mxStrm >> nCount; + orRanges.resize( nCount ); + for( RangeList::iterator aIt = orRanges.begin(), aEnd = orRanges.end(); mxStrm->isValid() && (aIt != aEnd); ++aIt ) + readRange( *aIt, bCol16Bit, bRow32Bit ); +} + +// ---------------------------------------------------------------------------- + +void BiffObjectBase::writeBooleanItem( const sal_Char* pcName, sal_uInt8 nBool ) +{ + writeDecItem( pcName, nBool, "BOOLEAN" ); +} + +void BiffObjectBase::writeErrorCodeItem( const sal_Char* pcName, sal_uInt8 nErrCode ) +{ + writeHexItem( pcName, nErrCode, mxErrCodes ); +} + +void BiffObjectBase::writeFontPortions( const BinFontPortionList& rPortions ) +{ + if( !rPortions.empty() ) + { + writeDecItem( "font-count", static_cast< sal_uInt32 >( rPortions.size() ) ); + TableGuard aTabGuard( out(), 14 ); + for( BinFontPortionList::const_iterator aIt = rPortions.begin(), aEnd = rPortions.end(); aIt != aEnd; ++aIt ) + { + MultiItemsGuard aMultiGuard( out() ); + writeDecItem( "char-pos", aIt->mnPos ); + writeDecItem( "font-idx", aIt->mnFontId, "FONTNAMES" ); + } + } +} + +// ---------------------------------------------------------------------------- + +OUString BiffObjectBase::dumpByteString( const sal_Char* pcName, BiffStringFlags nFlags, rtl_TextEncoding eDefaultTextEnc ) +{ + OSL_ENSURE( !getFlag( nFlags, static_cast< BiffStringFlags >( ~(BIFF_STR_8BITLENGTH | BIFF_STR_EXTRAFONTS) ) ), "BiffObjectBase::dumpByteString - unknown flag" ); + bool b8BitLength = getFlag( nFlags, BIFF_STR_8BITLENGTH ); + + OString aString = mxStrm->readByteString( !b8BitLength ); + BinFontPortionList aPortions; + if( getFlag( nFlags, BIFF_STR_EXTRAFONTS ) ) + aPortions.importPortions( *mxStrm, false ); + + // create string portions + OUStringBuffer aBuffer; + sal_Int32 nStrLen = aString.getLength(); + if( nStrLen > 0 ) + { + // add leading and trailing string position to ease the following loop + if( aPortions.empty() || (aPortions.front().mnPos > 0) ) + aPortions.insert( aPortions.begin(), BinFontPortionData( 0, -1 ) ); + if( aPortions.back().mnPos < nStrLen ) + aPortions.push_back( BinFontPortionData( nStrLen, -1 ) ); + + // use global text encoding, if nothing special is specified + if( eDefaultTextEnc == RTL_TEXTENCODING_DONTKNOW ) + eDefaultTextEnc = getBiffData().getTextEncoding(); + + // create all string portions according to the font id vector + for( BinFontPortionList::const_iterator aIt = aPortions.begin(); aIt->mnPos < nStrLen; ++aIt ) + { + sal_Int32 nPortionLen = (aIt + 1)->mnPos - aIt->mnPos; + if( nPortionLen > 0 ) + { + // convert byte string to unicode string, using current font encoding + rtl_TextEncoding eTextEnc = mxBiffData->getFontEncoding( static_cast< sal_uInt16 >( aIt->mnFontId ) ); + if( eTextEnc == RTL_TEXTENCODING_DONTKNOW ) + eTextEnc = eDefaultTextEnc; + aBuffer.append( OStringToOUString( aString.copy( aIt->mnPos, nPortionLen ), eTextEnc ) ); + } + } + } + + OUString aUniStr = aBuffer.makeStringAndClear(); + writeStringItem( pcName ? pcName : "text", aUniStr ); + return aUniStr; +} + +OUString BiffObjectBase::dumpUniString( const sal_Char* pcName, BiffStringFlags nFlags ) +{ + OSL_ENSURE( !getFlag( nFlags, static_cast< BiffStringFlags >( ~(BIFF_STR_8BITLENGTH | BIFF_STR_SMARTFLAGS) ) ), "BiffObjectBase::dumpUniString - unknown flag" ); + bool b8BitLength = getFlag( nFlags, BIFF_STR_8BITLENGTH ); + + // --- string header --- + sal_uInt16 nChars = b8BitLength ? mxStrm->readuInt8() : mxStrm->readuInt16(); + sal_uInt8 nFlagField = 0; + if( (nChars > 0) || !getFlag( nFlags, BIFF_STR_SMARTFLAGS ) ) + *mxStrm >> nFlagField; + + bool b16Bit, bFonts, bPhonetic; + sal_uInt16 nFontCount; + sal_uInt32 nPhoneticSize; + mxStrm->readExtendedUniStringHeader( b16Bit, bFonts, bPhonetic, nFontCount, nPhoneticSize, nFlagField ); + + // --- character array --- + OUString aString = mxStrm->readRawUniString( nChars, b16Bit ); + writeStringItem( pcName ? pcName : "text", aString ); + + // --- formatting --- + // #122185# bRich flag may be set, but format runs may be missing + if( nFontCount > 0 ) + { + IndentGuard aIndGuard( out() ); + BinFontPortionList aPortions; + aPortions.importPortions( *mxStrm, nFontCount, true ); + writeFontPortions( aPortions ); + } + + // --- phonetic information --- + // #122185# bPhonetic flag may be set, but phonetic data may be missing + if( nPhoneticSize > 0 ) + { + IndentGuard aIndGuard( out() ); + dumpBinary( "phonetic-data", nPhoneticSize, false ); + } + + return aString; +} + +OUString BiffObjectBase::dumpString( const sal_Char* pcName, BiffStringFlags nByteFlags, BiffStringFlags nUniFlags, rtl_TextEncoding eDefaultTextEnc ) +{ + return (getBiff() == BIFF8) ? dumpUniString( pcName, nUniFlags ) : dumpByteString( pcName, nByteFlags, eDefaultTextEnc ); +} + +OUString BiffObjectBase::dumpOleString( const sal_Char* pcName, sal_Int32 nCharCount, bool bUnicode ) +{ + OUString aString; + if( nCharCount > 0 ) + { + sal_uInt16 nReadChars = getLimitedValue< sal_uInt16, sal_Int32 >( nCharCount, 0, SAL_MAX_UINT16 ); + aString = bUnicode ? + mxStrm->readUnicodeArray( nReadChars ) : + mxStrm->readCharArray( nReadChars, getBiffData().getTextEncoding() ); + // skip remaining chars + sal_uInt32 nSkip = static_cast< sal_uInt32 >( nCharCount - nReadChars ); + mxStrm->skip( bUnicode ? (nSkip * 2) : nSkip ); + } + writeStringItem( pcName ? pcName : "text", aString ); + return aString; +} + +OUString BiffObjectBase::dumpOleString( const sal_Char* pcName, bool bUnicode ) +{ + return dumpOleString( pcName, mxStrm->readInt32(), bUnicode ); +} + +OUString BiffObjectBase::dumpNullString( const sal_Char* pcName, bool bUnicode ) +{ + OUString aString; + if( bUnicode ) + { + OUStringBuffer aBuffer; + sal_uInt16 nChar; + for( bool bLoop = true; bLoop && mxStrm->isValid(); ) + { + *mxStrm >> nChar; + if( (bLoop = (nChar != 0)) == true ) + aBuffer.append( static_cast< sal_Unicode >( nChar ) ); + } + aString = aBuffer.makeStringAndClear(); + } + else + { + OStringBuffer aBuffer; + sal_uInt8 nChar; + for( bool bLoop = true; bLoop && mxStrm->isValid(); ) + { + *mxStrm >> nChar; + if( (bLoop = (nChar != 0)) == true ) + aBuffer.append( static_cast< sal_Char >( nChar ) ); + } + aString = OStringToOUString( aBuffer.makeStringAndClear(), getBiffData().getTextEncoding() ); + } + writeStringItem( pcName ? pcName : "text", aString ); + return aString; +} + +sal_uInt8 BiffObjectBase::dumpBoolean( const sal_Char* pcName ) +{ + sal_uInt8 nBool; + *mxStrm >> nBool; + writeBooleanItem( pcName ? pcName : "boolean", nBool ); + return nBool; +} + +sal_uInt8 BiffObjectBase::dumpErrorCode( const sal_Char* pcName ) +{ + sal_uInt8 nErrCode; + *mxStrm >> nErrCode; + writeErrorCodeItem( pcName ? pcName : "errorcode", nErrCode ); + return nErrCode; +} + +sal_Int32 BiffObjectBase::dumpRgbColor( const sal_Char* pcName ) +{ + OoxColor aColor; + aColor.importColorRgb( *mxStrm ); + writeColorItem( pcName ? pcName : "color-rgb", aColor.mnValue ); + return aColor.mnValue; +} + +rtl_TextEncoding BiffObjectBase::dumpCodePage( const sal_Char* pcName ) +{ + sal_uInt16 nCodePage = dumpDec< sal_uInt16 >( pcName ? pcName : "codepage", "CODEPAGES" ); + return BiffHelper::calcTextEncodingFromCodePage( nCodePage ); +} + +void BiffObjectBase::dumpFormulaResult( const sal_Char* pcName ) +{ + MultiItemsGuard aMultiGuard( out() ); + sal_uInt8 pnResult[ 8 ]; + mxStrm->read( pnResult, 8 ); + writeArrayItem( pcName ? pcName : "result", pnResult, 8 ); + if( (pnResult[ 6 ] == 0xFF) && (pnResult[ 7 ] == 0xFF) ) + { + sal_uInt8 nType = pnResult[ 0 ]; + sal_uInt8 nData = pnResult[ 2 ]; + writeHexItem( "type", nType, mxResultType ); + switch( nType ) + { + case 1: writeBooleanItem( "value", nData ); break; + case 2: writeErrorCodeItem( "value", nData ); break; + } + } + else + { + double* pfValue = reinterpret_cast< double* >( pnResult ); + ByteOrderConverter::convertLittleEndian( *pfValue ); + writeDecItem( "value", *pfValue ); + } +} + +sal_Int32 BiffObjectBase::dumpColIndex( const sal_Char* pcName, bool bCol16Bit ) +{ + sal_Int32 nCol = readCol( bCol16Bit ); + writeColIndexItem( pcName ? pcName : "col-idx", nCol ); + return nCol; +} + +sal_Int32 BiffObjectBase::dumpRowIndex( const sal_Char* pcName, bool bRow32Bit ) +{ + sal_Int32 nRow = readRow( bRow32Bit ); + writeRowIndexItem( pcName ? pcName : "row-idx", nRow ); + return nRow; +} + +sal_Int32 BiffObjectBase::dumpColRange( const sal_Char* pcName, bool bCol16Bit ) +{ + sal_Int32 nCol1 = readCol( bCol16Bit ); + sal_Int32 nCol2 = readCol( bCol16Bit ); + writeColRangeItem( pcName ? pcName : "col-range", nCol1, nCol2 ); + return nCol2 - nCol1 + 1; +} + +sal_Int32 BiffObjectBase::dumpRowRange( const sal_Char* pcName, bool bRow32Bit ) +{ + sal_Int32 nRow1 = readRow( bRow32Bit ); + sal_Int32 nRow2 = readRow( bRow32Bit ); + writeRowRangeItem( pcName ? pcName : "row-range", nRow1, nRow2 ); + return nRow2 - nRow1 + 1; +} + +Address BiffObjectBase::dumpAddress( const sal_Char* pcName, bool bCol16Bit, bool bRow32Bit ) +{ + Address aPos; + readAddress( aPos, bCol16Bit, bRow32Bit ); + writeAddressItem( pcName ? pcName : "addr", aPos ); + return aPos; +} + +Range BiffObjectBase::dumpRange( const sal_Char* pcName, bool bCol16Bit, bool bRow32Bit ) +{ + Range aRange; + readRange( aRange, bCol16Bit, bRow32Bit ); + writeRangeItem( pcName ? pcName : "range", aRange ); + return aRange; +} + +void BiffObjectBase::dumpRangeList( const sal_Char* pcName, bool bCol16Bit, bool bRow32Bit ) +{ + RangeList aRanges; + readRangeList( aRanges, bCol16Bit, bRow32Bit ); + writeRangeListItem( pcName ? pcName : "range-list", aRanges ); +} + +void BiffObjectBase::dumpConstArrayHeader( sal_uInt32& rnCols, sal_uInt32& rnRows ) +{ + Output& rOut = out(); + MultiItemsGuard aMultiGuard( rOut ); + rnCols = dumpDec< sal_uInt8 >( "width" ); + rnRows = dumpDec< sal_uInt16 >( "height" ); + switch( getBiff() ) + { + case BIFF2: + case BIFF3: + case BIFF4: + case BIFF5: if( rnCols == 0 ) rnCols = 256; break; + case BIFF8: ++rnCols; ++rnRows; break; + case BIFF_UNKNOWN: break; + } + ItemGuard aItem( rOut, "size" ); + rOut.writeDec( rnCols ); + rOut.writeChar( 'x' ); + rOut.writeDec( rnRows ); + aItem.cont(); + rOut.writeDec( rnCols * rnRows ); +} + +OUString BiffObjectBase::dumpConstValue() +{ + Output& rOut = out(); + MultiItemsGuard aMultiGuard( rOut ); + OUStringBuffer aValue; + switch( dumpDec< sal_uInt8 >( "type", mxConstType ) ) + { + case BIFF_DATATYPE_EMPTY: + dumpUnused( 8 ); + aValue.append( OOX_DUMP_EMPTYVALUE ); + break; + case BIFF_DATATYPE_DOUBLE: + dumpDec< double >( "value" ); + aValue.append( rOut.getLastItemValue() ); + break; + case BIFF_DATATYPE_STRING: + aValue.append( dumpString( "value", BIFF_STR_8BITLENGTH ) ); + StringHelper::enclose( aValue, OOX_DUMP_STRQUOTE ); + break; + case BIFF_DATATYPE_BOOL: + dumpBoolean( "value" ); + aValue.append( rOut.getLastItemValue() ); + dumpUnused( 7 ); + break; + case BIFF_DATATYPE_ERROR: + dumpErrorCode( "value" ); + aValue.append( rOut.getLastItemValue() ); + dumpUnused( 7 ); + break; + } + return aValue.makeStringAndClear(); +} + +// ============================================================================ +// ============================================================================ + +FormulaObject::FormulaObject( const BiffObjectBase& rParent ) : + mpcName( 0 ), + mnSize( 0 ) +{ + BiffObjectBase::construct( rParent ); + constructFmlaObj(); +} + +FormulaObject::~FormulaObject() +{ +} + +sal_uInt16 FormulaObject::readFormulaSize() +{ + return (getBiff() == BIFF2) ? getBiffStream().readuInt8() : getBiffStream().readuInt16(); +} + +sal_uInt16 FormulaObject::dumpFormulaSize( const sal_Char* pcName ) +{ + if( !pcName ) pcName = "formula-size"; + sal_uInt16 nSize = readFormulaSize(); + writeDecItem( pcName, nSize ); + return nSize; +} + +void FormulaObject::dumpCellFormula( const sal_Char* pcName, sal_uInt16 nSize ) +{ + dumpFormula( pcName, nSize, false ); +} + +void FormulaObject::dumpCellFormula( const sal_Char* pcName ) +{ + dumpFormula( pcName, false ); +} + +void FormulaObject::dumpNameFormula( const sal_Char* pcName, sal_uInt16 nSize ) +{ + dumpFormula( pcName, nSize, true ); +} + +void FormulaObject::dumpNameFormula( const sal_Char* pcName ) +{ + dumpFormula( pcName, true ); +} + +void FormulaObject::implDump() +{ + { + MultiItemsGuard aMultiGuard( out() ); + writeEmptyItem( mpcName ); + writeDecItem( "formula-size", mnSize ); + } + if( mnSize == 0 ) return; + + Input& rIn = in(); + sal_Int64 nStartPos = rIn.tell(); + sal_Int64 nEndPos = ::std::min< sal_Int64 >( nStartPos + mnSize, rIn.getSize() ); + + bool bValid = mxTokens.get(); + mxStack.reset( new FormulaStack ); + maAddData.clear(); + IndentGuard aIndGuard( out() ); + { + TableGuard aTabGuard( out(), 8, 18 ); + while( bValid && (rIn.tell() < nEndPos) ) + { + MultiItemsGuard aMultiGuard( out() ); + writeHexItem( 0, static_cast< sal_uInt16 >( rIn.tell() - nStartPos ) ); + sal_uInt8 nTokenId = dumpHex< sal_uInt8 >( 0, mxTokens ); + bValid = mxTokens->hasName( nTokenId ); + if( bValid ) + { + sal_uInt8 nTokClass = nTokenId & BIFF_TOKCLASS_MASK; + sal_uInt8 nBaseId = nTokenId & BIFF_TOKID_MASK; + if( nTokClass == BIFF_TOKCLASS_NONE ) + { + switch( nBaseId ) + { + case BIFF_TOKID_EXP: dumpExpToken( "EXP" ); break; + case BIFF_TOKID_TBL: dumpExpToken( "TBL" ); break; + case BIFF_TOKID_ADD: dumpBinaryOpToken( "+" ); break; + case BIFF_TOKID_SUB: dumpBinaryOpToken( "-" ); break; + case BIFF_TOKID_MUL: dumpBinaryOpToken( "*" ); break; + case BIFF_TOKID_DIV: dumpBinaryOpToken( "/" ); break; + case BIFF_TOKID_POWER: dumpBinaryOpToken( "^" ); break; + case BIFF_TOKID_CONCAT: dumpBinaryOpToken( "&" ); break; + case BIFF_TOKID_LT: dumpBinaryOpToken( "<" ); break; + case BIFF_TOKID_LE: dumpBinaryOpToken( "<=" ); break; + case BIFF_TOKID_EQ: dumpBinaryOpToken( "=" ); break; + case BIFF_TOKID_GE: dumpBinaryOpToken( ">=" ); break; + case BIFF_TOKID_GT: dumpBinaryOpToken( "<" ); break; + case BIFF_TOKID_NE: dumpBinaryOpToken( "<>" ); break; + case BIFF_TOKID_ISECT: dumpBinaryOpToken( " " ); break; + case BIFF_TOKID_LIST: dumpBinaryOpToken( "," ); break; + case BIFF_TOKID_RANGE: dumpBinaryOpToken( ":" ); break; + case BIFF_TOKID_UPLUS: dumpUnaryOpToken( "+", "" ); break; + case BIFF_TOKID_UMINUS: dumpUnaryOpToken( "-", "" ); break; + case BIFF_TOKID_PERCENT: dumpUnaryOpToken( "", "%" ); break; + case BIFF_TOKID_PAREN: dumpUnaryOpToken( "(", ")" ); break; + case BIFF_TOKID_MISSARG: dumpMissArgToken(); break; + case BIFF_TOKID_STR: dumpStringToken(); break; + case BIFF_TOKID_NLR: bValid = dumpNlrToken(); break; + case BIFF_TOKID_ATTR: bValid = dumpAttrToken(); break; + case BIFF_TOKID_SHEET: dumpSheetToken(); break; + case BIFF_TOKID_ENDSHEET: dumpEndSheetToken(); break; + case BIFF_TOKID_ERR: dumpErrorToken(); break; + case BIFF_TOKID_BOOL: dumpBoolToken(); break; + case BIFF_TOKID_INT: dumpIntToken(); break; + case BIFF_TOKID_NUM: dumpDoubleToken(); break; + default: bValid = false; + } + } + else + { + OUString aTokClass = cfg().getName( mxClasses, nTokClass ); + switch( nBaseId ) + { + case BIFF_TOKID_ARRAY: dumpArrayToken( aTokClass ); break; + case BIFF_TOKID_FUNC: dumpFuncToken( aTokClass ); break; + case BIFF_TOKID_FUNCVAR: dumpFuncVarToken( aTokClass ); break; + case BIFF_TOKID_NAME: dumpNameToken( aTokClass ); break; + case BIFF_TOKID_REF: dumpRefToken( aTokClass, false ); break; + case BIFF_TOKID_AREA: dumpAreaToken( aTokClass, false ); break; + case BIFF_TOKID_MEMAREA: dumpMemAreaToken( aTokClass, true ); break; + case BIFF_TOKID_MEMERR: dumpMemAreaToken( aTokClass, false ); break; + case BIFF_TOKID_MEMNOMEM: dumpMemAreaToken( aTokClass, false ); break; + case BIFF_TOKID_MEMFUNC: dumpMemFuncToken( aTokClass ); break; + case BIFF_TOKID_REFERR: dumpRefErrToken( aTokClass, false ); break; + case BIFF_TOKID_AREAERR: dumpRefErrToken( aTokClass, true ); break; + case BIFF_TOKID_REFN: dumpRefToken( aTokClass, true ); break; + case BIFF_TOKID_AREAN: dumpAreaToken( aTokClass, true ); break; + case BIFF_TOKID_MEMAREAN: dumpMemFuncToken( aTokClass ); break; + case BIFF_TOKID_MEMNOMEMN: dumpMemFuncToken( aTokClass ); break; + case BIFF_TOKID_FUNCCE: dumpCmdToken( aTokClass ); break; + case BIFF_TOKID_NAMEX: dumpNameXToken( aTokClass ); break; + case BIFF_TOKID_REF3D: dumpRef3dToken( aTokClass, mbNameMode ); break; + case BIFF_TOKID_AREA3D: dumpArea3dToken( aTokClass, mbNameMode ); break; + case BIFF_TOKID_REFERR3D: dumpRefErr3dToken( aTokClass, false ); break; + case BIFF_TOKID_AREAERR3D: dumpRefErr3dToken( aTokClass, true ); break; + default: bValid = false; + } + } + } + } + } + bValid = nEndPos == rIn.tell(); + if( bValid ) + { + dumpAddTokenData(); + writeInfoItem( "formula", mxStack->getFormulaString() ); + writeInfoItem( "classes", mxStack->getClassesString() ); + } + else + dumpBinary( OOX_DUMP_ERRASCII( "formula-error" ), static_cast< sal_Int32 >( nEndPos - rIn.tell() ), false ); + + mpcName = 0; + mnSize = 0; +} + +void FormulaObject::dumpFormula( const sal_Char* pcName, sal_uInt16 nSize, bool bNameMode ) +{ + mpcName = pcName ? pcName : "formula"; + mnSize = nSize; + mbNameMode = bNameMode; + dump(); +} + +void FormulaObject::dumpFormula( const sal_Char* pcName, bool bNameMode ) +{ + dumpFormula( pcName, readFormulaSize(), bNameMode ); +} + +// private -------------------------------------------------------------------- + +void FormulaObject::constructFmlaObj() +{ + if( BiffObjectBase::implIsValid() ) + { + Reference< XSpreadsheetDocument > xDocument( getFilter().getModel(), UNO_QUERY ); + mxFuncProv.reset( new FunctionProvider( xDocument, getBiff(), true ) ); + + Config& rCfg = cfg(); + mxClasses = rCfg.getNameList( "TOKENCLASSES" ); + mxRelFlags = rCfg.getNameList( "REFRELFLAGS" ); + mxNlrTypes = rCfg.getNameList( "NLRTYPES" ); + mxAttrTypes = rCfg.getNameList( "ATTRTYPES" ); + mxSpTypes = rCfg.getNameList( "ATTRSPACETYPES" ); + + // create classified token names + mxTokens = rCfg.createNameList< ConstList >( "TOKENS" ); + mxTokens->includeList( rCfg.getNameList( "BASETOKENS" ) ); + + NameListRef xClassTokens = rCfg.getNameList( "CLASSTOKENS" ); + if( mxClasses.get() && xClassTokens.get() ) + for( NameListBase::const_iterator aCIt = mxClasses->begin(), aCEnd = mxClasses->end(); aCIt != aCEnd; ++aCIt ) + for( NameListBase::const_iterator aTIt = xClassTokens->begin(), aTEnd = xClassTokens->end(); aTIt != aTEnd; ++aTIt ) + mxTokens->setName( aCIt->first | aTIt->first, aTIt->second + aCIt->second ); + + mnColCount = 256; + mnRowCount = (getBiff() == BIFF8) ? 65536 : 16384; + } +} + +// ---------------------------------------------------------------------------- + +namespace { + +OUString lclCreateName( const OUString& rRef, sal_uInt16 nNameIdx ) +{ + OUStringBuffer aName( rRef ); + StringHelper::appendIndexedText( aName, CREATE_OUSTRING( "NAME" ), nNameIdx ); + return aName.makeStringAndClear(); +} + +OUString lclCreateNlr( const OUString& rData, bool bRel = true ) +{ + OUStringBuffer aNlr; + if( !bRel ) aNlr.append( OOX_DUMP_ADDRABS ); + StringHelper::appendIndexedText( aNlr, CREATE_OUSTRING( "NLR" ), rData ); + return aNlr.makeStringAndClear(); +} + +OUString lclCreateNlr( const TokenAddress& rPos ) +{ + OUStringBuffer aAddr; + StringHelper::appendAddrCol( aAddr, rPos.mnCol, true ); + StringHelper::appendAddrRow( aAddr, rPos.mnRow, true ); + return lclCreateNlr( aAddr.makeStringAndClear(), rPos.mbRelRow ); +} + +} // namespace + +// ---------------------------------------------------------------------------- + +TokenAddress FormulaObject::createTokenAddress( sal_uInt16 nCol, sal_uInt16 nRow, bool bRelC, bool bRelR, bool bNameMode ) const +{ + TokenAddress aPos; + aPos.mnCol = nCol; + if( bRelC && bNameMode && (nCol >= mnColCount / 2) ) aPos.mnCol -= mnColCount; + aPos.mbRelCol = bRelC; + aPos.mnRow = nRow; + if( bRelR && bNameMode && (nRow >= mnRowCount / 2) ) aPos.mnRow -= mnRowCount; + aPos.mbRelRow = bRelR; + return aPos; +} + +OUString FormulaObject::createRef( const OUString& rData ) const +{ + return maRefPrefix + rData; +} + +OUString FormulaObject::createName( sal_uInt16 nNameIdx ) const +{ + return lclCreateName( maRefPrefix, nNameIdx ); +} + +OUString FormulaObject::createPlaceHolder( size_t nIdx ) const +{ + OUStringBuffer aStr; + StringHelper::appendDec( aStr, static_cast< sal_uInt32 >( nIdx ) ); + StringHelper::enclose( aStr, OOX_DUMP_PLACEHOLDER ); + return aStr.makeStringAndClear(); +} + +OUString FormulaObject::createPlaceHolder() const +{ + return createPlaceHolder( maAddData.size() ); +} + +sal_uInt16 FormulaObject::readFuncId() +{ + return (getBiff() >= BIFF4) ? in().readValue< sal_uInt16 >() : in().readValue< sal_uInt8 >(); +} + +OUString FormulaObject::writeFuncIdItem( sal_uInt16 nFuncId, const FunctionInfo** oppFuncInfo ) +{ + ItemGuard aItemGuard( out(), "func-id" ); + writeHexItem( 0, nFuncId, "FUNCID" ); + OUStringBuffer aBuffer; + const FunctionInfo* pFuncInfo = mxFuncProv->getFuncInfoFromBiffFuncId( nFuncId ); + if( pFuncInfo ) + aBuffer.append( pFuncInfo->maOoxFuncName ); + else + { + bool bCmd = getFlag( nFuncId, BIFF_TOK_FUNCVAR_CMD ); + aBuffer.appendAscii( bCmd ? "CMD" : "FUNC" ); + StringHelper::appendIndex( aBuffer, nFuncId & BIFF_TOK_FUNCVAR_FUNCIDMASK ); + } + OUString aFuncName = aBuffer.makeStringAndClear(); + aItemGuard.cont(); + out().writeString( aFuncName ); + if( oppFuncInfo ) *oppFuncInfo = pFuncInfo; + return aFuncName; +} + +sal_uInt16 FormulaObject::dumpTokenCol( const sal_Char* pcName, bool& rbRelC, bool& rbRelR ) +{ + sal_uInt16 nCol = 0; + if( getBiff() == BIFF8 ) + { + nCol = dumpHex< sal_uInt16 >( pcName, mxRelFlags ); + rbRelC = getFlag( nCol, BIFF_TOK_REF_COLREL ); + rbRelR = getFlag( nCol, BIFF_TOK_REF_ROWREL ); + nCol &= BIFF_TOK_REF_COLMASK; + } + else + nCol = dumpDec< sal_uInt8 >( pcName ); + return nCol; +} + +sal_uInt16 FormulaObject::dumpTokenRow( const sal_Char* pcName, bool& rbRelC, bool& rbRelR ) +{ + sal_uInt16 nRow = 0; + if( getBiff() == BIFF8 ) + nRow = dumpDec< sal_uInt16 >( pcName ); + else + { + nRow = dumpHex< sal_uInt16 >( pcName, mxRelFlags ); + rbRelC = getFlag( nRow, BIFF_TOK_REF_COLREL ); + rbRelR = getFlag( nRow, BIFF_TOK_REF_ROWREL ); + nRow &= BIFF_TOK_REF_ROWMASK; + } + return nRow; +} + +TokenAddress FormulaObject::dumpTokenAddress( bool bNameMode ) +{ + bool bRelC = false; + bool bRelR = false; + sal_uInt16 nRow = dumpTokenRow( "row", bRelC, bRelR ); + sal_uInt16 nCol = dumpTokenCol( "col", bRelC, bRelR ); + return createTokenAddress( nCol, nRow, bRelC, bRelR, bNameMode ); +} + +TokenRange FormulaObject::dumpTokenRange( bool bNameMode ) +{ + bool bRelC1 = false; + bool bRelR1 = false; + bool bRelC2 = false; + bool bRelR2 = false; + sal_uInt16 nRow1 = dumpTokenRow( "row1", bRelC1, bRelR1 ); + sal_uInt16 nRow2 = dumpTokenRow( "row2", bRelC2, bRelR2 ); + sal_uInt16 nCol1 = dumpTokenCol( "col1", bRelC1, bRelR1 ); + sal_uInt16 nCol2 = dumpTokenCol( "col2", bRelC2, bRelR2 ); + TokenRange aRange; + aRange.maFirst = createTokenAddress( nCol1, nRow1, bRelC1, bRelR1, bNameMode ); + aRange.maLast = createTokenAddress( nCol2, nRow2, bRelC2, bRelR2, bNameMode ); + return aRange; +} + +sal_Int16 FormulaObject::readTokenRefIdx() +{ + sal_Int16 nRefIdx = dumpDec< sal_Int16 >( "ref-idx" ); + switch( getBiff() ) + { + case BIFF2: dumpUnused( 1 ); break; + case BIFF3: dumpUnused( 2 ); break; + case BIFF4: dumpUnused( 2 ); break; + case BIFF5: dumpUnused( 8 ); break; + case BIFF8: break; + case BIFF_UNKNOWN: break; + } + return nRefIdx; +} + +OUString FormulaObject::dumpTokenRefIdx() +{ + OUStringBuffer aRef( CREATE_OUSTRING( "REF" ) ); + StringHelper::appendIndex( aRef, readTokenRefIdx() ); + aRef.append( OOX_DUMP_TABSEP ); + return aRef.makeStringAndClear(); +} + +OUString FormulaObject::dumpTokenRefTabIdxs() +{ + sal_Int16 nRefIdx = readTokenRefIdx(); + OUStringBuffer aRef( CREATE_OUSTRING( "REF" ) ); + StringHelper::appendIndex( aRef, nRefIdx ); + if( getBiff() == BIFF5 ) + { + dumpDec< sal_Int16 >( "tab1" ); + sal_Int16 nTab2 = dumpDec< sal_Int16 >( "tab2" ); + if( (nRefIdx > 0) && (nTab2 > 0) && (nRefIdx != nTab2) ) + { + aRef.append( OOX_DUMP_RANGESEP ); + aRef.appendAscii( "REF" ); + StringHelper::appendIndex( aRef, nTab2 ); + } + } + aRef.append( OOX_DUMP_TABSEP ); + return aRef.makeStringAndClear(); +} + +void FormulaObject::dumpIntToken() +{ + dumpDec< sal_uInt16 >( "value" ); + mxStack->pushOperand( out().getLastItemValue() ); +} + +void FormulaObject::dumpDoubleToken() +{ + dumpDec< double >( "value" ); + mxStack->pushOperand( out().getLastItemValue() ); +} + +void FormulaObject::dumpStringToken() +{ + OUStringBuffer aValue; + aValue.append( dumpString( "value", BIFF_STR_8BITLENGTH, BIFF_STR_8BITLENGTH ) ); + StringHelper::enclose( aValue, OOX_DUMP_FMLASTRQUOTE ); + mxStack->pushOperand( aValue.makeStringAndClear() ); +} + +void FormulaObject::dumpBoolToken() +{ + dumpBoolean( "value" ); + mxStack->pushOperand( out().getLastItemValue() ); +} + +void FormulaObject::dumpErrorToken() +{ + dumpErrorCode( "value" ); + mxStack->pushOperand( out().getLastItemValue() ); +} + +void FormulaObject::dumpMissArgToken() +{ + mxStack->pushOperand( OUString( OOX_DUMP_EMPTYVALUE ) ); +} + +void FormulaObject::dumpArrayToken( const OUString& rTokClass ) +{ + dumpUnused( (getBiff() == BIFF2) ? 6 : 7 ); + mxStack->pushOperand( createPlaceHolder(), rTokClass ); + maAddData.push_back( ADDDATA_ARRAY ); +} + +void FormulaObject::dumpNameToken( const OUString& rTokClass ) +{ + sal_uInt16 nNameIdx = dumpDec< sal_uInt16 >( "name-idx" ); + switch( getBiff() ) + { + case BIFF2: dumpUnused( 5 ); break; + case BIFF3: + case BIFF4: dumpUnused( 8 ); break; + case BIFF5: dumpUnused( 12 ); break; + case BIFF8: dumpUnused( 2 ); break; + case BIFF_UNKNOWN: break; + } + mxStack->pushOperand( createName( nNameIdx ), rTokClass ); +} + +void FormulaObject::dumpNameXToken( const OUString& rTokClass ) +{ + OUString aRef = dumpTokenRefIdx(); + sal_uInt16 nNameIdx = dumpDec< sal_uInt16 >( "name-idx" ); + dumpUnused( (getBiff() == BIFF8) ? 2 : 12 ); + mxStack->pushOperand( lclCreateName( aRef, nNameIdx ), rTokClass ); +} + +void FormulaObject::dumpRefToken( const OUString& rTokClass, bool bNameMode ) +{ + TokenAddress aPos = dumpTokenAddress( bNameMode ); + writeTokenAddressItem( "addr", aPos, bNameMode ); + mxStack->pushOperand( createRef( out().getLastItemValue() ), rTokClass ); +} + +void FormulaObject::dumpAreaToken( const OUString& rTokClass, bool bNameMode ) +{ + TokenRange aRange = dumpTokenRange( bNameMode ); + writeTokenRangeItem( "range", aRange, bNameMode ); + mxStack->pushOperand( createRef( out().getLastItemValue() ), rTokClass ); +} + +void FormulaObject::dumpRefErrToken( const OUString& rTokClass, bool bArea ) +{ + dumpUnused( ((getBiff() == BIFF8) ? 4 : 3) * (bArea ? 2 : 1) ); + mxStack->pushOperand( createRef( getErrorName( BIFF_ERR_REF ) ), rTokClass ); +} + +void FormulaObject::dumpRef3dToken( const OUString& rTokClass, bool bNameMode ) +{ + OUString aRef = dumpTokenRefTabIdxs(); + TokenAddress aPos = dumpTokenAddress( bNameMode ); + writeTokenAddress3dItem( "addr", aRef, aPos, bNameMode ); + mxStack->pushOperand( out().getLastItemValue(), rTokClass ); +} + +void FormulaObject::dumpArea3dToken( const OUString& rTokClass, bool bNameMode ) +{ + OUString aRef = dumpTokenRefTabIdxs(); + TokenRange aRange = dumpTokenRange( bNameMode ); + writeTokenRange3dItem( "range", aRef, aRange, bNameMode ); + mxStack->pushOperand( out().getLastItemValue(), rTokClass ); +} + +void FormulaObject::dumpRefErr3dToken( const OUString& rTokClass, bool bArea ) +{ + OUString aRef = dumpTokenRefTabIdxs(); + dumpUnused( ((getBiff() == BIFF8) ? 4 : 3) * (bArea ? 2 : 1) ); + mxStack->pushOperand( aRef + getErrorName( BIFF_ERR_REF ), rTokClass ); +} + +void FormulaObject::dumpMemFuncToken( const OUString& /*rTokClass*/ ) +{ + dumpDec< sal_uInt16, sal_uInt8 >( getBiff() != BIFF2, "size" ); +} + +void FormulaObject::dumpMemAreaToken( const OUString& rTokClass, bool bAddData ) +{ + dumpUnused( (getBiff() == BIFF2) ? 3 : 4 ); + dumpMemFuncToken( rTokClass ); + if( bAddData ) + maAddData.push_back( ADDDATA_MEMAREA ); +} + +void FormulaObject::dumpExpToken( const StringWrapper& rName ) +{ + Address aPos; + aPos.mnRow = dumpDec< sal_uInt16 >( "row" ); + aPos.mnCol = dumpDec< sal_uInt16, sal_uInt8 >( getBiff() != BIFF2, "col" ); + writeAddressItem( "base-addr", aPos ); + OUStringBuffer aOp( rName.getString() ); + StringHelper::appendIndex( aOp, out().getLastItemValue() ); + mxStack->pushOperand( aOp.makeStringAndClear() ); +} + +void FormulaObject::dumpUnaryOpToken( const StringWrapper& rLOp, const StringWrapper& rROp ) +{ + mxStack->pushUnaryOp( rLOp, rROp ); +} + +void FormulaObject::dumpBinaryOpToken( const StringWrapper& rOp ) +{ + mxStack->pushBinaryOp( rOp ); +} + +void FormulaObject::dumpFuncToken( const OUString& rTokClass ) +{ + sal_uInt16 nFuncId = readFuncId(); + const FunctionInfo* pFuncInfo = 0; + OUString aFuncName = writeFuncIdItem( nFuncId, &pFuncInfo ); + if( pFuncInfo && (pFuncInfo->mnMinParamCount == pFuncInfo->mnMaxParamCount) ) + mxStack->pushFuncOp( aFuncName, rTokClass, pFuncInfo->mnMinParamCount ); + else + mxStack->setError(); +} + +void FormulaObject::dumpFuncVarToken( const OUString& rTokClass ) +{ + sal_uInt8 nParamCount; + in() >> nParamCount; + sal_uInt16 nFuncId = readFuncId(); + bool bCmd = getFlag( nFuncId, BIFF_TOK_FUNCVAR_CMD ); + if( bCmd ) + writeHexItem( "param-count", nParamCount, "PARAMCOUNT-CMD" ); + else + writeDecItem( "param-count", nParamCount ); + OUString aFuncName = writeFuncIdItem( nFuncId ); + if( bCmd && getFlag( nParamCount, BIFF_TOK_FUNCVAR_CMDPROMPT ) ) + { + aFuncName += OUString( OOX_DUMP_CMDPROMPT ); + nParamCount &= BIFF_TOK_FUNCVAR_COUNTMASK; + } + mxStack->pushFuncOp( aFuncName, rTokClass, nParamCount ); +} + +void FormulaObject::dumpCmdToken( const OUString& rTokClass ) +{ + sal_uInt8 nParamCount = dumpDec< sal_uInt8 >( "param-count", "PARAMCOUNT-CMD" ); + sal_uInt16 nCmdId = readFuncId() | BIFF_TOK_FUNCVAR_CMD; + OUString aFuncName = writeFuncIdItem( nCmdId ); + if( getFlag( nParamCount, BIFF_TOK_FUNCVAR_CMDPROMPT ) ) + { + aFuncName += OUString( OOX_DUMP_CMDPROMPT ); + nParamCount &= BIFF_TOK_FUNCVAR_COUNTMASK; + } + mxStack->pushFuncOp( aFuncName, rTokClass, nParamCount ); +} + +void FormulaObject::dumpSheetToken() +{ + dumpUnused( (getBiff() == BIFF2) ? 4 : 6 ); + maRefPrefix = dumpTokenRefIdx(); +} + +void FormulaObject::dumpEndSheetToken() +{ + dumpUnused( (getBiff() == BIFF2) ? 3 : 4 ); + maRefPrefix = OUString(); +} + +bool FormulaObject::dumpAttrToken() +{ + bool bValid = true; + bool bBiff2 = getBiff() == BIFF2; + sal_uInt8 nType = dumpHex< sal_uInt8 >( "type", mxAttrTypes ); + switch( nType ) + { + case BIFF_TOK_ATTR_VOLATILE: + dumpUnused( bBiff2 ? 1 : 2 ); + break; + case BIFF_TOK_ATTR_IF: + dumpDec< sal_uInt16, sal_uInt8 >( !bBiff2, "skip" ); + break; + case BIFF_TOK_ATTR_CHOOSE: + { + sal_uInt16 nCount = dumpDec< sal_uInt16, sal_uInt8 >( !bBiff2, "choices" ); + out().resetItemIndex(); + for( sal_uInt16 nIdx = 0; nIdx < nCount; ++nIdx ) + dumpDec< sal_uInt16, sal_uInt8 >( !bBiff2, "#skip" ); + dumpDec< sal_uInt16, sal_uInt8 >( !bBiff2, "skip-err" ); + } + break; + case BIFF_TOK_ATTR_SKIP: + dumpDec< sal_uInt16, sal_uInt8 >( !bBiff2, "skip" ); + break; + case BIFF_TOK_ATTR_SUM: + dumpUnused( bBiff2 ? 1 : 2 ); + mxStack->pushFuncOp( CREATE_OUSTRING( "SUM" ), OUString( OOX_DUMP_BASECLASS ), 1 ); + break; + case BIFF_TOK_ATTR_ASSIGN: + dumpUnused( bBiff2 ? 1 : 2 ); + break; + case BIFF_TOK_ATTR_SPACE: + case BIFF_TOK_ATTR_SPACE | BIFF_TOK_ATTR_VOLATILE: + switch( getBiff() ) + { + case BIFF2: + bValid = false; + break; + case BIFF3: + dumpDec< sal_uInt16 >( "leading-spaces" ); + break; + case BIFF4: + case BIFF5: + case BIFF8: + dumpDec< sal_uInt8 >( "char-type", mxSpTypes ); + dumpDec< sal_uInt8 >( "char-count" ); + break; + case BIFF_UNKNOWN: break; + } + break; + default: + bValid = false; + } + return bValid; +} + +bool FormulaObject::dumpNlrToken() +{ + const OUString aRefClass = cfg().getName( mxClasses, BIFF_TOKCLASS_REF ); + const OUString aValClass = cfg().getName( mxClasses, BIFF_TOKCLASS_VAL ); + + bool bValid = true; + sal_uInt8 nType = dumpHex< sal_uInt8 >( "type", mxNlrTypes ); + switch( nType ) + { + case BIFF_TOK_NLR_ERR: dumpNlrErrToken(); break; + case BIFF_TOK_NLR_ROWR: dumpNlrColRowToken( aRefClass, false ); break; + case BIFF_TOK_NLR_COLR: dumpNlrColRowToken( aRefClass, false ); break; + case BIFF_TOK_NLR_ROWV: dumpNlrColRowToken( aValClass, false ); break; + case BIFF_TOK_NLR_COLV: dumpNlrColRowToken( aValClass, false ); break; + case BIFF_TOK_NLR_RANGE: dumpNlrRangeToken( aRefClass, false ); break; + case BIFF_TOK_NLR_SRANGE: dumpNlrRangeToken( aRefClass, true ); break; + case BIFF_TOK_NLR_SROWR: dumpNlrColRowToken( aRefClass, true ); break; + case BIFF_TOK_NLR_SCOLR: dumpNlrColRowToken( aRefClass, true ); break; + case BIFF_TOK_NLR_SROWV: dumpNlrColRowToken( aValClass, true ); break; + case BIFF_TOK_NLR_SCOLV: dumpNlrColRowToken( aValClass, true ); break; + case BIFF_TOK_NLR_RANGEERR: dumpNlrRangeErrToken(); break; + default: bValid = false; + } + return bValid; +} + +void FormulaObject::dumpNlrErrToken() +{ + dumpDec< sal_uInt32 >( "delname-idx" ); + mxStack->pushOperand( lclCreateNlr( getErrorName( BIFF_ERR_NAME ) ) ); +} + +void FormulaObject::dumpNlrColRowToken( const OUString& rTokClass, bool bAddData ) +{ + if( bAddData ) + { + dumpUnused( 4 ); + mxStack->pushOperand( createPlaceHolder(), rTokClass ); + maAddData.push_back( ADDDATA_NLR ); + } + else + { + TokenAddress aPos = dumpTokenAddress( false ); + writeInfoItem( "addr", lclCreateNlr( aPos ) ); + mxStack->pushOperand( out().getLastItemValue(), rTokClass ); + } +} + +void FormulaObject::dumpNlrRangeToken( const OUString& rTokClass, bool bAddData ) +{ + if( bAddData ) + { + dumpUnused( 4 ); + mxStack->pushOperand( createPlaceHolder(), rTokClass ); + maAddData.push_back( ADDDATA_NLR ); + } + else + { + TokenAddress aPos = dumpTokenAddress( false ); + writeInfoItem( "addr", lclCreateNlr( aPos ) ); + mxStack->pushOperand( out().getLastItemValue(), rTokClass ); + } + dumpUnknown( 1 ); + dumpRange( "target-range" ); +} + +void FormulaObject::dumpNlrRangeErrToken() +{ + dumpDec< sal_uInt32 >( "delname-idx" ); + dumpUnused( 9 ); + mxStack->pushOperand( lclCreateNlr( getErrorName( BIFF_ERR_NAME ) ) ); +} + +void FormulaObject::dumpAddTokenData() +{ + Output& rOut = out(); + rOut.resetItemIndex(); + for( AddDataTypeVec::const_iterator aIt = maAddData.begin(), aEnd = maAddData.end(); aIt != aEnd; ++aIt ) + { + AddDataType eType = *aIt; + + { + ItemGuard aItem( rOut, "#add-data" ); + switch( eType ) + { + case ADDDATA_NLR: rOut.writeAscii( "tNlr" ); break; + case ADDDATA_ARRAY: rOut.writeAscii( "tArray" ); break; + case ADDDATA_MEMAREA: rOut.writeAscii( "tMemArea" ); break; + } + } + + size_t nIdx = aIt - maAddData.begin(); + IndentGuard aIndGuard( rOut ); + switch( eType ) + { + case ADDDATA_NLR: dumpAddDataNlr( nIdx ); break; + case ADDDATA_ARRAY: dumpAddDataArray( nIdx ); break; + case ADDDATA_MEMAREA: dumpAddDataMemArea( nIdx ); break; + } + } +} + +void FormulaObject::dumpAddDataNlr( size_t nIdx ) +{ + sal_uInt32 nFlags = dumpHex< sal_uInt32 >( "flags", "NLRADDFLAGS" ); + sal_uInt32 nCount = nFlags & BIFF_TOK_NLR_ADDMASK; + OUStringBuffer aBuffer; + for( sal_uInt32 nPos = 0; nPos < nCount; ++nPos ) + { + Address aPos; + readAddress( aPos ); + OUStringBuffer aAddr; + StringHelper::appendAddress( aAddr, aPos ); + StringHelper::appendToken( aBuffer, aAddr.makeStringAndClear(), OOX_DUMP_LISTSEP ); + } + OUString aAddrList = aBuffer.makeStringAndClear(); + writeInfoItem( "stacked-positions", aAddrList ); + mxStack->replaceOnTop( createPlaceHolder( nIdx ), lclCreateNlr( aAddrList ) ); +} + +void FormulaObject::dumpAddDataArray( size_t nIdx ) +{ + sal_uInt32 nCols, nRows; + dumpConstArrayHeader( nCols, nRows ); + + OUStringBuffer aOp; + TableGuard aTabGuard( out(), 17 ); + for( sal_uInt32 nRow = 0; nRow < nRows; ++nRow ) + { + OUStringBuffer aArrayLine; + for( sal_uInt32 nCol = 0; nCol < nCols; ++nCol ) + StringHelper::appendToken( aArrayLine, dumpConstValue(), OOX_DUMP_LISTSEP ); + StringHelper::appendToken( aOp, aArrayLine.makeStringAndClear(), OOX_DUMP_ARRAYSEP ); + } + StringHelper::enclose( aOp, '{', '}' ); + mxStack->replaceOnTop( createPlaceHolder( nIdx ), aOp.makeStringAndClear() ); +} + +void FormulaObject::dumpAddDataMemArea( size_t /*nIdx*/ ) +{ + dumpRangeList( 0, getBiff() == BIFF8 ); +} + +// ============================================================================ +// ============================================================================ + +RecordHeaderObject::RecordHeaderObject( const InputObjectBase& rParent, BiffInputStream& rStrm ) : + mrStrm( rStrm ) +{ + static const RecordHeaderConfigInfo saHeaderCfgInfo = + { + "REC", + "RECORD-NAMES", + "show-record-pos", + "show-record-size", + "show-record-id", + "show-record-name", + "show-record-body", + }; + RecordHeaderBase< sal_uInt16, sal_uInt32 >::construct( rParent, saHeaderCfgInfo ); + if( RecordHeaderBase< sal_uInt16, sal_uInt32 >::implIsValid() ) + mbMergeContRec = cfg().getBoolOption( "merge-continue-record", true ); +} + +bool RecordHeaderObject::implReadHeader( sal_Int64& ornRecPos, sal_uInt16& ornRecId, sal_uInt32& ornRecSize ) +{ + // previous record + switch( mrStrm.getRecId() ) + { + case BIFF_ID_CHBEGIN: + out().incIndent(); + break; + } + + // start next record + bool bValidRec = mrStrm.startNextRecord(); + ornRecPos = mrStrm.getCoreStreamPos() - 4; + ornRecId = mrStrm.getRecId(); + + // record specific settings + switch( ornRecId ) + { + case BIFF_ID_CHEND: + out().decIndent(); + break; + } + + // special CONTINUE handling + mrStrm.resetRecord( mbMergeContRec ); + if( mbMergeContRec ) switch( ornRecId ) + { + case BIFF_ID_OBJ: + case BIFF_ID_TXO: + case BIFF_ID_EOF: + case BIFF_ID_CONT: + mrStrm.resetRecord( false ); + break; + case BIFF_ID_MSODRAWINGGROUP: + case BIFF_ID_CHESCHERFORMAT: + mrStrm.resetRecord( true, ornRecId ); + break; + } + + ornRecSize = mrStrm.getRecSize(); + return bValidRec; +} + +// ============================================================================ + +RecordStreamObject::~RecordStreamObject() +{ +} + +void RecordStreamObject::construct( const ObjectBase& rParent, const OUString& rOutFileName, BinaryInputStreamRef xStrm, BiffType eBiff ) +{ + BiffObjectBase::construct( rParent, rOutFileName, xStrm, eBiff ); + if( BiffObjectBase::implIsValid() ) + { + mxHdrObj.reset( new RecordHeaderObject( *this, getBiffStream() ) ); + mxFmlaObj.reset( new FormulaObject( *this ) ); + mxDffObj.reset( new DffDumpObject( *this ) ); + mxSimpleRecs = cfg().getNameList( "SIMPLE-RECORDS" ); + } +} + +bool RecordStreamObject::implIsValid() const +{ + return isValid( mxHdrObj ) && isValid( mxFmlaObj ) && isValid( mxDffObj ) && BiffObjectBase::implIsValid(); +} + +void RecordStreamObject::implDump() +{ + while( mxHdrObj->startNextRecord() ) + { + if( mxHdrObj->isShowRecBody() ) + { + IndentGuard aIndGuard( out() ); + if( mxHdrObj->hasRecName() ) + dumpRecordBody(); + else + dumpRawBinary( mxHdrObj->getRecSize(), false ); + if( !getBiffStream().isValid() ) + writeInfoItem( "stream-state", OOX_DUMP_ERR_STREAM ); + } + out().emptyLine(); + } +} + +void RecordStreamObject::implDumpRecord() +{ +} + +sal_uInt16 RecordStreamObject::dumpRepeatedRecId() +{ + return dumpHex< sal_uInt16 >( "repeated-rec-id", mxHdrObj->getRecNames() ); +} + +void RecordStreamObject::dumpRecordBody() +{ + BiffInputStream& rStrm = getBiffStream(); + sal_uInt16 nRecId = rStrm.getRecId(); + if( cfg().hasName( mxSimpleRecs, nRecId ) ) + dumpSimpleRecord( cfg().getName( mxSimpleRecs, nRecId ) ); + else + implDumpRecord(); + // remaining undumped data + if( rStrm.getRecPos() == 0 ) + dumpRawBinary( rStrm.getRecSize(), false ); + else + dumpRemaining( rStrm.getRecLeft() ); +} + +void RecordStreamObject::dumpSimpleRecord( const OUString& rRecData ) +{ + ItemFormat aItemFmt; + aItemFmt.parse( rRecData ); + dumpItem( aItemFmt ); +} + +// ============================================================================ + +WorkbookStreamObject::WorkbookStreamObject( const ObjectBase& rParent, const OUString& rOutFileName, BinaryInputStreamRef xStrm ) +{ + construct( rParent, rOutFileName, xStrm ); +} + +WorkbookStreamObject::~WorkbookStreamObject() +{ + if( WorkbookStreamObject::implIsValid() ) + { + Config& rCfg = cfg(); + rCfg.eraseNameList( "FONTNAMES" ); + rCfg.eraseNameList( "FORMATS" ); + } +} + +void WorkbookStreamObject::construct( const ObjectBase& rParent, const OUString& rOutFileName, BinaryInputStreamRef xStrm ) +{ + if( xStrm.get() ) + { + BiffType eBiff = BiffDetector::detectStreamBiffVersion( *xStrm ); + RecordStreamObject::construct( rParent, rOutFileName, xStrm, eBiff ); + if( RecordStreamObject::implIsValid() ) + { + Config& rCfg = cfg(); + mxColors = rCfg.getNameList( "COLORS" ); + mxBorderStyles = rCfg.getNameList( "BORDERSTYLES" ); + mxFillPatterns = rCfg.getNameList( "FILLPATTERNS" ); + mxFontNames = rCfg.createNameList< ConstList >( "FONTNAMES" ); + mxFontNames->setName( 0, createFontName( CREATE_OUSTRING( "Arial" ), 200, false, false ) ); + mxFormats = rCfg.createNameList< ConstList >( "FORMATS" ); + mxFormats->includeList( rCfg.getNameList( "BUILTIN-FORMATS" ) ); + mnFormatIdx = 0; + mnPTRowFields = 0; + mnPTColFields = 0; + mnPTSxliIdx = 0; + mbHasCodePage = false; + } + } +} + +void WorkbookStreamObject::implDumpRecord() +{ + BiffInputStream& rStrm = getBiffStream(); + sal_uInt16 nRecId = rStrm.getRecId(); + sal_Size nRecSize = rStrm.getRecSize(); + BiffType eBiff = getBiff(); + + switch( nRecId ) + { + case BIFF2_ID_ARRAY: + case BIFF3_ID_ARRAY: + dumpRange( "array-range", false ); + dumpHex< sal_uInt16, sal_uInt8 >( eBiff != BIFF2, "flags", "ARRAY-FLAGS" ); + if( eBiff >= BIFF5 ) dumpUnused( 4 ); + getFormulaDumper().dumpCellFormula(); + break; + + case BIFF2_ID_BLANK: + case BIFF3_ID_BLANK: + dumpCellHeader( nRecId == BIFF2_ID_BLANK ); + break; + + case BIFF2_ID_BOF: + case BIFF3_ID_BOF: + case BIFF4_ID_BOF: + case BIFF5_ID_BOF: + dumpHex< sal_uInt16 >( "bof-type", "BOF-BIFFTYPE" ); + dumpHex< sal_uInt16 >( "sheet-type", "BOF-SHEETTYPE" ); + if( nRecSize >= 6 ) dumpDec< sal_uInt16 >( "build-id" ); + if( nRecSize >= 8 ) dumpDec< sal_uInt16 >( "build-year" ); + if( nRecSize >= 12 ) dumpHex< sal_uInt32 >( "history-flags", "BOF-HISTORY-FLAGS" ); + if( nRecSize >= 16 ) dumpDec< sal_uInt32 >( "lowest-ver" ); + break; + + case BIFF2_ID_BOOLERR: + case BIFF3_ID_BOOLERR: + dumpCellHeader( nRecId == BIFF2_ID_BOOLERR ); + dumpBoolErr(); + break; + + case BIFF_ID_CFHEADER: + dumpDec< sal_uInt16 >( "rule-count" ); + dumpBool< sal_uInt16 >( "need-update" ); + dumpRange( "bounding-range" ); + dumpRangeList(); + break; + + case BIFF_ID_CFRULE: + { + dumpDec< sal_uInt8 >( "type", "CFRULE-TYPE" ); + dumpDec< sal_uInt8 >( "operator", "CFRULE-OPERATOR" ); + sal_uInt16 nFmla1Size = dumpDec< sal_uInt16 >( "formula1-size" ); + sal_uInt16 nFmla2Size = dumpDec< sal_uInt16 >( "formula2-size" ); + sal_uInt32 nFlags = dumpHex< sal_uInt32 >( "flags", "CFRULE-FLAGS" ); + dumpUnused( 2 ); + if( getFlag< sal_uInt32 >( nFlags, 0x04000000 ) ) + { + writeEmptyItem( "font-block" ); + IndentGuard aIndGuard( out() ); + sal_uInt32 nRecPos = rStrm.getRecPos(); + dumpUniString( "name", BIFF_STR_8BITLENGTH ); + dumpUnused( nRecPos + 64 - rStrm.getRecPos() ); + dumpDec< sal_Int32 >( "height", "CONV-TWIP-TO-PT" ); + dumpHex< sal_uInt32 >( "flags", "CFRULE-FONTFLAGS" ); + dumpDec< sal_uInt16 >( "weight", "FONT-WEIGHT" ); + dumpDec< sal_uInt16 >( "escapement", "FONT-ESCAPEMENT" ); + dumpDec< sal_uInt8 >( "underline", "FONT-UNDERLINE" ); + dumpUnused( 3 ); // family/charset? + dumpDec< sal_Int32 >( "color", mxColors ); + dumpUnused( 4 ); + dumpHex< sal_uInt32 >( "used-flags", "CFRULE-FONTUSEDFLAGS" ); + dumpDec< sal_uInt32 >( "escapement-used", "CFRULE-FONTUSED" ); + dumpDec< sal_uInt32 >( "underline-used", "CFRULE-FONTUSED" ); + dumpUnused( 18 ); + } + if( getFlag< sal_uInt32 >( nFlags, 0x08000000 ) ) + { + writeEmptyItem( "alignment-block" ); + IndentGuard aIndGuard( out() ); + dumpHex< sal_uInt8 >( "alignent", "CFRULE-ALIGNMENT" ); + dumpHex< sal_uInt8 >( "rotation", "TEXTROTATION" ); + dumpHex< sal_uInt16 >( "indent", "CFRULE-INDENT" ); + dumpDec< sal_uInt16 >( "relative-indent" ); + dumpUnknown( 2 ); + } + if( getFlag< sal_uInt32 >( nFlags, 0x10000000 ) ) + { + writeEmptyItem( "border-block" ); + IndentGuard aIndGuard( out() ); + dumpHex< sal_uInt16 >( "border-style", "XF-BORDERSTYLE" ); + dumpHex< sal_uInt16 >( "border-color1", "XF-BORDERCOLOR1" ); + dumpHex< sal_uInt32 >( "border-color2", "CFRULE-BORDERCOLOR2" ); + } + if( getFlag< sal_uInt32 >( nFlags, 0x20000000 ) ) + { + writeEmptyItem( "pattern-block" ); + IndentGuard aIndGuard( out() ); + dumpHex< sal_uInt32 >( "pattern", "CFRULE-FILLBLOCK" ); + } + if( getFlag< sal_uInt32 >( nFlags, 0x40000000 ) ) + { + writeEmptyItem( "protection-block" ); + IndentGuard aIndGuard( out() ); + dumpHex< sal_uInt16 >( "flags", "CFRULE-PROTECTION-FLAGS" ); + } + if( nFmla1Size > 0 ) + getFormulaDumper().dumpNameFormula( "formula1", nFmla1Size ); + if( nFmla2Size > 0 ) + getFormulaDumper().dumpNameFormula( "formula2", nFmla2Size ); + } + break; + + case BIFF_ID_CH3DDATAFORMAT: + dumpDec< sal_uInt8 >( "base", "CH3DDATAFORMAT-BASE" ); + dumpDec< sal_uInt8 >( "top", "CH3DDATAFORMAT-TOP" ); + break; + + case BIFF_ID_CHAREAFORMAT: + dumpRgbColor( "fg-color-rgb" ); + dumpRgbColor( "bg-color-rgb" ); + dumpPatternIdx(); + dumpHex< sal_uInt16 >( "flags", "CHAREAFORMAT-FLAGS" ); + if( eBiff == BIFF8 ) dumpColorIdx( "fg-color-idx" ); + if( eBiff == BIFF8 ) dumpColorIdx( "bg-color-idx" ); + break; + + case BIFF_ID_CHAXESSET: + dumpDec< sal_uInt16 >( "axesset-id", "CHAXESSET-ID" ); + dumpRect< sal_Int32 >( "position", (eBiff <= BIFF4) ? "CONV-TWIP-TO-CM" : "" ); + break; + + case BIFF_ID_CHAXIS: + dumpDec< sal_uInt16 >( "axis-type", "CHAXIS-TYPE" ); + if( eBiff <= BIFF4 ) + dumpRect< sal_Int32 >( "position", "CONV-TWIP-TO-CM" ); + else + dumpUnused( 16 ); + break; + + case BIFF_ID_CHBAR: + dumpDec< sal_Int16 >( "overlap", "CONV-PERCENT-NEG" ); + dumpDec< sal_Int16 >( "gap", "CONV-PERCENT" ); + dumpHex< sal_uInt16 >( "flags", "CHBAR-FLAGS" ); + break; + + case BIFF_ID_CHCHART: + dumpRect< sal_Int32 >( "chart-frame", "CONV-PT1616-TO-CM", FORMATTYPE_FIX ); + break; + + case BIFF_ID_CHCHART3D: + dumpDec< sal_uInt16 >( "rotation-angle", "CONV-DEG" ); + dumpDec< sal_Int16 >( "elevation-angle", "CONV-DEG" ); + dumpDec< sal_uInt16 >( "eye-distance" ); + dumpDec< sal_uInt16 >( "relative-height", "CONV-PERCENT" ); + dumpDec< sal_uInt16 >( "relative-depth", "CONV-PERCENT" ); + dumpDec< sal_uInt16 >( "depth-gap", "CONV-PERCENT" ); + dumpHex< sal_uInt16 >( "flags", "CHCHART3D-FLAGS" ); + break; + + case BIFF_ID_CHTYPEGROUP: + dumpUnused( 16 ); + dumpHex< sal_uInt16 >( "flags", "CHTYPEGROUP-FLAGS" ); + if( eBiff >= BIFF5 ) dumpDec< sal_uInt16 >( "group-idx" ); + break; + + case BIFF_ID_CHDATAFORMAT: + dumpDec< sal_Int16 >( "point-idx", "CHDATAFORMAT-POINTIDX" ); + dumpDec< sal_Int16 >( "series-idx" ); + if( eBiff >= BIFF5 ) dumpDec< sal_Int16 >( "format-idx", "CHDATAFORMAT-FORMATIDX" ); + if( eBiff >= BIFF5 ) dumpHex< sal_uInt16 >( "flags", "CHDATAFORMAT-FLAGS" ); + break; + + case BIFF_ID_CHESCHERFORMAT: + getDffDumper().dump(); + break; + + case BIFF_ID_CHFRAME: + dumpDec< sal_uInt16 >( "format", "CHFRAME-FORMAT" ); + dumpHex< sal_uInt16 >( "flags", "CHFRAME-FLAGS" ); + break; + + case BIFF_ID_CHFRAMEPOS: + dumpDec< sal_uInt16 >( "object-type", "CHFRAMEPOS-OBJTYPE" ); + dumpDec< sal_uInt16 >( "size-mode", "CHFRAMEPOS-SIZEMODE" ); + dumpRect< sal_Int32 >( "position", (eBiff <= BIFF4) ? "CONV-TWIP-TO-CM" : "" ); + break; + + case BIFF_ID_CHLABELRANGE: + dumpDec< sal_uInt16 >( "axis-crossing" ); + dumpDec< sal_uInt16 >( "label-frequency" ); + dumpDec< sal_uInt16 >( "tick-frequency" ); + dumpHex< sal_uInt16 >( "flags", "CHLABELRANGE-FLAGS" ); + break; + + case BIFF_ID_CHLABELRANGE2: + dumpDec< sal_uInt16 >( "minimum-categ" ); + dumpDec< sal_uInt16 >( "maximum-categ" ); + dumpDec< sal_uInt16 >( "major-unit-value" ); + dumpDec< sal_uInt16 >( "major-unit" ); + dumpDec< sal_uInt16 >( "minor-unit-value" ); + dumpDec< sal_uInt16 >( "minor-unit" ); + dumpDec< sal_uInt16 >( "base-unit" ); + dumpDec< sal_uInt16 >( "axis-crossing-date" ); + dumpHex< sal_uInt16 >( "flags", "CHLABELRANGE2-FLAGS" ); + break; + + case BIFF_ID_CHLEGEND: + dumpRect< sal_Int32 >( "position", (eBiff <= BIFF4) ? "CONV-TWIP-TO-CM" : "" ); + dumpDec< sal_uInt8 >( "docked-pos", "CHLEGEND-DOCKPOS" ); + dumpDec< sal_uInt8 >( "spacing", "CHLEGEND-SPACING" ); + dumpHex< sal_uInt16 >( "flags", "CHLEGEND-FLAGS" ); + break; + + case BIFF_ID_CHLINEFORMAT: + dumpRgbColor(); + dumpDec< sal_uInt16 >( "line-type", "CHLINEFORMAT-LINETYPE" ); + dumpDec< sal_Int16 >( "line-weight", "CHLINEFORMAT-LINEWEIGHT" ); + dumpHex< sal_uInt16 >( "flags", "CHLINEFORMAT-FLAGS" ); + if( eBiff == BIFF8 ) dumpColorIdx(); + break; + + case BIFF_ID_CHMARKERFORMAT: + dumpRgbColor( "border-color-rgb" ); + dumpRgbColor( "fill-color-rgb" ); + dumpDec< sal_uInt16 >( "marker-type", "CHMARKERFORMAT-TYPE" ); + dumpHex< sal_uInt16 >( "flags", "CHMARKERFORMAT-FLAGS" ); + if( eBiff == BIFF8 ) dumpColorIdx( "border-color-idx" ); + if( eBiff == BIFF8 ) dumpColorIdx( "fill-color-idx" ); + if( eBiff == BIFF8 ) dumpDec< sal_Int32 >( "marker-size", "CONV-TWIP-TO-PT" ); + break; + + case BIFF_ID_CHOBJECTLINK: + dumpDec< sal_uInt16 >( "link-target", "CHOBJECTLINK-TARGET" ); + dumpDec< sal_Int16 >( "series-idx" ); + dumpDec< sal_Int16 >( "point-idx", "CHOBJECTLINK-POINT" ); + break; + + case BIFF_ID_CHPICFORMAT: + dumpDec< sal_uInt16 >( "bitmap-mode", "CHPICFORMAT-BITMAP-MODE" ); + dumpDec< sal_uInt16 >( "image-format", "CHPICFORMAT-IMAGE-FORMAT" ); + dumpHex< sal_uInt16 >( "flags", "CHPICFORMAT-FLAGS" ); + dumpDec< double >( "scaling-factor" ); + break; + + case BIFF_ID_CHPIE: + dumpDec< sal_uInt16 >( "angle", "CONV-DEG" ); + if( eBiff >= BIFF5 ) dumpDec< sal_uInt16 >( "hole-size" ); + if( eBiff >= BIFF8 ) dumpHex< sal_uInt16 >( "flags", "CHPIE-FLAGS" ); + break; + + case BIFF_ID_CHPLOTGROWTH: + dumpFix< sal_Int32 >( "horizontal-growth" ); + dumpFix< sal_Int32 >( "vertical-growth" ); + break; + + case BIFF_ID_CHPROPERTIES: + dumpHex< sal_uInt16 >( "flags", "CHPROPERTIES-FLAGS" ); + dumpDec< sal_uInt8 >( "empty-cells", "CHPROPERTIES-EMPTYCELLS" ); + break; + + case BIFF_ID_CHSCATTER: + if( eBiff == BIFF8 ) dumpDec< sal_uInt16 >( "bubble-size", "CONV-PERCENT" ); + if( eBiff == BIFF8 ) dumpDec< sal_uInt16 >( "size-type", "CHSCATTER-SIZETYPE" ); + if( eBiff == BIFF8 ) dumpHex< sal_uInt16 >( "flags", "CHSCATTER-FLAGS" ); + break; + + case BIFF_ID_CHSERERRORBAR: + dumpDec< sal_uInt8 >( "type", "CHSERERRORBAR-TYPE" ); + dumpDec< sal_uInt8 >( "source", "CHSERERRORBAR-SOURCE" ); + dumpBool< sal_uInt8 >( "draw-t-shape" ); + dumpBool< sal_uInt8 >( "draw-line" ); + dumpDec< double >( "value" ); + dumpDec< sal_uInt16 >( "custom-count" ); + break; + + case BIFF_ID_CHSERIES: + dumpDec< sal_uInt16 >( "categories-type", "CHSERIES-TYPE" ); + dumpDec< sal_uInt16 >( "values-type", "CHSERIES-TYPE" ); + dumpDec< sal_uInt16 >( "categories-count" ); + dumpDec< sal_uInt16 >( "values-count" ); + if( eBiff == BIFF8 ) dumpDec< sal_uInt16 >( "bubbles-type", "CHSERIES-TYPE" ); + if( eBiff == BIFF8 ) dumpDec< sal_uInt16 >( "bubbles-count" ); + break; + + case BIFF_ID_CHSERTRENDLINE: + switch( dumpDec< sal_uInt8 >( "type", "CHSERTRENDLINE-TYPE" ) ) + { + case 0: dumpDec< sal_uInt8 >( "order" ); break; + case 4: dumpDec< sal_uInt8 >( "average-period" ); break; + default: dumpUnused( 1 ); + } + dumpDec< double >( "intercept" ); + dumpBool< sal_uInt8 >( "show-equation" ); + dumpBool< sal_uInt8 >( "show-r-sqrare" ); + dumpDec< double >( "forecast-forward" ); + dumpDec< double >( "forecast-backward" ); + break; + + case BIFF_ID_CHSOURCELINK: + dumpDec< sal_uInt8 >( "link-target", "CHSOURCELINK-TARGET" ); + dumpDec< sal_uInt8 >( "link-type", "CHSOURCELINK-TYPE" ); + dumpHex< sal_uInt16 >( "flags", "CHSOURCELINK-FLAGS" ); + dumpFormatIdx(); + getFormulaDumper().dumpNameFormula(); + break; + + case BIFF_ID_CHSTRING: + dumpDec< sal_uInt16 >( "text-type", "CHSTRING-TYPE" ); + dumpString( "text", BIFF_STR_8BITLENGTH, BIFF_STR_8BITLENGTH ); + break; + + case BIFF_ID_CHTEXT: + dumpDec< sal_uInt8 >( "horizontal-align", "CHTEXT-HORALIGN" ); + dumpDec< sal_uInt8 >( "vertical-align", "CHTEXT-VERALIGN" ); + dumpDec< sal_uInt16 >( "fill-mode", "CHTEXT-FILLMODE" ); + dumpRgbColor(); + dumpRect< sal_Int32 >( "position", (eBiff <= BIFF4) ? "CONV-TWIP-TO-CM" : "" ); + dumpHex< sal_uInt16 >( "flags", "CHTEXT-FLAGS" ); + if( eBiff == BIFF8 ) dumpColorIdx(); + if( eBiff == BIFF8 ) dumpDec< sal_uInt16 >( "placement", "CHTEXT-PLACEMENT" ); + if( eBiff == BIFF8 ) dumpDec< sal_uInt16 >( "rotation", "TEXTROTATION" ); + break; + + case BIFF_ID_CHTICK: + dumpDec< sal_uInt8 >( "major-ticks", "CHTICK-TYPE" ); + dumpDec< sal_uInt8 >( "minor-ticks", "CHTICK-TYPE" ); + dumpDec< sal_uInt8 >( "label-position", "CHTICK-LABELPOS" ); + dumpDec< sal_uInt8 >( "fill-mode", "CHTEXT-FILLMODE" ); + dumpRgbColor( "label-color-rgb" ); + dumpUnused( 16 ); + dumpHex< sal_uInt16 >( "flags", "CHTICK-FLAGS" ); + if( eBiff == BIFF8 ) dumpColorIdx( "label-color-idx" ); + if( eBiff == BIFF8 ) dumpDec< sal_uInt16 >( "label-rotation", "TEXTROTATION" ); + break; + + case BIFF_ID_CHUNITPROPERTIES: + dumpRepeatedRecId(); + dumpUnused( 2 ); + dumpDec< sal_Int16 >( "preset", "CHUNITPROPERTIES-PRESET" ); + dumpDec< double >( "unit" ); + dumpHex< sal_uInt16 >( "flags", "CHUNITPROPERTIES-FLAGS" ); + break; + + case BIFF_ID_CHVALUERANGE: + dumpDec< double >( "minimum" ); + dumpDec< double >( "maximum" ); + dumpDec< double >( "major-inc" ); + dumpDec< double >( "minor-inc" ); + dumpDec< double >( "axis-crossing" ); + dumpHex< sal_uInt16 >( "flags", "CHVALUERANGE-FLAGS" ); + break; + + case BIFF_ID_CHWRAPPEDRECORD: + dumpRepeatedRecId(); + dumpUnused( 2 ); + break; + + case BIFF_ID_CODENAME: + dumpUniString( "codename" ); + break; + + case BIFF_ID_CODEPAGE: + getBiffData().setTextEncoding( dumpCodePage() ); + mbHasCodePage = true; + break; + + case BIFF_ID_COLINFO: + dumpColRange(); + dumpDec< sal_uInt16 >( "col-width", "CONV-COLWIDTH" ); + dumpXfIdx( "xf-idx" ); + dumpHex< sal_uInt16 >( "flags", "COLINFO-FLAGS" ); + dumpUnused( 2 ); + break; + + case BIFF_ID_COLUMNDEFAULT: + out().resetItemIndex(); + for( sal_Int32 nCol = 0, nCount = dumpColRange(); nCol < nCount; ++nCol ) + dumpXfIdx( "#xf-idx", true ); + dumpUnused( 2 ); + break; + + case BIFF_ID_COLWIDTH: + dumpColRange( 0, false ); + dumpDec< sal_uInt16 >( "col-width", "CONV-COLWIDTH" ); + break; + + case BIFF_ID_CRN: + { + sal_Int32 nCol2 = dumpColIndex( "last-col-idx", false ); + sal_Int32 nCol1 = dumpColIndex( "first-col-idx", false ); + sal_Int32 nRow = dumpRowIndex( "row-idx" ); + TableGuard aTabGuard( out(), 14, 17 ); + for( Address aPos( nCol1, nRow ); rStrm.isValid() && (aPos.mnCol <= nCol2); ++aPos.mnCol ) + { + MultiItemsGuard aMultiGuard( out() ); + writeAddressItem( "pos", aPos ); + dumpConstValue(); + } + } + break; + + case BIFF_ID_DCONNAME: + dumpString( "source-name", BIFF_STR_8BITLENGTH ); + dumpString( "source-link", BIFF_STR_8BITLENGTH ); + break; + + case BIFF_ID_DCONREF: + dumpRange( "source-range", false ); + dumpString( "source-link", BIFF_STR_8BITLENGTH ); + break; + + case BIFF2_ID_DATATABLE: + dumpRange( "table-range", false ); + dumpBoolean( "recalc-always" ); + dumpBoolean( "row-table" ); + dumpAddress( "ref1" ); + break; + + case BIFF3_ID_DATATABLE: + dumpRange( "table-range", false ); + dumpHex< sal_uInt16 >( "flags", "DATATABLE-FLAGS" ); + dumpAddress( "ref1" ); + dumpAddress( "ref2" ); + break; + + case BIFF2_ID_DATATABLE2: + dumpRange( "table-range", false ); + dumpBoolean( "recalc-always" ); + dumpUnused( 1 ); + dumpAddress( "ref1" ); + dumpAddress( "ref2" ); + break; + + case BIFF_ID_DATAVALIDATION: + { + dumpHex< sal_uInt32 >( "flags", "DATAVALIDATION-FLAGS" ); + dumpUniString( "input-title" ); + dumpUniString( "error-title" ); + dumpUniString( "input-message" ); + dumpUniString( "error-message" ); + sal_uInt16 nFmla1Size = getFormulaDumper().dumpFormulaSize( "formula1-size" ); + dumpUnused( 2 ); + if( nFmla1Size > 0 ) + getFormulaDumper().dumpNameFormula( "formula1", nFmla1Size ); + sal_uInt16 nFmla2Size = getFormulaDumper().dumpFormulaSize( "formula2-size" ); + dumpUnused( 2 ); + if( nFmla2Size > 0 ) + getFormulaDumper().dumpNameFormula( "formula2", nFmla2Size ); + dumpRangeList(); + } + break; + + case BIFF_ID_DATAVALIDATIONS: + dumpHex< sal_uInt16 >( "flags", "DATAVALIDATIONS-FLAGS" ); + dumpDec< sal_Int32 >( "input-box-pos-x" ); + dumpDec< sal_Int32 >( "input-box-pos-y" ); + dumpDec< sal_Int32 >( "dropdown-object-id" ); + dumpDec< sal_Int32 >( "dval-entry-count" ); + break; + + case BIFF2_ID_DEFINEDNAME: + case BIFF3_ID_DEFINEDNAME: + { + dumpHex< sal_uInt16, sal_uInt8 >( eBiff != BIFF2, "flags", "DEFINEDNAME-FLAGS" ); + if( eBiff == BIFF2 ) dumpDec< sal_uInt8 >( "macro-type", "DEFINEDNAME-MACROTYPE-BIFF2" ); + dumpHex< sal_uInt8 >( "keyboard-shortcut" ); + sal_uInt8 nNameLen = dumpDec< sal_uInt8 >( "name-len" ); + sal_uInt16 nFmlaSize = getFormulaDumper().dumpFormulaSize(); + rtl_TextEncoding eTextEnc = getBiffData().getTextEncoding(); + if( eBiff >= BIFF5 ) + { + bool bBiff8 = eBiff == BIFF8; + if( bBiff8 ) dumpUnused( 2 ); else dumpDec< sal_uInt16 >( "externsheet-idx", "DEFINEDNAME-SHEETIDX" ); + dumpDec< sal_uInt16 >( "sheet-idx", "DEFINEDNAME-SHEETIDX" ); + sal_uInt8 nMenuLen = dumpDec< sal_uInt8 >( "menu-text-len" ); + sal_uInt8 nDescrLen = dumpDec< sal_uInt8 >( "description-text-len" ); + sal_uInt8 nHelpLen = dumpDec< sal_uInt8 >( "help-text-len" ); + sal_uInt8 nStatusLen = dumpDec< sal_uInt8 >( "statusbar-text-len" ); + writeStringItem( "name", bBiff8 ? rStrm.readUniString( nNameLen ) : rStrm.readCharArray( nNameLen, eTextEnc ) ); + getFormulaDumper().dumpNameFormula( 0, nFmlaSize ); + if( nMenuLen > 0 ) writeStringItem( "menu-text", bBiff8 ? rStrm.readUniString( nMenuLen ) : rStrm.readCharArray( nMenuLen, eTextEnc ) ); + if( nDescrLen > 0 ) writeStringItem( "description-text", bBiff8 ? rStrm.readUniString( nDescrLen ) : rStrm.readCharArray( nDescrLen, eTextEnc ) ); + if( nHelpLen > 0 ) writeStringItem( "help-text", bBiff8 ? rStrm.readUniString( nHelpLen ) : rStrm.readCharArray( nHelpLen, eTextEnc ) ); + if( nStatusLen > 0 ) writeStringItem( "statusbar-text", bBiff8 ? rStrm.readUniString( nStatusLen ) : rStrm.readCharArray( nStatusLen, eTextEnc ) ); + } + else + { + writeStringItem( "name", rStrm.readCharArray( nNameLen, eTextEnc ) ); + getFormulaDumper().dumpNameFormula( 0, nFmlaSize ); + if( eBiff == BIFF2 ) getFormulaDumper().dumpFormulaSize(); + } + } + break; + + case BIFF3_ID_DEFROWHEIGHT: + dumpHex< sal_uInt16 >( "flags", "DEFROWHEIGHT-FLAGS" ); + dumpDec< sal_uInt16 >( "row-height", "CONV-TWIP-TO-PT" ); + break; + + case BIFF2_ID_DIMENSION: + case BIFF3_ID_DIMENSION: + dumpRange( "used-area", true, (nRecId == BIFF3_ID_DIMENSION) && (eBiff == BIFF8) ); + if( nRecId == BIFF3_ID_DIMENSION ) dumpUnused( 2 ); + break; + + case BIFF_ID_EXTERNALBOOK: + { + sal_uInt16 nCount = dumpDec< sal_uInt16 >( "sheet-count" ); + if( rStrm.getRecLeft() == 2 ) + dumpHex< sal_uInt16 >( "special-key", "EXTERNALBOOK-KEY" ); + else + { + dumpString( "workbook-url" ); + out().resetItemIndex(); + for( sal_uInt16 nSheet = 0; rStrm.isValid() && (nSheet < nCount); ++nSheet ) + dumpString( "#sheet-name" ); + } + } + break; + + case BIFF2_ID_EXTERNALNAME: + case BIFF3_ID_EXTERNALNAME: + { + sal_uInt16 nFlags = (eBiff >= BIFF3) ? dumpHex< sal_uInt16 >( "flags", "EXTERNALNAME-FLAGS" ) : 0; + if( eBiff >= BIFF5 ) + { + if( getFlag< sal_uInt16 >( nFlags, 0x0010 ) ) + { + dumpHex< sal_uInt32 >( "storage-id" ); + } + else + { + dumpDec< sal_uInt16 >( "externsheet-idx" ); + dumpUnused( 2 ); + } + } + OUString aName = dumpString( "name", BIFF_STR_8BITLENGTH, BIFF_STR_8BITLENGTH ); + if( (aName.getLength() > 0) && (aName[ 0 ] == 1) && (rStrm.getRecLeft() >= 2) ) + getFormulaDumper().dumpNameFormula(); + } + break; + + case BIFF_ID_EXTERNSHEET: + if( eBiff == BIFF8 ) + { + sal_uInt16 nCount = dumpDec< sal_uInt16 >( "ref-count" ); + TableGuard aTabGuard( out(), 10, 17, 24 ); + out().resetItemIndex(); + for( sal_uInt16 nRefId = 0; rStrm.isValid() && (nRefId < nCount); ++nRefId ) + { + MultiItemsGuard aMultiGuard( out() ); + writeEmptyItem( "#ref" ); + dumpDec< sal_uInt16 >( "extbook-idx" ); + dumpDec< sal_Int16 >( "first-sheet", "EXTERNSHEET-IDX" ); + dumpDec< sal_Int16 >( "last-sheet", "EXTERNSHEET-IDX" ); + } + } + else + { + OStringBuffer aUrl( rStrm.readByteString( false ) ); + if( (aUrl.getLength() > 0) && (aUrl[ 0 ] == '\x03') ) + aUrl.append( static_cast< sal_Char >( rStrm.readuInt8() ) ); + writeStringItem( "encoded-url", OStringToOUString( aUrl.makeStringAndClear(), getBiffData().getTextEncoding() ) ); + } + break; + + case BIFF2_ID_FONT: + case BIFF3_ID_FONT: + dumpFontRec(); + break; + + case BIFF2_ID_FORMAT: + case BIFF4_ID_FORMAT: + dumpFormatRec(); + break; + + case BIFF2_ID_FORMULA: + case BIFF3_ID_FORMULA: + case BIFF4_ID_FORMULA: + dumpCellHeader( eBiff == BIFF2 ); + dumpFormulaResult(); + dumpHex< sal_uInt16, sal_uInt8 >( eBiff != BIFF2, "flags", "FORMULA-FLAGS" ); + if( eBiff >= BIFF5 ) dumpUnused( 4 ); + getFormulaDumper().dumpCellFormula(); + break; + + case BIFF_ID_FOOTER: + if( rStrm.getRecLeft() > 0 ) + dumpString( "footer", BIFF_STR_8BITLENGTH ); + break; + + case BIFF_ID_HEADER: + if( rStrm.getRecLeft() > 0 ) + dumpString( "header", BIFF_STR_8BITLENGTH ); + break; + + case BIFF_ID_HYPERLINK: + dumpRange(); + if( cfg().getStringOption( dumpGuid( "guid" ), OUString() ).equalsAscii( "StdHlink" ) ) + { + dumpUnknown( 4 ); + sal_uInt32 nFlags = dumpHex< sal_uInt32 >( "flags", "HYPERLINK-FLAGS" ); + if( getFlag( nFlags, BIFF_HYPERLINK_DISPLAY ) ) + dumpOleString( "display", true ); + if( getFlag( nFlags, BIFF_HYPERLINK_FRAME ) ) + dumpOleString( "target-frame", true ); + if( getFlag( nFlags, BIFF_HYPERLINK_TARGET ) ) + { + if( getFlag( nFlags, BIFF_HYPERLINK_UNC ) ) + { + dumpOleString( "unc-path", true ); + } + else + { + OUString aGuid = cfg().getStringOption( dumpGuid( "content-type" ), OUString() ); + if( aGuid.equalsAscii( "FileMoniker" ) ) + { + dumpDec< sal_Int16 >( "up-level" ); + dumpOleString( "dos-name", false ); + dumpUnknown( 24 ); + if( dumpDec< sal_Int32 >( "total-bytes" ) > 0 ) + { + sal_Int32 nBytes = dumpDec< sal_Int32 >( "filename-bytes" ); + dumpUnknown( 2 ); + dumpOleString( "filename", nBytes / 2, true ); + } + } + else if( aGuid.equalsAscii( "URLMoniker" ) ) + { + sal_Int32 nBytes = dumpDec< sal_Int32 >( "url-bytes" ); + dumpOleString( "url", nBytes / 2, true ); + } + } + } + if( getFlag( nFlags, BIFF_HYPERLINK_LOC ) ) + dumpOleString( "location", true ); + } + break; + + case BIFF2_ID_INTEGER: + dumpCellHeader( true ); + dumpDec< sal_uInt16 >( "value" ); + break; + + case BIFF2_ID_LABEL: + case BIFF3_ID_LABEL: + { + bool bBiff2 = nRecId == BIFF2_ID_LABEL; + sal_uInt16 nXfIdx = dumpCellHeader( bBiff2 ); + rtl_TextEncoding eOldTextEnc = getBiffData().getTextEncoding(); + getBiffData().setTextEncoding( getBiffData().getXfEncoding( nXfIdx ) ); + dumpString( "value", bBiff2 ? BIFF_STR_8BITLENGTH : BIFF_STR_DEFAULT ); + getBiffData().setTextEncoding( eOldTextEnc ); + } + break; + + case BIFF_ID_LABELRANGES: + dumpRangeList( "row-ranges" ); + dumpRangeList( "col-ranges" ); + break; + + case BIFF_ID_LABELSST: + dumpCellHeader(); + dumpDec< sal_Int32 >( "sst-idx" ); + break; + + case BIFF_ID_MSODRAWING: + case BIFF_ID_MSODRAWINGGROUP: + case BIFF_ID_MSODRAWINGSEL: + getDffDumper().dump(); + break; + + case BIFF_ID_MULTBLANK: + { + Address aPos = dumpAddress(); + { + TableGuard aTabGuard( out(), 12 ); + for( ; rStrm.getRecLeft() >= 4; ++aPos.mnCol ) + { + MultiItemsGuard aMultiGuard( out() ); + writeAddressItem( "pos", aPos ); + dumpXfIdx(); + } + } + dumpColIndex( "last-col-idx" ); + } + break; + + case BIFF_ID_MULTRK: + { + Address aPos = dumpAddress(); + { + TableGuard aTabGuard( out(), 12, 12 ); + for( ; rStrm.getRecLeft() >= 8; ++aPos.mnCol ) + { + MultiItemsGuard aMultiGuard( out() ); + writeAddressItem( "pos", aPos ); + dumpXfIdx(); + dumpRk( "value" ); + } + } + dumpColIndex( "last-col-idx" ); + } + break; + + case BIFF2_ID_NUMBER: + case BIFF3_ID_NUMBER: + dumpCellHeader( nRecId == BIFF2_ID_NUMBER ); + dumpDec< double >( "value" ); + break; + + case BIFF_ID_OBJ: + dumpObjRec(); + break; + + case BIFF_ID_PAGESETUP: + dumpDec< sal_uInt16 >( "paper-size", "PAGESETUP-PAPERSIZE" ); + dumpDec< sal_uInt16 >( "scaling", "CONV-PERCENT" ); + dumpDec< sal_uInt16 >( "first-page" ); + dumpDec< sal_uInt16 >( "scale-to-width", "PAGESETUP-SCALETOPAGES" ); + dumpDec< sal_uInt16 >( "scale-to-height", "PAGESETUP-SCALETOPAGES" ); + dumpHex< sal_uInt16 >( "flags", "PAGESETUP-FLAGS" ); + if( eBiff >= BIFF5 ) + { + dumpDec< sal_uInt16 >( "horizontal-res", "PAGESETUP-DPI" ); + dumpDec< sal_uInt16 >( "vertical-res", "PAGESETUP-DPI" ); + dumpDec< double >( "header-margin", "CONV-INCH-TO-CM" ); + dumpDec< double >( "footer-margin", "CONV-INCH-TO-CM" ); + dumpDec< sal_uInt16 >( "copies" ); + } + break; + + case BIFF_ID_PANE: + dumpDec< sal_uInt16 >( "x-pos", "CONV-TWIP-TO-CM" ); + dumpDec< sal_uInt16 >( "y-pos", "CONV-TWIP-TO-CM" ); + dumpAddress( "first-visible-cell" ); + dumpDec< sal_uInt8 >( "active-pane", "PANE-ID" ); + break; + + case BIFF_ID_PHONETICPR: + dumpDec< sal_uInt16 >( "font-id", "FONTNAMES" ); + dumpHex< sal_uInt16 >( "flags", "PHONETICPR-FLAGS" ); + dumpRangeList( "show-phonetic" ); + break; + + case BIFF_ID_PROJEXTSHEET: + dumpDec< sal_uInt8 >( "sheet-type", "PROJEXTSHEET-TYPE" ); + dumpUnused( 1 ); + dumpByteString( "sheet-link", BIFF_STR_8BITLENGTH ); + break; + + case BIFF_ID_RK: + dumpCellHeader(); + dumpRk( "value" ); + break; + + case BIFF2_ID_ROW: + { + dumpRowIndex(); + dumpColIndex( "first-used-col-idx" ); + dumpColIndex( "first-free-col-idx" ); + dumpHex< sal_uInt16 >( "height", "ROW-HEIGHT" ); + dumpUnused( 2 ); + bool bHasDefXf = dumpBool< sal_uInt8 >( "custom-format" ); + dumpDec< sal_uInt16 >( "cell-offset" ); + if( bHasDefXf ) dumpXfIdx( "custom-format", true ); + if( bHasDefXf ) dumpXfIdx( "custom-xf-idx", false ); + } + break; + + case BIFF3_ID_ROW: + dumpRowIndex(); + dumpColIndex( "first-used-col-idx" ); + dumpColIndex( "first-free-col-idx" ); + dumpHex< sal_uInt16 >( "height", "ROW-HEIGHT" ); + dumpUnused( (eBiff <= BIFF4) ? 2 : 4 ); + if( eBiff <= BIFF4 ) dumpDec< sal_uInt16 >( "cell-offset" ); + dumpHex< sal_uInt32 >( "flags", "ROW-FLAGS" ); + break; + + case BIFF_ID_RSTRING: + { + sal_uInt16 nXfIdx = dumpCellHeader(); + rtl_TextEncoding eOldTextEnc = getBiffData().getTextEncoding(); + getBiffData().setTextEncoding( getBiffData().getXfEncoding( nXfIdx ) ); + dumpString( "value" ); + getBiffData().setTextEncoding( eOldTextEnc ); + BinFontPortionList aPortions; + aPortions.importPortions( rStrm, eBiff == BIFF8 ); + writeFontPortions( aPortions ); + } + break; + + case BIFF_ID_SCL: + { + sal_uInt16 nNum = dumpDec< sal_uInt16 >( "numerator" ); + sal_uInt16 nDen = dumpDec< sal_uInt16 >( "denominator" ); + if( nDen > 0 ) writeDecItem( "current-zoom", static_cast< sal_uInt16 >( nNum * 100 / nDen ), "CONV-PERCENT" ); + } + break; + + case BIFF_ID_SCREENTIP: + dumpRepeatedRecId(); + dumpRange(); + dumpNullString( "tooltip", true ); + break; + + case BIFF_ID_SELECTION: + dumpDec< sal_uInt8 >( "pane", "PANE-ID" ); + dumpAddress( "active-cell" ); + dumpDec< sal_uInt16 >( "list-idx" ); + dumpRangeList( "selection", false ); + break; + + case BIFF_ID_SHAREDFMLA: + dumpRange( "formula-range", false ); + dumpUnused( 1 ); + dumpDec< sal_uInt8 >( "cell-count" ); + getFormulaDumper().dumpCellFormula(); + break; + + case BIFF_ID_SHEET: + if( eBiff >= BIFF5 ) dumpHex< sal_uInt32 >( "sheet-stream-pos", "CONV-DEC" ); + if( eBiff >= BIFF5 ) dumpDec< sal_uInt8 >( "sheet-state", "SHEET-STATE" ); + if( eBiff >= BIFF5 ) dumpDec< sal_uInt8 >( "sheet-type", "SHEET-TYPE" ); + dumpString( "sheet-name", BIFF_STR_8BITLENGTH, BIFF_STR_8BITLENGTH ); + break; + + case BIFF_ID_SHEETHEADER: + dumpHex< sal_uInt32 >( "substream-size", "CONV-DEC" ); + dumpByteString( "sheet-name", BIFF_STR_8BITLENGTH ); + break; + + case BIFF_ID_SHEETPROTECTION: + dumpRepeatedRecId(); + dumpUnused( 17 ); + dumpHex< sal_uInt16 >( "allowed-flags", "SHEETPROTECTION-FLAGS" ); + dumpUnused( 2 ); + break; + + case BIFF_ID_SST: + dumpDec< sal_uInt32 >( "string-cell-count" ); + dumpDec< sal_uInt32 >( "sst-size" ); + out().resetItemIndex(); + while( rStrm.isValid() && (rStrm.getRecLeft() >= 3) ) + dumpUniString( "#entry" ); + break; + + case BIFF2_ID_STRING: + case BIFF3_ID_STRING: + dumpString( "result", ((nRecId == BIFF2_ID_STRING) && (eBiff <= BIFF4)) ? BIFF_STR_8BITLENGTH : BIFF_STR_DEFAULT ); + break; + + case BIFF_ID_STYLE: + { + sal_uInt16 nFlags = dumpHex< sal_uInt16 >( "flags", "STYLE-FLAGS" ); + if( getFlag( nFlags, BIFF_STYLE_BUILTIN ) ) + { + dumpDec< sal_uInt8 >( "builtin-idx", "STYLE-BUILTIN" ); + dumpDec< sal_uInt8 >( "outline-level" ); + } + else + dumpString( "style-name", BIFF_STR_8BITLENGTH ); + } + break; + + case BIFF_ID_SXDI: + { + dumpDec< sal_uInt16 >( "field-idx" ); + dumpDec< sal_uInt16 >( "function", "SXDI-FUNC" ); + dumpDec< sal_uInt16 >( "data-format", "SXDI-FORMAT" ); + dumpDec< sal_uInt16 >( "format-basefield-idx" ); + dumpDec< sal_uInt16 >( "format-baseitem-idx", "SXDI-BASEITEM" ); + dumpFormatIdx(); + sal_uInt16 nNameLen = dumpDec< sal_uInt16 >( "item-name-len", "SX-NAMELEN" ); + if( nNameLen != BIFF_PT_NOSTRING ) + writeStringItem( "item-name", rStrm.readUniString( nNameLen ) ); + } + break; + + case BIFF_ID_SXEXT: + if( eBiff == BIFF8 ) + { + dumpHex< sal_uInt16 >( "flags", "SXEXT-FLAGS" ); + dumpDec< sal_uInt16 >( "param-string-count" ); + dumpDec< sal_uInt16 >( "sql-statement-string-count" ); + dumpDec< sal_uInt16 >( "webquery-postmethod-string-count" ); + dumpDec< sal_uInt16 >( "server-pagefields-string-count" ); + dumpDec< sal_uInt16 >( "odbc-connection-string-count" ); + } + break; + + case BIFF_ID_SXIVD: + out().resetItemIndex(); + for( sal_Size nIdx = 0, nCount = rStrm.getRecLeft() / 2; nIdx < nCount; ++nIdx ) + dumpDec< sal_uInt16 >( "#field-idx" ); + break; + + case BIFF_ID_SXLI: + if( mnPTSxliIdx < 2 ) + { + sal_uInt16 nCount = (mnPTSxliIdx == 0) ? mnPTRowFields : mnPTColFields; + sal_Size nLineSize = 8 + 2 * nCount; + out().resetItemIndex(); + while( rStrm.getRecLeft() >= nLineSize ) + { + writeEmptyItem( "#line-data" ); + IndentGuard aIndGuard( out() ); + MultiItemsGuard aMultiGuard( out() ); + dumpDec< sal_uInt16 >( "ident-count" ); + dumpDec< sal_uInt16 >( "item-type", "SXLI-ITEMTYPE" ); + dumpDec< sal_uInt16 >( "used-count" ); + dumpHex< sal_uInt16 >( "flags", "SXLI-FLAGS" ); + OUStringBuffer aItemList; + for( sal_uInt16 nIdx = 0; nIdx < nCount; ++nIdx ) + StringHelper::appendToken( aItemList, in().readValue< sal_uInt16 >() ); + writeInfoItem( "item-idxs", aItemList.makeStringAndClear() ); + } + ++mnPTSxliIdx; + } + break; + + case BIFF_ID_SXSTRING: + dumpString( "value" ); + break; + + case BIFF_ID_SXVD: + { + dumpDec< sal_uInt16 >( "axis-type", "SXVD-AXISTYPE" ); + dumpDec< sal_uInt16 >( "subtotal-count" ); + dumpHex< sal_uInt16 >( "subtotals", "SXVD-SUBTOTALS" ); + dumpDec< sal_uInt16 >( "item-count" ); + sal_uInt16 nNameLen = dumpDec< sal_uInt16 >( "field-name-len", "SX-NAMELEN" ); + if( nNameLen != BIFF_PT_NOSTRING ) + writeStringItem( "field-name", rStrm.readUniString( nNameLen ) ); + } + break; + + case BIFF_ID_SXVDEX: + dumpHex< sal_uInt32 >( "flags", "SXVDEX-FLAGS" ); + dumpDec< sal_uInt16 >( "autosort-basefield-idx" ); + dumpDec< sal_uInt16 >( "autoshow-basefield-idx" ); + dumpFormatIdx(); + break; + + case BIFF_ID_SXVI: + { + dumpDec< sal_uInt16 >( "item-type", "SXVI-ITEMTYPE" ); + dumpHex< sal_uInt16 >( "flags", "SXVI-FLAGS" ); + dumpDec< sal_uInt16 >( "cache-idx" ); + sal_uInt16 nNameLen = dumpDec< sal_uInt16 >( "item-name-len", "SX-NAMELEN" ); + if( nNameLen != BIFF_PT_NOSTRING ) + writeStringItem( "item-name", rStrm.readUniString( nNameLen ) ); + } + break; + + case BIFF_ID_SXVIEW: + { + dumpRange( "output-range" ); + dumpRowIndex( "first-header-row-idx" ); + dumpAddress( "first-data-pos" ); + dumpDec< sal_uInt16 >( "cache-idx" ); + dumpUnused( 2 ); + dumpDec< sal_uInt16 >( "default-data-axis", "SXVD-AXISTYPE" ); + dumpDec< sal_Int16 >( "default-data-pos" ); + dumpDec< sal_uInt16 >( "field-count" ); + mnPTRowFields = dumpDec< sal_uInt16 >( "row-field-count" ); + mnPTColFields = dumpDec< sal_uInt16 >( "column-field-count" ); + dumpDec< sal_uInt16 >( "page-field-count" ); + dumpDec< sal_uInt16 >( "data-field-count" ); + dumpDec< sal_uInt16 >( "data-row-count" ); + dumpDec< sal_uInt16 >( "data-column-count" ); + dumpHex< sal_uInt16 >( "flags", "SXVIEW-FLAGS" ); + dumpDec< sal_uInt16 >( "auto-format-idx" ); + sal_uInt16 nTabNameLen = dumpDec< sal_uInt16 >( "table-name-len" ); + sal_uInt16 nDataNameLen = dumpDec< sal_uInt16 >( "data-name-len" ); + writeStringItem( "table-name", rStrm.readUniString( nTabNameLen ) ); + writeStringItem( "data-name", rStrm.readUniString( nDataNameLen ) ); + mnPTSxliIdx = 0; + } + break; + + case BIFF_ID_WINDOW1: + dumpDec< sal_uInt16 >( "window-x", "CONV-TWIP-TO-CM" ); + dumpDec< sal_uInt16 >( "window-y", "CONV-TWIP-TO-CM" ); + dumpDec< sal_uInt16 >( "window-width", "CONV-TWIP-TO-CM" ); + dumpDec< sal_uInt16 >( "window-height", "CONV-TWIP-TO-CM" ); + if( eBiff <= BIFF4 ) + { + dumpBool< sal_uInt8 >( "hidden" ); + } + else + { + dumpHex< sal_uInt16 >( "flags", "WINDOW1-FLAGS" ); + dumpDec< sal_uInt16 >( "active-tab" ); + dumpDec< sal_uInt16 >( "first-visible-tab" ); + dumpDec< sal_uInt16 >( "selected-tabs" ); + dumpDec< sal_uInt16 >( "tabbar-ratio", "WINDOW1-TABBARRATIO" ); + } + break; + + case BIFF2_ID_WINDOW2: + dumpBool< sal_uInt8 >( "show-formulas" ); + dumpBool< sal_uInt8 >( "show-gridlines" ); + dumpBool< sal_uInt8 >( "show-headings" ); + dumpBool< sal_uInt8 >( "frozen-panes" ); + dumpBool< sal_uInt8 >( "show-zeros" ); + dumpAddress( "first-visible-cell" ); + dumpBool< sal_uInt8 >( "auto-grid-color" ); + dumpRgbColor( "grid-color-rgb" ); + break; + + case BIFF3_ID_WINDOW2: + dumpHex< sal_uInt16 >( "flags", "WINDOW2-FLAGS" ); + dumpAddress( "first-visible-cell" ); + if( eBiff == BIFF8 ) + { + dumpColorIdx( "grid-color-idx" ); + dumpUnused( 2 ); + if( rStrm.getRecLeft() >= 8 ) + { + dumpDec< sal_uInt16 >( "pagebreak-zoom", "CONV-PERCENT" ); + dumpDec< sal_uInt16 >( "normal-zoom", "CONV-PERCENT" ); + dumpUnused( 4 ); + } + } + else + dumpRgbColor( "grid-color-rgb" ); + break; + + case BIFF_ID_XCT: + dumpDec< sal_uInt16 >( "crn-count" ); + if( eBiff == BIFF8 ) dumpDec< sal_Int16 >( "sheet-idx" ); + break; + + case BIFF2_ID_XF: + case BIFF3_ID_XF: + case BIFF4_ID_XF: + case BIFF5_ID_XF: + dumpXfRec(); + break; + } +} + +OUString WorkbookStreamObject::createFontName( const OUString& rName, sal_uInt16 nHeight, bool bBold, bool bItalic ) const +{ + OUStringBuffer aName( rName ); + StringHelper::enclose( aName, OOX_DUMP_STRQUOTE ); + StringHelper::appendToken( aName, cfg().getName( "CONV-TWIP-TO-PT", nHeight ), ',' ); + if( bBold ) + StringHelper::appendToken( aName, CREATE_OUSTRING( "bold" ), ',' ); + if( bItalic ) + StringHelper::appendToken( aName, CREATE_OUSTRING( "italic" ), ',' ); + return aName.makeStringAndClear(); +} + +sal_uInt16 WorkbookStreamObject::dumpPatternIdx( const sal_Char* pcName, bool b16Bit ) +{ + return dumpDec< sal_uInt16, sal_uInt8 >( b16Bit, pcName ? pcName : "fill-pattern", mxFillPatterns ); +} + +sal_uInt16 WorkbookStreamObject::dumpColorIdx( const sal_Char* pcName, bool b16Bit ) +{ + return dumpDec< sal_uInt16, sal_uInt8 >( b16Bit, pcName ? pcName : "color-idx", mxColors ); +} + +sal_uInt16 WorkbookStreamObject::dumpFontIdx( const sal_Char* pcName, bool b16Bit ) +{ + return dumpDec< sal_uInt16, sal_uInt8 >( b16Bit, pcName ? pcName : "font-idx", "FONTNAMES" ); +} + +sal_uInt16 WorkbookStreamObject::dumpFormatIdx( const sal_Char* pcName ) +{ + return dumpDec< sal_uInt16, sal_uInt8 >( getBiff() >= BIFF5, pcName ? pcName : "fmt-idx", "FORMATS" ); +} + +sal_uInt16 WorkbookStreamObject::dumpXfIdx( const sal_Char* pcName, bool bBiff2Style ) +{ + if( !pcName ) pcName = "xf-idx"; + sal_uInt16 nXfIdx = 0; + if( bBiff2Style ) + { + dumpHex< sal_uInt8 >( pcName, "CELL-XFINDEX" ); + dumpHex< sal_uInt8 >( "fmt-font-idx", "CELL-XFFORMAT" ); + dumpHex< sal_uInt8 >( "style", "CELL-XFSTYLE" ); + } + else + nXfIdx = dumpDec< sal_uInt16 >( pcName ); + return nXfIdx; +} + +sal_uInt16 WorkbookStreamObject::dumpCellHeader( bool bBiff2Style ) +{ + dumpAddress(); + return dumpXfIdx( 0, bBiff2Style ); +} + +void WorkbookStreamObject::dumpBoolErr() +{ + MultiItemsGuard aMultiGuard( out() ); + sal_uInt8 nValue = dumpHex< sal_uInt8 >( "value" ); + bool bErrCode = dumpBool< sal_uInt8 >( "is-errorcode" ); + if( bErrCode ) + writeErrorCodeItem( "errorcode", nValue ); + else + writeBooleanItem( "boolean", nValue ); +} + +void WorkbookStreamObject::dumpFontRec() +{ + sal_uInt16 nFontId = getBiffData().getFontCount(); + out().resetItemIndex( nFontId ); + writeEmptyItem( "#font" ); + sal_uInt16 nHeight = dumpDec< sal_uInt16 >( "height", "CONV-TWIP-TO-PT" ); + sal_uInt16 nFlags = dumpHex< sal_uInt16 >( "flags", "FONT-FLAGS" ); + bool bBold = getFlag( nFlags, BIFF_FONTFLAG_BOLD ); + bool bItalic = getFlag( nFlags, BIFF_FONTFLAG_ITALIC ); + rtl_TextEncoding eFontEnc = RTL_TEXTENCODING_DONTKNOW; + if( getBiff() >= BIFF3 ) + dumpColorIdx(); + if( getBiff() >= BIFF5 ) + { + bBold = dumpDec< sal_uInt16 >( "weight", "FONT-WEIGHT" ) > 450; + dumpDec< sal_uInt16 >( "escapement", "FONT-ESCAPEMENT" ); + dumpDec< sal_uInt8 >( "underline", "FONT-UNDERLINE" ); + dumpDec< sal_uInt8 >( "family", "FONT-FAMILY" ); + sal_uInt8 nCharSet = dumpDec< sal_uInt8 >( "charset", "CHARSET" ); + eFontEnc = rtl_getTextEncodingFromWindowsCharset( nCharSet ); + dumpUnused( 1 ); + } + OUString aName = dumpString( "name", BIFF_STR_8BITLENGTH, BIFF_STR_8BITLENGTH ); + + // append font data to vector + mxFontNames->setName( nFontId, createFontName( aName, nHeight, bBold, bItalic ) ); + + // store font encoding + getBiffData().appendFontEncoding( eFontEnc ); + + // set font encoding as default text encoding in case of missing CODEPAGE record + if( !mbHasCodePage && (nFontId == 0) ) + getBiffData().setTextEncoding( eFontEnc ); +} + +void WorkbookStreamObject::dumpFormatRec() +{ + sal_uInt16 nFormatIdx = 0; + switch( getBiff() ) + { + case BIFF2: + case BIFF3: + nFormatIdx = mnFormatIdx++; + out().resetItemIndex( nFormatIdx ); + writeEmptyItem( "#fmt" ); + break; + case BIFF4: + nFormatIdx = mnFormatIdx++; + out().resetItemIndex( nFormatIdx ); + writeEmptyItem( "#fmt" ); + dumpUnused( 2 ); + break; + case BIFF5: + case BIFF8: + getBiffStream() >> nFormatIdx; + out().resetItemIndex( nFormatIdx ); + writeEmptyItem( "#fmt" ); + writeDecItem( "fmt-idx", nFormatIdx ); + break; + case BIFF_UNKNOWN: break; + } + OUString aFormat = dumpString( "format", BIFF_STR_8BITLENGTH ); + mxFormats->setName( nFormatIdx, aFormat ); +} + +void WorkbookStreamObject::dumpXfRec() +{ + sal_uInt16 nXfId = getBiffData().getXfCount(); + out().resetItemIndex( nXfId ); + writeEmptyItem( "#xf" ); + sal_uInt16 nFontId = dumpFontIdx( 0, getBiff() >= BIFF5 ); + switch( getBiff() ) + { + case BIFF2: + dumpUnused( 1 ); + dumpHex< sal_uInt8 >( "type-flags", "XF-TYPEFLAGS" ); + dumpHex< sal_uInt8 >( "style-flags", "XF-STYLEFLAGS" ); + break; + case BIFF3: + dumpFormatIdx(); + dumpHex< sal_uInt8 >( "type-flags", "XF-TYPEFLAGS" ); + dumpHex< sal_uInt8 >( "used-attributes", "XF-USEDATTRIBS-FLAGS" ); + dumpHex< sal_uInt16 >( "alignment", "XF-ALIGNMENT" ); + dumpHex< sal_uInt16 >( "fill-style", "XF-FILL" ); + dumpHex< sal_uInt32 >( "border-style", "XF-BORDER" ); + break; + case BIFF4: + dumpFormatIdx(); + dumpHex< sal_uInt16 >( "type-flags", "XF-TYPEFLAGS" ); + dumpHex< sal_uInt8 >( "alignment", "XF-ALIGNMENT" ); + dumpHex< sal_uInt8 >( "used-attributes", "XF-USEDATTRIBS-FLAGS" ); + dumpHex< sal_uInt16 >( "fill-style", "XF-FILL" ); + dumpHex< sal_uInt32 >( "border-style", "XF-BORDER" ); + break; + case BIFF5: + dumpFormatIdx(); + dumpHex< sal_uInt16 >( "type-flags", "XF-TYPEFLAGS" ); + dumpHex< sal_uInt8 >( "alignment", "XF-ALIGNMENT" ); + dumpHex< sal_uInt8 >( "orientation", "XF-ORIENTATTRIBS" ); + dumpHex< sal_uInt32 >( "fill-style", "XF-FILL" ); + dumpHex< sal_uInt32 >( "border-style", "XF-BORDER" ); + break; + case BIFF8: + dumpFormatIdx(); + dumpHex< sal_uInt16 >( "type-flags", "XF-TYPEFLAGS" ); + dumpHex< sal_uInt8 >( "alignment", "XF-ALIGNMENT" ); + dumpDec< sal_uInt8 >( "rotation", "TEXTROTATION" ); + dumpHex< sal_uInt8 >( "text-flags", "XF-TEXTFLAGS" ); + dumpHex< sal_uInt8 >( "used-attributes", "XF-USEDATTRIBS-FLAGS" ); + dumpHex< sal_uInt16 >( "border-style", "XF-BORDERSTYLE" ); + dumpHex< sal_uInt16 >( "border-color1", "XF-BORDERCOLOR1" ); + dumpHex< sal_uInt32 >( "border-color2", "XF-BORDERCOLOR2" ); + dumpHex< sal_uInt16 >( "fill-color", "XF-FILLCOLOR" ); + break; + case BIFF_UNKNOWN: break; + } + getBiffData().appendXfFontId( nFontId ); +} + +void WorkbookStreamObject::dumpObjRec() +{ + switch( getBiff() ) + { + case BIFF5: dumpObjRecBiff5(); break; + case BIFF8: dumpObjRecBiff8(); break; + default:; + } +} + +void WorkbookStreamObject::dumpObjRecBiff5() +{ + dumpDec< sal_uInt32 >( "obj-count" ); + sal_uInt16 nObjType = dumpDec< sal_uInt16 >( "obj-type", "OBJ-TYPE" ); + dumpDec< sal_uInt16 >( "obj-id" ); + dumpHex< sal_uInt16 >( "flags", "OBJ-FLAGS" ); + getDffDumper().dumpDffClientRect(); + dumpDec< sal_uInt16 >( "macro-len" ); + dumpUnused( 6 ); + switch( nObjType ) + { + case BIFF_OBJCMO_LINE: + dumpColorIdx( "line-color-idx", false ); + dumpDec< sal_uInt8 >( "line-type", "OBJ-LINETYPE" ); + dumpDec< sal_uInt8 >( "line-weight", "OBJ-LINEWEIGHT" ); + dumpHex< sal_uInt8 >( "line-flags", "OBJ-FLAGS-AUTO" ); + dumpHex< sal_uInt16 >( "line-end", "OBJ-LINEENDS" ); + dumpDec< sal_uInt8 >( "line-direction", "OBJ-LINEDIR" ); + dumpUnused( 1 ); + break; + case BIFF_OBJCMO_RECTANGLE: + dumpColorIdx( "back-color-idx", false ); + dumpColorIdx( "patt-color-idx", false ); + dumpPatternIdx( 0, false ); + dumpHex< sal_uInt8 >( "area-flags", "OBJ-FLAGS-AUTO" ); + dumpColorIdx( "line-color-idx", false ); + dumpDec< sal_uInt8 >( "line-type", "OBJ-LINETYPE" ); + dumpDec< sal_uInt8 >( "line-weight", "OBJ-LINEWEIGHT" ); + dumpHex< sal_uInt8 >( "line-flags", "OBJ-FLAGS-AUTO" ); + dumpHex< sal_uInt16 >( "frame-style", "OBJ-FRAMESTYLE-FLAGS" ); + break; + case BIFF_OBJCMO_CHART: + dumpColorIdx( "back-color-idx", false ); + dumpColorIdx( "patt-color-idx", false ); + dumpPatternIdx( 0, false ); + dumpHex< sal_uInt8 >( "area-flags", "OBJ-FLAGS-AUTO" ); + dumpColorIdx( "line-color-idx", false ); + dumpDec< sal_uInt8 >( "line-type", "OBJ-LINETYPE" ); + dumpDec< sal_uInt8 >( "line-weight", "OBJ-LINEWEIGHT" ); + dumpHex< sal_uInt8 >( "line-flags", "OBJ-FLAGS-AUTO" ); + dumpHex< sal_uInt16 >( "frame-style", "OBJ-FRAMESTYLE-FLAGS" ); + dumpHex< sal_uInt16 >( "chart-flags", "OBJ-CHART-FLAGS" ); + dumpUnused( 16 ); + break; + } +} + +void WorkbookStreamObject::dumpObjRecBiff8() +{ + Output& rOut = out(); + BiffInputStream& rStrm = getBiffStream(); + NameListRef xRecNames = cfg().getNameList( "OBJ-RECNAMES" ); + bool bLinked = false; + bool bControl = false; + bool bCtlsStrm = false; + bool bLoop = true; + while( bLoop && (rStrm.getRecLeft() >= 4) ) + { + rOut.emptyLine(); + sal_uInt16 nSubRecId, nSubRecSize; + { + MultiItemsGuard aMultiGuard( rOut ); + writeEmptyItem( "OBJREC" ); + writeHexItem( "pos", rStrm.getRecPos() ); + rStrm >> nSubRecId >> nSubRecSize; + writeHexItem( "size", nSubRecSize ); + writeHexItem( "id", nSubRecId, xRecNames ); + } + + sal_uInt32 nSubRecStart = rStrm.getRecPos(); + // sometimes the last subrecord has an invalid length + sal_uInt32 nRealRecSize = ::std::min< sal_uInt32 >( nSubRecSize, rStrm.getRecLeft() ); + sal_uInt32 nSubRecEnd = nSubRecStart + nRealRecSize; + + IndentGuard aIndGuard( rOut ); + switch( nSubRecId ) + { + case BIFF_ID_OBJPIOGRBIT: + { + sal_uInt16 nFlags = dumpHex< sal_uInt16 >( "flags", "OBJPIOGRBIT-FLAGS" ); + bLinked = getFlag( nFlags, BIFF_OBJPIO_LINKED ); + bControl = getFlag( nFlags, BIFF_OBJPIO_CONTROL ); + bCtlsStrm = getFlag( nFlags, BIFF_OBJPIO_CTLSSTREAM ); + } + break; + case BIFF_ID_OBJPICTFMLA: + { + sal_uInt16 nLinkDataSize = dumpDec< sal_uInt16 >( "link-data-size" ); + sal_uInt32 nLinkDataEnd = rStrm.getRecPos() + nLinkDataSize; + { + IndentGuard aIndGuard2( rOut ); + sal_uInt16 nFmlaSize = getFormulaDumper().dumpFormulaSize(); + dumpUnused( 4 ); + getFormulaDumper().dumpNameFormula( "link", nFmlaSize ); + if( dumpDec< sal_uInt8 >( "has-class-name", "OBJPICTFMLA-HASCLASSNAME" ) == 3 ) + { + dumpUniString( "class-name", BIFF_STR_SMARTFLAGS ); + if( ((rStrm.getRecPos() - nSubRecStart) & 1) != 0 ) + dumpHex< sal_uInt8 >( "padding" ); + } + } + if( rStrm.getRecPos() != nLinkDataEnd ) + writeEmptyItem( OOX_DUMP_ERRASCII( "link-data-size" ) ); + if( rStrm.getRecPos() < nLinkDataEnd ) + dumpRemaining( nLinkDataEnd - rStrm.getRecPos() ); + rStrm.seek( nLinkDataEnd ); + if( nLinkDataEnd + 4 <= nSubRecEnd ) + { + if( bControl && bCtlsStrm ) + { + sal_uInt32 nPos = dumpHex< sal_uInt32 >( "ctls-stream-pos", "CONV-DEC" ); + sal_uInt32 nSize = dumpHex< sal_uInt32 >( "ctls-stream-size", "CONV-DEC" ); + IndentGuard aIndGuard2( rOut ); + rOut.emptyLine(); + dumpFormControl( nPos, nSize ); + rOut.emptyLine(); + } + else + dumpHex< sal_uInt32 >( "ole-storage-id" ); + } + if( bControl && (rStrm.getRecPos() + 8 <= nSubRecEnd) ) + { + sal_uInt32 nClassIdSize = dumpDec< sal_uInt32 >( "class-id-size" ); + if( nClassIdSize > 0 ) + { + IndentGuard aIndGuard2( rOut ); + sal_uInt32 nClassIdEnd = rStrm.getRecPos() + nClassIdSize; + dumpUnicodeArray( "class-id", static_cast< sal_Int32 >( nClassIdSize / 2 ) ); + rStrm.seek( nClassIdEnd ); + } + sal_uInt16 nCellLinkSize = dumpDec< sal_uInt16 >( "cell-link-size" ); + if( nCellLinkSize > 0 ) + { + IndentGuard aIndGuard2( rOut ); + sal_uInt32 nCellLinkEnd = rStrm.getRecPos() + nCellLinkSize; + sal_uInt16 nFmlaSize = getFormulaDumper().dumpFormulaSize( "cell-link-fmla-size" ); + dumpUnused( 4 ); + getFormulaDumper().dumpNameFormula( "cell-link", nFmlaSize ); + rStrm.seek( nCellLinkEnd ); + } + sal_uInt16 nSrcRangeSize = dumpDec< sal_uInt16 >( "source-range-size" ); + if( nSrcRangeSize > 0 ) + { + IndentGuard aIndGuard2( rOut ); + sal_uInt32 nSrcRangeEnd = rStrm.getRecPos() + nSrcRangeSize; + sal_uInt16 nFmlaSize = getFormulaDumper().dumpFormulaSize( "source-range-fmla-size" ); + dumpUnused( 4 ); + getFormulaDumper().dumpNameFormula( "source-range", nFmlaSize ); + rStrm.seek( nSrcRangeEnd ); + } + } + } + break; + case BIFF_ID_OBJCMO: + dumpDec< sal_uInt16 >( "type", "OBJCMO-TYPE" ); + dumpDec< sal_uInt16 >( "id" ); + dumpHex< sal_uInt16 >( "flags", "OBJCMO-FLAGS" ); + dumpUnused( 12 ); + break; + } + // remaining undumped data + if( rStrm.getRecPos() == nSubRecStart ) + dumpRawBinary( nRealRecSize, false ); + else + dumpRemaining( nSubRecEnd - rStrm.getRecPos() ); + rStrm.seek( nSubRecStart + nRealRecSize ); + } +} + +void WorkbookStreamObject::dumpFormControl( sal_uInt32 nStrmPos, sal_uInt32 nStrmSize ) +{ + writeHexItem( "stream-pos", nStrmPos, "CONV-DEC" ); + writeHexItem( "stream-size", nStrmSize, "CONV-DEC" ); +} + +// ============================================================================ + +PivotCacheStreamObject::PivotCacheStreamObject( const ObjectBase& rParent, const ::rtl::OUString& rOutFileName, BinaryInputStreamRef xStrm ) +{ + RecordStreamObject::construct( rParent, rOutFileName, xStrm, BIFF8 ); +} + +void PivotCacheStreamObject::implDumpRecord() +{ + BiffInputStream& rStrm = getBiffStream(); + sal_uInt16 nRecId = rStrm.getRecId(); + + switch( nRecId ) + { + case BIFF_ID_SXDATETIME: + { + sal_uInt16 nYear, nMonth; + sal_uInt8 nDay, nHour, nMin, nSec; + rStrm >> nYear >> nMonth >> nDay >> nHour >> nMin >> nSec; + DateTime aDateTime( 0, nSec, nMin, nHour, nDay, nMonth, nYear ); + writeDateTimeItem( "value", aDateTime ); + } + break; + + case BIFF_ID_SXDB: + dumpDec< sal_uInt32 >( "source-records" ); + dumpHex< sal_uInt16 >( "stream-id" ); + dumpHex< sal_uInt16 >( "flags", "SXDB-FLAGS" ); + dumpDec< sal_uInt16 >( "block-records" ); + dumpDec< sal_uInt16 >( "standard-field-count" ); + dumpDec< sal_uInt16 >( "total-field-count" ); + dumpUnused( 2 ); + dumpDec< sal_uInt16 >( "database-type", "SXDB-TYPE" ); + dumpUniString( "user-name" ); + break; + + case BIFF_ID_SXFIELD: + dumpHex< sal_uInt16 >( "flags", "SXFIELD-FLAGS" ); + dumpDec< sal_uInt16 >( "group-child-field" ); + dumpDec< sal_uInt16 >( "group-base-field" ); + dumpDec< sal_uInt16 >( "visible-items" ); + dumpDec< sal_uInt16 >( "group-items" ); + dumpDec< sal_uInt16 >( "base-items" ); + dumpDec< sal_uInt16 >( "original-items" ); + if( rStrm.getRecLeft() >= 3 ) + dumpUniString( "item-name" ); + break; + + case BIFF_ID_SXSTRING: + dumpUniString( "value" ); + break; + } +} + +// ============================================================================ +// ============================================================================ + +RootStorageObject::RootStorageObject( const DumperBase& rParent ) +{ + RootStorageObjectBase::construct( rParent ); +} + +void RootStorageObject::implDumpStream( BinaryInputStreamRef xStrm, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSystemFileName ) +{ + if( rStrgPath.getLength() == 0 ) + { + if( (rStrmName == CREATE_OUSTRING( "Book" )) || (rStrmName == CREATE_OUSTRING( "Workbook" )) ) + WorkbookStreamObject( *this, rSystemFileName, xStrm ).dump(); + else if( (rStrmName == CREATE_OUSTRING( "\005SummaryInformation" )) || (rStrmName == CREATE_OUSTRING( "\005DocumentSummaryInformation" )) ) + OlePropertyStreamObject( *this, rSystemFileName, xStrm ).dump(); + else + InputStreamObject( *this, rSystemFileName, xStrm ).dump(); + } + else if( rStrgPath == CREATE_OUSTRING( "_SX_DB_CUR" ) ) + { + PivotCacheStreamObject( *this, rSystemFileName, xStrm ).dump(); + } +} + +// ============================================================================ +// ============================================================================ + +Dumper::Dumper( const FilterBase& rFilter ) +{ + ConfigRef xCfg( new Config( "OOO_BIFFDUMPER" ) ); + DumperBase::construct( rFilter, xCfg ); +} + +void Dumper::implDump() +{ + WorkbookStreamObject( *this, getFilter().getFileUrl() + CREATE_OUSTRING( ".dump" ), getRootStream() ).dump(); + RootStorageObject( *this ).dump(); +} + +// ============================================================================ + +} // namespace biff +} // namespace dump +} // namespace oox + +#endif + diff --git a/oox/source/dump/biffdumperconfig.dat b/oox/source/dump/biffdumperconfig.dat new file mode 100644 index 000000000000..7fbbf7cbcab7 --- /dev/null +++ b/oox/source/dump/biffdumperconfig.dat @@ -0,0 +1,1782 @@ + +# dumper settings ============================================================ + +# Path to base configuration data, relative to this file. +include-config-file=dumperconfig.dat + +# BIFF record settings ------------------------------------------------------- + +# Show total stream position of the record (default=on). +# 0=off, 1=on +show-record-pos=0 + +# Show total record size in bytes (including CONTINUE records, if enabled, +# see 'merge-continue-record' option) (default=on). +# 0=off, 1=on +show-record-size=1 + +# Show record identifier (default=on). +# 0=off, 1=on +show-record-id=1 + +# Show record name, if known (default=on). +# 0=off, 1=on +show-record-name=1 + +# Show record contents (default=on). +# 0=off, 1=on +show-record-body=1 + +# Merge CONTINUE records with leading record (default=on). +# 0=off - show CONTINUE records separately (hex dump) +# 1=on - show contents of leading record together with following CONTINUE +merge-continue-record=1 + +# name maps ================================================================== +# +# List of constants +# ----------------- +# Defines names for specific values. +# +# constlist = +# default = (default=?err:no-name) +# include = [,...] +# exclude = [,...] +# quote-names = 0|1|false|true (default=0) +# = +# end +# +# List of multiple contants per line +# ---------------------------------- +# Defines names for contiguous ranges of values. +# +# multilist = +# default = (default=?err:no-name) +# ignore-empty = 0|1|false|true (default=1) +# include = [,...] +# exclude = [,...] +# = [,...] +# end +# +# List of multiple contants, shortened format +# ------------------------------------------- +# Defines names for a contiguous range of values. The entire list definition +# is given in a single text line. +# +# shortlist = ,,[,...] +# +# List of flags +# ------------- +# Defines names for single bits in a bit field. +# +# flagslist = +# ignore = (default=0) +# include = [,...] +# exclude = [,...] +# = [!] +# end +# +# List of flags and values in a bitfield +# -------------------------------------- +# Defines names for single bits and for embedded values in a bit field. +# +# combilist = +# ignore = (default=0) +# include = [,...] +# exclude = [,...] +# = [!] +# = ,,[,] +# end +# +# Unit converter +# -------------- +# Converts values and appends a unit name. +# +# unitconverter = ,[/], + +# common --------------------------------------------------------------------- + +unitconverter=CONV-PERCENT-NEG,-1,% +unitconverter=CONV-COLWIDTH,/256,chars + +shortlist=BIFF,0,biff2,biff3,biff4,biff5,biff8 + +constlist=ERRORCODES + 0x00=#NULL! + 0x07=#DIV/0! + 0x0F=#VALUE! + 0x17=#REF! + 0x1D=#NAME? + 0x24=#NUM! + 0x2A=#N/A +end + +shortlist=EGA-COLORS,0,ega-black,ega-white,ega-red,ega-green,ega-blue,ega-yellow,ega-magenta,ega-cyan + +constlist=COLORS-BIFF2 + include=EGA-COLORS + default= + 24=sys-window-text + 25=sys-window-bg + 0x7FFF=sys-window-text +end + +constlist=COLORS-BIFF5 + include=EGA-COLORS + default= + 64=sys-window-text + 65=sys-window-bg + 67=sys-button-face + 77=sys-window-text-chart + 78=sys-window-bg-chart + 79=auto-border-chart + 80=sys-tooltip-bg + 81=sys-tooltip-text + 0x7FFF=sys-window-text +end + +shortlist=BORDERSTYLES-BIFF3,0,none,thin,medium,dash,dot,thick,double,hair + +multilist=BORDERSTYLES-BIFF8 + include=BORDERSTYLES-BIFF3 + 8=medium-dash,thin-dash-dot,medium-dash-dot,thin-dash-dot-dot,medium-dash-dot-dot,slant-dash-dot +end + +multilist=FILLPATTERNS-BIFF3 + 0=no-fill,solid-fill,50%-grey,75%-grey,25%-grey + 5=hor-stripe,ver-stripe,rev-diag-stripe,diag-stripe,diag-crosshatch + 10=thick-diag-crosshatch,thin-hor-stripe,thin-ver-stripe,thin-rev-diag-stripe,thin-diag-stripe + 15=thin-hor-crosshatch,thin-diag-crosshatch,12.5%-grey,6.25%-grey +end + +shortlist=TEXTORIENTATION,0,horizontal,stacked,90°-ccw,90°-cw + +constlist=TEXTROTATION-BIFF8 + default= + 255=stacked +end + +multilist=BUILTIN-FORMATS + quote-names=1 + 0=General,0,0.00,'#,##0','#,##0.00' + 5='"$"#,##0_);\("$"#,##0\)','"$"#,##0_);[Red]\("$"#,##0\)','"$"#,##0.00_);\("$"#,##0.00\)','"$"#,##0.00_);[Red]\("$"#,##0.00\)',0% + 10=0.00%,0.00E+00,# ?/?,# ??/??,M/D/YYYY + 15=D-MMM-YY,D-MMM,MMM-YY,h:mm AM/PM,h:mm:ss AM/PM + 20=h:mm,h:mm:ss,M/D/YYYY h:mm,General,General + 25=General,General,M/D/YYYY,M/D/YYYY,M/D/YYYY + 30=M/D/YYYY,M/D/YYYY,h:mm:ss,h:mm:ss,h:mm:ss + 35=h:mm:ss,M/D/YYYY,'#,##0_);(#,##0)','#,##0_);[Red](#,##0)','#,##0.00_);(#,##0.00)' + 40='#,##0.00_);[Red](#,##0.00)' + 41='_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)' + 42='_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_)' + 43='_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)' + 44='_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)' + 45=mm:ss,[h]:mm:ss,mm:ss.0,##0.0E+0,@ + 50=M/D/YYYY,M/D/YYYY,M/D/YYYY,M/D/YYYY,M/D/YYYY + 55=M/D/YYYY,M/D/YYYY,M/D/YYYY,M/D/YYYY,0 + 60=0.00,'#,##0','#,##0.00','$#,##0_);($#,##0)','$#,##0_);[Red]($#,##0)' + 65='$#,##0.00_);($#,##0.00)','$#,##0.00_);[Red]($#,##0.00)',0%,0.00%,# ?/? + 70=# ??/??,M/D/YYYY,M/D/YYYY,D-MMM-YY,D-MMM + 75=MMM-YY,h:mm,h:mm:ss,M/D/YYYY h:mm,mm:ss + 80=[h]:mm:ss,mm:ss.0 +end + +constlist=CONSTVALUE-TYPE + 0=empty + 1=number + 2=string + 4=boolean + 16=error +end + +# formulas ------------------------------------------------------------------- + +multilist=BASETOKENS-BIFF2 + 0x00=,tExp,tTbl,tAdd,tSub,tMul,tDiv,tPower + 0x08=tConcat,tLT,tLE,tEQ,tGE,tGT,tNE,tIsect + 0x10=tList,tRange,tUplus,tUminus,tPercent,tParen,tMissArg,tStr + 0x18=,tAttr,tSheet,tEndSheet,tErr,tBool,tInt,tNum +end + +constlist=BASETOKENS-BIFF5 + include=BASETOKENS-BIFF2 + exclude=0x1A,0x1B +end + +constlist=BASETOKENS-BIFF8 + include=BASETOKENS-BIFF5 + 0x18=tNlr +end + +constlist=TOKENCLASSES + 0x20=R + 0x40=V + 0x60=A +end + +multilist=CLASSTOKENS-BIFF2 + 0x00=tArray,tFunc,tFuncVar,tName,tRef,tArea,tMemArea,tMemErr + 0x08=tMemNoMem,tMemFunc,tRefErr,tAreaErr,tRefN,tAreaN,tMemAreaN,tMemNoMemN + 0x18=tFuncCE +end + +constlist=CLASSTOKENS-BIFF4 + include=CLASSTOKENS-BIFF2 + exclude=0x18 +end + +multilist=CLASSTOKENS-BIFF5 + include=CLASSTOKENS-BIFF4 + 0x19=tNameX,tRef3d,tArea3d,tRefErr3d,tAreaErr3d +end + +combilist=FUNCID + 0x7FFF=uint16,dec,func-id + 0x8000=command +end + +combilist=PARAMCOUNT-CMD + 0x7F=uint8,dec,count + 0x80=prompt +end + +combilist=REFRELFLAGS + 0x3FFF=uint16,dec,value + 0x4000=col-rel + 0x8000=row-rel +end + +multilist=NLRTYPES + 0x00=,tNlrErr,tNlrRowR,tNlrColR,,,tNlrRowV,tNlrColV + 0x08=,,tNlrRange,tNlrSRange,tNlrSRowR,tNlrSColR,tNlrSRowV,tNlrSColV + 0x10=tNlrRangeErr,,,,,,, + 0x18=,,,,,tNlrSxName,, +end + +combilist=NLRADDFLAGS + 0x3FFFFFFF=uint32,dec,count + 0x80000000=rel +end + +flagslist=ATTRTYPES + 0x01=volatile + 0x02=if + 0x04=choose + 0x08=skip + 0x10=sum + 0x20=assign + 0x40=space +end + +shortlist=ATTRSPACETYPES,0,space-before-token,cr-before-token,space-before-open,cr-before-open,space-before-close,cr-before-close,leading-space + +# record names --------------------------------------------------------------- + +multilist=RECORD-NAMES-BIFF2 + # worksheet records + 0x0000=DIMENSION,BLANK,INTEGER,NUMBER,LABEL,BOOLERR,FORMULA,STRING + 0x0008=ROW,BOF,EOF,INDEX,CALCCOUNT,CALCMODE,PRECISION,REFMODE + 0x0010=DELTA,ITERATION,PROTECT,PASSWORD,HEADER,FOOTER,EXTERNCOUNT,EXTERNSHEET + 0x0018=DEFINEDNAME,WINDOWPROTECT,VERTICALPAGEBREAKS,HORIZONTALPAGEBREAKS,NOTE,SELECTION,FORMAT,BUILTINFMTCOUNT + 0x0020=COLUMNDEFAULT,ARRAY,DATEMODE,EXTERNALNAME,COLWIDTH,DEFAULTROWHEIGHT,LEFTMARGIN,RIGHTMARGIN + 0x0028=TOPMARGIN,BOTTOMMARGIN,PRINTHEADERS,PRINTGRIDLINES,,,,FILEPASS + 0x0030=,FONT,FONT2,PRINTSIZE,,INFOOPTS,DATATABLE,DATATABLE2 + 0x0038=WNDESK,,BEGINPREF,ENDPREF,CONTINUE,WINDOW1,WINDOW2, + 0x0040=BACKUP,PANE,CODEPAGE,XF,IXFE,EFONT,SHOWSCROLL,SHOWFORMULA + 0x0048=STATUSBAR,SHORTMENUS,DDEENABLED,AUTODEC,MENUKEY,PLS|ZOOM,MENUUND,MOVESEL + 0x0050=DCON,DCONREF,DCONNAME,,,DEFCOLWIDTH,, + # worksheet records new in BIFF3, but supported in BIFF2 streams + 0x0200=DIMENSION,BLANK,,NUMBER,LABEL,BOOLERR,, + 0x027E=RK + # BIFF5 style BOF + 0x0809=BOF + # chart records + 0x1000=,CHUNITS,CHCHART,CHSERIES,CHSOURCELINK,,CHDATAFORMAT,CHLINEFORMAT + 0x1008=,CHMARKERFORMAT,CHAREAFORMAT,CHPIEFORMAT,CHATTACHEDLABEL,CHSTRING,, + 0x1010=,,,,CHTYPEGROUP,CHLEGEND,CHSERIESLIST,CHBAR + 0x1018=CHLINE,CHPIE,CHAREA,CHSCATTER,CHCHARTLINE,CHAXIS,CHTICK,CHVALUERANGE + 0x1020=CHLABELRANGE,CHAXISLINE,CHFORMATLINK,,CHDEFAULTTEXT,CHTEXT,CHFONT,CHOBJECTLINK + 0x1028=,,,,,CHARROW,,CHARROWHEAD + 0x1030=,,CHFRAME,CHBEGIN,CHEND,CHPLOTFRAME,CHCHARTSIZE,CHRELPOSITION + 0x1038=CHARROWRELPOS,,CHCHART3D,,,,, +end + +multilist=RECORD-NAMES-BIFF3 + include=RECORD-NAMES-BIFF2 + # worksheet records + exclude=0x0006,0x0008,0x0009,0x000B,0x0018,0x0020,0x0021,0x0023,0x0024,0x0025,0x0031,0x0036,0x0037,0x003E,0x0043,0x0044,0x0045 + 0x0050=,,,,,,BUILTINFMTCOUNT, + 0x0058=TOOLBAR,XCT,CRN,FILESHARING,WRITEACCESS,OBJ,UNCALCED,SAFERECALC + 0x0060=TEMPLATE,INTL,,OBJECTPROTECT,,,, + 0x0068=,,,,,,, + 0x0070=,,,,,,, + 0x0078=,,,,,COLINFO,,IMDATA + 0x0080=GUTS,SHEETPR,GRIDSET,HCENTER,VCENTER,,WRITEPROT,ADDIN + 0x0088=EDG,PUB,NOTEOFF,LH,COUNTRY,HIDEOBJ,, + 0x0090=SORT,SUB,PALETTE,,LHRECORD,LHNGRAPH,, + 0x0200=,,,,,,FORMULA,STRING + 0x0208=ROW,BOF,,INDEX,,,, + 0x0218=DEFINEDNAME + 0x0221=ARRAY + 0x0223=EXTERNALNAME + 0x0225=DEFAULTROWHEIGHT + 0x0231=FONT + 0x0236=DATATABLE + 0x023E=WINDOW2 + 0x0243=XF + 0x0293=STYLE + # chart records + 0x103C=CHPICFORMAT +end + +multilist=RECORD-NAMES-BIFF4 + include=RECORD-NAMES-BIFF3 + # worksheet/workbook records + exclude=0x0206,0x0209,0x001E,0x0243 + 0x0085=SHEET + 0x0088=,,,,,,SHEETSOFFSET,SHEETHEADER + 0x0090=,,,,,SOUND,SYNC + 0x0098=LPR,STANDARDWIDTH,FNGROUPNAME,,FNGROUPCOUNT,,, + 0x00A0=SCL,PAGESETUP,FNPROTO,PROJEXTSHEET,,,, + 0x00A8=DRAGDROP,COORDLIST,,GCW,,,, + 0x0406=FORMULA + 0x0409=BOF + 0x041E=FORMAT + 0x0443=XF + # chart records + 0x1038=,,,CHMULTILINK,,CHDROPBAR,CHRADARLINE,CHSURFACE +end + +multilist=RECORD-NAMES-BIFF5 + include=RECORD-NAMES-BIFF4 + # worksheet/workbook records + exclude=0x0409,0x0218,0x0223,0x0231,0x0443 + 0x0006=FORMULA + 0x0018=DEFINEDNAME + 0x0023=EXTERNALNAME + 0x0031=FONT + 0x0098=,,,FILTERMODE,,AUTOFILTERINFO,AUTOFILTER, + 0x00A8=,,,,,,SCENMAN,SCENARIO + 0x00B0=SXVIEW,SXVD,SXVI,,SXIVD,SXLI,SXPI, + 0x00B8=DOCROUTE,RECIPNAME,,,SHAREDFMLA,MULTRK,MULTBLANK, + 0x00C0=,MMS,ADDMENU,DELMENU,,SXDI,SXDB,SXFIELD + 0x00C8=SXINDEXLIST,SXDOUBLE,SXBOOLEAN,SXERROR,SXINTEGER,SXSTRING,SXDATETIME,SXEMPTY + 0x00D0=SXTBL,SXTBRGITEM,SXTBPG,OBPROJ,,SXIDSTM,RSTRING,DBCELL + 0x00D8=SXNUMGROUP,SXGROUPINFO,BOOKBOOL,REVERT,SXEXT|PARAMQRY,SCENPROTECT,OLESIZE,UDDESC + 0x00E0=XF,INTERFACEHDR,INTERFACEEND,SXVS,,,, + 0x0206=FORMULA + # chart records + exclude=0x1004,0x102D,0x102F,0x1036,0x1037,0x1038,0x103B + 0x1040=CHRADARAREA,CHAXESSET,,CHLEGENDENTRY,CHPROPERTIES,CHSERGROUP,CHUSEDAXESSETS, + 0x1048=CHPIVOTREF,,CHSERPARENT,CHSERTRENDLINE,,,CHFORMAT,CHPOS + 0x1050=CHFORMATRUNS,CHSOURCELINK,,,,,, + 0x1058=,,,CHSERERRORBAR,,CHSERIESFORMAT,, +end + +multilist=RECORD-NAMES-BIFF8 + include=RECORD-NAMES-BIFF5 + # worksheet/workbook records + 0x00E0=,,,,,CELLMERGING,, + 0x00E8=,BITMAP,,MSODRAWINGGROUP,MSODRAWING,MSODRAWINGSELECTION,,PHONETICPR + 0x00F0=SXRULE,SXEX,SXFILT,,,,SXNAME,SXSELECT + 0x00F8=SXPAIR,SXFMLA,,SXFORMAT,SST,LABELSST,,EXTSST + 0x0100=SXVDEX,,,SXFORMULA,,,, + 0x0120=,,SXDBEX,,,,, + 0x0130=,,,,,,,CHTRINSERT + 0x0138=CHTRINFO,,,CHTRCELLCONTENT,,TABID,, + 0x0140=CHTRMOVERANGE,,,,,,, + 0x0148=,,,,,CHTRINSERTTAB,, + 0x0158=,,,,,,,LABELRANGES + 0x0160=USESELFS,DSF,XL5MODIFY,,,,, + 0x0190=,,,,,,CHTRHEADER, + 0x01A8=,USERBVIEW,USERSVIEWBEGIN,USERSVIEWEND,,QSI,EXTERNALBOOK,PROT4REV + 0x01B0=CFHEADER,CFRULE,DATAVALIDATIONS,,,DCONBIN,TXO,REFRESHALL + 0x01B8=HYPERLINK,NLRDELNAME,CODENAME,SXFDBTYPE,PROT4REVPASS,,DATAVALIDATION, + 0x0800=SCREENTIP,,,WEBQRYSETTINGS,WEBQRYTABLES,,, + 0x0850=,CHWRAPPEDRECORD,,,,,,CHUNITPROPERTIES + 0x0858=CHPIVOTREF,,,,,,, + 0x0860=,,SHEETLAYOUT,,,,,SHEETPROTECTION + # chart records + 0x1058=,,,,,,,CH3DDATAFORMAT + 0x1060=CHFONTBASE,CHPIEEXT,CHLABELRANGE2,CHDATATABLE,CHPLOTGROWTH,CHSERINDEX,CHESCHERFORMAT,CHPIEEXTSETT +end + +# simple records ------------------------------------------------------------- + +constlist=SIMPLE-RECORDS-BIFF2 + 0x000C=uint16,dec,max-iterations + 0x000D=int16,dec,calc-mode,CALCMODE + 0x000E=uint16,bool,calc-precise + 0x000F=uint16,dec,ref-mode,REFMODE + 0x0010=double,dec,epsilon + 0x0011=uint16,bool,iterate-recursive + 0x0012=uint16,bool,workbook-protected + 0x0013=uint16,hex,password-hash + 0x0016=uint16,dec,externsheets + 0x0019=uint16,bool,window-protected + 0x001F=uint16,dec,builtin-fmt-count + 0x0022=uint16,dec,null-date,DATEMODE + 0x0025=uint16,hex,rowheight-flags,DEFROWHEIGHT-FLAGS + 0x0026=double,dec,left-margin,CONV-INCH-TO-CM + 0x0027=double,dec,right-margin,CONV-INCH-TO-CM + 0x0028=double,dec,top-margin,CONV-INCH-TO-CM + 0x0029=double,dec,bottom-margin,CONV-INCH-TO-CM + 0x002A=uint16,bool,print-sheet-headers + 0x002B=uint16,bool,print-gridlines + 0x0040=uint16,bool,backup-on-save + 0x0044=uint16,dec,xf-idx + 0x0045=uint16,dec,font-color-idx,COLORS + 0x0055=uint16,dec,base-col-width + 0x100B=uint16,dec,extrusion,CONV-PERCENT + 0x100C=uint16,hex,flags,CHATTACHEDLABEL-FLAGS + 0x1018=uint16,hex,flags,CHLINE-FLAGS + 0x101A=uint16,hex,flags,CHAREA-FLAGS + 0x101C=uint16,dec,line-type,CHCHARTLINE-TYPE + 0x1021=uint16,dec,axisline-id,CHAXISLINE-ID + 0x1024=uint16,dec,text-idx + 0x1026=uint16,dec,font-idx,FONTNAMES + 0x1045=uint16,dec,group-idx + 0x1046=uint16,dec,used-axessets + 0x104A=uint16,dec,series-idx + 0x104E=uint16,dec,fmt-idx,FORMATS +end + +constlist=SIMPLE-RECORDS-BIFF3 + include=SIMPLE-RECORDS-BIFF2 + 0x0056=uint16,dec,builtin-fmt-count + 0x005E=uint16,unused + 0x005F=uint16,bool,recalc-on-save + 0x0063=uint16,bool,objects-protected + 0x0081=uint16,hex,flags,SHEETPR-FLAGS + 0x0082=uint16,bool,print-gridlines-changed + 0x0083=uint16,bool,horizontal-centered + 0x0084=uint16,bool,vertical-centered + 0x008D=uint16,dec,object-mode,HIDEOBJ +end + +constlist=SIMPLE-RECORDS-BIFF4 + include=SIMPLE-RECORDS-BIFF3 + 0x008E=uint32,hex,stream-pos,CONV-DEC + 0x0099=uint16,dec,default-col-width,CONV-COLWIDTH + 0x009C=uint16,dec,func-group-count + 0x103D=uint16,dec,bar-dist + 0x103E=uint16,hex,flags,CHRADAR-FLAGS + 0x103F=uint16,hex,flags,CHSURFACE-FLAGS +end + +constlist=SIMPLE-RECORDS-BIFF5 + include=SIMPLE-RECORDS-BIFF4 + 0x00C9=double,dec,value + 0x00CA=uint16,bool,value + 0x00CB=uint16,hex,error-code,ERRORCODES + 0x00CC=int16,dec,value + 0x00D5=uint16,hex,pivotcache-stream-id + 0x00D8=uint16,hex,flags,SXNUMGROUP-FLAGS + 0x00DA=uint16,bool,strip-cached-values + 0x00DD=uint16,bool,scenarios-protected + 0x00E3=uint16,dec,source-type,SXVS-TYPE + 0x1040=uint16,hex,flags,CHRADAR-FLAGS + 0x105D=uint16,hex,flags,CHSERIESFORMAT-FLAGS +end + +constlist=SIMPLE-RECORDS-BIFF8 + include=SIMPLE-RECORDS-BIFF5 + 0x00E1=uint16,dec,codepage,CODEPAGES + 0x0160=uint16,bool,use-nat-lang-refs + 0x0161=uint16,bool,double-stream + 0x01AF=uint16,bool,revlog-protected + 0x01B7=uint16,bool,refresh-all + 0x01BB=uint16,dec,sql-data-type,SXFDBTYPE-DATATYPE + 0x01BC=uint16,hex,password-hash + 0x1065=uint16,dec,series-idx +end + +# ARRAY ---------------------------------------------------------------------- + +flagslist=ARRAY-FLAGS-BIFF2 + 0x0001=recalc-always +end + +flagslist=ARRAY-FLAGS-BIFF3 + include=ARRAY-FLAGS-BIFF2 + 0x0002=recalc-onload +end + +# BOF ------------------------------------------------------------------------ + +constlist=BOF-BIFFTYPE + 0x0000=from-id + 0x0007=biff2 + 0x0200=biff2 + 0x0300=biff3 + 0x0400=biff4 + 0x0500=biff5 + 0x0600=biff8 +end + +constlist=BOF-SHEETTYPE + 0x0005=globals + 0x0006=vb-module + 0x0010=sheet + 0x0020=chart + 0x0040=macro + 0x0100=workspace +end + +flagslist=BOF-HISTORY-FLAGS + 0x00000001=windows + 0x00000002=risc + 0x00000004=beta + 0x00000008=win-any + 0x00000010=mac-any + 0x00000020=beta-any + 0x00000100=risc-any + # missing mac here? +end + +# CALCMODE ------------------------------------------------------------------- + +shortlist=CALCMODE,-1,automatic-no-table,manual,automatic + +# CFRULE --------------------------------------------------------------------- + +shortlist=CFRULE-TYPE,1,value,formula +shortlist=CFRULE-OPERATOR,0,none,between,not-between,equal,not-equal,greater-than,less-than,greater-equal,less-equal + +flagslist=CFRULE-FLAGS + ignore=0x00380080 + 0x00000001=!hor-align-used + 0x00000002=!vert-align-used + 0x00000004=!text-wrap-used + 0x00000008=!rotation-used + 0x00000010=!justify-lastline-used + 0x00000020=!indent-used + 0x00000040=!shrinktofit-used + 0x00000100=!cell-locked-used + 0x00000200=!cell-hidden-used + 0x00000400=!left-border-used + 0x00000800=!right-border-used + 0x00001000=!top-border-used + 0x00002000=!bottom-border-used + 0x00004000=!tl-to-br-used + 0x00008000=!bl-to-tr-used + 0x00010000=!fill-pattern-used + 0x00020000=!fg-color-idx-used + 0x00040000=!bg-color-idx-used + 0x04000000=font-block + 0x08000000=alignment-block + 0x10000000=border-block + 0x20000000=pattern-block + 0x40000000=protection-block + 0x80000000=!text-dir-used +end + +combilist=CFRULE-ALIGNMENT + 0x07=uint8,dec,hor-align,XF-HORALIGN + 0x08=text-wrap + 0x70=uint8,dec,ver-align,XF-VERALIGN + 0x80=justify-lastline +end + +combilist=CFRULE-INDENT + 0x000F=uint8,dec,indent + 0x0010=shrink-to-fit + 0x00C0=uint8,dec,text-dir,XF-TEXTDIRECTION +end + +flagslist=CFRULE-FONTFLAGS + 0x00000002=italic + 0x00000008=outline + 0x00000010=shadow + 0x00000020=condense + 0x00000040=extend + 0x00000080=strikeout +end + +flagslist=CFRULE-FONTUSEDFLAGS + 0x00000002=!italic-used + 0x00000008=!outline-used + 0x00000010=!shadow-used + 0x00000020=!condense-used + 0x00000040=!extend-used + 0x00000080=!strikeout-used +end + +constlist=CFRULE-FONTUSED + 0=used + 1=not-used +end + +combilist=CFRULE-BORDERCOLOR2 + 0x0000007F=uint8,dec,top-color,COLORS + 0x00003F80=uint8,dec,bottom-color,COLORS + 0x001FC000=uint8,dec,diag-color,COLORS + 0x01E00000=uint8,dec,diag-style,BORDERSTYLES +end + +combilist=CFRULE-FILLBLOCK + 0x0000FC00=uint8,dec,fill-pattern,FILLPATTERNS + 0x007F0000=uint8,dec,fg-color-idx,COLORS + 0x3F800000=uint8,dec,bg-color-idx,COLORS +end + +flagslist=CFRULE-PROTECTION-FLAGS + 0x0001=locked + 0x0002=formula-hidden +end + +# CH3DDATAFORMAT ------------------------------------------------------------- + +shortlist=CH3DDATAFORMAT-BASE,0,rectangular,circular +shortlist=CH3DDATAFORMAT-TOP,0,straight,sharp,trunc + +# CHAREA --------------------------------------------------------------------- + +flagslist=CHAREA-FLAGS + 0x0001=stacked + 0x0002=percent + 0x0004=shadow +end + +# CHAREAFORMAT --------------------------------------------------------------- + +flagslist=CHAREAFORMAT-FLAGS + 0x0001=auto + 0x0002=swap-negative +end + +# CHATTACHEDLABEL ------------------------------------------------------------ + +flagslist=CHATTACHEDLABEL-FLAGS + 0x0001=show-value + 0x0002=show-percent + 0x0004=show-categ-percent + 0x0008=smoothed + 0x0010=show-categ + 0x0020=show-bubble +end + +# CHAXESSET ------------------------------------------------------------------ + +shortlist=CHAXESSET-ID,0,primary,secondary + +# CHAXIS --------------------------------------------------------------------- + +shortlist=CHAXIS-TYPE,0,x-axis,y-axis,z-axis + +# CHAXISLINE ----------------------------------------------------------------- + +shortlist=CHAXISLINE-ID,0,axisline,major-grid,minor-grid,wall + +# CHBAR ---------------------------------------------------------------------- + +flagslist=CHBAR-FLAGS + 0x0001=horizontal + 0x0002=stacked + 0x0004=percent + 0x0008=shadow +end + +# CHCHART3D ------------------------------------------------------------------ + +flagslist=CHCHART3D-FLAGS + ignore=0x0010 + 0x0001=real3d + 0x0002=clustered + 0x0004=auto-height + 0x0020=2d-plotarea +end + +# CHTYPEGROUP ---------------------------------------------------------------- + +flagslist=CHTYPEGROUP-FLAGS + 0x0001=varied-colors +end + +# CHCHARTLINE ---------------------------------------------------------------- + +shortlist=CHCHARTLINE-TYPE,0,drop-line,hi-lo-line,series-connector + +# CHDATAFORMAT --------------------------------------------------------------- + +constlist=CHDATAFORMAT-POINTIDX + default= + -1=all-points +end + +constlist=CHDATAFORMAT-FORMATIDX + default= + -3=axesset-global +end + +flagslist=CHDATAFORMAT-FLAGS + 0x0001=excel4-colors +end + +# CHFRAME -------------------------------------------------------------------- + +shortlist=CHFRAME-FORMAT,0,standard,,,,shadow + +flagslist=CHFRAME-FLAGS + 0x0001=auto-size + 0x0002=auto-pos +end + +# CHFRAMEPOS ----------------------------------------------------------------- + +shortlist=CHFRAMEPOS-OBJTYPE,2,any,,,legend +shortlist=CHFRAMEPOS-SIZEMODE,1,manual,auto + +# CHLABELRANGE --------------------------------------------------------------- + +flagslist=CHLABELRANGE-FLAGS + 0x0001=cross-between-categ + 0x0002=maximum-axis-cross + 0x0004=reverse-order +end + +# CHLABELRANGE2 -------------------------------------------------------------- + +flagslist=CHLABELRANGE2-FLAGS + 0x0001=auto-minimum + 0x0002=auto-maximum + 0x0004=auto-major + 0x0008=auto-minor + 0x0010=date-axis + 0x0020=auto-base + 0x0040=auto-axis-cross + 0x0080=auto-date +end + +# CHLEGEND ------------------------------------------------------------------- + +shortlist=CHLEGEND-DOCKPOS,0,bottom,top-left,top,right,left,,,manual +shortlist=CHLEGEND-SPACING,0,close,medium,open + +flagslist=CHLEGEND-FLAGS + 0x0001=docked + 0x0002=auto-series + 0x0004=auto-pos-x + 0x0008=auto-pos-y + 0x0010=stacked + 0x0020=data-table +end + +# CHLINE --------------------------------------------------------------------- + +flagslist=CHLINE-FLAGS + 0x0001=stacked + 0x0002=percent + 0x0004=shadow +end + +# CHLINEFORMAT --------------------------------------------------------------- + +shortlist=CHLINEFORMAT-LINETYPE,0,solid,dash,dot,dash-dot,dash-dot-dot,none,25%-pattern,50%-pattern,75%-pattern +shortlist=CHLINEFORMAT-LINEWEIGHT,-1,hair,thin,medium,thick + +flagslist=CHLINEFORMAT-FLAGS + 0x0001=auto + 0x0004=axis-enabled +end + +# CHMARKERFORMAT ------------------------------------------------------------- + +shortlist=CHMARKERFORMAT-TYPE,0,none,square,diamond,triangle,cross,star,dow-jones,std-dev,circle,plus + +flagslist=CHMARKERFORMAT-FLAGS + 0x0001=auto + 0x0010=no-fill + 0x0020=no-border +end + +# CHOBJECTLINK --------------------------------------------------------------- + +shortlist=CHOBJECTLINK-TARGET,0,none,title,y-axis,x-axis,datapoint,legend,none,z-axis,,,,,axis-unit + +constlist=CHOBJECTLINK-POINT + default= + -2=unknown + -1=all-points +end + +# CHPICFORMAT ---------------------------------------------------------------- + +shortlist=CHPICFORMAT-BITMAP-MODE,1,stretched,stacked,stacked-scaled + +constlist=CHPICFORMAT-IMAGE-FORMAT + 2=wmf + 9=bmp + 19=?emf +end + +shortlist=CHPICFORMAT-ENV,1,windows,apple + +combilist=CHPICFORMAT-FLAGS + 0x00FF=uint16,dec,environment,CHPICFORMAT-ENV + 0x0100=format-only + 0x0200=top-bottom + 0x0400=front-back + 0x0800=left-right +end + +# CHPIE ---------------------------------------------------------------------- + +flagslist=CHPIE-FLAGS + 0x0001=shadow + 0x0002=connectors +end + +# CHRADAR, CHRADARAREA ------------------------------------------------------- + +flagslist=CHRADAR-FLAGS + 0x0001=axis-labels + 0x0002=shadow +end + +# CHPROPERTIES --------------------------------------------------------------- + +shortlist=CHPROPERTIES-EMPTYCELLS,0,do-not-plot,as-zero,interpolated + +flagslist=CHPROPERTIES-FLAGS + 0x0001=manual-format + 0x0002=plot-visible-only + 0x0004=fixed-size + 0x0008=manual-plotarea +end + +# CHSCATTER ------------------------------------------------------------------ + +shortlist=CHSCATTER-SIZETYPE,0,none,area,width + +flagslist=CHSCATTER-FLAGS + 0x0001=bubbles + 0x0002=show-negative + 0x0004=shadow +end + +# CHSERERRORBAR -------------------------------------------------------------- + +shortlist=CHSERERRORBAR-TYPE,1,x-plus,x-minus,y-plus,y-minus +shortlist=CHSERERRORBAR-SOURCE,1,percent,fixed,std-deviation,custom,std-error + +# CHSERIES ------------------------------------------------------------------- + +shortlist=CHSERIES-TYPE,0,date,numeric,sequence,text + +# CHSERIESFORMAT ------------------------------------------------------------- + +flagslist=CHSERIESFORMAT-FLAGS + 0x0001=spline + 0x0002=bubbles-3d + 0x0004=shadow +end + +# CHSERTRENDLINE ------------------------------------------------------------- + +shortlist=CHSERTRENDLINE-TYPE,0,poynomial,exponential,logarithmic,power,moving-average + +# CHSOURCELINK --------------------------------------------------------------- + +shortlist=CHSOURCELINK-TARGET,0,title,values,category,bubbles +shortlist=CHSOURCELINK-TYPE,0,default,constant,sheet-link + +flagslist=CHSOURCELINK-FLAGS + 0x0001=custom-numfmt +end + +# CHSTRING ------------------------------------------------------------------- + +shortlist=CHSTRING-TYPE,0,text,category-default,value-default,x-prefix,x-postfix,y-prefix,y-postfix,comment + +# CHSURFACE ------------------------------------------------------------------ + +flagslist=CHSURFACE-FLAGS + 0x0001=filled + 0x0002=shadow +end + +# CHTEXT --------------------------------------------------------------------- + +shortlist=CHTEXT-HORALIGN,1,left,center,right,block,distribute +shortlist=CHTEXT-VERALIGN,1,top,center,bottom,block,distribute +shortlist=CHTEXT-FILLMODE,1,transparent,opaque + +combilist=CHTEXT-FLAGS-BIFF2 + 0x0001=auto-color + 0x0002=show-symbol + 0x0004=show-value + 0x0008=vertical + 0x0010=auto-text + 0x0020=default-format + 0x0040=deleted + 0x0080=auto-fill +end + +combilist=CHTEXT-FLAGS-BIFF3 + include=CHTEXT-FLAGS-BIFF2 + 0x0700=uint8,dec,orientation,TEXTORIENTATION +end + +combilist=CHTEXT-FLAGS-BIFF5 + include=CHTEXT-FLAGS-BIFF3 + 0x0800=show-categ-percent + 0x1000=show-percent +end + +combilist=CHTEXT-FLAGS-BIFF8 + include=CHTEXT-FLAGS-BIFF5 + 0x2000=show-bubble-size + 0x4000=show-categ +end + +multilist=CHTEXT-PLACEMENT + default= + 0=context,outside,inside,center,axis,above,below,left,right,auto,manual +end + +# CHTICK --------------------------------------------------------------------- + +shortlist=CHTICK-TYPE,0,none,inside,outside,both +# TODO: really different label positions in BIFF2-BIFF4? +shortlist=CHTICK-LABELPOS-BIFF2,0,none,near,below,above +shortlist=CHTICK-LABELPOS-BIFF5,0,none,below,above,near + +flagslist=CHTICK-FLAGS-BIFF2 + 0x0001=auto-color + 0x0002=auto-fill +end + +combilist=CHTICK-FLAGS-BIFF3 + include=CHTICK-FLAGS-BIFF2 + 0x001C=uint8,dec,orientation,TEXTORIENTATION + 0x0020=auto-rotation +end + +# CHUNITPROPERTIES ----------------------------------------------------------- + +shortlist=CHUNITPROPERTIES-PRESET,-1,manual,none,hundred,thousand,(10000),(100000),million,(10million),(100million),billion,trillion + +flagslist=CHUNITPROPERTIES-FLAGS + 0x0002=show-unit +end + +# CHVALUERANGE --------------------------------------------------------------- + +flagslist=CHVALUERANGE-FLAGS + ignore=0x0100 + 0x0001=auto-minimum + 0x0002=auto-maximum + 0x0004=auto-major + 0x0008=auto-minor + 0x0010=auto-axis-cross + 0x0020=logarithmic + 0x0040=reverse-order + 0x0080=maximum-axis-cross +end + +# COLINFO -------------------------------------------------------------------- + +combilist=COLINFO-FLAGS + 0x0001=hidden + 0x0002=custom-width + 0x0004=best-fit + 0x0700=uint8,dec,outline-level + 0x1000=outline-collapsed +end + +# DATATABLE ------------------------------------------------------------------ + +flagslist=DATATABLE-FLAGS-BIFF3 + 0x0001=recalc-always + 0x0002=recalc-on-load + 0x0004=row-table + 0x0008=table-2d +end + +flagslist=DATATABLE-FLAGS-BIFF8 + include=DATATABLE-FLAGS-BIFF3 + 0x0010=ref1-deleted + 0x0020=ref2-deleted +end + +# DATAVALIDATION ------------------------------------------------------------- + +combilist=DATAVALIDATION-FLAGS + 0x0000000F=uint8,dec,type,DATAVALIDATION-TYPE + 0x00000070=uint8,dec,error-style,DATAVALIDATION-ERRORSTYLE + 0x00000080=string-list + 0x00000100=ignore-empty + 0x00000200=no-dropdown + 0x00040000=show-input-box + 0x00080000=show-error-box + 0x00F00000=uint8,dec,operator,DATAVALIDATION-OPERATOR +end + +shortlist=DATAVALIDATION-TYPE,0,any,whole,decimal,list,date,time,text-length,custom +shortlist=DATAVALIDATION-OPERATOR,0,between,not-between,equal,not-equal,greater-than,less-than,greater-equal,less-equal +shortlist=DATAVALIDATION-ERRORSTYLE,0,error,warning,info + +# DATAVALIDATIONS ------------------------------------------------------------ + +flagslist=DATAVALIDATIONS-FLAGS + 0x0001=input-box-visible + 0x0002=input-box-at-cell + 0x0004=cached +end + +# DATEMODE ------------------------------------------------------------------- + +shortlist=DATEMODE,0,1899-12-31,1904-01-01 + +# DEFINEDNAME ---------------------------------------------------------------- + +flagslist=DEFINEDNAME-FLAGS-BIFF2 + 0x02=macro + 0x04=complex +end + +shortlist=DEFINEDNAME-MACROTYPE-BIFF2,0,none,function,procedure + +flagslist=DEFINEDNAME-FLAGS-BIFF3 + 0x0001=hidden + 0x0002=function + 0x0004=command + 0x0008=macro + 0x0010=complex + 0x0020=builtin +end + +combilist=DEFINEDNAME-FLAGS-BIFF4 + include=DEFINEDNAME-FLAGS-BIFF3 + 0x0FC0=uint16,dec,func-group,DEFINEDNAME-FUNCGROUP +end + +combilist=DEFINEDNAME-FLAGS-BIFF5 + include=DEFINEDNAME-FLAGS-BIFF4 + 0x0004=vba + 0x1000=binary +end + +shortlist=DEFINEDNAME-FUNCGROUP,0,none,financial,date-time,math-trig,statistical,lookup-ref,database,text,logical,information,commands,customizing,macro-control,dde-external,user-definded + +constlist=DEFINEDNAME-SHEETIDX + default= + 0=global +end + +# DEFROWHEIGHT --------------------------------------------------------------- + +combilist=DEFROWHEIGHT-FLAGS-BIFF2 + 0x7FFF=uint16,dec,row-height,CONV-TWIP-TO-PT + 0x8000=unchanged +end + +flagslist=DEFROWHEIGHT-FLAGS-BIFF3 + 0x0001=custom-height + 0x0002=hidden + 0x0004=thick-top + 0x0008=thick-bottom +end + +# EXTERNALBOOK --------------------------------------------------------------- + +constlist=EXTERNALBOOK-KEY + 0x0401=self-reference + 0x3A01=analysis-addin +end + +# EXTERNALNAME --------------------------------------------------------------- + +flagslist=EXTERNALNAME-FLAGS-BIFF3 + 0x0001=builtin + 0x0002=automatic + 0x0004=pic-link +end + +combilist=EXTERNALNAME-FLAGS-BIFF5 + include=EXTERNALNAME-FLAGS-BIFF3 + 0x0008=dde-stddocumentname + 0x0010=ole-link + 0x7FE0=uint16,dec,clipboard-format + 0x8000=iconified +end + +# EXTERNSHEET ---------------------------------------------------------------- + +constlist=EXTERNSHEET-IDX-BIFF8 + default= + -1=deleted + -2=special +end + +# FONT ----------------------------------------------------------------------- + +flagslist=FONT-FLAGS + 0x0001=bold + 0x0002=italic + 0x0004=underline + 0x0008=strikeout + 0x0010=outline + 0x0020=shadow + 0x0040=condense + 0x0080=extend +end + +constlist=FONT-WEIGHT + 400=normal + 700=bold +end + +multilist=FONT-UNDERLINE + 0x00=none,single,double + 0x21=single-acc,double-acc +end + +shortlist=FONT-ESCAPEMENT,0,none,superscript,subscript +shortlist=FONT-FAMILY,0,none,roman,swiss,modern,script,decorative + +# FORMULA -------------------------------------------------------------------- + +flagslist=FORMULA-FLAGS-BIFF2 + 0x0001=recalc-always +end + +flagslist=FORMULA-FLAGS-BIFF3 + include=FORMULA-FLAGS-BIFF2 + 0x0002=recalc-onload +end + +flagslist=FORMULA-FLAGS-BIFF5 + include=FORMULA-FLAGS-BIFF3 + 0x0008=shared-fmla +end + +shortlist=FORMULA-RESULTTYPE,0,string,boolean,error,empty + +# HIDEOBJ -------------------------------------------------------------------- + +shortlist=HIDEOBJ,0,show,placeholder,hide + +# HYPERLINK ------------------------------------------------------------------ + +79EAC9D0-BAF9-11CE-8C82-00AA004BA90B=StdHlink +00000303-0000-0000-C000-000000000046=FileMoniker +79EAC9E0-BAF9-11CE-8C82-00AA004BA90B=URLMoniker + +flagslist=HYPERLINK-FLAGS + 0x00000001=target + 0x00000002=absolute + 0x00000004=display-1 + 0x00000008=location + 0x00000010=display-2 + 0x00000080=frame + 0x00000100=unc-path +end + +# OBJ ------------------------------------------------------------------------ + +multilist=OBJ-TYPE-BIFF5 + 0=group,line,rect,oval,arc,chart,textbox,button,pic,polygon + 10=,checkbox,optbutton,edit,label,dialog,spin,scrollbar,listbox,groupbox + 20=dropdown +end + +flagslist=OBJ-FLAGS-BIFF5 + 0x0001=selected + 0x0002=auto-size + 0x0004=auto-move + 0x0010=protected + 0x0080=grouped + 0x0100=hidden + 0x0200=visible + 0x0400=printable +end + +flagslist=OBJ-FLAGS-AUTO-BIFF5 + 0x0001=auto +end + +shortlist=OBJ-LINETYPE,0,solid,dash,dot,dash-dot,dash-dot-dot,25%-pattern,50%-pattern,75%-pattern +shortlist=OBJ-LINEWEIGHT,0,hair,thin,medium,thick + +shortlist=OBJ-ARROWHEAD-TYPE-BIFF5,0,none,open,filled,double-end-open,double-end-filled +shortlist=OBJ-ARROWHEAD-WIDTH-BIFF5,0,narrow,medium,wide +shortlist=OBJ-ARROWHEAD-LENGTH-BIFF5,0,short,medium,long + +combilist=OBJ-LINEENDS-BIFF5 + 0x000F=uint8,dec,arrowhead-type,OBJ-ARROWHEAD-TYPE + 0x00F0=uint8,dec,arrowhead-width,OBJ-ARROWHEAD-WIDTH + 0x0F00=uint8,dec,arrowhead-length,OBJ-ARROWHEAD-LENGTH +end + +shortlist=OBJ-LINEDIR-BIFF5,0,topleft-to-bottomright,topright-to-bottomleft,bottomright-to-topleft,bottomleft-to-topright + +combilist=OBJ-FRAMESTYLE-FLAGS-BIFF5 + 0x0001=rounded + 0x0002=shadow + 0x03FC=uint16,dec,rounded-diameter +end + +flagslist=OBJ-CHART-FLAGS-BIFF5 + 0x0001=linked-to-sheet +end + +multilist=OBJ-RECNAMES-BIFF8 + 0x0000=OBJEND,,,,OBJMACRO,,OBJGMO,OBJCF + 0x0008=OBJPIOGRBIT,OBJPICTFMLA,OBJCBLS,,OBJSBS,,OBJSBSFMLA,OBJGBODATA + 0x0010=,,,OBJLBSDATA,OBJCBLSFMLA,OBJCMO,, +end + +flagslist=OBJPIOGRBIT-FLAGS + 0x0001=manual-size + 0x0002=linked + 0x0008=symbol + 0x0010=control + 0x0020=ctls-stream + 0x0200=auto-load +end + +shortlist=OBJPICTFMLA-HASCLASSNAME,0,false,,,true + +multilist=OBJCMO-TYPE + include=OBJ-TYPE-BIFF5 + 25=note + 30=drawing +end + +flagslist=OBJCMO-FLAGS + 0x0001=locked + 0x0010=printable + 0x2000=auto-line + 0x4000=auto-area +end + +# PAGESETUP ------------------------------------------------------------------ + +multilist=PAGESETUP-PAPERSIZE + 0=undefined,letter,letter-small,tabloid,ledger,legal,statement,executive,a3,a4 + 10=a4-small,a5,b4,b5,folio,quarto,10x14,11x17,note,envelope-9 + 20=envelope-10,envelope-11,envelope-12,envelope-14,c,d,e,envelope-dl,envelope-c5,envelope-c3 + 30=envelope-c4,envelope-c6,envelope-c65,envelope-b4,envelope-b5,envelope-b6,envelope-italy,envelope-monarch,envelope-6-3/4,us-standard-fanfold + 40=german-standard-fanfold,german-legal-fanfold,b4,japanese-dbl-postcaed,9x11,10x11,15x11,, + 50=envelope-invite,letter-extra,legal-extra,tabloid-extra,a4-extra,letter-transverse,a4-transverse,letter-extra-transverse,super-a-a4,super-b-a3,letter-plus + 60=a4-plus,a5-transverse,jis-b5-transverse,a3-extra,a5-extra,b5-extra,a2,a3-transverse,a3-extra-transverse +end + +constlist=PAGESETUP-SCALETOPAGES + default= + 0=automatic +end + +flagslist=PAGESETUP-FLAGS-BIFF4 + 0x0001=print-in-rows + 0x0002=portrait + 0x0004=uninitialized + 0x0008=black-and-white +end + +flagslist=PAGESETUP-FLAGS-BIFF5 + include=PAGESETUP-FLAGS-BIFF4 + 0x0010=draft-quality + 0x0020=print-notes + 0x0040=default-orientation + 0x0080=use-first-page +end + +combilist=PAGESETUP-FLAGS-BIFF8 + include=PAGESETUP-FLAGS-BIFF5 + 0x0200=print-notes-at-end + 0x0C00=uint8,dec,print-errors,PAGESETUP-PRINTERRORS +end + +shortlist=PAGESETUP-PRINTERRORS,0,displayed,none,as-dashes,as-na + +unitconverter=PAGESETUP-DPI,1,dpi + +# PANE ----------------------------------------------------------------------- + +shortlist=PANE-ID,0,bottom-right,top-right,bottom-left,top-left + +# PHONETICPR ----------------------------------------------------------------- + +shortlist=PHONETICPR-TYPE,0,halfwidth-katakana,fullwidth-katakana,hiragana,no-conversion +shortlist=PHONETICPR-ALIGNMENT,0,no-control,left,center,distributed + +combilist=PHONETICPR-FLAGS + ignore=0x0030 + 0x0003=uint8,dec,type,PHONETICPR-TYPE + 0x000C=uint8,dec,alignment,PHONETICPR-ALIGNMENT +end + +# PROJEXTSHEET --------------------------------------------------------------- + +shortlist=PROJEXTSHEET-TYPE,0,sheet,macro,chart + +# REFMODE -------------------------------------------------------------------- + +shortlist=REFMODE,0,R1C1,A1 + +# ROW ------------------------------------------------------------------------ + +combilist=ROW-HEIGHT + 0x7FFF=uint16,dec,height,CONV-TWIP-TO-PT + 0x8000=default-height +end + +combilist=ROW-FLAGS + ignore=0x00000100 + 0x00000007=uint8,dec,outline-level + 0x00000010=outline-collapsed + 0x00000020=hidden + 0x00000040=custom-height + 0x00000080=custom-format + 0x0FFF0000=uint16,dec,custom-xf-idx + 0x10000000=thick-top + 0x20000000=thick-bottom + 0x40000000=show-phonetic +end + +# SHEET ---------------------------------------------------------------------- + +shortlist=SHEET-STATE,0,visible,hidden,very-hidden +shortlist=SHEET-TYPE,0,worksheet,,chart,,,,vb-module + +# SHEETPR -------------------------------------------------------------------- + +shortlist=SHEETPR-WINDOWPOS,0,tiled,horizontal,vertical,cascaded + +flagslist=SHEETPR-FLAGS-BIFF3 + 0x0001=show-autopagebreaks + 0x0010=dialog-sheet + 0x0020=outline-auto-style + 0x0040=outline-symbols-below + 0x0080=outline-symbols-right + 0x0100=fit-to-pages + 0x0200=skip-linked-values + 0x0400=show-row-outline + 0x0800=show-column-outline +end + +flagslist=SHEETPR-FLAGS-BIFF4 + include=SHEETPR-FLAGS-BIFF3 + 0x3000=uint8,dec,window-pos,SHEETPR-WINDOWPOS + 0x4000=lotus-expr-eval + 0x8000=lotus-formula-edit +end + +flagslist=SHEETPR-FLAGS-BIFF5 + include=SHEETPR-FLAGS-BIFF4 + exclude=0x0200,0x3000 +end + +# SHEETPROTECTION ------------------------------------------------------------ + +flagslist=SHEETPROTECTION-FLAGS + 0x0001=edit-object + 0x0002=edit-scenario + 0x0004=format-cell + 0x0008=format-column + 0x0010=format-row + 0x0020=insert-column + 0x0040=insert-row + 0x0080=insert-hyperlink + 0x0100=delete-column + 0x0200=delete-row + 0x0400=select-locked + 0x0800=sort + 0x1000=use-autofilter + 0x2000=pivottable-report + 0x4000=select-unlocked +end + +# STYLE ---------------------------------------------------------------------- + +combilist=STYLE-FLAGS + 0x0FFF=uint16,dec,xf-idx + 0x8000=builtin +end + +shortlist=STYLE-BUILTIN,0,normal,rowlevel,collevel,comma,currency,percent,comma-0,currency-0,hyperlink,followed-hyperlink + +# common for pivot tables ---------------------------------------------------- + +constlist=SX-NAMELEN + default= + 0xFFFF=name-in-cache +end + +# SXDB ----------------------------------------------------------------------- + +flagslist=SXDB-FLAGS + 0x0001=save-data + 0x0002=invalid + 0x0004=refresh-on-load + 0x0008=opt-cache + 0x0010=backgr-query + 0x0020=enable-refresh +end + +constlist=SXDB-TYPE + 1=worksheet + 2=external + 4=consolidation + 8=scenario +end + +# SXDI ----------------------------------------------------------------------- + +shortlist=SXDI-FUNC,0,sum,count-all,average,max,min,product,count-num,std-dev,std-dev-p,variance,variance-p +shortlist=SXDI-FORMAT,0,normal,diff-from,percent-of,percent-diff-from,running-total-in,percent-of-row,percent-of-column,percent-of-total,index + +multilist=SXDI-BASEITEM + default= + 0x7FFB=previous-item,next-item +end + +# SXEXT ---------------------------------------------------------------------- + +combilist=SXEXT-FLAGS + 0x0007=uint8,dec,source-type,SXEXT-SOURCETYPE + 0x0008=odbc-connection + 0x0010=odbc-sql + 0x0020=server-pagefields + 0x0040=webquery + 0x0080=save-password + 0x0100=tables-html-only +end + +shortlist=SXEXT-SOURCETYPE,1,odbc,dao,,webquery + +# SXFDBTYPE ------------------------------------------------------------------ + +shortlist=SXFDBTYPE-DATATYPE,0,unknown,char,numeric,decimal,integer,small-int,float,real,double,datetime,,,var-char + +# SXFIELD -------------------------------------------------------------------- + +combilist=SXFIELD-FLAGS + 0x0001=has-items + 0x0002=postpone-items + 0x0004=calculated + 0x0008=has-child + 0x0010=numeric-group + 0x0020=16bit-indexes + 0x0DE0=uint16,hex,data-type,SXFIELD-TYPE,noshift +end + +constlist=SXFIELD-TYPE + 0x0000=none + 0x0480=string-only + 0x0520=integer-optdouble + 0x0560=double-only + 0x05A0=string-integer-optdouble + 0x05E0=string-double-only + 0x0900=date-only + 0x0980=date-empty-only + 0x0D00=date-number + 0x0D80=date-string-optnumber +end + +# SXLI ----------------------------------------------------------------------- + +shortlist=SXLI-ITEMTYPE,0,data,default,sum,count-num,average,max,min,product,count-num,std-dev,std-dev-p,variance,variance-p,grandtotal,blank-line + +combilist=SXLI-FLAGS + 0x0001=field-name + 0x01FE=uint16,dec,data-field-idx + 0x0200=subtotal + 0x0400=blocktotal + 0x0800=grandtotal + 0x1000=multi-data +end + +# SXNUMGROUP ----------------------------------------------------------------- + +combilist=SXNUMGROUP-FLAGS + 0x0001=auto-min + 0x0002=auto-max + 0x003C=uint8,dec,data-type,SXNUMGROUP-TYPE +end + +shortlist=SXNUMGROUP-TYPE,1,second,minute,hour,day,month,quarter,year,numeric + +# SXVD ----------------------------------------------------------------------- + +flagslist=SXVD-AXISTYPE + 0x0001=row + 0x0002=column + 0x0004=page + 0x0008=data +end + +flagslist=SXVD-SUBTOTALS + 0x0001=default + 0x0002=sum + 0x0004=count-all + 0x0008=average + 0x0010=max + 0x0020=min + 0x0040=product + 0x0080=count-num + 0x0100=std-dev + 0x0200=std-dev-p + 0x0400=variance + 0x0800=variance-p +end + +# SXVDEX --------------------------------------------------------------------- + +combilist=SXVDEX-FLAGS + 0x00000001=show-all-items + 0x00000002=drag-to-row + 0x00000004=drag-to-column + 0x00000008=drag-to-page + 0x00000010=drag-to-hide + 0x00000080=server-based + 0x00000200=autosort + 0x00000400=autosort-ascending + 0x00000800=autoshow + 0x00001000=autoshow-top-values + 0x00002000=calculated + 0x00200000=layout-report + 0x00400000=layout-blank + 0x00800000=layout-top + 0xFF000000=uint8,dec,autoshow-item-count +end + +# SXVI ----------------------------------------------------------------------- + +multilist=SXVI-ITEMTYPE + 0=data,default,sum,count-num,average,max,min,product,count-num,std-dev,std-dev-p,variance,variance-p,grandtotal + 254=page,none +end + +flagslist=SXVI-FLAGS + 0x0001=hidden + 0x0002=hide-detail + 0x0004=calculated + 0x0008=missing +end + +# SXVIEW --------------------------------------------------------------------- + +flagslist=SXVIEW-FLAGS + 0x0001=row-grandtotals + 0x0002=column-grandtotals + 0x0008=auto-format + 0x0010=size-auto-format + 0x0020=font-auto-format + 0x0040=align-auto-format + 0x0080=border-auto-format + 0x0100=pattern-auto-format + 0x0200=number-auto-format +end + +# SXVS ----------------------------------------------------------------------- + +flagslist=SXVS-TYPE + 0x0001=spreadsheet + 0x0002=extern + 0x0004=consolidation-area + 0x0008=pivot-table + 0x0010=scenario +end + +# WINDOW1 -------------------------------------------------------------------- + +flagslist=WINDOW1-FLAGS + 0x0001=hidden + 0x0002=minimized + 0x0008=show-horizontal-scroll + 0x0010=show-vertical-scroll + 0x0020=show-tabbar +end + +unitconverter=WINDOW1-TABBARRATIO,/10,% + +# WINDOW2 -------------------------------------------------------------------- + +flagslist=WINDOW2-FLAGS-BIFF3 + 0x0001=show-formulas + 0x0002=show-gridlines + 0x0004=show-headings + 0x0008=frozen-panes + 0x0010=show-zeros + 0x0020=default-gridcolor + 0x0040=right-to-left + 0x0080=show-outline-symbols + 0x0100=remove-split-with-freeze +end + +flagslist=WINDOW2-FLAGS-BIFF5 + include=WINDOW2-FLAGS-BIFF3 + 0x0200=sheet-selected + 0x0400=sheet-active +end + +flagslist=WINDOW2-FLAGS-BIFF8 + include=WINDOW2-FLAGS-BIFF5 + 0x0800=pagebreak-mode +end + +# XF ------------------------------------------------------------------------- + +shortlist=XF-HORALIGN,0,general,left,center,right,fill,block,center-across-sel,distribute +shortlist=XF-VERALIGN,0,top,center,bottom,justify,distribute +shortlist=XF-TEXTDIRECTION,0,context,left-to-right,right-to-left + +flagslist=XF-PROTECTION-FLAGS + 0x01=locked + 0x02=formula-hidden + 0x04=style-xf +end + +flagslist=XF-USEDATTRIBS-FLAGS + 0x04=format + 0x08=font + 0x10=alignment + 0x20=border + 0x40=area + 0x80=protection +end + +combilist=XF-STYLEFLAGS-BIFF2 + 0x07=uint8,dec,hor-align,XF-HORALIGN + 0x08=left-border + 0x10=right-border + 0x20=top-border + 0x40=bottom-border + 0x80=fill +end + +combilist=XF-TYPEFLAGS-BIFF2 + 0x3F=uint8,dec,fmt-idx,FORMATS + 0x40=locked + 0x80=formula-hidden +end + +flagslist=XF-TYPEFLAGS-BIFF3 + include=XF-PROTECTION-FLAGS +end + +combilist=XF-TYPEFLAGS-BIFF4 + include=XF-TYPEFLAGS-BIFF3 + 0xFFF0=uint16,dec,parent-xf-idx +end + +combilist=XF-ALIGNMENT-BIFF3 + 0x0007=uint8,dec,hor-align,XF-HORALIGN + 0x0008=text-wrap + 0xFFF0=uint16,dec,parent-xf-idx +end + +combilist=XF-ALIGNMENT-BIFF4 + 0x07=uint8,dec,hor-align,XF-HORALIGN + 0x08=text-wrap + 0x30=uint8,dec,ver-align,XF-VERALIGN + 0xC0=uint8,dec,orientation,TEXTORIENTATION +end + +combilist=XF-ALIGNMENT-BIFF5 + 0x07=uint8,dec,hor-align,XF-HORALIGN + 0x08=text-wrap + 0x70=uint8,dec,ver-align,XF-VERALIGN + 0x80=justify-lastline +end + +combilist=XF-ORIENTATTRIBS-BIFF5 + include=XF-USEDATTRIBS-FLAGS + 0x03=uint8,dec,orientation,TEXTORIENTATION +end + +combilist=XF-TEXTFLAGS-BIFF8 + 0x0F=uint8,dec,indent + 0x10=shrink-to-fit + 0xC0=uint8,dec,text-dir,XF-TEXTDIRECTION +end + +combilist=XF-FILL-BIFF3 + 0x003F=uint8,dec,fill-pattern,FILLPATTERNS + 0x07C0=uint8,dec,fg-color-idx,COLORS + 0xF800=uint8,dec,bg-color-idx,COLORS +end + +combilist=XF-BORDER-BIFF3 + 0x00000007=uint8,dec,top-style,BORDERSTYLES + 0x000000F8=uint8,dec,top-color,COLORS + 0x00000700=uint8,dec,left-style,BORDERSTYLES + 0x0000F800=uint8,dec,left-color,COLORS + 0x00070000=uint8,dec,bottom-style,BORDERSTYLES + 0x00F80000=uint8,dec,bottom-color,COLORS + 0x07000000=uint8,dec,right-style,BORDERSTYLES + 0xF8000000=uint8,dec,right-color,COLORS +end + +combilist=XF-FILL-BIFF5 + 0x0000007F=uint8,dec,fg-color-idx,COLORS + 0x00003F80=uint8,dec,bg-color-idx,COLORS + 0x003F0000=uint8,dec,fill-pattern,FILLPATTERNS + 0x01C00000=uint8,dec,bottom-style,BORDERSTYLES + 0xFE000000=uint8,dec,bottom-color,COLORS +end + +combilist=XF-BORDER-BIFF5 + 0x00000007=uint8,dec,top-style,BORDERSTYLES + 0x00000038=uint8,dec,left-style,BORDERSTYLES + 0x000001C0=uint8,dec,right-style,BORDERSTYLES + 0x0000FE00=uint8,dec,top-color,COLORS + 0x007F0000=uint8,dec,left-color,COLORS + 0x3F800000=uint8,dec,right-color,COLORS +end + +combilist=XF-BORDERSTYLE-BIFF8 + 0x000F=uint8,dec,left-style,BORDERSTYLES + 0x00F0=uint8,dec,right-style,BORDERSTYLES + 0x0F00=uint8,dec,top-style,BORDERSTYLES + 0xF000=uint8,dec,bottom-style,BORDERSTYLES +end + +combilist=XF-BORDERCOLOR1-BIFF8 + 0x007F=uint8,dec,left-color,COLORS + 0x3F80=uint8,dec,right-color,COLORS + 0x4000=diag-tl-to-br + 0x8000=diag-bl-to-tr +end + +combilist=XF-BORDERCOLOR2-BIFF8 + 0x0000007F=uint8,dec,top-color,COLORS + 0x00003F80=uint8,dec,bottom-color,COLORS + 0x001FC000=uint8,dec,diag-color,COLORS + 0x01E00000=uint8,dec,diag-style,BORDERSTYLES + 0xFC000000=uint8,dec,fill-pattern,FILLPATTERNS +end + +combilist=XF-FILLCOLOR-BIFF8 + 0x007F=uint8,dec,fg-color-idx,COLORS + 0x3F80=uint8,dec,bg-color-idx,COLORS +end + +# BIFF2 XF index field ------------------------------------------------------- + +constlist=XFINDEX-BIFF2 + default= + 63=from-ixfe +end + +combilist=CELL-XFINDEX-BIFF2 + 0x3F=uint8,dec,xf-idx,XFINDEX-BIFF2 + 0x40=locked + 0x80=formula-hidden +end + +combilist=CELL-XFFORMAT-BIFF2 + 0x3F=uint8,dec,fmt-idx,FORMATS + 0xC0=uint8,dec,font-idx,FONTNAMES +end + +combilist=CELL-XFSTYLE-BIFF2 + include=XF-STYLEFLAGS-BIFF2 +end + +# ============================================================================ + diff --git a/oox/source/dump/dffdumper.cxx b/oox/source/dump/dffdumper.cxx new file mode 100644 index 000000000000..cb9d1262efae --- /dev/null +++ b/oox/source/dump/dffdumper.cxx @@ -0,0 +1,212 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: dffdumper.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:58 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/dump/dffdumper.hxx" + +#if OOX_INCLUDE_DUMPER + +namespace oox { +namespace dump { + +// ============================================================================ + +DffRecordHeaderObject::DffRecordHeaderObject( const InputObjectBase& rParent ) +{ + static const RecordHeaderConfigInfo saHeaderCfgInfo = + { + "DFFREC", + "DFF-RECORD-NAMES", + "show-dff-record-pos", + "show-dff-record-size", + "show-dff-record-id", + "show-dff-record-name", + "show-dff-record-body", + }; + RecordHeaderBase< sal_uInt16, sal_uInt32 >::construct( rParent, saHeaderCfgInfo ); + if( RecordHeaderBase< sal_uInt16, sal_uInt32 >::implIsValid() ) + { + mxRecInst = cfg().getNameList( "DFF-RECORD-INST" ); + mnBodyStart = mnBodyEnd = 0; + mnInstVer = 0; + } +} + +bool DffRecordHeaderObject::implIsValid() const +{ + return isValid( mxRecInst ) && RecordHeaderBase< sal_uInt16, sal_uInt32 >::implIsValid(); +} + +bool DffRecordHeaderObject::implReadHeader( sal_Int64& ornRecPos, sal_uInt16& ornRecId, sal_uInt32& ornRecSize ) +{ + ornRecPos = in().tell(); + if( ornRecPos >= in().getSize() ) return false; + in() >> mnInstVer >> ornRecId >> ornRecSize; + mnBodyStart = in().tell(); + mnBodyEnd = ::std::min< sal_Int64 >( mnBodyStart + ornRecSize, in().getSize() ); + return in().isValidPos(); +} + +void DffRecordHeaderObject::implWriteExtHeader() +{ + writeHexItem( "instance", mnInstVer, mxRecInst ); +} + +// ============================================================================ + +DffDumpObject::DffDumpObject( const InputObjectBase& rParent ) +{ + InputObjectBase::construct( rParent ); + if( InputObjectBase::implIsValid() ) + mxHdrObj.reset( new DffRecordHeaderObject( *this ) ); +} + +DffDumpObject::~DffDumpObject() +{ +} + +void DffDumpObject::dumpDffClientPos( const sal_Char* pcName, sal_Int32 nSubScale ) +{ + MultiItemsGuard aMultiGuard( out() ); + TableGuard aTabGuard( out(), 17 ); + dumpDec< sal_uInt16 >( pcName ); + ItemGuard aItem( out(), "sub-units" ); + sal_uInt16 nSubUnits; + in() >> nSubUnits; + out().writeDec( nSubUnits ); + out().writeChar( '/' ); + out().writeDec( nSubScale ); +} + +void DffDumpObject::dumpDffClientRect() +{ + dumpDffClientPos( "start-col", 1024 ); + dumpDffClientPos( "start-row", 256 ); + dumpDffClientPos( "end-col", 1024 ); + dumpDffClientPos( "end-row", 256 ); +} + +bool DffDumpObject::implIsValid() const +{ + return isValid( mxHdrObj ) && InputObjectBase::implIsValid(); +} + +void DffDumpObject::implDump() +{ + while( mxHdrObj->startNextRecord() ) + { + if( mxHdrObj->getVer() != 0x0F ) + { + if( mxHdrObj->isShowRecBody() ) + dumpRecordBody(); + in().seek( mxHdrObj->getBodyEnd() ); + } + out().emptyLine(); + } +} + +void DffDumpObject::dumpRecordBody() +{ + IndentGuard aIndGuard( out() ); + + // record contents + if( mxHdrObj->hasRecName() ) switch( mxHdrObj->getRecId() ) + { + case 0xF00B: + dumpDffOptRec(); + break; + case 0xF010: + dumpHex< sal_uInt16 >( "flags", "DFFCLIENTANCHOR-FLAGS" ); + dumpDffClientRect(); + break; + } + + // remaining undumped data + sal_Int64 nPos = in().tell(); + if( nPos == mxHdrObj->getBodyStart() ) + dumpRawBinary( mxHdrObj->getRecSize(), false ); + else if( nPos < mxHdrObj->getBodyEnd() ) + dumpRemaining( static_cast< sal_Int32 >( mxHdrObj->getBodyEnd() - nPos ) ); +} + +void DffDumpObject::dumpDffOptRec() +{ + sal_uInt16 nInst = mxHdrObj->getInst(); + sal_Int64 nBodyEnd = mxHdrObj->getBodyEnd(); + out().resetItemIndex(); + for( sal_uInt16 nIdx = 0; (nIdx < nInst) && (in().tell() < nBodyEnd); ++nIdx ) + { + sal_uInt16 nPropId = dumpDffOptPropHeader(); + IndentGuard aIndent( out() ); + dumpDffOptPropValue( nPropId, in().readValue< sal_uInt32 >() ); + } +} + +sal_uInt16 DffDumpObject::dumpDffOptPropHeader() +{ + MultiItemsGuard aMultiGuard( out() ); + TableGuard aTabGuard( out(), 11 ); + writeEmptyItem( "#prop" ); + return dumpHex< sal_uInt16 >( "id", "DFFOPT-PROPERTY-ID" ); +} + +void DffDumpObject::dumpDffOptPropValue( sal_uInt16 nPropId, sal_uInt32 nValue ) +{ + switch( nPropId & 0x3FFF ) + { + case 127: writeHexItem( "flags", nValue, "DFFOPT-LOCK-FLAGS" ); break; + case 191: writeHexItem( "flags", nValue, "DFFOPT-TEXT-FLAGS" ); break; + case 255: writeHexItem( "flags", nValue, "DFFOPT-TEXTGEO-FLAGS" ); break; + case 319: writeHexItem( "flags", nValue, "DFFOPT-PICTURE-FLAGS" ); break; + case 383: writeHexItem( "flags", nValue, "DFFOPT-GEO-FLAGS" ); break; + case 447: writeHexItem( "flags", nValue, "DFFOPT-FILL-FLAGS" ); break; + case 511: writeHexItem( "flags", nValue, "DFFOPT-LINE-FLAGS" ); break; + case 575: writeHexItem( "flags", nValue, "DFFOPT-SHADOW-FLAGS" ); break; + case 639: writeHexItem( "flags", nValue, "DFFOPT-PERSP-FLAGS" ); break; + case 703: writeHexItem( "flags", nValue, "DFFOPT-3DOBJ-FLAGS" ); break; + case 767: writeHexItem( "flags", nValue, "DFFOPT-3DSTYLE-FLAGS" ); break; + case 831: writeHexItem( "flags", nValue, "DFFOPT-SHAPE1-FLAGS" ); break; + case 895: writeHexItem( "flags", nValue, "DFFOPT-CALLOUT-FLAGS" ); break; + case 959: writeHexItem( "flags", nValue, "DFFOPT-SHAPE2-FLAGS" ); break; + default: writeHexItem( "value", nValue ); + } +} + +// ============================================================================ + +} // namespace dump +} // namespace oox + +#endif + diff --git a/oox/source/dump/dumperbase.cxx b/oox/source/dump/dumperbase.cxx new file mode 100644 index 000000000000..0c9cff9ea5f7 --- /dev/null +++ b/oox/source/dump/dumperbase.cxx @@ -0,0 +1,2775 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: dumperbase.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:58 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/dump/dumperbase.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "oox/helper/binaryoutputstream.hxx" +#include "oox/core/filterbase.hxx" +#include "oox/xls/biffhelper.hxx" + +#if OOX_INCLUDE_DUMPER + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::rtl::OString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::util::DateTime; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::ucb::XSimpleFileAccess; +using ::com::sun::star::io::XActiveDataSink; +using ::com::sun::star::io::XActiveDataSource; +using ::com::sun::star::io::XInputStream; +using ::com::sun::star::io::XTextInputStream; +using ::com::sun::star::io::XOutputStream; +using ::com::sun::star::io::XTextOutputStream; +using ::oox::core::FilterBase; + +namespace oox { +namespace dump { + +const sal_Unicode OOX_DUMP_BOM = 0xFEFF; +const sal_Int32 OOX_DUMP_MAXSTRLEN = 80; +const sal_Int32 OOX_DUMP_INDENT = 2; +const sal_Unicode OOX_DUMP_BINDOT = '.'; +const sal_Unicode OOX_DUMP_CFG_LISTSEP = ','; +const sal_Unicode OOX_DUMP_CFG_QUOTE = '\''; +const sal_Unicode OOX_DUMP_LF = '\n'; +const sal_Unicode OOX_DUMP_ITEMSEP = '='; +const sal_Int32 OOX_DUMP_BYTESPERLINE = 16; +const sal_Int32 OOX_DUMP_MAXARRAY = 16; + +// ============================================================================ +// ============================================================================ + +// file names ----------------------------------------------------------------- + +OUString InputOutputHelper::convertFileNameToUrl( const OUString& rFileName ) +{ + OUString aFileUrl; + if( ::osl::FileBase::getFileURLFromSystemPath( rFileName, aFileUrl ) == ::osl::FileBase::E_None ) + return aFileUrl; + return OUString(); +} + +sal_Int32 InputOutputHelper::getFileNamePos( const OUString& rFileUrl ) +{ + sal_Int32 nSepPos = rFileUrl.lastIndexOf( '/' ); + return (nSepPos < 0) ? 0 : (nSepPos + 1); +} + +Reference< XInputStream > InputOutputHelper::openInputStream( const OUString& rFileName ) +{ + Reference< XInputStream > xInStrm; + try + { + Reference< XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + Reference< XSimpleFileAccess > xFileAccess( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY_THROW ); + xInStrm = xFileAccess->openFileRead( rFileName ); + } + catch( Exception& ) + { + } + return xInStrm; +} + +Reference< XTextInputStream > InputOutputHelper::openTextInputStream( const Reference< XInputStream >& rxInStrm, const OUString& rEncoding ) +{ + Reference< XTextInputStream > xTextInStrm; + if( rxInStrm.is() ) try + { + Reference< XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + Reference< XActiveDataSink > xDataSink( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TextInputStream" ) ), UNO_QUERY_THROW ); + xDataSink->setInputStream( rxInStrm ); + xTextInStrm.set( xDataSink, UNO_QUERY_THROW ); + } + catch( Exception& ) + { + } + if( xTextInStrm.is() ) + xTextInStrm->setEncoding( rEncoding ); + return xTextInStrm; +} + +Reference< XTextInputStream > InputOutputHelper::openTextInputStream( const OUString& rFileName, const OUString& rEncoding ) +{ + return openTextInputStream( openInputStream( rFileName ), rEncoding ); +} + +Reference< XOutputStream > InputOutputHelper::openOutputStream( const OUString& rFileName ) +{ + Reference< XOutputStream > xOutStrm; + try + { + Reference< XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + Reference< XSimpleFileAccess > xFileAccess( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY_THROW ); + if( !xFileAccess->isFolder( rFileName ) ) + { + try { xFileAccess->kill( rFileName ); } catch( Exception& ) {} + xOutStrm = xFileAccess->openFileWrite( rFileName ); + } + } + catch( Exception& ) + { + } + return xOutStrm; +} + +Reference< XTextOutputStream > InputOutputHelper::openTextOutputStream( const Reference< XOutputStream >& rxOutStrm, const OUString& rEncoding ) +{ + Reference< XTextOutputStream > xTextOutStrm; + if( rxOutStrm.is() ) try + { + Reference< XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + Reference< XActiveDataSource > xDataSource( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TextOutputStream" ) ), UNO_QUERY_THROW ); + xDataSource->setOutputStream( rxOutStrm ); + xTextOutStrm.set( xDataSource, UNO_QUERY_THROW ); + } + catch( Exception& ) + { + } + if( xTextOutStrm.is() ) + xTextOutStrm->setEncoding( rEncoding ); + return xTextOutStrm; +} + +Reference< XTextOutputStream > InputOutputHelper::openTextOutputStream( const OUString& rFileName, const OUString& rEncoding ) +{ + return openTextOutputStream( openOutputStream( rFileName ), rEncoding ); +} + +// ============================================================================ +// ============================================================================ + +ItemFormat::ItemFormat() : + meDataType( DATATYPE_VOID ), + meFmtType( FORMATTYPE_NONE ) +{ +} + +void ItemFormat::set( DataType eDataType, FormatType eFmtType, const OUString& rItemName ) +{ + meDataType = eDataType; + meFmtType = eFmtType; + maItemName = rItemName; + maListName = OUString(); +} + +void ItemFormat::set( DataType eDataType, FormatType eFmtType, const OUString& rItemName, const OUString& rListName ) +{ + set( eDataType, eFmtType, rItemName ); + maListName = rListName; +} + +OUStringVector::const_iterator ItemFormat::parse( const OUStringVector& rFormatVec ) +{ + set( DATATYPE_VOID, FORMATTYPE_NONE, OUString() ); + + OUStringVector::const_iterator aIt = rFormatVec.begin(), aEnd = rFormatVec.end(); + OUString aDataType, aFmtType; + if( aIt != aEnd ) aDataType = *aIt++; + if( aIt != aEnd ) aFmtType = *aIt++; + if( aIt != aEnd ) maItemName = *aIt++; + if( aIt != aEnd ) maListName = *aIt++; + + meDataType = StringHelper::convertToDataType( aDataType ); + meFmtType = StringHelper::convertToFormatType( aFmtType ); + + if( meFmtType == FORMATTYPE_NONE ) + { + if( aFmtType.equalsAscii( "unused" ) ) + set( meDataType, FORMATTYPE_HEX, CREATE_OUSTRING( OOX_DUMP_UNUSED ) ); + else if( aFmtType.equalsAscii( "unknown" ) ) + set( meDataType, FORMATTYPE_HEX, CREATE_OUSTRING( OOX_DUMP_UNKNOWN ) ); + } + + return aIt; +} + +OUStringVector ItemFormat::parse( const OUString& rFormatStr ) +{ + OUStringVector aFormatVec; + StringHelper::convertStringToStringList( aFormatVec, rFormatStr, false ); + OUStringVector::const_iterator aIt = parse( aFormatVec ); + return OUStringVector( aIt, const_cast< const OUStringVector& >( aFormatVec ).end() ); +} + +// ============================================================================ +// ============================================================================ + +// append string to string ---------------------------------------------------- + +void StringHelper::appendChar( ::rtl::OUStringBuffer& rStr, sal_Unicode cChar, sal_Int32 nCount ) +{ + for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex ) + rStr.append( cChar ); +} + +void StringHelper::appendString( OUStringBuffer& rStr, const OUString& rData, sal_Int32 nWidth, sal_Unicode cFill ) +{ + appendChar( rStr, cFill, nWidth - rData.getLength() ); + rStr.append( rData ); +} + +// append decimal ------------------------------------------------------------- + +void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt8 nData, sal_Int32 nWidth, sal_Unicode cFill ) +{ + appendString( rStr, OUString::valueOf( static_cast< sal_Int32 >( nData ) ), nWidth, cFill ); +} + +void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int8 nData, sal_Int32 nWidth, sal_Unicode cFill ) +{ + appendString( rStr, OUString::valueOf( static_cast< sal_Int32 >( nData ) ), nWidth, cFill ); +} + +void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt16 nData, sal_Int32 nWidth, sal_Unicode cFill ) +{ + appendString( rStr, OUString::valueOf( static_cast< sal_Int32 >( nData ) ), nWidth, cFill ); +} + +void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int16 nData, sal_Int32 nWidth, sal_Unicode cFill ) +{ + appendString( rStr, OUString::valueOf( static_cast< sal_Int32 >( nData ) ), nWidth, cFill ); +} + +void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt32 nData, sal_Int32 nWidth, sal_Unicode cFill ) +{ + appendString( rStr, OUString::valueOf( static_cast< sal_Int64 >( nData ) ), nWidth, cFill ); +} + +void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int32 nData, sal_Int32 nWidth, sal_Unicode cFill ) +{ + appendString( rStr, OUString::valueOf( nData ), nWidth, cFill ); +} + +void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt64 nData, sal_Int32 nWidth, sal_Unicode cFill ) +{ + /* Values greater than biggest signed 64bit integer will change to + negative when converting to sal_Int64. Therefore, the trailing digit + will be written separately. */ + OUStringBuffer aBuffer; + if( nData > 9 ) + aBuffer.append( OUString::valueOf( static_cast< sal_Int64 >( nData / 10 ) ) ); + aBuffer.append( static_cast< sal_Unicode >( '0' + (nData % 10) ) ); + appendString( rStr, aBuffer.makeStringAndClear(), nWidth, cFill ); +} + +void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int64 nData, sal_Int32 nWidth, sal_Unicode cFill ) +{ + appendString( rStr, OUString::valueOf( nData ), nWidth, cFill ); +} + +void StringHelper::appendDec( OUStringBuffer& rStr, double fData, sal_Int32 nWidth, sal_Unicode cFill ) +{ + appendString( rStr, ::rtl::math::doubleToUString( fData, rtl_math_StringFormat_G, 15, '.', true ), nWidth, cFill ); +} + +// append hexadecimal --------------------------------------------------------- + +void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt8 nData, bool bPrefix ) +{ + static const sal_Unicode spcHexDigits[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; + if( bPrefix ) + rStr.appendAscii( "0x" ); + rStr.append( spcHexDigits[ (nData >> 4) & 0x0F ] ).append( spcHexDigits[ nData & 0x0F ] ); +} + +void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int8 nData, bool bPrefix ) +{ + appendHex( rStr, static_cast< sal_uInt8 >( nData ), bPrefix ); +} + +void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt16 nData, bool bPrefix ) +{ + appendHex( rStr, static_cast< sal_uInt8 >( nData >> 8 ), bPrefix ); + appendHex( rStr, static_cast< sal_uInt8 >( nData ), false ); +} + +void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int16 nData, bool bPrefix ) +{ + appendHex( rStr, static_cast< sal_uInt16 >( nData ), bPrefix ); +} + +void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt32 nData, bool bPrefix ) +{ + appendHex( rStr, static_cast< sal_uInt16 >( nData >> 16 ), bPrefix ); + appendHex( rStr, static_cast< sal_uInt16 >( nData ), false ); +} + +void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int32 nData, bool bPrefix ) +{ + appendHex( rStr, static_cast< sal_uInt32 >( nData ), bPrefix ); +} + +void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt64 nData, bool bPrefix ) +{ + appendHex( rStr, static_cast< sal_uInt32 >( nData >> 32 ), bPrefix ); + appendHex( rStr, static_cast< sal_uInt32 >( nData ), false ); +} + +void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int64 nData, bool bPrefix ) +{ + appendHex( rStr, static_cast< sal_uInt64 >( nData ), bPrefix ); +} + +void StringHelper::appendHex( OUStringBuffer& rStr, double fData, bool bPrefix ) +{ + appendHex( rStr, *reinterpret_cast< const sal_uInt64* >( &fData ), bPrefix ); +} + +// append shortened hexadecimal ----------------------------------------------- + +void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt8 nData, bool bPrefix ) +{ + if( nData != 0 ) + appendHex( rStr, nData, bPrefix ); +} + +void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int8 nData, bool bPrefix ) +{ + appendShortHex( rStr, static_cast< sal_uInt8 >( nData ), bPrefix ); +} + +void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt16 nData, bool bPrefix ) +{ + if( nData > 0xFF ) + appendHex( rStr, nData, bPrefix ); + else + appendShortHex( rStr, static_cast< sal_uInt8 >( nData ), bPrefix ); +} + +void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int16 nData, bool bPrefix ) +{ + appendShortHex( rStr, static_cast< sal_uInt16 >( nData ), bPrefix ); +} + +void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt32 nData, bool bPrefix ) +{ + if( nData > 0xFFFF ) + appendHex( rStr, nData, bPrefix ); + else + appendShortHex( rStr, static_cast< sal_uInt16 >( nData ), bPrefix ); +} + +void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int32 nData, bool bPrefix ) +{ + appendShortHex( rStr, static_cast< sal_uInt32 >( nData ), bPrefix ); +} + +void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt64 nData, bool bPrefix ) +{ + if( nData > 0xFFFFFFFF ) + appendHex( rStr, nData, bPrefix ); + else + appendShortHex( rStr, static_cast< sal_uInt32 >( nData ), bPrefix ); +} + +void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int64 nData, bool bPrefix ) +{ + appendShortHex( rStr, static_cast< sal_uInt64 >( nData ), bPrefix ); +} + +// append binary -------------------------------------------------------------- + +void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt8 nData, bool bDots ) +{ + for( sal_uInt8 nMask = 0x80; nMask != 0; (nMask >>= 1) &= 0x7F ) + { + rStr.append( static_cast< sal_Unicode >( (nData & nMask) ? '1' : '0' ) ); + if( bDots && (nMask == 0x10) ) + rStr.append( OOX_DUMP_BINDOT ); + } +} + +void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int8 nData, bool bDots ) +{ + appendBin( rStr, static_cast< sal_uInt8 >( nData ), bDots ); +} + +void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt16 nData, bool bDots ) +{ + appendBin( rStr, static_cast< sal_uInt8 >( nData >> 8 ), bDots ); + if( bDots ) + rStr.append( OOX_DUMP_BINDOT ); + appendBin( rStr, static_cast< sal_uInt8 >( nData ), bDots ); +} + +void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int16 nData, bool bDots ) +{ + appendBin( rStr, static_cast< sal_uInt16 >( nData ), bDots ); +} + +void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt32 nData, bool bDots ) +{ + appendBin( rStr, static_cast< sal_uInt16 >( nData >> 16 ), bDots ); + if( bDots ) + rStr.append( OOX_DUMP_BINDOT ); + appendBin( rStr, static_cast< sal_uInt16 >( nData ), bDots ); +} + +void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int32 nData, bool bDots ) +{ + appendBin( rStr, static_cast< sal_uInt32 >( nData ), bDots ); +} + +void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt64 nData, bool bDots ) +{ + appendBin( rStr, static_cast< sal_uInt32 >( nData >> 32 ), bDots ); + if( bDots ) + rStr.append( OOX_DUMP_BINDOT ); + appendBin( rStr, static_cast< sal_uInt32 >( nData ), bDots ); +} + +void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int64 nData, bool bDots ) +{ + appendBin( rStr, static_cast< sal_uInt64 >( nData ), bDots ); +} + +void StringHelper::appendBin( OUStringBuffer& rStr, double fData, bool bDots ) +{ + appendBin( rStr, *reinterpret_cast< const sal_uInt64* >( &fData ), bDots ); +} + +// append formatted value ----------------------------------------------------- + +void StringHelper::appendBool( OUStringBuffer& rStr, bool bData ) +{ + rStr.appendAscii( bData ? "true" : "false" ); +} + +// append columns, rows, addresses -------------------------------------------- + +void StringHelper::appendAddrCol( OUStringBuffer& rStr, sal_Int32 nCol, bool bRel ) +{ + if( !bRel ) rStr.append( OOX_DUMP_ADDRABS ); + sal_Int32 nPos = rStr.getLength(); + for( sal_Int32 nTemp = nCol; nTemp >= 0; (nTemp /= 26) -= 1 ) + rStr.insert( nPos, static_cast< sal_Unicode >( 'A' + (nTemp % 26) ) ); +} + +void StringHelper::appendAddrRow( OUStringBuffer& rStr, sal_Int32 nRow, bool bRel ) +{ + if( !bRel ) rStr.append( OOX_DUMP_ADDRABS ); + appendDec( rStr, nRow + 1 ); +} + +void StringHelper::appendAddrName( OUStringBuffer& rStr, sal_Unicode cPrefix, sal_Int32 nColRow, bool bRel ) +{ + rStr.append( cPrefix ); + if( bRel && (nColRow != 0) ) + { + rStr.append( OOX_DUMP_R1C1OPEN ); + appendDec( rStr, nColRow ); + rStr.append( OOX_DUMP_R1C1CLOSE ); + } + else if( !bRel ) + appendDec( rStr, nColRow + 1 ); +} + +void StringHelper::appendAddress( OUStringBuffer& rStr, const Address& rPos ) +{ + appendAddrCol( rStr, rPos.mnCol, true ); + appendAddrRow( rStr, rPos.mnRow, true ); +} + +void StringHelper::appendRange( OUStringBuffer& rStr, const Range& rRange ) +{ + appendAddress( rStr, rRange.maFirst ); + rStr.append( OOX_DUMP_RANGESEP ); + appendAddress( rStr, rRange.maLast ); +} + +void StringHelper::appendRangeList( OUStringBuffer& rStr, const RangeList& rRanges ) +{ + OUStringBuffer aData; + for( RangeList::const_iterator aIt = rRanges.begin(), aEnd = rRanges.end(); aIt != aEnd; ++aIt ) + { + OUStringBuffer aRange; + appendRange( aRange, *aIt ); + appendToken( aData, aRange.makeStringAndClear(), OOX_DUMP_LISTSEP ); + } + rStr.append( aData.makeStringAndClear() ); +} + +void StringHelper::appendAddress( OUStringBuffer& rStr, const TokenAddress& rPos, bool bR1C1 ) +{ + if( bR1C1 && (rPos.mbRelCol || rPos.mbRelRow) ) + { + appendAddrName( rStr, OOX_DUMP_R1C1ROW, rPos.mnRow, rPos.mbRelRow ); + appendAddrName( rStr, OOX_DUMP_R1C1COL, rPos.mnCol, rPos.mbRelCol ); + } + else + { + appendAddrCol( rStr, rPos.mnCol, rPos.mbRelCol ); + appendAddrRow( rStr, rPos.mnRow, rPos.mbRelRow ); + } +} + +void StringHelper::appendRange( OUStringBuffer& rStr, const TokenRange& rRange, bool bR1C1 ) +{ + appendAddress( rStr, rRange.maFirst, bR1C1 ); + rStr.append( OOX_DUMP_RANGESEP ); + appendAddress( rStr, rRange.maLast, bR1C1 ); +} + +// encoded text output -------------------------------------------------------- + +void StringHelper::appendCChar( OUStringBuffer& rStr, sal_Unicode cChar, bool bPrefix ) +{ + if( cChar > 0x00FF ) + { + if( bPrefix ) + rStr.appendAscii( "\\u" ); + appendHex( rStr, static_cast< sal_uInt16 >( cChar ), false ); + } + else + { + if( bPrefix ) + rStr.appendAscii( "\\x" ); + appendHex( rStr, static_cast< sal_uInt8 >( cChar ), false ); + } +} + +void StringHelper::appendEncChar( OUStringBuffer& rStr, sal_Unicode cChar, sal_Int32 nCount, bool bPrefix ) +{ + if( cChar < 0x0020 ) + { + // C-style hex code + OUStringBuffer aCode; + appendCChar( aCode, cChar, bPrefix ); + for( sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx ) + rStr.append( aCode ); + } + else + { + appendChar( rStr, cChar, nCount ); + } +} + +void StringHelper::appendEncString( OUStringBuffer& rStr, const OUString& rData, bool bPrefix ) +{ + sal_Int32 nBeg = 0; + sal_Int32 nIdx = 0; + sal_Int32 nEnd = rData.getLength(); + while( nIdx < nEnd ) + { + // find next character that needs encoding + while( (nIdx < nEnd) && (rData[ nIdx ] >= 0x20) ) ++nIdx; + // append portion + if( nBeg < nIdx ) + { + if( (nBeg == 0) && (nIdx == nEnd) ) + rStr.append( rData ); + else + rStr.append( rData.copy( nBeg, nIdx - nBeg ) ); + } + // append characters to be encoded + while( (nIdx < nEnd) && (rData[ nIdx ] < 0x20) ) + { + appendCChar( rStr, rData[ nIdx ], bPrefix ); + ++nIdx; + } + // adjust limits + nBeg = nIdx; + } +} + +// token list ----------------------------------------------------------------- + +void StringHelper::appendToken( OUStringBuffer& rStr, const OUString& rToken, sal_Unicode cSep ) +{ + if( (rStr.getLength() > 0) && (rToken.getLength() > 0) ) + rStr.append( cSep ); + rStr.append( rToken ); +} + +void StringHelper::appendToken( OUStringBuffer& rStr, sal_Int64 nToken, sal_Unicode cSep ) +{ + OUStringBuffer aToken; + appendDec( aToken, nToken ); + appendToken( rStr, aToken.makeStringAndClear(), cSep ); +} + +void StringHelper::prependToken( OUStringBuffer& rStr, const OUString& rToken, sal_Unicode cSep ) +{ + if( (rStr.getLength() > 0) && (rToken.getLength() > 0) ) + rStr.insert( 0, cSep ); + rStr.insert( 0, rToken ); +} + +void StringHelper::prependToken( OUStringBuffer& rStr, sal_Int64 nToken, sal_Unicode cSep ) +{ + OUStringBuffer aToken; + appendDec( aToken, nToken ); + prependToken( rStr, aToken.makeStringAndClear(), cSep ); +} + +void StringHelper::appendIndex( OUStringBuffer& rStr, const OUString& rIdx ) +{ + rStr.append( sal_Unicode( '[' ) ).append( rIdx ).append( sal_Unicode( ']' ) ); +} + +void StringHelper::appendIndex( OUStringBuffer& rStr, sal_Int64 nIdx ) +{ + OUStringBuffer aToken; + appendDec( aToken, nIdx ); + appendIndex( rStr, aToken.makeStringAndClear() ); +} + +void StringHelper::appendIndexedText( OUStringBuffer& rStr, const OUString& rData, const OUString& rIdx ) +{ + rStr.append( rData ); + appendIndex( rStr, rIdx ); +} + +void StringHelper::appendIndexedText( OUStringBuffer& rStr, const OUString& rData, sal_Int64 nIdx ) +{ + rStr.append( rData ); + appendIndex( rStr, nIdx ); +} + +OUString StringHelper::getToken( const OUString& rData, sal_Int32& rnPos, sal_Unicode cSep ) +{ + return trimSpaces( rData.getToken( 0, cSep, rnPos ) ); +} + +void StringHelper::enclose( OUStringBuffer& rStr, sal_Unicode cOpen, sal_Unicode cClose ) +{ + rStr.insert( 0, cOpen ).append( cClose ? cClose : cOpen ); +} + +// string conversion ---------------------------------------------------------- + +namespace { + +sal_Int32 lclIndexOf( const OUString& rStr, sal_Unicode cChar, sal_Int32 nStartPos ) +{ + sal_Int32 nIndex = rStr.indexOf( cChar, nStartPos ); + return (nIndex < 0) ? rStr.getLength() : nIndex; +} + +OUString lclTrimQuotedStringList( const OUString& rStr ) +{ + OUStringBuffer aBuffer; + sal_Int32 nPos = 0; + sal_Int32 nLen = rStr.getLength(); + while( nPos < nLen ) + { + if( rStr[ nPos ] == OOX_DUMP_CFG_QUOTE ) + { + // quoted string, skip leading quote character + ++nPos; + // process quoted text and ambedded literal quote characters + OUStringBuffer aToken; + do + { + // seek to next quote character and add text portion to token buffer + sal_Int32 nEnd = lclIndexOf( rStr, OOX_DUMP_CFG_QUOTE, nPos ); + aToken.append( rStr.copy( nPos, nEnd - nPos ) ); + // process literal quotes + while( (nEnd + 1 < nLen) && (rStr[ nEnd ] == OOX_DUMP_CFG_QUOTE) && (rStr[ nEnd + 1 ] == OOX_DUMP_CFG_QUOTE) ) + { + aToken.append( OOX_DUMP_CFG_QUOTE ); + nEnd += 2; + } + // nEnd is start of possible next text portion + nPos = nEnd; + } + while( (nPos < nLen) && (rStr[ nPos ] != OOX_DUMP_CFG_QUOTE) ); + // add token, seek to list separator, ignore text following closing quote + aBuffer.append( aToken.makeStringAndClear() ); + nPos = lclIndexOf( rStr, OOX_DUMP_CFG_LISTSEP, nPos ); + if( nPos < nLen ) + aBuffer.append( OOX_DUMP_LF ); + // set current position behind list separator + ++nPos; + } + else + { + // find list separator, add token text to buffer + sal_Int32 nEnd = lclIndexOf( rStr, OOX_DUMP_CFG_LISTSEP, nPos ); + aBuffer.append( rStr.copy( nPos, nEnd - nPos ) ); + if( nEnd < nLen ) + aBuffer.append( OOX_DUMP_LF ); + // set current position behind list separator + nPos = nEnd + 1; + } + } + + return aBuffer.makeStringAndClear(); +} + +} // namespace + +OUString StringHelper::trimSpaces( const OUString& rStr ) +{ + sal_Int32 nBeg = 0; + while( (nBeg < rStr.getLength()) && ((rStr[ nBeg ] == ' ') || (rStr[ nBeg ] == '\t')) ) + ++nBeg; + sal_Int32 nEnd = rStr.getLength(); + while( (nEnd > nBeg) && ((rStr[ nEnd - 1 ] == ' ') || (rStr[ nEnd - 1 ] == '\t')) ) + --nEnd; + return rStr.copy( nBeg, nEnd - nBeg ); +} + +OString StringHelper::convertToUtf8( const OUString& rStr ) +{ + return ::rtl::OUStringToOString( rStr, RTL_TEXTENCODING_UTF8 ); +} + +DataType StringHelper::convertToDataType( const OUString& rStr ) +{ + DataType eType = DATATYPE_VOID; + if( rStr.equalsAscii( "int8" ) ) + eType = DATATYPE_INT8; + else if( rStr.equalsAscii( "uint8" ) ) + eType = DATATYPE_UINT8; + else if( rStr.equalsAscii( "int16" ) ) + eType = DATATYPE_INT16; + else if( rStr.equalsAscii( "uint16" ) ) + eType = DATATYPE_UINT16; + else if( rStr.equalsAscii( "int32" ) ) + eType = DATATYPE_INT32; + else if( rStr.equalsAscii( "uint32" ) ) + eType = DATATYPE_UINT32; + else if( rStr.equalsAscii( "int64" ) ) + eType = DATATYPE_INT64; + else if( rStr.equalsAscii( "uint64" ) ) + eType = DATATYPE_UINT64; + else if( rStr.equalsAscii( "float" ) ) + eType = DATATYPE_FLOAT; + else if( rStr.equalsAscii( "double" ) ) + eType = DATATYPE_DOUBLE; + return eType; +} + +FormatType StringHelper::convertToFormatType( const OUString& rStr ) +{ + FormatType eType = FORMATTYPE_NONE; + if( rStr.equalsAscii( "dec" ) ) + eType = FORMATTYPE_DEC; + else if( rStr.equalsAscii( "hex" ) ) + eType = FORMATTYPE_HEX; + else if( rStr.equalsAscii( "bin" ) ) + eType = FORMATTYPE_BIN; + else if( rStr.equalsAscii( "fix" ) ) + eType = FORMATTYPE_FIX; + else if( rStr.equalsAscii( "bool" ) ) + eType = FORMATTYPE_BOOL; + return eType; +} + +bool StringHelper::convertFromDec( sal_Int64& ornData, const OUString& rData ) +{ + sal_Int32 nPos = 0; + sal_Int32 nLen = rData.getLength(); + bool bNeg = false; + if( (nLen > 0) && (rData[ 0 ] == '-') ) + { + bNeg = true; + ++nPos; + } + ornData = 0; + for( ; nPos < nLen; ++nPos ) + { + sal_Unicode cChar = rData[ nPos ]; + if( (cChar < '0') || (cChar > '9') ) + return false; + (ornData *= 10) += (cChar - '0'); + } + if( bNeg ) + ornData *= -1; + return true; +} + +bool StringHelper::convertFromHex( sal_Int64& ornData, const OUString& rData ) +{ + ornData = 0; + for( sal_Int32 nPos = 0, nLen = rData.getLength(); nPos < nLen; ++nPos ) + { + sal_Unicode cChar = rData[ nPos ]; + if( ('0' <= cChar) && (cChar <= '9') ) + cChar -= '0'; + else if( ('A' <= cChar) && (cChar <= 'F') ) + cChar -= ('A' - 10); + else if( ('a' <= cChar) && (cChar <= 'f') ) + cChar -= ('a' - 10); + else + return false; + (ornData <<= 4) += cChar; + } + return true; +} + +bool StringHelper::convertStringToInt( sal_Int64& ornData, const OUString& rData ) +{ + if( (rData.getLength() > 2) && (rData[ 0 ] == '0') && ((rData[ 1 ] == 'X') || (rData[ 1 ] == 'x')) ) + return convertFromHex( ornData, rData.copy( 2 ) ); + return convertFromDec( ornData, rData ); +} + +bool StringHelper::convertStringToDouble( double& orfData, const OUString& rData ) +{ + rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok; + sal_Int32 nSize = 0; + orfData = rtl::math::stringToDouble( rData, '.', '\0', &eStatus, &nSize ); + return (eStatus == rtl_math_ConversionStatus_Ok) && (nSize == rData.getLength()); +} + +bool StringHelper::convertStringToBool( const OUString& rData ) +{ + if( rData.equalsAscii( "true" ) ) + return true; + if( rData.equalsAscii( "false" ) ) + return false; + sal_Int64 nData; + return convertStringToInt( nData, rData ) && (nData != 0); +} + +void StringHelper::convertStringToStringList( OUStringVector& orVec, const OUString& rData, bool bIgnoreEmpty ) +{ + orVec.clear(); + OUString aUnquotedData = lclTrimQuotedStringList( rData ); + sal_Int32 nPos = 0; + sal_Int32 nLen = aUnquotedData.getLength(); + while( (0 <= nPos) && (nPos < nLen) ) + { + OUString aToken = getToken( aUnquotedData, nPos, OOX_DUMP_LF ); + if( !bIgnoreEmpty || (aToken.getLength() > 0) ) + orVec.push_back( aToken ); + } +} + +void StringHelper::convertStringToIntList( Int64Vector& orVec, const OUString& rData, bool bIgnoreEmpty ) +{ + orVec.clear(); + OUString aUnquotedData = lclTrimQuotedStringList( rData ); + sal_Int32 nPos = 0; + sal_Int32 nLen = aUnquotedData.getLength(); + sal_Int64 nData; + while( (0 <= nPos) && (nPos < nLen) ) + { + bool bOk = convertStringToInt( nData, getToken( aUnquotedData, nPos, OOX_DUMP_LF ) ); + if( !bIgnoreEmpty || bOk ) + orVec.push_back( bOk ? nData : 0 ); + } +} + +// ============================================================================ +// ============================================================================ + +FormulaStack::FormulaStack() : + mbError( false ) +{ +} + +void FormulaStack::pushOperand( const StringWrapper& rOp, const OUString& rTokClass ) +{ + maFmlaStack.push( rOp.getString() ); + maClassStack.push( rTokClass ); +} + +void FormulaStack::pushOperand( const StringWrapper& rOp ) +{ + pushOperand( rOp, OUString( OOX_DUMP_BASECLASS ) ); +} + +void FormulaStack::pushUnaryOp( const StringWrapper& rLOp, const StringWrapper& rROp ) +{ + pushUnaryOp( maFmlaStack, rLOp.getString(), rROp.getString() ); + pushUnaryOp( maClassStack, rLOp.getString(), rROp.getString() ); +} + +void FormulaStack::pushBinaryOp( const StringWrapper& rOp ) +{ + pushBinaryOp( maFmlaStack, rOp.getString() ); + pushBinaryOp( maClassStack, rOp.getString() ); +} + +void FormulaStack::pushFuncOp( const StringWrapper& rFunc, const OUString& rTokClass, sal_uInt8 nParamCount ) +{ + pushFuncOp( maFmlaStack, rFunc.getString(), nParamCount ); + pushFuncOp( maClassStack, rTokClass, nParamCount ); +} + +void FormulaStack::replaceOnTop( const OUString& rOld, const OUString& rNew ) +{ + if( !maFmlaStack.empty() ) + { + sal_Int32 nPos = maFmlaStack.top().indexOf( rOld ); + if( nPos >= 0 ) + maFmlaStack.top() = maFmlaStack.top().copy( 0, nPos ) + rNew + maFmlaStack.top().copy( nPos + rOld.getLength() ); + } +} + +const OUString& FormulaStack::getString( const StringStack& rStack ) const +{ + static const OUString saStackError = OOX_DUMP_ERRSTRING( "stack" ); + return (mbError || rStack.empty()) ? saStackError : rStack.top(); +} + +void FormulaStack::pushUnaryOp( StringStack& rStack, const OUString& rLOp, const OUString& rROp ) +{ + if( check( !rStack.empty() ) ) + rStack.top() = rLOp + rStack.top() + rROp; +} + +void FormulaStack::pushBinaryOp( StringStack& rStack, const OUString& rOp ) +{ + OUString aSecond; + if( check( !rStack.empty() ) ) + { + aSecond = rStack.top(); + rStack.pop(); + } + if( check( !rStack.empty() ) ) + rStack.top() = rStack.top() + rOp + aSecond; +} + +void FormulaStack::pushFuncOp( StringStack& rStack, const OUString& rOp, sal_uInt8 nParamCount ) +{ + OUStringBuffer aFunc; + for( sal_uInt8 nParam = 0; (nParam < nParamCount) && check( !rStack.empty() ); ++nParam ) + { + StringHelper::prependToken( aFunc, rStack.top(), OOX_DUMP_FUNCSEP ); + rStack.pop(); + } + StringHelper::enclose( aFunc, '(', ')' ); + aFunc.insert( 0, rOp ); + rStack.push( aFunc.makeStringAndClear() ); +} + +// ============================================================================ +// ============================================================================ + +Base::~Base() +{ +} + +// ============================================================================ +// ============================================================================ + +ConfigItemBase::~ConfigItemBase() +{ +} + +void ConfigItemBase::readConfigBlock( const ConfigInputStreamRef& rxStrm ) +{ + readConfigBlockContents( rxStrm ); +} + +void ConfigItemBase::implProcessConfigItemStr( + const ConfigInputStreamRef& /*rxStrm*/, const OUString& /*rKey*/, const OUString& /*rData*/ ) +{ +} + +void ConfigItemBase::implProcessConfigItemInt( + const ConfigInputStreamRef& /*rxStrm*/, sal_Int64 /*nKey*/, const OUString& /*rData*/ ) +{ +} + +void ConfigItemBase::readConfigBlockContents( const ConfigInputStreamRef& rxStrm ) +{ + bool bLoop = true; + while( bLoop && !rxStrm->isEOF() ) + { + OUString aKey, aData; + switch( readConfigLine( rxStrm, aKey, aData ) ) + { + case LINETYPE_DATA: + processConfigItem( rxStrm, aKey, aData ); + break; + case LINETYPE_END: + bLoop = false; + break; + } + } +} + +ConfigItemBase::LineType ConfigItemBase::readConfigLine( + const ConfigInputStreamRef& rxStrm, OUString& orKey, OUString& orData ) const +{ + OUString aLine; + while( !rxStrm->isEOF() && (aLine.getLength() == 0) ) + { + try { aLine = rxStrm->readLine(); } catch( Exception& ) { aLine = OUString(); } + if( (aLine.getLength() > 0) && (aLine[ 0 ] == OOX_DUMP_BOM) ) + aLine = aLine.copy( 1 ); + aLine = StringHelper::trimSpaces( aLine ); + if( aLine.getLength() > 0 ) + { + // ignore comments (starting with hash or semicolon) + sal_Unicode cChar = aLine[ 0 ]; + if( (cChar == '#') || (cChar == ';') ) + aLine = OUString(); + } + } + + LineType eResult = LINETYPE_END; + if( aLine.getLength() > 0 ) + { + sal_Int32 nEqPos = aLine.indexOf( '=' ); + if( nEqPos < 0 ) + { + orKey = aLine; + } + else + { + orKey = StringHelper::trimSpaces( aLine.copy( 0, nEqPos ) ); + orData = StringHelper::trimSpaces( aLine.copy( nEqPos + 1 ) ); + } + + if( (orKey.getLength() > 0) && ((orData.getLength() > 0) || !orKey.equalsAscii( "end" )) ) + eResult = LINETYPE_DATA; + } + + return eResult; +} + +ConfigItemBase::LineType ConfigItemBase::readConfigLine( const ConfigInputStreamRef& rxStrm ) const +{ + OUString aKey, aData; + return readConfigLine( rxStrm, aKey, aData ); +} + +void ConfigItemBase::processConfigItem( + const ConfigInputStreamRef& rxStrm, const OUString& rKey, const OUString& rData ) +{ + sal_Int64 nKey; + if( StringHelper::convertStringToInt( nKey, rKey ) ) + implProcessConfigItemInt( rxStrm, nKey, rData ); + else + implProcessConfigItemStr( rxStrm, rKey, rData ); +} + +// ============================================================================ + +NameListBase::~NameListBase() +{ +} + +void NameListBase::setName( sal_Int64 nKey, const StringWrapper& rNameWrp ) +{ + implSetName( nKey, rNameWrp.getString() ); +} + +void NameListBase::includeList( NameListRef xList ) +{ + if( xList.get() ) + { + for( const_iterator aIt = xList->begin(), aEnd = xList->end(); aIt != aEnd; ++aIt ) + maMap[ aIt->first ] = aIt->second; + implIncludeList( *xList ); + } +} + +bool NameListBase::implIsValid() const +{ + return true; +} + +void NameListBase::implProcessConfigItemStr( + const ConfigInputStreamRef& rxStrm, const OUString& rKey, const OUString& rData ) +{ + if( rKey.equalsAscii( "include" ) ) + include( rData ); + else if( rKey.equalsAscii( "exclude" ) ) + exclude( rData ); + else + ConfigItemBase::implProcessConfigItemStr( rxStrm, rKey, rData ); +} + +void NameListBase::implProcessConfigItemInt( + const ConfigInputStreamRef& /*rxStrm*/, sal_Int64 nKey, const OUString& rData ) +{ + implSetName( nKey, rData ); +} + +void NameListBase::insertRawName( sal_Int64 nKey, const OUString& rName ) +{ + maMap[ nKey ] = rName; +} + +const OUString* NameListBase::findRawName( sal_Int64 nKey ) const +{ + const_iterator aIt = maMap.find( nKey ); + return (aIt == end()) ? 0 : &aIt->second; +} + +void NameListBase::include( const OUString& rListKeys ) +{ + OUStringVector aVec; + StringHelper::convertStringToStringList( aVec, rListKeys, true ); + for( OUStringVector::const_iterator aIt = aVec.begin(), aEnd = aVec.end(); aIt != aEnd; ++aIt ) + includeList( mrCfgData.getNameList( *aIt ) ); +} + +void NameListBase::exclude( const OUString& rKeys ) +{ + Int64Vector aVec; + StringHelper::convertStringToIntList( aVec, rKeys, true ); + for( Int64Vector::const_iterator aIt = aVec.begin(), aEnd = aVec.end(); aIt != aEnd; ++aIt ) + maMap.erase( *aIt ); +} + +// ============================================================================ + +ConstList::ConstList( const SharedConfigData& rCfgData ) : + NameListBase( rCfgData ), + maDefName( OOX_DUMP_ERR_NONAME ), + mbQuoteNames( false ) +{ +} + +void ConstList::implProcessConfigItemStr( + const ConfigInputStreamRef& rxStrm, const OUString& rKey, const OUString& rData ) +{ + if( rKey.equalsAscii( "default" ) ) + setDefaultName( rData ); + else if( rKey.equalsAscii( "quote-names" ) ) + setQuoteNames( StringHelper::convertStringToBool( rData ) ); + else + NameListBase::implProcessConfigItemStr( rxStrm, rKey, rData ); +} + +void ConstList::implSetName( sal_Int64 nKey, const OUString& rName ) +{ + insertRawName( nKey, rName ); +} + +OUString ConstList::implGetName( const Config& /*rCfg*/, sal_Int64 nKey ) const +{ + const OUString* pName = findRawName( nKey ); + OUString aName = pName ? *pName : maDefName; + if( mbQuoteNames ) + { + OUStringBuffer aBuffer( aName ); + StringHelper::enclose( aBuffer, OOX_DUMP_STRQUOTE ); + aName = aBuffer.makeStringAndClear(); + } + return aName; +} + +OUString ConstList::implGetNameDbl( const Config& /*rCfg*/, double /*fValue*/ ) const +{ + return OUString(); +} + +void ConstList::implIncludeList( const NameListBase& rList ) +{ + if( const ConstList* pConstList = dynamic_cast< const ConstList* >( &rList ) ) + { + maDefName = pConstList->maDefName; + mbQuoteNames = pConstList->mbQuoteNames; + } +} + +// ============================================================================ + +MultiList::MultiList( const SharedConfigData& rCfgData ) : + ConstList( rCfgData ), + mbIgnoreEmpty( true ) +{ +} + +void MultiList::setNamesFromVec( sal_Int64 nStartKey, const OUStringVector& rNames ) +{ + sal_Int64 nKey = nStartKey; + for( OUStringVector::const_iterator aIt = rNames.begin(), aEnd = rNames.end(); aIt != aEnd; ++aIt, ++nKey ) + if( !mbIgnoreEmpty || (aIt->getLength() > 0) ) + insertRawName( nKey, *aIt ); +} + +void MultiList::implProcessConfigItemStr( + const ConfigInputStreamRef& rxStrm, const OUString& rKey, const OUString& rData ) +{ + if( rKey.equalsAscii( "ignore-empty" ) ) + mbIgnoreEmpty = StringHelper::convertStringToBool( rData ); + else + ConstList::implProcessConfigItemStr( rxStrm, rKey, rData ); +} + +void MultiList::implSetName( sal_Int64 nKey, const OUString& rName ) +{ + OUStringVector aNames; + StringHelper::convertStringToStringList( aNames, rName, false ); + setNamesFromVec( nKey, aNames ); +} + +// ============================================================================ + +FlagsList::FlagsList( const SharedConfigData& rCfgData ) : + NameListBase( rCfgData ), + mnIgnore( 0 ) +{ +} + +void FlagsList::implProcessConfigItemStr( + const ConfigInputStreamRef& rxStrm, const OUString& rKey, const OUString& rData ) +{ + if( rKey.equalsAscii( "ignore" ) ) + { + sal_Int64 nIgnore; + if( StringHelper::convertStringToInt( nIgnore, rData ) ) + setIgnoreFlags( nIgnore ); + } + else + { + NameListBase::implProcessConfigItemStr( rxStrm, rKey, rData ); + } +} + +void FlagsList::implSetName( sal_Int64 nKey, const OUString& rName ) +{ + insertRawName( nKey, rName ); +} + +OUString FlagsList::implGetName( const Config& /*rCfg*/, sal_Int64 nKey ) const +{ + sal_Int64 nFlags = nKey; + setFlag( nFlags, mnIgnore, false ); + sal_Int64 nFound = 0; + OUStringBuffer aName; + // add known flags + for( const_iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt ) + { + sal_Int64 nMask = aIt->first; + const OUString& rFlagName = aIt->second; + bool bNegated = (rFlagName.getLength() > 0) && (rFlagName[ 0 ] == '!'); + if( getFlag( nFlags, nMask ) != bNegated ) + StringHelper::appendToken( aName, bNegated ? rFlagName.copy( 1 ) : rFlagName ); + setFlag( nFound, nMask ); + } + // add unknown flags + setFlag( nFlags, nFound, false ); + if( nFlags != 0 ) + { + OUStringBuffer aUnknown( CREATE_OUSTRING( OOX_DUMP_UNKNOWN ) ); + aUnknown.append( OOX_DUMP_ITEMSEP ); + StringHelper::appendShortHex( aUnknown, nFlags, true ); + StringHelper::enclose( aUnknown, '(', ')' ); + StringHelper::appendToken( aName, aUnknown.makeStringAndClear() ); + } + return aName.makeStringAndClear(); +} + +OUString FlagsList::implGetNameDbl( const Config& /*rCfg*/, double /*fValue*/ ) const +{ + return OUString(); +} + +void FlagsList::implIncludeList( const NameListBase& rList ) +{ + if( const FlagsList* pFlagsList = dynamic_cast< const FlagsList* >( &rList ) ) + mnIgnore = pFlagsList->mnIgnore; +} + +// ============================================================================ + +CombiList::CombiList( const SharedConfigData& rCfgData ) : + FlagsList( rCfgData ) +{ +} + +void CombiList::implSetName( sal_Int64 nKey, const OUString& rName ) +{ + if( (nKey & (nKey - 1)) != 0 ) // more than a single bit set? + { + ExtItemFormat& rItemFmt = maFmtMap[ nKey ]; + OUStringVector aRemain = rItemFmt.parse( rName ); + rItemFmt.mbShiftValue = aRemain.empty() || !aRemain.front().equalsAscii( "noshift" ); + } + else + { + FlagsList::implSetName( nKey, rName ); + } +} + +OUString CombiList::implGetName( const Config& rCfg, sal_Int64 nKey ) const +{ + sal_Int64 nFlags = nKey; + sal_Int64 nFound = 0; + OUStringBuffer aName; + // add known flag fields + for( ExtItemFormatMap::const_iterator aIt = maFmtMap.begin(), aEnd = maFmtMap.end(); aIt != aEnd; ++aIt ) + { + sal_Int64 nMask = aIt->first; + if( nMask != 0 ) + { + const ExtItemFormat& rItemFmt = aIt->second; + + sal_uInt64 nUFlags = static_cast< sal_uInt64 >( nFlags ); + sal_uInt64 nUMask = static_cast< sal_uInt64 >( nMask ); + if( rItemFmt.mbShiftValue ) + while( (nUMask & 1) == 0 ) { nUFlags >>= 1; nUMask >>= 1; } + + sal_uInt64 nUValue = nUFlags & nUMask; + sal_Int64 nSValue = static_cast< sal_Int64 >( nUValue ); + if( getFlag< sal_uInt64 >( nUValue, (nUMask + 1) >> 1 ) ) + setFlag( nSValue, static_cast< sal_Int64 >( ~nUMask ) ); + + OUStringBuffer aItem( rItemFmt.maItemName ); + OUStringBuffer aValue; + switch( rItemFmt.meDataType ) + { + case DATATYPE_INT8: StringHelper::appendValue( aValue, static_cast< sal_Int8 >( nSValue ), rItemFmt.meFmtType ); break; + case DATATYPE_UINT8: StringHelper::appendValue( aValue, static_cast< sal_uInt8 >( nUValue ), rItemFmt.meFmtType ); break; + case DATATYPE_INT16: StringHelper::appendValue( aValue, static_cast< sal_Int16 >( nSValue ), rItemFmt.meFmtType ); break; + case DATATYPE_UINT16: StringHelper::appendValue( aValue, static_cast< sal_uInt16 >( nUValue ), rItemFmt.meFmtType ); break; + case DATATYPE_INT32: StringHelper::appendValue( aValue, static_cast< sal_Int32 >( nSValue ), rItemFmt.meFmtType ); break; + case DATATYPE_UINT32: StringHelper::appendValue( aValue, static_cast< sal_uInt32 >( nUValue ), rItemFmt.meFmtType ); break; + case DATATYPE_INT64: StringHelper::appendValue( aValue, nSValue, rItemFmt.meFmtType ); break; + case DATATYPE_UINT64: StringHelper::appendValue( aValue, nUValue, rItemFmt.meFmtType ); break; + case DATATYPE_FLOAT: StringHelper::appendValue( aValue, static_cast< float >( nSValue ), rItemFmt.meFmtType ); break; + case DATATYPE_DOUBLE: StringHelper::appendValue( aValue, static_cast< double >( nSValue ), rItemFmt.meFmtType ); break; + default:; + } + StringHelper::appendToken( aItem, aValue.makeStringAndClear(), OOX_DUMP_ITEMSEP ); + if( rItemFmt.maListName.getLength() > 0 ) + { + OUString aValueName = rCfg.getName( rItemFmt.maListName, static_cast< sal_Int64 >( nUValue ) ); + StringHelper::appendToken( aItem, aValueName, OOX_DUMP_ITEMSEP ); + } + StringHelper::enclose( aItem, '(', ')' ); + StringHelper::appendToken( aName, aItem.makeStringAndClear() ); + setFlag( nFound, nMask ); + } + } + setFlag( nFlags, nFound, false ); + StringHelper::appendToken( aName, FlagsList::implGetName( rCfg, nFlags ) ); + return aName.makeStringAndClear(); +} + +void CombiList::implIncludeList( const NameListBase& rList ) +{ + if( const CombiList* pCombiList = dynamic_cast< const CombiList* >( &rList ) ) + maFmtMap = pCombiList->maFmtMap; + FlagsList::implIncludeList( rList ); +} + +// ============================================================================ + +UnitConverter::UnitConverter( const SharedConfigData& rCfgData ) : + NameListBase( rCfgData ), + mfFactor( 1.0 ) +{ +} + +void UnitConverter::implSetName( sal_Int64 /*nKey*/, const OUString& /*rName*/ ) +{ + // nothing to do +} + +OUString UnitConverter::implGetName( const Config& rCfg, sal_Int64 nKey ) const +{ + return implGetNameDbl( rCfg, static_cast< double >( nKey ) ); +} + +OUString UnitConverter::implGetNameDbl( const Config& /*rCfg*/, double fValue ) const +{ + OUStringBuffer aValue; + StringHelper::appendDec( aValue, mfFactor * fValue ); + aValue.append( maUnitName ); + return aValue.makeStringAndClear(); +} + +void UnitConverter::implIncludeList( const NameListBase& /*rList*/ ) +{ +} + +// ============================================================================ + +NameListRef NameListWrapper::getNameList( const Config& rCfg ) const +{ + return mxList.get() ? mxList : (mxList = rCfg.getNameList( maNameWrp.getString() )); +} + +// ============================================================================ +// ============================================================================ + +SharedConfigData::SharedConfigData( const OUString& rFileName ) +{ + construct( rFileName ); +} + +SharedConfigData::~SharedConfigData() +{ +} + +void SharedConfigData::construct( const OUString& rFileName ) +{ + mbLoaded = false; + OUString aFileUrl = InputOutputHelper::convertFileNameToUrl( rFileName ); + if( aFileUrl.getLength() > 0 ) + { + sal_Int32 nNamePos = InputOutputHelper::getFileNamePos( aFileUrl ); + maConfigPath = aFileUrl.copy( 0, nNamePos ); + mbLoaded = readConfigFile( aFileUrl ); + } +} + +void SharedConfigData::setOption( const OUString& rKey, const OUString& rData ) +{ + maConfigData[ rKey ] = rData; +} + +const OUString* SharedConfigData::getOption( const OUString& rKey ) const +{ + ConfigDataMap::const_iterator aIt = maConfigData.find( rKey ); + return (aIt == maConfigData.end()) ? 0 : &aIt->second; +} + +void SharedConfigData::setNameList( const OUString& rListName, NameListRef xList ) +{ + if( rListName.getLength() > 0 ) + maNameLists[ rListName ] = xList; +} + +void SharedConfigData::eraseNameList( const OUString& rListName ) +{ + maNameLists.erase( rListName ); +} + +NameListRef SharedConfigData::getNameList( const OUString& rListName ) const +{ + NameListRef xList; + NameListMap::const_iterator aIt = maNameLists.find( rListName ); + if( aIt != maNameLists.end() ) + xList = aIt->second; + return xList; +} + +bool SharedConfigData::implIsValid() const +{ + return mbLoaded; +} + +void SharedConfigData::implProcessConfigItemStr( + const ConfigInputStreamRef& rxStrm, const OUString& rKey, const OUString& rData ) +{ + if( rKey.equalsAscii( "include-config-file" ) ) + readConfigFile( maConfigPath + rData ); + else if( rKey.equalsAscii( "constlist" ) ) + readNameList< ConstList >( rxStrm, rData ); + else if( rKey.equalsAscii( "multilist" ) ) + readNameList< MultiList >( rxStrm, rData ); + else if( rKey.equalsAscii( "flagslist" ) ) + readNameList< FlagsList >( rxStrm, rData ); + else if( rKey.equalsAscii( "combilist" ) ) + readNameList< CombiList >( rxStrm, rData ); + else if( rKey.equalsAscii( "shortlist" ) ) + createShortList( rData ); + else if( rKey.equalsAscii( "unitconverter" ) ) + createUnitConverter( rData ); + else + setOption( rKey, rData ); +} + +bool SharedConfigData::readConfigFile( const OUString& rFileUrl ) +{ + bool bLoaded = false; + Reference< XTextInputStream > xTextInStrm = + InputOutputHelper::openTextInputStream( rFileUrl, CREATE_OUSTRING( "UTF-8" ) ); + if( xTextInStrm.is() ) + { + readConfigBlockContents( xTextInStrm ); + bLoaded = true; + } + return bLoaded; +} + +void SharedConfigData::createShortList( const OUString& rData ) +{ + OUStringVector aDataVec; + StringHelper::convertStringToStringList( aDataVec, rData, false ); + if( aDataVec.size() >= 3 ) + { + sal_Int64 nStartKey; + if( StringHelper::convertStringToInt( nStartKey, aDataVec[ 1 ] ) ) + { + ::boost::shared_ptr< MultiList > xList = createNameList< MultiList >( aDataVec[ 0 ] ); + if( xList.get() ) + { + aDataVec.erase( aDataVec.begin(), aDataVec.begin() + 2 ); + xList->setNamesFromVec( nStartKey, aDataVec ); + } + } + } +} + +void SharedConfigData::createUnitConverter( const OUString& rData ) +{ + OUStringVector aDataVec; + StringHelper::convertStringToStringList( aDataVec, rData, false ); + if( aDataVec.size() >= 2 ) + { + OUString aFactor = aDataVec[ 1 ]; + bool bRecip = (aFactor.getLength() > 0) && (aFactor[ 0 ] == '/'); + if( bRecip ) + aFactor = aFactor.copy( 1 ); + double fFactor; + if( StringHelper::convertStringToDouble( fFactor, aFactor ) && (fFactor != 0.0) ) + { + ::boost::shared_ptr< UnitConverter > xList = createNameList< UnitConverter >( aDataVec[ 0 ] ); + if( xList.get() ) + { + xList->setFactor( bRecip ? (1.0 / fFactor) : fFactor ); + if( aDataVec.size() >= 3 ) + xList->setUnitName( aDataVec[ 2 ] ); + } + } + } +} + +// ============================================================================ + +Config::Config( const Config& rParent ) : + Base() // c'tor needs to be called explicitly to avoid compiler warning +{ + construct( rParent ); +} + +Config::Config( const OUString& rFileName ) +{ + construct( rFileName ); +} + +Config::Config( const sal_Char* pcEnvVar ) +{ + construct( pcEnvVar ); +} + +Config::~Config() +{ +} + +void Config::construct( const Config& rParent ) +{ + *this = rParent; +} + +void Config::construct( const OUString& rFileName ) +{ + mxCfgData.reset( new SharedConfigData( rFileName ) ); +} + +void Config::construct( const sal_Char* pcEnvVar ) +{ + if( pcEnvVar ) + if( const sal_Char* pcFileName = ::getenv( pcEnvVar ) ) + construct( OUString::createFromAscii( pcFileName ) ); +} + +void Config::setStringOption( const StringWrapper& rKey, const StringWrapper& rData ) +{ + mxCfgData->setOption( rKey.getString(), rData.getString() ); +} + +const OUString& Config::getStringOption( const StringWrapper& rKey, const OUString& rDefault ) const +{ + const OUString* pData = implGetOption( rKey.getString() ); + return pData ? *pData : rDefault; +} + +bool Config::getBoolOption( const StringWrapper& rKey, bool bDefault ) const +{ + const OUString* pData = implGetOption( rKey.getString() ); + return pData ? StringHelper::convertStringToBool( *pData ) : bDefault; +} + +bool Config::isDumperEnabled() const +{ + return getBoolOption( "enable-dumper", false ); +} + +bool Config::isImportEnabled() const +{ + return getBoolOption( "enable-import", true ); +} + +void Config::setNameList( const StringWrapper& rListName, NameListRef xList ) +{ + mxCfgData->setNameList( rListName.getString(), xList ); +} + +void Config::eraseNameList( const StringWrapper& rListName ) +{ + mxCfgData->eraseNameList( rListName.getString() ); +} + +NameListRef Config::getNameList( const StringWrapper& rListName ) const +{ + return implGetNameList( rListName.getString() ); +} + +bool Config::implIsValid() const +{ + return isValid( mxCfgData ); +} + +const OUString* Config::implGetOption( const OUString& rKey ) const +{ + return mxCfgData->getOption( rKey ); +} + +NameListRef Config::implGetNameList( const OUString& rListName ) const +{ + return mxCfgData->getNameList( rListName ); +} + +// ============================================================================ +// ============================================================================ + +bool Input::implIsValid() const +{ + return true; +} + +Input& operator>>( Input& rIn, sal_Int64& rnData ) +{ + return rIn >> *reinterpret_cast< double* >( &rnData ); +} + +Input& operator>>( Input& rIn, sal_uInt64& rnData ) +{ + return rIn >> *reinterpret_cast< double* >( &rnData ); +} + +// ============================================================================ + +BinaryInput::BinaryInput( BinaryInputStream& rStrm ) : + mrStrm( rStrm ) +{ +} + +sal_Int64 BinaryInput::getSize() const +{ + return mrStrm.getLength(); +} + +sal_Int64 BinaryInput::tell() const +{ + return mrStrm.tell(); +} + +void BinaryInput::seek( sal_Int64 nPos ) +{ + mrStrm.seek( nPos ); +} + +void BinaryInput::skip( sal_Int32 nBytes ) +{ + mrStrm.skip( nBytes ); +} + +sal_Int32 BinaryInput::read( void* pBuffer, sal_Int32 nBytes ) +{ + return mrStrm.read( pBuffer, nBytes ); +} + +bool BinaryInput::implIsValid() const +{ + return mrStrm.is() && Input::implIsValid(); +} + +BinaryInput& BinaryInput::operator>>( sal_Int8& rnData ) { mrStrm >> rnData; return *this; } +BinaryInput& BinaryInput::operator>>( sal_uInt8& rnData ) { mrStrm >> rnData; return *this; } +BinaryInput& BinaryInput::operator>>( sal_Int16& rnData ) { mrStrm >> rnData; return *this; } +BinaryInput& BinaryInput::operator>>( sal_uInt16& rnData ) { mrStrm >> rnData; return *this; } +BinaryInput& BinaryInput::operator>>( sal_Int32& rnData ) { mrStrm >> rnData; return *this; } +BinaryInput& BinaryInput::operator>>( sal_uInt32& rnData ) { mrStrm >> rnData; return *this; } +BinaryInput& BinaryInput::operator>>( float& rfData ) { mrStrm >> rfData; return *this; } +BinaryInput& BinaryInput::operator>>( double& rfData ) { mrStrm >> rfData; return *this; } + +// ============================================================================ +// ============================================================================ + +Output::Output( const Reference< XTextOutputStream >& rxStrm ) +{ + construct( rxStrm ); +} + +Output::Output( const ::rtl::OUString& rFileName ) +{ + construct( InputOutputHelper::openTextOutputStream( rFileName, CREATE_OUSTRING( "UTF-8" ) ) ); +} + +// ---------------------------------------------------------------------------- + +void Output::newLine() +{ + if( maLine.getLength() > 0 ) + { + mxStrm->writeString( maIndent ); + maLine.append( sal_Unicode( '\n' ) ); + mxStrm->writeString( maLine.makeStringAndClear() ); + mnCol = 0; + mnLastItem = 0; + } +} + +void Output::emptyLine( size_t nCount ) +{ + for( size_t nIdx = 0; nIdx < nCount; ++nIdx ) + mxStrm->writeString( OUString( sal_Unicode( '\n' ) ) ); +} + +void Output::incIndent() +{ + OUStringBuffer aBuffer( maIndent ); + StringHelper::appendChar( aBuffer, ' ', OOX_DUMP_INDENT ); + maIndent = aBuffer.makeStringAndClear(); +} + +void Output::decIndent() +{ + if( maIndent.getLength() >= OOX_DUMP_INDENT ) + maIndent = maIndent.copy( OOX_DUMP_INDENT ); +} + +void Output::resetIndent() +{ + maIndent = OUString(); +} + +void Output::startTable( sal_Int32 nW1 ) +{ + startTable( 1, &nW1 ); +} + +void Output::startTable( sal_Int32 nW1, sal_Int32 nW2 ) +{ + sal_Int32 pnColWidths[ 2 ]; + pnColWidths[ 0 ] = nW1; + pnColWidths[ 1 ] = nW2; + startTable( 2, pnColWidths ); +} + +void Output::startTable( sal_Int32 nW1, sal_Int32 nW2, sal_Int32 nW3 ) +{ + sal_Int32 pnColWidths[ 3 ]; + pnColWidths[ 0 ] = nW1; + pnColWidths[ 1 ] = nW2; + pnColWidths[ 2 ] = nW3; + startTable( 3, pnColWidths ); +} + +void Output::startTable( sal_Int32 nW1, sal_Int32 nW2, sal_Int32 nW3, sal_Int32 nW4 ) +{ + sal_Int32 pnColWidths[ 4 ]; + pnColWidths[ 0 ] = nW1; + pnColWidths[ 1 ] = nW2; + pnColWidths[ 2 ] = nW3; + pnColWidths[ 3 ] = nW4; + startTable( 4, pnColWidths ); +} + +void Output::startTable( size_t nColCount, const sal_Int32* pnColWidths ) +{ + maColPos.clear(); + maColPos.push_back( 0 ); + sal_Int32 nColPos = 0; + for( size_t nCol = 0; nCol < nColCount; ++nCol ) + { + nColPos = nColPos + pnColWidths[ nCol ]; + maColPos.push_back( nColPos ); + } +} + +void Output::tab() +{ + tab( mnCol + 1 ); +} + +void Output::tab( size_t nCol ) +{ + mnCol = nCol; + if( mnCol < maColPos.size() ) + { + sal_Int32 nColPos = maColPos[ mnCol ]; + if( maLine.getLength() >= nColPos ) + maLine.setLength( ::std::max< sal_Int32 >( nColPos - 1, 0 ) ); + StringHelper::appendChar( maLine, ' ', nColPos - maLine.getLength() ); + } + else + { + StringHelper::appendChar( maLine, ' ', 2 ); + } +} + +void Output::endTable() +{ + maColPos.clear(); +} + +void Output::resetItemIndex( sal_Int64 nIdx ) +{ + mnItemIdx = nIdx; +} + +void Output::startItem( const sal_Char* pcName ) +{ + if( mnItemLevel == 0 ) + { + if( (mnMultiLevel > 0) && (maLine.getLength() > 0) ) + tab(); + if( pcName ) + { + writeItemName( pcName ); + writeChar( OOX_DUMP_ITEMSEP ); + } + } + ++mnItemLevel; + mnLastItem = maLine.getLength(); +} + +void Output::contItem() +{ + if( mnItemLevel > 0 ) + { + if( (maLine.getLength() == 0) || (maLine[ maLine.getLength() - 1 ] != OOX_DUMP_ITEMSEP) ) + writeChar( OOX_DUMP_ITEMSEP ); + mnLastItem = maLine.getLength(); + } +} + +void Output::endItem() +{ + if( mnItemLevel > 0 ) + { + maLastItem = OUString( maLine.getStr() + mnLastItem ); + if( (maLastItem.getLength() == 0) && (mnLastItem > 0) && (maLine[ mnLastItem - 1 ] == OOX_DUMP_ITEMSEP) ) + maLine.setLength( mnLastItem - 1 ); + --mnItemLevel; + } + if( mnItemLevel == 0 ) + { + if( mnMultiLevel == 0 ) + newLine(); + } + else + contItem(); +} + +void Output::startMultiItems() +{ + ++mnMultiLevel; +} + +void Output::endMultiItems() +{ + if( mnMultiLevel > 0 ) + --mnMultiLevel; + if( mnMultiLevel == 0 ) + newLine(); +} + +// ---------------------------------------------------------------------------- + +void Output::writeChar( sal_Unicode cChar, sal_Int32 nCount ) +{ + StringHelper::appendEncChar( maLine, cChar, nCount ); +} + +void Output::writeAscii( const sal_Char* pcStr ) +{ + if( pcStr ) + maLine.appendAscii( pcStr ); +} + +void Output::writeString( const OUString& rStr ) +{ + StringHelper::appendEncString( maLine, rStr ); +} + +void Output::writeArray( const sal_uInt8* pnData, sal_Size nSize, sal_Unicode cSep ) +{ + const sal_uInt8* pnEnd = pnData ? (pnData + nSize) : 0; + for( const sal_uInt8* pnByte = pnData; pnByte < pnEnd; ++pnByte ) + { + if( pnByte > pnData ) + writeChar( cSep ); + writeHex( *pnByte, false ); + } +} + +void Output::writeBool( bool bData ) +{ + StringHelper::appendBool( maLine, bData ); +} + +void Output::writeColor( sal_Int32 nColor ) +{ + writeChar( 'a' ); + writeDec( static_cast< sal_uInt8 >( nColor >> 24 ) ); + writeAscii( ",r" ); + writeDec( static_cast< sal_uInt8 >( nColor >> 16 ) ); + writeAscii( ",g" ); + writeDec( static_cast< sal_uInt8 >( nColor >> 8 ) ); + writeAscii( ",b" ); + writeDec( static_cast< sal_uInt8 >( nColor ) ); +} + +void Output::writeDateTime( const DateTime& rDateTime ) +{ + writeDec( rDateTime.Year, 4, '0' ); + writeChar( '-' ); + writeDec( rDateTime.Month, 2, '0' ); + writeChar( '-' ); + writeDec( rDateTime.Day, 2, '0' ); + writeChar( 'T' ); + writeDec( rDateTime.Hours, 2, '0' ); + writeChar( ':' ); + writeDec( rDateTime.Minutes, 2, '0' ); + writeChar( ':' ); + writeDec( rDateTime.Seconds, 2, '0' ); +} + +void Output::writeColIndex( sal_Int32 nCol ) +{ + StringHelper::appendAddrCol( maLine, nCol, true ); +} + +void Output::writeRowIndex( sal_Int32 nRow ) +{ + StringHelper::appendAddrRow( maLine, nRow, true ); +} + +void Output::writeColRowRange( sal_Int32 nColRow1, sal_Int32 nColRow2 ) +{ + writeDec( nColRow1 ); + writeChar( OOX_DUMP_RANGESEP ); + writeDec( nColRow2 ); +} + +void Output::writeColRange( sal_Int32 nCol1, sal_Int32 nCol2 ) +{ + writeColIndex( nCol1 ); + writeChar( OOX_DUMP_RANGESEP ); + writeColIndex( nCol2 ); +} + +void Output::writeRowRange( sal_Int32 nRow1, sal_Int32 nRow2 ) +{ + writeRowIndex( nRow1 ); + writeChar( OOX_DUMP_RANGESEP ); + writeRowIndex( nRow2 ); +} + +void Output::writeAddress( const Address& rPos ) +{ + StringHelper::appendAddress( maLine, rPos ); +} + +void Output::writeRange( const Range& rRange ) +{ + StringHelper::appendRange( maLine, rRange ); +} + +void Output::writeRangeList( const RangeList& rRanges ) +{ + StringHelper::appendRangeList( maLine, rRanges ); +} + +// ---------------------------------------------------------------------------- + +void Output::construct( const Reference< XTextOutputStream >& rxStrm ) +{ + mxStrm = rxStrm; + mnCol = mnItemLevel = mnMultiLevel = 0; + mnItemIdx = 0; + mnLastItem = 0; + if( mxStrm.is() ) + { + writeChar( OOX_DUMP_BOM ); + writeAscii( "OpenOffice.org binary file dumper v2.0" ); + newLine(); + emptyLine(); + } +} + +bool Output::implIsValid() const +{ + return mxStrm.is(); +} + +void Output::writeItemName( const sal_Char* pcName ) +{ + if( pcName && (*pcName == '#') ) + { + writeAscii( pcName + 1 ); + StringHelper::appendIndex( maLine, mnItemIdx++ ); + } + else + writeAscii( pcName ); +} + +// ============================================================================ +// ============================================================================ + +ObjectBase::~ObjectBase() +{ +} + +void ObjectBase::construct( const FilterBase& rFilter, ConfigRef xConfig ) +{ + mpFilter = &rFilter; + mxConfig = xConfig; +} + +void ObjectBase::construct( const ObjectBase& rParent ) +{ + *this = rParent; +} + +void ObjectBase::dump() +{ + if( isValid() ) + implDump(); +} + +bool ObjectBase::implIsValid() const +{ + return mpFilter && mpFilter->isImportFilter() && isValid( mxConfig ); +} + +ConfigRef ObjectBase::implReconstructConfig() +{ + return mxConfig; +} + +void ObjectBase::implDump() +{ +} + +void ObjectBase::reconstructConfig() +{ + mxConfig = implReconstructConfig(); +} + +// ============================================================================ +// ============================================================================ + +RootStorageObjectBase::~RootStorageObjectBase() +{ +} + +void RootStorageObjectBase::construct( const ObjectBase& rParent ) +{ + ObjectBase::construct( rParent ); +} + +void RootStorageObjectBase::implDump() +{ + StorageRef xStrg = getFilter().getStorage(); + if( xStrg.get() && xStrg->isStorage() ) + extractStorage( xStrg, getFilter().getFileUrl() + CREATE_OUSTRING( ".dump" ) ); +} + +void RootStorageObjectBase::implDumpStream( BinaryInputStreamRef, const OUString&, const OUString&, const OUString& ) +{ +} + +void RootStorageObjectBase::extractStream( StorageBase& rStrg, const OUString& rStrmName, const OUString& rSystemFileName ) +{ + BinaryInputStream aInStrm( rStrg.openInputStream( rStrmName ), true ); + if( aInStrm.is() ) + { + BinaryOutputStream aOutStrm( InputOutputHelper::openOutputStream( rSystemFileName ), true ); + if( aOutStrm.is() ) + aOutStrm.copy( aInStrm ); + } + BinaryInputStreamRef xDumpStrm( new BinaryInputStream( InputOutputHelper::openInputStream( rSystemFileName ), true ) ); + if( xDumpStrm->is() ) + implDumpStream( xDumpStrm, rStrg.getPath(), rStrmName, rSystemFileName + CREATE_OUSTRING( ".dump" ) ); +} + +void RootStorageObjectBase::extractStorage( StorageRef xStrg, const OUString& rSystemPath ) +{ + // create directory in file system + ::osl::FileBase::RC eRes = ::osl::Directory::create( rSystemPath ); + if( (eRes == ::osl::FileBase::E_None) || (eRes == ::osl::FileBase::E_EXIST) ) + { + // process children of the storage + for( StorageIterator aIt( xStrg ); aIt.isValid(); ++aIt ) + { + // encode all characters < 0x20 + OUStringBuffer aBuffer; + StringHelper::appendEncString( aBuffer, aIt.getName(), false ); + + // replace all characters reserved in file system + OUString aSystemName = aBuffer.makeStringAndClear(); + static const sal_Unicode spcReserved[] = { '/', '\\', ':', '*', '?', '<', '>', '|' }; + for( const sal_Unicode* pcChar = spcReserved; pcChar < STATIC_ARRAY_END( spcReserved ); ++pcChar ) + aSystemName = aSystemName.replace( *pcChar, '_' ); + + // build full path + OUString aFullSystemName = rSystemPath + OUString( sal_Unicode( '/' ) ) + aSystemName; + + // handle storages and streams + if( aIt.isStorage() ) + extractStorage( xStrg->openSubStorage( aIt.getName(), false ), aFullSystemName ); + else if( aIt.isStream() ) + extractStream( *xStrg, aIt.getName(), aFullSystemName ); + } + } +} + +// ============================================================================ + +StorageIterator::StorageIterator( StorageRef xStrg ) : + mxStrg( xStrg ) +{ + if( mxStrg.get() ) + mxStrg->getElementNames( maNames ); + maIt = maNames.begin(); +} + +StorageIterator::~StorageIterator() +{ +} + +size_t StorageIterator::getElementCount() const +{ + return maNames.size(); +} + +StorageIterator& StorageIterator::operator++() +{ + if( maIt != maNames.end() ) + ++maIt; + return *this; +} + +OUString StorageIterator::getName() const +{ + OUString aName; + if( maIt != maNames.end() ) + aName = *maIt; + return aName; +} + +bool StorageIterator::isStream() const +{ + return isValid() && mxStrg->openInputStream( *maIt ).is(); +} + +bool StorageIterator::isStorage() const +{ + if( !isValid() ) + return false; + StorageRef xStrg = mxStrg->openSubStorage( *maIt, false ); + return xStrg.get() && xStrg->isStorage(); +} + +bool StorageIterator::implIsValid() const +{ + return mxStrg.get() && mxStrg->isStorage() && (maIt != maNames.end()); +} + +// ============================================================================ +// ============================================================================ + +OutputObjectBase::~OutputObjectBase() +{ +} + +void OutputObjectBase::construct( const ObjectBase& rParent, const OUString& rOutFileName ) +{ + ObjectBase::construct( rParent ); + mxOut.reset( new Output( rOutFileName ) ); +} + +void OutputObjectBase::construct( const ObjectBase& rParent, OutputRef xOut ) +{ + ObjectBase::construct( rParent ); + mxOut = xOut; +} + +void OutputObjectBase::construct( const OutputObjectBase& rParent ) +{ + *this = rParent; +} + +bool OutputObjectBase::implIsValid() const +{ + return isValid( mxOut ) && ObjectBase::implIsValid(); +} + +OutputRef OutputObjectBase::implReconstructOutput() +{ + return mxOut; +} + +void OutputObjectBase::reconstructOutput() +{ + mxOut = implReconstructOutput(); +} + +void OutputObjectBase::writeEmptyItem( const sal_Char* pcName ) +{ + ItemGuard aItem( *mxOut, pcName ); +} + +void OutputObjectBase::writeInfoItem( const sal_Char* pcName, const StringWrapper& rData ) +{ + ItemGuard aItem( *mxOut, pcName ); + mxOut->writeString( rData.getString() ); +} + +void OutputObjectBase::writeStringItem( const sal_Char* pcName, const ::rtl::OUString& rData ) +{ + ItemGuard aItem( *mxOut, pcName ); + mxOut->writeAscii( "(len=" ); + mxOut->writeDec( rData.getLength() ); + mxOut->writeAscii( ")," ); + OUStringBuffer aValue( rData.copy( 0, ::std::min( rData.getLength(), OOX_DUMP_MAXSTRLEN ) ) ); + StringHelper::enclose( aValue, OOX_DUMP_STRQUOTE ); + mxOut->writeString( aValue.makeStringAndClear() ); + if( rData.getLength() > OOX_DUMP_MAXSTRLEN ) + mxOut->writeAscii( ",cut" ); +} + +void OutputObjectBase::writeArrayItem( const sal_Char* pcName, const sal_uInt8* pnData, sal_Size nSize, sal_Unicode cSep ) +{ + ItemGuard aItem( *mxOut, pcName ); + mxOut->writeArray( pnData, nSize, cSep ); +} + +void OutputObjectBase::writeBoolItem( const sal_Char* pcName, bool bData ) +{ + ItemGuard aItem( *mxOut, pcName ); + mxOut->writeBool( bData ); +} + +double OutputObjectBase::writeRkItem( const sal_Char* pcName, sal_Int32 nRk ) +{ + MultiItemsGuard aMultiGuard( out() ); + writeHexItem( pcName, static_cast< sal_uInt32 >( nRk ), "RK-FLAGS" ); + double fValue = ::oox::xls::BiffHelper::calcDoubleFromRk( nRk ); + writeDecItem( "decoded", fValue ); + return fValue; +} + +void OutputObjectBase::writeColorItem( const sal_Char* pcName, sal_Int32 nColor ) +{ + ItemGuard aItem( *mxOut, pcName ); + writeHexItem( pcName, nColor ); + mxOut->writeColor( nColor ); +} + +void OutputObjectBase::writeDateTimeItem( const sal_Char* pcName, const DateTime& rDateTime ) +{ + ItemGuard aItem( *mxOut, pcName ); + mxOut->writeDateTime( rDateTime ); +} + +void OutputObjectBase::writeGuidItem( const sal_Char* pcName, const OUString& rGuid ) +{ + ItemGuard aItem( *mxOut, pcName ); + mxOut->writeString( rGuid ); + aItem.cont(); + mxOut->writeString( cfg().getStringOption( rGuid, OUString() ) ); +} + +void OutputObjectBase::writeColIndexItem( const sal_Char* pcName, sal_Int32 nCol ) +{ + Output& rOut = out(); + ItemGuard aItem( rOut, pcName ); + rOut.writeDec( nCol ); + aItem.cont(); + rOut.writeColIndex( nCol ); +} + +void OutputObjectBase::writeRowIndexItem( const sal_Char* pcName, sal_Int32 nRow ) +{ + Output& rOut = out(); + ItemGuard aItem( rOut, pcName ); + rOut.writeDec( nRow ); + aItem.cont(); + rOut.writeRowIndex( nRow ); +} + +void OutputObjectBase::writeColRangeItem( const sal_Char* pcName, sal_Int32 nCol1, sal_Int32 nCol2 ) +{ + Output& rOut = out(); + ItemGuard aItem( rOut, pcName ); + rOut.writeColRowRange( nCol1, nCol2 ); + aItem.cont(); + rOut.writeColRange( nCol1, nCol2 ); +} + +void OutputObjectBase::writeRowRangeItem( const sal_Char* pcName, sal_Int32 nRow1, sal_Int32 nRow2 ) +{ + Output& rOut = out(); + ItemGuard aItem( rOut, pcName ); + rOut.writeColRowRange( nRow1, nRow2 ); + aItem.cont(); + rOut.writeRowRange( nRow1, nRow2 ); +} + +void OutputObjectBase::writeAddressItem( const sal_Char* pcName, const Address& rPos ) +{ + ItemGuard aItem( out(), pcName ); + StringHelper::appendAddress( out().getLine(), rPos ); +} + +void OutputObjectBase::writeRangeItem( const sal_Char* pcName, const Range& rRange ) +{ + ItemGuard aItem( out(), pcName ); + StringHelper::appendRange( out().getLine(), rRange ); +} + +void OutputObjectBase::writeRangeListItem( const sal_Char* pcName, const RangeList& rRanges ) +{ + MultiItemsGuard aMultiGuard( out() ); + writeEmptyItem( pcName ); + writeDecItem( "count", static_cast< sal_uInt16 >( rRanges.size() ) ); + ItemGuard aItem( out(), "ranges" ); + StringHelper::appendRangeList( out().getLine(), rRanges ); +} + +void OutputObjectBase::writeTokenAddressItem( const sal_Char* pcName, const TokenAddress& rPos, bool bNameMode ) +{ + ItemGuard aItem( out(), pcName ); + StringHelper::appendAddress( out().getLine(), rPos, bNameMode ); +} + +void OutputObjectBase::writeTokenAddress3dItem( const sal_Char* pcName, const OUString& rRef, const TokenAddress& rPos, bool bNameMode ) +{ + ItemGuard aItem( out(), pcName ); + out().writeString( rRef ); + StringHelper::appendAddress( out().getLine(), rPos, bNameMode ); +} + +void OutputObjectBase::writeTokenRangeItem( const sal_Char* pcName, const TokenRange& rRange, bool bNameMode ) +{ + ItemGuard aItem( out(), pcName ); + StringHelper::appendRange( out().getLine(), rRange, bNameMode ); +} + +void OutputObjectBase::writeTokenRange3dItem( const sal_Char* pcName, const OUString& rRef, const TokenRange& rRange, bool bNameMode ) +{ + ItemGuard aItem( out(), pcName ); + out().writeString( rRef ); + StringHelper::appendRange( out().getLine(), rRange, bNameMode ); +} + +// ============================================================================ +// ============================================================================ + +InputObjectBase::~InputObjectBase() +{ +} + +void InputObjectBase::construct( const ObjectBase& rParent, const ::rtl::OUString& rOutFileName, InputRef xIn ) +{ + OutputObjectBase::construct( rParent, rOutFileName ); + mxIn = xIn; +} + +void InputObjectBase::construct( const ObjectBase& rParent, OutputRef xOut, InputRef xIn ) +{ + OutputObjectBase::construct( rParent, xOut ); + mxIn = xIn; +} + +void InputObjectBase::construct( const OutputObjectBase& rParent, InputRef xIn ) +{ + OutputObjectBase::construct( rParent ); + mxIn = xIn; +} + +void InputObjectBase::construct( const InputObjectBase& rParent ) +{ + *this = rParent; +} + +bool InputObjectBase::implIsValid() const +{ + return isValid( mxIn ) && OutputObjectBase::implIsValid(); +} + +InputRef InputObjectBase::implReconstructInput() +{ + return mxIn; +} + +void InputObjectBase::reconstructInput() +{ + mxIn = implReconstructInput(); +} + +void InputObjectBase::skipBlock( sal_Int32 nBytes, bool bShowSize ) +{ + sal_Int64 nEndPos = ::std::min< sal_Int64 >( mxIn->tell() + nBytes, mxIn->getSize() ); + if( mxIn->tell() < nEndPos ) + { + if( bShowSize ) + writeDecItem( "skipped-data-size", static_cast< sal_uInt64 >( nEndPos - mxIn->tell() ) ); + mxIn->seek( nEndPos ); + } +} + +void InputObjectBase::dumpRawBinary( sal_Int32 nBytes, bool bShowOffset, bool bStream ) +{ + Output& rOut = out(); + TableGuard aTabGuard( rOut, + bShowOffset ? 12 : 0, + 3 * OOX_DUMP_BYTESPERLINE / 2 + 1, + 3 * OOX_DUMP_BYTESPERLINE / 2 + 1, + OOX_DUMP_BYTESPERLINE / 2 + 1 ); + + sal_Int32 nMaxShowSize = cfg().getIntOption< sal_Int32 >( + bStream ? "max-binary-stream-size" : "max-binary-data-size", SAL_MAX_INT32 ); + + bool bSeekable = mxIn->getSize() >= 0; + sal_Int64 nEndPos = bSeekable ? ::std::min< sal_Int64 >( mxIn->tell() + nBytes, mxIn->getSize() ) : 0; + sal_Int64 nDumpEnd = bSeekable ? ::std::min< sal_Int64 >( mxIn->tell() + nMaxShowSize, nEndPos ) : nMaxShowSize; + sal_Int64 nPos = bSeekable ? mxIn->tell() : 0; + bool bLoop = true; + + while( bLoop && (nPos < nDumpEnd) ) + { + rOut.writeHex( static_cast< sal_uInt32 >( nPos ) ); + rOut.tab(); + + sal_uInt8 pnLineData[ OOX_DUMP_BYTESPERLINE ]; + sal_Int32 nLineSize = bSeekable ? ::std::min( static_cast< sal_Int32 >( nDumpEnd - mxIn->tell() ), OOX_DUMP_BYTESPERLINE ) : OOX_DUMP_BYTESPERLINE; + sal_Int32 nReadSize = mxIn->read( pnLineData, nLineSize ); + bLoop = nReadSize == nLineSize; + nPos += nReadSize; + + if( nReadSize > 0 ) + { + const sal_uInt8* pnByte = 0; + const sal_uInt8* pnEnd = 0; + for( pnByte = pnLineData, pnEnd = pnLineData + nReadSize; pnByte != pnEnd; ++pnByte ) + { + if( (pnByte - pnLineData) == (OOX_DUMP_BYTESPERLINE / 2) ) rOut.tab(); + rOut.writeHex( *pnByte, false ); + rOut.writeChar( ' ' ); + } + + aTabGuard.tab( 3 ); + for( pnByte = pnLineData, pnEnd = pnLineData + nLineSize; pnByte != pnEnd; ++pnByte ) + { + if( (pnByte - pnLineData) == (OOX_DUMP_BYTESPERLINE / 2) ) rOut.tab(); + rOut.writeChar( static_cast< sal_Unicode >( (*pnByte < 0x20) ? '.' : *pnByte ) ); + } + rOut.newLine(); + } + } + + // skip undumped data + if( bSeekable ) + skipBlock( static_cast< sal_Int32 >( nEndPos - mxIn->tell() ) ); +} + +void InputObjectBase::dumpBinary( const sal_Char* pcName, sal_Int32 nBytes, bool bShowOffset ) +{ + { + MultiItemsGuard aMultiGuard( out() ); + writeEmptyItem( pcName ); + writeDecItem( "size", nBytes ); + } + IndentGuard aIndGuard( out() ); + dumpRawBinary( nBytes, bShowOffset ); +} + +void InputObjectBase::dumpArray( const sal_Char* pcName, sal_Int32 nBytes, sal_Unicode cSep ) +{ + sal_Int32 nDumpSize = getLimitedValue< sal_Int32, sal_Int64 >( mxIn->getSize() - mxIn->tell(), 0, nBytes ); + if( nDumpSize > OOX_DUMP_MAXARRAY ) + { + dumpBinary( pcName, nBytes, false ); + } + else if( nDumpSize > 1 ) + { + sal_uInt8 pnData[ OOX_DUMP_MAXARRAY ]; + mxIn->read( pnData, nDumpSize ); + writeArrayItem( pcName, pnData, nDumpSize, cSep ); + } + else if( nDumpSize == 1 ) + dumpHex< sal_uInt8 >( pcName ); +} + +void InputObjectBase::dumpRemaining( sal_Int32 nBytes ) +{ + if( nBytes > 0 ) + { + if( cfg().getBoolOption( "show-trailing-unknown", true ) ) + dumpBinary( "remaining-data", nBytes, false ); + else + skipBlock( nBytes ); + } +} + +OUString InputObjectBase::dumpCharArray( const sal_Char* pcName, sal_Int32 nSize, rtl_TextEncoding eTextEnc ) +{ + sal_Int32 nDumpSize = getLimitedValue< sal_Int32, sal_Int64 >( mxIn->getSize() - mxIn->tell(), 0, nSize ); + OUString aString; + if( nDumpSize > 0 ) + { + ::std::vector< sal_Char > aBuffer( static_cast< sal_Size >( nSize ) + 1 ); + sal_Int32 nCharsRead = mxIn->read( &aBuffer.front(), nSize ); + aBuffer[ nCharsRead ] = 0; + aString = OStringToOUString( OString( &aBuffer.front() ), eTextEnc ); + } + writeStringItem( pcName, aString ); + return aString; +} + +OUString InputObjectBase::dumpUnicodeArray( const sal_Char* pcName, sal_Int32 nSize ) +{ + OUStringBuffer aBuffer; + for( sal_Int32 nIndex = 0; mxIn->isValidPos() && (nIndex < nSize); ++nIndex ) + aBuffer.append( static_cast< sal_Unicode >( mxIn->readValue< sal_uInt16 >() ) ); + OUString aString = aBuffer.makeStringAndClear(); + writeStringItem( pcName, aString ); + return aString; +} + +double InputObjectBase::dumpRk( const sal_Char* pcName ) +{ + sal_Int32 nRk; + *mxIn >> nRk; + return writeRkItem( pcName ? pcName : "rk-value", nRk ); +} + +OUString InputObjectBase::dumpGuid( const sal_Char* pcName ) +{ + OUStringBuffer aBuffer; + sal_uInt32 nData32; + sal_uInt16 nData16; + sal_uInt8 nData8; + + *mxIn >> nData32; + StringHelper::appendHex( aBuffer, nData32, false ); + aBuffer.append( sal_Unicode( '-' ) ); + *mxIn >> nData16; + StringHelper::appendHex( aBuffer, nData16, false ); + aBuffer.append( sal_Unicode( '-' ) ); + *mxIn >> nData16; + StringHelper::appendHex( aBuffer, nData16, false ); + aBuffer.append( sal_Unicode( '-' ) ); + *mxIn >> nData8; + StringHelper::appendHex( aBuffer, nData8, false ); + *mxIn >> nData8; + StringHelper::appendHex( aBuffer, nData8, false ); + aBuffer.append( sal_Unicode( '-' ) ); + for( int nIndex = 0; nIndex < 6; ++nIndex ) + { + *mxIn >> nData8; + StringHelper::appendHex( aBuffer, nData8, false ); + } + OUString aGuid = aBuffer.makeStringAndClear(); + writeGuidItem( pcName ? pcName : "guid", aGuid ); + return aGuid; +} + +void InputObjectBase::dumpItem( const ItemFormat& rItemFmt ) +{ + switch( rItemFmt.meDataType ) + { + case DATATYPE_VOID: break; + case DATATYPE_INT8: dumpValue< sal_Int8 >( rItemFmt ); break; + case DATATYPE_UINT8: dumpValue< sal_uInt8 >( rItemFmt ); break; + case DATATYPE_INT16: dumpValue< sal_Int16 >( rItemFmt ); break; + case DATATYPE_UINT16: dumpValue< sal_uInt16 >( rItemFmt ); break; + case DATATYPE_INT32: dumpValue< sal_Int32 >( rItemFmt ); break; + case DATATYPE_UINT32: dumpValue< sal_uInt32 >( rItemFmt ); break; + case DATATYPE_INT64: dumpValue< sal_Int64 >( rItemFmt ); break; + case DATATYPE_UINT64: dumpValue< sal_uInt64 >( rItemFmt ); break; + case DATATYPE_FLOAT: dumpValue< float >( rItemFmt ); break; + case DATATYPE_DOUBLE: dumpValue< double >( rItemFmt ); break; + default:; + } +} + +// ============================================================================ + +InputStreamObject::InputStreamObject( const ObjectBase& rParent, const OUString& rOutFileName, BinaryInputStreamRef xStrm ) +{ + construct( rParent, rOutFileName, xStrm ); +} + +InputStreamObject::~InputStreamObject() +{ +} + +void InputStreamObject::construct( const ObjectBase& rParent, const OUString& rOutFileName, BinaryInputStreamRef xStrm ) +{ + mxStrm = xStrm; + if( mxStrm.get() ) + InputObjectBase::construct( rParent, rOutFileName, InputRef( new BinaryInput( *mxStrm ) ) ); +} + +sal_Int64 InputStreamObject::getStreamSize() const +{ + return mxStrm.get() ? mxStrm->getLength() : -1; +} + +void InputStreamObject::dumpBinaryStream( bool bShowOffset ) +{ + in().seek( 0 ); + dumpRawBinary( getLimitedValue< sal_Int32, sal_Int64 >( in().getSize(), 0, SAL_MAX_INT32 ), bShowOffset, true ); + out().emptyLine(); +} + +bool InputStreamObject::implIsValid() const +{ + return mxStrm.get() && mxStrm->is() && InputObjectBase::implIsValid(); +} + +void InputStreamObject::implDump() +{ + dumpBinaryStream(); +} + +// ============================================================================ + +TextStreamObject::TextStreamObject( const ObjectBase& rParent, const OUString& rOutFileName, BinaryInputStreamRef xStrm ) : + InputStreamObject( rParent, rOutFileName, xStrm ) +{ +} + +void TextStreamObject::implDump() +{ + dumpTextStream( osl_getThreadTextEncoding() ); +} + +void TextStreamObject::dumpTextStream( rtl_TextEncoding eTextEnc, bool bShowLines ) +{ + Output& rOut = out(); + TableGuard aTabGuard( rOut, bShowLines ? 8 : 0 ); + + const sal_Char* pcTextEnc = rtl_getBestUnixCharsetFromTextEncoding( eTextEnc ); + OUString aEncoding = OUString::createFromAscii( pcTextEnc ? pcTextEnc : "UTF-8" ); + Reference< XTextInputStream > xTextStrm = InputOutputHelper::openTextInputStream( getStream().getXInputStream(), aEncoding ); + if( xTextStrm.is() ) + { + sal_uInt32 nLine = 0; + while( !xTextStrm->isEOF() ) + { + rOut.writeDec( ++nLine, 6 ); + rOut.tab(); + try { rOut.writeString( xTextStrm->readLine() ); } catch( Exception& ) {} + rOut.newLine(); + } + } + rOut.emptyLine(); +} + +// ============================================================================ +// ============================================================================ + +RecordHeaderImplBase::~RecordHeaderImplBase() +{ +} + +void RecordHeaderImplBase::construct( const InputObjectBase& rParent, const RecordHeaderConfigInfo& rCfgInfo ) +{ + InputObjectBase::construct( rParent ); + if( InputObjectBase::implIsValid() ) + { + const Config& rCfg = cfg(); + mpcTitle = rCfgInfo.mpcTitle; + mxRecNames = rCfg.getNameList( rCfgInfo.mpcRecNames ); + mbShowRecPos = rCfg.getBoolOption( rCfgInfo.mpcShowRecPos, true ); + mbShowRecSize = rCfg.getBoolOption( rCfgInfo.mpcShowRecSize, true ); + mbShowRecId = rCfg.getBoolOption( rCfgInfo.mpcShowRecId, true ); + mbShowRecName = rCfg.getBoolOption( rCfgInfo.mpcShowRecName, true ); + mbShowRecBody = rCfg.getBoolOption( rCfgInfo.mpcShowRecBody, true ); + } +} + +bool RecordHeaderImplBase::implIsValid() const +{ + return isValid( mxRecNames ) && InputObjectBase::implIsValid(); +} + +// ============================================================================ +// ============================================================================ + +DumperBase::~DumperBase() +{ +} + +bool DumperBase::isImportEnabled() const +{ + return !isValid() || cfg().isImportEnabled(); +} + +StorageRef DumperBase::getRootStorage() const +{ + return getFilter().getStorage(); +} + +BinaryInputStreamRef DumperBase::getRootStream() const +{ + BinaryInputStreamRef xStrm; + if( StorageBase* pStrg = getRootStorage().get() ) + xStrm.reset( new BinaryInputStream( pStrg->openInputStream( OUString() ), false ) ); + return xStrm; +} + +void DumperBase::construct( const FilterBase& rFilter, ConfigRef xConfig ) +{ + if( rFilter.isImportFilter() && isValid( xConfig ) && xConfig->isDumperEnabled() ) + ObjectBase::construct( rFilter, xConfig ); +} + +// ============================================================================ +// ============================================================================ + +} // namespace dump +} // namespace oox + +#endif + diff --git a/oox/source/dump/dumperconfig.dat b/oox/source/dump/dumperconfig.dat new file mode 100644 index 000000000000..b3920e210090 --- /dev/null +++ b/oox/source/dump/dumperconfig.dat @@ -0,0 +1,436 @@ + +# dumper settings ============================================================ + +# Enable entire dumper (default=off). If dumper is disabled, no output into +# a text file is done. This option does not affect the options 'enable-import' +# and 'extract-storage-streams'. +# 0=off, 1=on +enable-dumper=1 + +# Enable import after dumping (default=on). Disabling this option allows +# to dump a file without loading it. This option is independent from the +# 'enable-dumper' option. +# 0=off, 1=on +enable-import=1 + +# Maximum size of binary stream dumps (default=infinite). +max-binary-stream-size=0x1000 + +# Maximum size of binary data blocks in content dumps (default=infinite). +max-binary-data-size=0x0200 + +# Shows unknown trailing data as binary dump (default=on). +# 0=off, 1=on +show-trailing-unknown=1 + +# DFF record settings -------------------------------------------------------- + +# Show total stream position of the DFF record (default=on). +# 0=off, 1=on +show-dff-record-pos=0 + +# Show total DFF record size in bytes (default=on). +# 0=off, 1=on +show-dff-record-size=1 + +# Show DFF record identifier (default=on). +# 0=off, 1=on +show-dff-record-id=1 + +# Show DFF record name, if known (default=on). +# 0=off, 1=on +show-dff-record-name=1 + +# Show DFF record contents (default=on). +# 0=off, 1=on +show-dff-record-body=1 + +# name lists ================================================================= + +unitconverter=CONV-DEC,1 +unitconverter=CONV-PERCENT,1,% +unitconverter=CONV-DEG,1,° +unitconverter=CONV-INCH-TO-CM,2.54,cm +unitconverter=CONV-TWIP-TO-PT,/20,pt +unitconverter=CONV-PT-TO-CM,/28.346457,cm +unitconverter=CONV-PT1616-TO-CM,/1857713.4,cm +unitconverter=CONV-TWIP-TO-CM,/566.92913,cm + +constlist=BOOLEAN + 0=FALSE + default=TRUE +end + +combilist=RK-FLAGS + 0x00000001=div-100 + 0x00000002=integer + 0xFFFFFFFC=int32,dec,value +end + +constlist=CHARSET + 0=win-1252-latin-1 + 1=system-default + 2=symbol + 77=apple-roman + 128=win-932-japanese-shift-jis + 129=win-949-korean-hangul + 130=win-1361-korean-johab + 134=win-936-chinese-simplified-gbk + 136=win-950-chinese-traditional-big5 + 161=win-1253-greek + 162=win-1254-turkish + 163=win-1258-vietnamese + 177=win-1255-hebrew + 178=win-1256-arabic + 186=win-1257-baltic + 204=win-1251-cyrillic + 222=win-874-thai + 238=win-1250-latin-2-central-european + 255=ibm-850-latin-1 +end + +constlist=CODEPAGES + 367=ascii + 437=ibm-437-us + 708=iso-8859-6 + 720=ibm-720-arabic + 737=ibm-737-greek + 775=ibm-775-baltic + 850=ibm-850-latin-1 + 852=ibm-852-latin-2-central-european + 855=ibm-855-cyrillic + 857=ibm-857-turkish + 858=ibm-858-multilingual-latin-1-with-euro + 860=ibm-860-portuguese + 861=ibm-861-icelandic + 862=ibm-862-hebrew + 863=ibm-863-canadian-french + 864=ibm-864-arabic + 865=ibm-865-nordic + 866=ibm-866-cyrillic-russian + 869=ibm-869-greek-modern + 874=win-874-thai + 932=win-932-japanese-shift-jis + 936=win-936-chinese-simplified-gbk + 949=win-949-korean-wansung + 950=win-950-chinese-traditional-big5 + 1200=utf-16 + 1250=win-1250-latin-2-central-european + 1251=win-1251-cyrillic + 1252=win-1252-latin-1 + 1253=win-1253-greek + 1254=win-1254-turkish + 1255=win-1255-hebrew + 1256=win-1256-arabic + 1257=win-1257-baltic + 1258=win-1258-vietnamese + 1361=win-1361-korean-johab + 10000=apple-roman + 10001=apple-japanese + 10002=apple-chinese-traditional + 10003=apple-korean + 10004=apple-arabic + 10005=apple-hebrew + 10006=apple-greek + 10007=apple-cyrillic + 10008=apple-chinese-simplified + 10010=apple-romanian + 10017=apple-ukrainian + 10029=apple-central-european-with-euro + 10079=apple-icelandic + 10081=apple-turkish + 10082=apple-croatian + 20127=ascii + 20866=koi8-r + 21866=koi8-u + 28591=iso-8859-1 + 28592=iso-8859-2 + 28593=iso-8859-3 + 28594=iso-8859-4 + 28595=iso-8859-5 + 28596=iso-8859-6 + 28597=iso-8859-7 + 28598=iso-8859-8 + 28599=iso-8859-9 + 28605=iso-8859-15 + 32768=apple-romanian + 32769=win-1252-latin-1 + 50220=iso-2022-jp + 50225=iso-2022-kr + 51932=euc-jp + 51936=euc-cn + 51949=euc-kr + 65000=utf-7 + 65001=utf-8 +end + +# DFF stream ----------------------------------------------------------------- + +multilist=DFF-RECORD-NAMES + 0xF000=DFFDGGCONTAINER,DFFBSTORECONTAINER,DFFDGCONTAINER,DFFSPGRCONTAINER,DFFSPCONTAINER,DFFSOLVERCONTAINER,DFFDGG,DFFBSE + 0xF008=DFFDG,DFFSPGR,DFFSP,DFFOPT,DFFTEXTBOX,DFFCLIENTTEXTBOX,DFFANCHOR,DFFCHILDANCHOR + 0xF010=DFFCLIENTANCHOR,DFFCLIENTDATA,DFFCONNECTORRULE,DFFALIGNRULE,DFFARCRULE,DFFCLIENTRULE,DFFCLASSID,DFFCALLOUTRULE + # 0xF018-0xF117 reserved for pictures + 0xF118=DFFREGROUPITEM,DFFSELECTION,DFFCOLORMRU,,,DFFDELETEDPSPL,DFFSPLITMENUCOLORS,DFFOLEOBJECT + 0xF120=DFFCOLORSCHEME,,DFFUSERDEFPROP +end + +combilist=DFF-RECORD-INST + 0x000F=uint8,hex,version,DFF-RECORD-VERSION + 0xFFF0=uint16,dec,instance +end + +constlist=DFF-RECORD-VERSION + default= + 15=container +end + +flagslist=DFFCLIENTANCHOR-FLAGS + 0x0001=pos-locked + 0x0002=size-locked +end + +combilist=DFFOPT-PROPERTY-ID + 0x3FFF=uint16,dec,id,DFFOPT-PROPERTY-NAMES + 0x4000=picture + 0x8000=complex +end + +multilist=DFFOPT-PROPERTY-NAMES + # transform + 0x0004=rotation + # protection + 0x007F=lock-flags + # text + 0x0080=text-id,text-left,text-top,text-right,text-bottom,text-wrap-mode,text-scale,text-anchor-mode + 0x0088=text-flow,text-font-rotation,text-next-shape,text-bidi + 0x00BF=text-flags + # text geometry + 0x00C0=text-unicode-string,text-rtf-string,text-curve-align,text-def-size,text-spacing,text-font-family + 0x00FF=text-geometry-flags + # picture + 0x0100=pic-crop-top,pic-crop-bottom,pic-crop-left,pic-crop-right,pic-data,pic-file-name,pic-flags,pic-transparency-color + 0x0108=pic-contrast,pic-brightness,pic-gamma,pic-id,pic-double-cr-mod,pic-fill-cr-mod,pic-line-cr-mod,pic-data-print + 0x0110=pic-name-print,pic-flags-print + 0x013F=pic-flags + # geometry + 0x0140=geo-left,geo-top,geo-right,geo-bottom,geo-shape-path,geo-vertices,geo-segment-info,geo-adjust-1 + 0x0148=geo-adjust-2,geo-adjust-3,geo-adjust-4,geo-adjust-5,geo-adjust-6,geo-adjust-7,geo-adjust-8,geo-adjust-9 + 0x0150=geo-adjust-10,geo-connect-points,geo-stretch-x,geo-stretch-y,geo-handles,geo-formulas,geo-text-recs + 0x0158=geo-connector-type + 0x017F=geo-flags + # fill style + 0x0180=fill-type,fill-color,fill-opacity,fill-back-color,fill-back-opacity,fill-cr-mod,fill-blip,fill-blip-name + 0x0188=fill-blip-flags,fill-width,fill-height,fill-angle,fill-focus,fill-to-left,fill-to-top,fill-to-right + 0x0190=fill-to-bottom,fill-rect-left,fill-rect-top,fill-rect-right,fill-rect-bottom,fill-dz-type,fill-shade-preset,fill-shade-colors + 0x0198=fill-origin-x,fill-origin-y,fill-shape-origin-x,fill-shape-origin-y,fill-shade-type + 0x01BF=fill-flags + # line style + 0x01C0=line-color,line-opacity,line-back-color,line-cr-mod,line-type,line-fill-blip,line-fill-blip-name,line-fill-blip-flags + 0x01C8=line-fill-width,line-fill-height,line-fill-dz-type,line-width,line-miter-limit,line-style,line-dash,line-dash-style + 0x01D0=line-start-arrow-head,line-end-arrow-head,line-start-arrow-width,line-start-arrow-length,line-end-arrow-width,line-end-arrow-length,line-join-style,line-end-cap-style + 0x01FF=line-flags + # shadow style + 0x0200=shadow-type,shadow-color,shadow-highlight,shadow-cr-mod,shadow-opacity,shadow-offset-x,shadow-offset-y,shadow-2nd-offset-x + 0x0208=shadow-2nd-offset-y,shadow-scale-x-to-x,shadow-scale-y-to-x,shadow-scale-x-to-y,shadow-scale-y-to-y,shadow-persp-x,shadow-persp-y,shadow-weight + 0x0210=shadow-origin-x,shadow-origin-y + 0x023F=shadow-flags + # perspective + 0x0240=persp-type,persp-offset-x,persp-offsety,persp-scale-x-to-x,persp-scale-y-to-x,persp-scale-x-to-y,persp-scale-y-to-y,persp-persp-x + 0x0248=persp-persp-y,persp-weight,persp-origin-x,persp-origin-y + 0x027F=persp-flags + # 3d object + 0x0280=3dobj-specular-amt,3dobj-diffuse-amt,3dobj-shininess,3dobj-edge-thickness,3dobj-extrude-forward,3dobj-extrude-backward,3dobj-extrude-plane,3dobj-extrusion-color + 0x0288=3dobj-cr-mod + 0x02BF=3dobj-flags + # 3d style + 0x02C0=3dstyle-y-rotation,3dstyle-x-rotation,3dstyle-rotation-axis-x,3dstyle-rotation-axis-y,3dstyle-rotation-axis-z,3dstyle-rotation,3dstyle-rotation-center-x,3dstyle-rotation-center-y + 0x02C8=3dstyle-rotation-center-z,3dstyle-render-mode,3dstyle-tolerance,3dstyle-view-point-x,3dstyle-view-point-y,3dstyle-view-point-z,3dstyle-origin-x,3dstyle-origin-y + 0x02D0=3dstyle-skew-angle,3dstyle-skew-amount,3dstyle-ambient-intensity,3dstyle-key-light-x,3dstyle-key-light-y,3dstyle-key-light-z,3dstyle-key-light-intensity,3dstyle-fill-light-x + 0x02D8=3dstyle-fill-light-y,3dstyle-fill-light-z,3dstyle-fill-light-intensity + 0x02FF=3dstyle-flags + # shape 1 + 0x0301=,shape-master,,shape-connect-style,shape-bw-mod,shape-bw-mode-pure-bw,shape-bw-mode-bw + 0x033F=shape1-flags + # callout + 0x0340=callout-type,callout-box-distance,callout-angle,callout-drop-type,callout-drop-distance,callout-length + 0x037F=callout-flags + # shape 2 + 0x0380=shape-name,shape-description,shape-hyperlink,shape-wrap-polygon-vertices,shape-wrap-left,shape-wrap-top,shape-wrap-right,shape-wrap-bottom + 0x0388=shape-regroup-id + 0x03BF=shape2-flags +end + +flagslist=DFFOPT-LOCK-FLAGS + 0x00000001=lock-against-grouping + 0x00000002=lock-adjust-handles + 0x00000004=lock-text + 0x00000008=lock-vertices + 0x00000010=lock-cropping + 0x00000020=lock-against-select + 0x00000040=lock-position + 0x00000080=lock-aspect-ratio + 0x00000100=lock-rotation +end + +flagslist=DFFOPT-TEXT-FLAGS + 0x00000001=fit-text-to-shape + 0x00000002=fit-shape-to-text + 0x00000004=rotate-text + 0x00000008=auto-text-margin + 0x00000010=select-text +end + +flagslist=DFFOPT-TEXTGEO-FLAGS + 0x00000001=strike-through + 0x00000002=small-caps + 0x00000004=shadow + 0x00000008=underline + 0x00000010=italic + 0x00000020=bold + 0x00000040=no-measure-along-path + 0x00000080=stretch-height + 0x00000100=scale-on-path + 0x00000200=shrink-to-fit + 0x00000400=stretch-to-fit + 0x00000800=tightening + 0x00001000=kerning + 0x00002000=vertical + 0x00004000=has-effect + 0x00008000=reverse-rows +end + +flagslist=DFFOPT-PICTURE-FLAGS + 0x00000001=ole-alive + 0x00000002=bi-level-display + 0x00000004=grayscale + 0x00000008=no-hit-test +end + +flagslist=DFFOPT-GEO-FLAGS + 0x00000001=fill-support + 0x00000002=fill-shade-shape-support + 0x00000004=fontwork-support + 0x00000008=line-support + 0x00000010=3d-support + 0x00000020=shadow-support +end + +flagslist=DFFOPT-FILL-FLAGS + 0x00000001=no-fill-hit-test + 0x00000002=use-large-rect + 0x00000004=register-pattern + 0x00000008=hit-test-fill + 0x00000010=has-fill +end + +flagslist=DFFOPT-LINE-FLAGS + 0x00000001=draw-dash-for-invisible + 0x00000002=register-pattern + 0x00000004=hit-test-line + 0x00000008=has-line + 0x00000010=arrowhead-support +end + +flagslist=DFFOPT-SHADOW-FLAGS + 0x00000001=excel5-style + 0x00000002=has-shadow +end + +flagslist=DFFOPT-PERSP-FLAGS + 0x00000001=has-perspective +end + +flagslist=DFFOPT-3DOBJ-FLAGS + 0x00000001=light-face + 0x00000002=extrusion-color + 0x00000004=metallic + 0x00000008=has-3d +end + +flagslist=DFFOPT-3DSTYLE-FLAGS + 0x00000001=fill-color-harsh + 0x00000002=key-color-harsh + 0x00000004=parallel + 0x00000008=rotation-center-auto + 0x00000010=constrain-rotation +end + +flagslist=DFFOPT-SHAPE1-FLAGS + 0x00000001=background + 0x00000002=delete-attached-object + 0x00000008=lock-shape-type + 0x00000010=prefer-rel-resize + 0x00000020=ole-iconified +end + +flagslist=DFFOPT-CALLOUT-FLAGS + 0x00000001=length-specified + 0x00000002=drop-auto + 0x00000004=minus-y + 0x00000008=minus-x + 0x00000010=has-text-border + 0x00000020=has-accent-bar + 0x00000040=is-callout +end + +flagslist=DFFOPT-SHAPE2-FLAGS + 0x00000001=print + 0x00000002=hidden + 0x00000004=1d-adjustment + 0x00000008=action-attached + 0x00000010=notify-double-click + 0x00000020=behind-text + 0x00000040=wrap-edited +end + +# OLE property stream -------------------------------------------------------- + +F29F85E0-4FF9-1068-AB91-08002B27B3D9=GlobalDocProp +D5CDD502-2E9C-101B-9397-08002B2CF9AE=BuiltinDocProp +D5CDD505-2E9C-101B-9397-08002B2CF9AE=CustomDocProp + +constlist=OLEPROP-BYTE-ORDER + 0xFEFF=big-endian + 0xFFFE=little-endian +end + +shortlist=OLEPROP-OSTYPE,0,dos,mac,win32,unix + +multilist=OLEPROP-BASEIDS + quote-names=1 + default= + 0=dictionary,codepage +end + +multilist=OLEPROP-GLOBALIDS + include=OLEPROP-BASEIDS + 2=title,subject,author,keywords,comments,template,last-author,rev-number + 10=edit-time,last-printed,create-time,last-saved,page-count,word-count,char-count,thumbnail,appname,security +end + +multilist=OLEPROP-BUILTINIDS + include=OLEPROP-BASEIDS + 2=category,pres-target,byte-count,line-count,para-count,slide-count,note-count,hidden-slide-count + 10=clips,scale-crop,heading-pairs,part-titles,manager,company,links-uptodate +end + +multilist=OLEPROP-TYPE-SIMPLE + 0=empty,null,int16,int32,float,double,fixed,date,string8,dispatch + 10=error,bool,variant,unknown,decimal,int8,uint8,uint16,uint32 + 20=int64,uint64,int,uint,void,hresult,ptr,savearray,c-array,userdef + 30=string8,string16 + 64=time-stamp,blob,stream,storage,stream-obj,storage-obj + 70=blob-obj,clip-fmt,guid,vers-stream + 0x0FFF=str8-blob +end + +combilist=OLEPROP-TYPE + 0x0FFF=int32,dec,base-type,OLEPROP-TYPE-SIMPLE + 0x1000=vector + 0x2000=array + 0x4000=byref +end + +# ============================================================================ + diff --git a/oox/source/dump/makefile.mk b/oox/source/dump/makefile.mk new file mode 100644 index 000000000000..c960b2099838 --- /dev/null +++ b/oox/source/dump/makefile.mk @@ -0,0 +1,60 @@ +#************************************************************************* +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.2 $ +# +# last change: $Author: rt $ $Date: 2008-01-17 08:05:58 $ +# +# The Contents of this file are made available subject to +# the terms of GNU Lesser General Public License Version 2.1. +# +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2005 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=oox +TARGET=dump +AUTOSEG=true + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/biffdumper.obj \ + $(SLO)$/dffdumper.obj \ + $(SLO)$/dumperbase.obj \ + $(SLO)$/olestoragedumper.obj \ + $(SLO)$/xlsbdumper.obj + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk diff --git a/oox/source/dump/olestoragedumper.cxx b/oox/source/dump/olestoragedumper.cxx new file mode 100644 index 000000000000..9b3ef531b3e8 --- /dev/null +++ b/oox/source/dump/olestoragedumper.cxx @@ -0,0 +1,449 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: olestoragedumper.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:58 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/dump/olestoragedumper.hxx" +#include +#include +#include +#include +#include +#include +#include "oox/helper/binaryoutputstream.hxx" +#include "oox/core/filterbase.hxx" + +#if OOX_INCLUDE_DUMPER + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::rtl::OString; +using ::rtl::OStringToOUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::util::DateTime; +using ::com::sun::star::io::XInputStream; +using ::com::sun::star::io::XOutputStream; + +namespace oox { +namespace dump { + +// ============================================================================ + +namespace { + +const sal_Int32 OLEPROP_ID_DICTIONARY = 0; +const sal_Int32 OLEPROP_ID_CODEPAGE = 1; + +const sal_Int32 OLEPROP_TYPE_INT16 = 2; +const sal_Int32 OLEPROP_TYPE_INT32 = 3; +const sal_Int32 OLEPROP_TYPE_FLOAT = 4; +const sal_Int32 OLEPROP_TYPE_DOUBLE = 5; +const sal_Int32 OLEPROP_TYPE_DATE = 7; +const sal_Int32 OLEPROP_TYPE_STRING = 8; +const sal_Int32 OLEPROP_TYPE_STATUS = 10; +const sal_Int32 OLEPROP_TYPE_BOOL = 11; +const sal_Int32 OLEPROP_TYPE_VARIANT = 12; +const sal_Int32 OLEPROP_TYPE_INT8 = 16; +const sal_Int32 OLEPROP_TYPE_UINT8 = 17; +const sal_Int32 OLEPROP_TYPE_UINT16 = 18; +const sal_Int32 OLEPROP_TYPE_UINT32 = 19; +const sal_Int32 OLEPROP_TYPE_INT64 = 20; +const sal_Int32 OLEPROP_TYPE_UINT64 = 21; +const sal_Int32 OLEPROP_TYPE_STRING8 = 30; +const sal_Int32 OLEPROP_TYPE_STRING16 = 31; +const sal_Int32 OLEPROP_TYPE_FILETIME = 64; +const sal_Int32 OLEPROP_TYPE_BLOB = 65; +const sal_Int32 OLEPROP_TYPE_STREAM = 66; +const sal_Int32 OLEPROP_TYPE_STORAGE = 67; +const sal_Int32 OLEPROP_TYPE_CLIPFMT = 71; + +const sal_uInt16 CODEPAGE_UNICODE = 1200; + +} // namespace + +// ============================================================================ + +OlePropertyStreamObject::OlePropertyStreamObject( const ObjectBase& rParent, const OUString& rOutFileName, BinaryInputStreamRef xStrm ) : + InputStreamObject( rParent, rOutFileName, xStrm ) +{ +} + +void OlePropertyStreamObject::implDump() +{ + Input& rIn = in(); + Output& rOut = out(); + + OUStringVector aGuidVec; + ::std::vector< sal_uInt32 > aStartPosVec; + + // dump header + writeEmptyItem( "HEADER" ); + { + IndentGuard aIndGuard( rOut ); + dumpHex< sal_uInt16 >( "byte-order", "OLEPROP-BYTE-ORDER" ); + dumpDec< sal_uInt16 >( "version" ); + dumpDec< sal_uInt16 >( "os-minor" ); + dumpDec< sal_uInt16 >( "os-type", "OLEPROP-OSTYPE" ); + dumpGuid( "guid" ); + sal_Int32 nSectCount = dumpDec< sal_Int32 >( "section-count" ); + + // dump table of section positions + { + TableGuard aTabGuard( rOut, 15, 60 ); + rOut.resetItemIndex(); + for( sal_Int32 nSectIdx = 0; (nSectIdx < nSectCount) && rIn.isValidPos(); ++nSectIdx ) + { + MultiItemsGuard aMultiGuard( rOut ); + writeEmptyItem( "#section" ); + aGuidVec.push_back( dumpGuid( "guid" ) ); + aStartPosVec.push_back( dumpHex< sal_uInt32 >( "start-pos" ) ); + } + } + } + rOut.emptyLine(); + + // dump sections + for( size_t nSectIdx = 0; (nSectIdx < aStartPosVec.size()) && rIn.isValidPos(); ++nSectIdx ) + dumpSection( aGuidVec[ nSectIdx ], aStartPosVec[ nSectIdx ] ); +} + +void OlePropertyStreamObject::dumpSection( const OUString& rGuid, sal_uInt32 nStartPos ) +{ + Input& rIn = in(); + Output& rOut = out(); + + // property ID names + mxPropIds = cfg().createNameList< ConstList >( "OLEPROP-IDS" ); + OUString aGuidName = cfg().getStringOption( rGuid, OUString() ); + if( aGuidName.equalsAscii( "GlobalDocProp" ) ) + mxPropIds->includeList( cfg().getNameList( "OLEPROP-GLOBALIDS" ) ); + else if( aGuidName.equalsAscii( "BuiltinDocProp" ) ) + mxPropIds->includeList( cfg().getNameList( "OLEPROP-BUILTINIDS" ) ); + else + mxPropIds->includeList( cfg().getNameList( "OLEPROP-BASEIDS" ) ); + + // property ID/position map + typedef ::std::map< sal_Int32, sal_uInt32 > PropertyPosMap; + PropertyPosMap aPropMap; + + // dump section header line + writeSectionHeader( rGuid, nStartPos ); + + // seek to section + IndentGuard aIndGuard( rOut ); + if( startElement( nStartPos ) ) + { + // dump section header + dumpDec< sal_Int32 >( "size" ); + sal_Int32 nPropCount = dumpDec< sal_Int32 >( "property-count" ); + + // dump table of property positions + { + TableGuard aTabGuard( rOut, 15, 25 ); + rOut.resetItemIndex(); + for( sal_Int32 nPropIdx = 0; (nPropIdx < nPropCount) && rIn.isValidPos(); ++nPropIdx ) + { + MultiItemsGuard aMultiGuard( rOut ); + writeEmptyItem( "#property" ); + sal_Int32 nPropId = dumpDec< sal_Int32 >( "id", mxPropIds ); + sal_uInt32 nPropPos = nStartPos + dumpHex< sal_uInt32 >( "start-pos" ); + aPropMap[ nPropId ] = nPropPos; + } + } + } + rOut.emptyLine(); + + // code page property + meTextEnc = osl_getThreadTextEncoding(); + mbIsUnicode = false; + PropertyPosMap::iterator aCodePageIt = aPropMap.find( OLEPROP_ID_CODEPAGE ); + if( aCodePageIt != aPropMap.end() ) + { + dumpCodePageProperty( aCodePageIt->second ); + aPropMap.erase( aCodePageIt ); + } + + // dictionary property + PropertyPosMap::iterator aDictIt = aPropMap.find( OLEPROP_ID_DICTIONARY ); + if( aDictIt != aPropMap.end() ) + { + dumpDictionaryProperty( aDictIt->second ); + aPropMap.erase( aDictIt ); + } + + // other properties + for( PropertyPosMap::const_iterator aIt = aPropMap.begin(), aEnd = aPropMap.end(); aIt != aEnd; ++aIt ) + dumpProperty( aIt->first, aIt->second ); + + // remove the user defined list of property ID names + cfg().eraseNameList( "OLEPROP-IDS" ); +} + +void OlePropertyStreamObject::dumpProperty( sal_Int32 nPropId, sal_uInt32 nStartPos ) +{ + writePropertyHeader( nPropId, nStartPos ); + IndentGuard aIndGuard( out() ); + if( startElement( nStartPos ) ) + dumpPropertyContents( nPropId ); + out().emptyLine(); +} + +void OlePropertyStreamObject::dumpCodePageProperty( sal_uInt32 nStartPos ) +{ + writePropertyHeader( OLEPROP_ID_CODEPAGE, nStartPos ); + IndentGuard aIndGuard( out() ); + if( startElement( nStartPos ) ) + { + sal_Int32 nType = dumpPropertyType(); + if( nType == OLEPROP_TYPE_INT16 ) + { + sal_uInt16 nCodePage = dumpDec< sal_uInt16 >( "codepage", "CODEPAGES" ); + rtl_TextEncoding nNewTextEnc = rtl_getTextEncodingFromWindowsCodePage( nCodePage ); + if( nNewTextEnc != RTL_TEXTENCODING_DONTKNOW ) + meTextEnc = nNewTextEnc; + mbIsUnicode = nCodePage == CODEPAGE_UNICODE; + } + else + dumpPropertyContents( OLEPROP_ID_CODEPAGE ); + } + out().emptyLine(); +} + +void OlePropertyStreamObject::dumpDictionaryProperty( sal_uInt32 nStartPos ) +{ + writePropertyHeader( OLEPROP_ID_DICTIONARY, nStartPos ); + IndentGuard aIndGuard( out() ); + if( startElement( nStartPos ) ) + { + sal_Int32 nCount = dumpDec< sal_Int32 >( "count" ); + for( sal_Int32 nIdx = 0; (nIdx < nCount) && in().isValidPos(); ++nIdx ) + { + MultiItemsGuard aMultiGuard( out() ); + TableGuard aTabGuard( out(), 10, 20 ); + sal_Int32 nId = dumpDec< sal_Int32 >( "id" ); + OUString aName = dumpString8( "name" ); + if( mxPropIds.get() ) + mxPropIds->setName( nId, aName ); + } + } + out().emptyLine(); +} + +void OlePropertyStreamObject::dumpPropertyContents( sal_Int32 nPropId ) +{ + sal_Int32 nType = dumpPropertyType(); + if( getFlag< sal_Int32 >( nType, 0x1000 ) ) // vector + { + sal_Int32 nBaseType = nType & 0x0FFF; + sal_Int32 nElemCount = dumpDec< sal_Int32 >( "element-count" ); + for( sal_Int32 nElemIdx = 0; (nElemIdx < nElemCount) && in().isValidPos(); ++nElemIdx ) + { + out().resetItemIndex( nElemIdx ); + writeEmptyItem( "#element" ); + IndentGuard aIndGuard( out() ); + dumpPropertyValue( nPropId, nBaseType ); + } + } + else if( !getFlag< sal_Int32 >( nType, 0x7000 ) ) + { + dumpPropertyValue( nPropId, nType ); + } +} + +void OlePropertyStreamObject::dumpPropertyValue( sal_Int32 nPropId, sal_Int32 nBaseType ) +{ + switch( nBaseType ) + { + case OLEPROP_TYPE_INT16: dumpDec< sal_Int16 >( "value" ); break; + case OLEPROP_TYPE_INT32: dumpDec< sal_Int32 >( "value" ); break; + case OLEPROP_TYPE_FLOAT: dumpDec< float >( "value" ); break; + case OLEPROP_TYPE_DOUBLE: dumpDec< double >( "value" ); break; + case OLEPROP_TYPE_DATE: dumpDec< double >( "date" ); break; + case OLEPROP_TYPE_STRING: dumpString8( "value" ); break; + case OLEPROP_TYPE_STATUS: dumpHex< sal_Int32 >( "status" ); break; + case OLEPROP_TYPE_BOOL: dumpBool< sal_Int16 >( "value" ); break; + case OLEPROP_TYPE_VARIANT: dumpPropertyContents( nPropId ); break; + case OLEPROP_TYPE_INT8: dumpDec< sal_Int8 >( "value" ); break; + case OLEPROP_TYPE_UINT8: dumpDec< sal_uInt8 >( "value" ); break; + case OLEPROP_TYPE_UINT16: dumpDec< sal_uInt16 >( "value" ); break; + case OLEPROP_TYPE_UINT32: dumpDec< sal_uInt32 >( "value" ); break; + case OLEPROP_TYPE_INT64: dumpDec< sal_Int64 >( "value" ); break; + case OLEPROP_TYPE_UINT64: dumpDec< sal_uInt64 >( "value" ); break; + case OLEPROP_TYPE_STRING8: dumpString8( "value" ); break; + case OLEPROP_TYPE_STRING16: dumpString16( "value" ); break; + case OLEPROP_TYPE_FILETIME: dumpFileTime( "file-time" ); break; + case OLEPROP_TYPE_BLOB: dumpBlob( "data" ); break; + case OLEPROP_TYPE_STREAM: dumpString8( "stream-name" ); break; + case OLEPROP_TYPE_STORAGE: dumpString8( "storage-name" ); break; + case OLEPROP_TYPE_CLIPFMT: dumpBlob( "clip-data" ); break; + } +} + +sal_Int32 OlePropertyStreamObject::dumpPropertyType() +{ + return dumpHex< sal_Int32 >( "type", "OLEPROP-TYPE" ); +} + +void OlePropertyStreamObject::dumpBlob( const sal_Char* pcName ) +{ + sal_Int32 nSize = dumpDec< sal_Int32 >( "data-size" ); + if( nSize > 0 ) + dumpBinary( pcName, nSize ); +} + +OUString OlePropertyStreamObject::dumpString8( const sal_Char* pcName ) +{ + sal_Int32 nLen = dumpDec< sal_Int32 >( "string-len" ); + return mbIsUnicode ? dumpCharArray16( pcName, nLen ) : dumpCharArray8( pcName, nLen ); +} + +OUString OlePropertyStreamObject::dumpCharArray8( const sal_Char* pcName, sal_Int32 nCharCount ) +{ + OUString aData; + size_t nLen = getLimitedValue< size_t, sal_Int32 >( nCharCount, 0, 1024 ); + if( nLen > 0 ) + { + ::std::vector< sal_Char > aBuffer( nLen + 1 ); + in().read( &aBuffer.front(), nLen ); + aBuffer[ nLen ] = 0; + aData = OStringToOUString( OString( &aBuffer.front() ), meTextEnc ); + } + writeStringItem( pcName, aData ); + return aData; +} + +OUString OlePropertyStreamObject::dumpString16( const sal_Char* pcName ) +{ + sal_Int32 nLen = dumpDec< sal_Int32 >( "string-len" ); + return dumpCharArray16( pcName, nLen ); +} + +OUString OlePropertyStreamObject::dumpCharArray16( const sal_Char* pcName, sal_Int32 nCharCount ) +{ + size_t nLen = getLimitedValue< size_t, sal_Int32 >( nCharCount, 0, 1024 ); + ::std::vector< sal_Unicode > aBuffer; + aBuffer.reserve( nLen + 1 ); + for( size_t nIdx = 0; nIdx < nLen; ++nIdx ) + aBuffer.push_back( static_cast< sal_Unicode >( in().readValue< sal_uInt16 >() ) ); + aBuffer.push_back( 0 ); + OUString aData( &aBuffer.front() ); + writeStringItem( pcName, aData ); + if( nLen & 1 ) dumpUnused( 2 ); // always padding to 32bit + return aData; +} + +DateTime OlePropertyStreamObject::dumpFileTime( const sal_Char* pcName ) +{ + DateTime aDateTime; + + ItemGuard aItem( out(), pcName ); + sal_Int64 nFileTime = dumpDec< sal_Int64 >( 0 ); + // file time is in 10^-7 seconds (100 nanoseconds), convert to 1/100 seconds + nFileTime /= 100000; + // entire days + sal_Int64 nDays = nFileTime / sal_Int64( 360000 * 24 ); + // number of entire years + sal_Int64 nYears = (nDays - (nDays / (4 * 365)) + (nDays / (100 * 365)) - (nDays / (400 * 365))) / 365; + // remaining days in the year + sal_Int64 nDaysInYear = nDays - (nYears * 365 + nYears / 4 - nYears / 100 + nYears / 400); + // the year (file dates start from 1601-01-01) + aDateTime.Year = static_cast< sal_uInt16 >( 1601 + nYears ); + // leap year? + bool bLeap = ((aDateTime.Year % 4 == 0) && (aDateTime.Year % 100 != 0)) || (aDateTime.Year % 400 == 0); + // static arrays with number of days in month + static const sal_Int64 spnDaysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + static const sal_Int64 spnDaysInMonthL[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + const sal_Int64* pnDaysInMonth = bLeap ? spnDaysInMonthL : spnDaysInMonth; + // the month + aDateTime.Month = 1; + while( nDaysInYear >= *pnDaysInMonth ) + { + nDaysInYear -= *pnDaysInMonth++; + ++aDateTime.Month; + } + // the day + aDateTime.Day = static_cast< sal_uInt16 >( nDaysInYear + 1 ); + // number of 1/100 seconds in the day + sal_Int64 nTimeInDay = nFileTime % sal_Int64( 360000 * 24 ); + // 1/100 seconds + aDateTime.HundredthSeconds = static_cast< sal_uInt16 >( nTimeInDay % 100 ); + nTimeInDay /= 100; + // seconds + aDateTime.Seconds = static_cast< sal_uInt16 >( nTimeInDay % 60 ); + nTimeInDay /= 60; + // minutes + aDateTime.Minutes = static_cast< sal_uInt16 >( nTimeInDay % 60 ); + nTimeInDay /= 60; + // hours + aDateTime.Hours = static_cast< sal_uInt16 >( nTimeInDay ); + +// aDateTime.convertToLocalTime(); + writeDateTimeItem( 0, aDateTime ); + return aDateTime; +} + +bool OlePropertyStreamObject::startElement( sal_uInt32 nStartPos ) +{ + sal_Int64 nStartPos64 = static_cast< sal_Int64>( nStartPos ); + bool bPosOk = nStartPos64 < in().getSize(); + if( bPosOk ) + in().seek( nStartPos64 ); + else + writeInfoItem( "stream-state", OOX_DUMP_ERR_STREAM ); + return bPosOk; +} + +void OlePropertyStreamObject::writeSectionHeader( const OUString& rGuid, sal_uInt32 nStartPos ) +{ + MultiItemsGuard aMultiGuard( out() ); + writeEmptyItem( "SECTION" ); + writeGuidItem( "guid", rGuid ); + writeHexItem( "pos", nStartPos ); +} + +void OlePropertyStreamObject::writePropertyHeader( sal_Int32 nPropId, sal_uInt32 nStartPos ) +{ + MultiItemsGuard aMultiGuard( out() ); + writeEmptyItem( "PROPERTY" ); + writeDecItem( "id", nPropId, mxPropIds ); + writeHexItem( "pos", nStartPos ); +} + +// ============================================================================ +// ============================================================================ + +} // namespace dump +} // namespace oox + +#endif + diff --git a/oox/source/dump/xlsbdumper.cxx b/oox/source/dump/xlsbdumper.cxx new file mode 100644 index 000000000000..3dd2e66cdb77 --- /dev/null +++ b/oox/source/dump/xlsbdumper.cxx @@ -0,0 +1,1920 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: xlsbdumper.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:59 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/dump/xlsbdumper.hxx" +#include +#include +#include "oox/core/filterbase.hxx" +#include "oox/xls/formulabase.hxx" +#include "oox/xls/ooxtokens.hxx" +#include "oox/xls/richstring.hxx" + +#if OOX_INCLUDE_DUMPER + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::sheet::XSpreadsheetDocument; +using ::oox::core::FilterBase; + +using namespace ::oox::xls; + +namespace oox { +namespace dump { +namespace xlsb { + +// ============================================================================ + +namespace { + +const sal_uInt8 OOBIN_STRINGFLAG_FONTS = 0x01; +const sal_uInt8 OOBIN_STRINGFLAG_PHONETICS = 0x02; + +const sal_uInt8 OOBIN_TOK_ARRAY_DOUBLE = 0; +const sal_uInt8 OOBIN_TOK_ARRAY_STRING = 1; +const sal_uInt8 OOBIN_TOK_ARRAY_BOOL = 2; +const sal_uInt8 OOBIN_TOK_ARRAY_ERROR = 4; + +} // namespace + +// ============================================================================ + +RecordStreamInput::RecordStreamInput() : + mxStrm( new RecordInputStream( RecordDataSequence() ) ) +{ +} + +RecordStreamInput::~RecordStreamInput() +{ +} + +bool RecordStreamInput::implIsValid() const +{ + return mxStrm.get() && Input::implIsValid(); +} + +void RecordStreamInput::createStream( const RecordDataSequence& rData ) +{ + mxStrm.reset( new RecordInputStream( rData ) ); +} + +sal_Int64 RecordStreamInput::getSize() const +{ + return mxStrm->getRecSize(); +} + +sal_Int64 RecordStreamInput::tell() const +{ + return mxStrm->getRecPos(); +} + +void RecordStreamInput::seek( sal_Int64 nPos ) +{ + mxStrm->seek( static_cast< sal_Int32 >( nPos ) ); +} + +void RecordStreamInput::skip( sal_Int32 nBytes ) +{ + mxStrm->skip( nBytes ); +} + +sal_Int32 RecordStreamInput::read( void* pBuffer, sal_Int32 nSize ) +{ + return mxStrm->read( pBuffer, nSize ); +} + +RecordStreamInput& RecordStreamInput::operator>>( sal_Int8& rnData ) { *mxStrm >> rnData; return *this; } +RecordStreamInput& RecordStreamInput::operator>>( sal_uInt8& rnData ) { *mxStrm >> rnData; return *this; } +RecordStreamInput& RecordStreamInput::operator>>( sal_Int16& rnData ) { *mxStrm >> rnData; return *this; } +RecordStreamInput& RecordStreamInput::operator>>( sal_uInt16& rnData ) { *mxStrm >> rnData; return *this; } +RecordStreamInput& RecordStreamInput::operator>>( sal_Int32& rnData ) { *mxStrm >> rnData; return *this; } +RecordStreamInput& RecordStreamInput::operator>>( sal_uInt32& rnData ) { *mxStrm >> rnData; return *this; } +RecordStreamInput& RecordStreamInput::operator>>( float& rfData ) { *mxStrm >> rfData; return *this; } +RecordStreamInput& RecordStreamInput::operator>>( double& rfData ) { *mxStrm >> rfData; return *this; } + +// ============================================================================ + +RecordObjectBase::RecordObjectBase() +{ +} + +RecordObjectBase::~RecordObjectBase() +{ +} + +void RecordObjectBase::construct( const OutputObjectBase& rParent ) +{ + mxStrmIn.reset( new RecordStreamInput ); + InputObjectBase::construct( rParent, mxStrmIn ); + constructRecObjBase(); +} + +void RecordObjectBase::construct( const RecordObjectBase& rParent ) +{ + *this = rParent; +} + +bool RecordObjectBase::implIsValid() const +{ + return isValid( mxStrmIn ) && InputObjectBase::implIsValid(); +} + +void RecordObjectBase::createRecordStream( const RecordDataSequence& rData ) +{ + mxStrmIn->createStream( rData ); +} + +OUString RecordObjectBase::getErrorName( sal_uInt8 nErrCode ) const +{ + return cfg().getName( mxErrCodes, nErrCode ); +} + +// ------------------------------------------------------------------------ + +void RecordObjectBase::readAddress( Address& orAddress ) +{ + in() >> orAddress.mnRow >> orAddress.mnCol; +} + +void RecordObjectBase::readRange( Range& orRange ) +{ + in() >> orRange.maFirst.mnRow >> orRange.maLast.mnRow >> orRange.maFirst.mnCol >> orRange.maLast.mnCol; +} + +void RecordObjectBase::readRangeList( RangeList& orRanges ) +{ + sal_Int32 nCount; + in() >> nCount; + if( nCount >= 0 ) + { + orRanges.resize( getLimitedValue< size_t, sal_Int32 >( nCount, 0, SAL_MAX_UINT16 ) ); + for( RangeList::iterator aIt = orRanges.begin(), aEnd = orRanges.end(); in().isValidPos() && (aIt != aEnd); ++aIt ) + readRange( *aIt ); + } + else + orRanges.clear(); +} + +// ---------------------------------------------------------------------------- + +void RecordObjectBase::writeBooleanItem( const sal_Char* pcName, sal_uInt8 nBool ) +{ + writeDecItem( pcName, nBool, "BOOLEAN" ); +} + +void RecordObjectBase::writeErrorCodeItem( const sal_Char* pcName, sal_uInt8 nErrCode ) +{ + writeHexItem( pcName, nErrCode, mxErrCodes ); +} + +void RecordObjectBase::writeFontPortions( const BinFontPortionList& rPortions ) +{ + if( !rPortions.empty() ) + { + writeDecItem( "font-count", static_cast< sal_uInt32 >( rPortions.size() ) ); + IndentGuard aIndGuard( out() ); + TableGuard aTabGuard( out(), 14 ); + for( BinFontPortionList::const_iterator aIt = rPortions.begin(), aEnd = rPortions.end(); aIt != aEnd; ++aIt ) + { + MultiItemsGuard aMultiGuard( out() ); + writeDecItem( "char-pos", aIt->mnPos ); + writeDecItem( "font-id", aIt->mnFontId, "FONTNAMES" ); + } + } +} + +void RecordObjectBase::writePhoneticPortions( const BinPhoneticPortionList& rPortions ) +{ + if( !rPortions.empty() ) + { + writeDecItem( "portion-count", static_cast< sal_uInt32 >( rPortions.size() ) ); + IndentGuard aIndGuard( out() ); + TableGuard aTabGuard( out(), 14, 21 ); + for( BinPhoneticPortionList::const_iterator aIt = rPortions.begin(), aEnd = rPortions.end(); aIt != aEnd; ++aIt ) + { + MultiItemsGuard aMultiGuard( out() ); + writeDecItem( "char-pos", aIt->mnPos ); + writeDecItem( "base-text-start", aIt->mnBasePos ); + writeDecItem( "base-text-length", aIt->mnBaseLen ); + } + } +} + +// ---------------------------------------------------------------------------- + +sal_uInt8 RecordObjectBase::dumpBoolean( const sal_Char* pcName ) +{ + sal_uInt8 nBool; + in() >> nBool; + writeBooleanItem( pcName ? pcName : "boolean", nBool ); + return nBool; +} + +sal_uInt8 RecordObjectBase::dumpErrorCode( const sal_Char* pcName ) +{ + sal_uInt8 nErrCode; + in() >> nErrCode; + writeErrorCodeItem( pcName ? pcName : "errorcode", nErrCode ); + return nErrCode; +} + +OUString RecordObjectBase::dumpString( const sal_Char* pcName, bool bRich, bool b32BitLen ) +{ + sal_uInt8 nFlags = bRich ? dumpHex< sal_uInt8 >( "flags", "STRING-FLAGS" ) : 0; + + OUString aString = getRecordStream().readString( b32BitLen ); + writeStringItem( pcName ? pcName : "text", aString ); + + // --- formatting --- + if( getFlag( nFlags, OOBIN_STRINGFLAG_FONTS ) ) + { + IndentGuard aIndGuard( out() ); + BinFontPortionList aPortions; + aPortions.importPortions( getRecordStream() ); + writeFontPortions( aPortions ); + } + + // --- phonetic text --- + if( getFlag( nFlags, OOBIN_STRINGFLAG_PHONETICS ) ) + { + IndentGuard aIndGuard( out() ); + dumpString( "phonetic-text" ); + BinPhoneticPortionList aPortions; + aPortions.importPortions( getRecordStream() ); + writePhoneticPortions( aPortions ); + dumpDec< sal_uInt16 >( "font-id", "FONTNAMES" ); + dumpHex< sal_uInt16 >( "flags", "PHONETIC-FLAGS" ); + } + + return aString; +} + +void RecordObjectBase::dumpColor( const sal_Char* pcName ) +{ + MultiItemsGuard aMultiGuard( out() ); + writeEmptyItem( pcName ? pcName : "color" ); + switch( dumpDec< sal_uInt8 >( "type", "COLOR-TYPE" ) ) + { + case 0: + case 1: + case 3: dumpDec< sal_uInt8 >( "index", "PALETTE-COLORS" ); break; + case 5: dumpUnused( 1 ); break; + case 7: dumpDec< sal_uInt8 >( "theme-id" ); break; + default: dumpUnknown( 1 ); + } + dumpDec< sal_Int16 >( "tint", "CONV-TINT" ); + sal_uInt8 nR, nG, nB, nA; + in() >> nR >> nG >> nB >> nA; + writeColorItem( "rgb", (((((static_cast< sal_Int32 >( nA ) << 8) | nR) << 8) | nG) << 8) | nB ); +} + +sal_Int32 RecordObjectBase::dumpColIndex( const sal_Char* pcName ) +{ + sal_Int32 nCol; + in() >> nCol; + writeColIndexItem( pcName ? pcName : "col-idx", nCol ); + return nCol; +} + +sal_Int32 RecordObjectBase::dumpRowIndex( const sal_Char* pcName ) +{ + sal_Int32 nRow; + in() >> nRow; + writeRowIndexItem( pcName ? pcName : "row-idx", nRow ); + return nRow; +} + +sal_Int32 RecordObjectBase::dumpColRange( const sal_Char* pcName ) +{ + sal_Int32 nCol1, nCol2; + in() >> nCol1 >> nCol2; + writeColRangeItem( pcName ? pcName : "col-range", nCol1, nCol2 ); + return nCol2 - nCol1 + 1; +} + +sal_Int32 RecordObjectBase::dumpRowRange( const sal_Char* pcName ) +{ + sal_Int32 nRow1, nRow2; + in() >> nRow1 >> nRow2; + writeRowRangeItem( pcName ? pcName : "row-range", nRow1, nRow2 ); + return nRow2 - nRow1 + 1; +} + +Address RecordObjectBase::dumpAddress( const sal_Char* pcName ) +{ + Address aPos; + readAddress( aPos ); + writeAddressItem( pcName ? pcName : "addr", aPos ); + return aPos; +} + +Range RecordObjectBase::dumpRange( const sal_Char* pcName ) +{ + Range aRange; + readRange( aRange ); + writeRangeItem( pcName ? pcName : "range", aRange ); + return aRange; +} + +void RecordObjectBase::dumpRangeList( const sal_Char* pcName ) +{ + RangeList aRanges; + readRangeList( aRanges ); + writeRangeListItem( pcName ? pcName : "range-list", aRanges ); +} + +// ---------------------------------------------------------------------------- + +void RecordObjectBase::constructRecObjBase() +{ + if( RecordObjectBase::implIsValid() ) + mxErrCodes = cfg().getNameList( "ERRORCODES" ); +} + +// ============================================================================ + +FormulaObject::FormulaObject( const RecordObjectBase& rParent ) : + mpcName( 0 ), + mnSize( 0 ) +{ + RecordObjectBase::construct( rParent ); + constructFmlaObj(); +} + +FormulaObject::~FormulaObject() +{ +} + +void FormulaObject::dumpCellFormula( const sal_Char* pcName ) +{ + dumpFormula( pcName, false ); +} + +void FormulaObject::dumpNameFormula( const sal_Char* pcName ) +{ + dumpFormula( pcName, true ); +} + +void FormulaObject::implDump() +{ + { + MultiItemsGuard aMultiGuard( out() ); + writeEmptyItem( mpcName ); + writeDecItem( "formula-size", mnSize ); + } + if( mnSize < 0 ) return; + + Input& rIn = in(); + sal_Int64 nStartPos = rIn.tell(); + sal_Int64 nEndPos = ::std::min< sal_Int64 >( nStartPos + mnSize, rIn.getSize() ); + + bool bValid = mxTokens.get(); + mxStack.reset( new FormulaStack ); + maAddData.clear(); + IndentGuard aIndGuard( out() ); + { + TableGuard aTabGuard( out(), 8, 18 ); + while( bValid && (rIn.tell() < nEndPos) ) + { + MultiItemsGuard aMultiGuard( out() ); + writeHexItem( 0, static_cast< sal_uInt16 >( rIn.tell() - nStartPos ) ); + sal_uInt8 nTokenId = dumpHex< sal_uInt8 >( 0, mxTokens ); + bValid = mxTokens->hasName( nTokenId ); + if( bValid ) + { + sal_uInt8 nTokClass = nTokenId & BIFF_TOKCLASS_MASK; + sal_uInt8 nBaseId = nTokenId & BIFF_TOKID_MASK; + if( nTokClass == BIFF_TOKCLASS_NONE ) + { + switch( nBaseId ) + { + case BIFF_TOKID_EXP: dumpExpToken( "EXP" ); break; + case BIFF_TOKID_ADD: dumpBinaryOpToken( "+" ); break; + case BIFF_TOKID_SUB: dumpBinaryOpToken( "-" ); break; + case BIFF_TOKID_MUL: dumpBinaryOpToken( "*" ); break; + case BIFF_TOKID_DIV: dumpBinaryOpToken( "/" ); break; + case BIFF_TOKID_POWER: dumpBinaryOpToken( "^" ); break; + case BIFF_TOKID_CONCAT: dumpBinaryOpToken( "&" ); break; + case BIFF_TOKID_LT: dumpBinaryOpToken( "<" ); break; + case BIFF_TOKID_LE: dumpBinaryOpToken( "<=" ); break; + case BIFF_TOKID_EQ: dumpBinaryOpToken( "=" ); break; + case BIFF_TOKID_GE: dumpBinaryOpToken( ">=" ); break; + case BIFF_TOKID_GT: dumpBinaryOpToken( "<" ); break; + case BIFF_TOKID_NE: dumpBinaryOpToken( "<>" ); break; + case BIFF_TOKID_ISECT: dumpBinaryOpToken( " " ); break; + case BIFF_TOKID_LIST: dumpBinaryOpToken( "," ); break; + case BIFF_TOKID_RANGE: dumpBinaryOpToken( ":" ); break; + case BIFF_TOKID_UPLUS: dumpUnaryOpToken( "+", "" ); break; + case BIFF_TOKID_UMINUS: dumpUnaryOpToken( "-", "" ); break; + case BIFF_TOKID_PERCENT: dumpUnaryOpToken( "", "%" ); break; + case BIFF_TOKID_PAREN: dumpUnaryOpToken( "(", ")" ); break; + case BIFF_TOKID_MISSARG: dumpMissArgToken(); break; + case BIFF_TOKID_STR: dumpStringToken(); break; + case BIFF_TOKID_NLR: bValid = dumpTableToken(); break; + case BIFF_TOKID_ATTR: bValid = dumpAttrToken(); break; + case BIFF_TOKID_ERR: dumpErrorToken(); break; + case BIFF_TOKID_BOOL: dumpBoolToken(); break; + case BIFF_TOKID_INT: dumpIntToken(); break; + case BIFF_TOKID_NUM: dumpDoubleToken(); break; + default: bValid = false; + } + } + else + { + OUString aTokClass = cfg().getName( mxClasses, nTokClass ); + switch( nBaseId ) + { + case BIFF_TOKID_ARRAY: dumpArrayToken( aTokClass ); break; + case BIFF_TOKID_FUNC: dumpFuncToken( aTokClass ); break; + case BIFF_TOKID_FUNCVAR: dumpFuncVarToken( aTokClass ); break; + case BIFF_TOKID_NAME: dumpNameToken( aTokClass ); break; + case BIFF_TOKID_REF: dumpRefToken( aTokClass, false ); break; + case BIFF_TOKID_AREA: dumpAreaToken( aTokClass, false ); break; + case BIFF_TOKID_MEMAREA: dumpMemAreaToken( aTokClass, true ); break; + case BIFF_TOKID_MEMERR: dumpMemAreaToken( aTokClass, false ); break; + case BIFF_TOKID_MEMNOMEM: dumpMemAreaToken( aTokClass, false ); break; + case BIFF_TOKID_MEMFUNC: dumpMemFuncToken( aTokClass ); break; + case BIFF_TOKID_REFERR: dumpRefErrToken( aTokClass, false ); break; + case BIFF_TOKID_AREAERR: dumpRefErrToken( aTokClass, true ); break; + case BIFF_TOKID_REFN: dumpRefToken( aTokClass, true ); break; + case BIFF_TOKID_AREAN: dumpAreaToken( aTokClass, true ); break; + case BIFF_TOKID_MEMAREAN: dumpMemFuncToken( aTokClass ); break; + case BIFF_TOKID_MEMNOMEMN: dumpMemFuncToken( aTokClass ); break; + case BIFF_TOKID_NAMEX: dumpNameXToken( aTokClass ); break; + case BIFF_TOKID_REF3D: dumpRef3dToken( aTokClass, mbNameMode ); break; + case BIFF_TOKID_AREA3D: dumpArea3dToken( aTokClass, mbNameMode ); break; + case BIFF_TOKID_REFERR3D: dumpRefErr3dToken( aTokClass, false ); break; + case BIFF_TOKID_AREAERR3D: dumpRefErr3dToken( aTokClass, true ); break; + default: bValid = false; + } + } + } + } + } + + if( nEndPos == rIn.tell() ) + { + dumpAddTokenData(); + if( mnSize > 0 ) + { + writeInfoItem( "formula", mxStack->getFormulaString() ); + writeInfoItem( "classes", mxStack->getClassesString() ); + } + } + else + { + dumpBinary( OOX_DUMP_ERRASCII( "formula-error" ), static_cast< sal_Int32 >( nEndPos - rIn.tell() ), false ); + sal_Int32 nAddDataSize = dumpDec< sal_Int32 >( "add-data-size" ); + dumpBinary( "add-data", nAddDataSize, false ); + } + + mpcName = 0; + mnSize = 0; +} + +void FormulaObject::dumpFormula( const sal_Char* pcName, bool bNameMode ) +{ + mpcName = pcName ? pcName : "formula"; + in() >> mnSize; + mbNameMode = bNameMode; + dump(); +} + +// private -------------------------------------------------------------------- + +void FormulaObject::constructFmlaObj() +{ + if( RecordObjectBase::implIsValid() ) + { + Reference< XSpreadsheetDocument > xDocument( getFilter().getModel(), UNO_QUERY ); + mxFuncProv.reset( new FunctionProvider( xDocument, true ) ); + + Config& rCfg = cfg(); + mxClasses = rCfg.getNameList( "TOKENCLASSES" ); + mxRelFlags = rCfg.getNameList( "REFRELFLAGS" ); + mxAttrTypes = rCfg.getNameList( "ATTRTYPES" ); + mxSpTypes = rCfg.getNameList( "ATTRSPACETYPES" ); + + // create classified token names + mxTokens = rCfg.createNameList< ConstList >( "TOKENS" ); + mxTokens->includeList( rCfg.getNameList( "BASETOKENS" ) ); + + NameListRef xClassTokens = rCfg.getNameList( "CLASSTOKENS" ); + if( mxClasses.get() && xClassTokens.get() ) + for( NameListBase::const_iterator aCIt = mxClasses->begin(), aCEnd = mxClasses->end(); aCIt != aCEnd; ++aCIt ) + for( NameListBase::const_iterator aTIt = xClassTokens->begin(), aTEnd = xClassTokens->end(); aTIt != aTEnd; ++aTIt ) + mxTokens->setName( aCIt->first | aTIt->first, aTIt->second + aCIt->second ); + + mnColCount = 16384; + mnRowCount = 1024 * 1024; + } +} + +// ---------------------------------------------------------------------------- + +namespace { + +OUString lclCreateName( const OUString& rRef, sal_Int32 nNameId ) +{ + OUStringBuffer aName( rRef ); + StringHelper::appendIndexedText( aName, CREATE_OUSTRING( "NAME" ), nNameId ); + return aName.makeStringAndClear(); +} + +} // namespace + +// ---------------------------------------------------------------------------- + +TokenAddress FormulaObject::createTokenAddress( sal_Int32 nCol, sal_Int32 nRow, bool bRelC, bool bRelR, bool bNameMode ) const +{ + TokenAddress aPos; + aPos.mnCol = nCol; + if( bRelC && bNameMode && (nCol >= mnColCount / 2) ) aPos.mnCol -= mnColCount; + aPos.mbRelCol = bRelC; + aPos.mnRow = nRow; + if( bRelR && bNameMode && (nRow >= mnRowCount / 2) ) aPos.mnRow -= mnRowCount; + aPos.mbRelRow = bRelR; + return aPos; +} + +OUString FormulaObject::createRef( const OUString& rData ) const +{ + return maRefPrefix + rData; +} + +OUString FormulaObject::createName( sal_Int32 nNameId ) const +{ + return lclCreateName( maRefPrefix, nNameId ); +} + +OUString FormulaObject::createPlaceHolder( size_t nIdx ) const +{ + OUStringBuffer aStr; + StringHelper::appendDec( aStr, static_cast< sal_uInt32 >( nIdx ) ); + StringHelper::enclose( aStr, OOX_DUMP_PLACEHOLDER ); + return aStr.makeStringAndClear(); +} + +OUString FormulaObject::createPlaceHolder() const +{ + return createPlaceHolder( maAddData.size() ); +} + +OUString FormulaObject::writeFuncIdItem( sal_uInt16 nFuncId, const FunctionInfo** oppFuncInfo ) +{ + ItemGuard aItemGuard( out(), "func-id" ); + writeHexItem( 0, nFuncId, "FUNCID" ); + OUStringBuffer aBuffer; + const FunctionInfo* pFuncInfo = mxFuncProv->getFuncInfoFromOobFuncId( nFuncId ); + if( pFuncInfo ) + aBuffer.append( pFuncInfo->maOoxFuncName ); + else + { + bool bCmd = getFlag( nFuncId, BIFF_TOK_FUNCVAR_CMD ); + aBuffer.appendAscii( bCmd ? "CMD" : "FUNC" ); + StringHelper::appendIndex( aBuffer, nFuncId & BIFF_TOK_FUNCVAR_FUNCIDMASK ); + } + OUString aFuncName = aBuffer.makeStringAndClear(); + aItemGuard.cont(); + out().writeString( aFuncName ); + if( oppFuncInfo ) *oppFuncInfo = pFuncInfo; + return aFuncName; +} + +sal_Int32 FormulaObject::dumpTokenCol( const sal_Char* pcName, bool& rbRelC, bool& rbRelR ) +{ + sal_uInt16 nCol = dumpHex< sal_uInt16 >( pcName, mxRelFlags ); + rbRelC = getFlag( nCol, OOBIN_TOK_REF_COLREL ); + rbRelR = getFlag( nCol, OOBIN_TOK_REF_ROWREL ); + nCol &= OOBIN_TOK_REF_COLMASK; + return nCol; +} + +sal_Int32 FormulaObject::dumpTokenRow( const sal_Char* pcName ) +{ + return dumpDec< sal_Int32 >( pcName ); +} + +TokenAddress FormulaObject::dumpTokenAddress( bool bNameMode ) +{ + bool bRelC = false; + bool bRelR = false; + sal_Int32 nRow = dumpTokenRow( "row" ); + sal_Int32 nCol = dumpTokenCol( "col", bRelC, bRelR ); + return createTokenAddress( nCol, nRow, bRelC, bRelR, bNameMode ); +} + +TokenRange FormulaObject::dumpTokenRange( bool bNameMode ) +{ + bool bRelC1 = false; + bool bRelR1 = false; + bool bRelC2 = false; + bool bRelR2 = false; + sal_Int32 nRow1 = dumpTokenRow( "row1" ); + sal_Int32 nRow2 = dumpTokenRow( "row2" ); + sal_Int32 nCol1 = dumpTokenCol( "col1", bRelC1, bRelR1 ); + sal_Int32 nCol2 = dumpTokenCol( "col2", bRelC2, bRelR2 ); + TokenRange aRange; + aRange.maFirst = createTokenAddress( nCol1, nRow1, bRelC1, bRelR1, bNameMode ); + aRange.maLast = createTokenAddress( nCol2, nRow2, bRelC2, bRelR2, bNameMode ); + return aRange; +} + +sal_Int16 FormulaObject::readTokenRefId() +{ + return dumpDec< sal_Int16 >( "ref-id" ); +} + +OUString FormulaObject::dumpTokenRefId() +{ + OUStringBuffer aRef( CREATE_OUSTRING( "REF" ) ); + StringHelper::appendIndex( aRef, readTokenRefId() ); + aRef.append( OOX_DUMP_TABSEP ); + return aRef.makeStringAndClear(); +} + +void FormulaObject::dumpIntToken() +{ + dumpDec< sal_uInt16 >( "value" ); + mxStack->pushOperand( out().getLastItemValue() ); +} + +void FormulaObject::dumpDoubleToken() +{ + dumpDec< double >( "value" ); + mxStack->pushOperand( out().getLastItemValue() ); +} + +void FormulaObject::dumpStringToken() +{ + OUStringBuffer aBuffer( dumpString( "value", false, false ) ); + StringHelper::enclose( aBuffer, OOX_DUMP_FMLASTRQUOTE ); + mxStack->pushOperand( aBuffer.makeStringAndClear() ); +} + +void FormulaObject::dumpBoolToken() +{ + dumpBoolean( "value" ); + mxStack->pushOperand( out().getLastItemValue() ); +} + +void FormulaObject::dumpErrorToken() +{ + dumpErrorCode( "value" ); + mxStack->pushOperand( out().getLastItemValue() ); +} + +void FormulaObject::dumpMissArgToken() +{ + mxStack->pushOperand( OUString( OOX_DUMP_EMPTYVALUE ) ); +} + +void FormulaObject::dumpArrayToken( const OUString& rTokClass ) +{ + dumpUnused( 14 ); + mxStack->pushOperand( createPlaceHolder(), rTokClass ); + maAddData.push_back( ADDDATA_ARRAY ); +} + +void FormulaObject::dumpNameToken( const OUString& rTokClass ) +{ + sal_Int32 nNameId = dumpDec< sal_Int32 >( "name-id" ); + mxStack->pushOperand( createName( nNameId ), rTokClass ); +} + +void FormulaObject::dumpNameXToken( const OUString& rTokClass ) +{ + OUString aRef = dumpTokenRefId(); + sal_Int32 nNameId = dumpDec< sal_Int32 >( "name-id" ); + mxStack->pushOperand( lclCreateName( aRef, nNameId ), rTokClass ); +} + +void FormulaObject::dumpRefToken( const OUString& rTokClass, bool bNameMode ) +{ + TokenAddress aPos = dumpTokenAddress( bNameMode ); + writeTokenAddressItem( "addr", aPos, bNameMode ); + mxStack->pushOperand( createRef( out().getLastItemValue() ), rTokClass ); +} + +void FormulaObject::dumpAreaToken( const OUString& rTokClass, bool bNameMode ) +{ + TokenRange aRange = dumpTokenRange( bNameMode ); + writeTokenRangeItem( "range", aRange, bNameMode ); + mxStack->pushOperand( createRef( out().getLastItemValue() ), rTokClass ); +} + +void FormulaObject::dumpRefErrToken( const OUString& rTokClass, bool bArea ) +{ + dumpUnused( 4 * (bArea ? 2 : 1) ); + mxStack->pushOperand( createRef( getErrorName( BIFF_ERR_REF ) ), rTokClass ); +} + +void FormulaObject::dumpRef3dToken( const OUString& rTokClass, bool bNameMode ) +{ + OUString aRef = dumpTokenRefId(); + TokenAddress aPos = dumpTokenAddress( bNameMode ); + writeTokenAddress3dItem( "addr", aRef, aPos, bNameMode ); + mxStack->pushOperand( out().getLastItemValue(), rTokClass ); +} + +void FormulaObject::dumpArea3dToken( const OUString& rTokClass, bool bNameMode ) +{ + OUString aRef = dumpTokenRefId(); + TokenRange aRange = dumpTokenRange( bNameMode ); + writeTokenRange3dItem( "range", aRef, aRange, bNameMode ); + mxStack->pushOperand( out().getLastItemValue(), rTokClass ); +} + +void FormulaObject::dumpRefErr3dToken( const OUString& rTokClass, bool bArea ) +{ + OUString aRef = dumpTokenRefId(); + dumpUnused( 4 * (bArea ? 2 : 1) ); + mxStack->pushOperand( aRef + getErrorName( BIFF_ERR_REF ), rTokClass ); +} + +void FormulaObject::dumpMemFuncToken( const OUString& /*rTokClass*/ ) +{ + dumpDec< sal_uInt16 >( "size" ); +} + +void FormulaObject::dumpMemAreaToken( const OUString& rTokClass, bool bAddData ) +{ + dumpUnused( 4 ); + dumpMemFuncToken( rTokClass ); + if( bAddData ) + maAddData.push_back( ADDDATA_MEMAREA ); +} + +void FormulaObject::dumpExpToken( const StringWrapper& rName ) +{ + Address aPos; + dumpRowIndex( "base-row" ); + OUStringBuffer aOp( rName.getString() ); + StringHelper::appendIndex( aOp, createPlaceHolder() + out().getLastItemValue() ); + mxStack->pushOperand( aOp.makeStringAndClear() ); + maAddData.push_back( ADDDATA_EXP ); +} + +void FormulaObject::dumpUnaryOpToken( const StringWrapper& rLOp, const StringWrapper& rROp ) +{ + mxStack->pushUnaryOp( rLOp, rROp ); +} + +void FormulaObject::dumpBinaryOpToken( const StringWrapper& rOp ) +{ + mxStack->pushBinaryOp( rOp ); +} + +void FormulaObject::dumpFuncToken( const OUString& rTokClass ) +{ + sal_uInt16 nFuncId; + in() >> nFuncId; + const FunctionInfo* pFuncInfo = 0; + OUString aFuncName = writeFuncIdItem( nFuncId, &pFuncInfo ); + if( pFuncInfo && (pFuncInfo->mnMinParamCount == pFuncInfo->mnMaxParamCount) ) + mxStack->pushFuncOp( aFuncName, rTokClass, pFuncInfo->mnMinParamCount ); + else + mxStack->setError(); +} + +void FormulaObject::dumpFuncVarToken( const OUString& rTokClass ) +{ + sal_uInt8 nParamCount; + sal_uInt16 nFuncId; + in() >> nParamCount >> nFuncId; + bool bCmd = getFlag( nFuncId, BIFF_TOK_FUNCVAR_CMD ); + if( bCmd ) + writeHexItem( "param-count", nParamCount, "PARAMCOUNT-CMD" ); + else + writeDecItem( "param-count", nParamCount ); + OUString aFuncName = writeFuncIdItem( nFuncId ); + if( bCmd && getFlag( nParamCount, BIFF_TOK_FUNCVAR_CMDPROMPT ) ) + { + aFuncName += OUString( OOX_DUMP_CMDPROMPT ); + nParamCount &= BIFF_TOK_FUNCVAR_COUNTMASK; + } + mxStack->pushFuncOp( aFuncName, rTokClass, nParamCount ); +} + +bool FormulaObject::dumpTableToken() +{ + Output& rOut = out(); + dumpUnused( 3 ); + sal_uInt16 nFlags = dumpHex< sal_uInt16 >( "flags", "TABLEFLAGS" ); + sal_uInt16 nTabId = dumpDec< sal_uInt16 >( "table-id" ); + dumpUnused( 2 ); + { + sal_uInt16 nCol1, nCol2; + in() >> nCol1 >> nCol2; + ItemGuard aItem( rOut, "cols" ); + rOut.writeDec( nCol1 ); + if( nCol1 != nCol2 ) + { + rOut.writeChar( OOX_DUMP_RANGESEP ); + rOut.writeDec( nCol2 ); + } + } + OUStringBuffer aColRange; + StringHelper::appendIndex( aColRange, rOut.getLastItemValue() ); + OUStringBuffer aParams; + size_t nParams = 0; + if( getFlag( nFlags, OOBIN_TOK_TABLE_ALL ) && ++nParams ) + StringHelper::appendToken( aParams, CREATE_OUSTRING( "[#All]" ) ); + if( getFlag( nFlags, OOBIN_TOK_TABLE_HEADERS ) && ++nParams ) + StringHelper::appendToken( aParams, CREATE_OUSTRING( "[#Headers]" ) ); + if( getFlag( nFlags, OOBIN_TOK_TABLE_DATA ) && ++nParams ) + StringHelper::appendToken( aParams, CREATE_OUSTRING( "[#Data]" ) ); + if( getFlag( nFlags, OOBIN_TOK_TABLE_TOTALS ) && ++nParams ) + StringHelper::appendToken( aParams, CREATE_OUSTRING( "[#Totals]" ) ); + if( getFlag( nFlags, OOBIN_TOK_TABLE_THISROW ) && ++nParams ) + StringHelper::appendToken( aParams, CREATE_OUSTRING( "[#This Row]" ) ); + if( (getFlag( nFlags, OOBIN_TOK_TABLE_COLUMN ) || getFlag( nFlags, OOBIN_TOK_TABLE_COLRANGE )) && ++nParams ) + StringHelper::appendToken( aParams, aColRange.makeStringAndClear() ); + OUStringBuffer aOp; + StringHelper::appendIndexedText( aOp, CREATE_OUSTRING( "TABLE" ), nTabId ); + if( nParams > 1 ) + StringHelper::appendIndex( aOp, aParams.makeStringAndClear() ); + else if( nParams == 1 ) + aOp.append( aParams.makeStringAndClear() ); + mxStack->pushOperand( aOp.makeStringAndClear() ); + return true; +} + +bool FormulaObject::dumpAttrToken() +{ + bool bValid = true; + sal_uInt8 nType = dumpHex< sal_uInt8 >( "type", mxAttrTypes ); + switch( nType ) + { + case OOBIN_TOK_ATTR_VOLATILE: + dumpUnused( 2 ); + break; + case OOBIN_TOK_ATTR_IF: + dumpDec< sal_uInt16 >( "skip" ); + break; + case OOBIN_TOK_ATTR_CHOOSE: + { + sal_uInt16 nCount = dumpDec< sal_uInt16 >( "choices" ); + out().resetItemIndex(); + for( sal_uInt16 nIdx = 0; nIdx < nCount; ++nIdx ) + dumpDec< sal_uInt16 >( "#skip" ); + dumpDec< sal_uInt16 >( "skip-err" ); + } + break; + case OOBIN_TOK_ATTR_SKIP: + dumpDec< sal_uInt16 >( "skip" ); + break; + case OOBIN_TOK_ATTR_SUM: + dumpUnused( 2 ); + mxStack->pushFuncOp( CREATE_OUSTRING( "SUM" ), OUString( OOX_DUMP_BASECLASS ), 1 ); + break; + case OOBIN_TOK_ATTR_ASSIGN: + dumpUnused( 2 ); + break; + case OOBIN_TOK_ATTR_SPACE: + case OOBIN_TOK_ATTR_SPACE | BIFF_TOK_ATTR_VOLATILE: + dumpDec< sal_uInt8 >( "char-type", mxSpTypes ); + dumpDec< sal_uInt8 >( "char-count" ); + break; + case OOBIN_TOK_ATTR_IFERROR: + dumpDec< sal_uInt16 >( "skip" ); + break; + default: + bValid = false; + } + return bValid; +} + +void FormulaObject::dumpAddTokenData() +{ + Output& rOut = out(); + rOut.resetItemIndex(); + Input& rIn = in(); + sal_Int32 nAddDataSize = (in().getSize() - in().tell() >= 4) ? dumpDec< sal_Int32 >( "add-data-size" ) : 0; + sal_Int64 nEndPos = ::std::min< sal_Int64 >( rIn.tell() + nAddDataSize, rIn.getSize() ); + for( AddDataTypeVec::const_iterator aIt = maAddData.begin(), aEnd = maAddData.end(); (aIt != aEnd) && rIn.isValidPos() && (rIn.tell() < nEndPos); ++aIt ) + { + AddDataType eType = *aIt; + + { + ItemGuard aItem( rOut, "#add-data" ); + switch( eType ) + { + case ADDDATA_EXP: rOut.writeAscii( "tExp" ); break; + case ADDDATA_ARRAY: rOut.writeAscii( "tArray" ); break; + case ADDDATA_MEMAREA: rOut.writeAscii( "tMemArea" ); break; + } + } + + size_t nIdx = aIt - maAddData.begin(); + IndentGuard aIndGuard( rOut ); + switch( eType ) + { + case ADDDATA_EXP: dumpAddDataExp( nIdx ); break; + case ADDDATA_ARRAY: dumpAddDataArray( nIdx ); break; + case ADDDATA_MEMAREA: dumpAddDataMemArea( nIdx ); break; + default:; + } + } +} + +void FormulaObject::dumpAddDataExp( size_t nIdx ) +{ + dumpColIndex( "base-col" ); + mxStack->replaceOnTop( createPlaceHolder( nIdx ), out().getLastItemValue() ); +} + +void FormulaObject::dumpAddDataArray( size_t nIdx ) +{ + sal_Int32 nCols, nRows; + dumpaddDataArrayHeader( nCols, nRows ); + + OUStringBuffer aOp; + TableGuard aTabGuard( out(), 17 ); + for( sal_Int32 nRow = 0; nRow < nRows; ++nRow ) + { + OUStringBuffer aArrayLine; + for( sal_Int32 nCol = 0; nCol < nCols; ++nCol ) + StringHelper::appendToken( aArrayLine, dumpaddDataArrayValue(), OOX_DUMP_LISTSEP ); + StringHelper::appendToken( aOp, aArrayLine.makeStringAndClear(), OOX_DUMP_ARRAYSEP ); + } + StringHelper::enclose( aOp, '{', '}' ); + mxStack->replaceOnTop( createPlaceHolder( nIdx ), aOp.makeStringAndClear() ); +} + +void FormulaObject::dumpAddDataMemArea( size_t /*nIdx*/ ) +{ + dumpRangeList(); +} + +void FormulaObject::dumpaddDataArrayHeader( sal_Int32& rnCols, sal_Int32& rnRows ) +{ + Output& rOut = out(); + MultiItemsGuard aMultiGuard( rOut ); + rnRows = dumpDec< sal_Int32 >( "height" ); + rnCols = dumpDec< sal_Int32 >( "width" ); + ItemGuard aItem( rOut, "size" ); + rOut.writeDec( rnCols ); + rOut.writeChar( 'x' ); + rOut.writeDec( rnRows ); + aItem.cont(); + rOut.writeDec( rnCols * rnRows ); +} + +OUString FormulaObject::dumpaddDataArrayValue() +{ + Output& rOut = out(); + MultiItemsGuard aMultiGuard( rOut ); + OUStringBuffer aValue; + switch( dumpDec< sal_uInt8 >( "type", "ARRAYVALUE-TYPE" ) ) + { + case OOBIN_TOK_ARRAY_DOUBLE: + dumpDec< double >( "value" ); + aValue.append( rOut.getLastItemValue() ); + break; + case OOBIN_TOK_ARRAY_STRING: + aValue.append( dumpString( "value", false, false ) ); + StringHelper::enclose( aValue, OOX_DUMP_STRQUOTE ); + break; + case OOBIN_TOK_ARRAY_BOOL: + dumpBoolean( "value" ); + aValue.append( rOut.getLastItemValue() ); + break; + case OOBIN_TOK_ARRAY_ERROR: + dumpErrorCode( "value" ); + aValue.append( rOut.getLastItemValue() ); + dumpUnused( 3 ); + break; + } + return aValue.makeStringAndClear(); +} + +// ============================================================================ + +RecordObject::RecordObject( OutputObjectBase& rParent ) +{ + RecordObjectBase::construct( rParent ); + if( RecordObjectBase::implIsValid() ) + { + mxFmlaObj.reset( new FormulaObject( *this ) ); + mxSimpleRecs = cfg().getNameList( "SIMPLE-RECORDS" ); + } +} + +void RecordObject::dumpRecord( const RecordDataSequence& rData, sal_Int32 nRecId ) +{ + createRecordStream( rData ); + mnRecId = nRecId; + dump(); +} + +bool RecordObject::implIsValid() const +{ + return isValid( mxFmlaObj ) && RecordObjectBase::implIsValid(); +} + +void RecordObject::implDump() +{ + if( cfg().hasName( mxSimpleRecs, mnRecId ) ) + dumpSimpleRecord( cfg().getName( mxSimpleRecs, mnRecId ) ); + else + dumpRecordBody(); + + // remaining undumped data + RecordInputStream& rStrm = getRecordStream(); + if( rStrm.getRecPos() == 0 ) + dumpRawBinary( rStrm.getRecSize(), false ); + else + dumpRemaining( rStrm.getRecLeft() ); + if( !rStrm.isValid() ) + writeInfoItem( "stream-state", OOX_DUMP_ERR_STREAM ); +} + +void RecordObject::dumpCellHeader() +{ + dumpColIndex(); + dumpDec< sal_uInt16 >( "xf-id" ); + dumpHex< sal_uInt16 >( "flags", "CELL-FLAGS" ); +} + +void RecordObject::dumpSimpleRecord( const OUString& rRecData ) +{ + ItemFormat aItemFmt; + aItemFmt.parse( rRecData ); + dumpItem( aItemFmt ); +} + +void RecordObject::dumpRecordBody() +{ + switch( mnRecId ) + { + case OOBIN_ID_ARRAY: + dumpRange( "array-range" ); + dumpHex< sal_uInt8 >( "flags", "ARRAY-FLAGS" ); + mxFmlaObj->dumpCellFormula(); + break; + + case OOBIN_ID_BORDER: + dumpHex< sal_uInt8 >( "flags", "BORDER-FLAGS" ); + dumpDec< sal_uInt16 >( "top-style", "BORDERSTYLES" ); + dumpColor( "top-color" ); + dumpDec< sal_uInt16 >( "bottom-style", "BORDERSTYLES" ); + dumpColor( "bottom-color" ); + dumpDec< sal_uInt16 >( "left-style", "BORDERSTYLES" ); + dumpColor( "left-color" ); + dumpDec< sal_uInt16 >( "right-style", "BORDERSTYLES" ); + dumpColor( "right-color" ); + dumpDec< sal_uInt16 >( "diag-style", "BORDERSTYLES" ); + dumpColor( "diag-color" ); + break; + + case OOBIN_ID_BRK: + dumpDec< sal_Int32 >( "id" ); + dumpDec< sal_Int32 >( "min" ); + dumpDec< sal_Int32 >( "max" ); + dumpHex< sal_uInt32 >( "flags", "BRK-FLAGS" ); + break; + + case OOBIN_ID_CALCPR: + dumpDec< sal_Int32 >( "calc-id" ); + dumpDec< sal_Int32 >( "calc-mode", "CALCPR-CALCMODE" ); + dumpDec< sal_Int32 >( "iteration-count" ); + dumpDec< double >( "iteration-delta" ); + dumpDec< sal_Int32 >( "processor-count" ); + dumpHex< sal_uInt16 >( "flags", "CALCPR-FLAGS" ); + break; + + case OOBIN_ID_CELL_BLANK: + dumpCellHeader(); + break; + + case OOBIN_ID_CELL_BOOL: + dumpCellHeader(); + dumpBoolean(); + break; + + case OOBIN_ID_CELL_DOUBLE: + dumpCellHeader(); + dumpDec< double >( "value" ); + break; + + case OOBIN_ID_CELL_ERROR: + dumpCellHeader(); + dumpErrorCode(); + break; + + case OOBIN_ID_CELL_RK: + dumpCellHeader(); + dumpRk( "value" ); + break; + + case OOBIN_ID_CELL_RSTRING: + dumpCellHeader(); + dumpString( "value", true ); + break; + + case OOBIN_ID_CELL_SI: + dumpCellHeader(); + dumpDec< sal_Int32 >( "string-id" ); + break; + + case OOBIN_ID_CELL_STRING: + dumpCellHeader(); + dumpString( "value" ); + break; + + case OOBIN_ID_CELLSTYLE: + dumpDec< sal_Int32 >( "xf-id" ); + dumpHex< sal_uInt16 >( "flags", "CELLSTYLE-FLAGS" ); + dumpDec< sal_uInt8 >( "builtin-id", "CELLSTYLE-BUILTIN" ); + dumpDec< sal_uInt8 >( "outline-level" ); + dumpString( "name" ); + break; + + case OOBIN_ID_CFCOLOR: + dumpColor(); + break; + + case OOBIN_ID_CFRULE: + { + // type/subtype/operator is a mess... + dumpDec< sal_Int32 >( "type", "CFRULE-TYPE" ); + sal_Int32 nSubType = dumpDec< sal_Int32 >( "sub-type", "CFRULE-SUBTYPE" ); + dumpDec< sal_Int32 >( "dxf-id" ); + dumpDec< sal_Int32 >( "priority" ); + switch( nSubType ) + { + case 0: dumpDec< sal_Int32 >( "operator", "CFRULE-CELL-OPERATOR" ); break; + case 5: dumpDec< sal_Int32 >( "rank" ); break; + case 8: dumpDec< sal_Int32 >( "operator", "CFRULE-TEXT-OPERATOR" ); break; + case 15: dumpDec< sal_Int32 >( "operator", "CFRULE-TIME-OPERATOR" ); break; + case 16: dumpDec< sal_Int32 >( "operator", "CFRULE-TIME-OPERATOR" ); break; + case 17: dumpDec< sal_Int32 >( "operator", "CFRULE-TIME-OPERATOR" ); break; + case 18: dumpDec< sal_Int32 >( "operator", "CFRULE-TIME-OPERATOR" ); break; + case 19: dumpDec< sal_Int32 >( "operator", "CFRULE-TIME-OPERATOR" ); break; + case 20: dumpDec< sal_Int32 >( "operator", "CFRULE-TIME-OPERATOR" ); break; + case 21: dumpDec< sal_Int32 >( "operator", "CFRULE-TIME-OPERATOR" ); break; + case 22: dumpDec< sal_Int32 >( "operator", "CFRULE-TIME-OPERATOR" ); break; + case 23: dumpDec< sal_Int32 >( "operator", "CFRULE-TIME-OPERATOR" ); break; + case 24: dumpDec< sal_Int32 >( "operator", "CFRULE-TIME-OPERATOR" ); break; + case 25: dumpDec< sal_Int32 >( "std-dev" ); break; + case 26: dumpDec< sal_Int32 >( "std-dev" ); break; + case 29: dumpDec< sal_Int32 >( "std-dev" ); break; + case 30: dumpDec< sal_Int32 >( "std-dev" ); break; + default: dumpDec< sal_Int32 >( "operator", "CFRULE-OTHER-OPERATOR" ); + } + dumpUnknown( 8 ); + dumpHex< sal_uInt16 >( "flags", "CFRULE-FLAGS" ); + // for no obvious reason the formula sizes occur twice + dumpDec< sal_Int32 >( "formula1-size" ); + dumpDec< sal_Int32 >( "formula2-size" ); + dumpDec< sal_Int32 >( "formula3-size" ); + dumpString( "text" ); + if( in().getSize() - in().tell() >= 8 ) + mxFmlaObj->dumpNameFormula( "formula1" ); + if( in().getSize() - in().tell() >= 8 ) + mxFmlaObj->dumpNameFormula( "formula2" ); + if( in().getSize() - in().tell() >= 8 ) + mxFmlaObj->dumpNameFormula( "formula3" ); + } + break; + + case OOBIN_ID_COL: + dumpColRange(); + dumpDec< sal_uInt16 >( "col-width", "CONV-COLWIDTH" ); + dumpUnknown( 2 ); + dumpDec< sal_Int32 >( "custom-xf-id" ); + dumpHex< sal_uInt16 >( "flags", "COL-FLAGS" ); + break; + + case OOBIN_ID_COLBREAKS: + dumpDec< sal_Int32 >( "count" ); + dumpDec< sal_Int32 >( "manual-count" ); + break; + + case OOBIN_ID_COLOR: + dumpColor(); + break; + + case OOBIN_ID_CONDFORMATTING: + dumpDec< sal_Int32 >( "cfrule-count" ); + dumpUnknown( 4 ); + dumpRangeList(); + break; + + case OOBIN_ID_DATATABLE: + dumpRange( "table-range" ); + dumpAddress( "ref1" ); + dumpAddress( "ref2" ); + dumpHex< sal_uInt8 >( "flags", "DATATABLE-FLAGS" ); + break; + + case OOBIN_ID_DATAVALIDATION: + dumpHex< sal_uInt32 >( "flags", "DATAVALIDATION-FLAGS" ); + dumpRangeList(); + dumpString( "error-title" ); + dumpString( "error-message" ); + dumpString( "input-title" ); + dumpString( "input-message" ); + mxFmlaObj->dumpNameFormula( "formula1" ); + mxFmlaObj->dumpNameFormula( "formula2" ); + break; + + case OOBIN_ID_DATAVALIDATIONS: + dumpUnknown( 14 ); // flags, xWindow, yWindow + dumpDec< sal_Int32 >( "count" ); + break; + + case OOBIN_ID_DDEITEMVALUES: + dumpDec< sal_Int32 >( "rows" ); + dumpDec< sal_Int32 >( "columns" ); + break; + + case OOBIN_ID_DDEITEM_STRING: + dumpString( "value" ); + break; + + case OOBIN_ID_DEFINEDNAME: + dumpHex< sal_uInt16 >( "flags", "DEFINEDNAME-FLAGS" ); + dumpUnknown( 2 ); + dumpHex< sal_uInt8 >( "keyboard-shortcut" ); + dumpDec< sal_Int32 >( "sheet-id", "DEFINEDNAME-SHEETID" ); + dumpString( "name" ); + mxFmlaObj->dumpNameFormula(); + dumpString( "comment" ); + if( in().getSize() - in().tell() >= 4 ) dumpString( "menu-text" ); + if( in().getSize() - in().tell() >= 4 ) dumpString( "description-text" ); + if( in().getSize() - in().tell() >= 4 ) dumpString( "help-text" ); + if( in().getSize() - in().tell() >= 4 ) dumpString( "statusbar-text" ); + break; + + case OOBIN_ID_DIMENSION: + dumpRange( "used-range" ); + break; + + case OOBIN_ID_DRAWING: + dumpString( "rel-id" ); + break; + + case OOBIN_ID_DXF: + dumpHex< sal_uInt32 >( "flags", "DXF-FLAGS" ); + for( sal_uInt16 nIndex = 0, nCount = dumpDec< sal_uInt16 >( "subrec-count" ); in().isValidPos() && (nIndex < nCount); ++nIndex ) + { + out().startMultiItems(); + sal_Int64 nStartPos = in().tell(); + writeEmptyItem( "SUBREC" ); + sal_uInt16 nSubRecId = dumpDec< sal_uInt16 >( "id", "DXF-SUBREC" ); + sal_uInt16 nSubRecSize = dumpDec< sal_uInt16 >( "size" ); + sal_Int64 nEndPos = nStartPos + nSubRecSize; + out().endMultiItems(); + IndentGuard aIndGuard( out() ); + switch( nSubRecId ) + { + case 0: + dumpDec< sal_uInt8 >( "pattern", "FILLPATTERNS" ); + break; + case 1: + case 2: + dumpColor(); + break; + case 3: + dumpDec< sal_Int32 >( "gradient-type", "FILL-GRADIENTTYPE" ); + dumpDec< double >( "linear-angle" ); + dumpDec< double >( "pos-left" ); + dumpDec< double >( "pos-right" ); + dumpDec< double >( "pos-top" ); + dumpDec< double >( "pos-bottom" ); + break; + case 4: + dumpDec< sal_uInt16 >( "index" ); + dumpDec< double >( "stop-position" ); + dumpColor( "stop-color" ); + break; + case 5: + dumpColor(); + break; + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + dumpColor( "color" ); + dumpDec< sal_uInt16 >( "style", "BORDERSTYLES" ); + break; + case 13: + case 14: + dumpBoolean( "value" ); + break; + case 15: + dumpDec< sal_uInt8 >( "alignment", "XF-HORALIGN" ); + break; + case 16: + dumpDec< sal_uInt8 >( "alignment", "XF-VERALIGN" ); + break; + case 17: + dumpDec< sal_uInt8 >( "rotation", "TEXTROTATION" ); + break; + case 18: + dumpDec< sal_uInt16 >( "indent" ); + break; + case 19: + dumpDec< sal_uInt8 >( "text-dir", "XF-TEXTDIRECTION" ); + break; + case 20: + case 21: + case 22: + dumpBoolean( "value" ); + break; + case 24: + dumpString( "name", false, false ); + break; + case 25: + dumpDec< sal_uInt16 >( "weight", "FONT-WEIGHT" ); + break; + case 26: + dumpDec< sal_uInt16 >( "underline", "FONT-UNDERLINE" ); + break; + case 27: + dumpDec< sal_uInt16 >( "escapement", "FONT-ESCAPEMENT" ); + break; + case 28: + case 29: + case 30: + case 31: + case 32: + case 33: + dumpBoolean( "value" ); + break; + case 36: + dumpDec< sal_Int32 >( "height", "CONV-TWIP-TO-PT" ); + break; + case 37: + dumpDec< sal_uInt8 >( "scheme", "FONT-SCHEME" ); + break; + case 38: + dumpString( "numfmt", false, false ); + break; + case 41: + dumpDec< sal_uInt16 >( "numfmt-id" ); + break; + case 42: + dumpDec< sal_uInt16 >( "relative-indent" ); + break; + case 43: + case 44: + dumpBoolean( "value" ); + break; + } + if( in().tell() < nEndPos ) + dumpRemaining( static_cast< sal_Int32 >( nEndPos - in().tell() ) ); + in().seek( nEndPos ); + } + break; + + case OOBIN_ID_EXTCELL_BOOL: + dumpColIndex(); + dumpBoolean(); + break; + + case OOBIN_ID_EXTCELL_DOUBLE: + dumpColIndex(); + dumpDec< double >( "value" ); + break; + + case OOBIN_ID_EXTCELL_ERROR: + dumpColIndex(); + dumpErrorCode(); + break; + + case OOBIN_ID_EXTCELL_STRING: + dumpColIndex(); + dumpString( "value" ); + break; + + case OOBIN_ID_EXTERNALBOOK: + switch( dumpDec< sal_uInt16 >( "type", "EXTERNALBOOK-TYPE" ) ) + { + case 0: + dumpString( "rel-id" ); + dumpDec< sal_Int32 >( "unused" ); + break; + case 1: + dumpString( "dde-service" ); + dumpString( "dde-topic" ); + break; + case 2: + dumpString( "rel-id" ); + dumpString( "prog-id" ); + break; + } + break; + + case OOBIN_ID_EXTERNALNAME: + dumpString( "name" ); + break; + + case OOBIN_ID_EXTERNALNAMEFLAGS: + dumpHex< sal_uInt16 >( "flags", "EXTERNALNAMEFLAGS-FLAGS" ); + dumpDec< sal_Int32 >( "sheet-id" ); + dumpUnknown( 1 ); + break; + + case OOBIN_ID_EXTERNALREF: + dumpString( "rel-id" ); + break; + + case OOBIN_ID_EXTERNALSHEETS: + { + sal_Int32 nCount = dumpDec< sal_Int32 >( "ref-count" ); + TableGuard aTabGuard( out(), 13, 17, 24 ); + out().resetItemIndex(); + for( sal_Int32 nRefId = 0; in().isValidPos() && (nRefId < nCount); ++nRefId ) + { + MultiItemsGuard aMultiGuard( out() ); + writeEmptyItem( "#ref" ); + dumpDec< sal_Int32 >( "extref-id" ); + dumpDec< sal_Int32 >( "first-sheet", "EXTERNALSHEETS-ID" ); + dumpDec< sal_Int32 >( "last-sheet", "EXTERNALSHEETS-ID" ); + } + } + break; + + case OOBIN_ID_EXTROW: + dumpRowIndex(); + break; + + case OOBIN_ID_EXTSHEETDATA: + dumpDec< sal_Int32 >( "sheet-id" ); + dumpHex< sal_uInt8 >( "flags", "EXTSHEETDATA-FLAGS" ); + break; + + case OOBIN_ID_EXTSHEETNAMES: + out().resetItemIndex(); + for( sal_Int32 nSheet = 0, nCount = dumpDec< sal_Int32 >( "sheet-count" ); in().isValidPos() && (nSheet < nCount); ++nSheet ) + dumpString( "#sheet-name" ); + break; + + case OOBIN_ID_FILL: + dumpDec< sal_Int32 >( "fill-pattern", "FILLPATTERNS" ); + dumpColor( "fg-color" ); + dumpColor( "bg-color" ); + dumpDec< sal_Int32 >( "gradient-type", "FILL-GRADIENTTYPE" ); + dumpDec< double >( "linear-angle" ); + dumpDec< double >( "pos-left" ); + dumpDec< double >( "pos-right" ); + dumpDec< double >( "pos-top" ); + dumpDec< double >( "pos-bottom" ); + out().resetItemIndex(); + for( sal_Int32 nStop = 0, nStopCount = dumpDec< sal_Int32 >( "stop-count" ); (nStop < nStopCount) && in().isValidPos(); ++nStop ) + { + writeEmptyItem( "#stop" ); + IndentGuard aIndGuard( out() ); + dumpColor( "stop-color" ); + dumpDec< double >( "stop-position" ); + } + break; + + case OOBIN_ID_FILEVERSION: + dumpGuid( "codename" ); + dumpString( "app-name" ); + dumpString( "last-edited" ); + dumpString( "lowest-edited" ); + dumpString( "build-version" ); + break; + + case OOBIN_ID_FONT: + dumpDec< sal_uInt16 >( "height", "CONV-TWIP-TO-PT" ); + dumpHex< sal_uInt16 >( "flags", "FONT-FLAGS" ); + dumpDec< sal_uInt16 >( "weight", "FONT-WEIGHT" ); + dumpDec< sal_uInt16 >( "escapement", "FONT-ESCAPEMENT" ); + dumpDec< sal_uInt8 >( "underline", "FONT-UNDERLINE" ); + dumpDec< sal_uInt8 >( "family", "FONT-FAMILY" ); + dumpDec< sal_uInt8 >( "charset", "CHARSET" ); + dumpUnknown( 1 ); + dumpColor(); + dumpDec< sal_uInt8 >( "scheme", "FONT-SCHEME" ); + dumpString( "name" ); + break; + + case OOBIN_ID_FORMULA_BOOL: + dumpCellHeader(); + dumpBoolean(); + dumpHex< sal_uInt16 >( "flags", "FORMULA-FLAGS" ); + mxFmlaObj->dumpCellFormula(); + break; + + case OOBIN_ID_FORMULA_DOUBLE: + dumpCellHeader(); + dumpDec< double >( "value" ); + dumpHex< sal_uInt16 >( "flags", "FORMULA-FLAGS" ); + mxFmlaObj->dumpCellFormula(); + break; + + case OOBIN_ID_FORMULA_ERROR: + dumpCellHeader(); + dumpErrorCode(); + dumpHex< sal_uInt16 >( "flags", "FORMULA-FLAGS" ); + mxFmlaObj->dumpCellFormula(); + break; + + case OOBIN_ID_FORMULA_STRING: + dumpCellHeader(); + dumpString( "value" ); + dumpHex< sal_uInt16 >( "flags", "FORMULA-FLAGS" ); + mxFmlaObj->dumpCellFormula(); + break; + + case OOBIN_ID_HEADERFOOTER: + dumpHex< sal_uInt16 >( "flags", "HEADERFOOTER-FLAGS" ); + dumpString( "odd-header" ); + dumpString( "odd-footer" ); + dumpString( "even-header" ); + dumpString( "even-footer" ); + dumpString( "first-header" ); + dumpString( "first-footer" ); + break; + + case OOBIN_ID_HYPERLINK: + dumpRange(); + dumpString( "rel-id" ); + dumpString( "location" ); + dumpString( "tooltip" ); + dumpString( "display" ); + break; + + case OOBIN_ID_MERGECELL: + dumpRange(); + break; + + case OOBIN_ID_NUMFMT: + dumpDec< sal_uInt16 >( "numfmt-id" ); + dumpString( "format" ); + break; + + case OOBIN_ID_PAGEMARGINS: + dumpDec< double >( "left-margin" ); + dumpDec< double >( "right-margin" ); + dumpDec< double >( "top-margin" ); + dumpDec< double >( "bottom-margin" ); + dumpDec< double >( "header-margin" ); + dumpDec< double >( "footer-margin" ); + break; + + case OOBIN_ID_PAGESETUP: + dumpDec< sal_Int32 >( "paper-size", "PAGESETUP-PAPERSIZE" ); + dumpDec< sal_Int32 >( "scaling", "CONV-PERCENT" ); + dumpDec< sal_Int32 >( "horizontal-res", "PAGESETUP-DPI" ); + dumpDec< sal_Int32 >( "vertical-res", "PAGESETUP-DPI" ); + dumpDec< sal_Int32 >( "copies" ); + dumpDec< sal_Int32 >( "first-page" ); + dumpDec< sal_Int32 >( "scale-to-width", "PAGESETUP-SCALETOPAGES" ); + dumpDec< sal_Int32 >( "scale-to-height", "PAGESETUP-SCALETOPAGES" ); + dumpHex< sal_uInt16 >( "flags", "PAGESETUP-FLAGS" ); + dumpString( "printer-settings-rel-id" ); + break; + + case OOBIN_ID_PANE: + dumpDec< double >( "x-split-pos" ); + dumpDec< double >( "y-split-pos" ); + dumpAddress( "second-top-left" ); + dumpDec< sal_Int32 >( "active-pane", "PANE-ID" ); + dumpHex< sal_uInt8 >( "flags", "PANE-FLAGS" ); + break; + + case OOBIN_ID_PHONETICPR: + dumpDec< sal_uInt16 >( "font-id", "FONTNAMES" ); + dumpDec< sal_Int32 >( "type", "PHONETICPR-TYPE" ); + dumpDec< sal_Int32 >( "alignment", "PHONETICPR-ALIGNMENT" ); + break; + + case OOBIN_ID_ROW: + dumpRowIndex(); + dumpDec< sal_Int32 >( "custom-xf-id" ); + dumpDec< sal_uInt16 >( "height", "CONV-TWIP-TO-PT" ); + dumpHex< sal_uInt16 >( "flags", "ROW-FLAGS" ); + dumpUnknown( 5 ); + if( getRecordStream().getRecLeft() >= 8 ) + dumpRowRange( "row-spans" ); + break; + + case OOBIN_ID_ROWBREAKS: + dumpDec< sal_Int32 >( "count" ); + dumpDec< sal_Int32 >( "manual-count" ); + break; + + case OOBIN_ID_SELECTION: + dumpDec< sal_Int32 >( "pane", "PANE-ID" ); + dumpAddress( "active-cell" ); + dumpDec< sal_Int32 >( "active-cell-id" ); + dumpRangeList( "selection" ); + break; + + case OOBIN_ID_SHAREDFMLA: + dumpRange( "formula-range" ); + mxFmlaObj->dumpCellFormula(); + break; + + case OOBIN_ID_SHEET: + dumpDec< sal_Int32 >( "sheet-state", "SHEET-STATE" ); + dumpDec< sal_Int32 >( "sheet-id" ); + dumpString( "rel-id" ); + dumpString( "sheet-name" ); + break; + + case OOBIN_ID_SHEETFORMATPR: + dumpDec< sal_Int32 >( "default-col-width", "CONV-COLWIDTH" ); + dumpDec< sal_uInt16 >( "base-col-width" ); + dumpDec< sal_uInt16 >( "default-row-height", "CONV-TWIP-TO-PT" ); + dumpHex< sal_uInt16 >( "flags", "SHEETFORMATPR-FLAGS" ); + dumpDec< sal_uInt8 >( "max-row-outline" ); + dumpDec< sal_uInt8 >( "max-col-outline" ); + break; + + case OOBIN_ID_SHEETPR: + dumpHex< sal_uInt16 >( "flags", "SHEETPR-FLAGS" ); + dumpUnknown( 1 ); + dumpColor( "tab-color" ); + dumpUnknown( 8 ); + dumpString( "codename" ); + break; + + case OOBIN_ID_SHEETPROTECTION: + dumpHex< sal_uInt16 >( "password-hash" ); + // no flags field for all these boolean flags?!? + dumpDec< sal_Int32 >( "sheet-locked", "BOOLEAN" ); + dumpDec< sal_Int32 >( "objects-locked", "BOOLEAN" ); + dumpDec< sal_Int32 >( "scenarios-locked", "BOOLEAN" ); + dumpDec< sal_Int32 >( "format-cells-locked", "BOOLEAN" ); + dumpDec< sal_Int32 >( "format-columns-locked", "BOOLEAN" ); + dumpDec< sal_Int32 >( "format-rows-locked", "BOOLEAN" ); + dumpDec< sal_Int32 >( "insert-columns-locked", "BOOLEAN" ); + dumpDec< sal_Int32 >( "insert-rows-locked", "BOOLEAN" ); + dumpDec< sal_Int32 >( "insert-hyperlinks-locked", "BOOLEAN" ); + dumpDec< sal_Int32 >( "delete-columns-locked", "BOOLEAN" ); + dumpDec< sal_Int32 >( "delete-rows-locked", "BOOLEAN" ); + dumpDec< sal_Int32 >( "select-locked-cells-locked", "BOOLEAN" ); + dumpDec< sal_Int32 >( "sort-locked", "BOOLEAN" ); + dumpDec< sal_Int32 >( "autofilter-locked", "BOOLEAN" ); + dumpDec< sal_Int32 >( "pivot-tables-locked", "BOOLEAN" ); + dumpDec< sal_Int32 >( "select-unlocked-cells-locked", "BOOLEAN" ); + break; + + case OOBIN_ID_SHEETVIEW: + dumpHex< sal_uInt16 >( "flags", "SHEETVIEW-FLAGS" ); + dumpDec< sal_Int32 >( "view-type", "SHEETVIEW-TYPE" ); + dumpAddress( "top-left" ); + dumpDec< sal_Int32 >( "gridcolor-id", "PALETTE-COLORS" ); + dumpDec< sal_uInt16 >( "zoom-scale", "CONV-PERCENT" ); + dumpDec< sal_uInt16 >( "zoom-scale-normal", "CONV-PERCENT" ); + dumpDec< sal_uInt16 >( "zoom-scale-sheet-layout", "CONV-PERCENT" ); + dumpDec< sal_uInt16 >( "zoom-scale-page-layout", "CONV-PERCENT" ); + dumpDec< sal_Int32 >( "workbookview-id" ); + break; + + case OOBIN_ID_SI: + dumpString( "string", true ); + break; + + case OOBIN_ID_SST: + dumpDec< sal_Int32 >( "string-cell-count" ); + dumpDec< sal_Int32 >( "sst-size" ); + break; + + case OOBIN_ID_TABLE: + dumpRange(); + dumpDec< sal_Int32 >( "type", "TABLE-TYPE" ); + dumpDec< sal_Int32 >( "id" ); + dumpDec< sal_Int32 >( "header-rows" ); + dumpDec< sal_Int32 >( "totals-rows" ); + dumpHex< sal_uInt32 >( "flags", "TABLE-FLAGS" ); + dumpDec< sal_Int32 >( "headerrow-dxf-id" ); + dumpDec< sal_Int32 >( "data-dxf-id" ); + dumpDec< sal_Int32 >( "totalsrow-dxf-id" ); + dumpDec< sal_Int32 >( "table-border-dxf-id" ); + dumpDec< sal_Int32 >( "headerrow-border-dxf-id" ); + dumpDec< sal_Int32 >( "totalsrow-border-dxf-id" ); + dumpDec< sal_Int32 >( "connection-id" ); + dumpString( "name" ); + dumpString( "display-name" ); + dumpString( "comment" ); + dumpString( "headerrow-cell-style" ); + dumpString( "data-cell-style" ); + dumpString( "totalsrow-cell-style" ); + break; + + case OOBIN_ID_TABLEPART: + dumpString( "rel-id" ); + break; + + case OOBIN_ID_TABLESTYLEINFO: + dumpHex< sal_uInt16 >( "flags" ); + dumpString( "style-name" ); + break; + + case OOBIN_ID_VOLTYPEMAIN: + dumpString( "first" ); + break; + + case OOBIN_ID_VOLTYPESTP: + dumpString( "topic-value" ); + break; + + case OOBIN_ID_VOLTYPETR: + dumpAddress( "ref" ); + dumpDec< sal_Int32 >( "sheet-id" ); + break; + + case OOBIN_ID_WORKBOOKPR: + dumpHex< sal_uInt32 >( "flags", "WORKBBOKPR-FLAGS" ); + dumpDec< sal_Int32 >( "default-theme-version" ); + dumpString( "codename" ); + break; + + case OOBIN_ID_WORKBOOKVIEW: + dumpDec< sal_Int32 >( "x-window" ); + dumpDec< sal_Int32 >( "y-window" ); + dumpDec< sal_Int32 >( "win-width" ); + dumpDec< sal_Int32 >( "win-height" ); + dumpDec< sal_Int32 >( "tabbar-ratio" ); + dumpDec< sal_Int32 >( "first-sheet" ); + dumpDec< sal_Int32 >( "active-sheet" ); + dumpHex< sal_uInt8 >( "flags", "WORKBOOKVIEW-FLAGS" ); + break; + + case OOBIN_ID_XF: + dumpDec< sal_uInt16 >( "parent-xf-id" ); + dumpDec< sal_uInt16 >( "numfmt-id" ); + dumpDec< sal_uInt16 >( "font-id", "FONTNAMES" ); + dumpDec< sal_uInt16 >( "fill-id" ); + dumpDec< sal_uInt16 >( "border-id" ); + dumpHex< sal_uInt32 >( "alignment", "XF-ALIGNMENT" ); + dumpHex< sal_uInt16 >( "used-flags", "XF-USEDFLAGS" ); + break; + } +} + +// ============================================================================ + +RecordHeaderObject::RecordHeaderObject( const InputObjectBase& rParent ) +{ + static const RecordHeaderConfigInfo saHeaderCfgInfo = + { + "REC", + "RECORD-NAMES", + "show-record-pos", + "show-record-size", + "show-record-id", + "show-record-name", + "show-record-body", + }; + RecordHeaderBase< sal_Int32, sal_Int32 >::construct( rParent, saHeaderCfgInfo ); +} + +RecordHeaderObject::~RecordHeaderObject() +{ +} + +bool RecordHeaderObject::implReadHeader( sal_Int64& ornRecPos, sal_Int32& ornRecId, sal_Int32& ornRecSize ) +{ + bool bValidRec = readCompressedInt( ornRecPos, ornRecId ) && (ornRecId >= 0) && readCompressedInt( ornRecPos, ornRecSize ) && (ornRecSize >= 0); + if( bValidRec ) + { + maData.realloc( ornRecSize ); + bValidRec = (ornRecSize == 0) || (in().read( maData.getArray(), ornRecSize ) == ornRecSize); + ornRecPos += ornRecSize; + } + return bValidRec; +} + +bool RecordHeaderObject::readByte( sal_Int64& ornRecPos, sal_uInt8& ornByte ) +{ + ++ornRecPos; + return in().read( &ornByte, 1 ) == 1; +} + +bool RecordHeaderObject::readCompressedInt( sal_Int64& ornRecPos, sal_Int32& ornValue ) +{ + ornValue = 0; + sal_uInt8 nByte; + if( !readByte( ornRecPos, nByte ) ) return false; + ornValue = nByte & 0x7F; + if( (nByte & 0x80) == 0 ) return true; + if( !readByte( ornRecPos, nByte ) ) return false; + ornValue |= sal_Int32( nByte & 0x7F ) << 7; + if( (nByte & 0x80) == 0 ) return true; + if( !readByte( ornRecPos, nByte ) ) return false; + ornValue |= sal_Int32( nByte & 0x7F ) << 14; + if( (nByte & 0x80) == 0 ) return true; + if( !readByte( ornRecPos, nByte ) ) return false; + ornValue |= sal_Int32( nByte & 0x7F ) << 21; + return true; +} + +// ============================================================================ + +RecordStreamObject::RecordStreamObject( const ObjectBase& rParent, const OUString& rOutFileName, BinaryInputStreamRef xStrm ) +{ + InputStreamObject::construct( rParent, rOutFileName, xStrm ); + if( InputStreamObject::implIsValid() ) + { + mxHdrObj.reset( new RecordHeaderObject( *this ) ); + mxRecObj.reset( new RecordObject( *this ) ); + } +} + +bool RecordStreamObject::implIsValid() const +{ + return isValid( mxHdrObj ) && isValid( mxRecObj ) && InputStreamObject::implIsValid(); +} + +void RecordStreamObject::implDump() +{ + while( mxHdrObj->startNextRecord() ) + { + if( mxHdrObj->isShowRecBody() ) + { + IndentGuard aIndGuard( out() ); + mxRecObj->dumpRecord( mxHdrObj->getRecordData(), mxHdrObj->getRecId() ); + } + out().emptyLine(); + } +} + +// ============================================================================ + +RootStorageObject::RootStorageObject( const DumperBase& rParent ) +{ + RootStorageObjectBase::construct( rParent ); +} + +void RootStorageObject::implDumpStream( BinaryInputStreamRef xStrm, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSystemFileName ) +{ + if( (rStrgPath == CREATE_OUSTRING( "xl" )) || + (rStrgPath == CREATE_OUSTRING( "xl/externalLinks" )) || + (rStrgPath == CREATE_OUSTRING( "xl/macrosheets" )) || + (rStrgPath == CREATE_OUSTRING( "xl/tables" )) || + (rStrgPath == CREATE_OUSTRING( "xl/worksheets" )) ) + { + const OUString aBinSuffix = CREATE_OUSTRING( ".bin" ); + sal_Int32 nBinSuffixPos = rStrmName.getLength() - aBinSuffix.getLength(); + if( (nBinSuffixPos >= 0) && rStrmName.match( aBinSuffix, nBinSuffixPos ) ) + RecordStreamObject( *this, rSystemFileName, xStrm ).dump(); + } +} + +// ============================================================================ + +Dumper::Dumper( const FilterBase& rFilter ) +{ + ConfigRef xCfg( new Config( "OOO_XLSBDUMPER" ) ); + DumperBase::construct( rFilter, xCfg ); +} + +void Dumper::implDump() +{ + RootStorageObject( *this ).dump(); +} + +// ============================================================================ + +} // namespace xlsb +} // namespace dump +} // namespace oox + +#endif + diff --git a/oox/source/dump/xlsbdumperconfig.dat b/oox/source/dump/xlsbdumperconfig.dat new file mode 100644 index 000000000000..7c80a680745e --- /dev/null +++ b/oox/source/dump/xlsbdumperconfig.dat @@ -0,0 +1,655 @@ + +# dumper settings ============================================================ + +# Path to base configuration data, relative to this file. +include-config-file=dumperconfig.dat + +# XLSB record settings ------------------------------------------------------- + +# Show total stream position of the record (default=on). +# 0=off, 1=on +show-record-pos=0 + +# Show total record size in bytes (default=on). +# 0=off, 1=on +show-record-size=1 + +# Show record identifier (default=on). +# 0=off, 1=on +show-record-id=1 + +# Show record name, if known (default=on). +# 0=off, 1=on +show-record-name=1 + +# Show record contents (default=on). +# 0=off, 1=on +show-record-body=1 + +# common --------------------------------------------------------------------- + +unitconverter=CONV-TINT,/327.67,% +unitconverter=CONV-COLWIDTH,/256,chars + +constlist=ERRORCODES + 0x00=#NULL! + 0x07=#DIV/0! + 0x0F=#VALUE! + 0x17=#REF! + 0x1D=#NAME? + 0x24=#NUM! + 0x2A=#N/A +end + +flagslist=STRING-FLAGS + 0x01=rich-string + 0x02=phonetic-text +end + +flagslist=CELL-FLAGS + 0x0100=show-phonetic +end + +combilist=PHONETIC-FLAGS + ignore=0x0030 + 0x0003=uint8,dec,type,PHONETICPR-TYPE + 0x000C=uint8,dec,alignment,PHONETICPR-ALIGNMENT +end + +shortlist=COLOR-TYPE,0,none,auto,,indexed,,rgb,,theme + +multilist=PALETTE-COLORS + default= + 0=ega-black,ega-white,ega-red,ega-green,ega-blue,ega-yellow,ega-magenta,ega-cyan + 64=sys-window-text + 65=sys-window-bg + 67=sys-button-face + 77=sys-window-text-chart + 78=sys-window-bg-chart + 79=auto-border-chart + 80=sys-tooltip-bg + 81=sys-tooltip-text +end + +constlist=TEXTROTATION + default= + 255=stacked +end + +multilist=BORDERSTYLES + 0=none,thin,medium,dash,dot + 5=thick,double,hair,medium-dash,thin-dash-dot + 10=medium-dash-dot,thin-dash-dot-dot,medium-dash-dot-dot,slant-dash-dot +end + +multilist=FILLPATTERNS + 0=no-fill,solid-fill,50%-grey,75%-grey,25%-grey + 5=hor-stripe,ver-stripe,rev-diag-stripe,diag-stripe,diag-crosshatch + 10=thick-diag-crosshatch,thin-hor-stripe,thin-ver-stripe,thin-rev-diag-stripe,thin-diag-stripe + 15=thin-hor-crosshatch,thin-diag-crosshatch,12.5%-grey,6.25%-grey + 40=gradient +end + +# formulas ------------------------------------------------------------------- + +flagslist=FORMULA-FLAGS + 0x0002=recalc-always +end + +multilist=BASETOKENS + 0x00=,tExp,tTbl,tAdd,tSub,tMul,tDiv,tPower + 0x08=tConcat,tLT,tLE,tEQ,tGE,tGT,tNE,tIsect + 0x10=tList,tRange,tUplus,tUminus,tPercent,tParen,tMissArg,tStr + 0x18=tTable,tAttr,,,tErr,tBool,tInt,tNum +end + +constlist=TOKENCLASSES + 0x20=R + 0x40=V + 0x60=A +end + +multilist=CLASSTOKENS + 0x00=tArray,tFunc,tFuncVar,tName,tRef,tArea,tMemArea,tMemErr + 0x08=tMemNoMem,tMemFunc,tRefErr,tAreaErr,tRefN,tAreaN,tMemAreaN,tMemNoMemN + 0x18=,tNameX,tRef3d,tArea3d,tRefErr3d,tAreaErr3d +end + +combilist=FUNCID + 0x7FFF=uint16,dec,func-id + 0x8000=command +end + +combilist=PARAMCOUNT-CMD + 0x7F=uint8,dec,count + 0x80=prompt +end + +combilist=REFRELFLAGS + 0x3FFF=uint16,dec,value + 0x4000=col-rel + 0x8000=row-rel +end + +flagslist=TABLEFLAGS + 0x0001=single-column + 0x0002=column-range + 0x0004=#all + 0x0008=#headers + 0x0010=#data + 0x0020=#totals + 0x0040=#this-row + 0x0080=bracket-spaces + 0x0100=sep-spaces + 0x0200=single-row + 0x0400=single-cell +end + +flagslist=ATTRTYPES + 0x01=volatile + 0x02=if + 0x04=choose + 0x08=skip + 0x10=sum + 0x20=assign + 0x40=space + 0x80=iferror +end + +shortlist=ATTRSPACETYPES,0,space-before-token,cr-before-token,space-before-open,cr-before-open,space-before-close,cr-before-close,leading-space + +shortlist=ARRAYVALUE-TYPE,0,number,string,boolean,,error + +# record names --------------------------------------------------------------- + +multilist=RECORD-NAMES + 0x0000=ROW,CELL_BLANK,CELL_RK,CELL_ERROR,CELL_BOOL,CELL_DOUBLE,CELL_STRING,CELL_SI + 0x0008=FORMULA_STRING,FORMULA_DOUBLE,FORMULA_BOOL,FORMULA_ERROR,,,, + 0x0010=,,,SI,,,, + + 0x0020=,,,,,,,DEFINEDNAME + 0x0028=,,,FONT,NUMFMT,FILL,BORDER,XF + 0x0030=CELLSTYLE,,,,,,, + 0x0038=,,,,COL,,CELL_RSTRING,CALCCHAINCELL + 0x0040=DATAVALIDATION,,,,,,, + + 0x0080=FILEVERSION,WORKSHEET,WORKSHEET_END,WORKBOOK,WORKBOOK_END,SHEETVIEWS,SHEETVIEWS_END,BOOKVIEWS + 0x0088=BOOKVIEWS_END,SHEETVIEW,SHEETVIEW_END,,,,,SHEETS + 0x0090=SHEETS_END,SHEETDATA,SHEETDATA_END,SHEETPR,DIMENSION,,,PANE + 0x0098=SELECTION,WORKBOOKPR,,,SHEET,CALCPR,WORKBOOKVIEW,SST + 0x00A0=SST_END,AUTOFILTER,AUTOFILTER_END,FILTERCOLUMN,FILTERCOLUMN_END,,, + + 0x00B0=,MERGECELLS,MERGECELLS_END,,,,, + + 0x0110=,,,,,,STYLESHEET,STYLESHEET_END + + 0x0150=,,,,,,,TABLE + 0x0158=TABLE_END,TABLECOLUMNS,TABLECOLUMNS_END,TABLECOLUMN,TABLECOLUMN_END,,,CALCEDCOLUMNFMLA + 0x0160=,EXTERNALREFS,EXTERNALREFS_END,EXTERNALREF,,EXTERNALSELF,EXTERNALSAME,EXTSHEETNAMES + 0x0168=EXTERNALBOOK,,EXTERNALSHEETS,EXTSHEETDATA,EXTSHEETDATA_END,,EXTROW, + 0x0170=EXTCELL_DOUBLE,EXTCELL_BOOL,EXTCELL_ERROR,EXTCELL_STRING,,,, + + 0x0180=,,,,,,COLS,COLS_END + 0x0188=ROWBREAKS,ROWBREAKS_END,COLBREAKS,COLBREAKS_END,BRK,,, + + 0x01A8=,,ARRAY,SHAREDFMLA,DATATABLE,,, + + 0x01C8=,,,,,CONDFORMATTING,CONDFORMATTING_END,CFRULE + 0x01D0=CFRULE_END,ICONSET,ICONSET_END,DATABAR,DATABAR_END,COLORSCALE,COLORSCALE_END,CFVO + 0x01D8=,COLORS,COLORS_END,RGBCOLOR,PAGEMARGINS,PRINTOPTIONS,PAGESETUP,HEADERFOOTER + 0x01E0=HEADERFOOTER_END,,,,,SHEETFORMATPR,, + 0x01E8=,,,,,,HYPERLINK, + + 0x01F8=,DXFS,DXFS_END,DXF,TABLESTYLES,TABLESTYLES_END,, + 0x0200=,TABLESTYLEINFO,VOLTYPES,VOLTYPES_END,VOLTYPE,VOLTYPE_END,VOLTYPEMAIN,VOLTYPEMAIN_END + 0x0208=VOLTYPETP,VOLTYPETP_END,VOLTYPESTP,VOLTYPETR,,VOLTYPE_ERROR,, + 0x0210=CALCCHAIN,CALCCHAIN_END,,,,,,SHEETPROTECTION + 0x0218=,PHONETICPR,,,,,, + 0x0220=,,,,,,DRAWING,LEGACYDRAWING + + 0x0230=,,,,CFCOLOR,INDEXEDCOLORS,INDEXEDCOLORS_END, + 0x0238=,MRUCOLORS,MRUCOLORS_END,,COLOR,DATAVALIDATIONS,DATAVALIDATIONS_END, + 0x0240=,EXTERNALNAME,DDEITEMVALUES,DDEITEMVALUES_END,DDEITEM_DOUBLE,DDEITEM_ERROR,DDEITEM_STRING,DDEITEM_EMPTY + 0x0248=DDEITEM_BOOL,EXTERNALNAMEREF,EXTERNALNAMEFLAGS,SHEETDATASET|EXTERNALNAME_END,SHEETDATASET_END,,, + + 0x0258=,,,FILLS,FILLS_END,,, + 0x0260=,,,FONTS,FONTS_END,BORDERS,BORDERS_END,NUMFMTS + 0x0268=NUMFMTS_END,CELLXFS,CELLXFS_END,CELLSTYLES,CELLSTYLES_END,,, + 0x0270=,,CELLSTYLEXFS,CELLSTYLEXFS_END + 0x0278=,,,,,,,OLEOBJECT + + 0x0290=,,,,TABLEPARTS,TABLEPART,TABLEPARTS_END, +end + +# simple records ------------------------------------------------------------- + +constlist=SIMPLE-RECORDS + 0x0159=int32,dec,count + 0x01DD=uint16,hex,flags,PRINTOPTIONS-FLAGS + 0x01F9=int32,dec,count + 0x0204=int32,dec,type,VOLTYPE-TYPE + 0x020D=uint8,dec,error-code,ERRORCODES + 0x0244=double,dec,value + 0x0245=uint8,dec,error-code,ERRORCODES + 0x0248=uint8,dec,value,BOOLEAN + 0x025B=int32,dec,count + 0x0263=int32,dec,count + 0x0265=int32,dec,count + 0x0267=int32,dec,count + 0x0269=int32,dec,count + 0x026B=int32,dec,count + 0x0272=int32,dec,count + 0x0294=int32,dec,count +end + +# ARRAY ---------------------------------------------------------------------- + +flagslist=ARRAY-FLAGS + 0x01=recalc-always +end + +# BORDER --------------------------------------------------------------------- + +flagslist=BORDER-FLAGS + 0x01=diag-tl-to-br + 0x02=diag-bl-to-tr +end + +# BRK ------------------------------------------------------------------------ + +flagslist=BRK-FLAGS + 0x00000001=manual +end + +# CALCPR --------------------------------------------------------------------- + +shortlist=CALCPR-CALCMODE,0,manual,auto,auto-no-tables + +flagslist=CALCPR-FLAGS + 0x0002=a1 + 0x0004=iterate + 0x0008=full-precision + 0x0010=calc-complete + 0x0020=calc-on-save + 0x0040=concurrent + 0x0080=manual-processors + 0x0100=force-full-calc +end + +# CELLSTYLE ------------------------------------------------------------------ + +flagslist=CELLSTYLE-FLAGS + 0x0001=builtin + 0x0002=hidden + 0x0004=custom +end + +multilist=CELLSTYLE-BUILTIN + 0=normal,rowlevel,collevel,comma,currency,percent,comma-0,currency-0,hyperlink,followed-hyperlink + 10=note,warning-text,,,,title,heading-1,heading-2,heading-3,heading-4 + 20=input,output,calculation,check-cell,linked-cell,total,good,bad,neutral,accent1 + 30=20%-accent1,40%-accent1,60%-accent1,accent2,20%-accent2,40%-accent2,60%-accent2,accent3,20%-accent3,40%-accent3 + 40=60%-accent3,accent4,20%-accent4,40%-accent4,60%-accent4,accent5,20%-accent5,40%-accent5,60%-accent5,accent6 + 50=20%-accent6,40%-accent6,60%-accent6,explanatory-text +end + +# CFRULE --------------------------------------------------------------------- + +shortlist=CFRULE-TYPE,1,cell-is,expression,color-scale,data-bar,top-ten,icon-set + +multilist=CFRULE-SUBTYPE + 0=cell-is,expression,color-scale,data-bar,icon-set,top-ten,,unique-values,contains-text,contains-blanks + 10=not-contains-blanks,contains-errors,not-contains-errors,,,today,tomorrow,yesterday,last-7-days,last-month + 20=next-month,this-week,next-week,last-week,this-month,above-average,below-average,duplicate-values,,equal-above-average + 30=equal-below-average +end + +shortlist=CFRULE-CELL-OPERATOR,1,between,not-between,equal,not-equal,greater-than,less-than,greater-equal,less-equal +shortlist=CFRULE-TEXT-OPERATOR,0,contains,not-contains,begins-with,ends-with +shortlist=CFRULE-TIME-OPERATOR,0,today,yesterday,last-7-days,this-week,last-week,last-month,tomorrow,next-week,next-month,this-month +shortlist=CFRULE-OTHER-OPERATOR,0,none + +flagslist=CFRULE-FLAGS + 0x0002=stop-if-true + 0x0004=avove-average + 0x0008=bottom + 0x0010=percent +end + +# COL ------------------------------------------------------------------------ + +combilist=COL-FLAGS + 0x0001=hidden + 0x0002=custom-width + 0x0004=best-fit + 0x0700=uint8,dec,outline-level + 0x1000=outline-collapsed +end + +# DATATABLE ------------------------------------------------------------------ + +flagslist=DATATABLE-FLAGS + 0x01=row-table + 0x02=table-2d + 0x04=ref1-deleted + 0x08=ref2-deleted +end + +# DATAVALIDATION ------------------------------------------------------------- + +combilist=DATAVALIDATION-FLAGS + 0x0000000F=uint8,dec,type,DATAVALIDATION-TYPE + 0x00000070=uint8,dec,error-style,DATAVALIDATION-ERRORSTYLE + 0x00000080=string-list + 0x00000100=ignore-empty + 0x00000200=no-dropdown + 0x00040000=show-input-box + 0x00080000=show-error-box + 0x00F00000=uint8,dec,operator,DATAVALIDATION-OPERATOR +end + +shortlist=DATAVALIDATION-TYPE,0,any,whole,decimal,list,date,time,text-length,custom +shortlist=DATAVALIDATION-OPERATOR,0,between,not-between,equal,not-equal,greater-than,less-than,greater-equal,less-equal +shortlist=DATAVALIDATION-ERRORSTYLE,0,error,warning,info + +# DEFINEDNAME ---------------------------------------------------------------- + +combilist=DEFINEDNAME-FLAGS + 0x0001=hidden + 0x0002=function + 0x0004=command + 0x0008=macro + 0x0020=built-in + 0x0FC0=uint16,dec,func-group,DEFINEDNAME-FUNCGROUP +end + +shortlist=DEFINEDNAME-FUNCGROUP,0,none,financial,date-time,math-trig,statistical,lookup-ref,database,text,logical,information,commands,customizing,macro-control,dde-external,user-definded + +constlist=DEFINEDNAME-SHEETID + default= + -1=global +end + +# DXF ------------------------------------------------------------------------ + +flagslist=DXF-FLAGS + 0x00008000=border-outline +end + +multilist=DXF-SUBREC + 0=FILL-PATTERN,FILL-FGCOLOR,FILL-BGCOLOR,FILL-GRADIENT,FILL-STOP + 5=FONT-COLOR,BORDER-TOP,BORDER-BOTTOM,BORDER-LEFT,BORDER-RIGHT + 10=BORDER-DIAGONAL,BORDER-VERTICAL,BORDER-HORIZONTAL,BORDER-DIAGUP,BORDER-DIAGDOWN + 15=ALIGN-HORIZONTAL,ALIGN-VERTICAL,ALIGN-ROTATION,ALIGN-INDENT,ALIGN-READINGORDER + 20=ALIGN-WRAPTEXT,ALIGN-JUSTLASTLINE,ALIGN-SHRINKTOFIT,,FONT-NAME + 25=FONT-WEIGHT,FONT-UNDERLINE,FONT-ESCAPEMENT,FONT-ITALIC,FONT-STRIKE + 30=FONT-OUTLINE,FONT-SHADOW,FONT-CONDENSE,FONT-EXTEND, + 35=,FONT-HEIGHT,FONT-SCHEME,NUMFMT-CODE, + 40=,NUMFMT-ID,ALIGN-RELINDENT,PROT-LOCKED,PROT-HIDDEN +end + +# EXTERNALBOOK --------------------------------------------------------------- + +shortlist=EXTERNALBOOK-TYPE,0,book,dde-link,ole-link + +# EXTERNALNAMEFLAGS ---------------------------------------------------------- + +flagslist=EXTERNALNAMEFLAGS-FLAGS + 0x0002=automatic + 0x0004=pic-link + 0x0008=dde-stddocumentname + 0x0010=ole-link + 0x0020=iconified +end + +# EXTERNALSHEETS ------------------------------------------------------------- + +constlist=EXTERNALSHEETS-ID + default= + -1=deleted + -2=special +end + +# EXTSHEETDATA --------------------------------------------------------------- + +flagslist=EXTSHEETDATA-FLAGS + 0x01=refresh-error +end + +# FILL ----------------------------------------------------------------------- + +shortlist=FILL-GRADIENTTYPE,0,linear,path + +# FONT ----------------------------------------------------------------------- + +flagslist=FONT-FLAGS + 0x0001=bold + 0x0002=italic + 0x0008=strikeout + 0x0010=outline + 0x0020=shadow + 0x0040=condense + 0x0080=extend +end + +constlist=FONT-WEIGHT + 400=normal + 700=bold +end + +multilist=FONT-UNDERLINE + 0x00=none,single,double + 0x21=single-acc,double-acc +end + +shortlist=FONT-SCHEME,0,none,major,minor +shortlist=FONT-ESCAPEMENT,0,none,superscript,subscript +shortlist=FONT-FAMILY,0,none,roman,swiss,modern,script,decorative + +# HEADERFOOTER --------------------------------------------------------------- + +flagslist=HEADERFOOTER-FLAGS + 0x0001=diff-odd-even + 0x0002=diff-dirst + 0x0004=scale-with-doc + 0x0008=align-with-margins +end + +# PAGESETUP ------------------------------------------------------------------ + +multilist=PAGESETUP-PAPERSIZE + 0=undefined,letter,letter-small,tabloid,ledger,legal,statement,executive,a3,a4 + 10=a4-small,a5,b4,b5,folio,quarto,10x14,11x17,note,envelope-9 + 20=envelope-10,envelope-11,envelope-12,envelope-14,c,d,e,envelope-dl,envelope-c5,envelope-c3 + 30=envelope-c4,envelope-c6,envelope-c65,envelope-b4,envelope-b5,envelope-b6,envelope-italy,envelope-monarch,envelope-6-3/4,us-standard-fanfold + 40=german-standard-fanfold,german-legal-fanfold,b4,japanese-dbl-postcaed,9x11,10x11,15x11,, + 50=envelope-invite,letter-extra,legal-extra,tabloid-extra,a4-extra,letter-transverse,a4-transverse,letter-extra-transverse,super-a-a4,super-b-a3,letter-plus + 60=a4-plus,a5-transverse,jis-b5-transverse,a3-extra,a5-extra,b5-extra,a2,a3-transverse,a3-extra-transverse +end + +constlist=PAGESETUP-SCALETOPAGES + default= + 0=automatic +end + +combilist=PAGESETUP-FLAGS + 0x0001=print-in-rows + 0x0002=landscape + 0x0004=uninitialized + 0x0008=black-and-white + 0x0010=draft-quality + 0x0020=print-notes + 0x0040=default-orientation + 0x0080=use-first-page + 0x0100=print-notes-at-end + 0x0600=uint8,dec,print-errors,PAGESETUP-PRINTERRORS +end + +shortlist=PAGESETUP-PRINTERRORS,0,displayed,none,as-dashes,as-na + +unitconverter=PAGESETUP-DPI,1,dpi + +# PANE ----------------------------------------------------------------------- + +shortlist=PANE-ID,0,bottom-right,top-right,bottom-left,top-left + +flagslist=PANE-FLAGS + 0x01=frozen + 0x02=remove-split-with-freeze +end + +# PHONETICPR ----------------------------------------------------------------- + +shortlist=PHONETICPR-TYPE,0,halfwidth-katakana,fullwidth-katakana,hiragana,no-conversion +shortlist=PHONETICPR-ALIGNMENT,0,no-control,left,center,distributed + +# PRINTOPTIONS --------------------------------------------------------------- + +flagslist=PRINTOPTIONS-FLAGS + 0x0001=horizontal-centered + 0x0002=vertical-centered + 0x0004=print-headings + 0x0008=print-gridlines + 0x0010=gridlines-set +end + +# ROW ------------------------------------------------------------------------ + +combilist=ROW-FLAGS + 0x0001=thick-top + 0x0002=thick-bottom + 0x0700=uint8,dec,outline-level + 0x0800=outline-collapsed + 0x1000=hidden + 0x2000=custom-height + 0x4000=custom-format +end + +# SHEET ---------------------------------------------------------------------- + +shortlist=SHEET-STATE,0,visible,hidden,very-hidden + +# SHEETFORMATPR -------------------------------------------------------------- + +flagslist=SHEETFORMATPR-FLAGS + 0x0001=custom-row-height + 0x0002=rows-hidden +end + +# SHEETPR -------------------------------------------------------------------- + +flagslist=SHEETPR-FLAGS + 0x0001=show-autopagebreaks + 0x0020=outline-auto-style + 0x0040=row-symbols-below + 0x0080=column-symbols-right + 0x0100=fit-to-pages + 0x0400=show-outline-symbols +end + +# SHEETVIEW ------------------------------------------------------------------ + +flagslist=SHEETVIEW-FLAGS + 0x0001=window-protected + 0x0002=show-formulas + 0x0004=show-gridlines + 0x0008=show-headings + 0x0010=show-zeros + 0x0020=right-to-left + 0x0040=selected + 0x0080=show-ruler + 0x0100=show-outline-symbols + 0x0200=default-gridcolor + 0x0400=show-whitespace +end + +shortlist=SHEETVIEW-TYPE,0,normal,pagebreak-preview,page-layout + +# TABLE ---------------------------------------------------------------------- + +shortlist=TABLE-TYPE,0,worksheet,,,query-table + +flagslist=TABLE-FLAGS + 0x00000001=totals-row-shown + 0x00000002=published + 0x00000004=insert-row + 0x00000008=insert-row-shift +end + +# TABLESTYLEINFO ------------------------------------------------------------- + +flagslist=TABLESTYLEINFO-FLAGS + 0x0001=show-first-column + 0x0002=show-last-column + 0x0004=show-row-stripes + 0x0008=show-column-stripes +end + +# VOLTYPE -------------------------------------------------------------------- + +shortlist=VOLTYPE-TYPE,0,realtime-data,olap-functions + +# WORKBBOKPR ----------------------------------------------------------------- + +combilist=WORKBBOKPR-FLAGS + 0x00000001=date-1904 + 0x00000004=hide-border-unsel-tables + 0x00000008=filter-privacy + 0x00000010=prompted-solutions + 0x00000020=show-ink-annotation + 0x00000040=backup-file + 0x00000080=strip-extlink-values + 0x00000300=uint8,dec,update-links,WORKBBOKPR-UPDATELINKS + 0x00000400=hide-pivot-fieldlist + 0x00000800=publish-items + 0x00001000=check-compatibility + 0x00006000=uint8,dec,show-objects,WORKBBOKPR-SHOWOBJECTS + 0x00008000=show-pivotchart-filter + 0x00010000=autocompress-pic +end + +shortlist=WORKBBOKPR-UPDATELINKS,0,ask-user,never,always +shortlist=WORKBBOKPR-SHOWOBJECTS,0,show,placeholder,hide + +# WORKBOOKVIEW --------------------------------------------------------------- + +flagslist=WORKBOOKVIEW-FLAGS + 0x01=hidden + 0x02=minimized + 0x08=show-horizontal-scroll + 0x10=show-vertical-scroll + 0x20=show-tabbar + 0x40=autofilter-date-grouping +end + +# XF ------------------------------------------------------------------------- + +shortlist=XF-HORALIGN,0,general,left,center,right,fill,block,center-across-sel,distribute +shortlist=XF-VERALIGN,0,top,center,bottom,justify,distribute +shortlist=XF-TEXTDIRECTION,0,context,left-to-right,right-to-left + +combilist=XF-ALIGNMENT + 0x000000FF=uint8,dec,rotation,TEXTROTATION + 0x0000FF00=uint8,dec,indent + 0x00070000=uint8,dec,hor-align,XF-HORALIGN + 0x00380000=uint8,dec,ver-align,XF-VERALIGN + 0x00400000=text-wrap + 0x00800000=justify-lastline + 0x01000000=shrink-to-fit + 0x0C000000=uint8,dec,text-dir,XF-TEXTDIRECTION + 0x10000000=locked + 0x20000000=formula-hidden + 0x80000000=quote-prefix +end + +flagslist=XF-USEDFLAGS + 0x0001=format + 0x0002=font + 0x0004=alignment + 0x0008=border + 0x0010=fill + 0x0020=protection +end + +# ============================================================================ + diff --git a/oox/source/helper/attributelist.cxx b/oox/source/helper/attributelist.cxx new file mode 100644 index 000000000000..499e27e0751e --- /dev/null +++ b/oox/source/helper/attributelist.cxx @@ -0,0 +1,111 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: attributelist.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:59 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/helper/attributelist.hxx" +#include + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::xml::sax::XFastAttributeList; + +namespace oox { + +// ============================================================================ + +AttributeList::AttributeList( const Reference< XFastAttributeList >& rxAttribs ) : + mxAttribs( rxAttribs ) +{ + OSL_ENSURE( mxAttribs.is(), "AttributeList::AttributeList - missing attribute list interface" ); +} + +bool AttributeList::hasAttribute( sal_Int32 nElement ) const +{ + return mxAttribs->hasAttribute( nElement ); +} + +sal_Int32 AttributeList::getToken( sal_Int32 nElement, sal_Int32 nDefault ) const +{ + return mxAttribs->getOptionalValueToken( nElement, nDefault ); +} + +OUString AttributeList::getString( sal_Int32 nElement ) const +{ + return mxAttribs->getOptionalValue( nElement ); +} + +double AttributeList::getDouble( sal_Int32 nElement, double fDefault ) const +{ + OUString aValue = getString( nElement ); + return (aValue.getLength() == 0) ? fDefault : aValue.toDouble(); +} + +sal_Int32 AttributeList::getInteger( sal_Int32 nElement, sal_Int32 nDefault ) const +{ + OUString aValue = getString( nElement ); + return (aValue.getLength() == 0) ? nDefault : aValue.toInt32(); +} + +sal_uInt32 AttributeList::getUnsignedInteger( sal_Int32 nElement, sal_uInt32 nDefault ) const +{ + OUString aValue = getString( nElement ); + if( aValue.getLength() == 0 ) + return nDefault; + sal_Int64 nValue = aValue.toInt64(); + return static_cast< sal_uInt32 >( ((nValue < 0) || (nValue > SAL_MAX_UINT32)) ? 0 : nValue ); +} + +sal_Int32 AttributeList::getHex( sal_Int32 nElement, sal_Int32 nDefault ) const +{ + OUString aValue = getString( nElement ); + return (aValue.getLength() == 0) ? nDefault : aValue.toInt32( 16 ); +} + +bool AttributeList::getBool( sal_Int32 nElement, bool bDefault ) const +{ + // boolean attributes may be "true", "false", "on", "off", "1", or "0" + switch( getToken( nElement ) ) + { + case XML_true: return true; + case XML_on: return true; + case XML_false: return false; + case XML_off: return false; + } + return getInteger( nElement, bDefault ? 1 : 0 ) != 0; +} + +// ============================================================================ + +} // namespace oox + diff --git a/oox/source/helper/binaryinputstream.cxx b/oox/source/helper/binaryinputstream.cxx new file mode 100644 index 000000000000..d8eaae3ac163 --- /dev/null +++ b/oox/source/helper/binaryinputstream.cxx @@ -0,0 +1,113 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: binaryinputstream.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:59 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/helper/binaryinputstream.hxx" +#include +#include + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::io::XInputStream; + +namespace oox { + +// ============================================================================ + +BinaryInputStream::BinaryInputStream( const Reference< XInputStream >& rxInStrm, bool bAutoClose ) : + BinaryStreamBase( rxInStrm ), + mxInStrm( rxInStrm ), + mbAutoClose( bAutoClose ) +{ +} + +BinaryInputStream::~BinaryInputStream() +{ + if( mbAutoClose ) + close(); +} + +void BinaryInputStream::skip( sal_Int32 nBytes ) +{ + try + { + OSL_ENSURE( mxInStrm.is(), "BinaryInputStream::skip - invalid call" ); + mxInStrm->skipBytes( nBytes ); + } + catch( Exception& ) + { + OSL_ENSURE( false, "BinaryInputStream::skip - exception caught" ); + } +} + +sal_Int32 BinaryInputStream::read( Sequence< sal_Int8 >& orBuffer, sal_Int32 nBytes ) +{ + sal_Int32 nRet = 0; + try + { + OSL_ENSURE( mxInStrm.is(), "BinaryInputStream::read - invalid call" ); + nRet = mxInStrm->readBytes( orBuffer, nBytes ); + } + catch( Exception& ) + { + OSL_ENSURE( false, "BinaryInputStream::read - stream read error" ); + } + return nRet; +} + +sal_Int32 BinaryInputStream::read( void* opBuffer, sal_Int32 nBytes ) +{ + sal_Int32 nRet = read( maBuffer, nBytes ); + if( nRet > 0 ) + memcpy( opBuffer, maBuffer.getConstArray(), static_cast< size_t >( nRet ) ); + return nRet; +} + +void BinaryInputStream::close() +{ + if( mxInStrm.is() ) try + { + mxInStrm->closeInput(); + } + catch( Exception& ) + { + OSL_ENSURE( false, "BinaryInputStream::close - closing input stream failed" ); + } +} + +// ============================================================================ + +} // namespace oox + diff --git a/oox/source/helper/binaryoutputstream.cxx b/oox/source/helper/binaryoutputstream.cxx new file mode 100644 index 000000000000..c6e4bb2c9ad5 --- /dev/null +++ b/oox/source/helper/binaryoutputstream.cxx @@ -0,0 +1,121 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: binaryoutputstream.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:59 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/helper/binaryoutputstream.hxx" +#include +#include +#include "oox/helper/binaryinputstream.hxx" + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::io::XOutputStream; + +namespace oox { + +// ============================================================================ + +BinaryOutputStream::BinaryOutputStream( const Reference< XOutputStream >& rxOutStrm, bool bAutoClose ) : + BinaryStreamBase( rxOutStrm ), + mxOutStrm( rxOutStrm ), + mbAutoClose( bAutoClose ) +{ +} + +BinaryOutputStream::~BinaryOutputStream() +{ + if( mbAutoClose ) + close(); +} + +void BinaryOutputStream::write( const Sequence< sal_Int8 >& rBuffer ) +{ + try + { + OSL_ENSURE( mxOutStrm.is(), "BinaryOutputStream::write - invalid call" ); + mxOutStrm->writeBytes( rBuffer ); + } + catch( Exception& ) + { + OSL_ENSURE( false, "BinaryOutputStream::write - stream read error" ); + } +} + +void BinaryOutputStream::write( const void* pBuffer, sal_Int32 nBytes ) +{ + if( nBytes > 0 ) + { + maBuffer.realloc( nBytes ); + memcpy( maBuffer.getArray(), pBuffer, static_cast< size_t >( nBytes ) ); + write( maBuffer ); + } +} + +void BinaryOutputStream::copy( BinaryInputStream& rInStrm, sal_Int64 nBytes ) +{ + if( rInStrm.is() && (nBytes > 0) ) + { + sal_Int32 nBufferSize = getLimitedValue< sal_Int32, sal_Int64 >( nBytes, 0, 0x8000 ); + Sequence< sal_Int8 > aBuffer( nBufferSize ); + while( nBytes > 0 ) + { + sal_Int32 nReadSize = getLimitedValue< sal_Int32, sal_Int64 >( nBytes, 0, nBufferSize ); + sal_Int32 nBytesRead = rInStrm.read( aBuffer, nReadSize ); + write( aBuffer ); + if( nReadSize == nBytesRead ) + nBytes -= nReadSize; + else + nBytes = 0; + } + } +} + +void BinaryOutputStream::close() +{ + if( mxOutStrm.is() ) try + { + mxOutStrm->flush(); + mxOutStrm->closeOutput(); + } + catch( Exception& ) + { + OSL_ENSURE( false, "BinaryOutputStream::close - closing output stream failed" ); + } +} + +// ============================================================================ + +} // namespace oox + diff --git a/oox/source/helper/binarystreambase.cxx b/oox/source/helper/binarystreambase.cxx new file mode 100644 index 000000000000..4eb0bf45f645 --- /dev/null +++ b/oox/source/helper/binarystreambase.cxx @@ -0,0 +1,91 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: binarystreambase.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:59 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/helper/binarystreambase.hxx" +#include + +using ::com::sun::star::uno::Exception; + +namespace oox { + +// ============================================================================ + +BinaryStreamBase::~BinaryStreamBase() +{ +} + +sal_Int64 BinaryStreamBase::getLength() const +{ + try + { + return mxSeekable.is() ? mxSeekable->getLength() : -1; + } + catch( Exception& ) + { + OSL_ENSURE( false, "BinaryStreamBase::getLength - exception caught" ); + } + return -1; +} + +sal_Int64 BinaryStreamBase::tell() const +{ + try + { + return mxSeekable.is() ? mxSeekable->getPosition() : -1; + } + catch( Exception& ) + { + OSL_ENSURE( false, "BinaryStreamBase::tell - exception caught" ); + } + return -1; +} + +void BinaryStreamBase::seek( sal_Int64 nPos ) +{ + try + { + if( mxSeekable.is() ) + mxSeekable->seek( nPos ); + } + catch( Exception& ) + { + OSL_ENSURE( false, "BinaryStreamBase::seek - exception caught" ); + } +} + +// ============================================================================ + +} // namespace oox + diff --git a/oox/source/helper/containerhelper.cxx b/oox/source/helper/containerhelper.cxx new file mode 100644 index 000000000000..bb45b86ea561 --- /dev/null +++ b/oox/source/helper/containerhelper.cxx @@ -0,0 +1,173 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: containerhelper.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:59 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/helper/containerhelper.hxx" +#include +#include +#include +#include +#include +#include "oox/helper/helper.hxx" + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::container::XIndexContainer; +using ::com::sun::star::container::XNameAccess; +using ::com::sun::star::container::XNameContainer; + +namespace oox { + +// ============================================================================ + +Reference< XIndexContainer > ContainerHelper::createIndexContainer() +{ + Reference< XIndexContainer > xContainer; + try + { + Reference< XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + xContainer.set( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.document.IndexedPropertyValues" ) ), UNO_QUERY_THROW ); + } + catch( Exception& ) + { + } + OSL_ENSURE( xContainer.is(), "ContainerHelper::createIndexContainer - cannot create container" ); + return xContainer; +} + +bool ContainerHelper::insertByIndex( + const Reference< XIndexContainer >& rxIndexContainer, + sal_Int32 nIndex, const Any& rObject ) +{ + OSL_ENSURE( rxIndexContainer.is(), "ContainerHelper::insertByIndex - missing XIndexContainer interface" ); + bool bRet = false; + try + { + rxIndexContainer->insertByIndex( nIndex, rObject ); + bRet = true; + } + catch( Exception& ) + { + } + OSL_ENSURE( bRet, "ContainerHelper::insertByIndex - cannot insert object" ); + return bRet; +} + +Reference< XNameContainer > ContainerHelper::createNameContainer() +{ + Reference< XNameContainer > xContainer; + try + { + Reference< XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + xContainer.set( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.document.NamedPropertyValues" ) ), UNO_QUERY_THROW ); + } + catch( Exception& ) + { + } + OSL_ENSURE( xContainer.is(), "ContainerHelper::createNameContainer - cannot create container" ); + return xContainer; +} + +OUString ContainerHelper::getUnusedName( + const Reference< XNameAccess >& rxNameAccess, const OUString& rSuggestedName, + sal_Unicode cSeparator, sal_Int32 nFirstIndexToAppend ) +{ + OSL_ENSURE( rxNameAccess.is(), "ContainerHelper::getUnusedName - missing XNameAccess interface" ); + + OUString aNewName = rSuggestedName; + sal_Int32 nIndex = nFirstIndexToAppend; + while( rxNameAccess->hasByName( aNewName ) ) + aNewName = OUStringBuffer( rSuggestedName ).append( cSeparator ).append( nIndex++ ).makeStringAndClear(); + return aNewName; +} + +bool ContainerHelper::insertByName( + const Reference< XNameContainer >& rxNameContainer, + const OUString& rName, const Any& rObject ) +{ + OSL_ENSURE( rxNameContainer.is(), "ContainerHelper::insertByName - missing XNameContainer interface" ); + bool bRet = false; + try + { + rxNameContainer->insertByName( rName, rObject ); + bRet = true; + } + catch( Exception& ) + { + } + OSL_ENSURE( bRet, "ContainerHelper::insertByName - cannot insert object" ); + return bRet; +} + +OUString ContainerHelper::insertByUnusedName( + const Reference< XNameContainer >& rxNameContainer, const Any& rObject, + const OUString& rSuggestedName, sal_Unicode cSeparator, bool bRenameOldExisting ) +{ + OSL_ENSURE( rxNameContainer.is(), "ContainerHelper::insertByUnusedName - missing XNameContainer interface" ); + + // find an unused name + Reference< XNameAccess > xNameAccess( rxNameContainer, UNO_QUERY ); + OUString aNewName = getUnusedName( xNameAccess, rSuggestedName, cSeparator ); + + // rename existing object + if( bRenameOldExisting && rxNameContainer->hasByName( rSuggestedName ) ) + { + try + { + Any aOldObject = rxNameContainer->getByName( rSuggestedName ); + rxNameContainer->removeByName( rSuggestedName ); + rxNameContainer->insertByName( aNewName, aOldObject ); + aNewName = rSuggestedName; + } + catch( Exception& ) + { + OSL_ENSURE( false, "ContainerHelper::insertByUnusedName - cannot rename old object" ); + } + } + + // insert the new object and return its resulting name + insertByName( rxNameContainer, aNewName, rObject ); + return aNewName; +} + +// ============================================================================ + +} // namespace oox + diff --git a/oox/source/helper/makefile.mk b/oox/source/helper/makefile.mk new file mode 100644 index 000000000000..d35a5ca1ef45 --- /dev/null +++ b/oox/source/helper/makefile.mk @@ -0,0 +1,68 @@ +#************************************************************************* +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.2 $ +# +# last change: $Author: rt $ $Date: 2008-01-17 08:05:59 $ +# +# The Contents of this file are made available subject to +# the terms of GNU Lesser General Public License Version 2.1. +# +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2005 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=oox +TARGET=helper +AUTOSEG=true + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/attributelist.obj \ + $(SLO)$/binaryinputstream.obj \ + $(SLO)$/binaryoutputstream.obj \ + $(SLO)$/binarystreambase.obj \ + $(SLO)$/containerhelper.obj \ + $(SLO)$/olestorage.obj \ + $(SLO)$/progressbar.obj \ + $(SLO)$/propertymap.obj \ + $(SLO)$/propertysequence.obj \ + $(SLO)$/propertyset.obj \ + $(SLO)$/recordinputstream.obj \ + $(SLO)$/storagebase.obj \ + $(SLO)$/zipstorage.obj + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk diff --git a/oox/source/helper/olestorage.cxx b/oox/source/helper/olestorage.cxx new file mode 100644 index 000000000000..f68a9647697c --- /dev/null +++ b/oox/source/helper/olestorage.cxx @@ -0,0 +1,186 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: olestorage.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:59 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/helper/olestorage.hxx" +#include +#include +#include +#include +#include +#include "oox/helper/helper.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::container::XNameAccess; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::beans::PropertyValue; +using ::com::sun::star::embed::XStorage; +using ::com::sun::star::io::XInputStream; +using ::com::sun::star::io::XOutputStream; + +namespace oox { + +// ============================================================================ + +OleStorage::OleStorage( + const Reference< XMultiServiceFactory >& rxFactory, + const Reference< XInputStream >& rxInStream, + bool bBaseStreamAccess ) : + StorageBase( rxInStream, bBaseStreamAccess ) +{ + OSL_ENSURE( rxFactory.is(), "OleStorage::OleStorage - missing service factory" ); + // create base storage object + Sequence< Any > aArgs( 2 ); + aArgs[ 0 ] <<= rxInStream; + aArgs[ 1 ] <<= true; // true = do not create a copy of the input stream + mxStorage.set( rxFactory->createInstanceWithArguments( + CREATE_OUSTRING( "com.sun.star.embed.OLESimpleStorage" ), aArgs ), UNO_QUERY ); + mxElements.set( mxStorage, UNO_QUERY ); +} + +OleStorage::OleStorage( + const Reference< XMultiServiceFactory >& rxFactory, + const Reference< XOutputStream >& rxOutStream, + bool bBaseStreamAccess ) : + StorageBase( rxOutStream, bBaseStreamAccess ) +{ + OSL_ENSURE( rxFactory.is(), "OleStorage::OleStorage - missing service factory" ); + (void)rxFactory; // prevent compiler warning + OSL_ENSURE( false, "OleStorage::OleStorage - not implemented" ); + mxElements.set( mxStorage, UNO_QUERY ); +} + +OleStorage::OleStorage( const OleStorage& rParentStorage, const Reference< XNameAccess >& rxElementsAccess, const OUString& rElementName ) : + StorageBase( rParentStorage, rElementName ), + mxStorage( rParentStorage.mxStorage ), + mxElements( rxElementsAccess ) +{ + OSL_ENSURE( mxElements.is(), "OleStorage::OleStorage - missing elements access" ); +} + +OleStorage::~OleStorage() +{ +} + +// StorageBase interface ------------------------------------------------------ + +bool OleStorage::implIsStorage() const +{ + if( mxStorage.is() && mxElements.is() ) try + { + /* If this is not a storage, hasElements() throws an exception. But we + do not return the result of hasElements(), because an empty storage + is a valid storage too. */ + mxElements->hasElements(); + return true; + } + catch( Exception& ) + { + } + return false; +} + +Reference< XStorage > OleStorage::implGetXStorage() const +{ + OSL_ENSURE( false, "OleStorage::getXStorage - not implemented" ); + return Reference< XStorage >(); +} + +void OleStorage::implGetElementNames( ::std::vector< OUString >& orElementNames ) const +{ + Sequence< OUString > aNames; + if( mxStorage.is() ) try + { + aNames = mxElements->getElementNames(); + if( aNames.getLength() > 0 ) + orElementNames.insert( orElementNames.end(), aNames.getConstArray(), aNames.getConstArray() + aNames.getLength() ); + } + catch( Exception& ) + { + } +} + +StorageRef OleStorage::implOpenSubStorage( const OUString& rElementName, bool bCreate ) +{ + OSL_ENSURE( !bCreate, "OleStorage::implOpenSubStorage - creating substorages not implemented" ); + (void)bCreate; // prevent compiler warning + StorageRef xSubStorage; + if( mxElements.is() ) try + { + Reference< XNameAccess > xSubElements( mxElements->getByName( rElementName ), UNO_QUERY_THROW ); + xSubStorage.reset( new OleStorage( *this, xSubElements, rElementName ) ); + } + catch( Exception& ) + { + } + return xSubStorage; +} + +Reference< XInputStream > OleStorage::implOpenInputStream( const OUString& rElementName ) +{ + Reference< XInputStream > xInStream; + if( mxElements.is() ) try + { + xInStream.set( mxElements->getByName( rElementName ), UNO_QUERY ); + } + catch( Exception& ) + { + } + return xInStream; +} + +Reference< XOutputStream > OleStorage::implOpenOutputStream( const OUString& rElementName ) +{ + Reference< XOutputStream > xOutStream; + if( mxElements.is() && (rElementName.getLength() > 0) ) try + { + (void)rElementName; // prevent compiler warning + OSL_ENSURE( false, "OleStorage::implOpenOutputStream - not implemented" ); + } + catch( Exception& ) + { + } + return xOutStream; +} + +// ============================================================================ + +} // namespace oox + diff --git a/oox/source/helper/progressbar.cxx b/oox/source/helper/progressbar.cxx new file mode 100644 index 000000000000..b811eca2b3e9 --- /dev/null +++ b/oox/source/helper/progressbar.cxx @@ -0,0 +1,193 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: progressbar.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:59 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/helper/progressbar.hxx" +#include +#include "oox/helper/helper.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::task::XStatusIndicator; + +namespace oox { + +// ============================================================================ + +namespace { + +const sal_Int32 PROGRESS_RANGE = 1000000; + +} // namespace + +// ============================================================================ + +IProgressBar::~IProgressBar() +{ +} + +// ---------------------------------------------------------------------------- + +ISegmentProgressBar::~ISegmentProgressBar() +{ +} + +// ============================================================================ +// ============================================================================ + +ProgressBar::ProgressBar( const Reference< XStatusIndicator >& rxIndicator, const OUString& rText ) : + mxIndicator( rxIndicator ), + mfPosition( 0 ) +{ + if( mxIndicator.is() ) + mxIndicator->start( rText, PROGRESS_RANGE ); +} + +ProgressBar::~ProgressBar() +{ + if( mxIndicator.is() ) + mxIndicator->end(); +} + +double ProgressBar::getPosition() const +{ + return mfPosition; +} + +void ProgressBar::setPosition( double fPosition ) +{ + OSL_ENSURE( (mfPosition <= fPosition) && (fPosition <= 1.0), "ProgressBar::setPosition - invalid position" ); + mfPosition = getLimitedValue< double >( fPosition, mfPosition, 1.0 ); + if( mxIndicator.is() ) + mxIndicator->setValue( static_cast< sal_Int32 >( mfPosition * PROGRESS_RANGE ) ); +} + +// ============================================================================ + +namespace prv { + +class SubSegment : public ISegmentProgressBar +{ +public: + explicit SubSegment( IProgressBar& rParentProgress, double fStartPos, double fLength ); + + virtual double getPosition() const; + virtual void setPosition( double fPosition ); + + virtual double getFreeLength() const; + virtual ISegmentProgressBarRef createSegment( double fLength ); + +private: + IProgressBar& mrParentProgress; + double mfStartPos; + double mfLength; + double mfPosition; + double mfFreeStart; +}; + +// ---------------------------------------------------------------------------- + +SubSegment::SubSegment( IProgressBar& rParentProgress, double fStartPos, double fLength ) : + mrParentProgress( rParentProgress ), + mfStartPos( fStartPos ), + mfLength( fLength ), + mfPosition( 0.0 ), + mfFreeStart( 0.0 ) +{ +} + +double SubSegment::getPosition() const +{ + return mfPosition; +} + +void SubSegment::setPosition( double fPosition ) +{ + OSL_ENSURE( (mfPosition <= fPosition) && (fPosition <= 1.0), "SubSegment::setPosition - invalid position" ); + mfPosition = getLimitedValue< double >( fPosition, mfPosition, 1.0 ); + mrParentProgress.setPosition( mfStartPos + mfPosition * mfLength ); +} + +double SubSegment::getFreeLength() const +{ + return 1.0 - mfFreeStart; +} + +ISegmentProgressBarRef SubSegment::createSegment( double fLength ) +{ + OSL_ENSURE( (0.0 < fLength) && (fLength <= getFreeLength()), "SubSegment::createSegment - invalid length" ); + fLength = getLimitedValue< double >( fLength, 0.0, getFreeLength() ); + ISegmentProgressBarRef xSegment( new prv::SubSegment( *this, mfFreeStart, fLength ) ); + mfFreeStart += fLength; + return xSegment; +} + +} // namespace prv + +// ============================================================================ + +SegmentProgressBar::SegmentProgressBar( const Reference< XStatusIndicator >& rxIndicator, const OUString& rText ) : + maProgress( rxIndicator, rText ), + mfFreeStart( 0.0 ) +{ +} + +double SegmentProgressBar::getPosition() const +{ + return maProgress.getPosition(); +} + +void SegmentProgressBar::setPosition( double fPosition ) +{ + maProgress.setPosition( fPosition ); +} + +double SegmentProgressBar::getFreeLength() const +{ + return 1.0 - mfFreeStart; +} + +ISegmentProgressBarRef SegmentProgressBar::createSegment( double fLength ) +{ + OSL_ENSURE( (0.0 < fLength) && (fLength <= getFreeLength()), "SegmentProgressBar::createSegment - invalid length" ); + fLength = getLimitedValue< double >( fLength, 0.0, getFreeLength() ); + ISegmentProgressBarRef xSegment( new prv::SubSegment( maProgress, mfFreeStart, fLength ) ); + mfFreeStart += fLength; + return xSegment; +} + +// ============================================================================ + +} // namespace oox + diff --git a/oox/source/helper/propertymap.cxx b/oox/source/helper/propertymap.cxx new file mode 100644 index 000000000000..d6c8dd0b1cec --- /dev/null +++ b/oox/source/helper/propertymap.cxx @@ -0,0 +1,286 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: propertymap.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:59 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/helper/propertymap.hxx" + +#include +#include +#include +#include + +using ::rtl::OUString; +using ::osl::MutexGuard; +using ::osl::Mutex; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; + +namespace oox { + +bool PropertyMap::hasProperty( const ::rtl::OUString& rName ) const +{ + return find( rName ) != end(); +} + +const Any* PropertyMap::getPropertyValue( const ::rtl::OUString& rName ) const +{ + PropertyMapBase::const_iterator aIter( find( rName ) ); + return aIter != end() ? &((*aIter).second) : NULL; +} + +void PropertyMap::makeSequence( Sequence< NamedValue >& rSequence ) const +{ + rSequence.realloc( size() ); + NamedValue* pValues = rSequence.getArray(); + const_iterator aIter( begin() ); + const_iterator aEnd( end() ); + + for( ; aIter != aEnd; aIter++, pValues++ ) + { + pValues->Name = (*aIter).first; + pValues->Value = (*aIter).second; + } +} + + +void PropertyMap::makeSequence( Sequence< PropertyValue >& rSequence ) const +{ + rSequence.realloc( size() ); + PropertyValue* pValues = rSequence.getArray(); + const_iterator aIter( begin() ); + const_iterator aEnd( end() ); + + for( ; aIter != aEnd; aIter++, pValues++ ) + { + pValues->Name = (*aIter).first; + pValues->Value = (*aIter).second; + pValues->State = PropertyState_DIRECT_VALUE; + } +} + +void PropertyMap::makeSequence( Sequence< OUString >& rNames, Sequence< Any >& rValues ) const +{ + rNames.realloc( size() ); + rValues.realloc( size() ); + OUString* pNames = rNames.getArray(); + Any* pValues = rValues.getArray(); + const_iterator aIter( begin() ); + const_iterator aEnd( end() ); + + for( ; aIter != aEnd; aIter++, pNames++, pValues++ ) + { + *pNames = (*aIter).first; + *pValues = (*aIter).second; + } +} + + +void PropertyMap::dump_debug(const char *pMessage) +{ + const_iterator aIter( begin() ); + const_iterator aEnd( end() ); + + if( pMessage != NULL) + { + OSL_TRACE("OOX: %s", pMessage); + } + + if(aIter == aEnd) + { + OSL_TRACE("OOX: Properties empty"); + return; + } + + OSL_TRACE("OOX: Properties"); + + for( ; aIter != aEnd; aIter++ ) + { + std::string value; + const Any & any = (*aIter).second; + try { + char buffer[256]; + if(!any.hasValue() ) + { + value = "*empty*"; + } + else if(any.has() ) + { + OUString aStr; + any >>= aStr; + value = OUStringToOString( aStr, RTL_TEXTENCODING_ASCII_US ).getStr(); + } + else if(any.has()) + { + sal_Int16 v = 0; + any >>= v; + sprintf(buffer, "%d", (int)v); + value = buffer; + } + else if(any.has()) + { + sal_Int32 v = 0; + any >>= v; + sprintf(buffer, "%d", (int)v); + value = buffer; + } + else if(any.has()) + { + sal_Bool v = sal_False; + any >>= v; + sprintf(buffer, "%d", (int)v); + value = buffer; + } + else + { + value = "contains a: "; + value += OUStringToOString(any.getValueTypeName(), RTL_TEXTENCODING_ASCII_US ).getStr(); + } + } + catch( ... ) + { + value = "unable to convert from "; + value += OUStringToOString(any.getValueTypeName(), RTL_TEXTENCODING_ASCII_US ).getStr(); + } + OSL_TRACE("OOX: -> %s = %s", OUStringToOString( (*aIter).first, RTL_TEXTENCODING_ASCII_US ).getStr(), + value.c_str()); + } +} + +/** this class implements a generic XPropertySet + Properties of all names and types can be set and later retrieved + TODO: move this to comphelper or better find an existing implementation */ +class GenericPropertySet : public ::cppu::WeakImplHelper2< XPropertySet, XPropertySetInfo >, + private PropertyMapBase, + private Mutex +{ +public: + GenericPropertySet(); + GenericPropertySet( const PropertyMapBase& rProperties ); + + // XPropertySet + virtual Reference< XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw (RuntimeException); + virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const Any& aValue ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException); + virtual Any SAL_CALL getPropertyValue( const OUString& PropertyName ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException); + virtual void SAL_CALL addPropertyChangeListener( const OUString& aPropertyName, const Reference< XPropertyChangeListener >& xListener ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException); + virtual void SAL_CALL removePropertyChangeListener( const OUString& aPropertyName, const Reference< XPropertyChangeListener >& aListener ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException); + virtual void SAL_CALL addVetoableChangeListener( const OUString& PropertyName, const Reference< XVetoableChangeListener >& aListener ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException); + virtual void SAL_CALL removeVetoableChangeListener( const OUString& PropertyName, const Reference< XVetoableChangeListener >& aListener ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException); + + // XPropertySetInfo + virtual Sequence< Property > SAL_CALL getProperties( ) throw (RuntimeException); + virtual Property SAL_CALL getPropertyByName( const OUString& aName ) throw (UnknownPropertyException, RuntimeException); + virtual ::sal_Bool SAL_CALL hasPropertyByName( const OUString& Name ) throw (RuntimeException); +}; + +GenericPropertySet::GenericPropertySet() +{ +} + +GenericPropertySet::GenericPropertySet( const PropertyMapBase& rProperties ) +: PropertyMapBase( rProperties ) +{ +} + +Reference< XPropertySetInfo > SAL_CALL GenericPropertySet::getPropertySetInfo() throw (RuntimeException) +{ + return this; +} + +void SAL_CALL GenericPropertySet::setPropertyValue( const OUString& aPropertyName, const Any& aValue ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) +{ + MutexGuard aGuard( *this ); + (*this)[ aPropertyName ] = aValue; +} + +Any SAL_CALL GenericPropertySet::getPropertyValue( const OUString& PropertyName ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + iterator aIter( find( PropertyName ) ); + if( aIter == end() ) + throw UnknownPropertyException(); + + return (*aIter).second; +} + +void SAL_CALL GenericPropertySet::addPropertyChangeListener( const OUString& , const Reference< XPropertyChangeListener >& ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException) {} +void SAL_CALL GenericPropertySet::removePropertyChangeListener( const OUString& , const Reference< XPropertyChangeListener >& ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException) {} +void SAL_CALL GenericPropertySet::addVetoableChangeListener( const OUString& , const Reference< XVetoableChangeListener >& ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException) {} +void SAL_CALL GenericPropertySet::removeVetoableChangeListener( const OUString& , const Reference< XVetoableChangeListener >& ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException) {} + +// XPropertySetInfo +Sequence< Property > SAL_CALL GenericPropertySet::getProperties( ) throw (RuntimeException) +{ + Sequence< Property > aRet( size() ); + Property* pProperty = aRet.getArray(); + + for( iterator aIter = begin(); aIter != end(); aIter++, pProperty++ ) + { + pProperty->Name = (*aIter).first; + pProperty->Handle = 0; + pProperty->Type = (*aIter).second.getValueType(); + pProperty->Attributes = 0; + } + + return aRet; +} + +Property SAL_CALL GenericPropertySet::getPropertyByName( const OUString& aName ) throw (UnknownPropertyException, RuntimeException) +{ + iterator aIter( find( aName ) ); + if( aIter == end() ) + throw UnknownPropertyException(); + + Property aProperty; + aProperty.Name = (*aIter).first; + aProperty.Handle = 0; + aProperty.Type = (*aIter).second.getValueType(); + aProperty.Attributes = 0; + + return aProperty; +} + +::sal_Bool SAL_CALL GenericPropertySet::hasPropertyByName( const OUString& Name ) throw (RuntimeException) +{ + return find( Name ) != end(); +} + + +Reference< XPropertySet > PropertyMap::makePropertySet() const +{ + Reference< XPropertySet > xSet( new GenericPropertySet(*this) ); + return xSet; +} + +} + diff --git a/oox/source/helper/propertysequence.cxx b/oox/source/helper/propertysequence.cxx new file mode 100644 index 000000000000..becf2549f757 --- /dev/null +++ b/oox/source/helper/propertysequence.cxx @@ -0,0 +1,164 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: propertysequence.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:59 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/helper/propertysequence.hxx" +#include "oox/helper/propertyset.hxx" +#include +#include +#include + +using ::rtl::OUString; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::beans::PropertyValue; + +namespace oox { + +// ============================================================================ + +PropertySequence::PropertySequence( const sal_Char* const* ppcPropNames, + const sal_Char* const* ppcPropNames2, const sal_Char* const* ppcPropNames3 ) : + mnNextIndex( 0 ) +{ + OSL_ENSURE( ppcPropNames, "PropertySequence::PropertySequence - no strings found" ); + + // create OUStrings from ASCII property names + typedef ::std::pair< OUString, size_t > IndexedOUString; + typedef ::std::vector< IndexedOUString > IndexedOUStringVec; + IndexedOUStringVec aPropNameVec; + size_t nVecIdx = 0; + while( *ppcPropNames ) + { + OUString aPropName = OUString::createFromAscii( *ppcPropNames++ ); + aPropNameVec.push_back( IndexedOUString( aPropName, nVecIdx++ ) ); + } + if( ppcPropNames2 ) while( *ppcPropNames2 ) + { + OUString aPropName = OUString::createFromAscii( *ppcPropNames2++ ); + aPropNameVec.push_back( IndexedOUString( aPropName, nVecIdx++ ) ); + } + if( ppcPropNames3 ) while( *ppcPropNames3 ) + { + OUString aPropName = OUString::createFromAscii( *ppcPropNames3++ ); + aPropNameVec.push_back( IndexedOUString( aPropName, nVecIdx++ ) ); + } + + // sorts the pairs, which will be sorted by first component (the property name) + ::std::sort( aPropNameVec.begin(), aPropNameVec.end() ); + + // resize member sequences + size_t nSize = aPropNameVec.size(); + maNameSeq.realloc( static_cast< sal_Int32 >( nSize ) ); + maValueSeq.realloc( static_cast< sal_Int32 >( nSize ) ); + maNameOrder.resize( nSize ); + + // fill the property name sequence and store original sort order + sal_Int32 nSeqIdx = 0; + for( IndexedOUStringVec::const_iterator aIt = aPropNameVec.begin(), + aEnd = aPropNameVec.end(); aIt != aEnd; ++aIt, ++nSeqIdx ) + { + maNameSeq[ nSeqIdx ] = aIt->first; + maNameOrder[ aIt->second ] = nSeqIdx; + } +} + +void PropertySequence::clearAllAnys() +{ + for( sal_Int32 nIdx = 0, nLen = maValueSeq.getLength(); nIdx < nLen; ++nIdx ) + maValueSeq[ nIdx ].clear(); +} + +// read properties ------------------------------------------------------------ + +void PropertySequence::readFromPropertySet( const PropertySet& rPropSet ) +{ + rPropSet.getProperties( maValueSeq, maNameSeq ); + mnNextIndex = 0; +} + +bool PropertySequence::readValue( Any& rAny ) +{ + Any* pAny = getNextAny(); + if( pAny ) rAny = *pAny; + return pAny != 0; +} + +// write properties ----------------------------------------------------------- + +void PropertySequence::writeValue( const Any& rAny ) +{ + if( Any* pAny = getNextAny() ) + *pAny = rAny; +} + +void PropertySequence::writeToPropertySet( PropertySet& rPropSet ) +{ + OSL_ENSURE( mnNextIndex == maNameOrder.size(), "PropertySequence::writeToPropertySet - sequence not complete" ); + rPropSet.setProperties( maNameSeq, maValueSeq ); + mnNextIndex = 0; +} + +Sequence< PropertyValue > PropertySequence::createPropertySequence() +{ + OSL_ENSURE( mnNextIndex == maNameOrder.size(), "PropertySequence::createPropertySequence - sequence not complete" ); + Sequence< PropertyValue > aPropSeq( maNameSeq.getLength() ); + PropertyValue* pProp = aPropSeq.getArray(); + PropertyValue* pPropEnd = pProp + aPropSeq.getLength(); + const OUString* pName = maNameSeq.getConstArray(); + const Any* pValue = maValueSeq.getConstArray(); + for( ; pProp != pPropEnd; ++pProp, ++pName, ++pValue ) + { + pProp->Name = *pName; + pProp->Value = *pValue; + } + mnNextIndex = 0; + return aPropSeq; +} + +// private -------------------------------------------------------------------- + +Any* PropertySequence::getNextAny() +{ + OSL_ENSURE( mnNextIndex < maNameOrder.size(), "PropertySequence::getNextAny - sequence overflow" ); + Any* pAny = 0; + if( mnNextIndex < maNameOrder.size() ) + pAny = &maValueSeq[ maNameOrder[ mnNextIndex++ ] ]; + return pAny; +} + +// ============================================================================ + +} // namespace oox + diff --git a/oox/source/helper/propertyset.cxx b/oox/source/helper/propertyset.cxx new file mode 100644 index 000000000000..0b5af8269e6d --- /dev/null +++ b/oox/source/helper/propertyset.cxx @@ -0,0 +1,157 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: propertyset.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:59 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/helper/propertyset.hxx" +#include +#include + +using ::rtl::OUString; +using ::rtl::OStringBuffer; +using ::rtl::OUStringToOString; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::beans::XPropertySet; + +namespace oox { + +// ============================================================================ + +void PropertySet::set( const Reference< XPropertySet >& rxPropSet ) +{ + mxPropSet = rxPropSet; + mxMultiPropSet.set( mxPropSet, UNO_QUERY ); +} + +// Get properties ------------------------------------------------------------- + +bool PropertySet::getAnyProperty( Any& orValue, const OUString& rPropName ) const +{ + bool bHasValue = false; + try + { + if( mxPropSet.is() ) + { + orValue = mxPropSet->getPropertyValue( rPropName ); + bHasValue = true; + } + } + catch( Exception& ) + { + OSL_ENSURE( false, OStringBuffer( "PropertySet::getAnyProperty - cannot get property \"" ). + append( OUStringToOString( rPropName, RTL_TEXTENCODING_ASCII_US ) ).append( '"' ).getStr() ); + } + return bHasValue; +} + +bool PropertySet::getBoolProperty( const OUString& rPropName ) const +{ + Any aAny; + bool bValue = false; + return getAnyProperty( aAny, rPropName ) && (aAny >>= bValue) && bValue; +} + +void PropertySet::getProperties( Sequence< Any >& orValues, const Sequence< OUString >& rPropNames ) const +{ + try + { + if( mxMultiPropSet.is() ) // first try the XMultiPropertySet + { + orValues = mxMultiPropSet->getPropertyValues( rPropNames ); + } + else if( mxPropSet.is() ) + { + sal_Int32 nLen = rPropNames.getLength(); + const OUString* pPropName = rPropNames.getConstArray(); + const OUString* pPropNameEnd = pPropName + nLen; + orValues.realloc( nLen ); + Any* pValue = orValues.getArray(); + for( ; pPropName != pPropNameEnd; ++pPropName, ++pValue ) + *pValue = mxPropSet->getPropertyValue( *pPropName ); + } + } + catch( Exception& ) + { + OSL_ENSURE( false, "PropertySet::getProperties - cannot get all property values" ); + } +} + +// Set properties ------------------------------------------------------------- + +void PropertySet::setAnyProperty( const OUString& rPropName, const Any& rValue ) +{ + try + { + if( mxPropSet.is() ) + mxPropSet->setPropertyValue( rPropName, rValue ); + } + catch( Exception& ) + { + OSL_ENSURE( false, OStringBuffer( "PropertySet::setAnyProperty - cannot set property \"" ). + append( OUStringToOString( rPropName, RTL_TEXTENCODING_ASCII_US ) ).append( '"' ).getStr() ); + } +} + +void PropertySet::setProperties( const Sequence< OUString >& rPropNames, const Sequence< Any >& rValues ) +{ + OSL_ENSURE( rPropNames.getLength() == rValues.getLength(), + "PropertySet::setProperties - length of sequences different" ); + try + { + if( mxMultiPropSet.is() ) // first try the XMultiPropertySet + { + mxMultiPropSet->setPropertyValues( rPropNames, rValues ); + } + else if( mxPropSet.is() ) + { + const OUString* pPropName = rPropNames.getConstArray(); + const OUString* pPropNameEnd = pPropName + rPropNames.getLength(); + const Any* pValue = rValues.getConstArray(); + for( ; pPropName != pPropNameEnd; ++pPropName, ++pValue ) + mxPropSet->setPropertyValue( *pPropName, *pValue ); + } + } + catch( Exception& ) + { + OSL_ENSURE( false, "PropertySet::setAnyProperty - cannot set all property values" ); + } +} + +// ============================================================================ + +} // namespace oox + diff --git a/oox/source/helper/recordinputstream.cxx b/oox/source/helper/recordinputstream.cxx new file mode 100644 index 000000000000..66f414b36de5 --- /dev/null +++ b/oox/source/helper/recordinputstream.cxx @@ -0,0 +1,104 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: recordinputstream.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:59 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/helper/recordinputstream.hxx" +#include + +using ::rtl::OUString; + +namespace oox { + +// ============================================================================ + +RecordInputStream::RecordInputStream( const RecordDataSequence& rData ) : + maData( rData ), + mnRecSize( rData.getLength() ), + mnRecPos( 0 ), + mbValid( true ) +{ +} + +sal_Int32 RecordInputStream::read( void* opData, sal_Int32 nBytes ) +{ + sal_Int32 nReadSize = ::std::min( nBytes, getRecLeft() ); + OSL_ENSURE( !mbValid || (nReadSize == nBytes), "RecordInputStream::read - buffer overflow" ); + mbValid = nReadSize == nBytes; + if( mbValid && opData && (nReadSize > 0) ) + memcpy( opData, maData.getConstArray() + mnRecPos, nReadSize ); + mnRecPos += nReadSize; + return nReadSize; +} + +OUString RecordInputStream::readString( bool b32BitLen ) +{ + OUString aString; + sal_Int32 nCharCount = b32BitLen ? readValue< sal_Int32 >() : readValue< sal_Int16 >(); + // string length -1 is often used to indicate a missing string + OSL_ENSURE( !mbValid || (nCharCount >= -1), "RecordInputStream::readString - invalid string length" ); + if( mbValid && (nCharCount >= 0) ) + { + ::std::vector< sal_Unicode > aBuffer; + aBuffer.reserve( getLimitedValue< size_t, sal_Int32 >( nCharCount + 1, 0, 0xFFFF ) ); + for( sal_Int32 nCharIdx = 0; mbValid && (nCharIdx < nCharCount); ++nCharIdx ) + { + sal_uInt16 nChar; + readValue( nChar ); + aBuffer.push_back( static_cast< sal_Unicode >( nChar ) ); + } + aBuffer.push_back( 0 ); + aString = OUString( &aBuffer.front() ); + } + return aString; +} + +void RecordInputStream::seek( sal_Int32 nRecPos ) +{ + mnRecPos = getLimitedValue< sal_Int32, sal_Int32 >( nRecPos, 0, mnRecSize ); + OSL_ENSURE( !mbValid || (nRecPos == mnRecPos), "RecordInputStream::seek - invalid position" ); + mbValid = nRecPos == mnRecPos; +} + +void RecordInputStream::skip( sal_Int32 nBytes ) +{ + sal_Int32 nSkipSize = getLimitedValue< sal_Int32, sal_Int32 >( nBytes, 0, getRecLeft() ); + OSL_ENSURE( !mbValid || (nSkipSize == nBytes), "RecordInputStream::skip - buffer overflow" ); + mbValid = nSkipSize == nBytes; + mnRecPos += nSkipSize; +} + +// ============================================================================ + +} // namespace oox + diff --git a/oox/source/helper/storagebase.cxx b/oox/source/helper/storagebase.cxx new file mode 100644 index 000000000000..8fd7f1c25e80 --- /dev/null +++ b/oox/source/helper/storagebase.cxx @@ -0,0 +1,201 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: storagebase.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:59 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/helper/storagebase.hxx" +#include + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::embed::XStorage; +using ::com::sun::star::io::XInputStream; +using ::com::sun::star::io::XOutputStream; + +namespace oox { + +// ============================================================================ + +namespace { + +void lclSplitFirstElement( OUString& orElement, OUString& orRemainder, const OUString& rFullName ) +{ + sal_Int32 nSlashPos = rFullName.indexOf( '/' ); + if( (0 <= nSlashPos) && (nSlashPos < rFullName.getLength()) ) + { + orElement = rFullName.copy( 0, nSlashPos ); + orRemainder = rFullName.copy( nSlashPos + 1 ); + } + else + { + orElement = rFullName; + } +} + +} // namespace + +// ---------------------------------------------------------------------------- + +StorageBase::StorageBase( const Reference< XInputStream >& rxInStream, bool bBaseStreamAccess ) : + mxInStream( rxInStream ), + mpParentStorage( 0 ), + mbBaseStreamAccess( bBaseStreamAccess ) +{ + OSL_ENSURE( mxInStream.is(), "StorageBase::StorageBase - missing base input stream" ); +} + +StorageBase::StorageBase( const Reference< XOutputStream >& rxOutStream, bool bBaseStreamAccess ) : + mxOutStream( rxOutStream ), + mpParentStorage( 0 ), + mbBaseStreamAccess( bBaseStreamAccess ) +{ + OSL_ENSURE( mxOutStream.is(), "StorageBase::StorageBase - missing base output stream" ); +} + +StorageBase::StorageBase( const StorageBase& rParentStorage, const OUString& rStorageName ) : + maStorageName( rStorageName ), + mpParentStorage( &rParentStorage ), + mbBaseStreamAccess( false ) +{ +} + +StorageBase::~StorageBase() +{ +} + +bool StorageBase::isStorage() const +{ + return implIsStorage(); +} + +Reference< XStorage > StorageBase::getXStorage() const +{ + return implGetXStorage(); +} + +const OUString& StorageBase::getName() const +{ + return maStorageName; +} + +OUString StorageBase::getPath() const +{ + OUStringBuffer aBuffer; + if( mpParentStorage ) + aBuffer.append( mpParentStorage->getPath() ); + if( aBuffer.getLength() > 0 ) + aBuffer.append( sal_Unicode( '/' ) ); + aBuffer.append( maStorageName ); + return aBuffer.makeStringAndClear(); +} + +void StorageBase::getElementNames( ::std::vector< OUString >& orElementNames ) const +{ + orElementNames.clear(); + implGetElementNames( orElementNames ); +} + +StorageRef StorageBase::openSubStorage( const OUString& rStorageName, bool bCreate ) +{ + StorageRef xSubStorage; + OUString aElement, aRemainder; + lclSplitFirstElement( aElement, aRemainder, rStorageName ); + if( aElement.getLength() > 0 ) + xSubStorage = getSubStorage( aElement, bCreate ); + if( xSubStorage.get() && (aRemainder.getLength() > 0) ) + xSubStorage = xSubStorage->openSubStorage( aRemainder, bCreate ); + return xSubStorage; +} + +Reference< XInputStream > StorageBase::openInputStream( const OUString& rStreamName ) +{ + Reference< XInputStream > xInStream; + OUString aElement, aRemainder; + lclSplitFirstElement( aElement, aRemainder, rStreamName ); + if( aElement.getLength() > 0 ) + { + if( aRemainder.getLength() > 0 ) + { + StorageRef xSubStorage = getSubStorage( aElement, false ); + if( xSubStorage.get() ) + xInStream = xSubStorage->openInputStream( aRemainder ); + } + else + { + xInStream = implOpenInputStream( aElement ); + } + } + else if( mbBaseStreamAccess ) + { + xInStream = mxInStream; + } + return xInStream; +} + +Reference< XOutputStream > StorageBase::openOutputStream( const OUString& rStreamName ) +{ + Reference< XOutputStream > xOutStream; + OUString aElement, aRemainder; + lclSplitFirstElement( aElement, aRemainder, rStreamName ); + if( aElement.getLength() > 0 ) + { + if( aRemainder.getLength() > 0 ) + { + StorageRef xSubStorage = getSubStorage( aElement, true ); + if( xSubStorage.get() ) + xOutStream = xSubStorage->openOutputStream( aRemainder ); + } + else + { + xOutStream = implOpenOutputStream( aElement ); + } + } + else if( mbBaseStreamAccess ) + { + xOutStream = mxOutStream; + } + return xOutStream; +} + +StorageRef StorageBase::getSubStorage( const OUString& rElementName, bool bCreate ) +{ + SubStorageMap::iterator aIt = maSubStorages.find( rElementName ); + return (aIt == maSubStorages.end()) ? + (maSubStorages[ rElementName ] = implOpenSubStorage( rElementName, bCreate )) : aIt->second; +} + +// ============================================================================ + +} // namespace oox + diff --git a/oox/source/helper/zipstorage.cxx b/oox/source/helper/zipstorage.cxx new file mode 100644 index 000000000000..f9a11da3196b --- /dev/null +++ b/oox/source/helper/zipstorage.cxx @@ -0,0 +1,174 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: zipstorage.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:59 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/helper/zipstorage.hxx" +#include +#include +#include +#include +#include +#include "oox/helper/helper.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::embed::XStorage; +using ::com::sun::star::io::XInputStream; +using ::com::sun::star::io::XOutputStream; + +namespace oox { + +// ============================================================================ + +ZipStorage::ZipStorage( + const Reference< XMultiServiceFactory >& rxFactory, + const Reference< XInputStream >& rxInStream ) : + StorageBase( rxInStream, false ) +{ + OSL_ENSURE( rxFactory.is(), "ZipStorage::ZipStorage - missing service factory" ); + // create base storage object + try + { + mxStorage = ::comphelper::OStorageHelper::GetStorageFromInputStream( rxInStream, rxFactory ); + } + catch( Exception& ) + { + OSL_ENSURE( false, "ZipStorage::ZipStorage - cannot open input storage" ); + } +} + +ZipStorage::ZipStorage( + const Reference< XMultiServiceFactory >& rxFactory, + const Reference< XOutputStream >& rxOutStream ) : + StorageBase( rxOutStream, false ) +{ + OSL_ENSURE( rxFactory.is(), "ZipStorage::ZipStorage - missing service factory" ); + (void)rxFactory; // prevent compiler warning + OSL_ENSURE( false, "ZipStorage::ZipStorage - not implemented" ); +} + +ZipStorage::ZipStorage( const ZipStorage& rParentStorage, const Reference< XStorage >& rxStorage, const OUString& rElementName ) : + StorageBase( rParentStorage, rElementName ), + mxStorage( rxStorage ) +{ + OSL_ENSURE( mxStorage.is(), "ZipStorage::ZipStorage - missing storage" ); +} + +ZipStorage::~ZipStorage() +{ +} + +bool ZipStorage::implIsStorage() const +{ + return mxStorage.is(); +} + +Reference< XStorage > ZipStorage::implGetXStorage() const +{ + return mxStorage; +} + +void ZipStorage::implGetElementNames( ::std::vector< OUString >& orElementNames ) const +{ + Sequence< OUString > aNames; + if( mxStorage.is() ) try + { + aNames = mxStorage->getElementNames(); + if( aNames.getLength() > 0 ) + orElementNames.insert( orElementNames.end(), aNames.getConstArray(), aNames.getConstArray() + aNames.getLength() ); + } + catch( Exception& ) + { + } +} + +StorageRef ZipStorage::implOpenSubStorage( const OUString& rElementName, bool bCreate ) +{ + OSL_ENSURE( !bCreate, "ZipStorage::implOpenSubStorage - creating new sub storages not implemented" ); + (void)bCreate; // prevent compiler warning + + Reference< XStorage > xSubXStorage; + try + { + // XStorage::isStorageElement may throw various exceptions... + if( mxStorage->isStorageElement( rElementName ) ) + xSubXStorage = mxStorage->openStorageElement( + rElementName, ::com::sun::star::embed::ElementModes::READ ); + } + catch( Exception& ) + { + } + + StorageRef xSubStorage; + if( xSubXStorage.is() ) + xSubStorage.reset( new ZipStorage( *this, xSubXStorage, rElementName ) ); + return xSubStorage; +} + +Reference< XInputStream > ZipStorage::implOpenInputStream( const OUString& rElementName ) +{ + Reference< XInputStream > xInStream; + if( mxStorage.is() ) try + { + xInStream.set( mxStorage->openStreamElement( rElementName, ::com::sun::star::embed::ElementModes::READ ), UNO_QUERY ); + } + catch( Exception& ) + { + } + return xInStream; +} + +Reference< XOutputStream > ZipStorage::implOpenOutputStream( const OUString& rElementName ) +{ + Reference< XOutputStream > xOutStream; + if( mxStorage.is() ) try + { + (void)rElementName; + OSL_ENSURE( false, "ZipStorage::implOpenOutputStream - not implemented" ); + } + catch( Exception& ) + { + } + return xOutStream; +} + +// ============================================================================ + +} // namespace oox + diff --git a/oox/source/ppt/animationspersist.cxx b/oox/source/ppt/animationspersist.cxx new file mode 100644 index 000000000000..3094d7eee513 --- /dev/null +++ b/oox/source/ppt/animationspersist.cxx @@ -0,0 +1,210 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: animationspersist.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:05:59 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + + + +#include "oox/ppt/animationspersist.hxx" + +#include +#include +#include +#include +#include +#include + +#include "oox/drawingml/shape.hxx" + +#include "tokens.hxx" + +using rtl::OUString; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::presentation; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::text; + +namespace oox { namespace ppt { + + void ShapeTargetElement::convert( ::com::sun::star::uno::Any & rTarget, sal_Int16 & rSubType ) const + { + switch(mnType) + { + case XML_subSp: + rSubType = ShapeAnimationSubType::AS_WHOLE; + break; + case XML_bg: + rSubType = ShapeAnimationSubType::ONLY_BACKGROUND; + break; + case XML_txEl: + { + ParagraphTarget aParaTarget; + Reference< XShape > xShape; + rTarget >>= xShape; + aParaTarget.Shape = xShape; + rSubType = ShapeAnimationSubType::ONLY_TEXT; + + Reference< XText > xText( xShape, UNO_QUERY ); + if( xText.is() ) + { + switch(mnRangeType) + { + case XML_charRg: + // TODO calculate the corresponding paragraph for the text range.... + OSL_TRACE( "OOX: TODO calculate the corresponding paragraph for the text range..." ); + break; + case XML_pRg: + aParaTarget.Paragraph = static_cast< sal_Int16 >( maRange.start ); + // TODO what to do with more than one. + OSL_TRACE( "OOX: TODO what to do with more than one" ); + break; + } + rTarget = makeAny( aParaTarget ); + } + break; + } + default: + break; + } + } + + + Any AnimTargetElement::convert(const SlidePersistPtr & pSlide, sal_Int16 & nSubType) const + { + Any aTarget; + // see sd/source/files/ppt/pptinanimations.cxx:3191 (in importTargetElementContainer()) + switch(mnType) + { + case XML_inkTgt: + // TODO + OSL_TRACE( "OOX: TODO inkTgt" ); + break; + case XML_sldTgt: + // TODO + OSL_TRACE( "OOX: TODO sldTgt" ); + break; + case XML_sndTgt: + aTarget = makeAny(msValue); + break; + case XML_spTgt: + { + Any rTarget; + ::oox::drawingml::ShapePtr pShape = pSlide->getShape(msValue); + OSL_ENSURE( pShape, "failed to locate Shape"); + if( pShape ) + { + Reference< XShape > xShape( pShape->getXShape() ); + OSL_ENSURE( xShape.is(), "fail to get XShape from shape" ); + if( xShape.is() ) + { + rTarget <<= xShape; + maShapeTarget.convert(rTarget, nSubType); + aTarget = rTarget; + } + } + break; + } + default: + break; + } + return aTarget; + } + + +// BEGIN CUT&PASTE from sd/source/filter/ppt/pptinanimations.cxx +/** this adds an any to another any. + if rNewValue is empty, rOldValue is returned. + if rOldValue is empty, rNewValue is returned. + if rOldValue contains a value, a sequence with rOldValue and rNewValue is returned. + if rOldValue contains a sequence, a new sequence with the old sequence and rNewValue is returned. +*/ + static Any addToSequence( const Any& rOldValue, const Any& rNewValue ) + { + if( !rNewValue.hasValue() ) + { + return rOldValue; + } + else if( !rOldValue.hasValue() ) + { + return rNewValue; + } + else + { + Sequence< Any > aNewSeq; + if( rOldValue >>= aNewSeq ) + { + sal_Int32 nSize = aNewSeq.getLength(); + aNewSeq.realloc(nSize+1); + aNewSeq[nSize] = rNewValue; + } + else + { + aNewSeq.realloc(2); + aNewSeq[0] = rOldValue; + aNewSeq[1] = rNewValue; + } + return makeAny( aNewSeq ); + } + } +// END + + Any AnimationCondition::convert(const SlidePersistPtr & pSlide) const + { + Any aAny; + if( mpTarget ) + { + sal_Int16 nSubType; + aAny = mpTarget->convert( pSlide, nSubType ); + } + else + { + aAny = maValue; + } + return aAny; + } + + + Any AnimationCondition::convertList(const SlidePersistPtr & pSlide, const AnimationConditionList & l) + { + Any aAny; + for( AnimationConditionList::const_iterator iter = l.begin(); + iter != l.end(); iter++) + { + aAny = addToSequence( aAny, iter->convert(pSlide) ); + } + return aAny; + } + +} } + + diff --git a/oox/source/ppt/animationtypes.cxx b/oox/source/ppt/animationtypes.cxx new file mode 100644 index 000000000000..4f81d118ff81 --- /dev/null +++ b/oox/source/ppt/animationtypes.cxx @@ -0,0 +1,82 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: animationtypes.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + + +#include "animationtypes.hxx" + +#include + +#include "oox/helper/attributelist.hxx" + +#include "tokens.hxx" + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::animations; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace ppt { + +// ST_TLTime +Any GetTime( const ::rtl::OUString & val ) +{ + Any aDuration; + if( val.compareToAscii( "indefinite" ) == 0 ) + { + aDuration <<= Timing_INDEFINITE; + } + else + { + aDuration <<= val.toFloat() / 1000.0; + } + return aDuration; +} + + +// ST_TLTimeAnimateValueTime +Any GetTimeAnimateValueTime( const ::rtl::OUString & val ) +{ + Any aPercent; + if( val.compareToAscii( "indefinite" ) == 0 ) + { + aPercent <<= Timing_INDEFINITE; + } + else + { + aPercent <<= val.toFloat() / 100000.0; + } + return aPercent; +} + +} } diff --git a/oox/source/ppt/animationtypes.hxx b/oox/source/ppt/animationtypes.hxx new file mode 100644 index 000000000000..a242fcde7c70 --- /dev/null +++ b/oox/source/ppt/animationtypes.hxx @@ -0,0 +1,55 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: animationtypes.hxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + + + +#ifndef OOX_POWERPOINT_ANIMATIONTYPES_HXX +#define OOX_POWERPOINT_ANIMATIONTYPES_HXX + + +#include +#include + + +namespace oox { namespace ppt { + +// ST_TLTime +::com::sun::star::uno::Any GetTime( const ::rtl::OUString & val ); +// ST_TLTimeAnimateValueTime +::com::sun::star::uno::Any GetTimeAnimateValueTime( const ::rtl::OUString & val ); + +} } + +#endif diff --git a/oox/source/ppt/animvariantcontext.cxx b/oox/source/ppt/animvariantcontext.cxx new file mode 100644 index 000000000000..85fc20f55b75 --- /dev/null +++ b/oox/source/ppt/animvariantcontext.cxx @@ -0,0 +1,132 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: animvariantcontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "animvariantcontext.hxx" + +#include "comphelper/anytostring.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include + +#include +#include + +#include "oox/helper/attributelist.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/core/fragmenthandler.hxx" +#include "oox/drawingml/colorchoicecontext.hxx" +#include "pptfilterhelpers.hxx" +#include "tokens.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace ppt { + + AnimVariantContext::AnimVariantContext( const FragmentHandlerRef & xHandler, sal_Int32 aElement, + Any & aValue ) + : Context( xHandler ) + , mnElement( aElement ) + , maValue( aValue ) + { + } + + AnimVariantContext::~AnimVariantContext( ) throw( ) + { + } + + void SAL_CALL AnimVariantContext::endFastElement( sal_Int32 aElement ) + throw ( SAXException, RuntimeException) + { + if( ( aElement == mnElement ) && maColor.isUsed() ) + { + maValue = makeAny( maColor.getColor( *getHandler()->getFilter().get() ) ); + } + } + + + Reference< XFastContextHandler > + SAL_CALL AnimVariantContext::createFastChildContext( ::sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) + throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + AttributeList attribs(xAttribs); + + switch( aElementToken ) + { + case NMSP_PPT|XML_boolVal: + { + bool val = attribs.getBool( XML_val, false ); + maValue = makeAny( val ); + break; + } + case NMSP_PPT|XML_clrVal: + xRet.set( new ::oox::drawingml::colorChoiceContext( getHandler(), maColor ) ); + // we'll defer setting the Any until the end. + break; + case NMSP_PPT|XML_fltVal: + { + double val = attribs.getDouble( XML_val, 0.0 ); + maValue = makeAny( val ); + break; + } + case NMSP_PPT|XML_intVal: + { + sal_Int32 val = attribs.getInteger( XML_val, 0 ); + maValue = makeAny( val ); + break; + } + case NMSP_PPT|XML_strVal: + { + OUString val = attribs.getString( XML_val ); + convertMeasure( val ); // ignore success or failure if it fails, use as is + maValue = makeAny( val ); + break; + } + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; + } + + + +} } diff --git a/oox/source/ppt/animvariantcontext.hxx b/oox/source/ppt/animvariantcontext.hxx new file mode 100644 index 000000000000..8b88e33944d9 --- /dev/null +++ b/oox/source/ppt/animvariantcontext.hxx @@ -0,0 +1,69 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: animvariantcontext.hxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + + + +#ifndef OOX_PPT_ANIMVARIANTCONTEXT +#define OOX_PPT_ANIMVERIANTCONTEXT + + +#include + +#include "oox/core/context.hxx" +#include "oox/core/fragmenthandler.hxx" +#include "oox/drawingml/color.hxx" + +namespace oox { namespace ppt { + + /** context CT_TLAnimVariant */ + class AnimVariantContext + : public ::oox::core::Context + { + public: + AnimVariantContext( const ::oox::core::FragmentHandlerRef & xHandler, ::sal_Int32 aElement, ::com::sun::star::uno::Any & aValue ); + ~AnimVariantContext( ) throw( ); + virtual void SAL_CALL endFastElement( sal_Int32 /*aElement*/ ) throw ( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs ) throw ( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException ); + + private: + ::sal_Int32 mnElement; + ::com::sun::star::uno::Any& maValue; + ::oox::drawingml::Color maColor; + }; + +} } + + +#endif diff --git a/oox/source/ppt/backgroundproperties.cxx b/oox/source/ppt/backgroundproperties.cxx new file mode 100644 index 000000000000..e039a17ccb41 --- /dev/null +++ b/oox/source/ppt/backgroundproperties.cxx @@ -0,0 +1,79 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: backgroundproperties.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/ppt/backgroundproperties.hxx" + +#include + +#include "oox/drawingml/fillpropertiesgroupcontext.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using ::rtl::OUString; +using ::com::sun::star::beans::NamedValue; +using ::com::sun::star::beans::PropertyValue; +using ::com::sun::star::beans::XPropertySet; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { +// --------------------------------------------------------------------- + +BackgroundPropertiesContext::BackgroundPropertiesContext( const FragmentHandlerRef& xHandler, FillPropertiesPtr pFillPropertiesPtr ) throw() +: Context( xHandler ) +, mpFillPropertiesPtr( pFillPropertiesPtr ) +{ +} + +Reference< XFastContextHandler > BackgroundPropertiesContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case NMSP_PPT|XML_fill: // a:CT_FillEffect + break; + } + + // FillPropertiesGroupContext + if( !xRet.is() ) + xRet = FillPropertiesGroupContext::StaticCreateContext( getHandler(), aElementToken, xAttribs, *(mpFillPropertiesPtr.get()) ); + + return xRet; +} + +} } diff --git a/oox/source/ppt/buildlistcontext.cxx b/oox/source/ppt/buildlistcontext.cxx new file mode 100644 index 000000000000..dcff9e1b1b30 --- /dev/null +++ b/oox/source/ppt/buildlistcontext.cxx @@ -0,0 +1,121 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: buildlistcontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "buildlistcontext.hxx" +#include +#include "oox/helper/attributelist.hxx" +#include "oox/core/namespaces.hxx" + + +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using ::rtl::OUString; + +namespace oox { namespace ppt { + + BuildListContext::BuildListContext( const FragmentHandlerRef& xHandler, + const Reference< XFastAttributeList >& /*xAttribs*/, + TimeNodePtrList & aTimeNodeList) + : Context( xHandler ) + , maTimeNodeList( aTimeNodeList ) + , mbInBldGraphic( false ) + , mbBuildAsOne( false ) + { + } + + BuildListContext::~BuildListContext( ) + { + } + + void SAL_CALL BuildListContext::endFastElement( sal_Int32 aElement ) throw ( SAXException, RuntimeException) + { + switch( aElement ) + { + case NMSP_PPT|XML_bldGraphic: + mbInBldGraphic = false; + break; + default: + break; + } + } + + Reference< XFastContextHandler > SAL_CALL BuildListContext::createFastChildContext( ::sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) + throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case NMSP_PPT|XML_bldAsOne: + if( mbInBldGraphic ) + { + mbBuildAsOne = true; + } + break; + case NMSP_PPT|XML_bldSub: + if( mbInBldGraphic ) + { + } + break; + case NMSP_PPT|XML_bldGraphic: + { + mbInBldGraphic = true; + AttributeList attribs( xAttribs ); + OUString sShapeId = xAttribs->getOptionalValue( XML_spid ); +// TODO +// bool uiExpand = attribs.getBool( XML_uiExpand, true ); + /* this is unsigned */ +// sal_uInt32 nGroupId = attribs.getUnsignedInteger( XML_grpId, 0 ); + break; + } + case NMSP_DRAWINGML|XML_bldDgm: + case NMSP_DRAWINGML|XML_bldOleChart: + case NMSP_DRAWINGML|XML_bldP: + + break; + default: + break; + } + + if( !xRet.is() ) + xRet.set(this); + + return xRet; + } + + +} } diff --git a/oox/source/ppt/buildlistcontext.hxx b/oox/source/ppt/buildlistcontext.hxx new file mode 100644 index 000000000000..82d10b0ae91a --- /dev/null +++ b/oox/source/ppt/buildlistcontext.hxx @@ -0,0 +1,72 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: buildlistcontext.hxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + + + +#ifndef OOX_PPT_BUILDLISTCONTEXT +#define OOX_PPT_BUILDLISTCONTEXT + +#include "oox/ppt/timenode.hxx" +#include "oox/core/context.hxx" + +namespace oox { namespace ppt { + + + /** CT_BuildList */ + class BuildListContext + : public ::oox::core::Context + { + public: + BuildListContext( const ::oox::core::FragmentHandlerRef& xHandler, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs, + TimeNodePtrList & aTimeNodeList); + + ~BuildListContext( ); + + virtual void SAL_CALL endFastElement( sal_Int32 aElement ) throw ( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& /*xAttribs*/ ) throw ( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException ); + private: + TimeNodePtrList & maTimeNodeList; + bool mbInBldGraphic; + bool mbBuildAsOne; + }; + + + + +} } + +#endif diff --git a/oox/source/ppt/commonbehaviorcontext.cxx b/oox/source/ppt/commonbehaviorcontext.cxx new file mode 100644 index 000000000000..0d4f570df348 --- /dev/null +++ b/oox/source/ppt/commonbehaviorcontext.cxx @@ -0,0 +1,188 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: commonbehaviorcontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "comphelper/anytostring.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include +#include +#include + +#include +#include +#include + +#include "oox/core/namespaces.hxx" +#include "oox/core/fragmenthandler.hxx" + +#include "commonbehaviorcontext.hxx" +#include "commontimenodecontext.hxx" +#include "timetargetelementcontext.hxx" +#include "pptfilterhelpers.hxx" +#include "tokens.hxx" + + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::animations; + +namespace oox { namespace ppt { + + CommonBehaviorContext::CommonBehaviorContext( const FragmentHandlerRef& xHandler, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) + : TimeNodeContext( xHandler, NMSP_PPT|XML_cBhvr, xAttribs, pNode ) + , mbInAttrList( false ) + , mbIsInAttrName( false ) + { + } + + + CommonBehaviorContext::~CommonBehaviorContext( ) throw( ) + { + } + + + + void SAL_CALL CommonBehaviorContext::endFastElement( sal_Int32 aElement ) + throw ( SAXException, RuntimeException) + { + switch( aElement ) + { + case NMSP_PPT|XML_cBhvr: + { + if( !maAttributes.empty() ) + { + OUStringBuffer sAttributes; + std::list< Attribute >::const_iterator iter; + for(iter = maAttributes.begin(); iter != maAttributes.end(); iter++) + { + if( sAttributes.getLength() ) + { + sAttributes.appendAscii( ";" ); + } + sAttributes.append( iter->name ); + } + OUString sTmp( sAttributes.makeStringAndClear() ); + mpNode->getNodeProperties()[ NP_ATTRIBUTENAME ] = makeAny( sTmp ); + } + break; + } + case NMSP_PPT|XML_attrNameLst: + mbInAttrList = false; + break; + case NMSP_PPT|XML_attrName: + if( mbIsInAttrName ) + { + const ImplAttributeNameConversion *attrConv = gImplConversionList; + while( attrConv->mpMSName != NULL ) + { + if(msCurrentAttribute.compareToAscii( attrConv->mpMSName ) == 0 ) + { + Attribute attr; + attr.name = ::rtl::OUString::intern( attrConv->mpAPIName, + strlen(attrConv->mpAPIName), + RTL_TEXTENCODING_ASCII_US ); + attr.type = attrConv->meAttribute; + maAttributes.push_back( attr ); + OSL_TRACE( "OOX: attrName is %s -> %s", + OUSTRING_TO_CSTR( msCurrentAttribute ), + attrConv->mpAPIName ); + break; + } + attrConv++; + } + mbIsInAttrName = false; + } + break; + default: + break; + } + } + + + void CommonBehaviorContext::characters( const OUString& aChars ) + throw( SAXException, RuntimeException ) + { + if( mbIsInAttrName ) + { + msCurrentAttribute += aChars; + } + } + + + Reference< XFastContextHandler > SAL_CALL CommonBehaviorContext::createFastChildContext( ::sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) + throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + + switch ( aElementToken ) + { + case NMSP_PPT|XML_cTn: + xRet.set( new CommonTimeNodeContext( getHandler(), aElementToken, xAttribs, mpNode ) ); + break; + case NMSP_PPT|XML_tgtEl: + xRet.set( new TimeTargetElementContext( getHandler(), mpNode->getTarget() ) ); + break; + case NMSP_PPT|XML_attrNameLst: + mbInAttrList = true; + break; + case NMSP_PPT|XML_attrName: + { + if( mbInAttrList ) + { + mbIsInAttrName = true; + msCurrentAttribute = OUString(); + } + else + { + OSL_TRACE( "OOX: Attribute Name outside an Attribute List" ); + } + break; + } + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; + } + +} } diff --git a/oox/source/ppt/commonbehaviorcontext.hxx b/oox/source/ppt/commonbehaviorcontext.hxx new file mode 100644 index 000000000000..375495e19e3c --- /dev/null +++ b/oox/source/ppt/commonbehaviorcontext.hxx @@ -0,0 +1,90 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: commonbehaviorcontext.hxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + + +#ifndef OOX_PPT_COMMONBEHAVIORCONTEXT +#define OOX_PPT_COMMONBEHAVIORCONTEXT + +#include +#include "oox/ppt/timenodelistcontext.hxx" +#include "oox/ppt/animationspersist.hxx" +#include "conditioncontext.hxx" +#include "pptfilterhelpers.hxx" + +namespace oox { namespace ppt { + + struct Attribute + { + ::rtl::OUString name; + MS_AttributeNames type; + }; + + + /** CT_TLCommonBehaviorData */ + class CommonBehaviorContext + : public TimeNodeContext + { + public: + CommonBehaviorContext( const ::oox::core::FragmentHandlerRef& xHandler, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ); + ~CommonBehaviorContext( ) + throw( ); + + virtual void SAL_CALL endFastElement( sal_Int32 aElement ) + throw ( ::com::sun::star::xml::sax::SAXException, + ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL characters( const ::rtl::OUString& aChars ) + throw ( ::com::sun::star::xml::sax::SAXException, + ::com::sun::star::uno::RuntimeException ); + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& /*xAttribs*/ ) + throw ( ::com::sun::star::xml::sax::SAXException, + ::com::sun::star::uno::RuntimeException ); + + private: + bool mbInAttrList; + bool mbIsInAttrName; + std::list< Attribute > maAttributes; + ::rtl::OUString msCurrentAttribute; + }; + + +} } + + +#endif diff --git a/oox/source/ppt/commontimenodecontext.cxx b/oox/source/ppt/commontimenodecontext.cxx new file mode 100644 index 000000000000..232d59cb8d81 --- /dev/null +++ b/oox/source/ppt/commontimenodecontext.cxx @@ -0,0 +1,717 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: commontimenodecontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "commontimenodecontext.hxx" + +#include + +#include "comphelper/anytostring.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "oox/helper/attributelist.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/core/fragmenthandler.hxx" +#include "oox/ppt/pptimport.hxx" +#include "oox/drawingml/drawingmltypes.hxx" + +#include "animationtypes.hxx" +#include "tokens.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::animations; +using namespace ::com::sun::star::presentation; +using namespace ::com::sun::star::xml::sax; + + +using ::rtl::OUString; +using ::com::sun::star::beans::NamedValue; + +namespace oox { namespace ppt { + +// BEGIN CUT&PASTE from sd/source/filter/ppt/pptanimations.hxx +struct convert_subtype +{ + sal_Int32 mnID; + const sal_Char* mpStrSubType; +}; +static const convert_subtype gConvertArray[] = +{ + // fly in + { 1, "from-top" }, + { 2, "from-right" }, + { 3, "from-top-right" }, + { 4, "from-bottom" }, + { 5, "horizontal" }, + { 6, "from-bottom-right" }, + { 8, "from-left" }, + { 9, "from-top-left" }, + { 10, "vertical" }, + { 12, "from-bottom-left" }, + { 16, "in" }, + { 21, "vertical-in" }, + { 26, "horizontal-in" }, + { 32, "out" }, + { 36, "out-from-screen-center" }, + { 37, "vertical-out" }, + { 42, "horizontal-out" }, + { 272, "in-slightly" }, + { 288, "out-slightly" }, + { 528, "in-from-screen-center" }, + { 0, 0 } +}; + + +struct preset_maping +{ + sal_Int32 mnPresetClass; + sal_Int32 mnPresetId; + const sal_Char* mpStrPresetId; +}; + +static const preset_maping gPresetMaping[] = +{ + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 1 ,"ooo-entrance-appear" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 2 ,"ooo-entrance-fly-in" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 3 ,"ooo-entrance-venetian-blinds" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 4 ,"ooo-entrance-box" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 5 ,"ooo-entrance-checkerboard" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 6 ,"ooo-entrance-circle" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 7 ,"ooo-entrance-fly-in-slow" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 8 ,"ooo-entrance-diamond" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 9 ,"ooo-entrance-dissolve-in" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 10 ,"ooo-entrance-fade-in" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 11 ,"ooo-entrance-flash-once" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 12 ,"ooo-entrance-peek-in" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 13 ,"ooo-entrance-plus" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 14 ,"ooo-entrance-random-bars" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 15 ,"ooo-entrance-spiral-in" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 16 ,"ooo-entrance-split" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 17 ,"ooo-entrance-stretchy" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 18 ,"ooo-entrance-diagonal-squares" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 19 ,"ooo-entrance-swivel" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 20 ,"ooo-entrance-wedge" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 21 ,"ooo-entrance-wheel" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 22 ,"ooo-entrance-wipe" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 23 ,"ooo-entrance-zoom" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 24 ,"ooo-entrance-random" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 25 ,"ooo-entrance-boomerang" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 26 ,"ooo-entrance-bounce" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 27 ,"ooo-entrance-colored-lettering" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 28 ,"ooo-entrance-movie-credits" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 29 ,"ooo-entrance-ease-in" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 30 ,"ooo-entrance-float" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 31 ,"ooo-entrance-turn-and-grow" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 34 ,"ooo-entrance-breaks" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 35 ,"ooo-entrance-pinwheel" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 37 ,"ooo-entrance-rise-up" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 38 ,"ooo-entrance-falling-in" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 39 ,"ooo-entrance-thread" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 40 ,"ooo-entrance-unfold" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 41 ,"ooo-entrance-whip" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 42 ,"ooo-entrance-ascend" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 43 ,"ooo-entrance-center-revolve" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 45 ,"ooo-entrance-fade-in-and-swivel" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 47 ,"ooo-entrance-descend" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 48 ,"ooo-entrance-sling" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 49 ,"ooo-entrance-spin-in" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 50 ,"ooo-entrance-compress" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 51 ,"ooo-entrance-magnify" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 52 ,"ooo-entrance-curve-up" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 53 ,"ooo-entrance-fade-in-and-zoom" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 54 ,"ooo-entrance-glide" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 55 ,"ooo-entrance-expand" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 56 ,"ooo-entrance-flip" }, + { ::com::sun::star::presentation::EffectPresetClass::ENTRANCE, 58 ,"ooo-entrance-fold" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 1 ,"ooo-emphasis-fill-color" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 2 ,"ooo-emphasis-font" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 3 ,"ooo-emphasis-font-color" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 4 ,"ooo-emphasis-font-size" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 5 ,"ooo-emphasis-font-style" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 6 ,"ooo-emphasis-grow-and-shrink" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 7 ,"ooo-emphasis-line-color" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 8 ,"ooo-emphasis-spin" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 9 ,"ooo-emphasis-transparency" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 10 ,"ooo-emphasis-bold-flash" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 14 ,"ooo-emphasis-blast" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 15 ,"ooo-emphasis-bold-reveal" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 16 ,"ooo-emphasis-color-over-by-word" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 18 ,"ooo-emphasis-reveal-underline" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 19 ,"ooo-emphasis-color-blend" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 20 ,"ooo-emphasis-color-over-by-letter" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 21 ,"ooo-emphasis-complementary-color" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 22 ,"ooo-emphasis-complementary-color-2" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 23 ,"ooo-emphasis-contrasting-color" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 24 ,"ooo-emphasis-darken" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 25 ,"ooo-emphasis-desaturate" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 26 ,"ooo-emphasis-flash-bulb" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 27 ,"ooo-emphasis-flicker" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 28 ,"ooo-emphasis-grow-with-color" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 30 ,"ooo-emphasis-lighten" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 31 ,"ooo-emphasis-style-emphasis" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 32 ,"ooo-emphasis-teeter" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 33 ,"ooo-emphasis-vertical-highlight" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 34 ,"ooo-emphasis-wave" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 35 ,"ooo-emphasis-blink" }, + { ::com::sun::star::presentation::EffectPresetClass::EMPHASIS, 36 ,"ooo-emphasis-shimmer" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 1 ,"ooo-exit-disappear" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 2 ,"ooo-exit-fly-out" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 3 ,"ooo-exit-venetian-blinds" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 4 ,"ooo-exit-box" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 5 ,"ooo-exit-checkerboard" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 6 ,"ooo-exit-circle" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 7 ,"ooo-exit-crawl-out" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 8 ,"ooo-exit-diamond" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 9 ,"ooo-exit-dissolve" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 10 ,"ooo-exit-fade-out" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 11 ,"ooo-exit-flash-once" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 12 ,"ooo-exit-peek-out" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 13 ,"ooo-exit-plus" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 14 ,"ooo-exit-random-bars" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 15 ,"ooo-exit-spiral-out" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 16 ,"ooo-exit-split" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 17 ,"ooo-exit-collapse" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 18 ,"ooo-exit-diagonal-squares" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 19 ,"ooo-exit-swivel" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 20 ,"ooo-exit-wedge" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 21 ,"ooo-exit-wheel" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 22 ,"ooo-exit-wipe" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 23 ,"ooo-exit-zoom" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 24 ,"ooo-exit-random" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 25 ,"ooo-exit-boomerang" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 26 ,"ooo-exit-bounce" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 27 ,"ooo-exit-colored-lettering" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 28 ,"ooo-exit-movie-credits" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 29 ,"ooo-exit-ease-out" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 30 ,"ooo-exit-float" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 31 ,"ooo-exit-turn-and-grow" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 34 ,"ooo-exit-breaks" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 35 ,"ooo-exit-pinwheel" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 37 ,"ooo-exit-sink-down" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 38 ,"ooo-exit-swish" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 39 ,"ooo-exit-thread" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 40 ,"ooo-exit-unfold" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 41 ,"ooo-exit-whip" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 42 ,"ooo-exit-descend" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 43 ,"ooo-exit-center-revolve" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 45 ,"ooo-exit-fade-out-and-swivel" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 47 ,"ooo-exit-ascend" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 48 ,"ooo-exit-sling" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 53 ,"ooo-exit-fade-out-and-zoom" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 55 ,"ooo-exit-contract" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 49 ,"ooo-exit-spin-out" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 50 ,"ooo-exit-stretchy" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 51 ,"ooo-exit-magnify" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 52 ,"ooo-exit-curve-down" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 54 ,"ooo-exit-glide" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 56 ,"ooo-exit-flip" }, + { ::com::sun::star::presentation::EffectPresetClass::EXIT, 58 ,"ooo-exit-fold" }, + + + + + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 16 ,"ooo-motionpath-4-point-star" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 5 ,"ooo-motionpath-5-point-star" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 11 ,"ooo-motionpath-6-point-star" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 17 ,"ooo-motionpath-8-point-star" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 1 ,"ooo-motionpath-circle" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 6 ,"ooo-motionpath-crescent-moon" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 3 ,"ooo-motionpath-diamond" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 13 ,"ooo-motionpath-equal-triangle" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 12 ,"ooo-motionpath-oval" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 9 ,"ooo-motionpath-heart" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 4 ,"ooo-motionpath-hexagon" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 10 ,"ooo-motionpath-octagon" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 14 ,"ooo-motionpath-parallelogram" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 15 ,"ooo-motionpath-pentagon" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 2 ,"ooo-motionpath-right-triangle" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 7 ,"ooo-motionpath-square" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 18 ,"ooo-motionpath-teardrop" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 8 ,"ooo-motionpath-trapezoid" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 37 ,"ooo-motionpath-arc-down" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 51 ,"ooo-motionpath-arc-left" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 58 ,"ooo-motionpath-arc-right" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 44 ,"ooo-motionpath-arc-up" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 41 ,"ooo-motionpath-bounce-left" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 54 ,"ooo-motionpath-bounce-right" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 48 ,"ooo-motionpath-curvy-left" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 61 ,"ooo-motionpath-curvy-right" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 60 ,"ooo-motionpath-decaying-wave" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 49 ,"ooo-motionpath-diagonal-down-right" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 56 ,"ooo-motionpath-diagonal-up-right" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 42 ,"ooo-motionpath-down" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 52 ,"ooo-motionpath-funnel" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 53 ,"ooo-motionpath-spring" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 62 ,"ooo-motionpath-stairs-down" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 50 ,"ooo-motionpath-turn-down" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 36 ,"ooo-motionpath-turn-down-right" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 43 ,"ooo-motionpath-turn-up" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 57 ,"ooo-motionpath-turn-up-right" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 64 ,"ooo-motionpath-up" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 47 ,"ooo-motionpath-wave" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 38 ,"ooo-motionpath-zigzag" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 31 ,"ooo-motionpath-bean" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 25 ,"ooo-motionpath-buzz-saw" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 20 ,"ooo-motionpath-curved-square" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 21 ,"ooo-motionpath-curved-x" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 23 ,"ooo-motionpath-curvy-star" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 28 ,"ooo-motionpath-figure-8-four" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 26 ,"ooo-motionpath-horizontal-figure-8" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 34 ,"ooo-motionpath-inverted-square" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 33 ,"ooo-motionpath-inverted-triangle" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 24 ,"ooo-motionpath-loop-de-loop" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 29 ,"ooo-motionpath-neutron" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 27 ,"ooo-motionpath-peanut" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 32 ,"ooo-motionpath-clover" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 19 ,"ooo-motionpath-pointy-star" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 30 ,"ooo-motionpath-swoosh" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 22 ,"ooo-motionpath-vertical-figure-8" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 35 ,"ooo-motionpath-left" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 63 ,"ooo-motionpath-right" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 55 ,"ooo-motionpath-spiral-left" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 46 ,"ooo-motionpath-spiral-right" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 40 ,"ooo-motionpath-sine-wave" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 59 ,"ooo-motionpath-s-curve-1" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 39 ,"ooo-motionpath-s-curve-2" }, + { ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH, 45 ,"ooo-motionpath-heartbeat" }, + + + { 0,0,0 } +}; + +// from sd/source/filter/ppt/pptinanimations.cxx +static OUString getConvertedSubType( sal_Int16 nPresetClass, sal_Int32 nPresetId, sal_Int32 nPresetSubType ) +{ + const sal_Char* pStr = 0; + + if( (nPresetClass == EffectPresetClass::ENTRANCE) || (nPresetClass == EffectPresetClass::EXIT) ) + { + // skip wheel effect + if( nPresetId != 21 ) + { + if( nPresetId == 5 ) + { + // checkerboard + switch( nPresetSubType ) + { + case 5: pStr = "downward"; break; + case 10: pStr = "across"; break; + } + } + else if( nPresetId == 17 ) + { + // stretch + if( nPresetSubType == 10 ) + pStr = "across"; + } + else if( nPresetId == 18 ) + { + // strips + switch( nPresetSubType ) + { + case 3: pStr = "right-to-top"; break; + case 6: pStr = "right-to-bottom"; break; + case 9: pStr = "left-to-top"; break; + case 12: pStr = "left-to-bottom"; break; + } + } + + if( pStr == 0 ) + { + const convert_subtype* p = gConvertArray; + + while( p->mpStrSubType ) + { + if( p->mnID == nPresetSubType ) + { + pStr = p->mpStrSubType; + break; + } + p++; + } + } + } + } + + if( pStr ) + return OUString::createFromAscii( pStr ); + else + return OUString::valueOf( nPresetSubType ); +} + +// END + + CommonTimeNodeContext::CommonTimeNodeContext( const FragmentHandlerRef& xHandler, + sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) + : TimeNodeContext( xHandler, aElement, xAttribs, pNode ) + , mbIterate( false ) + { + AttributeList attribs( xAttribs ); + sal_Int32 nInt; // some temporary int value for float conversions + + NodePropertyMap & aProps = pNode->getNodeProperties(); + PropertyMap & aUserData = pNode->getUserData(); + + if( attribs.hasAttribute( XML_accel ) ) + { + double dPercent = ::oox::drawingml::GetPositiveFixedPercentage( xAttribs->getOptionalValue( XML_accel ) ); + aProps[ NP_ACCELERATION ] <<= dPercent; + } + + if( attribs.hasAttribute( XML_afterEffect ) ) + { + aUserData[ CREATE_OUSTRING( "after-effect" ) ] + = makeAny( attribs.getBool( XML_afterEffect, false ) ); + } + aProps[ NP_AUTOREVERSE ] = makeAny( attribs.getBool( XML_autoRev, false ) ); + + // TODO + if( attribs.hasAttribute( XML_bldLvl ) ) + { + attribs.getInteger( XML_bldLvl, 0 ); + } + if( attribs.hasAttribute( XML_decel ) ) + { + double dPercent = ::oox::drawingml::GetPositiveFixedPercentage( xAttribs->getOptionalValue( XML_decel ) ); + aProps[ NP_DECELERATE ] <<= dPercent; + } + // TODO + if( attribs.hasAttribute( XML_display ) ) + { + aProps[ NP_DISPLAY ] <<= attribs.getBool( XML_display, true ); + } + if( attribs.hasAttribute( XML_dur ) ) + { + aProps[ NP_DURATION ] = GetTime( xAttribs->getOptionalValue( XML_dur) ); + } + // TODO + if( attribs.hasAttribute( XML_evtFilter ) ) + { + xAttribs->getOptionalValue( XML_evtFilter ); + } + // ST_TLTimeNodeFillType + if( attribs.hasAttribute( XML_fill ) ) + { + nInt = xAttribs->getOptionalValueToken( XML_fill, 0 ); + if( nInt != 0 ) + { + sal_Int16 nEnum; + switch( nInt ) + { + case XML_remove: + nEnum = AnimationFill::REMOVE; + break; + case XML_freeze: + nEnum = AnimationFill::FREEZE; + break; + case XML_hold: + nEnum = AnimationFill::HOLD; + break; + case XML_transition: + nEnum = AnimationFill::TRANSITION; + break; + default: + nEnum = AnimationFill::DEFAULT; + break; + } + aProps[ NP_FILL ] <<= (sal_Int16)nEnum; + } + } + if( attribs.hasAttribute( XML_grpId ) ) + { + attribs.getUnsignedInteger( XML_grpId, 0 ); + } + // ST_TLTimeNodeID + if( attribs.hasAttribute( XML_id ) ) + { + sal_uInt32 nId = attribs.getUnsignedInteger( XML_id, 0 ); + pNode->setId( nId ); + } + // ST_TLTimeNodeMasterRelation + nInt = xAttribs->getOptionalValueToken( XML_masterRel, 0 ); + if( nInt ) + { + // TODO + switch(nInt) + { + case XML_sameClick: + case XML_lastClick: + case XML_nextClick: + break; + } + } + + // TODO + if( attribs.hasAttribute( XML_nodePh ) ) + { + attribs.getBool( XML_nodePh, false ); + } + // ST_TLTimeNodeType + nInt = xAttribs->getOptionalValueToken( XML_nodeType, 0 ); + if( nInt != 0 ) + { + sal_Int16 nEnum; + switch( nInt ) + { + case XML_clickEffect: + case XML_clickPar: + nEnum = EffectNodeType::ON_CLICK; + break; + case XML_withEffect: + case XML_withGroup: + nEnum = EffectNodeType::WITH_PREVIOUS; + break; + case XML_mainSeq: + nEnum = EffectNodeType::MAIN_SEQUENCE; + break; + case XML_interactiveSeq: + nEnum = EffectNodeType::INTERACTIVE_SEQUENCE; + break; + case XML_afterGroup: + case XML_afterEffect: + nEnum = EffectNodeType::AFTER_PREVIOUS; + break; + case XML_tmRoot: + nEnum = EffectNodeType::TIMING_ROOT; + break; + default: + nEnum = EffectNodeType::DEFAULT; + break; + } + aUserData[ CREATE_OUSTRING( "node-type" ) ] <<= nEnum; + } + + // ST_TLTimeNodePresetClassType + nInt = xAttribs->getOptionalValueToken( XML_presetClass, 0 ); + sal_Int16 nEffectPresetClass = 0; + sal_Int32 nPresetId = 0; + sal_Int32 nPresetSubType = 0; + if( nInt != 0 ) + { + // TODO put that in a function + switch( nInt ) + { + case XML_entr: + nEffectPresetClass = EffectPresetClass::ENTRANCE; + break; + case XML_exit: + nEffectPresetClass = EffectPresetClass::EXIT; + break; + case XML_emph: + nEffectPresetClass = EffectPresetClass::EMPHASIS; + break; + case XML_path: + nEffectPresetClass = EffectPresetClass::MOTIONPATH; + break; + case XML_verb: + // TODO check that the value below is correct + nEffectPresetClass = EffectPresetClass::OLEACTION; + break; + case XML_mediacall: + nEffectPresetClass = EffectPresetClass::MEDIACALL; + break; + default: + nEffectPresetClass = 0; + break; + } + aUserData[ CREATE_OUSTRING( "preset-class" ) ] = makeAny( nEffectPresetClass ); + if( attribs.hasAttribute( XML_presetID ) ) + { + nPresetId = attribs.getInteger( XML_presetID, 0 ); + const preset_maping* p = gPresetMaping; + while( p->mpStrPresetId && ((p->mnPresetClass != nEffectPresetClass) || (p->mnPresetId != nPresetId )) ) + p++; + + aUserData[ CREATE_OUSTRING( "preset-id" ) ] + = makeAny( OUString::createFromAscii( p->mpStrPresetId ) ); + nPresetSubType = attribs.getInteger( XML_presetSubtype, 0 ); + if( nPresetSubType ) + { + aUserData[ CREATE_OUSTRING( "preset-sub-type" ) ] + = makeAny( getConvertedSubType( nEffectPresetClass, nPresetId, nPresetSubType ) ); + } + } + } + if( attribs.hasAttribute( XML_repeatCount ) ) + { + aProps[ NP_REPEATCOUNT ] = GetTime( xAttribs->getOptionalValue( XML_repeatCount ) ); + } + /* see pptinanimation */ +// aProps[ NP_REPEATCOUNT ] <<= (fCount < ((float)3.40282346638528860e+38)) ? makeAny( (double)fCount ) : makeAny( Timing_INDEFINITE ); + if( attribs.hasAttribute( XML_repeatDur ) ) + { + aProps[ NP_REPEATDURATION ] = GetTime( xAttribs->getOptionalValue( XML_repeatDur ) ); + } + // TODO repeatDur is otherwise the same as dur. What shall we do? -- Hub + + // ST_TLTimeNodeRestartType + nInt = xAttribs->getOptionalValueToken( XML_restart, 0 ); + if( nInt != 0 ) + { + // TODO put that in a function + sal_Int16 nEnum; + switch( nInt ) + { + case XML_always: + nEnum = AnimationRestart::ALWAYS; + break; + case XML_whenNotActive: + nEnum = AnimationRestart::WHEN_NOT_ACTIVE; + break; + case XML_never: + nEnum = AnimationRestart::NEVER; + break; + default: + nEnum = AnimationRestart::DEFAULT; + break; + } + aProps[ NP_RESTART ] <<= (sal_Int16)nEnum; + } + // ST_Percentage TODO + xAttribs->getOptionalValue( XML_spd /*"10000" */ ); + // ST_TLTimeNodeSyncType TODO + xAttribs->getOptionalValue( XML_syncBehavior ); + // TODO (string) + xAttribs->getOptionalValue( XML_tmFilter ); + } + + + CommonTimeNodeContext::~CommonTimeNodeContext( ) throw ( ) + { + } + + + void SAL_CALL CommonTimeNodeContext::endFastElement( sal_Int32 aElement ) throw ( SAXException, RuntimeException) + { + if( aElement == ( NMSP_PPT|XML_iterate ) ) + { + mbIterate = false; + } + } + + + Reference< XFastContextHandler > SAL_CALL CommonTimeNodeContext::createFastChildContext( ::sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + + switch ( aElementToken ) + { + case NMSP_PPT|XML_childTnLst: + case NMSP_PPT|XML_subTnLst: + xRet.set( new TimeNodeListContext( getHandler(), mpNode->getChilds() ) ); + break; + + case NMSP_PPT|XML_stCondLst: + xRet.set( new CondListContext( getHandler(), aElementToken, xAttribs, mpNode, mpNode->getStartCondition() ) ); + break; + case NMSP_PPT|XML_endCondLst: + xRet.set( new CondListContext( getHandler(), aElementToken, xAttribs, mpNode, mpNode->getEndCondition() ) ); + break; + + case NMSP_PPT|XML_endSync: + xRet.set( new CondContext( getHandler(), xAttribs, mpNode, mpNode->getEndSyncValue() ) ); + break; + case NMSP_PPT|XML_iterate: + { + sal_Int32 nVal = xAttribs->getOptionalValueToken( XML_type, XML_el ); + if( nVal != 0 ) + { + // TODO put that in a function + sal_Int16 nEnum; + switch( nVal ) + { + case XML_el: + nEnum = TextAnimationType::BY_PARAGRAPH; + break; + case XML_lt: + nEnum = TextAnimationType::BY_LETTER; + break; + case XML_wd: + nEnum = TextAnimationType::BY_WORD; + break; + default: + // default is BY_WORD. See Ppt97Animation::GetTextAnimationType() + // in sd/source/filter/ppt/ppt97animations.cxx:297 + nEnum = TextAnimationType::BY_WORD; + break; + } + mpNode->getNodeProperties()[ NP_ITERATETYPE ] <<= nEnum; + } + // in case of exception we ignore the whole tag. + AttributeList attribs( xAttribs ); + // TODO what to do with this + /*bool bBackwards =*/ attribs.getBool( XML_backwards, false ); + mbIterate = true; + break; + } + case NMSP_PPT|XML_tmAbs: + if( mbIterate ) + { + AttributeList attribs( xAttribs ); + double fTime = attribs.getUnsignedInteger( XML_val, 0 ); + // time in ms. property is in % TODO + mpNode->getNodeProperties()[ NP_ITERATEINTERVAL ] <<= fTime; + } + break; + case NMSP_PPT|XML_tmPct: + if( mbIterate ) + { + AttributeList attribs( xAttribs ); + double fPercent = (double)attribs.getUnsignedInteger( XML_val, 0 ) / 100000.0; + mpNode->getNodeProperties()[ NP_ITERATEINTERVAL ] <<= fPercent; + } + break; + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; + } + +} } diff --git a/oox/source/ppt/commontimenodecontext.hxx b/oox/source/ppt/commontimenodecontext.hxx new file mode 100644 index 000000000000..245a96d5d3d9 --- /dev/null +++ b/oox/source/ppt/commontimenodecontext.hxx @@ -0,0 +1,70 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: commontimenodecontext.hxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + + +#ifndef OOX_PPT_COMMONTIMENODECONTEXT +#define OOX_PPT_COMMONTIMENODECONTEXT + + +#include +#include "oox/ppt/timenode.hxx" +#include "oox/ppt/timenodelistcontext.hxx" +#include "conditioncontext.hxx" + + +namespace oox { namespace ppt { + + /** CT_TLCommonTimeNodeData */ + class CommonTimeNodeContext + : public TimeNodeContext + { + public: + CommonTimeNodeContext( const ::oox::core::FragmentHandlerRef& xHandler, sal_Int32 aElement, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs, const TimeNodePtr & pNode); + ~CommonTimeNodeContext( ) throw( ); + + virtual void SAL_CALL endFastElement( sal_Int32 aElement ) throw ( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& /*xAttribs*/ ) throw ( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException ); + + private: + bool mbIterate; + ::com::sun::star::uno::Reference< ::com::sun::star::animations::XIterateContainer > mxIter; + }; + + +} } + + +#endif diff --git a/oox/source/ppt/conditioncontext.cxx b/oox/source/ppt/conditioncontext.cxx new file mode 100644 index 000000000000..59234c7f80e0 --- /dev/null +++ b/oox/source/ppt/conditioncontext.cxx @@ -0,0 +1,222 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: conditioncontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "conditioncontext.hxx" + +#include "comphelper/anytostring.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include + +#include +#include +#include +#include + +#include "oox/helper/attributelist.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/core/fragmenthandler.hxx" +#include "oox/core/context.hxx" +#include "oox/ppt/animationspersist.hxx" +#include "animationtypes.hxx" + +#include "timetargetelementcontext.hxx" +#include "tokens.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::animations; + +namespace oox { namespace ppt { + + CondContext::CondContext( const FragmentHandlerRef & xHandler, const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode, AnimationCondition & aValue ) + : TimeNodeContext( xHandler, NMSP_PPT|XML_cond, xAttribs, pNode ) + , maCond( aValue ) + { + maEvent.Trigger = EventTrigger::NONE; + maEvent.Repeat = 0; + + AttributeList attribs( xAttribs ); + if( attribs.hasAttribute( XML_evt ) ) + { + sal_Int32 nEvent = xAttribs->getOptionalValueToken( XML_evt, 0 ); + switch( nEvent ) + { + case XML_onBegin: + maEvent.Trigger = EventTrigger::ON_BEGIN; + break; + case XML_onEnd: + maEvent.Trigger = EventTrigger::ON_END; + break; + case XML_begin: + maEvent.Trigger = EventTrigger::BEGIN_EVENT; + break; + case XML_end: + maEvent.Trigger = EventTrigger::END_EVENT; + break; + case XML_onClick: + maEvent.Trigger = EventTrigger::ON_CLICK; + break; + case XML_onDblClick: + maEvent.Trigger = EventTrigger::ON_DBL_CLICK; + break; + case XML_onMouseOver: + maEvent.Trigger = EventTrigger::ON_MOUSE_ENTER; + break; + case XML_onMouseOut: + maEvent.Trigger = EventTrigger::ON_MOUSE_LEAVE; + break; + case XML_onNext: + maEvent.Trigger = EventTrigger::ON_NEXT; + break; + case XML_onPrev: + maEvent.Trigger = EventTrigger::ON_PREV; + break; + case XML_onStopAudio: + maEvent.Trigger = EventTrigger::ON_STOP_AUDIO; + break; + default: + break; + } + } + if( attribs.hasAttribute( XML_delay ) || ( maEvent.Trigger == EventTrigger::NONE ) ) + { + maEvent.Offset = GetTime( xAttribs->getOptionalValue( XML_delay ) ); + } + } + + CondContext::~CondContext( ) throw( ) + { + if( maCond.mnType == 0 ) + { + maCond.maValue = (maEvent.Trigger == EventTrigger::NONE) ? maEvent.Offset : makeAny( maEvent ); + } + } + + Reference< XFastContextHandler > SAL_CALL CondContext::createFastChildContext( ::sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case NMSP_PPT|XML_rtn: + { + // ST_TLTriggerRuntimeNode { first, last, all } + sal_Int32 aTok; + sal_Int16 nEnum; + aTok = xAttribs->getOptionalValueToken( XML_val, XML_first ); + switch( aTok ) + { + case XML_first: + nEnum = AnimationEndSync::FIRST; + break; + case XML_last: + nEnum = AnimationEndSync::LAST; + break; + case XML_all: + nEnum = AnimationEndSync::ALL; + break; + default: + break; + } + maCond.mnType = aElementToken; + maCond.maValue = makeAny( nEnum ); + break; + } + case NMSP_PPT|XML_tn: + { + maCond.mnType = aElementToken; + AttributeList attribs( xAttribs ); + sal_uInt32 nId = attribs.getUnsignedInteger( XML_val, 0 ); + maCond.maValue = makeAny( nId ); + break; + } + case NMSP_PPT|XML_tgtEl: + // CT_TLTimeTargetElement + xRet.set( new TimeTargetElementContext( getHandler(), maCond.getTarget() ) ); + break; + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; + + } + + + + /** CT_TLTimeConditionList */ + CondListContext::CondListContext( const FragmentHandlerRef & xHandler, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode, + AnimationConditionList & aCond ) + : TimeNodeContext( xHandler, aElement, xAttribs, pNode ) + , maConditions( aCond ) + { + } + + CondListContext::~CondListContext( ) + throw( ) + { + } + + Reference< XFastContextHandler > CondListContext::createFastChildContext( ::sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs ) throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + + switch( aElement ) + { + case NMSP_PPT|XML_cond: + // add a condition to the list + maConditions.push_back( AnimationCondition() ); + xRet.set( new CondContext( getHandler(), xAttribs, mpNode, maConditions.back() ) ); + break; + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; + } + + +} } + diff --git a/oox/source/ppt/conditioncontext.hxx b/oox/source/ppt/conditioncontext.hxx new file mode 100644 index 000000000000..c0e3dc139ddf --- /dev/null +++ b/oox/source/ppt/conditioncontext.hxx @@ -0,0 +1,92 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: conditioncontext.hxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + + +#ifndef OOX_PPT_CONDITIONCONTEXT +#define OOX_PPT_CONDITIONCONTEXT + +#include +#include + +#include "oox/core/fragmenthandler.hxx" +#include "oox/ppt/timenode.hxx" +#include "oox/ppt/timenodelistcontext.hxx" +#include "oox/ppt/animationspersist.hxx" + +namespace oox { namespace ppt { + + + /** CT_TLTimeCondition */ + class CondContext + : public TimeNodeContext + { + public: + CondContext( const ::oox::core::FragmentHandlerRef & xHandler, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode, AnimationCondition & aCond ); + ~CondContext( ) throw( ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs ) throw ( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException ); + + private: +// ::com::sun::star::uno::Any & maCond; + ::com::sun::star::animations::Event maEvent; +// AnimTargetElementPtr mpTarget; + AnimationCondition & maCond; + }; + + + + /** CT_TLTimeConditionList */ + class CondListContext + : public TimeNodeContext + { + public: + CondListContext( const ::oox::core::FragmentHandlerRef & xHandler, + sal_Int32 aElement, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode, AnimationConditionList & aCondList ); + ~CondListContext( ) throw( ); + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& /*xAttribs*/ ) throw ( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException ); + + private: + AnimationConditionList & maConditions; + }; + + +} } + + +#endif diff --git a/oox/source/ppt/customshowlistcontext.cxx b/oox/source/ppt/customshowlistcontext.cxx new file mode 100644 index 000000000000..01d57cee5c8c --- /dev/null +++ b/oox/source/ppt/customshowlistcontext.cxx @@ -0,0 +1,129 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: customshowlistcontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "customshowlistcontext.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + + +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace ppt { + +class CustomShowContext : public ::oox::core::Context +{ + CustomShow mrCustomShow; + +public: + CustomShowContext( const ::oox::core::FragmentHandlerRef& xHandler, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs, + CustomShow& rCustomShow ); + ~CustomShowContext( ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL + createFastChildContext( ::sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& /*xAttribs*/ ) + throw ( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException ); +}; + +CustomShowContext::CustomShowContext( const FragmentHandlerRef& xHandler, + const Reference< XFastAttributeList >& rxAttribs, + CustomShow& rCustomShow ) +: Context( xHandler ) +, mrCustomShow( rCustomShow ) +{ + mrCustomShow.maName = rxAttribs->getOptionalValue( XML_name ); + mrCustomShow.mnId = rxAttribs->getOptionalValue( XML_id ); +} + +CustomShowContext::~CustomShowContext( ) +{ +} + +Reference< XFastContextHandler > SAL_CALL CustomShowContext::createFastChildContext( sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) + throw ( SAXException, RuntimeException ) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case NMSP_PPT|XML_sld : + mrCustomShow.maSldLst.push_back( xAttribs->getOptionalValue( NMSP_RELATIONSHIPS | XML_id ) ); + default: + break; + } + if( !xRet.is() ) + xRet.set( this ); + + return xRet; +} + +//--------------------------------------------------------------------------- + +CustomShowListContext::CustomShowListContext( const FragmentHandlerRef& xHandler, + std::vector< CustomShow >& rCustomShowList ) +: Context( xHandler ) +, mrCustomShowList( rCustomShowList ) +{ +} + +CustomShowListContext::~CustomShowListContext( ) +{ +} + +Reference< XFastContextHandler > SAL_CALL CustomShowListContext::createFastChildContext( sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) + throw ( SAXException, RuntimeException ) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case NMSP_PPT|XML_custShow : + { + CustomShow aCustomShow; + mrCustomShowList.push_back( aCustomShow ); + xRet = new CustomShowContext( getHandler(), xAttribs, mrCustomShowList.back() ); + } + default: + break; + } + if( !xRet.is() ) + xRet.set( this ); + + return xRet; +} + + +} } diff --git a/oox/source/ppt/customshowlistcontext.hxx b/oox/source/ppt/customshowlistcontext.hxx new file mode 100644 index 000000000000..6cebe9acfe1d --- /dev/null +++ b/oox/source/ppt/customshowlistcontext.hxx @@ -0,0 +1,71 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: customshowlistcontext.hxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + + + +#ifndef OOX_POWERPOINT_CUSTOMSHOWLISTCONTEXT_HXX +#define OOX_POWERPOINT_CUSTOMSHOWLISTCONTEXT_HXX + +#include "oox/core/context.hxx" +#include + +namespace oox { namespace ppt { + + + struct CustomShow + { + ::rtl::OUString maName; + ::rtl::OUString mnId; + std::vector< rtl::OUString >maSldLst; + }; + + /** CT_ */ + class CustomShowListContext : public ::oox::core::Context + { + std::vector< CustomShow >& mrCustomShowList; + + public: + CustomShowListContext( const ::oox::core::FragmentHandlerRef& xHandler, + std::vector< CustomShow >& rCustomShowList ); + + ~CustomShowListContext( ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL + createFastChildContext( ::sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& /*xAttribs*/ ) + throw ( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException ); + }; + +} } + +#endif diff --git a/oox/source/ppt/layoutfragmenthandler.cxx b/oox/source/ppt/layoutfragmenthandler.cxx new file mode 100644 index 000000000000..2f2bdf83db81 --- /dev/null +++ b/oox/source/ppt/layoutfragmenthandler.cxx @@ -0,0 +1,92 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: layoutfragmenthandler.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "comphelper/anytostring.hxx" +#include "cppuhelper/exc_hlp.hxx" + +#include +#include + +#include "oox/ppt/layoutfragmenthandler.hxx" +#include "oox/drawingml/shapegroupcontext.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using rtl::OUString; +using namespace ::com::sun::star; +using namespace ::oox::core; +using namespace ::oox::drawingml; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::container; + +namespace oox { namespace ppt { + +// CT_SlideLayout + +LayoutFragmentHandler::LayoutFragmentHandler( const oox::core::XmlFilterRef& xFilter, const ::rtl::OUString& rFragmentPath, oox::ppt::SlidePersistPtr pMasterPersistPtr ) + throw() +: SlideFragmentHandler( xFilter, rFragmentPath, pMasterPersistPtr, Layout ) +{ +} + +LayoutFragmentHandler::~LayoutFragmentHandler() + throw() +{ + +} + +Reference< XFastContextHandler > LayoutFragmentHandler::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet( this ); + switch( aElementToken ) + { + case NMSP_PPT|XML_sldLayout: // CT_SlideLayout + mpSlidePersistPtr->setLayoutValueToken( xAttribs->getOptionalValueToken( XML_type, 0 ) ); // CT_SlideLayoutType + break; + default: + xRet.set( SlideFragmentHandler::createFastChildContext( aElementToken, xAttribs ) ); + } + return xRet; +} + +void SAL_CALL LayoutFragmentHandler::endDocument() + throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException) +{ +} + +} } + diff --git a/oox/source/ppt/makefile.mk b/oox/source/ppt/makefile.mk new file mode 100644 index 000000000000..3614459118a7 --- /dev/null +++ b/oox/source/ppt/makefile.mk @@ -0,0 +1,83 @@ +#************************************************************************* +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.2 $ +# +# last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ +# +# The Contents of this file are made available subject to +# the terms of GNU Lesser General Public License Version 2.1. +# +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2005 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=oox +TARGET=ppt +AUTOSEG=true + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/pptimport.obj\ + $(SLO)$/presentationfragmenthandler.obj\ + $(SLO)$/slidefragmenthandler.obj\ + $(SLO)$/layoutfragmenthandler.obj\ + $(SLO)$/backgroundproperties.obj\ + $(SLO)$/slidetransitioncontext.obj\ + $(SLO)$/slidetransition.obj\ + $(SLO)$/slidetimingcontext.obj\ + $(SLO)$/slidepersist.obj\ + $(SLO)$/slidemastertextstylescontext.obj \ + $(SLO)$/timenode.obj\ + $(SLO)$/pptfilterhelpers.obj\ + $(SLO)$/soundactioncontext.obj \ + $(SLO)$/commontimenodecontext.obj \ + $(SLO)$/commonbehaviorcontext.obj \ + $(SLO)$/conditioncontext.obj \ + $(SLO)$/timetargetelementcontext.obj \ + $(SLO)$/timenodelistcontext.obj \ + $(SLO)$/animationspersist.obj \ + $(SLO)$/animvariantcontext.obj \ + $(SLO)$/timeanimvaluecontext.obj \ + $(SLO)$/pptshape.obj \ + $(SLO)$/pptshapegroupcontext.obj \ + $(SLO)$/pptshapecontext.obj \ + $(SLO)$/pptshapepropertiescontext.obj \ + $(SLO)$/buildlistcontext.obj \ + $(SLO)$/animationtypes.obj \ + $(SLO)$/customshowlistcontext.obj + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk diff --git a/oox/source/ppt/pptfilterhelpers.cxx b/oox/source/ppt/pptfilterhelpers.cxx new file mode 100644 index 000000000000..18db5912686b --- /dev/null +++ b/oox/source/ppt/pptfilterhelpers.cxx @@ -0,0 +1,148 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: pptfilterhelpers.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + + +#include +#include + +#include "pptfilterhelpers.hxx" + + +using rtl::OUString; + +#include "pptfilterhelpers.hxx" + +namespace oox { namespace ppt { + + // BEGIN CUT&PASTE from sd pptanimations.hxx + + + static const transition gTransitions[] = + { + { "wipe(up)", ::com::sun::star::animations::TransitionType::BARWIPE, ::com::sun::star::animations::TransitionSubType::TOPTOBOTTOM, sal_True }, + { "wipe(right)", ::com::sun::star::animations::TransitionType::BARWIPE, ::com::sun::star::animations::TransitionSubType::LEFTTORIGHT, sal_False }, + { "wipe(left)", ::com::sun::star::animations::TransitionType::BARWIPE, ::com::sun::star::animations::TransitionSubType::LEFTTORIGHT, sal_True }, + { "wipe(down)", ::com::sun::star::animations::TransitionType::BARWIPE, ::com::sun::star::animations::TransitionSubType::TOPTOBOTTOM, sal_False }, + { "wheel(1)", ::com::sun::star::animations::TransitionType::PINWHEELWIPE, ::com::sun::star::animations::TransitionSubType::ONEBLADE, sal_True }, + { "wheel(2)", ::com::sun::star::animations::TransitionType::PINWHEELWIPE, ::com::sun::star::animations::TransitionSubType::TWOBLADEVERTICAL, sal_True }, + { "wheel(3)", ::com::sun::star::animations::TransitionType::PINWHEELWIPE, ::com::sun::star::animations::TransitionSubType::THREEBLADE, sal_True }, + { "wheel(4)", ::com::sun::star::animations::TransitionType::PINWHEELWIPE, ::com::sun::star::animations::TransitionSubType::FOURBLADE, sal_True }, + { "wheel(8)", ::com::sun::star::animations::TransitionType::PINWHEELWIPE, ::com::sun::star::animations::TransitionSubType::EIGHTBLADE, sal_True }, + { "strips(downLeft)", ::com::sun::star::animations::TransitionType::WATERFALLWIPE, ::com::sun::star::animations::TransitionSubType::HORIZONTALRIGHT, sal_True }, + { "strips(upLeft)", ::com::sun::star::animations::TransitionType::WATERFALLWIPE, ::com::sun::star::animations::TransitionSubType::HORIZONTALLEFT, sal_False }, + { "strips(downRight)", ::com::sun::star::animations::TransitionType::WATERFALLWIPE, ::com::sun::star::animations::TransitionSubType::HORIZONTALLEFT, sal_True }, + { "strips(upRight)", ::com::sun::star::animations::TransitionType::WATERFALLWIPE, ::com::sun::star::animations::TransitionSubType::HORIZONTALRIGHT, sal_False }, + { "barn(inVertical)", ::com::sun::star::animations::TransitionType::BARNDOORWIPE, ::com::sun::star::animations::TransitionSubType::VERTICAL, sal_False }, + { "barn(outVertical)", ::com::sun::star::animations::TransitionType::BARNDOORWIPE, ::com::sun::star::animations::TransitionSubType::VERTICAL, sal_True }, + { "barn(inHorizontal)", ::com::sun::star::animations::TransitionType::BARNDOORWIPE, ::com::sun::star::animations::TransitionSubType::HORIZONTAL, sal_False }, + { "barn(outHorizontal)", ::com::sun::star::animations::TransitionType::BARNDOORWIPE, ::com::sun::star::animations::TransitionSubType::HORIZONTAL, sal_True }, + { "randombar(vertical)", ::com::sun::star::animations::TransitionType::RANDOMBARWIPE, ::com::sun::star::animations::TransitionSubType::VERTICAL, sal_True}, + { "randombar(horizontal)", ::com::sun::star::animations::TransitionType::RANDOMBARWIPE, ::com::sun::star::animations::TransitionSubType::HORIZONTAL, sal_True }, + { "checkerboard(down)", ::com::sun::star::animations::TransitionType::CHECKERBOARDWIPE, ::com::sun::star::animations::TransitionSubType::DOWN, sal_True}, + { "checkerboard(across)", ::com::sun::star::animations::TransitionType::CHECKERBOARDWIPE, ::com::sun::star::animations::TransitionSubType::ACROSS, sal_True }, + { "plus(out)", ::com::sun::star::animations::TransitionType::FOURBOXWIPE, ::com::sun::star::animations::TransitionSubType::CORNERSIN, sal_False }, + { "plus(in)", ::com::sun::star::animations::TransitionType::FOURBOXWIPE, ::com::sun::star::animations::TransitionSubType::CORNERSIN, sal_True }, + { "diamond(out)", ::com::sun::star::animations::TransitionType::IRISWIPE, ::com::sun::star::animations::TransitionSubType::DIAMOND, sal_True }, + { "diamond(in)", ::com::sun::star::animations::TransitionType::IRISWIPE, ::com::sun::star::animations::TransitionSubType::DIAMOND, sal_False }, + { "circle(out)", ::com::sun::star::animations::TransitionType::ELLIPSEWIPE, ::com::sun::star::animations::TransitionSubType::HORIZONTAL, sal_True }, + { "circle(in)", ::com::sun::star::animations::TransitionType::ELLIPSEWIPE, ::com::sun::star::animations::TransitionSubType::HORIZONTAL, sal_False }, + { "box(out)", ::com::sun::star::animations::TransitionType::IRISWIPE, ::com::sun::star::animations::TransitionSubType::RECTANGLE, sal_True }, + { "box(in)", ::com::sun::star::animations::TransitionType::IRISWIPE, ::com::sun::star::animations::TransitionSubType::RECTANGLE, sal_False }, + { "wedge", ::com::sun::star::animations::TransitionType::FANWIPE, ::com::sun::star::animations::TransitionSubType::CENTERTOP, sal_True }, + { "blinds(vertical)", ::com::sun::star::animations::TransitionType::BLINDSWIPE, ::com::sun::star::animations::TransitionSubType::VERTICAL, sal_True }, + { "blinds(horizontal)", ::com::sun::star::animations::TransitionType::BLINDSWIPE, ::com::sun::star::animations::TransitionSubType::HORIZONTAL, sal_True }, + { "fade", ::com::sun::star::animations::TransitionType::FADE, ::com::sun::star::animations::TransitionSubType::CROSSFADE, sal_True }, + { "slide(fromTop)", ::com::sun::star::animations::TransitionType::SLIDEWIPE, ::com::sun::star::animations::TransitionSubType::FROMTOP, sal_True }, + { "slide(fromRight)", ::com::sun::star::animations::TransitionType::SLIDEWIPE, ::com::sun::star::animations::TransitionSubType::FROMRIGHT, sal_True }, + { "slide(fromLeft)", ::com::sun::star::animations::TransitionType::SLIDEWIPE, ::com::sun::star::animations::TransitionSubType::FROMLEFT, sal_True }, + { "slide(fromBottom)", ::com::sun::star::animations::TransitionType::SLIDEWIPE, ::com::sun::star::animations::TransitionSubType::FROMBOTTOM, sal_True }, + { "dissolve", ::com::sun::star::animations::TransitionType::DISSOLVE, ::com::sun::star::animations::TransitionSubType::DEFAULT, sal_True }, + { "image", ::com::sun::star::animations::TransitionType::DISSOLVE, ::com::sun::star::animations::TransitionSubType::DEFAULT, sal_True }, // TODO + { NULL, 0, 0, sal_False } + }; + + const transition* transition::find( const OUString& rName ) + { + const transition* p = gTransitions; + + while( p->mpName ) + { + if( rName.compareToAscii( p->mpName ) == 0 ) + return p; + + p++; + } + + return NULL; + } + + + bool convertMeasure( OUString& rString ) + { + bool bRet = false; + + const sal_Char* pSource[] = { "ppt_x", "ppt_y", "ppt_w", "ppt_h", NULL }; + const sal_Char* pDest[] = { "x", "y", "width", "height", NULL }; + sal_Int32 nIndex = 0; + + const sal_Char** ps = pSource; + const sal_Char** pd = pDest; + + while( *ps ) + { + const OUString aSearch( OUString::createFromAscii( *ps ) ); + while( (nIndex = rString.indexOf( aSearch, nIndex )) != -1 ) + { + sal_Int32 nLength = aSearch.getLength(); + if( nIndex && (rString.getStr()[nIndex-1] == '#' ) ) + { + nIndex--; + nLength++; + } + + const OUString aNew( OUString::createFromAscii( *pd ) ); + rString = rString.replaceAt( nIndex, nLength, aNew ); + nIndex += aNew.getLength(); + bRet = true; + } + ps++; + pd++; + } + + return bRet; + } + + +} } diff --git a/oox/source/ppt/pptfilterhelpers.hxx b/oox/source/ppt/pptfilterhelpers.hxx new file mode 100644 index 000000000000..82b301bccae3 --- /dev/null +++ b/oox/source/ppt/pptfilterhelpers.hxx @@ -0,0 +1,112 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: pptfilterhelpers.hxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + + +#ifndef OOX_PPT_PPTFILTERHELPERS +#define OOX_PPT_PPTFILTERHELPERS + +#include + +namespace oox { namespace ppt { + + +//BEGIN CUT&PASTE from sd pptanimations.hxx + // conversion of MS to OOo attributes. + enum MS_AttributeNames + { + MS_PPT_X, MS_PPT_Y, MS_PPT_W, MS_PPT_H, MS_PPT_C, MS_R, MS_XSHEAR, MS_FILLCOLOR, MS_FILLTYPE, + MS_STROKECOLOR, MS_STROKEON, MS_STYLECOLOR, MS_STYLEROTATION, MS_FONTWEIGHT, + MS_STYLEUNDERLINE, MS_STYLEFONTFAMILY, MS_STYLEFONTSIZE, MS_STYLEFONTSTYLE, + MS_STYLEVISIBILITY, MS_STYLEOPACITY, MS_UNKNOWN + }; + + struct ImplAttributeNameConversion + { + MS_AttributeNames meAttribute; + const char* mpMSName; + const char* mpAPIName; + }; + + static const ImplAttributeNameConversion gImplConversionList[] = + { + { MS_PPT_X, "ppt_x", "X" }, + { MS_PPT_Y, "ppt_y", "Y" }, + { MS_PPT_W, "ppt_w", "Width" }, + { MS_PPT_H, "ppt_h", "Height" }, + { MS_PPT_C, "ppt_c", "DimColor" }, + { MS_R, "r", "Rotate" }, + { MS_XSHEAR, "xshear", "SkewX" }, + { MS_FILLCOLOR, "fillColor", "FillColor" }, + { MS_FILLCOLOR, "fillcolor", "FillColor" }, + { MS_FILLTYPE, "fill.type", "FillStyle" }, + { MS_STROKECOLOR, "stroke.color", "LineColor" }, + { MS_STROKEON, "stroke.on", "LineStyle" }, + { MS_STYLECOLOR, "style.color", "CharColor" }, + { MS_STYLEROTATION, "style.rotation", "Rotate" }, + { MS_FONTWEIGHT, "style.fontWeight", "CharWeight" }, + { MS_STYLEUNDERLINE, "style.textDecorationUnderline","CharUnderline" }, + { MS_STYLEFONTFAMILY, "style.fontFamily", "CharFontName" }, + { MS_STYLEFONTSIZE, "style.fontSize", "CharHeight" }, + { MS_STYLEFONTSTYLE, "style.fontStyle", "CharPosture" }, + { MS_STYLEVISIBILITY, "style.visibility", "Visibility" }, + { MS_STYLEOPACITY, "style.opacity", "Opacity" }, + { MS_UNKNOWN, NULL, NULL } + }; + //END CUT&PASTE + + + // BEGIN CUT&PASTE from sd pptanimations.hxx + struct transition + { + const sal_Char* mpName; + sal_Int16 mnType; + sal_Int16 mnSubType; + sal_Bool mbDirection; // true: default geometric direction + + static const transition* find( const rtl::OUString& rName ); + static const sal_Char* find( const sal_Int16 mnType, const sal_Int16 mnSubType, const sal_Bool bDirection ); + }; + // END CUT&PASTE + + + // BEGIN CUT&PASTE from sd pptinanimation.cxx + bool convertMeasure( ::rtl::OUString& rString ); + // END CUT&PASTE from sd pptinanimation.cxx + + +} } + + +#endif diff --git a/oox/source/ppt/pptimport.cxx b/oox/source/ppt/pptimport.cxx new file mode 100644 index 000000000000..4752f1bdb83a --- /dev/null +++ b/oox/source/ppt/pptimport.cxx @@ -0,0 +1,135 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: pptimport.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/ppt/pptimport.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace oox::core; + +namespace oox { namespace ppt { + +OUString SAL_CALL PowerPointImport_getImplementationName() throw() +{ + return CREATE_OUSTRING( "com.sun.star.comp.Impress.oox.PowerPointImport" ); +} + +uno::Sequence< OUString > SAL_CALL PowerPointImport_getSupportedServiceNames() throw() +{ + const OUString aServiceName = CREATE_OUSTRING( "com.sun.star.comp.ooxpptx" ); + const Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +uno::Reference< uno::XInterface > SAL_CALL PowerPointImport_createInstance(const uno::Reference< lang::XMultiServiceFactory > & rSMgr ) throw( uno::Exception ) +{ + return (cppu::OWeakObject*)new PowerPointImport( rSMgr ); +} + +PowerPointImport::PowerPointImport( const uno::Reference< lang::XMultiServiceFactory > & rSMgr ) + : XmlFilterBase( rSMgr ) +{ +} + +PowerPointImport::~PowerPointImport() +{ +} + +bool PowerPointImport::importDocument() throw() +{ + OUString aFragmentPath = getFragmentPathFromType( CREATE_RELATIONS_TYPE( "officeDocument" ) ); + return importFragment( new PresentationFragmentHandler( this, aFragmentPath ) ); +} + +bool PowerPointImport::exportDocument() throw() +{ + return false; +} + +sal_Int32 PowerPointImport::getSchemeClr( sal_Int32 nColorSchemeToken ) const +{ + sal_Int32 nColor = 0; + if ( mpActualSlidePersist ) + { + sal_Bool bColorMapped = sal_False; + oox::drawingml::ClrMapPtr pClrMapPtr( mpActualSlidePersist->getClrMap() ); + if ( pClrMapPtr ) + bColorMapped = pClrMapPtr->getColorMap( nColorSchemeToken ); + + if ( !bColorMapped ) // try masterpage mapping + { + SlidePersistPtr pMasterPersist = mpActualSlidePersist->getMasterPersist(); + if ( pMasterPersist ) + { + pClrMapPtr = pMasterPersist->getClrMap(); + if ( pClrMapPtr ) + bColorMapped = pClrMapPtr->getColorMap( nColorSchemeToken ); + } + } + oox::drawingml::ClrSchemePtr pClrSchemePtr( mpActualSlidePersist->getClrScheme() ); + if ( pClrSchemePtr ) + pClrSchemePtr->getColor( nColorSchemeToken, nColor ); + else + { + drawingml::ThemePtr pTheme = mpActualSlidePersist->getTheme(); + if( pTheme ) + { + pTheme->getClrScheme()->getColor( nColorSchemeToken, nColor ); + } + else + { + OSL_TRACE("OOX: PowerPointImport::mpThemePtr is NULL"); + } + } + } + return nColor; +} + +const oox::vml::DrawingPtr PowerPointImport::getDrawings() +{ + oox::vml::DrawingPtr xRet; + if ( mpActualSlidePersist ) + xRet = mpActualSlidePersist->getDrawing(); + return xRet; +} + +OUString PowerPointImport::implGetImplementationName() const +{ + return PowerPointImport_getImplementationName(); +} + +}} diff --git a/oox/source/ppt/pptshape.cxx b/oox/source/ppt/pptshape.cxx new file mode 100644 index 000000000000..8335ba57c408 --- /dev/null +++ b/oox/source/ppt/pptshape.cxx @@ -0,0 +1,179 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: pptshape.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/ppt/pptshape.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +#include +#include +#include +#include +#include +#include +#include "oox/ppt/slidepersist.hxx" + +using rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::drawing; + +namespace oox { namespace ppt { + +PPTShape::PPTShape( const oox::ppt::ShapeLocation eShapeLocation, const sal_Char* pServiceName ) +: Shape( pServiceName ) +, meShapeLocation( eShapeLocation ) +, mbReferenced( sal_False ) +{ +} + +PPTShape::~PPTShape() +{ +} + +void PPTShape::addShape( const oox::core::XmlFilterBase& rFilterBase, const Reference< XModel > &rxModel, const oox::ppt::SlidePersist& rSlidePersist, const oox::drawingml::ThemePtr pThemePtr, + std::map< OUString, ::oox::drawingml::ShapePtr > & aShapeMap, const Reference< XShapes >& rxShapes, const awt::Rectangle* pShapeRect ) +{ + // only placeholder from layout are being inserted + if ( mnSubType && ( meShapeLocation == Master ) ) + return; + try + { + rtl::OUString sServiceName( msServiceName ); + if( sServiceName.getLength() ) + { + oox::drawingml::TextListStylePtr aMasterTextListStyle; + Reference< lang::XMultiServiceFactory > xServiceFact( rxModel, UNO_QUERY_THROW ); + switch( mnSubType ) + { + case XML_ctrTitle : + case XML_title : + { + const rtl::OUString sTitleShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.TitleTextShape" ) ); + sServiceName = sTitleShapeService; + aMasterTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getTitleTextStyle() : rSlidePersist.getTitleTextStyle(); + } + break; + case XML_obj : + { + const rtl::OUString sOutlinerShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.OutlinerShape" ) ); + sServiceName = sOutlinerShapeService; + aMasterTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle(); + } + break; + case XML_body : + { + const rtl::OUString sNotesShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.NotesShape" ) ); + const rtl::OUString sOutlinerShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.OutlinerShape" ) ); + if ( rSlidePersist.isNotesPage() ) + { + sServiceName = sNotesShapeService; + aMasterTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getNotesTextStyle() : rSlidePersist.getNotesTextStyle(); + } + else + { + sServiceName = sOutlinerShapeService; + aMasterTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle(); + } + } + break; + case XML_dt : + { + const rtl::OUString sDateTimeShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.DateTimeShape" ) ); + sServiceName = sDateTimeShapeService; + } + break; + case XML_hdr : + { + const rtl::OUString sHeaderShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.HeaderShape" ) ); + sServiceName = sHeaderShapeService; + } + break; + case XML_ftr : + { + const rtl::OUString sFooterShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.FooterShape" ) ); + sServiceName = sFooterShapeService; + } + break; + case XML_sldNum : + { + const rtl::OUString sSlideNumberShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.SlideNumberShape" ) ); + sServiceName = sSlideNumberShapeService; + } + break; + case XML_sldImg : + { + const rtl::OUString sPageShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.PageShape" ) ); + sServiceName = sPageShapeService; + } + break; + + default: + break; + + } + if ( !aMasterTextListStyle.get() ) + aMasterTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getOtherTextStyle() : rSlidePersist.getOtherTextStyle(); + setMasterTextListStyle( aMasterTextListStyle ); + + Reference< XShape > xShape( createAndInsert( rFilterBase, sServiceName, rxModel, pThemePtr, rxShapes, pShapeRect ) ); + + if( msId.getLength() ) + { + aShapeMap[ msId ] = shared_from_this(); + } + + // if this is a group shape, we have to add also each child shape + Reference< XShapes > xShapes( xShape, UNO_QUERY ); + if ( xShapes.is() ) + addChilds( rFilterBase, *this, rxModel, pThemePtr, aShapeMap, xShapes, pShapeRect ? *pShapeRect : awt::Rectangle( maPosition.X, maPosition.Y, maSize.Width, maSize.Height ) ); + } + } + catch( const Exception& ) + { + } +} + +void PPTShape::applyShapeReference( const oox::drawingml::Shape& rReferencedShape ) +{ + Shape::applyShapeReference( rReferencedShape ); +} + +} } diff --git a/oox/source/ppt/pptshapecontext.cxx b/oox/source/ppt/pptshapecontext.cxx new file mode 100644 index 000000000000..00631845d63b --- /dev/null +++ b/oox/source/ppt/pptshapecontext.cxx @@ -0,0 +1,209 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: pptshapecontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include +#include +#include +#include +#include + +#include "oox/ppt/pptshape.hxx" +#include "oox/ppt/pptshapecontext.hxx" +#include "oox/ppt/pptshapepropertiescontext.hxx" +#include "oox/ppt/slidepersist.hxx" +#include "oox/drawingml/shapestylecontext.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/drawingml/fillpropertiesgroupcontext.hxx" +#include "oox/drawingml/lineproperties.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/drawingml/customshapegeometry.hxx" +#include "oox/drawingml/textbodycontext.hxx" +#include "tokens.hxx" + +using rtl::OUString; +using namespace oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace ppt { + +// CT_Shape +PPTShapeContext::PPTShapeContext( const oox::ppt::SlidePersistPtr pSlidePersistPtr, const FragmentHandlerRef& xHandler, + oox::drawingml::ShapePtr pMasterShapePtr, oox::drawingml::ShapePtr pShapePtr ) +: oox::drawingml::ShapeContext( xHandler, pMasterShapePtr, pShapePtr ) +, mpSlidePersistPtr( pSlidePersistPtr ) +{ +} + +oox::drawingml::ShapePtr findPlaceholder( const sal_Int32 nMasterPlaceholder, std::vector< oox::drawingml::ShapePtr >& rShapes ) +{ + oox::drawingml::ShapePtr aShapePtr; + std::vector< oox::drawingml::ShapePtr >::reverse_iterator aRevIter( rShapes.rbegin() ); + while( aRevIter != rShapes.rend() ) + { + if ( (*aRevIter)->getSubType() == nMasterPlaceholder ) + { + aShapePtr = *aRevIter; + break; + } + std::vector< oox::drawingml::ShapePtr >& rChilds = (*aRevIter)->getChilds(); + aShapePtr = findPlaceholder( nMasterPlaceholder, rChilds ); + if ( aShapePtr.get() ) + break; + aRevIter++; + } + return aShapePtr; +} + +// if nFirstPlaceholder can't be found, it will be searched for nSecondPlaceholder +oox::drawingml::ShapePtr findPlaceholder( sal_Int32 nFirstPlaceholder, sal_Int32 nSecondPlaceholder, std::vector< oox::drawingml::ShapePtr >& rShapes ) +{ + oox::drawingml::ShapePtr pPlaceholder = findPlaceholder( nFirstPlaceholder, rShapes ); + return !nSecondPlaceholder || pPlaceholder.get() ? pPlaceholder : findPlaceholder( nSecondPlaceholder, rShapes ); +} + +Reference< XFastContextHandler > PPTShapeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + // nvSpPr CT_ShapeNonVisual begin +// case NMSP_PPT|XML_drElemPr: +// break; + case NMSP_PPT|XML_cNvPr: + mpShapePtr->setId( xAttribs->getOptionalValue( XML_id ) ); + mpShapePtr->setName( xAttribs->getOptionalValue( XML_name ) ); + break; + case NMSP_PPT|XML_ph: + { + sal_Int32 nSubType( xAttribs->getOptionalValueToken( XML_type, XML_obj ) ); + mpShapePtr->setSubType( nSubType ); + mpShapePtr->setIndex( xAttribs->getOptionalValue( XML_idx ).toInt32() ); + if ( nSubType ) + { + PPTShape* pPPTShapePtr = dynamic_cast< PPTShape* >( mpShapePtr.get() ); + if ( pPPTShapePtr ) + { + oox::ppt::ShapeLocation eShapeLocation = pPPTShapePtr->getShapeLocation(); + if ( ( eShapeLocation == Slide ) || ( eShapeLocation == Layout ) ) + { + // inheriting properties from placeholder objects by cloning shape + + sal_Int32 nFirstPlaceholder = 0; + sal_Int32 nSecondPlaceholder = 0; + switch( nSubType ) + { + case XML_ctrTitle : // slide/layout + nFirstPlaceholder = XML_ctrTitle; + nSecondPlaceholder = XML_title; + break; + case XML_subTitle : // slide/layout + nFirstPlaceholder = XML_subTitle; + nSecondPlaceholder = XML_title; + break; + case XML_obj : // slide/layout + nFirstPlaceholder = XML_body; + break; + case XML_dt : // slide/layout/master/notes/notesmaster/handoutmaster + case XML_sldNum : // slide/layout/master/notes/notesmaster/handoutmaster + case XML_ftr : // slide/layout/master/notes/notesmaster/handoutmaster + case XML_hdr : // notes/notesmaster/handoutmaster + case XML_body : // slide/layout/master/notes/notesmaster + case XML_title : // slide/layout/master/ + case XML_chart : // slide/layout + case XML_tbl : // slide/layout + case XML_clipArt : // slide/layout + case XML_dgm : // slide/layout + case XML_media : // slide/layout + case XML_sldImg : // notes/notesmaster + case XML_pic : // slide/layout + nFirstPlaceholder = nSubType; + default: + break; + } + if ( nFirstPlaceholder ) + { + oox::drawingml::ShapePtr pPlaceholder; + if ( eShapeLocation == Layout ) // for layout objects the referenced object can be found within the same shape tree + pPlaceholder = findPlaceholder( nFirstPlaceholder, nSecondPlaceholder, mpSlidePersistPtr->getShapes()->getChilds() ); + else if ( eShapeLocation == Slide ) // normal slide shapes have to search within the corresponding master tree for referenced objects + { + SlidePersistPtr pMasterPersist( mpSlidePersistPtr->getMasterPersist() ); + if ( pMasterPersist.get() ) + pPlaceholder = findPlaceholder( nFirstPlaceholder, nSecondPlaceholder, pMasterPersist->getShapes()->getChilds() ); + } + if ( pPlaceholder.get() ) + { + mpShapePtr->applyShapeReference( *pPlaceholder.get() ); + PPTShape* pPPTShape = dynamic_cast< PPTShape* >( pPlaceholder.get() ); + if ( pPPTShape ) + pPPTShape->setReferenced( sal_True ); + } + } + } + } + } + break; + } + // nvSpPr CT_ShapeNonVisual end + + case NMSP_PPT|XML_spPr: + xRet = new PPTShapePropertiesContext( this, *(mpShapePtr.get()) ); + break; + + case NMSP_PPT|XML_style: + xRet = new oox::drawingml::ShapeStyleContext( this, *(mpShapePtr.get()) ); + break; + + case NMSP_PPT|XML_txBody: + { + xRet = new oox::drawingml::TextBodyContext( getHandler(), *(mpShapePtr.get()) ); + break; + } + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; +} + + +} } diff --git a/oox/source/ppt/pptshapegroupcontext.cxx b/oox/source/ppt/pptshapegroupcontext.cxx new file mode 100644 index 000000000000..f5b7a0703237 --- /dev/null +++ b/oox/source/ppt/pptshapegroupcontext.cxx @@ -0,0 +1,123 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: pptshapegroupcontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include +#include +#include + +#include "oox/ppt/pptshape.hxx" +#include "oox/ppt/pptshapecontext.hxx" +#include "oox/ppt/pptshapegroupcontext.hxx" +#include "oox/drawingml/graphicshapecontext.hxx" +#include "oox/drawingml/lineproperties.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/drawingml/customshapegeometry.hxx" +#include "oox/drawingml/textbodycontext.hxx" +#include "oox/drawingml/connectorshapecontext.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using rtl::OUString; +using namespace oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace ppt { + +PPTShapeGroupContext::PPTShapeGroupContext( const oox::ppt::SlidePersistPtr pSlidePersistPtr, const ShapeLocation eShapeLocation, + const FragmentHandlerRef& xHandler, sal_Int32 aElementToken, + oox::drawingml::ShapePtr pMasterShapePtr, oox::drawingml::ShapePtr pGroupShapePtr ) +: ShapeGroupContext( xHandler, aElementToken, pMasterShapePtr, pGroupShapePtr ) +, mpSlidePersistPtr( pSlidePersistPtr ) +, meShapeLocation( eShapeLocation ) +{ +} + +Reference< XFastContextHandler > PPTShapeGroupContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case NMSP_PPT|XML_cNvPr: + mpGroupShapePtr->setId( xAttribs->getOptionalValue( XML_id ) ); + mpGroupShapePtr->setName( xAttribs->getOptionalValue( XML_name ) ); + break; + case NMSP_PPT|XML_ph: + mpGroupShapePtr->setSubType( xAttribs->getOptionalValueToken( XML_type, FastToken::DONTKNOW ) ); + mpGroupShapePtr->setIndex( xAttribs->getOptionalValue( XML_idx ).toInt32() ); + break; + // nvSpPr CT_ShapeNonVisual end + + case NMSP_PPT|XML_grpSpPr: + xRet = new oox::drawingml::ShapePropertiesContext( this, *(mpGroupShapePtr.get()) ); + break; + case NMSP_PPT|XML_spPr: + xRet = new oox::drawingml::ShapePropertiesContext( this, *(mpGroupShapePtr.get()) ); + break; +/* + case NMSP_PPT|XML_style: + xRet = new ShapeStyleContext( getParser() ); + break; +*/ + case NMSP_PPT|XML_cxnSp: // connector shape + xRet.set( new oox::drawingml::ConnectorShapeContext( getHandler(), aElementToken, mpGroupShapePtr, oox::drawingml::ShapePtr( new PPTShape( meShapeLocation, "com.sun.star.drawing.ConnectorShape" ) ) ) ); + break; + case NMSP_PPT|XML_grpSp: // group shape + xRet.set( new PPTShapeGroupContext( mpSlidePersistPtr, meShapeLocation, getHandler(), aElementToken, mpGroupShapePtr, oox::drawingml::ShapePtr( new PPTShape( meShapeLocation, "com.sun.star.drawing.GroupShape" ) ) ) ); + break; + case NMSP_PPT|XML_sp: // Shape + xRet.set( new oox::ppt::PPTShapeContext( mpSlidePersistPtr, getHandler(), mpGroupShapePtr, oox::drawingml::ShapePtr( new PPTShape( meShapeLocation, "com.sun.star.drawing.CustomShape" ) ) ) ); + break; + case NMSP_PPT|XML_pic: // CT_Picture + xRet.set( new oox::drawingml::GraphicShapeContext( getHandler(), mpGroupShapePtr, oox::drawingml::ShapePtr( new PPTShape( meShapeLocation, "com.sun.star.drawing.GraphicObjectShape" ) ) ) ); + break; + case NMSP_PPT|XML_graphicFrame: // CT_GraphicalObjectFrame + xRet.set( new oox::drawingml::GraphicalObjectFrameContext( getHandler(), mpGroupShapePtr, oox::drawingml::ShapePtr( new PPTShape( meShapeLocation, "com.sun.star.drawing.OLE2Shape" ) ) ) ); + break; + + } + if( !xRet.is() ) + xRet.set( this ); + + + return xRet; +} + +} } diff --git a/oox/source/ppt/pptshapepropertiescontext.cxx b/oox/source/ppt/pptshapepropertiescontext.cxx new file mode 100644 index 000000000000..c4455fd310c5 --- /dev/null +++ b/oox/source/ppt/pptshapepropertiescontext.cxx @@ -0,0 +1,94 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: pptshapepropertiescontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include +#include +#include +#include +#include + +#include "oox/ppt/pptshape.hxx" +#include "oox/ppt/pptshapepropertiescontext.hxx" +#include "oox/ppt/slidepersist.hxx" +#include "oox/drawingml/shapestylecontext.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/drawingml/fillpropertiesgroupcontext.hxx" +#include "oox/drawingml/lineproperties.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/drawingml/customshapegeometry.hxx" +#include "oox/drawingml/textbodycontext.hxx" +#include "tokens.hxx" + +using rtl::OUString; +using namespace oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace ppt { + +// CT_Shape +PPTShapePropertiesContext::PPTShapePropertiesContext( const ContextRef& xParent, ::oox::drawingml::Shape& rShape ) +: ShapePropertiesContext( xParent, rShape ) +{ +} + +Reference< XFastContextHandler > PPTShapePropertiesContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case NMSP_DRAWINGML | XML_xfrm: + { + static const OUString sIsPlaceholderDependent( RTL_CONSTASCII_USTRINGPARAM( "IsPlaceholderDependent" ) ); + mrShape.getShapeProperties()[ sIsPlaceholderDependent ] <<= Any( sal_False ); + + xRet = ShapePropertiesContext::createFastChildContext( aElementToken, xAttribs ); + } + break; + + default: + xRet = ShapePropertiesContext::createFastChildContext( aElementToken, xAttribs ); + break; + } + return xRet; +} + +} } diff --git a/oox/source/ppt/presentationfragmenthandler.cxx b/oox/source/ppt/presentationfragmenthandler.cxx new file mode 100644 index 000000000000..b511f2705eb7 --- /dev/null +++ b/oox/source/ppt/presentationfragmenthandler.cxx @@ -0,0 +1,301 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: presentationfragmenthandler.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "comphelper/anytostring.hxx" +#include "cppuhelper/exc_hlp.hxx" + +#include +#include +#include +#include +#include +#include +#include + +#include "oox/drawingml/theme.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/drawingml/themefragmenthandler.hxx" +#include "oox/drawingml/textliststylecontext.hxx" +#include "oox/ppt/pptshape.hxx" +#include "oox/ppt/presentationfragmenthandler.hxx" +#include "oox/ppt/slidefragmenthandler.hxx" +#include "oox/ppt/layoutfragmenthandler.hxx" +#include "oox/ppt/pptimport.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using rtl::OUString; +using namespace ::com::sun::star; +using namespace ::oox::core; +using namespace ::oox::drawingml; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::presentation; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace ppt { + +PresentationFragmentHandler::PresentationFragmentHandler( const XmlFilterRef& xFilter, const OUString& rFragmentPath ) throw() +: FragmentHandler( xFilter, rFragmentPath ) +, mpTextListStyle( new TextListStyle()) +{ +} + +PresentationFragmentHandler::~PresentationFragmentHandler() throw() +{ + +} +void PresentationFragmentHandler::startDocument() throw (SAXException, RuntimeException) +{ +} + +void PresentationFragmentHandler::endDocument() throw (SAXException, RuntimeException) +{ + try + { + Reference< frame::XModel > xModel( getFilter()->getModel() ); + Reference< drawing::XDrawPage > xSlide; + sal_uInt32 nSlide; + + // importing slide pages and its corresponding notes page + Reference< drawing::XDrawPagesSupplier > xDPS( xModel, uno::UNO_QUERY_THROW ); + Reference< drawing::XDrawPages > xDrawPages( xDPS->getDrawPages(), uno::UNO_QUERY_THROW ); + + for( nSlide = 0; nSlide < maSlidesVector.size(); nSlide++ ) + { + if( nSlide == 0 ) + xDrawPages->getByIndex( 0 ) >>= xSlide; + else + xSlide = xDrawPages->insertNewByIndex( nSlide ); + + OUString aSlideFragmentPath = getFragmentPathFromRelId( maSlidesVector[ nSlide ] ); + if( aSlideFragmentPath.getLength() > 0 ) + { + SlidePersistPtr pMasterPersistPtr; + SlidePersistPtr pSlidePersistPtr( new SlidePersist( sal_False, sal_False, xSlide, + ShapePtr( new PPTShape( Slide, "com.sun.star.drawing.GroupShape" ) ), mpTextListStyle ) ); + + FragmentHandlerRef xSlideFragmentHandler( new SlideFragmentHandler( getFilter(), aSlideFragmentPath, pSlidePersistPtr, Slide ) ); + + // importing the corresponding masterpage/layout + OUString aLayoutFragmentPath = xSlideFragmentHandler->getFragmentPathFromType( CREATE_RELATIONS_TYPE( "slideLayout" ) ); + if ( aLayoutFragmentPath.getLength() > 0 ) + { + // importing layout + RelationsRef xLayoutRelations = getFilter()->importRelations( aLayoutFragmentPath ); + if( const Relation* pMaster = xLayoutRelations->getRelationFromType( CREATE_RELATIONS_TYPE( "slideMaster" ) ) ) + { + OUString aMasterFragmentPath = Relations::getFragmentPathFromTarget( aLayoutFragmentPath, pMaster->maTarget ); + if ( aMasterFragmentPath.getLength() ) + { + // check if the corresponding masterpage+layout has already been imported + std::vector< SlidePersistPtr >& rMasterPages( (dynamic_cast< PowerPointImport& >( *getFilter() )).getMasterPages() ); + std::vector< SlidePersistPtr >::iterator aIter( rMasterPages.begin() ); + while( aIter != rMasterPages.end() ) + { + if ( ( (*aIter)->getPath() == aMasterFragmentPath ) && ( (*aIter)->getLayoutPath() == aLayoutFragmentPath ) ) + { + pMasterPersistPtr = *aIter; + break; + } + aIter++; + } + if ( aIter == rMasterPages.end() ) + { // masterpersist not found, we have to load it + Reference< drawing::XDrawPage > xMasterPage; + Reference< drawing::XMasterPagesSupplier > xMPS( xModel, uno::UNO_QUERY_THROW ); + Reference< drawing::XDrawPages > xMasterPages( xMPS->getMasterPages(), uno::UNO_QUERY_THROW ); + + if( !((dynamic_cast< PowerPointImport& >( *getFilter() )).getMasterPages().size() )) + xMasterPages->getByIndex( 0 ) >>= xMasterPage; + else + xMasterPage = xMasterPages->insertNewByIndex( xMasterPages->getCount() ); + + pMasterPersistPtr = SlidePersistPtr( new SlidePersist( sal_True, sal_False, xMasterPage, + ShapePtr( new PPTShape( Master, "com.sun.star.drawing.GroupShape" ) ), mpTextListStyle ) ); + pMasterPersistPtr->setLayoutPath( aLayoutFragmentPath ); + (dynamic_cast< PowerPointImport& >( *getFilter() )).getMasterPages().push_back( pMasterPersistPtr ); + (dynamic_cast< PowerPointImport& >( *getFilter() )).setActualSlidePersist( pMasterPersistPtr ); + FragmentHandlerRef xMasterFragmentHandler( new SlideFragmentHandler( getFilter(), aMasterFragmentPath, pMasterPersistPtr, Master ) ); + + // set the correct theme + OUString aThemeFragmentPath = xMasterFragmentHandler->getFragmentPathFromType( CREATE_RELATIONS_TYPE( "theme" ) ); + if( aThemeFragmentPath.getLength() > 0 ) + { + std::map< OUString, oox::drawingml::ThemePtr >& rThemes( (dynamic_cast< PowerPointImport& >( *getFilter() )).getThemes() ); + std::map< OUString, oox::drawingml::ThemePtr >::iterator aIter2( rThemes.find( aThemeFragmentPath ) ); + if( aIter2 == rThemes.end() ) + { + oox::drawingml::ThemePtr pThemePtr( new oox::drawingml::Theme() ); + pMasterPersistPtr->setTheme( pThemePtr ); + getFilter()->importFragment( new ThemeFragmentHandler( getFilter(), aThemeFragmentPath, *(pThemePtr.get()) ) ); + rThemes[ aThemeFragmentPath ] = pThemePtr; + } + else + { + pMasterPersistPtr->setTheme( (*aIter2).second ); + } + } + importSlide( xMasterFragmentHandler, pMasterPersistPtr ); + getFilter()->importFragment( new LayoutFragmentHandler( getFilter(), aLayoutFragmentPath, pMasterPersistPtr ) ); + pMasterPersistPtr->createBackground( *getFilter() ); + pMasterPersistPtr->createXShapes( *getFilter(), xModel ); + } + } + } + } + + // importing slide page + pSlidePersistPtr->setMasterPersist( pMasterPersistPtr ); + pSlidePersistPtr->setTheme( pMasterPersistPtr->getTheme() ); + Reference< drawing::XMasterPageTarget > xMasterPageTarget( pSlidePersistPtr->getPage(), UNO_QUERY ); + if( xMasterPageTarget.is() ) + xMasterPageTarget->setMasterPage( pMasterPersistPtr->getPage() ); + (dynamic_cast< PowerPointImport& >( *getFilter() )).getDrawPages().push_back( pSlidePersistPtr ); + (dynamic_cast< PowerPointImport& >( *getFilter() )).setActualSlidePersist( pSlidePersistPtr ); + importSlide( xSlideFragmentHandler, pSlidePersistPtr ); + pSlidePersistPtr->createBackground( *getFilter() ); + pSlidePersistPtr->createXShapes( *getFilter(), xModel ); + + // now importing the notes page + OUString aNotesFragmentPath = xSlideFragmentHandler->getFragmentPathFromType( CREATE_RELATIONS_TYPE( "notesSlide" ) ); + if( aNotesFragmentPath.getLength() > 0 ) + { + Reference< XPresentationPage > xPresentationPage( xSlide, UNO_QUERY ); + if ( xPresentationPage.is() ) + { + Reference< XDrawPage > xNotesPage( xPresentationPage->getNotesPage() ); + if ( xNotesPage.is() ) + { + SlidePersistPtr pNotesPersistPtr( new SlidePersist( sal_False, sal_True, xNotesPage, + ShapePtr( new PPTShape( Slide, "com.sun.star.drawing.GroupShape" ) ), mpTextListStyle ) ); + FragmentHandlerRef xNotesFragmentHandler( new SlideFragmentHandler( getFilter(), aNotesFragmentPath, pNotesPersistPtr, Slide ) ); + (dynamic_cast< PowerPointImport& >( *getFilter() )).getNotesPages().push_back( pNotesPersistPtr ); + (dynamic_cast< PowerPointImport& >( *getFilter() )).setActualSlidePersist( pNotesPersistPtr ); + importSlide( xNotesFragmentHandler, pNotesPersistPtr ); + pNotesPersistPtr->createBackground( *getFilter() ); + pNotesPersistPtr->createXShapes( *getFilter(), xModel ); + } + } + } + } + } + } + catch( uno::Exception& ) + { + OSL_ENSURE( false, + (rtl::OString("oox::ppt::PresentationFragmentHandler::EndDocument(), " + "exception caught: ") + + rtl::OUStringToOString( + comphelper::anyToString( cppu::getCaughtException() ), + RTL_TEXTENCODING_UTF8 )).getStr() ); + + } + + // todo error handling; +} + +// CT_Presentation +Reference< XFastContextHandler > PresentationFragmentHandler::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case NMSP_PPT|XML_presentation: + case NMSP_PPT|XML_sldMasterIdLst: + case NMSP_PPT|XML_notesMasterIdLst: + case NMSP_PPT|XML_sldIdLst: + break; + case NMSP_PPT|XML_sldMasterId: + maSlideMasterVector.push_back( xAttribs->getOptionalValue( NMSP_RELATIONSHIPS|XML_id ) ); + break; + case NMSP_PPT|XML_sldId: + maSlidesVector.push_back( xAttribs->getOptionalValue( NMSP_RELATIONSHIPS|XML_id ) ); + break; + case NMSP_PPT|XML_notesMasterId: + maNotesMasterVector.push_back( xAttribs->getOptionalValue(NMSP_RELATIONSHIPS|XML_id ) ); + break; + case NMSP_PPT|XML_sldSz: + maSlideSize = GetSize2D( xAttribs ); + break; + case NMSP_PPT|XML_notesSz: + maNotesSize = GetSize2D( xAttribs ); + break; + case NMSP_PPT|XML_custShowLst: + xRet.set( new CustomShowListContext( this , maCustomShowList ) ); + break; + case NMSP_PPT|XML_defaultTextStyle: + xRet.set( new TextListStyleContext( this, *(mpTextListStyle.get()) ) ); + break; + } + if ( !xRet.is() ) + xRet.set( this ); + return xRet; +} + +bool PresentationFragmentHandler::importSlide( const FragmentHandlerRef& rxSlideFragmentHandler, + const SlidePersistPtr pSlidePersistPtr ) +{ + Reference< drawing::XDrawPage > xSlide( pSlidePersistPtr->getPage() ); + SlidePersistPtr pMasterPersistPtr( pSlidePersistPtr->getMasterPersist() ); + if ( pMasterPersistPtr.get() ) + { + const OUString sLayout = CREATE_OUSTRING( "Layout" ); + uno::Reference< beans::XPropertySet > xSet( xSlide, uno::UNO_QUERY_THROW ); + xSet->setPropertyValue( sLayout, Any( pMasterPersistPtr->getLayoutFromValueToken() ) ); + } + while( xSlide->getCount() ) + { + Reference< drawing::XShape > xShape; + xSlide->getByIndex(0) >>= xShape; + xSlide->remove( xShape ); + } + + Reference< XPropertySet > xPropertySet( xSlide, UNO_QUERY ); + if ( xPropertySet.is() ) + { + static const OUString sWidth = CREATE_OUSTRING( "Width" ); + static const OUString sHeight = CREATE_OUSTRING( "Height" ); + awt::Size& rPageSize( pSlidePersistPtr->isNotesPage() ? maNotesSize : maSlideSize ); + xPropertySet->setPropertyValue( sWidth, Any( rPageSize.Width ) ); + xPropertySet->setPropertyValue( sHeight, Any( rPageSize.Height ) ); + } + pSlidePersistPtr->setPath( rxSlideFragmentHandler->getFragmentPath() ); + return getFilter()->importFragment( rxSlideFragmentHandler ); +} + +} } + diff --git a/oox/source/ppt/slidefragmenthandler.cxx b/oox/source/ppt/slidefragmenthandler.cxx new file mode 100644 index 000000000000..1740144cff5f --- /dev/null +++ b/oox/source/ppt/slidefragmenthandler.cxx @@ -0,0 +1,193 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: slidefragmenthandler.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "comphelper/anytostring.hxx" +#include "cppuhelper/exc_hlp.hxx" + +#include +#include + +#include "tokens.hxx" +#include "oox/core/namespaces.hxx" +#include +#include "oox/ppt/slidefragmenthandler.hxx" +#include "oox/ppt/slidetimingcontext.hxx" +#include "oox/ppt/slidetransitioncontext.hxx" +#include "oox/ppt/slidemastertextstylescontext.hxx" +#include "oox/ppt/pptshapegroupcontext.hxx" +#include "oox/ppt/pptshape.hxx" +#include "oox/drawingml/clrschemecontext.hxx" + + +using rtl::OUString; +using namespace ::com::sun::star; +using namespace ::oox::core; +using namespace ::oox::drawingml; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::container; + +namespace oox { namespace ppt { + +SlideFragmentHandler::SlideFragmentHandler( const oox::core::XmlFilterRef& xFilter, const ::rtl::OUString& rFragmentPath, oox::ppt::SlidePersistPtr pPersistPtr, const oox::ppt::ShapeLocation eShapeLocation ) throw() +: FragmentHandler( xFilter, rFragmentPath ) +, mpSlidePersistPtr( pPersistPtr ) +, meShapeLocation( eShapeLocation ) +{ + OUString aVMLDrawingFragmentPath = getFragmentPathFromType( CREATE_RELATIONS_TYPE( "vmlDrawing" ) ); + if( aVMLDrawingFragmentPath.getLength() > 0 ) + { + getFilter()->importFragment( new oox::vml::DrawingFragmentHandler( + getFilter(), aVMLDrawingFragmentPath, pPersistPtr->getDrawing() ) ); + } +} + +SlideFragmentHandler::~SlideFragmentHandler() throw() +{ +} + +Reference< XFastContextHandler > SlideFragmentHandler::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case NMSP_PPT|XML_sldMaster: // CT_SlideMaster + case NMSP_PPT|XML_handoutMaster: // CT_HandoutMaster + case NMSP_PPT|XML_sld: // CT_CommonSlideData + case NMSP_PPT|XML_notes: // CT_NotesSlide + case NMSP_PPT|XML_notesMaster: // CT_NotesMaster + break; + case NMSP_PPT|XML_cSld: // CT_CommonSlideData + maSlideName = xAttribs->getOptionalValue(XML_name); + break; + + case NMSP_PPT|XML_spTree: // CT_GroupShape + { + xRet.set( new PPTShapeGroupContext( mpSlidePersistPtr, meShapeLocation, this, aElementToken, mpSlidePersistPtr->getShapes(), + oox::drawingml::ShapePtr( new PPTShape( meShapeLocation, "com.sun.star.drawing.GroupShape" ) ) ) ); + } + break; + + case NMSP_PPT|XML_timing: // CT_SlideTiming + xRet.set( new SlideTimingContext( this, mpSlidePersistPtr->getTimeNodeList() ) ); + break; + case NMSP_PPT|XML_transition: // CT_SlideTransition + xRet.set( new SlideTransitionContext( this, xAttribs, maSlideProperties ) ); + break; + + // BackgroundGroup + case NMSP_PPT|XML_bgPr: // CT_BackgroundProperties + { + FillPropertiesPtr pFillPropertiesPtr( new FillProperties() ); + xRet.set( new BackgroundPropertiesContext( this, pFillPropertiesPtr ) ); + mpSlidePersistPtr->setBackgroundProperties( pFillPropertiesPtr ); + } + break; + case NMSP_PPT|XML_bgRef: // a:CT_StyleMatrixReference + break; + + case NMSP_PPT|XML_clrMap: // CT_ColorMapping + { + oox::drawingml::ClrMapPtr pClrMapPtr( new oox::drawingml::ClrMap() ); + xRet.set( new oox::drawingml::clrMapContext( this, xAttribs, *pClrMapPtr.get() ) ); + mpSlidePersistPtr->setClrMap( pClrMapPtr ); + } + break; + case NMSP_PPT|XML_clrMapOvr: // CT_ColorMappingOverride + case NMSP_PPT|XML_sldLayoutIdLst: // CT_SlideLayoutIdList + break; + case NMSP_PPT|XML_txStyles: // CT_SlideMasterTextStyles + xRet.set( new SlideMasterTextStylesContext( this, mpSlidePersistPtr ) ); + break; + case NMSP_PPT|XML_custDataLst: // CT_CustomerDataList + case NMSP_PPT|XML_tagLst: // CT_TagList + break; + } + + if( !xRet.is() ) + xRet.set(this); + + return xRet; +} + +void SAL_CALL SlideFragmentHandler::endDocument( ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException) +{ + try + { + Reference< XDrawPage > xSlide( mpSlidePersistPtr->getPage() ); + if( !maSlideProperties.empty() ) + { + uno::Reference< beans::XMultiPropertySet > xMSet( xSlide, uno::UNO_QUERY ); + if( xMSet.is() ) + { + uno::Sequence< OUString > aNames; + uno::Sequence< uno::Any > aValues; + maSlideProperties.makeSequence( aNames, aValues ); + xMSet->setPropertyValues( aNames, aValues); + } + else + { + uno::Reference< beans::XPropertySet > xSet( xSlide, uno::UNO_QUERY_THROW ); + uno::Reference< beans::XPropertySetInfo > xInfo( xSet->getPropertySetInfo() ); + + for( PropertyMap::const_iterator aIter( maSlideProperties.begin() ); aIter != maSlideProperties.end(); aIter++ ) + { + if ( xInfo->hasPropertyByName( (*aIter).first ) ) + xSet->setPropertyValue( (*aIter).first, (*aIter).second ); + } + } + } + if ( maSlideName.getLength() ) + { + Reference< XNamed > xNamed( xSlide, UNO_QUERY ); + if( xNamed.is() ) + xNamed->setName( maSlideName ); + } + } + catch( uno::Exception& ) + { + OSL_ENSURE( false, + (rtl::OString("oox::ppt::SlideFragmentHandler::EndElement(), " + "exception caught: ") + + rtl::OUStringToOString( + comphelper::anyToString( cppu::getCaughtException() ), + RTL_TEXTENCODING_UTF8 )).getStr() ); + } +} + +} } + diff --git a/oox/source/ppt/slidemastertextstylescontext.cxx b/oox/source/ppt/slidemastertextstylescontext.cxx new file mode 100644 index 000000000000..6a389131eb03 --- /dev/null +++ b/oox/source/ppt/slidemastertextstylescontext.cxx @@ -0,0 +1,94 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: slidemastertextstylescontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/drawingml/textliststyle.hxx" +#include "oox/drawingml/textliststylecontext.hxx" +#include "oox/ppt/slidemastertextstylescontext.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace ppt { + +SlideMasterTextStylesContext::SlideMasterTextStylesContext( const ::oox::core::FragmentHandlerRef& xHandler, SlidePersistPtr pSlidePersistPtr ) +: Context( xHandler ) +, mpSlidePersistPtr( pSlidePersistPtr ) +{ +} + +SlideMasterTextStylesContext::~SlideMasterTextStylesContext() +{ +} + +Reference< XFastContextHandler > SlideMasterTextStylesContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& /* xAttribs */ ) throw (SAXException, RuntimeException) +{ + oox::drawingml::TextListStylePtr aTextListStylePtr; + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case NMSP_PPT|XML_titleStyle: + { + aTextListStylePtr = mpSlidePersistPtr->getTitleTextStyle(); + break; + } + case NMSP_PPT|XML_bodyStyle: + { + aTextListStylePtr = mpSlidePersistPtr->getBodyTextStyle(); + break; + } + case NMSP_PPT|XML_notesStyle: + { + aTextListStylePtr = mpSlidePersistPtr->getNotesTextStyle(); + break; + } + case NMSP_PPT|XML_otherStyle: + { + aTextListStylePtr = mpSlidePersistPtr->getOtherTextStyle(); + break; + } + } + if ( aTextListStylePtr ) + xRet.set( new oox::drawingml::TextListStyleContext( getHandler(), *(aTextListStylePtr.get()) ) ); + if( !xRet.is() ) + xRet.set( this ); + + return xRet; +} + +} } diff --git a/oox/source/ppt/slidepersist.cxx b/oox/source/ppt/slidepersist.cxx new file mode 100644 index 000000000000..b397b4cb3d59 --- /dev/null +++ b/oox/source/ppt/slidepersist.cxx @@ -0,0 +1,320 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: slidepersist.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include +#include "oox/ppt/timenode.hxx" +#include "oox/ppt/pptshape.hxx" +#include "oox/ppt/slidepersist.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::animations; + +namespace oox { namespace ppt { + +SlidePersist::SlidePersist( sal_Bool bMaster, sal_Bool bNotes, + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& rxPage, + oox::drawingml::ShapePtr pShapesPtr, const drawingml::TextListStylePtr & pDefaultTextStyle ) +: mpDrawingPtr( new oox::vml::Drawing ) +, mxPage( rxPage ) +, maShapesPtr( pShapesPtr ) +, mnLayoutValueToken( 0 ) +, mbMaster( bMaster ) +, mbNotes ( bNotes ) +, maDefaultTextStylePtr( pDefaultTextStyle ) +, maTitleTextStylePtr( new oox::drawingml::TextListStyle ) +, maBodyTextStylePtr( new oox::drawingml::TextListStyle ) +, maNotesTextStylePtr( new oox::drawingml::TextListStyle ) +, maOtherTextStylePtr( new oox::drawingml::TextListStyle ) +{ +} + +SlidePersist::~SlidePersist() +{ + +} + +sal_Int16 SlidePersist::getLayoutFromValueToken() +{ + sal_Int16 nLayout = 20; // 20 == blanc (so many magic numbers :-( the description at com.sun.star.presentation.DrawPage.Layout does not help) + switch( mnLayoutValueToken ) + { + case XML_blank: nLayout = 20; break; + case XML_chart: nLayout = 2; break; + case XML_chartAndTx: nLayout = 7; break; + case XML_clipArtAndTx: nLayout = 9; break; + case XML_clipArtAndVertTx: nLayout = 24; break; + case XML_fourObj: nLayout = 18; break; + case XML_obj: nLayout = 11; break; + case XML_objAndTx: nLayout = 13; break; + case XML_objOverTx: nLayout = 14; break; + case XML_tbl: nLayout = 8; break; + case XML_title: nLayout = 0; break; + case XML_titleOnly: nLayout = 19; break; + case XML_twoObj: + case XML_twoColTx: nLayout = 3; break; + case XML_twoObjAndTx: nLayout = 15; break; + case XML_twoObjOverTx: nLayout = 16; break; + case XML_tx: nLayout = 1; break; + case XML_txAndChart: nLayout = 4; break; + case XML_txAndClipArt: nLayout = 6; break; + case XML_txAndMedia: nLayout = 6; break; + case XML_txAndObj: nLayout = 10; break; + case XML_txAndTwoObj: nLayout = 12; break; + case XML_txOverObj: nLayout = 17; break; + case XML_vertTitleAndTx: nLayout = 22; break; + case XML_vertTitleAndTxOverChart: nLayout = 21; break; + case XML_vertTx: nLayout = 23; break; + + case XML_twoTxTwoObj: + case XML_twoObjAndObj: + case XML_objTx: + case XML_picTx: + case XML_secHead: + case XML_objOnly: + case XML_objAndTwoObj: + case XML_mediaAndTx: + case XML_dgm: + case XML_cust: + default: + nLayout = 20; + } + return nLayout; +} + +void SlidePersist::createXShapes( const oox::core::XmlFilterBase& rFilterBase, Reference< frame::XModel > xModel ) +{ + applyTextStyles( xModel ); + + Reference< XShapes > xShapes( getPage(), UNO_QUERY ); + + std::vector< oox::drawingml::ShapePtr >& rShapes( maShapesPtr->getChilds() ); + std::vector< oox::drawingml::ShapePtr >::iterator aShapesIter( rShapes.begin() ); + while( aShapesIter != rShapes.end() ) + { + std::vector< oox::drawingml::ShapePtr >& rChilds( (*aShapesIter++)->getChilds() ); + std::vector< oox::drawingml::ShapePtr >::iterator aChildIter( rChilds.begin() ); + while( aChildIter != rChilds.end() ) + { + PPTShape* pPPTShape = dynamic_cast< PPTShape* >( (*aChildIter).get() ); + if ( pPPTShape ) + pPPTShape->addShape( rFilterBase, xModel, *this, getTheme(), getShapeMap(), xShapes, NULL ); + else + (*aChildIter)->addShape( rFilterBase, xModel, getTheme(), getShapeMap(), xShapes, NULL ); + + aChildIter++; + } + } + + Reference< XAnimationNodeSupplier > xNodeSupplier( getPage(), UNO_QUERY); + if( xNodeSupplier.is() ) + { + Reference< XAnimationNode > xNode( xNodeSupplier->getAnimationNode() ); + if( xNode.is() && !maTimeNodeList.empty() ) + { + SlidePersistPtr pSlidePtr( shared_from_this() ); + TimeNodePtr pNode(maTimeNodeList.front()); + OSL_ENSURE( pNode, "pNode" ); + + pNode->setNode( xModel, xNode, pSlidePtr ); + } + } +} + +void SlidePersist::createBackground( const oox::core::XmlFilterBase& rFilterBase ) +{ + if ( mpBackgroundPropertiesPtr ) + { + try + { + PropertyMap aPropMap; + static const rtl::OUString sBackground( RTL_CONSTASCII_USTRINGPARAM( "Background" ) ); + uno::Reference< beans::XPropertySet > xPagePropSet( mxPage, uno::UNO_QUERY_THROW ); + uno::Reference< beans::XPropertySet > xPropertySet( aPropMap.makePropertySet() ); + mpBackgroundPropertiesPtr->pushToPropSet( rFilterBase, xPropertySet ); + xPagePropSet->setPropertyValue( sBackground, Any( xPropertySet ) ); + } + catch( Exception ) + { + } + } +} + +void setTextStyle( Reference< beans::XPropertySet >& rxPropSet, + oox::drawingml::TextListStylePtr& pTextListStylePtr, int nLevel ) +{ + ::oox::drawingml::TextParagraphPropertiesPtr pTextParagraphPropertiesPtr( pTextListStylePtr->getListStyle()[ nLevel ] ); + if( pTextParagraphPropertiesPtr == NULL ) + { + // no properties. return + return; + } + ::oox::drawingml::TextCharacterPropertiesPtr pTextCharacterPropertiesPtr( pTextParagraphPropertiesPtr->getTextCharacterProperties() ); + if( pTextCharacterPropertiesPtr == NULL ) + { + // no properties. return + return; + } + PropertyMap& rParagraphProperties( pTextParagraphPropertiesPtr->getTextParagraphPropertyMap() ); + PropertyMap& rCharacterProperties( pTextCharacterPropertiesPtr->getTextCharacterPropertyMap() ); + + int i; + Sequence< rtl::OUString > aNames; + Sequence< Any > aValues; + rParagraphProperties.makeSequence( aNames, aValues ); + for( i = 0; i < aNames.getLength(); i++ ) + rxPropSet->setPropertyValue( aNames[ i ], aValues[ i ] ); + rCharacterProperties.makeSequence( aNames, aValues ); + for( i = 0; i < aNames.getLength(); i++ ) + rxPropSet->setPropertyValue( aNames[ i ], aValues[ i ] ); +} + +void SlidePersist::applyTextStyles( Reference< frame::XModel > xModel ) +{ + if ( mbMaster ) + { + try + { + Reference< style::XStyleFamiliesSupplier > aXStyleFamiliesSupplier( xModel, UNO_QUERY_THROW ); + Reference< container::XNameAccess > aXNameAccess( aXStyleFamiliesSupplier->getStyleFamilies() ); + Reference< container::XNamed > aXNamed( mxPage, UNO_QUERY_THROW ); + + if ( aXNameAccess.is() && aXNamed.is() ) + { + oox::drawingml::TextListStylePtr pTextListStylePtr; + rtl::OUString aStyle; + rtl::OUString aFamily; + + const rtl::OUString sOutline( RTL_CONSTASCII_USTRINGPARAM( "outline1" ) ); + const rtl::OUString sTitle( RTL_CONSTASCII_USTRINGPARAM( "title" ) ); + const rtl::OUString sStandard( RTL_CONSTASCII_USTRINGPARAM( "standard" ) ); + const rtl::OUString sSubtitle( RTL_CONSTASCII_USTRINGPARAM( "subtitle" ) ); + + for( int i = 0; i < 4; i++ ) // todo: aggregation of bodystyle (subtitle) + { + switch( i ) + { + case 0 : // title style + { + pTextListStylePtr = maTitleTextStylePtr; + aStyle = sTitle; + aFamily= aXNamed->getName(); + break; + } + case 1 : // body style + { + pTextListStylePtr = maBodyTextStylePtr; + aStyle = sOutline; + aFamily= aXNamed->getName(); + break; + } + case 3 : // notes style + { + pTextListStylePtr = maNotesTextStylePtr; + aStyle = sTitle; + aFamily= aXNamed->getName(); + break; + } + case 4 : // standard style + { + pTextListStylePtr = maOtherTextStylePtr; + aStyle = sStandard; + aFamily = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "graphics" ) ); + break; + } + case 5 : // subtitle + { + pTextListStylePtr = maBodyTextStylePtr; + aStyle = sSubtitle; + aFamily = aXNamed->getName(); + break; + } + } + Reference< container::XNameAccess > xFamilies; + if ( aXNameAccess->hasByName( aFamily ) ) + { + if( aXNameAccess->getByName( aFamily ) >>= xFamilies ) + { + if ( xFamilies->hasByName( aStyle ) ) + { + Reference< style::XStyle > aXStyle; + if ( xFamilies->getByName( aStyle ) >>= aXStyle ) + { + Reference< beans::XPropertySet > xPropSet( aXStyle, UNO_QUERY_THROW ); + setTextStyle( xPropSet, maDefaultTextStylePtr, 0 ); + setTextStyle( xPropSet, pTextListStylePtr, 0 ); + for ( int nLevel = 1; nLevel < 5; nLevel++ ) + { + if ( i == 1 /* BodyStyle */ ) + { + sal_Char pOutline[ 9 ] = "outline1"; + pOutline[ 7 ] = static_cast< sal_Char >( '1' + i ); + rtl::OUString sOutlineStyle( rtl::OUString::createFromAscii( pOutline ) ); + if ( xFamilies->hasByName( sOutlineStyle ) ) + { + xFamilies->getByName( sOutlineStyle ) >>= aXStyle; + if( aXStyle.is() ) + xPropSet = Reference< beans::XPropertySet >( aXStyle, UNO_QUERY_THROW ); + } + } + setTextStyle( xPropSet, maDefaultTextStylePtr, nLevel ); + setTextStyle( xPropSet, pTextListStylePtr, nLevel ); + } + } + } + } + } + } + } + } + catch( Exception& ) + { + } + } +} + +} } + diff --git a/oox/source/ppt/slidetimingcontext.cxx b/oox/source/ppt/slidetimingcontext.cxx new file mode 100644 index 000000000000..a0c15363b27c --- /dev/null +++ b/oox/source/ppt/slidetimingcontext.cxx @@ -0,0 +1,113 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: slidetimingcontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/ppt/slidetimingcontext.hxx" + +#include "comphelper/anytostring.hxx" +#include "cppuhelper/exc_hlp.hxx" + +#include "oox/ppt/backgroundproperties.hxx" +#include "oox/ppt/slidefragmenthandler.hxx" +#include "oox/drawingml/shapegroupcontext.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/core/skipcontext.hxx" +#include "oox/ppt/timenodelistcontext.hxx" +#include "buildlistcontext.hxx" +#include "tokens.hxx" + +using rtl::OUString; +using namespace ::com::sun::star; +using namespace ::oox::core; +using namespace ::oox::drawingml; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::container; + +namespace oox { namespace ppt { + +SlideTimingContext::SlideTimingContext( const ::oox::core::FragmentHandlerRef& xHandler, TimeNodePtrList & aTimeNodeList ) throw() + : Context( xHandler ) + , maTimeNodeList( aTimeNodeList ) +{ +} + +SlideTimingContext::~SlideTimingContext() throw() +{ + +} + +void SlideTimingContext::endFastElement( sal_Int32 /*aElement*/ ) throw ( SAXException, RuntimeException) +{ +} + + +Reference< XFastContextHandler > SlideTimingContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case NMSP_PPT|XML_bldLst: + xRet.set( new BuildListContext( getHandler(), xAttribs, maTimeNodeList ) ); + break; + case NMSP_PPT|XML_extLst: + xRet.set( new SkipContext( getHandler() ) ); + break; + case NMSP_PPT|XML_tnLst: + // timing nodes + { + xRet.set( new TimeNodeListContext( getHandler(), maTimeNodeList ) ); + } + break; + + default: + break; + } + + if( !xRet.is() ) + xRet.set(this); + + return xRet; +} + +void SAL_CALL SlideTimingContext::endDocument( ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException) +{ + +} + +} } + diff --git a/oox/source/ppt/slidetransition.cxx b/oox/source/ppt/slidetransition.cxx new file mode 100644 index 000000000000..04f325d4113f --- /dev/null +++ b/oox/source/ppt/slidetransition.cxx @@ -0,0 +1,393 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: slidetransition.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/ppt/slidetransition.hxx" + +#include +#include +#include +#include +#include + +#include "oox/helper/helper.hxx" +#include "oox/helper/propertymap.hxx" +#include "oox/core/namespaces.hxx" +#include "pptfilterhelpers.hxx" +#include "tokens.hxx" + +using rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::animations; +using namespace ::com::sun::star::presentation; + +namespace oox { namespace ppt { + + + SlideTransition::SlideTransition() + : mnTransitionType( 0 ) + , mnTransitionSubType( 0 ) + , mbTransitionDirectionNormal( true ) + , mnAnimationSpeed( AnimationSpeed_FAST ) + , mnFadeColor( 0 ) + , mbMode( true ) + { + + } + + + SlideTransition::SlideTransition(const OUString & sFilterName) + : mnTransitionType( 0 ) + , mnTransitionSubType( 0 ) + , mbTransitionDirectionNormal( true ) + , mnAnimationSpeed( AnimationSpeed_FAST ) + , mnFadeColor( 0 ) + , mbMode( true ) + { + const transition *p = transition::find( sFilterName ); + if( p ) + { + mnTransitionType = p->mnType; + mnTransitionSubType = p->mnSubType; + mbTransitionDirectionNormal = p->mbDirection; + } + } + + + void SlideTransition::setSlideProperties( PropertyMap & aProps ) + { + try + { + aProps[ CREATE_OUSTRING( "TransitionType" ) ] = Any( mnTransitionType ); + aProps[ CREATE_OUSTRING( "TransitionSubtype" ) ] = Any( mnTransitionSubType ); + aProps[ CREATE_OUSTRING( "TransitionDirection" ) ] = Any( mbTransitionDirectionNormal ); + aProps[ CREATE_OUSTRING( "Speed" ) ] = Any( mnAnimationSpeed ); + aProps[ CREATE_OUSTRING( "TransitionFadeColor" ) ] = Any( mnFadeColor ); + } + catch( Exception& ) + { + // should not happen + OSL_ENSURE( false, "exception raised" ); + } + } + + void SlideTransition::setTransitionFilterProperties( const Reference< XTransitionFilter > & xFilter ) + { + try + { + xFilter->setTransition( mnTransitionType ); + xFilter->setSubtype( mnTransitionSubType ); + xFilter->setDirection( mbTransitionDirectionNormal ); + xFilter->setFadeColor( mnFadeColor ); + xFilter->setMode( mbMode ); + } + catch( Exception& ) + { + // should not happen + OSL_ENSURE( false, "exception raised" ); + } + } + + + void SlideTransition::setOoxTransitionSpeed( sal_Int32 nToken) + { + switch( nToken ) + { + /* In case you want to use time values in second, + * the speed values are located in the PPT97 importer + * sd/source/filter/ppt/ppt97animations.cxx:664 + * (void Ppt97Animation::UpdateCacheData() const) + */ + case XML_fast: + mnAnimationSpeed = AnimationSpeed_FAST; + break; + case XML_med: + mnAnimationSpeed = AnimationSpeed_MEDIUM; + break; + case XML_slow: + mnAnimationSpeed = AnimationSpeed_SLOW; + break; + default: + // should not happen. just ignore + break; + } + } + + + + sal_Int16 SlideTransition::ooxToOdpEightDirections( ::sal_Int32 nOoxType ) + { + sal_Int16 nOdpDirection; + nOdpDirection = ooxToOdpBorderDirections( nOoxType ); + if( nOdpDirection == 0 ) + { + nOdpDirection = ooxToOdpCornerDirections( nOoxType ); + } + return nOdpDirection; + } + + + sal_Int16 SlideTransition::ooxToOdpBorderDirections( ::sal_Int32 nOoxType ) + { + sal_Int16 nOdpDirection; + switch( nOoxType ) + { + case XML_d: + nOdpDirection = TransitionSubType::FROMTOP; + break; + case XML_l: + nOdpDirection = TransitionSubType::FROMLEFT; + break; + case XML_r: + nOdpDirection = TransitionSubType::FROMRIGHT; + break; + case XML_u: + nOdpDirection = TransitionSubType::FROMBOTTOM; + break; + default: + nOdpDirection= 0; + break; + } + return nOdpDirection; + } + + sal_Int16 SlideTransition::ooxToOdpCornerDirections( ::sal_Int32 nOoxType ) + { + sal_Int16 nOdpDirection; + switch( nOoxType ) + { + case XML_lu: + nOdpDirection = TransitionSubType::FROMBOTTOMRIGHT; + break; + case XML_ru: + nOdpDirection = TransitionSubType::FROMBOTTOMLEFT; + break; + case XML_ld: + nOdpDirection = TransitionSubType::FROMTOPRIGHT; + break; + case XML_rd: + nOdpDirection = TransitionSubType::FROMTOPLEFT; + break; + default: + nOdpDirection = 0; + break; + } + return nOdpDirection; + } + + + sal_Int16 SlideTransition::ooxToOdpDirection( ::sal_Int32 nOoxType ) + { + sal_Int16 nOdpDir; + switch( nOoxType ) + { + case XML_vert: + nOdpDir = TransitionSubType::VERTICAL; + break; + case XML_horz: + nOdpDir = TransitionSubType::HORIZONTAL; + break; + default: + nOdpDir = 0; + break; + } + return nOdpDir; + } + + void SlideTransition::setOoxTransitionType( ::sal_Int32 OoxType, ::sal_Int32 param1, ::sal_Int32 param2 ) + { + switch( OoxType ) + { + case NMSP_PPT|XML_blinds: + mnTransitionType = TransitionType::BLINDSWIPE; + mnTransitionSubType = ooxToOdpDirection( param1 ); + break; + case NMSP_PPT|XML_checker: + mnTransitionType = TransitionType::CHECKERBOARDWIPE; + switch ( param1 ) + { + case XML_vert: + mnTransitionSubType = TransitionSubType::DOWN; + break; + case XML_horz: + mnTransitionSubType = TransitionSubType::ACROSS; + break; + default: + break; + } + break; + case NMSP_PPT|XML_comb: + mnTransitionType = TransitionType::PUSHWIPE; + switch( param1 ) + { + case XML_vert: + mnTransitionSubType = TransitionSubType::COMBVERTICAL; + break; + case XML_horz: + mnTransitionSubType = TransitionSubType::COMBHORIZONTAL; + break; + default: + break; + } + break; + case NMSP_PPT|XML_cover: + mnTransitionType = TransitionType::SLIDEWIPE; + mnTransitionSubType = ooxToOdpEightDirections( param1 ); + break; + case NMSP_PPT|XML_pull: // uncover + mnTransitionType = TransitionType::SLIDEWIPE; + mnTransitionSubType = ooxToOdpEightDirections( param1 ); + mbTransitionDirectionNormal = false; + break; + case NMSP_PPT|XML_cut: + // The binfilter seems to ignore this transition. + // Fade to black instead if thrBlk is true. + if( param1 ) + { + mnTransitionType = TransitionType::FADE; + mnTransitionSubType = TransitionSubType::FADEOVERCOLOR; + } + OSL_TRACE( "OOX: cut transition fallback." ); + break; + case NMSP_PPT|XML_fade: + mnTransitionType = TransitionType::FADE; + if( param1 ) + { + mnTransitionSubType = TransitionSubType::FADEOVERCOLOR; + } + else + { + mnTransitionSubType = TransitionSubType::CROSSFADE; + } + break; + case NMSP_PPT|XML_push: + mnTransitionType = TransitionType::PUSHWIPE; + mnTransitionSubType = ooxToOdpBorderDirections( param1 ); + break; + case NMSP_PPT|XML_wipe: + mnTransitionType = TransitionType::BARWIPE; + mnTransitionSubType = ooxToOdpBorderDirections( param1 ); + break; + case NMSP_PPT|XML_split: + mnTransitionType = TransitionType::BARNDOORWIPE; + mnTransitionSubType = ooxToOdpDirection( param1 ); + if( param2 == XML_in ) + { + // reverse + mbTransitionDirectionNormal = false; + } + break; + case NMSP_PPT|XML_wheel: + mnTransitionType = TransitionType::PINWHEELWIPE; + switch( param1 ) + { + case 1: + mnTransitionSubType = TransitionSubType::ONEBLADE; + break; + case 2: + mnTransitionSubType = TransitionSubType::TWOBLADEVERTICAL; + break; + case 3: + mnTransitionSubType = TransitionSubType::THREEBLADE; + break; + case 4: + mnTransitionSubType = TransitionSubType::FOURBLADE; + break; + case 8: + mnTransitionSubType = TransitionSubType::EIGHTBLADE; + break; + default: + OSL_TRACE( "OOX: strange number of blades for thw wheel-wipe %d", param1 ); + if( param1 > 8 ) + { + mnTransitionSubType = TransitionSubType::EIGHTBLADE; + } + else if( param1 > 4 ) + { + mnTransitionSubType = TransitionSubType::FOURBLADE; + } + else if( param1 == 0) + { + mnTransitionSubType = TransitionSubType::ONEBLADE; + } + break; + } + break; + case NMSP_PPT|XML_randomBar: + mnTransitionType = TransitionType::RANDOMBARWIPE; + mnTransitionSubType = ooxToOdpDirection( param1 ); + break; + case NMSP_PPT|XML_circle: + mnTransitionType = TransitionType::ELLIPSEWIPE; + mnTransitionSubType = TransitionSubType::CIRCLE; + break; + case NMSP_PPT|XML_diamond: + mnTransitionType = TransitionType::IRISWIPE; + mnTransitionSubType = TransitionSubType::DIAMOND; + break; + case NMSP_PPT|XML_dissolve: + mnTransitionType = TransitionType::DISSOLVE; + mnTransitionSubType = TransitionSubType::DEFAULT; + break; + case NMSP_PPT|XML_newsflash: + // this is what the PPT binary filter does.... not sure I agree. + mnTransitionType = TransitionType::FOURBOXWIPE; + mnTransitionSubType = TransitionSubType::CORNERSOUT; + break; + case NMSP_PPT|XML_plus: + mnTransitionType = TransitionType::FOURBOXWIPE; + mnTransitionSubType = TransitionSubType::CORNERSOUT; + break; + case NMSP_PPT|XML_random: + mnTransitionType = TransitionType::RANDOM; + mnTransitionSubType = TransitionSubType::DEFAULT; + break; + case NMSP_PPT|XML_wedge: + mnTransitionType = TransitionType::FANWIPE; + mnTransitionSubType = TransitionSubType::CENTERTOP; + break; + case NMSP_PPT|XML_zoom: + mnTransitionType = TransitionType::ZOOM; + mnTransitionSubType = TransitionSubType::DEFAULT; + break; + default: + mnTransitionType = 0; + break; + } + } + + +} } diff --git a/oox/source/ppt/slidetransitioncontext.cxx b/oox/source/ppt/slidetransitioncontext.cxx new file mode 100644 index 000000000000..c26067b9fa69 --- /dev/null +++ b/oox/source/ppt/slidetransitioncontext.cxx @@ -0,0 +1,213 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: slidetransitioncontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/ppt/slidetransitioncontext.hxx" + +#include "comphelper/anytostring.hxx" +#include "cppuhelper/exc_hlp.hxx" + +#include +#include + +#include +#include "oox/ppt/slidefragmenthandler.hxx" +#include "oox/ppt/soundactioncontext.hxx" +#include "oox/drawingml/shapegroupcontext.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/core/skipcontext.hxx" + +#include "tokens.hxx" + +using rtl::OUString; +using namespace ::com::sun::star; +using namespace ::oox::core; +using namespace ::oox::drawingml; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::container; + +namespace oox { namespace ppt { + + +SlideTransitionContext::SlideTransitionContext( const FragmentHandlerRef& xHandler, const Reference< XFastAttributeList >& xAttribs, PropertyMap & aProperties ) throw() +: Context( xHandler ) +, maSlideProperties( aProperties ) +, mbHasTransition( sal_False ) +{ + AttributeList attribs(xAttribs); + + // ST_TransitionSpeed + maTransition.setOoxTransitionSpeed( xAttribs->getOptionalValueToken( XML_spd, XML_fast ) ); + + // TODO + attribs.getBool( XML_advClick, true ); + + // careful. if missing, no auto advance... 0 looks like a valid value + // for auto advance + if(attribs.hasAttribute( XML_advTm )) + { + // TODO + xAttribs->getOptionalValue( XML_advTm ); + } +} + +SlideTransitionContext::~SlideTransitionContext() throw() +{ + +} + +Reference< XFastContextHandler > SlideTransitionContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case NMSP_PPT|XML_blinds: + case NMSP_PPT|XML_checker: + case NMSP_PPT|XML_comb: + case NMSP_PPT|XML_randomBar: + if (!mbHasTransition) + { + mbHasTransition = true; + maTransition.setOoxTransitionType( aElementToken, xAttribs->getOptionalValueToken( XML_dir, XML_horz ), 0); + // ST_Direction { XML_horz, XML_vert } + } + break; + case NMSP_PPT|XML_cover: + case NMSP_PPT|XML_pull: + if (!mbHasTransition) + { + mbHasTransition = true; + maTransition.setOoxTransitionType( aElementToken, xAttribs->getOptionalValueToken( XML_dir, XML_l ), 0 ); + // ST_TransitionEightDirectionType { ST_TransitionSideDirectionType { + // XML_d, XML_d, XML_r, XML_u }, + // ST_TransitionCornerDirectionType { + // XML_ld, XML_lu, XML_rd, XML_ru } + } + break; + case NMSP_PPT|XML_cut: + case NMSP_PPT|XML_fade: + if (!mbHasTransition) + { + mbHasTransition = true; + AttributeList attribs(xAttribs); + // CT_OptionalBlackTransition xdb:bool + maTransition.setOoxTransitionType( aElementToken, attribs.getBool( XML_thruBlk, false ), 0); + } + break; + case NMSP_PPT|XML_push: + case NMSP_PPT|XML_wipe: + if (!mbHasTransition) + { + mbHasTransition = true; + maTransition.setOoxTransitionType( aElementToken, xAttribs->getOptionalValueToken( XML_dir, XML_l ), 0 ); + // ST_TransitionSideDirectionType { XML_d, XML_l, XML_r, XML_u } + } + break; + case NMSP_PPT|XML_split: + if (!mbHasTransition) + { + mbHasTransition = true; + maTransition.setOoxTransitionType( aElementToken, xAttribs->getOptionalValueToken( XML_orient, XML_horz ), xAttribs->getOptionalValueToken( XML_dir, XML_out ) ); + // ST_Direction { XML_horz, XML_vert } + // ST_TransitionInOutDirectionType { XML_out, XML_in } + } + break; + case NMSP_PPT|XML_zoom: + if (!mbHasTransition) + { + mbHasTransition = true; + maTransition.setOoxTransitionType( aElementToken, xAttribs->getOptionalValueToken( XML_dir, XML_out ), 0 ); + // ST_TransitionInOutDirectionType { XML_out, XML_in } + } + break; + case NMSP_PPT|XML_wheel: + if (!mbHasTransition) + { + mbHasTransition = true; + AttributeList attribs(xAttribs); + maTransition.setOoxTransitionType( aElementToken, attribs.getUnsignedInteger( XML_spokes, 4 ), 0 ); + // unsignedInt + } + break; + case NMSP_PPT|XML_circle: + case NMSP_PPT|XML_diamond: + case NMSP_PPT|XML_dissolve: + case NMSP_PPT|XML_newsflash: + case NMSP_PPT|XML_plus: + case NMSP_PPT|XML_random: + case NMSP_PPT|XML_wedge: + // CT_Empty + if (!mbHasTransition) + { + mbHasTransition = true; + maTransition.setOoxTransitionType( aElementToken, 0, 0 ); + } + break; + + + case NMSP_PPT|XML_sndAc: // CT_TransitionSoundAction + //"Sound" + xRet.set( new SoundActionContext ( this->getHandler(), maSlideProperties ) ); + break; + case NMSP_PPT|XML_extLst: // CT_OfficeArtExtensionList + xRet.set( new SkipContext( getHandler() ) ); + break; + default: + break; + } + + if( !xRet.is() ) + xRet.set(this); + + return xRet; +} + +void SlideTransitionContext::endFastElement( sal_Int32 aElement ) throw (::com::sun::star::xml::sax::SAXException, RuntimeException) +{ + if( aElement == (NMSP_PPT|XML_transition) ) + { + if( mbHasTransition ) + { + maTransition.setSlideProperties( maSlideProperties ); + mbHasTransition = false; + } + } +} + + +} } + diff --git a/oox/source/ppt/soundactioncontext.cxx b/oox/source/ppt/soundactioncontext.cxx new file mode 100644 index 000000000000..b5e8c3dbd84d --- /dev/null +++ b/oox/source/ppt/soundactioncontext.cxx @@ -0,0 +1,144 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: soundactioncontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/ppt/soundactioncontext.hxx" + +#include "comphelper/anytostring.hxx" +#include "cppuhelper/exc_hlp.hxx" + +#include "oox/helper/attributelist.hxx" +#include "oox/helper/propertymap.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/drawingml/embeddedwavaudiofile.hxx" +#include "tokens.hxx" + +using rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::uno; + + +namespace oox { namespace ppt { + + + SoundActionContext::SoundActionContext( const FragmentHandlerRef& xHandler, PropertyMap & aProperties ) throw() + : Context( xHandler ) + , maSlideProperties( aProperties ) + , mbHasStartSound( false ) + , mbLoopSound( false ) + , mbStopSound( false ) + { + } + + + SoundActionContext::~SoundActionContext() throw() + { + } + + + void SoundActionContext::endFastElement( sal_Int32 aElement ) throw (SAXException, RuntimeException) + { + if ( aElement == ( NMSP_PPT|XML_sndAc ) ) + { + if( mbHasStartSound ) + { + OUString url; + // TODO this is very wrong + if ( msSndName.getLength() != 0 ) + { + // try the builtIn version + url = msSndName; + } +#if 0 // OOo does not support embedded data yet + else if ( msEmbedded.getLength() != 0 ) + { + RelationsRef xRel = getHandler()->getRelations(); + url = xRel->getRelationById( msEmbedded )->msTarget; + } + else if ( msLink.getLength() != 0 ) + { + url = msLink; + } +#endif + if ( url.getLength() != 0 ) + { + maSlideProperties[ CREATE_OUSTRING( "Sound" ) ] = Any( url ); + maSlideProperties[ CREATE_OUSTRING( "SoundOn" ) ] = Any( sal_True ); + } + } +// else if( mbStopSound ) +// { +// maSlideProperties[ CREATE_OUSTRING( "" ) ] = Any( sal_True ); +// } + } + } + + + Reference< XFastContextHandler > SoundActionContext::createFastChildContext( ::sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) + { + Reference< XFastContextHandler > xRet; + AttributeList attribs(xAttribs); + + switch( aElement ) + { + case NMSP_PPT|XML_snd: + if( mbHasStartSound ) + { + drawingml::EmbeddedWAVAudioFile aAudio; + drawingml::getEmbeddedWAVAudioFile( getHandler(), xAttribs, aAudio); + + msSndName = ( aAudio.mbBuiltIn ? aAudio.msName : aAudio.msLink ); + } + break; + case NMSP_PPT|XML_endSnd: + // CT_Empty + mbStopSound = true; + break; + case NMSP_PPT|XML_stSnd: + mbHasStartSound = true; + mbLoopSound = attribs.getBool( XML_loop, false ); + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; + } + + + +} } diff --git a/oox/source/ppt/timeanimvaluecontext.cxx b/oox/source/ppt/timeanimvaluecontext.cxx new file mode 100644 index 000000000000..1fc6b462690a --- /dev/null +++ b/oox/source/ppt/timeanimvaluecontext.cxx @@ -0,0 +1,113 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: timeanimvaluecontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:00 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + + + + +#include "timeanimvaluecontext.hxx" + +#include "oox/core/namespaces.hxx" +#include "animvariantcontext.hxx" + +#include "tokens.hxx" + + +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace ppt { + + TimeAnimValueListContext::TimeAnimValueListContext( const FragmentHandlerRef& xHandler, + const Reference< XFastAttributeList >& /*xAttribs*/, + TimeAnimationValueList & aTavList ) + : Context( xHandler ) + , maTavList( aTavList ) + , mbInValue( false ) + { + } + + + TimeAnimValueListContext::~TimeAnimValueListContext( ) + { + } + + + void SAL_CALL TimeAnimValueListContext::endFastElement( sal_Int32 aElement ) + throw ( SAXException, RuntimeException) + { + if( aElement == ( NMSP_PPT|XML_tav ) ) + { + mbInValue = false; + } + } + + + Reference< XFastContextHandler > SAL_CALL TimeAnimValueListContext::createFastChildContext( ::sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) + throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + + switch ( aElementToken ) + { + case NMSP_PPT|XML_tav: + { + mbInValue = true; + TimeAnimationValue val; + val.msFormula = xAttribs->getOptionalValue( XML_fmla ); + val.msTime = xAttribs->getOptionalValue( XML_tm ); + maTavList.push_back( val ); + break; + } + case NMSP_PPT|XML_val: + if( mbInValue ) + { + // CT_TLAnimVariant + xRet.set( new AnimVariantContext( getHandler(), aElementToken, maTavList.back().maValue ) ); + } + break; + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; + } + + +} } diff --git a/oox/source/ppt/timeanimvaluecontext.hxx b/oox/source/ppt/timeanimvaluecontext.hxx new file mode 100644 index 000000000000..912a5c8176dd --- /dev/null +++ b/oox/source/ppt/timeanimvaluecontext.hxx @@ -0,0 +1,72 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: timeanimvaluecontext.hxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:01 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + + + +#ifndef OOX_PPT_TIMEANIMVALUELISTCONTEXT +#define OOX_PPT_TIMEANIMVALUELISTCONTEXT + +#include "oox/core/context.hxx" +#include "oox/ppt/animationspersist.hxx" + +namespace oox { namespace ppt { + + /** CT_TLTimeAnimateValueList */ + class TimeAnimValueListContext + : public ::oox::core::Context + { + public: + TimeAnimValueListContext( const ::oox::core::FragmentHandlerRef& xHandler, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs, + TimeAnimationValueList & aTavList ); + + ~TimeAnimValueListContext( ); + + virtual void SAL_CALL endFastElement( sal_Int32 aElement ) throw ( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& /*xAttribs*/ ) throw ( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException ); + + + private: + TimeAnimationValueList & maTavList; + bool mbInValue; + }; + + + + +} } + +#endif diff --git a/oox/source/ppt/timenode.cxx b/oox/source/ppt/timenode.cxx new file mode 100644 index 000000000000..b14e02d8487c --- /dev/null +++ b/oox/source/ppt/timenode.cxx @@ -0,0 +1,635 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: timenode.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:01 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/ppt/timenode.hxx" + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "oox/helper/helper.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::animations; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::presentation; + +namespace oox { namespace ppt { + + OUString TimeNode::getServiceName( sal_Int16 nNodeType ) + { + OUString sServiceName; + switch( nNodeType ) + { + case AnimationNodeType::PAR: +// sServiceName = CREATE_OUSTRING("com.sun.star.animations.IterateContainer"); + sServiceName = CREATE_OUSTRING("com.sun.star.animations.ParallelTimeContainer"); + break; + case AnimationNodeType::SEQ: + sServiceName = CREATE_OUSTRING("com.sun.star.animations.SequenceTimeContainer"); + break; + case AnimationNodeType::ANIMATE: + sServiceName = CREATE_OUSTRING("com.sun.star.animations.Animate"); + break; + case AnimationNodeType::ANIMATECOLOR: + sServiceName = CREATE_OUSTRING("com.sun.star.animations.AnimateColor"); + break; + case AnimationNodeType::TRANSITIONFILTER: + sServiceName = CREATE_OUSTRING("com.sun.star.animations.TransitionFilter"); + break; + case AnimationNodeType::ANIMATEMOTION: + sServiceName = CREATE_OUSTRING("com.sun.star.animations.AnimateMotion"); + break; + case AnimationNodeType::ANIMATETRANSFORM: + sServiceName = CREATE_OUSTRING("com.sun.star.animations.AnimateTransform"); + break; + case AnimationNodeType::COMMAND: + sServiceName = CREATE_OUSTRING("com.sun.star.animations.Command"); + break; + case AnimationNodeType::SET: + sServiceName = CREATE_OUSTRING("com.sun.star.animations.AnimateSet"); + break; + case AnimationNodeType::AUDIO: + sServiceName = CREATE_OUSTRING("com.sun.star.animations.Audio"); + break; + default: + OSL_TRACE( "OOX: uhandled type %x", nNodeType ); + break; + } + return sServiceName; + } + + + + TimeNode::TimeNode( sal_Int16 nNodeType ) + : mnNodeType( nNodeType ) + , mbHasEndSyncValue( false ) + { + } + + + TimeNode::~TimeNode() + { + } + +// BEGIN CUT&PASTE from sd/source/filter/ppt/pptinanimations.hxx +// -------------------------------------------------------------------- + static void fixMainSequenceTiming( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode ) + { + try + { + bool bFirst = true; + Reference< XEnumerationAccess > xEA( xNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xE( xEA->createEnumeration(), UNO_QUERY_THROW ); + while( xE->hasMoreElements() ) + { + // click node + Reference< XAnimationNode > xClickNode( xE->nextElement(), UNO_QUERY ); + + Event aEvent; + aEvent.Trigger = EventTrigger::ON_NEXT; + aEvent.Repeat = 0; + xClickNode->setBegin( makeAny( aEvent ) ); + + if( bFirst ) + { + bFirst = false; + Reference< XEnumerationAccess > xEA2( xClickNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xE2( xEA2->createEnumeration(), UNO_QUERY_THROW ); + if( xE2->hasMoreElements() ) + { + // with node + xE2->nextElement() >>= xEA2; + if( xEA2.is() ) + xE2.query( xEA2->createEnumeration() ); + else + xE2.clear(); + + if( xE2.is() && xE2->hasMoreElements() ) + { + Reference< XAnimationNode > xEffectNode( xE2->nextElement(), UNO_QUERY_THROW ); + const Sequence< NamedValue > aUserData( xEffectNode->getUserData() ); + const NamedValue* p = aUserData.getConstArray(); + sal_Int32 nLength = aUserData.getLength(); + while( nLength-- ) + { + if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "node-type" ) ) ) + { + sal_Int16 nNodeType = 0; + p->Value >>= nNodeType; + if( nNodeType != ::com::sun::star::presentation::EffectNodeType::ON_CLICK ) + { + // first effect does not start on click, so correct + // first click nodes begin to 0s + xClickNode->setBegin( makeAny( (double)0.0 ) ); + break; + } + } + p++; + } + } + } + } + } + } + catch( Exception& e ) + { + (void)e; + OSL_TRACE("fixMainSequenceTiming(), exception caught!" ); + } + } + +// -------------------------------------------------------------------- + + static void fixInteractiveSequenceTiming( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode ) + { + try + { + Any aBegin( xNode->getBegin() ); + Any aEmpty; + xNode->setBegin( aEmpty ); + + Reference< XEnumerationAccess > xEA( xNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xE( xEA->createEnumeration(), UNO_QUERY_THROW ); + while( xE->hasMoreElements() ) + { + // click node + Reference< XAnimationNode > xClickNode( xE->nextElement(), UNO_QUERY ); + xClickNode->setBegin( aBegin ); + } + } + catch( Exception& e ) + { + (void)e; + OSL_TRACE("fixInteractiveSequenceTiming(), exception caught!" ); + } + } + +// END CUT&PASTE + + void TimeNode::addNode( const Reference< XModel > &rxModel, + const Reference< XAnimationNode >& rxNode, const SlidePersistPtr & pSlide ) + { + try { + OUString sServiceName = getServiceName( mnNodeType ); + Reference< XAnimationNode > xNode = createAndInsert(sServiceName, rxModel, rxNode ); + setNode( rxModel, xNode, pSlide ); + } + catch( const Exception& e ) + { + OSL_TRACE( "OOX: exception raised in TimeNode::addNode() - %s", + OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); + } + } + + void TimeNode::setNode( const Reference< XModel > &rxModel, + const Reference< XAnimationNode >& xNode, const SlidePersistPtr & pSlide ) + { + OSL_ENSURE( xNode.is(), "null node passed" ); + + try { + if( msId.getLength() ) + { + pSlide->getAnimNodesMap()[ msId ] = xNode; + } + + if( mpTarget ) + { + sal_Int16 nSubType; + maNodeProperties[ NP_TARGET ] = mpTarget->convert( pSlide, nSubType ); + if( mpTarget->mnType == XML_spTgt ) + { + maNodeProperties[ NP_SUBITEM ] <<= nSubType; + } + } + + if( !maStCondList.empty() ) + { + Any aAny = AnimationCondition::convertList( pSlide, maStCondList ); + if( aAny.hasValue() ) + { + xNode->setBegin( aAny ); + } + + } + if( !maEndCondList.empty() ) + { + Any aAny = AnimationCondition::convertList( pSlide, maEndCondList ); + if( aAny.hasValue() ) + { + xNode->setEnd( aAny ); + } + } +#if 0 // FIXME even the binary filter has this disabled. + if( !maNextCondList.empty() ) + { + Any aAny = AnimationCondition::convertList( pSlide, maNextCondList ); + if( aAny.hasValue() ) + { + xNode->setNext( aAny ); + } + } + if( !maPrevCondList.empty() ) + { + Any aAny = AnimationCondition::convertList( pSlide, maPrevCondList ); + if( aAny.hasValue() ) + { + xNode->setPrev( aAny ); + } + } +#endif + if( mbHasEndSyncValue ) + { + Any aValue = maEndSyncValue.convert( pSlide ); + xNode->setEndSync(aValue); + } + + Sequence< NamedValue > aUserDataSeq; + maUserData.makeSequence(aUserDataSeq); + if( aUserDataSeq.getLength() ) + { + maNodeProperties[ NP_USERDATA ] = makeAny(aUserDataSeq); + } + + Reference< XAnimate > xAnimate( xNode, UNO_QUERY ); + Reference< XAnimateColor > xAnimateColor( xNode, UNO_QUERY ); + Reference< XAnimateMotion > xAnimateMotion( xNode, UNO_QUERY ); + Reference< XAnimateTransform > xAnimateTransform( xNode, UNO_QUERY ); + Reference< XCommand > xCommand( xNode, UNO_QUERY ); + Reference< XIterateContainer > xIterateContainer( xNode, UNO_QUERY ); + sal_Int16 nInt16 = 0; + sal_Bool bBool = sal_False; + double fDouble = 0; + OUString sString; + Sequence< NamedValue > aSeq; + + for( int i = 0; i < _NP_SIZE; i++) + { + Any & aValue( maNodeProperties[ i ] ); + if( aValue.hasValue() ) + { + switch( i ) + { + case NP_TO: + if( xAnimate.is() ) + xAnimate->setTo( aValue ); + break; + case NP_FROM: + if( xAnimate.is() ) + xAnimate->setFrom( aValue ); + break; + case NP_BY: + if( xAnimate.is() ) + xAnimate->setBy( aValue ); + break; + case NP_TARGET: + if( xAnimate.is() ) + xAnimate->setTarget( aValue ); + break; + case NP_SUBITEM: + if( xAnimate.is() ) + { + if( aValue >>= nInt16 ) + xAnimate->setSubItem( nInt16 ); + else + { + OSL_TRACE( "any >>= failed %d", __LINE__ ); + } + } + break; + case NP_ATTRIBUTENAME: + if( xAnimate.is() ) + { + if( aValue >>= sString ) + xAnimate->setAttributeName( sString ); + else + { + OSL_TRACE( "any >>= failed %d", __LINE__ ); + } + } + break; + case NP_CALCMODE: + if( xAnimate.is() ) + { + if( aValue >>= nInt16 ) + xAnimate->setCalcMode( nInt16 ); + else + { + OSL_TRACE( "any >>= failed %d", __LINE__ ); + } + } + break; + case NP_KEYTIMES: + if( xAnimate.is() ) + { + Sequence aKeyTimes; + if( aValue >>= aKeyTimes ) + xAnimate->setKeyTimes(aKeyTimes); + else + { + OSL_TRACE( "any >>= failed %d", __LINE__ ); + } + } + break; + case NP_VALUES: + if( xAnimate.is() ) + { + Sequence aValues; + if( aValue >>= aValues ) + xAnimate->setValues(aValues); + else + { + OSL_TRACE( "any >>= failed %d", __LINE__ ); + } + } + break; + case NP_FORMULA: + if( xAnimate.is() ) + { + if( aValue >>= sString ) + xAnimate->setFormula(sString); + else + { + OSL_TRACE( "any >>= failed %d", __LINE__ ); + } + } + break; + case NP_COLORINTERPOLATION: + if( xAnimateColor.is() ) + { + if( aValue >>= nInt16 ) + xAnimateColor->setColorInterpolation( nInt16 ); + else + { + OSL_TRACE( "any >>= failed %d", __LINE__ ); + } + } + break; + case NP_DIRECTION: + if( xAnimateColor.is() ) + { + if( aValue >>= bBool ) + xAnimateColor->setDirection( bBool ); + else + { + OSL_TRACE( "any >>= failed %d", __LINE__ ); + } + } + break; + case NP_PATH: + if( xAnimateMotion.is() ) + xAnimateMotion->setPath( aValue ); + break; + case NP_TRANSFORMTYPE: + if( xAnimateTransform.is() ) + { + if( aValue >>= nInt16 ) + xAnimateTransform->setTransformType( nInt16 ); + else + { + OSL_TRACE( "any >>= failed %d", __LINE__ ); + } + } + break; + case NP_USERDATA: + if( aValue >>= aSeq ) + xNode->setUserData( aSeq ); + else + { + OSL_TRACE( "any >>= failed %d", __LINE__ ); + } + break; + case NP_ACCELERATION: + if( aValue >>= fDouble ) + xNode->setAcceleration( fDouble ); + else + { + OSL_TRACE( "any >>= failed %d", __LINE__ ); + } + break; + case NP_DECELERATE: + if( aValue >>= fDouble ) + xNode->setDecelerate( fDouble ); + else + { + OSL_TRACE( "any >>= failed %d", __LINE__ ); + } + break; + case NP_AUTOREVERSE: + if( aValue >>= bBool ) + xNode->setAutoReverse( bBool ); + else + { + OSL_TRACE( "any >>= failed %d", __LINE__ ); + } + break; + case NP_DURATION: + xNode->setDuration( aValue ); + break; + case NP_FILL: + if( aValue >>= nInt16 ) + xNode->setFill( nInt16 ); + else + { + OSL_TRACE( "any >>= failed %d", __LINE__ ); + } + break; + case NP_REPEATCOUNT: + xNode->setRepeatCount( aValue ); + break; + case NP_REPEATDURATION: + xNode->setRepeatDuration( aValue ); + break; + case NP_RESTART: + if( aValue >>= nInt16 ) + xNode->setRestart( nInt16 ); + else + { + OSL_TRACE( "any >>= failed %d", __LINE__ ); + } + break; + case NP_COMMAND: + if( xCommand.is() ) + { + if( aValue >>= nInt16 ) + xCommand->setCommand( nInt16 ); + else + { + OSL_TRACE( "any >>= failed %d", __LINE__ ); + } + } + break; + case NP_PARAMETER: + if( xCommand.is() ) + xCommand->setParameter( aValue ); + break; + case NP_ITERATETYPE: + if( xIterateContainer.is() ) + { + if( aValue >>= nInt16 ) + xIterateContainer->setIterateType( nInt16 ); + else + { + OSL_TRACE( "any >>= failed %d", __LINE__ ); + } + } + break; + case NP_ITERATEINTERVAL: + if( xIterateContainer.is() ) + { + if( aValue >>= fDouble ) + xIterateContainer->setIterateInterval( fDouble ); + else + { + OSL_TRACE( "any >>= failed %d", __LINE__ ); + } + } + break; + default: + OSL_TRACE( "ERR-OOX: unknown prop index %d", i ); + break; + } + } + } + + if( mnNodeType == AnimationNodeType::TRANSITIONFILTER ) + { + + Reference< XTransitionFilter > xFilter( xNode, UNO_QUERY ); + maTransitionFilter.setTransitionFilterProperties( xFilter ); + } + + std::for_each( maChilds.begin(), maChilds.end(), + boost::bind(&TimeNode::addNode, _1, rxModel, boost::ref(xNode), + boost::ref(pSlide) ) ); + + switch( mnNodeType ) + { + case AnimationNodeType::SEQ: + { + sal_Int16 nEnum = 0; + if( maUserData[ CREATE_OUSTRING( "node-type" ) ] >>= nEnum ) + { + if( nEnum == EffectNodeType::MAIN_SEQUENCE ) + { + fixMainSequenceTiming( xNode ); + } + else if( nEnum == EffectNodeType::INTERACTIVE_SEQUENCE ) + { + fixInteractiveSequenceTiming( xNode ); + } + } + break; + } + case AnimationNodeType::PAR: + // some other cut&paste... from AnimationImporter::importAnimationContainer() + break; + } + } + catch( const Exception& e ) + { + OSL_TRACE( "OOX: exception raised in TimeNode::setNode() - %s", + OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); + } + } + + + Reference< XAnimationNode > TimeNode::createAndInsert( const OUString& rServiceName, const Reference< XModel > &/*rxModel*/, + const Reference< XAnimationNode >& rxNode ) + { + try { + Reference< XAnimationNode > xNode ( ::comphelper::getProcessServiceFactory()->createInstance(rServiceName ), + UNO_QUERY_THROW ); + Reference< XTimeContainer > xParentContainer( rxNode, UNO_QUERY_THROW ); + + xParentContainer->appendChild( xNode ); + return xNode; + } + catch( const Exception& e ) + { + OSL_TRACE( "OOX: exception raised in TimeNode::createAndInsert() trying to create a service %s = %s", + OUStringToOString( rServiceName, RTL_TEXTENCODING_ASCII_US ).getStr(), + OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); + } + + return Reference< XAnimationNode >(); + } + + + void TimeNode::setId( sal_Int32 nId ) + { + msId = OUString::valueOf(nId); + } + + void TimeNode::setTo( const Any & aTo ) + { + maNodeProperties[ NP_TO ] = aTo; + } + + + void TimeNode::setFrom( const Any & aFrom ) + { + maNodeProperties[ NP_FROM ] = aFrom; + } + + void TimeNode::setBy( const Any & aBy ) + { + maNodeProperties[ NP_BY ] = aBy; + } + + +} } diff --git a/oox/source/ppt/timenodelistcontext.cxx b/oox/source/ppt/timenodelistcontext.cxx new file mode 100644 index 000000000000..af5822711645 --- /dev/null +++ b/oox/source/ppt/timenodelistcontext.cxx @@ -0,0 +1,1181 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: timenodelistcontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:01 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/ppt/timenodelistcontext.hxx" + +#include "comphelper/anytostring.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "oox/helper/attributelist.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/drawingml/colorchoicecontext.hxx" +#include "oox/ppt/slidetransition.hxx" +#include "tokens.hxx" + +#include "animvariantcontext.hxx" +#include "commonbehaviorcontext.hxx" +#include "conditioncontext.hxx" +#include "commontimenodecontext.hxx" +#include "timeanimvaluecontext.hxx" +#include "animationtypes.hxx" + +using namespace ::oox::core; +using namespace ::oox::drawingml; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::animations; +using namespace ::com::sun::star::presentation; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::awt; +using ::com::sun::star::beans::NamedValue; + +using ::rtl::OUString; + +namespace oox { namespace ppt { + + struct AnimColor + { + AnimColor(sal_Int16 cs, sal_Int32 o, sal_Int32 t, sal_Int32 th ) + : colorSpace( cs ), one( o ), two( t ), three( th ) + { + } + + sal_Int32 get() + { + sal_Int32 nColor; + + switch( colorSpace ) + { + case AnimationColorSpace::HSL: + nColor = ( ( ( one * 128 ) / 360 ) & 0xff ) << 16 + | ( ( ( two * 128 ) / 1000 ) & 0xff ) << 8 + | ( ( ( three * 128 ) / 1000 ) & 0xff ); + break; + case AnimationColorSpace::RGB: + nColor = ( ( ( one * 128 ) / 1000 ) & 0xff ) << 16 + | ( ( ( two * 128 ) / 1000 ) & 0xff ) << 8 + | ( ( ( three * 128 ) / 1000 ) & 0xff ); + break; + default: + nColor = 0; + break; + } + return nColor; + } + + sal_Int16 colorSpace; + sal_Int32 one; + sal_Int32 two; + sal_Int32 three; + }; + + + /** CT_TLMediaNodeAudio + CT_TLMediaNodeVideo */ + class MediaNodeContext + : public TimeNodeContext + { + public: + MediaNodeContext( const FragmentHandlerRef& xHandler, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) + : TimeNodeContext( xHandler, aElement, xAttribs, pNode ) + , mbIsNarration( false ) + , mbFullScrn( false ) + { + AttributeList attribs( xAttribs ); + + switch( aElement ) + { + case NMSP_PPT|XML_audio: + mbIsNarration = attribs.getBool( XML_isNarration, false ); + break; + case NMSP_PPT|XML_video: + mbFullScrn = attribs.getBool( XML_fullScrn, false ); + break; + default: + break; + } + } + + virtual void SAL_CALL endFastElement( sal_Int32 aElement ) + throw ( SAXException, RuntimeException) + { + if( aElement == ( NMSP_PPT|XML_audio ) ) + { + // TODO deal with mbIsNarration + } + else if( aElement == ( NMSP_PPT|XML_video ) ) + { + // TODO deal with mbFullScrn + } + } + + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) + throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + + switch ( aElementToken ) + { + case NMSP_PPT|XML_cBhvr: + xRet.set( new CommonBehaviorContext ( getHandler(), xAttribs, mpNode ) ); + break; + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; + } + + private: + bool mbIsNarration; + bool mbFullScrn; + }; + + + /** CT_TLSetBehavior + */ + class SetTimeNodeContext + : public TimeNodeContext + { + public: + SetTimeNodeContext( const FragmentHandlerRef& xHandler, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) + : TimeNodeContext( xHandler, aElement, xAttribs, pNode ) + { + + } + + ~SetTimeNodeContext() throw () + { + if( maTo.hasValue() ) + { + // TODO + // HACK !!! discard and refactor + OUString aString; + if( maTo >>= aString ) + { + OSL_TRACE( "Magic conversion %s", OUSTRING_TO_CSTR( aString ) ); + maTo = makeAny( aString.equalsAscii( "visible" ) ? sal_True : sal_False ); + if( !maTo.has() ) + OSL_TRACE( "conversion failed" ); + } + mpNode->setTo( maTo ); + } + + } + + virtual void SAL_CALL endFastElement( sal_Int32 /*aElement*/ ) + throw ( SAXException, RuntimeException) + { + } + + + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) + throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + + switch ( aElementToken ) + { + case NMSP_PPT|XML_cBhvr: + xRet.set( new CommonBehaviorContext ( getHandler(), xAttribs, mpNode ) ); + break; + case NMSP_PPT|XML_to: + // CT_TLAnimVariant + xRet.set( new AnimVariantContext( getHandler(), aElementToken, maTo ) ); + break; + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; + } + private: + Any maTo; + }; + + /** CT_TLCommandBehavior + */ + class CmdTimeNodeContext + : public TimeNodeContext + { + public: + CmdTimeNodeContext( const FragmentHandlerRef& xHandler, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) + : TimeNodeContext( xHandler, aElement, xAttribs, pNode ) + , maType(0) + { + switch ( aElement ) + { + case NMSP_PPT|XML_cmd: + msCommand = xAttribs->getOptionalValue( XML_cmd ); + maType = xAttribs->getOptionalValueToken( XML_type, 0 ); + break; + default: + break; + } + } + + ~CmdTimeNodeContext() throw () + { + } + + virtual void SAL_CALL endFastElement( sal_Int32 aElement ) + throw ( SAXException, RuntimeException) + { + if( aElement == ( NMSP_PPT|XML_cmd ) ) + { + try { + // see sd/source/filter/ppt/pptinanimations.cxx + // in AnimationImporter::importCommandContainer() + // REFACTOR? + // a good chunk of this code has been copied verbatim *sigh* + sal_Int16 nCommand = EffectCommands::CUSTOM; + NamedValue aParamValue; + + switch( maType ) + { + case XML_verb: + aParamValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("Verb")); + // TODO make sure msCommand has what we want + aParamValue.Value <<= msCommand.toInt32(); + nCommand = EffectCommands::VERB; + break; + case XML_evt: + case XML_call: + if( msCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "onstopaudio" ) ) ) + { + nCommand = EffectCommands::STOPAUDIO; + } + else if( msCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("play") ) ) + { + nCommand = EffectCommands::PLAY; + } + else if( msCommand.compareToAscii( RTL_CONSTASCII_STRINGPARAM("playFrom") ) == 0 ) + { + const OUString aMediaTime( msCommand.copy( 9, msCommand.getLength() - 10 ) ); + rtl_math_ConversionStatus eStatus; + double fMediaTime = ::rtl::math::stringToDouble( aMediaTime, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL ); + if( eStatus == rtl_math_ConversionStatus_Ok ) + { + aParamValue.Name = CREATE_OUSTRING("MediaTime"); + aParamValue.Value <<= fMediaTime; + } + nCommand = EffectCommands::PLAY; + } + else if( msCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("togglePause") ) ) + { + nCommand = EffectCommands::TOGGLEPAUSE; + } + else if( msCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("stop") ) ) + { + nCommand = EffectCommands::STOP; + } + break; + } + mpNode->getNodeProperties()[ NP_COMMAND ] = makeAny((sal_Int16)nCommand); + if( nCommand == EffectCommands::CUSTOM ) + { + OSL_TRACE("OOX: CmdTimeNodeContext::endFastElement(), unknown command!"); + aParamValue.Name = CREATE_OUSTRING("UserDefined"); + aParamValue.Value <<= msCommand; + } + if( aParamValue.Value.hasValue() ) + { + Sequence< NamedValue > aParamSeq( &aParamValue, 1 ); + mpNode->getNodeProperties()[ NP_PARAMETER ] = makeAny( aParamSeq ); + } + } + catch( RuntimeException& ) + { + OSL_TRACE( "OOX: Exception in CmdTimeNodeContext::endFastElement()" ); + } + } + } + + + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) + throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + + switch ( aElementToken ) + { + case NMSP_PPT|XML_cBhvr: + xRet.set( new CommonBehaviorContext ( getHandler(), xAttribs, mpNode ) ); + break; + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; + } + + private: + OUString msCommand; + sal_Int32 maType; + }; + + + /** CT_TLTimeNodeSequence + */ + class SequenceTimeNodeContext + : public TimeNodeContext + { + public: + SequenceTimeNodeContext( const FragmentHandlerRef& xHandler, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) + : TimeNodeContext( xHandler, aElement, xAttribs, pNode ) + , mnNextAc(0) + , mnPrevAc(0) + { + AttributeList attribs(xAttribs); + mbConcurrent = attribs.getBool( XML_concurrent, false ); + // ST_TLNextActionType { none, seek } + mnNextAc = xAttribs->getOptionalValueToken( XML_nextAc, 0 ); + // ST_TLPreviousActionType { none, skipTimed } + mnPrevAc = xAttribs->getOptionalValueToken( XML_prevAc, 0 ); + } + + ~SequenceTimeNodeContext() throw() + { + } + + + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) + throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + + switch ( aElementToken ) + { + case NMSP_PPT|XML_cTn: + xRet.set( new CommonTimeNodeContext( getHandler(), aElementToken, xAttribs, mpNode ) ); + break; + case NMSP_PPT|XML_nextCondLst: + xRet.set( new CondListContext( getHandler(), aElementToken, xAttribs, mpNode, + mpNode->getNextCondition() ) ); + break; + case NMSP_PPT|XML_prevCondLst: + xRet.set( new CondListContext( getHandler(), aElementToken, xAttribs, mpNode, + mpNode->getPrevCondition() ) ); + break; + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; + } + private: + bool mbConcurrent; + sal_Int32 mnNextAc, mnPrevAc; + }; + + + /** CT_TLTimeNodeParallel + * CT_TLTimeNodeExclusive + */ + class ParallelExclTimeNodeContext + : public TimeNodeContext + { + public: + ParallelExclTimeNodeContext( const FragmentHandlerRef& xHandler, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) + : TimeNodeContext( xHandler, aElement, xAttribs, pNode ) + { + } + + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) + throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + + switch ( aElementToken ) + { + case NMSP_PPT|XML_cTn: + xRet.set( new CommonTimeNodeContext( getHandler(), aElementToken, xAttribs, mpNode ) ); + break; + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; + } + + protected: + + }; + + + /** CT_TLAnimateColorBehavior */ + class AnimColorContext + : public TimeNodeContext + { + public: + AnimColorContext( const FragmentHandlerRef& xHandler, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) throw() + : TimeNodeContext( xHandler, aElement, xAttribs, pNode ) + // ST_TLAnimateColorSpace ( XML_rgb, XML_hsl } + , mnColorSpace( xAttribs->getOptionalValueToken( XML_clrSpc, 0 ) ) + // ST_TLAnimateColorDirection { XML_cw, XML_ccw } + , mnDir( xAttribs->getOptionalValueToken( XML_dir, 0 ) ) + , mbHasByColor( false ) + , m_byColor( AnimationColorSpace::RGB, 0, 0, 0) + { + } + ~AnimColorContext() throw() + { + } + + virtual void SAL_CALL endFastElement( sal_Int32 aElement ) throw ( SAXException, RuntimeException) + { + //xParentNode + if( aElement == mnElement ) + { + NodePropertyMap & pProps(mpNode->getNodeProperties()); + pProps[ NP_DIRECTION ] = makeAny( mnDir == XML_cw ); + pProps[ NP_COLORINTERPOLATION ] = makeAny( mnColorSpace == XML_hsl ? AnimationColorSpace::HSL : AnimationColorSpace::RGB ); + if( maToClr.isUsed() ) + { + mpNode->setTo( Any( maToClr.getColor( *getHandler()->getFilter().get() ) ) ); + } + if( maFromClr.isUsed() ) + { + mpNode->setFrom( Any( maFromClr.getColor( *getHandler()->getFilter().get() ) ) ); + } + if( mbHasByColor ) + { + mpNode->setBy( Any ( m_byColor.get() ) ); + } + + } + } + + + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + + switch ( aElementToken ) + { + case NMSP_PPT|XML_hsl: + // CT_TLByHslColorTransform + { + if( mbHasByColor ) + { + m_byColor.colorSpace = AnimationColorSpace::HSL; + m_byColor.one = xAttribs->getOptionalValue( XML_h ).toInt32( ); + m_byColor.two = xAttribs->getOptionalValue( XML_s ).toInt32( ); + m_byColor.three = xAttribs->getOptionalValue( XML_l ).toInt32( ); + } + xRet.set(this); + break; + } + case NMSP_PPT|XML_rgb: + { + if( mbHasByColor ) + { + // CT_TLByRgbColorTransform + m_byColor.colorSpace = AnimationColorSpace::RGB; + m_byColor.one = xAttribs->getOptionalValue( XML_r ).toInt32(); + m_byColor.two = xAttribs->getOptionalValue( XML_g ).toInt32(); + m_byColor.three = xAttribs->getOptionalValue( XML_b ).toInt32(); + } + xRet.set(this); + break; + } + case NMSP_PPT|XML_by: + // CT_TLByAnimateColorTransform + mbHasByColor = true; + xRet.set(this); + break; + case NMSP_PPT|XML_cBhvr: + xRet.set( new CommonBehaviorContext ( getHandler(), xAttribs, mpNode ) ); + break; + case NMSP_PPT|XML_to: + // CT_Color + xRet.set( new colorChoiceContext( getHandler(), maToClr ) ); + break; + case NMSP_PPT|XML_from: + // CT_Color + xRet.set( new colorChoiceContext( getHandler(), maFromClr ) ); + break; + + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; + } + + + private: + sal_Int32 mnColorSpace; + sal_Int32 mnDir; + bool mbHasByColor; + AnimColor m_byColor; + oox::drawingml::Color maToClr; + oox::drawingml::Color maFromClr; + }; + + + /** CT_TLAnimateBehavior */ + class AnimContext + : public TimeNodeContext + { + public: + AnimContext( const FragmentHandlerRef& xHandler, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) throw() + : TimeNodeContext( xHandler, aElement, xAttribs, pNode ) + { + NodePropertyMap & aProps( pNode->getNodeProperties() ); + sal_Int32 nCalcMode = xAttribs->getOptionalValueToken( XML_calcmode, 0 ); + if(nCalcMode) + { + sal_Int16 nEnum = 0; + switch(nCalcMode) + { + case XML_discrete: + nEnum = AnimationCalcMode::DISCRETE; + break; + case XML_lin: + nEnum = AnimationCalcMode::LINEAR; + break; + case XML_fmla: + default: + // TODO what value is good ? + nEnum = AnimationCalcMode::DISCRETE; + break; + } + aProps[ NP_CALCMODE ] = makeAny(nEnum); + } + OUString aStr; + aStr = xAttribs->getOptionalValue( XML_from ); + if( aStr.getLength() ) + { + pNode->setFrom( makeAny( aStr ) ); + } + aStr = xAttribs->getOptionalValue( XML_by ); + if( aStr.getLength() ) + { + pNode->setBy( makeAny( aStr ) ); + } + aStr = xAttribs->getOptionalValue( XML_to ); + if( aStr.getLength() ) + { + pNode->setTo( makeAny( aStr ) ); + } + mnValueType = xAttribs->getOptionalValueToken( XML_valueType, 0 ); + } + + + ~AnimContext() throw () + { + ::std::list< TimeAnimationValue >::iterator iter, end; + int nKeyTimes = maTavList.size(); + if( nKeyTimes > 0) + { + int i; + Sequence< double > aKeyTimes( nKeyTimes ); + Sequence< Any > aValues( nKeyTimes ); + + NodePropertyMap & aProps( mpNode->getNodeProperties() ); + end = maTavList.end(); + for(iter = maTavList.begin(), i=0; iter != end; iter++,i++) + { + // TODO what to do if it is Timing_INFINITE ? + Any aTime = GetTimeAnimateValueTime( iter->msTime ); + aTime >>= aKeyTimes[i]; + aValues[i] = iter->maValue; + + OUString aTest; + iter->maValue >>= aTest; + if( aTest.getLength() != 0 ) + { + aValues[i] = iter->maValue; + } + else + { + aProps[ NP_FORMULA ] <<= iter->msFormula; + } + } + aProps[ NP_VALUES ] <<= aValues; + aProps[ NP_KEYTIMES ] <<= aKeyTimes; + } + } + + + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + + switch ( aElementToken ) + { + case NMSP_PPT|XML_cBhvr: + xRet.set( new CommonBehaviorContext ( getHandler(), xAttribs, mpNode ) ); + break; + case NMSP_PPT|XML_tavLst: + xRet.set( new TimeAnimValueListContext ( getHandler(), xAttribs, maTavList ) ); + break; + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; + } + private: + sal_Int32 mnValueType; + TimeAnimationValueList maTavList; + }; + + + /** CT_TLAnimateScaleBehavior */ + class AnimScaleContext + : public TimeNodeContext + { + public: + AnimScaleContext( const FragmentHandlerRef& xHandler, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) throw() + : TimeNodeContext( xHandler, aElement, xAttribs, pNode ) + , mbZoomContents( false ) + { + AttributeList attribs( xAttribs ); + // TODO what to do with mbZoomContents + mbZoomContents = attribs.getBool( XML_zoomContents, false ); + pNode->getNodeProperties()[ NP_TRANSFORMTYPE ] + = makeAny((sal_Int16)AnimationTransformType::SCALE); + } + + ~AnimScaleContext( ) throw( ) + { + } + + virtual void SAL_CALL endFastElement( sal_Int32 aElement ) throw ( SAXException, RuntimeException) + { + if( aElement == mnElement ) + { + if( maTo.hasValue() ) + { + mpNode->setTo( maTo ); + } + if( maBy.hasValue() ) + { + mpNode->setBy( maBy ); + } + if( maFrom.hasValue() ) + { + mpNode->setFrom( maFrom ); + } + } + } + + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) + throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + + switch ( aElementToken ) + { + case NMSP_PPT|XML_cBhvr: + xRet.set( new CommonBehaviorContext ( getHandler(), xAttribs, mpNode ) ); + break; + case NMSP_PPT|XML_to: + { + // CT_TLPoint + Point p = GetPointPercent( xAttribs ); + maTo <<= p.X; + maTo <<= p.Y; + break; + } + case NMSP_PPT|XML_from: + { + // CT_TLPoint + Point p = GetPointPercent( xAttribs ); + maFrom <<= p.X; + maFrom <<= p.Y; + break; + } + case NMSP_PPT|XML_by: + { + // CT_TLPoint + Point p = GetPointPercent( xAttribs ); + maBy <<= p.X; + maBy <<= p.Y; + break; + } + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; + } + private: + Any maBy; + Any maFrom; + Any maTo; + bool mbZoomContents; + }; + + + /** CT_TLAnimateRotationBehavior */ + class AnimRotContext + : public TimeNodeContext + { + public: + AnimRotContext( const FragmentHandlerRef& xHandler, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) throw() + : TimeNodeContext( xHandler, aElement, xAttribs, pNode ) + { + AttributeList attribs( xAttribs ); + + pNode->getNodeProperties()[ NP_TRANSFORMTYPE ] + = makeAny((sal_Int16)AnimationTransformType::ROTATE); + // TODO make sure the units are OK + if(attribs.hasAttribute( XML_by ) ) + { + sal_Int32 nBy = attribs.getInteger( XML_by, 0 ); + pNode->setBy( makeAny( nBy ) ); + } + if(attribs.hasAttribute( XML_from ) ) + { + sal_Int32 nFrom = attribs.getInteger( XML_from, 0 ); + pNode->setFrom( makeAny( nFrom ) ); + } + if(attribs.hasAttribute( XML_to ) ) + { + sal_Int32 nTo = attribs.getInteger( XML_to, 0 ); + pNode->setTo( makeAny( nTo ) ); + } + } + + ~AnimRotContext( ) throw( ) + { + } + + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + + switch ( aElementToken ) + { + case NMSP_PPT|XML_cBhvr: + xRet.set( new CommonBehaviorContext ( getHandler(), xAttribs, mpNode ) ); + break; + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; + } + }; + + + + /** CT_TLAnimateMotionBehavior */ + class AnimMotionContext + : public TimeNodeContext + { + public: + AnimMotionContext( const FragmentHandlerRef& xHandler, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) throw() + : TimeNodeContext( xHandler, aElement, xAttribs, pNode ) + { + pNode->getNodeProperties()[ NP_TRANSFORMTYPE ] + = makeAny((sal_Int16)AnimationTransformType::TRANSLATE); + + AttributeList attribs( xAttribs ); + // ST_TLAnimateMotionBehaviorOrigin { parent, layour } + sal_Int32 nOrigin = xAttribs->getOptionalValueToken( XML_origin, 0 ); + if( nOrigin != 0 ) + { + switch(nOrigin) + { + case XML_layout: + case XML_parent: + break; + } + // TODO + } + + OUString aStr = xAttribs->getOptionalValue( XML_path ); + aStr = aStr.replace( 'E', ' ' ); + aStr = aStr.trim(); + pNode->getNodeProperties()[ NP_PATH ] = makeAny(aStr); + + // ST_TLAnimateMotionPathEditMode{ fixed, relative } + mnPathEditMode = xAttribs->getOptionalValueToken( XML_pathEditMode, 0 ); + msPtsTypes = xAttribs->getOptionalValue( XML_ptsTypes ); + mnAngle = attribs.getInteger( XML_rAng, 0 ); + // TODO make sure the units are right. Likely not. + } + + ~AnimMotionContext( ) throw() + { + } + + + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) + throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + + switch ( aElementToken ) + { + case NMSP_PPT|XML_cBhvr: + xRet.set( new CommonBehaviorContext ( getHandler(), xAttribs, mpNode ) ); + break; + case NMSP_PPT|XML_to: + { + // CT_TLPoint + Point p = GetPointPercent( xAttribs ); + Any rAny; + rAny <<= p.X; + rAny <<= p.Y; + mpNode->setTo( rAny ); + break; + } + case NMSP_PPT|XML_from: + { + // CT_TLPoint + Point p = GetPointPercent( xAttribs ); + Any rAny; + rAny <<= p.X; + rAny <<= p.Y; + mpNode->setFrom( rAny ); + break; + } + case NMSP_PPT|XML_by: + { + // CT_TLPoint + Point p = GetPointPercent( xAttribs ); + Any rAny; + rAny <<= p.X; + rAny <<= p.Y; + mpNode->setBy( rAny ); + break; + } + case NMSP_PPT|XML_rCtr: + { + // CT_TLPoint + Point p = GetPointPercent( xAttribs ); + // TODO push + break; + } + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; + } + private: + OUString msPtsTypes; + sal_Int32 mnPathEditMode; + sal_Int32 mnAngle; + }; + + + /** CT_TLAnimateEffectBehavior */ + class AnimEffectContext + : public TimeNodeContext + { + public: + AnimEffectContext( const FragmentHandlerRef& xHandler, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) throw() + : TimeNodeContext( xHandler, aElement, xAttribs, pNode ) + { + sal_Int32 nDir = xAttribs->getOptionalValueToken( XML_transition, 0 ); + OUString sFilter = xAttribs->getOptionalValue( XML_filter ); + // TODO +// OUString sPrList = xAttribs->getOptionalValue( XML_prLst ); + + if( sFilter.getLength() ) + { + SlideTransition aFilter( sFilter ); + aFilter.setMode( nDir == XML_out ? false : true ); + pNode->setTransitionFilter( aFilter ); + } + } + + + ~AnimEffectContext( ) throw() + { + } + + + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + + switch ( aElementToken ) + { + case NMSP_PPT|XML_cBhvr: + xRet.set( new CommonBehaviorContext ( getHandler(), xAttribs, mpNode ) ); + break; + case NMSP_PPT|XML_progress: + xRet.set( new AnimVariantContext( getHandler(), aElementToken, maProgress ) ); + // TODO handle it. + break; + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; + } + private: + Any maProgress; + OUString msFilter; + OUString msPrList; + }; + + + + TimeNodeContext * TimeNodeContext::makeContext( const FragmentHandlerRef& xHandler, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) + { + TimeNodeContext *pCtx = NULL; + switch( aElement ) + { + case NMSP_PPT|XML_animClr: + pCtx = new AnimColorContext( xHandler, aElement, xAttribs, pNode ); + break; + case NMSP_PPT|XML_par: + pCtx = new ParallelExclTimeNodeContext( xHandler, aElement, xAttribs, pNode ); + break; + case NMSP_PPT|XML_seq: + pCtx = new SequenceTimeNodeContext( xHandler, aElement, xAttribs, pNode ); + break; + case NMSP_PPT|XML_excl: + pCtx = new ParallelExclTimeNodeContext( xHandler, aElement, xAttribs, pNode ); + break; + case NMSP_PPT|XML_anim: + pCtx = new AnimContext ( xHandler, aElement, xAttribs, pNode ); + break; + case NMSP_PPT|XML_animEffect: + pCtx = new AnimEffectContext( xHandler, aElement, xAttribs, pNode ); + break; + case NMSP_PPT|XML_animMotion: + pCtx = new AnimMotionContext( xHandler, aElement, xAttribs, pNode ); + break; + case NMSP_PPT|XML_animRot: + pCtx = new AnimRotContext( xHandler, aElement, xAttribs, pNode ); + break; + case NMSP_PPT|XML_animScale: + pCtx = new AnimScaleContext( xHandler, aElement, xAttribs, pNode ); + break; + case NMSP_PPT|XML_cmd: + pCtx = new CmdTimeNodeContext( xHandler, aElement, xAttribs, pNode ); + break; + case NMSP_PPT|XML_set: + pCtx = new SetTimeNodeContext( xHandler, aElement, xAttribs, pNode ); + break; + case NMSP_PPT|XML_audio: + case NMSP_PPT|XML_video: + pCtx = new MediaNodeContext( xHandler, aElement, xAttribs, pNode ); + break; + default: + break; + } + return pCtx; + } + + + TimeNodeContext::TimeNodeContext( const FragmentHandlerRef& xHandler, sal_Int32 aElement, + const Reference< XFastAttributeList >& /*xAttribs*/, + const TimeNodePtr & pNode ) throw() + : Context( xHandler ) + , mnElement( aElement ) + , mpNode( pNode ) + { + } + + + TimeNodeContext::~TimeNodeContext( ) throw() + { + + } + + + TimeNodeListContext::TimeNodeListContext( const FragmentHandlerRef& xHandler, TimeNodePtrList & aList ) + throw() + : Context( xHandler ) + , maList( aList ) + { + } + + + TimeNodeListContext::~TimeNodeListContext( ) throw() + { + } + + + Reference< XFastContextHandler > SAL_CALL TimeNodeListContext::createFastChildContext( ::sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) + { + Reference< XFastContextHandler > xRet; + + sal_Int16 nNodeType; + + switch( aElementToken ) + { + case NMSP_PPT|XML_par: + nNodeType = AnimationNodeType::PAR; + break; + case NMSP_PPT|XML_seq: + nNodeType = AnimationNodeType::SEQ; + break; + case NMSP_PPT|XML_excl: + // TODO pick the right type. We choose parallel for now as + // there does not seem to be an "Exclusive" + nNodeType = AnimationNodeType::PAR; + break; + case NMSP_PPT|XML_anim: + nNodeType = AnimationNodeType::ANIMATE; + break; + case NMSP_PPT|XML_animClr: + nNodeType = AnimationNodeType::ANIMATECOLOR; + break; + case NMSP_PPT|XML_animEffect: + nNodeType = AnimationNodeType::TRANSITIONFILTER; + break; + case NMSP_PPT|XML_animMotion: + nNodeType = AnimationNodeType::ANIMATEMOTION; + break; + case NMSP_PPT|XML_animRot: + case NMSP_PPT|XML_animScale: + nNodeType = AnimationNodeType::ANIMATETRANSFORM; + break; + case NMSP_PPT|XML_cmd: + nNodeType = AnimationNodeType::COMMAND; + break; + case NMSP_PPT|XML_set: + nNodeType = AnimationNodeType::SET; + break; + case NMSP_PPT|XML_audio: + nNodeType = AnimationNodeType::AUDIO; + break; + case NMSP_PPT|XML_video: + nNodeType = AnimationNodeType::AUDIO; + OSL_TRACE( "OOX: video requested, gave Audio instead" ); + break; + + default: + nNodeType = AnimationNodeType::CUSTOM; + OSL_TRACE( "OOX: uhandled token %x", aElementToken ); + break; + } + + TimeNodePtr pNode(new TimeNode(nNodeType)); + maList.push_back( pNode ); + Context * pContext = TimeNodeContext::makeContext( getHandler(), aElementToken, xAttribs, pNode ); + xRet.set( ( pContext != NULL ? pContext : this ) ); + + if( !xRet.is() ) + xRet.set(this); + + return xRet; + } + + +} } diff --git a/oox/source/ppt/timetargetelementcontext.cxx b/oox/source/ppt/timetargetelementcontext.cxx new file mode 100644 index 000000000000..19d941619e46 --- /dev/null +++ b/oox/source/ppt/timetargetelementcontext.cxx @@ -0,0 +1,185 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: timetargetelementcontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:01 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "timetargetelementcontext.hxx" + +#include "comphelper/anytostring.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include + +#include + +#include "oox/helper/attributelist.hxx" +#include "oox/core/namespaces.hxx" +#include "oox/drawingml/embeddedwavaudiofile.hxx" +#include "tokens.hxx" + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::oox::core; + +using ::rtl::OUString; + +namespace oox { namespace ppt { + + + + // CT_TLShapeTargetElement + class ShapeTargetElementContext + : public Context + { + public: + ShapeTargetElementContext( const ::oox::core::Context & xParent, ShapeTargetElement & aValue ) + : Context( xParent ) + , bTargetSet(false) + , maShapeTarget(aValue) + { + } + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) + throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case NMSP_PPT|XML_bg: + bTargetSet = true; + maShapeTarget.mnType = XML_bg; + break; + case NMSP_PPT|XML_txEl: + bTargetSet = true; + maShapeTarget.mnType = XML_txEl; + break; + case NMSP_PPT|XML_subSp: + bTargetSet = true; + maShapeTarget.mnType = XML_subSp; + maShapeTarget.msSubShapeId = xAttribs->getOptionalValue( XML_spid ); + break; + case NMSP_PPT|XML_graphicEl: + case NMSP_PPT|XML_oleChartEl: + bTargetSet = true; + // TODO + break; + case NMSP_PPT|XML_charRg: + case NMSP_PPT|XML_pRg: + if( bTargetSet && maShapeTarget.mnType == XML_txEl ) + { + maShapeTarget.mnRangeType = (aElementToken & ~NMSP_MASK); + maShapeTarget.maRange = drawingml::GetIndexRange( xAttribs ); + } + break; + default: + break; + } + if( !xRet.is() ) + xRet.set( this ); + return xRet; + } + + private: + bool bTargetSet; + ShapeTargetElement & maShapeTarget; + }; + + + + TimeTargetElementContext::TimeTargetElementContext( const FragmentHandlerRef & xHandler, + const AnimTargetElementPtr & pValue ) + : Context( xHandler ), + mpTarget( pValue ) + { + OSL_ENSURE( mpTarget, "no valid target passed" ); + } + + + TimeTargetElementContext::~TimeTargetElementContext( ) throw( ) + { + } + + void SAL_CALL TimeTargetElementContext::endFastElement( sal_Int32 /*aElement*/ ) throw ( SAXException, RuntimeException) + { + } + + Reference< XFastContextHandler > SAL_CALL TimeTargetElementContext::createFastChildContext( ::sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case NMSP_PPT|XML_inkTgt: + { + mpTarget->mnType = XML_inkTgt; + OUString aId = xAttribs->getOptionalValue( XML_spid ); + if( aId.getLength() ) + { + mpTarget->msValue = aId; + } + break; + } + case NMSP_PPT|XML_sldTgt: + mpTarget->mnType = XML_sldTgt; + break; + case NMSP_PPT|XML_sndTgt: + { + mpTarget->mnType = XML_sndTgt; + drawingml::EmbeddedWAVAudioFile aAudio; + drawingml::getEmbeddedWAVAudioFile( getHandler(), xAttribs, aAudio); + + OUString sSndName = ( aAudio.mbBuiltIn ? aAudio.msName : aAudio.msLink ); + mpTarget->msValue = sSndName; + break; + } + case NMSP_PPT|XML_spTgt: + { + mpTarget->mnType = XML_spTgt; + OUString aId = xAttribs->getOptionalValue( XML_spid ); + mpTarget->msValue = aId; + xRet.set( new ShapeTargetElementContext( *this, mpTarget->maShapeTarget ) ); + break; + } + default: + OSL_TRACE( "OOX: unhandled tag %ld in TL_TimeTargetElement.", (aElementToken & ~NMSP_MASK) ); + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; + } + + +} } diff --git a/oox/source/ppt/timetargetelementcontext.hxx b/oox/source/ppt/timetargetelementcontext.hxx new file mode 100644 index 000000000000..8c7c5b6422e0 --- /dev/null +++ b/oox/source/ppt/timetargetelementcontext.hxx @@ -0,0 +1,65 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: timetargetelementcontext.hxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:01 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + + + +#ifndef OOX_PPT_TIMETARGETELEMENTCONTEXT +#define OOX_PPT_TIMETARGETELEMENTCONTEXT + + +#include "oox/core/context.hxx" +#include "oox/core/fragmenthandler.hxx" +#include "oox/ppt/animationspersist.hxx" + +namespace oox { namespace ppt { + + /** context CT_TLTimeTargetElement */ + class TimeTargetElementContext + : public ::oox::core::Context + { + public: + TimeTargetElementContext( const ::oox::core::FragmentHandlerRef & xHandler, const AnimTargetElementPtr & aValue ); + ~TimeTargetElementContext( ) throw( ); + virtual void SAL_CALL endFastElement( sal_Int32 /*aElement*/ ) throw ( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs ) throw ( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException ); + + private: + AnimTargetElementPtr mpTarget; + }; + +} } + + +#endif diff --git a/oox/source/shape/FastTokenHandlerService.cxx b/oox/source/shape/FastTokenHandlerService.cxx new file mode 100644 index 000000000000..cfa78248e43c --- /dev/null +++ b/oox/source/shape/FastTokenHandlerService.cxx @@ -0,0 +1,119 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: FastTokenHandlerService.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:06 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ +#include +#include "FastTokenHandlerService.hxx" + +namespace oox { +namespace shape { + +using namespace ::com::sun::star; + +FastTokenHandlerService::FastTokenHandlerService(uno::Reference< uno::XComponentContext > const & context) : + m_xContext(context) +{} + +// com.sun.star.uno.XServiceInfo: +::rtl::OUString SAL_CALL FastTokenHandlerService::getImplementationName() throw (uno::RuntimeException) +{ + return FastTokenHandlerService_getImplementationName(); +} + +::sal_Bool SAL_CALL FastTokenHandlerService::supportsService(::rtl::OUString const & serviceName) throw (uno::RuntimeException) +{ + uno::Sequence< ::rtl::OUString > serviceNames = FastTokenHandlerService_getSupportedServiceNames(); + for (::sal_Int32 i = 0; i < serviceNames.getLength(); ++i) { + if (serviceNames[i] == serviceName) + return sal_True; + } + return sal_False; +} + +uno::Sequence< ::rtl::OUString > SAL_CALL FastTokenHandlerService::getSupportedServiceNames() throw (uno::RuntimeException) +{ + return FastTokenHandlerService_getSupportedServiceNames(); +} + +::sal_Int32 SAL_CALL FastTokenHandlerService::getToken(const ::rtl::OUString & Identifier) throw (::com::sun::star::uno::RuntimeException) +{ + return mFastTokenHandler.getToken(Identifier); +} + +::rtl::OUString SAL_CALL FastTokenHandlerService::getIdentifier(::sal_Int32 Token) throw (::com::sun::star::uno::RuntimeException) +{ + return mFastTokenHandler.getIdentifier(Token); +} + +::sal_Int32 SAL_CALL FastTokenHandlerService::getTokenFromUTF8(const ::com::sun::star::uno::Sequence< ::sal_Int8 > & Identifier) throw (::com::sun::star::uno::RuntimeException) +{ + return mFastTokenHandler.getTokenFromUTF8(Identifier); +} + +::rtl::OUString SAL_CALL FastTokenHandlerService_getImplementationName() { + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.oox.FastTokenHandlerService")); +} + +uno::Sequence< ::rtl::OUString > SAL_CALL FastTokenHandlerService_getSupportedServiceNames() +{ + uno::Sequence< ::rtl::OUString > s(1); + s[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.xml.sax.FastTokenHandler")); + return s; +} + +uno::Reference< uno::XInterface > SAL_CALL FastTokenHandlerService_create( + const uno::Reference< uno::XComponentContext > & context) + SAL_THROW((uno::Exception)) +{ + return static_cast< ::cppu::OWeakObject * >(new FastTokenHandlerService(context)); +} + +uno::Reference< uno::XInterface > SAL_CALL +FastTokenHandlerService_createInstance +( const uno::Reference< lang::XMultiServiceFactory > & rSMgr) +throw( uno::Exception ) +{ + uno::Reference + xPropertySet(rSMgr, uno::UNO_QUERY_THROW); + uno::Any aDefaultContext = xPropertySet->getPropertyValue + (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DefaultContext"))); + + uno::Reference xContext; + aDefaultContext >>= xContext; + + return FastTokenHandlerService_create(xContext); +} + +}} diff --git a/oox/source/shape/FastTokenHandlerService.hxx b/oox/source/shape/FastTokenHandlerService.hxx new file mode 100644 index 000000000000..c3c8a8e4034c --- /dev/null +++ b/oox/source/shape/FastTokenHandlerService.hxx @@ -0,0 +1,89 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: FastTokenHandlerService.hxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:06 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ +#ifndef OOX_SHAPE_FAST_TOKEN_HANDLER_SERVICE_HXX +#define OOX_SHAPE_FAST_TOKEN_HANDLER_SERVICE_HXX + +#include + +#include "sal/config.h" +#include "cppuhelper/factory.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "cppuhelper/implbase2.hxx" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/xml/sax/XFastTokenHandler.hpp" + +namespace css = ::com::sun::star; + +namespace oox { +namespace shape { + +class FastTokenHandlerService: + public ::cppu::WeakImplHelper2< + css::lang::XServiceInfo, + css::xml::sax::XFastTokenHandler> +{ +public: + explicit FastTokenHandlerService(css::uno::Reference< css::uno::XComponentContext > const & context); + + // ::com::sun::star::lang::XServiceInfo: + virtual ::rtl::OUString SAL_CALL getImplementationName() throw (css::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL supportsService(const ::rtl::OUString & ServiceName) throw (css::uno::RuntimeException); + virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw (css::uno::RuntimeException); + + // ::com::sun::star::xml::sax::XFastTokenHandler: + virtual ::sal_Int32 SAL_CALL getToken(const ::rtl::OUString & Identifier) throw (css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getIdentifier(::sal_Int32 Token) throw (css::uno::RuntimeException); + virtual ::sal_Int32 SAL_CALL getTokenFromUTF8(const css::uno::Sequence< ::sal_Int8 > & Identifier) throw (css::uno::RuntimeException); + +private: + FastTokenHandlerService(FastTokenHandlerService &); // not defined + void operator =(FastTokenHandlerService &); // not defined + + virtual ~FastTokenHandlerService() {} + + css::uno::Reference< css::uno::XComponentContext > m_xContext; + FastTokenHandler mFastTokenHandler; +}; + +::rtl::OUString SAL_CALL FastTokenHandlerService_getImplementationName(); + +css::uno::Sequence< ::rtl::OUString > SAL_CALL FastTokenHandlerService_getSupportedServiceNames(); + +css::uno::Reference< css::uno::XInterface > SAL_CALL _FastTokenHandlerService_create( + const css::uno::Reference< css::uno::XComponentContext > & context) + SAL_THROW((css::uno::Exception)); + +}} +#endif // OOX_SHAPE_FAST_TOKEN_HANDLER_SERVICE_HXX diff --git a/oox/source/shape/ShapeContextHandler.cxx b/oox/source/shape/ShapeContextHandler.cxx new file mode 100644 index 000000000000..acf0dd477de1 --- /dev/null +++ b/oox/source/shape/ShapeContextHandler.cxx @@ -0,0 +1,245 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: ShapeContextHandler.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:06 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ +#include "ShapeContextHandler.hxx" +#include "oox/core/fragmenthandler.hxx" + +namespace oox { namespace shape { + +using namespace ::com::sun::star; +using namespace core; +using namespace drawingml; + +ShapeContextHandler::ShapeContextHandler +(uno::Reference< uno::XComponentContext > const & context) : +m_xContext(context) +{ + FragmentHandlerRef rFragmentHandler; + ShapePtr pMasterShape; + mpShape.reset(new Shape("com.sun.star.drawing.GraphicObjectShape" )); + + mxGraphicShapeContext.set(new GraphicShapeContext(rFragmentHandler, + pMasterShape, + mpShape)); + + mpThemePtr.reset(new Theme()); + uno::Reference + xFactory(context->getServiceManager(), uno::UNO_QUERY_THROW); + mpFilterBase.reset(new ShapeFilterBase(xFactory)); +} + +ShapeContextHandler::~ShapeContextHandler() +{ +} + +// ::com::sun::star::xml::sax::XFastContextHandler: +void SAL_CALL ShapeContextHandler::startFastElement +(::sal_Int32 Element, + const uno::Reference< xml::sax::XFastAttributeList > & Attribs) + throw (uno::RuntimeException, xml::sax::SAXException) +{ + if (mxGraphicShapeContext.is()) + mxGraphicShapeContext->startFastElement(Element, Attribs); +} + +void SAL_CALL ShapeContextHandler::startUnknownElement +(const ::rtl::OUString & Namespace, const ::rtl::OUString & Name, + const uno::Reference< xml::sax::XFastAttributeList > & Attribs) + throw (uno::RuntimeException, xml::sax::SAXException) +{ + if (mxGraphicShapeContext.is()) + mxGraphicShapeContext->startUnknownElement(Namespace, Name, Attribs); +} + +void SAL_CALL ShapeContextHandler::endFastElement(::sal_Int32 Element) + throw (uno::RuntimeException, xml::sax::SAXException) +{ + if (mxGraphicShapeContext.is()) + mxGraphicShapeContext->endFastElement(Element); +} + +void SAL_CALL ShapeContextHandler::endUnknownElement +(const ::rtl::OUString & Namespace, + const ::rtl::OUString & Name) + throw (uno::RuntimeException, xml::sax::SAXException) +{ + if (mxGraphicShapeContext.is()) + mxGraphicShapeContext->endUnknownElement(Namespace, Name); +} + +uno::Reference< xml::sax::XFastContextHandler > SAL_CALL +ShapeContextHandler::createFastChildContext +(::sal_Int32 Element, + const uno::Reference< xml::sax::XFastAttributeList > & Attribs) + throw (uno::RuntimeException, xml::sax::SAXException) +{ + uno::Reference< xml::sax::XFastContextHandler > xResult; + + if (mxGraphicShapeContext.is()) + xResult.set(mxGraphicShapeContext->createFastChildContext + (Element, Attribs)); + + return xResult; +} + +uno::Reference< xml::sax::XFastContextHandler > SAL_CALL +ShapeContextHandler::createUnknownChildContext +(const ::rtl::OUString & Namespace, + const ::rtl::OUString & Name, + const uno::Reference< xml::sax::XFastAttributeList > & Attribs) + throw (uno::RuntimeException, xml::sax::SAXException) +{ + if (mxGraphicShapeContext.is()) + return mxGraphicShapeContext->createUnknownChildContext + (Namespace, Name, Attribs); + + return uno::Reference< xml::sax::XFastContextHandler >(); +} + +void SAL_CALL ShapeContextHandler::characters(const ::rtl::OUString & aChars) + throw (uno::RuntimeException, xml::sax::SAXException) +{ + if (mxGraphicShapeContext.is()) + mxGraphicShapeContext->characters(aChars); +} + +// ::com::sun::star::xml::sax::XFastShapeContextHandler: +uno::Reference< drawing::XShape > SAL_CALL +ShapeContextHandler::getShape() throw (uno::RuntimeException) +{ + uno::Reference< drawing::XShape > xResult; + std::map< ::rtl::OUString, ShapePtr > aShapeMap; + + if (mpFilterBase.get() != NULL && mxModel.is() && + mpThemePtr.get() != NULL && mxShapes.is()) + { + mpShape->addShape + (*mpFilterBase, mxModel, mpThemePtr, aShapeMap, + mxShapes, NULL); + + xResult.set(mpShape->getXShape()); + } + + return xResult; +} + +css::uno::Reference< css::drawing::XShapes > SAL_CALL +ShapeContextHandler::getShapes() throw (css::uno::RuntimeException) +{ + return mxShapes; +} + +void SAL_CALL ShapeContextHandler::setShapes +(const css::uno::Reference< css::drawing::XShapes > & the_value) + throw (css::uno::RuntimeException) +{ + mxShapes = the_value; +} + +css::uno::Reference< css::frame::XModel > SAL_CALL +ShapeContextHandler::getModel() throw (css::uno::RuntimeException) +{ + return mxModel; +} + +void SAL_CALL ShapeContextHandler::setModel +(const css::uno::Reference< css::frame::XModel > & the_value) + throw (css::uno::RuntimeException) +{ + mxModel = the_value; +} + +::rtl::OUString ShapeContextHandler::getImplementationName() + throw (css::uno::RuntimeException) +{ + return ShapeContextHandler_getImplementationName(); +} + +uno::Sequence< ::rtl::OUString > ShapeContextHandler::getSupportedServiceNames() + throw (css::uno::RuntimeException) +{ + return ShapeContextHandler_getSupportedServiceNames(); +} + +::rtl::OUString SAL_CALL ShapeContextHandler_getImplementationName() { + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.oox.ShapeContextHandler")); +} + +::sal_Bool SAL_CALL ShapeContextHandler::supportsService +(const ::rtl::OUString & ServiceName) throw (css::uno::RuntimeException) +{ + uno::Sequence< ::rtl::OUString > aSeq = getSupportedServiceNames(); + + if (aSeq[0].equals(ServiceName)) + return sal_True; + + return sal_False; +} + +uno::Sequence< ::rtl::OUString > SAL_CALL +ShapeContextHandler_getSupportedServiceNames() +{ + uno::Sequence< ::rtl::OUString > s(1); + s[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.xml.sax.FastShapeContextHandler")); + return s; +} + +uno::Reference< uno::XInterface > SAL_CALL +ShapeContextHandler_create( + const uno::Reference< uno::XComponentContext > & context) + SAL_THROW((uno::Exception)) +{ + return static_cast< ::cppu::OWeakObject * > + (new ShapeContextHandler(context)); +} + +uno::Reference< uno::XInterface > SAL_CALL +ShapeContextHandler_createInstance +( const uno::Reference< lang::XMultiServiceFactory > & rSMgr) +throw( uno::Exception ) +{ + uno::Reference + xPropertySet(rSMgr, uno::UNO_QUERY_THROW); + uno::Any aDefaultContext = xPropertySet->getPropertyValue + (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DefaultContext"))); + + uno::Reference xContext; + aDefaultContext >>= xContext; + + return ShapeContextHandler_create(xContext); +} + +}} diff --git a/oox/source/shape/ShapeContextHandler.hxx b/oox/source/shape/ShapeContextHandler.hxx new file mode 100644 index 000000000000..6b79de0924b2 --- /dev/null +++ b/oox/source/shape/ShapeContextHandler.hxx @@ -0,0 +1,160 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: ShapeContextHandler.hxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:06 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ +#ifndef OOX_SHAPE_SHAPE_CONTEXT_HANDLER_HXX +#define OOX_SHAPE_SHAPE_CONTEXT_HANDLER_HXX + +#include +#include "sal/config.h" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "cppuhelper/implbase1.hxx" +#include "com/sun/star/xml/sax/XFastShapeContextHandler.hpp" +#include "oox/drawingml/graphicshapecontext.hxx" +#include "oox/drawingml/shape.hxx" +#include "oox/drawingml/theme.hxx" +#include "ShapeFilterBase.hxx" + +namespace css = ::com::sun::star; + +namespace oox { namespace shape { + +// component and service helper functions: +::rtl::OUString SAL_CALL ShapeContextHandler_getImplementationName(); + +css::uno::Sequence< ::rtl::OUString > SAL_CALL +ShapeContextHandler_getSupportedServiceNames(); + +css::uno::Reference< css::uno::XInterface > SAL_CALL +ShapeContextHandler_create +( css::uno::Reference< css::uno::XComponentContext > const & context ); + +css::uno::Reference< css::uno::XInterface > SAL_CALL +ShapeContextHandler_createInstance +( const css::uno::Reference< css::lang::XMultiServiceFactory > & rSMgr) +throw( css::uno::Exception ); + +class ShapeContextHandler: + public ::cppu::WeakImplHelper1< + css::xml::sax::XFastShapeContextHandler> +{ +public: + explicit ShapeContextHandler + (css::uno::Reference< css::uno::XComponentContext > const & context); + + virtual ~ShapeContextHandler(); + + // ::com::sun::star::lang::XServiceInfo: + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException); + + virtual ::sal_Bool SAL_CALL supportsService + (const ::rtl::OUString & ServiceName) throw (css::uno::RuntimeException); + + virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames() throw (css::uno::RuntimeException); + + // ::com::sun::star::xml::sax::XFastContextHandler: + virtual void SAL_CALL startFastElement + (::sal_Int32 Element, + const css::uno::Reference< css::xml::sax::XFastAttributeList > & Attribs) + throw (css::uno::RuntimeException, css::xml::sax::SAXException); + + virtual void SAL_CALL startUnknownElement + (const ::rtl::OUString & Namespace, + const ::rtl::OUString & Name, + const css::uno::Reference< css::xml::sax::XFastAttributeList > & Attribs) + throw (css::uno::RuntimeException, css::xml::sax::SAXException); + + virtual void SAL_CALL endFastElement(::sal_Int32 Element) + throw (css::uno::RuntimeException, css::xml::sax::SAXException); + + virtual void SAL_CALL endUnknownElement + (const ::rtl::OUString & Namespace, + const ::rtl::OUString & Name) + throw (css::uno::RuntimeException, css::xml::sax::SAXException); + + virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL + createFastChildContext + (::sal_Int32 Element, + const css::uno::Reference< css::xml::sax::XFastAttributeList > & Attribs) + throw (css::uno::RuntimeException, css::xml::sax::SAXException); + + virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL + createUnknownChildContext + (const ::rtl::OUString & Namespace, + const ::rtl::OUString & Name, + const css::uno::Reference< css::xml::sax::XFastAttributeList > & Attribs) + throw (css::uno::RuntimeException, css::xml::sax::SAXException); + + virtual void SAL_CALL characters(const ::rtl::OUString & aChars) + throw (css::uno::RuntimeException, css::xml::sax::SAXException); + + // ::com::sun::star::xml::sax::XFastShapeContextHandler: + virtual css::uno::Reference< css::drawing::XShape > SAL_CALL getShape() + throw (css::uno::RuntimeException); + + virtual css::uno::Reference< css::drawing::XShapes > SAL_CALL getShapes() + throw (css::uno::RuntimeException); + + virtual void SAL_CALL setShapes + (const css::uno::Reference< css::drawing::XShapes > & the_value) + throw (css::uno::RuntimeException); + + virtual css::uno::Reference< css::frame::XModel > SAL_CALL getModel() + throw (css::uno::RuntimeException); + + virtual void SAL_CALL setModel + (const css::uno::Reference< css::frame::XModel > & the_value) + throw (css::uno::RuntimeException); + +private: + ShapeContextHandler(ShapeContextHandler &); // not defined + void operator =(ShapeContextHandler &); // not defined + + css::uno::Reference< css::uno::XComponentContext > m_xContext; + drawingml::ShapePtr mpShape; + + typedef boost::shared_ptr + GraphicShapeContextPtr; + css::uno::Reference mxGraphicShapeContext; + + ShapeFilterBase::Pointer_t mpFilterBase; + css::uno::Reference mxModel; + drawingml::ThemePtr mpThemePtr; + css::uno::Reference mxShapes; +}; + +}} + +#endif // OOX_SHAPE_SHAPE_CONTEXT_HANDLER_HXX diff --git a/oox/source/shape/ShapeFilterBase.cxx b/oox/source/shape/ShapeFilterBase.cxx new file mode 100644 index 000000000000..30c4cdf462e5 --- /dev/null +++ b/oox/source/shape/ShapeFilterBase.cxx @@ -0,0 +1,69 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: ShapeFilterBase.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:06 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ +#include "ShapeFilterBase.hxx" + +namespace oox { +namespace shape { + +using namespace ::com::sun::star; + +ShapeFilterBase::ShapeFilterBase +(const uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& + rxFactory) +: XmlFilterBase(rxFactory) +{ +} + +ShapeFilterBase::~ShapeFilterBase() +{ +} + +sal_Int32 ShapeFilterBase::getSchemeClr(sal_Int32 /*nColorSchemeToken*/ ) const +{ + return 0; +} + +const vml::DrawingPtr ShapeFilterBase::getDrawings() +{ + return vml::DrawingPtr(); +} + +::rtl::OUString ShapeFilterBase::implGetImplementationName() const +{ + return ::rtl::OUString(); +} + +} +} diff --git a/oox/source/shape/ShapeFilterBase.hxx b/oox/source/shape/ShapeFilterBase.hxx new file mode 100644 index 000000000000..ab9270141dba --- /dev/null +++ b/oox/source/shape/ShapeFilterBase.hxx @@ -0,0 +1,80 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: ShapeFilterBase.hxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:07 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef OOX_SHAPE_SHAPEFILTERBASE_HXX +#define OOX_SHAPE_SHAPEFILTERBASE_HXX + +#include +#include +#include "oox/vml/drawing.hxx" +#include "oox/core/xmlfilterbase.hxx" + +namespace oox { +namespace shape { + +class FragmentHandler; + +// ============================================================================ + + +class ShapeFilterBase : public core::XmlFilterBase +{ +public: + typedef boost::shared_ptr Pointer_t; + + explicit ShapeFilterBase( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory ); + + virtual ~ShapeFilterBase(); + + /** Has to be implemented by each filter to resolve scheme colors. */ + virtual sal_Int32 getSchemeClr( sal_Int32 nColorSchemeToken ) const; + + /** Has to be implemented by each filter to return drawings collection. */ + virtual const ::oox::vml::DrawingPtr getDrawings(); + + virtual rtl::OUString implGetImplementationName() const; + + virtual bool importDocument() { return false; } + virtual bool exportDocument() { return false; } +}; + +// ============================================================================ + +} // namespace shape +} // namespace oox + +#endif + diff --git a/oox/source/shape/makefile.mk b/oox/source/shape/makefile.mk new file mode 100644 index 000000000000..d0233a990e2a --- /dev/null +++ b/oox/source/shape/makefile.mk @@ -0,0 +1,58 @@ +#************************************************************************* +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.2 $ +# +# last change: $Author: rt $ $Date: 2008-01-17 08:06:07 $ +# +# The Contents of this file are made available subject to +# the terms of GNU Lesser General Public License Version 2.1. +# +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2005 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=oox +TARGET=shape +AUTOSEG=true + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/ShapeContextHandler.obj \ + $(SLO)$/ShapeFilterBase.obj \ + $(SLO)$/FastTokenHandlerService.obj + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk diff --git a/oox/source/token/gentoken.pl b/oox/source/token/gentoken.pl new file mode 100644 index 000000000000..8f0a4610d926 --- /dev/null +++ b/oox/source/token/gentoken.pl @@ -0,0 +1,55 @@ +$ARGV0 = shift @ARGV; +$ARGV1 = shift @ARGV; +$ARGV2 = shift @ARGV; + +open ( TOKENS, $ARGV0 ) || die "can't open token file: $!"; +my %tokens; + +while ( defined ($line = ) ) +{ + chomp($line); + @token = split(/\s+/,$line); + if ( not defined ($token[1]) ) + { + $token[1] = "XML_".$token[0]; + $token[1] =~ tr/\-\.\:/___/; + $token[1] =~ s/\+/PLUS/g; + $token[1] =~ s/\-/MINUS/g; + } + + $tokens{$token[0]} = $token[1]; +} +close ( TOKENS ); + +open ( HXX, ">$ARGV1" ) || die "can't open tokens.hxx file: $!"; +open ( GPERF, ">$ARGV2" ) || die "can't open tokens.gperf file: $!"; + +print ( GPERF "%language=C++\n" ); +print ( GPERF "%global-table\n" ); +print ( GPERF "%null-strings\n" ); +print ( GPERF "%struct-type\n" ); +print ( GPERF "struct xmltoken\n" ); +print ( GPERF "{\n" ); +print ( GPERF " const sal_Char *name; sal_Int32 nToken; \n" ); +print ( GPERF "};\n" ); +print ( GPERF "%%\n" ); + +print ( HXX "#ifndef _TOKEN_HXX_\n" ); +print ( HXX "#define _TOKEN_HXX_\n\n" ); +print ( HXX "#ifndef _SAL_TYPES_H_\n" ); +print ( HXX "#include \n" ); +print ( HXX "#endif\n\n" ); + +$i = 0; +foreach( sort(keys(%tokens)) ) +{ + print( HXX "const sal_Int32 $tokens{$_} = $i;\n" ); + print( GPERF "$_,$tokens{$_}\n" ); + $i = $i + 1; +} +print ( GPERF "%%\n" ); +print ( HXX "const sal_Int32 XML_TOKEN_COUNT = $i;\n" ); +print ( HXX "const sal_Int32 XML_TOKEN_INVALID = -1;\n\n" ); +print ( HXX "#endif\n" ); +close ( HXX ); +close ( GPERF ); diff --git a/oox/source/token/makefile.mk b/oox/source/token/makefile.mk new file mode 100644 index 000000000000..543138315aa0 --- /dev/null +++ b/oox/source/token/makefile.mk @@ -0,0 +1,66 @@ +#************************************************************************* +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.2 $ +# +# last change: $Author: rt $ $Date: 2008-01-17 08:06:07 $ +# +# The Contents of this file are made available subject to +# the terms of GNU Lesser General Public License Version 2.1. +# +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2005 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=oox +TARGET=token + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/tokenmap.obj + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk + +$(INCCOM)$/tokens.hxx $(MISC)$/tokens.gperf : tokens.txt gentoken.pl + $(PERL) gentoken.pl tokens.txt $(INCCOM)$/tokens.hxx $(MISC)$/tokens.gperf + +$(INCCOM)$/tokens.cxx : $(MISC)$/tokens.gperf + gperf --compare-strncmp --output-file=$(MISC)$/_tokens.cxx $(MISC)$/tokens.gperf + $(TYPE) $(MISC)$/_tokens.cxx | $(SED) -e "s/(char\*)0/(char\*)0, 0/g" >$(INCCOM)$/tokens.cxx + +$(SLO)$/tokenmap.obj : $(INCCOM)$/tokens.cxx $(INCCOM)$/tokens.hxx + +$(INCCOM)$/tokens.gperf : $(INCCOM)$/tokens.hxx diff --git a/oox/source/token/parsexsd.pl b/oox/source/token/parsexsd.pl new file mode 100644 index 000000000000..3b6745121e4c --- /dev/null +++ b/oox/source/token/parsexsd.pl @@ -0,0 +1,48 @@ +$ARGV = shift @ARGV; +my %tokens; + +my @files = glob("$ARGV/*.rnc"); + +open( TOKEN, ">tokens.txt" ) || die "can't write token file"; + +foreach( @files ) +{ + print( "parsing $_\n" ); + open ( XSD, $_ ) || die "can't open token file: $!"; + while( ) + { + chomp($_); + if( /element (\S*:)?(\S*)/ ) + { + $tokens{$2} = 1; + print("."); + } + elsif( /attribute (\S*:)?(\S*)/ ) + { + $tokens{$2} = 1; + print("."); + } + elsif( /list\s*\{/ ) + { + while( ) + { + chomp($_); + last if( /^\s*\}/ ); + if( /"(\S*?)\"/ ) + { + $tokens{$1} = 1; + print("."); + } + } + } + } + close ( XSD ); + + print("\n" ); +} + +foreach( sort(keys(%tokens)) ) +{ + print TOKEN "$_\n"; +} +close( TOKEN ); diff --git a/oox/source/token/tokenmap.cxx b/oox/source/token/tokenmap.cxx new file mode 100644 index 000000000000..016e3055da53 --- /dev/null +++ b/oox/source/token/tokenmap.cxx @@ -0,0 +1,105 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tokenmap.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:07 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include +#include + +#include + +#include "oox/core/fasttokenhandler.hxx" +#include "tokens.hxx" + +using ::rtl::OUString; +using ::osl::Mutex; +using ::osl::MutexGuard; +using namespace ::com::sun::star::xml::sax; + +#ifdef WNT +#pragma warning(disable:4129) +#endif + +namespace oox +{ + +#include "tokens.cxx" + +Mutex& getTokenMutex() +{ + static Mutex aMutex; + return aMutex; +} + +::sal_Int32 FastTokenHandler::getToken( const ::rtl::OUString& Identifier ) throw (::com::sun::star::uno::RuntimeException) +{ + MutexGuard guard( getTokenMutex() ); + + rtl::OString aUTF8( Identifier.getStr(), Identifier.getLength(), RTL_TEXTENCODING_UTF8 ); + + struct xmltoken * t = Perfect_Hash::in_word_set( aUTF8, aUTF8.getLength() ); + if( t ) + return t->nToken; + else + return FastToken::DONTKNOW; +} + +::rtl::OUString FastTokenHandler::getIdentifier( ::sal_Int32 nToken ) throw (::com::sun::star::uno::RuntimeException) +{ + MutexGuard guard( getTokenMutex() ); + + if( nToken >= XML_TOKEN_COUNT ) + return OUString(); + + static OUString aTokens[XML_TOKEN_COUNT]; + + if( aTokens[nToken].getLength() == 0 ) + aTokens[nToken] = OUString::createFromAscii(wordlist[nToken].name); + + return aTokens[nToken]; +} + +::sal_Int32 FastTokenHandler::getTokenFromUTF8( const ::com::sun::star::uno::Sequence< ::sal_Int8 >& Identifier ) throw (::com::sun::star::uno::RuntimeException) +{ + MutexGuard guard( getTokenMutex() ); + + struct xmltoken * t = Perfect_Hash::in_word_set((const char*)Identifier.getConstArray(), Identifier.getLength()); + if( t ) + return t->nToken; + else + return FastToken::DONTKNOW; +} + +} + + diff --git a/oox/source/token/tokens.txt b/oox/source/token/tokens.txt new file mode 100644 index 000000000000..bb8f4ceac6ec --- /dev/null +++ b/oox/source/token/tokens.txt @@ -0,0 +1,5569 @@ +1D +1pic +1picTitle +2D +2pic +2picTitle +35mm +3Arrows +3ArrowsGray +3Flags +3Signs +3Symbols +3Symbols2 +3TrafficLights1 +3TrafficLights2 +3dDkShadow +3dLight +4Arrows +4ArrowsGray +4Rating +4RedToBlack +4TrafficLights +4pic +4picTitle +5Arrows +5ArrowsGray +5Quarters +5Rating +A1 +A3 +A4 +AbbreviatedCaseNumber +Accel +Accel2 +AlbumTitle +Always +Anchor +AppVersion +Append +Application +Art +ArticleInAPeriodical +Artist +Author +AutoFill +AutoFit +AutoLine +AutoPict +AutoScale +B4ISO +B4JIS +B5ISO +B5JIS +Bitmap +Book +BookAuthor +BookSection +BookTitle +BroadcastTitle +Broadcaster +Button +CF +Camera +Cancel +Case +CaseNumber +ChapterNumber +Characters +CharactersWithSpaces +Checkbox +Checked +City +ClientData +ColHidden +Colored +Column +Comments +Company +Compiler +Composer +Conductor +ConferenceName +ConferenceProceedings +ConnectionID +Content +ContentType +Corporate +Counsel +CountryRegion +Court +DDE +DMY +DVASPECT_CONTENT +DVASPECT_ICON +DYM +DataBinding +DataBindingLoadMode +DataBindingName +Day +DayAccessed +Default +DefaultSize +Department +Dialog +DigSig +Director +Disabled +Dismiss +Distributor +DocSecurity +DocumentFromInternetSite +DrawAspect +Drop +DropLines +DropStyle +Dx +EMD +ENTITIES +ENTITY +Edit +Edition +Editor +ElectronicSource +Embed +EnhancedMetaFile +Extension +False +FieldCodes +FileBinding +FileBindingName +Film +First +FirstButton +FmlaGroup +FmlaLink +FmlaMacro +FmlaPict +FmlaRange +FmlaTxbx +Format +Formula +GBox +Group +Guid +HLinks +HTMLInset +HTMLOutset +HeadingPairs +Help +HiddenSlides +Hiragana +Horiz +HyperlinkBase +HyperlinksChanged +ID +IDREF +IDREFS +Icon +Id +Inc +Institution +InternetSite +InternetSiteTitle +Interview +Interviewee +Interviewer +Inventor +Issue +JournalArticle +JournalName +JustLastX +LCID +LCT +Label +Last +LineA +Lines +Link +LinkType +LinksUpToDate +List +ListItem +LockText +Locked +LockedField +M1 +M10 +M11 +M12 +M2 +M3 +M4 +M5 +M6 +M7 +M8 +M9 +MDY +MMClips +MYD +Manager +Map +MapInfo +MapOCX +Max +Medium +Middle +Min +Misc +Month +MonthAccessed +MoveWithCells +Movie +MultiLine +MultiSel +NA +NCName +NMTOKEN +NMTOKENS +NOTATION +Name +NameList +Namespace +NoThreeD +NoThreeD2 +Note +Notes +NumberVolumes +OLEObject +OLEUPDATE_ALWAYS +OLEUPDATE_ONCALL +ObjectID +ObjectType +OnCall +Override +Page +Pages +Paragraphs +PartName +Patent +PatentNumber +Performance +Performer +PeriodicalTitle +Person +Pict +PictOld +PictPrint +PictScreen +Picture +PresentationFormat +PreserveFormat +PreserveSortAFLayout +PrintObject +ProducerName +ProductionCompany +ProgID +Properties +PublicationTitle +Publisher +Q1 +Q2 +Q3 +Q4 +QName +R1C1 +Radio +RecalcAlways +RecordingNumber +Rect +RectA +RefOrder +Relationship +RelationshipReference +Relationships +RelationshipsGroupReference +Report +Reporter +RootElement +Row +RowHidden +ScaleCrop +Schema +SchemaID +SchemaRef +ScriptExtended +ScriptLanguage +ScriptLocation +ScriptText +Scroll +SecretEdit +Sel +SelType +SelectedStyle +SelectionNamespaces +Shape +ShapeID +SharedDoc +ShortTitle +ShowImportExportValidationErrors +SignatureTime +SizeWithCells +Slides +SoundRecording +Source +SourceId +SourceType +Sources +Spin +StandardNumber +StateProvince +Station +StyleName +Tag +Target +TargetMode +Template +TextHAlign +TextVAlign +Theater +ThesisType +Title +TitlesOfParts +TotalTime +Translator +True +Type +Types +UIObj +URI +URL +UpdateMode +VScroll +VTEdit +Val +ValidIds +Value +Version +Visible +Volume +WidthMin +Words +Writer +XY +YDM +YMD +YZ +Year +YearAccessed +ZX +a +aa +above +aboveAverage +absSizeAnchor +absolute +absoluteAnchor +abstractNum +abstractNumId +aca +acc +accPr +accel +accent1 +accent2 +accent3 +accent4 +accent5 +accent6 +accentBorderCallout1 +accentBorderCallout2 +accentBorderCallout3 +accentCallout1 +accentCallout2 +accentCallout3 +accentbar +accumulate +action +actionButtonBackPrevious +actionButtonBeginning +actionButtonBlank +actionButtonDocument +actionButtonEnd +actionButtonForwardNext +actionButtonHelp +actionButtonHome +actionButtonInformation +actionButtonMovie +actionButtonReturn +actionButtonSound +active +activeBorder +activeCaption +activeCell +activeCellId +activeCol +activePane +activeRecord +activeRow +activeSheetId +activeTab +activeWritingStyle +actualPg +ad +add +additionalCharacteristics +additive +addlxml +addressBook +addressFieldName +adj +adjLst +adjust +adjustColumnWidth +adjustLineHeightInTable +adjustRightInd +adjusthandles +administrators +advAuto +advClick +advTm +advise +aft +after +afterAutospacing +afterEffect +afterGroup +afterLines +ahLst +ahPolar +ahXY +aiueo +aiueoFullWidth +alg +algIdExt +algIdExtSource +algn +alias +aliases +aliceBlue +align +alignBordersAndEdges +alignOff +alignTablesRowByRow +alignTx +alignWithMargins +alignment +alignshape +all +allAtOnce +allCaption +allDrilled +allLines +allPages +allPts +allUniqueName +allowBlank +allowOverlap +allowPNG +allowPng +allowRefreshQuery +allowSpaceOfSameStyleInTable +allowcomments +allowincell +allowoverlap +aln +alnAt +alnScr +alongPath +alpha +alphaBiLevel +alphaCeiling +alphaFloor +alphaInv +alphaLcParenBoth +alphaLcParenR +alphaLcPeriod +alphaMod +alphaModFix +alphaOff +alphaOutset +alphaRepl +alphaUcParenBoth +alphaUcParenR +alphaUcPeriod +alt +altChunk +altChunkPr +altLang +altName +althref +always +alwaysMergeEmptyNamespace +alwaysShow +alwaysShowPlaceholderText +amt +anchor +anchorCtr +anchorLock +anchorlock +anchorx +anchory +ancst +ancstOrSelf +and +ang +angle +anim +animBg +animClr +animEffect +animLvl +animMotion +animOne +animRot +animScale +annotation +annotationRef +antiqueWhite +antsBlack +antsRed +any +anyType +anyURI +appName +appWorkspace +apples +applyAlignment +applyAlignmentFormats +applyBorder +applyBorderFormats +applyBreakingRules +applyFill +applyFont +applyFontFormats +applyNumberFormat +applyNumberFormats +applyPatternFormats +applyProtection +applyStyles +applyToEnd +applyToFront +applyToSides +applyWidthHeightFormats +aqua +aquamarine +ar +arabic1Minus +arabic2Minus +arabicAbjad +arabicAlpha +arabicDbPeriod +arabicDbPlain +arabicParenBoth +arabicParenR +arabicPeriod +arabicPlain +arc +arcTo +archedScallops +arcsize +area +area3DChart +areaChart +areaError +arg +argPr +argSz +around +arr +array +arrow +arrowok +artDeco +asDisplayed +ascending +ascendingAlpha +ascendingNatural +ascii +asciiTheme +aspect +aspectratio +assign +asst +asteriskTotals +atEnd +atLeast +atMost +attachedSchema +attachedTemplate +attr +attrName +attrNameLst +attribute +audio +audioCd +audioFile +author +authorId +authors +auto +autoAdjust +autoCaption +autoCaptions +autoCompressPictures +autoEnd +autoExp +autoFilter +autoFilterDateGrouping +autoFormatId +autoFormatOverride +autoHyphenation +autoLoad +autoNoTable +autoPage +autoPageBreaks +autoRecover +autoRedefine +autoRepublish +autoRev +autoShow +autoSortScope +autoSpaceDE +autoSpaceDN +autoSpaceLikeWord95 +autoStart +autoText +autoTitleDeleted +autoTxRot +autoTxt +autoUpdate +autoUpdateAnimBg +autoZero +autofit +autofitToFirstFixedWidthCell +autoformat +autolayout +autorotationcenter +avLst +average +avg +avgSubtotal +axId +axPos +axis +axisCol +axisPage +axisRow +axisValues +azure +b +bCs +bCtr +bCtrCh +bCtrDes +bIns +bL +bMarg +bOff +bR +babyPacifier +babyRattle +back +backWall +backdepth +backdrop +background +background1 +background2 +backgroundQuery +backgroundRefresh +backupFile +backward +backwardCompatible +backwards +bal +balanceSingleByteDoubleByteWidth +balanced +balloons3Colors +balloonsHotAir +band1H +band1Horz +band1V +band1Vert +band2H +band2Horz +band2V +band2Vert +bandCol +bandFmt +bandFmts +bandRow +banner +bar +bar3DChart +barChart +barDir +barPr +base +base64Binary +baseColWidth +baseField +baseItem +baseJc +baseTimeUnit +baseType +basedOn +baseline +basicBlackDashes +basicBlackDots +basicBlackSquares +basicThinLines +basicWhiteDashes +basicWhiteDots +basicWhiteSquares +basicWideInline +basicWideMidline +basicWideOutline +bats +bbPlcHdr +bc +bdr +bef +before +beforeAutospacing +beforeLines +beg +begChr +begMarg +begPad +begPts +begSty +begin +beginsWith +behavior +behaviors +behindDoc +beige +below +belowAverage +bend +bendDist +bendPt +beneathText +bentArrow +bentConnector2 +bentConnector3 +bentConnector4 +bentConnector5 +bentUpArrow +bestFit +between +bevel +bevelB +bevelT +bg +bg1 +bg2 +bgClr +bgColor +bgFillStyleLst +bgPr +bgRef +bi +biLevel +bib +bibliography +bidi +bidiVisual +bilevel +billions +birds +birdsFlight +bisque +bk +bkPtFixedVal +bkpt +bl +black +blackAndWhite +blackGray +blackTextAndLines +blackTextOnWhite +blackWhite +blacklevel +blanchedAlmond +blank +blankRow +bld +bldAsOne +bldChart +bldDgm +bldGraphic +bldLst +bldLvl +bldOleChart +bldP +bldStep +bldSub +blend +blinds +blinkBackground +blip +blipFill +blipPhldr +blob +block +blockArc +blockQuote +blue +blueMod +blueOff +blueViolet +blur +blurRad +bmk +body +bodyDiv +bodyPr +bodyStyle +bold +boldItalic +bookFoldPrinting +bookFoldPrintingSheets +bookFoldRevPrinting +bookViews +bookmarkEnd +bookmarkIdSeed +bookmarkStart +bool +boolVal +boolean +border +borderBox +borderBoxPr +borderCallout1 +borderCallout2 +borderCallout3 +borderId +borderbottom +borderbottomcolor +borderleft +borderleftcolor +borderright +borderrightcolor +borders +bordersDoNotSurroundFooter +bordersDoNotSurroundHeader +bordertop +bordertopcolor +bot +both +bothSides +bottom +bottomFromText +bottomLeft +bottomMargin +bottomRight +boundingCube +box +boxPr +br +bracePair +bracketPair +branch +breadthByLvl +breadthByNode +bright +brightRoom +brightness +brk +brkBin +brkBinSub +brown +browse +browser +bstr +btLr +btnFace +btnHighlight +btnShadow +btnText +buAutoNum +buBlip +buChar +buClr +buClrTx +buFont +buFontTx +buNone +buSzPct +buSzPts +buSzTx +bubble3D +bubbleChart +bubbleScale +bubbleSize +build +builtIn +builtInGroupCount +builtInUnit +builtinId +bulEnabled +bullet +bulletEnabled +bullseye +burlyWood +button +bw +bwMode +bwmode +bwnormal +bwpure +bx +by +byPosition +byte +c +cBhvr +cGp +cGpRule +cMediaNode +cNvCxnSpPr +cNvGraphicFramePr +cNvGrpSpPr +cNvPicPr +cNvPr +cNvSpPr +cSld +cSldViewPr +cSp +cTn +cViewPr +ca +cabins +cacheField +cacheFields +cacheHierarchies +cacheHierarchy +cacheId +cacheIndex +cacheSource +cachedColBalance +cadetBlue +cakeSlice +calcChain +calcCompleted +calcId +calcMode +calcOnExit +calcOnSave +calcPr +calcmode +calculated +calculatedColumn +calculatedColumnFormula +calculatedItem +calculatedItems +calculatedMember +calculatedMembers +calendar +calendarType +call +callout +callout1 +callout2 +callout3 +camera +can +canSlip +candyCorn +cantSplit +canvas +cap +caps +caption +captionBeginsWith +captionBetween +captionContains +captionEndsWith +captionEqual +captionGreaterThan +captionGreaterThanOrEqual +captionLessThan +captionLessThanOrEqual +captionNotBeginsWith +captionNotBetween +captionNotContains +captionNotEndsWith +captionNotEqual +captionText +captions +cardinalText +caseSensitive +cat +catAx +catLst +catalog +category +categoryEl +categoryIdx +ccw +ccwIn +ccwOut +cell +cell3D +cellColor +cellComments +cellDel +cellIns +cellIs +cellMerge +cellMeta +cellMetadata +cellSmartTag +cellSmartTagPr +cellSmartTags +cellStyle +cellStyleXfs +cellStyles +cellWatch +cellWatches +cellXfs +celticKnotwork +center +centerContinuous +centerGroup +centered +certificateBanner +cf +cfRule +cfvo +ch +chAlign +chDir +chExt +chMax +chOff +chOrder +chPref +chainLink +champagneBottle +changesSavedWin +chapNum +chapSep +chapStyle +char +charRg +charSpace +character +characterSpacingControl +characteristic +charset +chart +chartAndTx +chartFormat +chartFormats +chartObject +chartPlus +chartSpace +chartStar +chartX +chartreuse +chartsheet +checkBox +checkCompatibility +checkErrors +checkStyle +checked +checkedBarBlack +checkedBarColor +checker +checkered +chevron +chicago +childStyle +childTnLst +chilly +chineseCounting +chineseCountingThousand +chineseLegalSimplified +chocolate +choose +chord +chosung +chr +christmasTree +chromakey +circle +circleNumDbPlain +circleNumWdBlackPlain +circleNumWdWhitePlain +circlesLines +circlesRectangles +circularArrow +citation +class +classic +classicalWave +clean +clear +clearAll +clearComments +clearContents +clearFormats +click +clickAndTypeStyle +clickEffect +clickPar +clientData +clientInsertedTime +clip +clipArt +clipArtAndTx +clipArtAndVertTx +clippath +clipped +cliptowrap +clocks +close +cloud +cloudCallout +clr +clrChange +clrData +clrFrom +clrIdx +clrMap +clrMapOvr +clrMode +clrMru +clrRepl +clrScheme +clrSchemeMapping +clrSpc +clrTo +clrVal +clsid +clustered +cm +cmAuthor +cmAuthorLst +cmLst +cmd +cmpd +cnfStyle +cnt +code +codeName +codePage +coerce +coherent3DOff +col +colBreaks +colDelim +colFields +colFirst +colGrandTotals +colHeaderCaption +colHierarchiesUsage +colHierarchyUsage +colId +colItems +colLast +colOff +colPageCount +collapse +collapsed +collapsedLevelsAreSubtotals +colon +color +color2 +colorFilter +colorId +colorScale +colormenu +colormode +colormru +colors +colorsDef +colorsDefHdr +colorsDefHdrLst +cols +column +columnSort +comb +combine +combineBrackets +comboBox +commIndAndComment +commIndicator +commNone +comma +command +commandType +comment +commentList +commentRangeEnd +commentRangeStart +commentReference +comments +comp +compact +compactData +compass +compat +compatLnSpc +compatMode +complex +composite +compressPunctuation +compressPunctuationAndJapaneseKana +computedArea +concurrent +concurrentCalc +concurrentManualCount +cond +condense +conditionalFormat +conditionalFormats +conditionalFormatting +cone +coneToMax +confetti +confettiGrays +confettiOutline +confettiStreamers +confettiWhite +conn +connDist +connRout +connectString +connectangles +connection +connectionId +connections +connectloc +connectlocs +connector +connectortype +connecttype +consecutive +consecutiveHyphenLimit +consolidation +constr +constrLst +constrainbounds +cont +contDir +containsBlank +containsBlanks +containsDate +containsErrors +containsInteger +containsMixedTypes +containsNonDate +containsNumber +containsSemiMixedTypes +containsString +containsText +content +contentLocked +contentStatus +contentType +contextualSpacing +continuationNotice +continuationSeparator +continue +continuous +contourClr +contourW +contrast +contrasting +contributors +control +control1 +control2 +controls +convMailMergeEsc +convex +coolSlant +coordorigin +coordsize +copies +copy +coral +coreProperties +corner +cornerTabs +cornerTriangles +cornflowerBlue +cornsilk +count +countA +countASubtotal +countBy +countNums +countSubtotal +couponCutoutDashes +couponCutoutDots +cover +coverPg +cp +cr +crashSave +crazyMaze +created +createdVersion +creator +creaturesButterfly +creaturesFish +creaturesInsects +creaturesLadyBug +credentials +crimson +cropbottom +cropleft +cropping +cropright +croptop +cross +crossAx +crossBetween +crossStitch +crosses +crossesAt +cryptAlgorithmClass +cryptAlgorithmSid +cryptAlgorithmType +cryptProvider +cryptProviderType +cryptProviderTypeExt +cryptProviderTypeExtSource +cryptSpinCount +cs +csCatId +csTypeId +csb0 +csb1 +css +cstate +cstheme +ct +ctr +ctrShpMap +ctrTitle +ctrX +ctrXOff +ctrY +ctrYOff +ctrlPr +cube +cubicBezTo +culture +cup +curly +current +currentDate +currentTime +curve +curved +curvedConnector2 +curvedConnector3 +curvedConnector4 +curvedConnector5 +curvedDownArrow +curvedLeftArrow +curvedRightArrow +curvedUpArrow +cust +custAng +custAutoTxt +custBib +custClr +custClrLst +custCoverPg +custDash +custData +custDataLst +custEq +custFlipHor +custFlipVert +custFtrs +custGeom +custHdrs +custLinFactNeighborX +custLinFactNeighborY +custLinFactX +custLinFactY +custPgNum +custPgNumB +custPgNumMargins +custPgNumT +custQuickParts +custRadScaleInc +custRadScaleRad +custScaleX +custScaleY +custShow +custShowLst +custSplit +custSzX +custSzY +custT +custTblOfContents +custTbls +custTxtBox +custUnit +custWatermarks +custom +custom1 +custom2 +custom3 +custom4 +custom5 +customBuiltin +customFilter +customFilters +customFormat +customHeight +customList +customListSort +customMarkFollows +customMenu +customPr +customProperties +customRollUp +customSheetView +customSheetViews +customStyle +customView +customWidth +customWorkbookView +customWorkbookViews +customXml +customXmlDelRangeEnd +customXmlDelRangeStart +customXmlInsRangeEnd +customXmlInsRangeStart +customXmlMoveFromRangeEnd +customXmlMoveFromRangeStart +customXmlMoveToRangeEnd +customXmlMoveToRangeStart +customXmlPr +cut +cw +cwIn +cwOut +cx +cxn +cxnId +cxnLst +cxnSp +cxnSpLocks +cy +cyan +cycle +cylinder +d +dLbl +dLblPos +dLbls +dPr +dPt +dTable +dark1 +dark2 +darkBlue +darkCyan +darkDown +darkGray +darkGreen +darkGrid +darkHorizontal +darkMagenta +darkRed +darkTrellis +darkUp +darkVertical +darkYellow +darken +darkenLess +dash +dashDnDiag +dashDot +dashDotDot +dashDotDotHeavy +dashDotHeavy +dashDotStroked +dashHeavy +dashHorz +dashLong +dashLongHeavy +dashSmallGap +dashUpDiag +dashVert +dashed +dashedHeavy +dashedSmall +dashstyle +data +dataBar +dataBinding +dataBound +dataCaption +dataCellStyle +dataConsolidate +dataDxfId +dataExtractLoad +dataField +dataFields +dataModel +dataOnRows +dataOnly +dataPosition +dataRef +dataRefs +dataSource +dataSourceSort +dataTable +dataType +dataValidation +dataValidations +database +databaseField +datastoreItem +date +date1904 +dateAx +dateBetween +dateEqual +dateFormat +dateGroupItem +dateNewerThan +dateNewerThanOrEqual +dateNotBetween +dateNotEqual +dateOlderThan +dateOlderThanOrEqual +dateTime +dateTimeGrouping +day +dayLong +dayShort +days +dbColumn +dbPr +dbl +dblStrike +ddList +ddeItem +ddeItems +ddeLink +ddeService +ddeTopic +dec +decagon +decel +decimal +decimalEnclosedCircle +decimalEnclosedCircleChinese +decimalEnclosedFullstop +decimalEnclosedParen +decimalFullWidth +decimalFullWidth2 +decimalHalfWidth +decimalSymbol +decimalZero +decoArch +decoArchColor +decoBlocks +decorated +decorative +deepPink +deepSkyBlue +def +defJc +defLockedState +defPPr +defQFormat +defRPr +defSemiHidden +defStyle +defTabSz +defUIPriority +defUnhideWhenUsed +default +defaultAttributeDrillState +defaultColWidth +defaultGridColor +defaultMemberUniqueName +defaultPivotStyle +defaultRowHeight +defaultSubtotal +defaultTabStop +defaultTableStyle +defaultTextStyle +defaultThemeVersion +definedName +definedNames +deg +degHide +degree +del +del1 +del2 +delInstrText +delText +delay +delete +deleteCol +deleteColumns +deleteRow +deleteRows +deleted +deletedField +delimited +delimiter +den +denormalized +depth +depthByBranch +depthByNode +depthPercent +des +desOrSelf +desc +descending +descendingAlpha +descendingNatural +descr +description +destId +destOrd +destination +destinationFile +detectmouseclick +dgm +dgmbasetextscale +dgmfontsize +dgmlayout +dgmlayoutmru +dgmnodekind +dgmscalex +dgmscaley +dgmstyle +diagBrick +diagCross +diagStripe +diagonal +diagonalDown +diagonalUp +diagram +dialogsheet +diam +diamond +diamondsGray +diff +difference +differentFirst +differentOddEven +diffusity +dim +dimGray +dimension +dimensionUniqueName +dimensions +dir +dirty +disableEdit +disableFieldList +disablePrompts +disableRefresh +disabled +discrete +discretePr +diskRevisions +dispBlanksAs +dispDef +dispEq +dispRSqr +dispUnits +dispUnitsLbl +displacedByCustomXml +display +displayBackgroundShape +displayFolder +displayHangulFixedWidth +displayHorizontalDrawingGridEvery +displayName +displayText +displayVerticalDrawingGridEvery +displayed +dissolve +dist +distB +distL +distR +distT +distance +distribute +distributeLetter +distributeSpace +distributed +div +divBdr +divId +divot +divs +divsChild +dk1 +dk2 +dkBlue +dkCyan +dkDnDiag +dkEdge +dkGoldenrod +dkGray +dkGreen +dkHorz +dkKhaki +dkMagenta +dkOliveGreen +dkOrange +dkOrchid +dkRed +dkSalmon +dkSeaGreen +dkSlateBlue +dkSlateGray +dkTurquoise +dkUpDiag +dkVert +dkViolet +dllVersion +dm +dn +dnDiag +doNotAutoCompressPictures +doNotAutofitConstrainedTables +doNotBreakConstrainedForcedTable +doNotBreakWrappedTables +doNotCompress +doNotDemarcateInvalidXml +doNotDisplayPageBoundaries +doNotEmbedSmartTags +doNotExpandShiftReturn +doNotHyphenateCaps +doNotIncludeSubdocsInStats +doNotLeaveBackslashAlone +doNotOrganizeInFolder +doNotRelyOnCSS +doNotSaveAsSingleFile +doNotShadeFormData +doNotSnapToGridInCell +doNotSuppressBlankLines +doNotSuppressIndentation +doNotSuppressParagraphBorders +doNotTrackFormatting +doNotTrackMoves +doNotUseEastAsianBreakRules +doNotUseHTMLParagraphAutoSpacing +doNotUseIndentAsNumberingTabStop +doNotUseLongFileNames +doNotUseMarginsForDrawingGridOrigin +doNotValidateAgainstSchema +doNotVertAlignCellWithSp +doNotVertAlignInTxbx +doNotWrapTextWithPunct +doc +docDefaults +docEnd +docGrid +docLocation +docPart +docPartBody +docPartCategory +docPartGallery +docPartList +docPartObj +docPartPr +docPartUnique +docParts +docPr +docVar +docVars +document +document1 +document2 +documentProtection +documentType +dodecagon +dodgerBlue +donut +dos +dot +dotDash +dotDashHeavy +dotDmnd +dotDotDash +dotDotDashHeavy +dotGrid +dotted +dottedHeavy +double +double-struck +doubleAccounting +doubleD +doubleDiamonds +doubleQuote +doubleWave +doubleclicknotify +doughnutChart +down +downArrow +downArrowCallout +downBars +downThenOver +dpi +dr +draft +dragOff +dragToCol +dragToData +dragToPage +dragToRow +drawing +drawingGridHorizontalOrigin +drawingGridHorizontalSpacing +drawingGridVerticalOrigin +drawingGridVerticalSpacing +drill +drop +dropCap +dropDownList +dropLines +dropauto +ds +dstNode +dstrike +dt +dt2D +dtr +duotone +duplicateValues +dur +duration +dvAspect +dx +dxa +dxaOrig +dxf +dxfId +dxfs +dy +dyaOrig +dynamicAddress +dynamicFilter +dz +e +eMail +ea +ea1ChsPeriod +ea1ChsPlain +ea1ChtPeriod +ea1ChtPlain +ea1JpnChsDbPeriod +ea1JpnKorPeriod +ea1JpnKorPlain +eaLnBrk +eaVert +eachPage +eachSect +earth1 +earth2 +eastAsia +eastAsiaTheme +eastAsianLayout +eb +eclipsingSquares1 +eclipsingSquares2 +ed +edGrp +edge +edit +editAs +editData +editPage +editas +edited +editors +effect +effectClrLst +effectDag +effectExtent +effectLst +effectRef +effectStyle +effectStyleLst +eggsBlack +el +elbow +ellipse +ellipseRibbon +ellipseRibbon2 +ellipsis +else +em +emDash +email +embed +embedBold +embedBoldItalic +embedItalic +embedRegular +embedSystemFonts +embedTrueTypeFonts +embeddedFont +embeddedFontLst +emboss +embosscolor +emph +empty +emptyCellReference +enDash +enableDrill +enableFieldProperties +enableFormatConditionsCalculation +enableRefresh +enableWizard +enabled +encoding +end +endA +endAngle +endChr +endCnv +endCondLst +endCxn +endDate +endMarg +endNum +endOfListFormulaUpdate +endPad +endParaRPr +endPos +endPts +endSnd +endSty +endSync +endarrow +endarrowlength +endarrowwidth +endcap +endnote +endnotePr +endnoteRef +endnoteReference +endnotes +endsWith +enforcement +entr +entries +entry +entryMacro +envelopes +eol +eq +eqArr +eqArrPr +eqn +equ +equal +equalAverage +equalWidth +equation +equationxml +err +errBarType +errBars +errDir +errValType +error +errorCaption +errorStyle +errorTitle +errors +evalError +evalOrder +even +evenAndOddHeaders +evenFooter +evenHeader +evenPage +everyone +evt +evtFilter +exact +excl +exclusive +exit +exitMacro +exp +explosion +expression +ext +extLst +extend +extendable +extent +external +externalBook +externalData +externalLink +externalReference +externalReferences +extraClrScheme +extraClrSchemeLst +extrusion +extrusionClr +extrusionH +extrusionOk +extrusioncolor +extrusionok +f +fHdr +fLocksText +fLocksWithSheet +fName +fNode +fPr +fPrintsWithSheet +fPublished +facet +fact +factor +fade +fadeDir +fallback +false +family +fans +fast +fax +fc +ffData +fgClr +fgColor +fi +field +fieldGroup +fieldId +fieldIdWrapped +fieldListSortAscending +fieldMapData +fieldPosition +fieldPrintTitles +fieldUsage +fieldsUsage +fileRecoveryPr +fileSharing +fileType +fileVersion +filetime +fill +fillClrLst +fillFormulas +fillId +fillOverlay +fillRect +fillRef +fillStyleLst +fillToRect +fillcolor +filled +fillok +fills +filltype +film +filter +filterColumn +filterMode +filterPrivacy +filterUnique +filterVal +filters +firebrick +firecrackers +first +firstAndLastLine +firstBackgroundRefresh +firstCol +firstColumn +firstColumnStripe +firstColumnSubheading +firstDataCol +firstDataRow +firstFooter +firstHeader +firstHeaderCell +firstHeaderRow +firstLine +firstLineChars +firstLineOnly +firstPage +firstPageNumber +firstRow +firstRowStripe +firstRowSubheading +firstSheet +firstSliceAng +firstSlideNum +firstSubtotalColumn +firstSubtotalRow +firstTotalCell +fitText +fitToHeight +fitToPage +fitToSlide +fitToWidth +fitpath +fitshape +fixed +fixedVal +flat +flatBorders +flatTx +fld +fldChar +fldCharType +fldData +fldLock +fldSimple +flip +flipH +flipV +float +flood +floor +floralWhite +flowChartAlternateProcess +flowChartCollate +flowChartConnector +flowChartDecision +flowChartDelay +flowChartDisplay +flowChartDocument +flowChartExtract +flowChartInputOutput +flowChartInternalStorage +flowChartMagneticDisk +flowChartMagneticDrum +flowChartMagneticTape +flowChartManualInput +flowChartManualOperation +flowChartMerge +flowChartMultidocument +flowChartOfflineStorage +flowChartOffpageConnector +flowChartOnlineStorage +flowChartOr +flowChartPredefinedProcess +flowChartPreparation +flowChartProcess +flowChartPunchedCard +flowChartPunchedTape +flowChartSort +flowChartSummingJunction +flowChartTerminator +flowDir +flowersBlockPrint +flowersDaisies +flowersModern1 +flowersModern2 +flowersPansy +flowersRedRose +flowersRoses +flowersTeacup +flowersTiny +fltVal +fmla +fmt +fmtId +fmtScheme +fmtid +focus +focusposition +focussize +folHlink +foldedCorner +follow +followColorScheme +followSib +followedHyperlink +font +fontAlgn +fontColor +fontId +fontKey +fontRef +fontScale +fontScheme +fontSz +fonts +footer +footerReference +footnote +footnoteLayoutLikeWW8 +footnotePr +footnoteRef +footnoteReference +footnotes +for +forEach +forName +forceAA +forceFullCalc +forceUpgrade +forcedash +foredepth +forestGreen +forgetLastTabAlignment +formFld +formLetters +formProt +format +formatCells +formatCode +formatColumns +formatRows +formats +formatting +forms +formsDesign +formula +formula1 +formula2 +formulaRange +formulas +forward +fourObj +fov +fraktur +frame +frameLayout +framePr +frameSlides +frameStyle1 +frameStyle2 +frameStyle3 +frameStyle4 +frameStyle5 +frameStyle6 +frameStyle7 +frameset +framesetSplitbar +freeze +freezing +from +fromB +fromL +fromR +fromT +fromWordArt +front +frozen +frozenSplit +ftr +ftrs +fuchsia +full +fullAlpha +fullCalcOnLoad +fullDate +fullHangul +fullKatakana +fullPage +fullPrecision +fullScrn +fullwidthKatakana +func +funcPr +function +functionGroup +functionGroupId +functionGroups +funnel +futureMetadata +g +gDay +gMonth +gMonthDay +gYear +gYearMonth +gain +gainsboro +gallery +gamma +ganada +gap +gapDepth +gapWidth +gd +gdLst +gdRefAng +gdRefR +gdRefX +gdRefY +ge +gear6 +gear9 +gems +general +gfxdata +ghostCol +ghostRow +ghostWhite +gingerbreadMan +glossaryDocument +glow +goal +gold +goldenrod +grDir +gradFill +gradient +gradientActiveCaption +gradientCenter +gradientFill +gradientInactiveCaption +gradientRadial +gradientUnscaled +gradientshapeok +gramEnd +gramStart +grammar +grand +grandCol +grandRow +grandTotalCaption +graphic +graphicData +graphicEl +graphicFrame +graphicFrameLocks +grav +gray +gray0625 +gray125 +grayOutline +grayScale +grayText +grayWhite +grayscale +grayscl +greaterThan +greaterThanOrEqual +green +greenMod +greenOff +greenYellow +gregorian +gregorianArabic +gregorianMeFrench +gregorianUs +gregorianXlitEnglish +gregorianXlitFrench +gridAfter +gridBefore +gridCol +gridDropZones +gridLegend +gridLines +gridLinesSet +gridSpacing +gridSpan +group +groupBy +groupChr +groupChrPr +groupInterval +groupItems +groupLevel +groupLevels +groupMember +groupMembers +grouping +groups +grow +growAutofit +growShrinkType +grpFill +grpId +grpSp +grpSpLocks +grpSpPr +gs +gsLst +gt +gte +guid +guide +guideLst +gutter +gutterAtTop +h +hAnchor +hAnsi +hAnsiTheme +hArH +hMerge +hMode +hOff +hPercent +hR +hRule +hSpace +hagakiCard +hair +hairline +half +halfAlpha +halfFrame +halfHangul +halfKatakana +halfwidthKatakana +handles +handmade1 +handmade2 +handoutMaster +handoutMasterId +handoutMasterIdLst +handoutView +handouts1 +handouts2 +handouts3 +handouts4 +handouts6 +handouts9 +hang +hanging +hangingChars +hangingPunct +hardEdge +harsh +hasCustomPrompt +hash +hashData +hdr +hdrShapeDefaults +hdrs +headEnd +header +headerFooter +headerReference +headerRow +headerRowBorderDxfId +headerRowCellStyle +headerRowCount +headerRowDxfId +headerSource +headers +headersInLastRefresh +heading +headings +heart +heartBalloon +heartGray +hearts +heavy +hebrew +hebrew1 +hebrew2 +hebrew2Minus +heebieJeebies +help +helpText +heptagon +hex +hexBinary +hexagon +hf +hiLowLines +hidden +hiddenButton +hiddenColumn +hiddenColumns +hiddenLevel +hiddenRow +hiddenRows +hiddenSlides +hide +hideBot +hideGeom +hideGrammaticalErrors +hideLastTrans +hideLeft +hideMark +hideNewItems +hidePivotFieldList +hideRight +hideSpellingErrors +hideTop +hier +hierAlign +hierBranch +hierChild +hierRoot +hierarchy +hierarchyUsage +high +highContrast +highKashida +highlight +highlightClick +highlightText +hijri +hindiAlpha1Period +hindiAlphaPeriod +hindiConsonants +hindiCounting +hindiNumParenR +hindiNumPeriod +hindiNumbers +hindiVowels +hint +hiragana +history +hlink +hlinkClick +hlinkHover +hlinkMouseOver +hold +holeSize +holly +homePlate +honeydew +horizontal +horizontalCentered +horizontalDpi +horizontalScroll +horz +horzAlign +horzAnchor +horzBarState +horzBrick +horzCross +horzOverflow +horzStripe +hotLight +hotPink +hour +hours +houseFunky +how +hps +hpsBaseText +hpsRaise +hqprint +hr +hralign +href +hrnoshade +hrpct +hrstd +hsl +hslClr +ht +htmlFormat +htmlPubPr +htmlTables +hue +hueDir +hueMod +hueOff +hundredMillions +hundredThousands +hundreds +hybridMultilevel +hyperlink +hyperlinks +hyphen +hyphenationZone +hypnotic +i +i1 +i2 +i3 +i4 +i8 +iCs +iLevel +iMeasureFld +iMeasureHier +iceCreamCones +icon +iconFilter +iconId +iconSet +id +idcntr +iddest +identifier +ideographDigital +ideographEnclosedCircle +ideographLegalTraditional +ideographTraditional +ideographZodiac +ideographZodiacTraditional +idmap +idref +idsrc +idx +if +ignore +ignoreMixedContent +ignoredError +ignoredErrors +ilvl +image +imagealignshape +imageaspect +imagedata +imagesize +imeMode +img +imgH +imgSz +imgW +immersive +imprint +in +inBase +inByRing +inEnd +inactiveBorder +inactiveCaption +inactiveCaptionText +includeHiddenRowCol +includeNewItemsInFilter +includePrintSettings +ind +indefinite +indent +index +indexed +indexedColors +indianRed +indigo +infoBk +infoText +information +init +initials +ink +inkAnnotations +inkTgt +inline +inlineStr +inner +innerShdw +inputCells +ins +insDel +insertBlankRow +insertClear +insertCol +insertColumns +insertDelete +insertHyperlinks +insertPageBreak +insertRow +insertRowShift +insertRows +inset +insetmode +insetpen +insetpenok +inside +insideH +insideMargin +insideV +instr +instrText +int +intLim +intVal +integer +integrated +interSp +interactiveSeq +intercept +intermediate +interval +intraSp +inv +invGamma +invGray +invalEndChars +invalStChars +invalid +invalidUrl +inverseGray +invertIfNegative +invx +invy +iroha +irohaFullWidth +irregularSeal1 +irregularSeal2 +is +isLgl +isNarration +isPhoto +iscomment +isometricBottomDown +isometricBottomUp +isometricLeftDown +isometricLeftUp +isometricOffAxis1Left +isometricOffAxis1Right +isometricOffAxis1Top +isometricOffAxis2Left +isometricOffAxis2Right +isometricOffAxis2Top +isometricOffAxis3Bottom +isometricOffAxis3Left +isometricOffAxis3Right +isometricOffAxis4Bottom +isometricOffAxis4Left +isometricOffAxis4Right +isometricRightDown +isometricRightUp +isometricTopDown +isometricTopUp +issignatureline +italic +item +itemID +itemPageCount +itemPrintTitles +items +iterate +iterateCount +iterateDelta +ivory +japan +japaneseCounting +japaneseDigitalTenThousand +japaneseLegal +jc +joinstyle +just +justLow +justify +justifyLastLine +k +keepAlive +keepChangeHistory +keepLines +keepNext +kern +key +keyAttribute +keywords +khaki +kinsoku +kiosk +korea +koreanCounting +koreanDigital +koreanDigital2 +koreanLegal +kpi +kpis +kumimoji +kx +ky +l +lB +lBounds +lCtrCh +lCtrDes +lIns +lMarg +lMargin +lOff +lT +label +labelOnly +landscape +lang +language +largest +last +last7Days +lastClick +lastClr +lastCol +lastColumn +lastEdited +lastGuid +lastHeaderCell +lastIdx +lastLineOnly +lastModifiedBy +lastMonth +lastPrinted +lastQuarter +lastRenderedPageBreak +lastRow +lastTotalCell +lastValue +lastView +lastWeek +lastYear +lat +latentStyles +latin +latinLnBrk +lavender +lavenderBlush +lawnGreen +layout +layoutDef +layoutDefHdr +layoutDefHdrLst +layoutInCell +layoutNode +layoutRawTableWidth +layoutTableRowsApart +layoutTarget +lblAlgn +lblOffset +ld +le +leader +leaderLines +ledger +left +leftArrow +leftArrowCallout +leftBrace +leftBracket +leftChars +leftCircularArrow +leftFromText +leftLabels +leftMargin +leftRightArrow +leftRightArrowCallout +leftRightCircularArrow +leftRightRibbon +leftRightUpArrow +leftUpArrow +legacy +legacyDrawing +legacyDrawingHF +legacyFlat1 +legacyFlat2 +legacyFlat3 +legacyFlat4 +legacyHarsh1 +legacyHarsh2 +legacyHarsh3 +legacyHarsh4 +legacyIndent +legacyMatte +legacyMetal +legacyNormal1 +legacyNormal2 +legacyNormal3 +legacyNormal4 +legacyObliqueBottom +legacyObliqueBottomLeft +legacyObliqueBottomRight +legacyObliqueFront +legacyObliqueLeft +legacyObliqueRight +legacyObliqueTop +legacyObliqueTopLeft +legacyObliqueTopRight +legacyPerspectiveBottom +legacyPerspectiveBottomLeft +legacyPerspectiveBottomRight +legacyPerspectiveFront +legacyPerspectiveLeft +legacyPerspectiveRight +legacyPerspectiveTop +legacyPerspectiveTopLeft +legacyPerspectiveTopRight +legacyPlastic +legacySpace +legacyWireframe +legend +legendEntry +legendPos +lemonChiffon +len +length +lengthspecified +lessThan +lessThanOrEqual +letter +level +lg +lgCheck +lgConfetti +lgDash +lgDashDot +lgDashDotDot +lgGrid +lid +light1 +light2 +lightBulb +lightDown +lightGray +lightGrayscale +lightGrid +lightHorizontal +lightRig +lightTrellis +lightUp +lightVertical +lighten +lightenLess +lightface +lightharsh +lightharsh2 +lightlevel +lightlevel2 +lightning1 +lightning2 +lightningBolt +lightposition +lightposition2 +lights +lim +limLoc +limLow +limLowPr +limUpp +limUppPr +lime +limeGreen +limo +lin +linClrLst +linDir +line +line3DChart +lineChart +lineInv +lineMarker +linePitch +lineRule +lineTo +lineWrapLikeWord6 +linear +linen +lines +linesAndChars +linestyle +lineStyleLst +link +linkStyles +linkTarget +linkToQuery +linkedToFile +list +listDataValidation +listEntry +listItem +listSeparator +lit +lkTxEntry +ln +lnB +lnBlToTr +lnDef +lnL +lnNumType +lnR +lnRef +lnSpAfChP +lnSpAfParP +lnSpCh +lnSpPar +lnSpc +lnSpcReduction +lnStyleLst +lnT +lnTlToBr +lnTo +lo +loCatId +loTypeId +local +localConnection +localRefresh +localSheetId +location +lock +lockRevision +lockStructure +lockWindows +locked +lockedCanvas +lockrotationcenter +log +logBase +lon +long +longCurve +longFileNames +longText +loop +low +lowKashida +lowerLetter +lowerRoman +lowestEdited +lpstr +lpwstr +lrTb +lrTbV +lsdException +lstStyle +lt +lt1 +lt2 +ltBlue +ltCoral +ltCyan +ltDnDiag +ltGoldenrodYellow +ltGray +ltGreen +ltHorz +ltPink +ltSalmon +ltSeaGreen +ltSkyBlue +ltSlateGray +ltSteelBlue +ltUpDiag +ltVert +ltYellow +lte +lu +lum +lumMod +lumOff +lvl +lvl1pPr +lvl2pPr +lvl3pPr +lvl4pPr +lvl5pPr +lvl6pPr +lvl7pPr +lvl8pPr +lvl9pPr +lvlAtOnce +lvlJc +lvlOne +lvlOverride +lvlPicBulletId +lvlRestart +lvlText +m +mPr +mac +macro +magenta +mailAsAttachment +mailMerge +mailSubject +mailingLabels +main +mainDocumentType +mainSeq +major +majorAscii +majorBidi +majorEastAsia +majorFont +majorGridlines +majorHAnsi +majorTickMark +majorTimeUnit +majorUnit +man +manifestLocation +manual +manualBreakCount +manualLayout +map +mapId +mapPins +mapleLeaf +mapleMuffins +mappedName +mappingCount +maps +marB +marBottom +marH +marL +marLeft +marR +marRight +marT +marTop +marW +margin +marker +markup +maroon +marquee +marqueeToothed +master +masterClrMapping +masterPages +masterRel +match +matchSrc +matchingName +mathDivide +mathEqual +mathFont +mathMinus +mathMultiply +mathNotEqual +mathPlus +mathPr +matrix +matte +max +maxAng +maxDate +maxDepth +maxDist +maxLength +maxMin +maxR +maxRId +maxRank +maxSheetId +maxSubtotal +maxVal +maxValue +maxX +maxY +maximized +mc +mcJc +mcPr +mcs +mdx +mdxMetadata +mdxSubqueries +measure +measureFilter +measureGroup +measureGroups +measures +med +medAquamarine +medBlue +medOrchid +medPurple +medSeaGreen +medSlateBlue +medSpringGreen +medTurquoise +medVioletRed +media +mediaAndTx +mediacall +medium +mediumDashDot +mediumDashDotDot +mediumDashed +mediumGray +mediumKashida +member +memberName +memberPropertyField +memberValueDatatype +members +menu +menuBar +menuHighlight +menuText +merge +mergeCell +mergeCells +mergeInterval +mergeItem +metadata +metadataStrings +metadataType +metadataTypes +metal +meth +method +mid +midCat +midL +midR +middle +middleDot +midnightBlue +millions +min +minAng +minDate +minLength +minMax +minR +minRId +minRefreshableVersion +minSubtotal +minSupportedVersion +minValue +minVer +minX +minY +minimized +minimumVersion +minor +minorAscii +minorBidi +minorEastAsia +minorFont +minorGridlines +minorHAnsi +minorTickMark +minorTimeUnit +minorUnit +mintCream +minus +minusx +minusy +minute +minutes +mirrorIndents +mirrorMargins +missingCaption +missingItemsLimit +mistyRose +miter +miterlimit +moccasin +mod +modelId +modern +modified +modifyVerifier +mongolianVert +monospace +month +monthLong +monthShort +months +moon +moons +morning +mosaic +moveFrom +moveFromRangeEnd +moveFromRangeStart +moveTo +moveToRangeEnd +moveToRangeStart +moveWith +movie +movingAvg +mp +mpFld +mpMap +mps +mr +mruColors +ms +mult +multiLevelType +multiLine +multiLvlStrCache +multiLvlStrRef +multilevel +multipleFieldFilters +multipleItemSelectionAllowed +musicNotes +mute +mwSmallCaps +n +na +name +nameLen +namespaceUri +namespaceuri +narHorz +narVert +narrow +nary +naryLim +naryPr +native +navajoWhite +navy +nc +nd +ndxf +neCell +negativeInteger +neq +never +new +newDocument +newLength +newName +newPage +newSection +newsflash +next +nextAc +nextClick +nextColumn +nextCondLst +nextId +nextMonth +nextPage +nextQuarter +nextTo +nextWeek +nextYear +nf +nil +nlCheck +noAdjustHandles +noArr +noAutofit +noBar +noBorder +noBreak +noBreakHyphen +noChangeArrowheads +noChangeAspect +noChangeShapeType +noColumnBalance +noControl +noConversion +noCrop +noDrilldown +noEditPoints +noEndCap +noEndnote +noExtraLineSpacing +noFill +noGrp +noIndicator +noLabel +noLeading +noLineBreaksAfter +noLineBreaksBefore +noMove +noMultiLvlLbl +noProof +noPunctuationKerning +noResize +noResizeAllowed +noRot +noSelect +noSmoking +noSpaceRaiseLower +noStrike +noTabHangInd +noTextEdit +noUngrp +noWrap +node +nodeHorzAlign +nodePh +nodeType +nodeVertAlign +nonAsst +nonAutoSortDefault +nonIsoscelesTrapezoid +nonNegativeInteger +nonNorm +nonPositiveInteger +none +nor +norm +normAutofit +normal +normalViewPr +normalizeH +normalizedString +northwest +notBeside +notBetween +notContains +notContainsBlanks +notContainsErrors +notContainsText +notEqual +notFirstPage +notSpecified +notTrueType +notchedRightArrow +notes +notesMaster +notesMasterId +notesMasterIdLst +notesMasterView +notesStyle +notesSz +notesTextViewPr +notesView +notesViewPr +nothing +np +ns +nsid +null +num +numCache +numCol +numFmt +numFmtId +numFmts +numId +numIdMacAtCleanup +numLit +numPicBullet +numPicBulletId +numPr +numRef +numRestart +numSld +numStart +numStyleLink +numTab +number +numberInDash +numberStoredAsText +numbering +numberingChange +nvCxnSpPr +nvGraphicFramePr +nvGrpSpPr +nvPicPr +nvPr +nvSpPr +nwCell +o +oMath +oMathPara +oMathParaPr +obj +objAndTwoObj +objAndTx +objDist +objOnly +objOverTx +objTx +object +objectDefaults +objects +obliqueBottom +obliqueBottomLeft +obliqueBottomRight +obliqueLeft +obliqueRight +obliqueTop +obliqueTopLeft +obliqueTopRight +oblob +obscured +oc +octagon +odbc +odcFile +oddFooter +oddHeader +oddPage +odso +odxf +ofPieChart +ofPieType +off +offset +offset2 +offsetFrom +olapFunctions +olapPr +old +oldComment +oldCustomMenu +oldDescription +oldFormula +oldFunction +oldFunctionGroupId +oldHelp +oldHidden +oldLace +oldLength +oldName +oldPh +oldQuotePrefix +oldShortcutKey +oldStatusBar +ole +oleChartEl +oleItem +oleItems +oleLink +oleObj +oleObject +oleObjects +oleSize +oleUpdate +oleicon +oleid +olive +oliveDrab +on +onBegin +onClick +onDblClick +onEnd +onMouseOut +onMouseOver +onNext +onPrev +onStopAudio +one +oneCell +oneCellAnchor +oneField +oned +onlySync +onlyUseConnectionFile +op +opEmu +opacity +opacity2 +open +openDmnd +operator +optimizeForBrowser +optimizeMemory +orange +orangeRed +orchid +order +ordinal +ordinalText +orgChart +organizeInFolders +orgchart +orient +orientation +orientationangle +origin +original +orthographicFront +ostorage +ostream +other +otherStyle +out +outByRing +outEnd +outer +outerShdw +outline +outline1pPr +outline2pPr +outlineData +outlineLevel +outlineLevelCol +outlineLevelRow +outlineLvl +outlinePr +outlineSymbols +outlineView +outlineViewPr +outset +outside +outsideMargin +oval +ovals +over +overThenDown +overflow +overflowPunct +overhead +overlap +overlay +override +overrideClrMapping +overwriteClear +owners +p +pBdr +pLen +pPos +pPr +pPrChange +pPrDefault +pRg +pStyle +packages +page +pageBottom +pageBreakBefore +pageBreakPreview +pageField +pageFieldLabels +pageFieldValues +pageFields +pageItem +pageLayout +pageMargins +pageOrder +pageOverThenDown +pageSetUpPr +pageSetup +pageStyle +pageWrap +pages +paleGoldenrod +paleGreen +paleTurquoise +paleVioletRed +palmsBlack +palmsColor +pane +panose +panose1 +papayaWhip +paperClips +paperSize +paperSrc +papyrus +par +parOf +parTrans +parTransId +parTxLTRAlign +parTxRTLAlign +paragraph +parallel +parallelogram +param +parameter +parameterType +parameters +parent +parentSet +parsePre +partyFavor +partyGlass +password +pasteAll +pasteBorders +pasteColWidths +pasteComments +pasteDataValidation +pasteFormats +pasteFormulas +pasteNumberFormats +pasteValues +path +pathEditMode +pathLst +pattFill +pattern +patternFill +patternType +pct +pct10 +pct12 +pct15 +pct20 +pct25 +pct30 +pct35 +pct37 +pct40 +pct45 +pct5 +pct50 +pct55 +pct60 +pct62 +pct65 +pct70 +pct75 +pct80 +pct85 +pct87 +pct90 +pct95 +peachPuff +penClr +pencils +pentagon +people +peopleHats +peopleWaving +percent +percentDiff +percentOfCol +percentOfRow +percentOfTotal +percentStacked +percentage +percentile +period +permEnd +permStart +personal +personalCompose +personalReply +personalView +perspective +perspectiveAbove +perspectiveAboveLeftFacing +perspectiveAboveRightFacing +perspectiveBelow +perspectiveContrastingLeftFacing +perspectiveContrastingRightFacing +perspectiveFront +perspectiveHeroicExtremeLeftFacing +perspectiveHeroicExtremeRightFacing +perspectiveHeroicLeftFacing +perspectiveHeroicRightFacing +perspectiveLeft +perspectiveRelaxed +perspectiveRelaxedModerately +perspectiveRight +peru +pg +pgBorders +pgMar +pgNum +pgNumB +pgNumMargins +pgNumT +pgNumType +pgSz +ph +phClr +phant +phantPr +phldr +phldrT +phonetic +phoneticPr +photoAlbum +pic +picLocks +picTx +pict +picture +pictureFormat +pictureOptions +pictureStackUnit +pid +pie +pie3DChart +pieChart +pieWedge +pinYin +pink +pitch +pitchFamily +pivot +pivotArea +pivotAreas +pivotButton +pivotCache +pivotCacheDefinition +pivotCacheRecords +pivotCaches +pivotField +pivotFields +pivotFmt +pivotFmts +pivotHierarchies +pivotHierarchy +pivotSelection +pivotSource +pivotTable +pivotTableDefinition +pivotTableStyle +pivotTableStyleInfo +pivotTables +pixelsPerInch +placeholder +placeholders +plaid +plane +plaque +plaqueTabs +plastic +plcHide +plotArea +plotVisOnly +plum +plus +poinsettias +points +polar +poly +polyline +portrait +pos +posEven +posOdd +posOffset +position +positionH +positionV +positiveInteger +post +postSp +postageStamp +powder +powderBlue +power +prLst +prSet +preSp +preced +precedSib +preferPic +preferRelativeResize +preferSingleView +preferrelative +prefixMappings +pres +presAssocID +presId +presLayoutVars +presName +presOf +presParOf +presStyleCnt +presStyleIdx +presStyleLbl +present +presentation +presentationAccent +presentationPr +presentationText +preserve +preserveFormatting +preserveHistory +preserveSortFilterLayout +presetClass +presetID +presetSubtype +prev +prevAc +prevCondLst +previousCol +previousRow +pri +primFontSz +print +printArea +printBodyTextBeforeHeader +printColBlack +printDrill +printFormsData +printFractionalCharacterWidth +printOptions +printPostScriptOverText +printSettings +printTwoOnOne +printer +printerSettings +priority +prnPr +prnWhat +product +productSubtotal +progId +progress +prompt +promptTitle +promptedSolutions +proofErr +proofState +property +propertyName +prot +protected +protectedRange +protectedRanges +protection +provid +proxy +prst +prstClr +prstDash +prstGeom +prstMaterial +prstShdw +prstTxWarp +pt +ptCount +ptInCategory +ptInSeries +ptLst +ptType +ptab +ptsTypes +pubBrowser +publishItems +publishToServer +published +pull +pumpkin1 +purple +push +pushPinNote1 +pushPinNote2 +pyra +pyraAcctBkgdNode +pyraAcctPos +pyraAcctRatio +pyraAcctTxMar +pyraAcctTxNode +pyraLvlNode +pyramid +pyramidToMax +pyramids +pyramidsAbove +qFormat +qs +qsCatId +qsTypeId +quadArrow +quadArrowCallout +quadBezTo +quadrants +qualifier +quarter +quarters +query +queryCache +queryFailed +queryTable +queryTableDeletedFields +queryTableField +queryTableFieldId +queryTableFields +queryTableRefresh +quickTimeFile +quotePrefix +r +r1 +r2 +r4 +r8 +rAng +rAngAx +rB +rCtr +rCtrCh +rCtrDes +rFont +rFonts +rId +rIns +rMarg +rMargin +rOff +rPh +rPr +rPrChange +rPrDefault +rSp +rSpRule +rStyle +rT +ra +rad +radPr +radarChart +radarStyle +radial +radiusrange +raf +random +randomBar +range +rangePr +rangeSet +rangeSets +rank +rankBy +rc +rcc +rcft +rcmt +rctx +rcv +rd +rdn +readModeInkLockDown +readOnly +readOnlyRecommended +readingOrder +realTimeData +recipientData +recipients +recolor +recolortarget +recommended +reconnectionMethod +recordCount +rect +red +redMod +redOff +ref +ref3D +refError +refFor +refForName +refMode +refPtType +refType +reference +references +refersTo +reflection +refreshAllConnections +refreshError +refreshOnChange +refreshOnLoad +refreshedBy +refreshedDate +refreshedVersion +regroupid +regrouptable +regular +rel +relIds +relOff +relSizeAnchor +relation +relationtable +relative +relativeFrom +relativeHeight +relativeIndent +relativeTo +relaxedInset +relid +relyOnVML +relyOnVml +remove +removeDataOnSave +removeDateAndTime +removePersonalInfoOnSave +removePersonalInformation +render +repairLoad +repeat +repeatCount +repeatDur +repl +resId +reservationPassword +resizeGraphics +resizeHandles +rest +restart +restored +restoredLeft +restoredTop +result +rev +revDir +revPos +reverse +reverseDiagStripe +reviewed +reviewedList +revision +revisionId +revisionView +revisions +revisionsPassword +rfmt +rgb +rgbColor +ribbon +ribbon2 +riblet +rich +richText +rig +right +rightArrow +rightArrowCallout +rightBrace +rightBracket +rightChars +rightFromText +rightMargin +rightToLeft +rightVertical +rings +ris +rm +rnd +roman +romanLcParenBoth +romanLcParenR +romanLcPeriod +romanUcParenBoth +romanUcParenR +romanUcPeriod +root +rosyBrown +rot +rotPath +rotWithShape +rotX +rotY +rotate +rotation +rotationangle +rotationcenter +round +round1Rect +round2DiagRect +round2SameRect +roundRect +roundedCorners +roundrect +row +rowBreaks +rowColShift +rowDrillCount +rowFields +rowGrandTotals +rowHeaderCaption +rowHierarchiesUsage +rowHierarchyUsage +rowItems +rowNumbers +rowOff +rowPageCount +rowSpan +rows +royalBlue +rqt +rrc +rsaAES +rsaFull +rsid +rsidDel +rsidP +rsidR +rsidRDefault +rsidRPr +rsidRoot +rsidSect +rsidTr +rsids +rsnm +rt +rtShortDist +rtTriangle +rtf +rtl +rtlCol +rtlGutter +rtn +ru +ruby +rubyAlign +rubyBase +rubyPr +rule +ruleLst +rules +runTotal +rupBuild +russianLower +russianUpper +s +sId +sPre +sPrePr +sSub +sSubPr +sSubSup +sSubSupPr +sSup +sSupPr +saddleBrown +safari +saka +salmon +salt +saltData +sameClick +sameDir +sampData +sandyBrown +sans-serif +sat +satMod +satOff +saveData +saveExternalLinkValues +saveFormsData +saveInvalidXml +savePassword +savePreviewPicture +saveSmartTagsAsXml +saveSubsetFonts +saveThroughXslt +saveXmlDataOnly +sawtooth +sawtoothGray +sb +scale +scaleToFitPaper +scaleWithDoc +scaled +scaling +scaredCat +scatterChart +scatterStyle +scenario +scenarios +scene3d +schema +schemaLibrary +schemaLocation +schemaRef +schemaRefs +scheme +schemeClr +scope +scr +screen +screen16x10 +screen16x9 +screen4x3 +scrgbClr +script +scrollBar +scrollbar +sd +sdt +sdtContent +sdtContentLocked +sdtEndPr +sdtLocked +sdtPr +seCell +seaGreen +seaShell +seattle +secChAlign +secFontSz +secHead +secLinDir +secSibSp +second +secondColumnStripe +secondColumnSubheading +secondPiePt +secondPieSize +secondRowStripe +secondRowSubheading +secondSubtotalColumn +secondSubtotalRow +seconds +sectEnd +sectPr +sectPrChange +securityDescriptor +seek +segments +selectFldWithFirstOrLastChar +selectLockedCells +selectUnlockedCells +selected +selection +self +semiHidden +semicolon +sendLocale +sep +sepChr +separate +separator +seq +ser +serAx +serLines +series +seriesEl +seriesIdx +serverCommand +serverField +serverFill +serverFont +serverFontColor +serverFormat +serverFormats +serverNumberFormat +serverSldId +serverSldModifiedTime +serverZoom +set +setDefinition +sets +settings +shade +shadeToTitle +shadow +shadowcolor +shadowedSquares +shadowok +shape +shapeDefaults +shapeId +shapeLayoutLikeWW8 +shapedefaults +shapeid +shapelayout +shapetype +shared +sharedItems +sharksTeeth +shd +shdw1 +shdw10 +shdw11 +shdw12 +shdw13 +shdw14 +shdw15 +shdw16 +shdw17 +shdw18 +shdw19 +shdw2 +shdw20 +shdw3 +shdw4 +shdw5 +shdw6 +shdw7 +shdw8 +shdw9 +sheet +sheetCalcPr +sheetData +sheetDataSet +sheetFormatPr +sheetId +sheetIdMap +sheetName +sheetNames +sheetPosition +sheetPr +sheetProtection +sheetView +sheetViews +sheets +shimmer +shingle +shininess +shorebirdTracks +short +shortcutKey +show +showAll +showAnimation +showAsCaption +showAsIcon +showAutoFilter +showBorderUnselectedTables +showBreaksInFrames +showBubbleSize +showButton +showCalcMbrs +showCaptions +showCatName +showCell +showColHeaders +showColStripes +showColumnStripes +showComments +showDLblsOverMax +showDataAs +showDataDropDown +showDataTips +showDrill +showDropDown +showDropDowns +showDropZones +showEmptyCol +showEmptyRow +showEnvelope +showError +showErrorMessage +showFirstColumn +showFormatting +showFormulaBar +showFormulas +showGridLines +showGuides +showHeader +showHeaders +showHorizontalScroll +showHorzBorder +showInFieldList +showInkAnnotation +showInputMessage +showItems +showKeys +showLastColumn +showLeaderLines +showLegendKey +showMasterPhAnim +showMasterSp +showMemberPropertyTips +showMissing +showMultipleLabel +showNarration +showNegBubbles +showObjects +showOutline +showOutlineIcons +showOutlineSymbols +showPageBreaks +showPercent +showPivotChartFilter +showPr +showPropAsCaption +showPropCell +showPropTip +showRowCol +showRowColHeaders +showRowHeaders +showRowStripes +showRuler +showScrollbar +showSerName +showSheetTabs +showSpeakerNotes +showSpecialPlsOnTitleSld +showStatusbar +showTip +showVal +showValue +showVertBorder +showVerticalScroll +showWhenStopped +showWhiteSpace +showXMLTags +showZeros +showingPlcHdr +showsigndate +shp +shpTxLTRAlignCh +shpTxRTLAlignCh +shrinkToFit +si +sib +sibSp +sibTrans +sibTransId +side +sideWall +sienna +sig +sigma +signatureline +signinginstructions +signinginstructionsset +sigprovurl +silver +simplePos +single +singleAccounting +singleLevel +singleQuote +singleSignOnId +singleXmlCell +singleXmlCells +singleclick +size +sizeAuto +sizeRepresents +skew +skewamt +skewangle +skip +skipTimed +skw +skyBlue +skyrocket +slantDashDot +slateBlue +slateGray +sld +sldAll +sldId +sldIdLst +sldImg +sldLayout +sldLayoutId +sldLayoutIdLst +sldLst +sldMaster +sldMasterId +sldMasterIdLst +sldMasterView +sldNum +sldRg +sldSorterView +sldSyncPr +sldSz +sldTgt +sldThumbnailView +sldView +slideViewPr +slides +slope +slow +sm +smCheck +smConfetti +smGrid +small +smallCaps +smallFrac +smartTag +smartTagPr +smartTagType +smartTagTypes +smartTags +smileyFace +smooth +smoothMarker +smtClean +smtId +snake +snapToChars +snapToGrid +snapToObjects +snapVertSplitter +snd +sndAc +sndTgt +sng +sngStrike +snip1Rect +snip2DiagRect +snip2SameRect +snipRoundRect +snow +snowflakeFancy +snowflakes +soft +softEdge +softHyphen +softRound +softmetal +solid +solidDmnd +solidFill +solutionID +solveOrder +sombrero +sort +sortBy +sortByTuple +sortCondition +sortMethod +sortState +sortType +sorterViewPr +source +sourceData +sourceFile +sourceFileName +sourceLinked +sourceObject +sourceRef +sourceSheetId +sourceType +southwest +sp +sp3d +spAutoFit +spDef +spLocks +spPr +spTgt +spTree +space +spaceForUL +spacing +spacingInWholePoints +span +spanAng +spans +sparkle +spc +spcAft +spcBef +spcCol +spcFirstLastPara +spcPct +spcPts +spd +specVanish +specularity +spellEnd +spellStart +speller +spelling +sphere +spid +spidmax +spinCount +split +splitAll +splitFirst +splitPgBreakAndParaMark +splitPos +splitType +spokes +spreadsheet +springGreen +spt +sq +sqlType +sqref +square +squareTabs +src +srcId +srcNode +srcOrd +srcRect +srgbClr +sst +st +stA +stAng +stBulletLvl +stCondLst +stCxn +stElem +stPos +stSnd +stack +stackScale +stacked +standard +star +star10 +star12 +star16 +star24 +star32 +star4 +star5 +star6 +star7 +star8 +stars +stars3d +starsBlack +starsShadowed +starsTop +start +startAngle +startAt +startDate +startNum +startOverride +startarrow +startarrowlength +startarrowwidth +state +status +statusBar +statusText +std +stdDev +stdDevP +stdDevPSubtotal +stdDevSubtotal +stdDevp +stdErr +stealth +steelBlue +stemThick +step +stockChart +stop +stopIfTrue +storage +storeItemID +storeMappedDataAs +stored +stp +str +strCache +strLit +strRef +strVal +stra +straight +straightConnector1 +stream +stretch +strictFirstAndLastChars +strike +strikeBLTR +strikeH +strikeTLBR +strikeV +string +stringValue1 +stringValue2 +stripedRightArrow +strips +stroke +strokecolor +stroked +strokeok +strokeweight +sty +style +styleData +styleDef +styleDefHdr +styleDefHdrLst +styleId +styleLbl +styleLink +styleLockQFSet +styleLockTheme +styleName +stylePaneFormatFilter +stylePaneSortMethod +styleSheet +styles +sub +subDoc +subFontBySize +subHide +subSp +subSup +subTitle +subTnLst +subject +subscript +subsetted +subtotal +subtotalCaption +subtotalHiddenItems +subtotalTop +suff +suggestedsigner +suggestedsigner2 +suggestedsigneremail +sum +sumSubtotal +summaryBelow +summaryLength +summaryRight +sun +sunrise +sunset +sup +supHide +superscript +supportAdvancedDrill +supportSubquery +suppressAutoHyphens +suppressBottomSpacing +suppressLineNumbers +suppressOverlap +suppressSpBfAfterPgBrk +suppressSpacingAtTopOfPage +suppressTopSpacing +suppressTopSpacingWP +surface3DChart +surfaceChart +swAng +swCell +swapBordersFacingPages +swirligig +swiss +switch +swooshArrow +sx +sy +sym +symbol +syncBehavior +syncHorizontal +syncRef +syncVertical +sysClr +sysDash +sysDashDot +sysDashDotDot +sysDot +sz +szCs +t +t1 +t2 +tCtr +tCtrCh +tCtrDes +tIns +tL +tMarg +tOff +tR +tab +tabColor +tabLst +tabRatio +tabSelected +table +tableBorderDxfId +tableColumn +tableColumnId +tableColumns +tablePart +tableParts +tableStyle +tableStyleElement +tableStyleId +tableStyleInfo +tableStyles +tableType +tablelimits +tableproperties +tables +tabs +tag +tagLst +tags +tailEnd +taiwan +taiwaneseCounting +taiwaneseCountingThousand +taiwaneseDigital +tan +target +targetScreenSize +targetScreenSz +targetscreensize +tav +tavLst +tbLrV +tbRl +tbRlV +tbl +tblBg +tblBorders +tblCellMar +tblCellSpacing +tblGrid +tblGridChange +tblHeader +tblInd +tblLayout +tblLook +tblOfContents +tblOverlap +tblPr +tblPrChange +tblPrEx +tblPrExChange +tblStyle +tblStyleColBandSize +tblStyleLst +tblStylePr +tblStyleRowBandSize +tblW +tblpPr +tblpX +tblpXSpec +tblpY +tblpYSpec +tbls +tc +tcBdr +tcBorders +tcFitText +tcMar +tcPr +tcPrChange +tcStyle +tcTxStyle +tcW +teal +teardrop +temporary +tenMillions +tenThousands +tentative +text +text1 +text2 +textAlignment +textAndBackground +textArchDown +textArchDownPour +textArchUp +textArchUpPour +textButton +textButtonPour +textCanDown +textCanUp +textCascadeDown +textCascadeUp +textChevron +textChevronInverted +textCircle +textCirclePour +textCurveDown +textCurveUp +textDates +textDeflate +textDeflateBottom +textDeflateInflate +textDeflateInflateDeflate +textDeflateTop +textDirection +textDoubleWave1 +textFadeDown +textFadeLeft +textFadeRight +textFadeUp +textField +textFields +textFile +textFit +textInflate +textInflateBottom +textInflateTop +textInput +textLength +textNoShape +textPlain +textPr +textRingInside +textRingOutside +textRotation +textSlantDown +textSlantUp +textStop +textTriangle +textTriangleInverted +textWave1 +textWave2 +textWave4 +textWrapping +textborder +textbox +textboxTightWrap +textboxrect +textdata +textlink +textpath +textpathok +tgtEl +tgtFrame +thai +thaiAlphaParenBoth +thaiAlphaParenR +thaiAlphaPeriod +thaiCounting +thaiDist +thaiDistribute +thaiLetters +thaiNumParenBoth +thaiNumParenR +thaiNumPeriod +thaiNumbers +theme +themeColor +themeElements +themeFill +themeFillShade +themeFillTint +themeFontLang +themeManager +themeOverride +themeShade +themeTint +thick +thickBetweenThin +thickBetweenThinLarge +thickBetweenThinSmall +thickBot +thickBottom +thickThin +thickThinLarge +thickThinLargeGap +thickThinMediumGap +thickThinSmall +thickThinSmallGap +thickTop +thicket +thickness +thin +thinDiagCross +thinDiagStripe +thinHorzCross +thinHorzStripe +thinReverseDiagStripe +thinThick +thinThickLarge +thinThickLargeGap +thinThickMediumGap +thinThickSmall +thinThickSmallGap +thinThickThinLargeGap +thinThickThinMediumGap +thinThickThinSmallGap +thinThin +thinVertStripe +thirdColumnSubheading +thirdRowSubheading +thirdSubtotalColumn +thirdSubtotalRow +thisMonth +thisQuarter +thisWeek +thisYear +thistle +thousands +threeDEmboss +threeDEngrave +threePt +thresh +through +thruBlk +tickLblPos +tickLblSkip +tickMarkSkip +tight +tile +tileRect +time +timePeriod +timing +tint +title +titleOnly +titlePg +titleStyle +tl +tl2br +tm +tmAbs +tmFilter +tmPct +tmRoot +tmpl +tmplLst +tn +tnLst +to +today +token +tomato +tomorrow +toolbar +tooltip +top +top10 +topAndBottom +topAutoShow +topFromText +topLabels +topLeft +topLeftCell +topLinePunct +topMargin +topRight +tornPaper +tornPaperBlack +totalRow +totalsRowBorderDxfId +totalsRowCellStyle +totalsRowCount +totalsRowDxfId +totalsRowFormula +totalsRowFunction +totalsRowLabel +totalsRowShown +tp +tpl +tplc +tpls +tr +tr2bl +trHeight +trPr +trPrChange +track +trackRevisions +trackedChanges +trans +transition +transitionEntry +transitionEvaluation +translucentPowder +transp +trapezoid +tree +trees +trellis +trend +trendline +trendlineLbl +trendlineType +tri +triangle +triangleParty +triangles +tribal1 +tribal2 +tribal3 +tribal4 +tribal5 +tribal6 +trillions +trim +triple +true +truncateFontHeightsLikeWP6 +tupleCache +turquoise +twistedLines1 +twistedLines2 +twoCell +twoCellAnchor +twoColTx +twoDigitTextYear +twoObj +twoObjAndObj +twoObjAndTx +twoObjOverTx +twoPt +twoTxTwoObj +tx +tx1 +tx2 +txAnchorHorz +txAnchorHorzCh +txAnchorVert +txAnchorVertCh +txAndChart +txAndClipArt +txAndMedia +txAndObj +txAndTwoObj +txBlDir +txBody +txBox +txDef +txDir +txEffectClrLst +txEl +txFillClrLst +txLinClrLst +txOverObj +txPr +txSp +txStyles +txbxContent +txtBox +ty +type +typeAny +typeface +types +u +uBounds +uFill +uFillTx +uLn +uLnTx +ua +udl +ui1 +ui2 +ui4 +ui8 +uiCompat97To2003 +uiExpand +uiPriority +uint +ulTrailSpace +un +unbalanced +unbalancedGroup +unboundColumnsLeft +unboundColumnsRight +undOvr +underDot +underlineTabInNumList +underscore +undo +undone +undrawn +ungrouping +unhideWhenUsed +uniqueCount +uniqueId +uniqueList +uniqueMemberProperty +uniqueName +uniqueParent +uniqueTag +uniqueValues +unknown +unknownRelationship +unlocked +unlockedFormula +unsignedByte +unsignedInt +unsignedLong +unsignedShort +up +upArrow +upArrowCallout +upBars +upDiag +upDownArrow +upDownArrowCallout +upDownBars +updateAutomatic +updateFields +updateLinks +updatedVersion +upgradeOnRefresh +upperLetter +upperRoman +upr +upright +uri +url +usb0 +usb1 +usb2 +usb3 +useA +useAltKinsokuLineBreakRules +useAnsiKerningPairs +useAutoFormatting +useBgFill +useDef +useFELayout +useFirstPageNumber +useLongFilenames +useNormalStyleForList +usePrinterDefaults +usePrinterMetrics +useSingleBorderforContiguousCells +useSpRect +useTimings +useWord2002TableStyleRules +useWord97LineBreakRules +useXSLTWhenSaving +user +userA +userB +userC +userD +userDrawn +userE +userF +userG +userH +userI +userInfo +userInterface +userJ +userK +userL +userM +userN +userName +userO +userP +userQ +userR +userS +userSet +userShapes +userT +userU +userV +userW +userX +userY +userZ +userdrawn +userhidden +users +uturnArrow +v +v3 +v3v4 +v4 +vAlign +vAnchor +vMerge +vMergeOrig +vSpace +vacatedStyle +val +valAx +value +valueBetween +valueEqual +valueGreaterThan +valueGreaterThanOrEqual +valueLessThan +valueLessThanOrEqual +valueMetadata +valueNotBetween +valueNotEqual +valueType +values +vanish +var +varLst +varP +varPSubtotal +varScale +varSubtotal +variable +variant +varp +varyColors +vbProcedure +vector +vendorID +venn +verb +version +vert +vert270 +vertAlign +vertAnchor +vertBarState +vertCompress +vertJc +vertOverflow +vertStripe +vertTitleAndTx +vertTitleAndTxOverChart +vertTx +vertical +verticalCentered +verticalDpi +verticalScroll +verticies +veryHidden +video +videoFile +vietnameseCounting +view +view3D +viewMergedData +viewPr +viewpoint +viewpointorigin +vine +violet +visibility +visible +visualTotals +vm +vml +vocabulary +vol +volType +volTypes +vstream +w +wAfter +wArH +wBefore +wMode +wOff +wR +warmMatte +warning +watermarks +wavAudioFile +wave +waveline +wavy +wavyDbl +wavyDouble +wavyHeavy +wd +wdDnDiag +wdUpDiag +weave +weavingAngles +weavingBraid +weavingRibbon +weavingStrips +web +webHidden +webPr +webPublishItem +webPublishItems +webPublishObject +webPublishObjects +webPublishing +webSettings +wedge +wedgeEllipseCallout +wedgeRectCallout +wedgeRoundRectCallout +weight +wheat +wheel +whenNotActive +white +whiteFlowers +whiteSmoke +whiteTextOnBlack +whole +wholeTable +wholeTbl +wide +widowControl +width +win +window +windowFrame +windowHeight +windowProtection +windowText +windowWidth +wipe +wireFrame +wireframe +withEffect +withGroup +woodwork +wordArtVert +wordArtVertRtl +wordWrap +words +workbook +workbookParameter +workbookPassword +workbookPr +workbookProtection +workbookView +workbookViewId +worksheet +worksheetSource +wpJustification +wpSpaceWidth +wrap +wrapIndent +wrapNone +wrapPolygon +wrapRight +wrapSquare +wrapText +wrapThrough +wrapTight +wrapTopAndBottom +wrapTrailSpaces +wrapcoords +writeProtection +wsDr +x +xAlign +xIllusions +xMode +xSplit +xVal +xWindow +xf +xfDxf +xfId +xfrm +xfrmType +xl2000 +xl97 +xlm +xml +xmlBased +xmlCellPr +xmlColumnPr +xmlDataType +xmlPr +xpath +xrange +xscale +xy +y +yAlign +yMode +ySplit +yVal +yWindow +year +yearLong +yearShort +yearToDate +years +yellow +yellowGreen +yesterday +yrange +z +zOrder +zOrderOff +zanyTriangles +zero +zeroAsc +zeroDesc +zeroHeight +zeroValues +zeroWid +zigZag +zigZagStitch +zoom +zoomContents +zoomScale +zoomScaleNormal +zoomScalePageLayoutView +zoomScaleSheetLayoutView +zoomToFit \ No newline at end of file diff --git a/oox/source/vml/makefile.mk b/oox/source/vml/makefile.mk new file mode 100644 index 000000000000..c49456af8bbd --- /dev/null +++ b/oox/source/vml/makefile.mk @@ -0,0 +1,58 @@ +#************************************************************************* +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.2 $ +# +# last change: $Author: rt $ $Date: 2008-01-17 08:06:07 $ +# +# The Contents of this file are made available subject to +# the terms of GNU Lesser General Public License Version 2.1. +# +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2005 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=oox +TARGET=vml +AUTOSEG=true + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/vmlshape.obj\ + $(SLO)$/vmldrawing.obj\ + $(SLO)$/vmldrawingfragmenthandler.obj + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk diff --git a/oox/source/vml/vmldrawing.cxx b/oox/source/vml/vmldrawing.cxx new file mode 100644 index 000000000000..482c8756b417 --- /dev/null +++ b/oox/source/vml/vmldrawing.cxx @@ -0,0 +1,101 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: vmldrawing.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:07 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/vml/drawing.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using namespace ::oox::core; + +namespace oox { namespace vml { + +Drawing::Drawing() +{ +} +Drawing::~Drawing() +{ +} + +ShapePtr Drawing::createShapeById( const rtl::OUString sId ) const +{ + ShapePtr pRet, pRef; + std::vector< ShapePtr >::const_iterator aIter( maShapes.begin() ); + while( aIter != maShapes.end() ) + { + if ( (*aIter)->msId == sId ) + { + pRef = (*aIter); + break; + } + aIter++; + } + if ( pRef ) + { + pRet = ShapePtr( new Shape() ); + if ( pRef->msType.getLength() ) + { + std::vector< ShapePtr >::const_iterator aShapeTypeIter( maShapeTypes.begin() ); + while( aShapeTypeIter != maShapeTypes.end() ) + { + if ( (*aShapeTypeIter)->msType == pRef->msType ) + { + pRet->applyAttributes( *(*aShapeTypeIter).get() ); + break; + } + aShapeTypeIter++; + } + } + pRet->applyAttributes( *pRef.get() ); + } + return pRet; +} + +rtl::OUString Drawing::getGraphicUrlById( const rtl::OUString sId ) const +{ + rtl::OUString sGraphicURL; + std::vector< ShapePtr >::const_iterator aIter( maShapes.begin() ); + while( aIter != maShapes.end() ) + { + if ( (*aIter)->msId == sId ) + { + sGraphicURL = (*aIter)->msGraphicURL; + break; + } + aIter++; + } + return sGraphicURL; +} + +} } diff --git a/oox/source/vml/vmldrawingfragmenthandler.cxx b/oox/source/vml/vmldrawingfragmenthandler.cxx new file mode 100644 index 000000000000..1fd9a4ecbb50 --- /dev/null +++ b/oox/source/vml/vmldrawingfragmenthandler.cxx @@ -0,0 +1,226 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: vmldrawingfragmenthandler.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:07 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "comphelper/anytostring.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "oox/core/context.hxx" +#include +#include + +#include "oox/vml/drawingfragmenthandler.hxx" +#include "oox/core/namespaces.hxx" +#include "tokens.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::container; + +namespace oox { namespace vml { + +//-------------------------------------------------------------------------------------------------------------- + +class BasicShapeContext : public oox::core::Context +{ +public: + BasicShapeContext( const FragmentHandlerRef& xHandler, + sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, const ShapePtr pShapePtr ); + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 Element, + const Reference< XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, RuntimeException); +private: + ShapePtr mpShapePtr; +}; +BasicShapeContext::BasicShapeContext( const FragmentHandlerRef& xHandler, + sal_Int32 /* aElement */, const Reference< XFastAttributeList >& xAttribs, const ShapePtr pShapePtr ) +: Context( xHandler ) +, mpShapePtr( pShapePtr ) +{ + mpShapePtr->msId = xAttribs->getOptionalValue( XML_id ); + mpShapePtr->msType = xAttribs->getOptionalValue( XML_type ); + rtl::OUString aShapeType( xAttribs->getOptionalValue( NMSP_OFFICE|XML_spt ) ); + if ( aShapeType.getLength() ) + mpShapePtr->mnShapeType = aShapeType.toInt32(); + rtl::OUString aCoordSize( xAttribs->getOptionalValue( XML_coordsize ) ); + if ( aCoordSize.getLength() ) + { + sal_Int32 nIndex = 0; + rtl::OUString aCoordWidth ( aCoordSize.getToken( 0, ',', nIndex ) ); + rtl::OUString aCoordHeight( aCoordSize.getToken( 0, ',', nIndex ) ); + if ( aCoordWidth.getLength() ) + mpShapePtr->mnCoordWidth = aCoordWidth.toInt32(); + if ( aCoordHeight.getLength() ) + mpShapePtr->mnCoordHeight = aCoordHeight.toInt32(); + } + mpShapePtr->msPath = xAttribs->getOptionalValue( XML_path ); + mpShapePtr->mnStroked = xAttribs->getOptionalValueToken( XML_stroked, 0 ); + mpShapePtr->mnFilled = xAttribs->getOptionalValueToken( XML_filled, 0 ); +} +Reference< XFastContextHandler > BasicShapeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case NMSP_VML|XML_imagedata: + { + OUString aRelId( xAttribs->getOptionalValue( NMSP_OFFICE|XML_relid ) ); + mpShapePtr->msGraphicURL = getHandler()->getFragmentPathFromRelId( aRelId ); + mpShapePtr->msImageTitle = xAttribs->getOptionalValue( NMSP_OFFICE|XML_title ); + } + break; + default: + break; + } + if( !xRet.is() ) + xRet.set( this ); + return xRet; +} + +//-------------------------------------------------------------------------------------------------------------- +// CT_Shapetype +class ShapeTypeContext : public BasicShapeContext +{ +public: + ShapeTypeContext( const FragmentHandlerRef& xHandler, + sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, const ShapePtr pShapePtr ); + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 Element, + const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException); + +}; +ShapeTypeContext::ShapeTypeContext( const FragmentHandlerRef& xHandler, + sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, const ShapePtr pShapePtr ) +: BasicShapeContext( xHandler, aElement, xAttribs, pShapePtr ) +{ +} +Reference< XFastContextHandler > ShapeTypeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; +// switch( aElementToken ) +// { +// default: + xRet = BasicShapeContext::createFastChildContext( aElementToken, xAttribs ); +// break; +// } + if( !xRet.is() ) + xRet.set( this ); + return xRet; +} + +//-------------------------------------------------------------------------------------------------------------- +// CT_Shape +class ShapeContext : public BasicShapeContext +{ +public: + ShapeContext( const FragmentHandlerRef& xHandler, + sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, const ShapePtr pShapePtr ); + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 Element, + const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException); +}; +ShapeContext::ShapeContext( const FragmentHandlerRef& xHandler, + sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs, const ShapePtr pShapePtr ) +: BasicShapeContext( xHandler, aElement, xAttribs, pShapePtr ) +{ +} +Reference< XFastContextHandler > ShapeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; +// switch( aElementToken ) +// { +// default: + xRet = BasicShapeContext::createFastChildContext( aElementToken, xAttribs ); +// break; +// } + if( !xRet.is() ) + xRet.set( this ); + return xRet; +} + +//-------------------------------------------------------------------------------------------------------------- + +DrawingFragmentHandler::DrawingFragmentHandler( const XmlFilterRef& xFilter, const OUString& rFragmentPath, const DrawingPtr pDrawingPtr ) + throw() +: FragmentHandler( xFilter, rFragmentPath ) +, mpDrawingPtr( pDrawingPtr ) +{ +} +DrawingFragmentHandler::~DrawingFragmentHandler() + throw() +{ +} +Reference< XFastContextHandler > DrawingFragmentHandler::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case XML_xml: + break; + case NMSP_OFFICE|XML_shapelayout: + break; + case NMSP_VML|XML_shapetype: + { + ShapePtr pShapePtr( new Shape ); + xRet = new ShapeTypeContext( this, aElementToken, xAttribs, pShapePtr ); + mpDrawingPtr->getShapeTypes().push_back( pShapePtr ); + } + break; + case NMSP_VML|XML_shape: + { + ShapePtr pShapePtr( new Shape ); + xRet = new ShapeContext( this, aElementToken, xAttribs, pShapePtr ); + mpDrawingPtr->getShapes().push_back( pShapePtr ); + } + break; + } + if( !xRet.is() ) + xRet.set( this ); + return xRet; +} + +void SAL_CALL DrawingFragmentHandler::endDocument() + throw (SAXException, RuntimeException) +{ +} + +//-------------------------------------------------------------------------------------------------------------- + + + +} } + diff --git a/oox/source/vml/vmlshape.cxx b/oox/source/vml/vmlshape.cxx new file mode 100644 index 000000000000..25e1f2d73c52 --- /dev/null +++ b/oox/source/vml/vmlshape.cxx @@ -0,0 +1,72 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: vmlshape.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:07 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/vml/shape.hxx" + +namespace oox { namespace vml { + +Shape::Shape() +: mnShapeType( 0 ) +, mnCoordWidth( 0 ) +, mnCoordHeight( 0 ) +, mnStroked( 0 ) +, mnFilled( 0 ) +{ +} +Shape::~Shape() +{ +} + +void Shape::applyAttributes( const vml::Shape& rSource ) +{ + if ( rSource.msId.getLength() ) + msId = rSource.msId; + if ( rSource.msType.getLength() ) + msType = rSource.msType; + if ( rSource.mnShapeType ) + mnShapeType = rSource.mnShapeType; + if ( rSource.mnCoordWidth ) + mnCoordWidth = rSource.mnCoordWidth; + if ( rSource.mnCoordHeight ) + mnCoordHeight = rSource.mnCoordHeight; + if ( rSource.mnStroked ) + mnStroked = rSource.mnStroked; + if ( rSource.mnFilled ) + mnFilled = rSource.mnFilled; + if ( rSource.msPath.getLength() ) + msPath = rSource.msPath; +} + +} } diff --git a/oox/source/xls/addressconverter.cxx b/oox/source/xls/addressconverter.cxx new file mode 100644 index 000000000000..9d2a781cfdc2 --- /dev/null +++ b/oox/source/xls/addressconverter.cxx @@ -0,0 +1,772 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: addressconverter.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:07 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/addressconverter.hxx" +#include +#include +#include +#include +#include +#include +#include "oox/helper/recordinputstream.hxx" +#include "oox/core/filterbase.hxx" +#include "oox/xls/biffinputstream.hxx" +#include "oox/xls/biffoutputstream.hxx" + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::rtl::OStringBuffer; +using ::rtl::OUStringToOString; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::container::XIndexAccess; +using ::com::sun::star::table::CellAddress; +using ::com::sun::star::table::CellRangeAddress; +using ::com::sun::star::sheet::XCellRangeAddressable; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +//! TODO: this limit may be changed +const sal_Int16 API_MAXTAB = 255; + +const sal_Int32 OOX_MAXCOL = static_cast< sal_Int32 >( (1 << 14) - 1 ); +const sal_Int32 OOX_MAXROW = static_cast< sal_Int32 >( (1 << 20) - 1 ); +const sal_Int16 OOX_MAXTAB = static_cast< sal_Int16 >( (1 << 15) - 1 ); + +const sal_Int32 BIFF2_MAXCOL = 255; +const sal_Int32 BIFF2_MAXROW = 16383; +const sal_Int16 BIFF2_MAXTAB = 0; + +const sal_Int32 BIFF3_MAXCOL = BIFF2_MAXCOL; +const sal_Int32 BIFF3_MAXROW = BIFF2_MAXROW; +const sal_Int16 BIFF3_MAXTAB = BIFF2_MAXTAB; + +const sal_Int32 BIFF4_MAXCOL = BIFF3_MAXCOL; +const sal_Int32 BIFF4_MAXROW = BIFF3_MAXROW; +const sal_Int16 BIFF4_MAXTAB = 32767; + +const sal_Int32 BIFF5_MAXCOL = BIFF4_MAXCOL; +const sal_Int32 BIFF5_MAXROW = BIFF4_MAXROW; +const sal_Int16 BIFF5_MAXTAB = BIFF4_MAXTAB; + +const sal_Int32 BIFF8_MAXCOL = BIFF5_MAXCOL; +const sal_Int32 BIFF8_MAXROW = 65535; +const sal_Int16 BIFF8_MAXTAB = BIFF5_MAXTAB; + +const sal_Unicode BIFF_URL_DRIVE = '\x01'; /// DOS drive letter or UNC path. +const sal_Unicode BIFF_URL_ROOT = '\x02'; /// Root directory of current drive. +const sal_Unicode BIFF_URL_SUBDIR = '\x03'; /// Subdirectory delimiter. +const sal_Unicode BIFF_URL_PARENT = '\x04'; /// Parent directory. +const sal_Unicode BIFF_URL_RAW = '\x05'; /// Unencoded URL. +const sal_Unicode BIFF_URL_INSTALL = '\x06'; /// Application installation directory. +const sal_Unicode BIFF_URL_INSTALL2 = '\x07'; /// Alternative application installation directory. +const sal_Unicode BIFF_URL_ADDIN = '\x08'; /// Add-in installation directory. +const sal_Unicode BIFF4_URL_SHEET = '\x09'; /// BIFF4 internal sheet. +const sal_Unicode BIFF_URL_UNC = '@'; /// UNC path root. + + +inline sal_uInt16 lclGetBiffAddressSize( bool bCol16Bit, bool bRow32Bit ) +{ + return (bCol16Bit ? 2 : 1) + (bRow32Bit ? 4 : 2); +} + +inline sal_uInt16 lclGetBiffRangeSize( bool bCol16Bit, bool bRow32Bit ) +{ + return 2 * lclGetBiffAddressSize( bCol16Bit, bRow32Bit ); +} + +} // namespace + +// ============================================================================ +// ============================================================================ + +CellAddress ApiCellRangeList::getBaseAddress() const +{ + if( empty() ) + return CellAddress(); + return CellAddress( front().Sheet, front().StartColumn, front().StartRow ); +} + +// ============================================================================ + +void BinAddress::read( RecordInputStream& rStrm ) +{ + rStrm >> mnRow >> mnCol; +} + +void BinAddress::read( BiffInputStream& rStrm, bool bCol16Bit, bool bRow32Bit ) +{ + mnRow = bRow32Bit ? rStrm.readInt32() : rStrm.readuInt16(); + mnCol = bCol16Bit ? rStrm.readuInt16() : rStrm.readuInt8(); +} + +void BinAddress::write( BiffOutputStream& rStrm, bool bCol16Bit, bool bRow32Bit ) const +{ + if( bRow32Bit ) + rStrm << mnRow; + else + rStrm << static_cast< sal_uInt16 >( mnRow ); + if( bCol16Bit ) + rStrm << static_cast< sal_uInt16 >( mnCol ); + else + rStrm << static_cast< sal_uInt8 >( mnCol ); +} + +// ============================================================================ + +bool BinRange::contains( const BinAddress& rAddr ) const +{ + return (maFirst.mnCol <= rAddr.mnCol) && (rAddr.mnCol <= maLast.mnCol) && + (maFirst.mnRow <= rAddr.mnRow) && (rAddr.mnRow <= maLast.mnRow); +} + +void BinRange::read( RecordInputStream& rStrm ) +{ + rStrm >> maFirst.mnRow >> maLast.mnRow >> maFirst.mnCol >> maLast.mnCol; +} + +void BinRange::read( BiffInputStream& rStrm, bool bCol16Bit, bool bRow32Bit ) +{ + maFirst.mnRow = bRow32Bit ? rStrm.readInt32() : rStrm.readuInt16(); + maLast.mnRow = bRow32Bit ? rStrm.readInt32() : rStrm.readuInt16(); + maFirst.mnCol = bCol16Bit ? rStrm.readuInt16() : rStrm.readuInt8(); + maLast.mnCol = bCol16Bit ? rStrm.readuInt16() : rStrm.readuInt8(); +} + +void BinRange::write( BiffOutputStream& rStrm, bool bCol16Bit, bool bRow32Bit ) const +{ + if( bRow32Bit ) + rStrm << maFirst.mnRow << maLast.mnRow; + else + rStrm << static_cast< sal_uInt16 >( maFirst.mnRow ) << static_cast< sal_uInt16 >( maLast.mnRow ); + if( bCol16Bit ) + rStrm << static_cast< sal_uInt16 >( maFirst.mnCol ) << static_cast< sal_uInt16 >( maLast.mnCol ); + else + rStrm << static_cast< sal_uInt8 >( maFirst.mnCol ) << static_cast< sal_uInt8 >( maLast.mnCol ); +} + +// ============================================================================ + +BinRange BinRangeList::getEnclosingRange() const +{ + BinRange aRange; + if( !empty() ) + { + const_iterator aIt = begin(), aEnd = end(); + aRange = *aIt; + for( ++aIt; aIt != aEnd; ++aIt ) + { + aRange.maFirst.mnCol = ::std::min( aRange.maFirst.mnCol, aIt->maFirst.mnCol ); + aRange.maFirst.mnRow = ::std::min( aRange.maFirst.mnRow, aIt->maFirst.mnRow ); + aRange.maLast.mnCol = ::std::max( aRange.maLast.mnCol, aIt->maLast.mnCol ); + aRange.maLast.mnRow = ::std::max( aRange.maLast.mnRow, aIt->maLast.mnRow ); + } + } + return aRange; +} + +void BinRangeList::read( RecordInputStream& rStrm ) +{ + sal_Int32 nCount = rStrm.readInt32(); + resize( getLimitedValue< size_t, sal_Int32 >( nCount, 0, rStrm.getRecLeft() / 16 ) ); + for( iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt ) + aIt->read( rStrm ); +} + +void BinRangeList::read( BiffInputStream& rStrm, bool bCol16Bit, bool bRow32Bit ) +{ + sal_uInt16 nCount = rStrm.readuInt16(); + resize( getLimitedValue< size_t, sal_uInt32 >( nCount, 0, rStrm.getRecLeft() / lclGetBiffRangeSize( bCol16Bit, bRow32Bit ) ) ); + for( iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt ) + aIt->read( rStrm, bCol16Bit, bRow32Bit ); +} + +void BinRangeList::write( BiffOutputStream& rStrm, bool bCol16Bit, bool bRow32Bit ) const +{ + writeSubList( rStrm, 0, size(), bCol16Bit, bRow32Bit ); +} + +void BinRangeList::writeSubList( BiffOutputStream& rStrm, size_t nBegin, size_t nCount, bool bCol16Bit, bool bRow32Bit ) const +{ + OSL_ENSURE( nBegin <= size(), "BiffRangeList::writeSubList - invalid start position" ); + size_t nEnd = ::std::min< size_t >( nBegin + nCount, size() ); + sal_uInt16 nBiffCount = getLimitedValue< sal_uInt16, size_t >( nEnd - nBegin, 0, SAL_MAX_UINT16 ); + rStrm << nBiffCount; + rStrm.setPortionSize( lclGetBiffRangeSize( bCol16Bit, bRow32Bit ) ); + for( const_iterator aIt = begin() + nBegin, aEnd = begin() + nEnd; aIt != aEnd; ++aIt ) + aIt->write( rStrm, bCol16Bit, bRow32Bit ); +} + +// ============================================================================ +// ============================================================================ + +AddressConverter::AddressConverter( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + mcUrlThisWorkbook( 0 ), + mcUrlExternal( 0 ), + mcUrlThisSheet( 0 ), + mcUrlInternal( 0 ), + mbColOverflow( false ), + mbRowOverflow( false ), + mbTabOverflow( false ) +{ + switch( getFilterType() ) + { + case FILTER_OOX: + initializeMaxPos( OOX_MAXTAB, OOX_MAXCOL, OOX_MAXROW ); + break; + case FILTER_BIFF: switch( getBiff() ) + { + case BIFF2: + initializeMaxPos( BIFF2_MAXTAB, BIFF2_MAXCOL, BIFF2_MAXROW ); + initializeEncodedUrl( '\x00', '\x01', '\x02', '\x00' ); + break; + case BIFF3: + initializeMaxPos( BIFF3_MAXTAB, BIFF3_MAXCOL, BIFF3_MAXROW ); + initializeEncodedUrl( '\x00', '\x01', '\x02', '\x00' ); + break; + case BIFF4: + initializeMaxPos( BIFF4_MAXTAB, BIFF4_MAXCOL, BIFF4_MAXROW ); + initializeEncodedUrl( '\x00', '\x01', '\x02', '\x00' ); + break; + case BIFF5: + initializeMaxPos( BIFF5_MAXTAB, BIFF5_MAXCOL, BIFF5_MAXROW ); + initializeEncodedUrl( '\x04', '\x01', '\x02', '\x03' ); + break; + case BIFF8: + initializeMaxPos( BIFF8_MAXTAB, BIFF8_MAXCOL, BIFF8_MAXROW ); + initializeEncodedUrl( '\x04', '\x01', '\x00', '\x02' ); + break; + case BIFF_UNKNOWN: break; + } + break; + case FILTER_UNKNOWN: break; + } +} + +// ---------------------------------------------------------------------------- + +bool AddressConverter::parseOoxAddress2d( + sal_Int32& ornColumn, sal_Int32& ornRow, + const OUString& rString, sal_Int32 nStart, sal_Int32 nLength ) +{ + ornColumn = ornRow = 0; + if( (nStart < 0) || (nStart >= rString.getLength()) || (nLength < 2) ) + return false; + + const sal_Unicode* pcChar = rString.getStr() + nStart; + const sal_Unicode* pcEndChar = pcChar + ::std::min( nLength, rString.getLength() - nStart ); + + enum { STATE_COL, STATE_ROW } eState = STATE_COL; + while( pcChar < pcEndChar ) + { + sal_Unicode cChar = *pcChar; + switch( eState ) + { + case STATE_COL: + { + if( ('a' <= cChar) && (cChar <= 'z') ) + (cChar -= 'a') += 'A'; + if( ('A' <= cChar) && (cChar <= 'Z') ) + { + /* Return, if 1-based column index is already 6 characters + long (12356631 is column index for column AAAAAA). */ + if( ornColumn >= 12356631 ) + return false; + (ornColumn *= 26) += (cChar - 'A' + 1); + } + else if( ornColumn > 0 ) + { + --pcChar; + eState = STATE_ROW; + } + else + return false; + } + break; + + case STATE_ROW: + { + if( ('0' <= cChar) && (cChar <= '9') ) + { + // return, if 1-based row is already 9 digits long + if( ornRow >= 100000000 ) + return false; + (ornRow *= 10) += (cChar - '0'); + } + else + return false; + } + break; + } + ++pcChar; + } + + --ornColumn; + --ornRow; + return (ornColumn >= 0) && (ornRow >= 0); +} + +bool AddressConverter::parseOoxRange2d( + sal_Int32& ornStartColumn, sal_Int32& ornStartRow, + sal_Int32& ornEndColumn, sal_Int32& ornEndRow, + const OUString& rString, sal_Int32 nStart, sal_Int32 nLength ) +{ + ornStartColumn = ornStartRow = ornEndColumn = ornEndRow = 0; + if( (nStart < 0) || (nStart >= rString.getLength()) || (nLength < 2) ) + return false; + + sal_Int32 nEnd = nStart + ::std::min( nLength, rString.getLength() - nStart ); + sal_Int32 nColonPos = rString.indexOf( ':', nStart ); + if( (nStart < nColonPos) && (nColonPos + 1 < nEnd) ) + { + return + parseOoxAddress2d( ornStartColumn, ornStartRow, rString, nStart, nColonPos - nStart ) && + parseOoxAddress2d( ornEndColumn, ornEndRow, rString, nColonPos + 1, nLength - nColonPos - 1 ); + } + + if( parseOoxAddress2d( ornStartColumn, ornStartRow, rString, nStart, nLength ) ) + { + ornEndColumn = ornStartColumn; + ornEndRow = ornStartRow; + return true; + } + + return false; +} + +namespace { + +bool lclAppendUrlChar( OUStringBuffer& orUrl, sal_Unicode cChar, bool bEncodeSpecial ) +{ + // #126855# encode special characters + if( bEncodeSpecial ) switch( cChar ) + { + case '#': orUrl.appendAscii( "%23" ); return true; + case '%': orUrl.appendAscii( "%25" ); return true; + } + orUrl.append( cChar ); + return cChar >= ' '; +} + +} // namespace + +bool AddressConverter::parseBiffTargetUrl( + OUString& orClassName, OUString& orTargetUrl, OUString& orSheetName, + const OUString& rBiffTargetUrl ) +{ + OUStringBuffer aTargetUrl; + OUStringBuffer aSheetName; + + enum + { + STATE_START, + STATE_ENCODED_PATH_START, /// Start of encoded file path. + STATE_ENCODED_PATH, /// Inside encoded file path. + STATE_ENCODED_DRIVE, /// DOS drive letter or start of UNC path. + STATE_ENCODED_URL, /// Encoded URL, e.g. http links. + STATE_UNENCODED, /// Unencoded URL, could be DDE or OLE. + STATE_DDE_OLE, /// Second part of DDE or OLE link. + STATE_FILENAME, /// File name enclosed in brackets. + STATE_SHEETNAME, /// Sheet name following enclosed file name. + STATE_UNSUPPORTED, /// Unsupported special paths. + STATE_ERROR + } + eState = STATE_START; + + const sal_Unicode* pcChar = rBiffTargetUrl.getStr(); + const sal_Unicode* pcEnd = pcChar + rBiffTargetUrl.getLength(); + for( ; (eState != STATE_ERROR) && (pcChar < pcEnd) && (*pcChar != 0); ++pcChar ) + { + sal_Unicode cChar = *pcChar; + switch( eState ) + { + case STATE_START: + if( (cChar == mcUrlThisWorkbook) || (cChar == mcUrlThisSheet) ) + { + if( pcChar + 1 < pcEnd ) eState = STATE_ERROR; + } + else if( cChar == mcUrlExternal ) + eState = (pcChar + 1 < pcEnd) ? STATE_ENCODED_PATH_START : STATE_ERROR; + else if( cChar == mcUrlInternal ) + eState = (pcChar + 1 < pcEnd) ? STATE_SHEETNAME : STATE_ERROR; + else + eState = lclAppendUrlChar( aTargetUrl, cChar, true ) ? STATE_UNENCODED : STATE_ERROR; + break; + + case STATE_ENCODED_PATH_START: + if( cChar == BIFF_URL_DRIVE ) + eState = STATE_ENCODED_DRIVE; + else if( cChar == BIFF_URL_ROOT ) + { + aTargetUrl.append( sal_Unicode( '/' ) ); + eState = STATE_ENCODED_PATH; + } + else if( cChar == BIFF_URL_PARENT ) + aTargetUrl.appendAscii( "../" ); + else if( cChar == BIFF_URL_RAW ) + eState = STATE_ENCODED_URL; + else if( cChar == BIFF_URL_INSTALL ) + eState = STATE_UNSUPPORTED; + else if( cChar == BIFF_URL_INSTALL2 ) + eState = STATE_UNSUPPORTED; + else if( cChar == BIFF_URL_ADDIN ) + eState = STATE_UNSUPPORTED; + else if( (getBiff() == BIFF4) && (cChar == BIFF4_URL_SHEET) ) + eState = STATE_SHEETNAME; + else if( cChar == '[' ) + eState = STATE_FILENAME; + else if( lclAppendUrlChar( aTargetUrl, cChar, true ) ) + eState = STATE_ENCODED_PATH; + else + eState = STATE_ERROR; + break; + + case STATE_ENCODED_PATH: + if( cChar == BIFF_URL_SUBDIR ) + aTargetUrl.append( sal_Unicode( '/' ) ); + else if( cChar == '[' ) + eState = STATE_FILENAME; + else if( !lclAppendUrlChar( aTargetUrl, cChar, true ) ) + eState = STATE_ERROR; + break; + + case STATE_ENCODED_DRIVE: + if( cChar == BIFF_URL_UNC ) + { + aTargetUrl.appendAscii( "file://" ); + eState = STATE_ENCODED_PATH; + } + else + { + aTargetUrl.appendAscii( "file:///" ); + eState = lclAppendUrlChar( aTargetUrl, cChar, false ) ? STATE_ENCODED_PATH : STATE_ERROR; + aTargetUrl.appendAscii( ":/" ); + } + break; + + case STATE_ENCODED_URL: + { + sal_Int32 nLength = cChar; + if( nLength + 1 == pcEnd - pcChar ) + aTargetUrl.append( pcChar + 1, nLength ); + else + eState = STATE_ERROR; + } + break; + + case STATE_UNENCODED: + if( cChar == BIFF_URL_SUBDIR ) + { + orClassName = aTargetUrl.makeStringAndClear(); + eState = STATE_DDE_OLE; + } + else if( cChar == '[' ) + eState = STATE_FILENAME; + else if( !lclAppendUrlChar( aTargetUrl, cChar, true ) ) + eState = STATE_ERROR; + break; + + case STATE_DDE_OLE: + if( !lclAppendUrlChar( aTargetUrl, cChar, true ) ) + eState = STATE_ERROR; + break; + + case STATE_FILENAME: + if( cChar == ']' ) + eState = STATE_SHEETNAME; + else if( !lclAppendUrlChar( aTargetUrl, cChar, true ) ) + eState = STATE_ERROR; + break; + + case STATE_SHEETNAME: + if( !lclAppendUrlChar( aSheetName, cChar, false ) ) + eState = STATE_ERROR; + break; + + case STATE_UNSUPPORTED: + pcChar = pcEnd - 1; + break; + + case STATE_ERROR: + break; + } + } + + orTargetUrl = aTargetUrl.makeStringAndClear(); + orSheetName = aSheetName.makeStringAndClear(); + + OSL_ENSURE( (eState != STATE_ERROR) && (pcChar == pcEnd), + OStringBuffer( "AddressConverter::parseBiffTargetUrl - parser error in target \"" ). + append( OUStringToOString( rBiffTargetUrl, RTL_TEXTENCODING_UTF8 ) ).append( '"' ).getStr() ); + return (eState != STATE_ERROR) && (eState != STATE_UNSUPPORTED) && (pcChar == pcEnd); +} + +// ---------------------------------------------------------------------------- + +bool AddressConverter::checkCol( sal_Int32 nCol, bool bTrackOverflow ) +{ + bool bValid = (0 <= nCol) && (nCol <= maMaxPos.Column); + if( !bValid && bTrackOverflow ) + mbColOverflow = true; + return bValid; +} + +bool AddressConverter::checkRow( sal_Int32 nRow, bool bTrackOverflow ) +{ + bool bValid = (0 <= nRow) && (nRow <= maMaxPos.Row); + if( !bValid && bTrackOverflow ) + mbRowOverflow = true; + return bValid; +} + +bool AddressConverter::checkTab( sal_Int16 nSheet, bool bTrackOverflow ) +{ + bool bValid = (0 <= nSheet) && (nSheet <= maMaxPos.Sheet); + if( !bValid && bTrackOverflow ) + mbTabOverflow |= (nSheet > maMaxPos.Sheet); // do not warn for deleted refs (-1) + return bValid; +} + +// ---------------------------------------------------------------------------- + +bool AddressConverter::checkCellAddress( const CellAddress& rAddress, bool bTrackOverflow ) +{ + return + checkTab( rAddress.Sheet, bTrackOverflow ) && + checkCol( rAddress.Column, bTrackOverflow ) && + checkRow( rAddress.Row, bTrackOverflow ); +} + +bool AddressConverter::convertToCellAddressUnckecked( CellAddress& orAddress, + const OUString& rString, sal_Int16 nSheet ) +{ + orAddress.Sheet = nSheet; + return parseOoxAddress2d( orAddress.Column, orAddress.Row, rString ); +} + +bool AddressConverter::convertToCellAddress( CellAddress& orAddress, + const OUString& rString, sal_Int16 nSheet, bool bTrackOverflow ) +{ + return + convertToCellAddressUnckecked( orAddress, rString, nSheet ) && + checkCellAddress( orAddress, bTrackOverflow ); +} + +CellAddress AddressConverter::createValidCellAddress( + const OUString& rString, sal_Int16 nSheet, bool bTrackOverflow ) +{ + CellAddress aAddress; + if( !convertToCellAddress( aAddress, rString, nSheet, bTrackOverflow ) ) + { + aAddress.Sheet = getLimitedValue< sal_Int16, sal_Int16 >( nSheet, 0, maMaxPos.Sheet ); + aAddress.Column = ::std::min( aAddress.Column, maMaxPos.Column ); + aAddress.Row = ::std::min( aAddress.Row, maMaxPos.Row ); + } + return aAddress; +} + +void AddressConverter::convertToCellAddressUnckecked( CellAddress& orAddress, + const BinAddress& rBinAddress, sal_Int16 nSheet ) +{ + orAddress.Sheet = nSheet; + orAddress.Column = rBinAddress.mnCol; + orAddress.Row = rBinAddress.mnRow; +} + +bool AddressConverter::convertToCellAddress( CellAddress& orAddress, + const BinAddress& rBinAddress, sal_Int16 nSheet, bool bTrackOverflow ) +{ + convertToCellAddressUnckecked( orAddress, rBinAddress, nSheet ); + return checkCellAddress( orAddress, bTrackOverflow ); +} + +CellAddress AddressConverter::createValidCellAddress( + const BinAddress& rBinAddress, sal_Int16 nSheet, bool bTrackOverflow ) +{ + CellAddress aAddress; + if( !convertToCellAddress( aAddress, rBinAddress, nSheet, bTrackOverflow ) ) + { + aAddress.Sheet = getLimitedValue< sal_Int16, sal_Int16 >( nSheet, 0, maMaxPos.Sheet ); + aAddress.Column = getLimitedValue< sal_Int32, sal_Int32 >( rBinAddress.mnCol, 0, maMaxPos.Column ); + aAddress.Row = getLimitedValue< sal_Int32, sal_Int32 >( rBinAddress.mnRow, 0, maMaxPos.Row ); + } + return aAddress; +} + +// ---------------------------------------------------------------------------- + +bool AddressConverter::checkCellRange( const CellRangeAddress& rRange, bool bTrackOverflow ) +{ + checkCol( rRange.EndColumn, bTrackOverflow ); + checkRow( rRange.EndRow, bTrackOverflow ); + return + checkTab( rRange.Sheet, bTrackOverflow ) && + checkCol( rRange.StartColumn, bTrackOverflow ) && + checkRow( rRange.StartRow, bTrackOverflow ); +} + +bool AddressConverter::validateCellRange( CellRangeAddress& orRange, bool bTrackOverflow ) +{ + if( orRange.StartColumn > orRange.EndColumn ) + ::std::swap( orRange.StartColumn, orRange.EndColumn ); + if( orRange.StartRow > orRange.EndRow ) + ::std::swap( orRange.StartRow, orRange.EndRow ); + if( !checkCellRange( orRange, bTrackOverflow ) ) + return false; + if( orRange.EndColumn > maMaxPos.Column ) + orRange.EndColumn = maMaxPos.Column; + if( orRange.EndRow > maMaxPos.Row ) + orRange.EndRow = maMaxPos.Row; + return true; +} + +bool AddressConverter::convertToCellRangeUnchecked( CellRangeAddress& orRange, + const OUString& rString, sal_Int16 nSheet ) +{ + orRange.Sheet = nSheet; + return parseOoxRange2d( orRange.StartColumn, orRange.StartRow, orRange.EndColumn, orRange.EndRow, rString ); +} + +bool AddressConverter::convertToCellRange( CellRangeAddress& orRange, + const OUString& rString, sal_Int16 nSheet, bool bTrackOverflow ) +{ + return + convertToCellRangeUnchecked( orRange, rString, nSheet ) && + validateCellRange( orRange, bTrackOverflow ); +} + +void AddressConverter::convertToCellRangeUnchecked( CellRangeAddress& orRange, + const BinRange& rBinRange, sal_Int16 nSheet ) +{ + orRange.Sheet = nSheet; + orRange.StartColumn = rBinRange.maFirst.mnCol; + orRange.StartRow = rBinRange.maFirst.mnRow; + orRange.EndColumn = rBinRange.maLast.mnCol; + orRange.EndRow = rBinRange.maLast.mnRow; +} + +bool AddressConverter::convertToCellRange( CellRangeAddress& orRange, + const BinRange& rBinRange, sal_Int16 nSheet, bool bTrackOverflow ) +{ + convertToCellRangeUnchecked( orRange, rBinRange, nSheet ); + return validateCellRange( orRange, bTrackOverflow ); +} + +// ---------------------------------------------------------------------------- + +bool AddressConverter::checkCellRangeList( const ApiCellRangeList& rRanges, bool bTrackOverflow ) +{ + for( ApiCellRangeList::const_iterator aIt = rRanges.begin(), aEnd = rRanges.end(); aIt != aEnd; ++aIt ) + if( !checkCellRange( *aIt, bTrackOverflow ) ) + return false; + return true; +} + +void AddressConverter::validateCellRangeList( ApiCellRangeList& orRanges, bool bTrackOverflow ) +{ + for( size_t nIndex = orRanges.size(); nIndex > 0; --nIndex ) + if( !validateCellRange( orRanges[ nIndex - 1 ], bTrackOverflow ) ) + orRanges.erase( orRanges.begin() + nIndex - 1 ); +} + +void AddressConverter::convertToCellRangeList( ApiCellRangeList& orRanges, + const OUString& rString, sal_Int16 nSheet, bool bTrackOverflow ) +{ + sal_Int32 nPos = 0; + sal_Int32 nLen = rString.getLength(); + CellRangeAddress aRange; + while( (0 <= nPos) && (nPos < nLen) ) + { + OUString aToken = rString.getToken( 0, ' ', nPos ); + if( (aToken.getLength() > 0) && convertToCellRange( aRange, aToken, nSheet, bTrackOverflow ) ) + orRanges.push_back( aRange ); + } +} + +void AddressConverter::convertToCellRangeList( ApiCellRangeList& orRanges, + const BinRangeList& rBinRanges, sal_Int16 nSheet, bool bTrackOverflow ) +{ + CellRangeAddress aRange; + for( BinRangeList::const_iterator aIt = rBinRanges.begin(), aEnd = rBinRanges.end(); aIt != aEnd; ++aIt ) + if( convertToCellRange( aRange, *aIt, nSheet, bTrackOverflow ) ) + orRanges.push_back( aRange ); +} + +// private -------------------------------------------------------------------- + +void AddressConverter::initializeMaxPos( + sal_Int16 nMaxXlsTab, sal_Int32 nMaxXlsCol, sal_Int32 nMaxXlsRow ) +{ + maMaxXlsPos.Sheet = nMaxXlsTab; + maMaxXlsPos.Column = nMaxXlsCol; + maMaxXlsPos.Row = nMaxXlsRow; + + // maximum cell position in Calc + try + { + Reference< XIndexAccess > xSheetsIA( getDocument()->getSheets(), UNO_QUERY_THROW ); + Reference< XCellRangeAddressable > xAddressable( xSheetsIA->getByIndex( 0 ), UNO_QUERY_THROW ); + CellRangeAddress aRange = xAddressable->getRangeAddress(); + maMaxApiPos = CellAddress( API_MAXTAB, aRange.EndColumn, aRange.EndRow ); + maMaxPos = getBaseFilter().isImportFilter() ? maMaxApiPos : maMaxXlsPos; + } + catch( Exception& ) + { + OSL_ENSURE( false, "AddressConverter::AddressConverter - cannot get sheet limits" ); + } +} + +void AddressConverter::initializeEncodedUrl( + sal_Unicode cUrlThisWorkbook, sal_Unicode cUrlExternal, + sal_Unicode cUrlThisSheet, sal_Unicode cUrlInternal ) +{ + mcUrlThisWorkbook = cUrlThisWorkbook; + mcUrlExternal = cUrlExternal; + mcUrlThisSheet = cUrlThisSheet; + mcUrlInternal = cUrlInternal; +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/autofiltercontext.cxx b/oox/source/xls/autofiltercontext.cxx new file mode 100644 index 000000000000..99f56575dc01 --- /dev/null +++ b/oox/source/xls/autofiltercontext.cxx @@ -0,0 +1,770 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: autofiltercontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:07 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/autofiltercontext.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/xls/addressconverter.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG_OOX_AUTOFILTER 0 + +#if USE_SC_MULTI_STRING_FILTER_PATCH +#include +#include +#include +using ::com::sun::star::sheet::TableFilterFieldNormal; +using ::com::sun::star::sheet::TableFilterFieldMultiString; +using ::com::sun::star::sheet::XExtendedSheetFilterDescriptor; +#else +#include +using ::com::sun::star::sheet::TableFilterField; +#endif + +#if DEBUG_OOX_AUTOFILTER +#include +#endif + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::std::list; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::container::XNameAccess; +using ::com::sun::star::container::XNamed; +using ::com::sun::star::table::CellRangeAddress; +using ::com::sun::star::table::XCellRange; +using ::com::sun::star::sheet::XDatabaseRange; +using ::com::sun::star::sheet::XDatabaseRanges; +using ::com::sun::star::sheet::XSheetFilterDescriptor; +using ::com::sun::star::i18n::LocaleDataItem; +using ::com::sun::star::i18n::XLocaleData; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::lang::Locale; + +namespace oox { +namespace xls { + +// ============================================================================ + +FilterFieldItem::FilterFieldItem() : +#if USE_SC_MULTI_STRING_FILTER_PATCH + mpField(new TableFilterFieldNormal), +#else + mpField(new TableFilterField), +#endif + meType(NORMAL) +{ +} + +FilterFieldItem::FilterFieldItem(Type eType) : + meType(eType) +{ +#if USE_SC_MULTI_STRING_FILTER_PATCH + switch ( eType ) + { + case MULTI_STRING: + mpField.reset(new TableFilterFieldMultiString); + break; + case NORMAL: + mpField.reset(new TableFilterFieldNormal); + break; + default: + mpField.reset(new TableFilterFieldNormal); + } +#else + mpField.reset(new TableFilterField); + meType = NORMAL; +#endif +} + +// ============================================================================ + +OoxAutoFilterContext::OoxAutoFilterContext( const OoxWorksheetFragmentBase& rFragment ) : + OoxWorksheetContextBase( rFragment ), + mbValidAddress( false ), + mbUseRegex( false ), + mbShowBlank( false ), + mbConnectionAnd( false ) +{ +} + +// oox.xls.OoxContextHelper interface ----------------------------------------- + +bool OoxAutoFilterContext::onCanCreateContext( sal_Int32 nElement ) const +{ + switch( getCurrentContext() ) + { + case XLS_TOKEN( autoFilter ): + return (nElement == XLS_TOKEN( filterColumn )); + case XLS_TOKEN( filterColumn ): + return (nElement == XLS_TOKEN( filters )) || + (nElement == XLS_TOKEN( customFilters )) || + (nElement == XLS_TOKEN( top10 )) || + (nElement == XLS_TOKEN( dynamicFilter )); + case XLS_TOKEN( filters ): + return (nElement == XLS_TOKEN( filter )); + case XLS_TOKEN( customFilters ): + return (nElement == XLS_TOKEN( customFilter )); + } + return false; +} + +void OoxAutoFilterContext::onStartElement( const AttributeList& rAttribs ) +{ + switch( getCurrentContext() ) + { + case XLS_TOKEN( autoFilter ): + importAutoFilter( rAttribs ); + break; + case XLS_TOKEN( filterColumn ): + if ( mbValidAddress ) + importFilterColumn( rAttribs ); + break; + case XLS_TOKEN( filters ): + if ( mbValidAddress ) + importFilters( rAttribs ); + break; + case XLS_TOKEN( filter ): + if ( mbValidAddress ) + importFilter( rAttribs ); + break; + case XLS_TOKEN( customFilters ): + if ( mbValidAddress ) + importCustomFilters( rAttribs ); + break; + case XLS_TOKEN( customFilter ): + if ( mbValidAddress ) + importCustomFilter( rAttribs ); + break; + case XLS_TOKEN( top10 ): + if ( mbValidAddress ) + importTop10( rAttribs ); + break; + case XLS_TOKEN( dynamicFilter ): + if ( mbValidAddress ) + importDynamicFilter( rAttribs ); + break; + } +} + +void OoxAutoFilterContext::onEndElement( const OUString& /*rChars*/ ) +{ + switch( getCurrentContext() ) + { + case XLS_TOKEN( autoFilter ): + maybeShowBlank(); + setAutoFilter(); + break; + case XLS_TOKEN( filters ): + setFilterNames(); + break; + } +} + +#if DEBUG_OOX_AUTOFILTER +static void lclPrintNormalField( +#if USE_SC_MULTI_STRING_FILTER_PATCH + TableFilterFieldNormal* pField +#else + TableFilterField* pField +#endif +) +{ + using namespace ::com::sun::star::sheet; + + printf(" Operator: "); + switch ( pField->Operator ) + { + case FilterOperator_EQUAL: + printf("EQUAL"); + break; + case FilterOperator_NOT_EQUAL: + printf("NOT_EQUAL"); + break; + case com::sun::star::sheet::FilterOperator_GREATER: + printf("GREATER"); + break; + case com::sun::star::sheet::FilterOperator_GREATER_EQUAL: + printf("GREATER_EQUAL"); + break; + case FilterOperator_LESS: + printf("LESS"); + break; + case FilterOperator_LESS_EQUAL: + printf("LESS_EQUAL"); + break; + case FilterOperator_NOT_EMPTY: + printf("NOT_EMPTY"); + break; + case FilterOperator_EMPTY: + printf("EMPTY"); + break; + case FilterOperator_BOTTOM_PERCENT: + printf("BOTTOM_PERCENT"); + break; + case FilterOperator_BOTTOM_VALUES: + printf("BOTTOM_VALUES"); + break; + case FilterOperator_TOP_PERCENT: + printf("TOP_PERCENT"); + break; + case FilterOperator_TOP_VALUES: + printf("TOP_VALUES"); + break; + default: + printf("other"); + } + printf("\n"); + + printf(" StringValue: %s\n", + OUStringToOString(pField->StringValue, RTL_TEXTENCODING_UTF8).getStr()); + + printf(" NumericValue: %g\n", pField->NumericValue); + + printf(" IsNumeric: "); + if (pField->IsNumeric) + printf("yes\n"); + else + printf("no\n"); +} + +static void lclPrintFieldConnection( ::com::sun::star::sheet::FilterConnection eConn ) +{ + using namespace ::com::sun::star::sheet; + + printf(" Connection: "); + switch ( eConn ) + { + case FilterConnection_AND: + printf("AND"); + break; + case FilterConnection_OR: + printf("OR"); + break; + case FilterConnection_MAKE_FIXED_SIZE: + printf("MAKE_FIXED_SIZE"); + break; + default: + printf("other"); + } + printf("\n"); +} + +static void lclPrintFilterField( const FilterFieldItem& aItem ) +{ + using namespace ::com::sun::star::sheet; + + printf("----------------------------------------\n"); +#if USE_SC_MULTI_STRING_FILTER_PATCH + { + // Print common fields first. + + TableFilterFieldBase* pField = aItem.mpField.get(); + printf(" Field: %ld\n", pField->Field); + lclPrintFieldConnection(pField->Connection); + } + switch ( aItem.meType ) + { + case FilterFieldItem::NORMAL: + { + TableFilterFieldNormal* pField = static_cast(aItem.mpField.get()); + lclPrintNormalField(pField); + } + break; + case FilterFieldItem::MULTI_STRING: + { + TableFilterFieldMultiString* pMultiStrField = static_cast(aItem.mpField.get()); + sal_Int32 nSize = pMultiStrField->StringSet.getLength(); + printf(" StringSet:\n"); + for ( sal_Int32 i = 0; i < nSize; ++i ) + { + printf(" * %s\n", + OUStringToOString(pMultiStrField->StringSet[i], RTL_TEXTENCODING_UTF8).getStr()); + } + } + break; + } +#else + TableFilterField* pField = aItem.mpField.get(); + printf(" Field: %ld\n", pField->Field); + lclPrintFieldConnection(pField->Connection); + lclPrintNormalField(pField); + +#endif + fflush(stdout); +} +#endif + +void OoxAutoFilterContext::initialize() +{ + maFields.clear(); + maFilterNames.clear(); + mbValidAddress = mbShowBlank = mbUseRegex = mbConnectionAnd = false; +} + +void OoxAutoFilterContext::setAutoFilter() +{ + using namespace ::com::sun::star::sheet; + + // Name this built-in database. + OUStringBuffer sDataAreaNameBuf( CREATE_OUSTRING("Excel_BuiltIn__FilterDatabase_ ") ); + sDataAreaNameBuf.append( static_cast(getSheetIndex()+1) ); + + OUString sDataAreaName = sDataAreaNameBuf.makeStringAndClear(); + Reference< XCellRange > xCellRange = getCellRange( maAutoFilterRange ); + + // Create a new database range, add filters to it and refresh the database + // for that to take effect. + + Reference< XDatabaseRanges > xDBRanges; + { + PropertySet aDocProp( getDocument() ); + aDocProp.getProperty( xDBRanges, CREATE_OUSTRING("DatabaseRanges") ); + if ( !xDBRanges.is() ) + { + OSL_ENSURE(false, "OoxAutoFilterContext::setAutoFilter: DBRange empty"); + return; + } + } + + Reference< XNameAccess > xNA( xDBRanges, UNO_QUERY_THROW ); + if ( !xNA->hasByName( sDataAreaName ) ) + xDBRanges->addNewByName( sDataAreaName, maAutoFilterRange ); + + Reference< XDatabaseRange > xDB( xNA->getByName( sDataAreaName ), UNO_QUERY ); + if ( xDB.is() ) + { + PropertySet aProp( xDB ); + aProp.setProperty( CREATE_OUSTRING("AutoFilter"), true ); + } + + sal_Int32 nSize = maFields.size(); + sal_Int32 nMaxFieldCount = nSize; + Reference< XSheetFilterDescriptor > xDescriptor = xDB->getFilterDescriptor(); + if ( xDescriptor.is() ) + { + PropertySet aProp( xDescriptor ); + aProp.setProperty( CREATE_OUSTRING("ContainsHeader"), true ); + aProp.setProperty( CREATE_OUSTRING("UseRegularExpressions"), mbUseRegex ); + aProp.getProperty( nMaxFieldCount, CREATE_OUSTRING("MaxFieldCount") ); + } + else + { + OSL_ENSURE(false, "OoxAutoFilterContext::setAutoFilter: descriptor is empty"); + return; + } + + // Unpack all column field items into a sequence. +#if USE_SC_MULTI_STRING_FILTER_PATCH + Reference< XExtendedSheetFilterDescriptor > xExtDescriptor( xDescriptor, UNO_QUERY ); + if ( !xExtDescriptor.is() ) + { + OSL_ENSURE(false, "OoxAutoFilterContext::setAutoFilter: extended descriptor is empty"); + return; + } + + xExtDescriptor->begin(); + + list< FilterFieldItem >::const_iterator itr = maFields.begin(), itrEnd = maFields.end(); + for (sal_Int32 i = 0; itr != itrEnd && i < nMaxFieldCount; ++itr, ++i) + { +#if DEBUG_OOX_AUTOFILTER + lclPrintFilterField(*itr); +#endif + switch ( itr->meType ) + { + case oox::xls::FilterFieldItem::MULTI_STRING: + { + // multi-string filter type + TableFilterFieldMultiString* pField = static_cast( itr->mpField.get() ); + xExtDescriptor->addFilterFieldMultiString( *pField ); + } + break; + case oox::xls::FilterFieldItem::NORMAL: + default: + // normal filter type + TableFilterFieldNormal* pField = static_cast( itr->mpField.get() ); + xExtDescriptor->addFilterFieldNormal( *pField ); + } + } + xExtDescriptor->commit(); + +#else + Sequence< TableFilterField > aFields(nSize); + list< FilterFieldItem >::const_iterator itr = maFields.begin(), itrEnd = maFields.end(); + for (sal_Int32 i = 0; itr != itrEnd && i < nMaxFieldCount; ++itr, ++i) + { +#if DEBUG_OOX_AUTOFILTER + lclPrintFilterField( *itr ); +#endif + aFields[i] = *itr->mpField; + } + xDescriptor->setFilterFields( aFields ); +#endif + xDB->refresh(); +} + +void OoxAutoFilterContext::maybeShowBlank() +{ + using namespace ::com::sun::star::sheet; + + if ( !mbShowBlank ) + return; + +#if USE_SC_MULTI_STRING_FILTER_PATCH + FilterFieldItem aItem(FilterFieldItem::NORMAL); + TableFilterFieldNormal* pField = static_cast(aItem.mpField.get()); + pField->Field = mnCurColID; + pField->Operator = FilterOperator_EMPTY; + pField->Connection = FilterConnection_AND; + pField->IsNumeric = false; +#else + FilterFieldItem aItem; + aItem.mpField->Field = mnCurColID; + aItem.mpField->Operator = FilterOperator_EMPTY; + aItem.mpField->Connection = FilterConnection_AND; + aItem.mpField->IsNumeric = false; +#endif + maFields.push_back(aItem); +} + +void OoxAutoFilterContext::setFilterNames() +{ + using namespace ::com::sun::star::sheet; + + + sal_Int32 size = maFilterNames.size(); + if ( !size ) + return; + +#if USE_SC_MULTI_STRING_FILTER_PATCH + Sequence< OUString > aStrList(size); + list< OUString >::const_iterator itr = maFilterNames.begin(), itrEnd = maFilterNames.end(); + for (sal_Int32 i = 0; itr != itrEnd; ++itr, ++i) + aStrList[i] = *itr; + + FilterFieldItem aItem(FilterFieldItem::MULTI_STRING); + TableFilterFieldMultiString* pField = static_cast( aItem.mpField.get() ); + pField->Field = mnCurColID; + pField->Connection = FilterConnection_AND; + pField->StringSet = aStrList; + + maFields.push_back(aItem); +#else + static const OUString sSep = CREATE_OUSTRING("|"); + + OUStringBuffer buf; + if ( size > 1 ) + { + buf.append( CREATE_OUSTRING("^(") ); + mbUseRegex = true; + } + + list< OUString >::const_iterator itr = maFilterNames.begin(), itrEnd = maFilterNames.end(); + bool bFirst = true; + for (; itr != itrEnd; ++itr) + { + if (bFirst) + bFirst = false; + else + buf.append( sSep ); + buf.append( *itr ); + } + if ( size > 1 ) + buf.append( CREATE_OUSTRING(")$") ); + + FilterFieldItem aItem; + aItem.mpField->Field = mnCurColID; + aItem.mpField->StringValue = buf.makeStringAndClear(); + aItem.mpField->Operator = FilterOperator_EQUAL; + aItem.mpField->Connection = FilterConnection_AND; + aItem.mpField->IsNumeric = false; + maFields.push_back(aItem); +#endif +} + +void OoxAutoFilterContext::importAutoFilter( const AttributeList& rAttribs ) +{ + initialize(); + + mbValidAddress = getAddressConverter().convertToCellRange( + maAutoFilterRange, rAttribs.getString( XML_ref ), getSheetIndex(), true ); +} + +void OoxAutoFilterContext::importFilterColumn( const AttributeList& rAttribs ) +{ + // hiddenButton and showButton attributes are not used for now. + mnCurColID = rAttribs.getInteger( XML_colId, -1 ); +} + +void OoxAutoFilterContext::importTop10( const AttributeList& rAttribs ) +{ + using namespace ::com::sun::star::sheet; + + // filterVal attribute is not necessarily, since Calc also supports top 10 + // and top 10% filter type. + FilterFieldItem aItem; +#if USE_SC_MULTI_STRING_FILTER_PATCH + TableFilterFieldNormal* pField = static_cast(aItem.mpField.get()); +#else + TableFilterField* pField = aItem.mpField.get(); +#endif + pField->Field = mnCurColID; + + bool bPercent = rAttribs.getBool( XML_percent, false ); + bool bTop = rAttribs.getBool( XML_top, true ); + pField->NumericValue = rAttribs.getDouble( XML_val, 0.0 ); + pField->IsNumeric = true; + + // When top10 filter item is present, that's the only filter item for that column. + if ( bTop ) + if ( bPercent ) + pField->Operator = FilterOperator_TOP_PERCENT; + else + pField->Operator = FilterOperator_TOP_VALUES; + else + if ( bPercent ) + pField->Operator = FilterOperator_BOTTOM_PERCENT; + else + pField->Operator = FilterOperator_BOTTOM_VALUES; + + maFields.push_back(aItem); +} + +void OoxAutoFilterContext::importCustomFilters( const AttributeList& rAttribs ) +{ + // OR is default when the 'and' attribute is absent. + mbConnectionAnd = rAttribs.getBool( XML_and, false ); +} + +/** Do a best-effort guess of whether or not the given string is numerical. */ +static bool lclIsNumeric( const OUString& _str, const LocaleDataItem& aLocaleItem ) +{ + OUString str = _str.trim(); + sal_Int32 size = str.getLength(); + + if ( !size ) + // Empty string. This can't be a number. + return false; + + // Get the decimal separator for the current locale. + const OUString& sep = aLocaleItem.decimalSeparator; + + bool bDecimalSep = false; + for (sal_Int32 i = 0; i < size; ++i) + { + OUString c = str.copy(i, 1); + if ( !c.compareTo(sep) ) + { + if ( bDecimalSep ) + return false; + else + { + bDecimalSep = true; + continue; + } + } + if ( (0 > c.compareToAscii("0") || 0 < c.compareToAscii("9")) ) + return false; + } + + return true; +} + +/** Convert wildcard characters to regex equivalent. Returns true if any + wildcard character is found. */ +static bool lclWildcard2Regex( OUString& str ) +{ + bool bWCFound = false; + OUStringBuffer buf; + sal_Int32 size = str.getLength(); + buf.ensureCapacity(size + 6); // pure heuristics. + + sal_Unicode dot = '.', star = '*', hat = '^', dollar = '$'; + buf.append(hat); + for (sal_Int32 i = 0; i < size; ++i) + { + OUString c = str.copy(i, 1); + if ( !c.compareToAscii("?") ) + { + buf.append(dot); + bWCFound = true; + } + else if ( !c.compareToAscii("*") ) + { + buf.append(dot); + buf.append(star); + bWCFound = true; + } + else + buf.append(c); + } + buf.append(dollar); + + if (bWCFound) + str = buf.makeStringAndClear(); + + return bWCFound; +} + +/** Translate Excel's filter operator to Calc's. */ +static ::com::sun::star::sheet::FilterOperator lclTranslateFilterOp( sal_Int32 nToken ) +{ + using namespace ::com::sun::star::sheet; + + switch ( nToken ) + { + case XML_equal: + return FilterOperator_EQUAL; + case XML_notEqual: + return FilterOperator_NOT_EQUAL; + case XML_greaterThan: + return FilterOperator_GREATER; + case XML_greaterThanOrEqual: + return FilterOperator_GREATER_EQUAL; + case XML_lessThan: + return FilterOperator_LESS; + case XML_lessThanOrEqual: + return FilterOperator_LESS_EQUAL; + } + return FilterOperator_EQUAL; +} + +void OoxAutoFilterContext::importCustomFilter( const AttributeList& rAttribs ) +{ + using namespace ::com::sun::star::sheet; + + sal_Int32 nToken = rAttribs.getToken( XML_operator, XML_equal ); +#if USE_SC_MULTI_STRING_FILTER_PATCH + FilterFieldItem aItem(FilterFieldItem::NORMAL); + TableFilterFieldNormal* pField = static_cast(aItem.mpField.get()); +#else + FilterFieldItem aItem; + TableFilterField* pField = aItem.mpField.get(); +#endif + pField->Field = mnCurColID; + pField->StringValue = rAttribs.getString( XML_val ); + pField->NumericValue = pField->StringValue.toDouble(); + pField->Operator = lclTranslateFilterOp( nToken ); + + if ( nToken == XML_notEqual && !pField->StringValue.compareToAscii(" ") ) + { + // Special case for hiding blanks. Excel translates "hide blanks" to + // (filter if notEqual " "). So, we need to translate it back. + pField->Operator = FilterOperator_NOT_EMPTY; + pField->IsNumeric = false; + maFields.push_back(aItem); + return; + } + + switch ( nToken ) + { + case XML_equal: + case XML_notEqual: + { + Reference< XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + Reference< XLocaleData > xLocale( xFactory->createInstance( + CREATE_OUSTRING("com.sun.star.i18n.LocaleData") ), UNO_QUERY ); + + if ( !xLocale.is() ) + return; + + LocaleDataItem aLocaleItem = xLocale->getLocaleItem( ::com::sun::star::lang::Locale() ); + pField->IsNumeric = lclIsNumeric(pField->StringValue, aLocaleItem); + + if ( !pField->IsNumeric && lclWildcard2Regex(pField->StringValue) ) + mbUseRegex = true; + + maFields.push_back(aItem); + } + break; + + case XML_greaterThan: + case XML_greaterThanOrEqual: + case XML_lessThan: + case XML_lessThanOrEqual: + { + pField->IsNumeric = true; + maFields.push_back(aItem); + } + break; + default: + OSL_ENSURE( false, "OoxAutoFilterContext::importCustomFilter: unhandled case" ); + } +} + +void OoxAutoFilterContext::importFilters( const AttributeList& rAttribs ) +{ + // blank (boolean) and calendarType attributes can be present, but not used for now. + + mbShowBlank = rAttribs.getBool( XML_blank, false ); + maFilterNames.clear(); +} + +void OoxAutoFilterContext::importFilter( const AttributeList& rAttribs ) +{ + if (mnCurColID == -1) + return; + + OUString value = rAttribs.getString( XML_val ); + if ( value.getLength() ) + maFilterNames.push_back(value); +} + +void OoxAutoFilterContext::importDynamicFilter( const AttributeList& /*rAttribs*/ ) +{ + // not implemented yet - Calc doesn't support this. +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/biffcodec.cxx b/oox/source/xls/biffcodec.cxx new file mode 100644 index 000000000000..0eb0db29aa91 --- /dev/null +++ b/oox/source/xls/biffcodec.cxx @@ -0,0 +1,211 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: biffcodec.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:07 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/biffcodec.hxx" +#include + +using ::rtl::OString; +using ::rtl::OUString; +using ::rtl::OStringToOUString; + +namespace oox { +namespace xls { + +// ============================================================================ + +const OString& BiffCodecHelper::getBiff5WbProtPassword() +{ + static const OString saPass( "VelvetSweatshop" ); + return saPass; +} + +const OUString& BiffCodecHelper::getBiff8WbProtPassword() +{ + static const OUString saPass = OStringToOUString( getBiff5WbProtPassword(), RTL_TEXTENCODING_ASCII_US ); + return saPass; +} + +// ============================================================================ + +BiffDecoderBase::BiffDecoderBase( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + mnError( CODEC_ERROR_UNSUPP_CRYPT ) +{ +} + +BiffDecoderBase::~BiffDecoderBase() +{ +} + +void BiffDecoderBase::decode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcData, sal_Int64 nStreamPos, sal_uInt16 nBytes ) +{ + if( pnDestData && pnSrcData && (nBytes > 0) ) + { + if( isValid() ) + implDecode( pnDestData, pnSrcData, nStreamPos, nBytes ); + else + memcpy( pnDestData, pnSrcData, nBytes ); + } +} + +void BiffDecoderBase::setHasValidPassword( bool bValid ) +{ + mnError = bValid ? CODEC_OK : CODEC_ERROR_WRONG_PASS; +} + +// ============================================================================ + +BiffDecoder_XOR::BiffDecoder_XOR( const WorkbookHelper& rHelper, sal_uInt16 nKey, sal_uInt16 nHash ) : + BiffDecoderBase( rHelper ), + maCodec( ::oox::core::BinaryCodec_XOR::CODEC_EXCEL ) +{ + init( BiffCodecHelper::getBiff5WbProtPassword(), nKey, nHash ); + if( !isValid() ) + { + OString aPass = OUStringToOString( queryPassword(), osl_getThreadTextEncoding() ); + init( aPass, nKey, nHash ); + } +} + +void BiffDecoder_XOR::init( const OString& rPass, sal_uInt16 nKey, sal_uInt16 nHash ) +{ + sal_Int32 nLen = rPass.getLength(); + bool bValid = (0 < nLen) && (nLen < 16); + + if( bValid ) + { + // copy byte string to sal_uInt8 array + sal_uInt8 pnPassw[ 16 ]; + memset( pnPassw, 0, sizeof( pnPassw ) ); + memcpy( pnPassw, rPass.getStr(), static_cast< size_t >( nLen ) ); + + // init codec + maCodec.initKey( pnPassw ); + bValid = maCodec.verifyKey( nKey, nHash ); + } + + setHasValidPassword( bValid ); +} + +void BiffDecoder_XOR::implDecode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcData, sal_Int64 nStreamPos, sal_uInt16 nBytes ) +{ + maCodec.startBlock(); + maCodec.skip( static_cast< sal_Int32 >( (nStreamPos + nBytes) & 0x0F ) ); + maCodec.decode( pnDestData, pnSrcData, nBytes ); +} + +// ============================================================================ + +namespace { + +/** Returns the block index of the passed stream position for RCF decryption. */ +sal_Int32 lclGetRcfBlock( sal_Int64 nStreamPos ) +{ + return static_cast< sal_Int32 >( nStreamPos / BIFF_RCF_BLOCKSIZE ); +} + +/** Returns the offset of the passed stream position in a block for RCF decryption. */ +sal_Int32 lclGetRcfOffset( sal_Int64 nStreamPos ) +{ + return static_cast< sal_Int32 >( nStreamPos % BIFF_RCF_BLOCKSIZE ); +} + +} // namespace + +// ---------------------------------------------------------------------------- + +BiffDecoder_RCF::BiffDecoder_RCF( const WorkbookHelper& rHelper, + sal_uInt8 pnDocId[ 16 ], sal_uInt8 pnSaltData[ 16 ], sal_uInt8 pnSaltHash[ 16 ] ) : + BiffDecoderBase( rHelper ) +{ + init( BiffCodecHelper::getBiff8WbProtPassword(), pnDocId, pnSaltData, pnSaltHash ); + if( !isValid() ) + init( queryPassword(), pnDocId, pnSaltData, pnSaltHash ); +} + +void BiffDecoder_RCF::init( const OUString& rPass, sal_uInt8 pnDocId[ 16 ], sal_uInt8 pnSaltData[ 16 ], sal_uInt8 pnSaltHash[ 16 ] ) +{ + sal_Int32 nLen = rPass.getLength(); + bool bValid = (0 < nLen) && (nLen < 16); + + if( bValid ) + { + // copy string to sal_uInt16 array + sal_uInt16 pnPassw[ 16 ]; + memset( pnPassw, 0, sizeof( pnPassw ) ); + const sal_Unicode* pcChar = rPass.getStr(); + const sal_Unicode* pcCharEnd = pcChar + nLen; + sal_uInt16* pnCurrPass = pnPassw; + for( ; pcChar < pcCharEnd; ++pcChar, ++pnCurrPass ) + *pnCurrPass = static_cast< sal_uInt16 >( *pcChar ); + + // init codec + maCodec.initKey( pnPassw, pnDocId ); + bValid = maCodec.verifyKey( pnSaltData, pnSaltHash ); + } + + setHasValidPassword( bValid ); +} + +void BiffDecoder_RCF::implDecode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcData, sal_Int64 nStreamPos, sal_uInt16 nBytes ) +{ + sal_uInt8* pnCurrDest = pnDestData; + const sal_uInt8* pnCurrSrc = pnSrcData; + sal_Int64 nCurrPos = nStreamPos; + sal_uInt16 nBytesLeft = nBytes; + while( nBytesLeft > 0 ) + { + // initialize codec for current stream position + maCodec.startBlock( lclGetRcfBlock( nCurrPos ) ); + maCodec.skip( lclGetRcfOffset( nCurrPos ) ); + + // decode the block + sal_uInt16 nBlockLeft = static_cast< sal_uInt16 >( BIFF_RCF_BLOCKSIZE - lclGetRcfOffset( nCurrPos ) ); + sal_uInt16 nDecBytes = ::std::min( nBytesLeft, nBlockLeft ); + maCodec.decode( pnCurrDest, pnCurrSrc, static_cast< sal_Int32 >( nDecBytes ) ); + + // prepare for next block + pnCurrDest += nDecBytes; + pnCurrSrc += nDecBytes; + nCurrPos += nDecBytes; + nBytesLeft = nBytesLeft - nDecBytes; + } +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/biffdetector.cxx b/oox/source/xls/biffdetector.cxx new file mode 100644 index 000000000000..b30e820fcbf0 --- /dev/null +++ b/oox/source/xls/biffdetector.cxx @@ -0,0 +1,241 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: biffdetector.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:08 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/biffdetector.hxx" +#include +#include +#include +#include +#include "oox/helper/binaryinputstream.hxx" +#include "oox/helper/olestorage.hxx" + +using ::rtl::OUString; +using ::rtl::OStringBuffer; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::uno::XInterface; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::beans::PropertyValue; +using ::com::sun::star::io::XInputStream; +using ::comphelper::MediaDescriptor; + +namespace oox { +namespace xls { + +// ============================================================================ + +Sequence< OUString > BiffDetector_getSupportedServiceNames() +{ + Sequence< OUString > aServiceNames( 1 ); + aServiceNames[ 0 ] = CREATE_OUSTRING( "com.sun.star.frame.ExtendedTypeDetection" ); + return aServiceNames; +} + +OUString BiffDetector_getImplementationName() +{ + return CREATE_OUSTRING( "com.sun.star.comp.oox.BiffDetector" ); +} + +Reference< XInterface > SAL_CALL BiffDetector_createInstance( const Reference< XMultiServiceFactory >& rxFactory ) throw( Exception ) +{ + return static_cast< ::cppu::OWeakObject* >( new BiffDetector( rxFactory ) ); +} + +// ============================================================================ + +BiffDetector::BiffDetector( const Reference< XMultiServiceFactory >& rxFactory ) : + mxFactory( rxFactory ) +{ +} + +BiffDetector::~BiffDetector() +{ +} + +BiffType BiffDetector::detectStreamBiffVersion( BinaryInputStream& rInStream ) +{ + BiffType eBiff = BIFF_UNKNOWN; + if( rInStream.is() && rInStream.isSeekable() && (rInStream.getLength() > 4) ) + { + sal_Int64 nOldPos = rInStream.tell(); + rInStream.seek( 0 ); + sal_uInt16 nBofId, nBofSize; + rInStream >> nBofId >> nBofSize; + + if( (4 <= nBofSize) && (nBofSize <= 16) && (rInStream.tell() + nBofSize <= rInStream.getLength()) ) + { + switch( nBofId ) + { + case BIFF2_ID_BOF: + eBiff = BIFF2; + break; + case BIFF3_ID_BOF: + eBiff = BIFF3; + break; + case BIFF4_ID_BOF: + eBiff = BIFF4; + break; + case BIFF5_ID_BOF: + { + if( 6 <= nBofSize ) + { + sal_uInt16 nVersion; + rInStream >> nVersion; + // #i23425# #i44031# #i62752# there are some *really* broken documents out there... + switch( nVersion & 0xFF00 ) + { + case 0: eBiff = BIFF5; break; // #i44031# #i62752# + case BIFF_BOF_BIFF2: eBiff = BIFF2; break; + case BIFF_BOF_BIFF3: eBiff = BIFF3; break; + case BIFF_BOF_BIFF4: eBiff = BIFF4; break; + case BIFF_BOF_BIFF5: eBiff = BIFF5; break; + case BIFF_BOF_BIFF8: eBiff = BIFF8; break; + default: OSL_ENSURE( false, + OStringBuffer( "lclDetectStreamBiffVersion - unknown BIFF version: 0x" ). + append( static_cast< sal_Int32 >( nVersion ), 16 ).getStr() ); + } + } + } + break; + // else do nothing, no BIFF stream + } + } + rInStream.seek( nOldPos ); + } + return eBiff; +} + +BiffType BiffDetector::detectStorageBiffVersion( OUString& orWorkbookStreamName, StorageRef xStorage ) +{ + static const OUString saBookName = CREATE_OUSTRING( "Book" ); + static const OUString saWorkbookName = CREATE_OUSTRING( "Workbook" ); + + BiffType eBiff = BIFF_UNKNOWN; + if( xStorage.get() ) + { + if( xStorage->isStorage() ) + { + // try to open the "Book" stream + BinaryInputStream aBookStrm5( xStorage->openInputStream( saBookName ), true ); + BiffType eBookStrm5Biff = detectStreamBiffVersion( aBookStrm5 ); + + // try to open the "Workbook" stream + BinaryInputStream aBookStrm8( xStorage->openInputStream( saWorkbookName ), true ); + BiffType eBookStrm8Biff = detectStreamBiffVersion( aBookStrm8 ); + + // decide which stream to use + if( (eBookStrm8Biff != BIFF_UNKNOWN) && ((eBookStrm5Biff == BIFF_UNKNOWN) || (eBookStrm8Biff > eBookStrm5Biff)) ) + { + /* Only "Workbook" stream exists; or both streams exist, + and "Workbook" has higher BIFF version than "Book" stream. */ + eBiff = eBookStrm8Biff; + orWorkbookStreamName = saWorkbookName; + } + else if( eBookStrm5Biff != BIFF_UNKNOWN ) + { + /* Only "Book" stream exists; or both streams exist, + and "Book" has higher BIFF version than "Workbook" stream. */ + eBiff = eBookStrm5Biff; + orWorkbookStreamName = saBookName; + } + } + else + { + // no storage, try plain input stream from medium (even for BIFF5+) + BinaryInputStream aStrm( xStorage->openInputStream( OUString() ), false ); + eBiff = detectStreamBiffVersion( aStrm ); + orWorkbookStreamName = OUString(); + } + } + + return eBiff; +} + +// com.sun.star.lang.XServiceInfo interface ----------------------------------- + +OUString SAL_CALL BiffDetector::getImplementationName() throw( RuntimeException ) +{ + return BiffDetector_getImplementationName(); +} + +sal_Bool SAL_CALL BiffDetector::supportsService( const OUString& rService ) throw( RuntimeException ) +{ + const Sequence< OUString > aServices( BiffDetector_getSupportedServiceNames() ); + const OUString* pArray = aServices.getConstArray(); + const OUString* pArrayEnd = pArray + aServices.getLength(); + return ::std::find( pArray, pArrayEnd, rService ) != pArrayEnd; +} + +Sequence< OUString > SAL_CALL BiffDetector::getSupportedServiceNames() throw( RuntimeException ) +{ + return BiffDetector_getSupportedServiceNames(); +} + +// com.sun.star.document.XExtendedFilterDetect interface ---------------------- + +OUString SAL_CALL BiffDetector::detect( Sequence< PropertyValue >& rDescriptor ) throw( RuntimeException ) +{ + OUString aTypeName; + + MediaDescriptor aDescriptor( rDescriptor ); + aDescriptor.addInputStream(); + + Reference< XInputStream > xInStrm( aDescriptor[ MediaDescriptor::PROP_INPUTSTREAM() ], UNO_QUERY ); + if( xInStrm.is() ) + { + OUString aWorkbookName; + StorageRef xStorage( new OleStorage( mxFactory, xInStrm, true ) ); + switch( detectStorageBiffVersion( aWorkbookName, xStorage ) ) + { + case BIFF2: + case BIFF3: + case BIFF4: aTypeName = CREATE_OUSTRING( "calc_MS_Excel_40" ); break; + case BIFF5: aTypeName = CREATE_OUSTRING( "calc_MS_Excel_95" ); break; + case BIFF8: aTypeName = CREATE_OUSTRING( "calc_MS_Excel_97" ); break; + default:; + } + } + + return aTypeName; +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/bifffragmenthandler.cxx b/oox/source/xls/bifffragmenthandler.cxx new file mode 100644 index 000000000000..061e213b1092 --- /dev/null +++ b/oox/source/xls/bifffragmenthandler.cxx @@ -0,0 +1,169 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: bifffragmenthandler.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:08 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/bifffragmenthandler.hxx" +#include "oox/xls/biffhelper.hxx" +#include "oox/xls/biffinputstream.hxx" + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +const sal_uInt16 BIFF_BOF_GLOBALS = 0x0005; /// BIFF5-BIFF8 workbook globals. +const sal_uInt16 BIFF_BOF_MODULE = 0x0006; /// BIFF5-BIFF8 Visual Basic module. +const sal_uInt16 BIFF_BOF_SHEET = 0x0010; /// BIFF2-BIFF8 worksheet/dialog sheet. +const sal_uInt16 BIFF_BOF_CHART = 0x0020; /// BIFF2-BIFF8 chart sheet. +const sal_uInt16 BIFF_BOF_MACRO = 0x0040; /// BIFF4-BIFF8 macro sheet. +const sal_uInt16 BIFF_BOF_WORKSPACE = 0x0100; /// BIFF3-BIFF8 workspace. + +} // namespace + +// ============================================================================ + +BiffFragmentHandler::~BiffFragmentHandler() +{ +} + +bool BiffFragmentHandler::importFragment( BiffInputStream& rStrm ) +{ + // default implementation: skip the entire fragment + return skipFragment( rStrm ); +} + +bool BiffFragmentHandler::isBofRecord( sal_uInt16 nRecId ) +{ + return (nRecId == BIFF2_ID_BOF) || (nRecId == BIFF3_ID_BOF) || (nRecId == BIFF4_ID_BOF) || (nRecId == BIFF5_ID_BOF); +} + +BiffFragmentType BiffFragmentHandler::startFragment( BiffInputStream& rStrm, BiffType eBiff ) +{ + BiffFragmentType eFragment = BIFF_FRAGMENT_UNKNOWN; + if( rStrm.startNextRecord() ) + { + /* #i23425# Don't rely on BOF record ID to read BOF contents, but on + the detected BIFF version. */ + if( isBofRecord( rStrm.getRecId() ) ) + { + // BOF is always written unencrypted + rStrm.enableDecoder( false ); + sal_uInt16 nType = rStrm.skip( 2 ).readuInt16(); + + // decide which fragment types are valid for current BIFF version + switch( eBiff ) + { + case BIFF2: switch( nType ) + { + case BIFF_BOF_CHART: eFragment = BIFF_FRAGMENT_EMPTYSHEET; break; + case BIFF_BOF_MACRO: eFragment = BIFF_FRAGMENT_MACRO; break; + // #i51490# Excel interprets invalid types as worksheet + default: eFragment = BIFF_FRAGMENT_WORKSHEET; + } + break; + + case BIFF3: switch( nType ) + { + case BIFF_BOF_CHART: eFragment = BIFF_FRAGMENT_EMPTYSHEET; break; + case BIFF_BOF_MACRO: eFragment = BIFF_FRAGMENT_MACRO; break; + case BIFF_BOF_WORKSPACE:eFragment = BIFF_FRAGMENT_UNKNOWN; break; + // #i51490# Excel interprets invalid types as worksheet + default: eFragment = BIFF_FRAGMENT_WORKSHEET; + }; + break; + + case BIFF4: switch( nType ) + { + case BIFF_BOF_CHART: eFragment = BIFF_FRAGMENT_EMPTYSHEET; break; + case BIFF_BOF_MACRO: eFragment = BIFF_FRAGMENT_MACRO; break; + case BIFF_BOF_WORKSPACE:eFragment = BIFF_FRAGMENT_WORKSPACE; break; + // #i51490# Excel interprets invalid types as worksheet + default: eFragment = BIFF_FRAGMENT_WORKSHEET; + }; + break; + + case BIFF5: + case BIFF8: switch( nType ) + { + case BIFF_BOF_GLOBALS: eFragment = BIFF_FRAGMENT_GLOBALS; break; + case BIFF_BOF_CHART: eFragment = BIFF_FRAGMENT_CHART; break; + case BIFF_BOF_MACRO: eFragment = BIFF_FRAGMENT_MACRO; break; + case BIFF_BOF_WORKSPACE:eFragment = BIFF_FRAGMENT_UNKNOWN; break; + // #i51490# Excel interprets invalid types as worksheet + default: eFragment = BIFF_FRAGMENT_WORKSHEET; + }; + break; + + case BIFF_UNKNOWN: break; + } + } + } + return eFragment; +} + +bool BiffFragmentHandler::skipFragment( BiffInputStream& rStrm ) +{ + while( rStrm.startNextRecord() && (rStrm.getRecId() != BIFF_ID_EOF) ) + if( isBofRecord( rStrm.getRecId() ) ) + skipFragment( rStrm ); + return rStrm.isValid() && (rStrm.getRecId() == BIFF_ID_EOF); +} + +// ============================================================================ + +BiffWorkbookFragmentBase::BiffWorkbookFragmentBase( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ) +{ +} + +// ============================================================================ + +BiffWorksheetFragmentBase::BiffWorksheetFragmentBase( const WorkbookHelper& rHelper, + ISegmentProgressBarRef xProgressBar, WorksheetType eSheetType, sal_Int32 nSheet ) : + WorksheetHelperRoot( rHelper, xProgressBar, eSheetType, nSheet ) +{ +} + +BiffWorksheetFragmentBase::BiffWorksheetFragmentBase( const WorksheetHelper& rHelper ) : + WorksheetHelperRoot( rHelper ) +{ +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/biffhelper.cxx b/oox/source/xls/biffhelper.cxx new file mode 100644 index 000000000000..fb04a87e2502 --- /dev/null +++ b/oox/source/xls/biffhelper.cxx @@ -0,0 +1,296 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: biffhelper.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:08 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/biffhelper.hxx" +#include +#include +#include "oox/xls/biffinputstream.hxx" +#include "oox/xls/biffoutputstream.hxx" +#include "oox/xls/worksheethelper.hxx" + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + +namespace oox { +namespace xls { + +// GUID ======================================================================= + +BiffGuid::BiffGuid() +{ + ::std::fill_n( mpnData, sizeof( mpnData ), 0 ); +} + +BiffGuid::BiffGuid( + sal_uInt32 nData1, sal_uInt16 nData2, sal_uInt16 nData3, + sal_uInt8 nData41, sal_uInt8 nData42, sal_uInt8 nData43, sal_uInt8 nData44, + sal_uInt8 nData45, sal_uInt8 nData46, sal_uInt8 nData47, sal_uInt8 nData48 ) +{ + // convert to little endian -> makes streaming easy + ByteOrderConverter::writeLittleEndian( mpnData, nData1 ); + ByteOrderConverter::writeLittleEndian( mpnData + 4, nData2 ); + ByteOrderConverter::writeLittleEndian( mpnData + 6, nData3 ); + mpnData[ 8 ] = nData41; + mpnData[ 9 ] = nData42; + mpnData[ 10 ] = nData43; + mpnData[ 11 ] = nData44; + mpnData[ 12 ] = nData45; + mpnData[ 13 ] = nData46; + mpnData[ 14 ] = nData47; + mpnData[ 15 ] = nData48; +} + +bool operator==( const BiffGuid& rGuid1, const BiffGuid& rGuid2 ) +{ + return ::std::equal( rGuid1.mpnData, STATIC_ARRAY_END( rGuid1.mpnData ), rGuid2.mpnData ); +} + +bool operator<( const BiffGuid& rGuid1, const BiffGuid& rGuid2 ) +{ + return ::std::lexicographical_compare( + rGuid1.mpnData, STATIC_ARRAY_END( rGuid1.mpnData ), + rGuid2.mpnData, STATIC_ARRAY_END( rGuid2.mpnData ) ); +} + +BiffInputStream& operator>>( BiffInputStream& rStrm, BiffGuid& rGuid ) +{ + rStrm.read( rGuid.mpnData, 16 ); // mpnData always in little endian + return rStrm; +} + +BiffOutputStream& operator<<( BiffOutputStream& rStrm, const BiffGuid& rGuid ) +{ + rStrm.setPortionSize( 16 ); + rStrm.write( rGuid.mpnData, 16 ); // mpnData already in little endian + rStrm.setPortionSize( 0 ); + return rStrm; +} + +// ============================================================================ + +namespace { + +const sal_Int32 BIFF_RK_100FLAG = 0x00000001; +const sal_Int32 BIFF_RK_INTFLAG = 0x00000002; +const sal_Int32 BIFF_RK_VALUEMASK = 0xFFFFFFFC; + +// ---------------------------------------------------------------------------- + +static const struct CodePageEntry +{ + sal_uInt16 mnCodePage; + rtl_TextEncoding meTextEnc; +} +spCodePages[] = +{ + { 437, RTL_TEXTENCODING_IBM_437 }, // OEM US +// { 720, RTL_TEXTENCODING_IBM_720 }, // OEM Arabic + { 737, RTL_TEXTENCODING_IBM_737 }, // OEM Greek + { 775, RTL_TEXTENCODING_IBM_775 }, // OEM Baltic + { 850, RTL_TEXTENCODING_IBM_850 }, // OEM Latin I + { 852, RTL_TEXTENCODING_IBM_852 }, // OEM Latin II (Central European) + { 855, RTL_TEXTENCODING_IBM_855 }, // OEM Cyrillic + { 857, RTL_TEXTENCODING_IBM_857 }, // OEM Turkish +// { 858, RTL_TEXTENCODING_IBM_858 }, // OEM Multilingual Latin I with Euro + { 860, RTL_TEXTENCODING_IBM_860 }, // OEM Portugese + { 861, RTL_TEXTENCODING_IBM_861 }, // OEM Icelandic + { 862, RTL_TEXTENCODING_IBM_862 }, // OEM Hebrew + { 863, RTL_TEXTENCODING_IBM_863 }, // OEM Canadian (French) + { 864, RTL_TEXTENCODING_IBM_864 }, // OEM Arabic + { 865, RTL_TEXTENCODING_IBM_865 }, // OEM Nordic + { 866, RTL_TEXTENCODING_IBM_866 }, // OEM Cyrillic (Russian) + { 869, RTL_TEXTENCODING_IBM_869 }, // OEM Greek (Modern) + { 874, RTL_TEXTENCODING_MS_874 }, // MS Windows Thai + { 932, RTL_TEXTENCODING_MS_932 }, // MS Windows Japanese Shift-JIS + { 936, RTL_TEXTENCODING_MS_936 }, // MS Windows Chinese Simplified GBK + { 949, RTL_TEXTENCODING_MS_949 }, // MS Windows Korean (Wansung) + { 950, RTL_TEXTENCODING_MS_950 }, // MS Windows Chinese Traditional BIG5 + { 1200, RTL_TEXTENCODING_DONTKNOW }, // Unicode (BIFF8) - return *_DONTKNOW to preserve old code page + { 1250, RTL_TEXTENCODING_MS_1250 }, // MS Windows Latin II (Central European) + { 1251, RTL_TEXTENCODING_MS_1251 }, // MS Windows Cyrillic + { 1252, RTL_TEXTENCODING_MS_1252 }, // MS Windows Latin I (BIFF4-BIFF8) + { 1253, RTL_TEXTENCODING_MS_1253 }, // MS Windows Greek + { 1254, RTL_TEXTENCODING_MS_1254 }, // MS Windows Turkish + { 1255, RTL_TEXTENCODING_MS_1255 }, // MS Windows Hebrew + { 1256, RTL_TEXTENCODING_MS_1256 }, // MS Windows Arabic + { 1257, RTL_TEXTENCODING_MS_1257 }, // MS Windows Baltic + { 1258, RTL_TEXTENCODING_MS_1258 }, // MS Windows Vietnamese + { 1361, RTL_TEXTENCODING_MS_1361 }, // MS Windows Korean (Johab) + { 10000, RTL_TEXTENCODING_APPLE_ROMAN }, // Apple Roman + { 32768, RTL_TEXTENCODING_APPLE_ROMAN }, // Apple Roman + { 32769, RTL_TEXTENCODING_MS_1252 } // MS Windows Latin I (BIFF2-BIFF3) +}; + +/** Predicate to search by given code page. */ +struct CodePageEntry_CPPred +{ + inline explicit CodePageEntry_CPPred( sal_uInt16 nCodePage ) : mnCodePage( nCodePage ) {} + inline bool operator()( const CodePageEntry& rEntry ) const { return rEntry.mnCodePage == mnCodePage; } + sal_uInt16 mnCodePage; +}; + +/** Predicate to search by given text encoding. */ +struct CodePageEntry_TEPred +{ + inline explicit CodePageEntry_TEPred( rtl_TextEncoding eTextEnc ) : meTextEnc( eTextEnc ) {} + inline bool operator()( const CodePageEntry& rEntry ) const { return rEntry.meTextEnc == meTextEnc; } + rtl_TextEncoding meTextEnc; +}; + +} // namespace + +// ============================================================================ + +const BiffGuid BiffHelper::maGuidStdHlink( + 0x79EAC9D0, 0xBAF9, 0x11CE, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B ); + +const BiffGuid BiffHelper::maGuidUrlMoniker( + 0x79EAC9E0, 0xBAF9, 0x11CE, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B ); + +const BiffGuid BiffHelper::maGuidFileMoniker( + 0x00000303, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 ); + +// conversion ----------------------------------------------------------------- + +double BiffHelper::calcDoubleFromRk( sal_Int32 nRkValue ) +{ + double fValue = 0.0; + if( getFlag( nRkValue, BIFF_RK_INTFLAG ) ) + { + sal_Int32 nTemp = nRkValue >> 2; + setFlag< sal_Int32 >( nTemp, 0xE0000000, nRkValue < 0 ); + fValue = nTemp; + } + else + { + sal_math_Double* pDouble = reinterpret_cast< sal_math_Double* >( &fValue ); + pDouble->w32_parts.msw = static_cast< sal_uInt32 >( nRkValue & BIFF_RK_VALUEMASK ); + } + + if( getFlag( nRkValue, BIFF_RK_100FLAG ) ) + fValue /= 100.0; + + return fValue; +} + +namespace { + +bool lclCalcRkFromDouble( sal_Int32& ornRkValue, double fValue ) +{ + // double + const sal_math_Double* pValue = reinterpret_cast< const sal_math_Double* >( &fValue ); + if( (pValue->w32_parts.lsw == 0) && ((pValue->w32_parts.msw & 0x3) == 0) ) + { + ornRkValue = static_cast< sal_Int32 >( pValue->w32_parts.msw ); + return true; + } + + // integer + double fInt = 0.0; + double fFrac = modf( fValue, &fInt ); + if( (fFrac == 0.0) && (-536870912.0 <= fInt) && (fInt <= 536870911.0) ) // 2^29 + { + ornRkValue = static_cast< sal_Int32 >( fInt ); + ornRkValue <<= 2; + ornRkValue |= BIFF_RK_INTFLAG; + return true; + } + + return false; +} + +} // namespace + +bool BiffHelper::calcRkFromDouble( sal_Int32& ornRkValue, double fValue ) +{ + if( lclCalcRkFromDouble( ornRkValue, fValue ) ) + return true; + + if( lclCalcRkFromDouble( ornRkValue, fValue * 100 ) ) + { + ornRkValue |= BIFF_RK_100FLAG; + return true; + } + + return false; +} + +double BiffHelper::calcDoubleFromError( sal_uInt8 nErrorCode ) +{ + sal_uInt16 nApiError = 0x7FFF; + switch( nErrorCode ) + { + case BIFF_ERR_NULL: nApiError = 521; break; + case BIFF_ERR_DIV0: nApiError = 532; break; + case BIFF_ERR_VALUE: nApiError = 519; break; + case BIFF_ERR_REF: nApiError = 524; break; + case BIFF_ERR_NAME: nApiError = 525; break; + case BIFF_ERR_NUM: nApiError = 503; break; + case BIFF_ERR_NA: nApiError = 0x7FFF; break; + default: OSL_ENSURE( false, "BiffHelper::calcDoubleFromError - unknown error code" ); + } + double fValue; + ::rtl::math::setNan( &fValue ); + reinterpret_cast< sal_math_Double* >( &fValue )->nan_parts.fraction_lo = nApiError; + return fValue; +} + +rtl_TextEncoding BiffHelper::calcTextEncodingFromCodePage( sal_uInt16 nCodePage ) +{ + const CodePageEntry* pEntry = ::std::find_if( spCodePages, STATIC_ARRAY_END( spCodePages ), CodePageEntry_CPPred( nCodePage ) ); + if( pEntry == STATIC_ARRAY_END( spCodePages ) ) + { + OSL_ENSURE( false, "UnitConverter::calcTextEncodingFromCodePage - unknown code page" ); + return RTL_TEXTENCODING_DONTKNOW; + } + return pEntry->meTextEnc; +} + +sal_uInt16 BiffHelper::calcCodePageFromTextEncoding( rtl_TextEncoding eTextEnc ) +{ + const CodePageEntry* pEntry = ::std::find_if( spCodePages, STATIC_ARRAY_END( spCodePages ), CodePageEntry_TEPred( eTextEnc ) ); + if( pEntry == STATIC_ARRAY_END( spCodePages ) ) + { + OSL_ENSURE( false, "UnitConverter::calcCodePageFromTextEncoding - unsupported text encoding" ); + return 1252; + } + return pEntry->mnCodePage; +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/biffinputstream.cxx b/oox/source/xls/biffinputstream.cxx new file mode 100644 index 000000000000..70428f9de3ad --- /dev/null +++ b/oox/source/xls/biffinputstream.cxx @@ -0,0 +1,646 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: biffinputstream.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:08 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/biffinputstream.hxx" +#include "oox/helper/binaryinputstream.hxx" + +using ::rtl::OUString; +using ::rtl::OString; +using ::rtl::OStringToOUString; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace prv { + +BiffInputRecordBuffer::BiffInputRecordBuffer( BinaryInputStream& rInStrm ) : + mrInStrm( rInStrm ), + mpCurrentData( 0 ), + mnHeaderPos( -1 ), + mnBodyPos( 0 ), + mnBufferBodyPos( 0 ), + mnNextHeaderPos( 0 ), + mnRecId( BIFF_ID_UNKNOWN ), + mnRecSize( 0 ), + mnRecPos( 0 ), + mbValidHeader( false ) +{ + OSL_ENSURE( mrInStrm.isSeekable(), "BiffInputRecordBuffer::BiffInputRecordBuffer - stream must be seekable" ); + mrInStrm.seekToStart(); + maOriginalData.reserve( SAL_MAX_UINT16 ); + maDecodedData.reserve( SAL_MAX_UINT16 ); + enableDecoder( false ); // updates mpCurrentData +} + +void BiffInputRecordBuffer::restartAt( sal_Int64 nPos ) +{ + mnHeaderPos = -1; + mnBodyPos = mnBufferBodyPos = 0; + mnNextHeaderPos = nPos; + mnRecId = BIFF_ID_UNKNOWN; + mnRecSize = mnRecPos = 0; + mbValidHeader = false; +} + +void BiffInputRecordBuffer::setDecoder( BiffDecoderRef xDecoder ) +{ + mxDecoder = xDecoder; + enableDecoder( true ); + updateDecoded(); +} + +void BiffInputRecordBuffer::enableDecoder( bool bEnable ) +{ + mpCurrentData = (bEnable && mxDecoder.get() && mxDecoder->isValid()) ? &maDecodedData : &maOriginalData; +} + +bool BiffInputRecordBuffer::startRecord( sal_Int64 nHeaderPos ) +{ + mbValidHeader = (0 <= nHeaderPos) && (nHeaderPos + 4 <= mrInStrm.getLength()); + if( mbValidHeader ) + { + mnHeaderPos = nHeaderPos; + mrInStrm.seek( nHeaderPos ); + mrInStrm >> mnRecId >> mnRecSize; + mnBodyPos = mrInStrm.tell(); + mnNextHeaderPos = mnBodyPos + mnRecSize; + mbValidHeader = mnNextHeaderPos <= mrInStrm.getLength(); + } + if( !mbValidHeader ) + { + mnHeaderPos = mnBodyPos = -1; + mnNextHeaderPos = 0; + mnRecId = BIFF_ID_UNKNOWN; + mnRecSize = 0; + } + mnRecPos = 0; + return mbValidHeader; +} + +bool BiffInputRecordBuffer::startNextRecord() +{ + return startRecord( mnNextHeaderPos ); +} + +sal_uInt16 BiffInputRecordBuffer::getNextRecId() +{ + sal_uInt16 nRecId = BIFF_ID_UNKNOWN; + if( mbValidHeader && (mnNextHeaderPos + 4 <= mrInStrm.getLength()) ) + { + mrInStrm.seek( mnNextHeaderPos ); + mrInStrm >> nRecId; + } + return nRecId; +} + +void BiffInputRecordBuffer::read( void* opData, sal_uInt16 nBytes ) +{ + updateBuffer(); + OSL_ENSURE( nBytes > 0, "BiffInputRecordBuffer::read - nothing to read" ); + OSL_ENSURE( nBytes <= getRecLeft(), "BiffInputRecordBuffer::read - buffer overflow" ); + memcpy( opData, &(*mpCurrentData)[ mnRecPos ], nBytes ); + mnRecPos = mnRecPos + nBytes; +} + +inline void BiffInputRecordBuffer::skip( sal_uInt16 nBytes ) +{ + OSL_ENSURE( nBytes > 0, "BiffInputRecordBuffer::skip - nothing to skip" ); + OSL_ENSURE( nBytes <= getRecLeft(), "BiffInputRecordBuffer::skip - buffer overflow" ); + mnRecPos = mnRecPos + nBytes; +} + +void BiffInputRecordBuffer::updateBuffer() +{ + OSL_ENSURE( mbValidHeader, "BiffInputRecordBuffer::updateBuffer - invalid access" ); + if( mnBodyPos != mnBufferBodyPos ) + { + mrInStrm.seek( mnBodyPos ); + maOriginalData.resize( mnRecSize ); + if( mnRecSize > 0 ) + mrInStrm.read( &maOriginalData.front(), static_cast< sal_Int32 >( mnRecSize ) ); + mnBufferBodyPos = mnBodyPos; + updateDecoded(); + } +} + +void BiffInputRecordBuffer::updateDecoded() +{ + if( mxDecoder.get() && mxDecoder->isValid() ) + { + maDecodedData.resize( mnRecSize ); + if( mnRecSize > 0 ) + mxDecoder->decode( &maDecodedData.front(), &maOriginalData.front(), mnBodyPos, mnRecSize ); + } +} + +} // namespace prv + +// ============================================================================ + +BiffInputStream::BiffInputStream( BinaryInputStream& rInStream, bool bContLookup ) : + maRecBuffer( rInStream ), + mnRecHandle( -1 ), + mnRecId( BIFF_ID_UNKNOWN ), + mnAltContId( BIFF_ID_UNKNOWN ), + mnCurrRecSize( 0 ), + mnComplRecSize( 0 ), + mbHasComplRec( false ), + mcNulSubst( BIFF_DEF_NUL_SUBST_CHAR ), + mbCont( bContLookup ), + mbValid( false ) +{ +} + +BiffInputStream::~BiffInputStream() +{ +} + +// record control ------------------------------------------------------------- + +bool BiffInputStream::startNextRecord() +{ + bool bValidRec = false; + /* #i4266# ignore zero records (id==len==0) (e.g. the application + "Crystal Report" writes zero records between other records) */ + bool bIsZeroRec = false; + do + { + // record header is never encrypted + maRecBuffer.enableDecoder( false ); + // read header of next raw record, returns false at end of stream + bValidRec = maRecBuffer.startNextRecord(); + // ignore record, if identifier and size are zero + bIsZeroRec = (maRecBuffer.getRecId() == 0) && (maRecBuffer.getRecSize() == 0); + } + while( bValidRec && ((mbCont && isContinueId( maRecBuffer.getRecId() )) || bIsZeroRec) ); + + // setup other class members + setupRecord(); + return isInRecord(); +} + +bool BiffInputStream::startRecordByHandle( sal_Int64 nRecHandle ) +{ + rewindToRecord( nRecHandle ); + return startNextRecord(); +} + +void BiffInputStream::resetRecord( bool bContLookup, sal_uInt16 nAltContId ) +{ + if( isInRecord() ) + { + mbCont = bContLookup; + mnAltContId = nAltContId; + restartRecord( true ); + maRecBuffer.enableDecoder( true ); + } +} + +void BiffInputStream::rewindRecord() +{ + rewindToRecord( mnRecHandle ); +} + +// decoder -------------------------------------------------------------------- + +void BiffInputStream::setDecoder( BiffDecoderRef xDecoder ) +{ + maRecBuffer.setDecoder( xDecoder ); +} + +BiffDecoderRef BiffInputStream::getDecoder() const +{ + return maRecBuffer.getDecoder(); +} + +void BiffInputStream::enableDecoder( bool bEnable ) +{ + maRecBuffer.enableDecoder( bEnable ); +} + +// stream/record state and info ----------------------------------------------- + +sal_uInt32 BiffInputStream::getRecPos() const +{ + return mbValid ? (mnCurrRecSize - maRecBuffer.getRecLeft()) : BIFF_REC_SEEK_TO_END; +} + +sal_uInt32 BiffInputStream::getRecSize() +{ + if( !mbHasComplRec ) + { + sal_uInt32 nCurrPos = getRecPos(); // save current position in record + while( jumpToNextContinue() ); // jumpToNextContinue() adds up mnCurrRecSize + mnComplRecSize = mnCurrRecSize; + mbHasComplRec = true; + seek( nCurrPos ); // restore position, seek() resets old mbValid state + } + return mnComplRecSize; +} + +sal_uInt32 BiffInputStream::getRecLeft() +{ + return mbValid ? (getRecSize() - getRecPos()) : 0; +} + +sal_uInt16 BiffInputStream::getNextRecId() +{ + sal_uInt16 nRecId = BIFF_ID_UNKNOWN; + if( isInRecord() ) + { + sal_uInt32 nCurrPos = getRecPos(); // save current position in record + while( jumpToNextContinue() ); // skip following CONTINUE records + if( maRecBuffer.startNextRecord() ) // read header of next record + nRecId = maRecBuffer.getRecId(); + seek( nCurrPos ); // restore position, seek() resets old mbValid state + } + return nRecId; +} + +sal_Int64 BiffInputStream::getCoreStreamPos() const +{ + return maRecBuffer.getCoreStream().tell(); +} + +sal_Int64 BiffInputStream::getCoreStreamSize() const +{ + return maRecBuffer.getCoreStream().getLength(); +} + +// stream read access --------------------------------------------------------- + +sal_uInt32 BiffInputStream::read( void* opData, sal_uInt32 nBytes ) +{ + sal_uInt32 nRet = 0; + if( mbValid && opData && (nBytes > 0) ) + { + sal_uInt8* pnBuffer = reinterpret_cast< sal_uInt8* >( opData ); + sal_uInt32 nBytesLeft = nBytes; + + while( mbValid && (nBytesLeft > 0) ) + { + sal_uInt16 nReadSize = getMaxRawReadSize( nBytesLeft ); + // check nReadSize, stream may already be located at end of a raw record + if( nReadSize > 0 ) + { + maRecBuffer.read( pnBuffer, nReadSize ); + nRet += nReadSize; + pnBuffer += nReadSize; + nBytesLeft -= nReadSize; + } + if( nBytesLeft > 0 ) + jumpToNextContinue(); + OSL_ENSURE( mbValid, "BiffInputStream::read - record overread" ); + } + } + return nRet; +} + +// seeking -------------------------------------------------------------------- + +BiffInputStream& BiffInputStream::seek( sal_uInt32 nRecPos ) +{ + if( isInRecord() ) + { + if( !mbValid || (nRecPos < getRecPos()) ) + restartRecord( false ); + if( mbValid && (nRecPos > getRecPos()) ) + skip( nRecPos - getRecPos() ); + } + return *this; +} + +BiffInputStream& BiffInputStream::skip( sal_uInt32 nBytes ) +{ + sal_uInt32 nBytesLeft = nBytes; + while( mbValid && (nBytesLeft > 0) ) + { + sal_uInt16 nSkipSize = getMaxRawReadSize( nBytesLeft ); + // check nSkipSize, stream may already be located at end of a raw record + if( nSkipSize > 0 ) + { + maRecBuffer.skip( nSkipSize ); + nBytesLeft -= nSkipSize; + } + if( nBytesLeft > 0 ) + jumpToNextContinue(); + OSL_ENSURE( mbValid, "BiffInputStream::skip - record overread" ); + } + return *this; +} + +// character arrays ----------------------------------------------------------- + +OString BiffInputStream::readCharArray( sal_uInt16 nChars ) +{ + ::std::vector< sal_Char > aBuffer( static_cast< size_t >( nChars ) + 1 ); + size_t nCharsRead = static_cast< size_t >( read( &aBuffer.front(), nChars ) ); + aBuffer[ nCharsRead ] = 0; + return OString( &aBuffer.front() ); +} + +OUString BiffInputStream::readCharArray( sal_uInt16 nChars, rtl_TextEncoding eTextEnc ) +{ + return OStringToOUString( readCharArray( nChars ), eTextEnc ); +} + +OUString BiffInputStream::readUnicodeArray( sal_uInt16 nChars ) +{ + ::std::vector< sal_Unicode > aBuffer; + aBuffer.reserve( static_cast< size_t >( nChars ) + 1 ); + sal_uInt16 nChar; + for( sal_uInt16 nCharIdx = 0; mbValid && (nCharIdx < nChars); ++nCharIdx ) + { + readValue( nChar ); + aBuffer.push_back( static_cast< sal_Unicode >( nChar ) ); + } + aBuffer.push_back( 0 ); + return OUString( &aBuffer.front() ); +} + +// byte strings --------------------------------------------------------------- + +OString BiffInputStream::readByteString( bool b16BitLen ) +{ + sal_uInt16 nStrLen = b16BitLen ? readuInt16() : readuInt8(); + return readCharArray( nStrLen ); +} + +OUString BiffInputStream::readByteString( bool b16BitLen, rtl_TextEncoding eTextEnc ) +{ + return OStringToOUString( readByteString( b16BitLen ), eTextEnc ); +} + +void BiffInputStream::skipByteString( bool b16BitLen ) +{ + skip( b16BitLen ? readuInt16() : readuInt8() ); +} + +// Unicode strings ------------------------------------------------------------ + +sal_uInt32 BiffInputStream::readExtendedUniStringHeader( + bool& rb16Bit, bool& rbFonts, bool& rbPhonetic, + sal_uInt16& rnFontCount, sal_uInt32& rnPhoneticSize, sal_uInt8 nFlags ) +{ + OSL_ENSURE( !getFlag( nFlags, BIFF_STRF_UNKNOWN ), "BiffInputStream::readExtendedUniStringHeader - unknown flags" ); + rb16Bit = getFlag( nFlags, BIFF_STRF_16BIT ); + rbFonts = getFlag( nFlags, BIFF_STRF_RICH ); + rbPhonetic = getFlag( nFlags, BIFF_STRF_PHONETIC ); + rnFontCount = 0; + if( rbFonts ) readValue( rnFontCount ); + rnPhoneticSize = 0; + if( rbPhonetic ) readValue( rnPhoneticSize ); + return rnPhoneticSize + 4 * rnFontCount; +} + +sal_uInt32 BiffInputStream::readExtendedUniStringHeader( bool& rb16Bit, sal_uInt8 nFlags ) +{ + bool bFonts, bPhonetic; + sal_uInt16 nFontCount; + sal_uInt32 nPhoneticSize; + return readExtendedUniStringHeader( rb16Bit, bFonts, bPhonetic, nFontCount, nPhoneticSize, nFlags ); +} + +OUString BiffInputStream::readRawUniString( sal_uInt16 nChars, bool b16Bit ) +{ + ::std::vector< sal_Unicode > aCharVec; + aCharVec.reserve( nChars + 1 ); + + /* This function has to react on CONTINUE records to reads the repeated + flags field, so readUnicodeArray() cannot be used here. */ + sal_uInt16 nCharsLeft = nChars; + while( isValid() && (nCharsLeft > 0) ) + { + sal_uInt16 nPortionCount = 0; + if( b16Bit ) + { + nPortionCount = ::std::min< sal_uInt16 >( nCharsLeft, maRecBuffer.getRecLeft() / 2 ); + OSL_ENSURE( (nPortionCount <= nCharsLeft) || ((maRecBuffer.getRecLeft() & 1) == 0), + "BiffInputStream::readRawUniString - missing a byte" ); + // read the character array + sal_uInt16 nReadChar; + for( sal_uInt16 nCharIdx = 0; isValid() && (nCharIdx < nPortionCount); ++nCharIdx ) + { + readValue( nReadChar ); + aCharVec.push_back( (nReadChar == 0) ? mcNulSubst : static_cast< sal_Unicode >( nReadChar ) ); + } + } + else + { + nPortionCount = getMaxRawReadSize( nCharsLeft ); + // read the character array + sal_uInt8 nReadChar; + for( sal_uInt16 nCharIdx = 0; isValid() && (nCharIdx < nPortionCount); ++nCharIdx ) + { + readValue( nReadChar ); + aCharVec.push_back( (nReadChar == 0) ? mcNulSubst : static_cast< sal_Unicode >( nReadChar ) ); + } + } + + // prepare for next CONTINUE record + nCharsLeft = nCharsLeft - nPortionCount; + if( nCharsLeft > 0 ) + jumpToNextStringContinue( b16Bit ); + } + + // string may contain embedded NUL characters, do not create the OUString by length of vector + aCharVec.push_back( 0 ); + return OUString( &aCharVec.front() ); +} + +OUString BiffInputStream::readUniString( sal_uInt16 nChars, sal_uInt8 nFlags ) +{ + bool b16Bit; + sal_uInt32 nExtSize = readExtendedUniStringHeader( b16Bit, nFlags ); + OUString aStr = readRawUniString( nChars, b16Bit ); + skip( nExtSize ); + return aStr; +} + +OUString BiffInputStream::readUniString( sal_uInt16 nChars ) +{ + return readUniString( nChars, readuInt8() ); +} + +OUString BiffInputStream::readUniString() +{ + return readUniString( readuInt16() ); +} + +void BiffInputStream::skipRawUniString( sal_uInt16 nChars, bool b16Bit ) +{ + sal_uInt16 nCharsLeft = nChars; + while( isValid() && (nCharsLeft > 0) ) + { + sal_uInt16 nPortionCount; + if( b16Bit ) + { + nPortionCount = ::std::min< sal_uInt16 >( nCharsLeft, maRecBuffer.getRecLeft() / 2 ); + OSL_ENSURE( (nPortionCount <= nCharsLeft) || ((maRecBuffer.getRecLeft() & 1) == 0), + "BiffInputStream::skipRawUniString - missing a byte" ); + skip( 2 * nPortionCount ); + } + else + { + nPortionCount = getMaxRawReadSize( nCharsLeft ); + skip( nPortionCount ); + } + + // prepare for next CONTINUE record + nCharsLeft = nCharsLeft - nPortionCount; + if( nCharsLeft > 0 ) + jumpToNextStringContinue( b16Bit ); + } +} + +void BiffInputStream::skipUniString( sal_uInt16 nChars, sal_uInt8 nFlags ) +{ + bool b16Bit; + sal_uInt32 nExtSize = readExtendedUniStringHeader( b16Bit, nFlags ); + skipRawUniString( nChars, b16Bit ); + skip( nExtSize ); +} + +void BiffInputStream::skipUniString( sal_uInt16 nChars ) +{ + skipUniString( nChars, readuInt8() ); +} + +void BiffInputStream::skipUniString() +{ + skipUniString( readuInt16() ); +} + +// private -------------------------------------------------------------------- + +void BiffInputStream::setupRecord() +{ + // initialize class members + mnRecHandle = maRecBuffer.getRecHeaderPos(); + mnRecId = maRecBuffer.getRecId(); + mnAltContId = BIFF_ID_UNKNOWN; + mnCurrRecSize = mnComplRecSize = maRecBuffer.getRecSize(); + mbHasComplRec = !mbCont; + mbValid = isInRecord(); + setNulSubstChar( BIFF_DEF_NUL_SUBST_CHAR ); + // enable decoder in new record + enableDecoder( true ); +} + +void BiffInputStream::restartRecord( bool bInvalidateRecSize ) +{ + if( isInRecord() ) + { + maRecBuffer.startRecord( getRecHandle() ); + mnCurrRecSize = maRecBuffer.getRecSize(); + if( bInvalidateRecSize ) + { + mnComplRecSize = mnCurrRecSize; + mbHasComplRec = !mbCont; + } + mbValid = true; + } +} + +void BiffInputStream::rewindToRecord( sal_Int64 nRecHandle ) +{ + if( nRecHandle >= 0 ) + { + maRecBuffer.restartAt( nRecHandle ); + mnRecHandle = -1; + mbValid = false; + } +} + +bool BiffInputStream::isContinueId( sal_uInt16 nRecId ) const +{ + return (nRecId == BIFF_ID_CONT) || (nRecId == mnAltContId); +} + +bool BiffInputStream::jumpToNextContinue() +{ + mbValid = mbValid && mbCont && isContinueId( maRecBuffer.getNextRecId() ) && maRecBuffer.startNextRecord(); + if( mbValid ) + mnCurrRecSize += maRecBuffer.getRecSize(); + return mbValid; +} + +bool BiffInputStream::jumpToNextStringContinue( bool& rb16Bit ) +{ + OSL_ENSURE( maRecBuffer.getRecLeft() == 0, "BiffInputStream::jumpToNextStringContinue - unexpected garbage" ); + + if( mbCont && (getRecLeft() > 0) ) + { + jumpToNextContinue(); + } + else if( mnRecId == BIFF_ID_CONT ) + { + /* CONTINUE handling is off, but we have started reading in a CONTINUE + record -> start next CONTINUE for TXO import. We really start a new + record here - no chance to return to string origin. */ + mbValid = mbValid && (maRecBuffer.getNextRecId() == BIFF_ID_CONT) && maRecBuffer.startNextRecord(); + if( mbValid ) + setupRecord(); + } + + // trying to read the flags invalidates stream, if no CONTINUE record has been found + sal_uInt8 nFlags; + readValue( nFlags ); + rb16Bit = getFlag( nFlags, BIFF_STRF_16BIT ); + return mbValid; +} + +bool BiffInputStream::ensureRawReadSize( sal_uInt16 nBytes ) +{ + if( mbValid && (nBytes > 0) ) + { + while( mbValid && (maRecBuffer.getRecLeft() == 0) ) jumpToNextContinue(); + mbValid = mbValid && (nBytes <= maRecBuffer.getRecLeft()); + OSL_ENSURE( mbValid, "BiffInputStream::ensureRawReadSize - record overread" ); + } + return mbValid; +} + +sal_uInt16 BiffInputStream::getMaxRawReadSize( sal_uInt32 nBytes ) const +{ + return static_cast< sal_uInt16 >( ::std::min< sal_uInt32 >( nBytes, maRecBuffer.getRecLeft() ) ); +} +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/biffoutputstream.cxx b/oox/source/xls/biffoutputstream.cxx new file mode 100644 index 000000000000..570b145931ce --- /dev/null +++ b/oox/source/xls/biffoutputstream.cxx @@ -0,0 +1,191 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: biffoutputstream.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:08 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/biffoutputstream.hxx" +#include "oox/helper/binaryoutputstream.hxx" + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace prv { + +BiffOutputRecordBuffer::BiffOutputRecordBuffer( BinaryOutputStream& rOutStrm, sal_uInt16 nMaxRecSize ) : + mrOutStrm( rOutStrm ), + mnMaxRecSize( nMaxRecSize ), + mnRecId( BIFF_ID_UNKNOWN ), + mbInRec( false ) +{ + OSL_ENSURE( mrOutStrm.isSeekable(), "BiffOutputRecordBuffer::BiffOutputRecordBuffer - stream must be seekable" ); + maData.reserve( SAL_MAX_UINT16 ); +} + +void BiffOutputRecordBuffer::startRecord( sal_uInt16 nRecId ) +{ + OSL_ENSURE( !mbInRec, "BiffOutputRecordBuffer::startRecord - another record still open" ); + mnRecId = nRecId; + maData.clear(); + mbInRec = true; +} + +void BiffOutputRecordBuffer::endRecord() +{ + OSL_ENSURE( mbInRec, "BiffOutputRecordBuffer::endRecord - no record open" ); + sal_uInt16 nRecSize = getLimitedValue< sal_uInt16, size_t >( maData.size(), 0, SAL_MAX_UINT16 ); + mrOutStrm.seekToEnd(); + mrOutStrm << mnRecId << nRecSize; + if( nRecSize > 0 ) + mrOutStrm.write( &maData.front(), nRecSize ); + mbInRec = false; +} + +void BiffOutputRecordBuffer::write( const void* pData, sal_uInt16 nBytes ) +{ + OSL_ENSURE( mbInRec, "BiffOutputRecordBuffer::write - no record open" ); + OSL_ENSURE( nBytes > 0, "BiffOutputRecordBuffer::write - nothing to write" ); + OSL_ENSURE( nBytes <= getRecLeft(), "BiffOutputRecordBuffer::write - buffer overflow" ); + maData.resize( maData.size() + nBytes ); + memcpy( &*(maData.end() - nBytes), pData, nBytes ); +} + +void BiffOutputRecordBuffer::fill( sal_uInt8 nValue, sal_uInt16 nBytes ) +{ + OSL_ENSURE( mbInRec, "BiffOutputRecordBuffer::write - no record open" ); + OSL_ENSURE( nBytes > 0, "BiffOutputRecordBuffer::write - nothing to write" ); + OSL_ENSURE( nBytes <= getRecLeft(), "BiffOutputRecordBuffer::write - buffer overflow" ); + maData.resize( maData.size() + nBytes, nValue ); +} + +} // namespace prv + +// ============================================================================ + +BiffOutputStream::BiffOutputStream( BinaryOutputStream& rOutStream, sal_uInt16 nMaxRecSize ) : + maRecBuffer( rOutStream, nMaxRecSize ), + mnPortionSize( 0 ), + mnPortionPos( 0 ) +{ +} + +BiffOutputStream::~BiffOutputStream() +{ +} + +// record control ------------------------------------------------------------- + +void BiffOutputStream::startRecord( sal_uInt16 nRecId ) +{ + maRecBuffer.startRecord( nRecId ); + setPortionSize( 0 ); +} + +void BiffOutputStream::endRecord() +{ + maRecBuffer.endRecord(); +} + +void BiffOutputStream::setPortionSize( sal_uInt16 nSize ) +{ + mnPortionSize = nSize; + mnPortionPos = 0; +} + +// stream/record state and info ----------------------------------------------- + +// stream write access -------------------------------------------------------- + +void BiffOutputStream::write( const void* pData, sal_uInt32 nBytes ) +{ + if( pData && (nBytes > 0) ) + { + const sal_uInt8* pnBuffer = reinterpret_cast< const sal_uInt8* >( pData ); + sal_uInt32 nBytesLeft = nBytes; + while( nBytesLeft > 0 ) + { + sal_uInt16 nBlockSize = prepareRawBlock( nBytesLeft ); + maRecBuffer.write( pnBuffer, nBlockSize ); + pnBuffer += nBlockSize; + nBytesLeft -= nBlockSize; + } + } +} + +void BiffOutputStream::fill( sal_uInt8 nValue, sal_uInt32 nBytes ) +{ + sal_uInt32 nBytesLeft = nBytes; + while( nBytesLeft > 0 ) + { + sal_uInt16 nBlockSize = prepareRawBlock( nBytesLeft ); + maRecBuffer.fill( nValue, nBlockSize ); + nBytesLeft -= nBlockSize; + } +} + +// private -------------------------------------------------------------------- + +void BiffOutputStream::ensureRawBlock( sal_uInt16 nSize ) +{ + if( (maRecBuffer.getRecLeft() < nSize) || + ((mnPortionSize > 0) && (mnPortionPos == 0) && (maRecBuffer.getRecLeft() < mnPortionSize)) ) + { + maRecBuffer.endRecord(); + maRecBuffer.startRecord( BIFF_ID_CONT ); + } + if( mnPortionSize > 0 ) + { + OSL_ENSURE( mnPortionPos + nSize <= mnPortionSize, "BiffOutputStreamI::ensureRawBlock - portion overflow" ); + mnPortionPos = (mnPortionPos + nSize) % mnPortionSize; // prevent compiler warning, do not use operator+=, operator%= + } +} + +sal_uInt16 BiffOutputStream::prepareRawBlock( sal_uInt32 nTotalSize ) +{ + sal_uInt16 nRecLeft = maRecBuffer.getRecLeft(); + if( mnPortionSize > 0 ) + { + OSL_ENSURE( mnPortionPos == 0, "BiffOutputStream::prepareRawBlock - block operation inside portion" ); + OSL_ENSURE( nTotalSize % mnPortionSize == 0, "BiffOutputStream::prepareRawBlock - portion size does not match block size" ); + nRecLeft = (nRecLeft / mnPortionSize) * mnPortionSize; + } + sal_uInt16 nSize = getLimitedValue< sal_uInt16, sal_uInt32 >( nTotalSize, 0, nRecLeft ); + ensureRawBlock( nSize ); + return nSize; +} +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/condformatbuffer.cxx b/oox/source/xls/condformatbuffer.cxx new file mode 100644 index 000000000000..f22910846d6c --- /dev/null +++ b/oox/source/xls/condformatbuffer.cxx @@ -0,0 +1,782 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: condformatbuffer.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:08 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/condformatbuffer.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "oox/helper/attributelist.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/helper/recordinputstream.hxx" +#include "oox/xls/addressconverter.hxx" +#include "oox/xls/biffinputstream.hxx" +#include "oox/xls/stylesbuffer.hxx" +#include "oox/xls/validationpropertyhelper.hxx" + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::beans::PropertyValue; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::style::XStyleFamiliesSupplier; +using ::com::sun::star::container::XNameAccess; +using ::com::sun::star::container::XIndexAccess; +using ::com::sun::star::container::XNameContainer; +using ::com::sun::star::table::CellAddress; +using ::com::sun::star::table::CellRangeAddress; +using ::com::sun::star::sheet::ConditionOperator; +using ::com::sun::star::table::XCellRange; +using ::com::sun::star::sheet::XSheetCellRanges; +using ::com::sun::star::sheet::XSheetConditionalEntries; +using ::com::sun::star::sheet::XSpreadsheetDocument; +using ::com::sun::star::sheet::XSpreadsheets; +using ::com::sun::star::sheet::XSpreadsheet; +using ::com::sun::star::style::XStyle; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +const sal_Int32 OOBIN_CFRULE_TYPE_CELLIS = 1; +const sal_Int32 OOBIN_CFRULE_TYPE_EXPRESSION = 2; +const sal_Int32 OOBIN_CFRULE_TYPE_COLORSCALE = 3; +const sal_Int32 OOBIN_CFRULE_TYPE_DATABAR = 4; +const sal_Int32 OOBIN_CFRULE_TYPE_TOPTEN = 5; +const sal_Int32 OOBIN_CFRULE_TYPE_ICONSET = 6; + +const sal_Int32 OOBIN_CFRULE_SUB_CELLIS = 0; +const sal_Int32 OOBIN_CFRULE_SUB_EXPRESSION = 1; +const sal_Int32 OOBIN_CFRULE_SUB_COLORSCALE = 2; +const sal_Int32 OOBIN_CFRULE_SUB_DATABAR = 3; +const sal_Int32 OOBIN_CFRULE_SUB_ICONSET = 4; +const sal_Int32 OOBIN_CFRULE_SUB_TOPTEN = 5; +const sal_Int32 OOBIN_CFRULE_SUB_UNIQUE = 7; +const sal_Int32 OOBIN_CFRULE_SUB_TEXT = 8; +const sal_Int32 OOBIN_CFRULE_SUB_BLANK = 9; +const sal_Int32 OOBIN_CFRULE_SUB_NOTBLANK = 10; +const sal_Int32 OOBIN_CFRULE_SUB_ERROR = 11; +const sal_Int32 OOBIN_CFRULE_SUB_NOTERROR = 12; +const sal_Int32 OOBIN_CFRULE_SUB_TODAY = 15; +const sal_Int32 OOBIN_CFRULE_SUB_TOMORROW = 16; +const sal_Int32 OOBIN_CFRULE_SUB_YESTERDAY = 17; +const sal_Int32 OOBIN_CFRULE_SUB_LAST7DAYS = 18; +const sal_Int32 OOBIN_CFRULE_SUB_LASTMONTH = 19; +const sal_Int32 OOBIN_CFRULE_SUB_NEXTMONTH = 20; +const sal_Int32 OOBIN_CFRULE_SUB_THISWEEK = 21; +const sal_Int32 OOBIN_CFRULE_SUB_NEXTWEEK = 22; +const sal_Int32 OOBIN_CFRULE_SUB_LASTWEEK = 23; +const sal_Int32 OOBIN_CFRULE_SUB_THISMONTH = 24; +const sal_Int32 OOBIN_CFRULE_SUB_ABOVEAVERAGE = 25; +const sal_Int32 OOBIN_CFRULE_SUB_BELOWAVERAGE = 26; +const sal_Int32 OOBIN_CFRULE_SUB_DUPLICATE = 27; +const sal_Int32 OOBIN_CFRULE_SUB_EQABOVEAVERAGE = 29; +const sal_Int32 OOBIN_CFRULE_SUB_EQBELOWAVERAGE = 30; + +const sal_Int32 OOBIN_CFRULE_TIMEOP_TODAY = 0; +const sal_Int32 OOBIN_CFRULE_TIMEOP_YESTERDAY = 1; +const sal_Int32 OOBIN_CFRULE_TIMEOP_LAST7DAYS = 2; +const sal_Int32 OOBIN_CFRULE_TIMEOP_THISWEEK = 3; +const sal_Int32 OOBIN_CFRULE_TIMEOP_LASTWEEK = 4; +const sal_Int32 OOBIN_CFRULE_TIMEOP_LASTMONTH = 5; +const sal_Int32 OOBIN_CFRULE_TIMEOP_TOMORROW = 6; +const sal_Int32 OOBIN_CFRULE_TIMEOP_NEXTWEEK = 7; +const sal_Int32 OOBIN_CFRULE_TIMEOP_NEXTMONTH = 8; +const sal_Int32 OOBIN_CFRULE_TIMEOP_THISMONTH = 9; + +const sal_uInt16 OOBIN_CFRULE_STOPIFTRUE = 0x0002; +const sal_uInt16 OOBIN_CFRULE_ABOVEAVERAGE = 0x0004; +const sal_uInt16 OOBIN_CFRULE_BOTTOM = 0x0008; +const sal_uInt16 OOBIN_CFRULE_PERCENT = 0x0010; + +// ---------------------------------------------------------------------------- + +template< typename Type > +void lclAppendProperty( ::std::vector< PropertyValue >& orProps, const OUString& rPropName, const Type& rValue ) +{ + orProps.push_back( PropertyValue() ); + orProps.back().Name = rPropName; + orProps.back().Value <<= rValue; +} + +} // namespace + +// ============================================================================ + +OoxCondFormatRuleData::OoxCondFormatRuleData() : + mnPriority( -1 ), + mnType( XML_TOKEN_INVALID ), + mnOperator( XML_TOKEN_INVALID ), + mnTimePeriod( XML_TOKEN_INVALID ), + mnRank( 0 ), + mnStdDev( 0 ), + mnDxfId( -1 ), + mbStopIfTrue( false ), + mbBottom( false ), + mbPercent( false ), + mbAboveAverage( true ), + mbEqualAverage( false ) +{ +} + +void OoxCondFormatRuleData::setBinOperator( sal_Int32 nOperator ) +{ + static const sal_Int32 spnOperators[] = { + XML_TOKEN_INVALID, XML_between, XML_notBetween, XML_equal, XML_notEqual, + XML_greaterThan, XML_lessThan, XML_greaterThanOrEqual, XML_lessThanOrEqual }; + mnOperator = STATIC_ARRAY_SELECT( spnOperators, nOperator, XML_TOKEN_INVALID ); +} + +void OoxCondFormatRuleData::setOobTextType( sal_Int32 nOperator ) +{ + // note: type XML_notContainsText vs. operator XML_notContains + static const sal_Int32 spnTypes[] = { XML_containsText, XML_notContainsText, XML_beginsWith, XML_endsWith }; + mnType = STATIC_ARRAY_SELECT( spnTypes, nOperator, XML_TOKEN_INVALID ); + static const sal_Int32 spnOperators[] = { XML_containsText, XML_notContains, XML_beginsWith, XML_endsWith }; + mnOperator = STATIC_ARRAY_SELECT( spnOperators, nOperator, XML_TOKEN_INVALID ); +} + +// ============================================================================ + +CondFormatRule::CondFormatRule( const CondFormat& rCondFormat ) : + WorksheetHelper( rCondFormat ), + mrCondFormat( rCondFormat ) +{ +} + +void CondFormatRule::importCfRule( const AttributeList& rAttribs ) +{ + maOoxData.maText = rAttribs.getString( XML_text ); + maOoxData.mnPriority = rAttribs.getInteger( XML_priority, -1 ); + maOoxData.mnType = rAttribs.getToken( XML_type, XML_TOKEN_INVALID ); + maOoxData.mnOperator = rAttribs.getToken( XML_operator, XML_TOKEN_INVALID ); + maOoxData.mnTimePeriod = rAttribs.getToken( XML_timePeriod, XML_TOKEN_INVALID ); + maOoxData.mnRank = rAttribs.getInteger( XML_rank, 0 ); + maOoxData.mnStdDev = rAttribs.getInteger( XML_stdDev, 0 ); + maOoxData.mnDxfId = rAttribs.getInteger( XML_dxfId, -1 ); + maOoxData.mbStopIfTrue = rAttribs.getBool( XML_stopIfTrue, false ); + maOoxData.mbBottom = rAttribs.getBool( XML_bottom, false ); + maOoxData.mbPercent = rAttribs.getBool( XML_percent, false ); + maOoxData.mbAboveAverage = rAttribs.getBool( XML_aboveAverage, true ); + maOoxData.mbEqualAverage = rAttribs.getBool( XML_equalAverage, false ); +} + +void CondFormatRule::appendFormula( const OUString& rFormula ) +{ + TokensFormulaContext aContext( true, false ); + aContext.setBaseAddress( mrCondFormat.getRanges().getBaseAddress() ); + getFormulaParser().importFormula( aContext, rFormula ); + maOoxData.maFormulas.push_back( aContext ); +} + +void CondFormatRule::importCfRule( RecordInputStream& rStrm ) +{ + sal_Int32 nType, nSubType, nOperator, nFmla1Size, nFmla2Size, nFmla3Size; + sal_uInt16 nFlags; + rStrm >> nType >> nSubType >> maOoxData.mnDxfId >> maOoxData.mnPriority >> nOperator; + rStrm.skip( 8 ); + rStrm >> nFlags >> nFmla1Size >> nFmla2Size >> nFmla3Size >> maOoxData.maText; + + /* Import the formulas. For no obvious reason, the sizes of the formulas + are already stored before. Nevertheless the following formulas contain + their own sizes. */ + + // first formula + OSL_ENSURE( (nFmla1Size >= 0) || ((nFmla2Size == 0) && (nFmla3Size == 0)), "CondFormatRule::importCfRule - missing first formula" ); + OSL_ENSURE( (nFmla1Size > 0) == (rStrm.getRecLeft() >= 8), "CondFormatRule::importCfRule - formula size mismatch" ); + if( rStrm.getRecLeft() >= 8 ) + { + TokensFormulaContext aContext( true, false ); + aContext.setBaseAddress( mrCondFormat.getRanges().getBaseAddress() ); + getFormulaParser().importFormula( aContext, rStrm ); + maOoxData.maFormulas.push_back( aContext ); + + // second formula + OSL_ENSURE( (nFmla2Size >= 0) || (nFmla3Size == 0), "CondFormatRule::importCfRule - missing second formula" ); + OSL_ENSURE( (nFmla2Size > 0) == (rStrm.getRecLeft() >= 8), "CondFormatRule::importCfRule - formula size mismatch" ); + if( rStrm.getRecLeft() >= 8 ) + { + getFormulaParser().importFormula( aContext, rStrm ); + maOoxData.maFormulas.push_back( aContext ); + + // third formula + OSL_ENSURE( (nFmla3Size > 0) == (rStrm.getRecLeft() >= 8), "CondFormatRule::importCfRule - formula size mismatch" ); + if( rStrm.getRecLeft() >= 8 ) + { + getFormulaParser().importFormula( aContext, rStrm ); + maOoxData.maFormulas.push_back( aContext ); + } + } + } + + // flags + maOoxData.mbStopIfTrue = getFlag( nFlags, OOBIN_CFRULE_STOPIFTRUE ); + maOoxData.mbBottom = getFlag( nFlags, OOBIN_CFRULE_BOTTOM ); + maOoxData.mbPercent = getFlag( nFlags, OOBIN_CFRULE_PERCENT ); + maOoxData.mbAboveAverage = getFlag( nFlags, OOBIN_CFRULE_ABOVEAVERAGE ); + // no flag for equalAverage, must be determined from subtype below... + + // Convert the type/operator settings. This is a real mess... + switch( nType ) + { + case OOBIN_CFRULE_TYPE_CELLIS: + OSL_ENSURE( nSubType == OOBIN_CFRULE_SUB_CELLIS, "CondFormatRule::importCfRule - rule type/subtype mismatch" ); + maOoxData.mnType = XML_cellIs; + maOoxData.setBinOperator( nOperator ); + OSL_ENSURE( maOoxData.mnOperator != XML_TOKEN_INVALID, "CondFormatRule::importCfRule - unknown operator" ); + break; + case OOBIN_CFRULE_TYPE_EXPRESSION: + // here we have to look at the subtype to find the real type... + switch( nSubType ) + { + case OOBIN_CFRULE_SUB_EXPRESSION: + OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" ); + maOoxData.mnType = XML_expression; + break; + case OOBIN_CFRULE_SUB_UNIQUE: + OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" ); + maOoxData.mnType = XML_uniqueValues; + break; + case OOBIN_CFRULE_SUB_TEXT: + maOoxData.setOobTextType( nOperator ); + OSL_ENSURE( maOoxData.mnType != XML_TOKEN_INVALID, "CondFormatRule::importCfRule - unexpected operator value" ); + break; + case OOBIN_CFRULE_SUB_BLANK: + OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" ); + maOoxData.mnType = XML_containsBlanks; + break; + case OOBIN_CFRULE_SUB_NOTBLANK: + OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" ); + maOoxData.mnType = XML_notContainsBlanks; + break; + case OOBIN_CFRULE_SUB_ERROR: + OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" ); + maOoxData.mnType = XML_containsErrors; + break; + case OOBIN_CFRULE_SUB_NOTERROR: + OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" ); + maOoxData.mnType = XML_notContainsErrors; + break; + case OOBIN_CFRULE_SUB_TODAY: + OSL_ENSURE( nOperator == OOBIN_CFRULE_TIMEOP_TODAY, "CondFormatRule::importCfRule - unexpected time operator value" ); + maOoxData.mnType = XML_timePeriod; + maOoxData.mnTimePeriod = XML_today; + break; + case OOBIN_CFRULE_SUB_TOMORROW: + OSL_ENSURE( nOperator == OOBIN_CFRULE_TIMEOP_TOMORROW, "CondFormatRule::importCfRule - unexpected time operator value" ); + maOoxData.mnType = XML_timePeriod; + maOoxData.mnTimePeriod = XML_tomorrow; + break; + case OOBIN_CFRULE_SUB_YESTERDAY: + OSL_ENSURE( nOperator == OOBIN_CFRULE_TIMEOP_YESTERDAY, "CondFormatRule::importCfRule - unexpected time operator value" ); + maOoxData.mnType = XML_timePeriod; + maOoxData.mnTimePeriod = XML_yesterday; + break; + case OOBIN_CFRULE_SUB_LAST7DAYS: + OSL_ENSURE( nOperator == OOBIN_CFRULE_TIMEOP_LAST7DAYS, "CondFormatRule::importCfRule - unexpected time operator value" ); + maOoxData.mnType = XML_timePeriod; + maOoxData.mnTimePeriod = XML_last7Days; + break; + case OOBIN_CFRULE_SUB_LASTMONTH: + OSL_ENSURE( nOperator == OOBIN_CFRULE_TIMEOP_LASTMONTH, "CondFormatRule::importCfRule - unexpected time operator value" ); + maOoxData.mnType = XML_timePeriod; + maOoxData.mnTimePeriod = XML_lastMonth; + break; + case OOBIN_CFRULE_SUB_NEXTMONTH: + OSL_ENSURE( nOperator == OOBIN_CFRULE_TIMEOP_NEXTMONTH, "CondFormatRule::importCfRule - unexpected time operator value" ); + maOoxData.mnType = XML_timePeriod; + maOoxData.mnTimePeriod = XML_nextMonth; + break; + case OOBIN_CFRULE_SUB_THISWEEK: + OSL_ENSURE( nOperator == OOBIN_CFRULE_TIMEOP_THISWEEK, "CondFormatRule::importCfRule - unexpected time operator value" ); + maOoxData.mnType = XML_timePeriod; + maOoxData.mnTimePeriod = XML_thisWeek; + break; + case OOBIN_CFRULE_SUB_NEXTWEEK: + OSL_ENSURE( nOperator == OOBIN_CFRULE_TIMEOP_NEXTWEEK, "CondFormatRule::importCfRule - unexpected time operator value" ); + maOoxData.mnType = XML_timePeriod; + maOoxData.mnTimePeriod = XML_nextWeek; + break; + case OOBIN_CFRULE_SUB_LASTWEEK: + OSL_ENSURE( nOperator == OOBIN_CFRULE_TIMEOP_LASTWEEK, "CondFormatRule::importCfRule - unexpected time operator value" ); + maOoxData.mnType = XML_timePeriod; + maOoxData.mnTimePeriod = XML_lastWeek; + break; + case OOBIN_CFRULE_SUB_THISMONTH: + OSL_ENSURE( nOperator == OOBIN_CFRULE_TIMEOP_THISMONTH, "CondFormatRule::importCfRule - unexpected time operator value" ); + maOoxData.mnType = XML_timePeriod; + maOoxData.mnTimePeriod = XML_thisMonth; + break; + case OOBIN_CFRULE_SUB_ABOVEAVERAGE: + OSL_ENSURE( maOoxData.mbAboveAverage, "CondFormatRule::importCfRule - wrong above-average flag" ); + maOoxData.mnType = XML_aboveAverage; + maOoxData.mnStdDev = nOperator; // operator field used for standard deviation + maOoxData.mbAboveAverage = true; + maOoxData.mbEqualAverage = false; // does not exist as real flag... + break; + case OOBIN_CFRULE_SUB_BELOWAVERAGE: + OSL_ENSURE( !maOoxData.mbAboveAverage, "CondFormatRule::importCfRule - wrong above-average flag" ); + maOoxData.mnType = XML_aboveAverage; + maOoxData.mnStdDev = nOperator; // operator field used for standard deviation + maOoxData.mbAboveAverage = false; + maOoxData.mbEqualAverage = false; // does not exist as real flag... + break; + case OOBIN_CFRULE_SUB_DUPLICATE: + OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" ); + maOoxData.mnType = XML_duplicateValues; + break; + case OOBIN_CFRULE_SUB_EQABOVEAVERAGE: + OSL_ENSURE( maOoxData.mbAboveAverage, "CondFormatRule::importCfRule - wrong above-average flag" ); + maOoxData.mnType = XML_aboveAverage; + maOoxData.mnStdDev = nOperator; // operator field used for standard deviation + maOoxData.mbAboveAverage = true; + maOoxData.mbEqualAverage = true; // does not exist as real flag... + break; + case OOBIN_CFRULE_SUB_EQBELOWAVERAGE: + OSL_ENSURE( !maOoxData.mbAboveAverage, "CondFormatRule::importCfRule - wrong above-average flag" ); + maOoxData.mnType = XML_aboveAverage; + maOoxData.mnStdDev = nOperator; // operator field used for standard deviation + maOoxData.mbAboveAverage = false; + maOoxData.mbEqualAverage = true; // does not exist as real flag... + break; + } + break; + case OOBIN_CFRULE_TYPE_COLORSCALE: + OSL_ENSURE( nSubType == OOBIN_CFRULE_SUB_COLORSCALE, "CondFormatRule::importCfRule - rule type/subtype mismatch" ); + OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" ); + maOoxData.mnType = XML_colorScale; + break; + case OOBIN_CFRULE_TYPE_DATABAR: + OSL_ENSURE( nSubType == OOBIN_CFRULE_SUB_DATABAR, "CondFormatRule::importCfRule - rule type/subtype mismatch" ); + OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" ); + maOoxData.mnType = XML_dataBar; + break; + case OOBIN_CFRULE_TYPE_TOPTEN: + OSL_ENSURE( nSubType == OOBIN_CFRULE_SUB_TOPTEN, "CondFormatRule::importCfRule - rule type/subtype mismatch" ); + maOoxData.mnType = XML_top10; + maOoxData.mnRank = nOperator; // operator field used for rank value + break; + case OOBIN_CFRULE_TYPE_ICONSET: + OSL_ENSURE( nSubType == OOBIN_CFRULE_SUB_ICONSET, "CondFormatRule::importCfRule - rule type/subtype mismatch" ); + OSL_ENSURE( nOperator == 0, "CondFormatRule::importCfRule - unexpected operator value" ); + maOoxData.mnType = XML_iconSet; + break; + default: + OSL_ENSURE( false, "CondFormatRule::importCfRule - unknown rule type" ); + } +} + +void CondFormatRule::importCfRule( BiffInputStream& rStrm, sal_Int32 nPriority ) +{ + sal_uInt8 nType, nOperator; + sal_uInt16 nFmla1Size, nFmla2Size; + sal_uInt32 nFlags; + rStrm >> nType >> nOperator >> nFmla1Size >> nFmla2Size >> nFlags; + rStrm.skip( 2 ); + + static const sal_Int32 spnTypeIds[] = { XML_TOKEN_INVALID, XML_cellIs, XML_expression }; + maOoxData.mnType = STATIC_ARRAY_SELECT( spnTypeIds, nType, XML_TOKEN_INVALID ); + + maOoxData.setBinOperator( nOperator ); + maOoxData.mnPriority = nPriority; + maOoxData.mbStopIfTrue = true; + + DxfRef xDxf = getStyles().createDxf( &maOoxData.mnDxfId ); + xDxf->importCfRule( rStrm, nFlags ); + xDxf->finalizeImport(); + + // import the formulas + OSL_ENSURE( (nFmla1Size > 0) || (nFmla2Size == 0), "CondFormatRule::importCfRule - missing first formula" ); + if( nFmla1Size > 0 ) + { + TokensFormulaContext aContext( true, false ); + aContext.setBaseAddress( mrCondFormat.getRanges().getBaseAddress() ); + getFormulaParser().importFormula( aContext, rStrm, &nFmla1Size ); + maOoxData.maFormulas.push_back( aContext ); + if( nFmla2Size > 0 ) + { + getFormulaParser().importFormula( aContext, rStrm, &nFmla2Size ); + maOoxData.maFormulas.push_back( aContext ); + } + } +} + +void CondFormatRule::finalizeImport( const Reference< XSheetConditionalEntries >& rxEntries ) +{ + ConditionOperator eOperator = ::com::sun::star::sheet::ConditionOperator_NONE; + + /* Replacement formula for unsupported rule types (text comparison rules, + time period rules, cell type rules). The replacement formulas below may + contain several placeholders: + - '#B' will be replaced by the current base address (may occur + several times). + - '#R' will be replaced by the entire range list of the conditional + formatting (absolute addresses). + - '#T' will be replaced by the quoted comparison text. + - '#L' will be replaced by the length of the comparison text (from + the 'text' attribute) used in text comparison rules. + - '#K' will be replaced by the rank (from the 'rank' attribute) used in + top-10 rules. + - '#M' will be replaced by the top/bottom flag (from the 'bottom' + attribute) used in the RANK function in top-10 rules. + */ + OUString aReplaceFormula; + + switch( maOoxData.mnType ) + { + case XML_cellIs: + eOperator = ValidationPropertyHelper::convertToApiOperator( maOoxData.mnOperator ); + break; + case XML_expression: + eOperator = ::com::sun::star::sheet::ConditionOperator_FORMULA; + break; + case XML_containsText: + OSL_ENSURE( maOoxData.mnOperator == XML_containsText, "CondFormatRule::finalizeImport - unexpected operator" ); + aReplaceFormula = CREATE_OUSTRING( "NOT(ISERROR(SEARCH(#T,#B)))" ); + break; + case XML_notContainsText: + // note: type XML_notContainsText vs. operator XML_notContains + OSL_ENSURE( maOoxData.mnOperator == XML_notContains, "CondFormatRule::finalizeImport - unexpected operator" ); + aReplaceFormula = CREATE_OUSTRING( "ISERROR(SEARCH(#T,#B))" ); + break; + case XML_beginsWith: + OSL_ENSURE( maOoxData.mnOperator == XML_beginsWith, "CondFormatRule::finalizeImport - unexpected operator" ); + aReplaceFormula = CREATE_OUSTRING( "LEFT(#B,#L)=#T" ); + break; + case XML_endsWith: + OSL_ENSURE( maOoxData.mnOperator == XML_endsWith, "CondFormatRule::finalizeImport - unexpected operator" ); + aReplaceFormula = CREATE_OUSTRING( "RIGHT(#B,#L)=#T" ); + break; + case XML_timePeriod: + switch( maOoxData.mnTimePeriod ) + { + case XML_yesterday: + aReplaceFormula = CREATE_OUSTRING( "FLOOR(#B,1)=TODAY()-1" ); + break; + case XML_today: + aReplaceFormula = CREATE_OUSTRING( "FLOOR(#B,1)=TODAY()" ); + break; + case XML_tomorrow: + aReplaceFormula = CREATE_OUSTRING( "FLOOR(#B,1)=TODAY()+1" ); + break; + case XML_last7Days: + aReplaceFormula = CREATE_OUSTRING( "AND(TODAY()-70" ); + break; + case XML_containsErrors: + aReplaceFormula = CREATE_OUSTRING( "ISERROR(#B)" ); + break; + case XML_notContainsErrors: + aReplaceFormula = CREATE_OUSTRING( "NOT(ISERROR(#B))" ); + break; + case XML_top10: + if( maOoxData.mbPercent ) + aReplaceFormula = CREATE_OUSTRING( "RANK(#B,#R,#M)/COUNT(#R)<=#K%" ); + else + aReplaceFormula = CREATE_OUSTRING( "RANK(#B,#R,#M)<=#K" ); + break; + case XML_aboveAverage: + if( maOoxData.mnStdDev == 0 ) + { + if( maOoxData.mbAboveAverage ) + aReplaceFormula = maOoxData.mbEqualAverage ? CREATE_OUSTRING( "#B>=AVERAGE(#R)" ) : CREATE_OUSTRING( "#B>AVERAGE(#R)" ); + else + aReplaceFormula = maOoxData.mbEqualAverage ? CREATE_OUSTRING( "#B<=AVERAGE(#R)" ) : CREATE_OUSTRING( "#B 0 ) + { + OUString aAddress, aRanges, aText; + sal_Int32 nStrPos = aReplaceFormula.getLength(); + while( (nStrPos = aReplaceFormula.lastIndexOf( '#', nStrPos )) >= 0 ) + { + switch( aReplaceFormula[ nStrPos + 1 ] ) + { + case 'B': // current base address + if( aAddress.getLength() == 0 ) + aAddress = FormulaProcessorBase::generateAddress2dString( mrCondFormat.getRanges().getBaseAddress(), false ); + aReplaceFormula = aReplaceFormula.replaceAt( nStrPos, 2, aAddress ); + break; + case 'R': // range list of conditional formatting + if( aRanges.getLength() == 0 ) + aRanges = FormulaProcessorBase::generateRangeList2dString( mrCondFormat.getRanges(), true, ',', true ); + aReplaceFormula = aReplaceFormula.replaceAt( nStrPos, 2, aRanges ); + break; + case 'T': // comparison text + if( aText.getLength() == 0 ) + { + // handle quote characters in comparison text + aText = maOoxData.maText; + sal_Int32 nQuotePos = aText.getLength(); + while( (nQuotePos = aText.lastIndexOf( '"', nQuotePos )) >= 0 ) + aText = aText.replaceAt( nQuotePos, 1, CREATE_OUSTRING( "\"\"" ) ); + aText = OUStringBuffer().append( sal_Unicode( '"' ) ).append( aText ).append( sal_Unicode( '"' ) ).makeStringAndClear(); + } + aReplaceFormula = aReplaceFormula.replaceAt( nStrPos, 2, aText ); + break; + case 'L': // length of comparison text + aReplaceFormula = aReplaceFormula.replaceAt( nStrPos, 2, + OUString::valueOf( maOoxData.maText.getLength() ) ); + break; + case 'K': // top-10 rank + aReplaceFormula = aReplaceFormula.replaceAt( nStrPos, 2, + OUString::valueOf( maOoxData.mnRank ) ); + break; + case 'M': // top-10 top/bottom flag + aReplaceFormula = aReplaceFormula.replaceAt( nStrPos, 2, + OUString::valueOf( static_cast< sal_Int32 >( maOoxData.mbBottom ? 1 : 0 ) ) ); + break; + default: + OSL_ENSURE( false, "CondFormatRule::finalizeImport - unknown placeholder" ); + } + } + + // set the replacement formula + maOoxData.maFormulas.clear(); + appendFormula( aReplaceFormula ); + eOperator = ::com::sun::star::sheet::ConditionOperator_FORMULA; + } + + if( rxEntries.is() && (eOperator != ::com::sun::star::sheet::ConditionOperator_NONE) && !maOoxData.maFormulas.empty() ) + { + ::std::vector< PropertyValue > aProps; + // create condition properties + lclAppendProperty( aProps, CREATE_OUSTRING( "Operator" ), eOperator ); + lclAppendProperty( aProps, CREATE_OUSTRING( "Formula1" ), maOoxData.maFormulas[ 0 ].getTokens() ); + if( maOoxData.maFormulas.size() >= 2 ) + lclAppendProperty( aProps, CREATE_OUSTRING( "Formula2" ), maOoxData.maFormulas[ 1 ].getTokens() ); + + // style name for the formatting attributes + OUString aStyleName = getStyles().createDxfStyle( maOoxData.mnDxfId ); + if( aStyleName.getLength() > 0 ) + lclAppendProperty( aProps, CREATE_OUSTRING( "StyleName" ), aStyleName ); + + // append the new rule + try + { + rxEntries->addNew( ContainerHelper::vectorToSequence( aProps ) ); + } + catch( Exception& ) + { + } + } +} + +// ============================================================================ + +OoxCondFormatData::OoxCondFormatData() : + mbPivot( false ) +{ +} + +// ============================================================================ + +CondFormat::CondFormat( const WorksheetHelper& rHelper ) : + WorksheetHelper( rHelper ) +{ +} + +void CondFormat::importConditionalFormatting( const AttributeList& rAttribs ) +{ + getAddressConverter().convertToCellRangeList( maOoxData.maRanges, rAttribs.getString( XML_sqref ), getSheetIndex(), true ); + maOoxData.mbPivot = rAttribs.getBool( XML_pivot, false ); +} + +CondFormatRuleRef CondFormat::importCfRule( const AttributeList& rAttribs ) +{ + CondFormatRuleRef xRule = createRule(); + xRule->importCfRule( rAttribs ); + insertRule( xRule ); + return xRule; +} + +void CondFormat::importCondFormatting( RecordInputStream& rStrm ) +{ + BinRangeList aRanges; + rStrm.skip( 8 ); + rStrm >> aRanges; + getAddressConverter().convertToCellRangeList( maOoxData.maRanges, aRanges, getSheetIndex(), true ); +} + +void CondFormat::importCfRule( RecordInputStream& rStrm ) +{ + CondFormatRuleRef xRule = createRule(); + xRule->importCfRule( rStrm ); + insertRule( xRule ); +} + +void CondFormat::importCfHeader( BiffInputStream& rStrm ) +{ + // import the CFHEADER record + sal_uInt16 nRuleCount; + BinRangeList aRanges; + rStrm >> nRuleCount; + rStrm.skip( 10 ); + rStrm >> aRanges; + getAddressConverter().convertToCellRangeList( maOoxData.maRanges, aRanges, getSheetIndex(), true ); + + // import following list of CFRULE records + for( sal_uInt16 nRule = 0; (nRule < nRuleCount) && (rStrm.getNextRecId() == BIFF_ID_CFRULE) && rStrm.startNextRecord(); ++nRule ) + { + CondFormatRuleRef xRule = createRule(); + xRule->importCfRule( rStrm, nRule + 1 ); + insertRule( xRule ); + } +} + +void CondFormat::finalizeImport() +{ + Reference< XSheetCellRanges > xRanges = getCellRangeList( maOoxData.maRanges ); + if( xRanges.is() ) + { + PropertySet aPropSet( xRanges ); + Reference< XSheetConditionalEntries > xEntries; + aPropSet.getProperty( xEntries, CREATE_OUSTRING( "ConditionalFormat" ) ); + if( xEntries.is() ) + { + // maRules is sorted by rule priority + maRules.forEachMem( &CondFormatRule::finalizeImport, xEntries ); + aPropSet.setProperty( CREATE_OUSTRING( "ConditionalFormat" ), xEntries ); + } + } +} + +CondFormatRuleRef CondFormat::createRule() +{ + return CondFormatRuleRef( new CondFormatRule( *this ) ); +} + +void CondFormat::insertRule( CondFormatRuleRef xRule ) +{ + if( xRule.get() && (xRule->getPriority() > 0) ) + { + OSL_ENSURE( maRules.find( xRule->getPriority() ) == maRules.end(), "CondFormat::insertRule - multiple rules with equal priority" ); + maRules[ xRule->getPriority() ] = xRule; + } +} + +// ============================================================================ + +CondFormatBuffer::CondFormatBuffer( const WorksheetHelper& rHelper ) : + WorksheetHelper( rHelper ) +{ +} + +CondFormatRef CondFormatBuffer::importConditionalFormatting( const AttributeList& rAttribs ) +{ + CondFormatRef xCondFmt = createCondFormat(); + xCondFmt->importConditionalFormatting( rAttribs ); + return xCondFmt; +} + +CondFormatRef CondFormatBuffer::importCondFormatting( RecordInputStream& rStrm ) +{ + CondFormatRef xCondFmt = createCondFormat(); + xCondFmt->importCondFormatting( rStrm ); + return xCondFmt; +} + +void CondFormatBuffer::importCfHeader( BiffInputStream& rStrm ) +{ + createCondFormat()->importCfHeader( rStrm ); +} + +void CondFormatBuffer::finalizeImport() +{ + maCondFormats.forEachMem( &CondFormat::finalizeImport ); +} + +// private -------------------------------------------------------------------- + +CondFormatRef CondFormatBuffer::createCondFormat() +{ + CondFormatRef xCondFmt( new CondFormat( *this ) ); + maCondFormats.push_back( xCondFmt ); + return xCondFmt; +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/condformatcontext.cxx b/oox/source/xls/condformatcontext.cxx new file mode 100644 index 000000000000..d387bc959cca --- /dev/null +++ b/oox/source/xls/condformatcontext.cxx @@ -0,0 +1,114 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: condformatcontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:08 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/condformatcontext.hxx" + +using ::rtl::OUString; + +namespace oox { +namespace xls { + +// ============================================================================ + +OoxCondFormatContext::OoxCondFormatContext( const OoxWorksheetFragmentBase& rFragment ) : + OoxWorksheetContextBase( rFragment ) +{ +} + +// oox.xls.OoxContextHelper interface ----------------------------------------- + +bool OoxCondFormatContext::onCanCreateContext( sal_Int32 nElement ) const +{ + switch( getCurrentContext() ) + { + case XLS_TOKEN( conditionalFormatting ): + return (nElement == XLS_TOKEN( cfRule )); + case XLS_TOKEN( cfRule ): + return (nElement == XLS_TOKEN( formula )); + } + return false; +} + +void OoxCondFormatContext::onStartElement( const AttributeList& rAttribs ) +{ + switch( getCurrentContext() ) + { + case XLS_TOKEN( conditionalFormatting ): + mxCondFmt = getCondFormats().importConditionalFormatting( rAttribs ); + break; + case XLS_TOKEN( cfRule ): + if( mxCondFmt.get() ) mxRule = mxCondFmt->importCfRule( rAttribs ); + break; + } +} + +void OoxCondFormatContext::onEndElement( const OUString& rChars ) +{ + switch( getCurrentContext() ) + { + case XLS_TOKEN( formula ): + if( mxCondFmt.get() && mxRule.get() ) mxRule->appendFormula( rChars ); + break; + } +} + +bool OoxCondFormatContext::onCanCreateRecordContext( sal_Int32 nRecId ) +{ + switch( getCurrentContext() ) + { + case OOBIN_ID_CONDFORMATTING: + return (nRecId == OOBIN_ID_CFRULE); + } + return false; +} + +void OoxCondFormatContext::onStartRecord( RecordInputStream& rStrm ) +{ + switch( getCurrentContext() ) + { + case OOBIN_ID_CONDFORMATTING: + mxCondFmt = getCondFormats().importCondFormatting( rStrm ); + break; + case OOBIN_ID_CFRULE: + if( mxCondFmt.get() ) mxCondFmt->importCfRule( rStrm ); + break; + } +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/connectionsfragment.cxx b/oox/source/xls/connectionsfragment.cxx new file mode 100644 index 000000000000..125e79cccc45 --- /dev/null +++ b/oox/source/xls/connectionsfragment.cxx @@ -0,0 +1,127 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: connectionsfragment.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:08 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/connectionsfragment.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/xls/webquerybuffer.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::sheet::XSpreadsheet; +using ::com::sun::star::xml::sax::SAXException; + +namespace oox { +namespace xls { + +OoxConnectionsFragment::OoxConnectionsFragment( const WorkbookHelper& rHelper, const OUString& rFragmentPath ) : + OoxWorkbookFragmentBase( rHelper, rFragmentPath ) +{ +} + +bool OoxConnectionsFragment::onCanCreateContext( sal_Int32 nElement ) const +{ + switch( getCurrentContext() ) + { + case XML_ROOT_CONTEXT: return (nElement == XLS_TOKEN( connections )); + case XLS_TOKEN( connections ): return (nElement == XLS_TOKEN( connection )); + case XLS_TOKEN( connection ): return (nElement == XLS_TOKEN( webPr )) || + (nElement == XLS_TOKEN( textPr )) || + (nElement == XLS_TOKEN( dbPr )) || + (nElement == XLS_TOKEN( olapPr )) || + (nElement == XLS_TOKEN( parameters )); + case XLS_TOKEN( webPr ): return (nElement == XLS_TOKEN( tables )); + case XLS_TOKEN( tables ): return (nElement == XLS_TOKEN( m )) || + (nElement == XLS_TOKEN( s )) || + (nElement == XLS_TOKEN( x )); + } + return false; +} + +void OoxConnectionsFragment::onStartElement( const AttributeList& rAttribs ) +{ + switch ( getCurrentContext() ) + { + case XLS_TOKEN( connection ): + importConnection( rAttribs ); + break; + case XLS_TOKEN( webPr ): + importWebPr( rAttribs ); + break; + case XLS_TOKEN( tables ): + importTables( rAttribs ); + break; + case XLS_TOKEN( s ): + importS( rAttribs ); + break; + case XLS_TOKEN( x ): + importX( rAttribs ); + break; + } +} + +void OoxConnectionsFragment::importConnection( const AttributeList& rAttribs ) +{ + if ( rAttribs.getInteger( XML_type, 0 ) == Connection::CONNECTION_WEBQUERY ) + { + getWebQueries().importConnection( rAttribs ); + } +} + +void OoxConnectionsFragment::importWebPr( const AttributeList& rAttribs ) +{ + getWebQueries().importWebPr( rAttribs ); +} + +void OoxConnectionsFragment::importTables( const AttributeList& /*rAttribs*/ ) +{ +// sal_Int32 nCount = rAttribs.getInteger( XML_count, 0 ); +} + +void OoxConnectionsFragment::importS( const AttributeList& /*rAttribs*/ ) +{ +// OUString aName = rAttribs.getString( XML_v ); +} + +void OoxConnectionsFragment::importX( const AttributeList& /*rAttribs*/ ) +{ +// sal_Int32 nSharedId = rAttribs.getInteger( XML_v, 0 ); +} + +} // namespace xls +} // namespace oox diff --git a/oox/source/xls/defnamesbuffer.cxx b/oox/source/xls/defnamesbuffer.cxx new file mode 100644 index 000000000000..6fc1623dea0e --- /dev/null +++ b/oox/source/xls/defnamesbuffer.cxx @@ -0,0 +1,674 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: defnamesbuffer.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:08 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/defnamesbuffer.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "oox/helper/attributelist.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/xls/addressconverter.hxx" +#include "oox/xls/biffinputstream.hxx" +#include "oox/xls/externallinkbuffer.hxx" +#include "oox/xls/formulaparser.hxx" +#include "oox/xls/ooxtokens.hxx" + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::container::XNameAccess; +using ::com::sun::star::table::CellAddress; +using ::com::sun::star::table::CellRangeAddress; +using ::com::sun::star::sheet::SingleReference; +using ::com::sun::star::sheet::ComplexReference; +using ::com::sun::star::sheet::XNamedRanges; +using ::com::sun::star::sheet::XNamedRange; +using ::com::sun::star::sheet::XFormulaTokens; +using ::com::sun::star::sheet::XPrintAreas; +using namespace ::com::sun::star::sheet::ReferenceFlags; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +const sal_uInt16 BIFF_DEFNAME_HIDDEN = 0x0001; +const sal_uInt16 BIFF_DEFNAME_FUNC = 0x0002; +const sal_uInt16 BIFF_DEFNAME_VBNAME = 0x0004; +const sal_uInt16 BIFF_DEFNAME_MACRO = 0x0008; +const sal_uInt16 BIFF_DEFNAME_CALCEXP = 0x0010; +const sal_uInt16 BIFF_DEFNAME_BUILTIN = 0x0020; +const sal_uInt16 BIFF_DEFNAME_FGROUPMASK = 0x0FC0; +const sal_uInt16 BIFF_DEFNAME_BIG = 0x1000; + +const sal_uInt8 BIFF2_DEFNAME_FUNC = 0x02; /// BIFF2 function/command flag. + +const sal_uInt16 BIFF_DEFNAME_GLOBAL = 0; /// 0 = Globally defined name. + +} // namespace + +// ============================================================================ + +OoxDefinedNameData::OoxDefinedNameData() : + mnSheet( -1 ), + mbMacro( false ), + mbFunction( false ), + mbVBName( false ), + mbHidden( false ) +{ +} + +// ============================================================================ + +namespace { + +const sal_uInt16 BIFF_REFFLAG_COL1REL = 0x0001; +const sal_uInt16 BIFF_REFFLAG_ROW1REL = 0x0002; +const sal_uInt16 BIFF_REFFLAG_COL2REL = 0x0004; +const sal_uInt16 BIFF_REFFLAG_ROW2REL = 0x0008; + +void lclConvertRefFlags( sal_Int32& ornFlags, sal_Int32& ornAbsPos, sal_Int32& ornRelPos, sal_Int32 nBasePos, sal_Int32 nApiRelFlag, bool bRel ) +{ + if( getFlag( ornFlags, nApiRelFlag ) && !bRel ) + { + // convert relative to absolute + setFlag( ornFlags, nApiRelFlag, false ); + ornAbsPos = nBasePos + ornRelPos; + } + else if( !getFlag( ornFlags, nApiRelFlag ) && bRel ) + { + // convert absolute to relative + setFlag( ornFlags, nApiRelFlag, true ); + ornRelPos = ornAbsPos - nBasePos; + } +} + +void lclConvertSingleRefFlags( SingleReference& orApiRef, const CellAddress& rBaseAddress, bool bColRel, bool bRowRel ) +{ + lclConvertRefFlags( + orApiRef.Flags, orApiRef.Column, orApiRef.RelativeColumn, + rBaseAddress.Column, COLUMN_RELATIVE, bColRel ); + lclConvertRefFlags( + orApiRef.Flags, orApiRef.Row, orApiRef.RelativeRow, + rBaseAddress.Row, ROW_RELATIVE, bRowRel ); +} + +} // namespace + +// ---------------------------------------------------------------------------- + +DefinedNameBase::DefinedNameBase( const WorkbookHelper& rHelper, sal_Int32 nLocalSheet ) : + WorkbookHelper( rHelper ) +{ + maOoxData.mnSheet = nLocalSheet; +} + +Any DefinedNameBase::getReference( const CellAddress& rBaseAddress ) const +{ + if( maRefAny.hasValue() && (maOoxData.maName.getLength() >= 2) && (maOoxData.maName[ 0 ] == '\x01') ) + { + sal_Unicode cFlagsChar = maOoxData.maName.toAsciiUpperCase()[ 1 ]; + if( ('A' <= cFlagsChar) && (cFlagsChar <= 'P') ) + { + sal_uInt16 nFlags = static_cast< sal_uInt16 >( cFlagsChar - 'A' ); + if( maRefAny.has< SingleReference >() && (cFlagsChar <= 'D') ) + { + SingleReference aApiRef; + maRefAny >>= aApiRef; + lclConvertSingleRefFlags( aApiRef, rBaseAddress, getFlag( nFlags, BIFF_REFFLAG_COL1REL ), getFlag( nFlags, BIFF_REFFLAG_ROW1REL ) ); + return Any( aApiRef ); + } + if( maRefAny.has< ComplexReference >() ) + { + ComplexReference aApiRef; + maRefAny >>= aApiRef; + lclConvertSingleRefFlags( aApiRef.Reference1, rBaseAddress, getFlag( nFlags, BIFF_REFFLAG_COL1REL ), getFlag( nFlags, BIFF_REFFLAG_ROW1REL ) ); + lclConvertSingleRefFlags( aApiRef.Reference2, rBaseAddress, getFlag( nFlags, BIFF_REFFLAG_COL2REL ), getFlag( nFlags, BIFF_REFFLAG_ROW2REL ) ); + return Any( aApiRef ); + } + } + } + return Any(); +} + +void DefinedNameBase::importOoxFormula( FormulaContext& rContext ) +{ + if( maOoxData.maFormula.getLength() > 0 ) + { + rContext.setBaseAddress( CellAddress( static_cast< sal_Int16 >( maOoxData.mnSheet ), 0, 0 ) ); + getFormulaParser().importFormula( rContext, maOoxData.maFormula ); + } + else + getFormulaParser().convertErrorToFormula( rContext, BIFF_ERR_NAME ); +} + +void DefinedNameBase::importOobFormula( FormulaContext& rContext, RecordInputStream& rStrm ) +{ + rContext.setBaseAddress( CellAddress( static_cast< sal_Int16 >( maOoxData.mnSheet ), 0, 0 ) ); + getFormulaParser().importFormula( rContext, rStrm ); +} + +void DefinedNameBase::importBiffFormula( FormulaContext& rContext, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ) +{ + rContext.setBaseAddress( CellAddress( static_cast< sal_Int16 >( maOoxData.mnSheet ), 0, 0 ) ); + if( !pnFmlaSize || (*pnFmlaSize > 0) ) + getFormulaParser().importFormula( rContext, rStrm, pnFmlaSize ); + else + getFormulaParser().convertErrorToFormula( rContext, BIFF_ERR_NAME ); +} + +void DefinedNameBase::setReference( const ApiTokenSequence& rTokens ) +{ + maRefAny = getFormulaParser().extractReference( rTokens ); +} + +// ============================================================================ + +namespace { + +const sal_Char* const spcLegacyPrefix = "Excel_BuiltIn_"; +const sal_Char* const spcOoxPrefix = "_xlnm."; + +const sal_Char* const sppcBaseNames[] = +{ + "Consolidate_Area", /* OOX */ + "Auto_Open", + "Auto_Close", + "Extract", /* OOX */ + "Database", /* OOX */ + "Criteria", /* OOX */ + "Print_Area", /* OOX */ + "Print_Titles", /* OOX */ + "Recorder", + "Data_Form", + "Auto_Activate", + "Auto_Deactivate", + "Sheet_Title", /* OOX */ + "_FilterDatabase" /* OOX */ +}; + +/** Localized names for _xlnm._FilterDatabase as used in BIFF5. */ +const sal_Char* const sppcFilterDbNames[] = +{ + "_FilterDatabase", // English + "_FilterDatenbank" // German +}; + +OUString lclGetBaseName( sal_Unicode cBuiltinId ) +{ + OSL_ENSURE( cBuiltinId < STATIC_ARRAY_SIZE( sppcBaseNames ), "lclGetBaseName - unknown builtin name" ); + OUStringBuffer aBuffer; + if( cBuiltinId < STATIC_ARRAY_SIZE( sppcBaseNames ) ) + aBuffer.appendAscii( sppcBaseNames[ cBuiltinId ] ); + else + aBuffer.append( static_cast< sal_Int32 >( cBuiltinId ) ); + return aBuffer.makeStringAndClear(); +} + +OUString lclGetFinalName( sal_Unicode cBuiltinId ) +{ + return OUStringBuffer().appendAscii( spcOoxPrefix ).append( lclGetBaseName( cBuiltinId ) ).makeStringAndClear(); +} + +sal_Unicode lclGetBuiltinIdFromOox( const OUString& rOoxName ) +{ + OUString aPrefix = OUString::createFromAscii( spcOoxPrefix ); + sal_Int32 nPrefixLen = aPrefix.getLength(); + if( rOoxName.matchIgnoreAsciiCase( aPrefix ) ) + { + for( sal_Unicode cBuiltinId = 0; cBuiltinId < STATIC_ARRAY_SIZE( sppcBaseNames ); ++cBuiltinId ) + { + OUString aBaseName = lclGetBaseName( cBuiltinId ); + sal_Int32 nBaseNameLen = aBaseName.getLength(); + if( (rOoxName.getLength() == nPrefixLen + nBaseNameLen) && rOoxName.matchIgnoreAsciiCase( aBaseName, nPrefixLen ) ) + return cBuiltinId; + } + } + return OOX_DEFNAME_UNKNOWN; +} + +sal_Unicode lclGetBuiltinIdFromOob( const OUString& rOobName ) +{ + for( sal_Unicode cBuiltinId = 0; cBuiltinId < STATIC_ARRAY_SIZE( sppcBaseNames ); ++cBuiltinId ) + if( rOobName.equalsIgnoreAsciiCaseAscii( sppcBaseNames[ cBuiltinId ] ) ) + return cBuiltinId; + return OOX_DEFNAME_UNKNOWN; +} + +bool lclIsFilterDatabaseName( const OUString& rName ) +{ + for( const sal_Char* const* ppcName = sppcFilterDbNames; ppcName < STATIC_ARRAY_END( sppcFilterDbNames ); ++ppcName ) + if( rName.equalsIgnoreAsciiCaseAscii( *ppcName ) ) + return true; + return false; +} + +} // namespace + +// ---------------------------------------------------------------------------- + +DefinedName::DefinedName( const WorkbookHelper& rHelper, sal_Int32 nLocalSheet ) : + DefinedNameBase( rHelper, nLocalSheet ), + mnTokenIndex( -1 ), + mcBuiltinId( OOX_DEFNAME_UNKNOWN ), + mpStrm( 0 ), + mnRecHandle( -1 ), + mnRecPos( 0 ), + mnFmlaSize( 0 ) +{ +} + +void DefinedName::importDefinedName( const AttributeList& rAttribs ) +{ + maOoxData.maName = rAttribs.getString( XML_name ); + maOoxData.mnSheet = rAttribs.getInteger( XML_localSheetId, -1 ); + maOoxData.mbMacro = rAttribs.getBool( XML_xlm, false ); + maOoxData.mbFunction = rAttribs.getBool( XML_function, false ); + maOoxData.mbVBName = rAttribs.getBool( XML_vbProcedure, false ); + maOoxData.mbHidden = rAttribs.getBool( XML_hidden, false ); + mcBuiltinId = lclGetBuiltinIdFromOox( maOoxData.maName ); +} + +void DefinedName::setFormula( const OUString& rFormula ) +{ + maOoxData.maFormula = rFormula; +} + +void DefinedName::importDefinedName( RecordInputStream& rStrm ) +{ + sal_uInt16 nFlags; + rStrm >> nFlags; + rStrm.skip( 3 ); // 2 bytes unknown, 1 byte keyboard shortcut + rStrm >> maOoxData.mnSheet >> maOoxData.maName; + + // macro function/command, hidden flag, equal flags in BIFF and OOBIN + maOoxData.mbMacro = getFlag( nFlags, BIFF_DEFNAME_MACRO ); + maOoxData.mbFunction = getFlag( nFlags, BIFF_DEFNAME_FUNC ); + maOoxData.mbVBName = getFlag( nFlags, BIFF_DEFNAME_VBNAME ); + maOoxData.mbHidden = getFlag( nFlags, BIFF_DEFNAME_HIDDEN ); + + // get builtin name index from name + if( getFlag( nFlags, BIFF_DEFNAME_BUILTIN ) ) + mcBuiltinId = lclGetBuiltinIdFromOob( maOoxData.maName ); + // unhide built-in names (_xlnm._FilterDatabase is always hidden) + if( isBuiltinName() ) + maOoxData.mbHidden = false; + + // store token array data + sal_Int32 nRecPos = rStrm.getRecPos(); + sal_Int32 nFmlaSize = rStrm.readInt32(); + rStrm.skip( nFmlaSize ); + sal_Int32 nAddDataSize = rStrm.readInt32(); + if( rStrm.isValid() && (nFmlaSize > 0) && (nAddDataSize >= 0) && (rStrm.getRecLeft() >= nAddDataSize) ) + { + sal_Int32 nTotalSize = 8 + nFmlaSize + nAddDataSize; + mxFormula.reset( new RecordDataSequence( nTotalSize ) ); + rStrm.seek( nRecPos ); + rStrm.read( mxFormula->getArray(), nTotalSize ); + } +} + +void DefinedName::importDefinedName( BiffInputStream& rStrm ) +{ + BiffType eBiff = getBiff(); + sal_uInt16 nFlags = 0; + sal_Int16 nRefId = BIFF_DEFNAME_GLOBAL; + sal_Int16 nTabId = BIFF_DEFNAME_GLOBAL; + sal_uInt8 nNameLen = 0, nShortCut = 0; + + switch( eBiff ) + { + case BIFF2: + { + sal_uInt8 nFlagsBiff2; + rStrm >> nFlagsBiff2; + rStrm.skip( 1 ); + rStrm >> nShortCut >> nNameLen; + mnFmlaSize = rStrm.readuInt8(); + setFlag( nFlags, BIFF_DEFNAME_FUNC, getFlag( nFlagsBiff2, BIFF2_DEFNAME_FUNC ) ); + maOoxData.maName = rStrm.readCharArray( nNameLen, getTextEncoding() ); + } + break; + case BIFF3: + case BIFF4: + rStrm >> nFlags >> nShortCut >> nNameLen >> mnFmlaSize; + maOoxData.maName = rStrm.readCharArray( nNameLen, getTextEncoding() ); + break; + case BIFF5: + rStrm >> nFlags >> nShortCut >> nNameLen >> mnFmlaSize >> nRefId >> nTabId; + maOoxData.maName = rStrm.skip( 4 ).readCharArray( nNameLen, getTextEncoding() ); + break; + case BIFF8: + rStrm >> nFlags >> nShortCut >> nNameLen >> mnFmlaSize >> nRefId >> nTabId; + maOoxData.maName = rStrm.skip( 4 ).readUniString( nNameLen ); + break; + case BIFF_UNKNOWN: break; + } + + // macro function/command, hidden flag + maOoxData.mbMacro = getFlag( nFlags, BIFF_DEFNAME_MACRO ); + maOoxData.mbFunction = getFlag( nFlags, BIFF_DEFNAME_FUNC ); + maOoxData.mbVBName = getFlag( nFlags, BIFF_DEFNAME_VBNAME ); + maOoxData.mbHidden = getFlag( nFlags, BIFF_DEFNAME_HIDDEN ); + + // get builtin name index from name + if( getFlag( nFlags, BIFF_DEFNAME_BUILTIN ) ) + { + OSL_ENSURE( maOoxData.maName.getLength() == 1, "DefinedName::importDefinedName - wrong builtin name" ); + if( maOoxData.maName.getLength() > 0 ) + { + mcBuiltinId = maOoxData.maName[ 0 ]; + if( mcBuiltinId == '?' ) // the NUL character is imported as '?' + mcBuiltinId = OOX_DEFNAME_CONSOLIDATEAREA; + } + } + /* In BIFF5, _xlnm._FilterDatabase appears as hidden user name without + built-in flag, and even worse, localized. */ + else if( (eBiff == BIFF5) && lclIsFilterDatabaseName( maOoxData.maName ) ) + { + mcBuiltinId = OOX_DEFNAME_FILTERDATABASE; + } + + // unhide built-in names (_xlnm._FilterDatabase is always hidden) + if( isBuiltinName() ) + maOoxData.mbHidden = false; + + // get sheet index for sheet-local names in BIFF5-BIFF8 + switch( getBiff() ) + { + case BIFF2: + case BIFF3: + case BIFF4: + break; + case BIFF5: + // #i44019# nTabId may be invalid, resolve nRefId to sheet index + if( nRefId != BIFF_DEFNAME_GLOBAL ) + if( const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId ).get() ) + if( pExtLink->getLinkType() == LINKTYPE_INTERNAL ) + maOoxData.mnSheet = pExtLink->getSheetIndex(); + break; + case BIFF8: + // one-based sheet index + if( nTabId != BIFF_DEFNAME_GLOBAL ) + maOoxData.mnSheet = nTabId - 1; + break; + case BIFF_UNKNOWN: + break; + } + + // store record position to be able to import token array later + mpStrm = &rStrm; + mnRecHandle = rStrm.getRecHandle(); + mnRecPos = rStrm.getRecPos(); +} + +void DefinedName::createNameObject() +{ + // do not create hidden names and names for (macro) functions + if( maOoxData.mbHidden || maOoxData.mbFunction ) + return; + + // convert original name to final Calc name + if( maOoxData.mbVBName ) + maFinalName = maOoxData.maName; + else if( isBuiltinName() ) + maFinalName = lclGetFinalName( mcBuiltinId ); + else + maFinalName = maOoxData.maName; //! TODO convert to valid name + + // append sheet index for local names in multi-sheet documents + if( isWorkbookFile() && !isGlobalName() ) + maFinalName = OUStringBuffer( maFinalName ).append( sal_Unicode( '_' ) ).append( maOoxData.mnSheet + 1 ).makeStringAndClear(); + + // special flags for this name + sal_Int32 nNameFlags = 0; + using namespace ::com::sun::star::sheet::NamedRangeFlag; + if( !isGlobalName() ) switch( mcBuiltinId ) + { + case OOX_DEFNAME_CRITERIA: nNameFlags = FILTER_CRITERIA; break; + case OOX_DEFNAME_PRINTAREA: nNameFlags = PRINT_AREA; break; + case OOX_DEFNAME_PRINTTITLES: nNameFlags = COLUMN_HEADER | ROW_HEADER; break; + } + + // create the name and insert it into the document, maFinalName will be changed to the resulting name + mxNamedRange = getDefinedNames().createDefinedName( maFinalName, nNameFlags ); + // index of this defined name used in formula token arrays + mnTokenIndex = getDefinedNames().getTokenIndex( mxNamedRange ); +} + +void DefinedName::convertFormula() +{ + Reference< XFormulaTokens > xTokens( mxNamedRange, UNO_QUERY ); + if( xTokens.is() ) + { + // convert and set formula of the defined name + SimpleFormulaContext aContext( xTokens, true, true ); + switch( getFilterType() ) + { + case FILTER_OOX: implImportOoxFormula( aContext ); break; + case FILTER_BIFF: implImportBiffFormula( aContext ); break; + case FILTER_UNKNOWN: break; + } + + // set builtin names (print ranges, repeated titles, filter ranges) + if( !isGlobalName() ) switch( mcBuiltinId ) + { + case OOX_DEFNAME_PRINTAREA: + { + Reference< XPrintAreas > xPrintAreas( getSheet( maOoxData.mnSheet ), UNO_QUERY ); + ApiCellRangeList aPrintRanges; + getFormulaParser().extractCellRangeList( aPrintRanges, xTokens->getTokens(), maOoxData.mnSheet ); + if( xPrintAreas.is() && !aPrintRanges.empty() ) + xPrintAreas->setPrintAreas( ContainerHelper::vectorToSequence( aPrintRanges ) ); + } + break; + case OOX_DEFNAME_PRINTTITLES: + { + Reference< XPrintAreas > xPrintAreas( getSheet( maOoxData.mnSheet ), UNO_QUERY ); + ApiCellRangeList aTitleRanges; + getFormulaParser().extractCellRangeList( aTitleRanges, xTokens->getTokens(), maOoxData.mnSheet ); + if( xPrintAreas.is() && !aTitleRanges.empty() ) + { + bool bHasRowTitles = false; + bool bHasColTitles = false; + const CellAddress& rMaxPos = getAddressConverter().getMaxAddress(); + for( ApiCellRangeList::const_iterator aIt = aTitleRanges.begin(), aEnd = aTitleRanges.end(); (aIt != aEnd) && (!bHasRowTitles || !bHasColTitles); ++aIt ) + { + bool bFullRow = (aIt->StartColumn == 0) && (aIt->EndColumn >= rMaxPos.Column); + bool bFullCol = (aIt->StartRow == 0) && (aIt->EndRow >= rMaxPos.Row); + if( !bHasRowTitles && bFullRow && !bFullCol ) + { + xPrintAreas->setTitleRows( *aIt ); + xPrintAreas->setPrintTitleRows( sal_True ); + bHasRowTitles = true; + } + else if( !bHasColTitles && bFullCol && !bFullRow ) + { + xPrintAreas->setTitleColumns( *aIt ); + xPrintAreas->setPrintTitleColumns( sal_True ); + bHasColTitles = true; + } + } + } + } + break; + } + } + else if( maOoxData.mbHidden && (maOoxData.maName.getLength() > 0) && (maOoxData.maName[ 0 ] == '\x01') ) + { + // import BIFF2-BIFF4 external references + TokensFormulaContext aContext( true, true ); + implImportBiffFormula( aContext ); + setReference( aContext.getTokens() ); + } +} + +void DefinedName::implImportOoxFormula( FormulaContext& rContext ) +{ + if( mxFormula.get() ) + { + RecordInputStream aStrm( *mxFormula ); + importOobFormula( rContext, aStrm ); + } + else + importOoxFormula( rContext ); +} + +void DefinedName::implImportBiffFormula( FormulaContext& rContext ) +{ + OSL_ENSURE( mpStrm, "DefinedName::importBiffFormula - missing BIFF stream" ); + sal_Int64 nCurrRecHandle = mpStrm->getRecHandle(); + if( mpStrm->startRecordByHandle( mnRecHandle ) ) + mpStrm->seek( mnRecPos ); + importBiffFormula( rContext, *mpStrm, &mnFmlaSize ); + mpStrm->startRecordByHandle( nCurrRecHandle ); +} + +// ============================================================================ + +DefinedNamesBuffer::DefinedNamesBuffer( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + maTokenIndexProp( CREATE_OUSTRING( "TokenIndex" ) ), + mnLocalSheet( -1 ) +{ +} + +Reference< XNamedRange > DefinedNamesBuffer::createDefinedName( OUString& orName, sal_Int32 nNameFlags ) const +{ + // find an unused name + Reference< XNamedRanges > xNamedRanges = getNamedRanges(); + Reference< XNameAccess > xNameAccess( xNamedRanges, UNO_QUERY ); + if( xNameAccess.is() ) + orName = ContainerHelper::getUnusedName( xNameAccess, orName, '_' ); + + // create the name and insert it into the Calc document + Reference< XNamedRange > xNamedRange; + if( xNamedRanges.is() && (orName.getLength() > 0) ) try + { + xNamedRanges->addNewByName( orName, OUString(), CellAddress( 0, 0, 0 ), nNameFlags ); + xNamedRange.set( xNamedRanges->getByName( orName ), UNO_QUERY ); + } + catch( Exception& ) + { + OSL_ENSURE( false, "DefinedNamesBuffer::createDefinedName - cannot create defined name" ); + } + return xNamedRange; +} + +sal_Int32 DefinedNamesBuffer::getTokenIndex( const Reference< XNamedRange >& rxNamedRange ) const +{ + PropertySet aPropSet( rxNamedRange ); + sal_Int32 nIndex = -1; + return aPropSet.getProperty( nIndex, maTokenIndexProp ) ? nIndex : -1; +} + +void DefinedNamesBuffer::setLocalSheetIndex( sal_Int32 nLocalSheet ) +{ + mnLocalSheet = nLocalSheet; +} + +DefinedNameRef DefinedNamesBuffer::importDefinedName( const AttributeList& rAttribs ) +{ + DefinedNameRef xDefName = createDefinedName(); + xDefName->importDefinedName( rAttribs ); + return xDefName; +} + +void DefinedNamesBuffer::importDefinedName( RecordInputStream& rStrm ) +{ + createDefinedName()->importDefinedName( rStrm ); +} + +void DefinedNamesBuffer::importDefinedName( BiffInputStream& rStrm ) +{ + createDefinedName()->importDefinedName( rStrm ); +} + +void DefinedNamesBuffer::finalizeImport() +{ + /* First insert all names without formula definition into the document. */ + maDefNames.forEachMem( &DefinedName::createNameObject ); + /* Now convert all name formulas, so that the formula parser can find all + names in case of circular dependencies. */ + maDefNames.forEachMem( &DefinedName::convertFormula ); +} + +DefinedNameRef DefinedNamesBuffer::getByIndex( sal_Int32 nIndex ) const +{ + return maDefNames.get( nIndex ); +} + +DefinedNameRef DefinedNamesBuffer::getByOoxName( const OUString& rOoxName, sal_Int32 nSheet ) const +{ + DefinedNameRef xGlobalName; // a found global name + DefinedNameRef xLocalName; // a found local name + for( DefNameVec::const_iterator aIt = maDefNames.begin(), aEnd = maDefNames.end(); (aIt != aEnd) && !xLocalName; ++aIt ) + { + DefinedNameRef xCurrName = *aIt; + if( xCurrName->getOoxName() == rOoxName ) + { + if( xCurrName->getSheetIndex() == nSheet ) + xLocalName = xCurrName; + else if( xCurrName->isGlobalName() ) + xGlobalName = xCurrName; + } + } + return xLocalName.get() ? xLocalName : xGlobalName; +} + +DefinedNameRef DefinedNamesBuffer::createDefinedName() +{ + DefinedNameRef xDefName( new DefinedName( *this, mnLocalSheet ) ); + maDefNames.push_back( xDefName ); + return xDefName; +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/excelfilter.cxx b/oox/source/xls/excelfilter.cxx new file mode 100644 index 000000000000..feaf77188ee6 --- /dev/null +++ b/oox/source/xls/excelfilter.cxx @@ -0,0 +1,284 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: excelfilter.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:08 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/excelfilter.hxx" +#include "oox/helper/binaryinputstream.hxx" +#include "oox/xls/biffdetector.hxx" +#include "oox/xls/biffinputstream.hxx" +#include "oox/xls/themebuffer.hxx" +#include "oox/xls/workbookfragment.hxx" +#include "oox/dump/biffdumper.hxx" +#include "oox/dump/xlsbdumper.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::XInterface; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::xml::sax::XFastDocumentHandler; +using ::oox::core::BinaryFilterBase; +using ::oox::core::FragmentHandlerRef; +using ::oox::core::RecordInfo; +using ::oox::core::RecordInfoProvider; +using ::oox::core::RecordInfoProviderRef; +using ::oox::core::Relation; +using ::oox::core::Relations; +using ::oox::core::XmlFilterBase; +using ::oox::vml::DrawingPtr; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +/** List of OOBIN record identifiers that start a new context level. */ +static const struct RecordInfo spRecInfos[] = +{ + { OOBIN_ID_BOOKVIEWS, OOBIN_ID_BOOKVIEWS + 1 }, + { OOBIN_ID_BORDERS, OOBIN_ID_BORDERS + 1 }, + { OOBIN_ID_CELLSTYLES, OOBIN_ID_CELLSTYLES + 1 }, + { OOBIN_ID_CELLSTYLEXFS, OOBIN_ID_CELLSTYLEXFS + 1 }, + { OOBIN_ID_CELLXFS, OOBIN_ID_CELLXFS + 1 }, + { OOBIN_ID_CFRULE, OOBIN_ID_CFRULE + 1 }, + { OOBIN_ID_COLBREAKS, OOBIN_ID_COLBREAKS + 1 }, + { OOBIN_ID_COLORS, OOBIN_ID_COLORS + 1 }, + { OOBIN_ID_COLORSCALE, OOBIN_ID_COLORSCALE + 1 }, + { OOBIN_ID_COLS, OOBIN_ID_COLS + 1 }, + { OOBIN_ID_CONDFORMATTING, OOBIN_ID_CONDFORMATTING + 1 }, + { OOBIN_ID_DATABAR, OOBIN_ID_DATABAR + 1 }, + { OOBIN_ID_DATAVALIDATIONS, OOBIN_ID_DATAVALIDATIONS + 1 }, + { OOBIN_ID_DDEITEMVALUES, OOBIN_ID_DDEITEMVALUES + 1 }, + { OOBIN_ID_DXFS, OOBIN_ID_DXFS + 1 }, + { OOBIN_ID_EXTERNALBOOK, -1 }, + { OOBIN_ID_EXTERNALREFS, OOBIN_ID_EXTERNALREFS + 1 }, + { OOBIN_ID_EXTROW, -1 }, + { OOBIN_ID_EXTSHEETDATA, OOBIN_ID_EXTSHEETDATA + 1 }, + { OOBIN_ID_FILLS, OOBIN_ID_FILLS + 1 }, + { OOBIN_ID_FONTS, OOBIN_ID_FONTS + 1 }, + { OOBIN_ID_HEADERFOOTER, OOBIN_ID_HEADERFOOTER + 1 }, + { OOBIN_ID_ICONSET, OOBIN_ID_ICONSET + 1 }, + { OOBIN_ID_INDEXEDCOLORS, OOBIN_ID_INDEXEDCOLORS + 1 }, + { OOBIN_ID_MERGECELLS, OOBIN_ID_MERGECELLS + 1 }, + { OOBIN_ID_MRUCOLORS, OOBIN_ID_MRUCOLORS + 1 }, + { OOBIN_ID_NUMFMTS, OOBIN_ID_NUMFMTS + 1 }, + { OOBIN_ID_ROW, -1 }, + { OOBIN_ID_ROWBREAKS, OOBIN_ID_ROWBREAKS + 1 }, + { OOBIN_ID_SHEETDATA, OOBIN_ID_SHEETDATA + 1 }, + { OOBIN_ID_SHEETDATASET, OOBIN_ID_SHEETDATASET + 1 }, + { OOBIN_ID_SHEETS, OOBIN_ID_SHEETS + 1 }, + { OOBIN_ID_SHEETVIEW, OOBIN_ID_SHEETVIEW + 1 }, + { OOBIN_ID_SHEETVIEWS, OOBIN_ID_SHEETVIEWS + 1 }, + { OOBIN_ID_SST, OOBIN_ID_SST + 1 }, + { OOBIN_ID_STYLESHEET, OOBIN_ID_STYLESHEET + 1 }, + { OOBIN_ID_TABLE, OOBIN_ID_TABLE + 1 }, + { OOBIN_ID_TABLEPARTS, OOBIN_ID_TABLEPARTS + 2 }, // end element increased by 2! + { OOBIN_ID_TABLESTYLES, OOBIN_ID_TABLESTYLES + 1 }, + { OOBIN_ID_VOLTYPE, OOBIN_ID_VOLTYPE + 1 }, + { OOBIN_ID_VOLTYPEMAIN, OOBIN_ID_VOLTYPEMAIN + 1 }, + { OOBIN_ID_VOLTYPES, OOBIN_ID_VOLTYPES + 1 }, + { OOBIN_ID_WORKBOOK, OOBIN_ID_WORKBOOK + 1 }, + { OOBIN_ID_WORKSHEET, OOBIN_ID_WORKSHEET + 1 }, + { -1, -1 } +}; + +} // namespace + +// ============================================================================ + +OUString SAL_CALL ExcelFilter_getImplementationName() throw() +{ + return CREATE_OUSTRING( "com.sun.star.comp.oox.ExcelFilter" ); +} + +Sequence< OUString > SAL_CALL ExcelFilter_getSupportedServiceNames() throw() +{ + OUString aServiceName = CREATE_OUSTRING( "com.sun.star.comp.oox.ExcelFilter" ); + Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +Reference< XInterface > SAL_CALL ExcelFilter_createInstance( + const Reference< XMultiServiceFactory >& rxFactory ) throw( Exception ) +{ + return static_cast< ::cppu::OWeakObject* >( new ExcelFilter( rxFactory ) ); +} + +// ---------------------------------------------------------------------------- + +ExcelFilter::ExcelFilter( const Reference< XMultiServiceFactory >& rxFactory ) : + XmlFilterBase( rxFactory ), + mpHelper( 0 ) +{ +} + +ExcelFilter::~ExcelFilter() +{ +} + +bool ExcelFilter::importDocument() throw() +{ +#if OOX_INCLUDE_DUMPER + { + ::oox::dump::xlsb::Dumper aDumper( *this ); + aDumper.dump(); + if( !aDumper.isImportEnabled() ) + return aDumper.isValid(); + } +#endif + + bool bRet = false; + OUString aWorkbookPath = getFragmentPathFromType( CREATE_RELATIONS_TYPE( "officeDocument" ) ); + if( aWorkbookPath.getLength() > 0 ) + { + WorkbookHelperRoot aHelper( *this ); + if( aHelper.isValid() ) + { + mpHelper = &aHelper; // needed for callbacks + bRet = importFragment( new OoxWorkbookFragment( aHelper, aWorkbookPath ) ); + mpHelper = 0; + } + } + return bRet; +} + +bool ExcelFilter::exportDocument() throw() +{ + return false; +} + +sal_Int32 ExcelFilter::getSchemeClr( sal_Int32 nColorSchemeToken ) const +{ + OSL_ENSURE( mpHelper, "ExcelFilter::getSchemeClr - no workbook helper" ); + return mpHelper ? mpHelper->getTheme().getColorByToken( nColorSchemeToken ) : -1; +} + +const DrawingPtr ExcelFilter::getDrawings() +{ + return DrawingPtr(); +} + +RecordInfoProviderRef ExcelFilter::getRecordInfoProvider() +{ + if( !mxRecInfoProv ) + mxRecInfoProv.reset( new RecordInfoProvider( spRecInfos ) ); + return mxRecInfoProv; +} + +OUString ExcelFilter::implGetImplementationName() const +{ + return ExcelFilter_getImplementationName(); +} + +// ============================================================================ + +OUString SAL_CALL ExcelBiffFilter_getImplementationName() throw() +{ + return CREATE_OUSTRING( "com.sun.star.comp.oox.ExcelBiffFilter" ); +} + +Sequence< OUString > SAL_CALL ExcelBiffFilter_getSupportedServiceNames() throw() +{ + OUString aServiceName = CREATE_OUSTRING( "com.sun.star.comp.oox.ExcelBiffFilter" ); + Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +Reference< XInterface > SAL_CALL ExcelBiffFilter_createInstance( + const Reference< XMultiServiceFactory >& rxFactory ) throw( Exception ) +{ + return static_cast< ::cppu::OWeakObject* >( new ExcelBiffFilter( rxFactory ) ); +} + +// ---------------------------------------------------------------------------- + +ExcelBiffFilter::ExcelBiffFilter( const Reference< XMultiServiceFactory >& rxFactory ) : + BinaryFilterBase( rxFactory ) +{ +} + +ExcelBiffFilter::~ExcelBiffFilter() +{ +} + +bool ExcelBiffFilter::importDocument() throw() +{ +#if OOX_INCLUDE_DUMPER + { + ::oox::dump::biff::Dumper aDumper( *this ); + aDumper.dump(); + if( !aDumper.isImportEnabled() ) + return aDumper.isValid(); + } +#endif + + bool bRet = false; + + // detect BIFF version and workbook stream name + OUString aWorkbookName; + BiffType eBiff = BiffDetector::detectStorageBiffVersion( aWorkbookName, getStorage() ); + BinaryInputStream aInStrm( getStorage()->openInputStream( aWorkbookName ), aWorkbookName.getLength() > 0 ); + OSL_ENSURE( (eBiff != BIFF_UNKNOWN) && aInStrm.is(), "ExcelBiffFilter::ExcelBiffFilter - invalid file format" ); + + if( (eBiff != BIFF_UNKNOWN) && aInStrm.is() ) + { + WorkbookHelperRoot aHelper( *this, eBiff ); + if( aHelper.isValid() ) + { + BiffWorkbookFragment aFragment( aHelper ); + BiffInputStream aBiffStream( aInStrm ); + bRet = aFragment.importFragment( aBiffStream ); + } + } + return bRet; +} + +bool ExcelBiffFilter::exportDocument() throw() +{ + return false; +} + +OUString ExcelBiffFilter::implGetImplementationName() const +{ + return ExcelBiffFilter_getImplementationName(); +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/externallinkbuffer.cxx b/oox/source/xls/externallinkbuffer.cxx new file mode 100644 index 000000000000..72dab2171955 --- /dev/null +++ b/oox/source/xls/externallinkbuffer.cxx @@ -0,0 +1,857 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: externallinkbuffer.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:08 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/externallinkbuffer.hxx" +#include +#include +#include +#include +#include "oox/helper/attributelist.hxx" +#include "oox/xls/addressconverter.hxx" +#include "oox/xls/biffinputstream.hxx" +#include "oox/xls/formulaparser.hxx" +#include "oox/xls/ooxfragmenthandler.hxx" +#include "oox/xls/worksheetbuffer.hxx" + +using ::rtl::OString; +using ::rtl::OStringBuffer; +using ::rtl::OStringToOUString; +using ::rtl::OUString; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::table::CellAddress; +using ::com::sun::star::sheet::XDDELinks; +using ::com::sun::star::sheet::XDDELinkResults; +using ::oox::core::Relations; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +const sal_uInt16 OOBIN_EXTERNALBOOK_BOOK = 0; +const sal_uInt16 OOBIN_EXTERNALBOOK_DDE = 1; +const sal_uInt16 OOBIN_EXTERNALBOOK_OLE = 2; + +const sal_uInt16 OOBIN_EXTNAME_AUTOMATIC = 0x0002; +const sal_uInt16 OOBIN_EXTNAME_PREFERPIC = 0x0004; +const sal_uInt16 OOBIN_EXTNAME_STDDOCNAME = 0x0008; +const sal_uInt16 OOBIN_EXTNAME_OLEOBJECT = 0x0010; +const sal_uInt16 OOBIN_EXTNAME_ICONIFIED = 0x0020; + +const sal_uInt16 BIFF_EXTNAME_BUILTIN = 0x0001; +const sal_uInt16 BIFF_EXTNAME_AUTOMATIC = 0x0002; +const sal_uInt16 BIFF_EXTNAME_PREFERPIC = 0x0004; +const sal_uInt16 BIFF_EXTNAME_STDDOCNAME = 0x0008; +const sal_uInt16 BIFF_EXTNAME_OLEOBJECT = 0x0010; +const sal_uInt16 BIFF_EXTNAME_ICONIFIED = 0x8000; + +} // namespace + +// ============================================================================ + +OoxExternalNameData::OoxExternalNameData() : + mbBuiltIn( false ), + mbNotify( false ), + mbPreferPic( false ), + mbStdDocName( false ), + mbOleObj( false ), + mbIconified( false ) +{ +} + +// ============================================================================ + +ExternalName::ExternalName( const ExternalLink& rParentLink, sal_Int32 nLocalSheet ) : + DefinedNameBase( rParentLink, nLocalSheet ), + mrParentLink( rParentLink ), + mnStorageId( 0 ), + mbDdeLinkCreated( false ) +{ +} + +void ExternalName::importDefinedName( const AttributeList& rAttribs ) +{ + maOoxData.maName = rAttribs.getString( XML_name ); + OSL_ENSURE( maOoxData.maName.getLength() > 0, "ExternalName::importDefinedName - empty name" ); + // zero-based index into sheet list of externalBook + maOoxData.mnSheet = mrParentLink.getSheetIndex( rAttribs.getInteger( XML_sheetId, -1 ) ); +} + +void ExternalName::importDdeItem( const AttributeList& rAttribs ) +{ + maOoxData.maName = rAttribs.getString( XML_name ); + OSL_ENSURE( maOoxData.maName.getLength() > 0, "ExternalName::importDdeItem - empty name" ); + maOoxExtNameData.mbOleObj = false; + maOoxExtNameData.mbStdDocName = rAttribs.getBool( XML_ole, false ); + maOoxExtNameData.mbNotify = rAttribs.getBool( XML_advise, false ); + maOoxExtNameData.mbPreferPic = rAttribs.getBool( XML_preferPic, false ); +} + +void ExternalName::importValues( const AttributeList& rAttribs ) +{ + setResultSize( rAttribs.getInteger( XML_cols, 1 ), rAttribs.getInteger( XML_rows, 1 ) ); +} + +void ExternalName::importOleItem( const AttributeList& rAttribs ) +{ + maOoxData.maName = rAttribs.getString( XML_name ); + OSL_ENSURE( maOoxData.maName.getLength() > 0, "ExternalName::importOleItem - empty name" ); + maOoxExtNameData.mbOleObj = true; + maOoxExtNameData.mbNotify = rAttribs.getBool( XML_advise, false ); + maOoxExtNameData.mbPreferPic = rAttribs.getBool( XML_preferPic, false ); + maOoxExtNameData.mbIconified = rAttribs.getBool( XML_icon, false ); +} + +void ExternalName::importExternalName( RecordInputStream& rStrm ) +{ + rStrm >> maOoxData.maName; + OSL_ENSURE( maOoxData.maName.getLength() > 0, "ExternalName::importExternalName - empty name" ); +} + +void ExternalName::importExternalNameFlags( RecordInputStream& rStrm ) +{ + sal_uInt16 nFlags; + sal_Int32 nSheetId; + rStrm >> nFlags >> nSheetId; + // one-based index into sheet list of EXTSHEETNAMES + maOoxData.mnSheet = mrParentLink.getSheetIndex( nSheetId - 1 ); + // no flag for built-in names, as in OOX... + maOoxExtNameData.mbNotify = getFlag( nFlags, OOBIN_EXTNAME_AUTOMATIC ); + maOoxExtNameData.mbPreferPic = getFlag( nFlags, OOBIN_EXTNAME_PREFERPIC ); + maOoxExtNameData.mbStdDocName = getFlag( nFlags, OOBIN_EXTNAME_STDDOCNAME ); + maOoxExtNameData.mbOleObj = getFlag( nFlags, OOBIN_EXTNAME_OLEOBJECT ); + maOoxExtNameData.mbIconified = getFlag( nFlags, OOBIN_EXTNAME_ICONIFIED ); + OSL_ENSURE( (mrParentLink.getLinkType() == LINKTYPE_OLE) == maOoxExtNameData.mbOleObj, + "ExternalName::importExternalNameFlags - wrong flags in external name" ); +} + +void ExternalName::importDdeItemValues( RecordInputStream& rStrm ) +{ + sal_Int32 nRows, nCols; + rStrm >> nRows >> nCols; + setResultSize( nCols, nRows ); +} + +void ExternalName::importDdeItemBool( RecordInputStream& rStrm ) +{ + appendResultValue< double >( (rStrm.readuInt8() == 0) ? 0.0 : 1.0 ); +} + +void ExternalName::importDdeItemDouble( RecordInputStream& rStrm ) +{ + appendResultValue( rStrm.readDouble() ); +} + +void ExternalName::importDdeItemError( RecordInputStream& rStrm ) +{ + appendResultValue( BiffHelper::calcDoubleFromError( rStrm.readuInt8() ) ); +} + +void ExternalName::importDdeItemString( RecordInputStream& rStrm ) +{ + appendResultValue( rStrm.readString() ); +} + +void ExternalName::importExternalName( BiffInputStream& rStrm ) +{ + sal_uInt16 nFlags = 0; + if( getBiff() >= BIFF3 ) + { + rStrm >> nFlags; + maOoxExtNameData.mbBuiltIn = getFlag( nFlags, BIFF_EXTNAME_BUILTIN ); + maOoxExtNameData.mbNotify = getFlag( nFlags, BIFF_EXTNAME_AUTOMATIC ); + maOoxExtNameData.mbPreferPic = getFlag( nFlags, BIFF_EXTNAME_PREFERPIC ); + + // BIFF5-BIFF8: sheet index for sheet-local names, OLE settings + if( getBiff() >= BIFF5 ) + { + maOoxExtNameData.mbStdDocName = getFlag( nFlags, BIFF_EXTNAME_STDDOCNAME ); + maOoxExtNameData.mbOleObj = getFlag( nFlags, BIFF_EXTNAME_OLEOBJECT ); + maOoxExtNameData.mbIconified = getFlag( nFlags, BIFF_EXTNAME_ICONIFIED ); + + if( maOoxExtNameData.mbOleObj ) + { + rStrm >> mnStorageId; + } + else + { + // get sheet index for sheet-local names + sal_Int16 nRefId = rStrm.skip( 2 ).readuInt16(); + switch( getBiff() ) + { + case BIFF2: + case BIFF3: + case BIFF4: + break; + case BIFF5: + // resolve nRefId to sheet index, zero is global name + if( nRefId > 0 ) + if( const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId ).get() ) + if( pExtLink->getLinkType() == LINKTYPE_EXTERNAL ) + maOoxData.mnSheet = pExtLink->getSheetIndex(); + break; + case BIFF8: + // one-based index into sheet list of EXTERNALBOOK record, zero is global name + if( nRefId > 0 ) + maOoxData.mnSheet = mrParentLink.getSheetIndex( nRefId - 1 ); + break; + case BIFF_UNKNOWN: + break; + } + } + } + } + + maOoxData.maName = (getBiff() == BIFF8) ? + rStrm.readUniString( rStrm.readuInt8() ) : + rStrm.readByteString( false, getTextEncoding() ); + OSL_ENSURE( maOoxData.maName.getLength() > 0, "ExternalName::importExternalName - empty name" ); + + switch( mrParentLink.getLinkType() ) + { + case LINKTYPE_EXTERNAL: + // external cell references that are stored in hidden external names (seen in BIFF3-BIFF4) + if( (maOoxData.maName.getLength() > 0) && (maOoxData.maName[ 0 ] == '\x01') && (rStrm.getRecLeft() > 2) ) + { + TokensFormulaContext aContext( true, true ); + importBiffFormula( aContext, rStrm ); + setReference( aContext.getTokens() ); + } + break; + + case LINKTYPE_DDE: + case LINKTYPE_OLE: + case LINKTYPE_MAYBE_DDE_OLE: + // DDE/OLE link results + if( rStrm.getRecLeft() > 3 ) + { + bool bBiff8 = getBiff() == BIFF8; + sal_Int32 nCols = rStrm.readuInt8(); + sal_Int32 nRows = rStrm.readuInt16(); + if( bBiff8 ) { ++nCols; ++nRows; } else if( nCols == 0 ) nCols = 256; + setResultSize( nCols, nRows ); + + bool bLoop = true; + while( bLoop && rStrm.isValid() && (maCurrIt != maResults.end()) ) + { + switch( rStrm.readuInt8() ) + { + case BIFF_DATATYPE_EMPTY: + appendResultValue( OUString() ); + rStrm.skip( 8 ); + break; + case BIFF_DATATYPE_DOUBLE: + appendResultValue( rStrm.readDouble() ); + break; + case BIFF_DATATYPE_STRING: + appendResultValue( bBiff8 ? rStrm.readUniString() : rStrm.readByteString( false, getTextEncoding() ) ); + break; + case BIFF_DATATYPE_BOOL: + appendResultValue< double >( (rStrm.readuInt8() == 0) ? 0.0 : 1.0 ); + rStrm.skip( 7 ); + break; + case BIFF_DATATYPE_ERROR: + appendResultValue( BiffHelper::calcDoubleFromError( rStrm.readuInt8() ) ); + rStrm.skip( 7 ); + break; + default: + bLoop = false; + } + } + OSL_ENSURE( bLoop && rStrm.isValid() && (maCurrIt == maResults.end()), + "ExternalName::importExternalName - stream error in result set" ); + } + break; + + default:; + } +} + +bool ExternalName::getDdeLinkData( OUString& orDdeServer, OUString& orDdeTopic, OUString& orDdeItem ) +{ + if( (mrParentLink.getLinkType() == LINKTYPE_DDE) && (maOoxData.maName.getLength() > 0) ) + { + // try to create a DDE link and to set the imported link results + if( !mbDdeLinkCreated ) try + { + Reference< XDDELinks > xDdeLinks( getDdeLinks(), UNO_QUERY_THROW ); + mxDdeLink = xDdeLinks->addDDELink( mrParentLink.getClassName(), mrParentLink.getTargetUrl(), maOoxData.maName, ::com::sun::star::sheet::DDELinkMode_DEFAULT ); + if( !maResults.empty() ) + { + Reference< XDDELinkResults > xResults( mxDdeLink, UNO_QUERY_THROW ); + xResults->setResults( ContainerHelper::matrixToSequenceSequence( maResults ) ); + } + mbDdeLinkCreated = true; + } + catch( Exception& ) + { + OSL_ENSURE( false, "ExternalName::getDdeLinkData - cannot create DDE link" ); + } + // get link data from created DDE link + if( mxDdeLink.is() ) + { + orDdeServer = mxDdeLink->getApplication(); + orDdeTopic = mxDdeLink->getTopic(); + orDdeItem = mxDdeLink->getItem(); + return true; + } + } + return false; +} + +void ExternalName::setResultSize( sal_Int32 nColumns, sal_Int32 nRows ) +{ + OSL_ENSURE( (mrParentLink.getLinkType() == LINKTYPE_DDE) || (mrParentLink.getLinkType() == LINKTYPE_OLE) || + (mrParentLink.getLinkType() == LINKTYPE_MAYBE_DDE_OLE), "ExternalName::setResultSize - wrong link type" ); + OSL_ENSURE( (nRows > 0) && (nColumns > 0), "ExternalName::setResultSize - invalid matrix size" ); + const CellAddress& rMaxPos = getAddressConverter().getMaxApiAddress(); + if( (0 < nRows) && (nRows <= rMaxPos.Row + 1) && (0 < nColumns) && (nColumns <= rMaxPos.Column + 1) ) + maResults.resize( static_cast< size_t >( nColumns ), static_cast< size_t >( nRows ), Any( BiffHelper::calcDoubleFromError( BIFF_ERR_NA ) ) ); + else + maResults.clear(); + maCurrIt = maResults.begin(); +} + +// ============================================================================ + +ExternalLink::ExternalLink( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + meLinkType( LINKTYPE_UNKNOWN ) +{ +} + +void ExternalLink::importExternalReference( const AttributeList& rAttribs ) +{ + maRelId = rAttribs.getString( R_TOKEN( id ) ); +} + +void ExternalLink::importExternalBook( const Relations& rRelations, const AttributeList& rAttribs ) +{ + OUString aTargetUrl = rRelations.getTargetFromRelId( rAttribs.getString( R_TOKEN( id ) ) ); + setExternalTargetUrl( aTargetUrl ); +} + +void ExternalLink::importSheetName( const AttributeList& rAttribs ) +{ + OUString aSheetName = rAttribs.getString( XML_val ); + OSL_ENSURE( aSheetName.getLength() > 0, "ExternalLink::importSheetName - empty sheet name" ); + if( meLinkType == LINKTYPE_EXTERNAL ) + maSheetIndexes.push_back( getWorksheets().insertExternalSheet( maTargetUrl, aSheetName ) ); +} + +void ExternalLink::importDefinedName( const AttributeList& rAttribs ) +{ + createExternalName()->importDefinedName( rAttribs ); +} + +void ExternalLink::importDdeLink( const AttributeList& rAttribs ) +{ + OUString aDdeService = rAttribs.getString( XML_ddeService ); + OUString aDdeTopic = rAttribs.getString( XML_ddeTopic ); + setDdeOleTargetUrl( aDdeService, aDdeTopic, LINKTYPE_DDE ); +} + +ExternalNameRef ExternalLink::importDdeItem( const AttributeList& rAttribs ) +{ + ExternalNameRef xExtName = createExternalName(); + xExtName->importDdeItem( rAttribs ); + return xExtName; +} + +void ExternalLink::importOleLink( const Relations& rRelations, const AttributeList& rAttribs ) +{ + OUString aProgId = rAttribs.getString( XML_progId ); + OUString aTargetUrl = rRelations.getTargetFromRelId( rAttribs.getString( R_TOKEN( id ) ) ); + setDdeOleTargetUrl( aProgId, aTargetUrl, LINKTYPE_OLE ); +} + +ExternalNameRef ExternalLink::importOleItem( const AttributeList& rAttribs ) +{ + ExternalNameRef xExtName = createExternalName(); + xExtName->importOleItem( rAttribs ); + return xExtName; +} + +void ExternalLink::importExternalRef( RecordInputStream& rStrm ) +{ + rStrm >> maRelId; +} + +void ExternalLink::importExternalSelf( RecordInputStream& ) +{ + meLinkType = LINKTYPE_SELF; +} + +void ExternalLink::importExternalBook( const Relations& rRelations, RecordInputStream& rStrm ) +{ + switch( rStrm.readuInt16() ) + { + case OOBIN_EXTERNALBOOK_BOOK: + { + OUString aTargetUrl = rRelations.getTargetFromRelId( rStrm.readString() ); + setExternalTargetUrl( aTargetUrl ); + } + break; + case OOBIN_EXTERNALBOOK_DDE: + { + OUString aDdeService, aDdeTopic; + rStrm >> aDdeService >> aDdeTopic; + setDdeOleTargetUrl( aDdeService, aDdeTopic, LINKTYPE_DDE ); + } + break; + case OOBIN_EXTERNALBOOK_OLE: + { + OUString aTargetUrl = rRelations.getTargetFromRelId( rStrm.readString() ); + OUString aProgId = rStrm.readString(); + setDdeOleTargetUrl( aProgId, aTargetUrl, LINKTYPE_OLE ); + } + break; + default: + OSL_ENSURE( false, "ExternalLink::importExternalBook - unknown link type" ); + } +} + +void ExternalLink::importExtSheetNames( RecordInputStream& rStrm ) +{ + // load external sheet names and create the linked sheets in the Calc document + OSL_ENSURE( meLinkType == LINKTYPE_EXTERNAL, "ExternalLink::importExtSheetNames - invalid link type" ); + if( meLinkType == LINKTYPE_EXTERNAL ) + { + WorksheetBuffer& rWorksheets = getWorksheets(); + for( sal_Int32 nSheet = 0, nCount = rStrm.readInt32(); rStrm.isValid() && (nSheet < nCount); ++nSheet ) + { + OUString aSheetName = rStrm.readString(); + OSL_ENSURE( aSheetName.getLength() > 0, "ExternalLink::importExtSheetNames - empty sheet name" ); + maSheetIndexes.push_back( rWorksheets.insertExternalSheet( maTargetUrl, aSheetName ) ); + } + } +} + +ExternalNameRef ExternalLink::importExternalName( RecordInputStream& rStrm ) +{ + ExternalNameRef xExtName = createExternalName(); + xExtName->importExternalName( rStrm ); + return xExtName; +} + +void ExternalLink::importExternSheet( BiffInputStream& rStrm ) +{ + OStringBuffer aTargetBuffer( rStrm.readByteString( false ) ); + // references to own sheets have wrong string length field (off by 1) + if( (aTargetBuffer.getLength() > 0) && (aTargetBuffer[ 0 ] == 3) ) + aTargetBuffer.append( static_cast< sal_Char >( rStrm.readuInt8() ) ); + // parse the encoded URL + OUString aBiffTarget = OStringToOUString( aTargetBuffer.makeStringAndClear(), getTextEncoding() ); + OUString aSheetName = parseBiffTargetUrl( aBiffTarget ); + switch( meLinkType ) + { + case LINKTYPE_INTERNAL: + maSheetIndexes.push_back( getWorksheets().getFinalSheetIndex( aSheetName ) ); + break; + case LINKTYPE_EXTERNAL: + maSheetIndexes.push_back( getWorksheets().insertExternalSheet( maTargetUrl, aSheetName ) ); + break; + default:; + } +} + +void ExternalLink::importExternalBook( BiffInputStream& rStrm ) +{ + OUString aTarget; + sal_uInt16 nSheetCount; + rStrm >> nSheetCount; + if( rStrm.getRecLeft() == 2 ) + { + if( rStrm.readuInt8() == 1 ) + { + sal_Char cChar = static_cast< sal_Char >( rStrm.readuInt8() ); + if( cChar != 0 ) + aTarget = OStringToOUString( OString( cChar ), getTextEncoding() ); + } + } + else if( rStrm.getRecLeft() >= 3 ) + { + aTarget = rStrm.readUniString(); + } + + // parse the encoded URL + OUString aDummySheetName = parseBiffTargetUrl( aTarget ); + OSL_ENSURE( aDummySheetName.getLength() == 0, "ExternalLink::importExternalBook - sheet name in encoded URL" ); + (void)aDummySheetName; // prevent compiler warning + + // load external sheet names and create the linked sheets in the Calc document + if( meLinkType == LINKTYPE_EXTERNAL ) + { + WorksheetBuffer& rWorksheets = getWorksheets(); + for( sal_uInt16 nSheet = 0; rStrm.isValid() && (nSheet < nSheetCount); ++nSheet ) + { + OUString aSheetName = rStrm.readUniString(); + OSL_ENSURE( aSheetName.getLength() > 0, "ExternalLink::importExternalBook - empty sheet name" ); + maSheetIndexes.push_back( rWorksheets.insertExternalSheet( maTargetUrl, aSheetName ) ); + } + } +} + +void ExternalLink::importExternalName( BiffInputStream& rStrm ) +{ + ExternalNameRef xExtName = createExternalName(); + xExtName->importExternalName( rStrm ); + switch( meLinkType ) + { + case LINKTYPE_DDE: + OSL_ENSURE( !xExtName->isOleObject(), "ExternalLink::importExternalName - OLE object in DDE link" ); + break; + case LINKTYPE_OLE: + OSL_ENSURE( xExtName->isOleObject(), "ExternalLink::importExternalName - anything but OLE object in OLE link" ); + break; + case LINKTYPE_MAYBE_DDE_OLE: + meLinkType = xExtName->isOleObject() ? LINKTYPE_OLE : LINKTYPE_DDE; + break; + default: + OSL_ENSURE( !xExtName->isOleObject(), "ExternalLink::importExternalName - OLE object in external name" ); + } +} + +sal_Int32 ExternalLink::getSheetIndex( sal_Int32 nTabId ) const +{ + OSL_ENSURE( (nTabId == 0) || (getFilterType() == FILTER_OOX) || (getBiff() == BIFF8), + "ExternalLink::getSheetIndex - invalid sheet index" ); + return ((0 <= nTabId) && (static_cast< size_t >( nTabId ) < maSheetIndexes.size())) ? + maSheetIndexes[ static_cast< size_t >( nTabId ) ] : -1; +} + +void ExternalLink::getSheetRange( LinkSheetRange& orSheetRange, sal_Int32 nTabId1, sal_Int32 nTabId2 ) const +{ + orSheetRange.setDeleted(); + switch( meLinkType ) + { + case LINKTYPE_SELF: + case LINKTYPE_INTERNAL: + orSheetRange.set( nTabId1, nTabId2 ); + break; + case LINKTYPE_EXTERNAL: switch( getFilterType() ) + { + case FILTER_OOX: + // OOBIN: passed indexes point into sheet list of EXTSHEETLIST + orSheetRange.set( getSheetIndex( nTabId1 ), getSheetIndex( nTabId2 ) ); + break; + case FILTER_BIFF: + switch( getBiff() ) + { + case BIFF2: + case BIFF3: + case BIFF4: + orSheetRange.set( getSheetIndex( nTabId1 ), getSheetIndex( nTabId2 ) ); + break; + case BIFF5: + // BIFF5: first sheet from this external link, last sheet is passed in nTabId2 + if( const ExternalLink* pExtLink2 = getExternalLinks().getExternalLink( nTabId2 ).get() ) + if( (pExtLink2->getLinkType() == LINKTYPE_EXTERNAL) && (maTargetUrl == pExtLink2->getTargetUrl()) ) + orSheetRange.set( getSheetIndex(), pExtLink2->getSheetIndex() ); + break; + case BIFF8: + // BIFF8: passed indexes point into sheet list of EXTERNALBOOK + orSheetRange.set( getSheetIndex( nTabId1 ), getSheetIndex( nTabId2 ) ); + break; + case BIFF_UNKNOWN: break; + } + break; + case FILTER_UNKNOWN: + break; + } + break; + + default:; + } +} + +ExternalNameRef ExternalLink::getNameByIndex( sal_Int32 nIndex ) const +{ + return maExtNames.get( nIndex ); +} + +// private -------------------------------------------------------------------- + +void ExternalLink::setExternalTargetUrl( const OUString& rTargetUrl ) +{ + maTargetUrl = getBaseFilter().getAbsoluteUrl( rTargetUrl ); + meLinkType = (maTargetUrl.getLength() > 0) ? LINKTYPE_EXTERNAL : LINKTYPE_UNKNOWN; + OSL_ENSURE( meLinkType == LINKTYPE_EXTERNAL, "ExternalLink::setExternalTargetUrl - empty target URL" ); +} + +void ExternalLink::setDdeOleTargetUrl( const OUString& rClassName, const OUString& rTargetUrl, ExternalLinkType eLinkType ) +{ + maClassName = rClassName; + maTargetUrl = rTargetUrl; + meLinkType = ((maClassName.getLength() > 0) && (maTargetUrl.getLength() > 0)) ? eLinkType : LINKTYPE_UNKNOWN; + OSL_ENSURE( meLinkType == eLinkType, "ExternalLink::setDdeOleTargetUrl - missing classname or target" ); +} + +OUString ExternalLink::parseBiffTargetUrl( const OUString& rBiffTargetUrl ) +{ + OUString aClassName, aTargetUrl, aSheetName; + meLinkType = LINKTYPE_UNKNOWN; + if( getAddressConverter().parseBiffTargetUrl( aClassName, aTargetUrl, aSheetName, rBiffTargetUrl ) ) + { + if( aClassName.getLength() > 0 ) + { + setDdeOleTargetUrl( aClassName, aTargetUrl, LINKTYPE_MAYBE_DDE_OLE ); + } + else if( aTargetUrl.getLength() == 0 ) + { + meLinkType = (aSheetName.getLength() > 0) ? LINKTYPE_INTERNAL : LINKTYPE_SELF; + } + else if( (aTargetUrl.getLength() == 1) && (aTargetUrl[ 0 ] == ':') ) + { + if( getBiff() >= BIFF4 ) + meLinkType = LINKTYPE_ANALYSIS; + } + else if( (aTargetUrl.getLength() == 1) && (aTargetUrl[ 0 ] == ' ') ) + { + meLinkType = LINKTYPE_UNKNOWN; + } + else + { + setExternalTargetUrl( aTargetUrl ); + } + } + return aSheetName; +} + +ExternalNameRef ExternalLink::createExternalName() +{ + ExternalNameRef xExtName( new ExternalName( *this, getSheetIndex() ) ); + maExtNames.push_back( xExtName ); + return xExtName; +} + +// ============================================================================ + +OoxRefSheets::OoxRefSheets() : + mnExtRefId( -1 ), + mnTabId1( -1 ), + mnTabId2( -1 ) +{ +} + +void OoxRefSheets::readOobData( RecordInputStream& rStrm ) +{ + rStrm >> mnExtRefId >> mnTabId1 >> mnTabId2; +} + +void OoxRefSheets::readBiff8Data( BiffInputStream& rStrm ) +{ + mnExtRefId = rStrm.readuInt16(); + mnTabId1 = rStrm.readInt16(); + mnTabId2 = rStrm.readInt16(); +} + +// ---------------------------------------------------------------------------- + +ExternalLinkBuffer::ExternalLinkBuffer( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + mbUseRefSheets( false ) +{ +} + +ExternalLinkRef ExternalLinkBuffer::importExternalReference( const AttributeList& rAttribs ) +{ + ExternalLinkRef xExtLink = createExternalLink(); + xExtLink->importExternalReference( rAttribs ); + return xExtLink; +} + +ExternalLinkRef ExternalLinkBuffer::importExternalRef( RecordInputStream& rStrm ) +{ + mbUseRefSheets = true; + ExternalLinkRef xExtLink = createExternalLink(); + xExtLink->importExternalRef( rStrm ); + return xExtLink; +} + +void ExternalLinkBuffer::importExternalSelf( RecordInputStream& rStrm ) +{ + mbUseRefSheets = true; + createExternalLink()->importExternalSelf( rStrm ); +} + +void ExternalLinkBuffer::importExternalSheets( RecordInputStream& rStrm ) +{ + OSL_ENSURE( mbUseRefSheets, "ExternalLinkBuffer::importExternalSheets - missing EXTERNALREFS records" ); + mbUseRefSheets = true; + OSL_ENSURE( maRefSheets.empty(), "ExternalLinkBuffer::importExternalSheets - multiple EXTERNALSHEETS records" ); + maRefSheets.clear(); + sal_Int32 nRefCount; + rStrm >> nRefCount; + size_t nMaxCount = getLimitedValue< size_t, sal_Int32 >( nRefCount, 0, rStrm.getRecLeft() / 12 ); + maRefSheets.reserve( nMaxCount ); + for( size_t nRefId = 0; rStrm.isValid() && (nRefId < nMaxCount); ++nRefId ) + { + OoxRefSheets aRefSheets; + aRefSheets.readOobData( rStrm ); + maRefSheets.push_back( aRefSheets ); + } +} + +ExternalLinkRef ExternalLinkBuffer::importExternSheet( BiffInputStream& rStrm ) +{ + OSL_ENSURE( getBiff() <= BIFF5, "ExternalLinkBuffer::importExternSheet - wrong BIFF version" ); + ExternalLinkRef xExtLink = createExternalLink(); + xExtLink->importExternSheet( rStrm ); + return xExtLink; +} + +ExternalLinkRef ExternalLinkBuffer::importExternalBook( BiffInputStream& rStrm ) +{ + ExternalLinkRef xExtLink = createExternalLink(); + xExtLink->importExternalBook( rStrm ); + return xExtLink; +} + +void ExternalLinkBuffer::importExternalName( BiffInputStream& rStrm ) +{ + if( !maExtLinks.empty() ) + maExtLinks.back()->importExternalName( rStrm ); +} + +void ExternalLinkBuffer::importExternSheet8( BiffInputStream& rStrm ) +{ + OSL_ENSURE( getBiff() == BIFF8, "ExternalLinkBuffer::importExternSheet - wrong BIFF version" ); + OSL_ENSURE( maRefSheets.empty(), "ExternalLinkBuffer::importExternSheet - multiple EXTERNSHEET records" ); + maRefSheets.clear(); + sal_uInt16 nRefCount; + rStrm >> nRefCount; + maRefSheets.reserve( nRefCount ); + for( sal_uInt16 nRefId = 0; rStrm.isValid() && (nRefId < nRefCount); ++nRefId ) + { + OoxRefSheets aRefSheets; + aRefSheets.readBiff8Data( rStrm ); + maRefSheets.push_back( aRefSheets ); + } +} + +ExternalLinkRef ExternalLinkBuffer::getExternalLink( sal_Int32 nRefId ) const +{ + ExternalLinkRef xExtLink; + switch( getFilterType() ) + { + case FILTER_OOX: + // OOXML: one-based index + if( !mbUseRefSheets ) + xExtLink = maExtLinks.get( nRefId - 1 ); + // OOBIN: zero-based index into ref-sheets list + else if( const OoxRefSheets* pRefSheets = getRefSheets( nRefId ) ) + xExtLink = maExtLinks.get( pRefSheets->mnExtRefId ); + break; + case FILTER_BIFF: + switch( getBiff() ) + { + case BIFF2: + case BIFF3: + case BIFF4: + // one-based index to EXTERNSHEET records + xExtLink = maExtLinks.get( nRefId - 1 ); + break; + case BIFF5: + if( nRefId < 0 ) + { + // internal links in formula tokens have negative index + xExtLink = maExtLinks.get( -nRefId - 1 ); + if( xExtLink.get() && !xExtLink->isInternalLink() ) + xExtLink.reset(); + } + else + { + // one-based index to EXTERNSHEET records + xExtLink = maExtLinks.get( nRefId - 1 ); + } + break; + case BIFF8: + // zero-based index into REF list in EXTERNSHEET record + if( const OoxRefSheets* pRefSheets = getRefSheets( nRefId ) ) + xExtLink = maExtLinks.get( pRefSheets->mnExtRefId ); + break; + case BIFF_UNKNOWN: break; + } + break; + case FILTER_UNKNOWN: break; + } + return xExtLink; +} + +LinkSheetRange ExternalLinkBuffer::getSheetRange( sal_Int32 nRefId, sal_Int16 nTabId1, sal_Int16 nTabId2 ) const +{ + OSL_ENSURE( getBiff() <= BIFF5, "ExternalLinkBuffer::getSheetRange - wrong BIFF version" ); + LinkSheetRange aSheetRange; + if( const ExternalLink* pExtLink = getExternalLink( nRefId ).get() ) + pExtLink->getSheetRange( aSheetRange, nTabId1, nTabId2 ); + return aSheetRange; +} + +LinkSheetRange ExternalLinkBuffer::getSheetRange( sal_Int32 nRefId ) const +{ + OSL_ENSURE( ((getFilterType() == FILTER_OOX) && mbUseRefSheets) || (getBiff() == BIFF8), "ExternalLinkBuffer::getSheetRange - wrong BIFF version" ); + LinkSheetRange aSheetRange; + if( const ExternalLink* pExtLink = getExternalLink( nRefId ).get() ) + if( const OoxRefSheets* pRefSheets = getRefSheets( nRefId ) ) + pExtLink->getSheetRange( aSheetRange, pRefSheets->mnTabId1, pRefSheets->mnTabId2 ); + return aSheetRange; +} + +// private -------------------------------------------------------------------- + +ExternalLinkRef ExternalLinkBuffer::createExternalLink() +{ + ExternalLinkRef xExtLink( new ExternalLink( *this ) ); + maExtLinks.push_back( xExtLink ); + return xExtLink; +} + +const OoxRefSheets* ExternalLinkBuffer::getRefSheets( sal_Int32 nRefId ) const +{ + return ((0 <= nRefId) && (static_cast< size_t >( nRefId ) < maRefSheets.size())) ? + &maRefSheets[ static_cast< size_t >( nRefId ) ] : 0; +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/externallinkfragment.cxx b/oox/source/xls/externallinkfragment.cxx new file mode 100644 index 000000000000..b291a6ad7147 --- /dev/null +++ b/oox/source/xls/externallinkfragment.cxx @@ -0,0 +1,392 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: externallinkfragment.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:08 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/externallinkfragment.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/core/recordparser.hxx" +#include "oox/xls/biffinputstream.hxx" +#include "oox/xls/defnamesbuffer.hxx" +#include "oox/xls/sheetdatacontext.hxx" +#include "oox/xls/unitconverter.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::xml::sax::XFastContextHandler; +using ::oox::core::RecordContextRef; +using ::oox::core::Relation; + +namespace oox { +namespace xls { + +// ============================================================================ + +OoxExternalLinkFragment::OoxExternalLinkFragment( const WorkbookHelper& rHelper, + const OUString& rFragmentPath, ExternalLink& rExtLink ) : + OoxWorkbookFragmentBase( rHelper, rFragmentPath ), + mrExtLink( rExtLink ), + mnResultType( XML_TOKEN_INVALID ) +{ +} + +bool OoxExternalLinkFragment::onCanCreateContext( sal_Int32 nElement ) const +{ + switch( getCurrentContext() ) + { + case XML_ROOT_CONTEXT: + return (nElement == XLS_TOKEN( externalLink )); + case XLS_TOKEN( externalLink ): + return (nElement == XLS_TOKEN( externalBook )) || + (nElement == XLS_TOKEN( ddeLink )) || + (nElement == XLS_TOKEN( oleLink )); + case XLS_TOKEN( externalBook ): + return (nElement == XLS_TOKEN( sheetNames )) || + (nElement == XLS_TOKEN( definedNames )) || + (nElement == XLS_TOKEN( sheetDataSet )); + case XLS_TOKEN( sheetNames ): + return (nElement == XLS_TOKEN( sheetName )); + case XLS_TOKEN( definedNames ): + return (nElement == XLS_TOKEN( definedName )); + case XLS_TOKEN( sheetDataSet ): + return (nElement == XLS_TOKEN( sheetData )); + case XLS_TOKEN( ddeLink ): + return (nElement == XLS_TOKEN( ddeItems )); + case XLS_TOKEN( ddeItems ): + return (nElement == XLS_TOKEN( ddeItem )); + case XLS_TOKEN( ddeItem ): + return (nElement == XLS_TOKEN( values )); + case XLS_TOKEN( values ): + return (nElement == XLS_TOKEN( value )); + case XLS_TOKEN( value ): + return (nElement == XLS_TOKEN( val )); + case XLS_TOKEN( oleLink ): + return (nElement == XLS_TOKEN( oleItems )); + case XLS_TOKEN( oleItems ): + return (nElement == XLS_TOKEN( oleItem )); + } + return false; +} + +Reference< XFastContextHandler > OoxExternalLinkFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( nElement ) + { + case XLS_TOKEN( sheetData ): + if( mrExtLink.getLinkType() == LINKTYPE_EXTERNAL ) + { + sal_Int32 nSheet = mrExtLink.getSheetIndex( rAttribs.getInteger( XML_sheetId, -1 ) ); + Reference< XFastContextHandler > xHandler; + ::rtl::Reference< OoxExternalSheetDataContext > xContext( new OoxExternalSheetDataContext( *this, SHEETTYPE_WORKSHEET, nSheet ) ); + if( xContext->isValidSheet() ) + xHandler.set( xContext.get() ); + return xHandler; + } + break; + } + return this; +} + +void OoxExternalLinkFragment::onStartElement( const AttributeList& rAttribs ) +{ + switch( getCurrentContext() ) + { + case XLS_TOKEN( externalBook ): mrExtLink.importExternalBook( getRelations(), rAttribs ); break; + case XLS_TOKEN( sheetName ): mrExtLink.importSheetName( rAttribs ); break; + case XLS_TOKEN( definedName ): mrExtLink.importDefinedName( rAttribs ); break; + case XLS_TOKEN( ddeLink ): mrExtLink.importDdeLink( rAttribs ); break; + case XLS_TOKEN( ddeItem ): mxExtName = mrExtLink.importDdeItem( rAttribs ); break; + case XLS_TOKEN( values ): if( mxExtName.get() ) mxExtName->importValues( rAttribs ); break; + case XLS_TOKEN( value ): mnResultType = rAttribs.getToken( XML_t, XML_n ); break; + case XLS_TOKEN( oleLink ): mrExtLink.importOleLink( getRelations(), rAttribs ); break; + case XLS_TOKEN( oleItem ): mxExtName = mrExtLink.importOleItem( rAttribs ); break; + } +} + +void OoxExternalLinkFragment::onEndElement( const OUString& rChars ) +{ + switch( getCurrentContext() ) + { + case XLS_TOKEN( val ): + maResultValue = rChars; + break; + case XLS_TOKEN( value ): + if( mxExtName.get() ) switch( mnResultType ) + { + case XML_b: + mxExtName->appendResultValue( maResultValue.toDouble() ); + break; + case XML_e: + mxExtName->appendResultValue( BiffHelper::calcDoubleFromError( getUnitConverter().calcBiffErrorCode( maResultValue ) ) ); + break; + case XML_n: + mxExtName->appendResultValue( maResultValue.toDouble() ); + break; + case XML_str: + mxExtName->appendResultValue( maResultValue ); + break; + default: + mxExtName->appendResultValue( BiffHelper::calcDoubleFromError( BIFF_ERR_NA ) ); + } + break; + } +} + +bool OoxExternalLinkFragment::onCanCreateRecordContext( sal_Int32 nRecId ) +{ + /* Weird things are going on in this fragment... + + Without external names, several EXTSHEETDATA/EXTSHEETDATA_END contexts + contain the external cells. They are not preceded by a SHEETDATASET + context record, but a SHEETDATASET_END record occurs at the end of the + stream. In this case we have to start a SHEETDATASET context on-the-fly + to keep the context stack valid. + */ + if( (getCurrentContext() == OOBIN_ID_EXTERNALBOOK) && (nRecId == OOBIN_ID_EXTSHEETDATA) ) + getRecordParser().pushContext( OOBIN_ID_SHEETDATASET, this ); + + /* With external names, SHEETDATASET contexts are opened after each + external name, but not closed before a new external name starts. Here + we have to close the SHEETDATASET context before. + */ + else if( (getCurrentContext() == OOBIN_ID_SHEETDATASET) && (nRecId != OOBIN_ID_EXTSHEETDATA) ) + getRecordParser().popContext(); + + switch( getCurrentContext() ) + { + case XML_ROOT_CONTEXT: + return (nRecId == OOBIN_ID_EXTERNALBOOK); + case OOBIN_ID_EXTERNALBOOK: + return (nRecId == OOBIN_ID_EXTSHEETNAMES) || + (nRecId == OOBIN_ID_EXTERNALNAME) || + (nRecId == OOBIN_ID_EXTERNALNAMEFLAGS) || + (nRecId == OOBIN_ID_SHEETDATASET) || + (nRecId == OOBIN_ID_DDEITEMVALUES); + case OOBIN_ID_SHEETDATASET: + return (nRecId == OOBIN_ID_EXTSHEETDATA); + case OOBIN_ID_DDEITEMVALUES: + return (nRecId == OOBIN_ID_DDEITEM_BOOL) || + (nRecId == OOBIN_ID_DDEITEM_DOUBLE) || + (nRecId == OOBIN_ID_DDEITEM_ERROR) || + (nRecId == OOBIN_ID_DDEITEM_STRING); + } + return false; +} + +RecordContextRef OoxExternalLinkFragment::onCreateRecordContext( sal_Int32 nRecId, RecordInputStream& rStrm ) +{ + switch( nRecId ) + { + case OOBIN_ID_EXTSHEETDATA: + if( mrExtLink.getLinkType() == LINKTYPE_EXTERNAL ) + { + sal_Int32 nSheet = mrExtLink.getSheetIndex( rStrm.readInt32() ); + RecordContextRef xRecContext; + ::rtl::Reference< OoxExternalSheetDataContext > xContext( new OoxExternalSheetDataContext( *this, SHEETTYPE_WORKSHEET, nSheet ) ); + if( xContext->isValidSheet() ) + xRecContext.set( xContext.get() ); + return xRecContext; + } + break; + } + return this; +} + +void OoxExternalLinkFragment::onStartRecord( RecordInputStream& rStrm ) +{ + switch( getCurrentContext() ) + { + case OOBIN_ID_EXTERNALBOOK: mrExtLink.importExternalBook( getRelations(), rStrm ); break; + case OOBIN_ID_EXTSHEETNAMES: mrExtLink.importExtSheetNames( rStrm ); break; + case OOBIN_ID_EXTERNALNAME: mxExtName = mrExtLink.importExternalName( rStrm ); break; + case OOBIN_ID_EXTERNALNAMEFLAGS: if( mxExtName.get() ) mxExtName->importExternalNameFlags( rStrm ); break; + case OOBIN_ID_DDEITEMVALUES: if( mxExtName.get() ) mxExtName->importDdeItemValues( rStrm ); break; + case OOBIN_ID_DDEITEM_BOOL: if( mxExtName.get() ) mxExtName->importDdeItemBool( rStrm ); break; + case OOBIN_ID_DDEITEM_DOUBLE: if( mxExtName.get() ) mxExtName->importDdeItemDouble( rStrm ); break; + case OOBIN_ID_DDEITEM_ERROR: if( mxExtName.get() ) mxExtName->importDdeItemError( rStrm ); break; + case OOBIN_ID_DDEITEM_STRING: if( mxExtName.get() ) mxExtName->importDdeItemString( rStrm ); break; + } +} + +// ============================================================================ + +BiffExternalLinkFragment::BiffExternalLinkFragment( const WorkbookHelper& rHelper, bool bImportDefNames ) : + BiffWorkbookFragmentBase( rHelper ), + mbImportDefNames( bImportDefNames ) +{ +} + +BiffExternalLinkFragment::~BiffExternalLinkFragment() +{ +} + +bool BiffExternalLinkFragment::importFragment( BiffInputStream& rStrm ) +{ + // process all record in this sheet fragment + while( rStrm.startNextRecord() && (rStrm.getRecId() != BIFF_ID_EOF) ) + { + if( isBofRecord( rStrm.getRecId() ) ) + skipFragment( rStrm ); // skip unknown embedded fragments + else + importRecord( rStrm ); + } + return rStrm.isValid() && (rStrm.getRecId() == BIFF_ID_EOF); +} + +void BiffExternalLinkFragment::importRecord( BiffInputStream& rStrm ) +{ + sal_uInt16 nRecId = rStrm.getRecId(); + switch( getBiff() ) + { + case BIFF2: switch( nRecId ) + { + case BIFF2_ID_EXTERNALNAME: importExternalName( rStrm ); break; + case BIFF_ID_EXTERNSHEET: importExternSheet( rStrm ); break; + case BIFF2_ID_DEFINEDNAME: importDefinedName( rStrm ); break; + } + break; + case BIFF3: switch( nRecId ) + { + case BIFF_ID_CRN: importCrn( rStrm ); break; + case BIFF3_ID_EXTERNALNAME: importExternalName( rStrm ); break; + case BIFF_ID_EXTERNSHEET: importExternSheet( rStrm ); break; + case BIFF3_ID_DEFINEDNAME: importDefinedName( rStrm ); break; + case BIFF_ID_XCT: importXct( rStrm ); break; + } + break; + case BIFF4: switch( nRecId ) + { + case BIFF_ID_CRN: importCrn( rStrm ); break; + case BIFF3_ID_EXTERNALNAME: importExternalName( rStrm ); break; + case BIFF_ID_EXTERNSHEET: importExternSheet( rStrm ); break; + case BIFF3_ID_DEFINEDNAME: importDefinedName( rStrm ); break; + case BIFF_ID_XCT: importXct( rStrm ); break; + } + break; + case BIFF5: switch( nRecId ) + { + case BIFF_ID_CRN: importCrn( rStrm ); break; + case BIFF5_ID_EXTERNALNAME: importExternalName( rStrm ); break; + case BIFF_ID_EXTERNSHEET: importExternSheet( rStrm ); break; + case BIFF5_ID_DEFINEDNAME: importDefinedName( rStrm ); break; + case BIFF_ID_XCT: importXct( rStrm ); break; + } + break; + case BIFF8: switch( nRecId ) + { + case BIFF_ID_CRN: importCrn( rStrm ); break; + case BIFF_ID_EXTERNALBOOK: importExternalBook( rStrm ); break; + case BIFF5_ID_EXTERNALNAME: importExternalName( rStrm ); break; + case BIFF_ID_EXTERNSHEET: importExternSheet( rStrm ); break; + case BIFF5_ID_DEFINEDNAME: importDefinedName( rStrm ); break; + case BIFF_ID_XCT: importXct( rStrm ); break; + } + break; + case BIFF_UNKNOWN: break; + } +} + +void BiffExternalLinkFragment::finalizeImport() +{ + getDefinedNames().finalizeImport(); +} + +// private -------------------------------------------------------------------- + +void BiffExternalLinkFragment::importExternSheet( BiffInputStream& rStrm ) +{ + mxContext.reset(); + if( getBiff() == BIFF8 ) + getExternalLinks().importExternSheet8( rStrm ); + else + mxExtLink = getExternalLinks().importExternSheet( rStrm ); +} + +void BiffExternalLinkFragment::importExternalBook( BiffInputStream& rStrm ) +{ + mxContext.reset(); + mxExtLink = getExternalLinks().importExternalBook( rStrm ); +} + +void BiffExternalLinkFragment::importExternalName( BiffInputStream& rStrm ) +{ + if( mxExtLink.get() ) + mxExtLink->importExternalName( rStrm ); +} + +void BiffExternalLinkFragment::importXct( BiffInputStream& rStrm ) +{ + mxContext.reset(); + if( mxExtLink.get() && (mxExtLink->getLinkType() == LINKTYPE_EXTERNAL) ) + { + sal_Int32 nSheet = -1; + switch( getBiff() ) + { + case BIFF2: + break; + case BIFF3: + case BIFF4: + case BIFF5: + nSheet = mxExtLink->getSheetIndex(); + break; + case BIFF8: + rStrm.skip( 2 ); + nSheet = mxExtLink->getSheetIndex( rStrm.readInt16() ); + break; + case BIFF_UNKNOWN: break; + } + + // create a sheet data context to import the CRN records and set the cached cell values + mxContext.reset( new BiffExternalSheetDataContext( *this, SHEETTYPE_WORKSHEET, nSheet ) ); + if( !mxContext->isValidSheet() ) + mxContext.reset(); + } +} + +void BiffExternalLinkFragment::importCrn( BiffInputStream& rStrm ) +{ + if( mxContext.get() ) + mxContext->importCrn( rStrm ); +} + +void BiffExternalLinkFragment::importDefinedName( BiffInputStream& rStrm ) +{ + if( mbImportDefNames ) + getDefinedNames().importDefinedName( rStrm ); +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/formulabase.cxx b/oox/source/xls/formulabase.cxx new file mode 100644 index 000000000000..4c5cb1bdfabc --- /dev/null +++ b/oox/source/xls/formulabase.cxx @@ -0,0 +1,1459 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: formulabase.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:08 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/formulabase.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "oox/helper/containerhelper.hxx" +#include "oox/helper/recordinputstream.hxx" +#include "oox/core/filterbase.hxx" +#include "oox/xls/biffinputstream.hxx" + +using ::rtl::OString; +using ::rtl::OStringBuffer; +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::rtl::OStringToOUString; +using ::rtl::OUStringToOString; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::table::CellAddress; +using ::com::sun::star::table::CellRangeAddress; +using ::com::sun::star::sheet::SingleReference; +using ::com::sun::star::sheet::ComplexReference; +using ::com::sun::star::sheet::FormulaToken; +using ::com::sun::star::sheet::FormulaOpCodeMapEntry; +using ::com::sun::star::sheet::XSpreadsheetDocument; +using ::com::sun::star::sheet::XFormulaOpCodeMapper; +using ::com::sun::star::sheet::XFormulaTokens; +using namespace ::com::sun::star::sheet::ReferenceFlags; + +namespace oox { +namespace xls { + +// reference helpers ========================================================== + +BinSingleRef2d::BinSingleRef2d() : + mnCol( 0 ), + mnRow( 0 ), + mbColRel( false ), + mbRowRel( false ) +{ +} + +void BinSingleRef2d::setOobData( sal_uInt16 nCol, sal_Int32 nRow, bool bRelativeAsOffset ) +{ + mnCol = nCol & OOBIN_TOK_REF_COLMASK; + mnRow = nRow & OOBIN_TOK_REF_ROWMASK; + mbColRel = getFlag( nCol, OOBIN_TOK_REF_COLREL ); + mbRowRel = getFlag( nCol, OOBIN_TOK_REF_ROWREL ); + if( bRelativeAsOffset && mbColRel && (mnCol > (OOBIN_TOK_REF_COLMASK >> 1)) ) + mnCol -= (OOBIN_TOK_REF_COLMASK + 1); + if( bRelativeAsOffset && mbRowRel && (mnRow > (OOBIN_TOK_REF_ROWMASK >> 1)) ) + mnRow -= (OOBIN_TOK_REF_ROWMASK + 1); +} + +void BinSingleRef2d::setBiff2Data( sal_uInt8 nCol, sal_uInt16 nRow, bool bRelativeAsOffset ) +{ + mnCol = nCol; + mnRow = nRow & BIFF_TOK_REF_ROWMASK; + mbColRel = getFlag( nRow, BIFF_TOK_REF_COLREL ); + mbRowRel = getFlag( nRow, BIFF_TOK_REF_ROWREL ); + if( bRelativeAsOffset && mbColRel && (mnCol >= 0x80) ) + mnCol -= 0x100; + if( bRelativeAsOffset && mbRowRel && (mnRow > (BIFF_TOK_REF_ROWMASK >> 1)) ) + mnRow -= (BIFF_TOK_REF_ROWMASK + 1); +} + +void BinSingleRef2d::setBiff8Data( sal_uInt16 nCol, sal_uInt16 nRow, bool bRelativeAsOffset ) +{ + mnCol = nCol & BIFF_TOK_REF_COLMASK; + mnRow = nRow; + mbColRel = getFlag( nCol, BIFF_TOK_REF_COLREL ); + mbRowRel = getFlag( nCol, BIFF_TOK_REF_ROWREL ); + if( bRelativeAsOffset && mbColRel && (mnCol > (BIFF_TOK_REF_COLMASK >> 1)) ) + mnCol -= (BIFF_TOK_REF_COLMASK + 1); + if( bRelativeAsOffset && mbRowRel && (mnRow >= 0x8000) ) + mnRow -= 0x10000; +} + +void BinSingleRef2d::readOobData( RecordInputStream& rStrm, bool bRelativeAsOffset ) +{ + sal_Int32 nRow; + sal_uInt16 nCol; + rStrm >> nRow >> nCol; + setOobData( nCol, nRow, bRelativeAsOffset ); +} + +void BinSingleRef2d::readBiff2Data( BiffInputStream& rStrm, bool bRelativeAsOffset ) +{ + sal_uInt16 nRow; + sal_uInt8 nCol; + rStrm >> nRow >> nCol; + setBiff2Data( nCol, nRow, bRelativeAsOffset ); +} + +void BinSingleRef2d::readBiff8Data( BiffInputStream& rStrm, bool bRelativeAsOffset ) +{ + sal_uInt16 nRow, nCol; + rStrm >> nRow >> nCol; + setBiff8Data( nCol, nRow, bRelativeAsOffset ); +} + +// ---------------------------------------------------------------------------- + +void BinComplexRef2d::readOobData( RecordInputStream& rStrm, bool bRelativeAsOffset ) +{ + sal_Int32 nRow1, nRow2; + sal_uInt16 nCol1, nCol2; + rStrm >> nRow1 >> nRow2 >> nCol1 >> nCol2; + maRef1.setOobData( nCol1, nRow1, bRelativeAsOffset ); + maRef2.setOobData( nCol2, nRow2, bRelativeAsOffset ); +} + +void BinComplexRef2d::readBiff2Data( BiffInputStream& rStrm, bool bRelativeAsOffset ) +{ + sal_uInt16 nRow1, nRow2; + sal_uInt8 nCol1, nCol2; + rStrm >> nRow1 >> nRow2 >> nCol1 >> nCol2; + maRef1.setBiff2Data( nCol1, nRow1, bRelativeAsOffset ); + maRef2.setBiff2Data( nCol2, nRow2, bRelativeAsOffset ); +} + +void BinComplexRef2d::readBiff8Data( BiffInputStream& rStrm, bool bRelativeAsOffset ) +{ + sal_uInt16 nRow1, nRow2, nCol1, nCol2; + rStrm >> nRow1 >> nRow2 >> nCol1 >> nCol2; + maRef1.setBiff8Data( nCol1, nRow1, bRelativeAsOffset ); + maRef2.setBiff8Data( nCol2, nRow2, bRelativeAsOffset ); +} + +// function data ============================================================== + +namespace { + +const size_t FUNCINFO_CLASSCOUNT = 5; /// Number of token class entries. + +const sal_uInt8 FUNCFLAG_VOLATILE = 0x01; /// Result is volatile (e.g. NOW() function). +const sal_uInt8 FUNCFLAG_IMPORTONLY = 0x02; /// Only used in import filter. +const sal_uInt8 FUNCFLAG_EXPORTONLY = 0x04; /// Only used in export filter. +const sal_uInt8 FUNCFLAG_MACROCALL = 0x08; /// Function is simulated by macro call in Excel. +const sal_uInt8 FUNCFLAG_EXTERNAL = 0x10; /// Function is external in Calc. + +typedef ::boost::shared_ptr< FunctionInfo > FunctionInfoRef; + +struct FunctionData +{ + const sal_Char* mpcOdfFuncName; /// ODF function name. + const sal_Char* mpcOoxFuncName; /// OOXML function name. + sal_uInt16 mnOobFuncId; /// OOBIN function identifier. + sal_uInt16 mnBiffFuncId; /// BIFF function identifier. + sal_uInt8 mnMinParamCount; /// Minimum number of parameters. + sal_uInt8 mnMaxParamCount; /// Maximum number of parameters. + sal_uInt8 mnRetClass; /// BIFF token class of the return value. + sal_uInt8 mpnParamClass[ FUNCINFO_CLASSCOUNT ]; /// Expected BIFF token classes of parameters. + sal_uInt8 mnFlags; /// Additional flags. + + inline bool isSupported( bool bImportFilter ) const; +}; + +inline bool FunctionData::isSupported( bool bImportFilter ) const +{ + /* For import filters: the FUNCFLAG_EXPORTONLY flag must not be set, + for export filters: the FUNCFLAG_IMPORTONLY flag must not be set. */ + return !getFlag( mnFlags, bImportFilter ? FUNCFLAG_EXPORTONLY : FUNCFLAG_IMPORTONLY ); +} + +const sal_uInt8 R = BIFF_TOKCLASS_REF; +const sal_uInt8 V = BIFF_TOKCLASS_VAL; +const sal_uInt8 A = BIFF_TOKCLASS_ARR; +const sal_uInt8 ER = FUNCINFO_PARAM_EXCELONLY | BIFF_TOKCLASS_REF; +const sal_uInt8 EV = FUNCINFO_PARAM_EXCELONLY | BIFF_TOKCLASS_VAL; +const sal_uInt8 EA = FUNCINFO_PARAM_EXCELONLY | BIFF_TOKCLASS_ARR; +const sal_uInt8 C = FUNCINFO_PARAM_CALCONLY; +const sal_uInt8 I = FUNCINFO_PARAM_INVALID; +const sal_uInt16 NOID = SAL_MAX_UINT16; +const sal_uInt8 MX = SAL_MAX_UINT8; + +/** Functions new in BIFF2. */ +static const FunctionData saFuncTableBiff2[] = +{ + { "COUNT", "COUNT", 0, 0, 0, MX, V, { R }, 0 }, + { "IF", "IF", 1, 1, 2, 3, R, { V, R }, 0 }, + { "ISNA", "ISNA", 2, 2, 1, 1, V, { V }, 0 }, + { "ISERROR", "ISERROR", 3, 3, 1, 1, V, { V }, 0 }, + { "SUM", "SUM", 4, 4, 0, MX, V, { R }, 0 }, + { "AVERAGE", "AVERAGE", 5, 5, 1, MX, V, { R }, 0 }, + { "MIN", "MIN", 6, 6, 1, MX, V, { R }, 0 }, + { "MAX", "MAX", 7, 7, 1, MX, V, { R }, 0 }, + { "ROW", "ROW", 8, 8, 0, 1, V, { R }, 0 }, + { "COLUMN", "COLUMN", 9, 9, 0, 1, V, { R }, 0 }, + { "NA", "NA", 10, 10, 0, 0, V, {}, 0 }, + { "NPV", "NPV", 11, 11, 2, MX, V, { V, R }, 0 }, + { "STDEV", "STDEV", 12, 12, 1, MX, V, { R }, 0 }, + { "DOLLAR", "DOLLAR", 13, 13, 1, 2, V, { V }, 0 }, + { "FIXED", "FIXED", 14, 14, 1, 2, V, { V, V, C, I }, 0 }, + { "SIN", "SIN", 15, 15, 1, 1, V, { V }, 0 }, + { "COS", "COS", 16, 16, 1, 1, V, { V }, 0 }, + { "TAN", "TAN", 17, 17, 1, 1, V, { V }, 0 }, + { "COT", "TAN", 17, 17, 1, 1, V, { V }, FUNCFLAG_EXPORTONLY }, + { "ATAN", "ATAN", 18, 18, 1, 1, V, { V }, 0 }, + { "ACOT", "ATAN", 18, 18, 1, 1, V, { V }, FUNCFLAG_EXPORTONLY }, + { "PI", "PI", 19, 19, 0, 0, V, {}, 0 }, + { "SQRT", "SQRT", 20, 20, 1, 1, V, { V }, 0 }, + { "EXP", "EXP", 21, 21, 1, 1, V, { V }, 0 }, + { "LN", "LN", 22, 22, 1, 1, V, { V }, 0 }, + { "LOG10", "LOG10", 23, 23, 1, 1, V, { V }, 0 }, + { "ABS", "ABS", 24, 24, 1, 1, V, { V }, 0 }, + { "INT", "INT", 25, 25, 1, 1, V, { V }, 0 }, + { "SIGN", "SIGN", 26, 26, 1, 1, V, { V }, 0 }, + { "ROUND", "ROUND", 27, 27, 2, 2, V, { V }, 0 }, + { "LOOKUP", "LOOKUP", 28, 28, 2, 3, V, { V, R }, 0 }, + { "INDEX", "INDEX", 29, 29, 2, 4, R, { R, V }, 0 }, + { "REPT", "REPT", 30, 30, 2, 2, V, { V }, 0 }, + { "MID", "MID", 31, 31, 3, 3, V, { V }, 0 }, + { "LEN", "LEN", 32, 32, 1, 1, V, { V }, 0 }, + { "VALUE", "VALUE", 33, 33, 1, 1, V, { V }, 0 }, + { "TRUE", "TRUE", 34, 34, 0, 0, V, {}, 0 }, + { "FALSE", "FALSE", 35, 35, 0, 0, V, {}, 0 }, + { "AND", "AND", 36, 36, 1, MX, V, { R }, 0 }, + { "OR", "OR", 37, 37, 1, MX, V, { R }, 0 }, + { "NOT", "NOT", 38, 38, 1, 1, V, { V }, 0 }, + { "MOD", "MOD", 39, 39, 2, 2, V, { V }, 0 }, + { "DCOUNT", "DCOUNT", 40, 40, 3, 3, V, { R }, 0 }, + { "DSUM", "DSUM", 41, 41, 3, 3, V, { R }, 0 }, + { "DAVERAGE", "DAVERAGE", 42, 42, 3, 3, V, { R }, 0 }, + { "DMIN", "DMIN", 43, 43, 3, 3, V, { R }, 0 }, + { "DMAX", "DMAX", 44, 44, 3, 3, V, { R }, 0 }, + { "DSTDEV", "DSTDEV", 45, 45, 3, 3, V, { R }, 0 }, + { "VAR", "VAR", 46, 46, 1, MX, V, { R }, 0 }, + { "DVAR", "DVAR", 47, 47, 3, 3, V, { R }, 0 }, + { "TEXT", "TEXT", 48, 48, 2, 2, V, { V }, 0 }, + { "LINEST", "LINEST", 49, 49, 1, 2, A, { R, R, C, C, I }, 0 }, + { "TREND", "TREND", 50, 50, 1, 3, A, { R, R, R, C, I }, 0 }, + { "LOGEST", "LOGEST", 51, 51, 1, 2, A, { R, R, C, C, I }, 0 }, + { "GROWTH", "GROWTH", 52, 52, 1, 3, A, { R, R, R, C, I }, 0 }, + { "PV", "PV", 56, 56, 3, 5, V, { V }, 0 }, + { "FV", "FV", 57, 57, 3, 5, V, { V }, 0 }, + { "NPER", "NPER", 58, 58, 3, 5, V, { V }, 0 }, + { "PMT", "PMT", 59, 59, 3, 5, V, { V }, 0 }, + { "RATE", "RATE", 60, 60, 3, 6, V, { V }, 0 }, + { "MIRR", "MIRR", 61, 61, 3, 3, V, { R, V }, 0 }, + { "IRR", "IRR", 62, 62, 1, 2, V, { R, V }, 0 }, + { "RAND", "RAND", 63, 63, 0, 0, V, {}, FUNCFLAG_VOLATILE }, + { "MATCH", "MATCH", 64, 64, 2, 3, V, { V, R }, 0 }, + { "DATE", "DATE", 65, 65, 3, 3, V, { V }, 0 }, + { "TIME", "TIME", 66, 66, 3, 3, V, { V }, 0 }, + { "DAY", "DAY", 67, 67, 1, 1, V, { V }, 0 }, + { "MONTH", "MONTH", 68, 68, 1, 1, V, { V }, 0 }, + { "YEAR", "YEAR", 69, 69, 1, 1, V, { V }, 0 }, + { "WEEKDAY", "WEEKDAY", 70, 70, 1, 1, V, { V, C, I }, 0 }, + { "HOUR", "HOUR", 71, 71, 1, 1, V, { V }, 0 }, + { "MINUTE", "MINUTE", 72, 72, 1, 1, V, { V }, 0 }, + { "SECOND", "SECOND", 73, 73, 1, 1, V, { V }, 0 }, + { "NOW", "NOW", 74, 74, 0, 0, V, {}, FUNCFLAG_VOLATILE }, + { "AREAS", "AREAS", 75, 75, 1, 1, V, { R }, 0 }, + { "ROWS", "ROWS", 76, 76, 1, 1, V, { R }, 0 }, + { "COLUMNS", "COLUMNS", 77, 77, 1, 1, V, { R }, 0 }, + { "OFFSET", "OFFSET", 78, 78, 3, 5, R, { R, V }, FUNCFLAG_VOLATILE }, + { "SEARCH", "SEARCH", 82, 82, 2, 3, V, { V }, 0 }, + { "TRANSPOSE", "TRANSPOSE", 83, 83, 1, 1, A, { A }, 0 }, + { "TYPE", "TYPE", 86, 86, 1, 1, V, { V }, 0 }, + { "ATAN2", "ATAN2", 97, 97, 2, 2, V, { V }, 0 }, + { "ASIN", "ASIN", 98, 98, 1, 1, V, { V }, 0 }, + { "ACOS", "ACOS", 99, 99, 1, 1, V, { V }, 0 }, + { "CHOOSE", "CHOOSE", 100, 100, 2, MX, R, { V, R }, 0 }, + { "HLOOKUP", "HLOOKUP", 101, 101, 3, 3, V, { V, R, R, C, I }, 0 }, + { "VLOOKUP", "VLOOKUP", 102, 102, 3, 3, V, { V, R, R, C, I }, 0 }, + { "ISREF", "ISREF", 105, 105, 1, 1, V, { R }, 0 }, + { "LOG", "LOG", 109, 109, 1, 2, V, { V }, 0 }, + { "CHAR", "CHAR", 111, 111, 1, 1, V, { V }, 0 }, + { "LOWER", "LOWER", 112, 112, 1, 1, V, { V }, 0 }, + { "UPPER", "UPPER", 113, 113, 1, 1, V, { V }, 0 }, + { "PROPER", "PROPER", 114, 114, 1, 1, V, { V }, 0 }, + { "LEFT", "LEFT", 115, 115, 1, 2, V, { V }, 0 }, + { "RIGHT", "RIGHT", 116, 116, 1, 2, V, { V }, 0 }, + { "EXACT", "EXACT", 117, 117, 2, 2, V, { V }, 0 }, + { "TRIM", "TRIM", 118, 118, 1, 1, V, { V }, 0 }, + { "REPLACE", "REPLACE", 119, 119, 4, 4, V, { V }, 0 }, + { "SUBSTITUTE", "SUBSTITUTE", 120, 120, 3, 4, V, { V }, 0 }, + { "CODE", "CODE", 121, 121, 1, 1, V, { V }, 0 }, + { "FIND", "FIND", 124, 124, 2, 3, V, { V }, 0 }, + { "CELL", "CELL", 125, 125, 1, 2, V, { V, R }, FUNCFLAG_VOLATILE }, + { "ISERR", "ISERR", 126, 126, 1, 1, V, { V }, 0 }, + { "ISTEXT", "ISTEXT", 127, 127, 1, 1, V, { V }, 0 }, + { "ISNUMBER", "ISNUMBER", 128, 128, 1, 1, V, { V }, 0 }, + { "ISBLANK", "ISBLANK", 129, 129, 1, 1, V, { V }, 0 }, + { "T", "T", 130, 130, 1, 1, V, { R }, 0 }, + { "N", "N", 131, 131, 1, 1, V, { R }, 0 }, + { "DATEVALUE", "DATEVALUE", 140, 140, 1, 1, V, { V }, 0 }, + { "TIMEVALUE", "TIMEVALUE", 141, 141, 1, 1, V, { V }, 0 }, + { "SLN", "SLN", 142, 142, 3, 3, V, { V }, 0 }, + { "SYD", "SYD", 143, 143, 4, 4, V, { V }, 0 }, + { "DDB", "DDB", 144, 144, 4, 5, V, { V }, 0 }, + { "INDIRECT", "INDIRECT", 148, 148, 1, 2, R, { V, EV, I }, FUNCFLAG_VOLATILE }, + { "CLEAN", "CLEAN", 162, 162, 1, 1, V, { V }, 0 }, + { "MDETERM", "MDETERM", 163, 163, 1, 1, V, { A }, 0 }, + { "MINVERSE", "MINVERSE", 164, 164, 1, 1, A, { A }, 0 }, + { "MMULT", "MMULT", 165, 165, 2, 2, A, { A }, 0 }, + { "IPMT", "IPMT", 167, 167, 4, 6, V, { V }, 0 }, + { "PPMT", "PPMT", 168, 168, 4, 6, V, { V }, 0 }, + { "COUNTA", "COUNTA", 169, 169, 0, MX, V, { R }, 0 }, + { "PRODUCT", "PRODUCT", 183, 183, 0, MX, V, { R }, 0 }, + { "FACT", "FACT", 184, 184, 1, 1, V, { V }, 0 }, + { "DPRODUCT", "DPRODUCT", 189, 189, 3, 3, V, { R }, 0 }, + { "ISNONTEXT", "ISNONTEXT", 190, 190, 1, 1, V, { V }, 0 }, + { "STDEVP", "STDEVP", 193, 193, 1, MX, V, { R }, 0 }, + { "VARP", "VARP", 194, 194, 1, MX, V, { R }, 0 }, + { "DSTDEVP", "DSTDEVP", 195, 195, 3, 3, V, { R }, 0 }, + { "DVARP", "DVARP", 196, 196, 3, 3, V, { R }, 0 }, + { "TRUNC", "TRUNC", 197, 197, 1, 1, V, { V, C, I }, 0 }, + { "ISLOGICAL", "ISLOGICAL", 198, 198, 1, 1, V, { V }, 0 }, + { "DCOUNTA", "DCOUNTA", 199, 199, 3, 3, V, { R }, 0 }, + { 0, 0, 255, 255, 1, MX, R, { ER, R }, FUNCFLAG_IMPORTONLY } // EXTERNAL +}; + +/** Functions new in BIFF3. */ +static const FunctionData saFuncTableBiff3[] = +{ + { "LINEST", "LINEST", 49, 49, 1, 4, A, { R, R, V, V }, 0 }, // BIFF2: 1-2, BIFF3: 1-4, + { "TREND", "TREND", 50, 50, 1, 4, A, { R, R, R, V }, 0 }, // BIFF2: 1-3, BIFF3: 1-4 + { "LOGEST", "LOGEST", 51, 51, 1, 4, A, { R, R, V, V }, 0 }, // BIFF2: 1-2, BIFF3: 1-4, + { "GROWTH", "GROWTH", 52, 52, 1, 4, A, { R, R, R, V }, 0 }, // BIFF2: 1-3, BIFF3: 1-4 + { "TRUNC", "TRUNC", 197, 197, 1, 2, V, { V }, 0 }, // BIFF2: 1, BIFF3: 1-2 + { "DOLLAR", "USDOLLAR", 204, 204, 1, 2, V, { V }, FUNCFLAG_IMPORTONLY }, + { 0/*"FIND"*/, "FINDB", 205, 205, 2, 3, V, { V }, 0 }, + { 0/*"SEARCH"*/, "SEARCHB", 206, 206, 2, 3, V, { V }, 0 }, + { 0/*"REPLACE"*/, "REPLACEB", 207, 207, 4, 4, V, { V }, 0 }, + { 0/*"LEFT"*/, "LEFTB", 208, 208, 1, 2, V, { V }, 0 }, + { 0/*"RIGHT"*/, "RIGHTB", 209, 209, 1, 2, V, { V }, 0 }, + { 0/*"MID"*/, "MIDB", 210, 210, 3, 3, V, { V }, 0 }, + { 0/*"LEN"*/, "LENB", 211, 211, 1, 1, V, { V }, 0 }, + { "ROUNDUP", "ROUNDUP", 212, 212, 2, 2, V, { V }, 0 }, + { "ROUNDDOWN", "ROUNDDOWN", 213, 213, 2, 2, V, { V }, 0 }, + { "ASC", "ASC", 214, 214, 1, 1, V, { V }, 0 }, + { "JIS", "DBCS", 215, 215, 1, 1, V, { V }, 0 }, + { "ADDRESS", "ADDRESS", 219, 219, 2, 5, V, { V, V, V, EV, V }, 0 }, + { "DAYS360", "DAYS360", 220, 220, 2, 2, V, { V, V, C, I }, 0 }, + { "TODAY", "TODAY", 221, 221, 0, 0, V, {}, FUNCFLAG_VOLATILE }, + { "VDB", "VDB", 222, 222, 5, 7, V, { V }, 0 }, + { "MEDIAN", "MEDIAN", 227, 227, 1, MX, V, { R }, 0 }, + { "SUMPRODUCT", "SUMPRODUCT", 228, 228, 1, MX, V, { A }, 0 }, + { "SINH", "SINH", 229, 229, 1, 1, V, { V }, 0 }, + { "COSH", "COSH", 230, 230, 1, 1, V, { V }, 0 }, + { "TANH", "TANH", 231, 231, 1, 1, V, { V }, 0 }, + { "COTH", "TANH", 231, 231, 1, 1, V, { V }, FUNCFLAG_EXPORTONLY }, + { "ASINH", "ASINH", 232, 232, 1, 1, V, { V }, 0 }, + { "ACOSH", "ACOSH", 233, 233, 1, 1, V, { V }, 0 }, + { "ATANH", "ATANH", 234, 234, 1, 1, V, { V }, 0 }, + { "ACOTH", "ATANH", 234, 234, 1, 1, V, { V }, FUNCFLAG_EXPORTONLY }, + { "DGET", "DGET", 235, 235, 3, 3, V, { R }, 0 }, + { "INFO", "INFO", 244, 244, 1, 1, V, { V }, FUNCFLAG_VOLATILE } +}; + +/** Functions new in BIFF4. */ +static const FunctionData saFuncTableBiff4[] = +{ + { "FIXED", "FIXED", 14, 14, 1, 3, V, { V }, 0 }, // BIFF2-3: 1-2, BIFF4: 1-3 + { "RANK", "RANK", 216, 216, 2, 3, V, { V, R, V }, 0 }, + { "DB", "DB", 247, 247, 4, 5, V, { V }, 0 }, + { "FREQUENCY", "FREQUENCY", 252, 252, 2, 2, A, { R }, 0 }, + { "ERROR.TYPE", "ERROR.TYPE", 261, 261, 1, 1, V, { V }, 0 }, + { "AVEDEV", "AVEDEV", 269, 269, 1, MX, V, { R }, 0 }, + { "BETADIST", "BETADIST", 270, 270, 3, 5, V, { V }, 0 }, + { "GAMMALN", "GAMMALN", 271, 271, 1, 1, V, { V }, 0 }, + { "BETAINV", "BETAINV", 272, 272, 3, 5, V, { V }, 0 }, + { "BINOMDIST", "BINOMDIST", 273, 273, 4, 4, V, { V }, 0 }, + { "LEGACY.CHIDIST", "CHIDIST", 274, 274, 2, 2, V, { V }, 0 }, + { "LEGACY.CHIINV", "CHIINV", 275, 275, 2, 2, V, { V }, 0 }, + { "COMBIN", "COMBIN", 276, 276, 2, 2, V, { V }, 0 }, + { "CONFIDENCE", "CONFIDENCE", 277, 277, 3, 3, V, { V }, 0 }, + { "CRITBINOM", "CRITBINOM", 278, 278, 3, 3, V, { V }, 0 }, + { "EVEN", "EVEN", 279, 279, 1, 1, V, { V }, 0 }, + { "EXPONDIST", "EXPONDIST", 280, 280, 3, 3, V, { V }, 0 }, + { "LEGACY.FDIST", "FDIST", 281, 281, 3, 3, V, { V }, 0 }, + { "LEGACY.FINV", "FINV", 282, 282, 3, 3, V, { V }, 0 }, + { "FISHER", "FISHER", 283, 283, 1, 1, V, { V }, 0 }, + { "FISHERINV", "FISHERINV", 284, 284, 1, 1, V, { V }, 0 }, + { "FLOOR", "FLOOR", 285, 285, 2, 2, V, { V, V, C, I }, 0 }, + { "GAMMADIST", "GAMMADIST", 286, 286, 4, 4, V, { V }, 0 }, + { "GAMMAINV", "GAMMAINV", 287, 287, 3, 3, V, { V }, 0 }, + { "CEILING", "CEILING", 288, 288, 2, 2, V, { V, V, C, I }, 0 }, + { "HYPGEOMDIST", "HYPGEOMDIST", 289, 289, 4, 4, V, { V }, 0 }, + { "LOGNORMDIST", "LOGNORMDIST", 290, 290, 3, 3, V, { V }, 0 }, + { "LOGINV", "LOGINV", 291, 291, 3, 3, V, { V }, 0 }, + { "NEGBINOMDIST", "NEGBINOMDIST", 292, 292, 3, 3, V, { V }, 0 }, + { "NORMDIST", "NORMDIST", 293, 293, 4, 4, V, { V }, 0 }, + { "LEGACY.NORMSDIST", "NORMSDIST", 294, 294, 1, 1, V, { V }, 0 }, + { "NORMINV", "NORMINV", 295, 295, 3, 3, V, { V }, 0 }, + { "LEGACY.NORMSINV", "NORMSINV", 296, 296, 1, 1, V, { V }, 0 }, + { "STANDARDIZE", "STANDARDIZE", 297, 297, 3, 3, V, { V }, 0 }, + { "ODD", "ODD", 298, 298, 1, 1, V, { V }, 0 }, + { "PERMUT", "PERMUT", 299, 299, 2, 2, V, { V }, 0 }, + { "POISSON", "POISSON", 300, 300, 3, 3, V, { V }, 0 }, + { "TDIST", "TDIST", 301, 301, 3, 3, V, { V }, 0 }, + { "WEIBULL", "WEIBULL", 302, 302, 4, 4, V, { V }, 0 }, + { "SUMXMY2", "SUMXMY2", 303, 303, 2, 2, V, { A }, 0 }, + { "SUMX2MY2", "SUMX2MY2", 304, 304, 2, 2, V, { A }, 0 }, + { "SUMX2PY2", "SUMX2PY2", 305, 305, 2, 2, V, { A }, 0 }, + { "LEGACY.CHITEST", "CHITEST", 306, 306, 2, 2, V, { A }, 0 }, + { "CORREL", "CORREL", 307, 307, 2, 2, V, { A }, 0 }, + { "COVAR", "COVAR", 308, 308, 2, 2, V, { A }, 0 }, + { "FORECAST", "FORECAST", 309, 309, 3, 3, V, { V, A }, 0 }, + { "FTEST", "FTEST", 310, 310, 2, 2, V, { A }, 0 }, + { "INTERCEPT", "INTERCEPT", 311, 311, 2, 2, V, { A }, 0 }, + { "PEARSON", "PEARSON", 312, 312, 2, 2, V, { A }, 0 }, + { "RSQ", "RSQ", 313, 313, 2, 2, V, { A }, 0 }, + { "STEYX", "STEYX", 314, 314, 2, 2, V, { A }, 0 }, + { "SLOPE", "SLOPE", 315, 315, 2, 2, V, { A }, 0 }, + { "TTEST", "TTEST", 316, 316, 4, 4, V, { A, A, V }, 0 }, + { "PROB", "PROB", 317, 317, 3, 4, V, { A, A, V }, 0 }, + { "DEVSQ", "DEVSQ", 318, 318, 1, MX, V, { R }, 0 }, + { "GEOMEAN", "GEOMEAN", 319, 319, 1, MX, V, { R }, 0 }, + { "HARMEAN", "HARMEAN", 320, 320, 1, MX, V, { R }, 0 }, + { "SUMSQ", "SUMSQ", 321, 321, 0, MX, V, { R }, 0 }, + { "KURT", "KURT", 322, 322, 1, MX, V, { R }, 0 }, + { "SKEW", "SKEW", 323, 323, 1, MX, V, { R }, 0 }, + { "ZTEST", "ZTEST", 324, 324, 2, 3, V, { R, V }, 0 }, + { "LARGE", "LARGE", 325, 325, 2, 2, V, { R, V }, 0 }, + { "SMALL", "SMALL", 326, 326, 2, 2, V, { R, V }, 0 }, + { "QUARTILE", "QUARTILE", 327, 327, 2, 2, V, { R, V }, 0 }, + { "PERCENTILE", "PERCENTILE", 328, 328, 2, 2, V, { R, V }, 0 }, + { "PERCENTRANK", "PERCENTRANK", 329, 329, 2, 3, V, { R, V, EV, I }, 0 }, + { "MODE", "MODE", 330, 330, 1, MX, V, { A }, 0 }, + { "TRIMMEAN", "TRIMMEAN", 331, 331, 2, 2, V, { R, V }, 0 }, + { "TINV", "TINV", 332, 332, 2, 2, V, { V }, 0 }, + + // *** Analysis add-in *** + + { "HEX2BIN", "HEX2BIN", 384, NOID, 1, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "HEX2DEC", "HEX2DEC", 385, NOID, 1, 1, V, { V }, FUNCFLAG_EXTERNAL }, + { "HEX2OCT", "HEX2OCT", 386, NOID, 1, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "DEC2BIN", "DEC2BIN", 387, NOID, 1, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "DEC2HEX", "DEC2HEX", 388, NOID, 1, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "DEC2OCT", "DEC2OCT", 389, NOID, 1, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "OCT2BIN", "OCT2BIN", 390, NOID, 1, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "OCT2HEX", "OCT2HEX", 391, NOID, 1, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "OCT2DEC", "OCT2DEC", 392, NOID, 1, 1, V, { V }, FUNCFLAG_EXTERNAL }, + { "BIN2DEC", "BIN2DEC", 393, NOID, 1, 1, V, { V }, FUNCFLAG_EXTERNAL }, + { "BIN2OCT", "BIN2OCT", 394, NOID, 1, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "BIN2HEX", "BIN2HEX", 395, NOID, 1, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "IMSUB", "IMSUB", 396, NOID, 2, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "IMDIV", "IMDIV", 397, NOID, 2, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "IMPOWER", "IMPOWER", 398, NOID, 2, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "IMABS", "IMABS", 399, NOID, 1, 1, V, { V }, FUNCFLAG_EXTERNAL }, + { "IMSQRT", "IMSQRT", 400, NOID, 1, 1, V, { V }, FUNCFLAG_EXTERNAL }, + { "IMLN", "IMLN", 401, NOID, 1, 1, V, { V }, FUNCFLAG_EXTERNAL }, + { "IMLOG2", "IMLOG2", 402, NOID, 1, 1, V, { V }, FUNCFLAG_EXTERNAL }, + { "IMLOG10", "IMLOG10", 403, NOID, 1, 1, V, { V }, FUNCFLAG_EXTERNAL }, + { "IMSIN", "IMSIN", 404, NOID, 1, 1, V, { V }, FUNCFLAG_EXTERNAL }, + { "IMCOS", "IMCOS", 405, NOID, 1, 1, V, { V }, FUNCFLAG_EXTERNAL }, + { "IMEXP", "IMEXP", 406, NOID, 1, 1, V, { V }, FUNCFLAG_EXTERNAL }, + { "IMARGUMENT", "IMARGUMENT", 407, NOID, 1, 1, V, { V }, FUNCFLAG_EXTERNAL }, + { "IMCONJUGATE", "IMCONJUGATE", 408, NOID, 1, 1, V, { V }, FUNCFLAG_EXTERNAL }, + { "IMAGINARY", "IMAGINARY", 409, NOID, 1, 1, V, { V }, FUNCFLAG_EXTERNAL }, + { "IMREAL", "IMREAL", 410, NOID, 1, 1, V, { V }, FUNCFLAG_EXTERNAL }, + { "COMPLEX", "COMPLEX", 411, NOID, 2, 3, V, { V }, FUNCFLAG_EXTERNAL }, + { "IMSUM", "IMSUM", 412, NOID, 1, MX, V, { R }, FUNCFLAG_EXTERNAL }, + { "IMPRODUCT", "IMPRODUCT", 413, NOID, 1, MX, V, { R }, FUNCFLAG_EXTERNAL }, + { "SERIESSUM", "SERIESSUM", 414, NOID, 4, 4, V, { V, V, V, R }, FUNCFLAG_EXTERNAL }, + { "FACTDOUBLE", "FACTDOUBLE", 415, NOID, 1, 1, V, { V }, FUNCFLAG_EXTERNAL }, + { "SQRTPI", "SQRTPI", 416, NOID, 1, 1, V, { V }, FUNCFLAG_EXTERNAL }, + { "QUOTIENT", "QUOTIENT", 417, NOID, 2, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "DELTA", "DELTA", 418, NOID, 1, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "GESTEP", "GESTEP", 419, NOID, 1, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "ISEVEN", "ISEVEN", 420, NOID, 1, 1, V, { V }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in + { "ISODD", "ISODD", 421, NOID, 1, 1, V, { V }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in + { "MROUND", "MROUND", 422, NOID, 2, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "ERF", "ERF", 423, NOID, 1, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "ERFC", "ERFC", 424, NOID, 1, 1, V, { V }, FUNCFLAG_EXTERNAL }, + { "BESSELJ", "BESSELJ", 425, NOID, 2, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "BESSELK", "BESSELK", 426, NOID, 2, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "BESSELY", "BESSELY", 427, NOID, 2, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "BESSELI", "BESSELI", 428, NOID, 2, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "XIRR", "XIRR", 429, NOID, 2, 3, V, { A, R, V }, FUNCFLAG_EXTERNAL }, + { "XNPV", "XNPV", 430, NOID, 3, 3, V, { V, A, R }, FUNCFLAG_EXTERNAL }, + { "PRICEMAT", "PRICEMAT", 431, NOID, 5, 6, V, { V }, FUNCFLAG_EXTERNAL }, + { "YIELDMAT", "YIELDMAT", 432, NOID, 5, 6, V, { V }, FUNCFLAG_EXTERNAL }, + { "INTRATE", "INTRATE", 433, NOID, 4, 5, V, { V }, FUNCFLAG_EXTERNAL }, + { "RECEIVED", "RECEIVED", 434, NOID, 4, 5, V, { V }, FUNCFLAG_EXTERNAL }, + { "DISC", "DISC", 435, NOID, 4, 5, V, { V }, FUNCFLAG_EXTERNAL }, + { "PRICEDISC", "PRICEDISC", 436, NOID, 4, 5, V, { V }, FUNCFLAG_EXTERNAL }, + { "YIELDDISC", "YIELDDISC", 437, NOID, 4, 5, V, { V }, FUNCFLAG_EXTERNAL }, + { "TBILLEQ", "TBILLEQ", 438, NOID, 3, 3, V, { V }, FUNCFLAG_EXTERNAL }, + { "TBILLPRICE", "TBILLPRICE", 439, NOID, 3, 3, V, { V }, FUNCFLAG_EXTERNAL }, + { "TBILLYIELD", "TBILLYIELD", 440, NOID, 3, 3, V, { V }, FUNCFLAG_EXTERNAL }, + { "PRICE", "PRICE", 441, NOID, 6, 7, V, { V }, FUNCFLAG_EXTERNAL }, + { "YIELD", "YIELD", 442, NOID, 6, 7, V, { V }, FUNCFLAG_EXTERNAL }, + { "DOLLARDE", "DOLLARDE", 443, NOID, 2, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "DOLLARFR", "DOLLARFR", 444, NOID, 2, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "NOMINAL", "NOMINAL", 445, NOID, 2, 2, V, { V }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in + { "EFFECT", "EFFECT", 446, NOID, 2, 2, V, { V }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in + { "CUMPRINC", "CUMPRINC", 447, NOID, 6, 6, V, { V }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in + { "CUMIPMT", "CUMIPMT", 448, NOID, 6, 6, V, { V }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in + { "EDATE", "EDATE", 449, NOID, 2, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "EOMONTH", "EOMONTH", 450, NOID, 2, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "YEARFRAC", "YEARFRAC", 451, NOID, 2, 3, V, { V }, FUNCFLAG_EXTERNAL }, + { "COUPDAYBS", "COUPDAYBS", 452, NOID, 3, 4, V, { V }, FUNCFLAG_EXTERNAL }, + { "COUPDAYS", "COUPDAYS", 453, NOID, 3, 4, V, { V }, FUNCFLAG_EXTERNAL }, + { "COUPDAYSNC", "COUPDAYSNC", 454, NOID, 3, 4, V, { V }, FUNCFLAG_EXTERNAL }, + { "COUPNCD", "COUPNCD", 455, NOID, 3, 4, V, { V }, FUNCFLAG_EXTERNAL }, + { "COUPNUM", "COUPNUM", 456, NOID, 3, 4, V, { V }, FUNCFLAG_EXTERNAL }, + { "COUPPCD", "COUPPCD", 457, NOID, 3, 4, V, { V }, FUNCFLAG_EXTERNAL }, + { "DURATION", "DURATION", 458, NOID, 5, 6, V, { V }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in + { "MDURATION", "MDURATION", 459, NOID, 5, 6, V, { V }, FUNCFLAG_EXTERNAL }, + { "ODDLPRICE", "ODDLPRICE", 460, NOID, 7, 8, V, { V }, FUNCFLAG_EXTERNAL }, + { "ODDLYIELD", "ODDLYIELD", 461, NOID, 8, 9, V, { V }, FUNCFLAG_EXTERNAL }, + { "ODDFPRICE", "ODDFPRICE", 462, NOID, 8, 9, V, { V }, FUNCFLAG_EXTERNAL }, + { "ODDFYIELD", "ODDFYIELD", 463, NOID, 8, 9, V, { V }, FUNCFLAG_EXTERNAL }, + { "RANDBETWEEN", "RANDBETWEEN", 464, NOID, 2, 2, V, {}, FUNCFLAG_VOLATILE | FUNCFLAG_EXTERNAL }, + { "WEEKNUM", "WEEKNUM", 465, NOID, 1, 2, V, { V }, FUNCFLAG_EXTERNAL }, + { "AMORDEGRC", "AMORDEGRC", 466, NOID, 6, 7, V, { V }, FUNCFLAG_EXTERNAL }, + { "AMORLINC", "AMORLINC", 467, NOID, 6, 7, V, { V }, FUNCFLAG_EXTERNAL }, + { "CONVERT", "CONVERT", 468, NOID, 3, 3, V, { V }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in + { "ACCRINT", "ACCRINT", 469, NOID, 6, 7, V, { V }, FUNCFLAG_EXTERNAL }, + { "ACCRINTM", "ACCRINTM", 470, NOID, 4, 5, V, { V }, FUNCFLAG_EXTERNAL }, + { "WORKDAY", "WORKDAY", 471, NOID, 2, 3, V, { V, V, A, C, I }, FUNCFLAG_EXTERNAL }, + { "NETWORKDAYS", "NETWORKDAYS", 472, NOID, 2, 3, V, { V, V, A, C, I }, FUNCFLAG_EXTERNAL }, + { "GCD", "GCD", 473, NOID, 1, MX, V, { R }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in + { "MULTINOMIAL", "MULTINOMIAL", 474, NOID, 1, MX, V, { R }, FUNCFLAG_EXTERNAL }, + { "LCM", "LCM", 475, NOID, 1, MX, V, { R }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in + { "FVSCHEDULE", "FVSCHEDULE", 476, NOID, 2, 2, V, { V, A }, FUNCFLAG_EXTERNAL } +// { "EUROCONVERT", "EUROCONVERT", NOID, NOID, 3, 5, V, { V }, FUNCFLAG_EXTERNAL }, // Euro conversion add-in +}; + +/** Functions new in BIFF5/BIFF7. */ +static const FunctionData saFuncTableBiff5[] = +{ + { "WEEKDAY", "WEEKDAY", 70, 70, 1, 2, V, { V }, 0 }, // BIFF2-4: 1, BIFF5: 1-2 + { "HLOOKUP", "HLOOKUP", 101, 101, 3, 4, V, { V, R, R, V }, 0 }, // BIFF2-4: 3, BIFF5: 3-4 + { "VLOOKUP", "VLOOKUP", 102, 102, 3, 4, V, { V, R, R, V }, 0 }, // BIFF2-4: 3, BIFF5: 3-4 + { "DAYS360", "DAYS360", 220, 220, 2, 3, V, { V }, 0 }, // BIFF3-4: 2, BIFF5: 2-3 + { 0, 0, 255, 255, 1, MX, R, { ER, R }, FUNCFLAG_EXPORTONLY }, // MACRO or EXTERNAL + { "CONCATENATE", "CONCATENATE", 336, 336, 0, MX, V, { V }, 0 }, + { "POWER", "POWER", 337, 337, 2, 2, V, { V }, 0 }, + { "RADIANS", "RADIANS", 342, 342, 1, 1, V, { V }, 0 }, + { "DEGREES", "DEGREES", 343, 343, 1, 1, V, { V }, 0 }, + { "SUBTOTAL", "SUBTOTAL", 344, 344, 2, MX, V, { V, R }, 0 }, + { "SUMIF", "SUMIF", 345, 345, 2, 3, V, { R, V, R }, 0 }, + { "COUNTIF", "COUNTIF", 346, 346, 2, 2, V, { R, V }, 0 }, + { "COUNTBLANK", "COUNTBLANK", 347, 347, 1, 1, V, { R }, 0 }, + { "ISPMT", "ISPMT", 350, 350, 4, 4, V, { V }, 0 }, + { 0, "DATEDIF", 351, 351, 3, 3, V, { V }, FUNCFLAG_IMPORTONLY }, // not supported in Calc + { 0, "DATESTRING", 352, 352, 1, 1, V, { V }, FUNCFLAG_IMPORTONLY }, // not supported in Calc, missing in OOX spec + { 0, "NUMBERSTRING", 353, 353, 2, 2, V, { V }, FUNCFLAG_IMPORTONLY }, // not supported in Calc, missing in OOX spec + { "ROMAN", "ROMAN", 354, 354, 1, 2, V, { V }, 0 } +}; + +/** Functions new in BIFF8. */ +static const FunctionData saFuncTableBiff8[] = +{ + { "GETPIVOTDATA", "GETPIVOTDATA", 358, 358, 2, MX, V, { V, R, V }, FUNCFLAG_IMPORTONLY }, + { "HYPERLINK", "HYPERLINK", 359, 359, 1, 2, V, { V }, 0 }, + { 0, "PHONETIC", 360, 360, 1, 1, V, { R }, FUNCFLAG_IMPORTONLY }, + { "AVERAGEA", "AVERAGEA", 361, 361, 1, MX, V, { R }, 0 }, + { "MAXA", "MAXA", 362, 362, 1, MX, V, { R }, 0 }, + { "MINA", "MINA", 363, 363, 1, MX, V, { R }, 0 }, + { "STDEVPA", "STDEVPA", 364, 364, 1, MX, V, { R }, 0 }, + { "VARPA", "VARPA", 365, 365, 1, MX, V, { R }, 0 }, + { "STDEVA", "STDEVA", 366, 366, 1, MX, V, { R }, 0 }, + { "VARA", "VARA", 367, 367, 1, MX, V, { R }, 0 }, + { "COM.MICROSOFT.BAHTTEXT", "BAHTTEXT", 368, 368, 1, 1, V, { V }, FUNCFLAG_MACROCALL }, + { 0, "THAIDAYOFWEEK", 369, 369, 1, 1, V, { V }, FUNCFLAG_MACROCALL }, + { 0, "THAIDIGIT", 370, 370, 1, 1, V, { V }, FUNCFLAG_MACROCALL }, + { 0, "THAIMONTHOFYEAR", 371, 371, 1, 1, V, { V }, FUNCFLAG_MACROCALL }, + { 0, "THAINUMSOUND", 372, 372, 1, 1, V, { V }, FUNCFLAG_MACROCALL }, + { 0, "THAINUMSTRING", 373, 373, 1, 1, V, { V }, FUNCFLAG_MACROCALL }, + { 0, "THAISTRINGLENGTH", 374, 374, 1, 1, V, { V }, FUNCFLAG_MACROCALL }, + { 0, "ISTHAIDIGIT", 375, 375, 1, 1, V, { V }, FUNCFLAG_MACROCALL }, + { 0, "ROUNDBAHTDOWN", 376, 376, 1, 1, V, { V }, FUNCFLAG_MACROCALL }, + { 0, "ROUNDBAHTUP", 377, 377, 1, 1, V, { V }, FUNCFLAG_MACROCALL }, + { 0, "THAIYEAR", 378, 378, 1, 1, V, { V }, FUNCFLAG_MACROCALL }, + { 0, "RTD", 379, 379, 3, 3, A, { V, V, R }, 0 } +}; + +/** Functions new in OOX. */ +static const FunctionData saFuncTableOox[] = +{ + { 0, "IFERROR", 480, NOID, 2, 2, V, { V, R }, 0 }, + { 0, "COUNTIFS", 481, NOID, 3, MX, V, { R, V }, 0 }, + { 0, "SUMIFS", 482, NOID, 3, MX, V, { R, V }, 0 }, + { 0, "AVERAGEIF", 483, NOID, 2, 3, V, { R, V, R }, 0 }, + { 0, "AVERAGEIFS", 484, NOID, 3, MX, V, { R, V }, 0 }, + { 0, "CUBEKPIMEMBER", NOID, NOID, 3, 4, V, { V }, 0 }, + { 0, "CUBEMEMBER", NOID, NOID, 2, 3, V, { V, A, V }, 0 }, + { 0, "CUBEMEMBERPROPERTY",NOID, NOID, 3, 3, V, { V }, 0 }, + { 0, "CUBERANKEDMEMBER", NOID, NOID, 3, 4, V, { V }, 0 }, + { 0, "CUBESET", NOID, NOID, 2, 5, V, { V, R, V }, 0 }, + { 0, "CUBESETCOUNT", NOID, NOID, 1, 1, V, { V }, 0 }, + { 0, "CUBEVALUE", NOID, NOID, 2, 2, V, { V, R }, 0 } +}; + +/** Functions defined by OpenFormula, but not supported by Calc or by Excel. */ +static const FunctionData saFuncTableOdf[] = +{ + { "ARABIC", 0, NOID, NOID, 1, 1, V, { V }, 0 }, + { "B", 0, NOID, NOID, 3, 4, V, { V }, 0 }, + { "BASE", 0, NOID, NOID, 2, 3, V, { V }, 0 }, + { "BITAND", 0, NOID, NOID, 2, 2, V, { V }, 0 }, + { "BITLSHIFT", 0, NOID, NOID, 2, 2, V, { V }, 0 }, + { "BITOR", 0, NOID, NOID, 2, 2, V, { V }, 0 }, + { "BITRSHIFT", 0, NOID, NOID, 2, 2, V, { V }, 0 }, + { "BITXOR", 0, NOID, NOID, 2, 2, V, { V }, 0 }, + { "CHISQDIST", 0, NOID, NOID, 2, 3, V, { V }, 0 }, + { "CHISQINV", 0, NOID, NOID, 2, 2, V, { V }, 0 }, + { "COMBINA", 0, NOID, NOID, 2, 2, V, { V }, 0 }, + { "DAYS", 0, NOID, NOID, 2, 2, V, { V }, 0 }, + { "DDE", 0, NOID, NOID, 3, 4, V, { V }, 0 }, + { "DECIMAL", 0, NOID, NOID, 2, 2, V, { V }, 0 }, + { "FDIST", 0, NOID, NOID, 3, 4, V, { V }, 0 }, + { "FINV", 0, NOID, NOID, 3, 3, V, { V }, 0 }, + { "FORMULA", 0, NOID, NOID, 1, 1, V, { R }, 0 }, + { "GAMMA", 0, NOID, NOID, 1, 1, V, { V }, 0 }, + { "GAUSS", 0, NOID, NOID, 1, 1, V, { V }, 0 }, + { "IFNA", 0, NOID, NOID, 2, 2, V, { V, R }, 0 }, + { "ISFORMULA", 0, NOID, NOID, 1, 1, V, { R }, 0 }, + { "ISOWEEKNUM", 0, NOID, NOID, 1, 2, V, { V }, 0 }, + { "MULTIPLE.OPERATIONS", 0, NOID, NOID, 3, 5, V, { R }, 0 }, + { "MUNIT", 0, NOID, NOID, 1, 1, A, { V }, 0 }, + { "NUMBERVALUE", 0, NOID, NOID, 2, 2, V, { V }, 0 }, + { "PDURATION", 0, NOID, NOID, 3, 3, V, { V }, 0 }, + { "PERMUTATIONA", 0, NOID, NOID, 2, 2, V, { V }, 0 }, + { "PHI", 0, NOID, NOID, 1, 1, V, { V }, 0 }, + { "RRI", 0, NOID, NOID, 3, 3, V, { V }, 0 }, + { "SHEET", 0, NOID, NOID, 1, 1, V, { R }, 0 }, + { "SHEETS", 0, NOID, NOID, 0, 1, V, { R }, 0 }, + { "SKEWP", 0, NOID, NOID, 1, MX, V, { R }, 0 }, + { "UNICHAR", 0, NOID, NOID, 1, 1, V, { V }, 0 }, + { "UNICODE", 0, NOID, NOID, 1, 1, V, { V }, 0 }, + { "XOR", 0, NOID, NOID, 1, MX, V, { R }, 0 } +}; + +} // namespace + +// function info parameter class iterator ===================================== + +FuncInfoParamClassIterator::FuncInfoParamClassIterator( const FunctionInfo& rFuncInfo ) : + mpnParamClass( rFuncInfo.mpnParamClass ), + mpnParamClassEnd( rFuncInfo.mpnParamClass + FUNCINFO_CLASSCOUNT ) +{ +} + +FuncInfoParamClassIterator& FuncInfoParamClassIterator::operator++() +{ + if( (mpnParamClass + 1 < mpnParamClassEnd) && (mpnParamClass[ 1 ] != 0) ) + ++mpnParamClass; + return *this; +} + +// function provider implementation =========================================== + +class FunctionProviderImpl +{ +public: + explicit FunctionProviderImpl( + ApiOpCodes& rOpCodes, + const Reference< XSpreadsheetDocument >& rxDocument, + bool bImportFilter ); + + explicit FunctionProviderImpl( + ApiOpCodes& rOpCodes, + const Reference< XSpreadsheetDocument >& rxDocument, + BiffType eBiff, + bool bImportFilter ); + + const FunctionInfo* getFuncInfoFromApiToken( const ApiToken& rToken ) const; + const FunctionInfo* getFuncInfoFromOoxFuncName( const OUString& rFuncName ) const; + const FunctionInfo* getFuncInfoFromOobFuncId( sal_uInt16 nFuncId ) const; + const FunctionInfo* getFuncInfoFromBiffFuncId( sal_uInt16 nFuncId ) const; + const FunctionInfo* getFuncInfoFromExternCallName( const OUString& rExtCallName ) const; + + Sequence< FormulaOpCodeMapEntry > getOoxParserMap() const; + +private: + typedef ::std::map< OUString, FormulaToken > FormulaTokenMap; + typedef Sequence< FormulaOpCodeMapEntry > OpCodeEntrySequence; + typedef ::std::vector< FormulaOpCodeMapEntry > OpCodeEntryVector; + + static bool fillEntrySeq( OpCodeEntrySequence& orEntrySeq, const Reference< XFormulaOpCodeMapper >& rxMapper, sal_Int32 nMapGroup ); + static bool fillTokenMap( FormulaTokenMap& orTokenMap, OpCodeEntrySequence& orEntrySeq, const Reference< XFormulaOpCodeMapper >& rxMapper, sal_Int32 nMapGroup ); + + static bool initOpCode( sal_Int32& ornOpCode, const OpCodeEntrySequence& rEntrySeq, sal_Int32 nSpecialId ); + static bool initOpCode( OpCodeEntryVector& orParserMap, sal_Int32& ornOpCode, const FormulaTokenMap& rTokenMap, const sal_Char* pcOdfName, const sal_Char* pcOoxName ); + + void construct( const Reference< XSpreadsheetDocument >& rxDocument, bool bImportFilter ); + void construct( const Reference< XSpreadsheetDocument >& rxDocument, BiffType eBiff, bool bImportFilter ); + + bool initFuncNames( const OpCodeEntrySequence& rEntrySeq ); + void initOpCodes( const Reference< XSpreadsheetDocument >& rxDocument ); + + void initFuncOpCode( FunctionInfo& orFuncInfo, const FormulaTokenMap& rFuncTokens ); + void initFuncMaps( const FunctionData* pBeg, const FunctionData* pEnd ); + +private: + typedef RefMap< sal_Int32, FunctionInfo > OpCodeFuncMap; + typedef RefMap< OUString, FunctionInfo > FuncNameMap; + typedef RefMap< sal_uInt16, FunctionInfo > FuncIdMap; + + ApiOpCodes& mrOpCodes; /// All needed API op-codes. + FormulaTokenMap maIntFuncTokens; /// Internal functions keyed by ODFF name. + FormulaTokenMap maExtFuncTokens; /// External functions keyed by ODFF name. + OpCodeFuncMap maOpCodeFuncs; /// Maps API op-codes to function data. + FuncNameMap maOoxFuncs; /// Maps OOXML function names to function data. + FuncNameMap maExtProgFuncs; /// Maps programmatical API function names to function data. + FuncIdMap maOobFuncs; /// Maps OOBIN function indexes to function data. + FuncIdMap maBiffFuncs; /// Maps BIFF function indexes to function data. + FuncNameMap maMacroFuncs; /// Maps BIFF macro function names to function data. + OpCodeEntryVector maParserMap; /// OOXML token mapping for formula parser service. + sal_uInt8 mnMaxParam; /// Maximum parameter count for current file type. + bool mbImportFilter; /// True = import filter, false = export filter. +}; + +// ---------------------------------------------------------------------------- + +FunctionProviderImpl::FunctionProviderImpl( ApiOpCodes& rOpCodes, + const Reference< XSpreadsheetDocument >& rxDocument, bool bImportFilter ) : + mrOpCodes( rOpCodes ), + mnMaxParam( OOX_MAX_PARAMCOUNT ) +{ + construct( rxDocument, bImportFilter ); +} + +FunctionProviderImpl::FunctionProviderImpl( ApiOpCodes& rOpCodes, + const Reference< XSpreadsheetDocument >& rxDocument, BiffType eBiff, bool bImportFilter ) : + mrOpCodes( rOpCodes ), + mnMaxParam( BIFF_MAX_PARAMCOUNT ) +{ + construct( rxDocument, eBiff, bImportFilter ); +} + +const FunctionInfo* FunctionProviderImpl::getFuncInfoFromApiToken( const ApiToken& rToken ) const +{ + const FunctionInfo* pFuncInfo = 0; + if( (rToken.OpCode == mrOpCodes.OPCODE_EXTERNAL) && rToken.Data.hasValue() ) + { + OUString aProgFuncName; + if( rToken.Data >>= aProgFuncName ) + pFuncInfo = maExtProgFuncs.get( aProgFuncName ).get(); + } + else + { + pFuncInfo = maOpCodeFuncs.get( rToken.OpCode ).get(); + } + return pFuncInfo; +} + +const FunctionInfo* FunctionProviderImpl::getFuncInfoFromOoxFuncName( const OUString& rFuncName ) const +{ + return maOoxFuncs.get( rFuncName ).get(); +} + +const FunctionInfo* FunctionProviderImpl::getFuncInfoFromOobFuncId( sal_uInt16 nFuncId ) const +{ + return maOobFuncs.get( nFuncId ).get(); +} + +const FunctionInfo* FunctionProviderImpl::getFuncInfoFromBiffFuncId( sal_uInt16 nFuncId ) const +{ + return maBiffFuncs.get( nFuncId ).get(); +} + +const FunctionInfo* FunctionProviderImpl::getFuncInfoFromExternCallName( const OUString& rExtCallName ) const +{ + return maMacroFuncs.get( rExtCallName ).get(); +} + +Sequence< FormulaOpCodeMapEntry > FunctionProviderImpl::getOoxParserMap() const +{ + return ContainerHelper::vectorToSequence( maParserMap ); +} + +// private -------------------------------------------------------------------- + +bool FunctionProviderImpl::fillEntrySeq( OpCodeEntrySequence& orEntrySeq, + const Reference< XFormulaOpCodeMapper >& rxMapper, sal_Int32 nMapGroup ) +{ + try + { + orEntrySeq = rxMapper->getAvailableMappings( ::com::sun::star::sheet::FormulaLanguage::ODFF, nMapGroup ); + return orEntrySeq.hasElements(); + } + catch( Exception& ) + { + } + return false; +} + +bool FunctionProviderImpl::fillTokenMap( FormulaTokenMap& orTokenMap, OpCodeEntrySequence& orEntrySeq, + const Reference< XFormulaOpCodeMapper >& rxMapper, sal_Int32 nMapGroup ) +{ + orTokenMap.clear(); + if( fillEntrySeq( orEntrySeq, rxMapper, nMapGroup ) ) + { + const FormulaOpCodeMapEntry* pEntry = orEntrySeq.getConstArray(); + const FormulaOpCodeMapEntry* pEntryEnd = pEntry + orEntrySeq.getLength(); + for( ; pEntry != pEntryEnd; ++pEntry ) + orTokenMap[ pEntry->Name ] = pEntry->Token; + } + return !orTokenMap.empty(); +} + +bool FunctionProviderImpl::initOpCode( sal_Int32& ornOpCode, + const OpCodeEntrySequence& rEntrySeq, sal_Int32 nSpecialId ) +{ + if( (0 <= nSpecialId) && (nSpecialId < rEntrySeq.getLength()) ) + { + ornOpCode = rEntrySeq[ nSpecialId ].Token.OpCode; + return true; + } + OSL_ENSURE( false, + OStringBuffer( "FunctionProviderImpl::initOpCode - opcode for special offset " ). + append( nSpecialId ).append( " not found" ).getStr() ); + return false; +} + +bool FunctionProviderImpl::initOpCode( OpCodeEntryVector& orParserMap, sal_Int32& ornOpCode, + const FormulaTokenMap& rTokenMap, const sal_Char* pcOdfName, const sal_Char* pcOoxName ) +{ + OUString aOdfName = OUString::createFromAscii( pcOdfName ); + FormulaTokenMap::const_iterator aIt = rTokenMap.find( aOdfName ); + if( aIt != rTokenMap.end() ) + { + ornOpCode = aIt->second.OpCode; + if( pcOoxName ) + { + FormulaOpCodeMapEntry aEntry; + aEntry.Name = OUString::createFromAscii( pcOoxName ); + aEntry.Token.OpCode = ornOpCode; + orParserMap.push_back( aEntry ); + } + return true; + } + OSL_ENSURE( false, + OStringBuffer( "FunctionProviderImpl::initOpCode - opcode for \"" ). + append( OUStringToOString( aOdfName, RTL_TEXTENCODING_ASCII_US ) ). + append( "\" not found" ).getStr() ); + return false; +} + +void FunctionProviderImpl::construct( + const Reference< XSpreadsheetDocument >& rxDocument, bool bImportFilter ) +{ + construct( rxDocument, BIFF8, bImportFilter ); + // additional functions for OOX + initFuncMaps( saFuncTableOox, STATIC_ARRAY_END( saFuncTableOox ) ); +} + +void FunctionProviderImpl::construct( + const Reference< XSpreadsheetDocument >& rxDocument, BiffType eBiff, bool bImportFilter ) +{ + mbImportFilter = bImportFilter; + OSL_ENSURE( mbImportFilter, "FunctionProviderImpl::construct - need special handling for macro call functions" ); + + // operator op-codes, special op-codes, function op-codes + initOpCodes( rxDocument ); + + /* Add functions supported in the current BIFF version only. + Function tables from later BIFF versions may overwrite single + functions from earlier tables. */ + if( eBiff >= BIFF2 ) + initFuncMaps( saFuncTableBiff2, STATIC_ARRAY_END( saFuncTableBiff2 ) ); + if( eBiff >= BIFF3 ) + initFuncMaps( saFuncTableBiff3, STATIC_ARRAY_END( saFuncTableBiff3 ) ); + if( eBiff >= BIFF4 ) + initFuncMaps( saFuncTableBiff4, STATIC_ARRAY_END( saFuncTableBiff4 ) ); + if( eBiff >= BIFF5 ) + initFuncMaps( saFuncTableBiff5, STATIC_ARRAY_END( saFuncTableBiff5 ) ); + if( eBiff >= BIFF8 ) + initFuncMaps( saFuncTableBiff8, STATIC_ARRAY_END( saFuncTableBiff8 ) ); +} + +bool FunctionProviderImpl::initFuncNames( const OpCodeEntrySequence& rEntrySeq ) +{ + const FormulaOpCodeMapEntry* pEntry = rEntrySeq.getConstArray(); + const FormulaOpCodeMapEntry* pEntryEnd = pEntry + rEntrySeq.getLength(); + for( ; pEntry != pEntryEnd; ++pEntry ) + { + if( pEntry->Token.OpCode == mrOpCodes.OPCODE_EXTERNAL ) + maExtFuncTokens[ pEntry->Name ] = pEntry->Token; + else + maIntFuncTokens[ pEntry->Name ] = pEntry->Token; + } + return true; +} + +void FunctionProviderImpl::initOpCodes( const Reference< XSpreadsheetDocument >& rxDocument ) +{ + bool bIsValid = false; + try + { + Reference< XMultiServiceFactory > xFactory( rxDocument, UNO_QUERY_THROW ); + Reference< XFormulaOpCodeMapper > xMapper( xFactory->createInstance( + CREATE_OUSTRING( "com.sun.star.sheet.FormulaOpCodeMapper" ) ), UNO_QUERY_THROW ); + + // op-codes provided as attributes + mrOpCodes.OPCODE_EXTERNAL = xMapper->getOpCodeExternal(); + mrOpCodes.OPCODE_UNKNOWN = xMapper->getOpCodeUnknown(); + + using namespace ::com::sun::star::sheet::FormulaMapGroup; + using namespace ::com::sun::star::sheet::FormulaMapGroupSpecialOffset; + + OpCodeEntrySequence aEntrySeq; + FormulaTokenMap aTokenMap; + bIsValid = + // special + fillEntrySeq( aEntrySeq, xMapper, SPECIAL ) && + initOpCode( mrOpCodes.OPCODE_PUSH, aEntrySeq, PUSH ) && + initOpCode( mrOpCodes.OPCODE_MISSING, aEntrySeq, MISSING ) && + initOpCode( mrOpCodes.OPCODE_SPACES, aEntrySeq, SPACES ) && + initOpCode( mrOpCodes.OPCODE_NAME, aEntrySeq, NAME ) && + initOpCode( mrOpCodes.OPCODE_DBAREA, aEntrySeq, DB_AREA ) && + initOpCode( mrOpCodes.OPCODE_NLR, aEntrySeq, COL_ROW_NAME ) && + initOpCode( mrOpCodes.OPCODE_MACRO, aEntrySeq, MACRO ) && + initOpCode( mrOpCodes.OPCODE_BAD, aEntrySeq, BAD ) && + initOpCode( mrOpCodes.OPCODE_NONAME, aEntrySeq, NO_NAME ) && + // separators + fillTokenMap( aTokenMap, aEntrySeq, xMapper, SEPARATORS ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_OPEN, aTokenMap, "(", "(" ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_CLOSE, aTokenMap, ")", ")" ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_SEP, aTokenMap, ";", "," ) && + // array separators + fillTokenMap( aTokenMap, aEntrySeq, xMapper, ARRAY_SEPARATORS ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_ARRAY_OPEN, aTokenMap, "{", "{" ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_ARRAY_CLOSE, aTokenMap, "}", "}" ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_ARRAY_ROWSEP, aTokenMap, "|", ";" ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_ARRAY_COLSEP, aTokenMap, ";", "," ) && + // unary operators + fillTokenMap( aTokenMap, aEntrySeq, xMapper, UNARY_OPERATORS ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_PLUS_SIGN, aTokenMap, "+", 0 ) && // same op-code as OPCODE_ADD + initOpCode( maParserMap, mrOpCodes.OPCODE_MINUS_SIGN, aTokenMap, "-", "-" ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_PERCENT, aTokenMap, "%", "%" ) && + // binary operators + fillTokenMap( aTokenMap, aEntrySeq, xMapper, BINARY_OPERATORS ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_ADD, aTokenMap, "+", "+" ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_SUB, aTokenMap, "-", "-" ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_MULT, aTokenMap, "*", "*" ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_DIV, aTokenMap, "/", "/" ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_POWER, aTokenMap, "^", "^" ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_CONCAT, aTokenMap, "&", "&" ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_EQUAL, aTokenMap, "=", "=" ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_NOT_EQUAL, aTokenMap, "<>", "<>" ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_LESS, aTokenMap, "<", "<" ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_LESS_EQUAL, aTokenMap, "<=", "<=" ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_GREATER, aTokenMap, ">", ">" ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_GREATER_EQUAL, aTokenMap, ">=", ">=" ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_INTERSECT, aTokenMap, "!", " " ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_LIST, aTokenMap, "~", "," ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_RANGE, aTokenMap, ":", ":" ) && + // functions + fillTokenMap( aTokenMap, aEntrySeq, xMapper, FUNCTIONS ) && + initFuncNames( aEntrySeq ) && + initOpCode( maParserMap, mrOpCodes.OPCODE_DDE, aTokenMap, "DDE", 0 ); + + // OPCODE_PLUS_SIGN and OPCODE_ADD should be equal, otherwise "+" has to be passed above + OSL_ENSURE( mrOpCodes.OPCODE_PLUS_SIGN == mrOpCodes.OPCODE_ADD, + "FunctionProviderImpl::initOpCodes - need opcode mapping for OPCODE_PLUS_SIGN" ); + // OPCODE_LIST not supported in Calc core + mrOpCodes.OPCODE_LIST = mrOpCodes.OPCODE_SEP; + } + catch( Exception& ) + { + } + OSL_ENSURE( bIsValid, "FunctionProviderImpl::initOpCodes - opcodes not initialized" ); +} + +void FunctionProviderImpl::initFuncOpCode( FunctionInfo& orFuncInfo, const FormulaTokenMap& rFuncTokens ) +{ + bool bRet = false; + if( orFuncInfo.mnOobFuncId == OOBIN_FUNC_EXTERNCALL ) + { + orFuncInfo.mnApiOpCode = mrOpCodes.OPCODE_EXTERNAL; + bRet = true; + } + else if( orFuncInfo.maOdfFuncName.getLength() > 0 ) + { + FormulaTokenMap::const_iterator aIt = rFuncTokens.find( orFuncInfo.maOdfFuncName ); + if( aIt != rFuncTokens.end() ) + { + orFuncInfo.mnApiOpCode = aIt->second.OpCode; + OSL_ENSURE( orFuncInfo.mnApiOpCode != mrOpCodes.OPCODE_NONAME, + OStringBuffer( "FunctionProviderImpl::initFuncOpCode - no valid op-code for \"" ). + append( OUStringToOString( orFuncInfo.maOdfFuncName, RTL_TEXTENCODING_ASCII_US ) ). + append( '"' ).getStr() ); + OSL_ENSURE( orFuncInfo.maOoxFuncName.getLength() > 0, + OStringBuffer( "FunctionProviderImpl::initFuncOpCode - no valid OOX function name for \"" ). + append( OUStringToOString( orFuncInfo.maOdfFuncName, RTL_TEXTENCODING_ASCII_US ) ). + append( '"' ).getStr() ); + bRet = (orFuncInfo.mnApiOpCode != mrOpCodes.OPCODE_EXTERNAL) || + ((aIt->second.Data >>= orFuncInfo.maExtProgName) && (orFuncInfo.maExtProgName.getLength() > 0)); + if( bRet ) + { + // create the parser map entry + FormulaOpCodeMapEntry aEntry; + aEntry.Name = orFuncInfo.maOoxFuncName; + aEntry.Token = aIt->second; + maParserMap.push_back( aEntry ); + } + } + OSL_ENSURE( bRet, + OStringBuffer( "FunctionProviderImpl::initFuncOpCode - opcode or external name for \"" ). + append( OUStringToOString( orFuncInfo.maOdfFuncName, RTL_TEXTENCODING_ASCII_US ) ). + append( "\" not found" ).getStr() ); + } + if( !bRet || (orFuncInfo.mnApiOpCode == mrOpCodes.OPCODE_UNKNOWN) ) + orFuncInfo.mnApiOpCode = mrOpCodes.OPCODE_NONAME; +} + +void FunctionProviderImpl::initFuncMaps( const FunctionData* pBeg, const FunctionData* pEnd ) +{ + for( const FunctionData* pIt = pBeg; pIt != pEnd; ++pIt ) + { + if( pIt->isSupported( mbImportFilter ) ) + { + // create a function info object + FunctionInfoRef xFuncInfo( new FunctionInfo ); + if( pIt->mpcOdfFuncName ) + xFuncInfo->maOdfFuncName = OUString::createFromAscii( pIt->mpcOdfFuncName ); + if( pIt->mpcOoxFuncName ) + xFuncInfo->maOoxFuncName = OUString::createFromAscii( pIt->mpcOoxFuncName ); + if( getFlag( pIt->mnFlags, FUNCFLAG_MACROCALL ) ) + xFuncInfo->maExternCallName = CREATE_OUSTRING( "_xlfn." ) + xFuncInfo->maOoxFuncName; + else if( getFlag( pIt->mnFlags, FUNCFLAG_EXTERNAL ) ) + xFuncInfo->maExternCallName = xFuncInfo->maOoxFuncName; + xFuncInfo->mnOobFuncId = pIt->mnOobFuncId; + xFuncInfo->mnBiffFuncId = pIt->mnBiffFuncId; + xFuncInfo->mnMinParamCount = pIt->mnMinParamCount; + xFuncInfo->mnMaxParamCount = (pIt->mnMaxParamCount == MX) ? mnMaxParam : pIt->mnMaxParamCount; + xFuncInfo->mnRetClass = pIt->mnRetClass; + xFuncInfo->mpnParamClass = pIt->mpnParamClass; + xFuncInfo->mbVolatile = getFlag( pIt->mnFlags, FUNCFLAG_VOLATILE ); + + // get API opcode from BIFF function index or function name + initFuncOpCode( *xFuncInfo, getFlag( pIt->mnFlags, FUNCFLAG_EXTERNAL ) ? maExtFuncTokens : maIntFuncTokens ); + + // insert the function info into the maps + if( xFuncInfo->mnApiOpCode != mrOpCodes.OPCODE_NONAME ) + { + if( (xFuncInfo->mnApiOpCode == mrOpCodes.OPCODE_EXTERNAL) && (xFuncInfo->maExtProgName.getLength() > 0) ) + maExtProgFuncs[ xFuncInfo->maExtProgName ] = xFuncInfo; + else + maOpCodeFuncs[ xFuncInfo->mnApiOpCode ] = xFuncInfo; + } + if( xFuncInfo->maOoxFuncName.getLength() > 0 ) + maOoxFuncs[ xFuncInfo->maOoxFuncName ] = xFuncInfo; + if( xFuncInfo->mnOobFuncId != NOID ) + maOobFuncs[ xFuncInfo->mnOobFuncId ] = xFuncInfo; + if( xFuncInfo->mnBiffFuncId != NOID ) + maBiffFuncs[ xFuncInfo->mnBiffFuncId ] = xFuncInfo; + if( xFuncInfo->maExternCallName.getLength() > 0 ) + maMacroFuncs[ xFuncInfo->maExternCallName ] = xFuncInfo; + } + } +} + +// function provider ========================================================== + +FunctionProvider::FunctionProvider( const WorkbookHelper& rHelper ) +{ + bool bImportFilter = rHelper.getBaseFilter().isImportFilter(); + switch( rHelper.getFilterType() ) + { + case FILTER_OOX: + mxImpl.reset( new FunctionProviderImpl( *this, rHelper.getDocument(), bImportFilter ) ); + break; + case FILTER_BIFF: + mxImpl.reset( new FunctionProviderImpl( *this, rHelper.getDocument(), rHelper.getBiff(), bImportFilter ) ); + break; + case FILTER_UNKNOWN: break; + } +} + +FunctionProvider::FunctionProvider( const Reference< XSpreadsheetDocument >& rxDocument, bool bImportFilter ) +{ + mxImpl.reset( new FunctionProviderImpl( *this, rxDocument, bImportFilter ) ); +} + +FunctionProvider::FunctionProvider( const Reference< XSpreadsheetDocument >& rxDocument, BiffType eBiff, bool bImportFilter ) +{ + mxImpl.reset( new FunctionProviderImpl( *this, rxDocument, eBiff, bImportFilter ) ); +} + +FunctionProvider::~FunctionProvider() +{ +} + +const FunctionInfo* FunctionProvider::getFuncInfoFromApiToken( const ApiToken& rToken ) const +{ + return mxImpl->getFuncInfoFromApiToken( rToken ); +} + +const FunctionInfo* FunctionProvider::getFuncInfoFromOoxFuncName( const OUString& rFuncName ) const +{ + return mxImpl->getFuncInfoFromOoxFuncName( rFuncName ); +} + +const FunctionInfo* FunctionProvider::getFuncInfoFromOobFuncId( sal_uInt16 nFuncId ) const +{ + return mxImpl->getFuncInfoFromOobFuncId( nFuncId ); +} + +const FunctionInfo* FunctionProvider::getFuncInfoFromBiffFuncId( sal_uInt16 nFuncId ) const +{ + return mxImpl->getFuncInfoFromBiffFuncId( nFuncId ); +} + +const FunctionInfo* FunctionProvider::getFuncInfoFromExternCallName( const OUString& rExtCallName ) const +{ + return mxImpl->getFuncInfoFromExternCallName( rExtCallName ); +} + +Sequence< FormulaOpCodeMapEntry > FunctionProvider::getOoxParserMap() const +{ + return mxImpl->getOoxParserMap(); +} + +// token sequence iterator ==================================================== + +ApiTokenIterator::ApiTokenIterator( const ApiTokenSequence& rTokens, sal_Int32 nSpacesOpCode, bool bSkipSpaces ) : + mpToken( rTokens.getConstArray() ), + mpTokenEnd( rTokens.getConstArray() + rTokens.getLength() ), + mnSpacesOpCode( nSpacesOpCode ), + mbSkipSpaces( bSkipSpaces ) +{ + skipSpaces(); +} + +ApiTokenIterator::ApiTokenIterator( const ApiTokenIterator& rIter, bool bSkipSpaces ) : + mpToken( rIter.mpToken ), + mpTokenEnd( rIter.mpTokenEnd ), + mnSpacesOpCode( rIter.mnSpacesOpCode ), + mbSkipSpaces( bSkipSpaces ) +{ + skipSpaces(); +} + +ApiTokenIterator& ApiTokenIterator::operator++() +{ + if( is() ) + { + ++mpToken; + skipSpaces(); + } + return *this; +} + +void ApiTokenIterator::skipSpaces() +{ + if( mbSkipSpaces ) + while( is() && (mpToken->OpCode == mnSpacesOpCode) ) + ++mpToken; +} + +// formual contexts =========================================================== + +FormulaContext::FormulaContext( bool bRelativeAsOffset, bool bAlways3dRefs ) : + maBaseAddress( 0, 0, 0 ), + mbRelativeAsOffset( bRelativeAsOffset ), + mbAlways3dRefs( bAlways3dRefs ) +{ +} + +FormulaContext::~FormulaContext() +{ +} + +void FormulaContext::setSharedFormula( const CellAddress& ) +{ +} + +// ---------------------------------------------------------------------------- + +TokensFormulaContext::TokensFormulaContext( bool bRelativeAsOffset, bool bAlways3dRefs ) : + FormulaContext( bRelativeAsOffset, bAlways3dRefs ) +{ +} + +void TokensFormulaContext::setTokens( const ApiTokenSequence& rTokens ) +{ + maTokens = rTokens; +} + +// ---------------------------------------------------------------------------- + +SimpleFormulaContext::SimpleFormulaContext( const Reference< XFormulaTokens >& rxTokens, + bool bRelativeAsOffset, bool bAlways3dRefs ) : + FormulaContext( bRelativeAsOffset, bAlways3dRefs ), + mxTokens( rxTokens ) +{ + OSL_ENSURE( mxTokens.is(), "SimpleFormulaContext::SimpleFormulaContext - missing XFormulaTokens interface" ); +} + +void SimpleFormulaContext::setTokens( const ApiTokenSequence& rTokens ) +{ + mxTokens->setTokens( rTokens ); +} + +// formula parser/formula compiler base class ================================= + +namespace { + +bool lclConvertToCellAddress( CellAddress& orAddress, const SingleReference& rSingleRef, sal_Int32 nExpectedSheet ) +{ + orAddress = CellAddress( static_cast< sal_Int16 >( rSingleRef.Sheet ), + rSingleRef.Column, rSingleRef.Row ); + return + ((nExpectedSheet < 0) || (nExpectedSheet == rSingleRef.Sheet)) && + !getFlag( rSingleRef.Flags, COLUMN_DELETED | ROW_DELETED | SHEET_DELETED ); +} + +bool lclConvertToCellRange( CellRangeAddress& orRange, const ComplexReference& rComplexRef, sal_Int32 nExpectedSheet ) +{ + orRange = CellRangeAddress( static_cast< sal_Int16 >( rComplexRef.Reference1.Sheet ), + rComplexRef.Reference1.Column, rComplexRef.Reference1.Row, + rComplexRef.Reference2.Column, rComplexRef.Reference2.Row ); + return + (rComplexRef.Reference1.Sheet == rComplexRef.Reference2.Sheet) && + ((nExpectedSheet < 0) || (nExpectedSheet == rComplexRef.Reference1.Sheet)) && + !getFlag( rComplexRef.Reference1.Flags, COLUMN_DELETED | ROW_DELETED | SHEET_DELETED ) && + !getFlag( rComplexRef.Reference2.Flags, COLUMN_DELETED | ROW_DELETED | SHEET_DELETED ); +} + +enum TokenToRangeListState { STATE_REF, STATE_SEP, STATE_OPEN, STATE_CLOSE, STATE_ERROR }; + +TokenToRangeListState lclProcessRef( ApiCellRangeList& orRanges, const Any& rData, sal_Int32 nExpectedSheet ) +{ + SingleReference aSingleRef; + if( rData >>= aSingleRef ) + { + CellAddress aAddress; + // ignore invalid addresses (with #REF! errors), but to not stop parsing + if( lclConvertToCellAddress( aAddress, aSingleRef, nExpectedSheet ) ) + orRanges.push_back( CellRangeAddress( aAddress.Sheet, aAddress.Column, aAddress.Row, aAddress.Column, aAddress.Row ) ); + return STATE_REF; + } + ComplexReference aComplexRef; + if( rData >>= aComplexRef ) + { + CellRangeAddress aRange; + // ignore invalid ranges (with #REF! errors), but to not stop parsing + if( lclConvertToCellRange( aRange, aComplexRef, nExpectedSheet ) ) + orRanges.push_back( aRange ); + return STATE_REF; + } + return STATE_ERROR; +} + +TokenToRangeListState lclProcessOpen( sal_Int32& ornParenLevel ) +{ + ++ornParenLevel; + return STATE_OPEN; +} + +TokenToRangeListState lclProcessClose( sal_Int32& ornParenLevel ) +{ + --ornParenLevel; + return (ornParenLevel >= 0) ? STATE_CLOSE : STATE_ERROR; +} + +} // namespace + +// ---------------------------------------------------------------------------- + +FormulaProcessorBase::FormulaProcessorBase( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + maFuncProv( rHelper ) +{ +} + +// ---------------------------------------------------------------------------- + +OUString FormulaProcessorBase::generateAddress2dString( const CellAddress& rAddress, bool bAbsolute ) +{ + return generateAddress2dString( BinAddress( rAddress ), bAbsolute ); +} + +OUString FormulaProcessorBase::generateAddress2dString( const BinAddress& rAddress, bool bAbsolute ) +{ + OUStringBuffer aBuffer; + // column + for( sal_Int32 nTemp = rAddress.mnCol; nTemp >= 0; (nTemp /= 26) -= 1 ) + aBuffer.insert( 0, sal_Unicode( 'A' + (nTemp % 26) ) ); + if( bAbsolute ) + aBuffer.insert( 0, sal_Unicode( '$' ) ); + // row + if( bAbsolute ) + aBuffer.append( sal_Unicode( '$' ) ); + aBuffer.append( static_cast< sal_Int32 >( rAddress.mnRow + 1 ) ); + return aBuffer.makeStringAndClear(); +} + +OUString FormulaProcessorBase::generateRange2dString( const CellRangeAddress& rRange, bool bAbsolute ) +{ + return generateRange2dString( BinRange( rRange ), bAbsolute ); +} + +OUString FormulaProcessorBase::generateRange2dString( const BinRange& rRange, bool bAbsolute ) +{ + OUStringBuffer aBuffer( generateAddress2dString( rRange.maFirst, bAbsolute ) ); + if( (rRange.getColCount() > 1) || (rRange.getRowCount() > 1) ) + aBuffer.append( sal_Unicode( ':' ) ).append( generateAddress2dString( rRange.maLast, bAbsolute ) ); + return aBuffer.makeStringAndClear(); +} + +OUString FormulaProcessorBase::generateRangeList2dString( const ApiCellRangeList& rRanges, + bool bAbsolute, sal_Unicode cSeparator, bool bEncloseMultiple ) +{ + OUStringBuffer aBuffer; + for( ApiCellRangeList::const_iterator aIt = rRanges.begin(), aEnd = rRanges.end(); aIt != aEnd; ++aIt ) + { + if( aBuffer.getLength() > 0 ) + aBuffer.append( cSeparator ); + aBuffer.append( generateRange2dString( *aIt, bAbsolute ) ); + } + if( bEncloseMultiple && (rRanges.size() > 1) ) + aBuffer.insert( 0, sal_Unicode( '(' ) ).append( sal_Unicode( ')' ) ); + return aBuffer.makeStringAndClear(); +} + +// ---------------------------------------------------------------------------- + +Any FormulaProcessorBase::extractReference( const ApiTokenSequence& rTokens ) const +{ + ApiTokenIterator aTokenIt( rTokens, maFuncProv.OPCODE_SPACES, true ); + if( aTokenIt.is() && (aTokenIt->OpCode == maFuncProv.OPCODE_PUSH) ) + { + Any aRefAny = aTokenIt->Data; + if( !(++aTokenIt).is() && (aRefAny.has< SingleReference >() || aRefAny.has< ComplexReference >()) ) + return aRefAny; + } + return Any(); +} + +void FormulaProcessorBase::extractCellRangeList( ApiCellRangeList& orRanges, + const ApiTokenSequence& rTokens, sal_Int32 nExpectedSheet ) const +{ + orRanges.clear(); + TokenToRangeListState eState = STATE_OPEN; + sal_Int32 nParenLevel = 0; + for( ApiTokenIterator aIt( rTokens, maFuncProv.OPCODE_SPACES, true ); aIt.is() && (eState != STATE_ERROR); ++aIt ) + { + sal_Int32 nOpCode = aIt->OpCode; + switch( eState ) + { + case STATE_REF: + if( nOpCode == maFuncProv.OPCODE_LIST ) eState = STATE_SEP; + else if( nOpCode == maFuncProv.OPCODE_CLOSE ) eState = lclProcessClose( nParenLevel ); + else eState = STATE_ERROR; + break; + case STATE_SEP: + if( nOpCode == maFuncProv.OPCODE_PUSH ) eState = lclProcessRef( orRanges, aIt->Data, nExpectedSheet ); + else if( nOpCode == maFuncProv.OPCODE_LIST ) eState = STATE_SEP; + else if( nOpCode == maFuncProv.OPCODE_OPEN ) eState = lclProcessOpen( nParenLevel ); + else if( nOpCode == maFuncProv.OPCODE_CLOSE ) eState = lclProcessClose( nParenLevel ); + else eState = STATE_ERROR; + break; + case STATE_OPEN: + if( nOpCode == maFuncProv.OPCODE_PUSH ) eState = lclProcessRef( orRanges, aIt->Data, nExpectedSheet ); + else if( nOpCode == maFuncProv.OPCODE_LIST ) eState = STATE_SEP; + else if( nOpCode == maFuncProv.OPCODE_OPEN ) eState = lclProcessOpen( nParenLevel ); + else if( nOpCode == maFuncProv.OPCODE_CLOSE ) eState = lclProcessClose( nParenLevel ); + else eState = STATE_ERROR; + break; + case STATE_CLOSE: + if( nOpCode == maFuncProv.OPCODE_LIST ) eState = STATE_SEP; + else if( nOpCode == maFuncProv.OPCODE_CLOSE ) eState = lclProcessClose( nParenLevel ); + else eState = STATE_ERROR; + break; + default:; + } + } + + if( eState == STATE_ERROR ) + orRanges.clear(); + else + getAddressConverter().validateCellRangeList( orRanges, false ); +} + +bool FormulaProcessorBase::extractString( OUString& orString, const ApiTokenSequence& rTokens ) const +{ + ApiTokenIterator aTokenIt( rTokens, maFuncProv.OPCODE_SPACES, true ); + return aTokenIt.is() && (aTokenIt->OpCode == maFuncProv.OPCODE_PUSH) && (aTokenIt->Data >>= orString) && !(++aTokenIt).is(); +} + +void FormulaProcessorBase::convertStringToStringList( + ApiTokenSequence& orTokens, sal_Unicode cStringSep, bool bTrimLeadingSpaces ) const +{ + OUString aString; + if( extractString( aString, orTokens ) && (aString.getLength() > 0) ) + { + ::std::vector< ApiToken > aNewTokens; + sal_Int32 nPos = 0; + sal_Int32 nLen = aString.getLength(); + while( (0 <= nPos) && (nPos < nLen) ) + { + OUString aEntry = aString.getToken( 0, cStringSep, nPos ); + if( bTrimLeadingSpaces ) + { + sal_Int32 nStart = 0; + while( (nStart < aEntry.getLength()) && (aEntry[ nStart ] == ' ') ) ++nStart; + aEntry = aEntry.copy( nStart ); + } + if( !aNewTokens.empty() ) + aNewTokens.push_back( ApiToken( maFuncProv.OPCODE_SEP, Any() ) ); + aNewTokens.push_back( ApiToken( maFuncProv.OPCODE_PUSH, Any( aEntry ) ) ); + } + orTokens = ContainerHelper::vectorToSequence( aNewTokens ); + } +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/formulaparser.cxx b/oox/source/xls/formulaparser.cxx new file mode 100644 index 000000000000..165d8f2b2873 --- /dev/null +++ b/oox/source/xls/formulaparser.cxx @@ -0,0 +1,2595 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: formulaparser.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:08 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/formulaparser.hxx" +#include +#include +#include +#include +#include +#include +#include "oox/helper/containerhelper.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/helper/recordinputstream.hxx" +#include "oox/xls/addressconverter.hxx" +#include "oox/xls/biffinputstream.hxx" +#include "oox/xls/defnamesbuffer.hxx" +#include "oox/xls/externallinkbuffer.hxx" +#include "oox/xls/tablebuffer.hxx" +#include "oox/xls/worksheethelper.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::table::CellAddress; +using ::com::sun::star::table::CellRangeAddress; +using ::com::sun::star::sheet::SingleReference; +using ::com::sun::star::sheet::ComplexReference; +using ::com::sun::star::sheet::XFormulaParser; +using namespace ::com::sun::star::sheet::ReferenceFlags; + +namespace oox { +namespace xls { + +// parser implementation base ================================================= + +class FormulaParserImpl : public WorkbookHelper +{ +public: + explicit FormulaParserImpl( + const WorkbookHelper& rHelper, + const FunctionProvider& rFuncProv ); + + /** Converts an XML formula string. */ + virtual void importOoxFormula( + FormulaContext& rContext, + const OUString& rFormulaString ); + + /** Imports and converts a OOBIN token array from the passed stream. */ + virtual void importOobFormula( + FormulaContext& rContext, + RecordInputStream& rStrm ); + + /** Imports and converts a BIFF token array from the passed stream. */ + virtual void importBiffFormula( + FormulaContext& rContext, + BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ); + + /** Finalizes the passed token array after import (e.g. adjusts function + parameters) and sets the formula using the passed context. */ + void setFormula( + FormulaContext& rContext, + const ApiTokenSequence& rTokens ); + +protected: + /** Sets the current formula context used for import. */ + inline FormulaContext& getFormulaContext() const { return *mpContext; } + + /** Sets the current formula context used for import. */ + void initializeImport( FormulaContext& rContext ); + /** Finalizes the passed token array after import. */ + void finalizeImport( const ApiTokenSequence& rTokens ); + /** Finalizes the internal token storage after import. */ + void finalizeImport(); + + /** Inserts a shared formula using the current formula context and passed base address. */ + void setSharedFormula( const BinAddress& rBaseAddr ); + + // token array ------------------------------------------------------------ + + bool resetSpaces(); + inline void incLeadingSpaces( sal_Int32 nSpaces ) { mnLeadingSpaces += nSpaces; } + inline void incOpeningSpaces( sal_Int32 nSpaces ) { mnOpeningSpaces += nSpaces; } + inline void incClosingSpaces( sal_Int32 nSpaces ) { mnClosingSpaces += nSpaces; } + + size_t getFormulaSize() const; + Any& appendRawToken( sal_Int32 nOpCode ); + Any& insertRawToken( sal_Int32 nOpCode, size_t nIndexFromEnd ); + size_t appendSpacesToken( sal_Int32 nSpaces ); + size_t insertSpacesToken( sal_Int32 nSpaces, size_t nIndexFromEnd ); + + size_t getOperandSize( size_t nOpCountFromEnd, size_t nOpIndex ) const; + void pushOperandSize( size_t nSize ); + size_t popOperandSize(); + + ApiToken& getOperandToken( size_t nOpCountFromEnd, size_t nOpIndex, size_t nTokenIndex ); + void removeOperand( size_t nOpCountFromEnd, size_t nOpIndex ); + void removeLastOperands( size_t nOpCountFromEnd ); + + bool pushOperandToken( sal_Int32 nOpCode, sal_Int32 nSpaces ); + bool pushAnyOperandToken( const Any& rAny, sal_Int32 nOpCode, sal_Int32 nSpaces ); + template< typename Type > + bool pushValueOperandToken( const Type& rValue, sal_Int32 nOpCode, sal_Int32 nSpaces ); + template< typename Type > + inline bool pushValueOperandToken( const Type& rValue, sal_Int32 nSpaces ) + { return pushValueOperandToken( rValue, mrFuncProv.OPCODE_PUSH, nSpaces ); } + bool pushParenthesesOperandToken( sal_Int32 nOpeningSpaces, sal_Int32 nClosingSpaces ); + bool pushUnaryPreOperatorToken( sal_Int32 nOpCode, sal_Int32 nSpaces ); + bool pushUnaryPostOperatorToken( sal_Int32 nOpCode, sal_Int32 nSpaces ); + bool pushBinaryOperatorToken( sal_Int32 nOpCode, sal_Int32 nSpaces ); + bool pushParenthesesOperatorToken( sal_Int32 nOpeningSpaces, sal_Int32 nClosingSpaces ); + bool pushFunctionOperatorToken( sal_Int32 nOpCode, size_t nParamCount, sal_Int32 nLeadingSpaces, sal_Int32 nClosingSpaces ); + bool pushFunctionOperatorToken( const FunctionInfo& rFuncInfo, size_t nParamCount, sal_Int32 nLeadingSpaces, sal_Int32 nClosingSpaces ); + + bool pushOperand( sal_Int32 nOpCode ); + bool pushAnyOperand( const Any& rAny, sal_Int32 nOpCode ); + template< typename Type > + bool pushValueOperand( const Type& rValue, sal_Int32 nOpCode ); + template< typename Type > + inline bool pushValueOperand( const Type& rValue ) + { return pushValueOperand( rValue, mrFuncProv.OPCODE_PUSH ); } + bool pushBoolOperand( bool bValue ); + bool pushErrorOperand( double fEncodedError ); + bool pushBiffErrorOperand( sal_uInt8 nErrorCode ); + bool pushParenthesesOperand(); + bool pushReferenceOperand( const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ); + bool pushReferenceOperand( const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ); + bool pushReferenceOperand( const LinkSheetRange& rSheetRange, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ); + bool pushReferenceOperand( const LinkSheetRange& rSheetRange, const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ); + bool pushNlrOperand( const BinSingleRef2d& rRef ); + bool pushEmbeddedRefOperand( const DefinedNameBase& rName ); + bool pushDefinedNameOperand( const DefinedNameRef& rxDefName ); + bool pushDdeLinkOperand( const OUString& rDdeServer, const OUString& rDdeTopic, const OUString& rDdeItem ); + bool pushExternalNameOperand( const ExternalNameRef& rxExtName, ExternalLinkType eLinkType ); + + bool pushUnaryPreOperator( sal_Int32 nOpCode ); + bool pushUnaryPostOperator( sal_Int32 nOpCode ); + bool pushBinaryOperator( sal_Int32 nOpCode ); + bool pushParenthesesOperator(); + bool pushFunctionOperator( sal_Int32 nOpCode, size_t nParamCount ); + bool pushFunctionOperator( const FunctionInfo& rFuncInfo, size_t nParamCount ); + +private: + // reference conversion --------------------------------------------------- + + void initReference2d( SingleReference& orApiRef ) const; + void initReference3d( SingleReference& orApiRef, sal_Int32 nSheet ) const; + void convertColRow( SingleReference& orApiRef, const BinSingleRef2d& rRef, bool bRelativeAsOffset ) const; + void convertReference( SingleReference& orApiRef, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const; + void convertReference( ComplexReference& orApiRef, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const; + void convertReference2d( SingleReference& orApiRef, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const; + void convertReference2d( ComplexReference& orApiRef, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const; + void convertReference3d( SingleReference& orApiRef, sal_Int32 nSheet, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const; + void convertReference3d( ComplexReference& orApiRef, const LinkSheetRange& rSheetRange, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const; + + // finalize token sequence ------------------------------------------------ + + typedef ::std::vector< const ApiToken* > ParameterPosVector; + + void processTokens( const ApiToken* pToken, const ApiToken* pTokenEnd ); + const ApiToken* processParameters( const FunctionInfo& rFuncInfo, const ApiToken* pToken, const ApiToken* pTokenEnd ); + + bool isEmptyParameter( const ApiToken* pToken, const ApiToken* pTokenEnd ) const; + OUString getExternCallParameter( const ApiToken* pToken, const ApiToken* pTokenEnd ) const; + const ApiToken* skipParentheses( const ApiToken* pToken, const ApiToken* pTokenEnd ) const; + const ApiToken* findParameters( ParameterPosVector& rParams, const ApiToken* pToken, const ApiToken* pTokenEnd ) const; + void appendCalcOnlyParameter( const FunctionInfo& rFuncInfo, size_t nParam ); + void appendRequiredParameters( const FunctionInfo& rFuncInfo, size_t nParamCount ); + + void appendFinalToken( const ApiToken& rToken ); + Any& appendFinalToken( sal_Int32 nOpCode ); + +protected: + const FunctionProvider& mrFuncProv; /// Function info provider. + const sal_Int32 mnMaxApiCol; /// Maximum column index in own document. + const sal_Int32 mnMaxApiRow; /// Maximum row index in own document. + const sal_Int32 mnMaxXlsCol; /// Maximum column index in imported document. + const sal_Int32 mnMaxXlsRow; /// Maximum row index in imported document. + +private: + typedef ::std::vector< ApiToken > ApiTokenVector; + typedef ::std::vector< size_t > SizeTypeVector; + + ApiTokenVector maTokenStorage; /// Raw unordered token storage. + SizeTypeVector maTokenIndexes; /// Indexes into maTokenStorage. + SizeTypeVector maOperandSizeStack; /// Stack with token sizes per operand. + FormulaContext* mpContext; /// Current formula context. + sal_Int32 mnLeadingSpaces; /// Current number of spaces before next token. + sal_Int32 mnOpeningSpaces; /// Current number of spaces before opening parenthesis. + sal_Int32 mnClosingSpaces; /// Current number of spaces before closing parenthesis. +}; + +// ---------------------------------------------------------------------------- + +FormulaParserImpl::FormulaParserImpl( const WorkbookHelper& rHelper, const FunctionProvider& rFuncProv ) : + WorkbookHelper( rHelper ), + mrFuncProv( rFuncProv ), + mnMaxApiCol( rHelper.getAddressConverter().getMaxApiAddress().Column ), + mnMaxApiRow( rHelper.getAddressConverter().getMaxApiAddress().Row ), + mnMaxXlsCol( rHelper.getAddressConverter().getMaxXlsAddress().Column ), + mnMaxXlsRow( rHelper.getAddressConverter().getMaxXlsAddress().Row ), + mpContext( 0 ) +{ + maTokenStorage.reserve( 0x2000 ); + maTokenIndexes.reserve( 0x2000 ); + maOperandSizeStack.reserve( 256 ); + resetSpaces(); +} + +void FormulaParserImpl::importOoxFormula( FormulaContext&, const OUString& ) +{ + OSL_ENSURE( false, "FormulaParserImpl::importOoxFormula - not implemented" ); +} + +void FormulaParserImpl::importOobFormula( FormulaContext&, RecordInputStream& ) +{ + OSL_ENSURE( false, "FormulaParserImpl::importOobFormula - not implemented" ); +} + +void FormulaParserImpl::importBiffFormula( FormulaContext&, BiffInputStream&, const sal_uInt16* ) +{ + OSL_ENSURE( false, "FormulaParserImpl::importBiffFormula - not implemented" ); +} + +void FormulaParserImpl::setFormula( FormulaContext& rContext, const ApiTokenSequence& rTokens ) +{ + initializeImport( rContext ); + finalizeImport( rTokens ); +} + +void FormulaParserImpl::initializeImport( FormulaContext& rContext ) +{ + maTokenStorage.clear(); + maTokenIndexes.clear(); + maOperandSizeStack.clear(); + mpContext = &rContext; +} + +void FormulaParserImpl::finalizeImport( const ApiTokenSequence& rTokens ) +{ + maTokenStorage.clear(); + const ApiToken* pToken = rTokens.getConstArray(); + processTokens( pToken, pToken + rTokens.getLength() ); + if( !maTokenStorage.empty() ) + mpContext->setTokens( ContainerHelper::vectorToSequence( maTokenStorage ) ); +} + +void FormulaParserImpl::finalizeImport() +{ + ApiTokenSequence aTokens( static_cast< sal_Int32 >( maTokenIndexes.size() ) ); + if( aTokens.hasElements() ) + { + ApiToken* pToken = aTokens.getArray(); + for( SizeTypeVector::const_iterator aIt = maTokenIndexes.begin(), aEnd = maTokenIndexes.end(); aIt != aEnd; ++aIt, ++pToken ) + *pToken = maTokenStorage[ *aIt ]; + } + finalizeImport( aTokens ); +} + +void FormulaParserImpl::setSharedFormula( const BinAddress& rBaseAddr ) +{ + CellAddress aApiBaseAddr; + if( getAddressConverter().convertToCellAddress( aApiBaseAddr, rBaseAddr, mpContext->getBaseAddress().Sheet, false ) ) + mpContext->setSharedFormula( aApiBaseAddr ); +} + +// token array ---------------------------------------------------------------- + +bool FormulaParserImpl::resetSpaces() +{ + mnLeadingSpaces = mnOpeningSpaces = mnClosingSpaces = 0; + return true; +} + +size_t FormulaParserImpl::getFormulaSize() const +{ + return maTokenIndexes.size(); +} + +Any& FormulaParserImpl::appendRawToken( sal_Int32 nOpCode ) +{ + size_t nTokenIndex = maTokenStorage.size(); + maTokenStorage.resize( nTokenIndex + 1 ); + maTokenStorage.back().OpCode = nOpCode; + maTokenIndexes.push_back( nTokenIndex ); + return maTokenStorage.back().Data; +} + +Any& FormulaParserImpl::insertRawToken( sal_Int32 nOpCode, size_t nIndexFromEnd ) +{ + size_t nTokenIndex = maTokenStorage.size(); + maTokenStorage.resize( nTokenIndex + 1 ); + maTokenStorage.back().OpCode = nOpCode; + maTokenIndexes.insert( maTokenIndexes.end() - nIndexFromEnd, nTokenIndex ); + return maTokenStorage.back().Data; +} + +size_t FormulaParserImpl::appendSpacesToken( sal_Int32 nSpaces ) +{ + if( nSpaces > 0 ) + { + appendRawToken( mrFuncProv.OPCODE_SPACES ) <<= nSpaces; + return 1; + } + return 0; +} + +size_t FormulaParserImpl::insertSpacesToken( sal_Int32 nSpaces, size_t nIndexFromEnd ) +{ + if( nSpaces > 0 ) + { + insertRawToken( mrFuncProv.OPCODE_SPACES, nIndexFromEnd ) <<= nSpaces; + return 1; + } + return 0; +} + +size_t FormulaParserImpl::getOperandSize( size_t nOpCountFromEnd, size_t nOpIndex ) const +{ + OSL_ENSURE( (nOpIndex < nOpCountFromEnd) && (nOpCountFromEnd <= maOperandSizeStack.size()), + "FormulaParserImpl::getOperandSize - invalid parameters" ); + return maOperandSizeStack[ maOperandSizeStack.size() - nOpCountFromEnd + nOpIndex ]; +} + +void FormulaParserImpl::pushOperandSize( size_t nSize ) +{ + maOperandSizeStack.push_back( nSize ); +} + +size_t FormulaParserImpl::popOperandSize() +{ + OSL_ENSURE( !maOperandSizeStack.empty(), "FormulaParserImpl::popOperandSize - invalid call" ); + size_t nOpSize = maOperandSizeStack.back(); + maOperandSizeStack.pop_back(); + return nOpSize; +} + +ApiToken& FormulaParserImpl::getOperandToken( size_t nOpCountFromEnd, size_t nOpIndex, size_t nTokenIndex ) +{ + OSL_ENSURE( getOperandSize( nOpCountFromEnd, nOpIndex ) > nTokenIndex, + "FormulaParserImpl::getOperandToken - invalid parameters" ); + SizeTypeVector::const_iterator aIndexIt = maTokenIndexes.end(); + for( SizeTypeVector::const_iterator aEnd = maOperandSizeStack.end(), aIt = aEnd - nOpCountFromEnd + nOpIndex; aIt != aEnd; ++aIt ) + aIndexIt -= *aIt; + return maTokenStorage[ *(aIndexIt + nTokenIndex) ]; +} + +void FormulaParserImpl::removeOperand( size_t nOpCountFromEnd, size_t nOpIndex ) +{ + OSL_ENSURE( (nOpIndex < nOpCountFromEnd) && (nOpCountFromEnd <= maOperandSizeStack.size()), + "FormulaParserImpl::removeOperand - invalid parameters" ); + // remove indexes into token storage, but do not touch storage itself + SizeTypeVector::iterator aSizeEnd = maOperandSizeStack.end(); + SizeTypeVector::iterator aSizeIt = aSizeEnd - nOpCountFromEnd + nOpIndex; + size_t nRemainingSize = 0; + for( SizeTypeVector::iterator aIt = aSizeIt + 1; aIt != aSizeEnd; ++aIt ) + nRemainingSize += *aIt; + maTokenIndexes.erase( maTokenIndexes.end() - nRemainingSize - *aSizeIt, maTokenIndexes.end() - nRemainingSize ); + maOperandSizeStack.erase( aSizeIt ); +} + +void FormulaParserImpl::removeLastOperands( size_t nOpCountFromEnd ) +{ + for( size_t nOpIndex = 0; nOpIndex < nOpCountFromEnd; ++nOpIndex ) + removeOperand( 1, 0 ); +} + +bool FormulaParserImpl::pushOperandToken( sal_Int32 nOpCode, sal_Int32 nSpaces ) +{ + size_t nSpacesSize = appendSpacesToken( nSpaces ); + appendRawToken( nOpCode ); + pushOperandSize( nSpacesSize + 1 ); + return true; +} + +bool FormulaParserImpl::pushAnyOperandToken( const Any& rAny, sal_Int32 nOpCode, sal_Int32 nSpaces ) +{ + size_t nSpacesSize = appendSpacesToken( nSpaces ); + appendRawToken( nOpCode ) = rAny; + pushOperandSize( nSpacesSize + 1 ); + return true; +} + +template< typename Type > +bool FormulaParserImpl::pushValueOperandToken( const Type& rValue, sal_Int32 nOpCode, sal_Int32 nSpaces ) +{ + size_t nSpacesSize = appendSpacesToken( nSpaces ); + appendRawToken( nOpCode ) <<= rValue; + pushOperandSize( nSpacesSize + 1 ); + return true; +} + +bool FormulaParserImpl::pushParenthesesOperandToken( sal_Int32 nOpeningSpaces, sal_Int32 nClosingSpaces ) +{ + size_t nSpacesSize = appendSpacesToken( nOpeningSpaces ); + appendRawToken( mrFuncProv.OPCODE_OPEN ); + nSpacesSize += appendSpacesToken( nClosingSpaces ); + appendRawToken( mrFuncProv.OPCODE_CLOSE ); + pushOperandSize( nSpacesSize + 2 ); + return true; +} + +bool FormulaParserImpl::pushUnaryPreOperatorToken( sal_Int32 nOpCode, sal_Int32 nSpaces ) +{ + bool bOk = maOperandSizeStack.size() >= 1; + if( bOk ) + { + size_t nOpSize = popOperandSize(); + size_t nSpacesSize = insertSpacesToken( nSpaces, nOpSize ); + insertRawToken( nOpCode, nOpSize ); + pushOperandSize( nOpSize + nSpacesSize + 1 ); + } + return bOk; +} + +bool FormulaParserImpl::pushUnaryPostOperatorToken( sal_Int32 nOpCode, sal_Int32 nSpaces ) +{ + bool bOk = maOperandSizeStack.size() >= 1; + if( bOk ) + { + size_t nOpSize = popOperandSize(); + size_t nSpacesSize = appendSpacesToken( nSpaces ); + appendRawToken( nOpCode ); + pushOperandSize( nOpSize + nSpacesSize + 1 ); + } + return bOk; +} + +bool FormulaParserImpl::pushBinaryOperatorToken( sal_Int32 nOpCode, sal_Int32 nSpaces ) +{ + bool bOk = maOperandSizeStack.size() >= 2; + if( bOk ) + { + size_t nOp2Size = popOperandSize(); + size_t nOp1Size = popOperandSize(); + size_t nSpacesSize = insertSpacesToken( nSpaces, nOp2Size ); + insertRawToken( nOpCode, nOp2Size ); + pushOperandSize( nOp1Size + nSpacesSize + 1 + nOp2Size ); + } + return bOk; +} + +bool FormulaParserImpl::pushParenthesesOperatorToken( sal_Int32 nOpeningSpaces, sal_Int32 nClosingSpaces ) +{ + bool bOk = maOperandSizeStack.size() >= 1; + if( bOk ) + { + size_t nOpSize = popOperandSize(); + size_t nSpacesSize = insertSpacesToken( nOpeningSpaces, nOpSize ); + insertRawToken( mrFuncProv.OPCODE_OPEN, nOpSize ); + nSpacesSize += appendSpacesToken( nClosingSpaces ); + appendRawToken( mrFuncProv.OPCODE_CLOSE ); + pushOperandSize( nOpSize + nSpacesSize + 2 ); + } + return bOk; +} + +bool FormulaParserImpl::pushFunctionOperatorToken( sal_Int32 nOpCode, size_t nParamCount, sal_Int32 nLeadingSpaces, sal_Int32 nClosingSpaces ) +{ + /* #i70925# if there are not enough tokens available on token stack, do + not exit with error, but reduce parameter count. */ + nParamCount = ::std::min( maOperandSizeStack.size(), nParamCount ); + + // convert all parameters on stack to a single operand separated with OPCODE_SEP + bool bOk = true; + for( size_t nParam = 1; bOk && (nParam < nParamCount); ++nParam ) + bOk = pushBinaryOperatorToken( mrFuncProv.OPCODE_SEP, 0 ); + + // add function parentheses and function name + return bOk && + ((nParamCount > 0) ? pushParenthesesOperatorToken( 0, nClosingSpaces ) : pushParenthesesOperandToken( 0, nClosingSpaces )) && + pushUnaryPreOperatorToken( nOpCode, nLeadingSpaces ); +} + +bool FormulaParserImpl::pushFunctionOperatorToken( const FunctionInfo& rFuncInfo, size_t nParamCount, sal_Int32 nLeadingSpaces, sal_Int32 nClosingSpaces ) +{ + bool bOk = pushFunctionOperatorToken( rFuncInfo.mnApiOpCode, nParamCount, nLeadingSpaces, nClosingSpaces ); + // try to create an external add-in call for the passed built-in function + if( bOk && (rFuncInfo.maExtProgName.getLength() > 0) ) + getOperandToken( 1, 0, 0 ).Data <<= rFuncInfo.maExtProgName; + return bOk; +} + +bool FormulaParserImpl::pushOperand( sal_Int32 nOpCode ) +{ + return pushOperandToken( nOpCode, mnLeadingSpaces ) && resetSpaces(); +} + +bool FormulaParserImpl::pushAnyOperand( const Any& rAny, sal_Int32 nOpCode ) +{ + return pushAnyOperandToken( rAny, nOpCode, mnLeadingSpaces ) && resetSpaces(); +} + +template< typename Type > +bool FormulaParserImpl::pushValueOperand( const Type& rValue, sal_Int32 nOpCode ) +{ + return pushValueOperandToken( rValue, nOpCode, mnLeadingSpaces ) && resetSpaces(); +} + +bool FormulaParserImpl::pushBoolOperand( bool bValue ) +{ + if( const FunctionInfo* pFuncInfo = mrFuncProv.getFuncInfoFromOobFuncId( bValue ? OOBIN_FUNC_TRUE : OOBIN_FUNC_FALSE ) ) + return pushFunctionOperator( pFuncInfo->mnApiOpCode, 0 ); + return pushValueOperand< double >( bValue ? 1.0 : 0.0 ); +} + +bool FormulaParserImpl::pushErrorOperand( double fEncodedError ) +{ + // HACK: enclose all error codes into an 1x1 matrix + // start token array with opening brace and leading spaces + pushOperand( mrFuncProv.OPCODE_ARRAY_OPEN ); + size_t nOpSize = popOperandSize(); + size_t nOldArraySize = maTokenIndexes.size(); + // push a double containing the Calc error code + appendRawToken( mrFuncProv.OPCODE_PUSH ) <<= fEncodedError; + // close token array and set resulting operand size + appendRawToken( mrFuncProv.OPCODE_ARRAY_CLOSE ); + pushOperandSize( nOpSize + maTokenIndexes.size() - nOldArraySize ); + return true; +} + +bool FormulaParserImpl::pushBiffErrorOperand( sal_uInt8 nErrorCode ) +{ + return pushErrorOperand( BiffHelper::calcDoubleFromError( nErrorCode ) ); +} + +bool FormulaParserImpl::pushParenthesesOperand() +{ + return pushParenthesesOperandToken( mnOpeningSpaces, mnClosingSpaces ) && resetSpaces(); +} + +bool FormulaParserImpl::pushReferenceOperand( const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) +{ + SingleReference aApiRef; + convertReference2d( aApiRef, rRef, bDeleted, bRelativeAsOffset ); + return pushValueOperand( aApiRef ); +} + +bool FormulaParserImpl::pushReferenceOperand( const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) +{ + ComplexReference aApiRef; + convertReference2d( aApiRef, rRef.maRef1, rRef.maRef2, bDeleted, bRelativeAsOffset ); + return pushValueOperand( aApiRef ); +} + +bool FormulaParserImpl::pushReferenceOperand( const LinkSheetRange& rSheetRange, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) +{ + if( rSheetRange.is3dRange() ) + { + // single-cell-range over several sheets, needs to create a ComplexReference + ComplexReference aApiRef; + convertReference3d( aApiRef, rSheetRange, rRef, rRef, bDeleted, bRelativeAsOffset ); + return pushValueOperand( aApiRef ); + } + SingleReference aApiRef; + convertReference3d( aApiRef, rSheetRange.isDeleted() ? -1 : rSheetRange.mnFirst, rRef, bDeleted, bRelativeAsOffset ); + return pushValueOperand( aApiRef ); +} + +bool FormulaParserImpl::pushReferenceOperand( const LinkSheetRange& rSheetRange, const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) +{ + ComplexReference aApiRef; + convertReference3d( aApiRef, rSheetRange, rRef.maRef1, rRef.maRef2, bDeleted, bRelativeAsOffset ); + return pushValueOperand( aApiRef ); +} + +bool FormulaParserImpl::pushNlrOperand( const BinSingleRef2d& rRef ) +{ + SingleReference aApiRef; + convertReference2d( aApiRef, rRef, false, false ); + return pushValueOperand( aApiRef, mrFuncProv.OPCODE_NLR ); +} + +bool FormulaParserImpl::pushEmbeddedRefOperand( const DefinedNameBase& rName ) +{ + Any aRefAny = rName.getReference( mpContext->getBaseAddress() ); + return aRefAny.hasValue() ? pushAnyOperand( aRefAny, mrFuncProv.OPCODE_PUSH ) : pushBiffErrorOperand( BIFF_ERR_NAME ); +} + +bool FormulaParserImpl::pushDefinedNameOperand( const DefinedNameRef& rxDefName ) +{ + if( !rxDefName ) + return pushBiffErrorOperand( BIFF_ERR_NAME ); + if( rxDefName->isMacroFunc( false ) ) + return pushValueOperand( rxDefName->getOoxName(), mrFuncProv.OPCODE_MACRO ); + if( rxDefName->getTokenIndex() >= 0 ) + return pushValueOperand( rxDefName->getTokenIndex(), mrFuncProv.OPCODE_NAME ); + return pushEmbeddedRefOperand( *rxDefName ); +} + +bool FormulaParserImpl::pushDdeLinkOperand( const OUString& rDdeServer, const OUString& rDdeTopic, const OUString& rDdeItem ) +{ + // create the function call DDE("server";"topic";"item") + return + pushValueOperandToken( rDdeServer, 0 ) && + pushValueOperandToken( rDdeTopic, 0 ) && + pushValueOperandToken( rDdeItem, 0 ) && + pushFunctionOperator( mrFuncProv.OPCODE_DDE, 3 ); +} + +bool FormulaParserImpl::pushExternalNameOperand( const ExternalNameRef& rxExtName, ExternalLinkType eLinkType ) +{ + if( rxExtName.get() ) switch( eLinkType ) + { + case LINKTYPE_INTERNAL: + case LINKTYPE_EXTERNAL: + return pushEmbeddedRefOperand( *rxExtName ); + + case LINKTYPE_ANALYSIS: + if( const FunctionInfo* pFuncInfo = mrFuncProv.getFuncInfoFromOoxFuncName( rxExtName->getOoxName() ) ) + if( pFuncInfo->maExternCallName.getLength() > 0 ) + return pushValueOperand( pFuncInfo->maExternCallName, mrFuncProv.OPCODE_MACRO ); + break; + + case LINKTYPE_DDE: + { + OUString aDdeServer, aDdeTopic, aDdeItem; + if( rxExtName->getDdeLinkData( aDdeServer, aDdeTopic, aDdeItem ) ) + return pushDdeLinkOperand( aDdeServer, aDdeTopic, aDdeItem ); + } + break; + + default: + OSL_ENSURE( eLinkType != LINKTYPE_SELF, "FormulaParserImpl::pushExternalNameOperand - invalid call" ); + } + return pushBiffErrorOperand( BIFF_ERR_NAME ); +} + +bool FormulaParserImpl::pushUnaryPreOperator( sal_Int32 nOpCode ) +{ + return pushUnaryPreOperatorToken( nOpCode, mnLeadingSpaces ) && resetSpaces(); +} + +bool FormulaParserImpl::pushUnaryPostOperator( sal_Int32 nOpCode ) +{ + return pushUnaryPostOperatorToken( nOpCode, mnLeadingSpaces ) && resetSpaces(); +} + +bool FormulaParserImpl::pushBinaryOperator( sal_Int32 nOpCode ) +{ + return pushBinaryOperatorToken( nOpCode, mnLeadingSpaces ) && resetSpaces(); +} + +bool FormulaParserImpl::pushParenthesesOperator() +{ + return pushParenthesesOperatorToken( mnOpeningSpaces, mnClosingSpaces ) && resetSpaces(); +} + +bool FormulaParserImpl::pushFunctionOperator( sal_Int32 nOpCode, size_t nParamCount ) +{ + return pushFunctionOperatorToken( nOpCode, nParamCount, mnLeadingSpaces, mnClosingSpaces ) && resetSpaces(); +} + +bool FormulaParserImpl::pushFunctionOperator( const FunctionInfo& rFuncInfo, size_t nParamCount ) +{ + return pushFunctionOperatorToken( rFuncInfo, nParamCount, mnLeadingSpaces, mnClosingSpaces ) && resetSpaces(); +} + +// reference conversion ------------------------------------------------------- + +void FormulaParserImpl::initReference2d( SingleReference& orApiRef ) const +{ + if( mpContext->isAlways3dRefs() ) + { + initReference3d( orApiRef, mpContext->getBaseAddress().Sheet ); + } + else + { + orApiRef.Flags = SHEET_RELATIVE; + // #i10184# absolute sheet index needed for relative references in shared formulas + orApiRef.Sheet = mpContext->getBaseAddress().Sheet; + orApiRef.RelativeSheet = 0; + } +} + +void FormulaParserImpl::initReference3d( SingleReference& orApiRef, sal_Int32 nSheet ) const +{ + orApiRef.Flags = SHEET_3D; + if( nSheet < 0 ) + { + orApiRef.Sheet = 0; + orApiRef.Flags |= SHEET_DELETED; + } + else + { + orApiRef.Sheet = nSheet; + } +} + +void FormulaParserImpl::convertReference( SingleReference& orApiRef, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const +{ + if( bDeleted ) + { + orApiRef.Column = 0; + orApiRef.Row = 0; + // no explicit information about whether row or column is deleted + orApiRef.Flags |= COLUMN_DELETED | ROW_DELETED; + } + else + { + // column/row indexes and flags + setFlag( orApiRef.Flags, COLUMN_RELATIVE, rRef.mbColRel ); + setFlag( orApiRef.Flags, ROW_RELATIVE, rRef.mbRowRel ); + (rRef.mbColRel ? orApiRef.RelativeColumn : orApiRef.Column) = rRef.mnCol; + (rRef.mbRowRel ? orApiRef.RelativeRow : orApiRef.Row) = rRef.mnRow; + // convert absolute indexes to relative offsets used in API + if( !bRelativeAsOffset ) + { + if( rRef.mbColRel ) + orApiRef.RelativeColumn -= mpContext->getBaseAddress().Column; + if( rRef.mbRowRel ) + orApiRef.RelativeRow -= mpContext->getBaseAddress().Row; + } + } +} + +void FormulaParserImpl::convertReference( ComplexReference& orApiRef, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const +{ + convertReference( orApiRef.Reference1, rRef1, bDeleted, bRelativeAsOffset ); + convertReference( orApiRef.Reference2, rRef2, bDeleted, bRelativeAsOffset ); + /* Handle references to complete rows or columns (e.g. $1:$2 or C:D), + need to expand or shrink to limits of own document. */ + if( !bDeleted && !rRef1.mbColRel && !rRef2.mbColRel && (orApiRef.Reference1.Column == 0) && (orApiRef.Reference2.Column == mnMaxXlsCol) ) + orApiRef.Reference2.Column = mnMaxApiCol; + if( !bDeleted && !rRef1.mbRowRel && !rRef2.mbRowRel && (orApiRef.Reference1.Row == 0) && (orApiRef.Reference2.Row == mnMaxXlsRow) ) + orApiRef.Reference2.Row = mnMaxApiRow; +} + +void FormulaParserImpl::convertReference2d( SingleReference& orApiRef, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const +{ + initReference2d( orApiRef ); + convertReference( orApiRef, rRef, bDeleted, bRelativeAsOffset ); +} + +void FormulaParserImpl::convertReference2d( ComplexReference& orApiRef, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const +{ + initReference2d( orApiRef.Reference1 ); + initReference2d( orApiRef.Reference2 ); + convertReference( orApiRef, rRef1, rRef2, bDeleted, bRelativeAsOffset ); + // remove sheet name from second part of reference + setFlag( orApiRef.Reference2.Flags, SHEET_3D, false ); +} + +void FormulaParserImpl::convertReference3d( SingleReference& orApiRef, sal_Int32 nSheet, const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) const +{ + initReference3d( orApiRef, nSheet ); + convertReference( orApiRef, rRef, bDeleted, bRelativeAsOffset ); +} + +void FormulaParserImpl::convertReference3d( ComplexReference& orApiRef, const LinkSheetRange& rSheetRange, const BinSingleRef2d& rRef1, const BinSingleRef2d& rRef2, bool bDeleted, bool bRelativeAsOffset ) const +{ + initReference3d( orApiRef.Reference1, rSheetRange.isDeleted() ? -1 : rSheetRange.mnFirst ); + initReference3d( orApiRef.Reference2, rSheetRange.isDeleted() ? -1 : rSheetRange.mnLast ); + convertReference( orApiRef, rRef1, rRef2, bDeleted, bRelativeAsOffset ); + // remove sheet name from second part of reference + setFlag( orApiRef.Reference2.Flags, SHEET_3D, rSheetRange.is3dRange() ); +} + +// finalize token sequence ---------------------------------------------------- + +void FormulaParserImpl::processTokens( const ApiToken* pToken, const ApiToken* pTokenEnd ) +{ + while( pToken < pTokenEnd ) + { + // push the current token into the vector + appendFinalToken( *pToken ); + // try to process a function, otherwise go to next token + if( const FunctionInfo* pFuncInfo = mrFuncProv.getFuncInfoFromApiToken( *pToken ) ) + pToken = processParameters( *pFuncInfo, pToken + 1, pTokenEnd ); + else + ++pToken; + } +} + +const ApiToken* FormulaParserImpl::processParameters( + const FunctionInfo& rFuncInfo, const ApiToken* pToken, const ApiToken* pTokenEnd ) +{ + // remember position of the token containing the function op-code + size_t nFuncNameIdx = maTokenStorage.size() - 1; + + // process a function, if an OPCODE_OPEN token is following + OSL_ENSURE( (pToken < pTokenEnd) && (pToken->OpCode == mrFuncProv.OPCODE_OPEN), "FormulaParserImpl::processParameters - OPCODE_OPEN expected" ); + if( (pToken < pTokenEnd) && (pToken->OpCode == mrFuncProv.OPCODE_OPEN) ) + { + // append the OPCODE_OPEN token to the vector + appendFinalToken( mrFuncProv.OPCODE_OPEN ); + + // store positions of OPCODE_OPEN, parameter separators, and OPCODE_CLOSE + ParameterPosVector aParams; + pToken = findParameters( aParams, pToken, pTokenEnd ); + OSL_ENSURE( aParams.size() >= 2, "FormulaParserImpl::processParameters - missing tokens" ); + size_t nParamCount = aParams.size() - 1; + + if( (nParamCount == 1) && isEmptyParameter( aParams[ 0 ] + 1, aParams[ 1 ] ) ) + { + /* Empty pair of parentheses -> function call without parameters, + process parameter, there might be spaces between parentheses. */ + processTokens( aParams[ 0 ] + 1, aParams[ 1 ] ); + } + else + { + const FunctionInfo* pRealFuncInfo = &rFuncInfo; + ParameterPosVector::const_iterator aPosIt = aParams.begin(); + + // preprocess add-ins, first parameter is reference to function name + if( rFuncInfo.mnOobFuncId == OOBIN_FUNC_EXTERNCALL ) + { + OUString aName = getExternCallParameter( *aPosIt + 1, *(aPosIt + 1) ); + if( const FunctionInfo* pExtFuncInfo = mrFuncProv.getFuncInfoFromExternCallName( aName ) ) + { + maTokenStorage[ nFuncNameIdx ].OpCode = pExtFuncInfo->mnApiOpCode; + // insert programmatic add-in function name + if( pExtFuncInfo->mnApiOpCode == mrFuncProv.OPCODE_EXTERNAL ) + maTokenStorage[ nFuncNameIdx ].Data <<= pExtFuncInfo->maExtProgName; + // prepare for following parameters + pRealFuncInfo = pExtFuncInfo; + --nParamCount; + ++aPosIt; + } + } + + // process all parameters + FuncInfoParamClassIterator aClassIt( *pRealFuncInfo ); + size_t nLastValidSize = maTokenStorage.size(); + size_t nLastValidCount = 0; + for( size_t nParam = 0; nParam < nParamCount; ++nParam, ++aPosIt, ++aClassIt ) + { + // add embedded Calc-only parameters + if( aClassIt.isCalcOnlyParam() ) + { + appendCalcOnlyParameter( *pRealFuncInfo, nParam ); + while( aClassIt.isCalcOnlyParam() ) ++aClassIt; + } + + const ApiToken* pParamBegin = *aPosIt + 1; + const ApiToken* pParamEnd = *(aPosIt + 1); + bool bIsEmpty = isEmptyParameter( pParamBegin, pParamEnd ); + + if( !aClassIt.isExcelOnlyParam() ) + { + // replace empty second and third parameter in IF function with zeros + if( (pRealFuncInfo->mnOobFuncId == OOBIN_FUNC_IF) && ((nParam == 1) || (nParam == 2)) && bIsEmpty ) + { + appendFinalToken( mrFuncProv.OPCODE_PUSH ) <<= static_cast< double >( 0.0 ); + bIsEmpty = false; + } + else + { + // process all tokens of the parameter + processTokens( pParamBegin, pParamEnd ); + } + // append parameter separator token + appendFinalToken( mrFuncProv.OPCODE_SEP ); + } + + /* #84453# Update size of new token sequence with valid parameters + to be able to remove trailing optional empty parameters. */ + if( !bIsEmpty || (nParam < pRealFuncInfo->mnMinParamCount) ) + { + nLastValidSize = maTokenStorage.size(); + nLastValidCount = nParam + 1; + } + } + + // #84453# remove trailing optional empty parameters + maTokenStorage.resize( nLastValidSize ); + + // add trailing Calc-only parameters + if( aClassIt.isCalcOnlyParam() ) + appendCalcOnlyParameter( *pRealFuncInfo, nLastValidCount ); + + // add optional parameters that are required in Calc + appendRequiredParameters( *pRealFuncInfo, nLastValidCount ); + + // remove last parameter separator token + if( maTokenStorage.back().OpCode == mrFuncProv.OPCODE_SEP ) + maTokenStorage.pop_back(); + } + + /* Append the OPCODE_CLOSE token to the vector, but only if there is + no OPCODE_BAD token at the end, this token already contains the + trailing closing parentheses. */ + if( (pTokenEnd - 1)->OpCode != mrFuncProv.OPCODE_BAD ) + appendFinalToken( mrFuncProv.OPCODE_CLOSE ); + } + + /* Replace OPCODE_EXTERNAL with OPCODE_NONAME to get #NAME! error in cell, + if no matching add-in function was found. */ + ApiToken& rFuncNameToken = maTokenStorage[ nFuncNameIdx ]; + if( (rFuncNameToken.OpCode == mrFuncProv.OPCODE_EXTERNAL) && !rFuncNameToken.Data.hasValue() ) + rFuncNameToken.OpCode = mrFuncProv.OPCODE_NONAME; + + return pToken; +} + +bool FormulaParserImpl::isEmptyParameter( const ApiToken* pToken, const ApiToken* pTokenEnd ) const +{ + while( (pToken < pTokenEnd) && (pToken->OpCode == mrFuncProv.OPCODE_SPACES) ) ++pToken; + if( (pToken < pTokenEnd) && (pToken->OpCode == mrFuncProv.OPCODE_MISSING) ) ++pToken; + while( (pToken < pTokenEnd) && (pToken->OpCode == mrFuncProv.OPCODE_SPACES) ) ++pToken; + return pToken == pTokenEnd; +} + +OUString FormulaParserImpl::getExternCallParameter( const ApiToken* pToken, const ApiToken* pTokenEnd ) const +{ + OUString aExtCallName; + while( (pToken < pTokenEnd) && (pToken->OpCode == mrFuncProv.OPCODE_SPACES) ) ++pToken; + if( (pToken < pTokenEnd) && (pToken->OpCode == mrFuncProv.OPCODE_MACRO) ) (pToken++)->Data >>= aExtCallName; + while( (pToken < pTokenEnd) && (pToken->OpCode == mrFuncProv.OPCODE_SPACES) ) ++pToken; + return (pToken == pTokenEnd) ? aExtCallName : OUString(); +} + +const ApiToken* FormulaParserImpl::skipParentheses( const ApiToken* pToken, const ApiToken* pTokenEnd ) const +{ + // skip tokens between OPCODE_OPEN and OPCODE_CLOSE + OSL_ENSURE( (pToken < pTokenEnd) && (pToken->OpCode == mrFuncProv.OPCODE_OPEN), "skipParentheses - OPCODE_OPEN expected" ); + ++pToken; + while( (pToken < pTokenEnd) && (pToken->OpCode != mrFuncProv.OPCODE_CLOSE) ) + { + if( pToken->OpCode == mrFuncProv.OPCODE_OPEN ) + pToken = skipParentheses( pToken, pTokenEnd ); + else + ++pToken; + } + // skip the OPCODE_CLOSE token + OSL_ENSURE( ((pToken < pTokenEnd) && (pToken->OpCode == mrFuncProv.OPCODE_CLOSE)) || ((pTokenEnd - 1)->OpCode == mrFuncProv.OPCODE_BAD), "skipParentheses - OPCODE_CLOSE expected" ); + return (pToken < pTokenEnd) ? (pToken + 1) : pTokenEnd; +} + +const ApiToken* FormulaParserImpl::findParameters( ParameterPosVector& rParams, + const ApiToken* pToken, const ApiToken* pTokenEnd ) const +{ + // push position of OPCODE_OPEN + OSL_ENSURE( (pToken < pTokenEnd) && (pToken->OpCode == mrFuncProv.OPCODE_OPEN), "FormulaParserImpl::findParameters - OPCODE_OPEN expected" ); + rParams.push_back( pToken++ ); + + // find positions of parameter separators + while( (pToken < pTokenEnd) && (pToken->OpCode != mrFuncProv.OPCODE_CLOSE) ) + { + if( pToken->OpCode == mrFuncProv.OPCODE_OPEN ) + pToken = skipParentheses( pToken, pTokenEnd ); + else if( pToken->OpCode == mrFuncProv.OPCODE_SEP ) + rParams.push_back( pToken++ ); + else + ++pToken; + } + + // push position of OPCODE_CLOSE + OSL_ENSURE( ((pToken < pTokenEnd) && (pToken->OpCode == mrFuncProv.OPCODE_CLOSE)) || ((pTokenEnd - 1)->OpCode == mrFuncProv.OPCODE_BAD), "FormulaParserImpl::findParameters - OPCODE_CLOSE expected" ); + rParams.push_back( pToken ); + return (pToken < pTokenEnd) ? (pToken + 1) : pTokenEnd; +} + +void FormulaParserImpl::appendCalcOnlyParameter( const FunctionInfo& rFuncInfo, size_t nParam ) +{ + (void)nParam; // prevent 'unused' warning + switch( rFuncInfo.mnOobFuncId ) + { + case OOBIN_FUNC_FLOOR: + case OOBIN_FUNC_CEILING: + OSL_ENSURE( nParam == 2, "FormulaParserImpl::appendCalcOnlyParameter - unexpected parameter index" ); + appendFinalToken( mrFuncProv.OPCODE_PUSH ) <<= static_cast< double >( 1.0 ); + appendFinalToken( mrFuncProv.OPCODE_SEP ); + break; + } +} + +void FormulaParserImpl::appendRequiredParameters( const FunctionInfo& rFuncInfo, size_t nParamCount ) +{ + switch( rFuncInfo.mnOobFuncId ) + { + case OOBIN_FUNC_WEEKNUM: + if( nParamCount == 1 ) + { + appendFinalToken( mrFuncProv.OPCODE_PUSH ) <<= static_cast< double >( 1.0 ); + appendFinalToken( mrFuncProv.OPCODE_SEP ); + } + break; + } +} + +void FormulaParserImpl::appendFinalToken( const ApiToken& rToken ) +{ + if( (rToken.OpCode == mrFuncProv.OPCODE_MACRO) && !rToken.Data.hasValue() ) + { + appendFinalToken( mrFuncProv.OPCODE_ARRAY_OPEN ); + appendFinalToken( mrFuncProv.OPCODE_PUSH ) <<= BiffHelper::calcDoubleFromError( BIFF_ERR_NAME ); + appendFinalToken( mrFuncProv.OPCODE_ARRAY_CLOSE ); + } + else + maTokenStorage.push_back( rToken ); +} + +Any& FormulaParserImpl::appendFinalToken( sal_Int32 nOpCode ) +{ + maTokenStorage.resize( maTokenStorage.size() + 1 ); + maTokenStorage.back().OpCode = nOpCode; + return maTokenStorage.back().Data; +} + +// OOX parser implementation ================================================== + +class OoxFormulaParserImpl : public FormulaParserImpl +{ +public: + explicit OoxFormulaParserImpl( + const WorkbookHelper& rHelper, + const FunctionProvider& rFuncProv ); + + virtual void importOoxFormula( + FormulaContext& rContext, + const OUString& rFormulaString ); + + virtual void importOobFormula( + FormulaContext& rContext, + RecordInputStream& rStrm ); + +private: + // import token contents and create API formula token --------------------- + + bool importAttrToken( RecordInputStream& rStrm ); + bool importSpaceToken( RecordInputStream& rStrm ); + bool importTableToken( RecordInputStream& rStrm ); + bool importArrayToken( RecordInputStream& rStrm ); + bool importRefToken( RecordInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); + bool importAreaToken( RecordInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); + bool importRef3dToken( RecordInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); + bool importArea3dToken( RecordInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); + bool importMemAreaToken( RecordInputStream& rStrm, bool bAddData ); + bool importMemFuncToken( RecordInputStream& rStrm ); + bool importNameToken( RecordInputStream& rStrm ); + bool importNameXToken( RecordInputStream& rStrm ); + bool importFuncToken( RecordInputStream& rStrm ); + bool importFuncVarToken( RecordInputStream& rStrm ); + bool importExpToken( RecordInputStream& rStrm ); + + LinkSheetRange readSheetRange( RecordInputStream& rStrm ); + + void swapStreamPosition( RecordInputStream& rStrm ); + void skipMemAreaAddData( RecordInputStream& rStrm ); + + // convert BIN token and push API operand or operator --------------------- + + bool pushOobName( sal_Int32 nNameId ); + bool pushOobExtName( sal_Int32 nRefId, sal_Int32 nNameId ); + bool pushOobFunction( sal_uInt16 nFuncId ); + bool pushOobFunction( sal_uInt16 nFuncId, sal_uInt8 nParamCount ); + +private: + Reference< XFormulaParser > mxParser; + PropertySet maParserProps; + const OUString maRefPosProp; + sal_Int32 mnAddDataPos; /// Current stream position for additional data (tExp, tArray, tMemArea). +}; + +// ---------------------------------------------------------------------------- + +OoxFormulaParserImpl::OoxFormulaParserImpl( const WorkbookHelper& rHelper, const FunctionProvider& rFuncProv ) : + FormulaParserImpl( rHelper, rFuncProv ), + maRefPosProp( CREATE_OUSTRING( "ReferencePosition" ) ), + mnAddDataPos( 0 ) +{ + try + { + Reference< XMultiServiceFactory > xFactory( getDocument(), UNO_QUERY_THROW ); + mxParser.set( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.sheet.FormulaParser" ) ), UNO_QUERY_THROW ); + } + catch( Exception& ) + { + } + OSL_ENSURE( mxParser.is(), "OoxFormulaParserImpl::OoxFormulaParserImpl - cannot create formula parser" ); + maParserProps.set( mxParser ); + maParserProps.setProperty( CREATE_OUSTRING( "CompileEnglish" ), true ); + maParserProps.setProperty( CREATE_OUSTRING( "R1C1Notation" ), false ); + maParserProps.setProperty( CREATE_OUSTRING( "Compatibility3DNotation" ), true ); + maParserProps.setProperty( CREATE_OUSTRING( "IgnoreLeadingSpaces" ), false ); + maParserProps.setProperty( CREATE_OUSTRING( "OpCodeMap" ), mrFuncProv.getOoxParserMap() ); +} + +void OoxFormulaParserImpl::importOoxFormula( + FormulaContext& rContext, const OUString& rFormulaString ) +{ + if( mxParser.is() ) + { + initializeImport( rContext ); + maParserProps.setProperty( maRefPosProp, getFormulaContext().getBaseAddress() ); + finalizeImport( mxParser->parseFormula( rFormulaString ) ); + } +} + +void OoxFormulaParserImpl::importOobFormula( FormulaContext& rContext, RecordInputStream& rStrm ) +{ + initializeImport( rContext ); + + sal_Int32 nFmlaSize = rStrm.readInt32(); + sal_Int32 nFmlaPos = rStrm.getRecPos(); + sal_Int32 nFmlaEndPos = nFmlaPos + nFmlaSize; + + rStrm.seek( nFmlaEndPos ); + sal_Int32 nAddDataSize = rStrm.readInt32(); + mnAddDataPos = rStrm.getRecPos(); + sal_Int32 nAddDataEndPos = mnAddDataPos + nAddDataSize; + rStrm.seek( nFmlaPos ); + + bool bOk = (nFmlaSize >= 0) && (nAddDataSize >= 0); + bool bRelativeAsOffset = getFormulaContext().isRelativeAsOffset(); + + while( bOk && rStrm.isValid() && (rStrm.getRecPos() < nFmlaEndPos) ) + { + sal_uInt8 nTokenId; + rStrm >> nTokenId; + sal_uInt8 nTokenClass = nTokenId & BIFF_TOKCLASS_MASK; + sal_uInt8 nBaseId = nTokenId & BIFF_TOKID_MASK; + + if( nTokenClass == BIFF_TOKCLASS_NONE ) + { + // base tokens + switch( nBaseId ) + { + case BIFF_TOKID_EXP: bOk = importExpToken( rStrm ); break; + case BIFF_TOKID_ADD: bOk = pushBinaryOperator( mrFuncProv.OPCODE_ADD ); break; + case BIFF_TOKID_SUB: bOk = pushBinaryOperator( mrFuncProv.OPCODE_SUB ); break; + case BIFF_TOKID_MUL: bOk = pushBinaryOperator( mrFuncProv.OPCODE_MULT ); break; + case BIFF_TOKID_DIV: bOk = pushBinaryOperator( mrFuncProv.OPCODE_DIV ); break; + case BIFF_TOKID_POWER: bOk = pushBinaryOperator( mrFuncProv.OPCODE_POWER ); break; + case BIFF_TOKID_CONCAT: bOk = pushBinaryOperator( mrFuncProv.OPCODE_CONCAT ); break; + case BIFF_TOKID_LT: bOk = pushBinaryOperator( mrFuncProv.OPCODE_LESS ); break; + case BIFF_TOKID_LE: bOk = pushBinaryOperator( mrFuncProv.OPCODE_LESS_EQUAL ); break; + case BIFF_TOKID_EQ: bOk = pushBinaryOperator( mrFuncProv.OPCODE_EQUAL ); break; + case BIFF_TOKID_GE: bOk = pushBinaryOperator( mrFuncProv.OPCODE_GREATER_EQUAL ); break; + case BIFF_TOKID_GT: bOk = pushBinaryOperator( mrFuncProv.OPCODE_GREATER ); break; + case BIFF_TOKID_NE: bOk = pushBinaryOperator( mrFuncProv.OPCODE_NOT_EQUAL ); break; + case BIFF_TOKID_ISECT: bOk = pushBinaryOperator( mrFuncProv.OPCODE_INTERSECT ); break; + case BIFF_TOKID_LIST: bOk = pushBinaryOperator( mrFuncProv.OPCODE_LIST ); break; + case BIFF_TOKID_RANGE: bOk = pushBinaryOperator( mrFuncProv.OPCODE_RANGE ); break; + case BIFF_TOKID_UPLUS: bOk = pushUnaryPreOperator( mrFuncProv.OPCODE_PLUS_SIGN ); break; + case BIFF_TOKID_UMINUS: bOk = pushUnaryPreOperator( mrFuncProv.OPCODE_MINUS_SIGN ); break; + case BIFF_TOKID_PERCENT: bOk = pushUnaryPostOperator( mrFuncProv.OPCODE_PERCENT ); break; + case BIFF_TOKID_PAREN: bOk = pushParenthesesOperator(); break; + case BIFF_TOKID_MISSARG: bOk = pushOperand( mrFuncProv.OPCODE_MISSING ); break; + case BIFF_TOKID_STR: bOk = pushValueOperand( rStrm.readString( false ) ); break; + case BIFF_TOKID_NLR: bOk = importTableToken( rStrm ); break; + case BIFF_TOKID_ATTR: bOk = importAttrToken( rStrm ); break; + case BIFF_TOKID_ERR: bOk = pushBiffErrorOperand( rStrm.readuInt8() ); break; + case BIFF_TOKID_BOOL: bOk = pushBoolOperand( rStrm.readuInt8() != BIFF_TOK_BOOL_FALSE ); break; + case BIFF_TOKID_INT: bOk = pushValueOperand< double >( rStrm.readuInt16() ); break; + case BIFF_TOKID_NUM: bOk = pushValueOperand( rStrm.readDouble() ); break; + default: bOk = false; + } + } + else + { + // classified tokens + switch( nBaseId ) + { + case BIFF_TOKID_ARRAY: bOk = importArrayToken( rStrm ); break; + case BIFF_TOKID_FUNC: bOk = importFuncToken( rStrm ); break; + case BIFF_TOKID_FUNCVAR: bOk = importFuncVarToken( rStrm ); break; + case BIFF_TOKID_NAME: bOk = importNameToken( rStrm ); break; + case BIFF_TOKID_REF: bOk = importRefToken( rStrm, false, false ); break; + case BIFF_TOKID_AREA: bOk = importAreaToken( rStrm, false, false ); break; + case BIFF_TOKID_MEMAREA: bOk = importMemAreaToken( rStrm, true ); break; + case BIFF_TOKID_MEMERR: bOk = importMemAreaToken( rStrm, false ); break; + case BIFF_TOKID_MEMNOMEM: bOk = importMemAreaToken( rStrm, false ); break; + case BIFF_TOKID_MEMFUNC: bOk = importMemFuncToken( rStrm ); break; + case BIFF_TOKID_REFERR: bOk = importRefToken( rStrm, true, false ); break; + case BIFF_TOKID_AREAERR: bOk = importAreaToken( rStrm, true, false ); break; + case BIFF_TOKID_REFN: bOk = importRefToken( rStrm, false, true ); break; + case BIFF_TOKID_AREAN: bOk = importAreaToken( rStrm, false, true ); break; + case BIFF_TOKID_MEMAREAN: bOk = importMemFuncToken( rStrm ); break; + case BIFF_TOKID_MEMNOMEMN: bOk = importMemFuncToken( rStrm ); break; + case BIFF_TOKID_NAMEX: bOk = importNameXToken( rStrm ); break; + case BIFF_TOKID_REF3D: bOk = importRef3dToken( rStrm, false, bRelativeAsOffset ); break; + case BIFF_TOKID_AREA3D: bOk = importArea3dToken( rStrm, false, bRelativeAsOffset ); break; + case BIFF_TOKID_REFERR3D: bOk = importRef3dToken( rStrm, true, bRelativeAsOffset ); break; + case BIFF_TOKID_AREAERR3D: bOk = importArea3dToken( rStrm, true, bRelativeAsOffset ); break; + default: bOk = false; + } + } + } + + // build and finalize the token sequence + if( bOk && (rStrm.getRecPos() == nFmlaEndPos) && (mnAddDataPos == nAddDataEndPos) ) + finalizeImport(); + + // seek behind token array + if( (nFmlaSize >= 0) && (nAddDataSize >= 0) ) + rStrm.seek( nAddDataEndPos ); +} + +// import token contents and create API formula token ------------------------- + +bool OoxFormulaParserImpl::importAttrToken( RecordInputStream& rStrm ) +{ + bool bOk = true; + sal_uInt8 nType; + rStrm >> nType; + // equal flags in BIFF and OOBIN + switch( nType ) + { + case OOBIN_TOK_ATTR_VOLATILE: + case OOBIN_TOK_ATTR_IF: + case OOBIN_TOK_ATTR_SKIP: + case OOBIN_TOK_ATTR_ASSIGN: + case OOBIN_TOK_ATTR_IFERROR: + rStrm.skip( 2 ); + break; + case OOBIN_TOK_ATTR_CHOOSE: + rStrm.skip( 2 * rStrm.readuInt16() + 2 ); + break; + case OOBIN_TOK_ATTR_SUM: + rStrm.skip( 2 ); + bOk = pushOobFunction( OOBIN_FUNC_SUM, 1 ); + break; + case OOBIN_TOK_ATTR_SPACE: + case OOBIN_TOK_ATTR_SPACE_VOLATILE: + bOk = importSpaceToken( rStrm ); + break; + default: + bOk = false; + } + return bOk; +} + +bool OoxFormulaParserImpl::importSpaceToken( RecordInputStream& rStrm ) +{ + // equal constants in BIFF and OOX + sal_uInt8 nType, nCount; + rStrm >> nType >> nCount; + switch( nType ) + { + case BIFF_TOK_ATTR_SPACE_SP: + case BIFF_TOK_ATTR_SPACE_BR: + incLeadingSpaces( nCount ); + break; + case BIFF_TOK_ATTR_SPACE_SP_OPEN: + case BIFF_TOK_ATTR_SPACE_BR_OPEN: + incOpeningSpaces( nCount ); + break; + case BIFF_TOK_ATTR_SPACE_SP_CLOSE: + case BIFF_TOK_ATTR_SPACE_BR_CLOSE: + incClosingSpaces( nCount ); + break; + } + return true; +} + +bool OoxFormulaParserImpl::importTableToken( RecordInputStream& rStrm ) +{ + sal_uInt16 nFlags, nTableId, nCol1, nCol2; + rStrm.skip( 3 ); + rStrm >> nFlags >> nTableId; + rStrm.skip( 2 ); + rStrm >> nCol1 >> nCol2; + TableRef xTable = getTables().getTable( nTableId ); + sal_Int32 nTokenIndex = xTable.get() ? xTable->getTokenIndex() : -1; + if( nTokenIndex >= 0 ) + { + sal_Int32 nWidth = xTable->getWidth(); + sal_Int32 nHeight = xTable->getHeight(); + sal_Int32 nStartCol = 0; + sal_Int32 nEndCol = nWidth - 1; + sal_Int32 nStartRow = 0; + sal_Int32 nEndRow = nHeight - 1; + bool bFixedStartRow = true; + bool bFixedHeight = false; + + bool bSingleCol = getFlag( nFlags, OOBIN_TOK_TABLE_COLUMN ); + bool bColRange = getFlag( nFlags, OOBIN_TOK_TABLE_COLRANGE ); + bool bValidRef = !bSingleCol || !bColRange; + OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - illegal combination of single column and column range" ); + if( bValidRef ) + { + if( bSingleCol ) + nStartCol = nEndCol = nCol1; + else if( bColRange ) + { nStartCol = nCol1; nEndCol = nCol2; } + bValidRef = (nStartCol <= nEndCol) && (nEndCol < nWidth); + OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - invalid column range" ); + } + + if( bValidRef ) + { + bool bAllRows = getFlag( nFlags, OOBIN_TOK_TABLE_ALL ); + bool bHeaderRows = getFlag( nFlags, OOBIN_TOK_TABLE_HEADERS ); + bool bDataRows = getFlag( nFlags, OOBIN_TOK_TABLE_DATA ); + bool bTotalsRows = getFlag( nFlags, OOBIN_TOK_TABLE_TOTALS ); + bool bThisRow = getFlag( nFlags, OOBIN_TOK_TABLE_THISROW ); + + sal_Int32 nStartDataRow = xTable->getHeaderRows(); + sal_Int32 nEndDataRow = nEndRow - xTable->getTotalsRows(); + bValidRef = (nStartRow <= nStartDataRow) && (nStartDataRow <= nEndDataRow) && (nEndDataRow <= nEndRow); + OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - invalid data row range" ); + if( bValidRef ) + { + if( bAllRows ) + { + bValidRef = !bHeaderRows && !bDataRows && !bTotalsRows && !bThisRow; + OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - unexpected flags in [#All] table token" ); + } + else if( bHeaderRows ) + { + bValidRef = !bTotalsRows && !bThisRow; + OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - unexpected flags in [#Headers] table token" ); + nEndRow = bDataRows ? nEndDataRow : (nStartDataRow - 1); + bFixedHeight = !bDataRows; + } + else if( bDataRows ) + { + bValidRef = !bThisRow; + OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - unexpected flags in [#Data] table token" ); + nStartRow = nStartDataRow; + if( !bTotalsRows ) nEndRow = nEndDataRow; + } + else if( bTotalsRows ) + { + bValidRef = !bThisRow; + OSL_ENSURE( bValidRef, "OoxFormulaParserImpl::importTableToken - unexpected flags in [#Totals] table token" ); + nStartRow = nEndDataRow + 1; + bFixedStartRow = false; + bFixedHeight = !bDataRows; + } + else if( bThisRow ) + { + nStartRow = nEndRow = getFormulaContext().getBaseAddress().Row - xTable->getRange().StartRow; + bFixedHeight = true; + } + else + { + // nothing is the same as [#Data] + nStartRow = nStartDataRow; + nEndRow = nEndDataRow; + } + } + if( bValidRef ) + bValidRef = (0 <= nStartRow) && (nStartRow <= nEndRow) && (nEndRow < nHeight); + } + if( bValidRef ) + { + // push single database area token, if table token refers to entire table + if( (nStartCol == 0) && (nEndCol + 1 == nWidth) && (nStartRow == 0) && (nEndRow + 1 == nHeight) ) + return pushValueOperand( nTokenIndex, mrFuncProv.OPCODE_DBAREA ); + // create an OFFSET function call to refer to a subrange of the table + const FunctionInfo* pRowsInfo = mrFuncProv.getFuncInfoFromOobFuncId( OOBIN_FUNC_ROWS ); + const FunctionInfo* pColumnsInfo = mrFuncProv.getFuncInfoFromOobFuncId( OOBIN_FUNC_COLUMNS ); + return + pRowsInfo && pColumnsInfo && + pushValueOperandToken( nTokenIndex, mrFuncProv.OPCODE_DBAREA, 0 ) && + (bFixedStartRow ? + pushValueOperandToken< double >( nStartRow, 0 ) : + (pushValueOperandToken( nTokenIndex, mrFuncProv.OPCODE_DBAREA, 0 ) && + pushFunctionOperatorToken( *pRowsInfo, 1, 0, 0 ) && + pushValueOperandToken< double >( nHeight - nStartRow, 0 ) && + pushBinaryOperatorToken( mrFuncProv.OPCODE_SUB, 0 ))) && + pushValueOperandToken< double >( nStartCol, 0 ) && + (bFixedHeight ? + pushValueOperandToken< double >( nEndRow - nStartRow + 1, 0 ) : + (pushValueOperandToken( nTokenIndex, mrFuncProv.OPCODE_DBAREA, 0 ) && + pushFunctionOperatorToken( *pRowsInfo, 1, 0, 0 ) && + (((nStartRow == 0) && (nEndRow + 1 == nHeight)) || + (pushValueOperandToken< double >( nHeight - (nEndRow - nStartRow + 1), 0 ) && + pushBinaryOperatorToken( mrFuncProv.OPCODE_SUB, 0 ))))) && + (((nStartCol == 0) && (nEndCol + 1 == nWidth)) ? + (pushValueOperandToken( nTokenIndex, mrFuncProv.OPCODE_DBAREA, 0 ) && + pushFunctionOperatorToken( *pColumnsInfo, 1, 0, 0 )) : + pushValueOperandToken< double >( nEndCol - nStartCol + 1, 0 )) && + pushOobFunction( OOBIN_FUNC_OFFSET, 5 ); + } + } + return pushBiffErrorOperand( BIFF_ERR_REF ); +} + +bool OoxFormulaParserImpl::importArrayToken( RecordInputStream& rStrm ) +{ + rStrm.skip( 14 ); + + // start token array with opening brace and leading spaces + pushOperand( mrFuncProv.OPCODE_ARRAY_OPEN ); + size_t nOpSize = popOperandSize(); + size_t nOldArraySize = getFormulaSize(); + + // read array size + swapStreamPosition( rStrm ); + sal_Int32 nRows = rStrm.readInt32(); + sal_Int32 nCols = rStrm.readInt32(); + OSL_ENSURE( (nCols > 0) && (nRows > 0), "OoxFormulaParserImpl::importArrayToken - empty array" ); + + // read array values and build token array + for( sal_Int32 nRow = 0; rStrm.isValid() && (nRow < nRows); ++nRow ) + { + if( nRow > 0 ) + appendRawToken( mrFuncProv.OPCODE_ARRAY_ROWSEP ); + for( sal_Int32 nCol = 0; rStrm.isValid() && (nCol < nCols); ++nCol ) + { + if( nCol > 0 ) + appendRawToken( mrFuncProv.OPCODE_ARRAY_COLSEP ); + switch( rStrm.readuInt8() ) + { + case OOBIN_TOK_ARRAY_DOUBLE: + appendRawToken( mrFuncProv.OPCODE_PUSH ) <<= rStrm.readDouble(); + break; + case OOBIN_TOK_ARRAY_STRING: + appendRawToken( mrFuncProv.OPCODE_PUSH ) <<= rStrm.readString( false ); + break; + case OOBIN_TOK_ARRAY_BOOL: + appendRawToken( mrFuncProv.OPCODE_PUSH ) <<= static_cast< double >( (rStrm.readuInt8() == 0) ? 0.0 : 1.0 ); + break; + case OOBIN_TOK_ARRAY_ERROR: + appendRawToken( mrFuncProv.OPCODE_PUSH ) <<= BiffHelper::calcDoubleFromError( rStrm.readuInt8() ); + rStrm.skip( 3 ); + break; + default: + OSL_ENSURE( false, "OoxFormulaParserImpl::importArrayToken - unknown data type" ); + appendRawToken( mrFuncProv.OPCODE_PUSH ) <<= BiffHelper::calcDoubleFromError( BIFF_ERR_NA ); + } + } + } + swapStreamPosition( rStrm ); + + // close token array and set resulting operand size + appendRawToken( mrFuncProv.OPCODE_ARRAY_CLOSE ); + pushOperandSize( nOpSize + getFormulaSize() - nOldArraySize ); + return true; +} + +bool OoxFormulaParserImpl::importRefToken( RecordInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) +{ + BinSingleRef2d aRef; + aRef.readOobData( rStrm, bRelativeAsOffset ); + return pushReferenceOperand( aRef, bDeleted, bRelativeAsOffset ); +} + +bool OoxFormulaParserImpl::importAreaToken( RecordInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) +{ + BinComplexRef2d aRef; + aRef.readOobData( rStrm, bRelativeAsOffset ); + return pushReferenceOperand( aRef, bDeleted, bRelativeAsOffset ); +} + +bool OoxFormulaParserImpl::importRef3dToken( RecordInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) +{ + LinkSheetRange aSheetRange = readSheetRange( rStrm ); + BinSingleRef2d aRef; + aRef.readOobData( rStrm, bRelativeAsOffset ); + return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset ); +} + +bool OoxFormulaParserImpl::importArea3dToken( RecordInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) +{ + LinkSheetRange aSheetRange = readSheetRange( rStrm ); + BinComplexRef2d aRef; + aRef.readOobData( rStrm, bRelativeAsOffset ); + return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset ); +} + +bool OoxFormulaParserImpl::importMemAreaToken( RecordInputStream& rStrm, bool bAddData ) +{ + rStrm.skip( 6 ); + if( bAddData ) + skipMemAreaAddData( rStrm ); + return true; +} + +bool OoxFormulaParserImpl::importMemFuncToken( RecordInputStream& rStrm ) +{ + rStrm.skip( 2 ); + return true; +} + +bool OoxFormulaParserImpl::importNameToken( RecordInputStream& rStrm ) +{ + return pushOobName( rStrm.readInt32() ); +} + +bool OoxFormulaParserImpl::importNameXToken( RecordInputStream& rStrm ) +{ + sal_Int32 nRefId = rStrm.readInt16(); + sal_Int32 nNameId = rStrm.readInt32(); + return pushOobExtName( nRefId, nNameId ); +} + +bool OoxFormulaParserImpl::importFuncToken( RecordInputStream& rStrm ) +{ + sal_uInt16 nFuncId; + rStrm >> nFuncId; + return pushOobFunction( nFuncId ); +} + +bool OoxFormulaParserImpl::importFuncVarToken( RecordInputStream& rStrm ) +{ + sal_uInt8 nParamCount; + sal_uInt16 nFuncId; + rStrm >> nParamCount >> nFuncId; + return pushOobFunction( nFuncId, nParamCount ); +} + +bool OoxFormulaParserImpl::importExpToken( RecordInputStream& rStrm ) +{ + BinAddress aBaseAddr; + rStrm >> aBaseAddr.mnRow; + swapStreamPosition( rStrm ); + rStrm >> aBaseAddr.mnCol; + swapStreamPosition( rStrm ); + setSharedFormula( aBaseAddr ); + // formula has been set, exit parser by returning false + return false; +} + +LinkSheetRange OoxFormulaParserImpl::readSheetRange( RecordInputStream& rStrm ) +{ + return getExternalLinks().getSheetRange( rStrm.readInt16() ); +} + +void OoxFormulaParserImpl::swapStreamPosition( RecordInputStream& rStrm ) +{ + sal_Int32 nRecPos = rStrm.getRecPos(); + rStrm.seek( mnAddDataPos ); + mnAddDataPos = nRecPos; +} + +void OoxFormulaParserImpl::skipMemAreaAddData( RecordInputStream& rStrm ) +{ + swapStreamPosition( rStrm ); + rStrm.skip( 16 * rStrm.readInt32() ); + swapStreamPosition( rStrm ); +} + +// convert BIN token and push API operand or operator ------------------------- + +bool OoxFormulaParserImpl::pushOobName( sal_Int32 nNameId ) +{ + // one-based in OOBIN formulas + return pushDefinedNameOperand( getDefinedNames().getByIndex( nNameId - 1 ) ); +} + +bool OoxFormulaParserImpl::pushOobExtName( sal_Int32 nRefId, sal_Int32 nNameId ) +{ + if( const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId ).get() ) + { + if( pExtLink->getLinkType() == LINKTYPE_SELF ) + return pushOobName( nNameId ); + // external name indexes are one-based in OOBIN + ExternalNameRef xExtName = pExtLink->getNameByIndex( nNameId - 1 ); + return pushExternalNameOperand( xExtName, pExtLink->getLinkType() ); + } + return pushBiffErrorOperand( BIFF_ERR_NAME ); +} + +bool OoxFormulaParserImpl::pushOobFunction( sal_uInt16 nFuncId ) +{ + if( const FunctionInfo* pFuncInfo = mrFuncProv.getFuncInfoFromOobFuncId( nFuncId ) ) + if( pFuncInfo->mnMinParamCount == pFuncInfo->mnMaxParamCount ) + return pushFunctionOperator( *pFuncInfo, pFuncInfo->mnMinParamCount ); + return pushFunctionOperator( mrFuncProv.OPCODE_NONAME, 0 ); +} + +bool OoxFormulaParserImpl::pushOobFunction( sal_uInt16 nFuncId, sal_uInt8 nParamCount ) +{ + if( getFlag( nFuncId, BIFF_TOK_FUNCVAR_CMD ) ) + nParamCount &= BIFF_TOK_FUNCVAR_COUNTMASK; + if( const FunctionInfo* pFuncInfo = mrFuncProv.getFuncInfoFromOobFuncId( nFuncId ) ) + return pushFunctionOperator( *pFuncInfo, nParamCount ); + return pushFunctionOperator( mrFuncProv.OPCODE_NONAME, nParamCount ); +} + +// BIFF parser implementation ================================================= + +namespace { + +/** A natural language reference struct with relative flag. */ +struct BiffNlr +{ + sal_Int32 mnCol; /// Column index. + sal_Int32 mnRow; /// Row index. + bool mbRel; /// True = relative column/row reference. + + explicit BiffNlr(); + + void readBiff8Data( BiffInputStream& rStrm ); +}; + +BiffNlr::BiffNlr() : + mnCol( 0 ), + mnRow( 0 ), + mbRel( false ) +{ +} + +void BiffNlr::readBiff8Data( BiffInputStream& rStrm ) +{ + sal_uInt16 nRow, nCol; + rStrm >> nRow >> nCol; + mnCol = nCol & BIFF_TOK_NLR_MASK; + mnRow = nRow; + mbRel = getFlag( nCol, BIFF_TOK_NLR_REL ); +} + +bool lclIsValidNlrStack( const BinAddress& rAddr1, const BinAddress& rAddr2, bool bRow ) +{ + return bRow ? + ((rAddr1.mnRow == rAddr2.mnRow) && (rAddr1.mnCol + 1 == rAddr2.mnCol)) : + ((rAddr1.mnCol == rAddr2.mnCol) && (rAddr1.mnRow + 1 == rAddr2.mnRow)); +} + +bool lclIsValidNlrRange( const BiffNlr& rNlr, const BinRange& rRange, bool bRow ) +{ + return bRow ? + ((rNlr.mnRow == rRange.maFirst.mnRow) && (rNlr.mnCol + 1 == rRange.maFirst.mnCol) && (rRange.maFirst.mnRow == rRange.maLast.mnRow)) : + ((rNlr.mnCol == rRange.maFirst.mnCol) && (rNlr.mnRow + 1 == rRange.maFirst.mnRow) && (rRange.maFirst.mnCol == rRange.maLast.mnCol)); +} + +} // namespace + +// ---------------------------------------------------------------------------- + +class BiffFormulaParserImpl : public FormulaParserImpl +{ +public: + explicit BiffFormulaParserImpl( + const WorkbookHelper& rHelper, + const FunctionProvider& rFuncProv ); + + virtual void importBiffFormula( + FormulaContext& rContext, + BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ); + +private: + // import token contents and create API formula token --------------------- + + bool importTokenNotAvailable( BiffInputStream& rStrm ); + bool importRefTokenNotAvailable( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); + bool importStrToken2( BiffInputStream& rStrm ); + bool importStrToken8( BiffInputStream& rStrm ); + bool importAttrToken( BiffInputStream& rStrm ); + bool importSpaceToken3( BiffInputStream& rStrm ); + bool importSpaceToken4( BiffInputStream& rStrm ); + bool importSheetToken2( BiffInputStream& rStrm ); + bool importSheetToken3( BiffInputStream& rStrm ); + bool importEndSheetToken2( BiffInputStream& rStrm ); + bool importEndSheetToken3( BiffInputStream& rStrm ); + bool importNlrToken( BiffInputStream& rStrm ); + bool importArrayToken( BiffInputStream& rStrm ); + bool importRefToken2( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); + bool importRefToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); + bool importAreaToken2( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); + bool importAreaToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); + bool importRef3dToken5( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); + bool importRef3dToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); + bool importArea3dToken5( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); + bool importArea3dToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ); + bool importMemAreaToken( BiffInputStream& rStrm, bool bAddData ); + bool importMemFuncToken( BiffInputStream& rStrm ); + bool importNameToken( BiffInputStream& rStrm ); + bool importNameXToken( BiffInputStream& rStrm ); + bool importFuncToken2( BiffInputStream& rStrm ); + bool importFuncToken4( BiffInputStream& rStrm ); + bool importFuncVarToken2( BiffInputStream& rStrm ); + bool importFuncVarToken4( BiffInputStream& rStrm ); + bool importFuncCEToken( BiffInputStream& rStrm ); + bool importExpToken5( BiffInputStream& rStrm ); + + bool importNlrAddrToken( BiffInputStream& rStrm, bool bRow ); + bool importNlrRangeToken( BiffInputStream& rStrm ); + bool importNlrSAddrToken( BiffInputStream& rStrm, bool bRow ); + bool importNlrSRangeToken( BiffInputStream& rStrm ); + bool importNlrErrToken( BiffInputStream& rStrm, sal_uInt16 nSkip ); + + sal_Int32 readRefId( BiffInputStream& rStrm ); + sal_uInt16 readNameId( BiffInputStream& rStrm ); + LinkSheetRange readSheetRange5( BiffInputStream& rStrm ); + LinkSheetRange readSheetRange8( BiffInputStream& rStrm ); + + void swapStreamPosition( BiffInputStream& rStrm ); + void skipMemAreaAddData( BiffInputStream& rStrm ); + bool readNlrSAddrAddData( BiffNlr& orNlr, BiffInputStream& rStrm, bool bRow ); + bool readNlrSRangeAddData( BiffNlr& orNlr, bool& orbIsRow, BiffInputStream& rStrm ); + + // convert BIFF token and push API operand or operator -------------------- + + bool pushBiffReference( const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ); + bool pushBiffReference( const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ); + bool pushBiffNlrAddr( const BiffNlr& rNlr, bool bRow ); + bool pushBiffNlrRange( const BiffNlr& rNlr, const BinRange& rRange ); + bool pushBiffNlrSAddr( const BiffNlr& rNlr, bool bRow ); + bool pushBiffNlrSRange( const BiffNlr& rNlr, const BinRange& rRange, bool bRow ); + bool pushBiffName( sal_uInt16 nNameId ); + bool pushBiffExtName( sal_Int32 nRefId, sal_uInt16 nNameId ); + bool pushBiffFunction( sal_uInt16 nFuncId ); + bool pushBiffFunction( sal_uInt16 nFuncId, sal_uInt8 nParamCount ); + + // ------------------------------------------------------------------------ +private: + typedef bool (BiffFormulaParserImpl::*ImportTokenFunc)( BiffInputStream& ); + typedef bool (BiffFormulaParserImpl::*ImportRefTokenFunc)( BiffInputStream&, bool, bool ); + + ImportTokenFunc mpImportStrToken; /// Pointer to tStr import function (string constant). + ImportTokenFunc mpImportSpaceToken; /// Pointer to tAttrSpace import function (spaces/line breaks). + ImportTokenFunc mpImportSheetToken; /// Pointer to tSheet import function (external reference). + ImportTokenFunc mpImportEndSheetToken; /// Pointer to tEndSheet import function (end of external reference). + ImportTokenFunc mpImportNlrToken; /// Pointer to tNlr import function (natural language reference). + ImportRefTokenFunc mpImportRefToken; /// Pointer to tRef import function (2d cell reference). + ImportRefTokenFunc mpImportAreaToken; /// Pointer to tArea import function (2d area reference). + ImportRefTokenFunc mpImportRef3dToken; /// Pointer to tRef3d import function (3d cell reference). + ImportRefTokenFunc mpImportArea3dToken; /// Pointer to tArea3d import function (3d area reference). + ImportTokenFunc mpImportNameXToken; /// Pointer to tNameX import function (external name). + ImportTokenFunc mpImportFuncToken; /// Pointer to tFunc import function (function with fixed parameter count). + ImportTokenFunc mpImportFuncVarToken; /// Pointer to tFuncVar import function (function with variable parameter count). + ImportTokenFunc mpImportFuncCEToken; /// Pointer to tFuncCE import function (command macro call). + ImportTokenFunc mpImportExpToken; /// Pointer to tExp import function (array/shared formula). + sal_uInt32 mnAddDataPos; /// Current stream position for additional data (tArray, tMemArea, tNlr). + sal_Int32 mnCurrRefId; /// Current ref-id from tSheet token (BIFF2-BIFF4 only). + sal_uInt16 mnAttrDataSize; /// Size of one tAttr data element. + sal_uInt16 mnArraySize; /// Size of tArray data. + sal_uInt16 mnNameSize; /// Size of tName data. + sal_uInt16 mnMemAreaSize; /// Size of tMemArea data. + sal_uInt16 mnMemFuncSize; /// Size of tMemFunc data. + sal_uInt16 mnRefIdSize; /// Size of unused data following a reference identifier. +}; + +// ---------------------------------------------------------------------------- + +BiffFormulaParserImpl::BiffFormulaParserImpl( const WorkbookHelper& rHelper, const FunctionProvider& rFuncProv ) : + FormulaParserImpl( rHelper, rFuncProv ), + mnAddDataPos( 0 ), + mnCurrRefId( 0 ) +{ + switch( getBiff() ) + { + case BIFF2: + mpImportStrToken = &BiffFormulaParserImpl::importStrToken2; + mpImportSpaceToken = &BiffFormulaParserImpl::importTokenNotAvailable; + mpImportSheetToken = &BiffFormulaParserImpl::importSheetToken2; + mpImportEndSheetToken = &BiffFormulaParserImpl::importEndSheetToken2; + mpImportNlrToken = &BiffFormulaParserImpl::importTokenNotAvailable; + mpImportRefToken = &BiffFormulaParserImpl::importRefToken2; + mpImportAreaToken = &BiffFormulaParserImpl::importAreaToken2; + mpImportRef3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable; + mpImportArea3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable; + mpImportNameXToken = &BiffFormulaParserImpl::importTokenNotAvailable; + mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken2; + mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken2; + mpImportFuncCEToken = &BiffFormulaParserImpl::importFuncCEToken; + mpImportExpToken = &BiffFormulaParserImpl::importTokenNotAvailable; + mnAttrDataSize = 1; + mnArraySize = 6; + mnNameSize = 5; + mnMemAreaSize = 4; + mnMemFuncSize = 1; + mnRefIdSize = 1; + break; + case BIFF3: + mpImportStrToken = &BiffFormulaParserImpl::importStrToken2; + mpImportSpaceToken = &BiffFormulaParserImpl::importSpaceToken3; + mpImportSheetToken = &BiffFormulaParserImpl::importSheetToken3; + mpImportEndSheetToken = &BiffFormulaParserImpl::importEndSheetToken3; + mpImportNlrToken = &BiffFormulaParserImpl::importTokenNotAvailable; + mpImportRefToken = &BiffFormulaParserImpl::importRefToken2; + mpImportAreaToken = &BiffFormulaParserImpl::importAreaToken2; + mpImportRef3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable; + mpImportArea3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable; + mpImportNameXToken = &BiffFormulaParserImpl::importTokenNotAvailable; + mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken2; + mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken2; + mpImportFuncCEToken = &BiffFormulaParserImpl::importFuncCEToken; + mpImportExpToken = &BiffFormulaParserImpl::importTokenNotAvailable; + mnAttrDataSize = 2; + mnArraySize = 7; + mnNameSize = 8; + mnMemAreaSize = 6; + mnMemFuncSize = 2; + mnRefIdSize = 2; + break; + case BIFF4: + mpImportStrToken = &BiffFormulaParserImpl::importStrToken2; + mpImportSpaceToken = &BiffFormulaParserImpl::importSpaceToken4; + mpImportSheetToken = &BiffFormulaParserImpl::importSheetToken3; + mpImportEndSheetToken = &BiffFormulaParserImpl::importEndSheetToken3; + mpImportNlrToken = &BiffFormulaParserImpl::importTokenNotAvailable; + mpImportRefToken = &BiffFormulaParserImpl::importRefToken2; + mpImportAreaToken = &BiffFormulaParserImpl::importAreaToken2; + mpImportRef3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable; + mpImportArea3dToken = &BiffFormulaParserImpl::importRefTokenNotAvailable; + mpImportNameXToken = &BiffFormulaParserImpl::importTokenNotAvailable; + mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken4; + mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken4; + mpImportFuncCEToken = &BiffFormulaParserImpl::importTokenNotAvailable; + mpImportExpToken = &BiffFormulaParserImpl::importTokenNotAvailable; + mnAttrDataSize = 2; + mnArraySize = 7; + mnNameSize = 8; + mnMemAreaSize = 6; + mnMemFuncSize = 2; + mnRefIdSize = 2; + break; + case BIFF5: + mpImportStrToken = &BiffFormulaParserImpl::importStrToken2; + mpImportSpaceToken = &BiffFormulaParserImpl::importSpaceToken4; + mpImportSheetToken = &BiffFormulaParserImpl::importTokenNotAvailable; + mpImportEndSheetToken = &BiffFormulaParserImpl::importTokenNotAvailable; + mpImportNlrToken = &BiffFormulaParserImpl::importTokenNotAvailable; + mpImportRefToken = &BiffFormulaParserImpl::importRefToken2; + mpImportAreaToken = &BiffFormulaParserImpl::importAreaToken2; + mpImportRef3dToken = &BiffFormulaParserImpl::importRef3dToken5; + mpImportArea3dToken = &BiffFormulaParserImpl::importArea3dToken5; + mpImportNameXToken = &BiffFormulaParserImpl::importNameXToken; + mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken4; + mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken4; + mpImportFuncCEToken = &BiffFormulaParserImpl::importTokenNotAvailable; + mpImportExpToken = &BiffFormulaParserImpl::importExpToken5; + mnAttrDataSize = 2; + mnArraySize = 7; + mnNameSize = 12; + mnMemAreaSize = 6; + mnMemFuncSize = 2; + mnRefIdSize = 8; + break; + case BIFF8: + mpImportStrToken = &BiffFormulaParserImpl::importStrToken8; + mpImportSpaceToken = &BiffFormulaParserImpl::importSpaceToken4; + mpImportSheetToken = &BiffFormulaParserImpl::importTokenNotAvailable; + mpImportEndSheetToken = &BiffFormulaParserImpl::importTokenNotAvailable; + mpImportNlrToken = &BiffFormulaParserImpl::importNlrToken; + mpImportRefToken = &BiffFormulaParserImpl::importRefToken8; + mpImportAreaToken = &BiffFormulaParserImpl::importAreaToken8; + mpImportRef3dToken = &BiffFormulaParserImpl::importRef3dToken8; + mpImportArea3dToken = &BiffFormulaParserImpl::importArea3dToken8; + mpImportNameXToken = &BiffFormulaParserImpl::importNameXToken; + mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken4; + mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken4; + mpImportFuncCEToken = &BiffFormulaParserImpl::importTokenNotAvailable; + mpImportExpToken = &BiffFormulaParserImpl::importExpToken5; + mnAttrDataSize = 2; + mnArraySize = 7; + mnNameSize = 2; + mnMemAreaSize = 6; + mnMemFuncSize = 2; + mnRefIdSize = 0; + break; + case BIFF_UNKNOWN: break; + } +} + +void BiffFormulaParserImpl::importBiffFormula( FormulaContext& rContext, + BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ) +{ + initializeImport( rContext ); + mnCurrRefId = 0; + + sal_uInt16 nFmlaSize = pnFmlaSize ? *pnFmlaSize : ((getBiff() == BIFF2) ? rStrm.readuInt8() : rStrm.readuInt16()); + sal_uInt32 nEndPos = mnAddDataPos = rStrm.getRecPos() + nFmlaSize; + bool bRelativeAsOffset = getFormulaContext().isRelativeAsOffset(); + + bool bOk = true; + while( bOk && rStrm.isValid() && (rStrm.getRecPos() < nEndPos) ) + { + sal_uInt8 nTokenId; + rStrm >> nTokenId; + sal_uInt8 nTokenClass = nTokenId & BIFF_TOKCLASS_MASK; + sal_uInt8 nBaseId = nTokenId & BIFF_TOKID_MASK; + + if( nTokenClass == BIFF_TOKCLASS_NONE ) + { + // base tokens + switch( nBaseId ) + { + case BIFF_TOKID_EXP: bOk = (this->*mpImportExpToken)( rStrm ); break; + case BIFF_TOKID_TBL: bOk = false; /* multiple op. will be set externally */ break; + case BIFF_TOKID_ADD: bOk = pushBinaryOperator( mrFuncProv.OPCODE_ADD ); break; + case BIFF_TOKID_SUB: bOk = pushBinaryOperator( mrFuncProv.OPCODE_SUB ); break; + case BIFF_TOKID_MUL: bOk = pushBinaryOperator( mrFuncProv.OPCODE_MULT ); break; + case BIFF_TOKID_DIV: bOk = pushBinaryOperator( mrFuncProv.OPCODE_DIV ); break; + case BIFF_TOKID_POWER: bOk = pushBinaryOperator( mrFuncProv.OPCODE_POWER ); break; + case BIFF_TOKID_CONCAT: bOk = pushBinaryOperator( mrFuncProv.OPCODE_CONCAT ); break; + case BIFF_TOKID_LT: bOk = pushBinaryOperator( mrFuncProv.OPCODE_LESS ); break; + case BIFF_TOKID_LE: bOk = pushBinaryOperator( mrFuncProv.OPCODE_LESS_EQUAL ); break; + case BIFF_TOKID_EQ: bOk = pushBinaryOperator( mrFuncProv.OPCODE_EQUAL ); break; + case BIFF_TOKID_GE: bOk = pushBinaryOperator( mrFuncProv.OPCODE_GREATER_EQUAL ); break; + case BIFF_TOKID_GT: bOk = pushBinaryOperator( mrFuncProv.OPCODE_GREATER ); break; + case BIFF_TOKID_NE: bOk = pushBinaryOperator( mrFuncProv.OPCODE_NOT_EQUAL ); break; + case BIFF_TOKID_ISECT: bOk = pushBinaryOperator( mrFuncProv.OPCODE_INTERSECT ); break; + case BIFF_TOKID_LIST: bOk = pushBinaryOperator( mrFuncProv.OPCODE_LIST ); break; + case BIFF_TOKID_RANGE: bOk = pushBinaryOperator( mrFuncProv.OPCODE_RANGE ); break; + case BIFF_TOKID_UPLUS: bOk = pushUnaryPreOperator( mrFuncProv.OPCODE_PLUS_SIGN ); break; + case BIFF_TOKID_UMINUS: bOk = pushUnaryPreOperator( mrFuncProv.OPCODE_MINUS_SIGN ); break; + case BIFF_TOKID_PERCENT: bOk = pushUnaryPostOperator( mrFuncProv.OPCODE_PERCENT ); break; + case BIFF_TOKID_PAREN: bOk = pushParenthesesOperator(); break; + case BIFF_TOKID_MISSARG: bOk = pushOperand( mrFuncProv.OPCODE_MISSING ); break; + case BIFF_TOKID_STR: bOk = (this->*mpImportStrToken)( rStrm ); break; + case BIFF_TOKID_NLR: bOk = (this->*mpImportNlrToken)( rStrm ); break; + case BIFF_TOKID_ATTR: bOk = importAttrToken( rStrm ); break; + case BIFF_TOKID_SHEET: bOk = (this->*mpImportSheetToken)( rStrm ); break; + case BIFF_TOKID_ENDSHEET: bOk = (this->*mpImportEndSheetToken)( rStrm ); break; + case BIFF_TOKID_ERR: bOk = pushBiffErrorOperand( rStrm.readuInt8() ); break; + case BIFF_TOKID_BOOL: bOk = pushBoolOperand( rStrm.readuInt8() != BIFF_TOK_BOOL_FALSE ); break; + case BIFF_TOKID_INT: bOk = pushValueOperand< double >( rStrm.readuInt16() ); break; + case BIFF_TOKID_NUM: bOk = pushValueOperand( rStrm.readDouble() ); break; + default: bOk = false; + } + } + else + { + // classified tokens + switch( nBaseId ) + { + case BIFF_TOKID_ARRAY: bOk = importArrayToken( rStrm ); break; + case BIFF_TOKID_FUNC: bOk = (this->*mpImportFuncToken)( rStrm ); break; + case BIFF_TOKID_FUNCVAR: bOk = (this->*mpImportFuncVarToken)( rStrm ); break; + case BIFF_TOKID_NAME: bOk = importNameToken( rStrm ); break; + case BIFF_TOKID_REF: bOk = (this->*mpImportRefToken)( rStrm, false, false ); break; + case BIFF_TOKID_AREA: bOk = (this->*mpImportAreaToken)( rStrm, false, false ); break; + case BIFF_TOKID_MEMAREA: bOk = importMemAreaToken( rStrm, true ); break; + case BIFF_TOKID_MEMERR: bOk = importMemAreaToken( rStrm, false ); break; + case BIFF_TOKID_MEMNOMEM: bOk = importMemAreaToken( rStrm, false ); break; + case BIFF_TOKID_MEMFUNC: bOk = importMemFuncToken( rStrm ); break; + case BIFF_TOKID_REFERR: bOk = (this->*mpImportRefToken)( rStrm, true, false ); break; + case BIFF_TOKID_AREAERR: bOk = (this->*mpImportAreaToken)( rStrm, true, false ); break; + case BIFF_TOKID_REFN: bOk = (this->*mpImportRefToken)( rStrm, false, true ); break; + case BIFF_TOKID_AREAN: bOk = (this->*mpImportAreaToken)( rStrm, false, true ); break; + case BIFF_TOKID_MEMAREAN: bOk = importMemFuncToken( rStrm ); break; + case BIFF_TOKID_MEMNOMEMN: bOk = importMemFuncToken( rStrm ); break; + case BIFF_TOKID_FUNCCE: bOk = (this->*mpImportFuncCEToken)( rStrm ); break; + case BIFF_TOKID_NAMEX: bOk = (this->*mpImportNameXToken)( rStrm ); break; + case BIFF_TOKID_REF3D: bOk = (this->*mpImportRef3dToken)( rStrm, false, bRelativeAsOffset ); break; + case BIFF_TOKID_AREA3D: bOk = (this->*mpImportArea3dToken)( rStrm, false, bRelativeAsOffset ); break; + case BIFF_TOKID_REFERR3D: bOk = (this->*mpImportRef3dToken)( rStrm, true, bRelativeAsOffset ); break; + case BIFF_TOKID_AREAERR3D: bOk = (this->*mpImportArea3dToken)( rStrm, true, bRelativeAsOffset ); break; + default: bOk = false; + } + } + } + + // build and finalize the token sequence + if( bOk && (rStrm.getRecPos() == nEndPos) ) + finalizeImport(); + + // seek behind additional token data of tArray, tMemArea, tNlr tokens + rStrm.seek( mnAddDataPos ); +} + +// import token contents and create API formula token ------------------------- + +bool BiffFormulaParserImpl::importTokenNotAvailable( BiffInputStream& ) +{ + // dummy function for pointer-to-member-function + return false; +} + +bool BiffFormulaParserImpl::importRefTokenNotAvailable( BiffInputStream&, bool, bool ) +{ + // dummy function for pointer-to-member-function + return false; +} + +bool BiffFormulaParserImpl::importStrToken2( BiffInputStream& rStrm ) +{ + return pushValueOperand( rStrm.readByteString( false, getTextEncoding() ) ); +} + +bool BiffFormulaParserImpl::importStrToken8( BiffInputStream& rStrm ) +{ + // read flags field for empty strings also + return pushValueOperand( rStrm.readUniString( rStrm.readuInt8() ) ); +} + +bool BiffFormulaParserImpl::importAttrToken( BiffInputStream& rStrm ) +{ + bool bOk = true; + sal_uInt8 nType; + rStrm >> nType; + switch( nType ) + { + case BIFF_TOK_ATTR_VOLATILE: + case BIFF_TOK_ATTR_IF: + case BIFF_TOK_ATTR_SKIP: + case BIFF_TOK_ATTR_ASSIGN: + rStrm.skip( mnAttrDataSize ); + break; + case BIFF_TOK_ATTR_CHOOSE: + rStrm.skip( mnAttrDataSize * (1 + ((getBiff() == BIFF2) ? rStrm.readuInt8() : rStrm.readuInt16())) ); + break; + case BIFF_TOK_ATTR_SUM: + rStrm.skip( mnAttrDataSize ); + bOk = pushBiffFunction( BIFF_FUNC_SUM, 1 ); + break; + case BIFF_TOK_ATTR_SPACE: + case BIFF_TOK_ATTR_SPACE_VOLATILE: + bOk = (this->*mpImportSpaceToken)( rStrm ); + break; + default: + bOk = false; + } + return bOk; +} + +bool BiffFormulaParserImpl::importSpaceToken3( BiffInputStream& rStrm ) +{ + rStrm.skip( 2 ); + return true; +} + +bool BiffFormulaParserImpl::importSpaceToken4( BiffInputStream& rStrm ) +{ + sal_uInt8 nType, nCount; + rStrm >> nType >> nCount; + switch( nType ) + { + case BIFF_TOK_ATTR_SPACE_SP: + case BIFF_TOK_ATTR_SPACE_BR: + incLeadingSpaces( nCount ); + break; + case BIFF_TOK_ATTR_SPACE_SP_OPEN: + case BIFF_TOK_ATTR_SPACE_BR_OPEN: + incOpeningSpaces( nCount ); + break; + case BIFF_TOK_ATTR_SPACE_SP_CLOSE: + case BIFF_TOK_ATTR_SPACE_BR_CLOSE: + incClosingSpaces( nCount ); + break; + } + return true; +} + +bool BiffFormulaParserImpl::importSheetToken2( BiffInputStream& rStrm ) +{ + rStrm.skip( 4 ); + mnCurrRefId = readRefId( rStrm ); + return true; +} + +bool BiffFormulaParserImpl::importSheetToken3( BiffInputStream& rStrm ) +{ + rStrm.skip( 6 ); + mnCurrRefId = readRefId( rStrm ); + return true; +} + +bool BiffFormulaParserImpl::importEndSheetToken2( BiffInputStream& rStrm ) +{ + rStrm.skip( 3 ); + mnCurrRefId = 0; + return true; +} + +bool BiffFormulaParserImpl::importEndSheetToken3( BiffInputStream& rStrm ) +{ + rStrm.skip( 4 ); + mnCurrRefId = 0; + return true; +} + +bool BiffFormulaParserImpl::importNlrToken( BiffInputStream& rStrm ) +{ + bool bOk = true; + sal_uInt8 nNlrType; + rStrm >> nNlrType; + switch( nNlrType ) + { + case BIFF_TOK_NLR_ERR: bOk = importNlrErrToken( rStrm, 4 ); break; + case BIFF_TOK_NLR_ROWR: bOk = importNlrAddrToken( rStrm, true ); break; + case BIFF_TOK_NLR_COLR: bOk = importNlrAddrToken( rStrm, false ); break; + case BIFF_TOK_NLR_ROWV: bOk = importNlrAddrToken( rStrm, true ); break; + case BIFF_TOK_NLR_COLV: bOk = importNlrAddrToken( rStrm, false ); break; + case BIFF_TOK_NLR_RANGE: bOk = importNlrRangeToken( rStrm ); break; + case BIFF_TOK_NLR_SRANGE: bOk = importNlrSRangeToken( rStrm ); break; + case BIFF_TOK_NLR_SROWR: bOk = importNlrSAddrToken( rStrm, true ); break; + case BIFF_TOK_NLR_SCOLR: bOk = importNlrSAddrToken( rStrm, false ); break; + case BIFF_TOK_NLR_SROWV: bOk = importNlrSAddrToken( rStrm, true ); break; + case BIFF_TOK_NLR_SCOLV: bOk = importNlrSAddrToken( rStrm, false ); break; + case BIFF_TOK_NLR_RANGEERR: bOk = importNlrErrToken( rStrm, 13 ); break; + case BIFF_TOK_NLR_SXNAME: bOk = importNlrErrToken( rStrm, 4 ); break; + default: bOk = false; + } + return bOk; +} + +bool BiffFormulaParserImpl::importArrayToken( BiffInputStream& rStrm ) +{ + rStrm.skip( mnArraySize ); + + // start token array with opening brace and leading spaces + pushOperand( mrFuncProv.OPCODE_ARRAY_OPEN ); + size_t nOpSize = popOperandSize(); + size_t nOldArraySize = getFormulaSize(); + bool bBiff8 = getBiff() == BIFF8; + + // read array size + swapStreamPosition( rStrm ); + sal_uInt16 nCols = rStrm.readuInt8(); + sal_uInt16 nRows = rStrm.readuInt16(); + if( bBiff8 ) { ++nCols; ++nRows; } else if( nCols == 0 ) nCols = 256; + OSL_ENSURE( (nCols > 0) && (nRows > 0), "BiffFormulaParserImpl::importArrayToken - empty array" ); + + // read array values and build token array + for( sal_uInt16 nRow = 0; rStrm.isValid() && (nRow < nRows); ++nRow ) + { + if( nRow > 0 ) + appendRawToken( mrFuncProv.OPCODE_ARRAY_ROWSEP ); + for( sal_uInt16 nCol = 0; rStrm.isValid() && (nCol < nCols); ++nCol ) + { + if( nCol > 0 ) + appendRawToken( mrFuncProv.OPCODE_ARRAY_COLSEP ); + switch( rStrm.readuInt8() ) + { + case BIFF_DATATYPE_EMPTY: + appendRawToken( mrFuncProv.OPCODE_PUSH ) <<= OUString(); + rStrm.skip( 8 ); + break; + case BIFF_DATATYPE_DOUBLE: + appendRawToken( mrFuncProv.OPCODE_PUSH ) <<= rStrm.readDouble(); + break; + case BIFF_DATATYPE_STRING: + appendRawToken( mrFuncProv.OPCODE_PUSH ) <<= bBiff8 ? + rStrm.readUniString() : + rStrm.readByteString( false, getTextEncoding() ); + break; + case BIFF_DATATYPE_BOOL: + appendRawToken( mrFuncProv.OPCODE_PUSH ) <<= static_cast< double >( (rStrm.readuInt8() == 0) ? 0.0 : 1.0 ); + rStrm.skip( 7 ); + break; + case BIFF_DATATYPE_ERROR: + appendRawToken( mrFuncProv.OPCODE_PUSH ) <<= BiffHelper::calcDoubleFromError( rStrm.readuInt8() ); + rStrm.skip( 7 ); + break; + default: + OSL_ENSURE( false, "BiffFormulaParserImpl::importArrayToken - unknown data type" ); + appendRawToken( mrFuncProv.OPCODE_PUSH ) <<= BiffHelper::calcDoubleFromError( BIFF_ERR_NA ); + } + } + } + swapStreamPosition( rStrm ); + + // close token array and set resulting operand size + appendRawToken( mrFuncProv.OPCODE_ARRAY_CLOSE ); + pushOperandSize( nOpSize + getFormulaSize() - nOldArraySize ); + return true; +} + +bool BiffFormulaParserImpl::importRefToken2( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) +{ + BinSingleRef2d aRef; + aRef.readBiff2Data( rStrm, bRelativeAsOffset ); + return pushBiffReference( aRef, bDeleted, bRelativeAsOffset ); +} + +bool BiffFormulaParserImpl::importRefToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) +{ + BinSingleRef2d aRef; + aRef.readBiff8Data( rStrm, bRelativeAsOffset ); + return pushBiffReference( aRef, bDeleted, bRelativeAsOffset ); +} + +bool BiffFormulaParserImpl::importAreaToken2( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) +{ + BinComplexRef2d aRef; + aRef.readBiff2Data( rStrm, bRelativeAsOffset ); + return pushBiffReference( aRef, bDeleted, bRelativeAsOffset ); +} + +bool BiffFormulaParserImpl::importAreaToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) +{ + BinComplexRef2d aRef; + aRef.readBiff8Data( rStrm, bRelativeAsOffset ); + return pushBiffReference( aRef, bDeleted, bRelativeAsOffset ); +} + +bool BiffFormulaParserImpl::importRef3dToken5( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) +{ + LinkSheetRange aSheetRange = readSheetRange5( rStrm ); + BinSingleRef2d aRef; + aRef.readBiff2Data( rStrm, bRelativeAsOffset ); + return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset ); +} + +bool BiffFormulaParserImpl::importRef3dToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) +{ + LinkSheetRange aSheetRange = readSheetRange8( rStrm ); + BinSingleRef2d aRef; + aRef.readBiff8Data( rStrm, bRelativeAsOffset ); + return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset ); +} + +bool BiffFormulaParserImpl::importArea3dToken5( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) +{ + LinkSheetRange aSheetRange = readSheetRange5( rStrm ); + BinComplexRef2d aRef; + aRef.readBiff2Data( rStrm, bRelativeAsOffset ); + return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset ); +} + +bool BiffFormulaParserImpl::importArea3dToken8( BiffInputStream& rStrm, bool bDeleted, bool bRelativeAsOffset ) +{ + LinkSheetRange aSheetRange = readSheetRange8( rStrm ); + BinComplexRef2d aRef; + aRef.readBiff8Data( rStrm, bRelativeAsOffset ); + return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset ); +} + +bool BiffFormulaParserImpl::importMemAreaToken( BiffInputStream& rStrm, bool bAddData ) +{ + rStrm.skip( mnMemAreaSize ); + if( bAddData ) + skipMemAreaAddData( rStrm ); + return true; +} + +bool BiffFormulaParserImpl::importMemFuncToken( BiffInputStream& rStrm ) +{ + rStrm.skip( mnMemFuncSize ); + return true; +} + +bool BiffFormulaParserImpl::importNameToken( BiffInputStream& rStrm ) +{ + sal_uInt16 nNameId = readNameId( rStrm ); + return (mnCurrRefId > 0) ? pushBiffExtName( mnCurrRefId, nNameId ) : pushBiffName( nNameId ); +} + +bool BiffFormulaParserImpl::importNameXToken( BiffInputStream& rStrm ) +{ + sal_Int32 nRefId = readRefId( rStrm ); + sal_uInt16 nNameId = readNameId( rStrm ); + return pushBiffExtName( nRefId, nNameId ); +} + +bool BiffFormulaParserImpl::importFuncToken2( BiffInputStream& rStrm ) +{ + sal_uInt8 nFuncId; + rStrm >> nFuncId; + return pushBiffFunction( nFuncId ); +} + +bool BiffFormulaParserImpl::importFuncToken4( BiffInputStream& rStrm ) +{ + sal_uInt16 nFuncId; + rStrm >> nFuncId; + return pushBiffFunction( nFuncId ); +} + +bool BiffFormulaParserImpl::importFuncVarToken2( BiffInputStream& rStrm ) +{ + sal_uInt8 nParamCount, nFuncId; + rStrm >> nParamCount >> nFuncId; + return pushBiffFunction( nFuncId, nParamCount ); +} + +bool BiffFormulaParserImpl::importFuncVarToken4( BiffInputStream& rStrm ) +{ + sal_uInt8 nParamCount; + sal_uInt16 nFuncId; + rStrm >> nParamCount >> nFuncId; + return pushBiffFunction( nFuncId, nParamCount & BIFF_TOK_FUNCVAR_COUNTMASK ); +} + +bool BiffFormulaParserImpl::importFuncCEToken( BiffInputStream& rStrm ) +{ + sal_uInt8 nParamCount, nFuncId; + rStrm >> nParamCount >> nFuncId; + sal_uInt16 nCmdId = nFuncId; + setFlag( nCmdId, BIFF_TOK_FUNCVAR_CMD ); + return pushBiffFunction( nCmdId, nParamCount ); +} + +bool BiffFormulaParserImpl::importExpToken5( BiffInputStream& rStrm ) +{ + BinAddress aBaseAddr; + aBaseAddr.read( rStrm ); + setSharedFormula( aBaseAddr ); + // formula has been set, exit parser by returning false + return false; +} + +bool BiffFormulaParserImpl::importNlrAddrToken( BiffInputStream& rStrm, bool bRow ) +{ + BiffNlr aNlr; + aNlr.readBiff8Data( rStrm ); + return pushBiffNlrAddr( aNlr, bRow ); +} + +bool BiffFormulaParserImpl::importNlrRangeToken( BiffInputStream& rStrm ) +{ + BiffNlr aNlr; + aNlr.readBiff8Data( rStrm ); + rStrm.skip( 1 ); + BinRange aRange; + rStrm >> aRange; + return pushBiffNlrRange( aNlr, aRange ); +} + +bool BiffFormulaParserImpl::importNlrSAddrToken( BiffInputStream& rStrm, bool bRow ) +{ + rStrm.skip( 4 ); + BiffNlr aNlr; + return readNlrSAddrAddData( aNlr, rStrm, bRow ) ? pushBiffNlrSAddr( aNlr, bRow ) : pushBiffErrorOperand( BIFF_ERR_REF ); +} + +bool BiffFormulaParserImpl::importNlrSRangeToken( BiffInputStream& rStrm ) +{ + rStrm.skip( 5 ); + BinRange aRange; + rStrm >> aRange; + BiffNlr aNlr; + bool bRow; + return readNlrSRangeAddData( aNlr, bRow, rStrm ) ? pushBiffNlrSRange( aNlr, aRange, bRow ) : pushBiffErrorOperand( BIFF_ERR_REF ); +} + +bool BiffFormulaParserImpl::importNlrErrToken( BiffInputStream& rStrm, sal_uInt16 nIgnore ) +{ + rStrm.skip( nIgnore ); + return pushBiffErrorOperand( BIFF_ERR_NAME ); +} + +sal_Int32 BiffFormulaParserImpl::readRefId( BiffInputStream& rStrm ) +{ + sal_Int16 nRefId; + rStrm >> nRefId; + rStrm.skip( mnRefIdSize ); + return nRefId; +} + +sal_uInt16 BiffFormulaParserImpl::readNameId( BiffInputStream& rStrm ) +{ + sal_uInt16 nNameId; + rStrm >> nNameId; + rStrm.skip( mnNameSize ); + return nNameId; +} + +LinkSheetRange BiffFormulaParserImpl::readSheetRange5( BiffInputStream& rStrm ) +{ + sal_Int32 nRefId = readRefId( rStrm ); + sal_Int16 nTab1, nTab2; + rStrm >> nTab1 >> nTab2; + return getExternalLinks().getSheetRange( nRefId, nTab1, nTab2 ); +} + +LinkSheetRange BiffFormulaParserImpl::readSheetRange8( BiffInputStream& rStrm ) +{ + return getExternalLinks().getSheetRange( readRefId( rStrm ) ); +} + +void BiffFormulaParserImpl::swapStreamPosition( BiffInputStream& rStrm ) +{ + sal_uInt32 nRecPos = rStrm.getRecPos(); + rStrm.seek( mnAddDataPos ); + mnAddDataPos = nRecPos; +} + +void BiffFormulaParserImpl::skipMemAreaAddData( BiffInputStream& rStrm ) +{ + swapStreamPosition( rStrm ); + sal_uInt32 nCount = rStrm.readuInt16(); + rStrm.skip( ((getBiff() == BIFF8) ? 8 : 6) * nCount ); + swapStreamPosition( rStrm ); +} + +bool BiffFormulaParserImpl::readNlrSAddrAddData( BiffNlr& orNlr, BiffInputStream& rStrm, bool bRow ) +{ + bool bIsRow; + return readNlrSRangeAddData( orNlr, bIsRow, rStrm ) && (bIsRow == bRow); +} + +bool BiffFormulaParserImpl::readNlrSRangeAddData( BiffNlr& orNlr, bool& orbIsRow, BiffInputStream& rStrm ) +{ + swapStreamPosition( rStrm ); + // read number of cell addresses and relative flag + sal_uInt32 nCount; + rStrm >> nCount; + bool bRel = getFlag( nCount, BIFF_TOK_NLR_ADDREL ); + nCount &= BIFF_TOK_NLR_ADDMASK; + sal_uInt32 nEndPos = rStrm.getRecPos() + 4 * nCount; + // read list of cell addresses + bool bValid = false; + if( nCount >= 2 ) + { + // detect column/row orientation + BinAddress aAddr1, aAddr2; + rStrm >> aAddr1 >> aAddr2; + orbIsRow = aAddr1.mnRow == aAddr2.mnRow; + bValid = lclIsValidNlrStack( aAddr1, aAddr2, orbIsRow ); + // read and verify additional cell positions + for( sal_uInt32 nIndex = 2; bValid && (nIndex < nCount); ++nIndex ) + { + aAddr1 = aAddr2; + rStrm >> aAddr2; + bValid = rStrm.isValid() && lclIsValidNlrStack( aAddr1, aAddr2, orbIsRow ); + } + // check that last imported position (aAddr2) is not at the end of the sheet + bValid = bValid && (orbIsRow ? (aAddr2.mnCol < mnMaxApiCol) : (aAddr2.mnRow < mnMaxApiRow)); + // fill the NLR struct with the last imported position + if( bValid ) + { + orNlr.mnCol = aAddr2.mnCol; + orNlr.mnRow = aAddr2.mnRow; + orNlr.mbRel = bRel; + } + } + // seek to end of additional data for this token + rStrm.seek( nEndPos ); + swapStreamPosition( rStrm ); + + return bValid; +} + +// convert BIFF token and push API operand or operator ------------------------ + +bool BiffFormulaParserImpl::pushBiffReference( const BinSingleRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) +{ + return (mnCurrRefId > 0) ? + pushReferenceOperand( getExternalLinks().getSheetRange( mnCurrRefId, 0, 0 ), rRef, bDeleted, bRelativeAsOffset ) : + pushReferenceOperand( rRef, bDeleted, bRelativeAsOffset ); +} + +bool BiffFormulaParserImpl::pushBiffReference( const BinComplexRef2d& rRef, bool bDeleted, bool bRelativeAsOffset ) +{ + return (mnCurrRefId > 0) ? + pushReferenceOperand( getExternalLinks().getSheetRange( mnCurrRefId, 0, 0 ), rRef, bDeleted, bRelativeAsOffset ) : + pushReferenceOperand( rRef, bDeleted, bRelativeAsOffset ); +} + +bool BiffFormulaParserImpl::pushBiffNlrAddr( const BiffNlr& rNlr, bool bRow ) +{ + BinSingleRef2d aRef; + aRef.mnCol = rNlr.mnCol; + aRef.mnRow = rNlr.mnRow; + aRef.mbColRel = !bRow; + aRef.mbRowRel = bRow; + return pushNlrOperand( aRef ); +} + +bool BiffFormulaParserImpl::pushBiffNlrRange( const BiffNlr& rNlr, const BinRange& rRange ) +{ + bool bRow = rNlr.mnRow == rRange.maFirst.mnRow; + return lclIsValidNlrRange( rNlr, rRange, bRow ) ? + pushBiffNlrAddr( rNlr, bRow ) : pushBiffErrorOperand( BIFF_ERR_REF ); +} + +bool BiffFormulaParserImpl::pushBiffNlrSAddr( const BiffNlr& rNlr, bool bRow ) +{ + BinRange aRange; + aRange.maFirst.mnCol = rNlr.mnCol + (bRow ? 1 : 0); + aRange.maFirst.mnRow = rNlr.mnRow + (bRow ? 0 : 1); + aRange.maLast.mnCol = bRow ? mnMaxApiCol : rNlr.mnCol; + aRange.maLast.mnRow = bRow ? rNlr.mnRow : mnMaxApiRow; + return pushBiffNlrSRange( rNlr, aRange, bRow ); +} + +bool BiffFormulaParserImpl::pushBiffNlrSRange( const BiffNlr& rNlr, const BinRange& rRange, bool bRow ) +{ + if( lclIsValidNlrRange( rNlr, rRange, bRow ) ) + { + BinComplexRef2d aRef; + aRef.maRef1.mnCol = rRange.maFirst.mnCol; + aRef.maRef1.mnRow = rRange.maFirst.mnRow; + aRef.maRef2.mnCol = rRange.maLast.mnCol; + aRef.maRef2.mnRow = rRange.maLast.mnRow; + aRef.maRef1.mbColRel = aRef.maRef2.mbColRel = !bRow && rNlr.mbRel; + aRef.maRef1.mbRowRel = aRef.maRef2.mbRowRel = bRow && rNlr.mbRel; + return pushReferenceOperand( aRef, false, false ); + } + return pushBiffErrorOperand( BIFF_ERR_REF ); +} + +bool BiffFormulaParserImpl::pushBiffName( sal_uInt16 nNameId ) +{ + // one-based in BIFF formulas + return pushDefinedNameOperand( getDefinedNames().getByIndex( static_cast< sal_Int32 >( nNameId ) - 1 ) ); +} + +bool BiffFormulaParserImpl::pushBiffExtName( sal_Int32 nRefId, sal_uInt16 nNameId ) +{ + if( const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId ).get() ) + { + if( pExtLink->getLinkType() == LINKTYPE_SELF ) + return pushBiffName( nNameId ); + // external name indexes are one-based in BIFF + ExternalNameRef xExtName = pExtLink->getNameByIndex( static_cast< sal_Int32 >( nNameId ) - 1 ); + return pushExternalNameOperand( xExtName, pExtLink->getLinkType() ); + } + return pushBiffErrorOperand( BIFF_ERR_NAME ); +} + +bool BiffFormulaParserImpl::pushBiffFunction( sal_uInt16 nFuncId ) +{ + if( const FunctionInfo* pFuncInfo = mrFuncProv.getFuncInfoFromBiffFuncId( nFuncId ) ) + if( pFuncInfo->mnMinParamCount == pFuncInfo->mnMaxParamCount ) + return pushFunctionOperator( *pFuncInfo, pFuncInfo->mnMinParamCount ); + return pushFunctionOperator( mrFuncProv.OPCODE_NONAME, 0 ); +} + +bool BiffFormulaParserImpl::pushBiffFunction( sal_uInt16 nFuncId, sal_uInt8 nParamCount ) +{ + if( getFlag( nFuncId, BIFF_TOK_FUNCVAR_CMD ) ) + nParamCount &= BIFF_TOK_FUNCVAR_COUNTMASK; + if( const FunctionInfo* pFuncInfo = mrFuncProv.getFuncInfoFromBiffFuncId( nFuncId ) ) + return pushFunctionOperator( *pFuncInfo, nParamCount ); + return pushFunctionOperator( mrFuncProv.OPCODE_NONAME, nParamCount ); +} + +// ============================================================================ + +FormulaParser::FormulaParser( const WorkbookHelper& rHelper ) : + FormulaProcessorBase( rHelper ) +{ + switch( getFilterType() ) + { + case FILTER_OOX: mxImpl.reset( new OoxFormulaParserImpl( rHelper, maFuncProv ) ); break; + case FILTER_BIFF: mxImpl.reset( new BiffFormulaParserImpl( rHelper, maFuncProv ) ); break; + case FILTER_UNKNOWN: break; + } +} + +FormulaParser::~FormulaParser() +{ +} + +void FormulaParser::importFormula( FormulaContext& rContext, const OUString& rFormulaString ) const +{ + mxImpl->importOoxFormula( rContext, rFormulaString ); +} + +void FormulaParser::importFormula( FormulaContext& rContext, RecordInputStream& rStrm ) const +{ + mxImpl->importOobFormula( rContext, rStrm ); +} + +void FormulaParser::importFormula( FormulaContext& rContext, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ) const +{ + mxImpl->importBiffFormula( rContext, rStrm, pnFmlaSize ); +} + +void FormulaParser::convertErrorToFormula( FormulaContext& rContext, sal_uInt8 nErrorCode ) const +{ + ApiTokenSequence aTokens( 3 ); + // HACK: enclose all error codes into an 1x1 matrix + aTokens[ 0 ].OpCode = maFuncProv.OPCODE_ARRAY_OPEN; + aTokens[ 1 ].OpCode = maFuncProv.OPCODE_PUSH; + aTokens[ 1 ].Data <<= BiffHelper::calcDoubleFromError( nErrorCode ); + aTokens[ 2 ].OpCode = maFuncProv.OPCODE_ARRAY_CLOSE; + mxImpl->setFormula( rContext, aTokens ); +} + +void FormulaParser::convertNameToFormula( FormulaContext& rContext, sal_Int32 nTokenIndex ) const +{ + if( nTokenIndex >= 0 ) + { + ApiTokenSequence aTokens( 1 ); + aTokens[ 0 ].OpCode = maFuncProv.OPCODE_NAME; + aTokens[ 0 ].Data <<= nTokenIndex; + mxImpl->setFormula( rContext, aTokens ); + } + else + convertErrorToFormula( rContext, BIFF_ERR_REF ); +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/headerfooterparser.cxx b/oox/source/xls/headerfooterparser.cxx new file mode 100644 index 000000000000..663a17c5c89f --- /dev/null +++ b/oox/source/xls/headerfooterparser.cxx @@ -0,0 +1,643 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: headerfooterparser.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:08 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/headerfooterparser.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "oox/helper/attributelist.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/xls/stylesbuffer.hxx" +#include "oox/xls/themebuffer.hxx" + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::rtl::OString; +using ::rtl::OStringBuffer; +using ::rtl::OUStringToOString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::sheet::XHeaderFooterContent; +using ::com::sun::star::text::XText; +using ::com::sun::star::text::XTextCursor; +using ::com::sun::star::text::XTextContent; +using ::com::sun::star::text::XTextRange; + +namespace oox { +namespace xls { + +// ============================================================================ + +enum HFPortionId +{ + HF_LEFT, + HF_CENTER, + HF_RIGHT, + HF_COUNT +}; + +// ---------------------------------------------------------------------------- + +struct HFPortionInfo +{ + Reference< XText > mxText; /// XText interface of this portion. + Reference< XTextCursor > mxStart; /// Start position of current text range for formatting. + Reference< XTextCursor > mxEnd; /// End position of current text range for formatting. + double mfTotalHeight; /// Sum of heights of previous lines in points. + double mfCurrHeight; /// Height of the current text line in points. + + bool initialize( const Reference< XText >& rxText ); +}; + +bool HFPortionInfo::initialize( const Reference< XText >& rxText ) +{ + mfTotalHeight = mfCurrHeight = 0.0; + mxText = rxText; + if( mxText.is() ) + { + mxStart = mxText->createTextCursor(); + mxEnd = mxText->createTextCursor(); + } + bool bRet = mxText.is() && mxStart.is() && mxEnd.is(); + OSL_ENSURE( bRet, "HFPortionInfo::initialize - missing interfaces" ); + return bRet; +} + +// ---------------------------------------------------------------------------- + +class HeaderFooterParserImpl : public WorkbookHelper +{ +public: + explicit HeaderFooterParserImpl( const WorkbookHelper& rHelper ); + + /** Parses the passed string and creates the header/footer contents. */ + void parse( + const Reference< XHeaderFooterContent >& rxContext, + const OUString& rData ); + + /** Returns the total height of the converted header or footer in points. */ + double getTotalHeight() const; + +private: + /** Returns the current edit engine text object. */ + inline HFPortionInfo& getPortion() { return maPortions[ meCurrPortion ]; } + /** Returns the start cursor of the current text range. */ + inline const Reference< XTextCursor >& getStartPos() { return getPortion().mxStart; } + /** Returns the end cursor of the current text range. */ + inline const Reference< XTextCursor >& getEndPos() { return getPortion().mxEnd; } + + /** Returns the current line height of the specified portion. */ + double getCurrHeight( HFPortionId ePortion ) const; + /** Returns the current line height. */ + double getCurrHeight() const; + + /** Updates the current line height of the specified portion, using the current font size. */ + void updateCurrHeight( HFPortionId ePortion ); + /** Updates the current line height, using the current font size. */ + void updateCurrHeight(); + + /** Sets the font attributes at the current selection. */ + void setAttributes(); + /** Appends and clears internal string buffer. */ + void appendText(); + /** Appends a line break and adjusts internal text height data. */ + void appendLineBreak(); + + /** Creates a text field from the passed service name. */ + Reference< XTextContent > createField( const OUString& rServiceName ) const; + /** Appends the passed text field. */ + void appendField( const Reference< XTextContent >& rxContent ); + + /** Sets the passed font name if it is valid. */ + void convertFontName( const OUString& rStyle ); + /** Converts a font style given as string. */ + void convertFontStyle( const OUString& rStyle ); + /** Converts a font color given as string. */ + void convertFontColor( const OUString& rColor ); + + /** Finalizes current portion: sets font attributes and updates text height data. */ + void finalizePortion(); + /** Changes current header/footer portion. */ + void setNewPortion( HFPortionId ePortion ); + +private: + typedef ::std::vector< HFPortionInfo > HFPortionInfoVec; + typedef ::std::set< OString > OStringSet; + + OUString maPageNumberService; + OUString maPageCountService; + OUString maSheetNameService; + OUString maFileNameService; + OUString maDateTimeService; + OUString maIsDateProp; + OUString maFileFormatProp; + OStringSet maBoldNames; /// All names for bold font style in lowercase UTF-8. + OStringSet maItalicNames; /// All names for italic font style in lowercase UTF-8. + HFPortionInfoVec maPortions; + HFPortionId meCurrPortion; /// Identifier of current H/F portion. + OUStringBuffer maBuffer; /// Text data to append to current text range. + OoxFontData maFontData; /// Font attributes of current text range. +}; + + +HeaderFooterParserImpl::HeaderFooterParserImpl( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + maPageNumberService( CREATE_OUSTRING( "com.sun.star.text.TextField.PageNumber" ) ), + maPageCountService( CREATE_OUSTRING( "com.sun.star.text.TextField.PageCount" ) ), + maSheetNameService( CREATE_OUSTRING( "com.sun.star.text.TextField.SheetName" ) ), + maFileNameService( CREATE_OUSTRING( "com.sun.star.text.TextField.FileName" ) ), + maDateTimeService( CREATE_OUSTRING( "com.sun.star.text.TextField.DateTime" ) ), + maIsDateProp( CREATE_OUSTRING( "IsDate" ) ), + maFileFormatProp( CREATE_OUSTRING( "FileFormat" ) ), + maPortions( static_cast< size_t >( HF_COUNT ) ), + meCurrPortion( HF_CENTER ) +{ + // different names for bold font style (lowercase) + maBoldNames.insert( CREATE_OSTRING( "bold" ) ); + maBoldNames.insert( CREATE_OSTRING( "fett" ) ); + maBoldNames.insert( CREATE_OSTRING( "demibold" ) ); + maBoldNames.insert( CREATE_OSTRING( "halbfett" ) ); + maBoldNames.insert( CREATE_OSTRING( "black" ) ); + maBoldNames.insert( CREATE_OSTRING( "heavy" ) ); + + // different names for italic font style (lowercase) + maItalicNames.insert( CREATE_OSTRING( "italic" ) ); + maItalicNames.insert( CREATE_OSTRING( "kursiv" ) ); + maItalicNames.insert( CREATE_OSTRING( "oblique" ) ); + maItalicNames.insert( CREATE_OSTRING( "schr\303\204g" ) ); // with uppercase A umlaut + maItalicNames.insert( CREATE_OSTRING( "schr\303\244g" ) ); // with lowercase A umlaut +} + +void HeaderFooterParserImpl::parse( const Reference< XHeaderFooterContent >& rxContext, const OUString& rData ) +{ + if( !rxContext.is() || (rData.getLength() == 0) || + !maPortions[ HF_LEFT ].initialize( rxContext->getLeftText() ) || + !maPortions[ HF_CENTER ].initialize( rxContext->getCenterText() ) || + !maPortions[ HF_RIGHT ].initialize( rxContext->getRightText() ) ) + return; + + meCurrPortion = HF_CENTER; + maBuffer.setLength( 0 ); + maFontData = getStyles().getDefaultFontData(); + OUStringBuffer aFontName; // current font name + OUStringBuffer aFontStyle; // current font style + sal_Int32 nFontHeight = 0; // current font height + + /** State of the parser. */ + enum + { + STATE_TEXT, /// Literal text data. + STATE_TOKEN, /// Control token following a '&' character. + STATE_FONTNAME, /// Font name ('&' is followed by '"', reads until next '"' or ','). + STATE_FONTSTYLE, /// Font style name (font part after ',', reads until next '"'). + STATE_FONTHEIGHT /// Font height ('&' is followed by num. digits, reads until non-digit). + } + eState = STATE_TEXT; + + const sal_Unicode* pcChar = rData.getStr(); + const sal_Unicode* pcEnd = pcChar + rData.getLength(); + for( ; (pcChar != pcEnd) && (*pcChar != 0); ++pcChar ) + { + sal_Unicode cChar = *pcChar; + switch( eState ) + { + case STATE_TEXT: + { + switch( cChar ) + { + case '&': // new token + appendText(); + eState = STATE_TOKEN; + break; + case '\n': // line break + appendText(); + appendLineBreak(); + break; + default: + maBuffer.append( cChar ); + } + } + break; + + case STATE_TOKEN: + { + // default: back to text mode, may be changed in specific cases + eState = STATE_TEXT; + // ignore case of token codes + if( ('a' <= cChar) && (cChar <= 'z') ) + (cChar -= 'a') += 'A'; + switch( cChar ) + { + case '&': maBuffer.append( cChar ); break; // the '&' character + + case 'L': setNewPortion( HF_LEFT ); break; // left portion + case 'C': setNewPortion( HF_CENTER ); break; // center portion + case 'R': setNewPortion( HF_RIGHT ); break; // right portion + + case 'P': // page number + appendField( createField( maPageNumberService ) ); + break; + case 'N': // total page count + appendField( createField( maPageCountService ) ); + break; + case 'A': // current sheet name + appendField( createField( maSheetNameService ) ); + break; + + case 'F': // file name + { + Reference< XTextContent > xContent = createField( maFileNameService ); + PropertySet aPropSet( xContent ); + aPropSet.setProperty( maFileFormatProp, ::com::sun::star::text::FilenameDisplayFormat::NAME_AND_EXT ); + appendField( xContent ); + } + break; + case 'Z': // file path (without file name), BIFF8 and OOX only + if( (getFilterType() == FILTER_OOX) || ((getFilterType() == FILTER_BIFF) && (getBiff() == BIFF8)) ) + { + Reference< XTextContent > xContent = createField( maFileNameService ); + PropertySet aPropSet( xContent ); + // FilenameDisplayFormat::PATH not supported by Calc + aPropSet.setProperty( maFileFormatProp, ::com::sun::star::text::FilenameDisplayFormat::FULL ); + appendField( xContent ); + /* path only is not supported -- if we find a '&Z&F' + combination for path/name, skip the '&F' part */ + if( (pcChar + 2 < pcEnd) && (pcChar[ 1 ] == '&') && ((pcChar[ 2 ] == 'f') || (pcChar[ 2 ] == 'F')) ) + pcChar += 2; + } + break; + case 'D': // date + { + Reference< XTextContent > xContent = createField( maDateTimeService ); + PropertySet aPropSet( xContent ); + aPropSet.setProperty( maIsDateProp, true ); + appendField( xContent ); + } + break; + case 'T': // time + { + Reference< XTextContent > xContent = createField( maDateTimeService ); + PropertySet aPropSet( xContent ); + aPropSet.setProperty( maIsDateProp, false ); + appendField( xContent ); + } + break; + + case 'B': // bold + setAttributes(); + maFontData.mbBold = !maFontData.mbBold; + break; + case 'I': // italic + setAttributes(); + maFontData.mbItalic = !maFontData.mbItalic; + break; + case 'U': // underline + setAttributes(); + maFontData.mnUnderline = (maFontData.mnUnderline == XML_single) ? XML_none : XML_single; + break; + case 'E': // double underline + setAttributes(); + maFontData.mnUnderline = (maFontData.mnUnderline == XML_double) ? XML_none : XML_double; + break; + case 'S': // strikeout + setAttributes(); + maFontData.mbStrikeout = !maFontData.mbStrikeout; + break; + case 'X': // superscript + setAttributes(); + maFontData.mnEscapement = (maFontData.mnEscapement == XML_superscript) ? XML_baseline : XML_superscript; + break; + case 'Y': // subsrcipt + setAttributes(); + maFontData.mnEscapement = (maFontData.mnEscapement == XML_subscript) ? XML_baseline : XML_subscript; + break; + case 'O': // outlined + setAttributes(); + maFontData.mbOutline = !maFontData.mbOutline; + break; + case 'H': // shadow + setAttributes(); + maFontData.mbShadow = !maFontData.mbShadow; + break; + + case 'K': // text color (not in BIFF) + if( (getFilterType() == FILTER_OOX) && (pcChar + 6 < pcEnd) ) + { + setAttributes(); + // eat the following 6 characters + convertFontColor( OUString( pcChar + 1, 6 ) ); + pcChar += 6; + } + break; + + case '\"': // font name + aFontName.setLength( 0 ); + aFontStyle.setLength( 0 ); + eState = STATE_FONTNAME; + break; + default: + if( ('0' <= cChar) && (cChar <= '9') ) // font size + { + nFontHeight = cChar - '0'; + eState = STATE_FONTHEIGHT; + } + } + } + break; + + case STATE_FONTNAME: + { + switch( cChar ) + { + case '\"': + setAttributes(); + convertFontName( aFontName.makeStringAndClear() ); + eState = STATE_TEXT; + break; + case ',': + eState = STATE_FONTSTYLE; + break; + default: + aFontName.append( cChar ); + } + } + break; + + case STATE_FONTSTYLE: + { + switch( cChar ) + { + case '\"': + setAttributes(); + convertFontName( aFontName.makeStringAndClear() ); + convertFontStyle( aFontStyle.makeStringAndClear() ); + eState = STATE_TEXT; + break; + default: + aFontStyle.append( cChar ); + } + } + break; + + case STATE_FONTHEIGHT: + { + if( ('0' <= cChar) && (cChar <= '9') ) + { + if( nFontHeight >= 0 ) + { + nFontHeight *= 10; + nFontHeight += (cChar - '0'); + if( nFontHeight > 1000 ) + nFontHeight = -1; + } + } + else + { + if( nFontHeight > 0 ) + { + setAttributes(); + maFontData.mfHeight = nFontHeight; + } + --pcChar; + eState = STATE_TEXT; + } + } + break; + } + } + + // finalize + finalizePortion(); + maPortions[ HF_LEFT ].mfTotalHeight += getCurrHeight( HF_LEFT ); + maPortions[ HF_CENTER ].mfTotalHeight += getCurrHeight( HF_CENTER ); + maPortions[ HF_RIGHT ].mfTotalHeight += getCurrHeight( HF_RIGHT ); +} + +double HeaderFooterParserImpl::getTotalHeight() const +{ + return ::std::max( maPortions[ HF_LEFT ].mfTotalHeight, + ::std::max( maPortions[ HF_CENTER ].mfTotalHeight, maPortions[ HF_RIGHT ].mfTotalHeight ) ); +} + +// private -------------------------------------------------------------------- + +double HeaderFooterParserImpl::getCurrHeight( HFPortionId ePortion ) const +{ + double fMaxHt = maPortions[ ePortion ].mfCurrHeight; + return (fMaxHt == 0.0) ? maFontData.mfHeight : fMaxHt; +} + +double HeaderFooterParserImpl::getCurrHeight() const +{ + return getCurrHeight( meCurrPortion ); +} + +void HeaderFooterParserImpl::updateCurrHeight( HFPortionId ePortion ) +{ + double& rfMaxHt = maPortions[ ePortion ].mfCurrHeight; + rfMaxHt = ::std::max( rfMaxHt, maFontData.mfHeight ); +} + +void HeaderFooterParserImpl::updateCurrHeight() +{ + updateCurrHeight( meCurrPortion ); +} + +void HeaderFooterParserImpl::setAttributes() +{ + Reference< XTextRange > xRange( getStartPos(), UNO_QUERY ); + getEndPos()->gotoRange( xRange, sal_False ); + getEndPos()->gotoEnd( sal_True ); + if( !getEndPos()->isCollapsed() ) + { + Font aFont( *this, maFontData ); + aFont.finalizeImport(); + PropertySet aPropSet( getEndPos() ); + aFont.writeToPropertySet( aPropSet, FONT_PROPTYPE_RICHTEXT ); + getStartPos()->gotoEnd( sal_False ); + getEndPos()->gotoEnd( sal_False ); + } +} + +void HeaderFooterParserImpl::appendText() +{ + if( maBuffer.getLength() > 0 ) + { + getEndPos()->gotoEnd( sal_False ); + getEndPos()->setString( maBuffer.makeStringAndClear() ); + updateCurrHeight(); + } +} + +void HeaderFooterParserImpl::appendLineBreak() +{ + getEndPos()->gotoEnd( sal_False ); + getEndPos()->setString( OUString( sal_Unicode( '\n' ) ) ); + getPortion().mfTotalHeight += getCurrHeight(); + getPortion().mfCurrHeight = 0; +} + +Reference< XTextContent > HeaderFooterParserImpl::createField( const OUString& rServiceName ) const +{ + Reference< XTextContent > xContent; + try + { + Reference< XMultiServiceFactory > xFactory( getDocument(), UNO_QUERY_THROW ); + xContent.set( xFactory->createInstance( rServiceName ), UNO_QUERY_THROW ); + } + catch( Exception& ) + { + OSL_ENSURE( false, + OStringBuffer( "HeaderFooterParserImpl::createField - error while creating text field \"" ). + append( OUStringToOString( rServiceName, RTL_TEXTENCODING_ASCII_US ) ). + append( '"' ).getStr() ); + } + return xContent; +} + +void HeaderFooterParserImpl::appendField( const Reference< XTextContent >& rxContent ) +{ + getEndPos()->gotoEnd( sal_False ); + try + { + Reference< XTextRange > xRange( getEndPos(), UNO_QUERY_THROW ); + getPortion().mxText->insertTextContent( xRange, rxContent, sal_False ); + updateCurrHeight(); + } + catch( Exception& ) + { + } +} + +void HeaderFooterParserImpl::convertFontName( const OUString& rName ) +{ + if( rName.getLength() > 0 ) + { + // single dash is document default font + if( (rName.getLength() == 1) && (rName[ 0 ] == '-') ) + maFontData.maName = getStyles().getDefaultFontData().maName; + else + maFontData.maName = rName; + } +} + +void HeaderFooterParserImpl::convertFontStyle( const OUString& rStyle ) +{ + maFontData.mbBold = maFontData.mbItalic = false; + sal_Int32 nPos = 0; + sal_Int32 nLen = rStyle.getLength(); + while( (0 <= nPos) && (nPos < nLen) ) + { + OString aToken = OUStringToOString( rStyle.getToken( 0, ' ', nPos ), RTL_TEXTENCODING_UTF8 ).toAsciiLowerCase(); + if( aToken.getLength() > 0 ) + { + if( maBoldNames.count( aToken ) > 0 ) + maFontData.mbBold = true; + else if( maItalicNames.count( aToken ) > 0 ) + maFontData.mbItalic = true; + } + } +} + +void HeaderFooterParserImpl::convertFontColor( const OUString& rColor ) +{ + OSL_ENSURE( rColor.getLength() == 6, "HeaderFooterParserImpl::convertFontColor - invalid font color code" ); + if( (rColor[ 2 ] == '+') || (rColor[ 2 ] == '-') ) + // theme color: TTSNNN (TT = decimal theme index, S = +/-, NNN = decimal tint/shade in percent) + maFontData.maColor.set( + XML_theme, rColor.copy( 0, 2 ).toInt32(), + static_cast< double >( rColor.copy( 2 ).toInt32() ) / 100.0 ); + else + // RGB color: RRGGBB + maFontData.maColor.set( XML_rgb, rColor.toInt32( 16 ) ); +} + +void HeaderFooterParserImpl::finalizePortion() +{ + appendText(); + setAttributes(); +} + +void HeaderFooterParserImpl::setNewPortion( HFPortionId ePortion ) +{ + if( ePortion != meCurrPortion ) + { + finalizePortion(); + meCurrPortion = ePortion; + maFontData = getStyles().getDefaultFontData(); + } +} + +// ============================================================================ + +HeaderFooterParser::HeaderFooterParser( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + mxImpl( new HeaderFooterParserImpl( rHelper ) ) +{ +} + +HeaderFooterParser::~HeaderFooterParser() +{ +} + +void HeaderFooterParser::parse( const Reference< XHeaderFooterContent >& rxContext, const OUString& rData ) +{ + mxImpl->parse( rxContext, rData ); +} + +double HeaderFooterParser::getTotalHeight() const +{ + return mxImpl->getTotalHeight(); +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/makefile.mk b/oox/source/xls/makefile.mk new file mode 100644 index 000000000000..f46737cb307b --- /dev/null +++ b/oox/source/xls/makefile.mk @@ -0,0 +1,106 @@ +#************************************************************************* +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.2 $ +# +# last change: $Author: rt $ $Date: 2008-01-17 08:06:08 $ +# +# The Contents of this file are made available subject to +# the terms of GNU Lesser General Public License Version 2.1. +# +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2005 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=oox +TARGET=xls +AUTOSEG=true + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/addressconverter.obj \ + $(SLO)$/autofiltercontext.obj \ + $(SLO)$/biffcodec.obj \ + $(SLO)$/biffdetector.obj \ + $(SLO)$/bifffragmenthandler.obj \ + $(SLO)$/biffhelper.obj \ + $(SLO)$/biffinputstream.obj \ + $(SLO)$/biffoutputstream.obj \ + $(SLO)$/condformatbuffer.obj \ + $(SLO)$/condformatcontext.obj \ + $(SLO)$/connectionsfragment.obj \ + $(SLO)$/defnamesbuffer.obj \ + $(SLO)$/excelfilter.obj \ + $(SLO)$/externallinkbuffer.obj \ + $(SLO)$/externallinkfragment.obj \ + $(SLO)$/formulabase.obj \ + $(SLO)$/formulaparser.obj \ + $(SLO)$/headerfooterparser.obj \ + $(SLO)$/numberformatsbuffer.obj \ + $(SLO)$/ooxcontexthandler.obj \ + $(SLO)$/ooxcontexthelper.obj \ + $(SLO)$/ooxfragmenthandler.obj \ + $(SLO)$/pagesettings.obj \ + $(SLO)$/pivotcachefragment.obj \ + $(SLO)$/pivottablebuffer.obj \ + $(SLO)$/pivottablefragment.obj \ + $(SLO)$/querytablefragment.obj \ + $(SLO)$/richstring.obj \ + $(SLO)$/richstringcontext.obj \ + $(SLO)$/sharedformulabuffer.obj \ + $(SLO)$/sharedstringsbuffer.obj \ + $(SLO)$/sharedstringsfragment.obj \ + $(SLO)$/sheetcellrangemap.obj \ + $(SLO)$/sheetdatacontext.obj \ + $(SLO)$/stylesbuffer.obj \ + $(SLO)$/stylesfragment.obj \ + $(SLO)$/stylespropertyhelper.obj \ + $(SLO)$/tablebuffer.obj \ + $(SLO)$/tablefragment.obj \ + $(SLO)$/themebuffer.obj \ + $(SLO)$/unitconverter.obj \ + $(SLO)$/validationpropertyhelper.obj \ + $(SLO)$/viewsettings.obj \ + $(SLO)$/webquerybuffer.obj \ + $(SLO)$/workbookfragment.obj \ + $(SLO)$/workbookhelper.obj \ + $(SLO)$/workbooksettings.obj \ + $(SLO)$/worksheetbuffer.obj \ + $(SLO)$/worksheetfragment.obj \ + $(SLO)$/worksheethelper.obj \ + $(SLO)$/worksheetsettings.obj + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk diff --git a/oox/source/xls/numberformatsbuffer.cxx b/oox/source/xls/numberformatsbuffer.cxx new file mode 100644 index 000000000000..3433a7885704 --- /dev/null +++ b/oox/source/xls/numberformatsbuffer.cxx @@ -0,0 +1,2124 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: numberformatsbuffer.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:08 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/numberformatsbuffer.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "oox/helper/attributelist.hxx" +#include "oox/helper/recordinputstream.hxx" +#include "oox/xls/biffinputstream.hxx" + +using ::rtl::OString; +using ::rtl::OStringBuffer; +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::rtl::OStringToOUString; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::container::XNameAccess; +using ::com::sun::star::lang::Locale; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::util::XNumberFormatsSupplier; +using ::com::sun::star::util::XNumberFormats; +using ::com::sun::star::util::XNumberFormatTypes; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +/** Stores the number format used in Calc for an Excel built-in number format. */ +struct BuiltinFormat +{ + sal_Int32 mnNumFmtId; /// Built-in number format index. + const sal_Char* mpcFmtCode; /// Format string, UTF-8, may be 0 (mnPredefId is used then). + sal_Int16 mnPredefId; /// Predefined format index, if mpcFmtCode is 0. + sal_Int32 mnReuseId; /// Use this format, if mpcFmtCode is 0 and mnPredefId is -1. +}; + +/** Defines a literal built-in number format. */ +#define NUMFMT_STRING( INDEX, FORMATCODE ) \ + { INDEX, FORMATCODE, -1, -1 } + +/** Defines a built-in number format that maps to an own predefined format. */ +#define NUMFMT_PREDEF( INDEX, PREDEFINED ) \ + { INDEX, 0, ::com::sun::star::i18n::NumberFormatIndex::PREDEFINED, -1 } + +/** Defines a built-in number format that is the same as the specified in nReuseId. */ +#define NUMFMT_REUSE( INDEX, REUSED_INDEX ) \ + { INDEX, 0, -1, REUSED_INDEX } + +/** Terminates a built-in number format table. */ +#define NUMFMT_ENDTABLE() \ + { -1, 0, -1, -1 } + +/** Defines builtin date and time formats 14...22. + @param SYSTEMDATE Complete short system date (for formats 14 and 22). + @param DAY Day format (for formats 15 and 16). + @param DAYSEP Separator between day and month (for formats 15 and 16). + @param MONTH Month format (for formats 15...17). + @param MONTHSEP Separator between month and year (for formats 15 and 17). + @param YEAR Year format (for formats 15 and 17). + @param HOUR12 Hour format for 12-hour AM/PM formats (formats 18 and 19). + @param HOUR24 Hour format for 24-hour formats (formats 20...22). */ +#define NUMFMT_ALLDATETIMES( SYSTEMDATE, DAY, DAYSEP, MONTH, MONTHSEP, YEAR, HOUR12, HOUR24 ) \ + NUMFMT_STRING( 14, SYSTEMDATE ), \ + NUMFMT_STRING( 15, DAY DAYSEP MONTH MONTHSEP YEAR ), \ + NUMFMT_STRING( 16, DAY DAYSEP MONTH ), \ + NUMFMT_STRING( 17, MONTH MONTHSEP YEAR ), \ + NUMFMT_STRING( 18, HOUR12 ":mm AM/PM" ), \ + NUMFMT_STRING( 19, HOUR12 ":mm:ss AM/PM" ), \ + NUMFMT_STRING( 20, HOUR24 ":mm" ), \ + NUMFMT_STRING( 21, HOUR24 ":mm:ss" ), \ + NUMFMT_STRING( 22, SYSTEMDATE " " HOUR24 ":mm" ) + +/** Defines builtin time formats INDEX and INDEX+1 for CJK locales. + @param INDEX First number format index. + @param HOURFORMAT Hour format. + @param HOUR Hour symbol. + @param MINUTE Minute symbol. + @param SECOND Second symbol. */ +#define NUMFMT_TIME_CJK( INDEX, HOURFORMAT, HOUR, MINUTE, SECOND ) \ + NUMFMT_STRING( INDEX + 0, HOURFORMAT "\"" HOUR "\"mm\"" MINUTE "\"" ), \ + NUMFMT_STRING( INDEX + 1, HOURFORMAT "\"" HOUR "\"mm\"" MINUTE "\"ss\"" SECOND "\"" ) + +/** Defines builtin time formats 32...35 for CJK locales. + @param HOUR12 Hour format for 12-hour AM/PM formats (formats 34 and 35). + @param HOUR24 Hour format for 24-hour formats (formats 32 and 33). + @param HOUR Hour symbol. + @param MINUTE Minute symbol. + @param SECOND Second symbol. */ +#define NUMFMT_ALLTIMES_CJK( HOUR12, HOUR24, HOUR, MINUTE, SECOND ) \ + NUMFMT_TIME_CJK( 32, HOUR24, HOUR, MINUTE, SECOND ), \ + NUMFMT_TIME_CJK( 34, "AM/PM" HOUR12, HOUR, MINUTE, SECOND ) + +/** Defines builtin currency formats INDEX...INDEX+3 in the following format: + "symbol, [minus], number". + @param INDEX First number format index. + @param SYMBOL Currency symbol. + @param SPACE Space character(s) between currency symbol and number. + @param MODIF Leading modifier for each portion (e.g. "t" for Thai formats). */ +#define NUMFMT_CURRENCY_SYMBOL_MINUS_NUMBER( INDEX, SYMBOL, SPACE, MODIF ) \ + NUMFMT_STRING( INDEX + 0, MODIF SYMBOL SPACE "#,##0;" MODIF SYMBOL SPACE "-#,##0" ), \ + NUMFMT_STRING( INDEX + 1, MODIF SYMBOL SPACE "#,##0;" "[RED]" MODIF SYMBOL SPACE "-#,##0" ), \ + NUMFMT_STRING( INDEX + 2, MODIF SYMBOL SPACE "#,##0.00;" MODIF SYMBOL SPACE "-#,##0.00" ), \ + NUMFMT_STRING( INDEX + 3, MODIF SYMBOL SPACE "#,##0.00;" "[RED]" MODIF SYMBOL SPACE "-#,##0.00" ) + +/** Defines builtin accounting formats INDEX...INDEX+3 in the following format: + "symbol, [minus], number". + @param INDEX First number format index. + @param SYMBOL Currency symbol. + @param SPACE Space character(s) between currency symbol and number. */ +#define NUMFMT_ACCOUNTING_SYMBOL_MINUS_NUMBER( INDEX, SYMBOL, SPACE ) \ + NUMFMT_STRING( INDEX + 0, "_ " "* #,##0_ ;" "_ " "* -#,##0_ ;" "_ " "* \"-\"_ ;" "_ @_ " ), \ + NUMFMT_STRING( INDEX + 1, "_ " SYMBOL SPACE "* #,##0_ ;" "_ " SYMBOL SPACE "* -#,##0_ ;" "_ " SYMBOL SPACE "* \"-\"_ ;" "_ @_ " ), \ + NUMFMT_STRING( INDEX + 2, "_ " "* #,##0.00_ ;" "_ " "* -#,##0.00_ ;" "_ " "* \"-\"?\?_ ;" "_ @_ " ), \ + NUMFMT_STRING( INDEX + 3, "_ " SYMBOL SPACE "* #,##0.00_ ;" "_ " SYMBOL SPACE "* -#,##0.00_ ;" "_ " SYMBOL SPACE "* \"-\"?\?_ ;" "_ @_ " ) + +/** Defines builtin currency formats 5...8 (with currency symbol), 37...40 + (blind currency symbol), and 41...44 (accounting), in the following format: + "symbol, [minus], number". + @param SYMBOL Currency symbol. + @param SPACE Space character(s) between currency symbol and number. */ +#define NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( SYMBOL, SPACE ) \ + NUMFMT_CURRENCY_SYMBOL_MINUS_NUMBER( 5, SYMBOL, SPACE, "" ), \ + NUMFMT_CURRENCY_SYMBOL_MINUS_NUMBER( 37, "", "", "" ), \ + NUMFMT_ACCOUNTING_SYMBOL_MINUS_NUMBER( 41, SYMBOL, SPACE ) + +/** Defines builtin currency formats INDEX...INDEX+3 in the following format: + "symbol, number, [minus]". + @param INDEX First number format index. + @param SYMBOL Currency symbol. + @param SPACE Space character(s) between currency symbol and number. + @param MODIF Leading modifier for each portion (e.g. "t" for Thai formats). */ +#define NUMFMT_CURRENCY_SYMBOL_NUMBER_MINUS( INDEX, SYMBOL, SPACE, MODIF ) \ + NUMFMT_STRING( INDEX + 0, MODIF SYMBOL SPACE "#,##0_-;" MODIF SYMBOL SPACE "#,##0-" ), \ + NUMFMT_STRING( INDEX + 1, MODIF SYMBOL SPACE "#,##0_-;" "[RED]" MODIF SYMBOL SPACE "#,##0-" ), \ + NUMFMT_STRING( INDEX + 2, MODIF SYMBOL SPACE "#,##0.00_-;" MODIF SYMBOL SPACE "#,##0.00-" ), \ + NUMFMT_STRING( INDEX + 3, MODIF SYMBOL SPACE "#,##0.00_-;" "[RED]" MODIF SYMBOL SPACE "#,##0.00-" ) + +/** Defines builtin accounting formats INDEX...INDEX+3 in the following format: + "symbol, number, [minus]". + @param INDEX First number format index. + @param SYMBOL Currency symbol. + @param SPACE Space character(s) between currency symbol and number. */ +#define NUMFMT_ACCOUNTING_SYMBOL_NUMBER_MINUS( INDEX, SYMBOL, SPACE ) \ + NUMFMT_STRING( INDEX + 0, "_-" "* #,##0_-;" "_-" "* #,##0-;" "_-" "* \"-\"_-;" "_-@_-" ), \ + NUMFMT_STRING( INDEX + 1, "_-" SYMBOL SPACE "* #,##0_-;" "_-" SYMBOL SPACE "* #,##0-;" "_-" SYMBOL SPACE "* \"-\"_-;" "_-@_-" ), \ + NUMFMT_STRING( INDEX + 2, "_-" "* #,##0.00_-;" "_-" "* #,##0.00-;" "_-" "* \"-\"?\?_-;" "_-@_-" ), \ + NUMFMT_STRING( INDEX + 3, "_-" SYMBOL SPACE "* #,##0.00_-;" "_-" SYMBOL SPACE "* #,##0.00-;" "_-" SYMBOL SPACE "* \"-\"?\?_-;" "_-@_-" ) + +/** Defines builtin currency formats 5...8 (with currency symbol), 37...40 + (blind currency symbol), and 41...44 (accounting), in the following format: + "symbol, number, [minus]". + @param SYMBOL Currency symbol. + @param SPACE Space character(s) between currency symbol and number. */ +#define NUMFMT_ALLCURRENCIES_SYMBOL_NUMBER_MINUS( SYMBOL, SPACE ) \ + NUMFMT_CURRENCY_SYMBOL_NUMBER_MINUS( 5, SYMBOL, SPACE, "" ), \ + NUMFMT_CURRENCY_SYMBOL_NUMBER_MINUS( 37, "", "", "" ), \ + NUMFMT_ACCOUNTING_SYMBOL_NUMBER_MINUS( 41, SYMBOL, SPACE ) + +/** Defines builtin currency formats INDEX...INDEX+3 in the following format: + "number, symbol, [minus]". + @param INDEX First number format index. + @param SYMBOL Currency symbol. + @param SPACE Space character(s) between number and currency symbol. + @param MODIF Leading modifier for each portion (e.g. "t" for Thai formats). */ +#define NUMFMT_CURRENCY_NUMBER_SYMBOL_MINUS( INDEX, SYMBOL, SPACE, MODIF ) \ + NUMFMT_STRING( INDEX + 0, MODIF "#,##0" SPACE SYMBOL "_-;" MODIF "#,##0" SPACE SYMBOL "-" ), \ + NUMFMT_STRING( INDEX + 1, MODIF "#,##0" SPACE SYMBOL "_-;" "[RED]" MODIF "#,##0" SPACE SYMBOL "-" ), \ + NUMFMT_STRING( INDEX + 2, MODIF "#,##0.00" SPACE SYMBOL "_-;" MODIF "#,##0.00" SPACE SYMBOL "-" ), \ + NUMFMT_STRING( INDEX + 3, MODIF "#,##0.00" SPACE SYMBOL "_-;" "[RED]" MODIF "#,##0.00" SPACE SYMBOL "-" ) + +/** Defines builtin accounting formats INDEX...INDEX+3 in the following format: + "number, symbol, [minus]". + @param INDEX First number format index. + @param SYMBOL Currency symbol. + @param BLINDS Blind currency symbol. + @param SPACE Space character(s) between number and currency symbol. */ +#define NUMFMT_ACCOUNTING_NUMBER_SYMBOL_MINUS( INDEX, SYMBOL, BLINDS, SPACE ) \ + NUMFMT_STRING( INDEX + 0, "_-* #,##0" SPACE BLINDS "_-;_-* #,##0" SPACE BLINDS "-;_-* \"-\"" SPACE BLINDS "_-;_-@_-" ), \ + NUMFMT_STRING( INDEX + 1, "_-* #,##0" SPACE SYMBOL "_-;_-* #,##0" SPACE SYMBOL "-;_-* \"-\"" SPACE SYMBOL "_-;_-@_-" ), \ + NUMFMT_STRING( INDEX + 2, "_-* #,##0.00" SPACE BLINDS "_-;_-* #,##0.00" SPACE BLINDS "-;_-* \"-\"?\?" SPACE BLINDS "_-;_-@_-" ), \ + NUMFMT_STRING( INDEX + 3, "_-* #,##0.00" SPACE SYMBOL "_-;_-* #,##0.00" SPACE SYMBOL "-;_-* \"-\"?\?" SPACE SYMBOL "_-;_-@_-" ) + +/** Defines builtin currency formats 5...8 (with currency symbol), 37...40 + (blind currency symbol), and 41...44 (accounting), in the following format: + "number, symbol, [minus]". + @param SYMBOL Currency symbol. + @param BLINDS Blind currency symbol. + @param SPACE Space character(s) between number and currency symbol. */ +#define NUMFMT_ALLCURRENCIES_NUMBER_SYMBOL_MINUS( SYMBOL, BLINDS, SPACE ) \ + NUMFMT_CURRENCY_NUMBER_SYMBOL_MINUS( 5, SYMBOL, SPACE, "" ), \ + NUMFMT_CURRENCY_NUMBER_SYMBOL_MINUS( 37, BLINDS, SPACE, "" ), \ + NUMFMT_ACCOUNTING_NUMBER_SYMBOL_MINUS( 41, SYMBOL, BLINDS, SPACE ) + +/** Defines builtin currency formats INDEX...INDEX+3 in the following format: + "[minus], symbol, number". + @param INDEX First number format index. + @param SYMBOL Currency symbol. + @param SPACE Space character(s) between currency symbol and number. + @param MODIF Leading modifier for each portion (e.g. "t" for Thai formats). */ +#define NUMFMT_CURRENCY_MINUS_SYMBOL_NUMBER( INDEX, SYMBOL, SPACE, MODIF ) \ + NUMFMT_STRING( INDEX + 0, MODIF SYMBOL SPACE "#,##0;" MODIF "-" SYMBOL SPACE "#,##0" ), \ + NUMFMT_STRING( INDEX + 1, MODIF SYMBOL SPACE "#,##0;" "[RED]" MODIF "-" SYMBOL SPACE "#,##0" ), \ + NUMFMT_STRING( INDEX + 2, MODIF SYMBOL SPACE "#,##0.00;" MODIF "-" SYMBOL SPACE "#,##0.00" ), \ + NUMFMT_STRING( INDEX + 3, MODIF SYMBOL SPACE "#,##0.00;" "[RED]" MODIF "-" SYMBOL SPACE "#,##0.00" ) + +/** Defines builtin accounting formats INDEX...INDEX+3 in the following order: + "[minus], symbol, number". + @param INDEX First number format index. + @param SYMBOL Currency symbol. + @param SPACE Space character(s) between currency symbol and number. */ +#define NUMFMT_ACCOUNTING_MINUS_SYMBOL_NUMBER( INDEX, SYMBOL, SPACE ) \ + NUMFMT_STRING( INDEX + 0, "_-" "* #,##0_-;" "-" "* #,##0_-;" "_-" "* \"-\"_-;" "_-@_-" ), \ + NUMFMT_STRING( INDEX + 1, "_-" SYMBOL SPACE "* #,##0_-;" "-" SYMBOL SPACE "* #,##0_-;" "_-" SYMBOL SPACE "* \"-\"_-;" "_-@_-" ), \ + NUMFMT_STRING( INDEX + 2, "_-" "* #,##0.00_-;" "-" "* #,##0.00_-;" "_-" "* \"-\"?\?_-;" "_-@_-" ), \ + NUMFMT_STRING( INDEX + 3, "_-" SYMBOL SPACE "* #,##0.00_-;" "-" SYMBOL SPACE "* #,##0.00_-;" "_-" SYMBOL SPACE "* \"-\"?\?_-;" "_-@_-" ) + +/** Defines builtin currency formats 5...8 (with currency symbol), 37...40 + (blind currency symbol), and 41...44 (accounting), in the following order: + "[minus], symbol, number". + @param SYMBOL Currency symbol. + @param SPACE Space character(s) between currency symbol and number. */ +#define NUMFMT_ALLCURRENCIES_MINUS_SYMBOL_NUMBER( SYMBOL, SPACE ) \ + NUMFMT_CURRENCY_MINUS_SYMBOL_NUMBER( 5, SYMBOL, SPACE, "" ), \ + NUMFMT_CURRENCY_MINUS_SYMBOL_NUMBER( 37, "", "", "" ), \ + NUMFMT_ACCOUNTING_MINUS_SYMBOL_NUMBER( 41, SYMBOL, SPACE ) + +/** Defines builtin currency formats INDEX...INDEX+3 in the following format: + "[minus], number, symbol". + @param INDEX First number format index. + @param SYMBOL Currency symbol. + @param SPACE Space character(s) between number and currency symbol. + @param MODIF Leading modifier for each portion (e.g. "t" for Thai formats). */ +#define NUMFMT_CURRENCY_MINUS_NUMBER_SYMBOL( INDEX, SYMBOL, SPACE, MODIF ) \ + NUMFMT_STRING( INDEX + 0, MODIF "#,##0" SPACE SYMBOL ";" MODIF "-#,##0" SPACE SYMBOL ), \ + NUMFMT_STRING( INDEX + 1, MODIF "#,##0" SPACE SYMBOL ";" "[RED]" MODIF "-#,##0" SPACE SYMBOL ), \ + NUMFMT_STRING( INDEX + 2, MODIF "#,##0.00" SPACE SYMBOL ";" MODIF "-#,##0.00" SPACE SYMBOL ), \ + NUMFMT_STRING( INDEX + 3, MODIF "#,##0.00" SPACE SYMBOL ";" "[RED]" MODIF "-#,##0.00" SPACE SYMBOL ) + +/** Defines builtin accounting formats INDEX...INDEX+3 in the following format: + "[minus], number, symbol". + @param INDEX First number format index. + @param SYMBOL Currency symbol. + @param BLINDS Blind currency symbol. + @param SPACE Space character(s) between number and currency symbol. */ +#define NUMFMT_ACCOUNTING_MINUS_NUMBER_SYMBOL( INDEX, SYMBOL, BLINDS, SPACE ) \ + NUMFMT_STRING( INDEX + 0, "_-* #,##0" SPACE BLINDS "_-;-* #,##0" SPACE BLINDS "_-;_-* \"-\"" SPACE BLINDS "_-;_-@_-" ), \ + NUMFMT_STRING( INDEX + 1, "_-* #,##0" SPACE SYMBOL "_-;-* #,##0" SPACE SYMBOL "_-;_-* \"-\"" SPACE SYMBOL "_-;_-@_-" ), \ + NUMFMT_STRING( INDEX + 2, "_-* #,##0.00" SPACE BLINDS "_-;-* #,##0.00" SPACE BLINDS "_-;_-* \"-\"?\?" SPACE BLINDS "_-;_-@_-" ), \ + NUMFMT_STRING( INDEX + 3, "_-* #,##0.00" SPACE SYMBOL "_-;-* #,##0.00" SPACE SYMBOL "_-;_-* \"-\"?\?" SPACE SYMBOL "_-;_-@_-" ) + +/** Defines builtin currency formats 5...8 (with currency symbol), 37...40 + (blind currency symbol), and 41...44 (accounting), in the following format: + "[minus], number, symbol". + @param SYMBOL Currency symbol. + @param BLINDS Blind currency symbol. + @param SPACE Space character(s) between number and currency symbol. */ +#define NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( SYMBOL, BLINDS, SPACE ) \ + NUMFMT_CURRENCY_MINUS_NUMBER_SYMBOL( 5, SYMBOL, SPACE, "" ), \ + NUMFMT_CURRENCY_MINUS_NUMBER_SYMBOL( 37, BLINDS, SPACE, "" ), \ + NUMFMT_ACCOUNTING_MINUS_NUMBER_SYMBOL( 41, SYMBOL, BLINDS, SPACE ) + +/** Defines builtin currency formats INDEX...INDEX+3 in the following format: + "[opening parenthesis], symbol, number, [closing parenthesis].". + @param INDEX First number format index. + @param SYMBOL Currency symbol. + @param SPACE Space character(s) between currency symbol and number. + @param MODIF Leading modifier for each portion (e.g. "t" for Thai formats). */ +#define NUMFMT_CURRENCY_OPEN_SYMBOL_NUMBER_CLOSE( INDEX, SYMBOL, SPACE, MODIF ) \ + NUMFMT_STRING( INDEX + 0, MODIF SYMBOL SPACE "#,##0_);" MODIF "(" SYMBOL SPACE "#,##0)" ), \ + NUMFMT_STRING( INDEX + 1, MODIF SYMBOL SPACE "#,##0_);" "[RED]" MODIF "(" SYMBOL SPACE "#,##0)" ), \ + NUMFMT_STRING( INDEX + 2, MODIF SYMBOL SPACE "#,##0.00_);" MODIF "(" SYMBOL SPACE "#,##0.00)" ), \ + NUMFMT_STRING( INDEX + 3, MODIF SYMBOL SPACE "#,##0.00_);" "[RED]" MODIF "(" SYMBOL SPACE "#,##0.00)" ) + +/** Defines builtin accounting formats INDEX...INDEX+3 in the following format: + "[opening parenthesis], symbol, number, [closing parenthesis].". + @param INDEX First number format index. + @param SYMBOL Currency symbol. + @param SPACE Space character(s) between currency symbol and number. */ +#define NUMFMT_ACCOUNTING_OPEN_SYMBOL_NUMBER_CLOSE( INDEX, SYMBOL, SPACE ) \ + NUMFMT_STRING( INDEX + 0, "_(" "* #,##0_);" "_(" "* (#,##0);" "_(" "* \"-\"_);" "_(@_)" ), \ + NUMFMT_STRING( INDEX + 1, "_(" SYMBOL SPACE "* #,##0_);" "_(" SYMBOL SPACE "* (#,##0);" "_(" SYMBOL SPACE "* \"-\"_);" "_(@_)" ), \ + NUMFMT_STRING( INDEX + 2, "_(" "* #,##0.00_);" "_(" "* (#,##0.00);" "_(" "* \"-\"?\?_);" "_(@_)" ), \ + NUMFMT_STRING( INDEX + 3, "_(" SYMBOL SPACE "* #,##0.00_);" "_(" SYMBOL SPACE "* (#,##0.00);" "_(" SYMBOL SPACE "* \"-\"?\?_);" "_(@_)" ) + +/** Defines builtin currency formats 5...8 (with currency symbol), 37...40 + (blind currency symbol), and 41...44 (accounting), in the following format: + "[opening parenthesis], symbol, number, [closing parenthesis].". + @param SYMBOL Currency symbol. + @param SPACE Space character(s) between currency symbol and number. */ +#define NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( SYMBOL, SPACE ) \ + NUMFMT_CURRENCY_OPEN_SYMBOL_NUMBER_CLOSE( 5, SYMBOL, SPACE, "" ), \ + NUMFMT_CURRENCY_OPEN_SYMBOL_NUMBER_CLOSE( 37, "", "", "" ), \ + NUMFMT_ACCOUNTING_OPEN_SYMBOL_NUMBER_CLOSE( 41, SYMBOL, SPACE ) + +/** Defines builtin currency formats INDEX...INDEX+3 in the following format: + "[opening parenthesis], number, symbol, [closing parenthesis].". + @param INDEX First number format index. + @param SYMBOL Currency symbol. + @param SPACE Space character(s) between number and currency symbol. + @param MODIF Leading modifier for each portion (e.g. "t" for Thai formats). */ +#define NUMFMT_CURRENCY_OPEN_NUMBER_SYMBOL_CLOSE( INDEX, SYMBOL, SPACE, MODIF ) \ + NUMFMT_STRING( INDEX + 0, MODIF "#,##0" SPACE SYMBOL "_);" MODIF "(#,##0" SPACE SYMBOL ")" ), \ + NUMFMT_STRING( INDEX + 1, MODIF "#,##0" SPACE SYMBOL "_);" "[RED]" MODIF "(#,##0" SPACE SYMBOL ")" ), \ + NUMFMT_STRING( INDEX + 2, MODIF "#,##0.00" SPACE SYMBOL "_);" MODIF "(#,##0.00" SPACE SYMBOL ")" ), \ + NUMFMT_STRING( INDEX + 3, MODIF "#,##0.00" SPACE SYMBOL "_);" "[RED]" MODIF "(#,##0.00" SPACE SYMBOL ")" ) + +/** Defines builtin accounting formats INDEX...INDEX+3 in the following format: + "[opening parenthesis], number, symbol, [closing parenthesis].". + @param INDEX First number format index. + @param SYMBOL Currency symbol. + @param BLINDS Blind currency symbol. + @param SPACE Space character(s) between number and currency symbol. */ +#define NUMFMT_ACCOUNTING_OPEN_NUMBER_SYMBOL_CLOSE( INDEX, SYMBOL, BLINDS, SPACE ) \ + NUMFMT_STRING( INDEX + 0, "_ * #,##0_)" SPACE BLINDS "_ ;_ * (#,##0)" SPACE BLINDS "_ ;_ * \"-\"_)" SPACE BLINDS "_ ;_ @_ " ), \ + NUMFMT_STRING( INDEX + 1, "_ * #,##0_)" SPACE SYMBOL "_ ;_ * (#,##0)" SPACE SYMBOL "_ ;_ * \"-\"_)" SPACE SYMBOL "_ ;_ @_ " ), \ + NUMFMT_STRING( INDEX + 2, "_ * #,##0.00_)" SPACE BLINDS "_ ;_ * (#,##0.00)" SPACE BLINDS "_ ;_ * \"-\"?\?_)" SPACE BLINDS "_ ;_ @_ " ), \ + NUMFMT_STRING( INDEX + 3, "_ * #,##0.00_)" SPACE SYMBOL "_ ;_ * (#,##0.00)" SPACE SYMBOL "_ ;_ * \"-\"?\?_)" SPACE SYMBOL "_ ;_ @_ " ) + +/** Defines builtin currency formats 5...8 (with currency symbol), 37...40 + (blind currency symbol), and 41...44 (accounting), in the following format: + "[opening parenthesis], number, symbol, [closing parenthesis].". + @param SYMBOL Currency symbol. + @param BLINDS Blind currency symbol. + @param SPACE Space character(s) between number and currency symbol. */ +#define NUMFMT_ALLCURRENCIES_OPEN_NUMBER_SYMBOL_CLOSE( SYMBOL, BLINDS, SPACE ) \ + NUMFMT_CURRENCY_OPEN_NUMBER_SYMBOL_CLOSE( 5, SYMBOL, SPACE, "" ), \ + NUMFMT_CURRENCY_OPEN_NUMBER_SYMBOL_CLOSE( 37, BLINDS, SPACE, "" ), \ + NUMFMT_ACCOUNTING_OPEN_NUMBER_SYMBOL_CLOSE( 41, SYMBOL, BLINDS, SPACE ) + +// currency unit characters +#define UTF8_BAHT "\340\270\277" +#define UTF8_COLON "\342\202\241" +#define UTF8_CURR_AR_AE "\330\257.\330\245." +#define UTF8_CURR_AR_BH "\330\257.\330\250." +#define UTF8_CURR_AR_DZ "\330\257.\330\254." +#define UTF8_CURR_AR_EG "\330\254.\331\205." +#define UTF8_CURR_AR_IQ "\330\257.\330\271." +#define UTF8_CURR_AR_JO "\330\257.\330\247." +#define UTF8_CURR_AR_KW "\330\257.\331\203." +#define UTF8_CURR_AR_LB "\331\204.\331\204." +#define UTF8_CURR_AR_LY "\330\257.\331\204." +#define UTF8_CURR_AR_MA "\330\257.\331\205." +#define UTF8_CURR_AR_OM "\330\261.\330\271." +#define UTF8_CURR_AR_QA "\330\261.\331\202." +#define UTF8_CURR_AR_SA "\330\261.\330\263." +#define UTF8_CURR_AR_SY "\331\204.\330\263." +#define UTF8_CURR_AR_TN "\330\257.\330\252." +#define UTF8_CURR_AR_YE "\330\261.\331\212." +#define UTF8_CURR_BN_IN "\340\246\237\340\246\276" +#define UTF8_CURR_FA_IR "\330\261\331\212\330\247\331\204" +#define UTF8_CURR_GU_IN "\340\252\260\340\253\202" +#define UTF8_CURR_HI_IN "\340\244\260\340\245\201" +#define UTF8_CURR_KN_IN "\340\262\260\340\263\202" +#define UTF8_CURR_ML_IN "\340\264\225" +#define UTF8_CURR_PA_IN "\340\250\260\340\251\201" +#define UTF8_CURR_TA_IN "\340\256\260\340\257\202" +#define UTF8_CURR_TE_IN "\340\260\260\340\261\202" +#define UTF8_DONG "\342\202\253" +#define UTF8_EURO "\342\202\254" +#define UTF8_POUND_GB "\302\243" +#define UTF8_RUFIYAA "\336\203" +#define UTF8_SHEQEL "\342\202\252" +#define UTF8_TUGRUG "\342\202\256" +#define UTF8_WON "\342\202\251" +#define UTF8_YEN_CN "\357\277\245" +#define UTF8_YEN_JP "\302\245" + +// Unicode characters for currency units +#define UTF8_CCARON_LC "\304\215" +#define UTF8_LSTROKE_LC "\305\202" +// Armenian +#define UTF8_HY_DA_LC "\325\244" +#define UTF8_HY_REH_LC "\326\200" +// Cyrillic +#define UTF8_CYR_G_LC "\320\263" +#define UTF8_CYR_L_LC "\320\273" +#define UTF8_CYR_M_LC "\320\274" +#define UTF8_CYR_N_LC "\320\275" +#define UTF8_CYR_O_LC "\320\276" +#define UTF8_CYR_R_LC "\321\200" +#define UTF8_CYR_S_LC "\321\201" +#define UTF8_CYR_W_LC "\320\262" + +// Japanese/Chinese date/time characters +#define UTF8_CJ_YEAR "\345\271\264" +#define UTF8_CJ_MON "\346\234\210" +#define UTF8_CJ_DAY "\346\227\245" +#define UTF8_CJ_HOUR "\346\231\202" +#define UTF8_CJ_MIN "\345\210\206" +#define UTF8_CJ_SEC "\347\247\222" + +// Chinese Simplified date/time characters +#define UTF8_CS_YEAR "\345\271\264" +#define UTF8_CS_MON "\346\234\210" +#define UTF8_CS_DAY "\346\227\245" +#define UTF8_CS_HOUR "\346\227\266" +#define UTF8_CS_MIN "\345\210\206" +#define UTF8_CS_SEC "\347\247\222" + +// Korean date/time characters +#define UTF8_KO_YEAR "\353\205\204" +#define UTF8_KO_MON "\354\233\224" +#define UTF8_KO_DAY "\354\235\274" +#define UTF8_KO_HOUR "\354\213\234" +#define UTF8_KO_MIN "\353\266\204" +#define UTF8_KO_SEC "\354\264\210" + +// ---------------------------------------------------------------------------- + +/** Default number format table. Last parent of all other tables, used for unknown locales. */ +static const BuiltinFormat spBuiltinFormats_BASE[] = +{ + // 0..13 numeric and currency formats + NUMFMT_PREDEF( 0, NUMBER_STANDARD ), // General + NUMFMT_PREDEF( 1, NUMBER_INT ), // 0 + NUMFMT_PREDEF( 2, NUMBER_DEC2 ), // 0.00 + NUMFMT_PREDEF( 3, NUMBER_1000INT ), // #,##0 + NUMFMT_PREDEF( 4, NUMBER_1000DEC2 ), // #,##0.00 + NUMFMT_PREDEF( 5, CURRENCY_1000INT ), // #,##0[symbol] + NUMFMT_PREDEF( 6, CURRENCY_1000INT_RED ), // #,##0[symbol];[RED]-#,##0[symbol] + NUMFMT_PREDEF( 7, CURRENCY_1000DEC2 ), // #,##0.00[symbol] + NUMFMT_PREDEF( 8, CURRENCY_1000DEC2_RED ), // #,##0.00[symbol];[RED]-#,##0.00[symbol] + NUMFMT_PREDEF( 9, PERCENT_INT ), // 0% + NUMFMT_PREDEF( 10, PERCENT_DEC2 ), // 0.00% + NUMFMT_PREDEF( 11, SCIENTIFIC_000E00 ), // 0.00E+00 + NUMFMT_PREDEF( 12, FRACTION_1 ), // # ?/? + NUMFMT_PREDEF( 13, FRACTION_2 ), // # ??/?? + + // 14...22 date and time formats + NUMFMT_PREDEF( 14, DATE_SYS_DDMMYYYY ), + NUMFMT_PREDEF( 15, DATE_SYS_DMMMYY ), + NUMFMT_PREDEF( 16, DATE_SYS_DDMMM ), + NUMFMT_PREDEF( 17, DATE_SYS_MMYY ), + NUMFMT_PREDEF( 18, TIME_HHMMAMPM ), + NUMFMT_PREDEF( 19, TIME_HHMMSSAMPM ), + NUMFMT_PREDEF( 20, TIME_HHMM ), + NUMFMT_PREDEF( 21, TIME_HHMMSS ), + NUMFMT_PREDEF( 22, DATETIME_SYSTEM_SHORT_HHMM ), + + // 23...36 international formats + NUMFMT_REUSE( 23, 0 ), + NUMFMT_REUSE( 24, 0 ), + NUMFMT_REUSE( 25, 0 ), + NUMFMT_REUSE( 26, 0 ), + NUMFMT_REUSE( 27, 14 ), + NUMFMT_REUSE( 28, 14 ), + NUMFMT_REUSE( 29, 14 ), + NUMFMT_REUSE( 30, 14 ), + NUMFMT_REUSE( 31, 14 ), + NUMFMT_REUSE( 32, 21 ), + NUMFMT_REUSE( 33, 21 ), + NUMFMT_REUSE( 34, 21 ), + NUMFMT_REUSE( 35, 21 ), + NUMFMT_REUSE( 36, 14 ), + + // 37...44 accounting formats, defaults without currency symbol here + NUMFMT_CURRENCY_MINUS_SYMBOL_NUMBER( 37, "", "", "" ), + NUMFMT_ACCOUNTING_MINUS_SYMBOL_NUMBER( 41, "", "" ), + + // 45...49 more special formats + NUMFMT_STRING( 45, "mm:ss" ), + NUMFMT_STRING( 46, "[h]:mm:ss" ), + NUMFMT_STRING( 47, "mm:ss.0" ), + NUMFMT_STRING( 48, "##0.0E+0" ), + NUMFMT_PREDEF( 49, TEXT ), + + // 50...81 international formats + NUMFMT_REUSE( 50, 14 ), + NUMFMT_REUSE( 51, 14 ), + NUMFMT_REUSE( 52, 14 ), + NUMFMT_REUSE( 53, 14 ), + NUMFMT_REUSE( 54, 14 ), + NUMFMT_REUSE( 55, 14 ), + NUMFMT_REUSE( 56, 14 ), + NUMFMT_REUSE( 57, 14 ), + NUMFMT_REUSE( 58, 14 ), + NUMFMT_REUSE( 59, 1 ), + NUMFMT_REUSE( 60, 2 ), + NUMFMT_REUSE( 61, 3 ), + NUMFMT_REUSE( 62, 4 ), + NUMFMT_REUSE( 63, 5 ), + NUMFMT_REUSE( 64, 6 ), + NUMFMT_REUSE( 65, 7 ), + NUMFMT_REUSE( 66, 8 ), + NUMFMT_REUSE( 67, 9 ), + NUMFMT_REUSE( 68, 10 ), + NUMFMT_REUSE( 69, 12 ), + NUMFMT_REUSE( 70, 13 ), + NUMFMT_REUSE( 71, 14 ), + NUMFMT_REUSE( 72, 14 ), + NUMFMT_REUSE( 73, 15 ), + NUMFMT_REUSE( 74, 16 ), + NUMFMT_REUSE( 75, 17 ), + NUMFMT_REUSE( 76, 20 ), + NUMFMT_REUSE( 77, 21 ), + NUMFMT_REUSE( 78, 22 ), + NUMFMT_REUSE( 79, 45 ), + NUMFMT_REUSE( 80, 46 ), + NUMFMT_REUSE( 81, 47 ), + + // 82...163 not used, must not occur in a file (Excel may crash) + + NUMFMT_ENDTABLE() +}; + +// ---------------------------------------------------------------------------- + +/** Arabic, U.A.E. */ +static const BuiltinFormat spBuiltinFormats_ar_AE[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_NUMBER_MINUS( "\"" UTF8_CURR_AR_AE "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Arabic, Bahrain. */ +static const BuiltinFormat spBuiltinFormats_ar_BH[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_NUMBER_MINUS( "\"" UTF8_CURR_AR_BH "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Arabic, Algeria. */ +static const BuiltinFormat spBuiltinFormats_ar_DZ[] = +{ + NUMFMT_ALLDATETIMES( "DD-MM-YYYY", "DD", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_SYMBOL_NUMBER_MINUS( "\"" UTF8_CURR_AR_DZ "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Arabic, Egypt. */ +static const BuiltinFormat spBuiltinFormats_ar_EG[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_NUMBER_MINUS( "\"" UTF8_CURR_AR_EG "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Arabic, Iraq. */ +static const BuiltinFormat spBuiltinFormats_ar_IQ[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_NUMBER_MINUS( "\"" UTF8_CURR_AR_IQ "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Arabic, Jordan. */ +static const BuiltinFormat spBuiltinFormats_ar_JO[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_NUMBER_MINUS( "\"" UTF8_CURR_AR_JO "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Arabic, Kuwait. */ +static const BuiltinFormat spBuiltinFormats_ar_KW[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_NUMBER_MINUS( "\"" UTF8_CURR_AR_KW "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Arabic, Lebanon. */ +static const BuiltinFormat spBuiltinFormats_ar_LB[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_NUMBER_MINUS( "\"" UTF8_CURR_AR_LB "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Arabic, Libya. */ +static const BuiltinFormat spBuiltinFormats_ar_LY[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_NUMBER_MINUS( "\"" UTF8_CURR_AR_LY "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Arabic, Morocco. */ +static const BuiltinFormat spBuiltinFormats_ar_MA[] = +{ + NUMFMT_ALLDATETIMES( "DD-MM-YYYY", "DD", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_SYMBOL_NUMBER_MINUS( "\"" UTF8_CURR_AR_MA "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Arabic, Oman. */ +static const BuiltinFormat spBuiltinFormats_ar_OM[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_NUMBER_MINUS( "\"" UTF8_CURR_AR_OM "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Arabic, Qatar. */ +static const BuiltinFormat spBuiltinFormats_ar_QA[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_NUMBER_MINUS( "\"" UTF8_CURR_AR_QA "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Arabic, Saudi Arabia. */ +static const BuiltinFormat spBuiltinFormats_ar_SA[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_NUMBER_MINUS( "\"" UTF8_CURR_AR_SA "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Arabic, Syria. */ +static const BuiltinFormat spBuiltinFormats_ar_SY[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_NUMBER_MINUS( "\"" UTF8_CURR_AR_SY "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Arabic, Tunisia. */ +static const BuiltinFormat spBuiltinFormats_ar_TN[] = +{ + NUMFMT_ALLDATETIMES( "DD-MM-YYYY", "DD", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_SYMBOL_NUMBER_MINUS( "\"" UTF8_CURR_AR_TN "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Arabic, Yemen. */ +static const BuiltinFormat spBuiltinFormats_ar_YE[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_NUMBER_MINUS( "\"" UTF8_CURR_AR_YE "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Belarusian, Belarus. */ +static const BuiltinFormat spBuiltinFormats_be_BY[] = +{ + // space character is group separator, literal spaces must be quoted + NUMFMT_ALLDATETIMES( "DD.MM.YYYY", "DD", ".", "MMM", ".", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( "\"" UTF8_CYR_R_LC ".\"", "_" UTF8_CYR_R_LC "_.", "\\ " ), + NUMFMT_ENDTABLE() +}; + +/** Bulgarian, Bulgaria. */ +static const BuiltinFormat spBuiltinFormats_bg_BG[] = +{ + // space character is group separator, literal spaces must be quoted + NUMFMT_ALLDATETIMES( "DD.M.YYYY", "DD", ".", "MMM", ".", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( "\"" UTF8_CYR_L_LC UTF8_CYR_W_LC "\"", "_" UTF8_CYR_L_LC "_" UTF8_CYR_W_LC, "\\ " ), + NUMFMT_ENDTABLE() +}; + +/** Bengali, India. */ +static const BuiltinFormat spBuiltinFormats_bn_IN[] = +{ + NUMFMT_ALLDATETIMES( "DD-MM-YY", "DD", "-", "MMM", "-", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( "\"" UTF8_CURR_BN_IN "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Czech, Czech Republic. */ +static const BuiltinFormat spBuiltinFormats_cs_CZ[] = +{ + // space character is group separator, literal spaces must be quoted + NUMFMT_ALLDATETIMES( "D.M.YYYY", "D", ".", "MMM", ".", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( "\"K" UTF8_CCARON_LC "\"", "_K_" UTF8_CCARON_LC, "\\ " ), + NUMFMT_ENDTABLE() +}; + +/** Danish, Denmark. */ +static const BuiltinFormat spBuiltinFormats_da_DK[] = +{ + NUMFMT_ALLDATETIMES( "DD-MM-YYYY", "DD", "-", "MMM", "-", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( "\"kr\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** German, Austria. */ +static const BuiltinFormat spBuiltinFormats_de_AT[] = +{ + NUMFMT_ALLDATETIMES( "DD.MM.YYYY", "DD", ".", "MMM", ".", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_MINUS_SYMBOL_NUMBER( UTF8_EURO, " " ), + NUMFMT_ENDTABLE() +}; + +/** German, Switzerland. */ +static const BuiltinFormat spBuiltinFormats_de_CH[] = +{ + NUMFMT_ALLDATETIMES( "DD.MM.YYYY", "DD", ". ", "MMM", " ", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( "\"SFr.\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** German, Germany. */ +static const BuiltinFormat spBuiltinFormats_de_DE[] = +{ + NUMFMT_ALLDATETIMES( "DD.MM.YYYY", "DD", ". ", "MMM", " ", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( UTF8_EURO, "_" UTF8_EURO, " " ), + NUMFMT_ENDTABLE() +}; + +/** German, Liechtenstein. */ +static const BuiltinFormat spBuiltinFormats_de_LI[] = +{ + NUMFMT_ALLDATETIMES( "DD.MM.YYYY", "DD", ". ", "MMM", " ", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( "\"CHF\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** German, Luxembourg. */ +static const BuiltinFormat spBuiltinFormats_de_LU[] = +{ + NUMFMT_ALLDATETIMES( "DD.MM.YYYY", "DD", ".", "MMM", ".", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( UTF8_EURO, "_" UTF8_EURO, " " ), + NUMFMT_ENDTABLE() +}; + +/** Divehi, Maldives. */ +static const BuiltinFormat spBuiltinFormats_div_MV[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YY", "DD", "-", "MMM", "-", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_NUMBER_SYMBOL_MINUS( "\"" UTF8_RUFIYAA ".\"", "_" UTF8_RUFIYAA "_.", " " ), + NUMFMT_ENDTABLE() +}; + +/** Greek, Greece. */ +static const BuiltinFormat spBuiltinFormats_el_GR[] = +{ + NUMFMT_ALLDATETIMES( "D/M/YYYY", "D", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( UTF8_EURO, "_" UTF8_EURO, " " ), + NUMFMT_ENDTABLE() +}; + +/** English, Australia. */ +static const BuiltinFormat spBuiltinFormats_en_AU[] = +{ + NUMFMT_ALLDATETIMES( "D/MM/YYYY", "D", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_SYMBOL_NUMBER( "$", "" ), + NUMFMT_ENDTABLE() +}; + +/** English, Belize. */ +static const BuiltinFormat spBuiltinFormats_en_BZ[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "\"BZ$\"", "" ), + NUMFMT_ENDTABLE() +}; + +/** English, Canada. */ +static const BuiltinFormat spBuiltinFormats_en_CA[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_SYMBOL_NUMBER( "$", "" ), + NUMFMT_ENDTABLE() +}; + +/** English, Caribbean. */ +static const BuiltinFormat spBuiltinFormats_en_CB[] = +{ + NUMFMT_ALLDATETIMES( "MM/DD/YYYY", "DD", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_SYMBOL_NUMBER( "$", "" ), + NUMFMT_ENDTABLE() +}; + +/** English, United Kingdom. */ +static const BuiltinFormat spBuiltinFormats_en_GB[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_MINUS_SYMBOL_NUMBER( UTF8_POUND_GB, "" ), + NUMFMT_ENDTABLE() +}; + +/** English, Ireland. */ +static const BuiltinFormat spBuiltinFormats_en_IE[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_MINUS_SYMBOL_NUMBER( UTF8_EURO, "" ), + NUMFMT_ENDTABLE() +}; + +/** English, Jamaica. */ +static const BuiltinFormat spBuiltinFormats_en_JM[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_MINUS_SYMBOL_NUMBER( "\"J$\"", "" ), + NUMFMT_ENDTABLE() +}; + +/** English, New Zealand. */ +static const BuiltinFormat spBuiltinFormats_en_NZ[] = +{ + NUMFMT_ALLDATETIMES( "D/MM/YYYY", "D", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_SYMBOL_NUMBER( "$", "" ), + NUMFMT_ENDTABLE() +}; + +/** English, Philippines. */ +static const BuiltinFormat spBuiltinFormats_en_PH[] = +{ + NUMFMT_ALLDATETIMES( "M/D/YYYY", "D", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "\"Php\"", "" ), + NUMFMT_ENDTABLE() +}; + +/** English, Trinidad and Tobago. */ +static const BuiltinFormat spBuiltinFormats_en_TT[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "\"TT$\"", "" ), + NUMFMT_ENDTABLE() +}; + +/** English, USA. */ +static const BuiltinFormat spBuiltinFormats_en_US[] = +{ + NUMFMT_ALLDATETIMES( "M/D/YYYY", "D", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "$", "" ), + NUMFMT_ENDTABLE() +}; + +/** English, South Africa. */ +static const BuiltinFormat spBuiltinFormats_en_ZA[] = +{ + NUMFMT_ALLDATETIMES( "YYYY/MM/DD", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( "\\R", " " ), + NUMFMT_ENDTABLE() +}; + +/** English, Zimbabwe. */ +static const BuiltinFormat spBuiltinFormats_en_ZW[] = +{ + NUMFMT_ALLDATETIMES( "M/D/YYYY", "D", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "\"Z$\"", "" ), + NUMFMT_ENDTABLE() +}; + +/** Spanish, Argentina. */ +static const BuiltinFormat spBuiltinFormats_es_AR[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( "$", " " ), + NUMFMT_ENDTABLE() +}; + +/** Spanish, Bolivia. */ +static const BuiltinFormat spBuiltinFormats_es_BO[] = +{ + // slashes must be quoted to prevent conversion to minus + NUMFMT_ALLDATETIMES( "DD\\/MM\\/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "\"$b\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Spanish, Chile. */ +static const BuiltinFormat spBuiltinFormats_es_CL[] = +{ + NUMFMT_ALLDATETIMES( "DD-MM-YYYY", "DD", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_SYMBOL_NUMBER( "$", " " ), + NUMFMT_ENDTABLE() +}; + +/** Spanish, Colombia. */ +static const BuiltinFormat spBuiltinFormats_es_CO[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "$", " " ), + NUMFMT_ENDTABLE() +}; + +/** Spanish, Costa Rica. */ +static const BuiltinFormat spBuiltinFormats_es_CR[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( UTF8_COLON, "" ), + NUMFMT_ENDTABLE() +}; + +/** Spanish, Dominican Republic. */ +static const BuiltinFormat spBuiltinFormats_es_DO[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "\"RD$\"", "" ), + NUMFMT_ENDTABLE() +}; + +/** Spanish, Ecuador. */ +static const BuiltinFormat spBuiltinFormats_es_EC[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "$", " " ), + NUMFMT_ENDTABLE() +}; + +/** Spanish, Spain. */ +static const BuiltinFormat spBuiltinFormats_es_ES[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( UTF8_EURO, "_" UTF8_EURO, " " ), + NUMFMT_ENDTABLE() +}; + +/** Spanish, Guatemala. */ +static const BuiltinFormat spBuiltinFormats_es_GT[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "\\Q", "" ), + NUMFMT_ENDTABLE() +}; + +/** Spanish, Honduras. */ +static const BuiltinFormat spBuiltinFormats_es_HN[] = +{ + // slashes must be quoted to prevent conversion to minus + NUMFMT_ALLDATETIMES( "DD\\/MM\\/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( "\"L.\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Spanish, Mexico. */ +static const BuiltinFormat spBuiltinFormats_es_MX[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_MINUS_SYMBOL_NUMBER( "$", "" ), + NUMFMT_ENDTABLE() +}; + +/** Spanish, Nicaragua. */ +static const BuiltinFormat spBuiltinFormats_es_NI[] = +{ + // slashes must be quoted to prevent conversion to minus + NUMFMT_ALLDATETIMES( "DD\\/MM\\/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "\"C$\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Spanish, Panama. */ +static const BuiltinFormat spBuiltinFormats_es_PA[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "\"B/.\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Spanish, Peru. */ +static const BuiltinFormat spBuiltinFormats_es_PE[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( "\"S/.\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Spanish, Puerto Rico. */ +static const BuiltinFormat spBuiltinFormats_es_PR[] = +{ + // slashes must be quoted to prevent conversion to minus + NUMFMT_ALLDATETIMES( "DD\\/MM\\/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "$", " " ), + NUMFMT_ENDTABLE() +}; + +/** Spanish, Paraguay. */ +static const BuiltinFormat spBuiltinFormats_es_PY[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "\"Gs\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Spanish, El Salvador. */ +static const BuiltinFormat spBuiltinFormats_es_SV[] = +{ + // slashes must be quoted to prevent conversion to minus + NUMFMT_ALLDATETIMES( "DD\\/MM\\/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "$", "" ), + NUMFMT_ENDTABLE() +}; + +/** Spanish, Uruguay. */ +static const BuiltinFormat spBuiltinFormats_es_UY[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "\"$U\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Spanish, Venezuela. */ +static const BuiltinFormat spBuiltinFormats_es_VE[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( "Bs", " " ), + NUMFMT_ENDTABLE() +}; + +/** Estonian, Estonia. */ +static const BuiltinFormat spBuiltinFormats_et_EE[] = +{ + // space character is group separator, literal spaces must be quoted + NUMFMT_ALLDATETIMES( "D.MM.YYYY", "D", ".", "MMM", ".", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( "\"kr\"", "_k_r", "\\ " ), + NUMFMT_ENDTABLE() +}; + +/** Farsi, Iran. */ +static const BuiltinFormat spBuiltinFormats_fa_IR[] = +{ + NUMFMT_ALLDATETIMES( "YYYY/MM/DD", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_NUMBER_MINUS( "\"" UTF8_CURR_FA_IR "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Finnish, Finland. */ +static const BuiltinFormat spBuiltinFormats_fi_FI[] = +{ + // space character is group separator, literal spaces must be quoted + NUMFMT_STRING( 9, "0\\ %" ), + NUMFMT_STRING( 10, "0.00\\ %" ), + NUMFMT_ALLDATETIMES( "D.M.YYYY", "D", ".", "MMM", ".", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( UTF8_EURO, "_" UTF8_EURO, "\\ " ), + NUMFMT_ENDTABLE() +}; + +/** Faroese, Faroe Islands. */ +static const BuiltinFormat spBuiltinFormats_fo_FO[] = +{ + NUMFMT_ALLDATETIMES( "DD-MM-YYYY", "DD", "-", "MMM", "-", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( "\"kr\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** French, Belgium. */ +static const BuiltinFormat spBuiltinFormats_fr_BE[] = +{ + NUMFMT_ALLDATETIMES( "D/MM/YYYY", "D", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( UTF8_EURO, "_" UTF8_EURO, " " ), + NUMFMT_ENDTABLE() +}; + +/** French, Canada. */ +static const BuiltinFormat spBuiltinFormats_fr_CA[] = +{ + // space character is group separator, literal spaces must be quoted + NUMFMT_ALLDATETIMES( "YYYY-MM-DD", "DD", "-", "MMM", "-", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_OPEN_NUMBER_SYMBOL_CLOSE( "$", "_$", "\\ " ), + NUMFMT_ENDTABLE() +}; + +/** French, Switzerland. */ +static const BuiltinFormat spBuiltinFormats_fr_CH[] = +{ + NUMFMT_ALLDATETIMES( "DD.MM.YYYY", "DD", ".", "MMM", ".", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( "\"SFr.\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** French, France. */ +static const BuiltinFormat spBuiltinFormats_fr_FR[] = +{ + // space character is group separator, literal spaces must be quoted + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( UTF8_EURO, "_" UTF8_EURO, "\\ " ), + NUMFMT_ENDTABLE() +}; + +/** French, Luxembourg. */ +static const BuiltinFormat spBuiltinFormats_fr_LU[] = +{ + // space character is group separator, literal spaces must be quoted + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( UTF8_EURO, "_" UTF8_EURO, "\\ " ), + NUMFMT_ENDTABLE() +}; + +/** French, Monaco. */ +static const BuiltinFormat spBuiltinFormats_fr_MC[] = +{ + // space character is group separator, literal spaces must be quoted + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( UTF8_EURO, "_" UTF8_EURO, "\\ " ), + NUMFMT_ENDTABLE() +}; + +/** Galizian, Spain. */ +static const BuiltinFormat spBuiltinFormats_gl_ES[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YY", "DD", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_SYMBOL_NUMBER( UTF8_EURO, " " ), + NUMFMT_ENDTABLE() +}; + +/** Gujarati, India. */ +static const BuiltinFormat spBuiltinFormats_gu_IN[] = +{ + NUMFMT_ALLDATETIMES( "DD-MM-YY", "DD", "-", "MMM", "-", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( "\"" UTF8_CURR_GU_IN "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Hebrew, Israel. */ +static const BuiltinFormat spBuiltinFormats_he_IL[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( UTF8_SHEQEL, " " ), + NUMFMT_ENDTABLE() +}; + +/** Hindi, India. */ +static const BuiltinFormat spBuiltinFormats_hi_IN[] = +{ + NUMFMT_ALLDATETIMES( "DD-MM-YYYY", "DD", "-", "MMM", "-", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( "\"" UTF8_CURR_HI_IN "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Croatian, Bosnia and Herzegowina. */ +static const BuiltinFormat spBuiltinFormats_hr_BA[] = +{ + NUMFMT_ALLDATETIMES( "D.M.YYYY", "D", ".", "MMM", ".", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( "\"KM\"", "_K_M", " " ), + NUMFMT_ENDTABLE() +}; + +/** Croatian, Croatia. */ +static const BuiltinFormat spBuiltinFormats_hr_HR[] = +{ + NUMFMT_ALLDATETIMES( "D.M.YYYY", "D", ".", "MMM", ".", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( "\"kn\"", "_k_n", " " ), + NUMFMT_ENDTABLE() +}; + +/** Hungarian, Hungary. */ +static const BuiltinFormat spBuiltinFormats_hu_HU[] = +{ + // space character is group separator, literal spaces must be quoted + // MMM is rendered differently in Calc and Excel (see #i41488#) + NUMFMT_ALLDATETIMES( "YYYY.MM.DD", "DD", ".", "MMM", ".", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( "\"Ft\"", "_F_t", "\\ " ), + NUMFMT_ENDTABLE() +}; + +/** Armenian, Armenia. */ +static const BuiltinFormat spBuiltinFormats_hy_AM[] = +{ + NUMFMT_ALLDATETIMES( "DD.MM.YYYY", "DD", ".", "MMM", ".", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( "\"" UTF8_HY_DA_LC UTF8_HY_REH_LC ".\"", "_" UTF8_HY_DA_LC "_" UTF8_HY_REH_LC "_.", " " ), + NUMFMT_ENDTABLE() +}; + +/** Indonesian, Indonesia. */ +static const BuiltinFormat spBuiltinFormats_id_ID[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "\"Rp\"", "" ), + NUMFMT_ENDTABLE() +}; + +/** Icelandic, Iceland. */ +static const BuiltinFormat spBuiltinFormats_is_IS[] = +{ + NUMFMT_ALLDATETIMES( "D.M.YYYY", "D", ".", "MMM", ".", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( "\"kr.\"", "_k_r_.", " " ), + NUMFMT_ENDTABLE() +}; + +/** Italian, Switzerland. */ +static const BuiltinFormat spBuiltinFormats_it_CH[] = +{ + NUMFMT_ALLDATETIMES( "DD.MM.YYYY", "DD", ".", "MMM", ".", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( "\"SFr.\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Italian, Italy. */ +static const BuiltinFormat spBuiltinFormats_it_IT[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_SYMBOL_NUMBER( UTF8_EURO, " " ), + NUMFMT_ENDTABLE() +}; + +/** Georgian, Georgia. */ +static const BuiltinFormat spBuiltinFormats_ka_GE[] = +{ + // space character is group separator, literal spaces must be quoted + NUMFMT_ALLDATETIMES( "DD.MM.YYYY", "DD", ".", "MMM", ".", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( "\"Lari\"", "_L_a_r_i", "\\ " ), + NUMFMT_ENDTABLE() +}; + +/** Kazakh, Kazakhstan. */ +static const BuiltinFormat spBuiltinFormats_kk_KZ[] = +{ + // space character is group separator, literal spaces must be quoted + NUMFMT_ALLDATETIMES( "DD.MM.YYYY", "DD", ".", "MMM", ".", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_SYMBOL_NUMBER( "\\T", "" ), + NUMFMT_ENDTABLE() +}; + +/** Kannada, India. */ +static const BuiltinFormat spBuiltinFormats_kn_IN[] = +{ + NUMFMT_ALLDATETIMES( "DD-MM-YY", "DD", "-", "MMM", "-", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( "\"" UTF8_CURR_KN_IN "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Kyrgyz, Kyrgyzstan. */ +static const BuiltinFormat spBuiltinFormats_ky_KG[] = +{ + // space character is group separator, literal spaces must be quoted + NUMFMT_ALLDATETIMES( "DD.MM.YY", "DD", ".", "MMM", ".", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( "\"" UTF8_CYR_S_LC UTF8_CYR_O_LC UTF8_CYR_M_LC "\"", "_" UTF8_CYR_S_LC "_" UTF8_CYR_O_LC "_" UTF8_CYR_M_LC, "\\ " ), + NUMFMT_ENDTABLE() +}; + +/** Lithuanian, Lithuania. */ +static const BuiltinFormat spBuiltinFormats_lt_LT[] = +{ + NUMFMT_ALLDATETIMES( "YYYY.MM.DD", "DD", ".", "MMM", ".", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( "\"Lt\"", "_L_t", " " ), + NUMFMT_ENDTABLE() +}; + +/** Latvian, Latvia. */ +static const BuiltinFormat spBuiltinFormats_lv_LV[] = +{ + // space character is group separator, literal spaces must be quoted + NUMFMT_ALLDATETIMES( "YYYY.MM.DD", "DD", ".", "MMM", ".", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_SYMBOL_NUMBER( "\"Ls\"", "\\ " ), + NUMFMT_ENDTABLE() +}; + +/** Malayalam, India. */ +static const BuiltinFormat spBuiltinFormats_ml_IN[] = +{ + NUMFMT_ALLDATETIMES( "DD-MM-YY", "DD", "-", "MMM", "-", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( "\"" UTF8_CURR_ML_IN "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Mongolian, Mongolia. */ +static const BuiltinFormat spBuiltinFormats_mn_MN[] = +{ + NUMFMT_ALLDATETIMES( "YY.MM.DD", "DD", ".", "MMM", ".", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( UTF8_TUGRUG, "_" UTF8_TUGRUG, "" ), + NUMFMT_ENDTABLE() +}; + +/** Malay, Brunei Darussalam. */ +static const BuiltinFormat spBuiltinFormats_ms_BN[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "$", "" ), + NUMFMT_ENDTABLE() +}; + +/** Malay, Malaysia. */ +static const BuiltinFormat spBuiltinFormats_ms_MY[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "\\R", "" ), + NUMFMT_ENDTABLE() +}; + +/** Maltese, Malta. */ +static const BuiltinFormat spBuiltinFormats_mt_MT[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_MINUS_SYMBOL_NUMBER( "\"Lm\"", "" ), + NUMFMT_ENDTABLE() +}; + +/** Dutch, Belgium. */ +static const BuiltinFormat spBuiltinFormats_nl_BE[] = +{ + // slashes must be quoted to prevent conversion to minus + NUMFMT_ALLDATETIMES( "D\\/MM\\/YYYY", "D", "\\/", "MMM", "\\/", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( UTF8_EURO, "_" UTF8_EURO, " " ), + NUMFMT_ENDTABLE() +}; + +/** Dutch, Netherlands. */ +static const BuiltinFormat spBuiltinFormats_nl_NL[] = +{ + NUMFMT_ALLDATETIMES( "D-M-YYYY", "D", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_SYMBOL_NUMBER_MINUS( UTF8_EURO, " " ), + NUMFMT_ENDTABLE() +}; + +/** Norwegian (Bokmal and Nynorsk), Norway. */ +static const BuiltinFormat spBuiltinFormats_no_NO[] = +{ + // space character is group separator, literal spaces must be quoted + NUMFMT_ALLDATETIMES( "DD.MM.YYYY", "DD", ".", "MMM", ".", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( "\"kr\"", "\\ " ), + NUMFMT_ENDTABLE() +}; + +/** Punjabi, India. */ +static const BuiltinFormat spBuiltinFormats_pa_IN[] = +{ + NUMFMT_ALLDATETIMES( "DD-MM-YY", "DD", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( "\"" UTF8_CURR_PA_IN "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Polish, Poland. */ +static const BuiltinFormat spBuiltinFormats_pl_PL[] = +{ + // space character is group separator, literal spaces must be quoted + // MMM is rendered differently in Calc and Excel (see #i72300#) + NUMFMT_ALLDATETIMES( "YYYY-MM-DD", "DD", "-", "MMM", "-", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( "\"z" UTF8_LSTROKE_LC "\"", "_z_" UTF8_LSTROKE_LC, "\\ " ), + NUMFMT_ENDTABLE() +}; + +/** Portugese, Brazil. */ +static const BuiltinFormat spBuiltinFormats_pt_BR[] = +{ + NUMFMT_ALLDATETIMES( "D/M/YYYY", "D", "/", "MMM", "/", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "\"R$\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Portugese, Portugal. */ +static const BuiltinFormat spBuiltinFormats_pt_PT[] = +{ + NUMFMT_ALLDATETIMES( "DD-MM-YYYY", "DD", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( UTF8_EURO, "_" UTF8_EURO, " " ), + NUMFMT_ENDTABLE() +}; + +/** Romanian, Romania. */ +static const BuiltinFormat spBuiltinFormats_ro_RO[] = +{ + // space character is group separator, literal spaces must be quoted (but see #i75367#) + NUMFMT_ALLDATETIMES( "DD.MM.YYYY", "DD", ".", "MMM", ".", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( "\"lei\"", "_l_e_i", "\\ " ), + NUMFMT_ENDTABLE() +}; + +/** Russian, Russian Federation. */ +static const BuiltinFormat spBuiltinFormats_ru_RU[] = +{ + // space character is group separator, literal spaces must be quoted + NUMFMT_ALLDATETIMES( "DD.MM.YYYY", "DD", ".", "MMM", ".", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( "\"" UTF8_CYR_R_LC ".\"", "_" UTF8_CYR_R_LC "_.", "" ), + NUMFMT_ENDTABLE() +}; + +/** Slovak, Slovakia. */ +static const BuiltinFormat spBuiltinFormats_sk_SK[] = +{ + // space character is group separator, literal spaces must be quoted + NUMFMT_ALLDATETIMES( "D.M.YYYY", "D", ".", "MMM", ".", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( "\"Sk\"", "_S_k", "\\ " ), + NUMFMT_ENDTABLE() +}; + +/** Slovenian, Slovenia. */ +static const BuiltinFormat spBuiltinFormats_sl_SI[] = +{ + NUMFMT_ALLDATETIMES( "D.M.YYYY", "D", ".", "MMM", ".", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( "\"SIT\"", "_S_I_T", " " ), + NUMFMT_ENDTABLE() +}; + +/** Swedish, Finland. */ +static const BuiltinFormat spBuiltinFormats_sv_FI[] = +{ + // space character is group separator, literal spaces must be quoted + NUMFMT_STRING( 9, "0\\ %" ), + NUMFMT_STRING( 10, "0.00\\ %" ), + NUMFMT_ALLDATETIMES( "D.M.YYYY", "D", ".", "MMM", ".", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( UTF8_EURO, "_" UTF8_EURO, "\\ " ), + NUMFMT_ENDTABLE() +}; + +/** Swedish, Sweden. */ +static const BuiltinFormat spBuiltinFormats_sv_SE[] = +{ + // space character is group separator, literal spaces must be quoted + NUMFMT_ALLDATETIMES( "YYYY-MM-DD", "DD", "-", "MMM", "-", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( "\"kr\"", "_k_r", "\\ " ), + NUMFMT_ENDTABLE() +}; + +/** Swahili, Tanzania. */ +static const BuiltinFormat spBuiltinFormats_sw_TZ[] = +{ + NUMFMT_ALLDATETIMES( "M/D/YYYY", "D", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "\\S", "" ), + NUMFMT_ENDTABLE() +}; + +/** Tamil, India. */ +static const BuiltinFormat spBuiltinFormats_ta_IN[] = +{ + NUMFMT_ALLDATETIMES( "DD-MM-YYYY", "DD", "-", "MMM", "-", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( "\"" UTF8_CURR_TA_IN "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Telugu, India. */ +static const BuiltinFormat spBuiltinFormats_te_IN[] = +{ + NUMFMT_ALLDATETIMES( "DD-MM-YY", "DD", "-", "MMM", "-", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( "\"" UTF8_CURR_TE_IN "\"", " " ), + NUMFMT_ENDTABLE() +}; + +/** Thai, Thailand. */ +static const BuiltinFormat spBuiltinFormats_th_TH[] = +{ + NUMFMT_ALLDATETIMES( "D/M/YYYY", "D", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_SYMBOL_NUMBER( UTF8_BAHT, "" ), + NUMFMT_CURRENCY_OPEN_SYMBOL_NUMBER_CLOSE( 63, UTF8_BAHT, "", "t" ), + NUMFMT_STRING( 59, "t0" ), + NUMFMT_STRING( 60, "t0.00" ), + NUMFMT_STRING( 61, "t#,##0" ), + NUMFMT_STRING( 62, "t#,##0.00" ), + NUMFMT_STRING( 67, "t0%" ), + NUMFMT_STRING( 68, "t0.00%" ), + NUMFMT_STRING( 69, "t# ?/?" ), + NUMFMT_STRING( 70, "t# ?\?/?\?" ), + NUMFMT_STRING( 71, "tD/M/EE" ), + NUMFMT_STRING( 72, "tD-MMM-E" ), + NUMFMT_STRING( 73, "tD-MMM" ), + NUMFMT_STRING( 74, "tMMM-E" ), + NUMFMT_STRING( 75, "th:mm" ), + NUMFMT_STRING( 76, "th:mm:ss" ), + NUMFMT_STRING( 77, "tD/M/EE h:mm" ), + NUMFMT_STRING( 78, "tmm:ss" ), + NUMFMT_STRING( 79, "t[h]:mm:ss" ), + NUMFMT_STRING( 80, "tmm:ss.0" ), + NUMFMT_STRING( 81, "D/M/E" ), + NUMFMT_ENDTABLE() +}; + +/** Turkish, Turkey. */ +static const BuiltinFormat spBuiltinFormats_tr_TR[] = +{ + NUMFMT_ALLDATETIMES( "DD.MM.YYYY", "DD", ".", "MMM", ".", "YY", "h", "hh" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( "\"TL\"", "_T_L", " " ), + NUMFMT_ENDTABLE() +}; + +/** Tatar, Russian Federation. */ +static const BuiltinFormat spBuiltinFormats_tt_RU[] = +{ + // space character is group separator, literal spaces must be quoted + NUMFMT_ALLDATETIMES( "DD.MM.YYYY", "DD", ".", "MMM", ".", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( "\"" UTF8_CYR_R_LC ".\"", "_" UTF8_CYR_R_LC "_.", "\\ " ), + NUMFMT_ENDTABLE() +}; + +/** Ukrainian, Ukraine. */ +static const BuiltinFormat spBuiltinFormats_uk_UA[] = +{ + // space character is group separator, literal spaces must be quoted + NUMFMT_ALLDATETIMES( "DD.MM.YYYY", "DD", ".", "MMM", ".", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( "\"" UTF8_CYR_G_LC UTF8_CYR_R_LC UTF8_CYR_N_LC ".\"", "_" UTF8_CYR_G_LC "_" UTF8_CYR_R_LC "_" UTF8_CYR_N_LC "_.", "\\ " ), + NUMFMT_ENDTABLE() +}; + +/** Urdu, Pakistan. */ +static const BuiltinFormat spBuiltinFormats_ur_PK[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_SYMBOL_NUMBER_MINUS( "\"Rs\"", "" ), + NUMFMT_ENDTABLE() +}; + +/** Vietnamese, Viet Nam. */ +static const BuiltinFormat spBuiltinFormats_vi_VN[] = +{ + NUMFMT_ALLDATETIMES( "DD/MM/YYYY", "DD", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_NUMBER_SYMBOL( UTF8_DONG, "_" UTF8_DONG, " " ), + NUMFMT_ENDTABLE() +}; + +// CJK ------------------------------------------------------------------------ + +/** Base table for CJK locales. */ +static const BuiltinFormat spBuiltinFormats_CJK[] = +{ + NUMFMT_REUSE( 29, 28 ), + NUMFMT_REUSE( 36, 27 ), + NUMFMT_REUSE( 50, 27 ), + NUMFMT_REUSE( 51, 28 ), + NUMFMT_REUSE( 52, 34 ), + NUMFMT_REUSE( 53, 35 ), + NUMFMT_REUSE( 54, 28 ), + NUMFMT_REUSE( 55, 34 ), + NUMFMT_REUSE( 56, 35 ), + NUMFMT_REUSE( 57, 27 ), + NUMFMT_REUSE( 58, 28 ), + NUMFMT_ENDTABLE() +}; + +/** Japanese, Japan. */ +static const BuiltinFormat spBuiltinFormats_ja_JP[] = +{ + NUMFMT_ALLDATETIMES( "YYYY/MM/DD", "DD", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_SYMBOL_NUMBER( UTF8_YEN_JP, "" ), + NUMFMT_CURRENCY_OPEN_SYMBOL_NUMBER_CLOSE( 23, "$", "", "" ), + NUMFMT_STRING( 27, "[$-411]GE.MM.DD" ), + NUMFMT_STRING( 28, "[$-411]GGGE\"" UTF8_CJ_YEAR "\"MM\"" UTF8_CJ_MON "\"DD\"" UTF8_CJ_DAY "\"" ), + NUMFMT_STRING( 30, "MM/DD/YY" ), + NUMFMT_STRING( 31, "YYYY\"" UTF8_CJ_YEAR "\"MM\"" UTF8_CJ_MON "\"DD\"" UTF8_CJ_DAY "\"" ), + NUMFMT_TIME_CJK( 32, "h", UTF8_CJ_HOUR, UTF8_CJ_MIN, UTF8_CJ_SEC ), + NUMFMT_STRING( 34, "YYYY\"" UTF8_CJ_YEAR "\"MM\"" UTF8_CJ_MON "\"" ), + NUMFMT_STRING( 35, "MM\"" UTF8_CJ_MON "\"DD\"" UTF8_CJ_DAY "\"" ), + NUMFMT_ENDTABLE() +}; + +/** Korean, South Korea. */ +static const BuiltinFormat spBuiltinFormats_ko_KR[] = +{ + NUMFMT_ALLDATETIMES( "YYYY-MM-DD", "DD", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_MINUS_SYMBOL_NUMBER( UTF8_WON, "" ), + NUMFMT_CURRENCY_OPEN_SYMBOL_NUMBER_CLOSE( 23, "$", "", "" ), + NUMFMT_STRING( 27, "YYYY" UTF8_CJ_YEAR " MM" UTF8_CJ_MON " DD" UTF8_CJ_DAY ), + NUMFMT_STRING( 28, "MM-DD" ), + NUMFMT_STRING( 30, "MM-DD-YY" ), + NUMFMT_STRING( 31, "YYYY" UTF8_KO_YEAR " MM" UTF8_KO_MON " DD" UTF8_KO_DAY ), + NUMFMT_TIME_CJK( 32, "h", UTF8_KO_HOUR, UTF8_KO_MIN, UTF8_KO_SEC ), + // slashes must be quoted to prevent conversion to minus + NUMFMT_STRING( 34, "YYYY\\/MM\\/DD" ), + NUMFMT_REUSE( 35, 14 ), + NUMFMT_ENDTABLE() +}; + +/** Chinese, China. */ +static const BuiltinFormat spBuiltinFormats_zh_CN[] = +{ + NUMFMT_ALLDATETIMES( "YYYY-M-D", "D", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_SYMBOL_MINUS_NUMBER( UTF8_YEN_CN, "" ), + NUMFMT_ALLTIMES_CJK( "h", "h", UTF8_CS_HOUR, UTF8_CS_MIN, UTF8_CS_SEC ), + NUMFMT_CURRENCY_OPEN_SYMBOL_NUMBER_CLOSE( 23, "$", "", "" ), + NUMFMT_STRING( 27, "YYYY\"" UTF8_CS_YEAR "\"M\"" UTF8_CS_MON "\"" ), + NUMFMT_STRING( 28, "M\"" UTF8_CS_MON "\"D\"" UTF8_CS_DAY "\"" ), + NUMFMT_STRING( 30, "M-D-YY" ), + NUMFMT_STRING( 31, "YYYY\"" UTF8_CS_YEAR "\"M\"" UTF8_CS_MON "\"D\"" UTF8_CS_DAY "\"" ), + NUMFMT_REUSE( 52, 27 ), + NUMFMT_REUSE( 53, 28 ), + NUMFMT_ENDTABLE() +}; + +/** Chinese, Hong Kong. */ +static const BuiltinFormat spBuiltinFormats_zh_HK[] = +{ + NUMFMT_ALLDATETIMES( "D/M/YYYY", "D", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "\"HK$\"", "" ), + NUMFMT_ALLTIMES_CJK( "h", "h", UTF8_CJ_HOUR, UTF8_CJ_MIN, UTF8_CJ_SEC ), + NUMFMT_CURRENCY_OPEN_SYMBOL_NUMBER_CLOSE( 23, "\"US$\"", "", "" ), + NUMFMT_STRING( 27, "[$-404]D/M/E" ), + NUMFMT_STRING( 28, "[$-404]D\"" UTF8_CJ_DAY "\"M\"" UTF8_CJ_MON "\"E\"" UTF8_CJ_YEAR "\"" ), + NUMFMT_STRING( 30, "M/D/YY" ), + NUMFMT_STRING( 31, "D\"" UTF8_CJ_DAY "\"M\"" UTF8_CJ_MON "\"YYYY\"" UTF8_CJ_YEAR "\"" ), + NUMFMT_ENDTABLE() +}; + +/** Chinese, Macau. */ +static const BuiltinFormat spBuiltinFormats_zh_MO[] = +{ + NUMFMT_ALLDATETIMES( "D/M/YYYY", "D", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "\\P", "" ), + NUMFMT_ALLTIMES_CJK( "h", "h", UTF8_CJ_HOUR, UTF8_CJ_MIN, UTF8_CJ_SEC ), + NUMFMT_CURRENCY_OPEN_SYMBOL_NUMBER_CLOSE( 23, "\"US$\"", "", "" ), + NUMFMT_STRING( 27, "[$-404]D/M/E" ), + NUMFMT_STRING( 28, "[$-404]D\"" UTF8_CJ_DAY "\"M\"" UTF8_CJ_MON "\"E\"" UTF8_CJ_YEAR "\"" ), + NUMFMT_STRING( 30, "M/D/YY" ), + NUMFMT_STRING( 31, "D\"" UTF8_CJ_DAY "\"M\"" UTF8_CJ_MON "\"YYYY\"" UTF8_CJ_YEAR "\"" ), + NUMFMT_ENDTABLE() +}; + +/** Chinese, Singapore. */ +static const BuiltinFormat spBuiltinFormats_zh_SG[] = +{ + NUMFMT_ALLDATETIMES( "D/M/YYYY", "D", "-", "MMM", "-", "YY", "h", "h" ), + NUMFMT_ALLCURRENCIES_OPEN_SYMBOL_NUMBER_CLOSE( "$", "" ), + NUMFMT_ALLTIMES_CJK( "h", "h", UTF8_CS_HOUR, UTF8_CS_MIN, UTF8_CS_SEC ), + NUMFMT_CURRENCY_OPEN_SYMBOL_NUMBER_CLOSE( 23, "$", "", "" ), + NUMFMT_STRING( 27, "YYYY\"" UTF8_CS_YEAR "\"M\"" UTF8_CS_MON "\"" ), + NUMFMT_STRING( 28, "M\"" UTF8_CS_MON "\"D\"" UTF8_CS_DAY "\"" ), + NUMFMT_STRING( 30, "M/D/YY" ), + NUMFMT_STRING( 31, "D\"" UTF8_CS_DAY "\"M\"" UTF8_CS_MON "\"YYYY\"" UTF8_CS_YEAR "\"" ), + NUMFMT_ENDTABLE() +}; + +/** Chinese, Taiwan. */ +static const BuiltinFormat spBuiltinFormats_zh_TW[] = +{ + NUMFMT_ALLDATETIMES( "YYYY/M/D", "D", "-", "MMM", "-", "YY", "hh", "hh" ), + NUMFMT_ALLCURRENCIES_MINUS_SYMBOL_NUMBER( "$", "" ), + NUMFMT_ALLTIMES_CJK( "hh", "hh", UTF8_CJ_HOUR, UTF8_CJ_MIN, UTF8_CJ_SEC ), + NUMFMT_CURRENCY_OPEN_SYMBOL_NUMBER_CLOSE( 23, "\"US$\"", "", "" ), + NUMFMT_STRING( 27, "[$-404]E/M/D" ), + NUMFMT_STRING( 28, "[$-404]E\"" UTF8_CJ_YEAR "\"M\"" UTF8_CJ_MON "\"D\"" UTF8_CJ_DAY "\"" ), + NUMFMT_STRING( 30, "M/D/YY" ), + NUMFMT_STRING( 31, "YYYY\"" UTF8_CJ_YEAR "\"M\"" UTF8_CJ_MON "\"D\"" UTF8_CJ_DAY "\"" ), + NUMFMT_ENDTABLE() +}; + +// ---------------------------------------------------------------------------- + +/** Specifies a built-in number format table for a specific locale. */ +struct BuiltinFormatTable +{ + const sal_Char* mpcLocale; /// The locale for this table. + const sal_Char* mpcParent; /// The locale of the parent table. + const BuiltinFormat* mpFormats; /// The number format table (may be 0, if equal to parent). +}; + +static const BuiltinFormatTable spBuiltinFormatTables[] = +{ // locale parent format table + { "*", "", spBuiltinFormats_BASE }, // Base table + { "af-ZA", "*", spBuiltinFormats_en_ZA }, // Afrikaans, South Africa + { "ar-AE", "*", spBuiltinFormats_ar_AE }, // Arabic, U.A.E. + { "ar-BH", "*", spBuiltinFormats_ar_BH }, // Arabic, Bahrain + { "ar-DZ", "*", spBuiltinFormats_ar_DZ }, // Arabic, Algeria + { "ar-EG", "*", spBuiltinFormats_ar_EG }, // Arabic, Egypt + { "ar-IQ", "*", spBuiltinFormats_ar_IQ }, // Arabic, Iraq + { "ar-JO", "*", spBuiltinFormats_ar_JO }, // Arabic, Jordan + { "ar-KW", "*", spBuiltinFormats_ar_KW }, // Arabic, Kuwait + { "ar-LB", "*", spBuiltinFormats_ar_LB }, // Arabic, Lebanon + { "ar-LY", "*", spBuiltinFormats_ar_LY }, // Arabic, Libya + { "ar-MA", "*", spBuiltinFormats_ar_MA }, // Arabic, Morocco + { "ar-OM", "*", spBuiltinFormats_ar_OM }, // Arabic, Oman + { "ar-QA", "*", spBuiltinFormats_ar_QA }, // Arabic, Qatar + { "ar-SA", "*", spBuiltinFormats_ar_SA }, // Arabic, Saudi Arabia + { "ar-SY", "*", spBuiltinFormats_ar_SY }, // Arabic, Syria + { "ar-TN", "*", spBuiltinFormats_ar_TN }, // Arabic, Tunisia + { "ar-YE", "*", spBuiltinFormats_ar_YE }, // Arabic, Yemen + { "be-BY", "*", spBuiltinFormats_be_BY }, // Belarusian, Belarus + { "bg-BG", "*", spBuiltinFormats_bg_BG }, // Bulgarian, Bulgaria + { "bn-IN", "*", spBuiltinFormats_bn_IN }, // Bengali, India + { "ca-ES", "*", spBuiltinFormats_es_ES }, // Catalan, Spain + { "cs-CZ", "*", spBuiltinFormats_cs_CZ }, // Czech, Czech Republic + { "cy-GB", "*", spBuiltinFormats_en_GB }, // Welsh, United Kingdom + { "da-DK", "*", spBuiltinFormats_da_DK }, // Danish, Denmark + { "de-AT", "*", spBuiltinFormats_de_AT }, // German, Austria + { "de-CH", "*", spBuiltinFormats_de_CH }, // German, Switzerland + { "de-DE", "*", spBuiltinFormats_de_DE }, // German, Germany + { "de-LI", "*", spBuiltinFormats_de_LI }, // German, Liechtenstein + { "de-LU", "*", spBuiltinFormats_de_LU }, // German, Luxembourg + { "div-MV", "*", spBuiltinFormats_div_MV }, // Divehi, Maldives + { "el-GR", "*", spBuiltinFormats_el_GR }, // Greek, Greece + { "en-AU", "*", spBuiltinFormats_en_AU }, // English, Australia + { "en-BZ", "*", spBuiltinFormats_en_BZ }, // English, Belize + { "en-CA", "*", spBuiltinFormats_en_CA }, // English, Canada + { "en-CB", "*", spBuiltinFormats_en_CB }, // English, Caribbean + { "en-GB", "*", spBuiltinFormats_en_GB }, // English, United Kingdom + { "en-IE", "*", spBuiltinFormats_en_IE }, // English, Ireland + { "en-JM", "*", spBuiltinFormats_en_JM }, // English, Jamaica + { "en-NZ", "*", spBuiltinFormats_en_NZ }, // English, New Zealand + { "en-PH", "*", spBuiltinFormats_en_PH }, // English, Philippines + { "en-TT", "*", spBuiltinFormats_en_TT }, // English, Trinidad and Tobago + { "en-US", "*", spBuiltinFormats_en_US }, // English, USA + { "en-ZA", "*", spBuiltinFormats_en_ZA }, // English, South Africa + { "en-ZW", "*", spBuiltinFormats_en_ZW }, // English, Zimbabwe + { "es-AR", "*", spBuiltinFormats_es_AR }, // Spanish, Argentina + { "es-BO", "*", spBuiltinFormats_es_BO }, // Spanish, Bolivia + { "es-CL", "*", spBuiltinFormats_es_CL }, // Spanish, Chile + { "es-CO", "*", spBuiltinFormats_es_CO }, // Spanish, Colombia + { "es-CR", "*", spBuiltinFormats_es_CR }, // Spanish, Costa Rica + { "es-DO", "*", spBuiltinFormats_es_DO }, // Spanish, Dominican Republic + { "es-EC", "*", spBuiltinFormats_es_EC }, // Spanish, Ecuador + { "es-ES", "*", spBuiltinFormats_es_ES }, // Spanish, Spain + { "es-GT", "*", spBuiltinFormats_es_GT }, // Spanish, Guatemala + { "es-HN", "*", spBuiltinFormats_es_HN }, // Spanish, Honduras + { "es-MX", "*", spBuiltinFormats_es_MX }, // Spanish, Mexico + { "es-NI", "*", spBuiltinFormats_es_NI }, // Spanish, Nicaragua + { "es-PA", "*", spBuiltinFormats_es_PA }, // Spanish, Panama + { "es-PE", "*", spBuiltinFormats_es_PE }, // Spanish, Peru + { "es-PR", "*", spBuiltinFormats_es_PR }, // Spanish, Puerto Rico + { "es-PY", "*", spBuiltinFormats_es_PY }, // Spanish, Paraguay + { "es-SV", "*", spBuiltinFormats_es_SV }, // Spanish, El Salvador + { "es-UY", "*", spBuiltinFormats_es_UY }, // Spanish, Uruguay + { "es-VE", "*", spBuiltinFormats_es_VE }, // Spanish, Venezuela + { "et-EE", "*", spBuiltinFormats_et_EE }, // Estonian, Estonia + { "fa-IR", "*", spBuiltinFormats_fa_IR }, // Farsi, Iran + { "fi-FI", "*", spBuiltinFormats_fi_FI }, // Finnish, Finland + { "fo-FO", "*", spBuiltinFormats_fo_FO }, // Faroese, Faroe Islands + { "fr-BE", "*", spBuiltinFormats_fr_BE }, // French, Belgium + { "fr-CA", "*", spBuiltinFormats_fr_CA }, // French, Canada + { "fr-CH", "*", spBuiltinFormats_fr_CH }, // French, Switzerland + { "fr-FR", "*", spBuiltinFormats_fr_FR }, // French, France + { "fr-LU", "*", spBuiltinFormats_fr_LU }, // French, Luxembourg + { "fr-MC", "*", spBuiltinFormats_fr_MC }, // French, Monaco + { "gl-ES", "*", spBuiltinFormats_gl_ES }, // Galizian, Spain + { "gu-IN", "*", spBuiltinFormats_gu_IN }, // Gujarati, India + { "he-IL", "*", spBuiltinFormats_he_IL }, // Hebrew, Israel + { "hi-IN", "*", spBuiltinFormats_hi_IN }, // Hindi, India + { "hr-BA", "*", spBuiltinFormats_hr_BA }, // Croatian, Bosnia and Herzegowina + { "hr-HR", "*", spBuiltinFormats_hr_HR }, // Croatian, Croatia + { "hu-HU", "*", spBuiltinFormats_hu_HU }, // Hungarian, Hungary + { "hy-AM", "*", spBuiltinFormats_hy_AM }, // Armenian, Armenia + { "id-ID", "*", spBuiltinFormats_id_ID }, // Indonesian, Indonesia + { "is-IS", "*", spBuiltinFormats_is_IS }, // Icelandic, Iceland + { "it-CH", "*", spBuiltinFormats_it_CH }, // Italian, Switzerland + { "it-IT", "*", spBuiltinFormats_it_IT }, // Italian, Italy + { "ka-GE", "*", spBuiltinFormats_ka_GE }, // Georgian, Georgia + { "kk-KZ", "*", spBuiltinFormats_kk_KZ }, // Kazakh, Kazakhstan + { "kn-IN", "*", spBuiltinFormats_kn_IN }, // Kannada, India + { "kok-IN", "*", spBuiltinFormats_hi_IN }, // Konkani, India + { "ky-KG", "*", spBuiltinFormats_ky_KG }, // Kyrgyz, Kyrgyzstan + { "lt-LT", "*", spBuiltinFormats_lt_LT }, // Lithuanian, Lithuania + { "lv-LV", "*", spBuiltinFormats_lv_LV }, // Latvian, Latvia + { "mi-NZ", "*", spBuiltinFormats_en_NZ }, // Maori, New Zealand + { "ml-IN", "*", spBuiltinFormats_ml_IN }, // Malayalam, India + { "mn-MN", "*", spBuiltinFormats_mn_MN }, // Mongolian, Mongolia + { "mr-IN", "*", spBuiltinFormats_hi_IN }, // Marathi, India + { "ms-BN", "*", spBuiltinFormats_ms_BN }, // Malay, Brunei Darussalam + { "ms-MY", "*", spBuiltinFormats_ms_MY }, // Malay, Malaysia + { "mt-MT", "*", spBuiltinFormats_mt_MT }, // Maltese, Malta + { "nb-NO", "*", spBuiltinFormats_no_NO }, // Norwegian Bokmal, Norway + { "nl-BE", "*", spBuiltinFormats_nl_BE }, // Dutch, Belgium + { "nl-NL", "*", spBuiltinFormats_nl_NL }, // Dutch, Netherlands + { "nn-NO", "*", spBuiltinFormats_no_NO }, // Norwegian Nynorsk, Norway + { "nso-ZA", "*", spBuiltinFormats_en_ZA }, // Northern Sotho, South Africa + { "pa-IN", "*", spBuiltinFormats_pa_IN }, // Punjabi, India + { "pl-PL", "*", spBuiltinFormats_pl_PL }, // Polish, Poland + { "pt-BR", "*", spBuiltinFormats_pt_BR }, // Portugese, Brazil + { "pt-PT", "*", spBuiltinFormats_pt_PT }, // Portugese, Portugal + { "qu-BO", "*", spBuiltinFormats_es_BO }, // Quechua, Bolivia + { "qu-EC", "*", spBuiltinFormats_es_EC }, // Quechua, Ecuador + { "qu-PE", "*", spBuiltinFormats_es_PE }, // Quechua, Peru + { "ro-RO", "*", spBuiltinFormats_ro_RO }, // Romanian, Romania + { "ru-RU", "*", spBuiltinFormats_ru_RU }, // Russian, Russian Federation + { "sa-IN", "*", spBuiltinFormats_hi_IN }, // Sanskrit, India + { "se-FI", "*", spBuiltinFormats_fi_FI }, // Sami, Finland + { "se-NO", "*", spBuiltinFormats_no_NO }, // Sami, Norway + { "se-SE", "*", spBuiltinFormats_sv_SE }, // Sami, Sweden + { "sk-SK", "*", spBuiltinFormats_sk_SK }, // Slovak, Slovakia + { "sl-SI", "*", spBuiltinFormats_sl_SI }, // Slovenian, Slovenia + { "sv-FI", "*", spBuiltinFormats_sv_FI }, // Swedish, Finland + { "sv-SE", "*", spBuiltinFormats_sv_SE }, // Swedish, Sweden + { "sw-TZ", "*", spBuiltinFormats_sw_TZ }, // Swahili, Tanzania + { "syr-SY", "*", spBuiltinFormats_ar_SY }, // Syriac, Syria + { "syr-TR", "*", spBuiltinFormats_tr_TR }, // Syriac, Turkey + { "ta-IN", "*", spBuiltinFormats_ta_IN }, // Tamil, India + { "te-IN", "*", spBuiltinFormats_te_IN }, // Telugu, India + { "th-TH", "*", spBuiltinFormats_th_TH }, // Thai, Thailand + { "tn-ZA", "*", spBuiltinFormats_en_ZA }, // Tswana, South Africa + { "tr-TR", "*", spBuiltinFormats_tr_TR }, // Turkish, Turkey + { "tt-RU", "*", spBuiltinFormats_tt_RU }, // Tatar, Russian Federation + { "uk-UA", "*", spBuiltinFormats_uk_UA }, // Ukrainian, Ukraine + { "ur-PK", "*", spBuiltinFormats_ur_PK }, // Urdu, Pakistan + { "vi-VN", "*", spBuiltinFormats_vi_VN }, // Vietnamese, Viet Nam + { "xh-ZA", "*", spBuiltinFormats_en_ZA }, // Xhosa, South Africa + { "zu-ZA", "*", spBuiltinFormats_en_ZA }, // Zulu, South Africa + + { "*CJK", "*", spBuiltinFormats_CJK }, // CJK base table + { "ja-JP", "*CJK", spBuiltinFormats_ja_JP }, // Japanese, Japan + { "ko-KR", "*CJK", spBuiltinFormats_ko_KR }, // Korean, South Korea + { "zh-CN", "*CJK", spBuiltinFormats_zh_CN }, // Chinese, China + { "zh-HK", "*CJK", spBuiltinFormats_zh_HK }, // Chinese, Hong Kong + { "zh-MO", "*CJK", spBuiltinFormats_zh_MO }, // Chinese, Macau + { "zh-SG", "*CJK", spBuiltinFormats_zh_SG }, // Chinese, Singapore + { "zh-TW", "*CJK", spBuiltinFormats_zh_TW } // Chinese, Taiwan +}; + +// ============================================================================ + +/** Functor for converting an XML number format to an API number format index. */ +class NumberFormatFunctor +{ +public: + explicit NumberFormatFunctor( const WorkbookHelper& rHelper ); + + inline bool is() const { return mxNumFmts.is(); } + + inline void operator()( NumberFormat& rNumFmt ) const + { rNumFmt.finalizeImport( mxNumFmts, maEnUsLocale ); } + +private: + Reference< XNumberFormats > mxNumFmts; + Locale maEnUsLocale; +}; + +// ---------------------------------------------------------------------------- + +NumberFormatFunctor::NumberFormatFunctor( const WorkbookHelper& rHelper ) : + maEnUsLocale( CREATE_OUSTRING( "en" ), CREATE_OUSTRING( "US" ), OUString() ) +{ + try + { + Reference< XNumberFormatsSupplier > xNumFmtsSupp( rHelper.getDocument(), UNO_QUERY_THROW ); + mxNumFmts = xNumFmtsSupp->getNumberFormats(); + } + catch( Exception& ) + { + } + OSL_ENSURE( mxNumFmts.is(), "NumberFormatFunctor::NumberFormatFunctor - cannot get number formats" ); +} + +} // namespace + +// ============================================================================ + +OoxNumFmtData::OoxNumFmtData() : + mnPredefId( -1 ) +{ +} + +// ---------------------------------------------------------------------------- + +namespace { + +sal_Int32 lclCreatePredefinedFormat( const Reference< XNumberFormats >& rxNumFmts, + sal_Int16 nPredefId, const Locale& rToLocale ) +{ + sal_Int32 nIndex = 0; + try + { + Reference< XNumberFormatTypes > xNumFmtTypes( rxNumFmts, UNO_QUERY_THROW ); + nIndex = (nPredefId >= 0) ? + xNumFmtTypes->getFormatIndex( nPredefId, rToLocale ) : + xNumFmtTypes->getStandardIndex( rToLocale ); + } + catch( Exception& ) + { + OSL_ENSURE( false, + OStringBuffer( "lclCreatePredefinedFormat - cannot create predefined number format " ). + append( OString::valueOf( static_cast< sal_Int32 >( nPredefId ) ) ).getStr() ); + } + return nIndex; +} + +sal_Int32 lclCreateFormat( const Reference< XNumberFormats >& rxNumFmts, + const OUString& rFmtCode, const Locale& rToLocale, const Locale& rFromLocale ) +{ + sal_Int32 nIndex = 0; + try + { + nIndex = rxNumFmts->addNewConverted( rFmtCode, rFromLocale, rToLocale ); + } + catch( Exception& ) + { + // BIFF2-BIFF4 stores standard format explicitly in stream + static const OUString saGeneral = CREATE_OUSTRING( "general" ); + if( rFmtCode.equalsIgnoreAsciiCase( saGeneral ) ) + { + nIndex = lclCreatePredefinedFormat( rxNumFmts, 0, rToLocale ); + } + else + { + OSL_ENSURE( false, + OStringBuffer( "lclCreateFormat - cannot create number format '" ). + append( OUStringToOString( rFmtCode, osl_getThreadTextEncoding() ) ). + append( '\'' ).getStr() ); + } + } + return nIndex; +} + +} // namespace + +// ---------------------------------------------------------------------------- + +NumberFormat::NumberFormat( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ) +{ +} + +void NumberFormat::setFormatCode( const OUString& rFmtCode ) +{ + maOoxData.maFmtCode = rFmtCode; +} + +void NumberFormat::setFormatCode( const Locale& rLocale, const sal_Char* pcFmtCode ) +{ + maOoxData.maLocale = rLocale; + maOoxData.maFmtCode = OStringToOUString( OString( pcFmtCode ), RTL_TEXTENCODING_UTF8 ); + maOoxData.mnPredefId = -1; +} + +void NumberFormat::setPredefinedId( const Locale& rLocale, sal_Int16 nPredefId ) +{ + maOoxData.maLocale = rLocale; + maOoxData.maFmtCode = OUString(); + maOoxData.mnPredefId = nPredefId; +} + +void NumberFormat::finalizeImport( const Reference< XNumberFormats >& rxNumFmts, const Locale& rFromLocale ) +{ + if( rxNumFmts.is() && (maOoxData.maFmtCode.getLength() > 0) ) + maApiData.mnIndex = lclCreateFormat( rxNumFmts, maOoxData.maFmtCode, maOoxData.maLocale, rFromLocale ); + else + maApiData.mnIndex = lclCreatePredefinedFormat( rxNumFmts, maOoxData.mnPredefId, maOoxData.maLocale ); +} + +void NumberFormat::writeToPropertySet( PropertySet& rPropSet ) const +{ + getStylesPropertyHelper().writeNumFmtProperties( rPropSet, maApiData ); +} + +// ============================================================================ + +NumberFormatsBuffer::NumberFormatsBuffer( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + mnNextBiffIndex( 0 ) +{ + // get the current locale + try + { + Reference< XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + Reference< XMultiServiceFactory > xConfigProv( + xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.configuration.ConfigurationProvider" ) ), + UNO_QUERY_THROW ); + + // try user-defined locale setting + Sequence< Any > aArgs( 1 ); + aArgs[ 0 ] <<= CREATE_OUSTRING( "org.openoffice.Setup/L10N/" ); + Reference< XNameAccess > xConfigNA( xConfigProv->createInstanceWithArguments( + CREATE_OUSTRING( "com.sun.star.configuration.ConfigurationAccess" ), aArgs ), UNO_QUERY_THROW ); + xConfigNA->getByName( CREATE_OUSTRING( "ooSetupSystemLocale" ) ) >>= maLocaleStr; + + // if set to "use system", get locale from system + if( maLocaleStr.getLength() == 0 ) + { + aArgs[ 0 ] <<= CREATE_OUSTRING( "org.openoffice.System/L10N/" ); + xConfigNA.set( xConfigProv->createInstanceWithArguments( + CREATE_OUSTRING( "com.sun.star.configuration.ConfigurationAccess" ), aArgs ), UNO_QUERY_THROW ); + xConfigNA->getByName( CREATE_OUSTRING( "Locale" ) ) >>= maLocaleStr; + } + } + catch( Exception& ) + { + OSL_ENSURE( false, "NumberFormatsBuffer::NumberFormatsBuffer - cannot get system locale" ); + } + + // create built-in formats for current locale + insertBuiltinFormats(); +} + +NumberFormatRef NumberFormatsBuffer::createNumFmt( sal_Int32 nNumFmtId, const OUString& rFmtCode ) +{ + NumberFormatRef xNumFmt; + if( nNumFmtId >= 0 ) + { + xNumFmt.reset( new NumberFormat( *this ) ); + maNumFmts[ nNumFmtId ] = xNumFmt; + xNumFmt->setFormatCode( rFmtCode ); + } + return xNumFmt; +} + +NumberFormatRef NumberFormatsBuffer::importNumFmt( const AttributeList& rAttribs ) +{ + sal_Int32 nNumFmtId = rAttribs.getInteger( XML_numFmtId, -1 ); + OUString aFmtCode = rAttribs.getString( XML_formatCode ); + return createNumFmt( nNumFmtId, aFmtCode ); +} + +void NumberFormatsBuffer::importNumFmt( RecordInputStream& rStrm ) +{ + sal_Int32 nNumFmtId = rStrm.readuInt16(); + OUString aFmtCode = rStrm.readString(); + createNumFmt( nNumFmtId, aFmtCode ); +} + +void NumberFormatsBuffer::importFormat( BiffInputStream& rStrm ) +{ + OUString aFmtCode; + switch( getBiff() ) + { + case BIFF2: + case BIFF3: + aFmtCode = rStrm.readByteString( false, getTextEncoding() ); + break; + case BIFF4: + // in BIFF4 the index field exists, but is undefined + aFmtCode = rStrm.skip( 2 ).readByteString( false, getTextEncoding() ); + break; + case BIFF5: + mnNextBiffIndex = rStrm.readuInt16(); + aFmtCode = rStrm.readByteString( false, getTextEncoding() ); + break; + case BIFF8: + mnNextBiffIndex = rStrm.readuInt16(); + aFmtCode = rStrm.readUniString(); + break; + case BIFF_UNKNOWN: break; + } + + createNumFmt( mnNextBiffIndex, aFmtCode ); + ++mnNextBiffIndex; +} + +void NumberFormatsBuffer::finalizeImport() +{ + maNumFmts.forEach( NumberFormatFunctor( *this ) ); +} + +void NumberFormatsBuffer::writeToPropertySet( PropertySet& rPropSet, sal_Int32 nNumFmtId ) const +{ + if( const NumberFormat* pNumFmt = maNumFmts.get( nNumFmtId ).get() ) + pNumFmt->writeToPropertySet( rPropSet ); +} + +void NumberFormatsBuffer::insertBuiltinFormats() +{ + // build a map containing pointers to all tables + typedef ::std::map< OUString, const BuiltinFormatTable* > BuiltinMap; + BuiltinMap aBuiltinMap; + for( const BuiltinFormatTable* pTable = spBuiltinFormatTables; + pTable != STATIC_ARRAY_END( spBuiltinFormatTables ); ++pTable ) + aBuiltinMap[ OUString::createFromAscii( pTable->mpcLocale ) ] = pTable; + + // convert locale string to locale struct + Locale aSysLocale; + sal_Int32 nDashPos = maLocaleStr.indexOf( '-' ); + if( nDashPos < 0 ) nDashPos = maLocaleStr.getLength(); + aSysLocale.Language = maLocaleStr.copy( 0, nDashPos ); + if( nDashPos + 1 < maLocaleStr.getLength() ) + aSysLocale.Country = maLocaleStr.copy( nDashPos + 1 ); + + // build a list of table pointers for the current locale, with all parent tables + typedef ::std::vector< const BuiltinFormatTable* > BuiltinVec; + BuiltinVec aBuiltinVec; + BuiltinMap::const_iterator aMIt = aBuiltinMap.find( maLocaleStr ), aMEnd = aBuiltinMap.end(); + OSL_ENSURE( aMIt != aMEnd, + OStringBuffer( "NumberFormatsBuffer::insertBuiltinFormats - locale '" ). + append( OUStringToOString( maLocaleStr, RTL_TEXTENCODING_ASCII_US ) ). + append( "' not supported (#i29949#)" ).getStr() ); + // start with default table, if no table has been found + if( aMIt == aMEnd ) + aMIt = aBuiltinMap.find( CREATE_OUSTRING( "*" ) ); + OSL_ENSURE( aMIt != aMEnd, "NumberFormatsBuffer::insertBuiltinFormats - default map not found" ); + // insert all tables into the vector + for( ; aMIt != aMEnd; aMIt = aBuiltinMap.find( OUString::createFromAscii( aMIt->second->mpcParent ) ) ) + aBuiltinVec.push_back( aMIt->second ); + + // insert the default formats in the format map (in reverse order from default table to system locale) + typedef ::std::map< sal_Int32, sal_Int32 > ReuseMap; + ReuseMap aReuseMap; + for( BuiltinVec::reverse_iterator aVIt = aBuiltinVec.rbegin(), aVEnd = aBuiltinVec.rend(); aVIt != aVEnd; ++aVIt ) + { + // do not put the current system locale for default table + Locale aLocale; + if( (*aVIt)->mpcLocale[ 0 ] != '\0' ) + aLocale = aSysLocale; + for( const BuiltinFormat* pBuiltin = (*aVIt)->mpFormats; pBuiltin && (pBuiltin->mnNumFmtId >= 0); ++pBuiltin ) + { + NumberFormatRef& rxNumFmt = maNumFmts[ pBuiltin->mnNumFmtId ]; + rxNumFmt.reset( new NumberFormat( *this ) ); + + bool bReuse = false; + if( pBuiltin->mpcFmtCode ) + rxNumFmt->setFormatCode( aLocale, pBuiltin->mpcFmtCode ); + else if( pBuiltin->mnPredefId >= 0 ) + rxNumFmt->setPredefinedId( aLocale, pBuiltin->mnPredefId ); + else + bReuse = pBuiltin->mnReuseId >= 0; + + if( bReuse ) + aReuseMap[ pBuiltin->mnNumFmtId ] = pBuiltin->mnReuseId; + else + aReuseMap.erase( pBuiltin->mnNumFmtId ); + } + } + + // copy reused number formats + for( ReuseMap::const_iterator aRIt = aReuseMap.begin(), aREnd = aReuseMap.end(); aRIt != aREnd; ++aRIt ) + maNumFmts[ aRIt->first ] = maNumFmts[ aRIt->second ]; +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/pagesettings.cxx b/oox/source/xls/pagesettings.cxx new file mode 100644 index 000000000000..6cb32f961352 --- /dev/null +++ b/oox/source/xls/pagesettings.cxx @@ -0,0 +1,641 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: pagesettings.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:08 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/pagesettings.hxx" +#include +#include +#include +#include +#include +#include "oox/helper/attributelist.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/helper/recordinputstream.hxx" +#include "oox/xls/biffinputstream.hxx" +#include "oox/xls/ooxtokens.hxx" +#include "oox/xls/unitconverter.hxx" + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::container::XNamed; +using ::com::sun::star::sheet::XHeaderFooterContent; +using ::com::sun::star::style::XStyle; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +const double OOX_MARGIN_DEFAULT_LR = 0.748; /// Left/right default margin in inches. +const double OOX_MARGIN_DEFAULT_TB = 0.984; /// Top/bottom default margin in inches. +const double OOX_MARGIN_DEFAULT_HF = 0.512; /// Header/footer default margin in inches. + +const sal_uInt16 OOBIN_HEADERFOOTER_DIFFEVEN = 0x0001; +const sal_uInt16 OOBIN_HEADERFOOTER_DIFFFIRST = 0x0002; +const sal_uInt16 OOBIN_HEADERFOOTER_SCALEDOC = 0x0004; +const sal_uInt16 OOBIN_HEADERFOOTER_ALIGNMARGIN = 0x0008; + +const sal_uInt16 OOBIN_PAGESETUP_INROWS = 0x0001; +const sal_uInt16 OOBIN_PAGESETUP_LANDSCAPE = 0x0002; +const sal_uInt16 OOBIN_PAGESETUP_INVALID = 0x0004; +const sal_uInt16 OOBIN_PAGESETUP_BLACKWHITE = 0x0008; +const sal_uInt16 OOBIN_PAGESETUP_DRAFTQUALITY = 0x0010; +const sal_uInt16 OOBIN_PAGESETUP_PRINTNOTES = 0x0020; +const sal_uInt16 OOBIN_PAGESETUP_DEFAULTORIENT = 0x0040; +const sal_uInt16 OOBIN_PAGESETUP_USEFIRSTPAGE = 0x0080; +const sal_uInt16 OOBIN_PAGESETUP_NOTES_END = 0x0100; // different to BIFF flag + +const sal_uInt16 OOBIN_PRINTOPT_HORCENTER = 0x0001; +const sal_uInt16 OOBIN_PRINTOPT_VERCENTER = 0x0002; +const sal_uInt16 OOBIN_PRINTOPT_PRINTHEADING = 0x0004; +const sal_uInt16 OOBIN_PRINTOPT_PRINTGRID = 0x0008; + +const sal_uInt16 BIFF_PAGESETUP_INROWS = 0x0001; +const sal_uInt16 BIFF_PAGESETUP_PORTRAIT = 0x0002; +const sal_uInt16 BIFF_PAGESETUP_INVALID = 0x0004; +const sal_uInt16 BIFF_PAGESETUP_BLACKWHITE = 0x0008; +const sal_uInt16 BIFF_PAGESETUP_DRAFTQUALITY = 0x0010; +const sal_uInt16 BIFF_PAGESETUP_PRINTNOTES = 0x0020; +const sal_uInt16 BIFF_PAGESETUP_DEFAULTORIENT = 0x0040; +const sal_uInt16 BIFF_PAGESETUP_USEFIRSTPAGE = 0x0080; +const sal_uInt16 BIFF_PAGESETUP_NOTES_END = 0x0200; + +} // namespace + +// ============================================================================ + +OoxPageData::OoxPageData() : + mfLeftMargin( OOX_MARGIN_DEFAULT_LR ), + mfRightMargin( OOX_MARGIN_DEFAULT_LR ), + mfTopMargin( OOX_MARGIN_DEFAULT_TB ), + mfBottomMargin( OOX_MARGIN_DEFAULT_TB ), + mfHeaderMargin( OOX_MARGIN_DEFAULT_HF ), + mfFooterMargin( OOX_MARGIN_DEFAULT_HF ), + mnPaperSize( 1 ), + mnCopies( 1 ), + mnScale( 100 ), + mnFirstPage( 1 ), + mnFitToWidth( 1 ), + mnFitToHeight( 1 ), + mnHorPrintRes( 600 ), + mnVerPrintRes( 600 ), + mnOrientation( XML_default ), + mnPageOrder( XML_downThenOver ), + mnCellComments( XML_none ), + mnPrintErrors( XML_displayed ), + mbUseEvenHF( false ), + mbUseFirstHF( false ), + mbValidSettings( true ), + mbUseFirstPage( false ), + mbBlackWhite( false ), + mbDraftQuality( false ), + mbFitToPages( false ), + mbHorCenter( false ), + mbVerCenter( false ), + mbPrintGrid( false ), + mbPrintHeadings( false ) +{ +} + +void OoxPageData::setBinPrintErrors( sal_uInt8 nPrintErrors ) +{ + static const sal_Int32 spnErrorIds[] = { XML_displayed, XML_none, XML_dash, XML_NA }; + mnPrintErrors = STATIC_ARRAY_SELECT( spnErrorIds, nPrintErrors, XML_none ); +} + +// ============================================================================ + +PageSettings::PageSettings( const WorksheetHelper& rHelper ) : + WorksheetHelper( rHelper ) +{ +} + +void PageSettings::importPageMargins( const AttributeList& rAttribs ) +{ + maOoxData.mfLeftMargin = rAttribs.getDouble( XML_left, OOX_MARGIN_DEFAULT_LR ); + maOoxData.mfRightMargin = rAttribs.getDouble( XML_right, OOX_MARGIN_DEFAULT_LR ); + maOoxData.mfTopMargin = rAttribs.getDouble( XML_top, OOX_MARGIN_DEFAULT_TB ); + maOoxData.mfBottomMargin = rAttribs.getDouble( XML_bottom, OOX_MARGIN_DEFAULT_TB ); + maOoxData.mfHeaderMargin = rAttribs.getDouble( XML_header, OOX_MARGIN_DEFAULT_HF ); + maOoxData.mfFooterMargin = rAttribs.getDouble( XML_footer, OOX_MARGIN_DEFAULT_HF ); +} + +void PageSettings::importPageSetup( const AttributeList& rAttribs ) +{ + maOoxData.maRelId = rAttribs.getString( R_TOKEN( id ) ); + maOoxData.mnPaperSize = rAttribs.getInteger( XML_paperSize, 1 ); + maOoxData.mnCopies = rAttribs.getInteger( XML_copies, 1 ); + maOoxData.mnScale = rAttribs.getInteger( XML_scale, 100 ); + maOoxData.mnFirstPage = rAttribs.getInteger( XML_firstPageNumber, 1 ); + maOoxData.mnFitToWidth = rAttribs.getInteger( XML_fitToWidth, 1 ); + maOoxData.mnFitToHeight = rAttribs.getInteger( XML_fitToHeight, 1 ); + maOoxData.mnHorPrintRes = rAttribs.getInteger( XML_horizontalDpi, 600 ); + maOoxData.mnVerPrintRes = rAttribs.getInteger( XML_verticalDpi, 600 ); + maOoxData.mnOrientation = rAttribs.getToken( XML_orientation, XML_default ); + maOoxData.mnPageOrder = rAttribs.getToken( XML_pageOrder, XML_downThenOver ); + maOoxData.mnCellComments = rAttribs.getToken( XML_cellComments, XML_none ); + maOoxData.mnPrintErrors = rAttribs.getToken( XML_errors, XML_displayed ); + maOoxData.mbValidSettings = rAttribs.getBool( XML_usePrinterDefaults, true ); + maOoxData.mbUseFirstPage = rAttribs.getBool( XML_useFirstPageNumber, false ); + maOoxData.mbBlackWhite = rAttribs.getBool( XML_blackAndWhite, false ); + maOoxData.mbDraftQuality = rAttribs.getBool( XML_draft, false ); +} + +void PageSettings::importPrintOptions( const AttributeList& rAttribs ) +{ + maOoxData.mbHorCenter = rAttribs.getBool( XML_horizontalCentered, false ); + maOoxData.mbVerCenter = rAttribs.getBool( XML_verticalCentered, false ); + maOoxData.mbPrintGrid = rAttribs.getBool( XML_gridLines, false ); + maOoxData.mbPrintHeadings = rAttribs.getBool( XML_headings, false ); +} + +void PageSettings::importHeaderFooter( const AttributeList& rAttribs ) +{ + maOoxData.mbUseEvenHF = rAttribs.getBool( XML_differentOddEven, false ); + maOoxData.mbUseFirstHF = rAttribs.getBool( XML_differentFirst, false ); +} + +void PageSettings::importHeaderFooterCharacters( const OUString& rChars, sal_Int32 nElement ) +{ + switch( nElement ) + { + case XLS_TOKEN( oddHeader ): maOoxData.maOddHeader += rChars; break; + case XLS_TOKEN( oddFooter ): maOoxData.maOddFooter += rChars; break; + case XLS_TOKEN( evenHeader ): maOoxData.maEvenHeader += rChars; break; + case XLS_TOKEN( evenFooter ): maOoxData.maEvenFooter += rChars; break; + case XLS_TOKEN( firstHeader ): maOoxData.maFirstHeader += rChars; break; + case XLS_TOKEN( firstFooter ): maOoxData.maFirstFooter += rChars; break; + } +} + +void PageSettings::importPageMargins( RecordInputStream& rStrm ) +{ + rStrm >> maOoxData.mfLeftMargin >> maOoxData.mfRightMargin + >> maOoxData.mfTopMargin >> maOoxData.mfBottomMargin + >> maOoxData.mfHeaderMargin >> maOoxData.mfFooterMargin; +} + +void PageSettings::importPageSetup( RecordInputStream& rStrm ) +{ + sal_uInt16 nFlags; + rStrm >> maOoxData.mnPaperSize >> maOoxData.mnScale + >> maOoxData.mnHorPrintRes >> maOoxData.mnVerPrintRes + >> maOoxData.mnCopies >> maOoxData.mnFirstPage + >> maOoxData.mnFitToWidth >> maOoxData.mnFitToHeight + >> nFlags >> maOoxData.maRelId; + maOoxData.setBinPrintErrors( extractValue< sal_uInt8 >( nFlags, 9, 2 ) ); + maOoxData.mnOrientation = getFlagValue( nFlags, OOBIN_PAGESETUP_DEFAULTORIENT, XML_default, getFlagValue( nFlags, OOBIN_PAGESETUP_LANDSCAPE, XML_landscape, XML_portrait ) ); + maOoxData.mnPageOrder = getFlagValue( nFlags, OOBIN_PAGESETUP_INROWS, XML_overThenDown, XML_downThenOver ); + maOoxData.mnCellComments = getFlagValue( nFlags, OOBIN_PAGESETUP_PRINTNOTES, getFlagValue( nFlags, OOBIN_PAGESETUP_NOTES_END, XML_atEnd, XML_asDisplayed ), XML_none ); + maOoxData.mbValidSettings = !getFlag( nFlags, OOBIN_PAGESETUP_INVALID ); + maOoxData.mbUseFirstPage = getFlag( nFlags, OOBIN_PAGESETUP_USEFIRSTPAGE ); + maOoxData.mbBlackWhite = getFlag( nFlags, OOBIN_PAGESETUP_BLACKWHITE ); + maOoxData.mbDraftQuality = getFlag( nFlags, OOBIN_PAGESETUP_DRAFTQUALITY ); +} + +void PageSettings::importPrintOptions( RecordInputStream& rStrm ) +{ + sal_uInt16 nFlags; + rStrm >> nFlags; + maOoxData.mbHorCenter = getFlag( nFlags, OOBIN_PRINTOPT_HORCENTER ); + maOoxData.mbVerCenter = getFlag( nFlags, OOBIN_PRINTOPT_VERCENTER ); + maOoxData.mbPrintGrid = getFlag( nFlags, OOBIN_PRINTOPT_PRINTGRID ); + maOoxData.mbPrintHeadings = getFlag( nFlags, OOBIN_PRINTOPT_PRINTHEADING ); +} + +void PageSettings::importHeaderFooter( RecordInputStream& rStrm ) +{ + sal_uInt16 nFlags; + rStrm >> nFlags + >> maOoxData.maOddHeader >> maOoxData.maOddFooter + >> maOoxData.maEvenHeader >> maOoxData.maEvenFooter + >> maOoxData.maFirstHeader >> maOoxData.maFirstFooter; + maOoxData.mbUseEvenHF = getFlag( nFlags, OOBIN_HEADERFOOTER_DIFFEVEN ); + maOoxData.mbUseFirstHF = getFlag( nFlags, OOBIN_HEADERFOOTER_DIFFFIRST ); +} + +void PageSettings::importLeftMargin( BiffInputStream& rStrm ) +{ + rStrm >> maOoxData.mfLeftMargin; +} + +void PageSettings::importRightMargin( BiffInputStream& rStrm ) +{ + rStrm >> maOoxData.mfRightMargin; +} + +void PageSettings::importTopMargin( BiffInputStream& rStrm ) +{ + rStrm >> maOoxData.mfTopMargin; +} + +void PageSettings::importBottomMargin( BiffInputStream& rStrm ) +{ + rStrm >> maOoxData.mfBottomMargin; +} + +void PageSettings::importPageSetup( BiffInputStream& rStrm ) +{ + sal_uInt16 nPaperSize, nScale, nFirstPage, nFitToWidth, nFitToHeight, nFlags; + rStrm >> nPaperSize >> nScale >> nFirstPage >> nFitToWidth >> nFitToHeight >> nFlags; + + maOoxData.mnPaperSize = nPaperSize; // equal in BIFF and OOX + maOoxData.mnScale = nScale; + maOoxData.mnFirstPage = nFirstPage; + maOoxData.mnFitToWidth = nFitToWidth; + maOoxData.mnFitToHeight = nFitToHeight; + maOoxData.mnOrientation = getFlagValue( nFlags, BIFF_PAGESETUP_PORTRAIT, XML_portrait, XML_landscape ); + maOoxData.mnPageOrder = getFlagValue( nFlags, BIFF_PAGESETUP_INROWS, XML_overThenDown, XML_downThenOver ); + maOoxData.mbValidSettings = !getFlag( nFlags, BIFF_PAGESETUP_INVALID ); + maOoxData.mbUseFirstPage = true; + maOoxData.mbBlackWhite = getFlag( nFlags, BIFF_PAGESETUP_BLACKWHITE ); + + if( getBiff() >= BIFF5 ) + { + sal_uInt16 nHorPrintRes, nVerPrintRes, nCopies; + rStrm >> nHorPrintRes >> nVerPrintRes >> maOoxData.mfHeaderMargin >> maOoxData.mfFooterMargin >> nCopies; + + maOoxData.mnCopies = nCopies; + maOoxData.mnOrientation = getFlagValue( nFlags, BIFF_PAGESETUP_DEFAULTORIENT, XML_default, maOoxData.mnOrientation ); + maOoxData.mnHorPrintRes = nHorPrintRes; + maOoxData.mnVerPrintRes = nVerPrintRes; + maOoxData.mnCellComments = getFlagValue( nFlags, BIFF_PAGESETUP_PRINTNOTES, XML_asDisplayed, XML_none ); + maOoxData.mbUseFirstPage = getFlag( nFlags, BIFF_PAGESETUP_USEFIRSTPAGE ); + maOoxData.mbDraftQuality = getFlag( nFlags, BIFF_PAGESETUP_DRAFTQUALITY ); + + if( getBiff() == BIFF8 ) + { + maOoxData.setBinPrintErrors( extractValue< sal_uInt8 >( nFlags, 10, 2 ) ); + maOoxData.mnCellComments = getFlagValue( nFlags, BIFF_PAGESETUP_PRINTNOTES, getFlagValue( nFlags, BIFF_PAGESETUP_NOTES_END, XML_atEnd, XML_asDisplayed ), XML_none ); + } + } +} + +void PageSettings::importHorCenter( BiffInputStream& rStrm ) +{ + maOoxData.mbHorCenter = rStrm.readuInt16() != 0; +} + +void PageSettings::importVerCenter( BiffInputStream& rStrm ) +{ + maOoxData.mbVerCenter = rStrm.readuInt16() != 0; +} + +void PageSettings::importPrintHeaders( BiffInputStream& rStrm ) +{ + maOoxData.mbPrintHeadings = rStrm.readuInt16() != 0; +} + +void PageSettings::importPrintGridLines( BiffInputStream& rStrm ) +{ + maOoxData.mbPrintGrid = rStrm.readuInt16() != 0; +} + +void PageSettings::importHeader( BiffInputStream& rStrm ) +{ + if( rStrm.getRecLeft() > 0 ) + maOoxData.maOddHeader = (getBiff() == BIFF8) ? rStrm.readUniString() : rStrm.readByteString( false, getTextEncoding() ); + else + maOoxData.maOddHeader = OUString(); +} + +void PageSettings::importFooter( BiffInputStream& rStrm ) +{ + if( rStrm.getRecLeft() > 0 ) + maOoxData.maOddFooter = (getBiff() == BIFF8) ? rStrm.readUniString() : rStrm.readByteString( false, getTextEncoding() ); + else + maOoxData.maOddFooter = OUString(); +} + +void PageSettings::setFitToPagesMode( bool bFitToPages ) +{ + maOoxData.mbFitToPages = bFitToPages; +} + +void PageSettings::finalizeImport() +{ + OUStringBuffer aStyleNameBuffer( CREATE_OUSTRING( "PageStyle_" ) ); + Reference< XNamed > xSheetName( getXSpreadsheet(), UNO_QUERY ); + if( xSheetName.is() ) + aStyleNameBuffer.append( xSheetName->getName() ); + else + aStyleNameBuffer.append( static_cast< sal_Int32 >( getSheetIndex() + 1 ) ); + OUString aStyleName = aStyleNameBuffer.makeStringAndClear(); + + Reference< XStyle > xStyle = createStyleObject( aStyleName, true ); + PropertySet aStyleProps( xStyle ); + getPageSettingsPropertyHelper().writePageSettingsProperties( aStyleProps, maOoxData, getSheetType() ); + + PropertySet aSheetProps( getXSpreadsheet() ); + aSheetProps.setProperty( CREATE_OUSTRING( "PageStyle" ), aStyleName ); +} + +// ============================================================================ + +namespace { + +/** Property names for page style settings. */ +const sal_Char* const sppcPageNames[] = +{ + "IsLandscape", + "FirstPageNumber", + "PrintDownFirst", + "PrintAnnotations", + "CenterHorizontally", + "CenterVertically", + "PrintGrid", + "PrintHeaders", + "LeftMargin", + "RightMargin", + "TopMargin", + "BottomMargin", + "HeaderIsOn", + "HeaderIsShared", + "HeaderIsDynamicHeight", + "HeaderHeight", + "HeaderBodyDistance", + "FooterIsOn", + "FooterIsShared", + "FooterIsDynamicHeight", + "FooterHeight", + "FooterBodyDistance", + 0 +}; + +/** Paper size in 1/100 millimeters. */ +struct ApiPaperSize +{ + sal_Int32 mnWidth; + sal_Int32 mnHeight; +}; + +#define IN2MM100( v ) static_cast< sal_Int32 >( (v) * 2540.0 + 0.5 ) +#define MM2MM100( v ) static_cast< sal_Int32 >( (v) * 100.0 + 0.5 ) + +static const ApiPaperSize spPaperSizeTable[] = +{ + { 0, 0 }, // 0 - (undefined) + { IN2MM100( 8.5 ), IN2MM100( 11 ) }, // 1 - Letter paper + { IN2MM100( 8.5 ), IN2MM100( 11 ) }, // 2 - Letter small paper + { IN2MM100( 11 ), IN2MM100( 17 ) }, // 3 - Tabloid paper + { IN2MM100( 17 ), IN2MM100( 11 ) }, // 4 - Ledger paper + { IN2MM100( 8.5 ), IN2MM100( 14 ) }, // 5 - Legal paper + { IN2MM100( 5.5 ), IN2MM100( 8.5 ) }, // 6 - Statement paper + { IN2MM100( 7.25 ), IN2MM100( 10.5 ) }, // 7 - Executive paper + { MM2MM100( 297 ), MM2MM100( 420 ) }, // 8 - A3 paper + { MM2MM100( 210 ), MM2MM100( 297 ) }, // 9 - A4 paper + { MM2MM100( 210 ), MM2MM100( 297 ) }, // 10 - A4 small paper + { MM2MM100( 148 ), MM2MM100( 210 ) }, // 11 - A5 paper + { MM2MM100( 250 ), MM2MM100( 353 ) }, // 12 - B4 paper + { MM2MM100( 176 ), MM2MM100( 250 ) }, // 13 - B5 paper + { IN2MM100( 8.5 ), IN2MM100( 13 ) }, // 14 - Folio paper + { MM2MM100( 215 ), MM2MM100( 275 ) }, // 15 - Quarto paper + { IN2MM100( 10 ), IN2MM100( 14 ) }, // 16 - Standard paper + { IN2MM100( 11 ), IN2MM100( 17 ) }, // 17 - Standard paper + { IN2MM100( 8.5 ), IN2MM100( 11 ) }, // 18 - Note paper + { IN2MM100( 3.875 ), IN2MM100( 8.875 ) }, // 19 - #9 envelope + { IN2MM100( 4.125 ), IN2MM100( 9.5 ) }, // 20 - #10 envelope + { IN2MM100( 4.5 ), IN2MM100( 10.375 ) }, // 21 - #11 envelope + { IN2MM100( 4.75 ), IN2MM100( 11 ) }, // 22 - #12 envelope + { IN2MM100( 5 ), IN2MM100( 11.5 ) }, // 23 - #14 envelope + { IN2MM100( 17 ), IN2MM100( 22 ) }, // 24 - C paper + { IN2MM100( 22 ), IN2MM100( 34 ) }, // 25 - D paper + { IN2MM100( 34 ), IN2MM100( 44 ) }, // 26 - E paper + { MM2MM100( 110 ), MM2MM100( 220 ) }, // 27 - DL envelope + { MM2MM100( 162 ), MM2MM100( 229 ) }, // 28 - C5 envelope + { MM2MM100( 324 ), MM2MM100( 458 ) }, // 29 - C3 envelope + { MM2MM100( 229 ), MM2MM100( 324 ) }, // 30 - C4 envelope + { MM2MM100( 114 ), MM2MM100( 162 ) }, // 31 - C6 envelope + { MM2MM100( 114 ), MM2MM100( 229 ) }, // 32 - C65 envelope + { MM2MM100( 250 ), MM2MM100( 353 ) }, // 33 - B4 envelope + { MM2MM100( 176 ), MM2MM100( 250 ) }, // 34 - B5 envelope + { MM2MM100( 176 ), MM2MM100( 125 ) }, // 35 - B6 envelope + { MM2MM100( 110 ), MM2MM100( 230 ) }, // 36 - Italy envelope + { IN2MM100( 3.875 ), IN2MM100( 7.5 ) }, // 37 - Monarch envelope + { IN2MM100( 3.625 ), IN2MM100( 6.5 ) }, // 38 - 6 3/4 envelope + { IN2MM100( 14.875 ), IN2MM100( 11 ) }, // 39 - US standard fanfold + { IN2MM100( 8.5 ), IN2MM100( 12 ) }, // 40 - German standard fanfold + { IN2MM100( 8.5 ), IN2MM100( 13 ) }, // 41 - German legal fanfold + { MM2MM100( 250 ), MM2MM100( 353 ) }, // 42 - ISO B4 + { MM2MM100( 200 ), MM2MM100( 148 ) }, // 43 - Japanese double postcard + { IN2MM100( 9 ), IN2MM100( 11 ) }, // 44 - Standard paper + { IN2MM100( 10 ), IN2MM100( 11 ) }, // 45 - Standard paper + { IN2MM100( 15 ), IN2MM100( 11 ) }, // 46 - Standard paper + { MM2MM100( 220 ), MM2MM100( 220 ) }, // 47 - Invite envelope + { 0, 0 }, // 48 - (undefined) + { 0, 0 }, // 49 - (undefined) + { IN2MM100( 9.275 ), IN2MM100( 12 ) }, // 50 - Letter extra paper + { IN2MM100( 9.275 ), IN2MM100( 15 ) }, // 51 - Legal extra paper + { IN2MM100( 11.69 ), IN2MM100( 18 ) }, // 52 - Tabloid extra paper + { MM2MM100( 236 ), MM2MM100( 322 ) }, // 53 - A4 extra paper + { IN2MM100( 8.275 ), IN2MM100( 11 ) }, // 54 - Letter transverse paper + { MM2MM100( 210 ), MM2MM100( 297 ) }, // 55 - A4 transverse paper + { IN2MM100( 9.275 ), IN2MM100( 12 ) }, // 56 - Letter extra transverse paper + { MM2MM100( 227 ), MM2MM100( 356 ) }, // 57 - SuperA/SuperA/A4 paper + { MM2MM100( 305 ), MM2MM100( 487 ) }, // 58 - SuperB/SuperB/A3 paper + { IN2MM100( 8.5 ), IN2MM100( 12.69 ) }, // 59 - Letter plus paper + { MM2MM100( 210 ), MM2MM100( 330 ) }, // 60 - A4 plus paper + { MM2MM100( 148 ), MM2MM100( 210 ) }, // 61 - A5 transverse paper + { MM2MM100( 182 ), MM2MM100( 257 ) }, // 62 - JIS B5 transverse paper + { MM2MM100( 322 ), MM2MM100( 445 ) }, // 63 - A3 extra paper + { MM2MM100( 174 ), MM2MM100( 235 ) }, // 64 - A5 extra paper + { MM2MM100( 201 ), MM2MM100( 276 ) }, // 65 - ISO B5 extra paper + { MM2MM100( 420 ), MM2MM100( 594 ) }, // 66 - A2 paper + { MM2MM100( 297 ), MM2MM100( 420 ) }, // 67 - A3 transverse paper + { MM2MM100( 322 ), MM2MM100( 445 ) } // 68 - A3 extra transverse paper +}; + +} // namespace + +// ---------------------------------------------------------------------------- + +PageSettingsPropertyHelper::HFHelperData::HFHelperData( const OUString& rLeftProp, const OUString& rRightProp ) : + maLeftProp( rLeftProp ), + maRightProp( rRightProp ), + mnHeight( 0 ), + mnBodyDist( 0 ), + mbHasContent( false ), + mbShareOddEven( false ), + mbDynamicHeight( false ) +{ +} + +// ---------------------------------------------------------------------------- + +PageSettingsPropertyHelper::PageSettingsPropertyHelper( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + maHFParser( rHelper ), + maPageProps( sppcPageNames ), + maHeaderData( CREATE_OUSTRING( "LeftPageHeaderContent" ), CREATE_OUSTRING( "RightPageHeaderContent" ) ), + maFooterData( CREATE_OUSTRING( "LeftPageFooterContent" ), CREATE_OUSTRING( "RightPageFooterContent" ) ) +{ +} + +void PageSettingsPropertyHelper::writePageSettingsProperties( + PropertySet& rPropSet, const OoxPageData& rData, WorksheetType eSheetType ) +{ + // printout scaling + if( rData.mbFitToPages ) + { + // fit to number of pages + rPropSet.setProperty( CREATE_OUSTRING( "ScaleToPagesX" ), getLimitedValue< sal_Int16, sal_Int32 >( rData.mnFitToWidth, 0, 1000 ) ); + rPropSet.setProperty( CREATE_OUSTRING( "ScaleToPagesY" ), getLimitedValue< sal_Int16, sal_Int32 >( rData.mnFitToHeight, 0, 1000 ) ); + } + else + { + // scale may be 0 which indicates uninitialized + sal_Int16 nScale = (rData.mbValidSettings && (rData.mnScale > 0)) ? getLimitedValue< sal_Int16, sal_Int32 >( rData.mnScale, 10, 400 ) : 100; + rPropSet.setProperty( CREATE_OUSTRING( "PageScale" ), nScale ); + } + + // paper orientation + bool bLandscape = rData.mnOrientation == XML_landscape; + // default orientation for current sheet type (chart sheets default to landscape) + if( !rData.mbValidSettings || (rData.mnOrientation == XML_default) ) switch( eSheetType ) + { + case SHEETTYPE_WORKSHEET: bLandscape = false; break; + case SHEETTYPE_CHART: bLandscape = true; break; + case SHEETTYPE_MACRO: bLandscape = false; break; + } + + // paper size + if( rData.mbValidSettings && (0 < rData.mnPaperSize) && (rData.mnPaperSize < static_cast< sal_Int32 >( STATIC_ARRAY_SIZE( spPaperSizeTable ) )) ) + { + const ApiPaperSize& rPaperSize = spPaperSizeTable[ rData.mnPaperSize ]; + ::com::sun::star::awt::Size aSize( rPaperSize.mnWidth, rPaperSize.mnHeight ); + if( bLandscape ) + ::std::swap( aSize.Width, aSize.Height ); + rPropSet.setProperty( CREATE_OUSTRING( "Size" ), aSize ); + } + + // header/footer + convertHeaderFooterData( rPropSet, maHeaderData, rData.maOddHeader, rData.maEvenHeader, rData.mbUseEvenHF, rData.mfTopMargin, rData.mfHeaderMargin ); + convertHeaderFooterData( rPropSet, maFooterData, rData.maOddFooter, rData.maEvenFooter, rData.mbUseEvenHF, rData.mfBottomMargin, rData.mfFooterMargin ); + + // write all properties to property set + const UnitConverter& rUnitConv = getUnitConverter(); + maPageProps + << bLandscape + << getLimitedValue< sal_Int16, sal_Int32 >( rData.mbUseFirstPage ? rData.mnFirstPage : 0, 0, 9999 ) + << (rData.mnPageOrder == XML_downThenOver) + << (rData.mnCellComments == XML_asDisplayed) + << rData.mbHorCenter + << rData.mbVerCenter + << rData.mbPrintGrid + << rData.mbPrintHeadings + << rUnitConv.calcMm100FromInches( rData.mfLeftMargin ) + << rUnitConv.calcMm100FromInches( rData.mfRightMargin ) + // #i23296# In Calc, "TopMargin" property is distance to top of header if enabled + << rUnitConv.calcMm100FromInches( maHeaderData.mbHasContent ? rData.mfHeaderMargin : rData.mfTopMargin ) + // #i23296# In Calc, "BottomMargin" property is distance to bottom of footer if enabled + << rUnitConv.calcMm100FromInches( maFooterData.mbHasContent ? rData.mfFooterMargin : rData.mfBottomMargin ) + << maHeaderData.mbHasContent + << maHeaderData.mbShareOddEven + << maHeaderData.mbDynamicHeight + << maHeaderData.mnHeight + << maHeaderData.mnBodyDist + << maFooterData.mbHasContent + << maFooterData.mbShareOddEven + << maFooterData.mbDynamicHeight + << maFooterData.mnHeight + << maFooterData.mnBodyDist + >> rPropSet; +} + +void PageSettingsPropertyHelper::convertHeaderFooterData( + PropertySet& rPropSet, HFHelperData& rHFData, + const OUString rOddContent, const OUString rEvenContent, bool bUseEvenContent, + double fPageMargin, double fContentMargin ) +{ + bool bHasOddContent = rOddContent.getLength() > 0; + bool bHasEvenContent = bUseEvenContent && (rEvenContent.getLength() > 0); + + sal_Int32 nOddHeight = bHasOddContent ? writeHeaderFooter( rPropSet, rHFData.maRightProp, rOddContent ) : 0; + sal_Int32 nEvenHeight = bHasEvenContent ? writeHeaderFooter( rPropSet, rHFData.maLeftProp, rEvenContent ) : 0; + + rHFData.mnHeight = 750; + rHFData.mnBodyDist = 250; + rHFData.mbHasContent = bHasOddContent || bHasEvenContent; + rHFData.mbShareOddEven = !bUseEvenContent; + rHFData.mbDynamicHeight = true; + + if( rHFData.mbHasContent ) + { + // use maximum height of odd/even header/footer + rHFData.mnHeight = ::std::max( nOddHeight, nEvenHeight ); + /* Calc contains distance between bottom of header and top of page + body in "HeaderBodyDistance" property, and distance between bottom + of page body and top of footer in "FooterBodyDistance" property */ + rHFData.mnBodyDist = getUnitConverter().calcMm100FromInches( fPageMargin - fContentMargin ) - rHFData.mnHeight; + /* #i23296# Distance less than 0 means, header or footer overlays page + body. As this is not possible in Calc, set fixed header or footer + height (crop header/footer) to get correct top position of page body. */ + rHFData.mbDynamicHeight = rHFData.mnBodyDist >= 0; + /* "HeaderHeight" property is in fact distance from top of header to + top of page body (including "HeaderBodyDistance"). + "FooterHeight" property is in fact distance from bottom of page + body to bottom of footer (including "FooterBodyDistance"). */ + rHFData.mnHeight += rHFData.mnBodyDist; + // negative body distance not allowed + rHFData.mnBodyDist = ::std::max< sal_Int32 >( rHFData.mnBodyDist, 0 ); + } +} + +sal_Int32 PageSettingsPropertyHelper::writeHeaderFooter( + PropertySet& rPropSet, const OUString& rPropName, const OUString& rContent ) +{ + OSL_ENSURE( rContent.getLength() > 0, "PageSettingsPropertyHelper::writeHeaderFooter - empty h/f string found" ); + sal_Int32 nHeight = 0; + if( rContent.getLength() > 0 ) + { + Reference< XHeaderFooterContent > xHFContent; + if( rPropSet.getProperty( xHFContent, rPropName ) && xHFContent.is() ) + { + maHFParser.parse( xHFContent, rContent ); + rPropSet.setProperty( rPropName, xHFContent ); + nHeight = getUnitConverter().calcMm100FromPoints( maHFParser.getTotalHeight() ); + } + } + return nHeight; +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/pivotcachefragment.cxx b/oox/source/xls/pivotcachefragment.cxx new file mode 100644 index 000000000000..adc7fe2076cb --- /dev/null +++ b/oox/source/xls/pivotcachefragment.cxx @@ -0,0 +1,160 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: pivotcachefragment.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/pivotcachefragment.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/xls/addressconverter.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::sheet::XSpreadsheet; +using ::com::sun::star::table::CellRangeAddress; +using ::com::sun::star::xml::sax::SAXException; + +namespace oox { +namespace xls { + +OoxPivotCacheFragment::OoxPivotCacheFragment( const WorkbookHelper& rHelper, + const OUString& rFragmentPath, + sal_uInt32 nCacheId ) : + OoxWorkbookFragmentBase( rHelper, rFragmentPath ), + mnCacheId( nCacheId ), + mbValidSource( false ) +{ +} + +bool OoxPivotCacheFragment::onCanCreateContext( sal_Int32 nElement ) const +{ + switch( getCurrentContext() ) + { + case XML_ROOT_CONTEXT: return nElement == XLS_TOKEN( pivotCacheDefinition ); + case XLS_TOKEN( pivotCacheDefinition ): return (nElement == XLS_TOKEN( cacheSource ) || + nElement == XLS_TOKEN( cacheFields )); + case XLS_TOKEN( cacheSource ): return nElement == XLS_TOKEN( worksheetSource ); + case XLS_TOKEN( cacheFields ): return nElement == XLS_TOKEN( cacheField ); + case XLS_TOKEN( cacheField ): return nElement == XLS_TOKEN( sharedItems ); + case XLS_TOKEN( sharedItems ): return nElement == XLS_TOKEN( s ); + } + return false; +} + +void OoxPivotCacheFragment::onStartElement( const AttributeList& rAttribs ) +{ + switch ( getCurrentContext() ) + { + case XLS_TOKEN( pivotCacheDefinition ): + importPivotCacheDefinition( rAttribs ); + break; + case XLS_TOKEN( cacheSource ): + importCacheSource( rAttribs ); + break; + case XLS_TOKEN( worksheetSource ): + if ( mbValidSource ) + importWorksheetSource( rAttribs ); + break; + case XLS_TOKEN( cacheFields ): + if ( mbValidSource ) + maPCacheData.maFields.reserve( rAttribs.getUnsignedInteger(XML_count, 1) ); + break; + case XLS_TOKEN( cacheField ): + if ( mbValidSource ) + importCacheField( rAttribs ); + break; + case XLS_TOKEN( sharedItems ): + if ( mbValidSource ) + maPCacheData.maFields.back().maItems.reserve( rAttribs.getUnsignedInteger(XML_count, 1) ); + break; + case XLS_TOKEN( s ): + if ( mbValidSource ) + maPCacheData.maFields.back().maItems.push_back( rAttribs.getString( XML_v ) ); + break; + } +} + +void OoxPivotCacheFragment::finalizeImport() +{ + if( mbValidSource ) + getPivotTables().setPivotCache( mnCacheId, maPCacheData ); +} + +void OoxPivotCacheFragment::importPivotCacheDefinition( const AttributeList& /*rAttribs*/ ) +{ +} + +void OoxPivotCacheFragment::importCacheSource( const AttributeList& rAttribs ) +{ + switch ( rAttribs.getToken(XML_type) ) + { + case XML_worksheet: + maPCacheData.meSourceType = PivotCacheData::WORKSHEET; + maPCacheData.mpSourceProp.reset( new PivotCacheData::WorksheetSource ); + mbValidSource = true; + break; + case XML_external: + maPCacheData.meSourceType = PivotCacheData::EXTERNAL; + maPCacheData.mpSourceProp.reset( new PivotCacheData::ExternalSource ); + mbValidSource = true; + break; + default: + // unsupported case source type. + break; + } +} + +void OoxPivotCacheFragment::importWorksheetSource( const AttributeList& rAttribs ) +{ + if ( maPCacheData.meSourceType != PivotCacheData::WORKSHEET ) + return; + + PivotCacheData::WorksheetSource* pSrc = static_cast( + maPCacheData.mpSourceProp.get() ); + + pSrc->maSrcRange = rAttribs.getString( XML_ref ); + pSrc->maSheetName = rAttribs.getString( XML_sheet ); +} + +void OoxPivotCacheFragment::importCacheField( const AttributeList& rAttribs ) +{ + PivotCacheField aField; + aField.maName = rAttribs.getString( XML_name ); + maPCacheData.maFields.push_back(aField); +} + +} // namespace xls +} // namespace oox diff --git a/oox/source/xls/pivottablebuffer.cxx b/oox/source/xls/pivottablebuffer.cxx new file mode 100644 index 000000000000..08e61b8a16d5 --- /dev/null +++ b/oox/source/xls/pivottablebuffer.cxx @@ -0,0 +1,275 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: pivottablebuffer.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/pivottablebuffer.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/xls/addressconverter.hxx" +#include "oox/xls/worksheetbuffer.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using ::com::sun::star::container::XIndexAccess; +using ::com::sun::star::container::XNameAccess; +using ::com::sun::star::container::XNamed; +using ::com::sun::star::sheet::XCellRangeData; +using ::com::sun::star::sheet::XDataPilotDescriptor; +using ::com::sun::star::sheet::XDataPilotField; +using ::com::sun::star::sheet::XDataPilotTables; +using ::com::sun::star::sheet::XDataPilotTablesSupplier; +using ::com::sun::star::sheet::XSheetFilterDescriptor; +using ::com::sun::star::sheet::XSpreadsheet; +using ::com::sun::star::table::CellAddress; +using ::com::sun::star::table::CellRangeAddress; +using ::com::sun::star::table::XCellRange; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::rtl::OUString; + +namespace oox { +namespace xls { + +// ============================================================================ + +PivotCacheData::PivotCacheData() : + meSourceType( WORKSHEET ), + mpSourceProp( static_cast(NULL) ) +{ +} + +PivotCacheData::WorksheetSource* PivotCacheData::getWorksheetSource() const +{ + if ( meSourceType != WORKSHEET ) + return NULL; + return static_cast( mpSourceProp.get() ); +} + +PivotCacheData::ExternalSource* PivotCacheData::getExternalSource() const +{ + if ( meSourceType != EXTERNAL ) + return NULL; + return static_cast( mpSourceProp.get() ); +} + +// ============================================================================ + +PivotTableField::PivotTableField() : + meAxis( ROW ), + mbDataField( false ) +{ +} + +// ---------------------------------------------------------------------------- + +PivotTableData::PivotTableData() +{ +} + +// ---------------------------------------------------------------------------- + +PivotTableBuffer::PivotTableBuffer( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ) +{ +} + +const PivotCacheData* PivotTableBuffer::getPivotCache( sal_uInt32 nCacheId ) const +{ + PivotCacheMapType::const_iterator itr = maPivotCacheMap.find(nCacheId), + itrEnd = maPivotCacheMap.end(); + + if ( itr != itrEnd ) + return &itr->second; + + return NULL; +} + +void PivotTableBuffer::setPivotCache( sal_uInt32 nCacheId, const PivotCacheData& aData ) +{ + maPivotCacheMap.insert( PivotCacheMapType::value_type(nCacheId, aData) ); +} + +PivotTableData* PivotTableBuffer::getPivotTable( const OUString& aName ) +{ + PivotTableMapType::iterator itr = maPivotTableMap.find(aName), + itrEnd = maPivotTableMap.end(); + + if ( itr != itrEnd ) + return &itr->second; + + return NULL; +} + +void PivotTableBuffer::setPivotTable( const OUString& aName, const PivotTableData& aData ) +{ + maPivotTableMap.insert( PivotTableMapType::value_type(aName, aData) ); + maCellRangeMap.addCellRange( aData.maRange ); +} + +bool PivotTableBuffer::isOverlapping( const CellAddress& aCellAddress ) const +{ + return maCellRangeMap.isOverlapping(aCellAddress); +} + +void PivotTableBuffer::finalizeImport() const +{ + PivotTableMapType::const_iterator itr = maPivotTableMap.begin(), itrEnd = maPivotTableMap.end(); + for ( ; itr != itrEnd; ++itr ) + writePivotTable( itr->first, itr->second ); +} + +void PivotTableBuffer::writePivotTable( const OUString& aName, const PivotTableData& aData ) const +{ + using namespace ::com::sun::star::sheet; + + const PivotCacheData* pCache = getPivotCache( aData.mnCacheId ); + if ( !pCache ) + { + OSL_ENSURE( false, "OoxPivotTableFragment::commit: pivot cache data not found" ); + return; + } + + const CellRangeAddress& aRange = aData.maRange; + Reference< XSpreadsheet > xSheet = getSheet( aRange.Sheet ); + if ( !xSheet.is() ) + return; + + try + { + Reference< XDataPilotTablesSupplier > xDPTSupplier( xSheet, UNO_QUERY_THROW ); + + Reference< XDataPilotTables > xDPTables( xDPTSupplier->getDataPilotTables(), UNO_QUERY_THROW ); + Reference< XDataPilotDescriptor > xDPDesc( xDPTables->createDataPilotDescriptor(), UNO_QUERY_THROW ); + if ( pCache->meSourceType != PivotCacheData::WORKSHEET ) + return; + + PivotCacheData::WorksheetSource* pSrc = pCache->getWorksheetSource(); + if ( !pSrc ) + return; + + OUString sheetname = pSrc->maSheetName; + OUString srcrange = pSrc->maSrcRange; + + CellRangeAddress aSrcRange; + if ( !getSourceRange( pSrc->maSheetName, pSrc->maSrcRange, aSrcRange ) ) + return; + + xDPDesc->setSourceRange(aSrcRange); + Reference< XIndexAccess > xIA = xDPDesc->getDataPilotFields(); + + bool bPageAxisExists = false; + + // Go through all fields in pivot table, and register them. + sal_Int32 nCount = ::std::min( xIA->getCount(), static_cast(aData.maFields.size()) ); + for ( sal_Int32 i = 0; i < nCount; ++i ) + { + Reference< XDataPilotField > xField( xIA->getByIndex(i), UNO_QUERY_THROW ); + PropertySet aProp( xField ); + Reference< XNamed > xNamed( xField, UNO_QUERY_THROW ); + + PivotTableField::AxisType eAxis = aData.maFields[i].meAxis; + if ( aData.maFields[i].mbDataField ) + eAxis = PivotTableField::VALUES; + + switch ( eAxis ) + { + case PivotTableField::COLUMN: + aProp.setProperty( CREATE_OUSTRING("Orientation"), DataPilotFieldOrientation_COLUMN ); + break; + case PivotTableField::ROW: + aProp.setProperty( CREATE_OUSTRING("Orientation"), DataPilotFieldOrientation_ROW ); + break; + case PivotTableField::PAGE: + bPageAxisExists = true; + aProp.setProperty( CREATE_OUSTRING("Orientation"), DataPilotFieldOrientation_PAGE ); + break; + case PivotTableField::VALUES: + aProp.setProperty( CREATE_OUSTRING("Orientation"), DataPilotFieldOrientation_DATA ); + break; + default: + OSL_ENSURE( false, "OoxPivotTableFragment::commit: unhandled case" ); + } + } + CellAddress aCell; + aCell.Sheet = aData.maRange.Sheet; + aCell.Column = aData.maRange.StartColumn; + aCell.Row = aData.maRange.StartRow; + if ( bPageAxisExists ) + aCell.Row -= 2; + + xDPTables->insertNewByName( aName, aCell, xDPDesc ); + } + catch ( const Exception& ) + { + OSL_ENSURE( false, "OoxPivotTableFragment::commit: exception thrown"); + return; + } +} + +bool PivotTableBuffer::getSourceRange( const OUString& aSheetName, const OUString& aRefName, + CellRangeAddress& rRange ) const +{ + sal_Int32 nCount = getWorksheets().getInternalSheetCount(); + for ( sal_Int32 nSheet = 0; nSheet < nCount; ++nSheet ) + { + Reference< XNamed > xNamed( getSheet( nSheet ), UNO_QUERY ); + if ( xNamed.is() && !aSheetName.compareTo( xNamed->getName() ) ) + return getAddressConverter().convertToCellRange( + rRange, aRefName, static_cast< sal_Int16 >( nSheet ), true ); + } + return false; +} + +// ============================================================================ + +} // namespace xls +} // namespace oox diff --git a/oox/source/xls/pivottablefragment.cxx b/oox/source/xls/pivottablefragment.cxx new file mode 100644 index 000000000000..48f99cb4d41c --- /dev/null +++ b/oox/source/xls/pivottablefragment.cxx @@ -0,0 +1,194 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: pivottablefragment.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/pivottablefragment.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/xls/addressconverter.hxx" + +#define DEBUG_OOX_PIVOTTABLE 1 + +#include +#include +#if DEBUG_OOX_PIVOTTABLE +#include +#endif + +using ::rtl::OUString; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::table::CellRangeAddress; +using ::com::sun::star::xml::sax::SAXException; + +namespace oox { +namespace xls { + +OoxPivotTableFragment::OoxPivotTableFragment( + const WorksheetHelper& rHelper, const OUString& rFragmentPath ) : + OoxWorksheetFragmentBase( rHelper, rFragmentPath ), + mbValidRange( false ) +{ +} + +bool OoxPivotTableFragment::onCanCreateContext( sal_Int32 nElement ) const +{ + switch( getCurrentContext() ) + { + case XML_ROOT_CONTEXT: return (nElement == XLS_TOKEN( pivotTableDefinition )); + case XLS_TOKEN( pivotTableDefinition ): return (nElement == XLS_TOKEN( location )) || + (nElement == XLS_TOKEN( pivotFields )) || + (nElement == XLS_TOKEN( rowFields )) || + (nElement == XLS_TOKEN( rowItems )) || + (nElement == XLS_TOKEN( colFields )) || + (nElement == XLS_TOKEN( colItems )) || + (nElement == XLS_TOKEN( pageFields )) || + (nElement == XLS_TOKEN( dataFields )) || + (nElement == XLS_TOKEN( pivotTableStyleInfo )); + case XLS_TOKEN( pivotFields ): return (nElement == XLS_TOKEN( pivotField )); + case XLS_TOKEN( pivotField ): return (nElement == XLS_TOKEN( items )); + case XLS_TOKEN( items ): return (nElement == XLS_TOKEN( item )); + case XLS_TOKEN( rowFields ): return (nElement == XLS_TOKEN( field )); + case XLS_TOKEN( colFields ): return (nElement == XLS_TOKEN( field )); + case XLS_TOKEN( pageFields ): return (nElement == XLS_TOKEN( pageField )); + case XLS_TOKEN( dataFields ): return (nElement == XLS_TOKEN( dataField )); + case XLS_TOKEN( colItems ): return (nElement == XLS_TOKEN( i )); + case XLS_TOKEN( rowItems ): return (nElement == XLS_TOKEN( i )); + } + return false; +} + +void OoxPivotTableFragment::onStartElement( const AttributeList& rAttribs ) +{ + switch ( getCurrentContext() ) + { + case XLS_TOKEN( pivotTableDefinition ): + importPivotTableDefinition( rAttribs ); + break; + case XLS_TOKEN( location ): + importLocation( rAttribs ); + break; + case XLS_TOKEN( pivotFields ): + importPivotFields( rAttribs ); + break; + case XLS_TOKEN( pivotField ): + importPivotField( rAttribs ); + break; + } +} + +void OoxPivotTableFragment::finalizeImport() +{ + if( mbValidRange ) + getPivotTables().setPivotTable( maName, maData ); +} + +void OoxPivotTableFragment::importLocation( const AttributeList& rAttribs ) +{ + CellRangeAddress aRange; + OUString aRangeName = rAttribs.getString( XML_ref ); + mbValidRange = getAddressConverter().convertToCellRange( + aRange, aRangeName, getSheetIndex(), true ); + + if ( mbValidRange ) + maData.maRange = aRange; +} + +void OoxPivotTableFragment::importPivotTableDefinition( const AttributeList& rAttribs ) +{ + if ( !rAttribs.hasAttribute( XML_cacheId ) ) + return; + + maName = rAttribs.getString( XML_name ); + maData.mnCacheId = rAttribs.getInteger( XML_cacheId, 0 ); + + // name="PivotTable3" + // cacheId="0" + // applyNumberFormats="0" + // applyBorderFormats="0" + // applyFontFormats="0" + // applyPatternFormats="0" + // applyAlignmentFormats="0" + // applyWidthHeightFormats="1" + // dataCaption="Values" + // updatedVersion="3" + // minRefreshableVersion="3" + // showCalcMbrs="0" + // useAutoFormatting="1" + // itemPrintTitles="1" + // createdVersion="3" + // indent="0" + // outline="1" + // outlineData="1" + // multipleFieldFilters="0" +} + +void OoxPivotTableFragment::importPivotFields( const AttributeList& rAttribs ) +{ + maData.maFields.reserve( rAttribs.getUnsignedInteger( XML_count, 1 ) ); +} + +void OoxPivotTableFragment::importPivotField( const AttributeList& rAttribs ) +{ + maData.maFields.push_back( PivotTableField() ); + PivotTableField& rField = maData.maFields.back(); + rField.mbDataField = rAttribs.getBool( XML_dataField, false ); + + // Possible values are: axisCol, axisRow, axisPage, axisValues + switch ( rAttribs.getToken( XML_axis ) ) + { + case XML_axisCol: + rField.meAxis = PivotTableField::COLUMN; + break; + case XML_axisRow: + rField.meAxis = PivotTableField::ROW; + break; + case XML_axisPage: + rField.meAxis = PivotTableField::PAGE; + break; + case XML_axisValues: + rField.meAxis = PivotTableField::VALUES; + break; + default: + break; + } +} + +} // namespace xls +} // namespace oox diff --git a/oox/source/xls/querytablefragment.cxx b/oox/source/xls/querytablefragment.cxx new file mode 100644 index 000000000000..703ec9f9f156 --- /dev/null +++ b/oox/source/xls/querytablefragment.cxx @@ -0,0 +1,82 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: querytablefragment.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/querytablefragment.hxx" +#include "oox/xls/webquerybuffer.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::sheet::XSpreadsheet; +using ::com::sun::star::xml::sax::SAXException; + +namespace oox { +namespace xls { + +OoxQueryTableFragment::OoxQueryTableFragment( + const WorkbookHelper& rHelper, const OUString& rFragmentPath ) : + OoxWorkbookFragmentBase( rHelper, rFragmentPath ) +{ +} + +bool OoxQueryTableFragment::onCanCreateContext( sal_Int32 nElement ) const +{ + switch( getCurrentContext() ) + { + case XML_ROOT_CONTEXT: return (nElement == XLS_TOKEN( queryTable )); + } + return false; +} + +void OoxQueryTableFragment::onStartElement( const AttributeList& rAttribs ) +{ + switch ( getCurrentContext() ) + { + case XLS_TOKEN( queryTable ): + importQueryTable( rAttribs ); + break; + } +} + +void OoxQueryTableFragment::importQueryTable( const AttributeList& rAttribs ) +{ + getWebQueries().importQueryTable( rAttribs ); +} + +} // namespace xls +} // namespace oox diff --git a/oox/source/xls/richstring.cxx b/oox/source/xls/richstring.cxx new file mode 100644 index 000000000000..97cc1cbe82c2 --- /dev/null +++ b/oox/source/xls/richstring.cxx @@ -0,0 +1,605 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: richstring.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/richstring.hxx" +#include +#include "oox/helper/attributelist.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/helper/recordinputstream.hxx" +#include "oox/xls/biffinputstream.hxx" + +using ::rtl::OString; +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::text::XText; +using ::com::sun::star::text::XTextRange; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +const sal_uInt8 OOBIN_STRINGFLAG_FONTS = 0x01; +const sal_uInt8 OOBIN_STRINGFLAG_PHONETICS = 0x02; + +} // namespace + +// ============================================================================ + +RichStringPortion::RichStringPortion( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + mnFontId( -1 ) +{ +} + +void RichStringPortion::setText( const OUString& rText ) +{ + maText = rText; +} + +FontRef RichStringPortion::importFont( const AttributeList& ) +{ + mxFont.reset( new Font( *this, false ) ); + return mxFont; +} + +void RichStringPortion::setFontId( sal_Int32 nFontId ) +{ + mnFontId = nFontId; +} + +void RichStringPortion::finalizeImport() +{ + if( mxFont.get() ) + mxFont->finalizeImport(); + else if( mnFontId >= 0 ) + mxFont = getStyles().getFont( mnFontId ); +} + +void RichStringPortion::convert( const Reference< XText >& rxText, sal_Int32 nXfId ) +{ + Reference< XTextRange > xRange = rxText->getEnd(); + xRange->setString( maText ); + if( mxFont.get() ) + { + PropertySet aPropSet( xRange ); + mxFont->writeToPropertySet( aPropSet, FONT_PROPTYPE_RICHTEXT ); + } + if( const Font* pFont = getStyles().getFontFromCellXf( nXfId ).get() ) + { + if( pFont->needsRichTextFormat() ) + { + PropertySet aPropSet( xRange ); + pFont->writeToPropertySet( aPropSet, FONT_PROPTYPE_RICHTEXT ); + } + } +} + +// ---------------------------------------------------------------------------- + +void BinFontPortionData::read( RecordInputStream& rStrm ) +{ + mnPos = rStrm.readuInt16(); + mnFontId = rStrm.readuInt16(); +} + +void BinFontPortionData::read( BiffInputStream& rStrm, bool b16Bit ) +{ + if( b16Bit ) + { + mnPos = rStrm.readuInt16(); + mnFontId = rStrm.readuInt16(); + } + else + { + mnPos = rStrm.readuInt8(); + mnFontId = rStrm.readuInt8(); + } +} + +// ---------------------------------------------------------------------------- + +void BinFontPortionList::appendPortion( const BinFontPortionData& rPortion ) +{ + // #i33341# real life -- same character index may occur several times + OSL_ENSURE( empty() || (back().mnPos <= rPortion.mnPos), "BinFontPortionList::appendPortion - wrong char order" ); + if( empty() || (back().mnPos < rPortion.mnPos) ) + push_back( rPortion ); + else + back().mnFontId = rPortion.mnFontId; +} + +void BinFontPortionList::importPortions( RecordInputStream& rStrm ) +{ + sal_Int32 nCount = rStrm.readInt32(); + clear(); + if( nCount > 0 ) + { + reserve( getLimitedValue< size_t, sal_Int32 >( nCount, 0, rStrm.getRecLeft() / 4 ) ); + /* #i33341# real life -- same character index may occur several times + -> use appendPortion() to validate string position. */ + BinFontPortionData aPortion; + for( sal_Int32 nIndex = 0; rStrm.isValid() && (nIndex < nCount); ++nIndex ) + { + aPortion.read( rStrm ); + appendPortion( aPortion ); + } + } +} + +void BinFontPortionList::importPortions( BiffInputStream& rStrm, sal_uInt16 nCount, bool b16Bit ) +{ + clear(); + reserve( nCount ); + /* #i33341# real life -- same character index may occur several times + -> use appendPortion() to validate string position. */ + BinFontPortionData aPortion; + for( sal_uInt16 nIndex = 0; rStrm.isValid() && (nIndex < nCount); ++nIndex ) + { + aPortion.read( rStrm, b16Bit ); + appendPortion( aPortion ); + } +} + +void BinFontPortionList::importPortions( BiffInputStream& rStrm, bool b16Bit ) +{ + sal_uInt16 nCount = b16Bit ? rStrm.readuInt16() : rStrm.readuInt8(); + importPortions( rStrm, nCount, b16Bit ); +} + +// ============================================================================ + +OoxPhoneticData::OoxPhoneticData() : + mnFontId( -1 ), + mnType( XML_fullwidthKatakana ), + mnAlignment( XML_left ) +{ +} + +void OoxPhoneticData::setBinData( sal_Int32 nType, sal_Int32 nAlignment ) +{ + static const sal_Int32 spnTypeIds[] = { XML_halfwidthKatakana, XML_fullwidthKatakana, XML_hiragana, XML_noConversion }; + mnType = STATIC_ARRAY_SELECT( spnTypeIds, nType, XML_fullwidthKatakana ); + + static const sal_Int32 spnAlignments[] = { XML_noControl, XML_left, XML_center, XML_distributed }; + mnAlignment = STATIC_ARRAY_SELECT( spnAlignments, nAlignment, XML_left ); +} + +// ---------------------------------------------------------------------------- + +PhoneticSettings::PhoneticSettings( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ) +{ +} + +void PhoneticSettings::importPhoneticPr( const AttributeList& rAttribs ) +{ + maOoxData.mnFontId = rAttribs.getInteger( XML_fontId, -1 ); + maOoxData.mnType = rAttribs.getToken( XML_type, XML_fullwidthKatakana ); + maOoxData.mnAlignment = rAttribs.getToken( XML_alignment, XML_left ); +} + +void PhoneticSettings::importPhoneticPr( RecordInputStream& rStrm ) +{ + sal_uInt16 nFontId; + sal_Int32 nType, nAlignment; + rStrm >> nFontId >> nType >> nAlignment; + maOoxData.mnFontId = nFontId; + maOoxData.setBinData( nType, nAlignment ); +} + +void PhoneticSettings::importPhoneticPr( BiffInputStream& rStrm ) +{ + sal_uInt16 nFontId, nFlags; + rStrm >> nFontId >> nFlags; + maOoxData.mnFontId = nFontId; + maOoxData.setBinData( extractValue< sal_Int32 >( nFlags, 0, 2 ), extractValue< sal_Int32 >( nFlags, 2, 2 ) ); + // following: range list with cells showing phonetic text +} + +void PhoneticSettings::importStringData( RecordInputStream& rStrm ) +{ + sal_uInt16 nFontId, nFlags; + rStrm >> nFontId >> nFlags; + maOoxData.mnFontId = nFontId; + maOoxData.setBinData( extractValue< sal_Int32 >( nFlags, 0, 2 ), extractValue< sal_Int32 >( nFlags, 2, 2 ) ); +} + +void PhoneticSettings::importStringData( BiffInputStream& rStrm ) +{ + sal_uInt16 nFontId, nFlags; + rStrm >> nFontId >> nFlags; + maOoxData.mnFontId = nFontId; + maOoxData.setBinData( extractValue< sal_Int32 >( nFlags, 0, 2 ), extractValue< sal_Int32 >( nFlags, 2, 2 ) ); +} + +// ============================================================================ + +RichStringPhonetic::RichStringPhonetic( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + mnBasePos( -1 ), + mnBaseEnd( -1 ) +{ +} + +void RichStringPhonetic::setText( const OUString& rText ) +{ + maText = rText; +} + +void RichStringPhonetic::importPhoneticRun( const AttributeList& rAttribs ) +{ + mnBasePos = rAttribs.getInteger( XML_sb, -1 ); + mnBaseEnd = rAttribs.getInteger( XML_eb, -1 ); +} + +void RichStringPhonetic::setBaseRange( sal_Int32 nBasePos, sal_Int32 nBaseEnd ) +{ + mnBasePos = nBasePos; + mnBaseEnd = nBaseEnd; +} + +// ---------------------------------------------------------------------------- + +void BinPhoneticPortionData::read( RecordInputStream& rStrm ) +{ + mnPos = rStrm.readuInt16(); + mnBasePos = rStrm.readuInt16(); + mnBaseLen = rStrm.readuInt16(); +} + +void BinPhoneticPortionData::read( BiffInputStream& rStrm ) +{ + mnPos = rStrm.readuInt16(); + mnBasePos = rStrm.readuInt16(); + mnBaseLen = rStrm.readuInt16(); +} + +// ---------------------------------------------------------------------------- + +void BinPhoneticPortionList::appendPortion( const BinPhoneticPortionData& rPortion ) +{ + // same character index may occur several times + OSL_ENSURE( empty() || ((back().mnPos <= rPortion.mnPos) && + (back().mnBasePos + back().mnBaseLen <= rPortion.mnBasePos)), + "BinPhoneticPortionList::appendPortion - wrong char order" ); + if( empty() || (back().mnPos < rPortion.mnPos) ) + { + push_back( rPortion ); + } + else if( back().mnPos == rPortion.mnPos ) + { + back().mnBasePos = rPortion.mnBasePos; + back().mnBaseLen = rPortion.mnBaseLen; + } +} + +void BinPhoneticPortionList::importPortions( RecordInputStream& rStrm ) +{ + sal_Int32 nCount = rStrm.readInt32(); + clear(); + if( nCount > 0 ) + { + reserve( getLimitedValue< size_t, sal_Int32 >( nCount, 0, rStrm.getRecLeft() / 6 ) ); + BinPhoneticPortionData aPortion; + for( sal_Int32 nIndex = 0; rStrm.isValid() && (nIndex < nCount); ++nIndex ) + { + aPortion.read( rStrm ); + appendPortion( aPortion ); + } + } +} + +OUString BinPhoneticPortionList::importPortions( BiffInputStream& rStrm, sal_uInt32 nPhoneticSize ) +{ + OUString aPhoneticText; + sal_uInt16 nPortionCount, nTextLen1, nTextLen2; + rStrm >> nPortionCount >> nTextLen1 >> nTextLen2; + OSL_ENSURE( nTextLen1 == nTextLen2, "BinPhoneticPortionList::importPortions - wrong phonetic text length" ); + if( (nTextLen1 == nTextLen2) && (nTextLen1 > 0) ) + { + sal_uInt32 nMinSize = static_cast< sal_uInt32 >( 2 * nTextLen1 + 6 * nPortionCount + 14 ); + OSL_ENSURE( nMinSize <= nPhoneticSize, "BinPhoneticPortionList::importPortions - wrong size of phonetic data" ); + if( nMinSize <= nPhoneticSize ) + { + aPhoneticText = rStrm.readUnicodeArray( nTextLen1 ); + clear(); + reserve( nPortionCount ); + BinPhoneticPortionData aPortion; + for( sal_uInt16 nPortion = 0; nPortion < nPortionCount; ++nPortion ) + { + aPortion.read( rStrm ); + appendPortion( aPortion ); + } + } + } + return aPhoneticText; +} + +// ============================================================================ + +RichString::RichString( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + maPhonSettings( rHelper ) +{ +} + +RichStringPortionRef RichString::importText( const AttributeList& ) +{ + return createPortion(); +} + +RichStringPortionRef RichString::importRun( const AttributeList& ) +{ + return createPortion(); +} + +RichStringPhoneticRef RichString::importPhoneticRun( const AttributeList& rAttribs ) +{ + RichStringPhoneticRef xPhonetic = createPhonetic(); + xPhonetic->importPhoneticRun( rAttribs ); + return xPhonetic; +} + +void RichString::importPhoneticPr( const AttributeList& rAttribs ) +{ + maPhonSettings.importPhoneticPr( rAttribs ); +} + +void RichString::importString( RecordInputStream& rStrm, bool bRich ) +{ + sal_uInt8 nFlags = bRich ? rStrm.readuInt8() : 0; + OUString aBaseText = rStrm.readString(); + + if( rStrm.isValid() && getFlag( nFlags, OOBIN_STRINGFLAG_FONTS ) ) + { + BinFontPortionList aPortions; + aPortions.importPortions( rStrm ); + createFontPortions( aBaseText, aPortions ); + } + else + { + createPortion()->setText( aBaseText ); + } + + if( rStrm.isValid() && getFlag( nFlags, OOBIN_STRINGFLAG_PHONETICS ) ) + { + OUString aPhoneticText = rStrm.readString(); + BinPhoneticPortionList aPortions; + aPortions.importPortions( rStrm ); + maPhonSettings.importStringData( rStrm ); + createPhoneticPortions( aPhoneticText, aPortions, aBaseText.getLength() ); + } +} + +void RichString::importByteString( BiffInputStream& rStrm, rtl_TextEncoding eDefaultTextEnc, BiffStringFlags nFlags ) +{ + OSL_ENSURE( !getFlag( nFlags, BIFF_STR_KEEPFONTS ), "RichString::importString - keep fonts not implemented" ); + OSL_ENSURE( !getFlag( nFlags, static_cast< BiffStringFlags >( ~(BIFF_STR_8BITLENGTH | BIFF_STR_EXTRAFONTS) ) ), "RichString::importByteString - unknown flag" ); + bool b8BitLength = getFlag( nFlags, BIFF_STR_8BITLENGTH ); + + OString aBaseText = rStrm.readByteString( !b8BitLength ); + + if( rStrm.isValid() && getFlag( nFlags, BIFF_STR_EXTRAFONTS ) ) + { + BinFontPortionList aPortions; + aPortions.importPortions( rStrm, false ); + createFontPortions( aBaseText, eDefaultTextEnc, aPortions ); + } + else + { + createPortion()->setText( OStringToOUString( aBaseText, eDefaultTextEnc ) ); + } +} + +void RichString::importUniString( BiffInputStream& rStrm, BiffStringFlags nFlags ) +{ + OSL_ENSURE( !getFlag( nFlags, BIFF_STR_KEEPFONTS ), "RichString::importUniString - keep fonts not implemented" ); + OSL_ENSURE( !getFlag( nFlags, static_cast< BiffStringFlags >( ~(BIFF_STR_8BITLENGTH | BIFF_STR_SMARTFLAGS) ) ), "RichString::importUniString - unknown flag" ); + bool b8BitLength = getFlag( nFlags, BIFF_STR_8BITLENGTH ); + + // --- string header --- + sal_uInt16 nChars = b8BitLength ? rStrm.readuInt8() : rStrm.readuInt16(); + sal_uInt8 nFlagField = 0; + if( (nChars > 0) || !getFlag( nFlags, BIFF_STR_SMARTFLAGS ) ) + rStrm >> nFlagField; + + bool b16Bit, bFonts, bPhonetic; + sal_uInt16 nFontCount; + sal_uInt32 nPhoneticSize; + rStrm.readExtendedUniStringHeader( b16Bit, bFonts, bPhonetic, nFontCount, nPhoneticSize, nFlagField ); + + // --- character array --- + OUString aBaseText = rStrm.readRawUniString( nChars, b16Bit ); + + // --- formatting --- + // #122185# bRich flag may be set, but format runs may be missing + if( rStrm.isValid() && (nFontCount > 0) ) + { + BinFontPortionList aPortions; + aPortions.importPortions( rStrm, nFontCount, true ); + createFontPortions( aBaseText, aPortions ); + } + else + { + createPortion()->setText( aBaseText ); + } + + // --- Asian phonetic information --- + // #122185# bPhonetic flag may be set, but phonetic info may be missing + if( rStrm.isValid() && (nPhoneticSize > 0) ) + { + sal_uInt32 nPhoneticEnd = rStrm.getRecPos() + nPhoneticSize; + OSL_ENSURE( nPhoneticSize > 14, "RichString::importUniString - wrong size of phonetic data" ); + if( nPhoneticSize > 14 ) + { + sal_uInt16 nId, nSize; + rStrm >> nId >> nSize; + OSL_ENSURE( nId == 1, "RichString::importUniString - unknown phonetic data identifier" ); + sal_uInt32 nMinSize = static_cast< sal_uInt32 >( nSize + 4 ); + OSL_ENSURE( nMinSize <= nPhoneticSize, "RichString::importUniString - wrong size of phonetic data" ); + if( (nId == 1) && (nMinSize <= nPhoneticSize) ) + { + maPhonSettings.importStringData( rStrm ); + BinPhoneticPortionList aPortions; + OUString aPhoneticText = aPortions.importPortions( rStrm, nPhoneticSize ); + createPhoneticPortions( aPhoneticText, aPortions, aBaseText.getLength() ); + } + } + rStrm.seek( nPhoneticEnd ); + } +} + +void RichString::finalizeImport() +{ + maFontPortions.forEachMem( &RichStringPortion::finalizeImport ); +} + +void RichString::convert( const Reference< XText >& rxText, sal_Int32 nXfId ) const +{ + for( PortionVec::const_iterator aIt = maFontPortions.begin(), aEnd = maFontPortions.end(); aIt != aEnd; ++aIt ) + { + (*aIt)->convert( rxText, nXfId ); + nXfId = -1; + } +} + +// private -------------------------------------------------------------------- + +RichStringPortionRef RichString::createPortion() +{ + RichStringPortionRef xPortion( new RichStringPortion( *this ) ); + maFontPortions.push_back( xPortion ); + return xPortion; +} + +RichStringPhoneticRef RichString::createPhonetic() +{ + RichStringPhoneticRef xPhonetic( new RichStringPhonetic( *this ) ); + maPhonPortions.push_back( xPhonetic ); + return xPhonetic; +} + +void RichString::createFontPortions( const OString& rText, rtl_TextEncoding eDefaultTextEnc, BinFontPortionList& rPortions ) +{ + maFontPortions.clear(); + sal_Int32 nStrLen = rText.getLength(); + if( nStrLen > 0 ) + { + // add leading and trailing string position to ease the following loop + if( rPortions.empty() || (rPortions.front().mnPos > 0) ) + rPortions.insert( rPortions.begin(), BinFontPortionData( 0, -1 ) ); + if( rPortions.back().mnPos < nStrLen ) + rPortions.push_back( BinFontPortionData( nStrLen, -1 ) ); + + // create all string portions according to the font id vector + for( BinFontPortionList::const_iterator aIt = rPortions.begin(); aIt->mnPos < nStrLen; ++aIt ) + { + sal_Int32 nPortionLen = (aIt + 1)->mnPos - aIt->mnPos; + if( (0 < nPortionLen) && (aIt->mnPos + nPortionLen <= nStrLen) ) + { + // convert byte string to unicode string, using current font encoding + FontRef xFont = getStyles().getFont( aIt->mnFontId ); + rtl_TextEncoding eTextEnc = xFont.get() ? xFont->getFontEncoding() : eDefaultTextEnc; + OUString aUniStr = OStringToOUString( rText.copy( aIt->mnPos, nPortionLen ), eTextEnc ); + // create string portion + RichStringPortionRef xPortion = createPortion(); + xPortion->setText( aUniStr ); + xPortion->setFontId( aIt->mnFontId ); + } + } + } +} + +void RichString::createFontPortions( const OUString& rText, BinFontPortionList& rPortions ) +{ + maFontPortions.clear(); + sal_Int32 nStrLen = rText.getLength(); + if( nStrLen > 0 ) + { + // add leading and trailing string position to ease the following loop + if( rPortions.empty() || (rPortions.front().mnPos > 0) ) + rPortions.insert( rPortions.begin(), BinFontPortionData( 0, -1 ) ); + if( rPortions.back().mnPos < nStrLen ) + rPortions.push_back( BinFontPortionData( nStrLen, -1 ) ); + + // create all string portions according to the font id vector + for( BinFontPortionList::const_iterator aIt = rPortions.begin(); aIt->mnPos < nStrLen; ++aIt ) + { + sal_Int32 nPortionLen = (aIt + 1)->mnPos - aIt->mnPos; + if( (0 < nPortionLen) && (aIt->mnPos + nPortionLen <= nStrLen) ) + { + RichStringPortionRef xPortion = createPortion(); + xPortion->setText( rText.copy( aIt->mnPos, nPortionLen ) ); + xPortion->setFontId( aIt->mnFontId ); + } + } + } +} + +void RichString::createPhoneticPortions( const ::rtl::OUString& rText, BinPhoneticPortionList& rPortions, sal_Int32 nBaseLen ) +{ + maPhonPortions.clear(); + sal_Int32 nStrLen = rText.getLength(); + if( nStrLen > 0 ) + { + // no portions - assign phonetic text to entire base text + if( rPortions.empty() ) + rPortions.push_back( BinPhoneticPortionData( 0, 0, nBaseLen ) ); + // add trailing string position to ease the following loop + if( rPortions.back().mnPos < nStrLen ) + rPortions.push_back( BinPhoneticPortionData( nStrLen, nBaseLen, 0 ) ); + + // create all phonetic portions according to the portions vector + for( BinPhoneticPortionList::const_iterator aIt = rPortions.begin(); aIt->mnPos < nStrLen; ++aIt ) + { + sal_Int32 nPortionLen = (aIt + 1)->mnPos - aIt->mnPos; + if( (0 < nPortionLen) && (aIt->mnPos + nPortionLen <= nStrLen) ) + { + RichStringPhoneticRef xPhonetic = createPhonetic(); + xPhonetic->setText( rText.copy( aIt->mnPos, nPortionLen ) ); + xPhonetic->setBaseRange( aIt->mnBasePos, aIt->mnBasePos + aIt->mnBaseLen ); + } + } + } +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/richstringcontext.cxx b/oox/source/xls/richstringcontext.cxx new file mode 100644 index 000000000000..fd9b21572cb6 --- /dev/null +++ b/oox/source/xls/richstringcontext.cxx @@ -0,0 +1,118 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: richstringcontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/richstringcontext.hxx" + +using ::rtl::OUString; + +namespace oox { +namespace xls { + +// ============================================================================ + +// oox.xls.OoxContextHelper interface ----------------------------------------- + +bool OoxRichStringContext::onCanCreateContext( sal_Int32 nElement ) const +{ + sal_Int32 nCurrContext = getCurrentContext(); + switch( nCurrContext ) + { + case XLS_TOKEN( si ): + case XLS_TOKEN( is ): + case XLS_TOKEN( text ): + return (nElement == XLS_TOKEN( t )) || + (nElement == XLS_TOKEN( r )) || + (nElement == XLS_TOKEN( rPh )) || + (nElement == XLS_TOKEN( phoneticPr )); + case XLS_TOKEN( r ): + return (nElement == XLS_TOKEN( rPr )) || + (nElement == XLS_TOKEN( t )); + case XLS_TOKEN( rPh ): + return (nElement == XLS_TOKEN( t )); + case XLS_TOKEN( rPr ): + return Font::isSupportedContext( nElement, nCurrContext ); + } + return false; +} + +void OoxRichStringContext::onStartElement( const AttributeList& rAttribs ) +{ + sal_Int32 nCurrContext = getCurrentContext(); + switch( nCurrContext ) + { + case XLS_TOKEN( t ): + if( !isPreviousContext( XLS_TOKEN( r ) ) && !isPreviousContext( XLS_TOKEN( rPh ) ) ) + mxPortion = mxString->importText( rAttribs ); + break; + case XLS_TOKEN( r ): + mxPortion = mxString->importRun( rAttribs ); + break; + case XLS_TOKEN( rPr ): + if( mxPortion.get() ) mxFont = mxPortion->importFont( rAttribs ); + break; + case XLS_TOKEN( rPh ): + mxPhonetic = mxString->importPhoneticRun( rAttribs ); + break; + case XLS_TOKEN( phoneticPr ): + mxString->importPhoneticPr( rAttribs ); + break; + default: + if( isPreviousContext( XLS_TOKEN( rPr ) ) && mxFont.get() ) + mxFont->importAttribs( nCurrContext, rAttribs ); + } +} + +void OoxRichStringContext::onEndElement( const OUString& rChars ) +{ + switch( getCurrentContext() ) + { + case XLS_TOKEN( t ): + switch( getPreviousContext() ) + { + case XLS_TOKEN( rPh ): + if( mxPhonetic.get() ) mxPhonetic->setText( rChars ); + break; + default: + if( mxPortion.get() ) mxPortion->setText( rChars ); + } + break; + } +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/sharedformulabuffer.cxx b/oox/source/xls/sharedformulabuffer.cxx new file mode 100644 index 000000000000..5a09ec22c407 --- /dev/null +++ b/oox/source/xls/sharedformulabuffer.cxx @@ -0,0 +1,220 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sharedformulabuffer.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/sharedformulabuffer.hxx" +#include +#include +#include "oox/helper/recordinputstream.hxx" +#include "oox/xls/addressconverter.hxx" +#include "oox/xls/biffinputstream.hxx" +#include "oox/xls/defnamesbuffer.hxx" +#include "oox/xls/formulaparser.hxx" + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::table::CellAddress; +using ::com::sun::star::table::CellRangeAddress; +using ::com::sun::star::sheet::XFormulaTokens; +using ::com::sun::star::sheet::XNamedRange; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +bool operator==( const CellAddress& rAddr1, const CellAddress& rAddr2 ) +{ + return + (rAddr1.Sheet == rAddr2.Sheet) && + (rAddr1.Column == rAddr2.Column) && + (rAddr1.Row == rAddr2.Row); +} + +bool lclContains( const CellRangeAddress& rRange, const CellAddress& rAddr ) +{ + return + (rRange.Sheet == rAddr.Sheet) && + (rRange.StartColumn <= rAddr.Column) && (rAddr.Column <= rRange.EndColumn) && + (rRange.StartRow <= rAddr.Row) && (rAddr.Row <= rRange.EndRow); +} + +} // namespace + +// ============================================================================ + +ExtCellFormulaContext::ExtCellFormulaContext( const WorksheetHelper& rHelper, + const Reference< XFormulaTokens >& rxTokens, const CellAddress& rCellPos ) : + SimpleFormulaContext( rxTokens, false, false ), + WorksheetHelper( rHelper ) +{ + setBaseAddress( rCellPos ); +} + +void ExtCellFormulaContext::setSharedFormula( const CellAddress& rBaseAddr ) +{ + getSharedFormulas().setSharedFormulaCell( *this, rBaseAddr ); +} + +// ============================================================================ + +SharedFormulaBuffer::SharedFormulaBuffer( const WorksheetHelper& rHelper ) : + WorksheetHelper( rHelper ) +{ +} + +void SharedFormulaBuffer::importSharedFmla( const OUString& rFormula, const OUString& rSharedRange, sal_Int32 nSharedId, const CellAddress& rBaseAddr ) +{ + CellRangeAddress aFmlaRange; + if( getAddressConverter().convertToCellRange( aFmlaRange, rSharedRange, getSheetIndex(), true ) ) + { + // create the defined name representing the shared formula + OSL_ENSURE( lclContains( aFmlaRange, rBaseAddr ), "SharedFormulaBuffer::importSharedFmla - invalid range for shared formula" ); + BinAddress aMapKey( nSharedId, 0 ); + Reference< XNamedRange > xNamedRange = createDefinedName( aMapKey ); + // convert the formula definition + Reference< XFormulaTokens > xTokens( xNamedRange, UNO_QUERY ); + if( xTokens.is() ) + { + SimpleFormulaContext aContext( xTokens, true, false ); + aContext.setBaseAddress( rBaseAddr ); + getFormulaParser().importFormula( aContext, rFormula ); + updateCachedCell( rBaseAddr, aMapKey ); + } + } +} + +void SharedFormulaBuffer::importSharedFmla( RecordInputStream& rStrm, const CellAddress& rBaseAddr ) +{ + BinRange aRange; + rStrm >> aRange; + CellRangeAddress aFmlaRange; + if( getAddressConverter().convertToCellRange( aFmlaRange, aRange, getSheetIndex(), true ) ) + { + // create the defined name representing the shared formula + OSL_ENSURE( lclContains( aFmlaRange, rBaseAddr ), "SharedFormulaBuffer::importSharedFmla - invalid range for shared formula" ); + BinAddress aMapKey( rBaseAddr ); + Reference< XNamedRange > xNamedRange = createDefinedName( aMapKey ); + // load the formula definition + Reference< XFormulaTokens > xTokens( xNamedRange, UNO_QUERY ); + if( xTokens.is() ) + { + SimpleFormulaContext aContext( xTokens, true, false ); + aContext.setBaseAddress( rBaseAddr ); + getFormulaParser().importFormula( aContext, rStrm ); + updateCachedCell( rBaseAddr, aMapKey ); + } + } +} + +void SharedFormulaBuffer::importSharedFmla( BiffInputStream& rStrm, const CellAddress& rBaseAddr ) +{ + BinRange aRange; + aRange.read( rStrm, false ); // always 8bit column indexes + CellRangeAddress aFmlaRange; + if( getAddressConverter().convertToCellRange( aFmlaRange, aRange, getSheetIndex(), true ) ) + { + // create the defined name representing the shared formula + OSL_ENSURE( lclContains( aFmlaRange, rBaseAddr ), "SharedFormulaBuffer::importSharedFmla - invalid range for shared formula" ); + BinAddress aMapKey( rBaseAddr ); + Reference< XNamedRange > xNamedRange = createDefinedName( aMapKey ); + // load the formula definition + Reference< XFormulaTokens > xTokens( xNamedRange, UNO_QUERY ); + if( xTokens.is() ) + { + rStrm.skip( 2 ); // flags + SimpleFormulaContext aContext( xTokens, true, false ); + aContext.setBaseAddress( rBaseAddr ); + getFormulaParser().importFormula( aContext, rStrm ); + updateCachedCell( rBaseAddr, aMapKey ); + } + } +} + +void SharedFormulaBuffer::setSharedFormulaCell( ExtCellFormulaContext& rContext, const CellAddress& rBaseAddr ) +{ + if( !implSetSharedFormulaCell( rContext, BinAddress( rBaseAddr ) ) ) + if( rContext.getBaseAddress() == rBaseAddr ) + mxLastContext.reset( new ExtCellFormulaContext( rContext ) ); +} + +void SharedFormulaBuffer::setSharedFormulaCell( ExtCellFormulaContext& rContext, sal_Int32 nSharedId ) +{ + implSetSharedFormulaCell( rContext, BinAddress( nSharedId, 0 ) ); +} + +Reference< XNamedRange > SharedFormulaBuffer::createDefinedName( const BinAddress& rMapKey ) +{ + OSL_ENSURE( maIndexMap.count( rMapKey ) == 0, "SharedFormulaBuffer::createDefinedName - shared formula exists already" ); + // create the defined name representing the shared formula + OUString aName = OUStringBuffer().appendAscii( "__shared_" ). + append( static_cast< sal_Int32 >( getSheetIndex() + 1 ) ). + append( sal_Unicode( '_' ) ).append( rMapKey.mnRow ). + append( sal_Unicode( '_' ) ).append( rMapKey.mnCol ).makeStringAndClear(); + Reference< XNamedRange > xNamedRange = getDefinedNames().createDefinedName( aName ); + sal_Int32 nTokenIndex = getDefinedNames().getTokenIndex( xNamedRange ); + if( nTokenIndex >= 0 ) + maIndexMap[ rMapKey ] = nTokenIndex; + return xNamedRange; +} + +bool SharedFormulaBuffer::implSetSharedFormulaCell( ExtCellFormulaContext& rContext, const BinAddress& rMapKey ) +{ + TokenIndexMap::const_iterator aIt = maIndexMap.find( rMapKey ); + sal_Int32 nTokenIndex = (aIt == maIndexMap.end()) ? -1 : aIt->second; + if( nTokenIndex >= 0 ) + { + getFormulaParser().convertNameToFormula( rContext, nTokenIndex ); + return true; + } + return false; +} + +void SharedFormulaBuffer::updateCachedCell( const CellAddress& rBaseAddr, const BinAddress& rMapKey ) +{ + if( mxLastContext.get() && (mxLastContext->getBaseAddress() == rBaseAddr) ) + implSetSharedFormulaCell( *mxLastContext, rMapKey ); + mxLastContext.reset(); +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/sharedstringsbuffer.cxx b/oox/source/xls/sharedstringsbuffer.cxx new file mode 100644 index 000000000000..85a6662e3004 --- /dev/null +++ b/oox/source/xls/sharedstringsbuffer.cxx @@ -0,0 +1,91 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sharedstringsbuffer.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/sharedstringsbuffer.hxx" +#include "oox/xls/biffinputstream.hxx" + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::text::XText; + +namespace oox { +namespace xls { + +// ============================================================================ + +SharedStringsBuffer::SharedStringsBuffer( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ) +{ +} + +RichStringRef SharedStringsBuffer::createRichString() +{ + RichStringRef xString( new RichString( *this ) ); + maStrings.push_back( xString ); + return xString; +} + +void SharedStringsBuffer::importSst( BiffInputStream& rStrm ) +{ + sal_Int32 nStringCount = rStrm.skip( 4 ).readInt32(); + if( nStringCount > 0 ) + { + maStrings.clear(); + maStrings.reserve( static_cast< size_t >( nStringCount ) ); + for( ; rStrm.isValid() && (nStringCount > 0); --nStringCount ) + { + RichStringRef xString( new RichString( *this ) ); + maStrings.push_back( xString ); + xString->importUniString( rStrm ); + } + } +} + +void SharedStringsBuffer::finalizeImport() +{ + maStrings.forEachMem( &RichString::finalizeImport ); +} + +void SharedStringsBuffer::convertString( const Reference< XText >& rxText, sal_Int32 nStringId, sal_Int32 nXfId ) const +{ + if( rxText.is() ) + if( const RichString* pString = maStrings.get( nStringId ).get() ) + pString->convert( rxText, nXfId ); +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/sharedstringsfragment.cxx b/oox/source/xls/sharedstringsfragment.cxx new file mode 100644 index 000000000000..8b7b1c5d6b6e --- /dev/null +++ b/oox/source/xls/sharedstringsfragment.cxx @@ -0,0 +1,110 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sharedstringsfragment.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/sharedstringsfragment.hxx" +#include "oox/xls/sharedstringsbuffer.hxx" +#include "oox/xls/richstringcontext.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::xml::sax::XFastContextHandler; + +namespace oox { +namespace xls { + +// ============================================================================ + +OoxSharedStringsFragment::OoxSharedStringsFragment( + const WorkbookHelper& rHelper, const OUString& rFragmentPath ) : + OoxWorkbookFragmentBase( rHelper, rFragmentPath ) +{ +} + +// oox.xls.OoxContextHelper interface ----------------------------------------- + +bool OoxSharedStringsFragment::onCanCreateContext( sal_Int32 nElement ) const +{ + switch( getCurrentContext() ) + { + case XML_ROOT_CONTEXT: + return (nElement == XLS_TOKEN( sst )); + case XLS_TOKEN( sst ): + return (nElement == XLS_TOKEN( si )); + } + return false; +} + +Reference< XFastContextHandler > OoxSharedStringsFragment::onCreateContext( sal_Int32 nElement, const AttributeList& /*rAttribs*/ ) +{ + switch( nElement ) + { + case XLS_TOKEN( si ): + return new OoxRichStringContext( *this, getSharedStrings().createRichString() ); + } + return this; +} + +bool OoxSharedStringsFragment::onCanCreateRecordContext( sal_Int32 nRecId ) +{ + switch( getCurrentContext() ) + { + case XML_ROOT_CONTEXT: + return (nRecId == OOBIN_ID_SST); + case OOBIN_ID_SST: + return (nRecId == OOBIN_ID_SI); + } + return false; +} + +void OoxSharedStringsFragment::onStartRecord( RecordInputStream& rStrm ) +{ + switch( getCurrentContext() ) + { + case OOBIN_ID_SI: getSharedStrings().createRichString()->importString( rStrm, true ); break; + } +} + +// oox.xls.OoxFragmentHandler interface --------------------------------------- + +void OoxSharedStringsFragment::finalizeImport() +{ + getSharedStrings().finalizeImport(); +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/sheetcellrangemap.cxx b/oox/source/xls/sheetcellrangemap.cxx new file mode 100644 index 000000000000..aeb35953a558 --- /dev/null +++ b/oox/source/xls/sheetcellrangemap.cxx @@ -0,0 +1,172 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sheetcellrangemap.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2007 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/sheetcellrangemap.hxx" + +#define DEBUG_OOX_CELLRANGE_MAP 0 + +#include +#include + +#if DEBUG_OOX_CELLRANGE_MAP +#include +#endif + +using ::com::sun::star::table::CellAddress; +using ::com::sun::star::table::CellRangeAddress; + +namespace oox { +namespace xls { + +SheetCellRangeMap::SheetCellRangeMap() +{ +} + +SheetCellRangeMap::~SheetCellRangeMap() throw() +{ +} + +void SheetCellRangeMap::addCellRange( const CellRangeAddress& aRangeAddr ) +{ + size_t nAreaId = maAreas.size(); + + // First, find the sheet ID. + SheetMapType::iterator posSheet = maSheetMap.find(aRangeAddr.Sheet); + if ( posSheet == maSheetMap.end() ) + { + maSheetMap.insert( SheetMapType::value_type(aRangeAddr.Sheet, SheetSet()) ); + posSheet = maSheetMap.find(aRangeAddr.Sheet); + OSL_ENSURE( posSheet != maSheetMap.end(), "SheetCellRangeMap::addCellRange: insertion failure" ); + } + SheetSet& rSheet = posSheet->second; + + addRange(rSheet.maColRanges, aRangeAddr.StartColumn, aRangeAddr.EndColumn, nAreaId); + addRange(rSheet.maRowRanges, aRangeAddr.StartRow, aRangeAddr.EndRow, nAreaId); + +#if DEBUG_OOX_CELLRANGE_MAP + fprintf(stdout, "SheetCellRangeMap::addCellRange: adding (sheet: %d) (col: %ld - %ld) (row: %ld - %ld) (area: %d)\n", + aRangeAddr.Sheet, aRangeAddr.StartColumn, aRangeAddr.EndColumn, aRangeAddr.StartRow, aRangeAddr.EndRow, nAreaId);fflush(stdout); +#endif + + maAreas.push_back(aRangeAddr); +} + +bool SheetCellRangeMap::isOverlapping( const CellAddress& aCellAddr ) const +{ + if ( maAreas.empty() ) + return false; + + SheetMapType::const_iterator pos = maSheetMap.find(aCellAddr.Sheet); + if ( pos == maSheetMap.end() ) + // There is no cell range registered for this sheet. + return false; + + const SheetSet& rSheet = pos->second; + return searchColumns( rSheet, aCellAddr ); +} + +void SheetCellRangeMap::addRange( StartEndMapType& rRangeMap, sal_Int32 nStart, sal_Int32 nEnd, size_t nAreaId ) +{ + StartEndMapType::iterator posStart = rRangeMap.find(nStart); + if ( posStart == rRangeMap.end() ) + { + EndAreaIdMapType aMap; + rRangeMap.insert( StartEndMapType::value_type(nStart, aMap) ); + posStart = rRangeMap.find(nStart); + OSL_ENSURE( posStart != rRangeMap.end(), "TableBuffer::addRangeToSet: insertion failure" ); + } + EndAreaIdMapType& rEndMap = posStart->second; + + EndAreaIdMapType::iterator posEnd = rEndMap.find(nEnd); + if ( posEnd == rEndMap.end() ) + { + AreaIdSetType aSet; + rEndMap.insert( EndAreaIdMapType::value_type(nEnd, aSet) ); + posEnd = rEndMap.find(nEnd); + OSL_ENSURE( posEnd != rEndMap.end(), "TableBuffer::addRangeToSet: insertion failure" ); + } + + AreaIdSetType& rSet = posEnd->second; + rSet.push_back(nAreaId); +} + +bool SheetCellRangeMap::expandSearch( const EndAreaIdMapType& rEndMap, const CellAddress& rCellAddr, bool bColumn ) const +{ + sal_Int32 nId = bColumn ? rCellAddr.Column : rCellAddr.Row; + + EndAreaIdMapType::const_reverse_iterator itr, itrBeg = rEndMap.rbegin(), itrEnd = rEndMap.rend(); + for ( itr = itrBeg; itr != itrEnd; ++itr ) + { + if ( itr->first >= nId ) + { + // The point is in-range. + const AreaIdSetType& rSet = itr->second; + AreaIdSetType::const_iterator itr2 = rSet.begin(), itr2End = rSet.end(); + for ( ; itr2 != itr2End; ++itr2 ) + { + OSL_ENSURE( maAreas.size() > *itr2, "SheetCellRangeMap::expandSearch: size mismatch" ); + const CellRangeAddress& rRange = maAreas[*itr2]; + if ( bColumn && rCellAddr.Row >= rRange.StartRow && rCellAddr.Row <= rRange.EndRow ) + return true; + if ( !bColumn && rCellAddr.Column >= rRange.StartColumn && rCellAddr.Column <= rRange.EndColumn ) + return true; + } + } + else if ( itr->first < nId ) + // No more enclosing ranges. + return false; + } + return false; +} + +bool SheetCellRangeMap::searchColumns( const SheetSet& rSheet, const CellAddress& aCellAddr ) const +{ + StartEndMapType::const_iterator itr, itrBeg = rSheet.maColRanges.begin(), itrEnd = rSheet.maColRanges.end(); + for ( itr = itrBeg; itr != itrEnd; ++itr ) + { + if ( itr->first <= aCellAddr.Column ) + { + if ( expandSearch(itr->second, aCellAddr, true) ) + return true; + } + else if ( itr->first > aCellAddr.Column ) + return false; + } + return false; +} + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/sheetdatacontext.cxx b/oox/source/xls/sheetdatacontext.cxx new file mode 100644 index 000000000000..b605326f2f07 --- /dev/null +++ b/oox/source/xls/sheetdatacontext.cxx @@ -0,0 +1,1160 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sheetdatacontext.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/sheetdatacontext.hxx" +#include +#include +#include +#include +#include +#include +#include "oox/helper/attributelist.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/helper/recordinputstream.hxx" +#include "oox/xls/addressconverter.hxx" +#include "oox/xls/biffinputstream.hxx" +#include "oox/xls/formulaparser.hxx" +#include "oox/xls/pivottablebuffer.hxx" +#include "oox/xls/richstringcontext.hxx" +#include "oox/xls/sharedformulabuffer.hxx" +#include "oox/xls/unitconverter.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::table::CellAddress; +using ::com::sun::star::table::CellRangeAddress; +using ::com::sun::star::table::CellContentType_EMPTY; +using ::com::sun::star::table::XCell; +using ::com::sun::star::table::XCellRange; +using ::com::sun::star::sheet::XFormulaTokens; +using ::com::sun::star::sheet::XArrayFormulaTokens; +using ::com::sun::star::text::XText; +using ::com::sun::star::xml::sax::XFastContextHandler; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +// record constants ----------------------------------------------------------- + +const sal_uInt16 OOBIN_CELL_SHOWPHONETIC = 0x0100; + +const sal_uInt8 OOBIN_DATATABLE_ROW = 0x01; +const sal_uInt8 OOBIN_DATATABLE_2D = 0x02; +const sal_uInt8 OOBIN_DATATABLE_REF1DEL = 0x04; +const sal_uInt8 OOBIN_DATATABLE_REF2DEL = 0x08; + +const sal_uInt16 OOBIN_ROW_THICKTOP = 0x0001; +const sal_uInt16 OOBIN_ROW_THICKBOTTOM = 0x0002; +const sal_uInt16 OOBIN_ROW_COLLAPSED = 0x0800; +const sal_uInt16 OOBIN_ROW_HIDDEN = 0x1000; +const sal_uInt16 OOBIN_ROW_CUSTOMHEIGHT = 0x2000; +const sal_uInt16 OOBIN_ROW_CUSTOMFORMAT = 0x4000; + +const sal_uInt8 BIFF_BOOLERR_BOOL = 0; +const sal_uInt8 BIFF_BOOLERR_ERROR = 1; + +const sal_uInt16 BIFF_DATATABLE_ROW = 0x0004; +const sal_uInt16 BIFF_DATATABLE_2D = 0x0008; +const sal_uInt16 BIFF_DATATABLE_REF1DEL = 0x0010; +const sal_uInt16 BIFF_DATATABLE_REF2DEL = 0x0020; + +const sal_uInt8 BIFF_FORMULA_RES_STRING = 0; /// Result is a string. +const sal_uInt8 BIFF_FORMULA_RES_BOOL = 1; /// Result is Boolean value. +const sal_uInt8 BIFF_FORMULA_RES_ERROR = 2; /// Result is error code. +const sal_uInt8 BIFF_FORMULA_RES_EMPTY = 3; /// Result is empty cell (BIFF8 only). +const sal_uInt16 BIFF_FORMULA_SHARED = 0x0008; /// Shared formula cell. + +const sal_uInt8 BIFF2_ROW_CUSTOMFORMAT = 0x01; +const sal_uInt16 BIFF_ROW_DEFAULTHEIGHT = 0x8000; +const sal_uInt16 BIFF_ROW_HEIGHTMASK = 0x7FFF; +const sal_uInt32 BIFF_ROW_COLLAPSED = 0x00000010; +const sal_uInt32 BIFF_ROW_HIDDEN = 0x00000020; +const sal_uInt32 BIFF_ROW_CUSTOMHEIGHT = 0x00000040; +const sal_uInt32 BIFF_ROW_CUSTOMFORMAT = 0x00000080; +const sal_uInt32 BIFF_ROW_THICKTOP = 0x10000000; +const sal_uInt32 BIFF_ROW_THICKBOTTOM = 0x20000000; +const sal_uInt32 BIFF_ROW_SHOWPHONETIC = 0x40000000; + +const sal_Int32 BIFF_XF_EXTENDED_IDS = 63; +const sal_uInt8 BIFF2_XF_MASK = 0x3F; + +// ---------------------------------------------------------------------------- + +/** Formula context for cell formulas. */ +class CellFormulaContext : public SimpleFormulaContext +{ +public: + explicit CellFormulaContext( + const Reference< XFormulaTokens >& rxTokens, + const CellAddress& rCellPos ); +}; + +CellFormulaContext::CellFormulaContext( const Reference< XFormulaTokens >& rxTokens, const CellAddress& rCellPos ) : + SimpleFormulaContext( rxTokens, false, false ) +{ + setBaseAddress( rCellPos ); +} + +// ---------------------------------------------------------------------------- + +/** Uses the XArrayFormulaTokens interface to set a token sequence. */ +class ArrayFormulaContext : public FormulaContext +{ +public: + explicit ArrayFormulaContext( + const Reference< XArrayFormulaTokens >& rxTokens, + const CellRangeAddress& rArrayRange ); + + virtual void setTokens( const ApiTokenSequence& rTokens ); + +private: + Reference< XArrayFormulaTokens > mxTokens; +}; + +ArrayFormulaContext::ArrayFormulaContext( + const Reference< XArrayFormulaTokens >& rxTokens, const CellRangeAddress& rArrayRange ) : + FormulaContext( false, false ), + mxTokens( rxTokens ) +{ + OSL_ENSURE( mxTokens.is(), "ArrayFormulaContext::ArrayFormulaContext - missing XArrayFormulaTokens interface" ); + setBaseAddress( CellAddress( rArrayRange.Sheet, rArrayRange.StartColumn, rArrayRange.StartRow ) ); +} + +void ArrayFormulaContext::setTokens( const ApiTokenSequence& rTokens ) +{ + mxTokens->setArrayTokens( rTokens ); +} + +// ---------------------------------------------------------------------------- + +} // namespace + +// ============================================================================ + +OoxSheetDataContext::OoxSheetDataContext( const OoxWorksheetFragmentBase& rFragment ) : + OoxWorksheetContextBase( rFragment ) +{ +} + +// oox.xls.OoxContextHelper interface ----------------------------------------- + +bool OoxSheetDataContext::onCanCreateContext( sal_Int32 nElement ) const +{ + switch( getCurrentContext() ) + { + case XLS_TOKEN( sheetData ): + return (nElement == XLS_TOKEN( row )); + case XLS_TOKEN( row ): + return (nElement == XLS_TOKEN( c )); + case XLS_TOKEN( c ): + return maCurrCell.mxCell.is() && + ((nElement == XLS_TOKEN( v )) || + (nElement == XLS_TOKEN( is )) || + (nElement == XLS_TOKEN( f ))); + } + return false; +} + +Reference< XFastContextHandler > OoxSheetDataContext::onCreateContext( sal_Int32 nElement, const AttributeList& /*rAttribs*/ ) +{ + switch( nElement ) + { + case XLS_TOKEN( is ): + mxInlineStr.reset( new RichString( *this ) ); + return new OoxRichStringContext( *this, mxInlineStr ); + } + return this; +} + +void OoxSheetDataContext::onStartElement( const AttributeList& rAttribs ) +{ + switch( getCurrentContext() ) + { + case XLS_TOKEN( row ): importRow( rAttribs ); break; + case XLS_TOKEN( c ): importCell( rAttribs ); break; + case XLS_TOKEN( f ): importFormula( rAttribs ); break; + } +} + +void OoxSheetDataContext::onEndElement( const OUString& rChars ) +{ + switch( getCurrentContext() ) + { + case XLS_TOKEN( v ): + maCurrCell.maValueStr = rChars; + maCurrCell.mbHasValueStr = true; + break; + + case XLS_TOKEN( f ): + if( maCurrCell.mxCell.is() ) try + { + switch( maCurrCell.mnFormulaType ) + { + case XML_normal: + if( rChars.getLength() > 0 ) + { + Reference< XFormulaTokens > xTokens( maCurrCell.mxCell, UNO_QUERY_THROW ); + CellFormulaContext aContext( xTokens, maCurrCell.maAddress ); + getFormulaParser().importFormula( aContext, rChars ); + } + break; + + case XML_array: + if( (maCurrCell.maFormulaRef.getLength() > 0) && (rChars.getLength() > 0) ) + { + CellRangeAddress aArrayRange; + Reference< XArrayFormulaTokens > xTokens( getCellRange( maCurrCell.maFormulaRef, &aArrayRange ), UNO_QUERY_THROW ); + ArrayFormulaContext aContext( xTokens, aArrayRange ); + getFormulaParser().importFormula( aContext, rChars ); + } + break; + + case XML_shared: + if( maCurrCell.mnSharedId >= 0 ) + { + if( rChars.getLength() > 0 ) + getSharedFormulas().importSharedFmla( rChars, maCurrCell.maFormulaRef, maCurrCell.mnSharedId, maCurrCell.maAddress ); + Reference< XFormulaTokens > xTokens( maCurrCell.mxCell, UNO_QUERY_THROW ); + ExtCellFormulaContext aContext( *this, xTokens, maCurrCell.maAddress ); + getSharedFormulas().setSharedFormulaCell( aContext, maCurrCell.mnSharedId ); + } + break; + + case XML_dataTable: + if( maCurrCell.maFormulaRef.getLength() > 0 ) + { + CellRangeAddress aTableRange; + if( getAddressConverter().convertToCellRange( aTableRange, maCurrCell.maFormulaRef, getSheetIndex(), true ) ) + setTableOperation( aTableRange, maTableData ); + } + break; + + default: + OSL_ENSURE( false, "OoxSheetDataContext::onEndElement - unknown formula type" ); + } + } + catch( Exception& ) + { + } + break; + + case XLS_TOKEN( c ): + if( maCurrCell.mxCell.is() ) + { + if( maCurrCell.mxCell->getType() == CellContentType_EMPTY ) + { + if( maCurrCell.mbHasValueStr ) + { + // implemented in WorksheetHelper class + setOoxCell( maCurrCell ); + } + else if( (maCurrCell.mnCellType == XML_inlineStr) && mxInlineStr.get() ) + { + // convert font settings + mxInlineStr->finalizeImport(); + // write string to cell + Reference< XText > xText( maCurrCell.mxCell, UNO_QUERY ); + if( xText.is() ) + mxInlineStr->convert( xText, maCurrCell.mnXfId ); + } + else + { + // empty cell, update cell type + maCurrCell.mnCellType = XML_TOKEN_INVALID; + } + } + + // store the cell formatting data + setCellFormat( maCurrCell ); + } + break; + } +} + +bool OoxSheetDataContext::onCanCreateRecordContext( sal_Int32 nRecId ) +{ + switch( getCurrentContext() ) + { + case OOBIN_ID_SHEETDATA: + return (nRecId == OOBIN_ID_ROW); + case OOBIN_ID_ROW: + return (nRecId == OOBIN_ID_ARRAY) || + (nRecId == OOBIN_ID_CELL_BOOL) || + (nRecId == OOBIN_ID_CELL_BLANK) || + (nRecId == OOBIN_ID_CELL_DOUBLE) || + (nRecId == OOBIN_ID_CELL_ERROR) || + (nRecId == OOBIN_ID_CELL_RK) || + (nRecId == OOBIN_ID_CELL_RSTRING) || + (nRecId == OOBIN_ID_CELL_SI) || + (nRecId == OOBIN_ID_CELL_STRING) || + (nRecId == OOBIN_ID_DATATABLE) || + (nRecId == OOBIN_ID_FORMULA_BOOL) || + (nRecId == OOBIN_ID_FORMULA_DOUBLE) || + (nRecId == OOBIN_ID_FORMULA_ERROR) || + (nRecId == OOBIN_ID_FORMULA_STRING) || + (nRecId == OOBIN_ID_SHAREDFMLA); + } + return false; +} + +void OoxSheetDataContext::onStartRecord( RecordInputStream& rStrm ) +{ + switch( getCurrentContext() ) + { + case OOBIN_ID_ARRAY: importArray( rStrm ); break; + case OOBIN_ID_CELL_BOOL: importCellBool( rStrm, false ); break; + case OOBIN_ID_CELL_BLANK: importCellBlank( rStrm ); break; + case OOBIN_ID_CELL_DOUBLE: importCellDouble( rStrm, false ); break; + case OOBIN_ID_CELL_ERROR: importCellError( rStrm, false ); break; + case OOBIN_ID_CELL_RK: importCellRk( rStrm ); break; + case OOBIN_ID_CELL_RSTRING: importCellRString( rStrm ); break; + case OOBIN_ID_CELL_SI: importCellSi( rStrm ); break; + case OOBIN_ID_CELL_STRING: importCellString( rStrm, false ); break; + case OOBIN_ID_DATATABLE: importDataTable( rStrm ); break; + case OOBIN_ID_FORMULA_BOOL: importCellBool( rStrm, true ); break; + case OOBIN_ID_FORMULA_DOUBLE: importCellDouble( rStrm, true ); break; + case OOBIN_ID_FORMULA_ERROR: importCellError( rStrm, true ); break; + case OOBIN_ID_FORMULA_STRING: importCellString( rStrm, true ); break; + case OOBIN_ID_ROW: importRow( rStrm ); break; + case OOBIN_ID_SHAREDFMLA: importSharedFmla( rStrm ); break; + } +} + +// private -------------------------------------------------------------------- + +void OoxSheetDataContext::importRow( const AttributeList& rAttribs ) +{ + OoxRowData aData; + aData.mnFirstRow = aData.mnLastRow = rAttribs.getInteger( XML_r, -1 ); + aData.mfHeight = rAttribs.getDouble( XML_ht, -1.0 ); + aData.mnXfId = rAttribs.getInteger( XML_s, -1 ); + aData.mnLevel = rAttribs.getInteger( XML_outlineLevel, 0 ); + aData.mbCustomHeight = rAttribs.getBool( XML_customHeight, false ); + aData.mbCustomFormat = rAttribs.getBool( XML_customFormat, false ); + aData.mbShowPhonetic = rAttribs.getBool( XML_ph, false ); + aData.mbHidden = rAttribs.getBool( XML_hidden, false ); + aData.mbCollapsed = rAttribs.getBool( XML_collapsed, false ); + aData.mbThickTop = rAttribs.getBool( XML_thickTop, false ); + aData.mbThickBottom = rAttribs.getBool( XML_thickBot, false ); + // set row properties in the current sheet + setRowData( aData ); +} + +void OoxSheetDataContext::importCell( const AttributeList& rAttribs ) +{ + maCurrCell.reset(); + maCurrCell.mxCell = getCell( rAttribs.getString( XML_r ), &maCurrCell.maAddress ); + maCurrCell.mnCellType = rAttribs.getToken( XML_t, XML_n ); + maCurrCell.mnXfId = rAttribs.getInteger( XML_s, -1 ); + maCurrCell.mbShowPhonetic = rAttribs.getBool( XML_ph, false ); + mxInlineStr.reset(); + + if( maCurrCell.mxCell.is() && getPivotTables().isOverlapping( maCurrCell.maAddress ) ) + // This cell overlaps a pivot table. Skip it. + maCurrCell.mxCell.clear(); +} + +void OoxSheetDataContext::importFormula( const AttributeList& rAttribs ) +{ + maCurrCell.maFormulaRef = rAttribs.getString( XML_ref ); + maCurrCell.mnFormulaType = rAttribs.getToken( XML_t, XML_normal ); + maCurrCell.mnSharedId = rAttribs.getInteger( XML_si, -1 ); + maTableData.maRef1 = rAttribs.getString( XML_r1 ); + maTableData.maRef2 = rAttribs.getString( XML_r2 ); + maTableData.mb2dTable = rAttribs.getBool( XML_dt2D, false ); + maTableData.mbRowTable = rAttribs.getBool( XML_dtr, false ); + maTableData.mbRef1Deleted = rAttribs.getBool( XML_del1, false ); + maTableData.mbRef2Deleted = rAttribs.getBool( XML_del2, false ); +} + +void OoxSheetDataContext::importCellHeader( RecordInputStream& rStrm ) +{ + maCurrCell.reset(); + sal_uInt16 nXfId, nFlags; + rStrm >> maCurrPos.mnCol >> nXfId >> nFlags; + + maCurrCell.mxCell = getCell( maCurrPos, &maCurrCell.maAddress ); + maCurrCell.mnXfId = nXfId; + maCurrCell.mbShowPhonetic = getFlag( nFlags, OOBIN_CELL_SHOWPHONETIC ); +} + +void OoxSheetDataContext::importCellBool( RecordInputStream& rStrm, bool bFormula ) +{ + importCellHeader( rStrm ); + maCurrCell.mnCellType = XML_b; + if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) ) + { + bool bValue = rStrm.readuInt8() != 0; + if( bFormula ) + { + importCellFormula( rStrm ); + } + else + { + setBooleanCell( maCurrCell.mxCell, bValue ); + // #108770# set 'Standard' number format for all Boolean cells + maCurrCell.mnNumFmtId = 0; + } + } + setCellFormat( maCurrCell ); +} + +void OoxSheetDataContext::importCellBlank( RecordInputStream& rStrm ) +{ + importCellHeader( rStrm ); + setCellFormat( maCurrCell ); +} + +void OoxSheetDataContext::importCellDouble( RecordInputStream& rStrm, bool bFormula ) +{ + importCellHeader( rStrm ); + maCurrCell.mnCellType = XML_n; + if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) ) + { + double fValue = rStrm.readDouble(); + if( bFormula ) + importCellFormula( rStrm ); + else + maCurrCell.mxCell->setValue( fValue ); + } + setCellFormat( maCurrCell ); +} + +void OoxSheetDataContext::importCellError( RecordInputStream& rStrm, bool bFormula ) +{ + importCellHeader( rStrm ); + maCurrCell.mnCellType = XML_e; + if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) ) + { + sal_uInt8 nErrorCode = rStrm.readuInt8(); + if( bFormula ) + importCellFormula( rStrm ); + else + setErrorCell( maCurrCell.mxCell, nErrorCode ); + } + setCellFormat( maCurrCell ); +} + +void OoxSheetDataContext::importCellRk( RecordInputStream& rStrm ) +{ + importCellHeader( rStrm ); + maCurrCell.mnCellType = XML_n; + if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) ) + maCurrCell.mxCell->setValue( BiffHelper::calcDoubleFromRk( rStrm.readInt32() ) ); + setCellFormat( maCurrCell ); +} + +void OoxSheetDataContext::importCellRString( RecordInputStream& rStrm ) +{ + importCellHeader( rStrm ); + maCurrCell.mnCellType = XML_inlineStr; + Reference< XText > xText( maCurrCell.mxCell, UNO_QUERY ); + if( xText.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) ) + { + RichString aString( *this ); + aString.importString( rStrm, true ); + aString.finalizeImport(); + aString.convert( xText, maCurrCell.mnXfId ); + } + setCellFormat( maCurrCell ); +} + +void OoxSheetDataContext::importCellSi( RecordInputStream& rStrm ) +{ + importCellHeader( rStrm ); + maCurrCell.mnCellType = XML_s; + if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) ) + setSharedStringCell( maCurrCell.mxCell, rStrm.readInt32(), maCurrCell.mnXfId ); + setCellFormat( maCurrCell ); +} + +void OoxSheetDataContext::importCellString( RecordInputStream& rStrm, bool bFormula ) +{ + importCellHeader( rStrm ); + maCurrCell.mnCellType = XML_inlineStr; + Reference< XText > xText( maCurrCell.mxCell, UNO_QUERY ); + if( xText.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) ) + { + RichString aString( *this ); + aString.importString( rStrm, false ); + aString.finalizeImport(); + if( bFormula ) + importCellFormula( rStrm ); + else + aString.convert( xText, maCurrCell.mnXfId ); + } + setCellFormat( maCurrCell ); +} + +void OoxSheetDataContext::importCellFormula( RecordInputStream& rStrm ) +{ + rStrm.skip( 2 ); + Reference< XFormulaTokens > xTokens( maCurrCell.mxCell, UNO_QUERY ); + if( xTokens.is() ) + { + ExtCellFormulaContext aContext( *this, xTokens, maCurrCell.maAddress ); + getFormulaParser().importFormula( aContext, rStrm ); + } +} + +void OoxSheetDataContext::importRow( RecordInputStream& rStrm ) +{ + OoxRowData aData; + + sal_uInt16 nHeight, nFlags; + rStrm >> maCurrPos.mnRow >> aData.mnXfId >> nHeight >> nFlags; + + // row index is 0-based in OOBIN, but OoxRowData expects 1-based + aData.mnFirstRow = aData.mnLastRow = maCurrPos.mnRow + 1; + // row height is in twips in OOBIN, convert to points + aData.mfHeight = nHeight / 20.0; + aData.mnLevel = extractValue< sal_Int32 >( nFlags, 8, 3 ); + aData.mbCustomHeight = getFlag( nFlags, OOBIN_ROW_CUSTOMHEIGHT ); + aData.mbCustomFormat = getFlag( nFlags, OOBIN_ROW_CUSTOMFORMAT ); + // 'show phonetic' missing in OOBIN (bug in Excel 2007) + aData.mbHidden = getFlag( nFlags, OOBIN_ROW_HIDDEN ); + aData.mbCollapsed = getFlag( nFlags, OOBIN_ROW_COLLAPSED ); + aData.mbThickTop = getFlag( nFlags, OOBIN_ROW_THICKTOP ); + aData.mbThickBottom = getFlag( nFlags, OOBIN_ROW_THICKBOTTOM ); + // set row properties in the current sheet + setRowData( aData ); +} + +void OoxSheetDataContext::importArray( RecordInputStream& rStrm ) +{ + BinRange aRange; + rStrm >> aRange; + CellRangeAddress aArrayRange; + Reference< XCellRange > xRange = getCellRange( aRange, &aArrayRange ); + Reference< XArrayFormulaTokens > xTokens( xRange, UNO_QUERY ); + if( xRange.is() && xTokens.is() ) + { + rStrm.skip( 1 ); + ArrayFormulaContext aContext( xTokens, aArrayRange ); + getFormulaParser().importFormula( aContext, rStrm ); + } +} + +void OoxSheetDataContext::importSharedFmla( RecordInputStream& rStrm ) +{ + getSharedFormulas().importSharedFmla( rStrm, maCurrCell.maAddress ); +} + +void OoxSheetDataContext::importDataTable( RecordInputStream& rStrm ) +{ + BinRange aRange; + rStrm >> aRange; + CellRangeAddress aTableRange; + if( getAddressConverter().convertToCellRange( aTableRange, aRange, getSheetIndex(), true ) ) + { + OoxDataTableData aTableData; + BinAddress aRef1, aRef2; + sal_uInt8 nFlags; + rStrm >> aRef1 >> aRef2 >> nFlags; + aTableData.maRef1 = FormulaProcessorBase::generateAddress2dString( aRef1, false ); + aTableData.maRef2 = FormulaProcessorBase::generateAddress2dString( aRef2, false ); + aTableData.mbRowTable = getFlag( nFlags, OOBIN_DATATABLE_ROW ); + aTableData.mb2dTable = getFlag( nFlags, OOBIN_DATATABLE_2D ); + aTableData.mbRef1Deleted = getFlag( nFlags, OOBIN_DATATABLE_REF1DEL ); + aTableData.mbRef2Deleted = getFlag( nFlags, OOBIN_DATATABLE_REF2DEL ); + setTableOperation( aTableRange, aTableData ); + } +} + +// ============================================================================ + +OoxExternalSheetDataContext::OoxExternalSheetDataContext( + const OoxWorkbookFragmentBase& rFragment, WorksheetType eSheetType, sal_Int32 nSheet ) : + OoxWorksheetContextBase( rFragment, ISegmentProgressBarRef(), eSheetType, nSheet ) +{ +} + +// oox.xls.ContextHelper interface -------------------------------------------- + +bool OoxExternalSheetDataContext::onCanCreateContext( sal_Int32 nElement ) const +{ + switch( getCurrentContext() ) + { + case XLS_TOKEN( sheetData ): + return (nElement == XLS_TOKEN( row )); + case XLS_TOKEN( row ): + return (nElement == XLS_TOKEN( cell )); + case XLS_TOKEN( cell ): + return (nElement == XLS_TOKEN( v )) && maCurrCell.mxCell.is(); + } + return false; +} + +void OoxExternalSheetDataContext::onStartElement( const AttributeList& rAttribs ) +{ + switch( getCurrentContext() ) + { + case XLS_TOKEN( cell ): + importCell( rAttribs ); + break; + } +} + +void OoxExternalSheetDataContext::onEndElement( const OUString& rChars ) +{ + switch( getCurrentContext() ) + { + case XLS_TOKEN( v ): + maCurrCell.maValueStr = rChars; + maCurrCell.mbHasValueStr = true; + break; + + case XLS_TOKEN( cell ): + if( maCurrCell.mxCell.is() ) + setOoxCell( maCurrCell, true ); + break; + } +} + +bool OoxExternalSheetDataContext::onCanCreateRecordContext( sal_Int32 nRecId ) +{ + switch( getCurrentContext() ) + { + case OOBIN_ID_EXTSHEETDATA: + return (nRecId == OOBIN_ID_EXTROW); + case OOBIN_ID_EXTROW: + return (nRecId == OOBIN_ID_EXTCELL_BOOL) || + (nRecId == OOBIN_ID_EXTCELL_DOUBLE) || + (nRecId == OOBIN_ID_EXTCELL_ERROR) || + (nRecId == OOBIN_ID_EXTCELL_STRING); + } + return false; +} + +void OoxExternalSheetDataContext::onStartRecord( RecordInputStream& rStrm ) +{ + switch( getCurrentContext() ) + { + case OOBIN_ID_EXTCELL_BOOL: importExtCellBool( rStrm ); break; + case OOBIN_ID_EXTCELL_DOUBLE: importExtCellDouble( rStrm ); break; + case OOBIN_ID_EXTCELL_ERROR: importExtCellError( rStrm ); break; + case OOBIN_ID_EXTCELL_STRING: importExtCellString( rStrm ); break; + case OOBIN_ID_EXTROW: rStrm >> maCurrPos.mnRow; break; + } +} + +// private -------------------------------------------------------------------- + +void OoxExternalSheetDataContext::importCell( const AttributeList& rAttribs ) +{ + maCurrCell.reset(); + maCurrCell.mxCell = getCell( rAttribs.getString( XML_r ), &maCurrCell.maAddress ); + maCurrCell.mnCellType = rAttribs.getToken( XML_t, XML_n ); +} + +void OoxExternalSheetDataContext::importCellHeader( RecordInputStream& rStrm ) +{ + maCurrCell.reset(); + rStrm >> maCurrPos.mnCol; + maCurrCell.mxCell = getCell( maCurrPos, &maCurrCell.maAddress ); +} + +void OoxExternalSheetDataContext::importExtCellBool( RecordInputStream& rStrm ) +{ + importCellHeader( rStrm ); + if( maCurrCell.mxCell.is() ) + setBooleanCell( maCurrCell.mxCell, rStrm.readuInt8() != 0 ); +} + +void OoxExternalSheetDataContext::importExtCellDouble( RecordInputStream& rStrm ) +{ + importCellHeader( rStrm ); + if( maCurrCell.mxCell.is() ) + maCurrCell.mxCell->setValue( rStrm.readDouble() ); +} + +void OoxExternalSheetDataContext::importExtCellError( RecordInputStream& rStrm ) +{ + importCellHeader( rStrm ); + if( maCurrCell.mxCell.is() ) + setErrorCell( maCurrCell.mxCell, rStrm.readuInt8() ); +} + +void OoxExternalSheetDataContext::importExtCellString( RecordInputStream& rStrm ) +{ + importCellHeader( rStrm ); + if( maCurrCell.mxCell.is() ) + setStringCell( maCurrCell.mxCell, rStrm.readString(), true ); +} + +// ============================================================================ +// ============================================================================ + +BiffSheetDataContext::BiffSheetDataContext( const WorksheetHelper& rHelper ) : + WorksheetHelper( rHelper ), + mnBiff2XfId( 0 ) +{ + mnArrayIgnoreSize = (getBiff() == BIFF2) ? 1 : ((getBiff() <= BIFF4) ? 2 : 6); + switch( getBiff() ) + { + case BIFF2: + mnFormulaIgnoreSize = 9; // double formula result, 1 byte flags + mnArrayIgnoreSize = 1; // recalc-always flag + break; + case BIFF3: + case BIFF4: + mnFormulaIgnoreSize = 10; // double formula result, 2 byte flags + mnArrayIgnoreSize = 2; // 2 byte flags + break; + case BIFF5: + case BIFF8: + mnFormulaIgnoreSize = 14; // double formula result, 2 byte flags, 4 bytes nothing + mnArrayIgnoreSize = 6; // 2 byte flags, 4 bytes nothing + break; + case BIFF_UNKNOWN: break; + } +} + +void BiffSheetDataContext::importRecord( BiffInputStream& rStrm ) +{ + sal_uInt16 nRecId = rStrm.getRecId(); + switch( nRecId ) + { + // records in all BIFF versions + case BIFF2_ID_ARRAY: // #i72713# + case BIFF3_ID_ARRAY: importArray( rStrm ); break; + case BIFF2_ID_BLANK: + case BIFF3_ID_BLANK: importBlank( rStrm ); break; + case BIFF2_ID_BOOLERR: + case BIFF3_ID_BOOLERR: importBoolErr( rStrm ); break; + case BIFF2_ID_INTEGER: importInteger( rStrm ); break; + case BIFF_ID_IXFE: rStrm >> mnBiff2XfId; break; + case BIFF2_ID_LABEL: + case BIFF3_ID_LABEL: importLabel( rStrm ); break; + case BIFF2_ID_NUMBER: + case BIFF3_ID_NUMBER: importNumber( rStrm ); break; + case BIFF_ID_RK: importRk( rStrm ); break; + + // BIFF specific records + default: switch( getBiff() ) + { + case BIFF2: switch( nRecId ) + { + case BIFF2_ID_DATATABLE: importDataTable( rStrm ); break; + case BIFF2_ID_DATATABLE2: importDataTable( rStrm ); break; + case BIFF2_ID_FORMULA: importFormula( rStrm ); break; + case BIFF2_ID_ROW: importRow( rStrm ); break; + } + break; + + case BIFF3: switch( nRecId ) + { + case BIFF3_ID_DATATABLE: importDataTable( rStrm ); break; + case BIFF3_ID_FORMULA: importFormula( rStrm ); break; + case BIFF3_ID_ROW: importRow( rStrm ); break; + } + break; + + case BIFF4: switch( nRecId ) + { + case BIFF3_ID_DATATABLE: importDataTable( rStrm ); break; + case BIFF4_ID_FORMULA: importFormula( rStrm ); break; + case BIFF3_ID_ROW: importRow( rStrm ); break; + } + break; + + case BIFF5: switch( nRecId ) + { + case BIFF3_ID_DATATABLE: importDataTable( rStrm ); break; + case BIFF3_ID_FORMULA: + case BIFF4_ID_FORMULA: + case BIFF5_ID_FORMULA: importFormula( rStrm ); break; + case BIFF_ID_MULTBLANK: importMultBlank( rStrm ); break; + case BIFF_ID_MULTRK: importMultRk( rStrm ); break; + case BIFF3_ID_ROW: importRow( rStrm ); break; + case BIFF_ID_RSTRING: importLabel( rStrm ); break; + case BIFF_ID_SHAREDFMLA: importSharedFmla( rStrm ); break; + } + break; + + case BIFF8: switch( nRecId ) + { + case BIFF3_ID_DATATABLE: importDataTable( rStrm ); break; + case BIFF3_ID_FORMULA: + case BIFF4_ID_FORMULA: + case BIFF5_ID_FORMULA: importFormula( rStrm ); break; + case BIFF_ID_LABELSST: importLabelSst( rStrm ); break; + case BIFF_ID_MULTBLANK: importMultBlank( rStrm ); break; + case BIFF_ID_MULTRK: importMultRk( rStrm ); break; + case BIFF3_ID_ROW: importRow( rStrm ); break; + case BIFF_ID_RSTRING: importLabel( rStrm ); break; + case BIFF_ID_SHAREDFMLA: importSharedFmla( rStrm ); break; + } + break; + + case BIFF_UNKNOWN: break; + } + } +} + +// private -------------------------------------------------------------------- + +void BiffSheetDataContext::setCurrCell( const BinAddress& rAddr ) +{ + maCurrCell.reset(); + maCurrCell.mxCell = getCell( rAddr, &maCurrCell.maAddress ); +} + +void BiffSheetDataContext::importXfId( BiffInputStream& rStrm, bool bBiff2 ) +{ + if( bBiff2 ) + { + sal_uInt8 nBiff2XfId; + rStrm >> nBiff2XfId; + rStrm.skip( 2 ); + maCurrCell.mnXfId = nBiff2XfId & BIFF2_XF_MASK; + if( maCurrCell.mnXfId == BIFF_XF_EXTENDED_IDS ) + maCurrCell.mnXfId = mnBiff2XfId; + } + else + { + maCurrCell.mnXfId = rStrm.readuInt16(); + } +} + +void BiffSheetDataContext::importCellHeader( BiffInputStream& rStrm, bool bBiff2 ) +{ + BinAddress aAddr; + rStrm >> aAddr; + setCurrCell( aAddr ); + importXfId( rStrm, bBiff2 ); +} + +void BiffSheetDataContext::importBlank( BiffInputStream& rStrm ) +{ + importCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_BLANK ); + setCellFormat( maCurrCell ); +} + +void BiffSheetDataContext::importBoolErr( BiffInputStream& rStrm ) +{ + importCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_BOOLERR ); + if( maCurrCell.mxCell.is() ) + { + sal_uInt8 nValue, nType; + rStrm >> nValue >> nType; + switch( nType ) + { + case BIFF_BOOLERR_BOOL: + maCurrCell.mnCellType = XML_b; + setBooleanCell( maCurrCell.mxCell, nValue != 0 ); + // #108770# set 'Standard' number format for all Boolean cells + maCurrCell.mnNumFmtId = 0; + break; + case BIFF_BOOLERR_ERROR: + maCurrCell.mnCellType = XML_e; + setErrorCell( maCurrCell.mxCell, nValue ); + break; + default: + OSL_ENSURE( false, "BiffSheetDataContext::importBoolErr - unknown cell type" ); + } + } + setCellFormat( maCurrCell ); +} + +void BiffSheetDataContext::importFormula( BiffInputStream& rStrm ) +{ + importCellHeader( rStrm, getBiff() == BIFF2 ); + maCurrCell.mnCellType = XML_n; + Reference< XFormulaTokens > xTokens( maCurrCell.mxCell, UNO_QUERY ); + if( xTokens.is() ) + { + rStrm.skip( mnFormulaIgnoreSize ); + ExtCellFormulaContext aContext( *this, xTokens, maCurrCell.maAddress ); + getFormulaParser().importFormula( aContext, rStrm ); + } + setCellFormat( maCurrCell ); +} + +void BiffSheetDataContext::importInteger( BiffInputStream& rStrm ) +{ + importCellHeader( rStrm, true ); + maCurrCell.mnCellType = XML_n; + if( maCurrCell.mxCell.is() ) + maCurrCell.mxCell->setValue( rStrm.readuInt16() ); + setCellFormat( maCurrCell ); +} + +void BiffSheetDataContext::importLabel( BiffInputStream& rStrm ) +{ + bool bBiff2Xf = rStrm.getRecId() == BIFF2_ID_LABEL; + importCellHeader( rStrm, bBiff2Xf ); + maCurrCell.mnCellType = XML_inlineStr; + Reference< XText > xText( maCurrCell.mxCell, UNO_QUERY ); + if( xText.is() ) + { + /* the deep secrets of BIFF type and record identifier... + record id BIFF XF type String type + 0x0004 2-7 3 byte 8-bit length, byte string + 0x0004 8 3 byte 16-bit length, unicode string + 0x0204 2-7 2 byte 16-bit length, byte string + 0x0204 8 2 byte 16-bit length, unicode string */ + + RichString aString( *this ); + if( getBiff() == BIFF8 ) + { + aString.importUniString( rStrm ); + } + else + { + // #i63105# use text encoding from FONT record + rtl_TextEncoding eTextEnc = getTextEncoding(); + if( const Font* pFont = getStyles().getFontFromCellXf( maCurrCell.mnXfId ).get() ) + eTextEnc = pFont->getFontEncoding(); + BiffStringFlags nFlags = bBiff2Xf ? BIFF_STR_8BITLENGTH : BIFF_STR_DEFAULT; + setFlag( nFlags, BIFF_STR_EXTRAFONTS, rStrm.getRecId() == BIFF_ID_RSTRING ); + aString.importByteString( rStrm, eTextEnc, nFlags ); + } + aString.finalizeImport(); + aString.convert( xText, maCurrCell.mnXfId ); + } + setCellFormat( maCurrCell ); +} + +void BiffSheetDataContext::importLabelSst( BiffInputStream& rStrm ) +{ + importCellHeader( rStrm, false ); + maCurrCell.mnCellType = XML_s; + if( maCurrCell.mxCell.is() ) + setSharedStringCell( maCurrCell.mxCell, rStrm.readInt32(), maCurrCell.mnXfId ); + setCellFormat( maCurrCell ); +} + +void BiffSheetDataContext::importMultBlank( BiffInputStream& rStrm ) +{ + BinAddress aAddr; + for( rStrm >> aAddr; rStrm.getRecLeft() > 2; ++aAddr.mnCol ) + { + setCurrCell( aAddr ); + importXfId( rStrm, false ); + setCellFormat( maCurrCell ); + } +} + +void BiffSheetDataContext::importMultRk( BiffInputStream& rStrm ) +{ + BinAddress aAddr; + for( rStrm >> aAddr; rStrm.getRecLeft() > 2; ++aAddr.mnCol ) + { + setCurrCell( aAddr ); + maCurrCell.mnCellType = XML_n; + importXfId( rStrm, false ); + sal_Int32 nRkValue = rStrm.readInt32(); + if( maCurrCell.mxCell.is() ) + maCurrCell.mxCell->setValue( BiffHelper::calcDoubleFromRk( nRkValue ) ); + setCellFormat( maCurrCell ); + } +} + +void BiffSheetDataContext::importNumber( BiffInputStream& rStrm ) +{ + importCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_NUMBER ); + maCurrCell.mnCellType = XML_n; + if( maCurrCell.mxCell.is() ) + maCurrCell.mxCell->setValue( rStrm.readDouble() ); + setCellFormat( maCurrCell ); +} + +void BiffSheetDataContext::importRk( BiffInputStream& rStrm ) +{ + importCellHeader( rStrm, false ); + maCurrCell.mnCellType = XML_n; + if( maCurrCell.mxCell.is() ) + maCurrCell.mxCell->setValue( BiffHelper::calcDoubleFromRk( rStrm.readInt32() ) ); + setCellFormat( maCurrCell ); +} + +void BiffSheetDataContext::importRow( BiffInputStream& rStrm ) +{ + OoxRowData aData; + + sal_uInt16 nRow, nHeight; + rStrm >> nRow; + rStrm.skip( 4 ); + rStrm >> nHeight; + if( getBiff() == BIFF2 ) + { + aData.mbCustomFormat = rStrm.skip( 2 ).readuInt8() == BIFF2_ROW_CUSTOMFORMAT; + if( aData.mbCustomFormat ) + aData.mnXfId = rStrm.skip( 5 ).readuInt16(); + } + else + { + sal_uInt32 nFlags = rStrm.skip( 4 ).readuInt32(); + aData.mnXfId = extractValue< sal_Int32 >( nFlags, 16, 12 ); + aData.mnLevel = extractValue< sal_Int32 >( nFlags, 0, 3 ); + aData.mbCustomFormat = getFlag( nFlags, BIFF_ROW_CUSTOMFORMAT ); + aData.mbCustomHeight = getFlag( nFlags, BIFF_ROW_CUSTOMHEIGHT ); + aData.mbShowPhonetic = getFlag( nFlags, BIFF_ROW_SHOWPHONETIC ); + aData.mbHidden = getFlag( nFlags, BIFF_ROW_HIDDEN ); + aData.mbCollapsed = getFlag( nFlags, BIFF_ROW_COLLAPSED ); + aData.mbThickTop = getFlag( nFlags, BIFF_ROW_THICKTOP ); + aData.mbThickBottom = getFlag( nFlags, BIFF_ROW_THICKBOTTOM ); + } + + // row index is 0-based in BIFF, but OoxRowData expects 1-based + aData.mnFirstRow = aData.mnLastRow = nRow + 1; + // row height is in twips in BIFF, convert to points + aData.mfHeight = (nHeight & BIFF_ROW_HEIGHTMASK) / 20.0; + // set row properties in the current sheet + setRowData( aData ); +} + +void BiffSheetDataContext::importArray( BiffInputStream& rStrm ) +{ + BinRange aRange; + aRange.read( rStrm, false ); // columns always 8-bit + CellRangeAddress aArrayRange; + Reference< XCellRange > xRange = getCellRange( aRange, &aArrayRange ); + Reference< XArrayFormulaTokens > xTokens( xRange, UNO_QUERY ); + if( xRange.is() && xTokens.is() ) + { + rStrm.skip( mnArrayIgnoreSize ); + ArrayFormulaContext aContext( xTokens, aArrayRange ); + getFormulaParser().importFormula( aContext, rStrm ); + } +} + +void BiffSheetDataContext::importSharedFmla( BiffInputStream& rStrm ) +{ + getSharedFormulas().importSharedFmla( rStrm, maCurrCell.maAddress ); +} + +void BiffSheetDataContext::importDataTable( BiffInputStream& rStrm ) +{ + BinRange aRange; + aRange.read( rStrm, false ); // columns always 8-bit + CellRangeAddress aTableRange; + if( getAddressConverter().convertToCellRange( aTableRange, aRange, getSheetIndex(), true ) ) + { + OoxDataTableData aTableData; + BinAddress aRef1, aRef2; + switch( rStrm.getRecId() ) + { + case BIFF2_ID_DATATABLE: + rStrm.skip( 1 ); + aTableData.mbRowTable = rStrm.readuInt8() != 0; + aTableData.mb2dTable = false; + rStrm >> aRef1; + break; + case BIFF2_ID_DATATABLE2: + rStrm.skip( 2 ); + aTableData.mb2dTable = true; + rStrm >> aRef1 >> aRef2; + break; + case BIFF3_ID_DATATABLE: + { + sal_uInt16 nFlags; + rStrm >> nFlags >> aRef1 >> aRef2; + aTableData.mbRowTable = getFlag( nFlags, BIFF_DATATABLE_ROW ); + aTableData.mb2dTable = getFlag( nFlags, BIFF_DATATABLE_2D ); + aTableData.mbRef1Deleted = getFlag( nFlags, BIFF_DATATABLE_REF1DEL ); + aTableData.mbRef2Deleted = getFlag( nFlags, BIFF_DATATABLE_REF2DEL ); + } + break; + default: + OSL_ENSURE( false, "BiffSheetDataContext::importDataTable - unknown record id" ); + } + aTableData.maRef1 = FormulaProcessorBase::generateAddress2dString( aRef1, false ); + aTableData.maRef2 = FormulaProcessorBase::generateAddress2dString( aRef2, false ); + setTableOperation( aTableRange, aTableData ); + } +} + +// ============================================================================ + +BiffExternalSheetDataContext::BiffExternalSheetDataContext( + const WorkbookHelper& rHelper, WorksheetType eSheetType, sal_Int32 nSheet ) : + WorksheetHelperRoot( rHelper, ISegmentProgressBarRef(), eSheetType, nSheet ) +{ +} + +void BiffExternalSheetDataContext::importCrn( BiffInputStream& rStrm ) +{ + sal_uInt8 nCol2, nCol1; + sal_uInt16 nRow; + rStrm >> nCol2 >> nCol1 >> nRow; + bool bLoop = true; + for( BinAddress aAddr( nCol1, nRow ); bLoop && rStrm.isValid() && (aAddr.mnCol <= nCol2); ++aAddr.mnCol ) + { + Reference< XCell > xCell = getCell( aAddr ); + bLoop = xCell.is(); + if( bLoop ) switch( rStrm.readuInt8() ) + { + case BIFF_DATATYPE_EMPTY: + rStrm.skip( 8 ); + setEmptyStringCell( xCell ); + break; + case BIFF_DATATYPE_DOUBLE: + xCell->setValue( rStrm.readDouble() ); + break; + case BIFF_DATATYPE_STRING: + { + OUString aText = (getBiff() == BIFF8) ? rStrm.readUniString() : rStrm.readByteString( false, getTextEncoding() ); + setStringCell( xCell, aText, true ); + } + break; + case BIFF_DATATYPE_BOOL: + setBooleanCell( xCell, rStrm.readuInt8() != 0 ); + rStrm.skip( 7 ); + break; + case BIFF_DATATYPE_ERROR: + setErrorCell( xCell, rStrm.readuInt8() ); + rStrm.skip( 7 ); + break; + default: + OSL_ENSURE( false, "BiffExternalSheetDataContext::importCrn - unknown data type" ); + bLoop = false; + } + } +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/stylesbuffer.cxx b/oox/source/xls/stylesbuffer.cxx new file mode 100644 index 000000000000..66b1ea9e8035 --- /dev/null +++ b/oox/source/xls/stylesbuffer.cxx @@ -0,0 +1,3214 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: stylesbuffer.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/stylesbuffer.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "oox/helper/attributelist.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/helper/recordinputstream.hxx" +#include "oox/xls/biffinputstream.hxx" +#include "oox/xls/condformatbuffer.hxx" +#include "oox/xls/ooxtokens.hxx" +#include "oox/xls/themebuffer.hxx" +#include "oox/xls/unitconverter.hxx" + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::awt::FontDescriptor; +using ::com::sun::star::awt::XDevice; +using ::com::sun::star::awt::XFont2; +using ::com::sun::star::table::BorderLine; +using ::com::sun::star::text::XText; +using ::com::sun::star::style::XStyle; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +// OOXML constants ------------------------------------------------------------ + +// OOX predefined color indexes (also used in BIFF3-BIFF8) +const sal_Int32 OOX_COLOR_USEROFFSET = 0; /// First user defined color in palette (OOX). +const sal_Int32 BIFF_COLOR_USEROFFSET = 8; /// First user defined color in palette (BIFF). + +// OOX font family (also used in BIFF) +const sal_Int32 OOX_FONTFAMILY_NONE = 0; +const sal_Int32 OOX_FONTFAMILY_ROMAN = 1; +const sal_Int32 OOX_FONTFAMILY_SWISS = 2; +const sal_Int32 OOX_FONTFAMILY_MODERN = 3; +const sal_Int32 OOX_FONTFAMILY_SCRIPT = 4; +const sal_Int32 OOX_FONTFAMILY_DECORATIVE = 5; + +// OOX font charset (also used in BIFF) +const sal_Int32 OOX_FONTCHARSET_UNUSED = -1; +const sal_Int32 OOX_FONTCHARSET_ANSI = 0; + +// OOX cell text direction (also used in BIFF) +const sal_Int32 OOX_XF_TEXTDIR_CONTEXT = 0; +const sal_Int32 OOX_XF_TEXTDIR_LTR = 1; +const sal_Int32 OOX_XF_TEXTDIR_RTL = 2; + +// OOX cell rotation (also used in BIFF) +const sal_Int32 OOX_XF_ROTATION_NONE = 0; +const sal_Int32 OOX_XF_ROTATION_90CCW = 90; +const sal_Int32 OOX_XF_ROTATION_90CW = 180; +const sal_Int32 OOX_XF_ROTATION_STACKED = 255; + +// OOX cell indentation +const sal_Int32 OOX_XF_INDENT_NONE = 0; + +// OOX built-in cell styles (also used in BIFF) +const sal_Int32 OOX_STYLE_NORMAL = 0; /// Default cell style. +const sal_Int32 OOX_STYLE_ROWLEVEL = 1; /// RowLevel_x cell style. +const sal_Int32 OOX_STYLE_COLLEVEL = 2; /// ColLevel_x cell style. + +const sal_Int32 OOX_STYLE_LEVELCOUNT = 7; /// Number of outline level styles. + +// OOBIN constants ------------------------------------------------------------ + +// OOBIN color types +const sal_uInt8 OOBIN_COLOR_AUTO = 1; +const sal_uInt8 OOBIN_COLOR_INDEXED = 3; +const sal_uInt8 OOBIN_COLOR_RGB = 5; +const sal_uInt8 OOBIN_COLOR_THEME = 7; + +// OOBIN diagonal borders +const sal_uInt8 OOBIN_BORDER_DIAG_TLBR = 0x01; /// Top-left to bottom-right. +const sal_uInt8 OOBIN_BORDER_DIAG_BLTR = 0x02; /// Bottom-left to top-right. + +// OOBIN gradient fill +const sal_Int32 OOBIN_FILL_GRADIENT = 40; + +// OOBIN XF flags +const sal_uInt32 OOBIN_XF_WRAPTEXT = 0x00400000; +const sal_uInt32 OOBIN_XF_JUSTLASTLINE = 0x00800000; +const sal_uInt32 OOBIN_XF_SHRINK = 0x01000000; +const sal_uInt32 OOBIN_XF_LOCKED = 0x10000000; +const sal_uInt32 OOBIN_XF_HIDDEN = 0x20000000; + +// OOBIN XF attribute used flags +const sal_uInt16 OOBIN_XF_NUMFMT_USED = 0x0001; +const sal_uInt16 OOBIN_XF_FONT_USED = 0x0002; +const sal_uInt16 OOBIN_XF_ALIGN_USED = 0x0004; +const sal_uInt16 OOBIN_XF_BORDER_USED = 0x0008; +const sal_uInt16 OOBIN_XF_AREA_USED = 0x0010; +const sal_uInt16 OOBIN_XF_PROT_USED = 0x0020; + +// OOBIN DXF constants +const sal_uInt16 OOBIN_DXF_FILL_PATTERN = 0; +const sal_uInt16 OOBIN_DXF_FILL_FGCOLOR = 1; +const sal_uInt16 OOBIN_DXF_FILL_BGCOLOR = 2; +const sal_uInt16 OOBIN_DXF_FILL_GRADIENT = 3; +const sal_uInt16 OOBIN_DXF_FILL_STOP = 4; +const sal_uInt16 OOBIN_DXF_FONT_COLOR = 5; +const sal_uInt16 OOBIN_DXF_BORDER_TOP = 6; +const sal_uInt16 OOBIN_DXF_BORDER_BOTTOM = 7; +const sal_uInt16 OOBIN_DXF_BORDER_LEFT = 8; +const sal_uInt16 OOBIN_DXF_BORDER_RIGHT = 9; +const sal_uInt16 OOBIN_DXF_BORDER_DIAG = 10; +const sal_uInt16 OOBIN_DXF_BORDER_VERT = 11; +const sal_uInt16 OOBIN_DXF_BORDER_HOR = 12; +const sal_uInt16 OOBIN_DXF_BORDER_DIAGUP = 13; +const sal_uInt16 OOBIN_DXF_BORDER_DIAGDOWN = 14; +const sal_uInt16 OOBIN_DXF_FONT_NAME = 24; +const sal_uInt16 OOBIN_DXF_FONT_WEIGHT = 25; +const sal_uInt16 OOBIN_DXF_FONT_UNDERLINE = 26; +const sal_uInt16 OOBIN_DXF_FONT_ESCAPEMENT = 27; +const sal_uInt16 OOBIN_DXF_FONT_ITALIC = 28; +const sal_uInt16 OOBIN_DXF_FONT_STRIKE = 29; +const sal_uInt16 OOBIN_DXF_FONT_OUTLINE = 30; +const sal_uInt16 OOBIN_DXF_FONT_SHADOW = 31; +const sal_uInt16 OOBIN_DXF_FONT_CONDENSE = 32; +const sal_uInt16 OOBIN_DXF_FONT_EXTEND = 33; +const sal_uInt16 OOBIN_DXF_FONT_HEIGHT = 36; +const sal_uInt16 OOBIN_DXF_FONT_SCHEME = 37; +const sal_uInt16 OOBIN_DXF_NUMFMT_CODE = 38; +const sal_uInt16 OOBIN_DXF_NUMFMT_ID = 41; + +// OOBIN CELLSTYLE flags +const sal_uInt16 OOBIN_CELLSTYLE_BUILTIN = 0x0001; +const sal_uInt16 OOBIN_CELLSTYLE_HIDDEN = 0x0002; +const sal_uInt16 OOBIN_CELLSTYLE_CUSTOM = 0x0004; + +// OOBIN and BIFF constants --------------------------------------------------- + +// BIFF predefined color indexes +const sal_uInt16 BIFF2_COLOR_BLACK = 0; /// Black (text) in BIFF2. +const sal_uInt16 BIFF2_COLOR_WHITE = 1; /// White (background) in BIFF2. + +// BIFF font flags, also used in OOBIN +const sal_uInt16 BIFF_FONTFLAG_BOLD = 0x0001; +const sal_uInt16 BIFF_FONTFLAG_ITALIC = 0x0002; +const sal_uInt16 BIFF_FONTFLAG_UNDERLINE = 0x0004; +const sal_uInt16 BIFF_FONTFLAG_STRIKEOUT = 0x0008; +const sal_uInt16 BIFF_FONTFLAG_OUTLINE = 0x0010; +const sal_uInt16 BIFF_FONTFLAG_SHADOW = 0x0020; +const sal_uInt16 BIFF_FONTFLAG_CONDENSE = 0x0040; + +// BIFF font weight +const sal_uInt16 BIFF_FONTWEIGHT_BOLD = 450; + +// BIFF font underline, also used in OOBIN +const sal_uInt8 BIFF_FONTUNDERL_NONE = 0; +const sal_uInt8 BIFF_FONTUNDERL_SINGLE = 1; +const sal_uInt8 BIFF_FONTUNDERL_DOUBLE = 2; +const sal_uInt8 BIFF_FONTUNDERL_SINGLE_ACC = 33; +const sal_uInt8 BIFF_FONTUNDERL_DOUBLE_ACC = 34; + +// BIFF XF flags +const sal_uInt16 BIFF_XF_LOCKED = 0x0001; +const sal_uInt16 BIFF_XF_HIDDEN = 0x0002; +const sal_uInt16 BIFF_XF_STYLE = 0x0004; +const sal_uInt16 BIFF_XF_STYLEPARENT = 0x0FFF; /// Syles don't have a parent. +const sal_uInt16 BIFF_XF_WRAPTEXT = 0x0008; /// Automatic line break. +const sal_uInt16 BIFF_XF_JUSTLASTLINE = 0x0080; +const sal_uInt16 BIFF_XF_SHRINK = 0x0010; /// Shrink to fit into cell. +const sal_uInt16 BIFF_XF_MERGE = 0x0020; + +// BIFF XF attribute used flags +const sal_uInt8 BIFF_XF_NUMFMT_USED = 0x01; +const sal_uInt8 BIFF_XF_FONT_USED = 0x02; +const sal_uInt8 BIFF_XF_ALIGN_USED = 0x04; +const sal_uInt8 BIFF_XF_BORDER_USED = 0x08; +const sal_uInt8 BIFF_XF_AREA_USED = 0x10; +const sal_uInt8 BIFF_XF_PROT_USED = 0x20; + +// BIFF XF text orientation +const sal_uInt8 BIFF_XF_ORIENT_NONE = 0; +const sal_uInt8 BIFF_XF_ORIENT_STACKED = 1; /// Stacked top to bottom. +const sal_uInt8 BIFF_XF_ORIENT_90CCW = 2; /// 90 degr. counterclockwise. +const sal_uInt8 BIFF_XF_ORIENT_90CW = 3; /// 90 degr. clockwise. + +// BIFF XF line styles +const sal_uInt8 BIFF_LINE_NONE = 0; +const sal_uInt8 BIFF_LINE_THIN = 1; + +// BIFF XF patterns +const sal_uInt8 BIFF_PATT_NONE = 0; +const sal_uInt8 BIFF_PATT_125 = 17; + +// BIFF2 XF flags +const sal_uInt8 BIFF2_XF_VALFMT_MASK = 0x3F; +const sal_uInt8 BIFF2_XF_LOCKED = 0x40; +const sal_uInt8 BIFF2_XF_HIDDEN = 0x80; +const sal_uInt8 BIFF2_XF_LEFTLINE = 0x08; +const sal_uInt8 BIFF2_XF_RIGHTLINE = 0x10; +const sal_uInt8 BIFF2_XF_TOPLINE = 0x20; +const sal_uInt8 BIFF2_XF_BOTTOMLINE = 0x40; +const sal_uInt8 BIFF2_XF_BACKGROUND = 0x80; + +// BIFF8 diagonal borders +const sal_uInt32 BIFF_XF_DIAG_TLBR = 0x40000000; /// Top-left to bottom-right. +const sal_uInt32 BIFF_XF_DIAG_BLTR = 0x80000000; /// Bottom-left to top-right. + +// BIFF STYLE flags +const sal_uInt16 BIFF_STYLE_BUILTIN = 0x8000; +const sal_uInt16 BIFF_STYLE_XFMASK = 0x0FFF; + +// BIFF conditional formatting +const sal_uInt32 BIFF_CFRULE_BORDER_LEFT = 0x00000400; +const sal_uInt32 BIFF_CFRULE_BORDER_RIGHT = 0x00000800; +const sal_uInt32 BIFF_CFRULE_BORDER_TOP = 0x00001000; +const sal_uInt32 BIFF_CFRULE_BORDER_BOTTOM = 0x00002000; +const sal_uInt32 BIFF_CFRULE_FILL_PATTERN = 0x00010000; +const sal_uInt32 BIFF_CFRULE_FILL_PATTCOLOR = 0x00020000; +const sal_uInt32 BIFF_CFRULE_FILL_FILLCOLOR = 0x00040000; +const sal_uInt32 BIFF_CFRULE_FONTBLOCK = 0x04000000; +const sal_uInt32 BIFF_CFRULE_ALIGNBLOCK = 0x08000000; +const sal_uInt32 BIFF_CFRULE_BORDERBLOCK = 0x10000000; +const sal_uInt32 BIFF_CFRULE_FILLBLOCK = 0x20000000; +const sal_uInt32 BIFF_CFRULE_PROTBLOCK = 0x40000000; + +const sal_uInt32 BIFF_CFRULE_FONT_STYLE = 0x00000002; /// Font posture or weight modified? +const sal_uInt32 BIFF_CFRULE_FONT_OUTLINE = 0x00000008; /// Font outline modified? +const sal_uInt32 BIFF_CFRULE_FONT_SHADOW = 0x00000010; /// Font shadow modified? +const sal_uInt32 BIFF_CFRULE_FONT_STRIKEOUT = 0x00000080; /// Font cancellation modified? +const sal_uInt32 BIFF_CFRULE_FONT_UNDERL = 0x00000001; /// Font underline type modified? +const sal_uInt32 BIFF_CFRULE_FONT_ESCAPEM = 0x00000001; /// Font escapement type modified? + +// ---------------------------------------------------------------------------- + +sal_Int32 lclGetRgbColor( sal_uInt8 nR, sal_uInt8 nG, sal_uInt8 nB, sal_uInt8 nA ) +{ + sal_Int32 nValue = nA; + nValue <<= 8; + nValue |= nR; + nValue <<= 8; + nValue |= nG; + nValue <<= 8; + nValue |= nB; + return nValue; +} + +} // namespace + +// ---------------------------------------------------------------------------- + +OoxColor::OoxColor() : + mfTint( 0.0 ), + mnType( XML_auto ), + mnValue( 0 ) +{ +} + +OoxColor::OoxColor( sal_Int32 nType, sal_Int32 nValue, double fTint ) : + mfTint( fTint ), + mnType( nType ), + mnValue( nValue ) +{ +} + +bool OoxColor::isAuto() const +{ + return mnType == XML_auto; +} + +void OoxColor::set( sal_Int32 nType, sal_Int32 nValue, double fTint ) +{ + mfTint = fTint; + mnType = nType; + mnValue = nValue; +} + +void OoxColor::importColor( const AttributeList& rAttribs ) +{ + mfTint = rAttribs.getDouble( XML_tint, 0.0 ); + if( rAttribs.getBool( XML_auto, false ) ) + { + mnType = XML_auto; + } + else if( rAttribs.hasAttribute( XML_rgb ) ) + { + mnType = XML_rgb; + mnValue = rAttribs.getHex( XML_rgb, API_RGB_TRANSPARENT ); + } + else if( rAttribs.hasAttribute( XML_theme ) ) + { + mnType = XML_theme; + mnValue = rAttribs.getInteger( XML_theme, -1 ); + } + else if( rAttribs.hasAttribute( XML_indexed ) ) + { + mnType = XML_indexed; + mnValue = rAttribs.getInteger( XML_indexed, -1 ); + } + else + { + mnType = XML_auto; + OSL_ENSURE( false, "OoxColor::importColor - unknown color type" ); + } +} + +void OoxColor::importColor( RecordInputStream& rStrm ) +{ + switch( rStrm.readuInt8() ) + { + case OOBIN_COLOR_AUTO: + mnType = XML_auto; + mfTint = 0.0; + rStrm.skip( 7 ); + break; + case OOBIN_COLOR_INDEXED: + mnType = XML_indexed; + mnValue = rStrm.readuInt8(); + mfTint = 0.0; + rStrm.skip( 6 ); + break; + case OOBIN_COLOR_RGB: + rStrm.skip( 3 ); + importColorRgb( rStrm ); + break; + case OOBIN_COLOR_THEME: + mnType = XML_theme; + mnValue = rStrm.readuInt8(); + // scale tint from signed 16-bit to double range -1.0 ... 1.0 + mfTint = static_cast< double >( rStrm.readInt16() ) / 0x7FFF; + rStrm.skip( 4 ); + break; + default: + OSL_ENSURE( false, "OoxColor::importColor - unknown color type" ); + mnType = XML_auto; + mfTint = 0.0; + rStrm.skip( 7 ); + } +} + +void OoxColor::importColorId( RecordInputStream& rStrm ) +{ + mfTint = 0.0; + mnType = XML_indexed; + rStrm >> mnValue; +} + +void OoxColor::importColorRgb( RecordInputStream& rStrm ) +{ + mfTint = 0.0; + mnType = XML_rgb; + sal_uInt8 nR, nG, nB, nA; + rStrm >> nR >> nG >> nB >> nA; + mnValue = lclGetRgbColor( nR, nG, nB, nA ); +} + +void OoxColor::importColorId( BiffInputStream& rStrm, bool b16Bit ) +{ + mfTint = 0.0; + mnType = XML_indexed; + mnValue = b16Bit ? rStrm.readuInt16() : rStrm.readuInt8(); +} + +void OoxColor::importColorRgb( BiffInputStream& rStrm ) +{ + mfTint = 0.0; + mnType = XML_rgb; + sal_uInt8 nR, nG, nB, nA; + rStrm >> nR >> nG >> nB >> nA; + mnValue = lclGetRgbColor( nR, nG, nB, nA ); +} + +RecordInputStream& operator>>( RecordInputStream& rStrm, OoxColor& orColor ) +{ + orColor.importColor( rStrm ); + return rStrm; +} + +// ============================================================================ + +namespace { + +/** Standard EGA colors, bright. */ +#define PALETTE_EGA_COLORS_LIGHT \ + 0x000000, 0xFFFFFF, 0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF, 0x00FFFF +/** Standard EGA colors, dark. */ +#define PALETTE_EGA_COLORS_DARK \ + 0x800000, 0x008000, 0x000080, 0x808000, 0x800080, 0x008080, 0xC0C0C0, 0x808080 + +/** Default color table for BIFF2. */ +static const sal_Int32 spnDefColors2[] = +{ +/* 0 */ PALETTE_EGA_COLORS_LIGHT +}; + +/** Default color table for BIFF3/BIFF4. */ +static const sal_Int32 spnDefColors3[] = +{ +/* 0 */ PALETTE_EGA_COLORS_LIGHT, +/* 8 */ PALETTE_EGA_COLORS_LIGHT, +/* 16 */ PALETTE_EGA_COLORS_DARK +}; + +/** Default color table for BIFF5. */ +static const sal_Int32 spnDefColors5[] = +{ +/* 0 */ PALETTE_EGA_COLORS_LIGHT, +/* 8 */ PALETTE_EGA_COLORS_LIGHT, +/* 16 */ PALETTE_EGA_COLORS_DARK, +/* 24 */ 0x8080FF, 0x802060, 0xFFFFC0, 0xA0E0E0, 0x600080, 0xFF8080, 0x0080C0, 0xC0C0FF, +/* 32 */ 0x000080, 0xFF00FF, 0xFFFF00, 0x00FFFF, 0x800080, 0x800000, 0x008080, 0x0000FF, +/* 40 */ 0x00CFFF, 0x69FFFF, 0xE0FFE0, 0xFFFF80, 0xA6CAF0, 0xDD9CB3, 0xB38FEE, 0xE3E3E3, +/* 48 */ 0x2A6FF9, 0x3FB8CD, 0x488436, 0x958C41, 0x8E5E42, 0xA0627A, 0x624FAC, 0x969696, +/* 56 */ 0x1D2FBE, 0x286676, 0x004500, 0x453E01, 0x6A2813, 0x85396A, 0x4A3285, 0x424242 +}; + +/** Default color table for BIFF8/OOX. */ +static const sal_Int32 spnDefColors8[] = +{ +/* 0 */ PALETTE_EGA_COLORS_LIGHT, +/* 8 */ PALETTE_EGA_COLORS_LIGHT, +/* 16 */ PALETTE_EGA_COLORS_DARK, +/* 24 */ 0x9999FF, 0x993366, 0xFFFFCC, 0xCCFFFF, 0x660066, 0xFF8080, 0x0066CC, 0xCCCCFF, +/* 32 */ 0x000080, 0xFF00FF, 0xFFFF00, 0x00FFFF, 0x800080, 0x800000, 0x008080, 0x0000FF, +/* 40 */ 0x00CCFF, 0xCCFFFF, 0xCCFFCC, 0xFFFF99, 0x99CCFF, 0xFF99CC, 0xCC99FF, 0xFFCC99, +/* 48 */ 0x3366FF, 0x33CCCC, 0x99CC00, 0xFFCC00, 0xFF9900, 0xFF6600, 0x666699, 0x969696, +/* 56 */ 0x003366, 0x339966, 0x003300, 0x333300, 0x993300, 0x993366, 0x333399, 0x333333 +}; + +#undef PALETTE_EGA_COLORS_LIGHT +#undef PALETTE_EGA_COLORS_DARK + +} // namespace + +// ---------------------------------------------------------------------------- + +ColorPalette::ColorPalette( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + mnWindowColor( ThemeBuffer::getSystemWindowColor() ), + mnWinTextColor( ThemeBuffer::getSystemWindowTextColor() ) +{ + // default colors + switch( getFilterType() ) + { + case FILTER_OOX: + maColors.insert( maColors.begin(), spnDefColors8, STATIC_ARRAY_END( spnDefColors8 ) ); + mnAppendIndex = OOX_COLOR_USEROFFSET; + break; + case FILTER_BIFF: + switch( getBiff() ) + { + case BIFF2: maColors.insert( maColors.begin(), spnDefColors2, STATIC_ARRAY_END( spnDefColors2 ) ); break; + case BIFF3: + case BIFF4: maColors.insert( maColors.begin(), spnDefColors3, STATIC_ARRAY_END( spnDefColors3 ) ); break; + case BIFF5: maColors.insert( maColors.begin(), spnDefColors5, STATIC_ARRAY_END( spnDefColors5 ) ); break; + case BIFF8: maColors.insert( maColors.begin(), spnDefColors8, STATIC_ARRAY_END( spnDefColors8 ) ); break; + case BIFF_UNKNOWN: break; + } + mnAppendIndex = BIFF_COLOR_USEROFFSET; + break; + case FILTER_UNKNOWN: break; + } +} + +void ColorPalette::importPaletteColor( const AttributeList& rAttribs ) +{ + appendColor( rAttribs.getHex( XML_rgb, API_RGB_TRANSPARENT ) ); +} + +void ColorPalette::importPaletteColor( RecordInputStream& rStrm ) +{ + OoxColor aColor; + aColor.importColorRgb( rStrm ); + appendColor( aColor.mnValue ); +} + +void ColorPalette::importPalette( BiffInputStream& rStrm ) +{ + sal_uInt16 nCount; + rStrm >> nCount; + OSL_ENSURE( rStrm.getRecLeft() == static_cast< sal_uInt32 >( 4 * nCount ), + "ColorPalette::importPalette - wrong palette size" ); + + // fill palette from BIFF_COLOR_USEROFFSET + mnAppendIndex = BIFF_COLOR_USEROFFSET; + OoxColor aColor; + for( sal_uInt16 nIndex = 0; rStrm.isValid() && (nIndex < nCount); ++nIndex ) + { + aColor.importColorRgb( rStrm ); + appendColor( aColor.mnValue ); + } +} + +sal_Int32 ColorPalette::getColor( sal_Int32 nIndex ) const +{ + sal_Int32 nColor = API_RGB_TRANSPARENT; + if( (0 <= nIndex) && (static_cast< size_t >( nIndex ) < maColors.size()) ) + { + nColor = maColors[ nIndex ]; + } + else switch( nIndex ) + { + case OOX_COLOR_WINDOWTEXT3: + case OOX_COLOR_WINDOWTEXT: + case OOX_COLOR_CHWINDOWTEXT: nColor = mnWinTextColor; break; + case OOX_COLOR_WINDOWBACK3: + case OOX_COLOR_WINDOWBACK: + case OOX_COLOR_CHWINDOWBACK: nColor = mnWindowColor; break; +// case OOX_COLOR_BUTTONBACK: +// case OOX_COLOR_CHBORDERAUTO: +// case OOX_COLOR_NOTEBACK: +// case OOX_COLOR_NOTETEXT: + case OOX_COLOR_FONTAUTO: nColor = API_RGB_TRANSPARENT; break; + default: + OSL_ENSURE( false, "ColorPalette::getColor - unknown color index" ); + } + return nColor; +} + +void ColorPalette::appendColor( sal_Int32 nRGBValue ) +{ + if( mnAppendIndex < maColors.size() ) + maColors[ mnAppendIndex ] = nRGBValue; + else + maColors.push_back( nRGBValue ); + ++mnAppendIndex; +} + +// ============================================================================ + +OoxFontData::OoxFontData() : + mnScheme( XML_none ), + mnFamily( OOX_FONTFAMILY_NONE ), + mnCharSet( OOX_FONTCHARSET_ANSI ), + mfHeight( 0.0 ), + mnUnderline( XML_none ), + mnEscapement( XML_baseline ), + mbBold( false ), + mbItalic( false ), + mbStrikeout( false ), + mbOutline( false ), + mbShadow( false ) +{ +} + +void OoxFontData::setBinScheme( sal_uInt8 nScheme ) +{ + static const sal_Int32 spnSchemes[] = { XML_none, XML_major, XML_minor }; + mnScheme = STATIC_ARRAY_SELECT( spnSchemes, nScheme, XML_none ); +} + +void OoxFontData::setBiffHeight( sal_uInt16 nHeight ) +{ + mfHeight = nHeight / 20.0; // convert twips to points +} + +void OoxFontData::setBiffWeight( sal_uInt16 nWeight ) +{ + mbBold = nWeight >= BIFF_FONTWEIGHT_BOLD; +} + +void OoxFontData::setBiffUnderline( sal_uInt16 nUnderline ) +{ + switch( nUnderline ) + { + case BIFF_FONTUNDERL_NONE: mnUnderline = XML_none; break; + case BIFF_FONTUNDERL_SINGLE: mnUnderline = XML_single; break; + case BIFF_FONTUNDERL_DOUBLE: mnUnderline = XML_double; break; + case BIFF_FONTUNDERL_SINGLE_ACC: mnUnderline = XML_singleAccounting; break; + case BIFF_FONTUNDERL_DOUBLE_ACC: mnUnderline = XML_doubleAccounting; break; + default: mnUnderline = XML_none; + } +} + +void OoxFontData::setBiffEscapement( sal_uInt16 nEscapement ) +{ + static const sal_Int32 spnEscapes[] = { XML_baseline, XML_superscript, XML_subscript }; + mnEscapement = STATIC_ARRAY_SELECT( spnEscapes, nEscapement, XML_baseline ); +} + +// ============================================================================ + +Font::Font( const WorkbookHelper& rHelper, bool bDxf ) : + WorkbookHelper( rHelper ), + maOoxData( rHelper.getTheme().getDefaultFontData() ), + maUsedFlags( !bDxf ), + mbDxf( bDxf ) +{ +} + +Font::Font( const WorkbookHelper& rHelper, const OoxFontData& rFontData ) : + WorkbookHelper( rHelper ), + maOoxData( rFontData ), + maUsedFlags( true ), + mbDxf( false ) +{ +} + +bool Font::isSupportedContext( sal_Int32 nElement, sal_Int32 nParentContext ) +{ + switch( nParentContext ) + { + case XLS_TOKEN( font ): + return (nElement == XLS_TOKEN( name )) || + (nElement == XLS_TOKEN( scheme )) || + (nElement == XLS_TOKEN( charset )) || + (nElement == XLS_TOKEN( family )) || + (nElement == XLS_TOKEN( sz )) || + (nElement == XLS_TOKEN( color )) || + (nElement == XLS_TOKEN( u )) || + (nElement == XLS_TOKEN( vertAlign )) || + (nElement == XLS_TOKEN( b )) || + (nElement == XLS_TOKEN( i )) || + (nElement == XLS_TOKEN( outline )) || + (nElement == XLS_TOKEN( shadow )) || + (nElement == XLS_TOKEN( strike )); + + case XLS_TOKEN( rPr ): + return (nElement == XLS_TOKEN( rFont )) || + (nElement == XLS_TOKEN( scheme )) || + (nElement == XLS_TOKEN( charset )) || + (nElement == XLS_TOKEN( family )) || + (nElement == XLS_TOKEN( sz )) || + (nElement == XLS_TOKEN( color )) || + (nElement == XLS_TOKEN( u )) || + (nElement == XLS_TOKEN( vertAlign )) || + (nElement == XLS_TOKEN( b )) || + (nElement == XLS_TOKEN( i )) || + (nElement == XLS_TOKEN( outline )) || + (nElement == XLS_TOKEN( shadow )) || + (nElement == XLS_TOKEN( strike )) || + (nElement == XLS_TOKEN( vertAlign )); + } + return false; +} + +void Font::importAttribs( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + const OoxFontData& rDefFontData = getTheme().getDefaultFontData(); + switch( nElement ) + { + case XLS_TOKEN( name ): + case XLS_TOKEN( rFont ): + if( rAttribs.hasAttribute( XML_val ) ) + { + maOoxData.maName = rAttribs.getString( XML_val ); + maUsedFlags.mbNameUsed = true; + } + break; + case XLS_TOKEN( scheme ): + maOoxData.mnScheme = rAttribs.getToken( XML_val, rDefFontData.mnScheme ); + break; + case XLS_TOKEN( family ): + maOoxData.mnFamily = rAttribs.getInteger( XML_val, rDefFontData.mnFamily ); + break; + case XLS_TOKEN( charset ): + maOoxData.mnCharSet = rAttribs.getInteger( XML_val, rDefFontData.mnCharSet ); + break; + case XLS_TOKEN( sz ): + maOoxData.mfHeight = rAttribs.getDouble( XML_val, rDefFontData.mfHeight ); + maUsedFlags.mbHeightUsed = true; + break; + case XLS_TOKEN( color ): + maOoxData.maColor.importColor( rAttribs ); + maUsedFlags.mbColorUsed = true; + break; + case XLS_TOKEN( u ): + maOoxData.mnUnderline = rAttribs.getToken( XML_val, XML_single ); + maUsedFlags.mbUnderlineUsed = true; + break; + case XLS_TOKEN( vertAlign ): + maOoxData.mnEscapement = rAttribs.getToken( XML_val, XML_baseline ); + maUsedFlags.mbEscapementUsed = true; + break; + case XLS_TOKEN( b ): + maOoxData.mbBold = rAttribs.getBool( XML_val, true ); + maUsedFlags.mbWeightUsed = true; + break; + case XLS_TOKEN( i ): + maOoxData.mbItalic = rAttribs.getBool( XML_val, true ); + maUsedFlags.mbPostureUsed = true; + break; + case XLS_TOKEN( strike ): + maOoxData.mbStrikeout = rAttribs.getBool( XML_val, true ); + maUsedFlags.mbStrikeoutUsed = true; + break; + case XLS_TOKEN( outline ): + maOoxData.mbOutline = rAttribs.getBool( XML_val, true ); + maUsedFlags.mbOutlineUsed = true; + break; + case XLS_TOKEN( shadow ): + maOoxData.mbShadow = rAttribs.getBool( XML_val, true ); + maUsedFlags.mbShadowUsed = true; + break; + } +} + +void Font::importFont( RecordInputStream& rStrm ) +{ + OSL_ENSURE( !mbDxf, "Font::importFont - unexpected conditional formatting flag" ); + + sal_uInt16 nHeight, nFlags, nWeight, nEscapement; + sal_uInt8 nUnderline, nFamily, nCharSet, nScheme; + rStrm >> nHeight >> nFlags >> nWeight >> nEscapement >> nUnderline >> nFamily >> nCharSet; + rStrm.skip( 1 ); + rStrm >> maOoxData.maColor >> nScheme >> maOoxData.maName; + + // equal constants in BIFF and OOBIN for weight, underline, and escapement + maOoxData.setBinScheme( nScheme ); + maOoxData.setBiffHeight( nHeight ); + maOoxData.setBiffWeight( nWeight ); + maOoxData.setBiffUnderline( nUnderline ); + maOoxData.setBiffEscapement( nEscapement ); + maOoxData.mnFamily = nFamily; + maOoxData.mnCharSet = nCharSet; + // equal flags in BIFF and OOBIN + maOoxData.mbItalic = getFlag( nFlags, BIFF_FONTFLAG_ITALIC ); + maOoxData.mbStrikeout = getFlag( nFlags, BIFF_FONTFLAG_STRIKEOUT ); + maOoxData.mbOutline = getFlag( nFlags, BIFF_FONTFLAG_OUTLINE ); + maOoxData.mbShadow = getFlag( nFlags, BIFF_FONTFLAG_SHADOW ); +} + +void Font::importDxfName( RecordInputStream& rStrm ) +{ + OSL_ENSURE( mbDxf, "Font::importDxfName - missing conditional formatting flag" ); + maOoxData.maName = rStrm.readString( false ); + maUsedFlags.mbColorUsed = true; +} + +void Font::importDxfColor( RecordInputStream& rStrm ) +{ + OSL_ENSURE( mbDxf, "Font::importDxfColor - missing conditional formatting flag" ); + rStrm >> maOoxData.maColor; + maUsedFlags.mbColorUsed = true; +} + +void Font::importDxfScheme( RecordInputStream& rStrm ) +{ + OSL_ENSURE( mbDxf, "Font::importDxfScheme - missing conditional formatting flag" ); + maOoxData.setBinScheme( rStrm.readuInt8() ); + maUsedFlags.mbSchemeUsed = true; +} + +void Font::importDxfHeight( RecordInputStream& rStrm ) +{ + OSL_ENSURE( mbDxf, "Font::importDxfHeight - missing conditional formatting flag" ); + maOoxData.setBiffHeight( rStrm.readuInt16() ); + maUsedFlags.mbHeightUsed = true; +} + +void Font::importDxfWeight( RecordInputStream& rStrm ) +{ + OSL_ENSURE( mbDxf, "Font::importDxfWeight - missing conditional formatting flag" ); + maOoxData.setBiffWeight( rStrm.readuInt16() ); + maUsedFlags.mbWeightUsed = true; +} + +void Font::importDxfUnderline( RecordInputStream& rStrm ) +{ + OSL_ENSURE( mbDxf, "Font::importDxfUnderline - missing conditional formatting flag" ); + maOoxData.setBiffUnderline( rStrm.readuInt16() ); + maUsedFlags.mbUnderlineUsed = true; +} + +void Font::importDxfEscapement( RecordInputStream& rStrm ) +{ + OSL_ENSURE( mbDxf, "Font::importDxfEscapement - missing conditional formatting flag" ); + maOoxData.setBiffEscapement( rStrm.readuInt16() ); + maUsedFlags.mbEscapementUsed = true; +} + +void Font::importDxfFlag( sal_Int32 nElement, RecordInputStream& rStrm ) +{ + OSL_ENSURE( mbDxf, "Font::importDxfFlag - missing conditional formatting flag" ); + bool bFlag = rStrm.readuInt8() != 0; + switch( nElement ) + { + case XML_i: + maOoxData.mbItalic = bFlag; + maUsedFlags.mbPostureUsed = true; + break; + case XML_strike: + maOoxData.mbStrikeout = bFlag; + maUsedFlags.mbStrikeoutUsed = true; + break; + case XML_outline: + maOoxData.mbOutline = bFlag; + maUsedFlags.mbOutlineUsed = true; + break; + case XML_shadow: + maOoxData.mbShadow = bFlag; + maUsedFlags.mbShadowUsed = true; + break; + default: + OSL_ENSURE( false, "Font::importDxfFlag - unexpected element identifier" ); + } +} + +void Font::importFont( BiffInputStream& rStrm ) +{ + OSL_ENSURE( !mbDxf, "Font::importFont - unexpected conditional formatting flag" ); + switch( getBiff() ) + { + case BIFF2: + importFontData2( rStrm ); + importFontName2( rStrm ); + break; + case BIFF3: + case BIFF4: + importFontData2( rStrm ); + importFontColor( rStrm ); + importFontName2( rStrm ); + break; + case BIFF5: + importFontData2( rStrm ); + importFontColor( rStrm ); + importFontData5( rStrm ); + importFontName2( rStrm ); + break; + case BIFF8: + importFontData2( rStrm ); + importFontColor( rStrm ); + importFontData5( rStrm ); + importFontName8( rStrm ); + break; + case BIFF_UNKNOWN: break; + } +} + +void Font::importFontColor( BiffInputStream& rStrm ) +{ + OSL_ENSURE( !mbDxf, "Font::importFontColor - unexpected conditional formatting flag" ); + maOoxData.maColor.importColorId( rStrm ); +} + +void Font::importCfRule( BiffInputStream& rStrm ) +{ + OSL_ENSURE( mbDxf, "Font::importCfRule - missing conditional formatting flag" ); + + sal_Int32 nHeight, nColor; + sal_uInt32 nStyle, nFontFlags1, nFontFlags2, nFontFlags3; + sal_uInt16 nWeight, nEscapement; + sal_uInt8 nUnderline; + + OSL_ENSURE( rStrm.getRecLeft() >= 118, "Font::importCfRule - missing record data" ); + sal_uInt32 nRecPos = rStrm.getRecPos(); + maOoxData.maName = rStrm.readUniString( rStrm.readuInt8() ); + maUsedFlags.mbNameUsed = maOoxData.maName.getLength() > 0; + OSL_ENSURE( rStrm.isValid() && (rStrm.getRecPos() <= nRecPos + 64), "Font::importCfRule - font name too long" ); + rStrm.seek( nRecPos + 64 ); + rStrm >> nHeight >> nStyle >> nWeight >> nEscapement >> nUnderline; + rStrm.skip( 3 ); + rStrm >> nColor; + rStrm.skip( 4 ); + rStrm >> nFontFlags1 >> nFontFlags2 >> nFontFlags3; + rStrm.skip( 18 ); + + if( (maUsedFlags.mbColorUsed = (0 <= nColor) && (nColor <= 0x7FFF)) == true ) + maOoxData.maColor.set( XML_indexed, nColor ); + if( (maUsedFlags.mbHeightUsed = (0 < nHeight) && (nHeight <= 0x7FFF)) == true ) + maOoxData.setBiffHeight( static_cast< sal_uInt16 >( nHeight ) ); + if( (maUsedFlags.mbUnderlineUsed = !getFlag( nFontFlags3, BIFF_CFRULE_FONT_UNDERL )) == true ) + maOoxData.setBiffUnderline( nUnderline ); + if( (maUsedFlags.mbEscapementUsed = !getFlag( nFontFlags2, BIFF_CFRULE_FONT_ESCAPEM )) == true ) + maOoxData.setBiffEscapement( nEscapement ); + if( (maUsedFlags.mbWeightUsed = maUsedFlags.mbPostureUsed = !getFlag( nFontFlags1, BIFF_CFRULE_FONT_STYLE )) == true ) + { + maOoxData.setBiffWeight( nWeight ); + maOoxData.mbItalic = getFlag( nStyle, BIFF_CFRULE_FONT_STYLE ); + } + if( (maUsedFlags.mbStrikeoutUsed = !getFlag( nFontFlags1, BIFF_CFRULE_FONT_STRIKEOUT )) == true ) + maOoxData.mbStrikeout = getFlag( nStyle, BIFF_CFRULE_FONT_STRIKEOUT ); + if( (maUsedFlags.mbOutlineUsed = !getFlag( nFontFlags1, BIFF_CFRULE_FONT_OUTLINE )) == true ) + maOoxData.mbOutline = getFlag( nStyle, BIFF_CFRULE_FONT_OUTLINE ); + if( (maUsedFlags.mbShadowUsed = !getFlag( nFontFlags1, BIFF_CFRULE_FONT_SHADOW )) == true ) + maOoxData.mbShadow = getFlag( nStyle, BIFF_CFRULE_FONT_SHADOW ); +} + +rtl_TextEncoding Font::getFontEncoding() const +{ + // #i63105# cells use text encoding from FONT record character set + // #i67768# BIFF2-BIFF4 FONT records do not contain character set + // #i71033# do not use maApiData, this function is used before finalizeImport() + rtl_TextEncoding eFontEnc = RTL_TEXTENCODING_DONTKNOW; + if( (0 <= maOoxData.mnCharSet) && (maOoxData.mnCharSet <= SAL_MAX_UINT8) ) + eFontEnc = rtl_getTextEncodingFromWindowsCharset( static_cast< sal_uInt8 >( maOoxData.mnCharSet ) ); + return (eFontEnc == RTL_TEXTENCODING_DONTKNOW) ? getTextEncoding() : eFontEnc; +} + +void Font::finalizeImport() +{ + namespace cssawt = ::com::sun::star::awt; + + // font name + maApiData.maDesc.Name = maOoxData.maName; + + // font family + switch( maOoxData.mnFamily ) + { + case OOX_FONTFAMILY_NONE: maApiData.maDesc.Family = cssawt::FontFamily::DONTKNOW; break; + case OOX_FONTFAMILY_ROMAN: maApiData.maDesc.Family = cssawt::FontFamily::ROMAN; break; + case OOX_FONTFAMILY_SWISS: maApiData.maDesc.Family = cssawt::FontFamily::SWISS; break; + case OOX_FONTFAMILY_MODERN: maApiData.maDesc.Family = cssawt::FontFamily::MODERN; break; + case OOX_FONTFAMILY_SCRIPT: maApiData.maDesc.Family = cssawt::FontFamily::SCRIPT; break; + case OOX_FONTFAMILY_DECORATIVE: maApiData.maDesc.Family = cssawt::FontFamily::DECORATIVE; break; + } + + // character set + if( (0 <= maOoxData.mnCharSet) && (maOoxData.mnCharSet <= 255) ) + maApiData.maDesc.CharSet = static_cast< sal_Int16 >( + rtl_getTextEncodingFromWindowsCharset( static_cast< sal_uInt8 >( maOoxData.mnCharSet ) ) ); + + // color, height, weight, slant, strikeout, outline, shadow + maApiData.mnColor = getStyles().getColor( maOoxData.maColor, API_RGB_TRANSPARENT ); + maApiData.maDesc.Height = static_cast< sal_Int16 >( maOoxData.mfHeight * 20.0 ); + maApiData.maDesc.Weight = maOoxData.mbBold ? cssawt::FontWeight::BOLD : cssawt::FontWeight::NORMAL; + maApiData.maDesc.Slant = maOoxData.mbItalic ? cssawt::FontSlant_ITALIC : cssawt::FontSlant_NONE; + maApiData.maDesc.Strikeout = maOoxData.mbStrikeout ? cssawt::FontStrikeout::SINGLE : cssawt::FontStrikeout::NONE; + maApiData.mbOutline = maOoxData.mbOutline; + maApiData.mbShadow = maOoxData.mbShadow; + + // underline + switch( maOoxData.mnUnderline ) + { + case XML_double: maApiData.maDesc.Underline = cssawt::FontUnderline::DOUBLE; break; + case XML_doubleAccounting: maApiData.maDesc.Underline = cssawt::FontUnderline::DOUBLE; break; + case XML_none: maApiData.maDesc.Underline = cssawt::FontUnderline::NONE; break; + case XML_single: maApiData.maDesc.Underline = cssawt::FontUnderline::SINGLE; break; + case XML_singleAccounting: maApiData.maDesc.Underline = cssawt::FontUnderline::SINGLE; break; + } + + // escapement + switch( maOoxData.mnEscapement ) + { + case XML_baseline: + maApiData.mnEscapement = API_ESCAPE_NONE; + maApiData.mnEscapeHeight = API_ESCAPEHEIGHT_NONE; + break; + case XML_superscript: + maApiData.mnEscapement = API_ESCAPE_SUPERSCRIPT; + maApiData.mnEscapeHeight = API_ESCAPEHEIGHT_DEFAULT; + break; + case XML_subscript: + maApiData.mnEscapement = API_ESCAPE_SUBSCRIPT; + maApiData.mnEscapeHeight = API_ESCAPEHEIGHT_DEFAULT; + break; + } + + // supported script types + if( maUsedFlags.mbNameUsed ) + { + Reference< XDevice > xDevice = getReferenceDevice(); + if( xDevice.is() ) + { + Reference< XFont2 > xFont( xDevice->getFont( maApiData.maDesc ), UNO_QUERY ); + if( xFont.is() ) + { + // #91658# CJK fonts + maApiData.mbHasAsian = + xFont->hasGlyphs( OUString( sal_Unicode( 0x3041 ) ) ) || // 3040-309F: Hiragana + xFont->hasGlyphs( OUString( sal_Unicode( 0x30A1 ) ) ) || // 30A0-30FF: Katakana + xFont->hasGlyphs( OUString( sal_Unicode( 0x3111 ) ) ) || // 3100-312F: Bopomofo + xFont->hasGlyphs( OUString( sal_Unicode( 0x3131 ) ) ) || // 3130-318F: Hangul Compatibility Jamo + xFont->hasGlyphs( OUString( sal_Unicode( 0x3301 ) ) ) || // 3300-33FF: CJK Compatibility + xFont->hasGlyphs( OUString( sal_Unicode( 0x3401 ) ) ) || // 3400-4DBF: CJK Unified Ideographs Extension A + xFont->hasGlyphs( OUString( sal_Unicode( 0x4E01 ) ) ) || // 4E00-9FAF: CJK Unified Ideographs + xFont->hasGlyphs( OUString( sal_Unicode( 0x7E01 ) ) ) || // 4E00-9FAF: CJK unified ideographs + xFont->hasGlyphs( OUString( sal_Unicode( 0xA001 ) ) ) || // A001-A48F: Yi Syllables + xFont->hasGlyphs( OUString( sal_Unicode( 0xAC01 ) ) ) || // AC00-D7AF: Hangul Syllables + xFont->hasGlyphs( OUString( sal_Unicode( 0xCC01 ) ) ) || // AC00-D7AF: Hangul Syllables + xFont->hasGlyphs( OUString( sal_Unicode( 0xF901 ) ) ) || // F900-FAFF: CJK Compatibility Ideographs + xFont->hasGlyphs( OUString( sal_Unicode( 0xFF71 ) ) ); // FF00-FFEF: Halfwidth/Fullwidth Forms + // #113783# CTL fonts + maApiData.mbHasCmplx = + xFont->hasGlyphs( OUString( sal_Unicode( 0x05D1 ) ) ) || // 0590-05FF: Hebrew + xFont->hasGlyphs( OUString( sal_Unicode( 0x0631 ) ) ) || // 0600-06FF: Arabic + xFont->hasGlyphs( OUString( sal_Unicode( 0x0721 ) ) ) || // 0700-074F: Syriac + xFont->hasGlyphs( OUString( sal_Unicode( 0x0911 ) ) ) || // 0900-0DFF: Indic scripts + xFont->hasGlyphs( OUString( sal_Unicode( 0x0E01 ) ) ) || // 0E00-0E7F: Thai + xFont->hasGlyphs( OUString( sal_Unicode( 0xFB21 ) ) ) || // FB1D-FB4F: Hebrew Presentation Forms + xFont->hasGlyphs( OUString( sal_Unicode( 0xFB51 ) ) ) || // FB50-FDFF: Arabic Presentation Forms-A + xFont->hasGlyphs( OUString( sal_Unicode( 0xFE71 ) ) ); // FE70-FEFF: Arabic Presentation Forms-B + // Western fonts + maApiData.mbHasWstrn = + (!maApiData.mbHasAsian && !maApiData.mbHasCmplx) || + xFont->hasGlyphs( OUString( sal_Unicode( 'A' ) ) ); + } + } + } +} + +const FontDescriptor& Font::getFontDescriptor() const +{ + return maApiData.maDesc; +} + +bool Font::needsRichTextFormat() const +{ + return maApiData.mnEscapement != API_ESCAPE_NONE; +} + +void Font::writeToPropertySet( PropertySet& rPropSet, FontPropertyType ePropType ) const +{ + getStylesPropertyHelper().writeFontProperties( rPropSet, maApiData, maUsedFlags, ePropType ); +} + +void Font::importFontData2( BiffInputStream& rStrm ) +{ + sal_uInt16 nHeight, nFlags; + rStrm >> nHeight >> nFlags; + + maOoxData.setBiffHeight( nHeight ); + maOoxData.mnFamily = OOX_FONTFAMILY_NONE; + maOoxData.mnCharSet = OOX_FONTCHARSET_UNUSED; // ensure to not use font charset in byte string import + maOoxData.mnUnderline = getFlagValue( nFlags, BIFF_FONTFLAG_UNDERLINE, XML_single, XML_none ); + maOoxData.mnEscapement = XML_none; + maOoxData.mbBold = getFlag( nFlags, BIFF_FONTFLAG_BOLD ); + maOoxData.mbItalic = getFlag( nFlags, BIFF_FONTFLAG_ITALIC ); + maOoxData.mbStrikeout = getFlag( nFlags, BIFF_FONTFLAG_STRIKEOUT ); + maOoxData.mbOutline = getFlag( nFlags, BIFF_FONTFLAG_OUTLINE ); + maOoxData.mbShadow = getFlag( nFlags, BIFF_FONTFLAG_SHADOW ); +} + +void Font::importFontData5( BiffInputStream& rStrm ) +{ + sal_uInt16 nWeight, nEscapement; + sal_uInt8 nUnderline, nFamily, nCharSet; + rStrm >> nWeight >> nEscapement >> nUnderline >> nFamily >> nCharSet; + rStrm.skip( 1 ); + + maOoxData.setBiffWeight( nWeight ); + maOoxData.setBiffUnderline( nUnderline ); + maOoxData.setBiffEscapement( nEscapement ); + // equal constants in XML and BIFF for family and charset + maOoxData.mnFamily = nFamily; + maOoxData.mnCharSet = nCharSet; +} + +void Font::importFontName2( BiffInputStream& rStrm ) +{ + maOoxData.maName = rStrm.readByteString( false, getTextEncoding() ); +} + +void Font::importFontName8( BiffInputStream& rStrm ) +{ + maOoxData.maName = rStrm.readUniString( rStrm.readuInt8() ); +} + +// ============================================================================ + +OoxAlignmentData::OoxAlignmentData() : + mnHorAlign( XML_general ), + mnVerAlign( XML_bottom ), + mnTextDir( OOX_XF_TEXTDIR_CONTEXT ), + mnRotation( OOX_XF_ROTATION_NONE ), + mnIndent( OOX_XF_INDENT_NONE ), + mbWrapText( false ), + mbShrink( false ), + mbJustLastLine( false ) +{ +} + +void OoxAlignmentData::setBinHorAlign( sal_uInt8 nHorAlign ) +{ + static const sal_Int32 spnHorAligns[] = { + XML_general, XML_left, XML_center, XML_right, + XML_fill, XML_justify, XML_centerContinuous, XML_distributed }; + mnHorAlign = STATIC_ARRAY_SELECT( spnHorAligns, nHorAlign, XML_general ); +} + +void OoxAlignmentData::setBinVerAlign( sal_uInt8 nVerAlign ) +{ + static const sal_Int32 spnVerAligns[] = { + XML_top, XML_center, XML_bottom, XML_justify, XML_distributed }; + mnVerAlign = STATIC_ARRAY_SELECT( spnVerAligns, nVerAlign, XML_bottom ); +} + +void OoxAlignmentData::setBinTextOrient( sal_uInt8 nTextOrient ) +{ + static const sal_Int32 spnRotations[] = { + OOX_XF_ROTATION_NONE, OOX_XF_ROTATION_STACKED, + OOX_XF_ROTATION_90CCW, OOX_XF_ROTATION_90CW }; + mnRotation = STATIC_ARRAY_SELECT( spnRotations, nTextOrient, OOX_XF_ROTATION_NONE ); +} + +// ============================================================================ + +Alignment::Alignment( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ) +{ +} + +void Alignment::importAlignment( const AttributeList& rAttribs ) +{ + maOoxData.mnHorAlign = rAttribs.getToken( XML_horizontal, XML_general ); + maOoxData.mnVerAlign = rAttribs.getToken( XML_vertical, XML_bottom ); + maOoxData.mnTextDir = rAttribs.getInteger( XML_readingOrder, OOX_XF_TEXTDIR_CONTEXT ); + maOoxData.mnRotation = rAttribs.getInteger( XML_textRotation, OOX_XF_ROTATION_NONE ); + maOoxData.mnIndent = rAttribs.getInteger( XML_indent, OOX_XF_INDENT_NONE ); + maOoxData.mbWrapText = rAttribs.getBool( XML_wrapText, false ); + maOoxData.mbShrink = rAttribs.getBool( XML_shrinkToFit, false ); + maOoxData.mbJustLastLine = rAttribs.getBool( XML_justifyLastLine, false ); +} + +void Alignment::setBinData( sal_uInt32 nFlags ) +{ + maOoxData.setBinHorAlign( extractValue< sal_uInt8 >( nFlags, 16, 3 ) ); + maOoxData.setBinVerAlign( extractValue< sal_uInt8 >( nFlags, 19, 3 ) ); + maOoxData.mnTextDir = extractValue< sal_Int32 >( nFlags, 26, 2 ); + maOoxData.mnRotation = extractValue< sal_Int32 >( nFlags, 0, 8 ); + maOoxData.mnIndent = extractValue< sal_uInt8 >( nFlags, 8, 8 ); + maOoxData.mbWrapText = getFlag( nFlags, OOBIN_XF_WRAPTEXT ); + maOoxData.mbShrink = getFlag( nFlags, OOBIN_XF_SHRINK ); + maOoxData.mbJustLastLine = getFlag( nFlags, OOBIN_XF_JUSTLASTLINE ); +} + +void Alignment::setBiff2Data( sal_uInt8 nFlags ) +{ + maOoxData.setBinHorAlign( extractValue< sal_uInt8 >( nFlags, 0, 3 ) ); +} + +void Alignment::setBiff3Data( sal_uInt16 nAlign ) +{ + maOoxData.setBinHorAlign( extractValue< sal_uInt8 >( nAlign, 0, 3 ) ); + maOoxData.mbWrapText = getFlag( nAlign, BIFF_XF_WRAPTEXT ); // new in BIFF3 +} + +void Alignment::setBiff4Data( sal_uInt16 nAlign ) +{ + maOoxData.setBinHorAlign( extractValue< sal_uInt8 >( nAlign, 0, 3 ) ); + maOoxData.setBinVerAlign( extractValue< sal_uInt8 >( nAlign, 4, 2 ) ); // new in BIFF4 + maOoxData.setBinTextOrient( extractValue< sal_uInt8 >( nAlign, 6, 2 ) ); // new in BIFF4 + maOoxData.mbWrapText = getFlag( nAlign, BIFF_XF_WRAPTEXT ); +} + +void Alignment::setBiff5Data( sal_uInt16 nAlign ) +{ + maOoxData.setBinHorAlign( extractValue< sal_uInt8 >( nAlign, 0, 3 ) ); + maOoxData.setBinVerAlign( extractValue< sal_uInt8 >( nAlign, 4, 3 ) ); + maOoxData.setBinTextOrient( extractValue< sal_uInt8 >( nAlign, 8, 2 ) ); + maOoxData.mbWrapText = getFlag( nAlign, BIFF_XF_WRAPTEXT ); +} + +void Alignment::setBiff8Data( sal_uInt16 nAlign, sal_uInt16 nMiscAttrib ) +{ + maOoxData.setBinHorAlign( extractValue< sal_uInt8 >( nAlign, 0, 3 ) ); + maOoxData.setBinVerAlign( extractValue< sal_uInt8 >( nAlign, 4, 3 ) ); + maOoxData.mnTextDir = extractValue< sal_Int32 >( nMiscAttrib, 6, 2 ); // new in BIFF8 + maOoxData.mnRotation = extractValue< sal_Int32 >( nAlign, 8, 8 ); // new in BIFF8 + maOoxData.mnIndent = extractValue< sal_uInt8 >( nMiscAttrib, 0, 4 ); // new in BIFF8 + maOoxData.mbWrapText = getFlag( nAlign, BIFF_XF_WRAPTEXT ); + maOoxData.mbShrink = getFlag( nMiscAttrib, BIFF_XF_SHRINK ); // new in BIFF8 + maOoxData.mbJustLastLine = getFlag( nAlign, BIFF_XF_JUSTLASTLINE ); // new in BIFF8(?) +} + +void Alignment::finalizeImport() +{ + namespace csstab = ::com::sun::star::table; + namespace csstxt = ::com::sun::star::text; + + // horizontal alignment + switch( maOoxData.mnHorAlign ) + { + case XML_center: maApiData.meHorJustify = csstab::CellHoriJustify_CENTER; break; + case XML_centerContinuous: maApiData.meHorJustify = csstab::CellHoriJustify_CENTER; break; + case XML_distributed: maApiData.meHorJustify = csstab::CellHoriJustify_BLOCK; break; + case XML_fill: maApiData.meHorJustify = csstab::CellHoriJustify_REPEAT; break; + case XML_general: maApiData.meHorJustify = csstab::CellHoriJustify_STANDARD; break; + case XML_justify: maApiData.meHorJustify = csstab::CellHoriJustify_BLOCK; break; + case XML_left: maApiData.meHorJustify = csstab::CellHoriJustify_LEFT; break; + case XML_right: maApiData.meHorJustify = csstab::CellHoriJustify_RIGHT; break; + } + + // vertical alignment + switch( maOoxData.mnVerAlign ) + { + case XML_bottom: maApiData.meVerJustify = csstab::CellVertJustify_BOTTOM; break; + case XML_center: maApiData.meVerJustify = csstab::CellVertJustify_CENTER; break; + case XML_distributed: maApiData.meVerJustify = csstab::CellVertJustify_TOP; break; + case XML_justify: maApiData.meVerJustify = csstab::CellVertJustify_TOP; break; + case XML_top: maApiData.meVerJustify = csstab::CellVertJustify_TOP; break; + } + + /* indentation: expressed as number of blocks of 3 space characters in + OOX, and as multiple of 10 points in BIFF. */ + sal_Int32 nIndent = 0; + switch( getFilterType() ) + { + case FILTER_OOX: nIndent = getUnitConverter().calcMm100FromSpaces( 3.0 * maOoxData.mnIndent ); break; + case FILTER_BIFF: nIndent = getUnitConverter().calcMm100FromPoints( 10.0 * maOoxData.mnIndent ); break; + case FILTER_UNKNOWN: break; + } + if( (0 <= nIndent) && (nIndent <= SAL_MAX_INT16) ) + maApiData.mnIndent = static_cast< sal_Int16 >( nIndent ); + + // complex text direction + switch( maOoxData.mnTextDir ) + { + case OOX_XF_TEXTDIR_CONTEXT: maApiData.mnWritingMode = csstxt::WritingMode2::PAGE; break; + case OOX_XF_TEXTDIR_LTR: maApiData.mnWritingMode = csstxt::WritingMode2::LR_TB; break; + case OOX_XF_TEXTDIR_RTL: maApiData.mnWritingMode = csstxt::WritingMode2::RL_TB; break; + } + + // rotation: 0-90 means 0 to 90 degrees ccw, 91-180 means 1 to 90 degrees cw, 255 means stacked + sal_Int32 nOoxRot = maOoxData.mnRotation; + maApiData.mnRotation = ((0 <= nOoxRot) && (nOoxRot <= 90)) ? + (100 * nOoxRot) : + (((91 <= nOoxRot) && (nOoxRot <= 180)) ? (100 * (450 - nOoxRot)) : 0); + + // "Orientation" property used for character stacking + maApiData.meOrientation = (nOoxRot == OOX_XF_ROTATION_STACKED) ? + csstab::CellOrientation_STACKED : csstab::CellOrientation_STANDARD; + + // alignment flags + maApiData.mbWrapText = maOoxData.mbWrapText; + maApiData.mbShrink = maOoxData.mbShrink; + +} + +void Alignment::writeToPropertySet( PropertySet& rPropSet ) const +{ + getStylesPropertyHelper().writeAlignmentProperties( rPropSet, maApiData ); +} + +// ============================================================================ + +OoxProtectionData::OoxProtectionData() : + mbLocked( true ), // default in Excel and Calc + mbHidden( false ) +{ +} + +// ============================================================================ + +Protection::Protection( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ) +{ +} + +void Protection::importProtection( const AttributeList& rAttribs ) +{ + maOoxData.mbLocked = rAttribs.getBool( XML_locked, true ); + maOoxData.mbHidden = rAttribs.getBool( XML_hidden, false ); +} + +void Protection::setBinData( sal_uInt32 nFlags ) +{ + maOoxData.mbLocked = getFlag( nFlags, OOBIN_XF_LOCKED ); + maOoxData.mbHidden = getFlag( nFlags, OOBIN_XF_HIDDEN ); +} + +void Protection::setBiff2Data( sal_uInt8 nNumFmt ) +{ + maOoxData.mbLocked = getFlag( nNumFmt, BIFF2_XF_LOCKED ); + maOoxData.mbHidden = getFlag( nNumFmt, BIFF2_XF_HIDDEN ); +} + +void Protection::setBiff3Data( sal_uInt16 nProt ) +{ + maOoxData.mbLocked = getFlag( nProt, BIFF_XF_LOCKED ); + maOoxData.mbHidden = getFlag( nProt, BIFF_XF_HIDDEN ); +} + +void Protection::finalizeImport() +{ + maApiData.maCellProt.IsLocked = maOoxData.mbLocked; + maApiData.maCellProt.IsFormulaHidden = maOoxData.mbHidden; +} + +void Protection::writeToPropertySet( PropertySet& rPropSet ) const +{ + getStylesPropertyHelper().writeProtectionProperties( rPropSet, maApiData ); +} + +// ============================================================================ + +OoxBorderLineData::OoxBorderLineData( bool bDxf ) : + maColor( XML_indexed, OOX_COLOR_WINDOWTEXT ), + mnStyle( XML_none ), + mbUsed( !bDxf ) +{ +} + +void OoxBorderLineData::setBiffStyle( sal_Int32 nLineStyle ) +{ + static const sal_Int32 spnStyleIds[] = { + XML_none, XML_thin, XML_medium, XML_dashed, + XML_dotted, XML_thick, XML_double, XML_hair, + XML_mediumDashed, XML_dashDot, XML_mediumDashDot, XML_dashDotDot, + XML_mediumDashDotDot, XML_slantDashDot }; + mnStyle = STATIC_ARRAY_SELECT( spnStyleIds, nLineStyle, XML_none ); +} + +void OoxBorderLineData::setBiffData( sal_uInt8 nLineStyle, sal_uInt16 nLineColor ) +{ + maColor.set( XML_indexed, nLineColor ); + setBiffStyle( nLineStyle ); +} + +// ============================================================================ + +OoxBorderData::OoxBorderData( bool bDxf ) : + maLeft( bDxf ), + maRight( bDxf ), + maTop( bDxf ), + maBottom( bDxf ), + maDiagonal( bDxf ), + mbDiagTLtoBR( false ), + mbDiagBLtoTR( false ) +{ +} + +// ============================================================================ + +namespace { + +inline void lclSetBorderLineWidth( BorderLine& rBorderLine, + sal_Int16 nOuter, sal_Int16 nDist = API_LINE_NONE, sal_Int16 nInner = API_LINE_NONE ) +{ + rBorderLine.OuterLineWidth = nOuter; + rBorderLine.LineDistance = nDist; + rBorderLine.InnerLineWidth = nInner; +} + +inline sal_Int32 lclGetBorderLineWidth( const BorderLine& rBorderLine ) +{ + return rBorderLine.OuterLineWidth + rBorderLine.LineDistance + rBorderLine.InnerLineWidth; +} + +const BorderLine* lclGetThickerLine( const BorderLine& rBorderLine1, sal_Bool bValid1, const BorderLine& rBorderLine2, sal_Bool bValid2 ) +{ + if( bValid1 && bValid2 ) + return (lclGetBorderLineWidth( rBorderLine1 ) < lclGetBorderLineWidth( rBorderLine2 )) ? &rBorderLine2 : &rBorderLine1; + if( bValid1 ) + return &rBorderLine1; + if( bValid2 ) + return &rBorderLine2; + return 0; +} + +} // namespace + +// ---------------------------------------------------------------------------- + +Border::Border( const WorkbookHelper& rHelper, bool bDxf ) : + WorkbookHelper( rHelper ), + maOoxData( bDxf ), + mbDxf( bDxf ) +{ +} + +bool Border::isSupportedContext( sal_Int32 nElement, sal_Int32 nParentContext ) +{ + switch( nParentContext ) + { + case XLS_TOKEN( border ): + return (nElement == XLS_TOKEN( left )) || + (nElement == XLS_TOKEN( right )) || + (nElement == XLS_TOKEN( top )) || + (nElement == XLS_TOKEN( bottom )) || + (nElement == XLS_TOKEN( diagonal )); + case XLS_TOKEN( left ): + case XLS_TOKEN( right ): + case XLS_TOKEN( top ): + case XLS_TOKEN( bottom ): + case XLS_TOKEN( diagonal ): + return (nElement == XLS_TOKEN( color )); + } + return false; +} + +void Border::importBorder( const AttributeList& rAttribs ) +{ + maOoxData.mbDiagTLtoBR = rAttribs.getBool( XML_diagonalDown, false ); + maOoxData.mbDiagBLtoTR = rAttribs.getBool( XML_diagonalUp, false ); +} + +void Border::importStyle( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( OoxBorderLineData* pBorderLine = getBorderLine( nElement ) ) + { + pBorderLine->mnStyle = rAttribs.getToken( XML_style, XML_none ); + pBorderLine->mbUsed = true; + } +} + +void Border::importColor( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( OoxBorderLineData* pBorderLine = getBorderLine( nElement ) ) + pBorderLine->maColor.importColor( rAttribs ); +} + +void Border::importBorder( RecordInputStream& rStrm ) +{ + sal_uInt8 nFlags = rStrm.readuInt8(); + maOoxData.mbDiagTLtoBR = getFlag( nFlags, OOBIN_BORDER_DIAG_TLBR ); + maOoxData.mbDiagBLtoTR = getFlag( nFlags, OOBIN_BORDER_DIAG_BLTR ); + maOoxData.maTop.setBiffStyle( rStrm.readuInt16() ); + rStrm >> maOoxData.maTop.maColor; + maOoxData.maBottom.setBiffStyle( rStrm.readuInt16() ); + rStrm >> maOoxData.maBottom.maColor; + maOoxData.maLeft.setBiffStyle( rStrm.readuInt16() ); + rStrm >> maOoxData.maLeft.maColor; + maOoxData.maRight.setBiffStyle( rStrm.readuInt16() ); + rStrm >> maOoxData.maRight.maColor; + maOoxData.maDiagonal.setBiffStyle( rStrm.readuInt16() ); + rStrm >> maOoxData.maDiagonal.maColor; +} + +void Border::importDxfBorder( sal_Int32 nElement, RecordInputStream& rStrm ) +{ + OSL_ENSURE( mbDxf, "Border::importDxfBorder - missing conditional formatting flag" ); + if( OoxBorderLineData* pBorderLine = getBorderLine( nElement ) ) + { + sal_uInt16 nStyle; + rStrm >> pBorderLine->maColor >> nStyle; + pBorderLine->setBiffStyle( nStyle ); + pBorderLine->mbUsed = true; + } +} + +void Border::setBiff2Data( sal_uInt8 nFlags ) +{ + OSL_ENSURE( !mbDxf, "Border::setBiff2Data - unexpected conditional formatting flag" ); + maOoxData.maLeft.setBiffData( getFlagValue( nFlags, BIFF2_XF_LEFTLINE, BIFF_LINE_THIN, BIFF_LINE_NONE ), BIFF2_COLOR_BLACK ); + maOoxData.maRight.setBiffData( getFlagValue( nFlags, BIFF2_XF_RIGHTLINE, BIFF_LINE_THIN, BIFF_LINE_NONE ), BIFF2_COLOR_BLACK ); + maOoxData.maTop.setBiffData( getFlagValue( nFlags, BIFF2_XF_TOPLINE, BIFF_LINE_THIN, BIFF_LINE_NONE ), BIFF2_COLOR_BLACK ); + maOoxData.maBottom.setBiffData( getFlagValue( nFlags, BIFF2_XF_BOTTOMLINE, BIFF_LINE_THIN, BIFF_LINE_NONE ), BIFF2_COLOR_BLACK ); + maOoxData.maDiagonal.mbUsed = false; +} + +void Border::setBiff3Data( sal_uInt32 nBorder ) +{ + OSL_ENSURE( !mbDxf, "Border::setBiff3Data - unexpected conditional formatting flag" ); + maOoxData.maLeft.setBiffData( extractValue< sal_uInt8 >( nBorder, 8, 3 ), extractValue< sal_uInt16 >( nBorder, 11, 5 ) ); + maOoxData.maRight.setBiffData( extractValue< sal_uInt8 >( nBorder, 24, 3 ), extractValue< sal_uInt16 >( nBorder, 27, 5 ) ); + maOoxData.maTop.setBiffData( extractValue< sal_uInt8 >( nBorder, 0, 3 ), extractValue< sal_uInt16 >( nBorder, 3, 5 ) ); + maOoxData.maBottom.setBiffData( extractValue< sal_uInt8 >( nBorder, 16, 3 ), extractValue< sal_uInt16 >( nBorder, 19, 5 ) ); + maOoxData.maDiagonal.mbUsed = false; +} + +void Border::setBiff5Data( sal_uInt32 nBorder, sal_uInt32 nArea ) +{ + OSL_ENSURE( !mbDxf, "Border::setBiff5Data - unexpected conditional formatting flag" ); + maOoxData.maLeft.setBiffData( extractValue< sal_uInt8 >( nBorder, 3, 3 ), extractValue< sal_uInt16 >( nBorder, 16, 7 ) ); + maOoxData.maRight.setBiffData( extractValue< sal_uInt8 >( nBorder, 6, 3 ), extractValue< sal_uInt16 >( nBorder, 23, 7 ) ); + maOoxData.maTop.setBiffData( extractValue< sal_uInt8 >( nBorder, 0, 3 ), extractValue< sal_uInt16 >( nBorder, 9, 7 ) ); + maOoxData.maBottom.setBiffData( extractValue< sal_uInt8 >( nArea, 22, 3 ), extractValue< sal_uInt16 >( nArea, 25, 7 ) ); + maOoxData.maDiagonal.mbUsed = false; +} + +void Border::setBiff8Data( sal_uInt32 nBorder1, sal_uInt32 nBorder2 ) +{ + OSL_ENSURE( !mbDxf, "Border::setBiff8Data - unexpected conditional formatting flag" ); + maOoxData.maLeft.setBiffData( extractValue< sal_uInt8 >( nBorder1, 0, 4 ), extractValue< sal_uInt16 >( nBorder1, 16, 7 ) ); + maOoxData.maRight.setBiffData( extractValue< sal_uInt8 >( nBorder1, 4, 4 ), extractValue< sal_uInt16 >( nBorder1, 23, 7 ) ); + maOoxData.maTop.setBiffData( extractValue< sal_uInt8 >( nBorder1, 8, 4 ), extractValue< sal_uInt16 >( nBorder2, 0, 7 ) ); + maOoxData.maBottom.setBiffData( extractValue< sal_uInt8 >( nBorder1, 12, 4 ), extractValue< sal_uInt16 >( nBorder2, 7, 7 ) ); + maOoxData.mbDiagTLtoBR = getFlag( nBorder1, BIFF_XF_DIAG_TLBR ); + maOoxData.mbDiagBLtoTR = getFlag( nBorder1, BIFF_XF_DIAG_BLTR ); + if( maOoxData.mbDiagTLtoBR || maOoxData.mbDiagBLtoTR ) + maOoxData.maDiagonal.setBiffData( extractValue< sal_uInt8 >( nBorder2, 21, 4 ), extractValue< sal_uInt16 >( nBorder2, 14, 7 ) ); +} + +void Border::importCfRule( BiffInputStream& rStrm, sal_uInt32 nFlags ) +{ + OSL_ENSURE( mbDxf, "Border::importCfRule - missing conditional formatting flag" ); + OSL_ENSURE( getFlag( nFlags, BIFF_CFRULE_BORDERBLOCK ), "Border::importCfRule - missing border block flag" ); + sal_uInt16 nStyle; + sal_uInt32 nColor; + rStrm >> nStyle >> nColor; + rStrm.skip( 2 ); + maOoxData.maLeft.setBiffData( extractValue< sal_uInt8 >( nStyle, 0, 4 ), extractValue< sal_uInt16 >( nColor, 0, 7 ) ); + maOoxData.maRight.setBiffData( extractValue< sal_uInt8 >( nStyle, 4, 4 ), extractValue< sal_uInt16 >( nColor, 7, 7 ) ); + maOoxData.maTop.setBiffData( extractValue< sal_uInt8 >( nStyle, 8, 4 ), extractValue< sal_uInt16 >( nColor, 16, 7 ) ); + maOoxData.maBottom.setBiffData( extractValue< sal_uInt8 >( nStyle, 12, 4 ), extractValue< sal_uInt16 >( nColor, 23, 7 ) ); + maOoxData.maLeft.mbUsed = !getFlag( nFlags, BIFF_CFRULE_BORDER_LEFT ); + maOoxData.maRight.mbUsed = !getFlag( nFlags, BIFF_CFRULE_BORDER_RIGHT ); + maOoxData.maTop.mbUsed = !getFlag( nFlags, BIFF_CFRULE_BORDER_TOP ); + maOoxData.maBottom.mbUsed = !getFlag( nFlags, BIFF_CFRULE_BORDER_BOTTOM ); +} + +void Border::finalizeImport() +{ + maApiData.mbBorderUsed = maOoxData.maLeft.mbUsed || maOoxData.maRight.mbUsed || maOoxData.maTop.mbUsed || maOoxData.maBottom.mbUsed; + maApiData.mbDiagUsed = maOoxData.maDiagonal.mbUsed; + + maApiData.maBorder.IsLeftLineValid = convertBorderLine( maApiData.maBorder.LeftLine, maOoxData.maLeft ); + maApiData.maBorder.IsRightLineValid = convertBorderLine( maApiData.maBorder.RightLine, maOoxData.maRight ); + maApiData.maBorder.IsTopLineValid = convertBorderLine( maApiData.maBorder.TopLine, maOoxData.maTop ); + maApiData.maBorder.IsBottomLineValid = convertBorderLine( maApiData.maBorder.BottomLine, maOoxData.maBottom ); + + if( !mbDxf ) + { + maApiData.maBorder.IsVerticalLineValid = maApiData.maBorder.IsLeftLineValid || maApiData.maBorder.IsRightLineValid; + if( const BorderLine* pVertLine = lclGetThickerLine( maApiData.maBorder.LeftLine, maApiData.maBorder.IsLeftLineValid, maApiData.maBorder.RightLine, maApiData.maBorder.IsRightLineValid ) ) + maApiData.maBorder.VerticalLine = *pVertLine; + + maApiData.maBorder.IsHorizontalLineValid = maApiData.maBorder.IsTopLineValid || maApiData.maBorder.IsBottomLineValid; + if( const BorderLine* pHorLine = lclGetThickerLine( maApiData.maBorder.TopLine, maApiData.maBorder.IsTopLineValid, maApiData.maBorder.BottomLine, maApiData.maBorder.IsBottomLineValid ) ) + maApiData.maBorder.HorizontalLine = *pHorLine; + } + + if( maOoxData.mbDiagTLtoBR ) + convertBorderLine( maApiData.maTLtoBR, maOoxData.maDiagonal ); + if( maOoxData.mbDiagBLtoTR ) + convertBorderLine( maApiData.maBLtoTR, maOoxData.maDiagonal ); +} + +void Border::writeToPropertySet( PropertySet& rPropSet ) const +{ + getStylesPropertyHelper().writeBorderProperties( rPropSet, maApiData ); +} + +OoxBorderLineData* Border::getBorderLine( sal_Int32 nElement ) +{ + switch( nElement ) + { + case XLS_TOKEN( left ): return &maOoxData.maLeft; + case XLS_TOKEN( right ): return &maOoxData.maRight; + case XLS_TOKEN( top ): return &maOoxData.maTop; + case XLS_TOKEN( bottom ): return &maOoxData.maBottom; + case XLS_TOKEN( diagonal ): return &maOoxData.maDiagonal; + } + return 0; +} + +bool Border::convertBorderLine( BorderLine& rBorderLine, const OoxBorderLineData& rLineData ) +{ + rBorderLine.Color = getStyles().getColor( rLineData.maColor, API_RGB_BLACK ); + switch( rLineData.mnStyle ) + { + case XML_dashDot: lclSetBorderLineWidth( rBorderLine, API_LINE_THIN ); break; + case XML_dashDotDot: lclSetBorderLineWidth( rBorderLine, API_LINE_THIN ); break; + case XML_dashed: lclSetBorderLineWidth( rBorderLine, API_LINE_THIN ); break; + case XML_dotted: lclSetBorderLineWidth( rBorderLine, API_LINE_THIN ); break; + case XML_double: lclSetBorderLineWidth( rBorderLine, API_LINE_THIN, API_LINE_THIN, API_LINE_THIN ); break; + case XML_hair: lclSetBorderLineWidth( rBorderLine, API_LINE_HAIR ); break; + case XML_medium: lclSetBorderLineWidth( rBorderLine, API_LINE_MEDIUM ); break; + case XML_mediumDashDot: lclSetBorderLineWidth( rBorderLine, API_LINE_MEDIUM ); break; + case XML_mediumDashDotDot: lclSetBorderLineWidth( rBorderLine, API_LINE_MEDIUM ); break; + case XML_mediumDashed: lclSetBorderLineWidth( rBorderLine, API_LINE_MEDIUM ); break; + case XML_none: lclSetBorderLineWidth( rBorderLine, API_LINE_NONE ); break; + case XML_slantDashDot: lclSetBorderLineWidth( rBorderLine, API_LINE_MEDIUM ); break; + case XML_thick: lclSetBorderLineWidth( rBorderLine, API_LINE_THICK ); break; + case XML_thin: lclSetBorderLineWidth( rBorderLine, API_LINE_THIN ); break; + default: lclSetBorderLineWidth( rBorderLine, API_LINE_NONE ); break; + } + return rLineData.mbUsed; +} + + +// ============================================================================ + +OoxPatternFillData::OoxPatternFillData( bool bDxf ) : + maPatternColor( XML_indexed, OOX_COLOR_WINDOWTEXT ), + maFillColor( XML_indexed, OOX_COLOR_WINDOWBACK ), + mnPattern( XML_none ), + mbPattColorUsed( !bDxf ), + mbFillColorUsed( !bDxf ), + mbPatternUsed( !bDxf ) +{ +} + +void OoxPatternFillData::setBinPattern( sal_Int32 nPattern ) +{ + static const sal_Int32 spnPatternIds[] = { + XML_none, XML_solid, XML_mediumGray, XML_darkGray, + XML_lightGray, XML_darkHorizontal, XML_darkVertical, XML_darkDown, + XML_darkUp, XML_darkGrid, XML_darkTrellis, XML_lightHorizontal, + XML_lightVertical, XML_lightDown, XML_lightUp, XML_lightGrid, + XML_lightTrellis, XML_gray125, XML_gray0625 }; + mnPattern = STATIC_ARRAY_SELECT( spnPatternIds, nPattern, XML_none ); +} + +void OoxPatternFillData::setBiffData( sal_uInt16 nPatternColor, sal_uInt16 nFillColor, sal_uInt8 nPattern ) +{ + maPatternColor.set( XML_indexed, static_cast< sal_Int32 >( nPatternColor ) ); + maFillColor.set( XML_indexed, static_cast< sal_Int32 >( nFillColor ) ); + // patterns equal in BIFF and OOBIN + setBinPattern( nPattern ); +} + +// ---------------------------------------------------------------------------- + +OoxGradientFillData::OoxGradientFillData() : + mnType( XML_linear ), + mfAngle( 0.0 ), + mfLeft( 0.0 ), + mfRight( 0.0 ), + mfTop( 0.0 ), + mfBottom( 0.0 ) +{ +} + +void OoxGradientFillData::readGradient( RecordInputStream& rStrm ) +{ + sal_Int32 nType; + rStrm >> nType >> mfAngle >> mfLeft >> mfRight >> mfTop >> mfBottom; + static const sal_Int32 spnTypes[] = { XML_linear, XML_path }; + mnType = STATIC_ARRAY_SELECT( spnTypes, nType, XML_TOKEN_INVALID ); +} + +void OoxGradientFillData::readGradientStop( RecordInputStream& rStrm, bool bDxf ) +{ + OoxColor aColor; + double fPosition; + if( bDxf ) + { + rStrm.skip( 2 ); + rStrm >> fPosition >> aColor; + } + else + { + rStrm >> aColor >> fPosition; + } + if( rStrm.isValid() && (fPosition >= 0.0) ) + maColors[ fPosition ] = aColor; +} + +// ============================================================================ + +namespace { + +inline sal_Int32 lclGetMixedColorComp( sal_Int32 nPatt, sal_Int32 nFill, sal_Int32 nAlpha ) +{ + return ((nPatt - nFill) * nAlpha) / 0x80 + nFill; +} + +sal_Int32 lclGetMixedColor( sal_Int32 nPattColor, sal_Int32 nFillColor, sal_Int32 nAlpha ) +{ + return + (lclGetMixedColorComp( nPattColor & 0xFF0000, nFillColor & 0xFF0000, nAlpha ) & 0xFF0000) | + (lclGetMixedColorComp( nPattColor & 0x00FF00, nFillColor & 0x00FF00, nAlpha ) & 0x00FF00) | + (lclGetMixedColorComp( nPattColor & 0x0000FF, nFillColor & 0x0000FF, nAlpha ) & 0x0000FF); +} + +} // namespace + +// ---------------------------------------------------------------------------- + +Fill::Fill( const WorkbookHelper& rHelper, bool bDxf ) : + WorkbookHelper( rHelper ), + mbDxf( bDxf ) +{ +} + +bool Fill::isSupportedContext( sal_Int32 nElement, sal_Int32 nParentContext ) +{ + switch( nParentContext ) + { + case XLS_TOKEN( fill ): + return (nElement == XLS_TOKEN( patternFill )) || + (nElement == XLS_TOKEN( gradientFill )); + case XLS_TOKEN( patternFill ): + return (nElement == XLS_TOKEN( fgColor )) || + (nElement == XLS_TOKEN( bgColor )); + case XLS_TOKEN( gradientFill ): + return (nElement == XLS_TOKEN( stop )); + case XLS_TOKEN( stop ): + return (nElement == XLS_TOKEN( color )); + } + return false; +} + +void Fill::importPatternFill( const AttributeList& rAttribs ) +{ + mxOoxPattData.reset( new OoxPatternFillData( mbDxf ) ); + mxOoxPattData->mnPattern = rAttribs.getToken( XML_patternType, XML_none ); + if( mbDxf ) + mxOoxPattData->mbPatternUsed = rAttribs.hasAttribute( XML_patternType ); +} + +void Fill::importFgColor( const AttributeList& rAttribs ) +{ + OSL_ENSURE( mxOoxPattData.get(), "Fill::importFgColor - missing pattern data" ); + if( mxOoxPattData.get() ) + { + mxOoxPattData->maPatternColor.importColor( rAttribs ); + mxOoxPattData->mbPattColorUsed = true; + } +} + +void Fill::importBgColor( const AttributeList& rAttribs ) +{ + OSL_ENSURE( mxOoxPattData.get(), "Fill::importBgColor - missing pattern data" ); + if( mxOoxPattData.get() ) + { + mxOoxPattData->maFillColor.importColor( rAttribs ); + mxOoxPattData->mbFillColorUsed = true; + } +} + +void Fill::importGradientFill( const AttributeList& rAttribs ) +{ + mxOoxGradData.reset( new OoxGradientFillData ); + mxOoxGradData->mnType = rAttribs.getToken( XML_type, XML_linear ); + mxOoxGradData->mfAngle = rAttribs.getDouble( XML_degree, 0.0 ); + mxOoxGradData->mfLeft = rAttribs.getDouble( XML_left, 0.0 ); + mxOoxGradData->mfRight = rAttribs.getDouble( XML_right, 0.0 ); + mxOoxGradData->mfTop = rAttribs.getDouble( XML_top, 0.0 ); + mxOoxGradData->mfBottom = rAttribs.getDouble( XML_bottom, 0.0 ); +} + +void Fill::importColor( const AttributeList& rAttribs, double fPosition ) +{ + OSL_ENSURE( mxOoxGradData.get(), "Fill::importColor - missing gradient data" ); + if( mxOoxGradData.get() && (fPosition >= 0.0) ) + mxOoxGradData->maColors[ fPosition ].importColor( rAttribs ); +} + +void Fill::importFill( RecordInputStream& rStrm ) +{ + OSL_ENSURE( !mbDxf, "Fill::importFill - unexpected conditional formatting flag" ); + sal_Int32 nPattern = rStrm.readInt32(); + if( nPattern == OOBIN_FILL_GRADIENT ) + { + mxOoxGradData.reset( new OoxGradientFillData ); + sal_Int32 nStopCount; + rStrm.skip( 16 ); + mxOoxGradData->readGradient( rStrm ); + rStrm >> nStopCount; + for( sal_Int32 nStop = 0; (nStop < nStopCount) && rStrm.isValid(); ++nStop ) + mxOoxGradData->readGradientStop( rStrm, false ); + } + else + { + mxOoxPattData.reset( new OoxPatternFillData( mbDxf ) ); + mxOoxPattData->setBinPattern( nPattern ); + rStrm >> mxOoxPattData->maPatternColor >> mxOoxPattData->maFillColor; + } +} + +void Fill::importDxfPattern( RecordInputStream& rStrm ) +{ + OSL_ENSURE( mbDxf, "Fill::importDxfPattern - missing conditional formatting flag" ); + if( !mxOoxPattData ) + mxOoxPattData.reset( new OoxPatternFillData( mbDxf ) ); + mxOoxPattData->setBinPattern( rStrm.readuInt8() ); + mxOoxPattData->mbPatternUsed = true; +} + +void Fill::importDxfFgColor( RecordInputStream& rStrm ) +{ + OSL_ENSURE( mbDxf, "Fill::importDxfFgColor - missing conditional formatting flag" ); + if( !mxOoxPattData ) + mxOoxPattData.reset( new OoxPatternFillData( mbDxf ) ); + mxOoxPattData->maPatternColor.importColor( rStrm ); + mxOoxPattData->mbPattColorUsed = true; +} + +void Fill::importDxfBgColor( RecordInputStream& rStrm ) +{ + OSL_ENSURE( mbDxf, "Fill::importDxfBgColor - missing conditional formatting flag" ); + if( !mxOoxPattData ) + mxOoxPattData.reset( new OoxPatternFillData( mbDxf ) ); + mxOoxPattData->maFillColor.importColor( rStrm ); + mxOoxPattData->mbFillColorUsed = true; +} + +void Fill::importDxfGradient( RecordInputStream& rStrm ) +{ + OSL_ENSURE( mbDxf, "Fill::importDxfGradient - missing conditional formatting flag" ); + if( !mxOoxGradData ) + mxOoxGradData.reset( new OoxGradientFillData ); + mxOoxGradData->readGradient( rStrm ); +} + +void Fill::importDxfStop( RecordInputStream& rStrm ) +{ + OSL_ENSURE( mbDxf, "Fill::importDxfStop - missing conditional formatting flag" ); + if( !mxOoxGradData ) + mxOoxGradData.reset( new OoxGradientFillData ); + mxOoxGradData->readGradientStop( rStrm, true ); +} + +void Fill::setBiff2Data( sal_uInt8 nFlags ) +{ + OSL_ENSURE( !mbDxf, "Fill::setBiff2Data - unexpected conditional formatting flag" ); + mxOoxPattData.reset( new OoxPatternFillData( mbDxf ) ); + mxOoxPattData->setBiffData( + BIFF2_COLOR_BLACK, + BIFF2_COLOR_WHITE, + getFlagValue( nFlags, BIFF2_XF_BACKGROUND, BIFF_PATT_125, BIFF_PATT_NONE ) ); +} + +void Fill::setBiff3Data( sal_uInt16 nArea ) +{ + OSL_ENSURE( !mbDxf, "Fill::setBiff3Data - unexpected conditional formatting flag" ); + mxOoxPattData.reset( new OoxPatternFillData( mbDxf ) ); + mxOoxPattData->setBiffData( + extractValue< sal_uInt16 >( nArea, 6, 5 ), + extractValue< sal_uInt16 >( nArea, 11, 5 ), + extractValue< sal_uInt8 >( nArea, 0, 6 ) ); +} + +void Fill::setBiff5Data( sal_uInt32 nArea ) +{ + OSL_ENSURE( !mbDxf, "Fill::setBiff5Data - unexpected conditional formatting flag" ); + mxOoxPattData.reset( new OoxPatternFillData( mbDxf ) ); + mxOoxPattData->setBiffData( + extractValue< sal_uInt16 >( nArea, 0, 7 ), + extractValue< sal_uInt16 >( nArea, 7, 7 ), + extractValue< sal_uInt8 >( nArea, 16, 6 ) ); +} + +void Fill::setBiff8Data( sal_uInt32 nBorder2, sal_uInt16 nArea ) +{ + OSL_ENSURE( !mbDxf, "Fill::setBiff8Data - unexpected conditional formatting flag" ); + mxOoxPattData.reset( new OoxPatternFillData( mbDxf ) ); + mxOoxPattData->setBiffData( + extractValue< sal_uInt16 >( nArea, 0, 7 ), + extractValue< sal_uInt16 >( nArea, 7, 7 ), + extractValue< sal_uInt8 >( nBorder2, 26, 6 ) ); +} + +void Fill::importCfRule( BiffInputStream& rStrm, sal_uInt32 nFlags ) +{ + OSL_ENSURE( mbDxf, "Fill::importCfRule - missing conditional formatting flag" ); + OSL_ENSURE( getFlag( nFlags, BIFF_CFRULE_FILLBLOCK ), "Fill::importCfRule - missing fill block flag" ); + mxOoxPattData.reset( new OoxPatternFillData( mbDxf ) ); + sal_uInt32 nFillData; + rStrm >> nFillData; + mxOoxPattData->setBiffData( + extractValue< sal_uInt16 >( nFillData, 16, 7 ), + extractValue< sal_uInt16 >( nFillData, 23, 7 ), + extractValue< sal_uInt8 >( nFillData, 10, 6 ) ); + mxOoxPattData->mbPattColorUsed = !getFlag( nFlags, BIFF_CFRULE_FILL_PATTCOLOR ); + mxOoxPattData->mbFillColorUsed = !getFlag( nFlags, BIFF_CFRULE_FILL_FILLCOLOR ); + mxOoxPattData->mbPatternUsed = !getFlag( nFlags, BIFF_CFRULE_FILL_PATTERN ); +} + +void Fill::finalizeImport() +{ + if( mxOoxPattData.get() ) + { + // finalize the OOX data struct + OoxPatternFillData& rOoxData = *mxOoxPattData; + if( mbDxf ) + { + if( rOoxData.mbFillColorUsed && (!rOoxData.mbPatternUsed || (rOoxData.mnPattern == XML_solid)) ) + { + rOoxData.maPatternColor = rOoxData.maFillColor; + rOoxData.mnPattern = XML_solid; + rOoxData.mbPattColorUsed = rOoxData.mbPatternUsed = true; + } + else if( !rOoxData.mbFillColorUsed && rOoxData.mbPatternUsed && (rOoxData.mnPattern == XML_solid) ) + { + rOoxData.mbPatternUsed = false; + } + } + + // convert to API fill settings + maApiData.mbUsed = rOoxData.mbPatternUsed; + if( rOoxData.mnPattern == XML_none ) + { + maApiData.mnColor = API_RGB_TRANSPARENT; + maApiData.mbTransparent = true; + } + else + { + sal_Int32 nAlpha = 0x80; + switch( rOoxData.mnPattern ) + { + case XML_darkDown: nAlpha = 0x40; break; + case XML_darkGray: nAlpha = 0x60; break; + case XML_darkGrid: nAlpha = 0x40; break; + case XML_darkHorizontal: nAlpha = 0x40; break; + case XML_darkTrellis: nAlpha = 0x60; break; + case XML_darkUp: nAlpha = 0x40; break; + case XML_darkVertical: nAlpha = 0x40; break; + case XML_gray0625: nAlpha = 0x08; break; + case XML_gray125: nAlpha = 0x10; break; + case XML_lightDown: nAlpha = 0x20; break; + case XML_lightGray: nAlpha = 0x20; break; + case XML_lightGrid: nAlpha = 0x38; break; + case XML_lightHorizontal: nAlpha = 0x20; break; + case XML_lightTrellis: nAlpha = 0x30; break; + case XML_lightUp: nAlpha = 0x20; break; + case XML_lightVertical: nAlpha = 0x20; break; + case XML_mediumGray: nAlpha = 0x40; break; + case XML_solid: nAlpha = 0x80; break; + } + + if( !rOoxData.mbPattColorUsed ) + rOoxData.maPatternColor.set( XML_auto, 0 ); + sal_Int32 nPattColor = getStyles().getColor( + rOoxData.maPatternColor, ThemeBuffer::getSystemWindowTextColor() ); + + if( !rOoxData.mbFillColorUsed ) + rOoxData.maFillColor.set( XML_auto, 0 ); + sal_Int32 nFillColor = getStyles().getColor( + rOoxData.maFillColor, ThemeBuffer::getSystemWindowColor() ); + + maApiData.mnColor = lclGetMixedColor( nPattColor, nFillColor, nAlpha ); + maApiData.mbTransparent = false; + } + } + else if( mxOoxGradData.get() && !mxOoxGradData->maColors.empty() ) + { + OoxGradientFillData& rOoxData = *mxOoxGradData; + maApiData.mbUsed = true; // no support for differential attributes + OoxGradientFillData::OoxColorMap::const_iterator aIt = rOoxData.maColors.begin(); + OSL_ENSURE( !aIt->second.isAuto(), "Fill::finalizeImport - automatic gradient color" ); + maApiData.mnColor = getStyles().getColor( aIt->second, API_RGB_TRANSPARENT ); + if( ++aIt != rOoxData.maColors.end() ) + { + OSL_ENSURE( !aIt->second.isAuto(), "Fill::finalizeImport - automatic gradient color" ); + sal_Int32 nEndColor = getStyles().getColor( aIt->second, API_RGB_TRANSPARENT ); + maApiData.mnColor = lclGetMixedColor( maApiData.mnColor, nEndColor, 0x40 ); + maApiData.mbTransparent = false; + } + } +} + +void Fill::writeToPropertySet( PropertySet& rPropSet ) const +{ + getStylesPropertyHelper().writeSolidFillProperties( rPropSet, maApiData ); +} + +// ============================================================================ + +OoxXfData::OoxXfData() : + mnStyleXfId( -1 ), + mnFontId( -1 ), + mnNumFmtId( -1 ), + mnBorderId( -1 ), + mnFillId( -1 ), + mbCellXf( true ), + mbFontUsed( false ), + mbNumFmtUsed( false ), + mbAlignUsed( false ), + mbProtUsed( false ), + mbBorderUsed( false ), + mbAreaUsed( false ) +{ +} + +// ============================================================================ + +Xf::Xf( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + maAlignment( rHelper ), + maProtection( rHelper ) +{ +} + +void Xf::setAllUsedFlags( bool bUsed ) +{ + maOoxData.mbAlignUsed = maOoxData.mbProtUsed = maOoxData.mbFontUsed = + maOoxData.mbNumFmtUsed = maOoxData.mbBorderUsed = maOoxData.mbAreaUsed = bUsed; +} + +void Xf::importXf( const AttributeList& rAttribs, bool bCellXf ) +{ + maOoxData.mbCellXf = bCellXf; + maOoxData.mnStyleXfId = rAttribs.getInteger( XML_xfId, -1 ); + maOoxData.mnFontId = rAttribs.getInteger( XML_fontId, -1 ); + maOoxData.mnNumFmtId = rAttribs.getInteger( XML_numFmtId, -1 ); + maOoxData.mnBorderId = rAttribs.getInteger( XML_borderId, -1 ); + maOoxData.mnFillId = rAttribs.getInteger( XML_fillId, -1 ); + + /* Default value of the apply*** attributes is dependent on context: + true in cellStyleXfs element, false in cellXfs element... */ + maOoxData.mbAlignUsed = rAttribs.getBool( XML_applyAlignment, !maOoxData.mbCellXf ); + maOoxData.mbProtUsed = rAttribs.getBool( XML_applyProtection, !maOoxData.mbCellXf ); + maOoxData.mbFontUsed = rAttribs.getBool( XML_applyFont, !maOoxData.mbCellXf ); + maOoxData.mbNumFmtUsed = rAttribs.getBool( XML_applyNumberFormat, !maOoxData.mbCellXf ); + maOoxData.mbBorderUsed = rAttribs.getBool( XML_applyBorder, !maOoxData.mbCellXf ); + maOoxData.mbAreaUsed = rAttribs.getBool( XML_applyFill, !maOoxData.mbCellXf ); +} + +void Xf::importAlignment( const AttributeList& rAttribs ) +{ + maAlignment.importAlignment( rAttribs ); +} + +void Xf::importProtection( const AttributeList& rAttribs ) +{ + maProtection.importProtection( rAttribs ); +} + +void Xf::importXf( RecordInputStream& rStrm, bool bCellXf ) +{ + maOoxData.mbCellXf = bCellXf; + maOoxData.mnStyleXfId = rStrm.readuInt16(); + maOoxData.mnNumFmtId = rStrm.readuInt16(); + maOoxData.mnFontId = rStrm.readuInt16(); + maOoxData.mnFillId = rStrm.readuInt16(); + maOoxData.mnBorderId = rStrm.readuInt16(); + sal_uInt32 nFlags = rStrm.readuInt32(); + maAlignment.setBinData( nFlags ); + maProtection.setBinData( nFlags ); + // used flags, see comments in Xf::setBiffUsedFlags() + sal_uInt16 nUsedFlags = rStrm.readuInt16(); + maOoxData.mbFontUsed = maOoxData.mbCellXf == getFlag( nUsedFlags, OOBIN_XF_FONT_USED ); + maOoxData.mbNumFmtUsed = maOoxData.mbCellXf == getFlag( nUsedFlags, OOBIN_XF_NUMFMT_USED ); + maOoxData.mbAlignUsed = maOoxData.mbCellXf == getFlag( nUsedFlags, OOBIN_XF_ALIGN_USED ); + maOoxData.mbProtUsed = maOoxData.mbCellXf == getFlag( nUsedFlags, OOBIN_XF_PROT_USED ); + maOoxData.mbBorderUsed = maOoxData.mbCellXf == getFlag( nUsedFlags, OOBIN_XF_BORDER_USED ); + maOoxData.mbAreaUsed = maOoxData.mbCellXf == getFlag( nUsedFlags, OOBIN_XF_AREA_USED ); +} + +void Xf::importXf( BiffInputStream& rStrm ) +{ + BorderRef xBorder = getStyles().createBorder( &maOoxData.mnBorderId ); + FillRef xFill = getStyles().createFill( &maOoxData.mnFillId ); + + switch( getBiff() ) + { + case BIFF2: + { + sal_uInt8 nFontId, nNumFmtId, nFlags; + rStrm >> nFontId; + rStrm.skip( 1 ); + rStrm >> nNumFmtId >> nFlags; + + // only cell XFs in BIFF2, no parent style, used flags always true + setAllUsedFlags( true ); + + // attributes + maAlignment.setBiff2Data( nFlags ); + maProtection.setBiff2Data( nNumFmtId ); + xBorder->setBiff2Data( nFlags ); + xFill->setBiff2Data( nFlags ); + maOoxData.mnFontId = static_cast< sal_Int32 >( nFontId ); + maOoxData.mnNumFmtId = static_cast< sal_Int32 >( nNumFmtId & BIFF2_XF_VALFMT_MASK ); + } + break; + + case BIFF3: + { + sal_uInt32 nBorder; + sal_uInt16 nTypeProt, nAlign, nArea; + sal_uInt8 nFontId, nNumFmtId; + rStrm >> nFontId >> nNumFmtId >> nTypeProt >> nAlign >> nArea >> nBorder; + + // XF type/parent + maOoxData.mbCellXf = !getFlag( nTypeProt, BIFF_XF_STYLE ); // new in BIFF3 + maOoxData.mnStyleXfId = extractValue< sal_Int32 >( nAlign, 4, 12 ); // new in BIFF3 + // attribute used flags + setBiffUsedFlags( extractValue< sal_uInt8 >( nTypeProt, 10, 6 ) ); // new in BIFF3 + + // attributes + maAlignment.setBiff3Data( nAlign ); + maProtection.setBiff3Data( nTypeProt ); + xBorder->setBiff3Data( nBorder ); + xFill->setBiff3Data( nArea ); + maOoxData.mnFontId = static_cast< sal_Int32 >( nFontId ); + maOoxData.mnNumFmtId = static_cast< sal_Int32 >( nNumFmtId ); + } + break; + + case BIFF4: + { + sal_uInt32 nBorder; + sal_uInt16 nTypeProt, nAlign, nArea; + sal_uInt8 nFontId, nNumFmtId; + rStrm >> nFontId >> nNumFmtId >> nTypeProt >> nAlign >> nArea >> nBorder; + + // XF type/parent + maOoxData.mbCellXf = !getFlag( nTypeProt, BIFF_XF_STYLE ); + maOoxData.mnStyleXfId = extractValue< sal_Int32 >( nTypeProt, 4, 12 ); + // attribute used flags + setBiffUsedFlags( extractValue< sal_uInt8 >( nAlign, 10, 6 ) ); + + // attributes + maAlignment.setBiff4Data( nAlign ); + maProtection.setBiff3Data( nTypeProt ); + xBorder->setBiff3Data( nBorder ); + xFill->setBiff3Data( nArea ); + maOoxData.mnFontId = static_cast< sal_Int32 >( nFontId ); + maOoxData.mnNumFmtId = static_cast< sal_Int32 >( nNumFmtId ); + } + break; + + case BIFF5: + { + sal_uInt32 nArea, nBorder; + sal_uInt16 nFontId, nNumFmtId, nTypeProt, nAlign; + rStrm >> nFontId >> nNumFmtId >> nTypeProt >> nAlign >> nArea >> nBorder; + + // XF type/parent + maOoxData.mbCellXf = !getFlag( nTypeProt, BIFF_XF_STYLE ); + maOoxData.mnStyleXfId = extractValue< sal_Int32 >( nTypeProt, 4, 12 ); + // attribute used flags + setBiffUsedFlags( extractValue< sal_uInt8 >( nAlign, 10, 6 ) ); + + // attributes + maAlignment.setBiff5Data( nAlign ); + maProtection.setBiff3Data( nTypeProt ); + xBorder->setBiff5Data( nBorder, nArea ); + xFill->setBiff5Data( nArea ); + maOoxData.mnFontId = static_cast< sal_Int32 >( nFontId ); + maOoxData.mnNumFmtId = static_cast< sal_Int32 >( nNumFmtId ); + } + break; + + case BIFF8: + { + sal_uInt32 nBorder1, nBorder2; + sal_uInt16 nFontId, nNumFmtId, nTypeProt, nAlign, nMiscAttrib, nArea; + rStrm >> nFontId >> nNumFmtId >> nTypeProt >> nAlign >> nMiscAttrib >> nBorder1 >> nBorder2 >> nArea; + + // XF type/parent + maOoxData.mbCellXf = !getFlag( nTypeProt, BIFF_XF_STYLE ); + maOoxData.mnStyleXfId = extractValue< sal_Int32 >( nTypeProt, 4, 12 ); + // attribute used flags + setBiffUsedFlags( extractValue< sal_uInt8 >( nMiscAttrib, 10, 6 ) ); + + // attributes + maAlignment.setBiff8Data( nAlign, nMiscAttrib ); + maProtection.setBiff3Data( nTypeProt ); + xBorder->setBiff8Data( nBorder1, nBorder2 ); + xFill->setBiff8Data( nBorder2, nArea ); + maOoxData.mnFontId = static_cast< sal_Int32 >( nFontId ); + maOoxData.mnNumFmtId = static_cast< sal_Int32 >( nNumFmtId ); + } + break; + + case BIFF_UNKNOWN: break; + } +} + +void Xf::finalizeImport() +{ + // alignment and protection + maAlignment.finalizeImport(); + maProtection.finalizeImport(); + // update used flags from cell style + if( maOoxData.mbCellXf ) + if( const Xf* pStyleXf = getStyles().getStyleXf( maOoxData.mnStyleXfId ).get() ) + updateUsedFlags( *pStyleXf ); +} + +FontRef Xf::getFont() const +{ + return getStyles().getFont( maOoxData.mnFontId ); +} + +bool Xf::hasAnyUsedFlags() const +{ + return + maOoxData.mbAlignUsed || maOoxData.mbProtUsed || maOoxData.mbFontUsed || + maOoxData.mbNumFmtUsed || maOoxData.mbBorderUsed || maOoxData.mbAreaUsed; +} + +void Xf::writeToPropertySet( PropertySet& rPropSet ) const +{ + StylesBuffer& rStyles = getStyles(); + + // create and set cell style + if( maOoxData.mbCellXf ) + { + const OUString& rStyleName = rStyles.createCellStyle( maOoxData.mnStyleXfId ); + rPropSet.setProperty( CREATE_OUSTRING( "CellStyle" ), rStyleName ); + } + + if( maOoxData.mbFontUsed ) + rStyles.writeFontToPropertySet( rPropSet, maOoxData.mnFontId ); + if( maOoxData.mbNumFmtUsed ) + rStyles.writeNumFmtToPropertySet( rPropSet, maOoxData.mnNumFmtId ); + if( maOoxData.mbAlignUsed ) + maAlignment.writeToPropertySet( rPropSet ); + if( maOoxData.mbProtUsed ) + maProtection.writeToPropertySet( rPropSet ); + if( maOoxData.mbBorderUsed ) + rStyles.writeBorderToPropertySet( rPropSet, maOoxData.mnBorderId ); + if( maOoxData.mbAreaUsed ) + rStyles.writeFillToPropertySet( rPropSet, maOoxData.mnFillId ); +} + +void Xf::setBiffUsedFlags( sal_uInt8 nUsedFlags ) +{ + /* Notes about finding the used flags: + - In cell XFs a *set* bit means a used attribute. + - In style XFs a *cleared* bit means a used attribute. + The boolean flags always store true, if the attribute is used. + The "maOoxData.mbCellXf == getFlag(...)" construct evaluates to true in + both mentioned cases: cell XF and set bit; or style XF and cleared bit. + */ + maOoxData.mbFontUsed = maOoxData.mbCellXf == getFlag( nUsedFlags, BIFF_XF_FONT_USED ); + maOoxData.mbNumFmtUsed = maOoxData.mbCellXf == getFlag( nUsedFlags, BIFF_XF_NUMFMT_USED ); + maOoxData.mbAlignUsed = maOoxData.mbCellXf == getFlag( nUsedFlags, BIFF_XF_ALIGN_USED ); + maOoxData.mbProtUsed = maOoxData.mbCellXf == getFlag( nUsedFlags, BIFF_XF_PROT_USED ); + maOoxData.mbBorderUsed = maOoxData.mbCellXf == getFlag( nUsedFlags, BIFF_XF_BORDER_USED ); + maOoxData.mbAreaUsed = maOoxData.mbCellXf == getFlag( nUsedFlags, BIFF_XF_AREA_USED ); +} + +void Xf::updateUsedFlags( const Xf& rStyleXf ) +{ + /* Enables the used flags, if the formatting attributes differ from the + passed style XF. In cell XFs Excel uses the cell attributes, if they + differ from the parent style XF. + #109899# ...or if the respective flag is not set in parent style XF. + */ + const OoxXfData& rStyleData = rStyleXf.maOoxData; + if( !maOoxData.mbFontUsed ) + maOoxData.mbFontUsed = !rStyleData.mbFontUsed || (maOoxData.mnFontId != rStyleData.mnFontId); + if( !maOoxData.mbNumFmtUsed ) + maOoxData.mbNumFmtUsed = !rStyleData.mbNumFmtUsed || (maOoxData.mnNumFmtId != rStyleData.mnNumFmtId); + if( !maOoxData.mbAlignUsed ) + maOoxData.mbAlignUsed = !rStyleData.mbAlignUsed || !(maAlignment.getApiData() == rStyleXf.maAlignment.getApiData()); + if( !maOoxData.mbProtUsed ) + maOoxData.mbProtUsed = !rStyleData.mbProtUsed || !(maProtection.getApiData() == rStyleXf.maProtection.getApiData()); + if( !maOoxData.mbBorderUsed ) + maOoxData.mbBorderUsed = !rStyleData.mbBorderUsed || (maOoxData.mnBorderId != rStyleData.mnBorderId); + if( !maOoxData.mbAreaUsed ) + maOoxData.mbAreaUsed = !rStyleData.mbAreaUsed || (maOoxData.mnFillId != rStyleData.mnFillId); +} + +// ============================================================================ + +Dxf::Dxf( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ) +{ +} + +FontRef Dxf::importFont( const AttributeList& ) +{ + createFont( true ); + return mxFont; +} + +void Dxf::importNumFmt( const AttributeList& rAttribs ) +{ + mxNumFmt = getStyles().importNumFmt( rAttribs ); +} + +void Dxf::importAlignment( const AttributeList& rAttribs ) +{ + mxAlignment.reset( new Alignment( *this ) ); + mxAlignment->importAlignment( rAttribs ); +} + +void Dxf::importProtection( const AttributeList& rAttribs ) +{ + mxProtection.reset( new Protection( *this ) ); + mxProtection->importProtection( rAttribs ); +} + +BorderRef Dxf::importBorder( const AttributeList& rAttribs ) +{ + createBorder( true ); + mxBorder->importBorder( rAttribs ); + return mxBorder; +} + +FillRef Dxf::importFill( const AttributeList& ) +{ + createFill( true ); + return mxFill; +} + +void Dxf::importDxf( RecordInputStream& rStrm ) +{ + sal_Int32 nNumFmtId = -1; + OUString aFmtCode; + sal_uInt16 nRecCount; + rStrm.skip( 4 ); // flags + rStrm >> nRecCount; + for( sal_uInt16 nRec = 0; rStrm.isValid() && (nRec < nRecCount); ++nRec ) + { + sal_uInt16 nSubRecId, nSubRecSize; + sal_Int32 nRecEnd = rStrm.getRecPos(); + rStrm >> nSubRecId >> nSubRecSize; + nRecEnd += nSubRecSize; + switch( nSubRecId ) + { + case OOBIN_DXF_FILL_PATTERN: createFill( false ); mxFill->importDxfPattern( rStrm ); break; + case OOBIN_DXF_FILL_FGCOLOR: createFill( false ); mxFill->importDxfFgColor( rStrm ); break; + case OOBIN_DXF_FILL_BGCOLOR: createFill( false ); mxFill->importDxfBgColor( rStrm ); break; + case OOBIN_DXF_FILL_GRADIENT: createFill( false ); mxFill->importDxfGradient( rStrm ); break; + case OOBIN_DXF_FILL_STOP: createFill( false ); mxFill->importDxfStop( rStrm ); break; + case OOBIN_DXF_FONT_COLOR: createFont( false ); mxFont->importDxfColor( rStrm ); break; + case OOBIN_DXF_BORDER_TOP: createBorder( false ); mxBorder->importDxfBorder( XLS_TOKEN( top ), rStrm ); break; + case OOBIN_DXF_BORDER_BOTTOM: createBorder( false ); mxBorder->importDxfBorder( XLS_TOKEN( bottom ), rStrm ); break; + case OOBIN_DXF_BORDER_LEFT: createBorder( false ); mxBorder->importDxfBorder( XLS_TOKEN( left ), rStrm ); break; + case OOBIN_DXF_BORDER_RIGHT: createBorder( false ); mxBorder->importDxfBorder( XLS_TOKEN( right ), rStrm ); break; + case OOBIN_DXF_FONT_NAME: createFont( false ); mxFont->importDxfName( rStrm ); break; + case OOBIN_DXF_FONT_WEIGHT: createFont( false ); mxFont->importDxfWeight( rStrm ); break; + case OOBIN_DXF_FONT_UNDERLINE: createFont( false ); mxFont->importDxfUnderline( rStrm ); break; + case OOBIN_DXF_FONT_ESCAPEMENT: createFont( false ); mxFont->importDxfEscapement( rStrm ); break; + case OOBIN_DXF_FONT_ITALIC: createFont( false ); mxFont->importDxfFlag( XML_i, rStrm ); break; + case OOBIN_DXF_FONT_STRIKE: createFont( false ); mxFont->importDxfFlag( XML_strike, rStrm ); break; + case OOBIN_DXF_FONT_OUTLINE: createFont( false ); mxFont->importDxfFlag( XML_outline, rStrm ); break; + case OOBIN_DXF_FONT_SHADOW: createFont( false ); mxFont->importDxfFlag( XML_shadow, rStrm ); break; + case OOBIN_DXF_FONT_HEIGHT: createFont( false ); mxFont->importDxfHeight( rStrm ); break; + case OOBIN_DXF_FONT_SCHEME: createFont( false ); mxFont->importDxfScheme( rStrm ); break; + case OOBIN_DXF_NUMFMT_CODE: aFmtCode = rStrm.readString( false ); break; + case OOBIN_DXF_NUMFMT_ID: nNumFmtId = rStrm.readuInt16(); break; + } + rStrm.seek( nRecEnd ); + } + OSL_ENSURE( rStrm.isValid() && (rStrm.getRecLeft() == 0), "Dxf::importDxf - unexpected remaining data" ); + mxNumFmt = getStyles().createNumFmt( nNumFmtId, aFmtCode ); +} + +void Dxf::importCfRule( BiffInputStream& rStrm, sal_uInt32 nFlags ) +{ + if( getFlag( nFlags, BIFF_CFRULE_FONTBLOCK ) ) + { + createFont( true ); + mxFont->importCfRule( rStrm ); + } + if( getFlag( nFlags, BIFF_CFRULE_ALIGNBLOCK ) ) + { + rStrm.skip( 8 ); + } + if( getFlag( nFlags, BIFF_CFRULE_BORDERBLOCK ) ) + { + createBorder( true ); + mxBorder->importCfRule( rStrm, nFlags ); + } + if( getFlag( nFlags, BIFF_CFRULE_FILLBLOCK ) ) + { + createFill( true ); + mxFill->importCfRule( rStrm, nFlags ); + } + if( getFlag( nFlags, BIFF_CFRULE_PROTBLOCK ) ) + { + rStrm.skip( 2 ); + } +} + +void Dxf::finalizeImport() +{ + if( mxFont.get() ) + mxFont->finalizeImport(); + // number format already finalized by the number formats buffer + if( mxAlignment.get() ) + mxAlignment->finalizeImport(); + if( mxProtection.get() ) + mxProtection->finalizeImport(); + if( mxBorder.get() ) + mxBorder->finalizeImport(); + if( mxFill.get() ) + mxFill->finalizeImport(); +} + +const OUString& Dxf::createDxfStyle( sal_Int32 nDxfId ) +{ + if( maFinalName.getLength() == 0 ) + { + maFinalName = OUStringBuffer( CREATE_OUSTRING( "ConditionalStyle_" ) ).append( nDxfId + 1 ).makeStringAndClear(); + Reference< XStyle > xStyle = createStyleObject( maFinalName, false ); + // write style formatting properties + PropertySet aPropSet( xStyle ); + if( mxFont.get() ) + mxFont->writeToPropertySet( aPropSet, FONT_PROPTYPE_CELL ); + if( mxNumFmt.get() ) + mxNumFmt->writeToPropertySet( aPropSet ); + if( mxAlignment.get() ) + mxAlignment->writeToPropertySet( aPropSet ); + if( mxProtection.get() ) + mxProtection->writeToPropertySet( aPropSet ); + if( mxBorder.get() ) + mxBorder->writeToPropertySet( aPropSet ); + if( mxFill.get() ) + mxFill->writeToPropertySet( aPropSet ); + } + return maFinalName; +} + +void Dxf::createFont( bool bAlwaysNew ) +{ + if( bAlwaysNew || !mxFont ) + mxFont.reset( new Font( *this, true ) ); +} + +void Dxf::createBorder( bool bAlwaysNew ) +{ + if( bAlwaysNew || !mxBorder ) + mxBorder.reset( new Border( *this, true ) ); +} + +void Dxf::createFill( bool bAlwaysNew ) +{ + if( bAlwaysNew || !mxFill ) + mxFill.reset( new Fill( *this, true ) ); +} + +// ============================================================================ + +namespace { + +const sal_Char* const spcLegacyStyleNamePrefix = "Excel_BuiltIn_"; +const sal_Char* const sppcLegacyStyleNames[] = +{ +#if OOX_XLS_USE_DEFAULT_STYLE + "", // use existing "Default" style +#else + "Normal", +#endif + "RowLevel_", // outline level will be appended + "ColumnLevel_", // outline level will be appended + "Comma", + "Currency", + "Percent", + "Comma_0", // new in BIFF4 + "Currency_0", + "Hyperlink", // new in BIFF8 + "Followed_Hyperlink" +}; +const sal_Int32 snLegacyStyleNamesCount = static_cast< sal_Int32 >( STATIC_ARRAY_SIZE( sppcLegacyStyleNames ) ); + +const sal_Char* const spcStyleNamePrefix = "Excel Built-in "; +const sal_Char* const sppcStyleNames[] = +{ +#if OOX_XLS_USE_DEFAULT_STYLE + "", // use existing "Default" style +#else + "Normal", +#endif + "RowLevel_", // outline level will be appended + "ColLevel_", // outline level will be appended + "Comma", + "Currency", + "Percent", + "Comma [0]", // new in BIFF4 + "Currency [0]", + "Hyperlink", // new in BIFF8 + "Followed Hyperlink", + "Note", // new in OOX + "Warning Text", + "", + "", + "", + "Title", + "Heading 1", + "Heading 2", + "Heading 3", + "Heading 4", + "Input", + "Output", + "Calculation", + "Check Cell", + "Linked Cell", + "Total", + "Good", + "Bad", + "Neutral", + "Accent1", + "20% - Accent1", + "40% - Accent1", + "60% - Accent1", + "Accent2", + "20% - Accent2", + "40% - Accent2", + "60% - Accent2", + "Accent3", + "20% - Accent3", + "40% - Accent3", + "60% - Accent3", + "Accent4", + "20% - Accent4", + "40% - Accent4", + "60% - Accent4", + "Accent5", + "20% - Accent5", + "40% - Accent5", + "60% - Accent5", + "Accent6", + "20% - Accent6", + "40% - Accent6", + "60% - Accent6", + "Explanatory Text" +}; +const sal_Int32 snStyleNamesCount = static_cast< sal_Int32 >( STATIC_ARRAY_SIZE( sppcStyleNames ) ); + +#if OOX_XLS_USE_DEFAULT_STYLE +const sal_Char* const spcDefaultStyleName = "Default"; +#endif + +OUString lclGetBuiltinStyleName( sal_Int32 nBuiltinId, const OUString& rName, sal_Int32 nLevel = 0 ) +{ + OUStringBuffer aStyleName; + OSL_ENSURE( (0 <= nBuiltinId) && (nBuiltinId < snStyleNamesCount), "lclGetBuiltinStyleName - unknown builtin style" ); +#if OOX_XLS_USE_DEFAULT_STYLE + if( nBuiltinId == OOX_STYLE_NORMAL ) // "Normal" becomes "Default" style + { + aStyleName.appendAscii( spcDefaultStyleName ); + } + else + { +#endif + aStyleName.appendAscii( spcStyleNamePrefix ); + if( (0 <= nBuiltinId) && (nBuiltinId < snStyleNamesCount) && (sppcStyleNames[ nBuiltinId ][ 0 ] != 0) ) + aStyleName.appendAscii( sppcStyleNames[ nBuiltinId ] ); + else if( rName.getLength() > 0 ) + aStyleName.append( rName ); + else + aStyleName.append( nBuiltinId ); + if( (nBuiltinId == OOX_STYLE_ROWLEVEL) || (nBuiltinId == OOX_STYLE_COLLEVEL) ) + aStyleName.append( nLevel ); +#if OOX_XLS_USE_DEFAULT_STYLE + } +#endif + return aStyleName.makeStringAndClear(); +} + +bool lclIsBuiltinStyleName( const OUString& rStyleName, sal_Int32* pnBuiltinId, sal_Int32* pnNextChar ) +{ +#if OOX_XLS_USE_DEFAULT_STYLE + // "Default" becomes "Normal" + if( rStyleName.equalsIgnoreAsciiCaseAscii( spcDefaultStyleName ) ) + { + if( pnBuiltinId ) *pnBuiltinId = OOX_STYLE_NORMAL; + if( pnNextChar ) *pnNextChar = rStyleName.getLength(); + return true; + } +#endif + + // try the other builtin styles + OUString aPrefix = OUString::createFromAscii( spcStyleNamePrefix ); + sal_Int32 nPrefixLen = aPrefix.getLength(); + sal_Int32 nFoundId = 0; + sal_Int32 nNextChar = 0; + if( rStyleName.matchIgnoreAsciiCase( aPrefix ) ) + { + OUString aShortName; + for( sal_Int32 nId = 0; nId < snStyleNamesCount; ++nId ) + { +#if OOX_XLS_USE_DEFAULT_STYLE + if( nId != OOX_STYLE_NORMAL ) + { +#endif + aShortName = OUString::createFromAscii( sppcStyleNames[ nId ] ); + if( rStyleName.matchIgnoreAsciiCase( aShortName, nPrefixLen ) && + (nNextChar < nPrefixLen + aShortName.getLength()) ) + { + nFoundId = nId; + nNextChar = nPrefixLen + aShortName.getLength(); + } +#if OOX_XLS_USE_DEFAULT_STYLE + } +#endif + } + } + + if( nNextChar > 0 ) + { + if( pnBuiltinId ) *pnBuiltinId = nFoundId; + if( pnNextChar ) *pnNextChar = nNextChar; + return true; + } + + if( pnBuiltinId ) *pnBuiltinId = -1; + if( pnNextChar ) *pnNextChar = 0; + return false; +} + +bool lclGetBuiltinStyleId( sal_Int32& rnBuiltinId, sal_Int32& rnLevel, const OUString& rStyleName ) +{ + sal_Int32 nBuiltinId; + sal_Int32 nNextChar; + if( lclIsBuiltinStyleName( rStyleName, &nBuiltinId, &nNextChar ) ) + { + if( (nBuiltinId == OOX_STYLE_ROWLEVEL) || (nBuiltinId == OOX_STYLE_COLLEVEL) ) + { + OUString aLevel = rStyleName.copy( nNextChar ); + sal_Int32 nLevel = aLevel.toInt32(); + if( (0 < nLevel) && (nLevel <= OOX_STYLE_LEVELCOUNT) ) + { + rnBuiltinId = nBuiltinId; + rnLevel = nLevel; + return true; + } + } + else if( rStyleName.getLength() == nNextChar ) + { + rnBuiltinId = nBuiltinId; + rnLevel = 0; + return true; + } + } + rnBuiltinId = -1; + rnLevel = 0; + return false; +} + +} // namespace + +// ---------------------------------------------------------------------------- + +OoxCellStyleData::OoxCellStyleData() : + mnXfId( -1 ), + mnBuiltinId( -1 ), + mnLevel( 0 ), + mbBuiltin( false ), + mbCustom( false ), + mbHidden( false ) +{ +} + +bool OoxCellStyleData::isDefaultStyle() const +{ + return mbBuiltin && (mnBuiltinId == OOX_STYLE_NORMAL); +} + +OUString OoxCellStyleData::createStyleName() const +{ + return isBuiltin() ? lclGetBuiltinStyleName( mnBuiltinId, maName, mnLevel ) : maName; +} + +// ============================================================================ + +CellStyle::CellStyle( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ) +{ +} + +void CellStyle::importCellStyle( const AttributeList& rAttribs ) +{ + maOoxData.maName = rAttribs.getString( XML_name ); + maOoxData.mnXfId = rAttribs.getInteger( XML_xfId, -1 ); + maOoxData.mnBuiltinId = rAttribs.getInteger( XML_builtinId, -1 ); + maOoxData.mnLevel = rAttribs.getInteger( XML_iLevel, 0 ); + maOoxData.mbBuiltin = rAttribs.hasAttribute( XML_builtinId ); + maOoxData.mbCustom = rAttribs.getBool( XML_customBuiltin, false ); + maOoxData.mbHidden = rAttribs.getBool( XML_hidden, false ); +} + +void CellStyle::importCellStyle( RecordInputStream& rStrm ) +{ + sal_uInt16 nFlags; + rStrm >> maOoxData.mnXfId >> nFlags; + maOoxData.mnBuiltinId = rStrm.readuInt8(); + maOoxData.mnLevel = rStrm.readuInt8(); + rStrm >> maOoxData.maName; + maOoxData.mbBuiltin = getFlag( nFlags, OOBIN_CELLSTYLE_BUILTIN ); + maOoxData.mbCustom = getFlag( nFlags, OOBIN_CELLSTYLE_CUSTOM ); + maOoxData.mbHidden = getFlag( nFlags, OOBIN_CELLSTYLE_HIDDEN ); +} + +void CellStyle::importStyle( BiffInputStream& rStrm ) +{ + sal_uInt16 nStyleXf; + rStrm >> nStyleXf; + maOoxData.mnXfId = static_cast< sal_Int32 >( nStyleXf & BIFF_STYLE_XFMASK ); + maOoxData.mbBuiltin = getFlag( nStyleXf, BIFF_STYLE_BUILTIN ); + if( maOoxData.mbBuiltin ) + { + maOoxData.mnBuiltinId = rStrm.readuInt8(); + maOoxData.mnLevel = rStrm.readuInt8(); + } + else + { + maOoxData.maName = (getBiff() == BIFF8) ? + rStrm.readUniString() : rStrm.readByteString( false, getTextEncoding() ); + } +} + +const OUString& CellStyle::createCellStyle( sal_Int32 nXfId, bool bSkipDefaultBuiltin ) +{ + if( maFinalName.getLength() == 0 ) + { + bool bBuiltin = maOoxData.isBuiltin(); + if( !bSkipDefaultBuiltin || !bBuiltin || maOoxData.mbCustom ) + { + // name of the style (generate unique name for builtin styles) + maFinalName = maOoxData.createStyleName(); + // #i1624# #i1768# ignore unnamed user styles + if( maFinalName.getLength() > 0 ) + { + Reference< XStyle > xStyle; +#if OOX_XLS_USE_DEFAULT_STYLE + // special handling for default style (do not create, but use existing) + if( isDefaultStyle() ) + { + /* Set all flags to true to have all properties in the style, + even if the used flags are not set (that's what Excel does). */ + if( Xf* pXf = getStyles().getStyleXf( nXfId ).get() ) + pXf->setAllUsedFlags( true ); + // use existing built-in style + xStyle = getStyleObject( maFinalName, false ); + } + else + { +#endif + /* Insert into cell styles collection, rename existing user styles, + if this is a built-in style, but do not do this in BIFF4 workspace + files, where built-in styles occur repeatedly. */ + bool bRenameExisting = bBuiltin && (getBiff() != BIFF4); + xStyle = createStyleObject( maFinalName, false, bRenameExisting ); +#if OOX_XLS_USE_DEFAULT_STYLE + } +#endif + + // write style formatting properties + PropertySet aPropSet( xStyle ); + getStyles().writeStyleXfToPropertySet( aPropSet, nXfId ); +#if OOX_XLS_USE_DEFAULT_STYLE +#else + if( !isDefaultStyle() && xStyle.is() ) + xStyle->setParentStyle( getStyles().getDefaultStyleName() ); +#endif + } + } + } + return maFinalName; +} + +// ============================================================================ + +namespace { + +sal_Int32 lclTintToColor( sal_Int32 nColor, double fTint ) +{ + if( nColor == 0x000000 ) + return 0x010101 * static_cast< sal_Int32 >( ::std::max( fTint, 0.0 ) * 255.0 ); + if( nColor == 0xFFFFFF ) + return 0x010101 * static_cast< sal_Int32 >( ::std::min( fTint + 1.0, 1.0 ) * 255.0 ); + + sal_Int32 nR = (nColor >> 16) & 0xFF; + sal_Int32 nG = (nColor >> 8) & 0xFF; + sal_Int32 nB = nColor & 0xFF; + + double fMean = (::std::min( ::std::min( nR, nG ), nB ) + ::std::max( ::std::max( nR, nG ), nB )) / 2.0; + double fTintTh = (fMean <= 127.5) ? ((127.5 - fMean) / (255.0 - fMean)) : (127.5 / fMean - 1.0); + if( (fTintTh < 0.0) || ((fTintTh == 0.0) && (fTint <= 0.0)) ) + { + double fTintMax = 255.0 / fMean - 1.0; + double fRTh = fTintTh / fTintMax * (255.0 - nR) + nR; + double fGTh = fTintTh / fTintMax * (255.0 - nG) + nG; + double fBTh = fTintTh / fTintMax * (255.0 - nB) + nB; + if( fTint <= fTintTh ) + { + double fFactor = (fTint + 1.0) / (fTintTh + 1.0); + nR = static_cast< sal_Int32 >( fFactor * fRTh + 0.5 ); + nG = static_cast< sal_Int32 >( fFactor * fGTh + 0.5 ); + nB = static_cast< sal_Int32 >( fFactor * fBTh + 0.5 ); + } + else + { + double fFactor = (fTint > 0.0) ? (fTint * fTintMax / fTintTh) : (fTint / fTintTh); + nR = static_cast< sal_Int32 >( fFactor * fRTh + (1.0 - fFactor) * nR + 0.5 ); + nG = static_cast< sal_Int32 >( fFactor * fGTh + (1.0 - fFactor) * nG + 0.5 ); + nB = static_cast< sal_Int32 >( fFactor * fBTh + (1.0 - fFactor) * nB + 0.5 ); + } + } + else + { + double fTintMin = fMean / (fMean - 255.0); + double fRTh = (1.0 - fTintTh / fTintMin) * nR; + double fGTh = (1.0 - fTintTh / fTintMin) * nG; + double fBTh = (1.0 - fTintTh / fTintMin) * nB; + if( fTint <= fTintTh ) + { + double fFactor = (fTint < 0.0) ? (fTint * -fTintMin / fTintTh) : (fTint / fTintTh); + nR = static_cast< sal_Int32 >( fFactor * fRTh + (1.0 - fFactor) * nR + 0.5 ); + nG = static_cast< sal_Int32 >( fFactor * fGTh + (1.0 - fFactor) * nG + 0.5 ); + nB = static_cast< sal_Int32 >( fFactor * fBTh + (1.0 - fFactor) * nB + 0.5 ); + } + else + { + double fFactor = (1.0 - fTint) / (1.0 - fTintTh); + nR = static_cast< sal_Int32 >( 255.5 - fFactor * (255.0 - fRTh) ); + nG = static_cast< sal_Int32 >( 255.5 - fFactor * (255.0 - fGTh) ); + nB = static_cast< sal_Int32 >( 255.5 - fFactor * (255.0 - fBTh) ); + } + } + + return (nR << 16) | (nG << 8) | nB; +} + +} // namespace + +// ---------------------------------------------------------------------------- + +StylesBuffer::StylesBuffer( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + maPalette( rHelper ), + maNumFmts( rHelper ), + maDefStyleName( lclGetBuiltinStyleName( OOX_STYLE_NORMAL, OUString() ) ), + mnDefStyleXf( -1 ) +{ +} + +FontRef StylesBuffer::createFont( sal_Int32* opnFontId ) +{ + if( opnFontId ) *opnFontId = static_cast< sal_Int32 >( maFonts.size() ); + FontRef xFont( new Font( *this, false ) ); + maFonts.push_back( xFont ); + return xFont; +} + +NumberFormatRef StylesBuffer::createNumFmt( sal_Int32 nNumFmtId, const OUString& rFmtCode ) +{ + return maNumFmts.createNumFmt( nNumFmtId, rFmtCode ); +} + +BorderRef StylesBuffer::createBorder( sal_Int32* opnBorderId ) +{ + if( opnBorderId ) *opnBorderId = static_cast< sal_Int32 >( maBorders.size() ); + BorderRef xBorder( new Border( *this, false ) ); + maBorders.push_back( xBorder ); + return xBorder; +} + +FillRef StylesBuffer::createFill( sal_Int32* opnFillId ) +{ + if( opnFillId ) *opnFillId = static_cast< sal_Int32 >( maFills.size() ); + FillRef xFill( new Fill( *this, false ) ); + maFills.push_back( xFill ); + return xFill; +} + +XfRef StylesBuffer::createCellXf( sal_Int32* opnXfId ) +{ + if( opnXfId ) *opnXfId = static_cast< sal_Int32 >( maCellXfs.size() ); + XfRef xXf( new Xf( *this ) ); + maCellXfs.push_back( xXf ); + return xXf; +} + +XfRef StylesBuffer::createStyleXf( sal_Int32* opnXfId ) +{ + if( opnXfId ) *opnXfId = static_cast< sal_Int32 >( maStyleXfs.size() ); + XfRef xXf( new Xf( *this ) ); + maStyleXfs.push_back( xXf ); + return xXf; +} + +DxfRef StylesBuffer::createDxf( sal_Int32* opnDxfId ) +{ + if( opnDxfId ) *opnDxfId = static_cast< sal_Int32 >( maDxfs.size() ); + DxfRef xDxf( new Dxf( *this ) ); + maDxfs.push_back( xDxf ); + return xDxf; +} + +void StylesBuffer::importPaletteColor( const AttributeList& rAttribs ) +{ + maPalette.importPaletteColor( rAttribs ); +} + +FontRef StylesBuffer::importFont( const AttributeList& ) +{ + return createFont(); +} + +NumberFormatRef StylesBuffer::importNumFmt( const AttributeList& rAttribs ) +{ + return maNumFmts.importNumFmt( rAttribs ); +} + +BorderRef StylesBuffer::importBorder( const AttributeList& rAttribs ) +{ + BorderRef xBorder = createBorder(); + xBorder->importBorder( rAttribs ); + return xBorder; +} + +FillRef StylesBuffer::importFill( const AttributeList& ) +{ + return createFill(); +} + +XfRef StylesBuffer::importXf( sal_Int32 nContext, const AttributeList& rAttribs ) +{ + XfRef xXf; + switch( nContext ) + { + case XLS_TOKEN( cellXfs ): + xXf = createCellXf(); + xXf->importXf( rAttribs, true ); + break; + case XLS_TOKEN( cellStyleXfs ): + xXf = createStyleXf(); + xXf->importXf( rAttribs, false ); + break; + } + return xXf; +} + +DxfRef StylesBuffer::importDxf( const AttributeList& ) +{ + return createDxf(); +} + +CellStyleRef StylesBuffer::importCellStyle( const AttributeList& rAttribs ) +{ + CellStyleRef xCellStyle( new CellStyle( *this ) ); + xCellStyle->importCellStyle( rAttribs ); + insertCellStyle( xCellStyle ); + return xCellStyle; +} + +void StylesBuffer::importPaletteColor( RecordInputStream& rStrm ) +{ + maPalette.importPaletteColor( rStrm ); +} + +void StylesBuffer::importFont( RecordInputStream& rStrm ) +{ + createFont()->importFont( rStrm ); +} + +void StylesBuffer::importNumFmt( RecordInputStream& rStrm ) +{ + maNumFmts.importNumFmt( rStrm ); +} + +void StylesBuffer::importBorder( RecordInputStream& rStrm ) +{ + createBorder()->importBorder( rStrm ); +} + +void StylesBuffer::importFill( RecordInputStream& rStrm ) +{ + createFill()->importFill( rStrm ); +} + +void StylesBuffer::importXf( sal_Int32 nContext, RecordInputStream& rStrm ) +{ + switch( nContext ) + { + case OOBIN_ID_CELLXFS: + createCellXf()->importXf( rStrm, true ); + break; + case OOBIN_ID_CELLSTYLEXFS: + createStyleXf()->importXf( rStrm, false ); + break; + } +} + +void StylesBuffer::importDxf( RecordInputStream& rStrm ) +{ + createDxf()->importDxf( rStrm ); +} + +void StylesBuffer::importCellStyle( RecordInputStream& rStrm ) +{ + CellStyleRef xCellStyle( new CellStyle( *this ) ); + xCellStyle->importCellStyle( rStrm ); + insertCellStyle( xCellStyle ); +} + +void StylesBuffer::importPalette( BiffInputStream& rStrm ) +{ + maPalette.importPalette( rStrm ); +} + +void StylesBuffer::importFont( BiffInputStream& rStrm ) +{ + /* Font with index 4 is not stored in BIFF. This means effectively, first + font in the BIFF file has index 0, fourth font has index 3, and fifth + font has index 5. Insert a dummy font to correctly map passed font + identifiers. */ + if( maFonts.size() == 4 ) + maFonts.push_back( maFonts.front() ); + + FontRef xFont = createFont(); + xFont->importFont( rStrm ); + + /* #i71033# Set stream text encoding from application font, if CODEPAGE + record is missing. Must be done now (not while finalizeImport() runs), + to be able to read all following byte strings correctly (e.g. cell + style names). */ + if( maFonts.size() == 1 ) + setAppFontEncoding( xFont->getFontEncoding() ); +} + +void StylesBuffer::importFontColor( BiffInputStream& rStrm ) +{ + if( !maFonts.empty() ) + maFonts.back()->importFontColor( rStrm ); +} + +void StylesBuffer::importFormat( BiffInputStream& rStrm ) +{ + maNumFmts.importFormat( rStrm ); +} + +void StylesBuffer::importXf( BiffInputStream& rStrm ) +{ + XfRef xXf( new Xf( *this ) ); + // store XF in both lists (except BIFF2 which does not support cell styles) + maCellXfs.push_back( xXf ); + if( getBiff() != BIFF2 ) + maStyleXfs.push_back( xXf ); + xXf->importXf( rStrm ); +} + +void StylesBuffer::importStyle( BiffInputStream& rStrm ) +{ + CellStyleRef xCellStyle( new CellStyle( *this ) ); + xCellStyle->importStyle( rStrm ); + insertCellStyle( xCellStyle ); +} + +void StylesBuffer::finalizeImport() +{ + // fonts first, are needed to finalize unit converter and XFs below + maFonts.forEachMem( &Font::finalizeImport ); + // finalize unit converter after default font is known + getUnitConverter().finalizeImport(); + // number formats + maNumFmts.finalizeImport(); + // borders and fills + maBorders.forEachMem( &Border::finalizeImport ); + maFills.forEachMem( &Fill::finalizeImport ); + + /* Style XFs and cell XFs. The BIFF format stores cell XFs and style XFs + mixed in a single list. The import filter has stored the XFs in both + lists to make the getStyleXf() function working correctly (e.g. for + retrieving the default font, see getDefaultFont() function), except for + BIFF2 which does not support cell styles at all. Therefore, if in BIFF + filter mode, we do not need to finalize the cell styles list. */ + if( getFilterType() == FILTER_OOX ) + maStyleXfs.forEachMem( &Xf::finalizeImport ); + maCellXfs.forEachMem( &Xf::finalizeImport ); + + // conditional formatting + maDxfs.forEachMem( &Dxf::finalizeImport ); + + // create the default cell style first + if( CellStyle* pDefStyle = maCellStyles.get( mnDefStyleXf ).get() ) + pDefStyle->createCellStyle( mnDefStyleXf ); + /* Create user-defined and modified builtin cell styles, passing true to + createStyleSheet() skips unchanged builtin styles. */ + for( CellStyleMap::iterator aIt = maCellStyles.begin(), aEnd = maCellStyles.end(); aIt != aEnd; ++aIt ) + aIt->second->createCellStyle( aIt->first, true ); +} + +sal_Int32 StylesBuffer::getColor( const OoxColor& rColor, sal_Int32 nAuto ) const +{ + sal_Int32 nColor = API_RGB_TRANSPARENT; + switch( rColor.mnType ) + { + case XML_auto: + nColor = nAuto; + break; + case XML_rgb: + nColor = rColor.mnValue & 0xFFFFFF; + break; + case XML_theme: + nColor = getTheme().getColorByIndex( rColor.mnValue ); + break; + case XML_indexed: + nColor = maPalette.getColor( rColor.mnValue ); + break; + default: + OSL_ENSURE( false, "StylesBuffer::getColor - unknown color type" ); + } + if( (rColor.mnType != XML_auto) && (nColor != API_RGB_TRANSPARENT) && (rColor.mfTint >= -1.0) && (rColor.mfTint != 0.0) && (rColor.mfTint <= 1.0) ) + nColor = lclTintToColor( nColor, rColor.mfTint ); + return nColor; +} + +FontRef StylesBuffer::getFont( sal_Int32 nFontId ) const +{ + return maFonts.get( nFontId ); +} + +XfRef StylesBuffer::getCellXf( sal_Int32 nXfId ) const +{ + return maCellXfs.get( nXfId ); +} + +XfRef StylesBuffer::getStyleXf( sal_Int32 nXfId ) const +{ + return maStyleXfs.get( nXfId ); +} + +DxfRef StylesBuffer::getDxf( sal_Int32 nDxfId ) const +{ + return maDxfs.get( nDxfId ); +} + +FontRef StylesBuffer::getFontFromCellXf( sal_Int32 nXfId ) const +{ + FontRef xFont; + if( const Xf* pXf = getCellXf( nXfId ).get() ) + xFont = pXf->getFont(); + return xFont; +} + +FontRef StylesBuffer::getDefaultFont() const +{ + FontRef xDefFont; + if( const Xf* pXf = getStyleXf( mnDefStyleXf ).get() ) + xDefFont = pXf->getFont(); + // no font from styles - try first loaded font (e.g. BIFF2) + if( !xDefFont ) + xDefFont = maFonts.get( 0 ); + OSL_ENSURE( xDefFont.get(), "StylesBuffer::getDefaultFont - no default font found" ); + return xDefFont; +} + +const OoxFontData& StylesBuffer::getDefaultFontData() const +{ + FontRef xDefFont = getDefaultFont(); + return xDefFont.get() ? xDefFont->getFontData() : getTheme().getDefaultFontData(); +} + +const OUString& StylesBuffer::createCellStyle( sal_Int32 nXfId ) const +{ + if( CellStyle* pCellStyle = maCellStyles.get( nXfId ).get() ) + return pCellStyle->createCellStyle( nXfId ); + // on error: fallback to default style + return maDefStyleName; +} + +const OUString& StylesBuffer::createDxfStyle( sal_Int32 nDxfId ) const +{ + if( Dxf* pDxf = maDxfs.get( nDxfId ).get() ) + return pDxf->createDxfStyle( nDxfId ); + // on error: fallback to default style + return maDefStyleName; +} + +#if OOX_XLS_USE_DEFAULT_STYLE +#else +const OUString& StylesBuffer::getDefaultStyleName() const +{ + return createCellStyle( mnDefStyleXf ); +} +#endif + +void StylesBuffer::writeFontToPropertySet( PropertySet& rPropSet, sal_Int32 nFontId ) const +{ + if( Font* pFont = maFonts.get( nFontId ).get() ) + pFont->writeToPropertySet( rPropSet, FONT_PROPTYPE_CELL ); +} + +void StylesBuffer::writeNumFmtToPropertySet( PropertySet& rPropSet, sal_Int32 nNumFmtId ) const +{ + maNumFmts.writeToPropertySet( rPropSet, nNumFmtId ); +} + +void StylesBuffer::writeBorderToPropertySet( PropertySet& rPropSet, sal_Int32 nBorderId ) const +{ + if( Border* pBorder = maBorders.get( nBorderId ).get() ) + pBorder->writeToPropertySet( rPropSet ); +} + +void StylesBuffer::writeFillToPropertySet( PropertySet& rPropSet, sal_Int32 nFillId ) const +{ + if( Fill* pFill = maFills.get( nFillId ).get() ) + pFill->writeToPropertySet( rPropSet ); +} + +void StylesBuffer::writeCellXfToPropertySet( PropertySet& rPropSet, sal_Int32 nXfId ) const +{ + if( Xf* pXf = maCellXfs.get( nXfId ).get() ) + pXf->writeToPropertySet( rPropSet ); +} + +void StylesBuffer::writeStyleXfToPropertySet( PropertySet& rPropSet, sal_Int32 nXfId ) const +{ + if( Xf* pXf = maStyleXfs.get( nXfId ).get() ) + pXf->writeToPropertySet( rPropSet ); +} + +void StylesBuffer::insertCellStyle( CellStyleRef xCellStyle ) +{ + if( xCellStyle->getXfId() >= 0 ) + { + maCellStyles[ xCellStyle->getXfId() ] = xCellStyle; + if( xCellStyle->isDefaultStyle() ) + mnDefStyleXf = xCellStyle->getXfId(); + } +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/stylesfragment.cxx b/oox/source/xls/stylesfragment.cxx new file mode 100644 index 000000000000..0ef9400dcbec --- /dev/null +++ b/oox/source/xls/stylesfragment.cxx @@ -0,0 +1,316 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: stylesfragment.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/stylesfragment.hxx" +#include "oox/helper/attributelist.hxx" + +using ::rtl::OUString; + +namespace oox { +namespace xls { + +// ============================================================================ + +OoxStylesFragment::OoxStylesFragment( + const WorkbookHelper& rHelper, const OUString& rFragmentPath ) : + OoxWorkbookFragmentBase( rHelper, rFragmentPath ), + mfGradPos( -1.0 ) +{ +} + +// oox.xls.OoxContextHelper interface ----------------------------------------- + +bool OoxStylesFragment::onCanCreateContext( sal_Int32 nElement ) const +{ + sal_Int32 nCurrContext = getCurrentContext(); + switch( nCurrContext ) + { + case XML_ROOT_CONTEXT: + return (nElement == XLS_TOKEN( styleSheet )); + case XLS_TOKEN( styleSheet ): + return (nElement == XLS_TOKEN( colors )) || + (nElement == XLS_TOKEN( fonts )) || + (nElement == XLS_TOKEN( numFmts )) || + (nElement == XLS_TOKEN( borders )) || + (nElement == XLS_TOKEN( fills )) || + (nElement == XLS_TOKEN( cellXfs )) || + (nElement == XLS_TOKEN( cellStyleXfs )) || + (nElement == XLS_TOKEN( dxfs )) || + (nElement == XLS_TOKEN( cellStyles )); + + case XLS_TOKEN( colors ): + return (nElement == XLS_TOKEN( indexedColors )); + case XLS_TOKEN( indexedColors ): + return (nElement == XLS_TOKEN( rgbColor )); + + case XLS_TOKEN( fonts ): + return (nElement == XLS_TOKEN( font )); + case XLS_TOKEN( font ): + return mxFont.get() && Font::isSupportedContext( nElement, nCurrContext ); + + case XLS_TOKEN( numFmts ): + return (nElement == XLS_TOKEN( numFmt )); + + case XLS_TOKEN( borders ): + return (nElement == XLS_TOKEN( border )); + case XLS_TOKEN( border ): + case XLS_TOKEN( left ): + case XLS_TOKEN( right ): + case XLS_TOKEN( top ): + case XLS_TOKEN( bottom ): + case XLS_TOKEN( diagonal ): + return mxBorder.get() && Border::isSupportedContext( nElement, nCurrContext ); + + case XLS_TOKEN( fills ): + return (nElement == XLS_TOKEN( fill )); + case XLS_TOKEN( fill ): + case XLS_TOKEN( patternFill ): + case XLS_TOKEN( gradientFill ): + case XLS_TOKEN( stop ): + return mxFill.get() && Fill::isSupportedContext( nElement, nCurrContext ); + + case XLS_TOKEN( cellStyleXfs ): + case XLS_TOKEN( cellXfs ): + return (nElement == XLS_TOKEN( xf )); + case XLS_TOKEN( xf ): + return mxXf.get() && + ((nElement == XLS_TOKEN( alignment )) || + (nElement == XLS_TOKEN( protection ))); + + case XLS_TOKEN( dxfs ): + return (nElement == XLS_TOKEN( dxf )); + case XLS_TOKEN( dxf ): + return mxDxf.get() && + ((nElement == XLS_TOKEN( font )) || + (nElement == XLS_TOKEN( numFmt )) || + (nElement == XLS_TOKEN( alignment )) || + (nElement == XLS_TOKEN( protection )) || + (nElement == XLS_TOKEN( border )) || + (nElement == XLS_TOKEN( fill ))); + + case XLS_TOKEN( cellStyles ): + return (nElement == XLS_TOKEN( cellStyle )); + } + return false; +} + +void OoxStylesFragment::onStartElement( const AttributeList& rAttribs ) +{ + sal_Int32 nCurrContext = getCurrentContext(); + sal_Int32 nPrevContext = getPreviousContext(); + + switch( nCurrContext ) + { + case XLS_TOKEN( color ): + switch( nPrevContext ) + { + case XLS_TOKEN( font ): + OSL_ENSURE( mxFont.get(), "OoxStylesFragment::onStartElement - missing font object" ); + mxFont->importAttribs( nCurrContext, rAttribs ); + break; + case XLS_TOKEN( stop ): + OSL_ENSURE( mxFill.get(), "OoxStylesFragment::onStartElement - missing fill object" ); + mxFill->importColor( rAttribs, mfGradPos ); + break; + default: + OSL_ENSURE( mxBorder.get(), "OoxStylesFragment::onStartElement - missing border object" ); + mxBorder->importColor( nPrevContext, rAttribs ); + } + break; + case XLS_TOKEN( rgbColor ): + getStyles().importPaletteColor( rAttribs ); + break; + + case XLS_TOKEN( font ): + mxFont = mxDxf.get() ? mxDxf->importFont( rAttribs ) : getStyles().importFont( rAttribs ); + break; + + case XLS_TOKEN( numFmt ): + if( mxDxf.get() ) + mxDxf->importNumFmt( rAttribs ); + else + getStyles().importNumFmt( rAttribs ); + break; + + case XLS_TOKEN( alignment ): + OSL_ENSURE( mxXf.get() || mxDxf.get(), "OoxStylesFragment::onStartElement - missing formatting object" ); + if( mxXf.get() ) + mxXf->importAlignment( rAttribs ); +#if 0 + else if( mxDxf.get() ) + mxDxf->importAlignment( rAttribs ); +#endif + break; + + case XLS_TOKEN( protection ): + OSL_ENSURE( mxXf.get() || mxDxf.get(), "OoxStylesFragment::onStartElement - missing formatting object" ); + if( mxXf.get() ) + mxXf->importProtection( rAttribs ); +#if 0 + else if( mxDxf.get() ) + mxDxf->importProtection( rAttribs ); +#endif + break; + + case XLS_TOKEN( border ): + mxBorder = mxDxf.get() ? mxDxf->importBorder( rAttribs ) : getStyles().importBorder( rAttribs ); + break; + + case XLS_TOKEN( fill ): + mxFill = mxDxf.get() ? mxDxf->importFill( rAttribs ) : getStyles().importFill( rAttribs ); + break; + case XLS_TOKEN( patternFill ): + OSL_ENSURE( mxFill.get(), "OoxStylesFragment::onStartElement - missing fill object" ); + mxFill->importPatternFill( rAttribs ); + break; + case XLS_TOKEN( fgColor ): + OSL_ENSURE( mxFill.get(), "OoxStylesFragment::onStartElement - missing fill object" ); + mxFill->importFgColor( rAttribs ); + break; + case XLS_TOKEN( bgColor ): + OSL_ENSURE( mxFill.get(), "OoxStylesFragment::onStartElement - missing fill object" ); + mxFill->importBgColor( rAttribs ); + break; + case XLS_TOKEN( gradientFill ): + OSL_ENSURE( mxFill.get(), "OoxStylesFragment::onStartElement - missing fill object" ); + mxFill->importGradientFill( rAttribs ); + break; + case XLS_TOKEN( stop ): + mfGradPos = rAttribs.getDouble( XML_position, -1.0 ); + break; + + case XLS_TOKEN( xf ): + mxXf = getStyles().importXf( nPrevContext, rAttribs ); + break; + case XLS_TOKEN( dxf ): + mxDxf = getStyles().importDxf( rAttribs ); + break; + + case XLS_TOKEN( cellStyle ): + getStyles().importCellStyle( rAttribs ); + break; + + default: switch( nPrevContext ) + { + case XLS_TOKEN( font ): + OSL_ENSURE( mxFont.get(), "OoxStylesFragment::onStartElement - missing font object" ); + mxFont->importAttribs( nCurrContext, rAttribs ); + break; + case XLS_TOKEN( border ): + OSL_ENSURE( mxBorder.get(), "OoxStylesFragment::onStartElement - missing border object" ); + mxBorder->importStyle( nCurrContext, rAttribs ); + break; + } + } +} + +void OoxStylesFragment::onEndElement( const OUString& /*rChars*/ ) +{ + switch( getCurrentContext() ) + { + case XLS_TOKEN( font ): mxFont.reset(); break; + case XLS_TOKEN( border ): mxBorder.reset(); break; + case XLS_TOKEN( fill ): mxFill.reset(); break; + case XLS_TOKEN( xf ): mxXf.reset(); break; + case XLS_TOKEN( dxf ): mxDxf.reset(); break; + } +} + +bool OoxStylesFragment::onCanCreateRecordContext( sal_Int32 nRecId ) +{ + switch( getCurrentContext() ) + { + case XML_ROOT_CONTEXT: + return (nRecId == OOBIN_ID_STYLESHEET); + case OOBIN_ID_STYLESHEET: + return (nRecId == OOBIN_ID_COLORS) || + (nRecId == OOBIN_ID_FONTS) || + (nRecId == OOBIN_ID_NUMFMTS) || + (nRecId == OOBIN_ID_BORDERS) || + (nRecId == OOBIN_ID_FILLS) || + (nRecId == OOBIN_ID_CELLSTYLEXFS) || + (nRecId == OOBIN_ID_CELLXFS) || + (nRecId == OOBIN_ID_DXFS) || + (nRecId == OOBIN_ID_CELLSTYLES); + case OOBIN_ID_COLORS: + return (nRecId == OOBIN_ID_INDEXEDCOLORS); + case OOBIN_ID_INDEXEDCOLORS: + return (nRecId == OOBIN_ID_RGBCOLOR); + case OOBIN_ID_FONTS: + return (nRecId == OOBIN_ID_FONT); + case OOBIN_ID_NUMFMTS: + return (nRecId == OOBIN_ID_NUMFMT); + case OOBIN_ID_BORDERS: + return (nRecId == OOBIN_ID_BORDER); + case OOBIN_ID_FILLS: + return (nRecId == OOBIN_ID_FILL); + case OOBIN_ID_CELLSTYLEXFS: + case OOBIN_ID_CELLXFS: + return (nRecId == OOBIN_ID_XF); + case OOBIN_ID_DXFS: + return (nRecId == OOBIN_ID_DXF); + case OOBIN_ID_CELLSTYLES: + return (nRecId == OOBIN_ID_CELLSTYLE); + } + return false; +} + +void OoxStylesFragment::onStartRecord( RecordInputStream& rStrm ) +{ + switch( getCurrentContext() ) + { + case OOBIN_ID_RGBCOLOR: getStyles().importPaletteColor( rStrm ); break; + case OOBIN_ID_FONT: getStyles().importFont( rStrm ); break; + case OOBIN_ID_NUMFMT: getStyles().importNumFmt( rStrm ); break; + case OOBIN_ID_BORDER: getStyles().importBorder( rStrm ); break; + case OOBIN_ID_FILL: getStyles().importFill( rStrm ); break; + case OOBIN_ID_XF: getStyles().importXf( getPreviousContext(), rStrm ); break; + case OOBIN_ID_DXF: getStyles().importDxf( rStrm ); break; + case OOBIN_ID_CELLSTYLE: getStyles().importCellStyle( rStrm ); break; + } +} + +// oox.xls.OoxFragmentHandler interface --------------------------------------- + +void OoxStylesFragment::finalizeImport() +{ + getStyles().finalizeImport(); +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/stylespropertyhelper.cxx b/oox/source/xls/stylespropertyhelper.cxx new file mode 100644 index 000000000000..91a8099de426 --- /dev/null +++ b/oox/source/xls/stylespropertyhelper.cxx @@ -0,0 +1,386 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: stylespropertyhelper.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/stylespropertyhelper.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include "oox/helper/propertyset.hxx" +#include "oox/xls/stylesbuffer.hxx" + +using ::rtl::OUString; + +namespace oox { +namespace xls { + +// ============================================================================ + +ApiFontUsedFlags::ApiFontUsedFlags( bool bAllUsed ) : + mbNameUsed( bAllUsed ), + mbColorUsed( bAllUsed ), + mbSchemeUsed( bAllUsed ), + mbHeightUsed( bAllUsed ), + mbUnderlineUsed( bAllUsed ), + mbEscapementUsed( bAllUsed ), + mbWeightUsed( bAllUsed ), + mbPostureUsed( bAllUsed ), + mbStrikeoutUsed( bAllUsed ), + mbOutlineUsed( bAllUsed ), + mbShadowUsed( bAllUsed ) +{ +} + +// ---------------------------------------------------------------------------- + +ApiFontData::ApiFontData() : + maDesc( + CREATE_OUSTRING( "Calibri" ), + 220, // height 11 points + 0, + OUString(), + ::com::sun::star::awt::FontFamily::DONTKNOW, + RTL_TEXTENCODING_DONTKNOW, + ::com::sun::star::awt::FontPitch::DONTKNOW, + 100.0, + ::com::sun::star::awt::FontWeight::NORMAL, + ::com::sun::star::awt::FontSlant_NONE, + ::com::sun::star::awt::FontUnderline::NONE, + ::com::sun::star::awt::FontStrikeout::NONE, + 0.0, + sal_False, + sal_False, + ::com::sun::star::awt::FontType::DONTKNOW ), + mnColor( API_RGB_TRANSPARENT ), + mnEscapement( API_ESCAPE_NONE ), + mnEscapeHeight( API_ESCAPEHEIGHT_NONE ), + mbOutline( false ), + mbShadow( false ), + mbHasWstrn( true ), + mbHasAsian( false ) +{ +} + +// ============================================================================ + +ApiNumFmtData::ApiNumFmtData() : + mnIndex( 0 ) +{ +} + +// ============================================================================ + +ApiAlignmentData::ApiAlignmentData() : + meHorJustify( ::com::sun::star::table::CellHoriJustify_STANDARD ), + meVerJustify( ::com::sun::star::table::CellVertJustify_STANDARD ), + meOrientation( ::com::sun::star::table::CellOrientation_STANDARD ), + mnRotation( 0 ), + mnWritingMode( ::com::sun::star::text::WritingMode2::PAGE ), + mnIndent( 0 ), + mbWrapText( false ), + mbShrink( false ) +{ +} + +bool operator==( const ApiAlignmentData& rLeft, const ApiAlignmentData& rRight ) +{ + return + (rLeft.meHorJustify == rRight.meHorJustify) && + (rLeft.meVerJustify == rRight.meVerJustify) && + (rLeft.meOrientation == rRight.meOrientation) && + (rLeft.mnRotation == rRight.mnRotation) && + (rLeft.mnWritingMode == rRight.mnWritingMode) && + (rLeft.mnIndent == rRight.mnIndent) && + (rLeft.mbWrapText == rRight.mbWrapText) && + (rLeft.mbShrink == rRight.mbShrink); +} + +// ============================================================================ + +ApiProtectionData::ApiProtectionData() : + maCellProt( sal_True, sal_False, sal_False, sal_False ) +{ +} + +bool operator==( const ApiProtectionData& rLeft, const ApiProtectionData& rRight ) +{ + return + (rLeft.maCellProt.IsLocked == rRight.maCellProt.IsLocked) && + (rLeft.maCellProt.IsFormulaHidden == rRight.maCellProt.IsFormulaHidden) && + (rLeft.maCellProt.IsHidden == rRight.maCellProt.IsHidden) && + (rLeft.maCellProt.IsPrintHidden == rRight.maCellProt.IsPrintHidden); +} + +// ============================================================================ + +ApiBorderData::ApiBorderData() : + mbBorderUsed( false ), + mbDiagUsed( false ) +{ +} + +// ============================================================================ + +ApiSolidFillData::ApiSolidFillData() : + mnColor( API_RGB_TRANSPARENT ), + mbTransparent( true ), + mbUsed( false ) +{ +} + +// ============================================================================ + +namespace { + +/** Property names for Western font name settings. */ +const sal_Char* const sppcWstrnFontNameNames[] = +{ + "CharFontName", + "CharFontFamily", + "CharFontCharSet", + 0 +}; + +/** Property names for Asian font name settings. */ +const sal_Char* const sppcAsianFontNameNames[] = +{ + "CharFontNameAsian", + "CharFontFamilyAsian", + "CharFontCharSetAsian", + 0 +}; + +/** Property names for Complex font name settings. */ +const sal_Char* const sppcCmplxFontNameNames[] = +{ + "CharFontNameComplex", + "CharFontFamilyComplex", + "CharFontCharSetComplex", + 0 +}; + +/** Property names for font height settings. */ +const sal_Char* const sppcFontHeightNames[] = +{ + "CharHeight", + "CharHeightAsian", + "CharHeightComplex", + 0 +}; + +/** Property names for font weight settings. */ +const sal_Char* const sppcFontWeightNames[] = +{ + "CharWeight", + "CharWeightAsian", + "CharWeightComplex", + 0 +}; + +/** Property names for font posture settings. */ +const sal_Char* const sppcFontPostureNames[] = +{ + "CharPosture", + "CharPostureAsian", + "CharPostureComplex", + 0 +}; + +/** Property names for font escapement settings. */ +const sal_Char* const sppcFontEscapeNames[] = +{ + "CharEscapement", + "CharEscapementHeight", + 0 +}; + +/** Property names for alignment. */ +const sal_Char* const sppcAlignmentNames[] = +{ + "HoriJustify", + "VertJustify", + "WritingMode", + "RotateAngle", + "RotateReference", + "Orientation", + "ParaIndent", + "IsTextWrapped", + "ShrinkToFit", + 0 +}; + +/** Property names for diagonal cell borders. */ +const sal_Char* const sppcDiagBorderNames[] = +{ + "DiagonalTLBR", + "DiagonalBLTR", + 0 +}; + +/** Property names for cell fill. */ +const sal_Char* const sppcSolidFillNames[] = +{ + "CellBackColor", + "IsCellBackgroundTransparent", + 0 +}; + +} // namespace + +// ---------------------------------------------------------------------------- + +StylesPropertyHelper::StylesPropertyHelper( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + maWstrnFontNameProps( sppcWstrnFontNameNames ), + maAsianFontNameProps( sppcAsianFontNameNames ), + maCmplxFontNameProps( sppcCmplxFontNameNames ), + maFontHeightProps( sppcFontHeightNames ), + maFontWeightProps( sppcFontWeightNames ), + maFontPostureProps( sppcFontPostureNames ), + maFontEscapeProps( sppcFontEscapeNames ), + maAlignProps( sppcAlignmentNames ), + maDiagBorderProps( sppcDiagBorderNames ), + maSolidFillProps( sppcSolidFillNames ), + maCharColorProp( CREATE_OUSTRING( "CharColor" ) ), + maCharUnderlineProp( CREATE_OUSTRING( "CharUnderline" ) ), + maCharStrikeoutProp( CREATE_OUSTRING( "CharStrikeout" ) ), + maCharContouredProp( CREATE_OUSTRING( "CharContoured" ) ), + maCharShadowedProp( CREATE_OUSTRING( "CharShadowed" ) ), + maNumFmtProp( CREATE_OUSTRING( "NumberFormat" ) ), + maCellProtProp( CREATE_OUSTRING( "CellProtection" ) ), + maBorderProp( CREATE_OUSTRING( "TableBorder" ) ) +{ +} + +void StylesPropertyHelper::writeFontProperties( PropertySet& rPropSet, + const ApiFontData& rFontData, const ApiFontUsedFlags& rUsedFlags, FontPropertyType ePropType ) +{ + // font name properties + if( rUsedFlags.mbNameUsed ) + { + if( rFontData.mbHasWstrn ) + maWstrnFontNameProps << rFontData.maDesc.Name << rFontData.maDesc.Family << rFontData.maDesc.CharSet >> rPropSet; + if( rFontData.mbHasAsian ) + maAsianFontNameProps << rFontData.maDesc.Name << rFontData.maDesc.Family << rFontData.maDesc.CharSet >> rPropSet; + if( rFontData.mbHasCmplx ) + maCmplxFontNameProps << rFontData.maDesc.Name << rFontData.maDesc.Family << rFontData.maDesc.CharSet >> rPropSet; + } + // font height + if( rUsedFlags.mbHeightUsed ) + { + float fHeight = static_cast< float >( rFontData.maDesc.Height / 20.0 ); // twips to points + maFontHeightProps << fHeight << fHeight << fHeight >> rPropSet; + } + // font weight + if( rUsedFlags.mbWeightUsed ) + { + float fWeight = rFontData.maDesc.Weight; + maFontWeightProps << fWeight << fWeight << fWeight >> rPropSet; + } + // font posture + if( rUsedFlags.mbPostureUsed ) + maFontPostureProps << rFontData.maDesc.Slant << rFontData.maDesc.Slant << rFontData.maDesc.Slant >> rPropSet; + // character color + if( rUsedFlags.mbColorUsed ) + rPropSet.setProperty( maCharColorProp, rFontData.mnColor ); + // underline style + if( rUsedFlags.mbUnderlineUsed ) + rPropSet.setProperty( maCharUnderlineProp, rFontData.maDesc.Underline ); + // strike out style + if( rUsedFlags.mbStrikeoutUsed ) + rPropSet.setProperty( maCharStrikeoutProp, rFontData.maDesc.Strikeout ); + // outline style + if( rUsedFlags.mbOutlineUsed ) + rPropSet.setProperty( maCharContouredProp, rFontData.mbOutline ); + // shadow style + if( rUsedFlags.mbShadowUsed ) + rPropSet.setProperty( maCharShadowedProp, rFontData.mbShadow ); + // escapement + if( rUsedFlags.mbEscapementUsed && (ePropType == FONT_PROPTYPE_RICHTEXT) ) + maFontEscapeProps << rFontData.mnEscapement << rFontData.mnEscapeHeight >> rPropSet; +} + +void StylesPropertyHelper::writeNumFmtProperties( + PropertySet& rPropSet, const ApiNumFmtData& rNumFmtData ) +{ + rPropSet.setProperty( maNumFmtProp, rNumFmtData.mnIndex ); +} + +void StylesPropertyHelper::writeAlignmentProperties( + PropertySet& rPropSet, const ApiAlignmentData& rAlignData ) +{ + maAlignProps + << rAlignData.meHorJustify + << rAlignData.meVerJustify + << rAlignData.mnWritingMode + << rAlignData.mnRotation + << ::com::sun::star::table::CellVertJustify_STANDARD // rotation reference + << rAlignData.meOrientation + << rAlignData.mnIndent + << rAlignData.mbWrapText + << rAlignData.mbShrink + >> rPropSet; +} + +void StylesPropertyHelper::writeProtectionProperties( + PropertySet& rPropSet, const ApiProtectionData& rProtData ) +{ + rPropSet.setProperty( maCellProtProp, rProtData.maCellProt ); +} + +void StylesPropertyHelper::writeBorderProperties( + PropertySet& rPropSet, const ApiBorderData& rBorderData ) +{ + if( rBorderData.mbBorderUsed ) + rPropSet.setProperty( maBorderProp, rBorderData.maBorder ); + if( rBorderData.mbDiagUsed ) + maDiagBorderProps << rBorderData.maTLtoBR << rBorderData.maBLtoTR >> rPropSet; +} + +void StylesPropertyHelper::writeSolidFillProperties( + PropertySet& rPropSet, const ApiSolidFillData& rFillData ) +{ + if( rFillData.mbUsed ) + maSolidFillProps << rFillData.mnColor << rFillData.mbTransparent >> rPropSet; +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/tablebuffer.cxx b/oox/source/xls/tablebuffer.cxx new file mode 100644 index 000000000000..5865422f62e5 --- /dev/null +++ b/oox/source/xls/tablebuffer.cxx @@ -0,0 +1,172 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tablebuffer.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/tablebuffer.hxx" +#include +#include +#include "oox/helper/attributelist.hxx" +#include "oox/helper/containerhelper.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/helper/recordinputstream.hxx" +#include "oox/xls/addressconverter.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::container::XNameAccess; +using ::com::sun::star::sheet::XDatabaseRanges; +using ::com::sun::star::sheet::XDatabaseRange; + +namespace oox { +namespace xls { + +// ============================================================================ + +OoxTableData::OoxTableData() : + mnId( -1 ), + mnType( XML_worksheet ), + mnHeaderRows( 1 ), + mnTotalsRows( 0 ) +{ +} + +// ============================================================================ + +Table::Table( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + mnTokenIndex( -1 ) +{ +} + +void Table::importTable( const AttributeList& rAttribs, sal_Int16 nSheet ) +{ + if( getAddressConverter().convertToCellRange( maOoxData.maRange, rAttribs.getString( XML_ref ), nSheet, true ) ) + { + maOoxData.maProgName = rAttribs.getString( XML_name ); + maOoxData.maDisplayName = rAttribs.getString( XML_displayName ); + maOoxData.mnId = rAttribs.getInteger( XML_id, -1 ); + maOoxData.mnType = rAttribs.getToken( XML_tableType, XML_worksheet ); + maOoxData.mnHeaderRows = rAttribs.getInteger( XML_headerRowCount, 1 ); + maOoxData.mnTotalsRows = rAttribs.getInteger( XML_totalsRowCount, 0 ); + } +} + +void Table::importTable( RecordInputStream& rStrm, sal_Int16 nSheet ) +{ + BinRange aBinRange; + rStrm >> aBinRange; + if( getAddressConverter().convertToCellRange( maOoxData.maRange, aBinRange, nSheet, true ) ) + { + sal_Int32 nType; + rStrm >> nType >> maOoxData.mnId >> maOoxData.mnHeaderRows >> maOoxData.mnTotalsRows; + rStrm.skip( 32 ); + rStrm >> maOoxData.maProgName >> maOoxData.maDisplayName; + + static const sal_Int32 spnTypes[] = { XML_worksheet, XML_TOKEN_INVALID, XML_TOKEN_INVALID, XML_queryTable }; + maOoxData.mnType = STATIC_ARRAY_SELECT( spnTypes, nType, XML_TOKEN_INVALID ); + } +} + +void Table::finalizeImport() +{ + if( maOoxData.maDisplayName.getLength() > 0 ) try + { + // find an unused name + Reference< XDatabaseRanges > xDatabaseRanges = getDatabaseRanges(); + Reference< XNameAccess > xNameAccess( xDatabaseRanges, UNO_QUERY_THROW ); + OUString aName = ContainerHelper::getUnusedName( xNameAccess, maOoxData.maDisplayName, '_' ); + xDatabaseRanges->addNewByName( aName, maOoxData.maRange ); + Reference< XDatabaseRange > xDatabaseRange( xDatabaseRanges->getByName( aName ), UNO_QUERY_THROW ); + PropertySet aPropSet( xDatabaseRange ); + if( !aPropSet.getProperty( mnTokenIndex, CREATE_OUSTRING( "TokenIndex" ) ) ) + mnTokenIndex = -1; + } + catch( Exception& ) + { + OSL_ENSURE( false, "Table::finalizeImport - cannot create database range" ); + } +} + +// ============================================================================ + +TableBuffer::TableBuffer( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ) +{ +} + +TableRef TableBuffer::importTable( const AttributeList& rAttribs, sal_Int16 nSheet ) +{ + TableRef xTable( new Table( *this ) ); + xTable->importTable( rAttribs, nSheet ); + insertTable( xTable ); + return xTable; +} + +TableRef TableBuffer::importTable( RecordInputStream& rStrm, sal_Int16 nSheet ) +{ + TableRef xTable( new Table( *this ) ); + xTable->importTable( rStrm, nSheet ); + insertTable( xTable ); + return xTable; +} + +void TableBuffer::finalizeImport() +{ + maTables.forEachMem( &Table::finalizeImport ); +} + +TableRef TableBuffer::getTable( sal_Int32 nTableId ) const +{ + return maTables.get( nTableId ); +} + +// private -------------------------------------------------------------------- + +void TableBuffer::insertTable( TableRef xTable ) +{ + sal_Int32 nTableId = xTable->getTableId(); + if( nTableId > 0 ) + { + OSL_ENSURE( maTables.find( nTableId ) == maTables.end(), "TableBuffer::insertTable - multiple table identifier" ); + maTables[ nTableId ] = xTable; + } +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/tablefragment.cxx b/oox/source/xls/tablefragment.cxx new file mode 100644 index 000000000000..53097159a05d --- /dev/null +++ b/oox/source/xls/tablefragment.cxx @@ -0,0 +1,92 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tablefragment.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/tablefragment.hxx" + +using ::rtl::OUString; + +namespace oox { +namespace xls { + +// ============================================================================ + +OoxTableFragment::OoxTableFragment( const WorksheetHelper& rHelper, const OUString& rFragmentPath ) : + OoxWorksheetFragmentBase( rHelper, rFragmentPath ) +{ +} + +// oox.xls.OoxContextHelper interface ----------------------------------------- + +bool OoxTableFragment::onCanCreateContext( sal_Int32 nElement ) const +{ + switch( getCurrentContext() ) + { + case XML_ROOT_CONTEXT: + return (nElement == XLS_TOKEN( table )); + } + return false; +} + +void OoxTableFragment::onStartElement( const AttributeList& rAttribs ) +{ + switch( getCurrentContext() ) + { + case XLS_TOKEN( table ): mxTable = getTables().importTable( rAttribs, getSheetIndex() ); break; + } +} + +bool OoxTableFragment::onCanCreateRecordContext( sal_Int32 nRecId ) +{ + switch( getCurrentContext() ) + { + case XML_ROOT_CONTEXT: + return (nRecId == OOBIN_ID_TABLE); + } + return false; +} + +void OoxTableFragment::onStartRecord( RecordInputStream& rStrm ) +{ + switch( getCurrentContext() ) + { + case OOBIN_ID_TABLE: mxTable = getTables().importTable( rStrm, getSheetIndex() ); break; + } +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/themebuffer.cxx b/oox/source/xls/themebuffer.cxx new file mode 100644 index 000000000000..1a930aa26845 --- /dev/null +++ b/oox/source/xls/themebuffer.cxx @@ -0,0 +1,170 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: themebuffer.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/themebuffer.hxx" +#include "oox/xls/stylesbuffer.hxx" +#include "oox/xls/stylespropertyhelper.hxx" + +using ::oox::drawingml::ClrScheme; +using ::oox::drawingml::Theme; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +/** Specifies default theme fonts for a specific locale. */ +struct BuiltinThemeFont +{ + const sal_Char* mpcLocale; /// The locale for this font setting. + const sal_Char* mpcHeadFont; /// Default heading font. + const sal_Char* mpcBodyFont; /// Default body font. +}; + +#define FONT_JA "\357\274\255\357\274\263 \357\274\260\343\202\264\343\202\267\343\203\203\343\202\257" +#define FONT_KO "\353\247\221\354\235\200 \352\263\240\353\224\225" +#define FONT_CS "\345\256\213\344\275\223" +#define FONT_CT "\346\226\260\347\264\260\346\230\216\351\253\224" + +static const BuiltinThemeFont spBuiltinThemeFonts[] = +{ // locale headings font body font + { "*", "Cambria", "Calibri" }, // Default + { "ar", "Times New Roman", "Arial" }, // Arabic + { "bn", "Vrinda", "Vrinda" }, // Bengali + { "div", "MV Boli", "MV Boli" }, // Divehi + { "fa", "Times New Roman", "Arial" }, // Farsi + { "gu", "Shruti", "Shruti" }, // Gujarati + { "he", "Times New Roman", "Arial" }, // Hebrew + { "hi", "Mangal", "Mangal" }, // Hindi + { "ja", FONT_JA, FONT_JA }, // Japanese + { "kn", "Tunga", "Tunga" }, // Kannada + { "ko", FONT_KO, FONT_KO }, // Korean + { "kok", "Mangal", "Mangal" }, // Konkani + { "ml", "Kartika", "Kartika" }, // Malayalam + { "mr", "Mangal", "Mangal" }, // Marathi + { "pa", "Raavi", "Raavi" }, // Punjabi + { "sa", "Mangal", "Mangal" }, // Sanskrit + { "syr", "Estrangelo Edessa", "Estrangelo Edessa" }, // Syriac + { "ta", "Latha", "Latha" }, // Tamil + { "te", "Gautami", "Gautami" }, // Telugu + { "th", "Tahoma", "Tahoma" }, // Thai + { "ur", "Times New Roman", "Arial" }, // Urdu + { "vi", "Times New Roman", "Arial" }, // Vietnamese + { "zh", FONT_CS, FONT_CS }, // Chinese, Simplified + { "zh-HK", FONT_CT, FONT_CT }, // Chinese, Hong Kong + { "zh-MO", FONT_CT, FONT_CT }, // Chinese, Macau + { "zh-TW", FONT_CT, FONT_CT } // Chinese, Taiwan +}; + +} // namespace + +// ---------------------------------------------------------------------------- + +ThemeBuffer::ThemeBuffer( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + mxDefFontData( new OoxFontData ) +{ + switch( getFilterType() ) + { + case FILTER_OOX: + //! TODO: locale dependent font name + mxDefFontData->maName = CREATE_OUSTRING( "Cambria" ); + mxDefFontData->mfHeight = 11.0; + break; + case FILTER_BIFF: + //! TODO: BIFF dependent font name + mxDefFontData->maName = CREATE_OUSTRING( "Arial" ); + mxDefFontData->mfHeight = 10.0; + break; + case FILTER_UNKNOWN: break; + } +} + +ThemeBuffer::~ThemeBuffer() +{ +} + +Theme& ThemeBuffer::getCoreTheme() const +{ + if( !mxTheme ) + mxTheme.reset( new Theme ); + return *mxTheme; +} + +sal_Int32 ThemeBuffer::getColorByToken( sal_Int32 nToken ) const +{ + sal_Int32 nColor = 0; + if( const ClrScheme* pClrScheme = getCoreTheme().getClrScheme().get() ) + if( pClrScheme->getColor( nToken, nColor ) ) + return nColor; + return API_RGB_TRANSPARENT; +} + +sal_Int32 ThemeBuffer::getColorByIndex( sal_Int32 nIndex ) const +{ + static const sal_Int32 spnColorTokens[] = { + XML_lt1, XML_dk1, XML_lt2, XML_dk2, XML_accent1, XML_accent2, + XML_accent3, XML_accent4, XML_accent5, XML_accent6, XML_hlink, XML_folHlink }; + + sal_Int32 nColor = 0; + if( const ClrScheme* pClrScheme = getCoreTheme().getClrScheme().get() ) + if( pClrScheme->getColor( STATIC_ARRAY_SELECT( spnColorTokens, nIndex, XML_TOKEN_INVALID ), nColor ) ) + return nColor; + return API_RGB_TRANSPARENT; +} + +sal_Int32 ThemeBuffer::getSystemColor( sal_Int32 nElement, sal_Int32 nDefaultColor ) +{ + sal_Int32 nColor = 0; + return ClrScheme::getSystemColor( nColor, nElement ) ? nColor : nDefaultColor; +} + +sal_Int32 ThemeBuffer::getSystemWindowColor() +{ + return getSystemColor( XML_window, 0xFFFFFF ); +} + +sal_Int32 ThemeBuffer::getSystemWindowTextColor() +{ + return getSystemColor( XML_windowText, 0x000000 ); +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/unitconverter.cxx b/oox/source/xls/unitconverter.cxx new file mode 100644 index 000000000000..66f92142413b --- /dev/null +++ b/oox/source/xls/unitconverter.cxx @@ -0,0 +1,209 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: unitconverter.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/unitconverter.hxx" +#include +#include +#include +#include +#include "oox/xls/stylesbuffer.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::awt::FontDescriptor; +using ::com::sun::star::awt::XDevice; +using ::com::sun::star::awt::DeviceInfo; +using ::com::sun::star::awt::XFont; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +const double MM100_PER_INCH = 2540.0; +const double INCH_PER_MM100 = 1.0 / MM100_PER_INCH; + +const double POINT_PER_INCH = 72.0; +const double INCH_PER_POINT = 1.0 / POINT_PER_INCH; + +const double MM100_PER_POINT = MM100_PER_INCH * INCH_PER_POINT; +const double POINT_PER_MM100 = 1.0 / MM100_PER_POINT; + +const double TWIP_PER_POINT = 20.0; +const double POINT_PER_TWIP = 1.0 / TWIP_PER_POINT; + +const double MM100_PER_TWIP = MM100_PER_POINT * POINT_PER_TWIP; +const double TWIP_PER_MM100 = 1.0 / MM100_PER_TWIP; + +} // namespace + +// ---------------------------------------------------------------------------- + +UnitConverter::UnitConverter( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + mfPixelPerMm100X( 0.08 ), + mfPixelPerMm100Y( 0.08 ), + mnDigitWidth( 200 ), + mnSpaceWidth( 100 ) +{ + // map error code names to BIFF error codes + maErrorCodes[ CREATE_OUSTRING( "#NULL!" ) ] = BIFF_ERR_NULL; + maErrorCodes[ CREATE_OUSTRING( "#DIV/0!" ) ] = BIFF_ERR_DIV0; + maErrorCodes[ CREATE_OUSTRING( "#VALUE!" ) ] = BIFF_ERR_VALUE; + maErrorCodes[ CREATE_OUSTRING( "#REF!" ) ] = BIFF_ERR_REF; + maErrorCodes[ CREATE_OUSTRING( "#NAME?" ) ] = BIFF_ERR_NAME; + maErrorCodes[ CREATE_OUSTRING( "#NUM!" ) ] = BIFF_ERR_NUM; + maErrorCodes[ CREATE_OUSTRING( "#NA" ) ] = BIFF_ERR_NA; +} + +void UnitConverter::finalizeImport() +{ + Reference< XDevice > xDevice = getReferenceDevice(); + if( xDevice.is() ) + { + // get pixel metric first, needed to get character widths below + DeviceInfo aInfo = xDevice->getInfo(); + mfPixelPerMm100X = aInfo.PixelPerMeterX / 100000.0; + mfPixelPerMm100Y = aInfo.PixelPerMeterY / 100000.0; + + // get character widths from default font + if( const Font* pDefFont = getStyles().getDefaultFont().get() ) + { + // XDevice expects pixels in font descriptor, but font contains twips + FontDescriptor aDesc = pDefFont->getFontDescriptor(); + aDesc.Height = static_cast< sal_Int16 >( calcPixelsXFromMm100( calcMm100FromTwips( aDesc.Height ) ) ); + Reference< XFont > xFont = xDevice->getFont( aDesc ); + if( xFont.is() ) + { + // get maximum width of all digits + sal_Int32 nDigitWidth = 0; + for( sal_Unicode cChar = '0'; cChar <= '9'; ++cChar ) + nDigitWidth = ::std::max( nDigitWidth, calcMm100FromPixelsX( xFont->getCharWidth( cChar ) ) ); + if( nDigitWidth > 0 ) + mnDigitWidth = nDigitWidth; + // get width of space character + sal_Int32 nSpaceWidth = calcMm100FromPixelsX( xFont->getCharWidth( ' ' ) ); + if( nSpaceWidth > 0 ) + mnSpaceWidth = nSpaceWidth; + } + } + } +} + +// conversion ----------------------------------------------------------------- + +sal_Int32 UnitConverter::calcMm100FromInches( double fInches ) const +{ + return static_cast< sal_Int32 >( fInches * MM100_PER_INCH ); +} + +sal_Int32 UnitConverter::calcMm100FromPoints( double fPoints ) const +{ + return static_cast< sal_Int32 >( fPoints * MM100_PER_POINT + 0.5 ); +} + +sal_Int32 UnitConverter::calcMm100FromTwips( double fTwips ) const +{ + return static_cast< sal_Int32 >( fTwips * MM100_PER_TWIP + 0.5 ); +} + +sal_Int32 UnitConverter::calcMm100FromPixelsX( double fPixels ) const +{ + return static_cast< sal_Int32 >( fPixels / mfPixelPerMm100X + 0.5 ); +} + +sal_Int32 UnitConverter::calcMm100FromPixelsY( double fPixels ) const +{ + return static_cast< sal_Int32 >( fPixels / mfPixelPerMm100Y + 0.5 ); +} + +sal_Int32 UnitConverter::calcMm100FromDigits( double fChars ) const +{ + return static_cast< sal_Int32 >( fChars * mnDigitWidth + 0.5 ); +} + +sal_Int32 UnitConverter::calcMm100FromSpaces( double fSpaces ) const +{ + return static_cast< sal_Int32 >( fSpaces * mnSpaceWidth + 0.5 ); +} + +double UnitConverter::calcInchesFromMm100( sal_Int32 nMm100 ) const +{ + return nMm100 * INCH_PER_MM100; +} + +double UnitConverter::calcPointsFromMm100( sal_Int32 nMm100 ) const +{ + return nMm100 * POINT_PER_MM100; +} + +double UnitConverter::calcTwipsFromMm100( sal_Int32 nMm100 ) const +{ + return nMm100 * TWIP_PER_MM100; +} + +double UnitConverter::calcPixelsXFromMm100( sal_Int32 nMm100 ) const +{ + return nMm100 * mfPixelPerMm100X; +} + +double UnitConverter::calcPixelsYFromMm100( sal_Int32 nMm100 ) const +{ + return nMm100 * mfPixelPerMm100Y; +} + +double UnitConverter::calcDigitsFromMm100( sal_Int32 nMm100 ) const +{ + return static_cast< double >( nMm100 ) / mnDigitWidth; +} + +double UnitConverter::calcSpacesFromMm100( sal_Int32 nMm100 ) const +{ + return static_cast< double >( nMm100 ) / mnSpaceWidth; +} + +sal_uInt8 UnitConverter::calcBiffErrorCode( const OUString& rErrorCode ) const +{ + ErrorCodeMap::const_iterator aIt = maErrorCodes.find( rErrorCode ); + return (aIt == maErrorCodes.end()) ? BIFF_ERR_NA : aIt->second; +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/validationpropertyhelper.cxx b/oox/source/xls/validationpropertyhelper.cxx new file mode 100644 index 000000000000..8784fad81cb0 --- /dev/null +++ b/oox/source/xls/validationpropertyhelper.cxx @@ -0,0 +1,174 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: validationpropertyhelper.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/validationpropertyhelper.hxx" +#include +#include +#include +#include +#include +#include "oox/helper/propertyset.hxx" +#include "oox/xls/ooxtokens.hxx" +#include "oox/xls/worksheethelper.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::beans::XPropertySet; +using ::com::sun::star::sheet::ValidationType; +using ::com::sun::star::sheet::ValidationAlertStyle; +using ::com::sun::star::sheet::ConditionOperator; +using ::com::sun::star::sheet::XSheetCondition; +using ::com::sun::star::sheet::XMultiFormulaTokens; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +const sal_Char* const sppcPropNames[] = +{ + "Type", + "ShowInputMessage", + "InputTitle", + "InputMessage", + "ShowErrorMessage", + "ErrorTitle", + "ErrorMessage", + "ErrorAlertStyle", + "ShowList", + "IgnoreBlankCells", + 0 +}; + +} // namespace + +// ---------------------------------------------------------------------------- + +ValidationPropertyHelper::ValidationPropertyHelper( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + maValProps( sppcPropNames ), + maValidationProp( CREATE_OUSTRING( "Validation" ) ) +{ +} + +void ValidationPropertyHelper::writeValidationProperties( PropertySet& rPropSet, const OoxValidationData& rValData ) +{ + Reference< XPropertySet > xValidation; + if( rPropSet.getProperty( xValidation, maValidationProp ) && xValidation.is() ) + { + PropertySet aValProps( xValidation ); + namespace csss = ::com::sun::star::sheet; + + // convert validation type to API enum + ValidationType eType = csss::ValidationType_ANY; + switch( rValData.mnType ) + { + case XML_custom: eType = csss::ValidationType_CUSTOM; break; + case XML_date: eType = csss::ValidationType_DATE; break; + case XML_decimal: eType = csss::ValidationType_DECIMAL; break; + case XML_list: eType = csss::ValidationType_LIST; break; + case XML_none: eType = csss::ValidationType_ANY; break; + case XML_textLength: eType = csss::ValidationType_TEXT_LEN; break; + case XML_time: eType = csss::ValidationType_TIME; break; + case XML_whole: eType = csss::ValidationType_WHOLE; break; + default: OSL_ENSURE( false, "ValidationPropertyHelper::writeValidationProperties - unknown validation type" ); + } + + // convert error alert style to API enum + ValidationAlertStyle nAlertStyle = csss::ValidationAlertStyle_STOP; + switch( rValData.mnErrorStyle ) + { + case XML_information: nAlertStyle = csss::ValidationAlertStyle_INFO; break; + case XML_stop: nAlertStyle = csss::ValidationAlertStyle_STOP; break; + case XML_warning: nAlertStyle = csss::ValidationAlertStyle_WARNING; break; + default: OSL_ENSURE( false, "ValidationPropertyHelper::writeValidationProperties - unknown error style" ); + } + + // convert dropdown style to API visibility constants + sal_Int16 nVisibility = rValData.mbNoDropDown ? csss::TableValidationVisibility::INVISIBLE : csss::TableValidationVisibility::UNSORTED; + + // write all properties + maValProps + << eType + << rValData.mbShowInputMsg << rValData.maInputTitle << rValData.maInputMessage + << rValData.mbShowErrorMsg << rValData.maErrorTitle << rValData.maErrorMessage + << nAlertStyle << nVisibility << rValData.mbAllowBlank + >> aValProps; + + try + { + // condition operator + Reference< XSheetCondition > xSheetCond( xValidation, UNO_QUERY_THROW ); + xSheetCond->setOperator( convertToApiOperator( rValData.mnOperator ) ); + + // condition formulas + Reference< XMultiFormulaTokens > xTokens( xValidation, UNO_QUERY_THROW ); + xTokens->setTokens( 0, rValData.maTokens1 ); + xTokens->setTokens( 1, rValData.maTokens2 ); + } + catch( Exception& ) + { + } + + // write back validation settings to cell range(s) + rPropSet.setProperty( maValidationProp, xValidation ); + } +} + +ConditionOperator ValidationPropertyHelper::convertToApiOperator( sal_Int32 nToken ) +{ + using namespace ::com::sun::star::sheet; + switch( nToken ) + { + case XML_between: return ConditionOperator_BETWEEN; + case XML_equal: return ConditionOperator_EQUAL; + case XML_greaterThan: return ConditionOperator_GREATER; + case XML_greaterThanOrEqual: return ConditionOperator_GREATER_EQUAL; + case XML_lessThan: return ConditionOperator_LESS; + case XML_lessThanOrEqual: return ConditionOperator_LESS_EQUAL; + case XML_notBetween: return ConditionOperator_NOT_BETWEEN; + case XML_notEqual: return ConditionOperator_NOT_EQUAL; + } + return ConditionOperator_NONE; +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/viewsettings.cxx b/oox/source/xls/viewsettings.cxx new file mode 100644 index 000000000000..7ec207015ae6 --- /dev/null +++ b/oox/source/xls/viewsettings.cxx @@ -0,0 +1,789 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: viewsettings.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/viewsettings.hxx" +#include +#include +#include +#include +#include +#include "oox/helper/attributelist.hxx" +#include "oox/helper/containerhelper.hxx" +#include "oox/helper/propertysequence.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/helper/recordinputstream.hxx" +#include "oox/xls/biffinputstream.hxx" +#include "oox/xls/ooxtokens.hxx" +#include "oox/xls/unitconverter.hxx" +#include "oox/xls/workbooksettings.hxx" +#include "oox/xls/worksheetbuffer.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::container::XNameContainer; +using ::com::sun::star::container::XIndexContainer; +using ::com::sun::star::container::XIndexAccess; +using ::com::sun::star::document::XViewDataSupplier; +using ::com::sun::star::table::CellAddress; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +const sal_Int32 OOX_BOOKVIEW_TABBARRATIO_DEF = 600; /// Default tabbar ratio. +const sal_Int32 OOX_SHEETVIEW_NORMALZOOM_DEF = 100; /// Default zoom for normal view. +const sal_Int32 OOX_SHEETVIEW_SHEETLAYZOOM_DEF = 60; /// Default zoom for pagebreak preview. +const sal_Int32 OOX_SHEETVIEW_PAGELAYZOOM_DEF = 100; /// Default zoom for page layout view. + +const sal_uInt8 OOBIN_PANE_FROZEN = 0x01; +const sal_uInt8 OOBIN_PANE_FROZENNOSPLIT = 0x02; + +const sal_uInt16 OOBIN_SHEETVIEW_WINPROTECTED = 0x0001; +const sal_uInt16 OOBIN_SHEETVIEW_SHOWFORMULAS = 0x0002; +const sal_uInt16 OOBIN_SHEETVIEW_SHOWGRID = 0x0004; +const sal_uInt16 OOBIN_SHEETVIEW_SHOWHEADINGS = 0x0008; +const sal_uInt16 OOBIN_SHEETVIEW_SHOWZEROS = 0x0010; +const sal_uInt16 OOBIN_SHEETVIEW_RIGHTTOLEFT = 0x0020; +const sal_uInt16 OOBIN_SHEETVIEW_SELECTED = 0x0040; +const sal_uInt16 OOBIN_SHEETVIEW_SHOWRULER = 0x0080; +const sal_uInt16 OOBIN_SHEETVIEW_SHOWOUTLINE = 0x0100; +const sal_uInt16 OOBIN_SHEETVIEW_DEFGRIDCOLOR = 0x0200; +const sal_uInt16 OOBIN_SHEETVIEW_SHOWWHITESPACE = 0x0400; + +const sal_uInt8 OOBIN_WBVIEW_HIDDEN = 0x01; +const sal_uInt8 OOBIN_WBVIEW_MINIMIZED = 0x02; +const sal_uInt8 OOBIN_WBVIEW_SHOWHORSCROLL = 0x08; +const sal_uInt8 OOBIN_WBVIEW_SHOWVERSCROLL = 0x10; +const sal_uInt8 OOBIN_WBVIEW_SHOWTABBAR = 0x20; +const sal_uInt8 OOBIN_WBVIEW_AUTOFILTERGROUP = 0x40; + +const sal_uInt8 BIFF_PANE_BOTTOMRIGHT = 0; /// Bottom-right pane. +const sal_uInt8 BIFF_PANE_TOPRIGHT = 1; /// Right, or top-right pane. +const sal_uInt8 BIFF_PANE_BOTTOMLEFT = 2; /// Bottom, or bottom-left pane. +const sal_uInt8 BIFF_PANE_TOPLEFT = 3; /// Single, top, left, or top-left pane. + +const sal_uInt16 BIFF_WINDOW1_HIDDEN = 0x0001; +const sal_uInt16 BIFF_WINDOW1_MINIMIZED = 0x0002; +const sal_uInt16 BIFF_WINDOW1_SHOWHORSCROLL = 0x0008; +const sal_uInt16 BIFF_WINDOW1_SHOWVERSCROLL = 0x0010; +const sal_uInt16 BIFF_WINDOW1_SHOWTABBAR = 0x0020; + +const sal_uInt16 BIFF_WINDOW2_SHOWFORMULAS = 0x0001; +const sal_uInt16 BIFF_WINDOW2_SHOWGRID = 0x0002; +const sal_uInt16 BIFF_WINDOW2_SHOWHEADINGS = 0x0004; +const sal_uInt16 BIFF_WINDOW2_FROZEN = 0x0008; +const sal_uInt16 BIFF_WINDOW2_SHOWZEROS = 0x0010; +const sal_uInt16 BIFF_WINDOW2_DEFGRIDCOLOR = 0x0020; +const sal_uInt16 BIFF_WINDOW2_RIGHTTOLEFT = 0x0040; +const sal_uInt16 BIFF_WINDOW2_SHOWOUTLINE = 0x0080; +const sal_uInt16 BIFF_WINDOW2_FROZENNOSPLIT = 0x0100; +const sal_uInt16 BIFF_WINDOW2_SELECTED = 0x0200; +const sal_uInt16 BIFF_WINDOW2_DISPLAYED = 0x0400; +const sal_uInt16 BIFF_WINDOW2_PAGEBREAKMODE = 0x0800; + +// Attention: view settings in Calc do not use com.sun.star.view.DocumentZoomType! +const sal_Int16 API_ZOOMTYPE_PERCENT = 0; /// Zoom value in percent. + +const sal_Int32 API_ZOOMVALUE_MIN = 20; /// Minimum zoom in Calc. +const sal_Int32 API_ZOOMVALUE_MAX = 400; /// Maximum zoom in Calc. + +// no predefined constants for split mode +const sal_Int16 API_SPLITMODE_NONE = 0; /// No splits in window. +const sal_Int16 API_SPLITMODE_SPLIT = 1; /// Window is split. +const sal_Int16 API_SPLITMODE_FREEZE = 2; /// Window has frozen panes. + +// no predefined constants for pane idetifiers +const sal_Int16 API_SPLITPANE_TOPLEFT = 0; /// Top-left, or top pane. +const sal_Int16 API_SPLITPANE_TOPRIGHT = 1; /// Top-right pane. +const sal_Int16 API_SPLITPANE_BOTTOMLEFT = 2; /// Bottom-left, bottom, left, or single pane. +const sal_Int16 API_SPLITPANE_BOTTOMRIGHT = 3; /// Bottom-right, or right pane. + +// ---------------------------------------------------------------------------- + +/** Property names for document view settings. */ +const sal_Char* const sppcDocNames[] = +{ + "Tables", + "ActiveTable", + "HasHorizontalScrollBar", + "HasVerticalScrollBar", + "HasSheetTabs", + "RelativeHorizontalTabbarWidth", + "ShowObjects", + "ShowCharts", + "ShowDrawing", + 0 +}; + +/** Property names for sheet view settings that are document-global in Calc. */ +const sal_Char* const sppcGlobalSheetNames[] = +{ + "GridColor", + "ZoomType", + "ZoomValue", + "PageViewZoomValue", + "ShowPageBreakPreview", + "ShowFormulas", + "ShowGrid", + "HasColumnRowHeaders", + "ShowZeroValues", + "IsOutlineSymbolsSet", + 0 +}; + +/** Property names for sheet view settings. */ +const sal_Char* const sppcSheetNames[] = +{ + "TableSelected", + "CursorPositionX", + "CursorPositionY", + "HorizontalSplitMode", + "VerticalSplitMode", + "HorizontalSplitPositionTwips", + "VerticalSplitPositionTwips", + "ActiveSplitRange", + "PositionLeft", + "PositionTop", + "PositionRight", + "PositionBottom", + 0 +}; + +// ---------------------------------------------------------------------------- + +/** Returns the OOXML pane identifier from the passed OOBIN or BIFF pane id. */ +sal_Int32 lclGetOoxPaneId( sal_Int32 nBinPaneId, sal_Int32 nDefaultPaneId ) +{ + static const sal_Int32 spnPaneIds[] = { XML_bottomRight, XML_topRight, XML_bottomLeft, XML_topLeft }; + return STATIC_ARRAY_SELECT( spnPaneIds, nBinPaneId, nDefaultPaneId ); +} + +} // namespace + +// ============================================================================ + +OoxSheetSelectionData::OoxSheetSelectionData() : + mnActiveCellId( 0 ) +{ +} + +// ---------------------------------------------------------------------------- + +OoxSheetViewData::OoxSheetViewData() : + maGridColor( XML_indexed, OOX_COLOR_WINDOWTEXT ), + mnWorkbookViewId( 0 ), + mnViewType( XML_normal ), + mnActivePaneId( XML_topLeft ), + mnPaneState( XML_split ), + mfSplitX( 0.0 ), + mfSplitY( 0.0 ), + mnCurrentZoom( 0 ), + mnNormalZoom( 0 ), + mnSheetLayoutZoom( 0 ), + mnPageLayoutZoom( 0 ), + mbSelected( false ), + mbRightToLeft( false ), + mbDefGridColor( true ), + mbShowFormulas( false ), + mbShowGrid( true ), + mbShowHeadings( true ), + mbShowZeros( true ), + mbShowOutline( true ) +{ +} + +bool OoxSheetViewData::isPageBreakPreview() const +{ + return mnViewType == XML_pageBreakPreview; +} + +sal_Int32 OoxSheetViewData::getNormalZoom() const +{ + const sal_Int32& rnZoom = isPageBreakPreview() ? mnNormalZoom : mnCurrentZoom; + sal_Int32 nZoom = (rnZoom > 0) ? rnZoom : OOX_SHEETVIEW_NORMALZOOM_DEF; + return getLimitedValue< sal_Int32 >( nZoom, API_ZOOMVALUE_MIN, API_ZOOMVALUE_MAX ); +} + +sal_Int32 OoxSheetViewData::getPageBreakZoom() const +{ + const sal_Int32& rnZoom = isPageBreakPreview() ? mnCurrentZoom : mnSheetLayoutZoom; + sal_Int32 nZoom = (rnZoom > 0) ? rnZoom : OOX_SHEETVIEW_SHEETLAYZOOM_DEF; + return getLimitedValue< sal_Int32 >( nZoom, API_ZOOMVALUE_MIN, API_ZOOMVALUE_MAX ); +} + +const OoxSheetSelectionData* OoxSheetViewData::getSelectionData( sal_Int32 nPaneId ) const +{ + return maSelMap.get( nPaneId ).get(); +} + +const OoxSheetSelectionData* OoxSheetViewData::getActiveSelectionData() const +{ + return getSelectionData( mnActivePaneId ); +} + +OoxSheetSelectionData& OoxSheetViewData::createSelectionData( sal_Int32 nPaneId ) +{ + OoxSelectionDataMap::mapped_type& rxSelData = maSelMap[ nPaneId ]; + if( !rxSelData ) + rxSelData.reset( new OoxSheetSelectionData ); + return *rxSelData; +} + +// ---------------------------------------------------------------------------- + +SheetViewSettings::SheetViewSettings( const WorksheetHelper& rHelper ) : + WorksheetHelper( rHelper ) +{ +} + +void SheetViewSettings::importSheetView( const AttributeList& rAttribs ) +{ + OoxSheetViewData& rData = *createSheetViewData(); + rData.maGridColor.set( XML_indexed, rAttribs.getInteger( XML_colorId, OOX_COLOR_WINDOWTEXT ) ); + rData.maFirstPos = getAddressConverter().createValidCellAddress( rAttribs.getString( XML_topLeftCell ), getSheetIndex(), false ); + rData.mnWorkbookViewId = rAttribs.getToken( XML_workbookViewId, 0 ); + rData.mnViewType = rAttribs.getToken( XML_view, XML_normal ); + rData.mnCurrentZoom = rAttribs.getInteger( XML_zoomScale, 100 ); + rData.mnNormalZoom = rAttribs.getInteger( XML_zoomScaleNormal, 0 ); + rData.mnSheetLayoutZoom = rAttribs.getInteger( XML_zoomScaleSheetLayoutView, 0 ); + rData.mnPageLayoutZoom = rAttribs.getInteger( XML_zoomScalePageLayoutView, 0 ); + rData.mbSelected = rAttribs.getBool( XML_tabSelected, false ); + rData.mbRightToLeft = rAttribs.getBool( XML_rightToLeft, false ); + rData.mbDefGridColor = rAttribs.getBool( XML_defaultGridColor, true ); + rData.mbShowFormulas = rAttribs.getBool( XML_showFormulas, false ); + rData.mbShowGrid = rAttribs.getBool( XML_showGridLines, true ); + rData.mbShowHeadings = rAttribs.getBool( XML_showRowColHeaders, true ); + rData.mbShowZeros = rAttribs.getBool( XML_showZeros, true ); + rData.mbShowOutline = rAttribs.getBool( XML_showOutlineSymbols, true ); +} + +void SheetViewSettings::importPane( const AttributeList& rAttribs ) +{ + OSL_ENSURE( !maSheetDatas.empty(), "SheetViewSettings::importPane - missing view data" ); + if( !maSheetDatas.empty() ) + { + OoxSheetViewData& rData = *maSheetDatas.back(); + rData.maSecondPos = getAddressConverter().createValidCellAddress( rAttribs.getString( XML_topLeftCell ), getSheetIndex(), false ); + rData.mnActivePaneId = rAttribs.getToken( XML_activePane, XML_topLeft ); + rData.mnPaneState = rAttribs.getToken( XML_state, XML_split ); + rData.mfSplitX = rAttribs.getDouble( XML_xSplit, 0.0 ); + rData.mfSplitY = rAttribs.getDouble( XML_ySplit, 0.0 ); + } +} + +void SheetViewSettings::importSelection( const AttributeList& rAttribs ) +{ + OSL_ENSURE( !maSheetDatas.empty(), "SheetViewSettings::importSelection - missing view data" ); + if( !maSheetDatas.empty() ) + { + // pane this selection belongs to + sal_Int32 nPaneId = rAttribs.getToken( XML_pane, XML_topLeft ); + OoxSheetSelectionData& rSelData = maSheetDatas.back()->createSelectionData( nPaneId ); + // cursor position + rSelData.maActiveCell = getAddressConverter().createValidCellAddress( rAttribs.getString( XML_activeCell ), getSheetIndex(), false ); + rSelData.mnActiveCellId = rAttribs.getInteger( XML_activeCellId, 0 ); + // selection + rSelData.maSelection.clear(); + getAddressConverter().convertToCellRangeList( rSelData.maSelection, rAttribs.getString( XML_sqref ), getSheetIndex(), false ); + } +} + +void SheetViewSettings::importSheetView( RecordInputStream& rStrm ) +{ + OoxSheetViewData& rData = *createSheetViewData(); + sal_uInt16 nFlags; + sal_Int32 nViewType; + BinAddress aFirstPos; + rStrm >> nFlags >> nViewType >> aFirstPos; + rData.maGridColor.importColorId( rStrm ); + rData.mnCurrentZoom = rStrm.readuInt16(); + rData.mnNormalZoom = rStrm.readuInt16(); + rData.mnSheetLayoutZoom = rStrm.readuInt16(); + rData.mnPageLayoutZoom = rStrm.readuInt16(); + rStrm >> rData.mnWorkbookViewId; + + rData.maFirstPos = getAddressConverter().createValidCellAddress( aFirstPos, getSheetIndex(), false ); + static const sal_Int32 spnViewTypes[] = { XML_normal, XML_pageBreakPreview, XML_pageLayout }; + rData.mnViewType = STATIC_ARRAY_SELECT( spnViewTypes, nViewType, XML_normal ); + rData.mbSelected = getFlag( nFlags, OOBIN_SHEETVIEW_SELECTED ); + rData.mbRightToLeft = getFlag( nFlags, OOBIN_SHEETVIEW_RIGHTTOLEFT ); + rData.mbDefGridColor = getFlag( nFlags, OOBIN_SHEETVIEW_DEFGRIDCOLOR ); + rData.mbShowFormulas = getFlag( nFlags, OOBIN_SHEETVIEW_SHOWFORMULAS ); + rData.mbShowGrid = getFlag( nFlags, OOBIN_SHEETVIEW_SHOWGRID ); + rData.mbShowHeadings = getFlag( nFlags, OOBIN_SHEETVIEW_SHOWHEADINGS ); + rData.mbShowZeros = getFlag( nFlags, OOBIN_SHEETVIEW_SHOWZEROS ); + rData.mbShowOutline = getFlag( nFlags, OOBIN_SHEETVIEW_SHOWOUTLINE ); +} + +void SheetViewSettings::importPane( RecordInputStream& rStrm ) +{ + OSL_ENSURE( !maSheetDatas.empty(), "SheetViewSettings::importPane - missing view data" ); + if( !maSheetDatas.empty() ) + { + OoxSheetViewData& rData = *maSheetDatas.back(); + + BinAddress aSecondPos; + sal_Int32 nActivePaneId; + sal_uInt8 nFlags; + rStrm >> rData.mfSplitX >> rData.mfSplitY >> aSecondPos >> nActivePaneId >> nFlags; + + rData.maSecondPos = getAddressConverter().createValidCellAddress( aSecondPos, getSheetIndex(), false ); + rData.mnActivePaneId = lclGetOoxPaneId( nActivePaneId, XML_topLeft ); + rData.mnPaneState = getFlagValue( nFlags, OOBIN_PANE_FROZEN, getFlagValue( nFlags, OOBIN_PANE_FROZENNOSPLIT, XML_frozen, XML_frozenSplit ), XML_split ); + } +} + +void SheetViewSettings::importSelection( RecordInputStream& rStrm ) +{ + OSL_ENSURE( !maSheetDatas.empty(), "SheetViewSettings::importSelection - missing view data" ); + if( !maSheetDatas.empty() ) + { + // pane this selection belongs to + sal_Int32 nPaneId = rStrm.readInt32(); + OoxSheetSelectionData& rSelData = maSheetDatas.back()->createSelectionData( lclGetOoxPaneId( nPaneId, -1 ) ); + // cursor position + BinAddress aActiveCell; + rStrm >> aActiveCell >> rSelData.mnActiveCellId; + rSelData.maActiveCell = getAddressConverter().createValidCellAddress( aActiveCell, getSheetIndex(), false ); + // selection + BinRangeList aSelection; + rStrm >> aSelection; + rSelData.maSelection.clear(); + getAddressConverter().convertToCellRangeList( rSelData.maSelection, aSelection, getSheetIndex(), false ); + } +} + +void SheetViewSettings::importWindow2( BiffInputStream& rStrm ) +{ + OSL_ENSURE( maSheetDatas.empty(), "SheetViewSettings::importWindow2 - multiple WINDOW2 records" ); + OoxSheetViewData& rData = *createSheetViewData(); + if( getBiff() == BIFF2 ) + { + rData.mbShowFormulas = rStrm.readuInt8() != 0; + rData.mbShowGrid = rStrm.readuInt8() != 0; + rData.mbShowHeadings = rStrm.readuInt8() != 0; + rData.mnPaneState = (rStrm.readuInt8() == 0) ? XML_split : XML_frozen; + rData.mbShowZeros = rStrm.readuInt8() != 0; + BinAddress aFirstPos; + rStrm >> aFirstPos; + rData.maFirstPos = getAddressConverter().createValidCellAddress( aFirstPos, getSheetIndex(), false ); + rData.mbDefGridColor = rStrm.readuInt8() != 0; + rData.maGridColor.importColorRgb( rStrm ); + } + else + { + sal_uInt16 nFlags; + BinAddress aFirstPos; + rStrm >> nFlags >> aFirstPos; + + rData.maFirstPos = getAddressConverter().createValidCellAddress( aFirstPos, getSheetIndex(), false ); + rData.mnViewType = getFlagValue( nFlags, BIFF_WINDOW2_PAGEBREAKMODE, XML_pageBreakPreview, XML_normal ); + rData.mnPaneState = getFlagValue( nFlags, BIFF_WINDOW2_FROZEN, getFlagValue( nFlags, BIFF_WINDOW2_FROZENNOSPLIT, XML_frozen, XML_frozenSplit ), XML_split ); + rData.mbSelected = getFlag( nFlags, BIFF_WINDOW2_SELECTED ); + rData.mbRightToLeft = getFlag( nFlags, BIFF_WINDOW2_RIGHTTOLEFT ); + rData.mbDefGridColor = getFlag( nFlags, BIFF_WINDOW2_DEFGRIDCOLOR ); + rData.mbShowFormulas = getFlag( nFlags, BIFF_WINDOW2_SHOWFORMULAS ); + rData.mbShowGrid = getFlag( nFlags, BIFF_WINDOW2_SHOWGRID ); + rData.mbShowHeadings = getFlag( nFlags, BIFF_WINDOW2_SHOWHEADINGS ); + rData.mbShowZeros = getFlag( nFlags, BIFF_WINDOW2_SHOWZEROS ); + rData.mbShowOutline = getFlag( nFlags, BIFF_WINDOW2_SHOWOUTLINE ); + + if( getBiff() == BIFF8 ) + { + rData.maGridColor.importColorId( rStrm ); + // zoom data not included in chart sheets + if( rStrm.getRecLeft() >= 6 ) + { + rStrm.skip( 2 ); + sal_uInt16 nPageZoom, nNormalZoom; + rStrm >> nPageZoom >> nNormalZoom; + rData.mnSheetLayoutZoom = nPageZoom; + rData.mnNormalZoom = nNormalZoom; + } + } + else + { + rData.maGridColor.importColorRgb( rStrm ); + } + } +} + +void SheetViewSettings::importPane( BiffInputStream& rStrm ) +{ + OSL_ENSURE( !maSheetDatas.empty(), "SheetViewSettings::importPane - missing leading WINDOW2 record" ); + if( !maSheetDatas.empty() ) + { + sal_uInt8 nActivePaneId; + sal_uInt16 nSplitX, nSplitY; + BinAddress aSecondPos; + rStrm >> nSplitX >> nSplitY >> aSecondPos >> nActivePaneId; + + OoxSheetViewData& rData = *maSheetDatas.back(); + rData.mfSplitX = nSplitX; + rData.mfSplitY = nSplitY; + rData.maSecondPos = getAddressConverter().createValidCellAddress( aSecondPos, getSheetIndex(), false ); + rData.mnActivePaneId = lclGetOoxPaneId( nActivePaneId, XML_topLeft ); + } +} + +void SheetViewSettings::importScl( BiffInputStream& rStrm ) +{ + OSL_ENSURE( !maSheetDatas.empty(), "SheetViewSettings::importScl - missing leading WINDOW2 record" ); + if( !maSheetDatas.empty() ) + { + sal_uInt16 nNum, nDenom; + rStrm >> nNum >> nDenom; + OSL_ENSURE( nDenom > 0, "SheetViewSettings::importScl - invalid denominator" ); + if( nDenom > 0 ) + maSheetDatas.back()->mnCurrentZoom = getLimitedValue< sal_Int32, sal_uInt16 >( (nNum * 100) / nDenom, 10, 400 ); + } +} + +void SheetViewSettings::importSelection( BiffInputStream& rStrm ) +{ + OSL_ENSURE( !maSheetDatas.empty(), "SheetViewSettings::importPane - missing leading WINDOW2 record" ); + if( !maSheetDatas.empty() ) + { + // pane this selection belongs to + sal_uInt8 nPaneId = rStrm.readuInt8(); + OoxSheetSelectionData& rSelData = maSheetDatas.back()->createSelectionData( lclGetOoxPaneId( nPaneId, -1 ) ); + // cursor position + BinAddress aActiveCell; + sal_uInt16 nActiveCellId; + rStrm >> aActiveCell >> nActiveCellId; + rSelData.maActiveCell = getAddressConverter().createValidCellAddress( aActiveCell, getSheetIndex(), false ); + rSelData.mnActiveCellId = nActiveCellId; + // selection + rSelData.maSelection.clear(); + BinRangeList aSelection; + aSelection.read( rStrm, false ); + getAddressConverter().convertToCellRangeList( rSelData.maSelection, aSelection, getSheetIndex(), false ); + } +} + +void SheetViewSettings::finalizeImport() +{ + // force creation of sheet view data to get the Excel defaults + OoxSheetViewDataRef xData = maSheetDatas.empty() ? createSheetViewData() : maSheetDatas.front(); + + // mirrored sheet (this is not a view setting in Calc) + // #i59590# real life: Excel ignores mirror flag in chart sheets + if( xData->mbRightToLeft && (getSheetType() != SHEETTYPE_CHART) ) + { + PropertySet aPropSet( getXSpreadsheet() ); + aPropSet.setProperty( CREATE_OUSTRING( "TableLayout" ), ::com::sun::star::text::WritingMode2::RL_TB ); + } + + // sheet selected (active sheet must be selected) + bool bSelected = xData->mbSelected || (getSheetIndex() == getViewSettings().getActiveSheetIndex()); + + // current cursor position (selection not supported via API) + const OoxSheetSelectionData* pSelData = xData->getActiveSelectionData(); + CellAddress aCursor = pSelData ? pSelData->maActiveCell : xData->maFirstPos; + + // freeze/split position + sal_Int16 nHSplitMode = API_SPLITMODE_NONE; + sal_Int16 nVSplitMode = API_SPLITMODE_NONE; + sal_Int32 nHSplitPos = 0; + sal_Int32 nVSplitPos = 0; + if( (xData->mnPaneState == XML_frozen) || (xData->mnPaneState == XML_frozenSplit) ) + { + /* Frozen panes: handle split position as row/column positions. + #i35812# Excel uses number of visible rows/columns in the + frozen area (rows/columns scolled outside are not incuded), + Calc uses absolute position of first unfrozen row/column. */ + const CellAddress& rMaxApiPos = getAddressConverter().getMaxApiAddress(); + if( (xData->mfSplitX >= 1.0) && (xData->maFirstPos.Column + xData->mfSplitX <= rMaxApiPos.Column) ) + nHSplitPos = static_cast< sal_Int32 >( xData->maFirstPos.Column + xData->mfSplitX ); + nHSplitMode = (nHSplitPos > 0) ? API_SPLITMODE_FREEZE : API_SPLITMODE_NONE; + if( (xData->mfSplitY >= 1.0) && (xData->maFirstPos.Row + xData->mfSplitY <= rMaxApiPos.Row) ) + nVSplitPos = static_cast< sal_Int32 >( xData->maFirstPos.Row + xData->mfSplitY ); + nVSplitMode = (nVSplitPos > 0) ? API_SPLITMODE_FREEZE : API_SPLITMODE_NONE; + } + else if( xData->mnPaneState == XML_split ) + { + // split window: view settings API uses twips... + nHSplitPos = getLimitedValue< sal_Int32, double >( xData->mfSplitX + 0.5, 0, SAL_MAX_INT32 ); + nHSplitMode = (nHSplitPos > 0) ? API_SPLITMODE_SPLIT : API_SPLITMODE_NONE; + nVSplitPos = getLimitedValue< sal_Int32, double >( xData->mfSplitY + 0.5, 0, SAL_MAX_INT32 ); + nVSplitMode = (nVSplitPos > 0) ? API_SPLITMODE_SPLIT : API_SPLITMODE_NONE; + } + + // active pane + sal_Int16 nActivePane = API_SPLITPANE_BOTTOMLEFT; + switch( xData->mnActivePaneId ) + { + // no horizontal split -> always use left panes + // no vertical split -> always use *bottom* panes + case XML_topLeft: + nActivePane = (nVSplitMode == API_SPLITMODE_NONE) ? API_SPLITPANE_BOTTOMLEFT : API_SPLITPANE_TOPLEFT; + break; + case XML_topRight: + nActivePane = (nHSplitMode == API_SPLITMODE_NONE) ? + ((nVSplitMode == API_SPLITMODE_NONE) ? API_SPLITPANE_BOTTOMLEFT : API_SPLITPANE_TOPLEFT) : + ((nVSplitMode == API_SPLITMODE_NONE) ? API_SPLITPANE_BOTTOMRIGHT : API_SPLITPANE_TOPRIGHT); + break; + case XML_bottomLeft: + nActivePane = API_SPLITPANE_BOTTOMLEFT; + break; + case XML_bottomRight: + nActivePane = (nHSplitMode == API_SPLITMODE_NONE) ? API_SPLITPANE_BOTTOMLEFT : API_SPLITPANE_BOTTOMRIGHT; + break; + } + + // automatic grid color + if( xData->mbDefGridColor ) + xData->maGridColor.set( XML_auto, 0 ); + + // write the sheet view settings into the property sequence + PropertySequence aSheetProps( sppcSheetNames, sppcGlobalSheetNames ); + aSheetProps + << bSelected + << aCursor.Column + << aCursor.Row + << nHSplitMode + << nVSplitMode + << nHSplitPos + << nVSplitPos + << nActivePane + << xData->maFirstPos.Column + << xData->maFirstPos.Row + << xData->maSecondPos.Column + << ((nVSplitPos > 0) ? xData->maSecondPos.Row : xData->maFirstPos.Row) + << getStyles().getColor( xData->maGridColor, API_RGB_TRANSPARENT ) + << API_ZOOMTYPE_PERCENT + << static_cast< sal_Int16 >( xData->getNormalZoom() ) + << static_cast< sal_Int16 >( xData->getPageBreakZoom() ) + << xData->isPageBreakPreview() + << xData->mbShowFormulas + << xData->mbShowGrid + << xData->mbShowHeadings + << xData->mbShowZeros + << xData->mbShowOutline; + + // store sheet view settings in global view settings object + getViewSettings().setSheetViewSettings( getSheetIndex(), xData, Any( aSheetProps.createPropertySequence() ) ); +} + +// private -------------------------------------------------------------------- + +OoxSheetViewDataRef SheetViewSettings::createSheetViewData() +{ + OoxSheetViewDataRef xData( new OoxSheetViewData ); + maSheetDatas.push_back( xData ); + return xData; +} + +// ============================================================================ + +OoxWorkbookViewData::OoxWorkbookViewData() : + mnWinX( 0 ), + mnWinY( 0 ), + mnWinWidth( 0 ), + mnWinHeight( 0 ), + mnActiveSheet( 0 ), + mnFirstVisSheet( 0 ), + mnTabBarWidth( OOX_BOOKVIEW_TABBARRATIO_DEF ), + mnVisibility( XML_visible ), + mbShowTabBar( true ), + mbShowHorScroll( true ), + mbShowVerScroll( true ), + mbMinimized( false ) +{ +} + +// ---------------------------------------------------------------------------- + +ViewSettings::ViewSettings( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ) +{ +} + +void ViewSettings::importWorkbookView( const AttributeList& rAttribs ) +{ + OoxWorkbookViewData& rData = createWorkbookViewData(); + rData.mnWinX = rAttribs.getInteger( XML_xWindow, 0 ); + rData.mnWinY = rAttribs.getInteger( XML_yWindow, 0 ); + rData.mnWinWidth = rAttribs.getInteger( XML_windowWidth, 0 ); + rData.mnWinHeight = rAttribs.getInteger( XML_windowHeight, 0 ); + rData.mnActiveSheet = rAttribs.getInteger( XML_activeTab, 0 ); + rData.mnFirstVisSheet = rAttribs.getInteger( XML_firstSheet, 0 ); + rData.mnTabBarWidth = rAttribs.getInteger( XML_tabRatio, 600 ); + rData.mnVisibility = rAttribs.getToken( XML_visibility, XML_visible ); + rData.mbShowTabBar = rAttribs.getBool( XML_showSheetTabs, true ); + rData.mbShowHorScroll = rAttribs.getBool( XML_showHorizontalScroll, true ); + rData.mbShowVerScroll = rAttribs.getBool( XML_showVerticalScroll, true ); + rData.mbMinimized = rAttribs.getBool( XML_minimized, false ); +} + +void ViewSettings::importWorkbookView( RecordInputStream& rStrm ) +{ + OoxWorkbookViewData& rData = createWorkbookViewData(); + sal_uInt8 nFlags; + rStrm >> rData.mnWinX >> rData.mnWinY >> rData.mnWinWidth >> rData.mnWinHeight >> rData.mnTabBarWidth >> rData.mnFirstVisSheet >> rData.mnActiveSheet >> nFlags; + rData.mnVisibility = getFlagValue( nFlags, OOBIN_WBVIEW_HIDDEN, XML_hidden, XML_visible ); + rData.mbShowTabBar = getFlag( nFlags, OOBIN_WBVIEW_SHOWTABBAR ); + rData.mbShowHorScroll = getFlag( nFlags, OOBIN_WBVIEW_SHOWHORSCROLL ); + rData.mbShowVerScroll = getFlag( nFlags, OOBIN_WBVIEW_SHOWVERSCROLL ); + rData.mbMinimized = getFlag( nFlags, OOBIN_WBVIEW_MINIMIZED ); +} + +void ViewSettings::importWindow1( BiffInputStream& rStrm ) +{ + sal_uInt16 nWinX, nWinY, nWinWidth, nWinHeight; + rStrm >> nWinX >> nWinY >> nWinWidth >> nWinHeight; + + // WINDOW1 record occures in every sheet in BIFF4W + OSL_ENSURE( maBookDatas.empty() || ((getBiff() == BIFF4) && isWorkbookFile()), + "ViewSettings::importWindow1 - multiple WINDOW1 records" ); + OoxWorkbookViewData& rData = createWorkbookViewData(); + rData.mnWinX = nWinX; + rData.mnWinY = nWinY; + rData.mnWinWidth = nWinWidth; + rData.mnWinHeight = nWinHeight; + + if( getBiff() <= BIFF4 ) + { + sal_uInt8 nHidden; + rStrm >> nHidden; + rData.mnVisibility = (nHidden == 0) ? XML_visible : XML_hidden; + } + else + { + sal_uInt16 nFlags, nActiveTab, nFirstVisTab, nSelectCnt, nTabBarWidth; + rStrm >> nFlags >> nActiveTab >> nFirstVisTab >> nSelectCnt >> nTabBarWidth; + + rData.mnActiveSheet = nActiveTab; + rData.mnFirstVisSheet = nFirstVisTab; + rData.mnTabBarWidth = nTabBarWidth; + rData.mnVisibility = getFlagValue( nFlags, BIFF_WINDOW1_HIDDEN, XML_hidden, XML_visible ); + rData.mbMinimized = getFlag( nFlags, BIFF_WINDOW1_MINIMIZED ); + rData.mbShowHorScroll = getFlag( nFlags, BIFF_WINDOW1_SHOWHORSCROLL ); + rData.mbShowVerScroll = getFlag( nFlags, BIFF_WINDOW1_SHOWVERSCROLL ); + rData.mbShowTabBar = getFlag( nFlags, BIFF_WINDOW1_SHOWTABBAR ); + } +} + +void ViewSettings::setSheetViewSettings( sal_Int32 nSheet, const OoxSheetViewDataRef& rxViewData, const Any& rProperties ) +{ + maSheetDatas[ nSheet ] = rxViewData; + maSheetProps[ nSheet ] = rProperties; +} + +void ViewSettings::finalizeImport() +{ + const WorksheetBuffer& rWorksheets = getWorksheets(); + if( rWorksheets.getInternalSheetCount() <= 0 ) return; + + // force creation of workbook view data to get the Excel defaults + const OoxWorkbookViewData& rData = maBookDatas.empty() ? createWorkbookViewData() : *maBookDatas.front(); + + // show object mode is part of workbook settings + sal_Int16 nShowMode = getWorkbookSettings().getApiShowObjectMode(); + + // view settings for all sheets + Reference< XNameContainer > xSheetsNC = ContainerHelper::createNameContainer(); + if( !xSheetsNC.is() ) return; + for( SheetPropertiesMap::const_iterator aIt = maSheetProps.begin(), aEnd = maSheetProps.end(); aIt != aEnd; ++aIt ) + ContainerHelper::insertByName( xSheetsNC, rWorksheets.getFinalSheetName( aIt->first ), aIt->second ); + + // use data of active sheet to set sheet properties that are document-global in Calc + sal_Int32 nActiveSheet = getActiveSheetIndex(); + OoxSheetViewDataRef& rxActiveSheetData = maSheetDatas[ nActiveSheet ]; + OSL_ENSURE( rxActiveSheetData.get(), "ViewSettings::finalizeImport - missing active sheet view settings" ); + if( !rxActiveSheetData ) + rxActiveSheetData.reset( new OoxSheetViewData ); + + PropertySequence aDocProps( sppcDocNames, sppcGlobalSheetNames ); + aDocProps + << xSheetsNC + << rWorksheets.getFinalSheetName( nActiveSheet ) + << rData.mbShowHorScroll + << rData.mbShowVerScroll + << rData.mbShowTabBar + << double( rData.mnTabBarWidth / 1000.0 ) + << nShowMode << nShowMode << nShowMode + << getStyles().getColor( rxActiveSheetData->maGridColor, API_RGB_TRANSPARENT ) + << API_ZOOMTYPE_PERCENT + << static_cast< sal_Int16 >( rxActiveSheetData->getNormalZoom() ) + << static_cast< sal_Int16 >( rxActiveSheetData->getPageBreakZoom() ) + << rxActiveSheetData->isPageBreakPreview() + << rxActiveSheetData->mbShowFormulas + << rxActiveSheetData->mbShowGrid + << rxActiveSheetData->mbShowHeadings + << rxActiveSheetData->mbShowZeros + << rxActiveSheetData->mbShowOutline; + + Reference< XIndexContainer > xContainer = ContainerHelper::createIndexContainer(); + if( xContainer.is() ) try + { + xContainer->insertByIndex( 0, Any( aDocProps.createPropertySequence() ) ); + Reference< XIndexAccess > xIAccess( xContainer, UNO_QUERY_THROW ); + Reference< XViewDataSupplier > xViewDataSuppl( getDocument(), UNO_QUERY_THROW ); + xViewDataSuppl->setViewData( xIAccess ); + } + catch( Exception& ) + { + OSL_ENSURE( false, "ViewSettings::finalizeImport - cannot create document view settings" ); + } +} + +sal_Int32 ViewSettings::getActiveSheetIndex() const +{ + sal_Int32 nSheetCount = getLimitedValue< sal_Int32, sal_Int32 >( getWorksheets().getInternalSheetCount(), 1, SAL_MAX_INT32 ); + return maBookDatas.empty() ? 0 : getLimitedValue< sal_Int32, sal_Int32 >( maBookDatas.front()->mnActiveSheet, 0, nSheetCount - 1 ); +} + +// private -------------------------------------------------------------------- + +OoxWorkbookViewData& ViewSettings::createWorkbookViewData() +{ + OoxWorkbookViewDataRef xData( new OoxWorkbookViewData ); + maBookDatas.push_back( xData ); + return *xData; +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/webquerybuffer.cxx b/oox/source/xls/webquerybuffer.cxx new file mode 100644 index 000000000000..c4ce7953dacd --- /dev/null +++ b/oox/source/xls/webquerybuffer.cxx @@ -0,0 +1,207 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: webquerybuffer.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/webquerybuffer.hxx" +#include "oox/helper/attributelist.hxx" + +#define DEBUG_OOX_WEBQUERY_BUFFER 1 + +#if DEBUG_OOX_WEBQUERY_BUFFER +#include +#endif + +using ::rtl::OUString; + +namespace oox { +namespace xls { + +const sal_Int32 Connection::CONNECTION_ODBC_SOURCE = 1; +const sal_Int32 Connection::CONNECTION_DAO_SOURCE = 2; +const sal_Int32 Connection::CONNECTION_FILE_SOURCE = 3; +const sal_Int32 Connection::CONNECTION_WEBQUERY = 4; +const sal_Int32 Connection::CONNECTION_OLEDB_SOURCE = 5; +const sal_Int32 Connection::CONNECTION_TEXT_SOURCE = 6; +const sal_Int32 Connection::CONNECTION_ADO_RECORD_SET = 7; +const sal_Int32 Connection::CONNECTION_DSP = 8; + +// ============================================================================ + +WebQueryBuffer::WebQueryBuffer( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ) +{ + maQueryTableMap.clear(); +} + +void WebQueryBuffer::importQueryTable( const AttributeList& rAttribs ) +{ + OUString aName = rAttribs.getString( XML_name ); + if ( !aName.getLength() ) + return; + + QueryTable aQTable; + aQTable.mnConnectionId = rAttribs.getInteger( XML_connectionId, 0 ); + + maQueryTableMap.insert( QueryTableHashMap::value_type( aName, aQTable ) ); + + // All documented attributes of queryTable: + // adjustColumnWidth (bool) + // applyAlignmentFormats (bool) + // applyBorderFormats (bool) + // applyFontFormats (bool) + // applyNumberFormats (bool) + // applyPatternFormats (bool) + // applyWidthHeightFormats (bool) + // autoFormatId (unsigned int) + // backgroundRefresh (bool) + // connectionId (unsigned int) + // disableEdit (bool) + // disableRefresh (bool) + // fillFormulas (bool) + // firstBackgroundRefresh (bool) + // growShrinkType (insertClear, insertDelete, overwriteClear) + // headers (bool) + // intermediate (bool) + // name (string) + // preserveFormatting(bool) + // refreshOnLoad (bool) + // removeDataOnSave (bool) + // rowNumbers (bool) +} + +void WebQueryBuffer::importConnection( const AttributeList& rAttribs ) +{ + if ( !rAttribs.hasAttribute( XML_id ) || !rAttribs.hasAttribute( XML_name ) ) + { + mnCurConnId = -1; + return; + } + + sal_uInt32 nId = rAttribs.getUnsignedInteger( XML_id, 0 ); + if ( maConnections.size() < (nId + 1) ) + maConnections.resize(nId + 1); + + Connection aConn; + aConn.maName = rAttribs.getString( XML_name ); + aConn.mnType = rAttribs.getInteger( XML_type, 0 ); + maConnections[nId] = aConn; + mnCurConnId = nId; + + // All documented attributes of connection. + // background (bool) + // credentials (integrated, none, prompt, stored) + // deleted (bool) + // description (string) + // id (unsigned int) + // interval (unsigned int) + // keepAlive (bool) + // minRefreshableVersion (unsigned byte) + // name (string) + // new (bool) + // odcFile (string) + // onlyUseConnectionFile (bool) + // reconnectionMethod (unsigned int) + // refreshedVersion (unsigned byte) + // refreshOnLoad (bool) + // saveData (bool) + // savePassword (bool) + // singleSignOnId (string) + // sourceFile (string) + // type (unsigned int) +} + +void WebQueryBuffer::importWebPr( const AttributeList& rAttribs ) +{ + if ( 0 > mnCurConnId ) + return; + + Connection& rConn = maConnections[mnCurConnId]; + rConn.mpProperties.reset( new WebProperties ); + WebProperties* pWebPr = static_cast< WebProperties* >( rConn.mpProperties.get() ); + pWebPr->maURL = rAttribs.getString( XML_url ); + + // All available attributes: + // consecutive (bool) + // editPage (string) + // firstRow (bool) + // htmlFormat (all, none, rtf) + // htmlTables (bool) + // parsePre (bool) + // post (string) + // sourceData (bool) + // textDates (bool) + // url (string) + // xl2000 (bool) + // xl97 (bool) + // xml (bool) +} + +void WebQueryBuffer::dump() const +{ +#if DEBUG_OOX_WEBQUERY_BUFFER + fprintf(stdout, "----------------------------------------\n"); + { + using ::std::vector; + vector< Connection >::const_iterator itr = maConnections.begin(), itrEnd = maConnections.end(); + sal_Int32 nId = 0; + for (; itr != itrEnd; ++itr, ++nId) + { + if ( itr->mnType == Connection::CONNECTION_WEBQUERY ) + { + WebProperties* pWebPr = static_cast< WebProperties* >( itr->mpProperties.get() ); + fprintf(stdout, "WebQueryBuffer::dump: id = %d url = %s\n", + (int)nId, + OUStringToOString(pWebPr->maURL, RTL_TEXTENCODING_UTF8).getStr()); + } + } + } + + QueryTableHashMap::const_iterator itr = maQueryTableMap.begin(), itrEnd = maQueryTableMap.end(); + for (; itr != itrEnd; ++itr) + { + fprintf(stdout, "WebQueryBuffer::dump: name = %s connection ID = %d\n", + OUStringToOString(itr->first, RTL_TEXTENCODING_UTF8).getStr(), + (int)(itr->second.mnConnectionId)); + } + + fprintf(stdout, "----------------------------------------\n"); + fflush(stdout); +#endif +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/workbookfragment.cxx b/oox/source/xls/workbookfragment.cxx new file mode 100644 index 000000000000..838711bb1198 --- /dev/null +++ b/oox/source/xls/workbookfragment.cxx @@ -0,0 +1,756 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: workbookfragment.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/workbookfragment.hxx" +#include +#include "oox/helper/attributelist.hxx" +#include "oox/helper/progressbar.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/helper/recordinputstream.hxx" +#include "oox/drawingml/themefragmenthandler.hxx" +#include "oox/xls/biffinputstream.hxx" +#include "oox/xls/connectionsfragment.hxx" +#include "oox/xls/externallinkbuffer.hxx" +#include "oox/xls/externallinkfragment.hxx" +#include "oox/xls/pivotcachefragment.hxx" +#include "oox/xls/sharedstringsbuffer.hxx" +#include "oox/xls/sharedstringsfragment.hxx" +#include "oox/xls/stylesfragment.hxx" +#include "oox/xls/tablebuffer.hxx" +#include "oox/xls/themebuffer.hxx" +#include "oox/xls/viewsettings.hxx" +#include "oox/xls/workbooksettings.hxx" +#include "oox/xls/worksheetbuffer.hxx" +#include "oox/xls/worksheetfragment.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::table::CellAddress; +using ::oox::core::FragmentHandlerRef; +using ::oox::core::Relation; +using ::oox::drawingml::ThemeFragmentHandler; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +const double PROGRESS_LENGTH_GLOBALS = 0.1; /// 10% of progress bar for globals import. + +const sal_uInt16 BIFF_FILEPASS_BIFF2 = 0x0000; +const sal_uInt16 BIFF_FILEPASS_BIFF8 = 0x0001; +const sal_uInt16 BIFF_FILEPASS_BIFF8_RCF = 0x0001; +const sal_uInt16 BIFF_FILEPASS_BIFF8_STRONG = 0x0002; + +} // namespace + +// ============================================================================ + +OoxWorkbookFragment::OoxWorkbookFragment( + const WorkbookHelper& rHelper, const OUString& rFragmentPath ) : + OoxWorkbookFragmentBase( rHelper, rFragmentPath ) +{ +} + +// oox.xls.OoxContextHelper interface ----------------------------------------- + +bool OoxWorkbookFragment::onCanCreateContext( sal_Int32 nElement ) const +{ + switch( getCurrentContext() ) + { + case XML_ROOT_CONTEXT: + return (nElement == XLS_TOKEN( workbook )); + case XLS_TOKEN( workbook ): + return (nElement == XLS_TOKEN( workbookPr )) || + (nElement == XLS_TOKEN( calcPr )) || + (nElement == XLS_TOKEN( sheets )) || + (nElement == XLS_TOKEN( bookViews )) || + (nElement == XLS_TOKEN( externalReferences )) || + (nElement == XLS_TOKEN( definedNames )) || + (nElement == XLS_TOKEN( pivotCaches )); + case XLS_TOKEN( sheets ): + return (nElement == XLS_TOKEN( sheet )); + case XLS_TOKEN( bookViews ): + return (nElement == XLS_TOKEN( workbookView )); + case XLS_TOKEN( externalReferences ): + return (nElement == XLS_TOKEN( externalReference )); + case XLS_TOKEN( definedNames ): + return (nElement == XLS_TOKEN( definedName )); + case XLS_TOKEN( pivotCaches ): + return (nElement == XLS_TOKEN( pivotCache )); + } + return false; +} + +void OoxWorkbookFragment::onStartElement( const AttributeList& rAttribs ) +{ + switch( getCurrentContext() ) + { + case XLS_TOKEN( workbookPr ): getWorkbookSettings().importWorkbookPr( rAttribs ); break; + case XLS_TOKEN( calcPr ): getWorkbookSettings().importCalcPr( rAttribs ); break; + case XLS_TOKEN( sheet ): getWorksheets().importSheet( rAttribs ); break; + case XLS_TOKEN( workbookView ): getViewSettings().importWorkbookView( rAttribs ); break; + case XLS_TOKEN( externalReference ): importExternalReference( rAttribs ); break; + case XLS_TOKEN( definedName ): importDefinedName( rAttribs ); break; + case XLS_TOKEN( pivotCache ): importPivotCache( rAttribs ); break; + } +} + +void OoxWorkbookFragment::onEndElement( const OUString& rChars ) +{ + switch( getCurrentContext() ) + { + case XLS_TOKEN( definedName ): + if( mxCurrName.get() ) mxCurrName->setFormula( rChars ); + break; + } +} + +bool OoxWorkbookFragment::onCanCreateRecordContext( sal_Int32 nRecId ) +{ + switch( getCurrentContext() ) + { + case XML_ROOT_CONTEXT: + return (nRecId == OOBIN_ID_WORKBOOK); + case OOBIN_ID_WORKBOOK: + return (nRecId == OOBIN_ID_WORKBOOKPR) || + (nRecId == OOBIN_ID_CALCPR) || + (nRecId == OOBIN_ID_SHEETS) || + (nRecId == OOBIN_ID_BOOKVIEWS) || + (nRecId == OOBIN_ID_EXTERNALREFS) || + (nRecId == OOBIN_ID_DEFINEDNAME); + case OOBIN_ID_SHEETS: + return (nRecId == OOBIN_ID_SHEET); + case OOBIN_ID_BOOKVIEWS: + return (nRecId == OOBIN_ID_WORKBOOKVIEW); + case OOBIN_ID_EXTERNALREFS: + return (nRecId == OOBIN_ID_EXTERNALREF) || + (nRecId == OOBIN_ID_EXTERNALSELF) || + (nRecId == OOBIN_ID_EXTERNALSHEETS); + } + return false; +} + +void OoxWorkbookFragment::onStartRecord( RecordInputStream& rStrm ) +{ + switch( getCurrentContext() ) + { + case OOBIN_ID_WORKBOOKPR: getWorkbookSettings().importWorkbookPr( rStrm ); break; + case OOBIN_ID_CALCPR: getWorkbookSettings().importCalcPr( rStrm ); break; + case OOBIN_ID_SHEET: getWorksheets().importSheet( rStrm ); break; + case OOBIN_ID_WORKBOOKVIEW: getViewSettings().importWorkbookView( rStrm ); break; + case OOBIN_ID_EXTERNALREF: importExternalRef( rStrm ); break; + case OOBIN_ID_EXTERNALSELF: getExternalLinks().importExternalSelf( rStrm ); break; + case OOBIN_ID_EXTERNALSHEETS: getExternalLinks().importExternalSheets( rStrm ); break; + case OOBIN_ID_DEFINEDNAME: getDefinedNames().importDefinedName( rStrm ); break; + } +} + +// oox.xls.OoxFragmentHandler interface --------------------------------------- + +void OoxWorkbookFragment::finalizeImport() +{ + ISegmentProgressBarRef xGlobalSegment = getProgressBar().createSegment( PROGRESS_LENGTH_GLOBALS ); + + // read the theme substream + OUString aThemeFragmentPath = getFragmentPathFromType( CREATE_RELATIONS_TYPE( "theme" ) ); + if( aThemeFragmentPath.getLength() > 0 ) + importOoxFragment( new ThemeFragmentHandler( getFilter(), aThemeFragmentPath, getTheme().getCoreTheme() ) ); + xGlobalSegment->setPosition( 0.25 ); + + // read the styles substream (requires finalized theme buffer) + OUString aStylesFragmentPath = getFragmentPathFromType( CREATE_RELATIONS_TYPE( "styles" ) ); + if( aStylesFragmentPath.getLength() > 0 ) + importOoxFragment( new OoxStylesFragment( *this, aStylesFragmentPath ) ); + xGlobalSegment->setPosition( 0.5 ); + + // read the shared string table substream (requires finalized styles buffer) + OUString aSstFragmentPath = getFragmentPathFromType( CREATE_RELATIONS_TYPE( "sharedStrings" ) ); + if( aSstFragmentPath.getLength() > 0 ) + importOoxFragment( new OoxSharedStringsFragment( *this, aSstFragmentPath ) ); + xGlobalSegment->setPosition( 0.75 ); + + // read the connections substream + OUString aConnFragmentPath = getFragmentPathFromType( CREATE_RELATIONS_TYPE( "connections" ) ); + if( aConnFragmentPath.getLength() > 0 ) + importOoxFragment( new OoxConnectionsFragment( *this, aConnFragmentPath ) ); + xGlobalSegment->setPosition( 1.0 ); + + /* Create fragments for all sheets, before importing them. Needed to do + some preprocessing in the fragment constructors, e.g. loading the table + fragments for all sheets that are needed before the cell formulas are + loaded. */ + typedef ::std::map< sal_Int32, FragmentHandlerRef > SheetFragmentMap; + SheetFragmentMap aSheetFragments; + WorksheetBuffer& rWorksheets = getWorksheets(); + sal_Int32 nSheetCount = rWorksheets.getInternalSheetCount(); + for( sal_Int32 nSheet = 0; nSheet < nSheetCount; ++nSheet ) + { + if( const Relation* pRelation = getRelations().getRelationFromRelId( rWorksheets.getSheetRelId( nSheet ) ) ) + { + // get fragment path of the sheet + OUString aFragmentPath = getFragmentPathFromTarget( pRelation->maTarget ); + OSL_ENSURE( aFragmentPath.getLength() > 0, "OoxWorkbookFragment::finalizeImport - cannot access sheet fragment" ); + if( aFragmentPath.getLength() > 0 ) + { + ::rtl::Reference< OoxWorksheetFragmentBase > xFragment; + double fSegmentLength = getProgressBar().getFreeLength() / (nSheetCount - nSheet); + ISegmentProgressBarRef xSheetSegment = getProgressBar().createSegment( fSegmentLength ); + // create the fragment according to the sheet type + if( pRelation->maType == CREATE_RELATIONS_TYPE( "worksheet" ) ) + xFragment.set( new OoxWorksheetFragment( *this, aFragmentPath, xSheetSegment, SHEETTYPE_WORKSHEET, nSheet ) ); + // insert the fragment into the map + OSL_ENSURE( xFragment.is(), "OoxWorkbookFragment::finalizeImport - unknown sheet type" ); + OSL_ENSURE( !xFragment.is() || xFragment->isValidSheet(), "OoxWorkbookFragment::finalizeImport - missing sheet in document" ); + if( xFragment.is() && xFragment->isValidSheet() ) + aSheetFragments[ nSheet ].set( xFragment.get() ); + } + } + } + + // create all defined names and database ranges + getDefinedNames().finalizeImport(); + getTables().finalizeImport(); + + // load all worksheets + for( sal_Int32 nSheet = 0; nSheet < nSheetCount; ++nSheet ) + { + SheetFragmentMap::iterator aIt = aSheetFragments.find( nSheet ); + if( aIt != aSheetFragments.end() ) + { + // import the sheet fragment + importOoxFragment( aIt->second ); + // delete fragment object, will free all allocated sheet buffers + aSheetFragments.erase( aIt ); + } + } + + // final conversions, e.g. calculation settings and view settings + finalizeWorkbookImport(); + + getPivotTables().finalizeImport(); +} + +// private -------------------------------------------------------------------- + +void OoxWorkbookFragment::importExternalReference( const AttributeList& rAttribs ) +{ + if( ExternalLink* pExtLink = getExternalLinks().importExternalReference( rAttribs ).get() ) + importExternalLinkFragment( *pExtLink ); +} + +void OoxWorkbookFragment::importDefinedName( const AttributeList& rAttribs ) +{ + mxCurrName = getDefinedNames().importDefinedName( rAttribs ); +} + +void OoxWorkbookFragment::importPivotCache( const AttributeList& rAttribs ) +{ + OUString aFragmentPath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ) ) ); + if( (aFragmentPath.getLength() > 0) && rAttribs.hasAttribute( XML_cacheId ) ) + { + sal_uInt32 nCacheId = rAttribs.getUnsignedInteger( XML_cacheId, 0 ); + importOoxFragment( new OoxPivotCacheFragment( *this, aFragmentPath, nCacheId ) ); + } +} + +void OoxWorkbookFragment::importExternalRef( RecordInputStream& rStrm ) +{ + if( ExternalLink* pExtLink = getExternalLinks().importExternalRef( rStrm ).get() ) + importExternalLinkFragment( *pExtLink ); +} + +void OoxWorkbookFragment::importExternalLinkFragment( ExternalLink& rExtLink ) +{ + OUString aFragmentPath = getFragmentPathFromRelId( rExtLink.getRelId() ); + if( aFragmentPath.getLength() > 0 ) + importOoxFragment( new OoxExternalLinkFragment( *this, aFragmentPath, rExtLink ) ); +} + +// ============================================================================ + +namespace { + +BiffDecoderRef lclImportFilePass_XOR( const WorkbookHelper& rHelper, BiffInputStream& rStrm ) +{ + BiffDecoderRef xDecoder; + OSL_ENSURE( rStrm.getRecLeft() == 4, "lclImportFilePass_XOR - wrong record size" ); + if( rStrm.getRecLeft() == 4 ) + { + sal_uInt16 nBaseKey, nHash; + rStrm >> nBaseKey >> nHash; + xDecoder.reset( new BiffDecoder_XOR( rHelper, nBaseKey, nHash ) ); + } + return xDecoder; +} + +BiffDecoderRef lclImportFilePass_RCF( const WorkbookHelper& rHelper, BiffInputStream& rStrm ) +{ + BiffDecoderRef xDecoder; + OSL_ENSURE( rStrm.getRecLeft() == 48, "lclImportFilePass_RCF - wrong record size" ); + if( rStrm.getRecLeft() == 48 ) + { + sal_uInt8 pnDocId[ 16 ]; + sal_uInt8 pnSaltData[ 16 ]; + sal_uInt8 pnSaltHash[ 16 ]; + rStrm.read( pnDocId, 16 ); + rStrm.read( pnSaltData, 16 ); + rStrm.read( pnSaltHash, 16 ); + xDecoder.reset( new BiffDecoder_RCF( rHelper, pnDocId, pnSaltData, pnSaltHash ) ); + } + return xDecoder; +} + +BiffDecoderRef lclImportFilePass_Strong( const WorkbookHelper& /*rHelper*/, BiffInputStream& /*rStrm*/ ) +{ + // not supported + return BiffDecoderRef(); +} + +BiffDecoderRef lclImportFilePass2( const WorkbookHelper& rHelper, BiffInputStream& rStrm ) +{ + return lclImportFilePass_XOR( rHelper, rStrm ); +} + +BiffDecoderRef lclImportFilePass8( const WorkbookHelper& rHelper, BiffInputStream& rStrm ) +{ + BiffDecoderRef xDecoder; + + switch( rStrm.readuInt16() ) + { + case BIFF_FILEPASS_BIFF2: + xDecoder = lclImportFilePass_XOR( rHelper, rStrm ); + break; + + case BIFF_FILEPASS_BIFF8: + switch( rStrm.skip( 2 ).readuInt16() ) + { + case BIFF_FILEPASS_BIFF8_RCF: + xDecoder = lclImportFilePass_RCF( rHelper, rStrm ); + break; + case BIFF_FILEPASS_BIFF8_STRONG: + xDecoder = lclImportFilePass_Strong( rHelper, rStrm ); + break; + default: + OSL_ENSURE( false, "lclImportFilePass8 - unknown BIFF8 encryption sub mode" ); + } + break; + + default: + OSL_ENSURE( false, "lclImportFilePass8 - unknown encryption mode" ); + } + + return xDecoder; +} + +} // namespace + +// ---------------------------------------------------------------------------- + +BiffWorkbookFragment::BiffWorkbookFragment( const WorkbookHelper& rHelper ) : + BiffWorkbookFragmentBase( rHelper ) +{ +} + +bool BiffWorkbookFragment::importFragment( BiffInputStream& rStrm ) +{ + bool bRet = false; + + BiffFragmentType eFragment = startFragment( rStrm, getBiff() ); + switch( eFragment ) + { + case BIFF_FRAGMENT_GLOBALS: + { + // import workbook globals fragment and create sheets in document + ISegmentProgressBarRef xGlobalsProgress = getProgressBar().createSegment( PROGRESS_LENGTH_GLOBALS ); + bRet = importGlobalsFragment( rStrm, *xGlobalsProgress ); + // load sheet fragments (do not return false in bRet on missing/broken sheets) + WorksheetBuffer& rWorksheets = getWorksheets(); + bool bNextSheet = bRet; + for( sal_Int32 nSheet = 0, nSheetCount = rWorksheets.getInternalSheetCount(); bNextSheet && (nSheet < nSheetCount); ++nSheet ) + { + // try to start a new sheet fragment + double fSegmentLength = getProgressBar().getFreeLength() / (nSheetCount - nSheet); + ISegmentProgressBarRef xSheetProgress = getProgressBar().createSegment( fSegmentLength ); + BiffFragmentType eSheetFragment = startFragment( rStrm, getBiff() ); + bNextSheet = importSheetFragment( rStrm, *xSheetProgress, eSheetFragment, nSheet ); + } + } + break; + + case BIFF_FRAGMENT_WORKSPACE: + { + bRet = importWorkspaceFragment( rStrm ); + // sheets are embedded in workspace fragment, nothing to do here + } + break; + + case BIFF_FRAGMENT_WORKSHEET: + case BIFF_FRAGMENT_CHART: + case BIFF_FRAGMENT_MACRO: + { + /* Single sheet without globals + - #i62752# possible in all BIFF versions + - do not return false in bRet on missing/broken sheets. */ + getWorksheets().initializeSingleSheet(); + importSheetFragment( rStrm, getProgressBar(), eFragment, 0 ); + // success, even if stream is broken + bRet = true; + } + break; + + default:; + } + + // final conversions, e.g. calculation settings and view settings + finalizeWorkbookImport(); + + return bRet; +} + +bool BiffWorkbookFragment::importWorkspaceFragment( BiffInputStream& rStrm ) +{ + // enable workbook mode, has not been set yet in BIFF4 workspace files + setIsWorkbookFile(); + + WorksheetBuffer& rWorksheets = getWorksheets(); + bool bRet = true; + + // import the workspace globals + ISegmentProgressBarRef xGlobalsProgress = getProgressBar().createSegment( PROGRESS_LENGTH_GLOBALS ); + bool bLoop = true; + while( bRet && bLoop && rStrm.startNextRecord() && (rStrm.getRecId() != BIFF_ID_EOF) ) + { + switch( rStrm.getRecId() ) + { + case BIFF_ID_SHEET: rWorksheets.importSheet( rStrm ); break; + case BIFF_ID_CODEPAGE: setCodePage( rStrm.readuInt16() ); break; + case BIFF_ID_FILEPASS: bRet = importFilePass( rStrm ); break; + case BIFF_ID_SHEETHEADER: rStrm.rewindRecord(); bLoop = false; break; + } + } + xGlobalsProgress->setPosition( 1.0 ); + + // load sheet fragments (do not return false in bRet on missing/broken sheets) + bool bNextSheet = bRet; + for( sal_Int32 nSheet = 0, nSheetCount = rWorksheets.getInternalSheetCount(); bNextSheet && (nSheet < nSheetCount); ++nSheet ) + { + // try to start a new sheet fragment (with leading SHEETHEADER record) + bNextSheet = rStrm.startNextRecord() && (rStrm.getRecId() == BIFF_ID_SHEETHEADER); + if( bNextSheet ) + { + double fSegmentLength = getProgressBar().getFreeLength() / (nSheetCount - nSheet); + ISegmentProgressBarRef xSheetProgress = getProgressBar().createSegment( fSegmentLength ); + /* Read current sheet name (sheet substreams may not be in the + same order as SHEET records are). */ + OUString aSheetName = rStrm.skip( 4 ).readByteString( false, getTextEncoding() ); + sal_Int32 nCurrSheet = rWorksheets.getFinalSheetIndex( aSheetName ); + // load the sheet fragment records + BiffFragmentType eSheetFragment = startFragment( rStrm, getBiff() ); + bNextSheet = importSheetFragment( rStrm, *xSheetProgress, eSheetFragment, nCurrSheet ); + // do not return false in bRet on missing/broken sheets + } + } + + return bRet; +} + +bool BiffWorkbookFragment::importGlobalsFragment( BiffInputStream& rStrm, ISegmentProgressBar& rProgressBar ) +{ + WorkbookSettings& rWorkbookSett = getWorkbookSettings(); + ViewSettings& rViewSett = getViewSettings(); + SharedStringsBuffer& rSharedStrings = getSharedStrings(); + StylesBuffer& rStyles = getStyles(); + WorksheetBuffer& rWorksheets = getWorksheets(); + + // collect records that need to be loaded in a second pass + typedef ::std::vector< sal_Int64 > RecordHandleVec; + RecordHandleVec aExtLinkRecs; + + bool bRet = true; + bool bLoop = true; + while( bRet && bLoop && rStrm.startNextRecord() ) + { + sal_uInt16 nRecId = rStrm.getRecId(); + bool bExtLinkRec = false; + + /* #i56376# BIFF5-BIFF8: If an EOF record for globals is missing, + simulate it. The issue is about a document where the sheet fragment + starts directly after the EXTSST record, without terminating the + globals fragment with an EOF record. */ + if( isBofRecord( nRecId ) || (nRecId == BIFF_ID_EOF) ) + { + bLoop = false; + } + else switch( nRecId ) + { + // records in all BIFF versions + case BIFF_ID_CODEPAGE: setCodePage( rStrm.readuInt16() ); break; + case BIFF_ID_DATEMODE: rWorkbookSett.importDateMode( rStrm ); break; + case BIFF_ID_FILEPASS: bRet = importFilePass( rStrm ); break; + case BIFF_ID_PRECISION: rWorkbookSett.importPrecision( rStrm ); break; + case BIFF_ID_WINDOW1: rViewSett.importWindow1( rStrm ); break; + + // BIFF specific records + default: switch( getBiff() ) + { + case BIFF2: switch( nRecId ) + { + case BIFF2_ID_DEFINEDNAME: bExtLinkRec = true; break; + case BIFF2_ID_EXTERNALNAME: bExtLinkRec = true; break; + case BIFF_ID_EXTERNSHEET: bExtLinkRec = true; break; + case BIFF2_ID_FONT: rStyles.importFont( rStrm ); break; + case BIFF_ID_FONTCOLOR: rStyles.importFontColor( rStrm ); break; + case BIFF2_ID_FORMAT: rStyles.importFormat( rStrm ); break; + case BIFF2_ID_XF: rStyles.importXf( rStrm ); break; + } + break; + + case BIFF3: switch( nRecId ) + { + case BIFF_ID_CRN: bExtLinkRec = true; break; + case BIFF3_ID_DEFINEDNAME: bExtLinkRec = true; break; + case BIFF3_ID_EXTERNALNAME: bExtLinkRec = true; break; + case BIFF_ID_EXTERNSHEET: bExtLinkRec = true; break; + case BIFF3_ID_FONT: rStyles.importFont( rStrm ); break; + case BIFF2_ID_FORMAT: rStyles.importFormat( rStrm ); break; + case BIFF_ID_HIDEOBJ: rWorkbookSett.importHideObj( rStrm ); break; + case BIFF_ID_PALETTE: rStyles.importPalette( rStrm ); break; + case BIFF_ID_STYLE: rStyles.importStyle( rStrm ); break; + case BIFF_ID_XCT: bExtLinkRec = true; break; + case BIFF3_ID_XF: rStyles.importXf( rStrm ); break; + } + break; + + case BIFF4: switch( nRecId ) + { + case BIFF_ID_CRN: bExtLinkRec = true; break; + case BIFF3_ID_DEFINEDNAME: bExtLinkRec = true; break; + case BIFF3_ID_EXTERNALNAME: bExtLinkRec = true; break; + case BIFF_ID_EXTERNSHEET: bExtLinkRec = true; break; + case BIFF3_ID_FONT: rStyles.importFont( rStrm ); break; + case BIFF4_ID_FORMAT: rStyles.importFormat( rStrm ); break; + case BIFF_ID_HIDEOBJ: rWorkbookSett.importHideObj( rStrm ); break; + case BIFF_ID_PALETTE: rStyles.importPalette( rStrm ); break; + case BIFF_ID_STYLE: rStyles.importStyle( rStrm ); break; + case BIFF_ID_XCT: bExtLinkRec = true; break; + case BIFF4_ID_XF: rStyles.importXf( rStrm ); break; + } + break; + + case BIFF5: switch( nRecId ) + { + case BIFF_ID_BOOKBOOL: rWorkbookSett.importBookBool( rStrm ); break; + case BIFF_ID_CRN: bExtLinkRec = true; break; + case BIFF5_ID_DEFINEDNAME: bExtLinkRec = true; break; + case BIFF5_ID_EXTERNALNAME: bExtLinkRec = true; break; + case BIFF_ID_EXTERNSHEET: bExtLinkRec = true; break; + case BIFF5_ID_FONT: rStyles.importFont( rStrm ); break; + case BIFF4_ID_FORMAT: rStyles.importFormat( rStrm ); break; + case BIFF_ID_HIDEOBJ: rWorkbookSett.importHideObj( rStrm ); break; + case BIFF_ID_PALETTE: rStyles.importPalette( rStrm ); break; + case BIFF_ID_SHEET: rWorksheets.importSheet( rStrm ); break; + case BIFF_ID_STYLE: rStyles.importStyle( rStrm ); break; + case BIFF_ID_XCT: bExtLinkRec = true; break; + case BIFF5_ID_XF: rStyles.importXf( rStrm ); break; + } + break; + + case BIFF8: switch( nRecId ) + { + case BIFF_ID_BOOKBOOL: rWorkbookSett.importBookBool( rStrm ); break; + case BIFF_ID_CODENAME: rWorkbookSett.importCodeName( rStrm ); break; + case BIFF_ID_CRN: bExtLinkRec = true; break; + case BIFF5_ID_DEFINEDNAME: bExtLinkRec = true; break; + case BIFF_ID_EXTERNALBOOK: bExtLinkRec = true; break; + case BIFF5_ID_EXTERNALNAME: bExtLinkRec = true; break; + case BIFF_ID_EXTERNSHEET: bExtLinkRec = true; break; + case BIFF5_ID_FONT: rStyles.importFont( rStrm ); break; + case BIFF4_ID_FORMAT: rStyles.importFormat( rStrm ); break; + case BIFF_ID_HIDEOBJ: rWorkbookSett.importHideObj( rStrm ); break; + case BIFF_ID_PALETTE: rStyles.importPalette( rStrm ); break; + case BIFF_ID_SHEET: rWorksheets.importSheet( rStrm ); break; + case BIFF_ID_SST: rSharedStrings.importSst( rStrm ); break; + case BIFF_ID_STYLE: rStyles.importStyle( rStrm ); break; + case BIFF_ID_USESELFS: rWorkbookSett.importUsesElfs( rStrm ); break; + case BIFF_ID_XCT: bExtLinkRec = true; break; + case BIFF5_ID_XF: rStyles.importXf( rStrm ); break; + } + break; + + case BIFF_UNKNOWN: break; + } + } + + if( bExtLinkRec ) + aExtLinkRecs.push_back( rStrm.getRecHandle() ); + } + + // finalize global buffers + rProgressBar.setPosition( 0.5 ); + rSharedStrings.finalizeImport(); + rStyles.finalizeImport(); + + /* Import external link data (EXTERNSHEET, EXTERNALNAME, DEFINEDNAME) + which need existing internal sheets (SHEET records). The SHEET records + may follow the external links records in some BIFF versions. */ + if( bRet && !aExtLinkRecs.empty() ) + { + // remember current stream position (the EOF record) + sal_Int64 nEofHandle = rStrm.getRecHandle(); + // this fragment class implements import of external link records + BiffExternalLinkFragment aLinkFragment( *this, true ); + // import all records by using their cached record handle + for( RecordHandleVec::const_iterator aIt = aExtLinkRecs.begin(), aEnd = aExtLinkRecs.end(); (aIt != aEnd) && rStrm.startRecordByHandle( *aIt ); ++aIt ) + aLinkFragment.importRecord( rStrm ); + // finalize global buffers + aLinkFragment.finalizeImport(); + // seek back to the EOF record of the workbook globals fragment + bRet = rStrm.startRecordByHandle( nEofHandle ); + } + + // #i56376# missing EOF - rewind before worksheet BOF record (see above) + if( bRet && isBofRecord( rStrm.getRecId() ) ) + rStrm.rewindRecord(); + + rProgressBar.setPosition( 1.0 ); + return bRet; +} + +bool BiffWorkbookFragment::importSheetFragment( BiffInputStream& rStrm, ISegmentProgressBar& rProgressBar, BiffFragmentType eFragment, sal_Int32 nSheet ) +{ + // find the sheet type for this fragment + WorksheetType eSheetType = SHEETTYPE_WORKSHEET; + bool bSkipSheet = false; + switch( eFragment ) + { + case BIFF_FRAGMENT_WORKSHEET: eSheetType = SHEETTYPE_WORKSHEET; break; + case BIFF_FRAGMENT_CHART: eSheetType = SHEETTYPE_CHART; break; + case BIFF_FRAGMENT_MACRO: eSheetType = SHEETTYPE_MACRO; break; + case BIFF_FRAGMENT_EMPTYSHEET: bSkipSheet = true; break; + default: return false; + } + + // skip this worksheet fragment (e.g. fragment type is BIFF_FRAGMENT_EMPTYSHEET) + if( bSkipSheet ) + { + rProgressBar.setPosition( 1.0 ); + return skipFragment( rStrm ); + } + + /* #i11183# Clear buffers that are used per-sheet, e.g. external links in + BIFF4W and BIFF5 files, or defined names in BIFF4W files. */ + createBuffersPerSheet(); + + // preprocess some records + switch( getBiff() ) + { + // load the workbook globals fragment records in BIFF2-BIFF4 + case BIFF2: + case BIFF3: + case BIFF4: + { + // set sheet index in defined names buffer to handle built-in names correctly + getDefinedNames().setLocalSheetIndex( nSheet ); + // remember current record to seek back below + sal_Int64 nRecHandle = rStrm.getRecHandle(); + // import the global records + ISegmentProgressBarRef xGlobalsProgress = rProgressBar.createSegment( PROGRESS_LENGTH_GLOBALS ); + importGlobalsFragment( rStrm, *xGlobalsProgress ); + // rewind stream to fragment BOF record + rStrm.startRecordByHandle( nRecHandle ); + } + break; + + // load the external link records for this sheet in BIFF5 + case BIFF5: + { + // remember current record to seek back below + sal_Int64 nRecHandle = rStrm.getRecHandle(); + // fragment implementing import of external link records + BiffExternalLinkFragment( *this, false ).importFragment( rStrm ); + // rewind stream to fragment BOF record + rStrm.startRecordByHandle( nRecHandle ); + } + break; + + case BIFF8: + break; + + case BIFF_UNKNOWN: + break; + } + + // create the worksheet fragment + ISegmentProgressBarRef xSheetProgress = rProgressBar.createSegment( rProgressBar.getFreeLength() ); + ::boost::shared_ptr< BiffWorksheetFragmentBase > xFragment; + switch( eSheetType ) + { + case SHEETTYPE_WORKSHEET: + case SHEETTYPE_MACRO: + xFragment.reset( new BiffWorksheetFragment( *this, xSheetProgress, eSheetType, nSheet ) ); + break; + case SHEETTYPE_CHART: + xFragment.reset( new BiffWorksheetFragmentBase( *this, xSheetProgress, eSheetType, nSheet ) ); + break; + } + // load the sheet fragment records + return xFragment->isValidSheet() && xFragment->importFragment( rStrm ); +} + +bool BiffWorkbookFragment::importFilePass( BiffInputStream& rStrm ) +{ + rStrm.enableDecoder( false ); + BiffDecoderRef xDecoder = (getBiff() == BIFF8) ? + lclImportFilePass8( *this, rStrm ) : lclImportFilePass2( *this, rStrm ); + + // set decoder at import stream + rStrm.setDecoder( xDecoder ); + //! TODO remember encryption state for export +// rStrm.GetRoot().GetExtDocOptions().GetDocSettings().mbEncrypted = true; + + return xDecoder.get() && xDecoder->isValid(); +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/workbookhelper.cxx b/oox/source/xls/workbookhelper.cxx new file mode 100644 index 000000000000..72c599a75437 --- /dev/null +++ b/oox/source/xls/workbookhelper.cxx @@ -0,0 +1,876 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: workbookhelper.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/workbookhelper.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "oox/helper/progressbar.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/core/binaryfilterbase.hxx" +#include "oox/core/xmlfilterbase.hxx" +#include "oox/xls/addressconverter.hxx" +#include "oox/xls/defnamesbuffer.hxx" +#include "oox/xls/externallinkbuffer.hxx" +#include "oox/xls/formulaparser.hxx" +#include "oox/xls/pagesettings.hxx" +#include "oox/xls/pivottablebuffer.hxx" +#include "oox/xls/sharedstringsbuffer.hxx" +#include "oox/xls/stylesbuffer.hxx" +#include "oox/xls/stylespropertyhelper.hxx" +#include "oox/xls/tablebuffer.hxx" +#include "oox/xls/themebuffer.hxx" +#include "oox/xls/unitconverter.hxx" +#include "oox/xls/validationpropertyhelper.hxx" +#include "oox/xls/viewsettings.hxx" +#include "oox/xls/webquerybuffer.hxx" +#include "oox/xls/workbooksettings.hxx" +#include "oox/xls/worksheetbuffer.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::container::XIndexAccess; +using ::com::sun::star::container::XNameAccess; +using ::com::sun::star::container::XNameContainer; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::awt::XDevice; +using ::com::sun::star::document::XActionLockable; +using ::com::sun::star::sheet::XSpreadsheetDocument; +using ::com::sun::star::sheet::XSpreadsheet; +using ::com::sun::star::sheet::XNamedRanges; +using ::com::sun::star::sheet::XDatabaseRanges; +using ::com::sun::star::style::XStyle; +using ::com::sun::star::style::XStyleFamiliesSupplier; +using ::oox::core::BinaryFilterBase; +using ::oox::core::FilterBase; +using ::oox::core::FragmentHandler; +using ::oox::core::XmlFilterBase; + +// Set this define to 1 to show the load/save time of a document in an assertion. +#define OOX_SHOW_LOADSAVE_TIME 0 + +namespace oox { +namespace xls { + +// ============================================================================ + +#if OSL_DEBUG_LEVEL > 0 + +struct WorkbookDataDebug +{ +#if OOX_SHOW_LOADSAVE_TIME + TimeValue maStartTime; +#endif + sal_Int32 mnDebugCount; + + explicit WorkbookDataDebug(); + ~WorkbookDataDebug(); +}; + +WorkbookDataDebug::WorkbookDataDebug() : + mnDebugCount( 0 ) +{ +#if OOX_SHOW_LOADSAVE_TIME + osl_getSystemTime( &maStartTime ); +#endif +} + +WorkbookDataDebug::~WorkbookDataDebug() +{ +#if OOX_SHOW_LOADSAVE_TIME + TimeValue aEndTime; + osl_getSystemTime( &aEndTime ); + sal_Int32 nMillis = (aEndTime.Seconds - maStartTime.Seconds) * 1000 + static_cast< sal_Int32 >( aEndTime.Nanosec - maStartTime.Nanosec ) / 1000000; + OSL_ENSURE( false, OStringBuffer( "load/save time = " ).append( nMillis / 1000.0 ).append( " seconds" ).getStr() ); +#endif + OSL_ENSURE( mnDebugCount == 0, "WorkbookDataDebug::~WorkbookDataDebug - failed to delete some objects" ); +} + +#endif + +// ============================================================================ + +class WorkbookData +#if OSL_DEBUG_LEVEL > 0 + : public WorkbookDataDebug +#endif +{ +public: + explicit WorkbookData( XmlFilterBase& rFilter ); + explicit WorkbookData( BinaryFilterBase& rFilter, BiffType eBiff ); + ~WorkbookData(); + + /** Returns true, if this helper refers to a valid document. */ + inline bool isValid() const { return mxDoc.is(); } + + // filter ----------------------------------------------------------------- + + /** Returns the base filter object (base class of all filters). */ + inline FilterBase& getBaseFilter() const { return mrBaseFilter; } + /** Returns the filter progress bar. */ + inline SegmentProgressBar& getProgressBar() const { return *mxProgressBar; } + /** Returns the file type of the current filter. */ + inline FilterType getFilterType() const { return meFilterType; } + /** Returns true, if the file is a multi-sheet document, or false if single-sheet. */ + inline bool isWorkbookFile() const { return mbWorkbook; } + + // document model --------------------------------------------------------- + + /** Returns a reference to the source/target spreadsheet document model. */ + inline Reference< XSpreadsheetDocument > getDocument() const { return mxDoc; } + /** Returns a reference to the specified spreadsheet in the document model. */ + Reference< XSpreadsheet > getSheet( sal_Int32 nSheet ) const; + /** Returns the reference device of the document. */ + Reference< XDevice > getReferenceDevice() const; + /** Returns the container for defined names from the Calc document. */ + Reference< XNamedRanges > getNamedRanges() const; + /** Returns the container for database ranges from the Calc document. */ + Reference< XDatabaseRanges > getDatabaseRanges() const; + /** Returns the container for DDE links from the Calc document. */ + Reference< XNameAccess > getDdeLinks() const; + /** Returns the cell or page styles container from the Calc document. */ + Reference< XNameContainer > getStyleFamily( bool bPageStyles ) const; + /** Returns the specified cell or page style from the Calc document. */ + Reference< XStyle > getStyleObject( const OUString& rStyleName, bool bPageStyle ) const; + /** Creates a com.sun.star.style.Style object and returns its final name. */ + Reference< XStyle > createStyleObject( OUString& orStyleName, bool bPageStyle, bool bRenameOldExisting ); + + // buffers ---------------------------------------------------------------- + + /** Returns the global workbook settings object. */ + inline WorkbookSettings& getWorkbookSettings() const { return *mxWorkbookSettings; } + /** Returns the workbook and sheet view settings object. */ + inline ViewSettings& getViewSettings() const { return *mxViewSettings; } + /** Returns the worksheet buffer containing sheet names and properties. */ + inline WorksheetBuffer& getWorksheets() const { return *mxWorksheets; } + /** Returns the office theme object read from the theme substorage. */ + inline ThemeBuffer& getTheme() const { return *mxTheme; } + /** Returns all cell formatting objects read from the styles substream. */ + inline StylesBuffer& getStyles() const { return *mxStyles; } + /** Returns the shared strings read from the shared strings substream. */ + inline SharedStringsBuffer& getSharedStrings() const { return *mxSharedStrings; } + /** Returns the external links read from the external links substream. */ + inline ExternalLinkBuffer& getExternalLinks() const { return *mxExtLinks; } + /** Returns the defined names read from the workbook globals. */ + inline DefinedNamesBuffer& getDefinedNames() const { return *mxDefNames; } + /** Returns the tables collection (equivalent to Calc's database ranges). */ + inline TableBuffer& getTables() const { return *mxTables; } + /** Returns the web queries. */ + inline WebQueryBuffer& getWebQueries() const { return *mxWebQueries; } + /** Returns the pivot tables. */ + inline PivotTableBuffer& getPivotTables() const { return *mxPivotTables; } + + // converters ------------------------------------------------------------- + + /** Returns the import formula parser. */ + inline FormulaParser& getFormulaParser() const { return *mxFmlaParser; } + /** Returns the measurement unit converter. */ + inline UnitConverter& getUnitConverter() const { return *mxUnitConverter; } + /** Returns the converter for string to cell address/range conversion. */ + inline AddressConverter& getAddressConverter() const { return *mxAddrConverter; } + /** Returns the converter for properties related to cell styles. */ + inline StylesPropertyHelper& getStylesPropertyHelper() const { return *mxStylesPropHlp; } + /** Returns the converter for properties related to page/print settings. */ + inline PageSettingsPropertyHelper& getPageSettingsPropertyHelper() const { return *mxPageSettPropHlp; } + /** Returns the converter for properties related to data validation. */ + inline ValidationPropertyHelper& getValidationPropertyHelper() const { return *mxValidationPropHlp; } + + // OOX specific ----------------------------------------------------------- + + /** Returns the base OOX filter object. */ + inline XmlFilterBase& getOoxFilter() const { return *mpOoxFilter; } + + // BIFF specific ---------------------------------------------------------- + + /** Returns the base BIFF filter object. */ + inline BinaryFilterBase& getBiffFilter() const { return *mpBiffFilter; } + /** Returns the BIFF type in binary filter. */ + inline BiffType getBiff() const { return meBiff; } + /** Returns the text encoding used to import/export byte strings. */ + inline rtl_TextEncoding getTextEncoding() const { return meTextEnc; } + /** Sets the text encoding to import/export byte strings. */ + void setTextEncoding( rtl_TextEncoding eTextEnc ); + /** Sets code page read from a CODEPAGE record for byte string import. */ + void setCodePage( sal_uInt16 nCodePage ); + /** Sets text encoding from the default application font, if CODEPAGE record is missing. */ + void setAppFontEncoding( rtl_TextEncoding eAppFontEnc ); + /** Enables workbook file mode, used for BIFF4 workspace files. */ + void setIsWorkbookFile(); + /** Recreates global buffers that are used per sheet in specific BIFF versions. */ + void createBuffersPerSheet(); + /** Looks for a password provided via API, or queries it via GUI. */ + OUString queryPassword(); + +private: + /** Initializes some basic members and sets needed document properties. */ + void initialize(); + /** Finalizes the filter process (sets some needed document properties). */ + void finalize(); + +private: + typedef ::std::auto_ptr< SegmentProgressBar > ProgressBarPtr; + typedef ::std::auto_ptr< WorkbookSettings > WorkbookSettPtr; + typedef ::std::auto_ptr< ViewSettings > ViewSettingsPtr; + typedef ::std::auto_ptr< WorksheetBuffer > WorksheetBfrPtr; + typedef ::std::auto_ptr< ThemeBuffer > ThemeBfrPtr; + typedef ::std::auto_ptr< StylesBuffer > StylesBfrPtr; + typedef ::std::auto_ptr< SharedStringsBuffer > SharedStrBfrPtr; + typedef ::std::auto_ptr< ExternalLinkBuffer > ExtLinkBfrPtr; + typedef ::std::auto_ptr< DefinedNamesBuffer > DefNamesBfrPtr; + typedef ::std::auto_ptr< TableBuffer > TableBfrPtr; + typedef ::std::auto_ptr< WebQueryBuffer > WebQueryBfrPtr; + typedef ::std::auto_ptr< PivotTableBuffer > PivotTableBfrPtr; + typedef ::std::auto_ptr< UnitConverter > UnitConvPtr; + typedef ::std::auto_ptr< AddressConverter > AddressConvPtr; + typedef ::std::auto_ptr< StylesPropertyHelper > StylesPropHlpPtr; + typedef ::std::auto_ptr< PageSettingsPropertyHelper > PageSettPropHlpPtr; + typedef ::std::auto_ptr< ValidationPropertyHelper > ValidationPropHlpPtr; + typedef ::std::auto_ptr< FormulaParser > FormulaParserPtr; + + OUString maRefDeviceProp; /// Property name for reference device. + OUString maNamedRangesProp; /// Property name for defined names. + OUString maDatabaseRangesProp; /// Property name for database ranges. + OUString maDdeLinksProp; /// Property name for DDE links. + OUString maCellStylesProp; /// Property name for cell styles. + OUString maPageStylesProp; /// Property name for page styles. + OUString maCellStyleServ; /// Service name for a cell style. + OUString maPageStyleServ; /// Service name for a page style. + Reference< XSpreadsheetDocument > mxDoc; /// Document model. + FilterBase& mrBaseFilter; /// Base filter object. + FilterType meFilterType; /// File type of the filter. + ProgressBarPtr mxProgressBar; /// The progress bar. + bool mbWorkbook; /// True = multi-sheet file. + + // buffers + WorkbookSettPtr mxWorkbookSettings; /// Global workbook settings. + ViewSettingsPtr mxViewSettings; /// Workbook and sheet view settings. + WorksheetBfrPtr mxWorksheets; /// Sheet info buffer. + ThemeBfrPtr mxTheme; /// Formatting theme from theme substream. + StylesBfrPtr mxStyles; /// All cell style objects from styles substream. + SharedStrBfrPtr mxSharedStrings; /// All strings from shared strings substream. + ExtLinkBfrPtr mxExtLinks; /// All external links. + DefNamesBfrPtr mxDefNames; /// All defined names. + TableBfrPtr mxTables; /// All tables (database ranges). + WebQueryBfrPtr mxWebQueries; /// Web queries buffer. + PivotTableBfrPtr mxPivotTables; /// Pivot tables buffer. + + // converters/helpers + FormulaParserPtr mxFmlaParser; /// Import formula parser. + UnitConvPtr mxUnitConverter; /// General unit converter. + AddressConvPtr mxAddrConverter; /// Cell address and cell range address converter. + StylesPropHlpPtr mxStylesPropHlp; /// Helper for all styles properties. + PageSettPropHlpPtr mxPageSettPropHlp; /// Helper for page/print properties. + ValidationPropHlpPtr mxValidationPropHlp; /// Helper for data validation properties. + + // OOX specific + XmlFilterBase* mpOoxFilter; /// Base OOX filter object. + + // BIFF specific + BinaryFilterBase* mpBiffFilter; /// Base BIFF filter object. + ::rtl::OUString maPassword; /// Password for stream encoder/decoder. + BiffType meBiff; /// BIFF version for BIFF import/export. + rtl_TextEncoding meTextEnc; /// BIFF byte string text encoding. + bool mbHasCodePage; /// True = CODEPAGE record exists in imported stream. + bool mbHasPassword; /// True = password already querried. +}; + +// ---------------------------------------------------------------------------- + +WorkbookData::WorkbookData( XmlFilterBase& rFilter ) : + mrBaseFilter( rFilter ), + meFilterType( FILTER_OOX ), + mpOoxFilter( &rFilter ), + meBiff( BIFF_UNKNOWN ) +{ + initialize(); +} + +WorkbookData::WorkbookData( BinaryFilterBase& rFilter, BiffType eBiff ) : + mrBaseFilter( rFilter ), + meFilterType( FILTER_BIFF ), + mpBiffFilter( &rFilter ), + meBiff( eBiff ) +{ + initialize(); +} + +WorkbookData::~WorkbookData() +{ + finalize(); +} + +// document model ------------------------------------------------------------- + +Reference< XDevice > WorkbookData::getReferenceDevice() const +{ + PropertySet aPropSet( mxDoc ); + Reference< XDevice > xDevice; + aPropSet.getProperty( xDevice, maRefDeviceProp ); + return xDevice; +} + +Reference< XNamedRanges > WorkbookData::getNamedRanges() const +{ + PropertySet aPropSet( mxDoc ); + Reference< XNamedRanges > xNamedRanges; + aPropSet.getProperty( xNamedRanges, maNamedRangesProp ); + return xNamedRanges; +} + +Reference< XDatabaseRanges > WorkbookData::getDatabaseRanges() const +{ + PropertySet aPropSet( mxDoc ); + Reference< XDatabaseRanges > xDatabaseRanges; + aPropSet.getProperty( xDatabaseRanges, maDatabaseRangesProp ); + return xDatabaseRanges; +} + +Reference< XNameAccess > WorkbookData::getDdeLinks() const +{ + PropertySet aPropSet( mxDoc ); + Reference< XNameAccess > xDdeLinks; + aPropSet.getProperty( xDdeLinks, maDdeLinksProp ); + return xDdeLinks; +} + +Reference< XNameContainer > WorkbookData::getStyleFamily( bool bPageStyles ) const +{ + Reference< XNameContainer > xStylesNC; + try + { + Reference< XStyleFamiliesSupplier > xFamiliesSup( mxDoc, UNO_QUERY_THROW ); + Reference< XNameAccess > xFamiliesNA( xFamiliesSup->getStyleFamilies(), UNO_QUERY_THROW ); + xStylesNC.set( xFamiliesNA->getByName( bPageStyles ? maPageStylesProp : maCellStylesProp ), UNO_QUERY_THROW ); + } + catch( Exception& ) + { + } + OSL_ENSURE( xStylesNC.is(), "WorkbookData::getStyleFamily - cannot access style family" ); + return xStylesNC; +} + +Reference< XStyle > WorkbookData::getStyleObject( const OUString& rStyleName, bool bPageStyle ) const +{ + Reference< XStyle > xStyle; + Reference< XNameContainer > xStylesNC = getStyleFamily( bPageStyle ); + if( xStylesNC.is() ) try + { + xStyle.set( xStylesNC->getByName( rStyleName ), UNO_QUERY_THROW ); + } + catch( Exception& ) + { + } + OSL_ENSURE( xStyle.is(), "WorkbookData::getStyleObject - cannot access style object" ); + return xStyle; +} + +Reference< XStyle > WorkbookData::createStyleObject( OUString& orStyleName, bool bPageStyle, bool bRenameOldExisting ) +{ + Reference< XStyle > xStyle; + Reference< XNameContainer > xStylesNC = getStyleFamily( bPageStyle ); + if( xStylesNC.is() ) try + { + Reference< XMultiServiceFactory > xFactory( mxDoc, UNO_QUERY_THROW ); + xStyle.set( xFactory->createInstance( bPageStyle ? maPageStyleServ : maCellStyleServ ), UNO_QUERY_THROW ); + orStyleName = ContainerHelper::insertByUnusedName( xStylesNC, Any( xStyle ), orStyleName, ' ', bRenameOldExisting ); + } + catch( Exception& ) + { + } + OSL_ENSURE( xStyle.is(), "WorkbookData::createStyleObject - cannot create style" ); + return xStyle; +} + +// BIFF specific -------------------------------------------------------------- + +void WorkbookData::setTextEncoding( rtl_TextEncoding eTextEnc ) +{ + if( eTextEnc != RTL_TEXTENCODING_DONTKNOW ) + meTextEnc = eTextEnc; +} + +void WorkbookData::setCodePage( sal_uInt16 nCodePage ) +{ + setTextEncoding( BiffHelper::calcTextEncodingFromCodePage( nCodePage ) ); + mbHasCodePage = true; +} + +void WorkbookData::setAppFontEncoding( rtl_TextEncoding eAppFontEnc ) +{ + if( !mbHasCodePage ) + setTextEncoding( eAppFontEnc ); +} + +void WorkbookData::setIsWorkbookFile() +{ + OSL_ENSURE( meBiff == BIFF4, "WorkbookData::setIsWorkbookFile - invalid call" ); + mbWorkbook = true; +} + +void WorkbookData::createBuffersPerSheet() +{ + switch( meBiff ) + { + case BIFF2: + case BIFF3: + break; + + case BIFF4: + // #i11183# sheets in BIFF4W files have own styles or names + if( mbWorkbook ) + { + mxStyles.reset( new StylesBuffer( WorkbookHelper( *this ) ) ); + mxDefNames.reset( new DefinedNamesBuffer( WorkbookHelper( *this ) ) ); + mxExtLinks.reset( new ExternalLinkBuffer( WorkbookHelper( *this ) ) ); + } + break; + + case BIFF5: + // BIFF5 stores external references per sheet + mxExtLinks.reset( new ExternalLinkBuffer( WorkbookHelper( *this ) ) ); + break; + + case BIFF8: + break; + + case BIFF_UNKNOWN: + break; + } +} + +OUString WorkbookData::queryPassword() +{ + if( !mbHasPassword ) + { + //! TODO + maPassword = OUString(); + // set to true, even if dialog has been cancelled (never ask twice) + mbHasPassword = true; + } + return maPassword; +} + +// private -------------------------------------------------------------------- + +void WorkbookData::initialize() +{ + maRefDeviceProp = CREATE_OUSTRING( "ReferenceDevice" ); + maNamedRangesProp = CREATE_OUSTRING( "NamedRanges" ); + maDatabaseRangesProp = CREATE_OUSTRING( "DatabaseRanges" ); + maDdeLinksProp = CREATE_OUSTRING( "DDELinks" ); + maCellStylesProp = CREATE_OUSTRING( "CellStyles" ); + maPageStylesProp = CREATE_OUSTRING( "PageStyles" ); + maCellStyleServ = CREATE_OUSTRING( "com.sun.star.style.CellStyle" ); + maPageStyleServ = CREATE_OUSTRING( "com.sun.star.style.PageStyle" ); + mbWorkbook = false; + meTextEnc = osl_getThreadTextEncoding(); + mbHasCodePage = false; + mbHasPassword = false; + + // the spreadsheet document + mxDoc.set( mrBaseFilter.getModel(), UNO_QUERY ); + OSL_ENSURE( mxDoc.is(), "WorkbookData::initialize - no spreadsheet document" ); + + mxWorkbookSettings.reset( new WorkbookSettings( WorkbookHelper( *this ) ) ); + mxViewSettings.reset( new ViewSettings( WorkbookHelper( *this ) ) ); + mxWorksheets.reset( new WorksheetBuffer( WorkbookHelper( *this ) ) ); + mxTheme.reset( new ThemeBuffer( WorkbookHelper( *this ) ) ); + mxStyles.reset( new StylesBuffer( WorkbookHelper( *this ) ) ); + mxSharedStrings.reset( new SharedStringsBuffer( WorkbookHelper( *this ) ) ); + mxExtLinks.reset( new ExternalLinkBuffer( WorkbookHelper( *this ) ) ); + mxDefNames.reset( new DefinedNamesBuffer( WorkbookHelper( *this ) ) ); + mxTables.reset( new TableBuffer( WorkbookHelper( *this ) ) ); + mxWebQueries.reset( new WebQueryBuffer( WorkbookHelper( *this ) ) ); + mxPivotTables.reset( new PivotTableBuffer( WorkbookHelper( *this ) ) ); + + mxUnitConverter.reset( new UnitConverter( WorkbookHelper( *this ) ) ); + mxAddrConverter.reset( new AddressConverter( WorkbookHelper( *this ) ) ); + mxStylesPropHlp.reset( new StylesPropertyHelper( WorkbookHelper( *this ) ) ); + mxPageSettPropHlp.reset( new PageSettingsPropertyHelper( WorkbookHelper( *this ) ) ); + mxValidationPropHlp.reset( new ValidationPropertyHelper( WorkbookHelper( *this ) ) ); + + // set some document properties needed during import + if( mrBaseFilter.isImportFilter() ) + { + PropertySet aPropSet( mxDoc ); + // enable editing read-only documents (e.g. from read-only files) + aPropSet.setProperty( CREATE_OUSTRING( "IsChangeReadOnlyEnabled" ), true ); + // #i76026# disable Undo while loading the document + aPropSet.setProperty( CREATE_OUSTRING( "IsUndoEnabled" ), false ); + // #i79826# disable calculating automatic row height while loading the document + aPropSet.setProperty( CREATE_OUSTRING( "IsAdjustHeightEnabled" ), false ); + // disable automatic update of linked sheets and DDE links + aPropSet.setProperty( CREATE_OUSTRING( "IsExecuteLinkEnabled" ), false ); + // #i79890# disable automatic update of defined names + Reference< XActionLockable > xLockable( getNamedRanges(), UNO_QUERY ); + if( xLockable.is() ) + xLockable->addActionLock(); + + //! TODO: localize progress bar text + mxProgressBar.reset( new SegmentProgressBar( mrBaseFilter.getStatusIndicator(), CREATE_OUSTRING( "Loading..." ) ) ); + mxFmlaParser.reset( new FormulaParser( WorkbookHelper( *this ) ) ); + } + else if( mrBaseFilter.isExportFilter() ) + { + //! TODO: localize progress bar text + mxProgressBar.reset( new SegmentProgressBar( mrBaseFilter.getStatusIndicator(), CREATE_OUSTRING( "Saving..." ) ) ); + } +} + +void WorkbookData::finalize() +{ + // set some document properties needed after import + if( mrBaseFilter.isImportFilter() ) + { + PropertySet aPropSet( mxDoc ); + // #i74668# do not insert default sheets + aPropSet.setProperty( CREATE_OUSTRING( "IsLoaded" ), true ); + // #i79890# enable automatic update of defined names (before IsAdjustHeightEnabled!) + Reference< XActionLockable > xLockable( getNamedRanges(), UNO_QUERY ); + if( xLockable.is() ) + xLockable->removeActionLock(); + // enable automatic update of linked sheets and DDE links + aPropSet.setProperty( CREATE_OUSTRING( "IsExecuteLinkEnabled" ), true ); + // #i79826# enable updating automatic row height after loading the document + aPropSet.setProperty( CREATE_OUSTRING( "IsAdjustHeightEnabled" ), true ); + // #i76026# enable Undo after loading the document + aPropSet.setProperty( CREATE_OUSTRING( "IsUndoEnabled" ), true ); + // disable editing read-only documents (e.g. from read-only files) + aPropSet.setProperty( CREATE_OUSTRING( "IsChangeReadOnlyEnabled" ), false ); + } +} + +// ============================================================================ + +WorkbookHelper::WorkbookHelper( WorkbookData& rBookData ) : +#if OSL_DEBUG_LEVEL > 0 + WorkbookHelperDebug( rBookData.mnDebugCount ), +#endif + mrBookData( rBookData ) +{ +} + +WorkbookHelper::~WorkbookHelper() +{ +} + +// filter --------------------------------------------------------------------- + +FilterBase& WorkbookHelper::getBaseFilter() const +{ + return mrBookData.getBaseFilter(); +} + +FilterType WorkbookHelper::getFilterType() const +{ + return mrBookData.getFilterType(); +} + +SegmentProgressBar& WorkbookHelper::getProgressBar() const +{ + return mrBookData.getProgressBar(); +} + +bool WorkbookHelper::isWorkbookFile() const +{ + return mrBookData.isWorkbookFile(); +} + +void WorkbookHelper::finalizeWorkbookImport() +{ + // workbook settings, document and sheet view settings + mrBookData.getWorkbookSettings().finalizeImport(); + mrBookData.getViewSettings().finalizeImport(); +} + +// document model ------------------------------------------------------------- + +Reference< XSpreadsheetDocument > WorkbookHelper::getDocument() const +{ + return mrBookData.getDocument(); +} + +Reference< XSpreadsheet > WorkbookHelper::getSheet( sal_Int32 nSheet ) const +{ + Reference< XSpreadsheet > xSheet; + try + { + Reference< XIndexAccess > xSheetsIA( getDocument()->getSheets(), UNO_QUERY_THROW ); + xSheet.set( xSheetsIA->getByIndex( nSheet ), UNO_QUERY_THROW ); + } + catch( Exception& ) + { + } + return xSheet; +} + +Reference< XDevice > WorkbookHelper::getReferenceDevice() const +{ + return mrBookData.getReferenceDevice(); +} + +Reference< XNamedRanges > WorkbookHelper::getNamedRanges() const +{ + return mrBookData.getNamedRanges(); +} + +Reference< XDatabaseRanges > WorkbookHelper::getDatabaseRanges() const +{ + return mrBookData.getDatabaseRanges(); +} + +Reference< XNameAccess > WorkbookHelper::getDdeLinks() const +{ + return mrBookData.getDdeLinks(); +} + +Reference< XNameContainer > WorkbookHelper::getStyleFamily( bool bPageStyles ) const +{ + return mrBookData.getStyleFamily( bPageStyles ); +} + +Reference< XStyle > WorkbookHelper::getStyleObject( const OUString& rStyleName, bool bPageStyle ) const +{ + return mrBookData.getStyleObject( rStyleName, bPageStyle ); +} + +Reference< XStyle > WorkbookHelper::createStyleObject( OUString& orStyleName, bool bPageStyle, bool bRenameOldExisting ) +{ + return mrBookData.createStyleObject( orStyleName, bPageStyle, bRenameOldExisting ); +} + +// buffers -------------------------------------------------------------------- + +WorkbookSettings& WorkbookHelper::getWorkbookSettings() const +{ + return mrBookData.getWorkbookSettings(); +} + +ViewSettings& WorkbookHelper::getViewSettings() const +{ + return mrBookData.getViewSettings(); +} + +WorksheetBuffer& WorkbookHelper::getWorksheets() const +{ + return mrBookData.getWorksheets(); +} + +ThemeBuffer& WorkbookHelper::getTheme() const +{ + return mrBookData.getTheme(); +} + +StylesBuffer& WorkbookHelper::getStyles() const +{ + return mrBookData.getStyles(); +} + +SharedStringsBuffer& WorkbookHelper::getSharedStrings() const +{ + return mrBookData.getSharedStrings(); +} + +ExternalLinkBuffer& WorkbookHelper::getExternalLinks() const +{ + return mrBookData.getExternalLinks(); +} + +DefinedNamesBuffer& WorkbookHelper::getDefinedNames() const +{ + return mrBookData.getDefinedNames(); +} + +TableBuffer& WorkbookHelper::getTables() const +{ + return mrBookData.getTables(); +} + +WebQueryBuffer& WorkbookHelper::getWebQueries() const +{ + return mrBookData.getWebQueries(); +} + +PivotTableBuffer& WorkbookHelper::getPivotTables() const +{ + return mrBookData.getPivotTables(); +} + +// converters ----------------------------------------------------------------- + +FormulaParser& WorkbookHelper::getFormulaParser() const +{ + return mrBookData.getFormulaParser(); +} + +UnitConverter& WorkbookHelper::getUnitConverter() const +{ + return mrBookData.getUnitConverter(); +} + +AddressConverter& WorkbookHelper::getAddressConverter() const +{ + return mrBookData.getAddressConverter(); +} + +StylesPropertyHelper& WorkbookHelper::getStylesPropertyHelper() const +{ + return mrBookData.getStylesPropertyHelper(); +} + +PageSettingsPropertyHelper& WorkbookHelper::getPageSettingsPropertyHelper() const +{ + return mrBookData.getPageSettingsPropertyHelper(); +} + +ValidationPropertyHelper& WorkbookHelper::getValidationPropertyHelper() const +{ + return mrBookData.getValidationPropertyHelper(); +} + +// OOX specific --------------------------------------------------------------- + +XmlFilterBase& WorkbookHelper::getOoxFilter() const +{ + OSL_ENSURE( mrBookData.getFilterType() == FILTER_OOX, "WorkbookHelper::getOoxFilter - invalid call" ); + return mrBookData.getOoxFilter(); +} + +bool WorkbookHelper::importOoxFragment( const ::rtl::Reference< FragmentHandler >& rxHandler ) +{ + return getOoxFilter().importFragment( rxHandler ); +} + +// BIFF specific -------------------------------------------------------------- + +BinaryFilterBase& WorkbookHelper::getBiffFilter() const +{ + OSL_ENSURE( mrBookData.getFilterType() == FILTER_BIFF, "WorkbookHelper::getBiffFilter - invalid call" ); + return mrBookData.getBiffFilter(); +} + +BiffType WorkbookHelper::getBiff() const +{ + return mrBookData.getBiff(); +} + +rtl_TextEncoding WorkbookHelper::getTextEncoding() const +{ + return mrBookData.getTextEncoding(); +} + +void WorkbookHelper::setTextEncoding( rtl_TextEncoding eTextEnc ) +{ + mrBookData.setTextEncoding( eTextEnc ); +} + +void WorkbookHelper::setCodePage( sal_uInt16 nCodePage ) +{ + mrBookData.setCodePage( nCodePage ); +} + +void WorkbookHelper::setAppFontEncoding( rtl_TextEncoding eAppFontEnc ) +{ + mrBookData.setAppFontEncoding( eAppFontEnc ); +} + +void WorkbookHelper::setIsWorkbookFile() +{ + mrBookData.setIsWorkbookFile(); +} + +void WorkbookHelper::createBuffersPerSheet() +{ + mrBookData.createBuffersPerSheet(); +} + +OUString WorkbookHelper::queryPassword() const +{ + return mrBookData.queryPassword(); +} + +// ============================================================================ + +namespace prv { + +WorkbookDataOwner::WorkbookDataOwner( WorkbookDataRef xBookData ) : + mxBookData( xBookData ) +{ +} + +WorkbookDataOwner::~WorkbookDataOwner() +{ +} + +} // namespace prv + +// ---------------------------------------------------------------------------- + +WorkbookHelperRoot::WorkbookHelperRoot( ::oox::core::XmlFilterBase& rFilter ) : + prv::WorkbookDataOwner( prv::WorkbookDataRef( new WorkbookData( rFilter ) ) ), + WorkbookHelper( *mxBookData ) +{ +} + +WorkbookHelperRoot::WorkbookHelperRoot( ::oox::core::BinaryFilterBase& rFilter, BiffType eBiff ) : + prv::WorkbookDataOwner( prv::WorkbookDataRef( new WorkbookData( rFilter, eBiff ) ) ), + WorkbookHelper( *mxBookData ) +{ +} + +bool WorkbookHelperRoot::isValid() const +{ + return mxBookData->isValid(); +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/workbooksettings.cxx b/oox/source/xls/workbooksettings.cxx new file mode 100644 index 000000000000..bb758dbb9511 --- /dev/null +++ b/oox/source/xls/workbooksettings.cxx @@ -0,0 +1,297 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: workbooksettings.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/workbooksettings.hxx" +#include +#include +#include +#include "oox/helper/attributelist.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/helper/recordinputstream.hxx" +#include "oox/xls/biffinputstream.hxx" + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::util::Date; +using ::com::sun::star::util::XNumberFormatsSupplier; +using ::com::sun::star::sheet::XCalculatable; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +const sal_uInt32 OOBIN_WORKBOOKPR_DATE1904 = 0x00000001; +const sal_uInt32 OOBIN_WORKBOOKPR_STRIPEXT = 0x00000080; + +const sal_uInt16 OOBIN_CALCPR_A1 = 0x0002; +const sal_uInt16 OOBIN_CALCPR_ITERATE = 0x0004; +const sal_uInt16 OOBIN_CALCPR_FULLPRECISION = 0x0008; +const sal_uInt16 OOBIN_CALCPR_CALCCOMPLETED = 0x0010; +const sal_uInt16 OOBIN_CALCPR_CALCONSAVE = 0x0020; +const sal_uInt16 OOBIN_CALCPR_CONCURRENT = 0x0040; +const sal_uInt16 OOBIN_CALCPR_MANUALPROC = 0x0080; + +// no predefined constants for show objects mode +const sal_Int16 API_SHOWMODE_SHOW = 0; /// Show drawing objects. +const sal_Int16 API_SHOWMODE_HIDE = 1; /// Hide drawing objects. +const sal_Int16 API_SHOWMODE_PLACEHOLDER = 2; /// Show placeholders for drawing objects. + +} // namespace + +// ============================================================================ + +OoxWorkbookPrData::OoxWorkbookPrData() : + mnShowObjectMode( XML_all ), + mnUpdateLinksMode( XML_userSet ), + mnDefaultThemeVer( -1 ), + mbDateMode1904( false ), + mbSaveExtLinkValues( true ) +{ +} + +void OoxWorkbookPrData::setBinObjectMode( sal_uInt16 nObjMode ) +{ + static const sal_Int32 spnObjModes[] = { XML_all, XML_placeholders, XML_none }; + mnShowObjectMode = STATIC_ARRAY_SELECT( spnObjModes, nObjMode, XML_all ); +} + +// ============================================================================ + +OoxCalcPrData::OoxCalcPrData() : + mfIterateDelta( 0.001 ), + mnCalcId( -1 ), + mnRefMode( XML_A1 ), + mnCalcMode( XML_auto ), + mnIterateCount( 100 ), + mnProcCount( -1 ), + mbCalcOnSave( true ), + mbCalcCompleted( true ), + mbFullPrecision( true ), + mbIterate( false ), + mbConcurrent( true ), + mbUseNlr( false ) +{ +} + +// ============================================================================ + +WorkbookSettings::WorkbookSettings( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ) +{ +} + +void WorkbookSettings::importWorkbookPr( const AttributeList& rAttribs ) +{ + maOoxBookData.maCodeName = rAttribs.getString( XML_codePage ); + maOoxBookData.mnShowObjectMode = rAttribs.getToken( XML_showObjects, XML_all ); + maOoxBookData.mnUpdateLinksMode = rAttribs.getToken( XML_updateLinks, XML_userSet ); + maOoxBookData.mnDefaultThemeVer = rAttribs.getInteger( XML_defaultThemeVersion, -1 ); + maOoxBookData.mbDateMode1904 = rAttribs.getBool( XML_date1904, false ); + maOoxBookData.mbSaveExtLinkValues = rAttribs.getBool( XML_saveExternalLinkValues, true ); +} + +void WorkbookSettings::importCalcPr( const AttributeList& rAttribs ) +{ + maOoxCalcData.mfIterateDelta = rAttribs.getDouble( XML_iterateDelta, 0.0001 ); + maOoxCalcData.mnCalcId = rAttribs.getInteger( XML_calcId, -1 ); + maOoxCalcData.mnRefMode = rAttribs.getToken( XML_refMode, XML_A1 ); + maOoxCalcData.mnCalcMode = rAttribs.getToken( XML_calcMode, XML_auto ); + maOoxCalcData.mnIterateCount = rAttribs.getInteger( XML_iterateCount, 100 ); + maOoxCalcData.mnProcCount = rAttribs.getInteger( XML_concurrentManualCount, -1 ); + maOoxCalcData.mbCalcOnSave = rAttribs.getBool( XML_calcOnSave, true ); + maOoxCalcData.mbCalcCompleted = rAttribs.getBool( XML_calcCompleted, true ); + maOoxCalcData.mbFullPrecision = rAttribs.getBool( XML_fullPrecision, true ); + maOoxCalcData.mbIterate = rAttribs.getBool( XML_iterate, false ); + maOoxCalcData.mbConcurrent = rAttribs.getBool( XML_concurrentCalc, true ); +} + +void WorkbookSettings::importWorkbookPr( RecordInputStream& rStrm ) +{ + sal_uInt32 nFlags; + rStrm >> nFlags >> maOoxBookData.mnDefaultThemeVer >> maOoxBookData.maCodeName; + maOoxBookData.setBinObjectMode( extractValue< sal_uInt16 >( nFlags, 13, 2 ) ); + maOoxBookData.mbDateMode1904 = getFlag( nFlags, OOBIN_WORKBOOKPR_DATE1904 ); + // set flag means: strip external link values + maOoxBookData.mbSaveExtLinkValues = !getFlag( nFlags, OOBIN_WORKBOOKPR_STRIPEXT ); +} + +void WorkbookSettings::importCalcPr( RecordInputStream& rStrm ) +{ + sal_Int32 nCalcMode, nProcCount; + sal_uInt16 nFlags; + rStrm >> maOoxCalcData.mnCalcId >> nCalcMode >> maOoxCalcData.mnIterateCount >> maOoxCalcData.mfIterateDelta >> nProcCount >> nFlags; + + static const sal_Int32 spnCalcModes[] = { XML_manual, XML_auto, XML_autoNoTable }; + maOoxCalcData.mnRefMode = getFlagValue( nFlags, OOBIN_CALCPR_A1, XML_A1, XML_R1C1 ); + maOoxCalcData.mnCalcMode = STATIC_ARRAY_SELECT( spnCalcModes, nCalcMode, XML_auto ); + maOoxCalcData.mnProcCount = getFlagValue< sal_Int32 >( nFlags, OOBIN_CALCPR_MANUALPROC, nProcCount, -1 ); + maOoxCalcData.mbCalcOnSave = getFlag( nFlags, OOBIN_CALCPR_CALCONSAVE ); + maOoxCalcData.mbCalcCompleted = getFlag( nFlags, OOBIN_CALCPR_CALCCOMPLETED ); + maOoxCalcData.mbFullPrecision = getFlag( nFlags, OOBIN_CALCPR_FULLPRECISION ); + maOoxCalcData.mbIterate = getFlag( nFlags, OOBIN_CALCPR_ITERATE ); + maOoxCalcData.mbConcurrent = getFlag( nFlags, OOBIN_CALCPR_CONCURRENT ); +} + +void WorkbookSettings::setSaveExtLinkValues( bool bSaveExtLinks ) +{ + maOoxBookData.mbSaveExtLinkValues = bSaveExtLinks; +} + +void WorkbookSettings::importBookBool( BiffInputStream& rStrm ) +{ + // value of 0 means save external values, value of 1 means strip external values + maOoxBookData.mbSaveExtLinkValues = rStrm.readuInt16() == 0; +} + +void WorkbookSettings::importCalcCount( BiffInputStream& rStrm ) +{ + maOoxCalcData.mnIterateCount = rStrm.readuInt16(); +} + +void WorkbookSettings::importCalcMode( BiffInputStream& rStrm ) +{ + sal_Int16 nCalcMode = rStrm.readInt16() + 1; + static const sal_Int32 spnCalcModes[] = { XML_autoNoTable, XML_manual, XML_auto }; + maOoxCalcData.mnCalcMode = STATIC_ARRAY_SELECT( spnCalcModes, nCalcMode, XML_auto ); +} + +void WorkbookSettings::importCodeName( BiffInputStream& rStrm ) +{ + maOoxBookData.maCodeName = rStrm.readUniString(); +} + +void WorkbookSettings::importDateMode( BiffInputStream& rStrm ) +{ + maOoxBookData.mbDateMode1904 = rStrm.readuInt16() != 0; +} + +void WorkbookSettings::importDelta( BiffInputStream& rStrm ) +{ + rStrm >> maOoxCalcData.mfIterateDelta; +} + +void WorkbookSettings::importHideObj( BiffInputStream& rStrm ) +{ + maOoxBookData.setBinObjectMode( rStrm.readuInt16() ); +} + +void WorkbookSettings::importIteration( BiffInputStream& rStrm ) +{ + maOoxCalcData.mbIterate = rStrm.readuInt16() != 0; +} + +void WorkbookSettings::importPrecision( BiffInputStream& rStrm ) +{ + maOoxCalcData.mbFullPrecision = rStrm.readuInt16() != 0; +} + +void WorkbookSettings::importRefMode( BiffInputStream& rStrm ) +{ + maOoxCalcData.mnRefMode = (rStrm.readuInt16() == 0) ? XML_R1C1 : XML_A1; +} + +void WorkbookSettings::importSaveRecalc( BiffInputStream& rStrm ) +{ + maOoxCalcData.mbCalcOnSave = rStrm.readuInt16() != 0; +} + +void WorkbookSettings::importUncalced( BiffInputStream& ) +{ + // existence of this record indicates incomplete recalc + maOoxCalcData.mbCalcCompleted = false; +} + +void WorkbookSettings::importUsesElfs( BiffInputStream& rStrm ) +{ + maOoxCalcData.mbUseNlr = rStrm.readuInt16() != 0; +} + +void WorkbookSettings::finalizeImport() +{ + // default settings + PropertySet aPropSet( getDocument() ); + switch( getFilterType() ) + { + case FILTER_OOX: + case FILTER_BIFF: + aPropSet.setProperty( CREATE_OUSTRING( "IgnoreCase" ), true ); // always in Excel + aPropSet.setProperty( CREATE_OUSTRING( "RegularExpressions" ), false ); // not supported in Excel + break; + case FILTER_UNKNOWN: + break; + } + + // calculation settings + Date aNullDate = maOoxBookData.mbDateMode1904 ? Date( 1, 1, 1904 ) : Date( 30, 12, 1899 ); + + aPropSet.setProperty( CREATE_OUSTRING( "NullDate" ), aNullDate ); + aPropSet.setProperty( CREATE_OUSTRING( "IsIterationEnabled" ), maOoxCalcData.mbIterate ); + aPropSet.setProperty( CREATE_OUSTRING( "IterationCount" ), maOoxCalcData.mnIterateCount ); + aPropSet.setProperty( CREATE_OUSTRING( "IterationEpsilon" ), maOoxCalcData.mfIterateDelta ); + aPropSet.setProperty( CREATE_OUSTRING( "CalcAsShown" ), !maOoxCalcData.mbFullPrecision ); + aPropSet.setProperty( CREATE_OUSTRING( "LookUpLabels" ), maOoxCalcData.mbUseNlr ); + + Reference< XNumberFormatsSupplier > xNumFmtsSupp( getDocument(), UNO_QUERY ); + if( xNumFmtsSupp.is() ) + { + PropertySet aNumFmtProp( xNumFmtsSupp->getNumberFormatSettings() ); + aNumFmtProp.setProperty( CREATE_OUSTRING( "NullDate" ), aNullDate ); + } + + Reference< XCalculatable > xCalculatable( getDocument(), UNO_QUERY ); + if( xCalculatable.is() ) + xCalculatable->enableAutomaticCalculation( (maOoxCalcData.mnCalcMode == XML_auto) || (maOoxCalcData.mnCalcMode == XML_autoNoTable) ); +} + +sal_Int16 WorkbookSettings::getApiShowObjectMode() const +{ + switch( maOoxBookData.mnShowObjectMode ) + { + case XML_all: return API_SHOWMODE_SHOW; + case XML_none: return API_SHOWMODE_HIDE; + // #i80528# placeholders not supported anymore, but this is handled internally in Calc + case XML_placeholders: return API_SHOWMODE_PLACEHOLDER; + } + return API_SHOWMODE_SHOW; +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/worksheetbuffer.cxx b/oox/source/xls/worksheetbuffer.cxx new file mode 100644 index 000000000000..d52d75bab6b0 --- /dev/null +++ b/oox/source/xls/worksheetbuffer.cxx @@ -0,0 +1,333 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: worksheetbuffer.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/worksheetbuffer.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "oox/helper/attributelist.hxx" +#include "oox/helper/containerhelper.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/helper/recordinputstream.hxx" +#include "oox/core/filterbase.hxx" +#include "oox/xls/biffinputstream.hxx" +#include "oox/xls/ooxtokens.hxx" + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::container::XIndexAccess; +using ::com::sun::star::container::XNameAccess; +using ::com::sun::star::container::XNamed; +using ::com::sun::star::lang::Locale; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::i18n::ParseResult; +using ::com::sun::star::sheet::XSpreadsheetDocument; +using ::com::sun::star::sheet::XSpreadsheets; +using ::com::sun::star::sheet::XSpreadsheet; +using ::com::sun::star::sheet::XExternalSheetName; +using ::com::sun::star::sheet::XSheetLinkable; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +/** Returns the base file name without path and extension. */ +OUString lclGetBaseFileName( const OUString& rUrl ) +{ + sal_Int32 nFileNamePos = ::std::max< sal_Int32 >( rUrl.lastIndexOf( '/' ) + 1, 0 ); + sal_Int32 nExtPos = rUrl.lastIndexOf( '.' ); + if( nExtPos <= nFileNamePos ) nExtPos = rUrl.getLength(); + return rUrl.copy( nFileNamePos, nExtPos - nFileNamePos ); +} + +} // namespace + +// ============================================================================ + +OoxSheetInfo::OoxSheetInfo() : + mnSheetId( -1 ), + mnState( XML_visible ) +{ +} + +// ============================================================================ + +WorksheetBuffer::WorksheetBuffer( const WorkbookHelper& rHelper ) : + WorkbookHelper( rHelper ), + maIsVisibleProp( CREATE_OUSTRING( "IsVisible" ) ) +{ + // character classification service for conversion to valid sheet names + Reference< XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + mxCharClass.set( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.i18n.CharacterClassification" ) ), UNO_QUERY ); + OSL_ENSURE( mxCharClass.is(), "WorksheetBuffer::WorksheetBuffer - no character classification service" ); +} + +void WorksheetBuffer::initializeSingleSheet() +{ + OSL_ENSURE( maSheetInfos.empty(), "WorksheetBuffer::initializeSingleSheet - invalid call" ); + OoxSheetInfo aSheetInfo; + aSheetInfo.maName = lclGetBaseFileName( getBaseFilter().getFileUrl() ); + insertSheet( aSheetInfo ); +} + +void WorksheetBuffer::importSheet( const AttributeList& rAttribs ) +{ + OoxSheetInfo aSheetInfo; + aSheetInfo.maId = rAttribs.getString( R_TOKEN( id ) ); + aSheetInfo.maName = rAttribs.getString( XML_name ); + aSheetInfo.mnSheetId = rAttribs.getInteger( XML_sheetId, -1 ); + aSheetInfo.mnState = rAttribs.getToken( XML_state, XML_visible ); + insertSheet( aSheetInfo ); +} + +void WorksheetBuffer::importSheet( RecordInputStream& rStrm ) +{ + sal_Int32 nState; + OoxSheetInfo aSheetInfo; + rStrm >> nState >> aSheetInfo.mnSheetId >> aSheetInfo.maId >> aSheetInfo.maName; + static const sal_Int32 spnStates[] = { XML_visible, XML_hidden, XML_veryHidden }; + aSheetInfo.mnState = STATIC_ARRAY_SELECT( spnStates, nState, XML_visible ); + insertSheet( aSheetInfo ); +} + +void WorksheetBuffer::importSheet( BiffInputStream& rStrm ) +{ + sal_uInt16 nState = 0; + if( getBiff() >= BIFF5 ) + { + rStrm.skip( 4 ); + rStrm >> nState; + } + + OoxSheetInfo aSheetInfo; + aSheetInfo.maName = (getBiff() == BIFF8) ? + rStrm.readUniString( rStrm.readuInt8() ) : + rStrm.readByteString( false, getTextEncoding() ); + static const sal_Int32 spnStates[] = { XML_visible, XML_hidden, XML_veryHidden }; + aSheetInfo.mnState = STATIC_ARRAY_SELECT( spnStates, nState, XML_visible ); + insertSheet( aSheetInfo ); +} + +sal_Int32 WorksheetBuffer::insertExternalSheet( const OUString& rTargetUrl, const OUString& rSheetName ) +{ + // try to find existing external sheet (needed for BIFF4W and BIFF5) + ExternalSheetName aExtSheet( rTargetUrl, rSheetName ); + ExternalSheetMap::iterator aIt = maExternalSheets.find( aExtSheet ); + if( aIt != maExternalSheets.end() ) + return aIt->second; + + // create a new external sheet + sal_Int16& rnSheet = maExternalSheets[ aExtSheet ]; + rnSheet = getTotalSheetCount(); + insertSheet( OUString(), rnSheet, false ); + + try + { + Reference< XSpreadsheet > xSheet = getSheet( rnSheet ); + // use base file name as sheet name, if sheet name is missing (e.g. links to BIFF2-BIFF4 files) + OUString aSheetName = rSheetName; + if( aSheetName.getLength() == 0 ) + aSheetName = lclGetBaseFileName( rTargetUrl ); + // link the sheet + Reference< XSheetLinkable > xLinkable( xSheet, UNO_QUERY_THROW ); + xLinkable->link( rTargetUrl, aSheetName, OUString(), OUString(), ::com::sun::star::sheet::SheetLinkMode_VALUE ); + // set the special external sheet name + Reference< XExternalSheetName > xSheetName( xSheet, UNO_QUERY_THROW ); + xSheetName->setExternalName( xLinkable->getLinkUrl(), xLinkable->getLinkSheetName() ); + } + catch( Exception& ) + { + } + + // return sheet index + return rnSheet; +} + +sal_Int32 WorksheetBuffer::getInternalSheetCount() const +{ + return static_cast< sal_Int32 >( maSheetInfos.size() ); +} + +OUString WorksheetBuffer::getSheetRelId( sal_Int32 nSheet ) const +{ + OUString aRelId; + if( const OoxSheetInfo* pInfo = getSheetInfo( nSheet ) ) + aRelId = pInfo->maId; + return aRelId; +} + +OUString WorksheetBuffer::getFinalSheetName( sal_Int32 nSheet ) const +{ + OUString aName; + if( const OoxSheetInfo* pInfo = getSheetInfo( nSheet ) ) + aName = pInfo->maFinalName; + return aName; +} + +OUString WorksheetBuffer::getFinalSheetName( const OUString& rName ) const +{ + for( SheetInfoVec::const_iterator aIt = maSheetInfos.begin(), aEnd = maSheetInfos.end(); aIt != aEnd; ++aIt ) + // TODO: handle encoded characters + if( aIt->maName.equalsIgnoreAsciiCase( rName ) ) + return aIt->maFinalName; + return OUString(); +} + +sal_Int32 WorksheetBuffer::getFinalSheetIndex( const OUString& rName ) const +{ + for( SheetInfoVec::const_iterator aIt = maSheetInfos.begin(), aEnd = maSheetInfos.end(); aIt != aEnd; ++aIt ) + // TODO: handle encoded characters + if( aIt->maName.equalsIgnoreAsciiCase( rName ) ) + return static_cast< sal_Int32 >( aIt - maSheetInfos.begin() ); + return -1; +} + +// private -------------------------------------------------------------------- + +sal_Int16 WorksheetBuffer::getTotalSheetCount() const +{ + try + { + Reference< XIndexAccess > xSheetsIA( getDocument()->getSheets(), UNO_QUERY_THROW ); + return static_cast< sal_Int16 >( xSheetsIA->getCount() ); + } + catch( Exception& ) + { + OSL_ENSURE( false, "WorksheetBuffer::getTotalSheetCount - cannot get sheet count" ); + } + return 1; +} + +const OoxSheetInfo* WorksheetBuffer::getSheetInfo( sal_Int32 nSheet ) const +{ + return ((0 <= nSheet) && (static_cast< size_t >( nSheet ) < maSheetInfos.size())) ? + &maSheetInfos[ static_cast< size_t >( nSheet ) ] : 0; +} + +OUString WorksheetBuffer::convertToValidSheetName( const OUString& rName, sal_Unicode cReplaceChar ) const +{ + if( !mxCharClass.is() ) return rName; + + using namespace ::com::sun::star::i18n::KParseTokens; + using namespace ::com::sun::star::i18n::KParseType; + + OUStringBuffer aFinalName( rName ); + Locale aLocale( CREATE_OUSTRING( "en" ), CREATE_OUSTRING( "US" ), OUString() ); + sal_Int32 nStartFlags = ANY_LETTER_OR_NUMBER | ASC_UNDERSCORE; + sal_Int32 nContFlags = nStartFlags; + OUString aStartChars; + OUString aContChars( sal_Unicode( ' ' ) ); + sal_Int32 nStartPos = 0; + while( nStartPos < aFinalName.getLength() ) + { + ParseResult aRes = mxCharClass->parsePredefinedToken( + IDENTNAME, rName, nStartPos, aLocale, nStartFlags, aStartChars, nContFlags, aContChars ); + if( aRes.EndPos < aFinalName.getLength() ) + { + aFinalName.setCharAt( aRes.EndPos, cReplaceChar ); + nStartFlags = nContFlags; + aStartChars = aContChars; + } + nStartPos = aRes.EndPos + 1; + } + return aFinalName.makeStringAndClear(); +} + +OUString WorksheetBuffer::insertSheet( const OUString& rName, sal_Int16 nSheet, bool bVisible ) +{ + OUString aFinalName = (rName.getLength() == 0) ? CREATE_OUSTRING( "Sheet" ) : convertToValidSheetName( rName, '_' ); + try + { + Reference< XSpreadsheets > xSheets( getDocument()->getSheets(), UNO_QUERY_THROW ); + Reference< XIndexAccess > xSheetsIA( xSheets, UNO_QUERY_THROW ); + Reference< XNameAccess > xSheetsNA( xSheets, UNO_QUERY_THROW ); + PropertySet aPropSet; + if( nSheet < xSheetsIA->getCount() ) + { + // existing sheet - try to rename + Reference< XNamed > xSheetName( xSheetsIA->getByIndex( nSheet ), UNO_QUERY_THROW ); + if( xSheetName->getName() != aFinalName ) + { + aFinalName = ContainerHelper::getUnusedName( xSheetsNA, aFinalName, ' ' ); + xSheetName->setName( aFinalName ); + } + aPropSet.set( xSheetName ); + } + else + { + // new sheet - insert with unused name + aFinalName = ContainerHelper::getUnusedName( xSheetsNA, aFinalName, ' ' ); + xSheets->insertNewByName( aFinalName, nSheet ); + aPropSet.set( xSheetsIA->getByIndex( nSheet ) ); + } + + // sheet properties + aPropSet.setProperty( maIsVisibleProp, bVisible ); + } + catch( Exception& ) + { + OSL_ENSURE( false, "WorksheetBuffer::insertSheet - cannot insert or rename worksheet" ); + } + return aFinalName; +} + +void WorksheetBuffer::insertSheet( const OoxSheetInfo& rSheetInfo ) +{ + OSL_ENSURE( maExternalSheets.empty(), "WorksheetBuffer::insertSheet - external sheets exist already" ); + sal_Int16 nSheet = static_cast< sal_Int16 >( maSheetInfos.size() ); + maSheetInfos.push_back( rSheetInfo ); + maSheetInfos.back().maFinalName = insertSheet( rSheetInfo.maName, nSheet, rSheetInfo.mnState == XML_visible ); +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/worksheetfragment.cxx b/oox/source/xls/worksheetfragment.cxx new file mode 100644 index 000000000000..0fce487bb5c7 --- /dev/null +++ b/oox/source/xls/worksheetfragment.cxx @@ -0,0 +1,1068 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: worksheetfragment.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/worksheetfragment.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/helper/recordinputstream.hxx" +#include "oox/core/relations.hxx" +#include "oox/xls/addressconverter.hxx" +#include "oox/xls/autofiltercontext.hxx" +#include "oox/xls/biffinputstream.hxx" +#include "oox/xls/condformatcontext.hxx" +#include "oox/xls/externallinkbuffer.hxx" +#include "oox/xls/pagesettings.hxx" +#include "oox/xls/pivottablefragment.hxx" +#include "oox/xls/querytablefragment.hxx" +#include "oox/xls/sheetdatacontext.hxx" +#include "oox/xls/tablefragment.hxx" +#include "oox/xls/viewsettings.hxx" +#include "oox/xls/workbooksettings.hxx" +#include "oox/xls/worksheetsettings.hxx" + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::table::CellAddress; +using ::com::sun::star::table::CellRangeAddress; +using ::com::sun::star::xml::sax::XFastContextHandler; +using ::oox::core::Relations; +using ::oox::core::RelationsRef; +using ::oox::core::RecordContextRef; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +const sal_uInt32 OOBIN_BRK_MANUAL = 0x00000001; + +const sal_uInt16 BIFF_COLINFO_HIDDEN = 0x0001; +const sal_uInt16 BIFF_COLINFO_COLLAPSED = 0x1000; + +const sal_uInt16 BIFF_DEFROW_CUSTOMHEIGHT = 0x0001; +const sal_uInt16 BIFF_DEFROW_HIDDEN = 0x0002; +const sal_uInt16 BIFF_DEFROW_THICKTOP = 0x0004; +const sal_uInt16 BIFF_DEFROW_THICKBOTTOM = 0x0008; +const sal_uInt16 BIFF2_DEFROW_DEFHEIGHT = 0x8000; +const sal_uInt16 BIFF2_DEFROW_MASK = 0x7FFF; + +const sal_uInt32 BIFF_DATAVAL_STRINGLIST = 0x00000080; +const sal_uInt32 BIFF_DATAVAL_ALLOWBLANK = 0x00000100; +const sal_uInt32 BIFF_DATAVAL_NODROPDOWN = 0x00000200; +const sal_uInt32 BIFF_DATAVAL_SHOWINPUT = 0x00040000; +const sal_uInt32 BIFF_DATAVAL_SHOWERROR = 0x00080000; + +const sal_uInt32 BIFF_HYPERLINK_TARGET = 0x00000001; /// File name or URL. +const sal_uInt32 BIFF_HYPERLINK_ABS = 0x00000002; /// Absolute path. +const sal_uInt32 BIFF_HYPERLINK_DISPLAY = 0x00000014; /// Display string. +const sal_uInt32 BIFF_HYPERLINK_LOC = 0x00000008; /// Target location. +const sal_uInt32 BIFF_HYPERLINK_FRAME = 0x00000080; /// Target frame. +const sal_uInt32 BIFF_HYPERLINK_UNC = 0x00000100; /// UNC path. + +} // namespace + +// ============================================================================ + +OoxWorksheetFragment::OoxWorksheetFragment( const WorkbookHelper& rHelper, + const OUString& rFragmentPath, ISegmentProgressBarRef xProgressBar, WorksheetType eSheetType, sal_Int32 nSheet ) : + OoxWorksheetFragmentBase( rHelper, rFragmentPath, xProgressBar, eSheetType, nSheet ) +{ + // import data tables related to this worksheet + RelationsRef xTableRels = getRelations().getRelationsFromType( CREATE_RELATIONS_TYPE( "table" ) ); + for( Relations::const_iterator aIt = xTableRels->begin(), aEnd = xTableRels->end(); aIt != aEnd; ++aIt ) + importOoxFragment( new OoxTableFragment( *this, getFragmentPathFromTarget( aIt->second.maTarget ) ) ); +} + +// oox.xls.OoxContextHelper interface ----------------------------------------- + +bool OoxWorksheetFragment::onCanCreateContext( sal_Int32 nElement ) const +{ + switch( getCurrentContext() ) + { + case XML_ROOT_CONTEXT: + return (nElement == XLS_TOKEN( worksheet )); + case XLS_TOKEN( worksheet ): + return (nElement == XLS_TOKEN( sheetPr )) || + (nElement == XLS_TOKEN( dimension )) || + (nElement == XLS_TOKEN( sheetFormatPr )) || + (nElement == XLS_TOKEN( sheetViews )) || + (nElement == XLS_TOKEN( cols )) || + (nElement == XLS_TOKEN( sheetData )) || + (nElement == XLS_TOKEN( mergeCells )) || + (nElement == XLS_TOKEN( hyperlinks )) || + (nElement == XLS_TOKEN( autoFilter )) || + (nElement == XLS_TOKEN( dataValidations )) || + (nElement == XLS_TOKEN( conditionalFormatting )) || + (nElement == XLS_TOKEN( pageMargins )) || + (nElement == XLS_TOKEN( pageSetup )) || + (nElement == XLS_TOKEN( headerFooter )) || + (nElement == XLS_TOKEN( printOptions )) || + (nElement == XLS_TOKEN( rowBreaks )) || + (nElement == XLS_TOKEN( colBreaks )) || + (nElement == XLS_TOKEN( sheetProtection )) || + (nElement == XLS_TOKEN( phoneticPr )); + case XLS_TOKEN( sheetPr ): + return (nElement == XLS_TOKEN( outlinePr )) || + (nElement == XLS_TOKEN( pageSetUpPr )); + case XLS_TOKEN( sheetViews ): + return (nElement == XLS_TOKEN( sheetView )); + case XLS_TOKEN( sheetView ): + return (nElement == XLS_TOKEN( pane )) || + (nElement == XLS_TOKEN( selection )); + case XLS_TOKEN( cols ): + return (nElement == XLS_TOKEN( col )); + case XLS_TOKEN( mergeCells ): + return (nElement == XLS_TOKEN( mergeCell )); + case XLS_TOKEN( hyperlinks ): + return (nElement == XLS_TOKEN( hyperlink )); + case XLS_TOKEN( dataValidations ): + return (nElement == XLS_TOKEN( dataValidation )); + case XLS_TOKEN( dataValidation ): + return (nElement == XLS_TOKEN( formula1 )) || + (nElement == XLS_TOKEN( formula2 )); + case XLS_TOKEN( headerFooter ): + return (nElement == XLS_TOKEN( firstHeader )) || + (nElement == XLS_TOKEN( firstFooter )) || + (nElement == XLS_TOKEN( oddHeader )) || + (nElement == XLS_TOKEN( oddFooter )) || + (nElement == XLS_TOKEN( evenHeader )) || + (nElement == XLS_TOKEN( evenFooter )); + case XLS_TOKEN( rowBreaks ): + case XLS_TOKEN( colBreaks ): + return (nElement == XLS_TOKEN( brk )); + } + return false; +} + +Reference< XFastContextHandler > OoxWorksheetFragment::onCreateContext( sal_Int32 nElement, const AttributeList& /*rAttribs*/ ) +{ + switch( nElement ) + { + case XLS_TOKEN( sheetData ): + return new OoxSheetDataContext( *this ); + case XLS_TOKEN( autoFilter ): + return new OoxAutoFilterContext( *this ); + case XLS_TOKEN( conditionalFormatting ): + return new OoxCondFormatContext( *this ); + } + return this; +} + +void OoxWorksheetFragment::onStartElement( const AttributeList& rAttribs ) +{ + switch( getCurrentContext() ) + { + case XLS_TOKEN( dimension ): importDimension( rAttribs ); break; + case XLS_TOKEN( sheetFormatPr ): importSheetFormatPr( rAttribs ); break; + case XLS_TOKEN( sheetView ): getSheetViewSettings().importSheetView( rAttribs ); break; + case XLS_TOKEN( pane ): getSheetViewSettings().importPane( rAttribs ); break; + case XLS_TOKEN( selection ): getSheetViewSettings().importSelection( rAttribs ); break; + case XLS_TOKEN( outlinePr ): getWorksheetSettings().importOutlinePr( rAttribs ); break; + case XLS_TOKEN( sheetProtection ): getWorksheetSettings().importSheetProtection( rAttribs ); break; + case XLS_TOKEN( phoneticPr ): getWorksheetSettings().importPhoneticPr( rAttribs ); break; + case XLS_TOKEN( col ): importCol( rAttribs ); break; + case XLS_TOKEN( mergeCell ): importMergeCell( rAttribs ); break; + case XLS_TOKEN( hyperlink ): importHyperlink( rAttribs ); break; + case XLS_TOKEN( dataValidation ): importDataValidation( rAttribs ); break; + case XLS_TOKEN( pageMargins ): getPageSettings().importPageMargins( rAttribs ); break; + case XLS_TOKEN( pageSetup ): getPageSettings().importPageSetup( rAttribs ); break; + case XLS_TOKEN( printOptions ): getPageSettings().importPrintOptions( rAttribs ); break; + case XLS_TOKEN( headerFooter ): getPageSettings().importHeaderFooter( rAttribs ); break; + case XLS_TOKEN( pageSetUpPr ): importPageSetUpPr( rAttribs ); break; + case XLS_TOKEN( brk ): importBrk( rAttribs ); break; + } +} + +void OoxWorksheetFragment::onEndElement( const OUString& rChars ) +{ + sal_Int32 nCurrentContext = getCurrentContext(); + switch( nCurrentContext ) + { + case XLS_TOKEN( firstHeader ): + case XLS_TOKEN( firstFooter ): + case XLS_TOKEN( oddHeader ): + case XLS_TOKEN( oddFooter ): + case XLS_TOKEN( evenHeader ): + case XLS_TOKEN( evenFooter ): + getPageSettings().importHeaderFooterCharacters( rChars, nCurrentContext ); + break; + case XLS_TOKEN( formula1 ): + if( mxValData.get() ) + { + importDataValFormula( mxValData->maTokens1, rChars, mxValData->maRanges.getBaseAddress() ); + // process string list of a list validation (convert to list of string tokens) + if( mxValData->mnType == XML_list ) + getFormulaParser().convertStringToStringList( mxValData->maTokens1, ',', true ); + } + break; + case XLS_TOKEN( formula2 ): + if( mxValData.get() ) + importDataValFormula( mxValData->maTokens2, rChars, mxValData->maRanges.getBaseAddress() ); + break; + case XLS_TOKEN( dataValidation ): + if( mxValData.get() ) + setValidation( *mxValData ); + mxValData.reset(); + break; + } +} + +bool OoxWorksheetFragment::onCanCreateRecordContext( sal_Int32 nRecId ) +{ + switch( getCurrentContext() ) + { + case XML_ROOT_CONTEXT: + return (nRecId == OOBIN_ID_WORKSHEET); + case OOBIN_ID_WORKSHEET: + return (nRecId == OOBIN_ID_SHEETPR) || + (nRecId == OOBIN_ID_DIMENSION) || + (nRecId == OOBIN_ID_SHEETFORMATPR) || + (nRecId == OOBIN_ID_SHEETVIEWS) || + (nRecId == OOBIN_ID_COLS) || + (nRecId == OOBIN_ID_SHEETDATA) || + (nRecId == OOBIN_ID_MERGECELLS) || + (nRecId == OOBIN_ID_HYPERLINK) || + (nRecId == OOBIN_ID_DATAVALIDATIONS) || + (nRecId == OOBIN_ID_CONDFORMATTING) || + (nRecId == OOBIN_ID_PAGEMARGINS) || + (nRecId == OOBIN_ID_PAGESETUP) || + (nRecId == OOBIN_ID_PRINTOPTIONS) || + (nRecId == OOBIN_ID_HEADERFOOTER) || + (nRecId == OOBIN_ID_ROWBREAKS) || + (nRecId == OOBIN_ID_COLBREAKS) || + (nRecId == OOBIN_ID_SHEETPROTECTION) || + (nRecId == OOBIN_ID_PHONETICPR); + case OOBIN_ID_SHEETVIEWS: + return (nRecId == OOBIN_ID_SHEETVIEW); + case OOBIN_ID_SHEETVIEW: + return (nRecId == OOBIN_ID_PANE) || + (nRecId == OOBIN_ID_SELECTION); + case OOBIN_ID_COLS: + return (nRecId == OOBIN_ID_COL); + case OOBIN_ID_MERGECELLS: + return (nRecId == OOBIN_ID_MERGECELL); + case OOBIN_ID_DATAVALIDATIONS: + return (nRecId == OOBIN_ID_DATAVALIDATION); + case OOBIN_ID_ROWBREAKS: + case OOBIN_ID_COLBREAKS: + return (nRecId == OOBIN_ID_BRK); + } + return false; +} + +RecordContextRef OoxWorksheetFragment::onCreateRecordContext( sal_Int32 nRecId, RecordInputStream& ) +{ + switch( nRecId ) + { + case OOBIN_ID_SHEETDATA: + return new OoxSheetDataContext( *this ); + case OOBIN_ID_CONDFORMATTING: + return new OoxCondFormatContext( *this ); + } + return this; +} + +void OoxWorksheetFragment::onStartRecord( RecordInputStream& rStrm ) +{ + switch( getCurrentContext() ) + { + case OOBIN_ID_SHEETPR: getWorksheetSettings().importSheetPr( rStrm ); break; + case OOBIN_ID_DIMENSION: importDimension( rStrm ); break; + case OOBIN_ID_SHEETPROTECTION: getWorksheetSettings().importSheetProtection( rStrm ); break; + case OOBIN_ID_PHONETICPR: getWorksheetSettings().importPhoneticPr( rStrm ); break; + case OOBIN_ID_SHEETFORMATPR: importSheetFormatPr( rStrm ); break; + case OOBIN_ID_SHEETVIEW: getSheetViewSettings().importSheetView( rStrm ); break; + case OOBIN_ID_PANE: getSheetViewSettings().importPane( rStrm ); break; + case OOBIN_ID_SELECTION: getSheetViewSettings().importSelection( rStrm ); break; + case OOBIN_ID_COL: importCol( rStrm ); break; + case OOBIN_ID_MERGECELL: importMergeCell( rStrm ); break; + case OOBIN_ID_HYPERLINK: importHyperlink( rStrm ); break; + case OOBIN_ID_DATAVALIDATION: importDataValidation( rStrm ); break; + case OOBIN_ID_PAGEMARGINS: getPageSettings().importPageMargins( rStrm ); break; + case OOBIN_ID_PAGESETUP: getPageSettings().importPageSetup( rStrm ); break; + case OOBIN_ID_PRINTOPTIONS: getPageSettings().importPrintOptions( rStrm ); break; + case OOBIN_ID_HEADERFOOTER: getPageSettings().importHeaderFooter( rStrm ); break; + case OOBIN_ID_BRK: importBrk( rStrm ); break; + } +} + +// oox.xls.OoxFragmentHandler interface --------------------------------------- + +void OoxWorksheetFragment::initializeImport() +{ + // initial processing in base class WorksheetHelper + initializeWorksheetImport(); + + // import query table fragments related to this worksheet + RelationsRef xQueryRels = getRelations().getRelationsFromType( CREATE_RELATIONS_TYPE( "queryTable" ) ); + for( Relations::const_iterator aIt = xQueryRels->begin(), aEnd = xQueryRels->end(); aIt != aEnd; ++aIt ) + importOoxFragment( new OoxQueryTableFragment( *this, getFragmentPathFromTarget( aIt->second.maTarget ) ) ); + + // import pivot table fragments related to this worksheet + RelationsRef xPivotRels = getRelations().getRelationsFromType( CREATE_RELATIONS_TYPE( "pivotTable" ) ); + for( Relations::const_iterator aIt = xPivotRels->begin(), aEnd = xPivotRels->end(); aIt != aEnd; ++aIt ) + importOoxFragment( new OoxPivotTableFragment( *this, getFragmentPathFromTarget( aIt->second.maTarget ) ) ); +} + +void OoxWorksheetFragment::finalizeImport() +{ + // final processing in base class WorksheetHelper + finalizeWorksheetImport(); +} + +// private -------------------------------------------------------------------- + +void OoxWorksheetFragment::importDimension( const AttributeList& rAttribs ) +{ + CellRangeAddress aRange; + getAddressConverter().convertToCellRangeUnchecked( aRange, rAttribs.getString( XML_ref ), getSheetIndex() ); + setDimension( aRange ); +} + +void OoxWorksheetFragment::importSheetFormatPr( const AttributeList& rAttribs ) +{ + // default column settings + setBaseColumnWidth( rAttribs.getInteger( XML_baseColWidth, 8 ) ); + setDefaultColumnWidth( rAttribs.getDouble( XML_defaultColWidth, 0.0 ) ); + // default row settings + setDefaultRowSettings( + rAttribs.getDouble( XML_defaultRowHeight, 0.0 ), + rAttribs.getBool( XML_customHeight, false ), + rAttribs.getBool( XML_zeroHeight, false ), + rAttribs.getBool( XML_thickTop, false ), + rAttribs.getBool( XML_thickBottom, false ) ); +} + +void OoxWorksheetFragment::importCol( const AttributeList& rAttribs ) +{ + OoxColumnData aData; + aData.mnFirstCol = rAttribs.getInteger( XML_min, -1 ); + aData.mnLastCol = rAttribs.getInteger( XML_max, -1 ); + aData.mfWidth = rAttribs.getDouble( XML_width, 0.0 ); + aData.mnXfId = rAttribs.getInteger( XML_style, -1 ); + aData.mnLevel = rAttribs.getInteger( XML_outlineLevel, 0 ); + aData.mbHidden = rAttribs.getBool( XML_hidden, false ); + aData.mbCollapsed = rAttribs.getBool( XML_collapsed, false ); + // set column properties in the current sheet + setColumnData( aData ); +} + +void OoxWorksheetFragment::importMergeCell( const AttributeList& rAttribs ) +{ + CellRangeAddress aRange; + if( getAddressConverter().convertToCellRange( aRange, rAttribs.getString( XML_ref ), getSheetIndex(), true ) ) + setMergedRange( aRange ); +} + +void OoxWorksheetFragment::importHyperlink( const AttributeList& rAttribs ) +{ + OoxHyperlinkData aData; + if( getAddressConverter().convertToCellRange( aData.maRange, rAttribs.getString( XML_ref ), getSheetIndex(), true ) ) + { + aData.maTarget = getRelations().getTargetFromRelId( rAttribs.getString( R_TOKEN( id ) ) ); + aData.maLocation = rAttribs.getString( XML_location ); + aData.maDisplay = rAttribs.getString( XML_display ); + aData.maTooltip = rAttribs.getString( XML_tooltip ); + setHyperlink( aData ); + } +} + +void OoxWorksheetFragment::importDataValidation( const AttributeList& rAttribs ) +{ + mxValData.reset( new OoxValidationData ); + getAddressConverter().convertToCellRangeList( mxValData->maRanges, rAttribs.getString( XML_sqref ), getSheetIndex(), true ); + mxValData->maInputTitle = rAttribs.getString( XML_promptTitle ); + mxValData->maInputMessage = rAttribs.getString( XML_prompt ); + mxValData->maErrorTitle = rAttribs.getString( XML_errorTitle ); + mxValData->maErrorMessage = rAttribs.getString( XML_error ); + mxValData->mnType = rAttribs.getToken( XML_type, XML_none ); + mxValData->mnOperator = rAttribs.getToken( XML_operator, XML_between ); + mxValData->mnErrorStyle = rAttribs.getToken( XML_errorStyle, XML_stop ); + mxValData->mbShowInputMsg = rAttribs.getBool( XML_showInputMessage, false ); + mxValData->mbShowErrorMsg = rAttribs.getBool( XML_showErrorMessage, false ); + /* The attribute showDropDown@dataValidation is in fact a "suppress + dropdown" flag, as it was in the BIFF format! ECMA specification + and attribute name are plain wrong! */ + mxValData->mbNoDropDown = rAttribs.getBool( XML_showDropDown, false ); + mxValData->mbAllowBlank = rAttribs.getBool( XML_allowBlank, false ); +} + +void OoxWorksheetFragment::importPageSetUpPr( const AttributeList& rAttribs ) +{ + // for whatever reason, this flag is still stored separated from the page settings + getPageSettings().setFitToPagesMode( rAttribs.getBool( XML_fitToPage, false ) ); +} + +void OoxWorksheetFragment::importBrk( const AttributeList& rAttribs ) +{ + OoxPageBreakData aData; + aData.mnColRow = rAttribs.getInteger( XML_id, 0 ); + aData.mnMin = rAttribs.getInteger( XML_id, 0 ); + aData.mnMax = rAttribs.getInteger( XML_id, 0 ); + aData.mbManual = rAttribs.getBool( XML_man, false ); + switch( getPreviousContext() ) + { + case XLS_TOKEN( rowBreaks ): setPageBreak( aData, true ); break; + case XLS_TOKEN( colBreaks ): setPageBreak( aData, false ); break; + } +} + +void OoxWorksheetFragment::importDataValFormula( ApiTokenSequence& orTokens, + const OUString& rFormula, const CellAddress& rBaseAddress ) +{ + TokensFormulaContext aContext( true, false ); + aContext.setBaseAddress( rBaseAddress ); + getFormulaParser().importFormula( aContext, rFormula ); + orTokens = aContext.getTokens(); +} + +void OoxWorksheetFragment::importDimension( RecordInputStream& rStrm ) +{ + BinRange aBinRange; + aBinRange.read( rStrm ); + CellRangeAddress aRange; + getAddressConverter().convertToCellRangeUnchecked( aRange, aBinRange, getSheetIndex() ); + setDimension( aRange ); +} + +void OoxWorksheetFragment::importSheetFormatPr( RecordInputStream& rStrm ) +{ + sal_Int32 nDefaultWidth; + sal_uInt16 nBaseWidth, nDefaultHeight, nFlags; + rStrm >> nDefaultWidth >> nBaseWidth >> nDefaultHeight >> nFlags; + + // base column with + setBaseColumnWidth( nBaseWidth ); + // default width is stored as 1/256th of a character in OOBIN, convert to entire character + setDefaultColumnWidth( static_cast< double >( nDefaultWidth ) / 256.0 ); + // row height is in twips in OOBIN, convert to points; equal flags in BIFF and OOBIN + setDefaultRowSettings( + nDefaultHeight / 20.0, + getFlag( nFlags, BIFF_DEFROW_CUSTOMHEIGHT ), + getFlag( nFlags, BIFF_DEFROW_HIDDEN ), + getFlag( nFlags, BIFF_DEFROW_THICKTOP ), + getFlag( nFlags, BIFF_DEFROW_THICKBOTTOM ) ); +} + +void OoxWorksheetFragment::importCol( RecordInputStream& rStrm ) +{ + OoxColumnData aData; + + sal_uInt16 nWidth, nFlags; + rStrm >> aData.mnFirstCol >> aData.mnLastCol >> nWidth; + rStrm.skip( 2 ); + rStrm >> aData.mnXfId >> nFlags; + + // column indexes are 0-based in OOBIN, but OoxColumnData expects 1-based + ++aData.mnFirstCol; + ++aData.mnLastCol; + // width is stored as 1/256th of a character in OOBIN, convert to entire character + aData.mfWidth = static_cast< double >( nWidth ) / 256.0; + // equal flags in BIFF and OOBIN + aData.mnLevel = extractValue< sal_Int32 >( nFlags, 8, 3 ); + aData.mbHidden = getFlag( nFlags, BIFF_COLINFO_HIDDEN ); + aData.mbCollapsed = getFlag( nFlags, BIFF_COLINFO_COLLAPSED ); + // set column properties in the current sheet + setColumnData( aData ); +} + +void OoxWorksheetFragment::importMergeCell( RecordInputStream& rStrm ) +{ + BinRange aBinRange; + rStrm >> aBinRange; + CellRangeAddress aRange; + if( getAddressConverter().convertToCellRange( aRange, aBinRange, getSheetIndex(), true ) ) + setMergedRange( aRange ); +} + +void OoxWorksheetFragment::importHyperlink( RecordInputStream& rStrm ) +{ + BinRange aBinRange; + rStrm >> aBinRange; + OoxHyperlinkData aData; + if( getAddressConverter().convertToCellRange( aData.maRange, aBinRange, getSheetIndex(), true ) ) + { + aData.maTarget = getRelations().getTargetFromRelId( rStrm.readString() ); + rStrm >> aData.maLocation >> aData.maTooltip >> aData.maDisplay; + setHyperlink( aData ); + } +} + +void OoxWorksheetFragment::importDataValidation( RecordInputStream& rStrm ) +{ + OoxValidationData aData; + + sal_uInt32 nFlags; + BinRangeList aRanges; + rStrm >> nFlags >> aRanges >> aData.maErrorTitle >> aData.maErrorMessage >> aData.maInputTitle >> aData.maInputMessage; + + // equal flags in BIFF and OOBIN + aData.setBinType( extractValue< sal_uInt8 >( nFlags, 0, 4 ) ); + aData.setBinOperator( extractValue< sal_uInt8 >( nFlags, 20, 4 ) ); + aData.setBinErrorStyle( extractValue< sal_uInt8 >( nFlags, 4, 3 ) ); + aData.mbAllowBlank = getFlag( nFlags, BIFF_DATAVAL_ALLOWBLANK ); + aData.mbNoDropDown = getFlag( nFlags, BIFF_DATAVAL_NODROPDOWN ); + aData.mbShowInputMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWINPUT ); + aData.mbShowErrorMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWERROR ); + + // cell range list + getAddressConverter().convertToCellRangeList( aData.maRanges, aRanges, getSheetIndex(), true ); + + // condition formula(s) + TokensFormulaContext aContext( true, false ); + aContext.setBaseAddress( aData.maRanges.getBaseAddress() ); + getFormulaParser().importFormula( aContext, rStrm ); + aData.maTokens1 = aContext.getTokens(); + getFormulaParser().importFormula( aContext, rStrm ); + aData.maTokens2 = aContext.getTokens(); + // process string list of a list validation (convert to list of string tokens) + if( (aData.mnType == XML_list) && getFlag( nFlags, BIFF_DATAVAL_STRINGLIST ) ) + getFormulaParser().convertStringToStringList( aData.maTokens1, ',', true ); + + // set validation data + setValidation( aData ); +} + +void OoxWorksheetFragment::importBrk( RecordInputStream& rStrm ) +{ + OoxPageBreakData aData; + sal_uInt32 nFlags; + rStrm >> aData.mnColRow >> aData.mnMin >> aData.mnMax >> nFlags; + aData.mbManual = getFlag( nFlags, OOBIN_BRK_MANUAL ); + switch( getPreviousContext() ) + { + case OOBIN_ID_ROWBREAKS: setPageBreak( aData, true ); break; + case OOBIN_ID_COLBREAKS: setPageBreak( aData, false ); break; + } +} + +// ============================================================================ + +BiffWorksheetFragment::BiffWorksheetFragment( const WorkbookHelper& rHelper, ISegmentProgressBarRef xProgressBar, WorksheetType eSheetType, sal_Int32 nSheet ) : + BiffWorksheetFragmentBase( rHelper, xProgressBar, eSheetType, nSheet ) +{ +} + +bool BiffWorksheetFragment::importFragment( BiffInputStream& rStrm ) +{ + // initial processing in base class WorksheetHelper + initializeWorksheetImport(); + + // create a SheetDataContext object that implements cell import + BiffSheetDataContext aSheetData( *this ); + + WorkbookSettings& rWorkbookSett = getWorkbookSettings(); + WorksheetSettings& rWorksheetSett = getWorksheetSettings(); + SheetViewSettings& rSheetViewSett = getSheetViewSettings(); + CondFormatBuffer& rCondFormats = getCondFormats(); + PageSettings& rPageSett = getPageSettings(); + + // process all record in this sheet fragment + while( rStrm.startNextRecord() && (rStrm.getRecId() != BIFF_ID_EOF) ) + { + sal_uInt16 nRecId = rStrm.getRecId(); + + if( isBofRecord( nRecId ) ) + { + // skip unknown embedded fragments (BOF/EOF blocks) + skipFragment( rStrm ); + } + else + { + // cache core stream position to detect if record is already processed + sal_Int64 nStrmPos = rStrm.getCoreStreamPos(); + + switch( nRecId ) + { + // records in all BIFF versions + case BIFF_ID_BOTTOMMARGIN: rPageSett.importBottomMargin( rStrm ); break; + case BIFF_ID_CALCCOUNT: rWorkbookSett.importCalcCount( rStrm ); break; + case BIFF_ID_CALCMODE: rWorkbookSett.importCalcMode( rStrm ); break; + case BIFF_ID_DEFCOLWIDTH: importDefColWidth( rStrm ); break; + case BIFF_ID_DELTA: rWorkbookSett.importDelta( rStrm ); break; + case BIFF2_ID_DIMENSION: importDimension( rStrm ); break; + case BIFF3_ID_DIMENSION: importDimension( rStrm ); break; + case BIFF_ID_FOOTER: rPageSett.importFooter( rStrm ); break; + case BIFF_ID_HEADER: rPageSett.importHeader( rStrm ); break; + case BIFF_ID_HORPAGEBREAKS: importPageBreaks( rStrm, true ); break; + case BIFF_ID_ITERATION: rWorkbookSett.importIteration( rStrm ); break; + case BIFF_ID_LEFTMARGIN: rPageSett.importLeftMargin( rStrm ); break; + case BIFF_ID_PANE: rSheetViewSett.importPane( rStrm ); break; + case BIFF_ID_PASSWORD: rWorksheetSett.importPassword( rStrm ); break; + case BIFF_ID_PRINTGRIDLINES: rPageSett.importPrintGridLines( rStrm ); break; + case BIFF_ID_PRINTHEADERS: rPageSett.importPrintHeaders( rStrm ); break; + case BIFF_ID_PROTECT: rWorksheetSett.importProtect( rStrm ); break; + case BIFF_ID_REFMODE: rWorkbookSett.importRefMode( rStrm ); break; + case BIFF_ID_RIGHTMARGIN: rPageSett.importRightMargin( rStrm ); break; + case BIFF_ID_SELECTION: rSheetViewSett.importSelection( rStrm ); break; + case BIFF_ID_TOPMARGIN: rPageSett.importTopMargin( rStrm ); break; + case BIFF_ID_VERPAGEBREAKS: importPageBreaks( rStrm, false ); break; + + // BIFF specific records + default: switch( getBiff() ) + { + case BIFF2: switch( nRecId ) + { + case BIFF_ID_COLUMNDEFAULT: importColumnDefault( rStrm ); break; + case BIFF_ID_COLWIDTH: importColWidth( rStrm ); break; + case BIFF2_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break; + case BIFF2_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break; + } + break; + + case BIFF3: switch( nRecId ) + { + case BIFF_ID_COLINFO: importColInfo( rStrm ); break; + case BIFF_ID_DEFCOLWIDTH: importDefColWidth( rStrm ); break; + case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break; + case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break; + case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break; + case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( rStrm ); break; + case BIFF_ID_SHEETPR: rWorksheetSett.importSheetPr( rStrm ); break; + case BIFF_ID_UNCALCED: rWorkbookSett.importUncalced( rStrm ); break; + case BIFF_ID_VCENTER: rPageSett.importVerCenter( rStrm ); break; + case BIFF3_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break; + + } + break; + + case BIFF4: switch( nRecId ) + { + case BIFF_ID_COLINFO: importColInfo( rStrm ); break; + case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break; + case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break; + case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break; + case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( rStrm ); break; + case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( rStrm ); break; + case BIFF_ID_SHEETPR: rWorksheetSett.importSheetPr( rStrm ); break; + case BIFF_ID_STANDARDWIDTH: importStandardWidth( rStrm ); break; + case BIFF_ID_UNCALCED: rWorkbookSett.importUncalced( rStrm ); break; + case BIFF_ID_VCENTER: rPageSett.importVerCenter( rStrm ); break; + case BIFF3_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break; + } + break; + + case BIFF5: switch( nRecId ) + { + case BIFF_ID_COLINFO: importColInfo( rStrm ); break; + case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break; + case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break; + case BIFF_ID_MERGEDCELLS: importMergedCells( rStrm ); break; // #i62300# also in BIFF5 + case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break; + case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( rStrm ); break; + case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( rStrm ); break; + case BIFF_ID_SCENPROTECT: rWorksheetSett.importScenProtect( rStrm ); break; + case BIFF_ID_SCL: rSheetViewSett.importScl( rStrm ); break; + case BIFF_ID_SHEETPR: rWorksheetSett.importSheetPr( rStrm ); break; + case BIFF_ID_STANDARDWIDTH: importStandardWidth( rStrm ); break; + case BIFF_ID_UNCALCED: rWorkbookSett.importUncalced( rStrm ); break; + case BIFF_ID_VCENTER: rPageSett.importVerCenter( rStrm ); break; + case BIFF3_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break; + } + break; + + case BIFF8: switch( nRecId ) + { + case BIFF_ID_CFHEADER: rCondFormats.importCfHeader( rStrm ); break; + case BIFF_ID_COLINFO: importColInfo( rStrm ); break; + case BIFF_ID_DATAVALIDATION: importDataValidation( rStrm ); break; + case BIFF_ID_DATAVALIDATIONS: importDataValidations( rStrm ); break; + case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break; + case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break; + case BIFF_ID_HYPERLINK: importHyperlink( rStrm ); break; + case BIFF_ID_LABELRANGES: importLabelRanges( rStrm ); break; + case BIFF_ID_MERGEDCELLS: importMergedCells( rStrm ); break; + case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break; + case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( rStrm ); break; + case BIFF_ID_SCENPROTECT: rWorksheetSett.importScenProtect( rStrm ); break; + case BIFF_ID_SCL: rSheetViewSett.importScl( rStrm ); break; + case BIFF_ID_SHEETPR: rWorksheetSett.importSheetPr( rStrm ); break; + case BIFF_ID_SHEETPROTECTION: rWorksheetSett.importSheetProtection( rStrm ); break; + case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( rStrm ); break; + case BIFF_ID_PHONETICPR: rWorksheetSett.importPhoneticPr( rStrm ); break; + case BIFF_ID_STANDARDWIDTH: importStandardWidth( rStrm ); break; + case BIFF_ID_UNCALCED: rWorkbookSett.importUncalced( rStrm ); break; + case BIFF_ID_VCENTER: rPageSett.importVerCenter( rStrm ); break; + case BIFF3_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break; + } + break; + + case BIFF_UNKNOWN: break; + } + } + + // record not processed, try cell records + if( rStrm.getCoreStreamPos() == nStrmPos ) + aSheetData.importRecord( rStrm ); + } + } + + // final processing in base class WorksheetHelper + finalizeWorksheetImport(); + return rStrm.getRecId() == BIFF_ID_EOF; +} + +// private -------------------------------------------------------------------- + +void BiffWorksheetFragment::importColInfo( BiffInputStream& rStrm ) +{ + sal_uInt16 nFirstCol, nLastCol, nWidth, nXfId, nFlags; + rStrm >> nFirstCol >> nLastCol >> nWidth >> nXfId >> nFlags; + + OoxColumnData aData; + // column indexes are 0-based in BIFF, but OoxColumnData expects 1-based + aData.mnFirstCol = static_cast< sal_Int32 >( nFirstCol ) + 1; + aData.mnLastCol = static_cast< sal_Int32 >( nLastCol ) + 1; + // width is stored as 1/256th of a character in BIFF, convert to entire character + aData.mfWidth = static_cast< double >( nWidth ) / 256.0; + aData.mnXfId = nXfId; + aData.mnLevel = extractValue< sal_Int32 >( nFlags, 8, 3 ); + aData.mbHidden = getFlag( nFlags, BIFF_COLINFO_HIDDEN ); + aData.mbCollapsed = getFlag( nFlags, BIFF_COLINFO_COLLAPSED ); + // set column properties in the current sheet + setColumnData( aData ); +} + +void BiffWorksheetFragment::importColumnDefault( BiffInputStream& rStrm ) +{ + sal_uInt16 nFirstCol, nLastCol, nXfId; + rStrm >> nFirstCol >> nLastCol >> nXfId; + convertColumnFormat( nFirstCol, nLastCol, nXfId ); +} + +void BiffWorksheetFragment::importColWidth( BiffInputStream& rStrm ) +{ + sal_uInt8 nFirstCol, nLastCol; + sal_uInt16 nWidth; + rStrm >> nFirstCol >> nLastCol >> nWidth; + + OoxColumnData aData; + // column indexes are 0-based in BIFF, but OoxColumnData expects 1-based + aData.mnFirstCol = static_cast< sal_Int32 >( nFirstCol ) + 1; + aData.mnLastCol = static_cast< sal_Int32 >( nLastCol ) + 1; + // width is stored as 1/256th of a character in BIFF, convert to entire character + aData.mfWidth = static_cast< double >( nWidth ) / 256.0; + // set column properties in the current sheet + setColumnData( aData ); +} + +void BiffWorksheetFragment::importDefColWidth( BiffInputStream& rStrm ) +{ + /* Stored as entire number of characters without padding pixels, which + will be added in setBaseColumnWidth(). Call has no effect, if a + width has already been set from the STANDARDWIDTH record. */ + setBaseColumnWidth( rStrm.readuInt16() ); +} + +void BiffWorksheetFragment::importDefRowHeight( BiffInputStream& rStrm ) +{ + sal_uInt16 nFlags = BIFF_DEFROW_CUSTOMHEIGHT, nHeight; + if( getBiff() != BIFF2 ) + rStrm >> nFlags; + rStrm >> nHeight; + if( getBiff() == BIFF2 ) + nHeight &= BIFF2_DEFROW_MASK; + // row height is in twips in BIFF, convert to points + setDefaultRowSettings( + nHeight / 20.0, + getFlag( nFlags, BIFF_DEFROW_CUSTOMHEIGHT ), + getFlag( nFlags, BIFF_DEFROW_HIDDEN ), + getFlag( nFlags, BIFF_DEFROW_THICKTOP ), + getFlag( nFlags, BIFF_DEFROW_THICKBOTTOM ) ); +} + +void BiffWorksheetFragment::importDataValidations( BiffInputStream& rStrm ) +{ + sal_Int32 nObjId; + rStrm.skip( 10 ); + rStrm >> nObjId; + //! TODO: invalidate object id in drawing object manager +} + +void BiffWorksheetFragment::importDataValidation( BiffInputStream& rStrm ) +{ + OoxValidationData aData; + + // flags + sal_uInt32 nFlags; + rStrm >> nFlags; + aData.setBinType( extractValue< sal_uInt8 >( nFlags, 0, 4 ) ); + aData.setBinOperator( extractValue< sal_uInt8 >( nFlags, 20, 4 ) ); + aData.setBinErrorStyle( extractValue< sal_uInt8 >( nFlags, 4, 3 ) ); + aData.mbAllowBlank = getFlag( nFlags, BIFF_DATAVAL_ALLOWBLANK ); + aData.mbNoDropDown = getFlag( nFlags, BIFF_DATAVAL_NODROPDOWN ); + aData.mbShowInputMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWINPUT ); + aData.mbShowErrorMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWERROR ); + + /* Message strings. Empty strings are single NUL characters (string length + is 1). Do not let the stream replace them with '?' characters. */ + rStrm.setNulSubstChar( '\0' ); + aData.maInputTitle = rStrm.readUniString(); + aData.maErrorTitle = rStrm.readUniString(); + aData.maInputMessage = rStrm.readUniString(); + aData.maErrorMessage = rStrm.readUniString(); + + /* Condition formula(s). String list is single tStr token with NUL + separators, replace them with LF characters. */ + rStrm.setNulSubstChar( '\n' ); + readDataValFormula( aData.maTokens1, rStrm ); + readDataValFormula( aData.maTokens2, rStrm ); + rStrm.setNulSubstChar(); // back to default + // process string list of a list validation (convert to list of string tokens) + if( (aData.mnType == XML_list) && getFlag( nFlags, BIFF_DATAVAL_STRINGLIST ) ) + getFormulaParser().convertStringToStringList( aData.maTokens1, '\n', true ); + + // cell range list + BinRangeList aRanges; + rStrm >> aRanges; + getAddressConverter().convertToCellRangeList( aData.maRanges, aRanges, getSheetIndex(), true ); + + // set validation data + setValidation( aData ); +} + +void BiffWorksheetFragment::importDimension( BiffInputStream& rStrm ) +{ + BinRange aBinRange; + aBinRange.read( rStrm, true, (rStrm.getRecId() == BIFF3_ID_DIMENSION) && (getBiff() == BIFF8) ); + // first unused row/column index in BIFF, not last used + if( aBinRange.maFirst.mnCol < aBinRange.maLast.mnCol ) --aBinRange.maLast.mnCol; + if( aBinRange.maFirst.mnRow < aBinRange.maLast.mnRow ) --aBinRange.maLast.mnRow; + // set dimension + CellRangeAddress aRange; + getAddressConverter().convertToCellRangeUnchecked( aRange, aBinRange, getSheetIndex() ); + setDimension( aRange ); +} + +void BiffWorksheetFragment::importHyperlink( BiffInputStream& rStrm ) +{ + OoxHyperlinkData aData; + + // read cell range for the hyperlink + BinRange aBiffRange; + rStrm >> aBiffRange; + // #i80006# Excel silently ignores invalid hi-byte of column index (TODO: everywhere?) + aBiffRange.maFirst.mnCol &= 0xFF; + aBiffRange.maLast.mnCol &= 0xFF; + if( !getAddressConverter().convertToCellRange( aData.maRange, aBiffRange, getSheetIndex(), true ) ) + return; + + BiffGuid aGuid; + sal_uInt32 nId, nFlags; + rStrm >> aGuid >> nId >> nFlags; + + OSL_ENSURE( aGuid == BiffHelper::maGuidStdHlink, "BiffWorksheetFragment::importHyperlink - unexpected header GUID" ); + OSL_ENSURE( nId == 2, "BiffWorksheetFragment::importHyperlink - unexpected header identifier" ); + if( !(aGuid == BiffHelper::maGuidStdHlink) ) + return; + + // display string + if( getFlag( nFlags, BIFF_HYPERLINK_DISPLAY ) ) + aData.maDisplay = readHyperlinkString( rStrm, true ); + // target frame (ignore) !TODO: DISPLAY/FRAME - right order? (never seen them together) + if( getFlag( nFlags, BIFF_HYPERLINK_FRAME ) ) + skipHyperlinkString( rStrm, true ); + + // target + if( getFlag( nFlags, BIFF_HYPERLINK_TARGET ) ) + { + if( getFlag( nFlags, BIFF_HYPERLINK_UNC ) ) + { + // UNC path + OSL_ENSURE( getFlag( nFlags, BIFF_HYPERLINK_ABS ), "BiffWorksheetFragment::importHyperlink - UNC link not absolute" ); + aData.maTarget = readHyperlinkString( rStrm, true ); + } + else + { + rStrm >> aGuid; + if( aGuid == BiffHelper::maGuidFileMoniker ) + { + // file name, maybe relative and with directory up-count + sal_Int16 nUpLevels; + rStrm >> nUpLevels; + OSL_ENSURE( (nUpLevels == 0) || !getFlag( nFlags, BIFF_HYPERLINK_ABS ), "BiffWorksheetFragment::importHyperlink - absolute filename with upcount" ); + OUString aShortName = readHyperlinkString( rStrm, false ); + if( rStrm.skip( 24 ).readInt32() > 0 ) + { + sal_Int32 nStrLen = rStrm.readInt32() / 2; // byte count to char count + rStrm.skip( 2 ); + aData.maTarget = readHyperlinkString( rStrm, nStrLen, true ); + } + if( aData.maTarget.getLength() == 0 ) + aData.maTarget = aShortName; + if( !getFlag( nFlags, BIFF_HYPERLINK_ABS ) ) + for( sal_uInt16 nLevel = 0; nLevel < nUpLevels; ++nLevel ) + aData.maTarget = CREATE_OUSTRING( "..\\" ) + aData.maTarget; + } + else if( aGuid == BiffHelper::maGuidUrlMoniker ) + { + // URL, maybe relative and with leading '../' + sal_Int32 nStrLen = rStrm.readInt32() / 2; // byte count to char count + aData.maTarget = readHyperlinkString( rStrm, nStrLen, true ); + } + else + { + OSL_ENSURE( false, "BiffWorksheetFragment::importHyperlink - unknown content GUID" ); + return; + } + } + } + + // target location + if( getFlag( nFlags, BIFF_HYPERLINK_LOC ) ) + aData.maLocation = readHyperlinkString( rStrm, true ); + + OSL_ENSURE( rStrm.getRecLeft() == 0, "BiffWorksheetFragment::importHyperlink - unknown record data" ); + + // try to read the SCREENTIP record + if( (rStrm.getNextRecId() == BIFF_ID_SCREENTIP) && rStrm.startNextRecord() ) + { + rStrm.skip( 2 ); // repeated record id + // the cell range, again + rStrm >> aBiffRange; + CellRangeAddress aRange; + if( getAddressConverter().convertToCellRange( aRange, aBiffRange, getSheetIndex(), true ) && + (aRange.StartColumn == aData.maRange.StartColumn) && + (aRange.StartRow == aData.maRange.StartRow) && + (aRange.EndColumn == aData.maRange.EndColumn) && + (aRange.EndRow == aData.maRange.EndRow) ) + { + /* This time, we have no string length, no flag field, and a + null-terminated 16-bit character array. */ + aData.maTooltip = rStrm.readUnicodeArray( static_cast< sal_uInt16 >( rStrm.getRecLeft() / 2 ) ); + } + } + + // store the hyperlink settings + setHyperlink( aData ); +} + +void BiffWorksheetFragment::importLabelRanges( BiffInputStream& rStrm ) +{ + BinRangeList aBiffRowRanges, aBiffColRanges; + rStrm >> aBiffRowRanges >> aBiffColRanges; + ApiCellRangeList aColRanges, aRowRanges; + getAddressConverter().convertToCellRangeList( aColRanges, aBiffColRanges, getSheetIndex(), true ); + getAddressConverter().convertToCellRangeList( aRowRanges, aBiffRowRanges, getSheetIndex(), true ); + setLabelRanges( aColRanges, aRowRanges ); +} + +void BiffWorksheetFragment::importMergedCells( BiffInputStream& rStrm ) +{ + BinRangeList aBiffRanges; + rStrm >> aBiffRanges; + ApiCellRangeList aRanges; + getAddressConverter().convertToCellRangeList( aRanges, aBiffRanges, getSheetIndex(), true ); + for( ApiCellRangeList::const_iterator aIt = aRanges.begin(), aEnd = aRanges.end(); aIt != aEnd; ++aIt ) + setMergedRange( *aIt ); +} + +void BiffWorksheetFragment::importPageBreaks( BiffInputStream& rStrm, bool bRowBreak ) +{ + OoxPageBreakData aData; + aData.mbManual = true; // only manual breaks stored in BIFF + bool bBiff8 = getBiff() == BIFF8; // skip start/end columns or rows in BIFF8 + + sal_uInt16 nCount; + rStrm >> nCount; + for( sal_uInt16 nIndex = 0; rStrm.isValid() && (nIndex < nCount); ++nIndex ) + { + aData.mnColRow = rStrm.readuInt16(); + setPageBreak( aData, bRowBreak ); + if( bBiff8 ) + rStrm.skip( 4 ); + } +} + +void BiffWorksheetFragment::importStandardWidth( BiffInputStream& rStrm ) +{ + sal_uInt16 nWidth; + rStrm >> nWidth; + // width is stored as 1/256th of a character in BIFF, convert to entire character + double fWidth = static_cast< double >( nWidth ) / 256.0; + // set as default width, will override the width from DEFCOLWIDTH record + setDefaultColumnWidth( fWidth ); +} + +void BiffWorksheetFragment::readDataValFormula( ApiTokenSequence& orTokens, BiffInputStream& rStrm ) +{ + sal_uInt16 nFmlaSize = rStrm.readuInt16(); + rStrm.skip( 2 ); + TokensFormulaContext aContext( true, false ); + getFormulaParser().importFormula( aContext, rStrm, &nFmlaSize ); + orTokens = aContext.getTokens(); +} + +OUString BiffWorksheetFragment::readHyperlinkString( BiffInputStream& rStrm, sal_Int32 nChars, bool bUnicode ) +{ + OUString aRet; + if( nChars > 0 ) + { + sal_uInt16 nReadChars = getLimitedValue< sal_uInt16, sal_Int32 >( nChars, 0, SAL_MAX_UINT16 ); + aRet = bUnicode ? + rStrm.readUnicodeArray( nReadChars ) : + rStrm.readCharArray( nReadChars, getTextEncoding() ); + // skip remaining chars + sal_uInt32 nSkip = static_cast< sal_uInt32 >( nChars - nReadChars ); + rStrm.skip( bUnicode ? (nSkip * 2) : nSkip ); + } + return aRet; +} + +OUString BiffWorksheetFragment::readHyperlinkString( BiffInputStream& rStrm, bool bUnicode ) +{ + return readHyperlinkString( rStrm, rStrm.readInt32(), bUnicode ); +} + +void BiffWorksheetFragment::skipHyperlinkString( BiffInputStream& rStrm, sal_Int32 nChars, bool bUnicode ) +{ + if( nChars > 0 ) + rStrm.skip( static_cast< sal_uInt32 >( bUnicode ? (nChars * 2) : nChars ) ); +} + +void BiffWorksheetFragment::skipHyperlinkString( BiffInputStream& rStrm, bool bUnicode ) +{ + skipHyperlinkString( rStrm, rStrm.readInt32(), bUnicode ); +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/worksheethelper.cxx b/oox/source/xls/worksheethelper.cxx new file mode 100644 index 000000000000..e6fdbd88d85a --- /dev/null +++ b/oox/source/xls/worksheethelper.cxx @@ -0,0 +1,1652 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: worksheethelper.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/worksheethelper.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "oox/helper/containerhelper.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/core/filterbase.hxx" +#include "oox/xls/addressconverter.hxx" +#include "oox/xls/condformatbuffer.hxx" +#include "oox/xls/formulaparser.hxx" +#include "oox/xls/ooxtokens.hxx" +#include "oox/xls/pagesettings.hxx" +#include "oox/xls/sharedformulabuffer.hxx" +#include "oox/xls/sharedstringsbuffer.hxx" +#include "oox/xls/stylesbuffer.hxx" +#include "oox/xls/unitconverter.hxx" +#include "oox/xls/validationpropertyhelper.hxx" +#include "oox/xls/viewsettings.hxx" +#include "oox/xls/worksheetbuffer.hxx" +#include "oox/xls/worksheetsettings.hxx" + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::util::XMergeable; +using ::com::sun::star::table::CellAddress; +using ::com::sun::star::table::CellRangeAddress; +using ::com::sun::star::table::BorderLine; +using ::com::sun::star::table::XColumnRowRange; +using ::com::sun::star::table::XTableColumns; +using ::com::sun::star::table::XTableRows; +using ::com::sun::star::table::XCell; +using ::com::sun::star::table::XCellRange; +using ::com::sun::star::sheet::XSpreadsheet; +using ::com::sun::star::sheet::XSheetCellRanges; +using ::com::sun::star::sheet::XSheetCellRangeContainer; +using ::com::sun::star::sheet::XCellAddressable; +using ::com::sun::star::sheet::XCellRangeAddressable; +using ::com::sun::star::sheet::XFormulaTokens; +using ::com::sun::star::sheet::XSheetOutline; +using ::com::sun::star::sheet::XMultipleOperation; +using ::com::sun::star::sheet::XLabelRanges; +using ::com::sun::star::text::XText; +using ::com::sun::star::text::XTextContent; +using ::com::sun::star::text::XTextRange; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +void lclUpdateProgressBar( ISegmentProgressBarRef xProgressBar, const CellRangeAddress& rDimension, sal_Int32 nRow ) +{ + if( xProgressBar.get() && (rDimension.StartRow <= nRow) && (nRow <= rDimension.EndRow) ) + { + double fPosition = static_cast< double >( nRow - rDimension.StartRow + 1 ) / (rDimension.EndRow - rDimension.StartRow + 1); + if( xProgressBar->getPosition() < fPosition ) + xProgressBar->setPosition( fPosition ); + } +} + +} // namespace + +// ============================================================================ +// ============================================================================ + +void OoxCellData::reset() +{ + mxCell.clear(); + maValueStr = maFormulaRef = OUString(); + mnCellType = mnFormulaType = XML_TOKEN_INVALID; + mnSharedId = mnXfId = mnNumFmtId = -1; + mbHasValueStr = mbShowPhonetic = false; +} + +// ---------------------------------------------------------------------------- + +OoxDataTableData::OoxDataTableData() : + mb2dTable( false ), + mbRowTable( false ), + mbRef1Deleted( false ), + mbRef2Deleted( false ) +{ +} + +// ---------------------------------------------------------------------------- + +OoxColumnData::OoxColumnData() : + mnFirstCol( -1 ), + mnLastCol( -1 ), + mfWidth( 0.0 ), + mnXfId( -1 ), + mnLevel( 0 ), + mbHidden( false ), + mbCollapsed( false ) +{ +} + +bool OoxColumnData::tryExpand( const OoxColumnData& rNewData ) +{ + bool bExpandable = + (mnFirstCol <= rNewData.mnFirstCol) && + (rNewData.mnFirstCol <= mnLastCol + 1) && + (mfWidth == rNewData.mfWidth) && + // ignore mnXfId, cell formatting is always set directly + (mnLevel == rNewData.mnLevel) && + (mbHidden == rNewData.mbHidden) && + (mbCollapsed == rNewData.mbCollapsed); + if( bExpandable ) + mnLastCol = rNewData.mnLastCol; + return bExpandable; +} + +// ---------------------------------------------------------------------------- + +OoxRowData::OoxRowData() : + mnFirstRow( -1 ), + mnLastRow( -1 ), + mfHeight( 0.0 ), + mnXfId( -1 ), + mnLevel( 0 ), + mbCustomHeight( false ), + mbCustomFormat( false ), + mbShowPhonetic( false ), + mbHidden( false ), + mbCollapsed( false ), + mbThickTop( false ), + mbThickBottom( false ) +{ +} + +bool OoxRowData::tryExpand( const OoxRowData& rNewData ) +{ + bool bExpandable = + (mnFirstRow <= rNewData.mnFirstRow) && + (rNewData.mnFirstRow <= mnLastRow + 1) && + (mfHeight == rNewData.mfHeight) && + // ignore mnXfId, mbCustomFormat, mbShowPhonetic - cell formatting is always set directly + (mnLevel == rNewData.mnLevel) && + (mbCustomHeight == rNewData.mbCustomHeight) && + (mbHidden == rNewData.mbHidden) && + (mbCollapsed == rNewData.mbCollapsed); + if( bExpandable ) + mnLastRow = rNewData.mnLastRow; + return bExpandable; +} + +// ---------------------------------------------------------------------------- + +OoxPageBreakData::OoxPageBreakData() : + mnColRow( 0 ), + mbManual( false ) +{ +} + +// ---------------------------------------------------------------------------- + +OoxHyperlinkData::OoxHyperlinkData() +{ +} + +// ---------------------------------------------------------------------------- + +OoxValidationData::OoxValidationData() : + mnType( XML_none ), + mnOperator( XML_between ), + mnErrorStyle( XML_stop ), + mbShowInputMsg( false ), + mbShowErrorMsg( false ), + mbNoDropDown( false ), + mbAllowBlank( false ) +{ +} + +void OoxValidationData::setBinType( sal_uInt8 nType ) +{ + static const sal_Int32 spnTypeIds[] = { + XML_none, XML_whole, XML_decimal, XML_list, XML_date, XML_time, XML_textLength, XML_custom }; + mnType = STATIC_ARRAY_SELECT( spnTypeIds, nType, XML_none ); +} + +void OoxValidationData::setBinOperator( sal_uInt8 nOperator ) +{ + static const sal_Int32 spnOperators[] = { + XML_between, XML_notBetween, XML_equal, XML_notEqual, + XML_greaterThan, XML_lessThan, XML_greaterThanOrEqual, XML_lessThanOrEqual }; + mnOperator = STATIC_ARRAY_SELECT( spnOperators, nOperator, XML_TOKEN_INVALID ); +} + +void OoxValidationData::setBinErrorStyle( sal_uInt8 nErrorStyle ) +{ + static const sal_Int32 spnErrorStyles[] = { XML_stop, XML_warning, XML_information }; + mnErrorStyle = STATIC_ARRAY_SELECT( spnErrorStyles, nErrorStyle, XML_stop ); +} + +// ============================================================================ +// ============================================================================ + +class WorksheetData : public WorkbookHelper +{ +public: + explicit WorksheetData( + const WorkbookHelper& rHelper, + ISegmentProgressBarRef xProgressBar, + WorksheetType eSheetType, + sal_Int32 nSheet ); + + /** Returns true, if this helper refers to an existing Calc sheet. */ + inline bool isValidSheet() const { return mxSheet.is(); } + + /** Returns a cell formula simulating an empty string result. */ + inline const OUString& getEmptyStringFormula() const { return maEmptyStrFormula; } + /** Returns a cell formula simulating the passed boolean value. */ + const OUString& getBooleanFormula( bool bValue ) const; + + /** Returns the type of this sheet. */ + inline WorksheetType getSheetType() const { return meSheetType; } + /** Returns the index of the current sheet. */ + inline sal_Int16 getSheetIndex() const { return mnSheet; } + /** Returns the XSpreadsheet interface of the current sheet. */ + inline const ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSpreadsheet >& + getXSpreadsheet() const { return mxSheet; } + + /** Returns the XCell interface for the passed cell address. */ + Reference< XCell > getCell( const CellAddress& rAddress ) const; + /** Returns the XCellRange interface for the passed cell range address. */ + Reference< XCellRange > getCellRange( const CellRangeAddress& rRange ) const; + /** Returns the XSheetCellRanges interface for the passed cell range addresses. */ + Reference< XSheetCellRanges > getCellRangeList( const ApiCellRangeList& rRanges ) const; + + /** Returns the XCellRange interface for a column. */ + Reference< XCellRange > getColumn( sal_Int32 nCol ) const; + /** Returns the XCellRange interface for a row. */ + Reference< XCellRange > getRow( sal_Int32 nRow ) const; + + /** Returns the XTableColumns interface for a range of columns. */ + Reference< XTableColumns > getColumns( sal_Int32 nFirstCol, sal_Int32 nLastCol ) const; + /** Returns the XTableRows interface for a range of rows. */ + Reference< XTableRows > getRows( sal_Int32 nFirstRow, sal_Int32 nLastRow ) const; + + /** Returns the worksheet settings object. */ + inline WorksheetSettings& getWorksheetSettings() { return maSheetSett; } + /** Returns the buffer containing all shared formulas in this sheet. */ + inline SharedFormulaBuffer& getSharedFormulas() { return maSharedFmlas; } + /** Returns the conditional formattings in this sheet. */ + inline CondFormatBuffer& getCondFormats() { return maCondFormats; } + /** Returns the page/print settings for this sheet. */ + inline PageSettings& getPageSettings() { return maPageSett; } + /** Returns the view settings for this sheet. */ + inline SheetViewSettings& getSheetViewSettings() { return maSheetViewSett; } + + /** Sets the dimension (used area) of the sheet. */ + void setDimension( const CellRangeAddress& rRange ); + /** Stores the cell format at the passed address. */ + void setCellFormat( const OoxCellData& rCellData ); + /** Merges the cells in the passed cell range. */ + void setMergedRange( const CellRangeAddress& rRange ); + /** Sets a column or row page break described in the passed struct. */ + void setPageBreak( const OoxPageBreakData& rData, bool bRowBreak ); + /** Inserts the hyperlink URL into the spreadsheet. */ + void setHyperlink( const OoxHyperlinkData& rHyperlink ); + /** Inserts the data validation settings into the spreadsheet. */ + void setValidation( const OoxValidationData& rValData ); + + /** Sets base width for all columns (without padding pixels). This value + is only used, if base width has not been set with setDefaultColumnWidth(). */ + void setBaseColumnWidth( sal_Int32 nWidth ); + /** Sets default width for all columns. This function overrides the base + width set with the setBaseColumnWidth() function. */ + void setDefaultColumnWidth( double fWidth ); + /** Sets column settings for a specific column range. + @descr Column default formatting is converted directly, other settings + are cached and converted in the finalizeImport() call. */ + void setColumnData( const OoxColumnData& rData ); + + /** Sets default height and hidden state for all unused rows in the sheet. */ + void setDefaultRowSettings( double fHeight, bool bCustomHeight, bool bHidden, bool bThickTop, bool bThickBottom ); + /** Sets row settings for a specific row. + @descr Row default formatting is converted directly, other settings + are cached and converted in the finalizeImport() call. */ + void setRowData( const OoxRowData& rData ); + + /** Converts column default cell formatting. */ + void convertColumnFormat( sal_Int32 nFirstCol, sal_Int32 nLastCol, sal_Int32 nXfId ); + /** Converts row default cell formatting. */ + void convertRowFormat( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId ); + + /** Initial conversion before importing the worksheet. */ + void initializeWorksheetImport(); + /** Final conversion after importing the worksheet. */ + void finalizeWorksheetImport(); + +private: + typedef ::std::vector< sal_Int32 > OutlineLevelVec; + typedef ::std::map< sal_Int32, OoxColumnData > OoxColumnDataMap; + typedef ::std::map< sal_Int32, OoxRowData > OoxRowDataMap; + typedef ::std::list< OoxHyperlinkData > OoxHyperlinkList; + typedef ::std::list< OoxValidationData > OoxValidationList; + + struct XfIdRange + { + CellRangeAddress maRange; /// The formatted cell range. + sal_Int32 mnXfId; /// XF identifier for the range. + sal_Int32 mnNumFmtId; /// Number format id overriding the XF. + + void set( const OoxCellData& rCellData ); + bool tryExpand( const OoxCellData& rCellData ); + bool tryMerge( const XfIdRange& rXfIdRange ); + }; + + struct MergedRange + { + CellRangeAddress maRange; /// The formatted cell range. + sal_Int32 mnHorAlign; /// Horizontal alignment in the range. + + explicit MergedRange( const CellRangeAddress& rAddress ); + explicit MergedRange( const CellAddress& rAddress, sal_Int32 nHorAlign ); + bool tryExpand( const CellAddress& rAddress, sal_Int32 nHorAlign ); + }; + + typedef ::std::pair< sal_Int32, sal_Int32 > RowColKey; + typedef ::std::map< RowColKey, XfIdRange > XfIdRangeMap; + typedef ::std::list< MergedRange > MergedRangeList; + + /** Writes all cell formatting attributes to the passed cell range. */ + void writeXfIdRangeProperties( const XfIdRange& rXfIdRange ) const; + /** Tries to merge the ranges last inserted in maXfIdRanges with existing ranges. */ + void mergeXfIdRanges(); + /** Finalizes the remaining ranges in maXfIdRanges. */ + void finalizeXfIdRanges(); + + /** Inserts all imported hyperlinks into their cell ranges. */ + void finalizeHyperlinkRanges() const; + /** Inserts a hyperlinks into the specified cell. */ + void finalizeHyperlink( const CellAddress& rAddress, const OUString& rUrl ) const; + + /** Inserts all imported data validations into their cell ranges. */ + void finalizeValidationRanges() const; + + /** Merges all cached merged ranges and updates right/bottom cell borders. */ + void finalizeMergedRanges() const; + /** Merges the passed merged range and updates right/bottom cell borders. */ + void finalizeMergedRange( const CellRangeAddress& rRange ) const; + + /** Converts column properties for all columns in the sheet. */ + void convertColumns(); + /** Converts column properties. */ + void convertColumns( OutlineLevelVec& orColLevels, sal_Int32 nFirstCol, sal_Int32 nLastCol, const OoxColumnData& rData ); + + /** Converts row properties for all rows in the sheet. */ + void convertRows(); + /** Converts row properties. */ + void convertRows( OutlineLevelVec& orRowLevels, sal_Int32 nFirstRow, sal_Int32 nLastRow, const OoxRowData& rData, double fDefHeight = -1.0 ); + + /** Converts outline grouping for the passed column or row. */ + void convertOutlines( OutlineLevelVec& orLevels, sal_Int32 nColRow, sal_Int32 nLevel, bool bCollapsed, bool bRows ); + /** Groups columns or rows for the given range. */ + void groupColumnsOrRows( sal_Int32 nFirstColRow, sal_Int32 nLastColRow, bool bCollapsed, bool bRows ); + +private: + const OUString maEmptyStrFormula; /// Replacement formula for empty string result. + const OUString maTrueFormula; /// Replacement formula for TRUE boolean cells. + const OUString maFalseFormula; /// Replacement formula for FALSE boolean cells. + const OUString maSheetCellRanges; /// Service name for a SheetCellRanges object. + const OUString maRightBorderProp; /// Property name of the right border of a cell. + const OUString maBottomBorderProp; /// Property name of the bottom border of a cell. + const OUString maWidthProp; /// Property name for column width. + const OUString maHeightProp; /// Property name for row height. + const OUString maVisibleProp; /// Property name for column/row visibility. + const OUString maPageBreakProp; /// Property name of a page break. + const OUString maUrlTextField; /// Service name for a URL text field. + const OUString maUrlProp; /// Property name for the URL string in a URL text field. + const OUString maReprProp; /// Property name for the URL representation in a URL text field. + const CellAddress& mrMaxApiPos; /// Reference to maximum Calc cell address from address converter. + CellRangeAddress maDimension; /// Dimension (used) area of the sheet. + OoxColumnData maDefColData; /// Default column formatting. + OoxColumnDataMap maColDatas; /// Column data sorted by first column index. + OoxRowData maDefRowData; /// Default row formatting. + OoxRowDataMap maRowDatas; /// Row data sorted by row index. + OoxHyperlinkList maHyperlinks; /// Cell ranges containing hyperlinks. + OoxValidationList maValidations; /// Cell ranges containing data validation settings. + XfIdRangeMap maXfIdRanges; /// Collected XF identifiers for cell ranges. + MergedRangeList maMergedRanges; /// Merged cell ranges. + MergedRangeList maCenterFillRanges; /// Merged cell ranges from 'center across' or 'fill' alignment. + WorksheetSettings maSheetSett; /// Global settings for this sheet. + SharedFormulaBuffer maSharedFmlas; /// Buffer for shared formulas in this sheet. + CondFormatBuffer maCondFormats; /// Buffer for conditional formattings. + PageSettings maPageSett; /// Page/print settings for this sheet. + SheetViewSettings maSheetViewSett; /// View settings for this sheet. + ISegmentProgressBarRef mxProgressBar; /// Sheet progress bar. + ISegmentProgressBarRef mxRowProgress; /// Progress bar for row/cell processing. + ISegmentProgressBarRef mxFinalProgress; /// Progress bar for finalization. + const WorksheetType meSheetType; /// Type of thes sheet. + Reference< XSpreadsheet > mxSheet; /// Reference to the current sheet. + sal_Int16 mnSheet; /// Index of the current sheet. + bool mbHasDefWidth; /// True = default column width is set from defaultColWidth attribute. +}; + +// ---------------------------------------------------------------------------- + +WorksheetData::WorksheetData( const WorkbookHelper& rHelper, ISegmentProgressBarRef xProgressBar, WorksheetType eSheetType, sal_Int32 nSheet ) : + WorkbookHelper( rHelper ), + maEmptyStrFormula( CREATE_OUSTRING( "=\"\"" ) ), + maTrueFormula( CREATE_OUSTRING( "=TRUE()" ) ), + maFalseFormula( CREATE_OUSTRING( "=FALSE()" ) ), + maSheetCellRanges( CREATE_OUSTRING( "com.sun.star.sheet.SheetCellRanges" ) ), + maRightBorderProp( CREATE_OUSTRING( "RightBorder" ) ), + maBottomBorderProp( CREATE_OUSTRING( "BottomBorder" ) ), + maWidthProp( CREATE_OUSTRING( "Width" ) ), + maHeightProp( CREATE_OUSTRING( "Height" ) ), + maVisibleProp( CREATE_OUSTRING( "IsVisible" ) ), + maPageBreakProp( CREATE_OUSTRING( "IsStartOfNewPage" ) ), + maUrlTextField( CREATE_OUSTRING( "com.sun.star.text.TextField.URL" ) ), + maUrlProp( CREATE_OUSTRING( "URL" ) ), + maReprProp( CREATE_OUSTRING( "Representation" ) ), + mrMaxApiPos( rHelper.getAddressConverter().getMaxApiAddress() ), + maSheetSett( WorksheetHelper( *this ) ), + maSharedFmlas( WorksheetHelper( *this ) ), + maCondFormats( WorksheetHelper( *this ) ), + maPageSett( WorksheetHelper( *this ) ), + maSheetViewSett( WorksheetHelper( *this ) ), + mxProgressBar( xProgressBar ), + meSheetType( eSheetType ), + mnSheet( static_cast< sal_Int16 >( nSheet ) ), + mbHasDefWidth( false ) +{ + OSL_ENSURE( nSheet <= SAL_MAX_INT16, "WorksheetData::WorksheetData - invalid sheet index" ); + mxSheet = getSheet( nSheet ); + if( !mxSheet.is() ) + mnSheet = -1; + + maDimension.Sheet = mnSheet; + + // default column settings (width and hidden state may be updated later) + maDefColData.mfWidth = 8.5; + maDefColData.mnXfId = -1; + maDefColData.mnLevel = 0; + maDefColData.mbHidden = false; + maDefColData.mbCollapsed = false; + + // default row settings (height and hidden state may be updated later) + maDefRowData.mfHeight = 0.0; + maDefRowData.mnXfId = -1; + maDefRowData.mnLevel = 0; + maDefRowData.mbCustomHeight = false; + maDefRowData.mbCustomFormat = false; + maDefRowData.mbShowPhonetic = false; + maDefRowData.mbHidden = false; + maDefRowData.mbCollapsed = false; + + if( mxProgressBar.get() ) + { + mxRowProgress = mxProgressBar->createSegment( 0.5 ); + mxFinalProgress = mxProgressBar->createSegment( 0.5 ); + } +} + +const OUString& WorksheetData::getBooleanFormula( bool bValue ) const +{ + return bValue ? maTrueFormula : maFalseFormula; +} + +Reference< XCell > WorksheetData::getCell( const CellAddress& rAddress ) const +{ + Reference< XCell > xCell; + if( mxSheet.is() ) try + { + xCell = mxSheet->getCellByPosition( rAddress.Column, rAddress.Row ); + } + catch( Exception& ) + { + } + return xCell; +} + +Reference< XCellRange > WorksheetData::getCellRange( const CellRangeAddress& rRange ) const +{ + Reference< XCellRange > xRange; + if( mxSheet.is() ) try + { + xRange = mxSheet->getCellRangeByPosition( rRange.StartColumn, rRange.StartRow, rRange.EndColumn, rRange.EndRow ); + } + catch( Exception& ) + { + } + return xRange; +} + +Reference< XSheetCellRanges > WorksheetData::getCellRangeList( const ApiCellRangeList& rRanges ) const +{ + Reference< XSheetCellRanges > xRanges; + if( mxSheet.is() && !rRanges.empty() ) try + { + Reference< XMultiServiceFactory > xFactory( getDocument(), UNO_QUERY_THROW ); + xRanges.set( xFactory->createInstance( maSheetCellRanges ), UNO_QUERY_THROW ); + Reference< XSheetCellRangeContainer > xRangeCont( xRanges, UNO_QUERY_THROW ); + xRangeCont->addRangeAddresses( ContainerHelper::vectorToSequence( rRanges ), sal_False ); + } + catch( Exception& ) + { + } + return xRanges; +} + +Reference< XCellRange > WorksheetData::getColumn( sal_Int32 nCol ) const +{ + Reference< XCellRange > xColumn; + try + { + Reference< XColumnRowRange > xColRowRange( mxSheet, UNO_QUERY_THROW ); + Reference< XTableColumns > xColumns = xColRowRange->getColumns(); + if( xColumns.is() ) + xColumn.set( xColumns->getByIndex( nCol ), UNO_QUERY ); + } + catch( Exception& ) + { + } + return xColumn; +} + +Reference< XCellRange > WorksheetData::getRow( sal_Int32 nRow ) const +{ + Reference< XCellRange > xRow; + try + { + Reference< XColumnRowRange > xColRowRange( mxSheet, UNO_QUERY_THROW ); + Reference< XTableRows > xRows = xColRowRange->getRows(); + xRow.set( xRows->getByIndex( nRow ), UNO_QUERY ); + } + catch( Exception& ) + { + } + return xRow; +} + +Reference< XTableColumns > WorksheetData::getColumns( sal_Int32 nFirstCol, sal_Int32 nLastCol ) const +{ + Reference< XTableColumns > xColumns; + nLastCol = ::std::min( nLastCol, mrMaxApiPos.Column ); + if( (0 <= nFirstCol) && (nFirstCol <= nLastCol) ) + { + Reference< XColumnRowRange > xRange( getCellRange( CellRangeAddress( mnSheet, nFirstCol, 0, nLastCol, 0 ) ), UNO_QUERY ); + if( xRange.is() ) + xColumns = xRange->getColumns(); + } + return xColumns; +} + +Reference< XTableRows > WorksheetData::getRows( sal_Int32 nFirstRow, sal_Int32 nLastRow ) const +{ + Reference< XTableRows > xRows; + nLastRow = ::std::min( nLastRow, mrMaxApiPos.Row ); + if( (0 <= nFirstRow) && (nFirstRow <= nLastRow) ) + { + Reference< XColumnRowRange > xRange( getCellRange( CellRangeAddress( mnSheet, 0, nFirstRow, 0, nLastRow ) ), UNO_QUERY ); + if( xRange.is() ) + xRows = xRange->getRows(); + } + return xRows; +} + +void WorksheetData::setDimension( const CellRangeAddress& rRange ) +{ + maDimension = rRange; +} + +void WorksheetData::setCellFormat( const OoxCellData& rCellData ) +{ + if( rCellData.mxCell.is() && (rCellData.mnXfId >= 0) || (rCellData.mnNumFmtId >= 0) ) + { + // try to merge existing ranges and to write some formatting properties + if( !maXfIdRanges.empty() ) + { + // get row index of last inserted cell + sal_Int32 nLastRow = maXfIdRanges.rbegin()->second.maRange.StartRow; + // row changed - try to merge ranges of last row with existing ranges + if( rCellData.maAddress.Row != nLastRow ) + { + mergeXfIdRanges(); + // write format properties of all ranges above last row and remove them + XfIdRangeMap::iterator aIt = maXfIdRanges.begin(), aEnd = maXfIdRanges.end(); + while( aIt != aEnd ) + { + if( aIt->second.maRange.EndRow < nLastRow ) + { + writeXfIdRangeProperties( aIt->second ); + maXfIdRanges.erase( aIt++ ); + } + else + ++aIt; + } + } + } + + // try to expand last existing range, or create new range entry + if( maXfIdRanges.empty() || !maXfIdRanges.rbegin()->second.tryExpand( rCellData ) ) + maXfIdRanges[ RowColKey( rCellData.maAddress.Row, rCellData.maAddress.Column ) ].set( rCellData ); + + // update merged ranges for 'center across selection' and 'fill' + if( const Xf* pXf = getStyles().getCellXf( rCellData.mnXfId ).get() ) + { + sal_Int32 nHorAlign = pXf->getAlignment().getOoxData().mnHorAlign; + if( (nHorAlign == XML_centerContinuous) || (nHorAlign == XML_fill) ) + { + /* start new merged range, if cell is not empty (#108781#), + or try to expand last range with empty cell */ + if( rCellData.mnCellType != XML_TOKEN_INVALID ) + maCenterFillRanges.push_back( MergedRange( rCellData.maAddress, nHorAlign ) ); + else if( !maCenterFillRanges.empty() ) + maCenterFillRanges.rbegin()->tryExpand( rCellData.maAddress, nHorAlign ); + } + } + } +} + +void WorksheetData::setMergedRange( const CellRangeAddress& rRange ) +{ + maMergedRanges.push_back( MergedRange( rRange ) ); +} + +void WorksheetData::setPageBreak( const OoxPageBreakData& rData, bool bRowBreak ) +{ + if( rData.mbManual && (rData.mnColRow > 0) ) + { + PropertySet aPropSet( bRowBreak ? getRow( rData.mnColRow ) : getColumn( rData.mnColRow ) ); + aPropSet.setProperty( maPageBreakProp, true ); + } +} + +void WorksheetData::setHyperlink( const OoxHyperlinkData& rHyperlink ) +{ + maHyperlinks.push_back( rHyperlink ); +} + +void WorksheetData::setValidation( const OoxValidationData& rValData ) +{ + maValidations.push_back( rValData ); +} + +void WorksheetData::setBaseColumnWidth( sal_Int32 nWidth ) +{ + // do not modify width, if setDefaultColumnWidth() has been used + if( !mbHasDefWidth && (nWidth > 0) ) + { + /* #i3006# add 5 pixels padding to the width, assuming 1 pixel = + 1/96 inch. => 5/96 inch == 1.32 mm. */ + const UnitConverter& rUnitConv = getUnitConverter(); + maDefColData.mfWidth = rUnitConv.calcDigitsFromMm100( rUnitConv.calcMm100FromDigits( nWidth ) + 132 ); + } +} + +void WorksheetData::setDefaultColumnWidth( double fWidth ) +{ + // overrides a width set with setBaseColumnWidth() + if( fWidth > 0.0 ) + { + maDefColData.mfWidth = fWidth; + mbHasDefWidth = true; + } +} + +void WorksheetData::setColumnData( const OoxColumnData& rData ) +{ + // convert 1-based OOX column indexes to 0-based API column indexes + sal_Int32 nFirstCol = rData.mnFirstCol - 1; + sal_Int32 nLastCol = rData.mnLastCol - 1; + if( (0 <= nFirstCol) && (nFirstCol <= mrMaxApiPos.Column) ) + { + // set column formatting directly, nLastCol is checked inside the function + convertColumnFormat( nFirstCol, nLastCol, rData.mnXfId ); + // expand last entry or add new entry + if( maColDatas.empty() || !maColDatas.rbegin()->second.tryExpand( rData ) ) + maColDatas[ nFirstCol ] = rData; + } +} + +void WorksheetData::setDefaultRowSettings( double fHeight, bool bCustomHeight, bool bHidden, bool bThickTop, bool bThickBottom ) +{ + maDefRowData.mfHeight = fHeight; + maDefRowData.mbCustomHeight = bCustomHeight; + maDefRowData.mbHidden = bHidden; + maDefRowData.mbThickTop = bThickTop; + maDefRowData.mbThickBottom = bThickBottom; +} + +void WorksheetData::setRowData( const OoxRowData& rData ) +{ + // convert 1-based OOX row indexes to 0-based API row indexes + sal_Int32 nFirstRow = rData.mnFirstRow - 1; + sal_Int32 nLastRow = rData.mnLastRow - 1; + if( (0 <= nFirstRow) && (nFirstRow <= mrMaxApiPos.Row) ) + { + // set row formatting directly + if( rData.mbCustomFormat ) + convertRowFormat( nFirstRow, nLastRow, rData.mnXfId ); + // expand last entry or add new entry + if( maRowDatas.empty() || !maRowDatas.rbegin()->second.tryExpand( rData ) ) + maRowDatas[ nFirstRow ] = rData; + } + lclUpdateProgressBar( mxRowProgress, maDimension, nLastRow ); +} + +void WorksheetData::convertColumnFormat( sal_Int32 nFirstCol, sal_Int32 nLastCol, sal_Int32 nXfId ) +{ + CellRangeAddress aRange( mnSheet, nFirstCol, 0, nLastCol, mrMaxApiPos.Row ); + if( getAddressConverter().validateCellRange( aRange, false ) ) + { + PropertySet aPropSet( getCellRange( aRange ) ); + getStyles().writeCellXfToPropertySet( aPropSet, nXfId ); + } +} + +void WorksheetData::convertRowFormat( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId ) +{ + CellRangeAddress aRange( mnSheet, 0, nFirstRow, mrMaxApiPos.Column, nLastRow ); + if( getAddressConverter().validateCellRange( aRange, false ) ) + { + PropertySet aPropSet( getCellRange( aRange ) ); + getStyles().writeCellXfToPropertySet( aPropSet, nXfId ); + } +} + +void WorksheetData::initializeWorksheetImport() +{ +#if OOX_XLS_USE_DEFAULT_STYLE +#else + // set default cell style for unused cells + PropertySet aPropSet( mxSheet ); + aPropSet.setProperty( CREATE_OUSTRING( "CellStyle" ), getStyles().getDefaultStyleName() ); +#endif +} + +void WorksheetData::finalizeWorksheetImport() +{ + finalizeXfIdRanges(); + finalizeHyperlinkRanges(); + finalizeValidationRanges(); + finalizeMergedRanges(); + maCondFormats.finalizeImport(); + maPageSett.finalizeImport(); + maSheetViewSett.finalizeImport(); + convertColumns(); + convertRows(); +} + +// private -------------------------------------------------------------------- + +void WorksheetData::XfIdRange::set( const OoxCellData& rCellData ) +{ + maRange.Sheet = rCellData.maAddress.Sheet; + maRange.StartColumn = maRange.EndColumn = rCellData.maAddress.Column; + maRange.StartRow = maRange.EndRow = rCellData.maAddress.Row; + mnXfId = rCellData.mnXfId; + mnNumFmtId = rCellData.mnNumFmtId; +} + +bool WorksheetData::XfIdRange::tryExpand( const OoxCellData& rCellData ) +{ + if( (mnXfId == rCellData.mnXfId) && (mnNumFmtId == rCellData.mnNumFmtId) && + (maRange.StartRow == rCellData.maAddress.Row) && + (maRange.EndRow == rCellData.maAddress.Row) && + (maRange.EndColumn + 1 == rCellData.maAddress.Column) ) + { + ++maRange.EndColumn; + return true; + } + return false; +} + +bool WorksheetData::XfIdRange::tryMerge( const XfIdRange& rXfIdRange ) +{ + if( (mnXfId == rXfIdRange.mnXfId) && + (mnNumFmtId == rXfIdRange.mnNumFmtId) && + (maRange.EndRow + 1 == rXfIdRange.maRange.StartRow) && + (maRange.StartColumn == rXfIdRange.maRange.StartColumn) && + (maRange.EndColumn == rXfIdRange.maRange.EndColumn) ) + { + maRange.EndRow = rXfIdRange.maRange.EndRow; + return true; + } + return false; +} + + +WorksheetData::MergedRange::MergedRange( const CellRangeAddress& rRange ) : + maRange( rRange ), + mnHorAlign( XML_TOKEN_INVALID ) +{ +} + +WorksheetData::MergedRange::MergedRange( const CellAddress& rAddress, sal_Int32 nHorAlign ) : + maRange( rAddress.Sheet, rAddress.Column, rAddress.Row, rAddress.Column, rAddress.Row ), + mnHorAlign( nHorAlign ) +{ +} + +bool WorksheetData::MergedRange::tryExpand( const CellAddress& rAddress, sal_Int32 nHorAlign ) +{ + if( (mnHorAlign == nHorAlign) && (maRange.StartRow == rAddress.Row) && + (maRange.EndRow == rAddress.Row) && (maRange.EndColumn + 1 == rAddress.Column) ) + { + ++maRange.EndColumn; + return true; + } + return false; +} + +void WorksheetData::writeXfIdRangeProperties( const XfIdRange& rXfIdRange ) const +{ + StylesBuffer& rStyles = getStyles(); + PropertySet aPropSet( getCellRange( rXfIdRange.maRange ) ); + if( rXfIdRange.mnXfId >= 0 ) + rStyles.writeCellXfToPropertySet( aPropSet, rXfIdRange.mnXfId ); + if( rXfIdRange.mnNumFmtId >= 0 ) + rStyles.writeNumFmtToPropertySet( aPropSet, rXfIdRange.mnNumFmtId ); +} + +void WorksheetData::mergeXfIdRanges() +{ + if( !maXfIdRanges.empty() ) + { + // get row index of last range + sal_Int32 nLastRow = maXfIdRanges.rbegin()->second.maRange.StartRow; + // process all ranges located in the same row of the last range + XfIdRangeMap::iterator aMergeIt = maXfIdRanges.end(); + while( (aMergeIt != maXfIdRanges.begin()) && ((--aMergeIt)->second.maRange.StartRow == nLastRow) ) + { + const XfIdRange& rMergeXfIdRange = aMergeIt->second; + // try to find a range that can be merged with rMergeRange + bool bFound = false; + for( XfIdRangeMap::iterator aIt = maXfIdRanges.begin(); !bFound && (aIt != aMergeIt); ++aIt ) + if( (bFound = aIt->second.tryMerge( rMergeXfIdRange )) == true ) + maXfIdRanges.erase( aMergeIt++ ); + } + } +} + +void WorksheetData::finalizeXfIdRanges() +{ + // try to merge remaining inserted ranges + mergeXfIdRanges(); + // write all formatting + sal_Int32 nLastRow = -1; + for( XfIdRangeMap::const_iterator aIt = maXfIdRanges.begin(), aEnd = maXfIdRanges.end(); aIt != aEnd; ++aIt ) + { + writeXfIdRangeProperties( aIt->second ); + if( aIt->first.first > nLastRow ) + lclUpdateProgressBar( mxFinalProgress, maDimension, nLastRow = aIt->first.first ); + } +} + +void WorksheetData::finalizeHyperlinkRanges() const +{ + for( OoxHyperlinkList::const_iterator aIt = maHyperlinks.begin(), aEnd = maHyperlinks.end(); aIt != aEnd; ++aIt ) + { + OUStringBuffer aUrlBuffer( getBaseFilter().getAbsoluteUrl( aIt->maTarget ) ); + if( aIt->maLocation.getLength() > 0 ) + aUrlBuffer.append( sal_Unicode( '#' ) ).append( aIt->maLocation ); + OUString aUrl = aUrlBuffer.makeStringAndClear(); + if( aUrl.getLength() > 0 ) + { + // convert '#SheetName!A1' to '#SheetName.A1' + if( aUrl[ 0 ] == '#' ) + { + sal_Int32 nSepPos = aUrl.lastIndexOf( '!' ); + if( nSepPos > 0 ) + { + // replace the exclamation mark with a period + aUrl = aUrl.replaceAt( nSepPos, 1, OUString( sal_Unicode( '.' ) ) ); + // #i66592# convert renamed sheets + bool bQuotedName = (nSepPos > 3) && (aUrl[ 1 ] == '\'') && (aUrl[ nSepPos - 1 ] == '\''); + sal_Int32 nNamePos = bQuotedName ? 2 : 1; + sal_Int32 nNameLen = nSepPos - (bQuotedName ? 3 : 1); + OUString aSheetName = aUrl.copy( nNamePos, nNameLen ); + OUString aFinalName = getWorksheets().getFinalSheetName( aSheetName ); + if( aFinalName.getLength() > 0 ) + aUrl = aUrl.replaceAt( nNamePos, nNameLen, aFinalName ); + } + } + + // try to insert URL into each cell of the range + for( CellAddress aAddress( mnSheet, aIt->maRange.StartColumn, aIt->maRange.StartRow ); aAddress.Row <= aIt->maRange.EndRow; ++aAddress.Row ) + for( aAddress.Column = aIt->maRange.StartColumn; aAddress.Column <= aIt->maRange.EndColumn; ++aAddress.Column ) + finalizeHyperlink( aAddress, aUrl ); + } + } +} + +void WorksheetData::finalizeHyperlink( const CellAddress& rAddress, const OUString& rUrl ) const +{ + Reference< XMultiServiceFactory > xFactory( getDocument(), UNO_QUERY ); + Reference< XCell > xCell = getCell( rAddress ); + Reference< XText > xText( xCell, UNO_QUERY ); + // hyperlinks only supported in text cells + if( xFactory.is() && xCell.is() && (xCell->getType() == ::com::sun::star::table::CellContentType_TEXT) && xText.is() ) + { + // create a URL field object and set its properties + Reference< XTextContent > xUrlField( xFactory->createInstance( maUrlTextField ), UNO_QUERY ); + OSL_ENSURE( xUrlField.is(), "WorksheetData::finalizeHyperlink - cannot create text field" ); + if( xUrlField.is() ) + { + // properties of the URL field + PropertySet aPropSet( xUrlField ); + aPropSet.setProperty( maUrlProp, rUrl ); + aPropSet.setProperty( maReprProp, xText->getString() ); + try + { + // insert the field into the cell + xText->setString( OUString() ); + Reference< XTextRange > xRange( xText->createTextCursor(), UNO_QUERY_THROW ); + xText->insertTextContent( xRange, xUrlField, sal_False ); + } + catch( const Exception& ) + { + OSL_ENSURE( false, "WorksheetData::finalizeHyperlink - cannot insert text field" ); + } + } + } +} + +void WorksheetData::finalizeValidationRanges() const +{ + ValidationPropertyHelper& rPropHelper = getValidationPropertyHelper(); + for( OoxValidationList::const_iterator aIt = maValidations.begin(), aEnd = maValidations.end(); aIt != aEnd; ++aIt ) + { + PropertySet aPropSet( getCellRangeList( aIt->maRanges ) ); + rPropHelper.writeValidationProperties( aPropSet, *aIt ); + } +} + +void WorksheetData::finalizeMergedRanges() const +{ + MergedRangeList::const_iterator aIt, aEnd; + for( aIt = maMergedRanges.begin(), aEnd = maMergedRanges.end(); aIt != aEnd; ++aIt ) + finalizeMergedRange( aIt->maRange ); + for( aIt = maCenterFillRanges.begin(), aEnd = maCenterFillRanges.end(); aIt != aEnd; ++aIt ) + finalizeMergedRange( aIt->maRange ); +} + +void WorksheetData::finalizeMergedRange( const CellRangeAddress& rRange ) const +{ + bool bMultiCol = rRange.StartColumn < rRange.EndColumn; + bool bMultiRow = rRange.StartRow < rRange.EndRow; + + if( bMultiCol || bMultiRow ) try + { + // merge the cell range + Reference< XMergeable > xMerge( getCellRange( rRange ), UNO_QUERY_THROW ); + xMerge->merge( sal_True ); + + // if merging this range worked (no overlapping merged ranges), update cell borders + PropertySet aTopLeft( getCell( CellAddress( mnSheet, rRange.StartColumn, rRange.StartRow ) ) ); + + // copy right border of top-right cell to right border of top-left cell + if( bMultiCol ) + { + PropertySet aTopRight( getCell( CellAddress( mnSheet, rRange.EndColumn, rRange.StartRow ) ) ); + BorderLine aLine; + if( aTopRight.getProperty( aLine, maRightBorderProp ) ) + aTopLeft.setProperty( maRightBorderProp, aLine ); + } + + // copy bottom border of bottom-left cell to bottom border of top-left cell + if( bMultiRow ) + { + PropertySet aBottomLeft( getCell( CellAddress( mnSheet, rRange.StartColumn, rRange.EndRow ) ) ); + BorderLine aLine; + if( aBottomLeft.getProperty( aLine, maBottomBorderProp ) ) + aTopLeft.setProperty( maBottomBorderProp, aLine ); + } + } + catch( Exception& ) + { + } +} + +void WorksheetData::convertColumns() +{ + sal_Int32 nNextCol = 0; + sal_Int32 nMaxCol = mrMaxApiPos.Column; + // stores first grouped column index for each level + OutlineLevelVec aColLevels; + + for( OoxColumnDataMap::const_iterator aIt = maColDatas.begin(), aEnd = maColDatas.end(); aIt != aEnd; ++aIt ) + { + // convert 1-based OOX column indexes to 0-based API column indexes + sal_Int32 nFirstCol = ::std::max( aIt->second.mnFirstCol - 1, nNextCol ); + sal_Int32 nLastCol = ::std::min( aIt->second.mnLastCol - 1, nMaxCol ); + + // process gap between two column datas, use default column data + if( nNextCol < nFirstCol ) + convertColumns( aColLevels, nNextCol, nFirstCol - 1, maDefColData ); + // process the column data + convertColumns( aColLevels, nFirstCol, nLastCol, aIt->second ); + + // cache next column to be processed + nNextCol = nLastCol + 1; + } + + // remaining default columns to end of sheet + convertColumns( aColLevels, nNextCol, nMaxCol, maDefColData ); + // close remaining column outlines spanning to end of sheet + convertOutlines( aColLevels, nMaxCol + 1, 0, false, false ); +} + +void WorksheetData::convertColumns( OutlineLevelVec& orColLevels, + sal_Int32 nFirstCol, sal_Int32 nLastCol, const OoxColumnData& rData ) +{ + Reference< XTableColumns > xColumns = getColumns( nFirstCol, nLastCol ); + if( xColumns.is() ) + { + PropertySet aPropSet( xColumns ); + // column width: convert 'number of characters' to column width in 1/100 mm + sal_Int32 nWidth = getUnitConverter().calcMm100FromDigits( rData.mfWidth ); + if( nWidth > 0 ) + aPropSet.setProperty( maWidthProp, nWidth ); + // hidden columns: TODO: #108683# hide columns later? + if( rData.mbHidden ) + aPropSet.setProperty( maVisibleProp, false ); + } + // outline settings for this column range + convertOutlines( orColLevels, nFirstCol, rData.mnLevel, rData.mbCollapsed, false ); +} + +void WorksheetData::convertRows() +{ + sal_Int32 nNextRow = 0; + sal_Int32 nMaxRow = mrMaxApiPos.Row; + // stores first grouped row index for each level + OutlineLevelVec aRowLevels; + + for( OoxRowDataMap::const_iterator aIt = maRowDatas.begin(), aEnd = maRowDatas.end(); aIt != aEnd; ++aIt ) + { + // convert 1-based OOX row indexes to 0-based API row indexes + sal_Int32 nFirstRow = ::std::max( aIt->second.mnFirstRow - 1, nNextRow ); + sal_Int32 nLastRow = ::std::min( aIt->second.mnLastRow - 1, nMaxRow ); + + // process gap between two row datas, use default row data + if( nNextRow < nFirstRow ) + convertRows( aRowLevels, nNextRow, nFirstRow - 1, maDefRowData ); + // process the row data + convertRows( aRowLevels, nFirstRow, nLastRow, aIt->second, maDefRowData.mfHeight ); + + // cache next row to be processed + nNextRow = nLastRow + 1; + } + + // remaining default rows to end of sheet + convertRows( aRowLevels, nNextRow, nMaxRow, maDefRowData ); + // close remaining row outlines spanning to end of sheet + convertOutlines( aRowLevels, nMaxRow + 1, 0, false, true ); +} + +void WorksheetData::convertRows( OutlineLevelVec& orRowLevels, + sal_Int32 nFirstRow, sal_Int32 nLastRow, const OoxRowData& rData, double fDefHeight ) +{ + Reference< XTableRows > xRows = getRows( nFirstRow, nLastRow ); + if( xRows.is() ) + { + PropertySet aPropSet( xRows ); + /* Row height: + - convert points to row height in 1/100 mm + - ignore rData.mbCustomHeight, Excel does not set optimal height + correctly, if a merged cell contains multi-line text. + */ + double fHeight = (rData.mfHeight >= 0.0) ? rData.mfHeight : fDefHeight; + sal_Int32 nHeight = getUnitConverter().calcMm100FromPoints( fHeight ); + if( nHeight > 0 ) + aPropSet.setProperty( maHeightProp, nHeight ); + // hidden rows: TODO: #108683# hide rows later? + if( rData.mbHidden ) + aPropSet.setProperty( maVisibleProp, false ); + } + // outline settings for this row range + convertOutlines( orRowLevels, nFirstRow, rData.mnLevel, rData.mbCollapsed, true ); +} + +void WorksheetData::convertOutlines( OutlineLevelVec& orLevels, + sal_Int32 nColRow, sal_Int32 nLevel, bool bCollapsed, bool bRows ) +{ + /* It is ensured from caller functions, that this function is called + without any gaps between the processed column or row ranges. */ + + OSL_ENSURE( nLevel >= 0, "WorksheetData::convertOutlines - negative outline level" ); + nLevel = ::std::max< sal_Int32 >( nLevel, 0 ); + + sal_Int32 nSize = orLevels.size(); + if( nSize < nLevel ) + { + // Outline level increased. Push the begin column position. + for( sal_Int32 nIndex = nSize; nIndex < nLevel; ++nIndex ) + orLevels.push_back( nColRow ); + } + else if( nLevel < nSize ) + { + // Outline level decreased. Pop them all out. + for( sal_Int32 nIndex = nLevel; nIndex < nSize; ++nIndex ) + { + sal_Int32 nFirstInLevel = orLevels.back(); + orLevels.pop_back(); + groupColumnsOrRows( nFirstInLevel, nColRow - 1, bCollapsed, bRows ); + bCollapsed = false; // collapse only once + } + } +} + +void WorksheetData::groupColumnsOrRows( sal_Int32 nFirstColRow, sal_Int32 nLastColRow, bool bCollapse, bool bRows ) +{ + try + { + Reference< XSheetOutline > xOutline( mxSheet, UNO_QUERY_THROW ); + if( bRows ) + { + CellRangeAddress aRange( mnSheet, 0, nFirstColRow, 0, nLastColRow ); + xOutline->group( aRange, ::com::sun::star::table::TableOrientation_ROWS ); + if( bCollapse ) + xOutline->hideDetail( aRange ); + } + else + { + CellRangeAddress aRange( mnSheet, nFirstColRow, 0, nLastColRow, 0 ); + xOutline->group( aRange, ::com::sun::star::table::TableOrientation_COLUMNS ); + if( bCollapse ) + xOutline->hideDetail( aRange ); + } + } + catch( Exception& ) + { + } +} + +// ============================================================================ +// ============================================================================ + +WorksheetHelper::WorksheetHelper( WorksheetData& rSheetData ) : + WorkbookHelper( rSheetData ), + mrSheetData( rSheetData ) +{ +} + +WorksheetType WorksheetHelper::getSheetType() const +{ + return mrSheetData.getSheetType(); +} + +sal_Int16 WorksheetHelper::getSheetIndex() const +{ + return mrSheetData.getSheetIndex(); +} + +const Reference< XSpreadsheet >& WorksheetHelper::getXSpreadsheet() const +{ + return mrSheetData.getXSpreadsheet(); +} + +Reference< XCell > WorksheetHelper::getCell( const CellAddress& rAddress ) const +{ + return mrSheetData.getCell( rAddress ); +} + +Reference< XCell > WorksheetHelper::getCell( const OUString& rAddressStr, CellAddress* opAddress ) const +{ + CellAddress aAddress; + if( getAddressConverter().convertToCellAddress( aAddress, rAddressStr, mrSheetData.getSheetIndex(), true ) ) + { + if( opAddress ) *opAddress = aAddress; + return mrSheetData.getCell( aAddress ); + } + return Reference< XCell >(); +} + +Reference< XCell > WorksheetHelper::getCell( const BinAddress& rBinAddress, CellAddress* opAddress ) const +{ + CellAddress aAddress; + if( getAddressConverter().convertToCellAddress( aAddress, rBinAddress, mrSheetData.getSheetIndex(), true ) ) + { + if( opAddress ) *opAddress = aAddress; + return mrSheetData.getCell( aAddress ); + } + return Reference< XCell >(); +} + +Reference< XCellRange > WorksheetHelper::getCellRange( const CellRangeAddress& rRange ) const +{ + return mrSheetData.getCellRange( rRange ); +} + +Reference< XCellRange > WorksheetHelper::getCellRange( const OUString& rRangeStr, CellRangeAddress* opRange ) const +{ + CellRangeAddress aRange; + if( getAddressConverter().convertToCellRange( aRange, rRangeStr, mrSheetData.getSheetIndex(), true ) ) + { + if( opRange ) *opRange = aRange; + return mrSheetData.getCellRange( aRange ); + } + return Reference< XCellRange >(); +} + +Reference< XCellRange > WorksheetHelper::getCellRange( const BinRange& rBinRange, CellRangeAddress* opRange ) const +{ + CellRangeAddress aRange; + if( getAddressConverter().convertToCellRange( aRange, rBinRange, mrSheetData.getSheetIndex(), true ) ) + { + if( opRange ) *opRange = aRange; + return mrSheetData.getCellRange( aRange ); + } + return Reference< XCellRange >(); +} + +Reference< XSheetCellRanges > WorksheetHelper::getCellRangeList( const ApiCellRangeList& rRanges ) const +{ + return mrSheetData.getCellRangeList( rRanges ); +} + +Reference< XSheetCellRanges > WorksheetHelper::getCellRangeList( + const OUString& rRangesStr, ApiCellRangeList* opRanges ) const +{ + ApiCellRangeList aRanges; + getAddressConverter().convertToCellRangeList( aRanges, rRangesStr, mrSheetData.getSheetIndex(), true ); + if( opRanges ) *opRanges = aRanges; + return mrSheetData.getCellRangeList( aRanges ); +} + +Reference< XSheetCellRanges > WorksheetHelper::getCellRangeList( + const BinRangeList& rBinRanges, ApiCellRangeList* opRanges ) const +{ + ApiCellRangeList aRanges; + getAddressConverter().convertToCellRangeList( aRanges, rBinRanges, mrSheetData.getSheetIndex(), true ); + if( opRanges ) *opRanges = aRanges; + return mrSheetData.getCellRangeList( aRanges ); +} + +CellAddress WorksheetHelper::getCellAddress( const Reference< XCell >& rxCell ) +{ + CellAddress aAddress; + Reference< XCellAddressable > xAddressable( rxCell, UNO_QUERY ); + OSL_ENSURE( xAddressable.is(), "WorksheetHelper::getCellAddress - cell reference not addressable" ); + if( xAddressable.is() ) + aAddress = xAddressable->getCellAddress(); + return aAddress; +} + +CellRangeAddress WorksheetHelper::getRangeAddress( const Reference< XCellRange >& rxRange ) +{ + CellRangeAddress aRange; + Reference< XCellRangeAddressable > xAddressable( rxRange, UNO_QUERY ); + OSL_ENSURE( xAddressable.is(), "WorksheetHelper::getRangeAddress - cell range reference not addressable" ); + if( xAddressable.is() ) + aRange = xAddressable->getRangeAddress(); + return aRange; +} + +Reference< XCellRange > WorksheetHelper::getColumn( sal_Int32 nCol ) const +{ + return mrSheetData.getColumn( nCol ); +} + +Reference< XCellRange > WorksheetHelper::getRow( sal_Int32 nRow ) const +{ + return mrSheetData.getRow( nRow ); +} + +Reference< XTableColumns > WorksheetHelper::getColumns( sal_Int32 nFirstCol, sal_Int32 nLastCol ) const +{ + return mrSheetData.getColumns( nFirstCol, nLastCol ); +} + +Reference< XTableRows > WorksheetHelper::getRows( sal_Int32 nFirstRow, sal_Int32 nLastRow ) const +{ + return mrSheetData.getRows( nFirstRow, nLastRow ); +} + +WorksheetSettings& WorksheetHelper::getWorksheetSettings() const +{ + return mrSheetData.getWorksheetSettings(); +} + +SharedFormulaBuffer& WorksheetHelper::getSharedFormulas() const +{ + return mrSheetData.getSharedFormulas(); +} + +CondFormatBuffer& WorksheetHelper::getCondFormats() const +{ + return mrSheetData.getCondFormats(); +} + +PageSettings& WorksheetHelper::getPageSettings() const +{ + return mrSheetData.getPageSettings(); +} + +SheetViewSettings& WorksheetHelper::getSheetViewSettings() const +{ + return mrSheetData.getSheetViewSettings(); +} + +void WorksheetHelper::setEmptyStringCell( const Reference< XCell >& rxCell ) const +{ + OSL_ENSURE( rxCell.is(), "WorksheetHelper::setEmptyStringCell - missing cell interface" ); + rxCell->setFormula( mrSheetData.getEmptyStringFormula() ); +} + +void WorksheetHelper::setStringCell( const Reference< XCell >& rxCell, const OUString& rText, bool bEmptyStringAsFormula ) const +{ + if( bEmptyStringAsFormula && (rText.getLength() == 0) ) + { + setEmptyStringCell( rxCell ); + } + else + { + OSL_ENSURE( rxCell.is(), "WorksheetHelper::setStringCell - missing cell interface" ); + Reference< XText > xText( rxCell, UNO_QUERY ); + if( xText.is() ) + xText->setString( rText ); + } +} + +void WorksheetHelper::setSharedStringCell( const Reference< XCell >& rxCell, sal_Int32 nStringId, sal_Int32 nXfId ) const +{ + OSL_ENSURE( rxCell.is(), "WorksheetHelper::setSharedStringCell - missing cell interface" ); + getSharedStrings().convertString( Reference< XText >( rxCell, UNO_QUERY ), nStringId, nXfId ); +} + +void WorksheetHelper::setBooleanCell( const Reference< XCell >& rxCell, bool bValue ) const +{ + OSL_ENSURE( rxCell.is(), "WorksheetHelper::setBooleanCell - missing cell interface" ); + rxCell->setFormula( mrSheetData.getBooleanFormula( bValue ) ); +} + +void WorksheetHelper::setErrorCell( const Reference< XCell >& rxCell, const OUString& rErrorCode ) const +{ + setErrorCell( rxCell, getUnitConverter().calcBiffErrorCode( rErrorCode ) ); +} + +void WorksheetHelper::setErrorCell( const Reference< XCell >& rxCell, sal_uInt8 nErrorCode ) const +{ + Reference< XFormulaTokens > xTokens( rxCell, UNO_QUERY ); + OSL_ENSURE( xTokens.is(), "WorksheetHelper::setErrorCell - missing cell interface" ); + if( xTokens.is() ) + { + SimpleFormulaContext aContext( xTokens, false, false ); + getFormulaParser().convertErrorToFormula( aContext, nErrorCode ); + } +} + +void WorksheetHelper::setOoxCell( OoxCellData& orCellData, bool bEmptyStringAsFormula ) const +{ + OSL_ENSURE( orCellData.mxCell.is(), "WorksheetHelper::setCell - missing cell interface" ); + if( orCellData.mbHasValueStr ) switch( orCellData.mnCellType ) + { + case XML_b: + setBooleanCell( orCellData.mxCell, orCellData.maValueStr.toDouble() != 0.0 ); + // #108770# set 'Standard' number format for all Boolean cells + orCellData.mnNumFmtId = 0; + break; + case XML_n: + orCellData.mxCell->setValue( orCellData.maValueStr.toDouble() ); + break; + case XML_e: + setErrorCell( orCellData.mxCell, orCellData.maValueStr ); + break; + case XML_str: + setStringCell( orCellData.mxCell, orCellData.maValueStr, bEmptyStringAsFormula ); + break; + case XML_s: + setSharedStringCell( orCellData.mxCell, orCellData.maValueStr.toInt32(), orCellData.mnXfId ); + break; + } +} + +void WorksheetHelper::setDimension( const CellRangeAddress& rRange ) +{ + mrSheetData.setDimension( rRange ); +} + +void WorksheetHelper::setCellFormat( const OoxCellData& rCellData ) +{ + mrSheetData.setCellFormat( rCellData ); +} + +void WorksheetHelper::setMergedRange( const CellRangeAddress& rRange ) +{ + mrSheetData.setMergedRange( rRange ); +} + +void WorksheetHelper::setPageBreak( const OoxPageBreakData& rData, bool bRowBreak ) +{ + mrSheetData.setPageBreak( rData, bRowBreak ); +} + +void WorksheetHelper::setHyperlink( const OoxHyperlinkData& rHyperlink ) +{ + mrSheetData.setHyperlink( rHyperlink ); +} + +void WorksheetHelper::setValidation( const OoxValidationData& rValData ) +{ + mrSheetData.setValidation( rValData ); +} + +void WorksheetHelper::setTableOperation( const CellRangeAddress& rRange, const OoxDataTableData& rTableData ) const +{ + OSL_ENSURE( getAddressConverter().checkCellRange( rRange, false ), "WorksheetHelper::setTableOperation - invalid range" ); + bool bOk = false; + if( !rTableData.mbRef1Deleted && (rTableData.maRef1.getLength() > 0) && (rRange.StartColumn > 0) && (rRange.StartRow > 0) ) + { + CellRangeAddress aOpRange = rRange; + CellAddress aRef1, aRef2; + if( getAddressConverter().convertToCellAddress( aRef1, rTableData.maRef1, mrSheetData.getSheetIndex(), true ) ) try + { + if( rTableData.mb2dTable ) + { + if( !rTableData.mbRef2Deleted && getAddressConverter().convertToCellAddress( aRef2, rTableData.maRef2, mrSheetData.getSheetIndex(), true ) ) + { + // API call expects input values inside operation range + --aOpRange.StartColumn; + --aOpRange.StartRow; + // formula range is top-left cell of operation range + CellRangeAddress aFormulaRange( mrSheetData.getSheetIndex(), aOpRange.StartColumn, aOpRange.StartRow, aOpRange.StartColumn, aOpRange.StartRow ); + // set multiple operation + Reference< XMultipleOperation > xMultOp( mrSheetData.getCellRange( aOpRange ), UNO_QUERY_THROW ); + xMultOp->setTableOperation( aFormulaRange, ::com::sun::star::sheet::TableOperationMode_BOTH, aRef2, aRef1 ); + bOk = true; + } + } + else if( rTableData.mbRowTable ) + { + // formula range is column to the left of operation range + CellRangeAddress aFormulaRange( mrSheetData.getSheetIndex(), aOpRange.StartColumn - 1, aOpRange.StartRow, aOpRange.StartColumn - 1, aOpRange.EndRow ); + // API call expects input values (top row) inside operation range + --aOpRange.StartRow; + // set multiple operation + Reference< XMultipleOperation > xMultOp( mrSheetData.getCellRange( aOpRange ), UNO_QUERY_THROW ); + xMultOp->setTableOperation( aFormulaRange, ::com::sun::star::sheet::TableOperationMode_ROW, aRef1, aRef1 ); + bOk = true; + } + else + { + // formula range is row above operation range + CellRangeAddress aFormulaRange( mrSheetData.getSheetIndex(), aOpRange.StartColumn, aOpRange.StartRow - 1, aOpRange.EndColumn, aOpRange.StartRow - 1 ); + // API call expects input values (left column) inside operation range + --aOpRange.StartColumn; + // set multiple operation + Reference< XMultipleOperation > xMultOp( mrSheetData.getCellRange( aOpRange ), UNO_QUERY_THROW ); + xMultOp->setTableOperation( aFormulaRange, ::com::sun::star::sheet::TableOperationMode_COLUMN, aRef1, aRef1 ); + bOk = true; + } + } + catch( Exception& ) + { + } + } + + // on error: fill cell range with error codes + if( !bOk ) + { + for( CellAddress aPos( mrSheetData.getSheetIndex(), rRange.StartColumn, rRange.StartRow ); aPos.Row <= rRange.EndRow; ++aPos.Row ) + for( aPos.Column = rRange.StartColumn; aPos.Column <= rRange.EndColumn; ++aPos.Column ) + setErrorCell( mrSheetData.getCell( aPos ), BIFF_ERR_REF ); + } +} + +void WorksheetHelper::setLabelRanges( const ApiCellRangeList& rColRanges, const ApiCellRangeList& rRowRanges ) +{ + const CellAddress& rMaxPos = getAddressConverter().getMaxApiAddress(); + Reference< XLabelRanges > xLabelRanges; + PropertySet aPropSet( getXSpreadsheet() ); + + if( !rColRanges.empty() && aPropSet.getProperty( xLabelRanges, CREATE_OUSTRING( "ColumnLabelRanges" ) ) && xLabelRanges.is() ) + { + for( ApiCellRangeList::const_iterator aIt = rColRanges.begin(), aEnd = rColRanges.end(); aIt != aEnd; ++aIt ) + { + CellRangeAddress aDataRange = *aIt; + if( aDataRange.EndRow < rMaxPos.Row ) + { + aDataRange.StartRow = aDataRange.EndRow + 1; + aDataRange.EndRow = rMaxPos.Row; + } + else if( aDataRange.StartRow > 0 ) + { + aDataRange.EndRow = aDataRange.StartRow - 1; + aDataRange.StartRow = 0; + } + xLabelRanges->addNew( *aIt, aDataRange ); + } + } + + if( !rRowRanges.empty() && aPropSet.getProperty( xLabelRanges, CREATE_OUSTRING( "RowLabelRanges" ) ) && xLabelRanges.is() ) + { + for( ApiCellRangeList::const_iterator aIt = rRowRanges.begin(), aEnd = rRowRanges.end(); aIt != aEnd; ++aIt ) + { + CellRangeAddress aDataRange = *aIt; + if( aDataRange.EndColumn < rMaxPos.Column ) + { + aDataRange.StartColumn = aDataRange.EndColumn + 1; + aDataRange.EndColumn = rMaxPos.Column; + } + else if( aDataRange.StartColumn > 0 ) + { + aDataRange.EndColumn = aDataRange.StartColumn - 1; + aDataRange.StartColumn = 0; + } + xLabelRanges->addNew( *aIt, aDataRange ); + } + } +} + +void WorksheetHelper::setBaseColumnWidth( sal_Int32 nWidth ) +{ + mrSheetData.setBaseColumnWidth( nWidth ); +} + +void WorksheetHelper::setDefaultColumnWidth( double fWidth ) +{ + mrSheetData.setDefaultColumnWidth( fWidth ); +} + +void WorksheetHelper::setColumnData( const OoxColumnData& rData ) +{ + mrSheetData.setColumnData( rData ); +} + +void WorksheetHelper::setDefaultRowSettings( double fHeight, bool bCustomHeight, bool bHidden, bool bThickTop, bool bThickBottom ) +{ + mrSheetData.setDefaultRowSettings( fHeight, bCustomHeight, bHidden, bThickTop, bThickBottom ); +} + +void WorksheetHelper::setRowData( const OoxRowData& rData ) +{ + mrSheetData.setRowData( rData ); +} + +void WorksheetHelper::convertColumnFormat( sal_Int32 nFirstCol, sal_Int32 nLastCol, sal_Int32 nXfId ) +{ + mrSheetData.convertColumnFormat( nFirstCol, nLastCol, nXfId ); +} + +void WorksheetHelper::convertRowFormat( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId ) +{ + mrSheetData.convertRowFormat( nFirstRow, nLastRow, nXfId ); +} + +void WorksheetHelper::initializeWorksheetImport() +{ + mrSheetData.initializeWorksheetImport(); +} + +void WorksheetHelper::finalizeWorksheetImport() +{ + mrSheetData.finalizeWorksheetImport(); +} + +// ============================================================================ + +namespace prv { + +WorksheetDataOwner::WorksheetDataOwner( WorksheetDataRef xSheetData ) : + mxSheetData( xSheetData ) +{ +} + +WorksheetDataOwner::~WorksheetDataOwner() +{ +} + +} // namespace prv + +// ---------------------------------------------------------------------------- + +WorksheetHelperRoot::WorksheetHelperRoot( const WorkbookHelper& rHelper, ISegmentProgressBarRef xProgressBar, WorksheetType eSheetType, sal_Int32 nSheet ) : + prv::WorksheetDataOwner( prv::WorksheetDataRef( new WorksheetData( rHelper, xProgressBar, eSheetType, nSheet ) ) ), + WorksheetHelper( *mxSheetData ) +{ +} + +WorksheetHelperRoot::WorksheetHelperRoot( const WorksheetHelper& rHelper ) : + prv::WorksheetDataOwner( prv::WorksheetDataRef() ), + WorksheetHelper( rHelper ) +{ +} + +WorksheetHelperRoot::WorksheetHelperRoot( const WorksheetHelperRoot& rHelper ) : + prv::WorksheetDataOwner( rHelper.mxSheetData ), + WorksheetHelper( rHelper ) +{ +} + +bool WorksheetHelperRoot::isValidSheet() const +{ + return mxSheetData->isValidSheet(); +} + +// ============================================================================ +// ============================================================================ + +} // namespace xls +} // namespace oox + diff --git a/oox/source/xls/worksheetsettings.cxx b/oox/source/xls/worksheetsettings.cxx new file mode 100644 index 000000000000..d827fc1ff70d --- /dev/null +++ b/oox/source/xls/worksheetsettings.cxx @@ -0,0 +1,270 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: worksheetsettings.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2008-01-17 08:06:10 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "oox/xls/worksheetsettings.hxx" +#include +#include "oox/helper/attributelist.hxx" +#include "oox/helper/recordinputstream.hxx" +#include "oox/xls/biffinputstream.hxx" +#include "oox/xls/pagesettings.hxx" +#include "oox/xls/workbooksettings.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::util::XProtectable; + +namespace oox { +namespace xls { + +// ============================================================================ + +namespace { + +const sal_uInt16 BIFF_SHEETPR_APPLYSTYLES = 0x0020; +const sal_uInt16 BIFF_SHEETPR_SYMBOLSBELOW = 0x0040; +const sal_uInt16 BIFF_SHEETPR_SYMBOLSRIGHT = 0x0080; +const sal_uInt16 BIFF_SHEETPR_FITTOPAGES = 0x0100; +const sal_uInt16 BIFF_SHEETPR_SKIPEXT = 0x0200; /// BIFF3-BIFF4 + +const sal_uInt16 BIFF_SHEETPROT_OBJECTS = 0x0001; +const sal_uInt16 BIFF_SHEETPROT_SCENARIOS = 0x0002; +const sal_uInt16 BIFF_SHEETPROT_FORMAT_CELLS = 0x0004; +const sal_uInt16 BIFF_SHEETPROT_FORMAT_COLUMNS = 0x0008; +const sal_uInt16 BIFF_SHEETPROT_FORMAT_ROWS = 0x0010; +const sal_uInt16 BIFF_SHEETPROT_INSERT_COLUMNS = 0x0020; +const sal_uInt16 BIFF_SHEETPROT_INSERT_ROWS = 0x0040; +const sal_uInt16 BIFF_SHEETPROT_INSERT_HLINKS = 0x0080; +const sal_uInt16 BIFF_SHEETPROT_DELETE_COLUMNS = 0x0100; +const sal_uInt16 BIFF_SHEETPROT_DELETE_ROWS = 0x0200; +const sal_uInt16 BIFF_SHEETPROT_SELECT_LOCKED = 0x0400; +const sal_uInt16 BIFF_SHEETPROT_SORT = 0x0800; +const sal_uInt16 BIFF_SHEETPROT_AUTOFILTER = 0x1000; +const sal_uInt16 BIFF_SHEETPROT_PIVOTTABLES = 0x2000; +const sal_uInt16 BIFF_SHEETPROT_SELECT_UNLOCKED = 0x4000; + +} // namespace + +// ============================================================================ + +OoxOutlinePrData::OoxOutlinePrData() : + mbApplyStyles( false ), + mbSummaryBelow( true ), + mbSummaryRight( true ) +{ +} + +// ============================================================================ + +OoxSheetProtectionData::OoxSheetProtectionData() : + mnPasswordHash( 0 ), + mbSheet( false ), + mbObjects( false ), + mbScenarios( false ), + mbFormatCells( true ), + mbFormatColumns( true ), + mbFormatRows( true ), + mbInsertColumns( true ), + mbInsertRows( true ), + mbInsertHyperlinks( true ), + mbDeleteColumns( true ), + mbDeleteRows( true ), + mbSelectLocked( false ), + mbSort( true ), + mbAutoFilter( true ), + mbPivotTables( true ), + mbSelectUnlocked( false ) +{ +} + +// ============================================================================ + +WorksheetSettings::WorksheetSettings( const WorksheetHelper& rHelper ) : + WorksheetHelper( rHelper ), + maPhoneticSett( rHelper ) +{ +} + +void WorksheetSettings::importOutlinePr( const AttributeList& rAttribs ) +{ + maOoxOutlineData.mbApplyStyles = rAttribs.getBool( XML_applyStyles, false ); + maOoxOutlineData.mbSummaryBelow = rAttribs.getBool( XML_summaryBelow, true ); + maOoxOutlineData.mbSummaryRight = rAttribs.getBool( XML_summaryRight, true ); +} + +void WorksheetSettings::importSheetProtection( const AttributeList& rAttribs ) +{ + sal_Int32 nHash = rAttribs.getHex( XML_password, 0 ); + OSL_ENSURE( (0 <= nHash) && (nHash <= SAL_MAX_UINT16), "WorksheetSettings::importSheetProtection - invalid password hash" ); + maOoxProtData.mnPasswordHash = static_cast< sal_uInt16 >( nHash ); + maOoxProtData.mbSheet = rAttribs.getBool( XML_sheet, false ); + maOoxProtData.mbObjects = rAttribs.getBool( XML_objects, false ); + maOoxProtData.mbScenarios = rAttribs.getBool( XML_scenarios, false ); + maOoxProtData.mbFormatCells = rAttribs.getBool( XML_formatCells, true ); + maOoxProtData.mbFormatColumns = rAttribs.getBool( XML_formatColumns, true ); + maOoxProtData.mbFormatRows = rAttribs.getBool( XML_formatRows, true ); + maOoxProtData.mbInsertColumns = rAttribs.getBool( XML_insertColumns, true ); + maOoxProtData.mbInsertRows = rAttribs.getBool( XML_insertRows, true ); + maOoxProtData.mbInsertHyperlinks = rAttribs.getBool( XML_insertHyperlinks, true ); + maOoxProtData.mbDeleteColumns = rAttribs.getBool( XML_deleteColumns, true ); + maOoxProtData.mbDeleteRows = rAttribs.getBool( XML_deleteRows, true ); + maOoxProtData.mbSelectLocked = rAttribs.getBool( XML_selectLockedCells, false ); + maOoxProtData.mbSort = rAttribs.getBool( XML_sort, true ); + maOoxProtData.mbAutoFilter = rAttribs.getBool( XML_autoFilter, true ); + maOoxProtData.mbPivotTables = rAttribs.getBool( XML_pivotTables, true ); + maOoxProtData.mbSelectUnlocked = rAttribs.getBool( XML_selectUnlockedCells, false ); +} + +void WorksheetSettings::importPhoneticPr( const AttributeList& rAttribs ) +{ + maPhoneticSett.importPhoneticPr( rAttribs ); +} + +void WorksheetSettings::importSheetPr( RecordInputStream& rStrm ) +{ + sal_uInt16 nFlags; + rStrm >> nFlags; + // outline settings, equal flags in BIFF and OOBIN + maOoxOutlineData.mbApplyStyles = getFlag( nFlags, BIFF_SHEETPR_APPLYSTYLES ); + maOoxOutlineData.mbSummaryRight = getFlag( nFlags, BIFF_SHEETPR_SYMBOLSRIGHT ); + maOoxOutlineData.mbSummaryBelow = getFlag( nFlags, BIFF_SHEETPR_SYMBOLSBELOW ); + /* Fit printout to width/height - for whatever reason, this flag is still + stored separated from the page settings */ + getPageSettings().setFitToPagesMode( getFlag( nFlags, BIFF_SHEETPR_FITTOPAGES ) ); +} + +void WorksheetSettings::importSheetProtection( RecordInputStream& rStrm ) +{ + rStrm >> maOoxProtData.mnPasswordHash; + // no flags field for all these boolean flags?!? + maOoxProtData.mbSheet = rStrm.readInt32() != 0; + maOoxProtData.mbObjects = rStrm.readInt32() != 0; + maOoxProtData.mbScenarios = rStrm.readInt32() != 0; + maOoxProtData.mbFormatCells = rStrm.readInt32() != 0; + maOoxProtData.mbFormatColumns = rStrm.readInt32() != 0; + maOoxProtData.mbFormatRows = rStrm.readInt32() != 0; + maOoxProtData.mbInsertColumns = rStrm.readInt32() != 0; + maOoxProtData.mbInsertRows = rStrm.readInt32() != 0; + maOoxProtData.mbInsertHyperlinks = rStrm.readInt32() != 0; + maOoxProtData.mbDeleteColumns = rStrm.readInt32() != 0; + maOoxProtData.mbDeleteRows = rStrm.readInt32() != 0; + maOoxProtData.mbSelectLocked = rStrm.readInt32() != 0; + maOoxProtData.mbSort = rStrm.readInt32() != 0; + maOoxProtData.mbAutoFilter = rStrm.readInt32() != 0; + maOoxProtData.mbPivotTables = rStrm.readInt32() != 0; + maOoxProtData.mbSelectUnlocked = rStrm.readInt32() != 0; +} + +void WorksheetSettings::importPhoneticPr( RecordInputStream& rStrm ) +{ + maPhoneticSett.importPhoneticPr( rStrm ); +} + +void WorksheetSettings::importSheetPr( BiffInputStream& rStrm ) +{ + sal_uInt16 nFlags; + rStrm >> nFlags; + // outline settings + maOoxOutlineData.mbApplyStyles = getFlag( nFlags, BIFF_SHEETPR_APPLYSTYLES ); + maOoxOutlineData.mbSummaryRight = getFlag( nFlags, BIFF_SHEETPR_SYMBOLSRIGHT ); + maOoxOutlineData.mbSummaryBelow = getFlag( nFlags, BIFF_SHEETPR_SYMBOLSBELOW ); + // fit printout to width/height + getPageSettings().setFitToPagesMode( getFlag( nFlags, BIFF_SHEETPR_FITTOPAGES ) ); + // save external linked values, in BIFF5-BIFF8 moved to BOOKBOOK record + if( getBiff() <= BIFF4 ) + getWorkbookSettings().setSaveExtLinkValues( !getFlag( nFlags, BIFF_SHEETPR_SKIPEXT ) ); +} + +void WorksheetSettings::importProtect( BiffInputStream& rStrm ) +{ + maOoxProtData.mbSheet = rStrm.readuInt16() != 0; +} + +void WorksheetSettings::importObjectProtect( BiffInputStream& rStrm ) +{ + maOoxProtData.mbObjects = rStrm.readuInt16() != 0; +} + +void WorksheetSettings::importScenProtect( BiffInputStream& rStrm ) +{ + maOoxProtData.mbScenarios = rStrm.readuInt16() != 0; +} + +void WorksheetSettings::importPassword( BiffInputStream& rStrm ) +{ + rStrm >> maOoxProtData.mnPasswordHash; +} + +void WorksheetSettings::importSheetProtection( BiffInputStream& rStrm ) +{ + sal_uInt16 nFlags = rStrm.skip( 19 ).readuInt16(); + // set flag means protection is disabled + maOoxProtData.mbObjects = !getFlag( nFlags, BIFF_SHEETPROT_OBJECTS ); + maOoxProtData.mbScenarios = !getFlag( nFlags, BIFF_SHEETPROT_SCENARIOS ); + maOoxProtData.mbFormatCells = !getFlag( nFlags, BIFF_SHEETPROT_FORMAT_CELLS ); + maOoxProtData.mbFormatColumns = !getFlag( nFlags, BIFF_SHEETPROT_FORMAT_COLUMNS ); + maOoxProtData.mbFormatRows = !getFlag( nFlags, BIFF_SHEETPROT_FORMAT_ROWS ); + maOoxProtData.mbInsertColumns = !getFlag( nFlags, BIFF_SHEETPROT_INSERT_COLUMNS ); + maOoxProtData.mbInsertRows = !getFlag( nFlags, BIFF_SHEETPROT_INSERT_ROWS ); + maOoxProtData.mbInsertHyperlinks = !getFlag( nFlags, BIFF_SHEETPROT_INSERT_HLINKS ); + maOoxProtData.mbDeleteColumns = !getFlag( nFlags, BIFF_SHEETPROT_DELETE_COLUMNS ); + maOoxProtData.mbDeleteRows = !getFlag( nFlags, BIFF_SHEETPROT_DELETE_ROWS ); + maOoxProtData.mbSelectLocked = !getFlag( nFlags, BIFF_SHEETPROT_SELECT_LOCKED ); + maOoxProtData.mbSort = !getFlag( nFlags, BIFF_SHEETPROT_SORT ); + maOoxProtData.mbAutoFilter = !getFlag( nFlags, BIFF_SHEETPROT_AUTOFILTER ); + maOoxProtData.mbPivotTables = !getFlag( nFlags, BIFF_SHEETPROT_PIVOTTABLES ); + maOoxProtData.mbSelectUnlocked = !getFlag( nFlags, BIFF_SHEETPROT_SELECT_UNLOCKED ); +} + +void WorksheetSettings::importPhoneticPr( BiffInputStream& rStrm ) +{ + maPhoneticSett.importPhoneticPr( rStrm ); +} + +void WorksheetSettings::finalizeImport() +{ + if( maOoxProtData.mbSheet ) + { + Reference< XProtectable > xProtectable( getXSpreadsheet(), UNO_QUERY ); + if( xProtectable.is() ) + xProtectable->protect( OUString() ); + } +} + +// ============================================================================ + +} // namespace xls +} // namespace oox + -- cgit